From 5c047b3849d8ce88a5dfc6d5a54889d086d1ca73 Mon Sep 17 00:00:00 2001 From: Agetian Date: Fri, 30 Nov 2018 22:12:44 +0300 Subject: [PATCH] - Some updates to Flash and PermanentCreatureAi logic. --- .../src/main/java/forge/ai/ComputerUtil.java | 16 ++++++++++++ .../forge/ai/ability/PermanentCreatureAi.java | 25 +++++++++---------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtil.java b/forge-ai/src/main/java/forge/ai/ComputerUtil.java index bd641d635c9..3ab921871c7 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtil.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtil.java @@ -958,6 +958,22 @@ public class ComputerUtil { return true; } + // if we have non-persistent mana in our pool, would be good to try to use it and not waste it + if (ai.getManaPool().willManaBeLostAtEndOfPhase()) { + boolean canUseToPayCost = false; + for (byte color : MagicColor.WUBRGC) { + if (ai.getManaPool().getAmountOfColor(color) > 0 + && ((card.getManaCost().getColorProfile() & color) == color)) { + canUseToPayCost = true; + break; + } + } + + if (canUseToPayCost) { + return true; + } + } + if (card.isCreature() && !card.hasKeyword(Keyword.DEFENDER) && (card.hasKeyword(Keyword.HASTE) || ComputerUtil.hasACardGivingHaste(ai, true) || sa.isDash())) { return true; diff --git a/forge-ai/src/main/java/forge/ai/ability/PermanentCreatureAi.java b/forge-ai/src/main/java/forge/ai/ability/PermanentCreatureAi.java index 717e69d4c9e..25993d5c7ce 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PermanentCreatureAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PermanentCreatureAi.java @@ -161,6 +161,15 @@ public class PermanentCreatureAi extends PermanentAi { int chanceToCastForETB = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_CAST_DUE_TO_ETB_EFFECTS); int chanceToRespondToStack = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_RESPOND_TO_STACK_WITH_ETB); int chanceToProcETBBeforeMain1 = aic.getIntProperty(AiProps.FLASH_CHANCE_TO_CAST_FOR_ETB_BEFORE_MAIN1); + boolean canCastAtOppTurn = true; + for (Card c : ai.getGame().getCardsIn(ZoneType.Battlefield)) { + for (StaticAbility s : c.getStaticAbilities()) { + if ("CantBeCast".equals(s.getParam("Mode")) && "True".equals(s.getParam("NonCasterTurn"))) { + canCastAtOppTurn = false; + } + } + } + if (hasFloatMana || willDiscardNow || willDieNow) { // Will lose mana in pool or about to discard a card in cleanup or about to die in combat, so use this opportunity @@ -170,7 +179,7 @@ public class PermanentCreatureAi extends PermanentAi { return isMyMain1OrLater; } else if (hasAmbushAI && MyRandom.percentTrue(chanceToObeyAmbushAI)) { // Is an ambusher, so try to hold for declare blockers in combat where the AI defends, if possible - return defOnlyAmbushAI ? isOppDeclareAttackers : (isOppDeclareAttackers || isMyDeclareBlockers); + return defOnlyAmbushAI && canCastAtOppTurn ? isOppDeclareAttackers : (isOppDeclareAttackers || isMyDeclareBlockers); } else if (valuableBlocker && isOppDeclareAttackers && MyRandom.percentTrue(chanceToAddBlocker)) { // Might serve as a valuable blocker in a combat where we are behind on untapped blockers return true; @@ -182,21 +191,11 @@ public class PermanentCreatureAi extends PermanentAi { } else if (hasETBTrigger && canRespondToStack && MyRandom.percentTrue(chanceToRespondToStack)) { // Try to do something meaningful in response to an opposing effect on stack. Note that this is currently // too random to likely be meaningful, serious improvement might be needed. - return true; + return canCastAtOppTurn || ph.getPlayerTurn().equals(ai); } else { - boolean canCastAtOppEOT = true; - for (Card c : ai.getGame().getCardsIn(ZoneType.Battlefield)) { - for (StaticAbility s : c.getStaticAbilities()) { - if ("CantBeCast".equals(s.getParam("Mode")) && "True".equals(s.getParam("NonCasterTurn"))) { - canCastAtOppEOT = false; - } - } - - } - // Doesn't have a ETB trigger and doesn't seem to be good as an ambusher, try to surprise the opp before my turn // TODO: maybe implement a way to reserve mana for this - return canCastAtOppEOT ? isEOTBeforeMyTurn : isOwnEOT; + return canCastAtOppTurn ? isEOTBeforeMyTurn : isOwnEOT; } }