mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
- Added Order of Succession
This commit is contained in:
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -48,6 +48,7 @@ forge-ai/src/main/java/forge/ai/ability/CharmAi.java -text
|
|||||||
forge-ai/src/main/java/forge/ai/ability/ChooseCardAi.java -text
|
forge-ai/src/main/java/forge/ai/ability/ChooseCardAi.java -text
|
||||||
forge-ai/src/main/java/forge/ai/ability/ChooseCardNameAi.java -text
|
forge-ai/src/main/java/forge/ai/ability/ChooseCardNameAi.java -text
|
||||||
forge-ai/src/main/java/forge/ai/ability/ChooseColorAi.java -text
|
forge-ai/src/main/java/forge/ai/ability/ChooseColorAi.java -text
|
||||||
|
forge-ai/src/main/java/forge/ai/ability/ChooseDirectionAi.java -text
|
||||||
forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java -text
|
forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java -text
|
||||||
forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java -text
|
forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java -text
|
||||||
forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java -text
|
forge-ai/src/main/java/forge/ai/ability/ChoosePlayerAi.java -text
|
||||||
@@ -307,6 +308,7 @@ forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java -text
|
|||||||
forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChooseCardEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ChooseCardNameEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChooseCardNameEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ChooseColorEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChooseColorEffect.java -text
|
||||||
|
forge-game/src/main/java/forge/game/ability/effects/ChooseDirectionEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ChooseGenericEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChooseGenericEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ChoosePlayerEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ChoosePlayerEffect.java -text
|
||||||
@@ -9560,6 +9562,7 @@ forge-gui/res/cardsfolder/o/ordeal_of_purphoros.txt -text
|
|||||||
forge-gui/res/cardsfolder/o/ordeal_of_thassa.txt -text
|
forge-gui/res/cardsfolder/o/ordeal_of_thassa.txt -text
|
||||||
forge-gui/res/cardsfolder/o/order_chaos.txt -text
|
forge-gui/res/cardsfolder/o/order_chaos.txt -text
|
||||||
forge-gui/res/cardsfolder/o/order_of_leitbur.txt svneol=native#text/plain
|
forge-gui/res/cardsfolder/o/order_of_leitbur.txt svneol=native#text/plain
|
||||||
|
forge-gui/res/cardsfolder/o/order_of_succession.txt -text
|
||||||
forge-gui/res/cardsfolder/o/order_of_the_ebon_hand.txt svneol=native#text/plain
|
forge-gui/res/cardsfolder/o/order_of_the_ebon_hand.txt svneol=native#text/plain
|
||||||
forge-gui/res/cardsfolder/o/order_of_the_golden_cricket.txt svneol=native#text/plain
|
forge-gui/res/cardsfolder/o/order_of_the_golden_cricket.txt svneol=native#text/plain
|
||||||
forge-gui/res/cardsfolder/o/order_of_the_sacred_bell.txt svneol=native#text/plain
|
forge-gui/res/cardsfolder/o/order_of_the_sacred_bell.txt svneol=native#text/plain
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import forge.card.mana.ManaCost;
|
|||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.deck.DeckSection;
|
import forge.deck.DeckSection;
|
||||||
|
import forge.game.Direction;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameActionUtil;
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
@@ -1534,6 +1535,23 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean chooseDirection(SpellAbility sa) {
|
||||||
|
if( sa == null || sa.getApi() == null ) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
// Left:True; Right:False
|
||||||
|
if ("GainControl".equals(sa.getParam("AILogic")) && game.getPlayers().size() > 2) {
|
||||||
|
List<Card> creats = CardLists.getType(game.getCardsIn(ZoneType.Battlefield), "Creature");
|
||||||
|
List<Card> left = CardLists.filterControlledBy(creats, game.getNextPlayerAfter(player, Direction.Left));
|
||||||
|
List<Card> right = CardLists.filterControlledBy(creats, game.getNextPlayerAfter(player, Direction.Right));
|
||||||
|
if (!left.isEmpty() || !right.isEmpty()) {
|
||||||
|
List<Card> all = new ArrayList<Card>(left);
|
||||||
|
all.addAll(right);
|
||||||
|
return left.contains(ComputerUtilCard.getBestCreatureAI(all));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MyRandom.getRandom().nextBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -503,6 +503,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
case TapOrUntap: return true;
|
case TapOrUntap: return true;
|
||||||
case UntapOrLeaveTapped: return defaultVal != null && defaultVal.booleanValue();
|
case UntapOrLeaveTapped: return defaultVal != null && defaultVal.booleanValue();
|
||||||
case UntapTimeVault: return false; // TODO Should AI skip his turn for time vault?
|
case UntapTimeVault: return false; // TODO Should AI skip his turn for time vault?
|
||||||
|
case LeftOrRight: return brains.chooseDirection(sa);
|
||||||
default:
|
default:
|
||||||
return MyRandom.getRandom().nextBoolean();
|
return MyRandom.getRandom().nextBoolean();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public enum SpellApiToAi {
|
|||||||
apiToClass.put(ApiType.Charm, CharmAi.class);
|
apiToClass.put(ApiType.Charm, CharmAi.class);
|
||||||
apiToClass.put(ApiType.ChooseCard, ChooseCardAi.class);
|
apiToClass.put(ApiType.ChooseCard, ChooseCardAi.class);
|
||||||
apiToClass.put(ApiType.ChooseColor, ChooseColorAi.class);
|
apiToClass.put(ApiType.ChooseColor, ChooseColorAi.class);
|
||||||
|
apiToClass.put(ApiType.ChooseDirection, ChooseDirectionAi.class);
|
||||||
apiToClass.put(ApiType.ChooseNumber, ChooseNumberAi.class);
|
apiToClass.put(ApiType.ChooseNumber, ChooseNumberAi.class);
|
||||||
apiToClass.put(ApiType.ChoosePlayer, ChoosePlayerAi.class);
|
apiToClass.put(ApiType.ChoosePlayer, ChoosePlayerAi.class);
|
||||||
apiToClass.put(ApiType.ChooseSource, ChooseSourceAi.class);
|
apiToClass.put(ApiType.ChooseSource, ChooseSourceAi.class);
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package forge.ai.ability;
|
||||||
|
|
||||||
|
import forge.ai.SpellAbilityAi;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
|
||||||
|
public class ChooseDirectionAi extends SpellAbilityAi {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||||
|
final String logic = sa.getParam("AILogic");
|
||||||
|
if (logic == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// TODO: default ai
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
||||||
|
return canPlayAI(ai, sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||||
|
return canPlayAI(ai, sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package forge.ai.ability;
|
package forge.ai.ability;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
|
import forge.ai.ComputerUtilCard;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
@@ -11,6 +13,7 @@ import forge.game.spellability.SpellAbility;
|
|||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,4 +117,9 @@ public class RepeatEachAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Card chooseSingleCard(Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional, Player targetedPlayer) {
|
||||||
|
return ComputerUtilCard.getBestCreatureAI(options);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -529,13 +529,25 @@ public class Game {
|
|||||||
* {@code null} if there are no players in the game.
|
* {@code null} if there are no players in the game.
|
||||||
*/
|
*/
|
||||||
public Player getNextPlayerAfter(final Player playerTurn) {
|
public Player getNextPlayerAfter(final Player playerTurn) {
|
||||||
|
return getNextPlayerAfter(playerTurn, this.turnOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the player whose turn it is after a given player's turn, taking turn
|
||||||
|
* order into account.
|
||||||
|
* @param playerTurn a {@link Player}, or {@code null}.
|
||||||
|
* @param turnOrder a {@link Direction}
|
||||||
|
* @return A {@link Player}, whose turn comes after the current player, or
|
||||||
|
* {@code null} if there are no players in the game.
|
||||||
|
*/
|
||||||
|
public Player getNextPlayerAfter(final Player playerTurn, final Direction turnOrder) {
|
||||||
int iPlayer = roIngamePlayers.indexOf(playerTurn);
|
int iPlayer = roIngamePlayers.indexOf(playerTurn);
|
||||||
|
|
||||||
if (roIngamePlayers.isEmpty()) {
|
if (roIngamePlayers.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int shift = this.getTurnOrder().getShift();
|
final int shift = turnOrder.getShift();
|
||||||
final int totalNumPlayers = allPlayers.size();
|
final int totalNumPlayers = allPlayers.size();
|
||||||
if (-1 == iPlayer) { // if playerTurn has just lost
|
if (-1 == iPlayer) { // if playerTurn has just lost
|
||||||
int iAlive;
|
int iAlive;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public enum ApiType {
|
|||||||
Charm (CharmEffect.class),
|
Charm (CharmEffect.class),
|
||||||
ChooseCard (ChooseCardEffect.class),
|
ChooseCard (ChooseCardEffect.class),
|
||||||
ChooseColor (ChooseColorEffect.class),
|
ChooseColor (ChooseColorEffect.class),
|
||||||
|
ChooseDirection (ChooseDirectionEffect.class),
|
||||||
ChooseNumber (ChooseNumberEffect.class),
|
ChooseNumber (ChooseNumberEffect.class),
|
||||||
ChoosePlayer (ChoosePlayerEffect.class),
|
ChoosePlayer (ChoosePlayerEffect.class),
|
||||||
ChooseSource (ChooseSourceEffect.class),
|
ChooseSource (ChooseSourceEffect.class),
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import forge.game.Direction;
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.PlayerController.BinaryChoiceType;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
|
||||||
|
public class ChooseDirectionEffect extends SpellAbilityEffect {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellEffect#resolve(java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resolve(final SpellAbility sa) {
|
||||||
|
final Card source = sa.getHostCard();
|
||||||
|
final Game game = source.getGame();
|
||||||
|
final List<Player> left = new ArrayList<Player>(game.getPlayers());
|
||||||
|
// TODO: We'd better set up turn order UI here
|
||||||
|
final String info = "Left (clockwise): " + left + "\r\nRight (anticlockwise):" + Lists.reverse(left);
|
||||||
|
sa.getActivatingPlayer().getController().notifyOfValue(sa, source, info);
|
||||||
|
|
||||||
|
boolean chosen = sa.getActivatingPlayer().getController().chooseBinary(sa,
|
||||||
|
"Choose a direction", BinaryChoiceType.LeftOrRight);
|
||||||
|
source.setChosenDirection(chosen ? Direction.Left : Direction.Right);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -117,8 +117,8 @@ public class RepeatEachEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
if (recordChoice) {
|
if (recordChoice) {
|
||||||
boolean random = sa.hasParam("Random");
|
boolean random = sa.hasParam("Random");
|
||||||
if (sa.hasParam("ChoosePlayer")) {
|
|
||||||
Map<Player, List<Card>> recordMap = new HashMap<Player, List<Card>>();
|
Map<Player, List<Card>> recordMap = new HashMap<Player, List<Card>>();
|
||||||
|
if (sa.hasParam("ChoosePlayer")) {
|
||||||
for (Card card : repeatCards) {
|
for (Card card : repeatCards) {
|
||||||
Player p;
|
Player p;
|
||||||
if (random) {
|
if (random) {
|
||||||
@@ -132,6 +132,33 @@ public class RepeatEachEffect extends SpellAbilityEffect {
|
|||||||
recordMap.put(p, Lists.newArrayList(card));
|
recordMap.put(p, Lists.newArrayList(card));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (sa.hasParam("ChooseCard")) {
|
||||||
|
List<Card> list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield),
|
||||||
|
sa.getParam("ChooseCard"), source.getController(), source);
|
||||||
|
String filterController = sa.getParam("FilterControlledBy");
|
||||||
|
// default: Starting with you and proceeding in the chosen direction
|
||||||
|
Player p = sa.getActivatingPlayer();
|
||||||
|
do {
|
||||||
|
List<Card> valid = new ArrayList<Card>(list);
|
||||||
|
if ("NextPlayerInChosenDirection".equals(filterController)) {
|
||||||
|
valid = CardLists.filterControlledBy(valid,
|
||||||
|
game.getNextPlayerAfter(p, source.getChosenDirection()));
|
||||||
|
}
|
||||||
|
Card card = p.getController().chooseSingleEntityForEffect(valid, sa, "Choose a card");
|
||||||
|
if (recordMap.containsKey(p)) {
|
||||||
|
recordMap.get(p).add(0, card);
|
||||||
|
} else {
|
||||||
|
recordMap.put(p, Lists.newArrayList(card));
|
||||||
|
}
|
||||||
|
if (source.getChosenDirection() != null) {
|
||||||
|
p = game.getNextPlayerAfter(p, source.getChosenDirection());
|
||||||
|
} else {
|
||||||
|
p = game.getNextPlayerAfter(p);
|
||||||
|
}
|
||||||
|
} while (!p.equals(sa.getActivatingPlayer()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for (Entry<Player, List<Card>> entry : recordMap.entrySet()) {
|
for (Entry<Player, List<Card>> entry : recordMap.entrySet()) {
|
||||||
// Remember the player and imprint the cards
|
// Remember the player and imprint the cards
|
||||||
source.addRemembered(entry.getKey());
|
source.addRemembered(entry.getKey());
|
||||||
@@ -142,5 +169,4 @@ public class RepeatEachEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private int chosenNumber;
|
private int chosenNumber;
|
||||||
private Player chosenPlayer;
|
private Player chosenPlayer;
|
||||||
private List<Card> chosenCard = new ArrayList<Card>();
|
private List<Card> chosenCard = new ArrayList<Card>();
|
||||||
|
private Direction chosenDirection = null;
|
||||||
|
|
||||||
private Card cloneOrigin = null;
|
private Card cloneOrigin = null;
|
||||||
private final List<Card> clones = new ArrayList<Card>();
|
private final List<Card> clones = new ArrayList<Card>();
|
||||||
@@ -1725,6 +1726,14 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
this.chosenCard = c;
|
this.chosenCard = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Direction getChosenDirection() {
|
||||||
|
return chosenDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChosenDirection(Direction chosenDirection) {
|
||||||
|
this.chosenDirection = chosenDirection;
|
||||||
|
}
|
||||||
|
|
||||||
// used for cards like Meddling Mage...
|
// used for cards like Meddling Mage...
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -1898,6 +1907,12 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
sb.append("]\r\n");
|
sb.append("]\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.chosenDirection != null) {
|
||||||
|
sb.append("\r\n[Chosen direction: ");
|
||||||
|
sb.append(this.getChosenDirection());
|
||||||
|
sb.append("]\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (this.hauntedBy.size() != 0) {
|
if (this.hauntedBy.size() != 0) {
|
||||||
sb.append("Haunted by: ");
|
sb.append("Haunted by: ");
|
||||||
for (final Card c : this.hauntedBy) {
|
for (final Card c : this.hauntedBy) {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ public abstract class PlayerController {
|
|||||||
OddsOrEvens,
|
OddsOrEvens,
|
||||||
UntapOrLeaveTapped,
|
UntapOrLeaveTapped,
|
||||||
UntapTimeVault,
|
UntapTimeVault,
|
||||||
|
LeftOrRight,
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final Game game;
|
protected final Game game;
|
||||||
|
|||||||
8
forge-gui/res/cardsfolder/o/order_of_succession.txt
Normal file
8
forge-gui/res/cardsfolder/o/order_of_succession.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Order of Succession
|
||||||
|
ManaCost:3 U
|
||||||
|
Types:Sorcery
|
||||||
|
A:SP$ ChooseDirection | Cost$ 3 U | SubAbility$ DBRepeat | AILogic$ GainControl | SpellDescription$ Choose left or right. Starting with you and proceeding in the chosen direction, each player chooses a creature controlled by the next player in that direction. Each player gains control of the creature he or she chose.
|
||||||
|
SVar:DBRepeat:DB$ RepeatEach | RepeatSubAbility$ DBGainControl | RecordChoice$ True | ChooseCard$ Creature | FilterControlledBy$ NextPlayerInChosenDirection
|
||||||
|
SVar:DBGainControl:DB$ GainControl | NewController$ Remembered | AllValid$ Card.IsImprinted
|
||||||
|
SVar:RemAIDeck:True
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/order_of_succession.jpg
|
||||||
@@ -794,6 +794,8 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
return ("Result: " + value);
|
return ("Result: " + value);
|
||||||
}
|
}
|
||||||
switch(sa.getApi()) {
|
switch(sa.getApi()) {
|
||||||
|
case ChooseDirection:
|
||||||
|
return value;
|
||||||
case ChooseNumber:
|
case ChooseNumber:
|
||||||
if (sa.hasParam("SecretlyChoose")) {
|
if (sa.hasParam("SecretlyChoose")) {
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
Reference in New Issue
Block a user