diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index b39679ad6d2..436b2ccfede 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -1982,4 +1982,18 @@ public class ComputerUtil { return hasTarget; } + + public static boolean hasReasonToPlaySaThisTurn(final Player ai, final SpellAbility sa) { + // This is currently used by ComputerUtilCost.willPayUnlessCost to determine if there's a viable reason to cast a spell + // that can be paid for with an untapped shockland. + + if (ai == null || sa == null) { + return false; + } + + AiPlayDecision decision = ((PlayerControllerAi)ai.getController()).getAi().canPlaySa(sa); + boolean willPlay = decision == AiPlayDecision.WillPlay || decision == AiPlayDecision.WaitForMain2; + + return willPlay; + } } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java index cecd9065d28..71f4bcf3a33 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java @@ -7,12 +7,15 @@ import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardLists; +import forge.game.card.CardPredicates; import forge.game.card.CounterType; import forge.game.combat.Combat; import forge.game.cost.*; import forge.game.player.Player; import forge.game.spellability.Spell; import forge.game.spellability.SpellAbility; +import forge.game.spellability.TargetChoices; +import forge.game.spellability.TargetRestrictions; import forge.game.zone.ZoneType; import forge.util.collect.FCollectionView; import forge.util.MyRandom; @@ -420,6 +423,7 @@ public class ComputerUtilCost { // If the new land size would equal the CMC of a card in AIs hand, play it untapped final int landsize = payer.getLandsInPlay().size() + 1; for (Card c : payer.getCardsIn(ZoneType.Hand)) { + int cmc = c.getCMC(); // try to determine if the mana shards provided by the lands would be applicable to pay the mana cost boolean canPay = c.getManaCost().canBePaidWithAvaliable(ColorSet.fromNames(getAvailableManaColors(payer, source)).getColor()); // try to determine that there is a valid target for a spell (very basic, consider expanding) @@ -428,16 +432,13 @@ public class ComputerUtilCost { // for auras, make sure that a good enough target exists requirementsMet = ComputerUtil.hasGoodTargetForAura(payer, c); } else if (c.isSorcery()) { - // for sorceries with one mode that has a target, consider actually having a target that makes the AI decide to play the spell ability + // for sorceries with one mode, consider actually checking for a reason for the AI to decide to play the spell ability if (c.getAllSpellAbilities().size() == 1) { SpellAbility ability = c.getFirstSpellAbility(); - if (ability != null && ability.usesTargeting()) { - AiPlayDecision decision = ((PlayerControllerAi)payer.getController()).getAi().canPlaySa(ability); - requirementsMet = decision == AiPlayDecision.WillPlay || decision == AiPlayDecision.WaitForMain2; - } + requirementsMet = ComputerUtil.hasReasonToPlaySaThisTurn(payer, ability); } } - if (landsize == c.getCMC() && canPay && requirementsMet) { + if (landsize == cmc && canPay && requirementsMet) { return true; } }