diff --git a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java index 3e4439530d2..76ebc001742 100644 --- a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java @@ -222,14 +222,29 @@ public abstract class SpellAbilityAi { @SuppressWarnings("unchecked") public T chooseSingleEntity(Player ai, SpellAbility sa, Collection options, boolean isOptional, Player targetedPlayer) { - T firstOption = Iterables.getFirst(options, null); - - if (firstOption instanceof Card) { - return (T) chooseSingleCard(ai, sa, (Collection) options, isOptional, targetedPlayer); + boolean hasPlayer = false; + boolean hasCard = false; + boolean hasPlaneswalker = false; + + for (T ent : options) { + if (ent instanceof Player) { + hasPlayer = true; + } else if (ent instanceof Card) { + hasCard = true; + if (((Card)ent).isPlaneswalker()) { + hasPlaneswalker = true; + } + } } - if (firstOption instanceof Player) { + + if (hasPlayer && hasPlaneswalker) { + return (T) chooseSinglePlayerOrPlaneswalker(ai, sa, (Collection) options); + } else if (hasCard) { + return (T) chooseSingleCard(ai, sa, (Collection) options, isOptional, targetedPlayer); + } else if (hasPlayer) { return (T) chooseSinglePlayer(ai, sa, (Collection) options); } + return null; } @@ -239,16 +254,20 @@ public abstract class SpellAbilityAi { } protected Card chooseSingleCard(Player ai, SpellAbility sa, Iterable options, boolean isOptional, Player targetedPlayer) { - System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleEntity is used for " + this.getClass().getName() + ". Consider declaring an overloaded method"); + System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleCard is used for " + this.getClass().getName() + ". Consider declaring an overloaded method"); return Iterables.getFirst(options, null); } - protected GameEntity chooseSinglePlayer(Player ai, SpellAbility sa, Iterable options) { - System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleEntity is used for " + this.getClass().getName() + ". Consider declaring an overloaded method"); + protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable options) { + System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSinglePlayer is used for " + this.getClass().getName() + ". Consider declaring an overloaded method"); return Iterables.getFirst(options, null); } + protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable options) { + System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSinglePlayerOrPlaneswalker is used for " + this.getClass().getName() + ". Consider declaring an overloaded method"); + return Iterables.getFirst(options, null); + } protected static boolean isUselessCreature(Player ai, Card c) { if (c == null) { diff --git a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java index 9b2a844cb4f..d3a0a126576 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java @@ -305,11 +305,30 @@ public class TokenAi extends SpellAbilityAi { return true; } - /* (non-Javadoc) + /* * @see forge.card.ability.SpellAbilityAi#chooseSinglePlayer(forge.game.player.Player, forge.card.spellability.SpellAbility, Iterable options) */ @Override - protected GameEntity chooseSinglePlayer(Player ai, SpellAbility sa, Iterable options) { + protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable options) { + // TODO: AILogic + Combat combat = ai.getGame().getCombat(); + // TokenAttacking + if (combat != null && sa.hasParam("TokenAttacking")) { + Card attacker = spawnToken(ai, sa); + for (Player p : options) { + if (!ComputerUtilCard.canBeBlockedProfitably(p, attacker)) { + return p; + } + } + } + return Iterables.getFirst(options, null); + } + + /* (non-Javadoc) + * @see forge.card.ability.SpellAbilityAi#chooseSinglePlayerOrPlaneswalker(forge.game.player.Player, forge.card.spellability.SpellAbility, Iterable options) + */ + @Override + protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable options) { // TODO: AILogic Combat combat = ai.getGame().getCombat(); // TokenAttacking @@ -323,8 +342,6 @@ public class TokenAi extends SpellAbilityAi { } // 2. Otherwise, go through the list of options one by one, choose the first one that can't be blocked profitably. Card attacker = spawnToken(ai, sa); - // TODO: this list potentially includes planeswalkers represented as Card objects. This may need further improvement - // (SpellAbilityAi::chooseSingleGameEntity normally expects the list of options to be of the same type). for (GameEntity p : options) { if (p instanceof Player && !ComputerUtilCard.canBeBlockedProfitably((Player)p, attacker)) { return p;