From 50442b99099a39c0957a1b00f82bc40377ff5e1e Mon Sep 17 00:00:00 2001 From: Michael Kamensky Date: Sun, 31 Oct 2021 12:43:20 +0300 Subject: [PATCH] - More advanced implementation for vs-Ward AI --- .../src/main/java/forge/ai/AiController.java | 18 ++++++++++++++++-- .../main/java/forge/ai/ComputerUtilCard.java | 14 ++++++++++++++ .../main/java/forge/ai/ComputerUtilCost.java | 5 ++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index fbd5f8b6c96..9dc299a78fd 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -739,8 +739,22 @@ public class AiController { if (sa.usesTargeting()) { for (Card tgt : sa.getTargets().getTargetCards()) { if (tgt.hasKeyword(Keyword.WARD)) { - int amount = tgt.getKeywordMagnitude(Keyword.WARD); - if (amount > 0 && !ComputerUtilCost.canPayCost(sa, player)) { + int amount = 0; + Cost wardCost = ComputerUtilCard.getTotalWardCost(tgt); + if (wardCost.hasManaCost()) { + amount = wardCost.getTotalMana().getCMC(); + if (amount > 0 && !ComputerUtilCost.canPayCost(sa, player)) { + return AiPlayDecision.CantAfford; + } + } + if (wardCost.hasSpecificCostType(CostPayLife.class)) { + int lifeToPay = wardCost.getCostPartByType(CostPayLife.class).convertAmount(); + if (lifeToPay > player.getLife() || (lifeToPay == player.getLife() && !player.cantLoseForZeroOrLessLife())) { + return AiPlayDecision.CantAfford; + } + } + if (wardCost.hasSpecificCostType(CostDiscard.class) + && wardCost.getCostPartByType(CostDiscard.class).convertAmount() > player.getCardsIn(ZoneType.Hand).size()) { return AiPlayDecision.CantAfford; } } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 81e504e62ed..7b478efb21d 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -11,6 +11,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import forge.card.mana.ManaCost; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -1971,6 +1972,19 @@ public class ComputerUtilCard { return AiPlayDecision.WillPlay; } + public static Cost getTotalWardCost(Card c) { + Cost totalCost = new Cost(ManaCost.NO_COST, false); + for (final KeywordInterface inst : c.getKeywords()) { + if (inst.getKeyword() == Keyword.WARD) { + final String keyword = inst.getOriginal(); + final String[] k = keyword.split(":"); + final Cost wardCost = new Cost(k[1], false); + totalCost = totalCost.add(wardCost); + } + } + return totalCost; + } + // Determine if the AI has an AI:RemoveDeck:All or an AI:RemoveDeck:Random hint specified. // Includes a NPE guard on getRules() which might otherwise be tripped on some cards (e.g. tokens). public static boolean isCardRemAIDeck(final Card card) { diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java index cb37f9c4f10..fd76612d1f7 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java @@ -593,7 +593,10 @@ public class ComputerUtilCost { if (sa.usesTargeting()) { for (Card tgt : sa.getTargets().getTargetCards()) { if (tgt.hasKeyword(Keyword.WARD)) { - extraManaNeeded += tgt.getKeywordMagnitude(Keyword.WARD); + Cost wardCost = ComputerUtilCard.getTotalWardCost(tgt); + if (wardCost.hasManaCost()) { + extraManaNeeded += wardCost.getTotalMana().getCMC(); + } } } }