From fcc3a28b8637fb2458512e69b203e15de35dc635 Mon Sep 17 00:00:00 2001 From: Agetian Date: Sun, 11 Nov 2018 17:38:32 +0300 Subject: [PATCH] - Fixed logic in reserving mana for combat tricks. --- forge-ai/src/main/java/forge/ai/AiController.java | 15 +++++++++++---- .../src/main/java/forge/ai/ComputerUtilCard.java | 12 ++++++++---- .../src/main/java/forge/ai/ability/FogAi.java | 6 ++++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 0da3b6d1a80..bf52438f8cc 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -628,16 +628,19 @@ public class AiController { return null; } - public void reserveManaSources(SpellAbility sa) { - reserveManaSources(sa, PhaseType.MAIN2, false); + public boolean reserveManaSources(SpellAbility sa) { + return reserveManaSources(sa, PhaseType.MAIN2, false); } - public void reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy) { + public boolean reserveManaSources(SpellAbility sa, PhaseType phaseType, boolean enemy) { ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, true, 0); CardCollection manaSources = ComputerUtilMana.getManaSourcesToPayCost(cost, sa, player); - AiCardMemory.MemorySet memSet; + if (manaSources.isEmpty()) { + return false; + } + AiCardMemory.MemorySet memSet; switch (phaseType) { case MAIN2: memSet = AiCardMemory.MemorySet.HELD_MANA_SOURCES_FOR_MAIN2; @@ -656,6 +659,10 @@ public class AiController { for (Card c : manaSources) { AiCardMemory.rememberCard(player, c, memSet); } + + // This is a simplification, since one mana source can produce more than one mana, + // but should work in most circumstances to ensure safety in whatever the AI is using this for. + return manaSources.size() >= cost.getConvertedManaCost(); } // This is for playing spells regularly (no Cascade/Ripple etc.) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 42c1fec448b..b2d53e838fb 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -1508,14 +1508,18 @@ public class ComputerUtilCard { // Attempt to hold combat tricks until blockers are declared, and try to lure the opponent into blocking // (The AI will only do it for one attacker at the moment, otherwise it risks running his attackers into // an army of opposing blockers with only one combat trick in hand) - AiCardMemory.rememberCard(ai, c, AiCardMemory.MemorySet.MANDATORY_ATTACKERS); - AiCardMemory.rememberCard(ai, c, AiCardMemory.MemorySet.TRICK_ATTACKERS); // Reserve the mana until Declare Blockers such that the AI doesn't tap out before having a chance to use // the combat trick + boolean reserved = false; if (ai.getController().isAI()) { - ((PlayerControllerAi) ai.getController()).getAi().reserveManaSources(sa, PhaseType.COMBAT_DECLARE_BLOCKERS, false); + reserved = ((PlayerControllerAi) ai.getController()).getAi().reserveManaSources(sa, PhaseType.COMBAT_DECLARE_BLOCKERS, false); + // Only proceed with this if we could actually reserve mana + if (reserved) { + AiCardMemory.rememberCard(ai, c, AiCardMemory.MemorySet.MANDATORY_ATTACKERS); + AiCardMemory.rememberCard(ai, c, AiCardMemory.MemorySet.TRICK_ATTACKERS); + return false; + } } - return false; } else { // Don't try to mix "lure" and "precast" paradigms for combat tricks, since that creates issues with // the AI overextending the attack diff --git a/forge-ai/src/main/java/forge/ai/ability/FogAi.java b/forge-ai/src/main/java/forge/ai/ability/FogAi.java index 09034ee8d7a..ecdb0c03b4f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/FogAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/FogAi.java @@ -45,8 +45,10 @@ public class FogAi extends SpellAbilityAi { || (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_BLOCKERS))) && (AiCardMemory.isMemorySetEmpty(ai, AiCardMemory.MemorySet.CHOSEN_FOG_EFFECT)) && (ComputerUtil.aiLifeInDanger(ai, false, 0))) { - ((PlayerControllerAi) ai.getController()).getAi().reserveManaSources(sa, PhaseType.COMBAT_DECLARE_BLOCKERS, true); - AiCardMemory.rememberCard(ai, hostCard, AiCardMemory.MemorySet.CHOSEN_FOG_EFFECT); + boolean reserved = ((PlayerControllerAi) ai.getController()).getAi().reserveManaSources(sa, PhaseType.COMBAT_DECLARE_BLOCKERS, true); + if (reserved) { + AiCardMemory.rememberCard(ai, hostCard, AiCardMemory.MemorySet.CHOSEN_FOG_EFFECT); + } } // AI should only activate this during Human's Declare Blockers phase