diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index f264dc1dee1..aada962ccb5 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -1732,6 +1732,17 @@ public class ComputerUtil { return safeCards; } + public static Card getKilledByTargeting(final SpellAbility sa, CardCollectionView validCards) { + CardCollection killables = new CardCollection(validCards); + killables = CardLists.filter(killables, new Predicate() { + @Override + public boolean apply(final Card c) { + return c.getController() != sa.getActivatingPlayer() && c.getSVar("Targeting").equals("Dies"); + } + }); + return ComputerUtilCard.getBestCreatureAI(killables); + } + public static int damageFromETB(final Player player, final Card permanent) { int damage = 0; final Game game = player.getGame(); diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java index d362b4e72df..cb186910b60 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java @@ -170,8 +170,9 @@ public class DamageDealAi extends DamageAiBase { final List killables = CardLists.filter(hPlay, new Predicate() { @Override public boolean apply(final Card c) { - return (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d) && !ComputerUtil.canRegenerate(ai, c) - && !(c.getSVar("SacMe").length() > 0); + return c.getSVar("Targeting").equals("Dies") + || (ComputerUtilCombat.getEnoughDamageToKill(c, d, source, false, noPrevention) <= d) && !ComputerUtil.canRegenerate(ai, c) + && !(c.getSVar("SacMe").length() > 0); } }); diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java b/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java index 7a36ac1d30b..e5212e0f909 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java @@ -467,10 +467,10 @@ public abstract class PumpAiBase extends SpellAbilityAi { list = CardLists.filter(list, new Predicate() { @Override public boolean apply(final Card c) { - if (c.getNetToughness() <= -defense) { + if (c.getSVar("Targeting").equals("Dies") || c.getNetToughness() <= -defense) { return true; // can kill indestructible creatures } - return ((ComputerUtilCombat.getDamageToKill(c) <= -defense) && !c.hasKeyword("Indestructible")); + return (ComputerUtilCombat.getDamageToKill(c) <= -defense && !c.hasKeyword("Indestructible")); } }); // leaves all creatures that will be destroyed } // -X/-X end diff --git a/forge-ai/src/main/java/forge/ai/ability/TapAiBase.java b/forge-ai/src/main/java/forge/ai/ability/TapAiBase.java index 0d191002525..d35a73fd222 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TapAiBase.java +++ b/forge-ai/src/main/java/forge/ai/ability/TapAiBase.java @@ -47,7 +47,7 @@ public abstract class TapAiBase extends SpellAbilityAi { tapList.remove(c); } - if (tapList.size() == 0) { + if (tapList.isEmpty()) { return false; } @@ -55,7 +55,7 @@ public abstract class TapAiBase extends SpellAbilityAi { Card choice = null; if (tapList.size() == 0) { - if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa)) || (sa.getTargets().getNumTargeted() == 0)) { + if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa) || sa.getTargets().getNumTargeted() == 0) { if (!mandatory) { sa.resetTargets(); } @@ -68,7 +68,7 @@ public abstract class TapAiBase extends SpellAbilityAi { } } - if (CardLists.getNotType(tapList, "Creature").size() == 0) { + if (CardLists.getNotType(tapList, "Creature").isEmpty()) { // if only creatures take the best choice = ComputerUtilCard.getBestCreatureAI(tapList); } else { @@ -76,7 +76,7 @@ public abstract class TapAiBase extends SpellAbilityAi { } if (choice == null) { // can't find anything left - if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) || (sa.getTargets().getNumTargeted() == 0)) { + if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa) || sa.getTargets().getNumTargeted() == 0) { if (!mandatory) { sa.resetTargets(); } @@ -117,9 +117,9 @@ public abstract class TapAiBase extends SpellAbilityAi { final Player opp = ai.getOpponent(); final Game game = ai.getGame(); CardCollection tapList = CardLists.filterControlledBy(game.getCardsIn(ZoneType.Battlefield), ai.getOpponents()); - tapList = CardLists.filter(tapList, Presets.UNTAPPED); tapList = CardLists.getValidCards(tapList, tgt.getValidTgts(), source.getController(), source); tapList = CardLists.getTargetableCards(tapList, sa); + tapList = CardLists.filter(tapList, Presets.UNTAPPED); tapList = CardLists.filter(tapList, new Predicate() { @Override public boolean apply(final Card c) { @@ -162,17 +162,18 @@ public abstract class TapAiBase extends SpellAbilityAi { return false; } + boolean goodTargets = false; while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(source, sa)) { Card choice = null; if (tapList.isEmpty()) { - if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa)) || (sa.getTargets().getNumTargeted() == 0)) { + if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(source, sa) || sa.getTargets().getNumTargeted() == 0) { if (!mandatory) { sa.resetTargets(); } return false; } else { - if (!ComputerUtil.shouldCastLessThanMax(ai, source)) { + if (!goodTargets && !ComputerUtil.shouldCastLessThanMax(ai, source)) { return false; } break; @@ -180,8 +181,11 @@ public abstract class TapAiBase extends SpellAbilityAi { } PhaseHandler phase = game.getPhaseHandler(); - if (phase.isPlayerTurn(ai) - && phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS)) { + Card primeTarget = ComputerUtil.getKilledByTargeting(sa, tapList); + if (primeTarget != null) { + choice = primeTarget; + goodTargets = true; + } else if (phase.isPlayerTurn(ai) && phase.getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS)) { // Tap creatures possible blockers before combat during AI's turn. List attackers; if (phase.getPhase().isAfter(PhaseType.COMBAT_DECLARE_ATTACKERS)) { @@ -224,7 +228,7 @@ public abstract class TapAiBase extends SpellAbilityAi { } if (choice == null) { // can't find anything left - if ((sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa)) || (sa.getTargets().getNumTargeted() == 0)) { + if (sa.getTargets().getNumTargeted() < tgt.getMinTargets(sa.getHostCard(), sa) || sa.getTargets().getNumTargeted() == 0) { if (!mandatory) { sa.resetTargets(); }