From c3f7640c4da2800e3ee22c09d19ab8221225397f Mon Sep 17 00:00:00 2001 From: Agetian Date: Sun, 1 Oct 2017 18:10:12 +0000 Subject: [PATCH] - A [hacky] fix to avoid the AI cheating with Thought Lash (otherwise it keeps exiling 1 card to it, no matter how many age counters are on it, essentially by "exiling" (not) the same card multiple times). A better solution is needed, feel free to improve. --- .../java/forge/ai/PlayerControllerAi.java | 22 +++++++++++-- .../java/forge/game/cost/CostPayment.java | 33 +++++++++++++++++-- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 7c47adb02ad..a422c1f19d8 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -25,9 +25,7 @@ import forge.game.ability.ApiType; import forge.game.card.*; import forge.game.card.CardPredicates.Presets; import forge.game.combat.Combat; -import forge.game.cost.Cost; -import forge.game.cost.CostPart; -import forge.game.cost.CostPartMana; +import forge.game.cost.*; import forge.game.mana.Mana; import forge.game.mana.ManaCostBeingPaid; import forge.game.phase.PhaseHandler; @@ -466,6 +464,24 @@ public class PlayerControllerAi extends PlayerController { final Ability ability = new AbilityStatic(c, cost, null) { @Override public void resolve() {} }; ability.setActivatingPlayer(c.getController()); + // FIXME: This is a hack to check if the AI can play the "exile from library" pay costs (Cumulative Upkeep, + // e.g. Thought Lash). We have to do it early since the cost will later be reconsolidated into a single + // payment for the AI, to avoid cheating (otherwise the AI repeatedly "exiles" the same card multiple times) + int nExileLib = 0; + List parts = CostAdjustment.adjust(cost, sa).getCostParts(); + for (final CostPart part : parts) { + if (part instanceof CostExile) { + CostExile exile = (CostExile) part; + if (exile.from == ZoneType.Library) { + nExileLib += exile.convertAmount(); + } + } + } + if (nExileLib > c.getController().getCardsIn(ZoneType.Library).size()) { + return false; + } + // - End of hack for Exile a card from library Cumulative Upkeep - + if (ComputerUtilCost.canPayCost(ability, c.getController())) { ComputerUtil.playNoStack(c.getController(), ability, game); return true; diff --git a/forge-game/src/main/java/forge/game/cost/CostPayment.java b/forge-game/src/main/java/forge/game/cost/CostPayment.java index 8a9e8d1cfc4..f9c18102ffe 100644 --- a/forge-game/src/main/java/forge/game/cost/CostPayment.java +++ b/forge-game/src/main/java/forge/game/cost/CostPayment.java @@ -17,16 +17,16 @@ */ package forge.game.cost; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import forge.game.Game; import forge.game.card.Card; import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; import java.util.List; import java.util.Map; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - /** *

* Cost_Payment class. @@ -169,6 +169,33 @@ public class CostPayment { // Set all of the decisions before attempting to pay anything final Game game = decisionMaker.getPlayer().getGame(); + + // FIXME: This is a hack which is necessary to make the AI pay the Cumulative Upkeep with "Exile a card from + // the top of your library" (Thought Lash) without cheating. Otherwise the AI pays only one card, no matter + // the age counters. We need a better solution here. + int nExileLib = 0; + List partsToChange = Lists.newArrayList(); + CostExile primeExile = null; + for (final CostPart part : parts) { + if (part instanceof CostExile) { + CostExile exile = (CostExile) part; + if (exile.from == ZoneType.Library) { + nExileLib += exile.convertAmount(); + if (nExileLib == 1) { + primeExile = exile; + } else { + partsToChange.add(exile); + } + } + } + } + if (nExileLib > 1 && primeExile != null) { + parts.removeAll(partsToChange); + primeExile.setAmount(String.valueOf(nExileLib)); + } + // - End of hack for Cumulative Upkeep: Exile a card from the top of your library - + + for (final CostPart part : parts) { PaymentDecision decision = part.accept(decisionMaker); if (null == decision) return false;