diff --git a/forge-ai/src/main/java/forge/ai/AiProps.java b/forge-ai/src/main/java/forge/ai/AiProps.java index d319c66b09f..a5e38d27abc 100644 --- a/forge-ai/src/main/java/forge/ai/AiProps.java +++ b/forge-ai/src/main/java/forge/ai/AiProps.java @@ -53,11 +53,16 @@ public enum AiProps { /** */ CHANCE_TO_TRADE_TO_SAVE_PLANESWALKER ("70"), /** */ CHANCE_TO_TRADE_DOWN_TO_SAVE_PLANESWALKER ("0"), /** */ THRESHOLD_CHUMP_TO_SAVE_PLANESWALKER ("-1"), /** */ - MIN_SPELL_CMC_TO_COUNTER ("0"), + MIN_SPELL_CMC_TO_COUNTER ("0"), /** */ + CHANCE_TO_COUNTER_CMC_1 ("50"), /** */ + CHANCE_TO_COUNTER_CMC_2 ("75"), /** */ + CHANCE_TO_COUNTER_CMC_3 ("100"), /** */ ALWAYS_COUNTER_OTHER_COUNTERSPELLS ("true"), /** */ ALWAYS_COUNTER_DAMAGE_SPELLS ("true"), /** */ ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS ("true"), /** */ ALWAYS_COUNTER_REMOVAL_SPELLS ("true"), /** */ + ALWAYS_COUNTER_PUMP_SPELLS ("true"), /** */ + ALWAYS_COUNTER_AURAS ("true"), /** */ ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS (""), /** */ ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS ("false"), /** */ PRIORITY_REDUCTION_FOR_STORM_SPELLS ("0"), /** */ diff --git a/forge-ai/src/main/java/forge/ai/ability/CounterAi.java b/forge-ai/src/main/java/forge/ai/ability/CounterAi.java index 4071229b7eb..0ac11fd568d 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CounterAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CounterAi.java @@ -144,14 +144,31 @@ public class CounterAi extends SpellAbilityAi { boolean ctrCmc0ManaPerms = aic.getBooleanProperty(AiProps.ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS); boolean ctrDamageSpells = aic.getBooleanProperty(AiProps.ALWAYS_COUNTER_DAMAGE_SPELLS); boolean ctrRemovalSpells = aic.getBooleanProperty(AiProps.ALWAYS_COUNTER_REMOVAL_SPELLS); + boolean ctrPumpSpells = aic.getBooleanProperty(AiProps.ALWAYS_COUNTER_PUMP_SPELLS); + boolean ctrAuraSpells = aic.getBooleanProperty(AiProps.ALWAYS_COUNTER_AURAS); boolean ctrOtherCounters = aic.getBooleanProperty(AiProps.ALWAYS_COUNTER_OTHER_COUNTERSPELLS); + int ctrChanceCMC1 = aic.getIntProperty(AiProps.CHANCE_TO_COUNTER_CMC_1); + int ctrChanceCMC2 = aic.getIntProperty(AiProps.CHANCE_TO_COUNTER_CMC_2); + int ctrChanceCMC3 = aic.getIntProperty(AiProps.CHANCE_TO_COUNTER_CMC_3); String ctrNamed = aic.getProperty(AiProps.ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS); + boolean dontCounter = false; + + if (tgtCMC == 1 && !MyRandom.percentTrue(ctrChanceCMC1)) { + dontCounter = true; + } else if (tgtCMC == 2 && !MyRandom.percentTrue(ctrChanceCMC2)) { + dontCounter = true; + } else if (tgtCMC == 3 && !MyRandom.percentTrue(ctrChanceCMC3)) { + dontCounter = true; + } + if (tgtSA != null && tgtCMC < aic.getIntProperty(AiProps.MIN_SPELL_CMC_TO_COUNTER)) { - boolean dontCounter = true; + dontCounter = true; Card tgtSource = tgtSA.getHostCard(); if ((tgtSource != null && tgtCMC == 0 && tgtSource.isPermanent() && !tgtSource.getManaAbilities().isEmpty() && ctrCmc0ManaPerms) || (tgtSA.getApi() == ApiType.DealDamage || tgtSA.getApi() == ApiType.LoseLife || tgtSA.getApi() == ApiType.DamageAll && ctrDamageSpells) || (tgtSA.getApi() == ApiType.Counter && ctrOtherCounters) + || ((tgtSA.getApi() == ApiType.Pump || tgtSA.getApi() == ApiType.PumpAll) && ctrPumpSpells) + || (tgtSA.getApi() == ApiType.Attach && ctrAuraSpells) || (tgtSA.getApi() == ApiType.Destroy || tgtSA.getApi() == ApiType.DestroyAll || tgtSA.getApi() == ApiType.Sacrifice || tgtSA.getApi() == ApiType.SacrificeAll && ctrRemovalSpells)) { dontCounter = false; @@ -164,8 +181,8 @@ public class CounterAi extends SpellAbilityAi { } } } - - // should not refrain from countering a CMC X spell if that's the only CMC + + // should not refrain from countering a CMC X spell if that's the only CMC // counterable with that particular counterspell type (e.g. Mental Misstep vs. CMC 1 spells) if (sa.getParamOrDefault("ValidTgts", "").startsWith("Card.cmcEQ")) { int validTgtCMC = AbilityUtils.calculateAmount(source, sa.getParam("ValidTgts").substring(10), sa); @@ -173,12 +190,12 @@ public class CounterAi extends SpellAbilityAi { dontCounter = false; } } - - if (dontCounter) { - return false; - } } - + + if (dontCounter) { + return false; + } + return toReturn; } diff --git a/forge-gui/res/ai/Cautious.ai b/forge-gui/res/ai/Cautious.ai index c0fa1371469..36615b2ecde 100644 --- a/forge-gui/res/ai/Cautious.ai +++ b/forge-gui/res/ai/Cautious.ai @@ -80,12 +80,17 @@ RESERVE_MANA_FOR_MAIN2_CHANCE=100 # If enabled, the AI will target artifacts and non-aura enchantments with removal aggressively ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true -# Counterspell timings +# Permission timings MIN_SPELL_CMC_TO_COUNTER=2 +CHANCE_TO_COUNTER_CMC_1=0 +CHANCE_TO_COUNTER_CMC_2=50 +CHANCE_TO_COUNTER_CMC_3=100 ALWAYS_COUNTER_OTHER_COUNTERSPELLS=true ALWAYS_COUNTER_DAMAGE_SPELLS=true ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS=true ALWAYS_COUNTER_REMOVAL_SPELLS=true +ALWAYS_COUNTER_PUMP_SPELLS=false +ALWAYS_COUNTER_AURAS=true ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS=None # Storm spell logic diff --git a/forge-gui/res/ai/Default.ai b/forge-gui/res/ai/Default.ai index 433d81edb96..78323e58c40 100644 --- a/forge-gui/res/ai/Default.ai +++ b/forge-gui/res/ai/Default.ai @@ -80,12 +80,17 @@ RESERVE_MANA_FOR_MAIN2_CHANCE=100 # If enabled, the AI will target artifacts and non-aura enchantments with removal aggressively ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true -# Counterspell timings +# Permission timings MIN_SPELL_CMC_TO_COUNTER=0 +CHANCE_TO_COUNTER_CMC_1=30 +CHANCE_TO_COUNTER_CMC_2=75 +CHANCE_TO_COUNTER_CMC_3=100 ALWAYS_COUNTER_OTHER_COUNTERSPELLS=true ALWAYS_COUNTER_DAMAGE_SPELLS=true ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS=true ALWAYS_COUNTER_REMOVAL_SPELLS=true +ALWAYS_COUNTER_PUMP_SPELLS=true +ALWAYS_COUNTER_AURAS=true ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS=None # Storm spell logic diff --git a/forge-gui/res/ai/Experimental.ai b/forge-gui/res/ai/Experimental.ai index 88aa6252fda..627adaff8e8 100644 --- a/forge-gui/res/ai/Experimental.ai +++ b/forge-gui/res/ai/Experimental.ai @@ -80,12 +80,17 @@ RESERVE_MANA_FOR_MAIN2_CHANCE=100 # If enabled, the AI will target artifacts and non-aura enchantments with removal aggressively ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true -# Counterspell timings +# Permission timings MIN_SPELL_CMC_TO_COUNTER=2 +CHANCE_TO_COUNTER_CMC_1=30 +CHANCE_TO_COUNTER_CMC_2=75 +CHANCE_TO_COUNTER_CMC_3=100 ALWAYS_COUNTER_OTHER_COUNTERSPELLS=true ALWAYS_COUNTER_DAMAGE_SPELLS=true ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS=true ALWAYS_COUNTER_REMOVAL_SPELLS=true +ALWAYS_COUNTER_PUMP_SPELLS=true +ALWAYS_COUNTER_AURAS=true ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS=None # Storm spell logic diff --git a/forge-gui/res/ai/Reckless.ai b/forge-gui/res/ai/Reckless.ai index 652d223faae..daa89678141 100644 --- a/forge-gui/res/ai/Reckless.ai +++ b/forge-gui/res/ai/Reckless.ai @@ -80,12 +80,17 @@ RESERVE_MANA_FOR_MAIN2_CHANCE=100 # If enabled, the AI will target artifacts and non-aura enchantments with removal aggressively ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=true -# Counterspell timings +# Permission timings MIN_SPELL_CMC_TO_COUNTER=0 +CHANCE_TO_COUNTER_CMC_1=80 +CHANCE_TO_COUNTER_CMC_2=100 +CHANCE_TO_COUNTER_CMC_3=100 ALWAYS_COUNTER_OTHER_COUNTERSPELLS=true ALWAYS_COUNTER_DAMAGE_SPELLS=true ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS=true ALWAYS_COUNTER_REMOVAL_SPELLS=true +ALWAYS_COUNTER_PUMP_SPELLS=true +ALWAYS_COUNTER_AURAS=true ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS=None # Storm spell logic