From ae5090a69a05d46a96e85e2282d3a3747ca9fec7 Mon Sep 17 00:00:00 2001 From: Agetian Date: Tue, 4 Dec 2018 14:33:46 +0300 Subject: [PATCH] - More careful use of Buyback spells without Buyback. --- .../src/main/java/forge/ai/AiController.java | 86 +++++++++++-------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 4b708ec5863..537a7666e93 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -801,48 +801,62 @@ public class AiController { if ("True".equals(card.getSVar("NonStackingEffect")) && isNonDisabledCardInPlay(card.getName())) { return AiPlayDecision.NeedsToPlayCriteriaNotMet; } + // Trying to play a card that has Buyback without a Buyback cost - - if (card.hasStartOfKeyword("Buyback")) { - //if (card.getBuybackAbility()!=null) { - if (!sa.isBuyBackAbility()) { - boolean wasteBuybackAllowed = false; - // About to lose game : allow - if (ComputerUtil.aiLifeInDanger(player, true, 0)) { - wasteBuybackAllowed = true; - } - int copies = CardLists.filter(player.getCardsIn(ZoneType.Hand), CardPredicates.nameEquals(card.getName())).size(); - // Have two copies : allow - if (copies >= 2) { - wasteBuybackAllowed = true; - } - // Won't be able to afford buyback any time soon - // If Buyback cost includes sacrifice, life, discard - int neededMana = 0; - for (SpellAbility sa2 : GameActionUtil.getOptionalCosts(sa)) { - if (sa2.isOptionalCostPaid(OptionalCost.Buyback)) { - Cost sac = sa2.getPayCosts(); - CostAdjustment.adjust(sac, sa2); // Does not recognize Memory Crystal anyway??? - neededMana = sac.getCostMana().getMana().getCMC(); - if (sac.hasSpecificCostType(CostPayLife.class) - || (sac.hasSpecificCostType(CostDiscard.class)) || - (sac.hasSpecificCostType(CostSacrifice.class))) { - neededMana = 999; - } - } - } - int hasMana = ComputerUtilMana.getAvailableManaEstimate(player, false); - if (hasMana < neededMana - 1) { - wasteBuybackAllowed = true; - } - - if (!wasteBuybackAllowed) return AiPlayDecision.NeedsToPlayCriteriaNotMet; - } + if (card.hasKeyword(Keyword.BUYBACK) && !sa.isBuyBackAbility() && !canPlaySpellWithoutBuyback(card, sa)) { + return AiPlayDecision.NeedsToPlayCriteriaNotMet; } + // add any other necessary logic to play a basic spell here return ComputerUtilCard.checkNeedsToPlayReqs(card, sa); } + private boolean canPlaySpellWithoutBuyback(Card card, SpellAbility sa) { + boolean wasteBuybackAllowed = false; + + // About to lose game : allow + if (ComputerUtil.aiLifeInDanger(player, true, 0)) { + wasteBuybackAllowed = true; + } + + int copies = CardLists.filter(player.getCardsIn(ZoneType.Hand), CardPredicates.nameEquals(card.getName())).size(); + // Have two copies : allow + if (copies >= 2) { + wasteBuybackAllowed = true; + + } + + int neededMana = 0; + boolean dangerousRecurringCost = false; + for (SpellAbility sa2 : GameActionUtil.getOptionalCosts(sa)) { + if (sa2.isOptionalCostPaid(OptionalCost.Buyback)) { + Cost sac = sa2.getPayCosts(); + CostAdjustment.adjust(sac, sa2); // TODO: Does not recognize Memory Crystal + if (sac.getCostMana() != null) { + neededMana = sac.getCostMana().getMana().getCMC(); + } + if (sac.hasSpecificCostType(CostPayLife.class) + || sac.hasSpecificCostType(CostDiscard.class) + || sac.hasSpecificCostType(CostSacrifice.class)) { + dangerousRecurringCost = true; + } + } + } + + // won't be able to afford buyback any time soon + // if Buyback cost includes sacrifice, life, discard + if (dangerousRecurringCost) { + wasteBuybackAllowed = true; + } + + int hasMana = ComputerUtilMana.getAvailableManaEstimate(player, false); + if (hasMana < neededMana - 1) { + wasteBuybackAllowed = true; + } + + return wasteBuybackAllowed; + } + // not sure "playing biggest spell" matters? private final static Comparator saComparator = new Comparator() { @Override