From 1acd48be9ecee684fd15b862294f81a9ad6d2c23 Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 19 Jul 2016 19:34:02 +0000 Subject: [PATCH] - Attempted fix for the Token AI crashing when the AI is trying to decide which player/planeswalker to attack with a spawned token. Consider improving. --- .../main/java/forge/ai/SpellAbilityAi.java | 2 +- .../main/java/forge/ai/ability/TokenAi.java | 22 +++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java index 98f2a55b71a..3e4439530d2 100644 --- a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java @@ -244,7 +244,7 @@ public abstract class SpellAbilityAi { } - protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable options) { + 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"); return Iterables.getFirst(options, 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 960b5e2e688..9b2a844cb4f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java @@ -12,6 +12,7 @@ import forge.ai.ComputerUtilMana; import forge.ai.SpellAbilityAi; import forge.ai.SpellApiToAi; import forge.game.Game; +import forge.game.GameEntity; import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; @@ -308,14 +309,27 @@ public class TokenAi extends SpellAbilityAi { * @see forge.card.ability.SpellAbilityAi#chooseSinglePlayer(forge.game.player.Player, forge.card.spellability.SpellAbility, Iterable options) */ @Override - protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable options) { + protected GameEntity chooseSinglePlayer(Player ai, SpellAbility sa, Iterable options) { // TODO: AILogic Combat combat = ai.getGame().getCombat(); - // TokenAttacking + // TokenAttacking if (combat != null && sa.hasParam("TokenAttacking")) { + // 1. If the card that spawned the token was sent at a planeswalker, attack the same planeswalker with the token. Consider improving. + GameEntity def = combat.getDefenderByAttacker(sa.getHostCard()); + if (def != null && def instanceof Card) { + if (((Card)def).isPlaneswalker()) { + return def; + } + } + // 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); - for (Player p : options) { - if (!ComputerUtilCard.canBeBlockedProfitably(p, attacker)) { + // 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; + } + if (p instanceof Card && !ComputerUtilCard.canBeBlockedProfitably(((Card)p).getController(), attacker)) { return p; } }