diff --git a/forge-ai/src/main/java/forge/ai/AiProps.java b/forge-ai/src/main/java/forge/ai/AiProps.java index e690516d685..1cd25db3f3c 100644 --- a/forge-ai/src/main/java/forge/ai/AiProps.java +++ b/forge-ai/src/main/java/forge/ai/AiProps.java @@ -45,7 +45,12 @@ public enum AiProps { /** */ ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS ("false"), /** */ PRIORITY_REDUCTION_FOR_STORM_SPELLS ("0"), /** */ USE_BERSERK_AGGRESSIVELY ("false"), /** */ - MIN_COUNT_FOR_STORM_SPELLS ("0"); /** */ + MIN_COUNT_FOR_STORM_SPELLS ("0"), /** */ + STRIPMINE_MIN_LANDS_IN_HAND_TO_ACTIVATE ("1"), /** */ + STRIPMINE_MIN_LANDS_FOR_NO_TIMING_CHECK ("3"), /** */ + STRIPMINE_MIN_LANDS_OTB_FOR_NO_TEMPO_CHECK ("6"), /** */ + STRIPMINE_MAX_LANDS_TO_ATTEMPT_MANALOCKING ("3"), /** */ + STRIPMINE_HIGH_PRIORITY_ON_SKIPPED_LANDDROP ("false"); /** */ private final String strDefaultVal; diff --git a/forge-ai/src/main/java/forge/ai/ability/DestroyAi.java b/forge-ai/src/main/java/forge/ai/ability/DestroyAi.java index 978a5db4ce7..5d7451671a3 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DestroyAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DestroyAi.java @@ -1,11 +1,14 @@ package forge.ai.ability; import com.google.common.base.Predicate; +import forge.ai.AiController; +import forge.ai.AiProps; import forge.ai.ComputerUtil; import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCost; import forge.ai.ComputerUtilMana; +import forge.ai.PlayerControllerAi; import forge.ai.SpellAbilityAi; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; @@ -405,15 +408,25 @@ public class DestroyAi extends SpellAbilityAi { Player tgtPlayer = tgtLand.getController(); int oppLandsOTB = tgtPlayer.getLandsInPlay().size(); + // AI profile-dependent properties + AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); + int amountNoTempoCheck = aic.getIntProperty(AiProps.STRIPMINE_MIN_LANDS_OTB_FOR_NO_TEMPO_CHECK); + int amountNoTimingCheck = aic.getIntProperty(AiProps.STRIPMINE_MIN_LANDS_FOR_NO_TIMING_CHECK); + int amountLandsInHand = aic.getIntProperty(AiProps.STRIPMINE_MIN_LANDS_IN_HAND_TO_ACTIVATE); + int amountLandsToManalock = aic.getIntProperty(AiProps.STRIPMINE_MAX_LANDS_TO_ATTEMPT_MANALOCKING); + boolean highPriorityIfNoLandDrop = aic.getBooleanProperty(AiProps.STRIPMINE_HIGH_PRIORITY_ON_SKIPPED_LANDDROP); + // if the opponent didn't play a land and has few lands OTB, might be worth mana-locking him PhaseHandler ph = ai.getGame().getPhaseHandler(); boolean oppSkippedLandDrop = (tgtPlayer.getLandsPlayedLastTurn() == 0 && ph.isPlayerTurn(ai)) || (tgtPlayer.getLandsPlayedThisTurn() == 0 && ph.isPlayerTurn(tgtPlayer) && ph.getPhase().isAfter(PhaseType.MAIN2)); - boolean canManaLock = oppLandsOTB <= 3 && oppSkippedLandDrop; + boolean canManaLock = oppLandsOTB <= amountLandsToManalock && oppSkippedLandDrop; // Best target is a basic land, and there's only one of it, so destroying it may potentially color-lock the opponent + // (triggers either if the opponent skipped a land drop or if there are quite a few lands already in play but only one of the given type) CardCollection oppLands = tgtPlayer.getLandsInPlay(); - boolean canColorLock = oppSkippedLandDrop && tgtLand.isBasicLand() && CardLists.filter(oppLands, CardPredicates.nameEquals(tgtLand.getName())).size() == 1; + boolean canColorLock = (oppSkippedLandDrop || oppLands.size() > 3) + && tgtLand.isBasicLand() && CardLists.filter(oppLands, CardPredicates.nameEquals(tgtLand.getName())).size() == 1; // Non-basic lands are currently not ranked in any way in ComputerUtilCard#getBestLandAI, so if a non-basic land is best target, // consider killing it off unless there's too much potential tempo loss. @@ -424,7 +437,13 @@ public class DestroyAi extends SpellAbilityAi { // Try not to lose tempo too much and not to mana-screw yourself when considering this logic int numLandsInHand = CardLists.filter(ai.getCardsIn(ZoneType.Hand), CardPredicates.Presets.LANDS_PRODUCING_MANA).size(); int numLandsOTB = CardLists.filter(ai.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.LANDS_PRODUCING_MANA).size(); - boolean tempoCheck = numLandsOTB > 5 || (numLandsInHand > 0 && ((numLandsInHand + numLandsOTB > 2) || canManaLock || canColorLock || nonBasicTgt)); + + // If the opponent skipped a land drop, consider not looking at having the extra land in hand if the profile allows it + boolean isHighPriority = highPriorityIfNoLandDrop && oppSkippedLandDrop; + + boolean timingCheck = canManaLock || canColorLock || nonBasicTgt; + boolean tempoCheck = numLandsOTB >= amountNoTempoCheck + || ((numLandsInHand >= amountLandsInHand || isHighPriority) && ((numLandsInHand + numLandsOTB >= amountNoTimingCheck) || timingCheck)); return tempoCheck; } diff --git a/forge-gui/res/ai/Cautious.ai b/forge-gui/res/ai/Cautious.ai index 616bd108f86..8f103307bf6 100644 --- a/forge-gui/res/ai/Cautious.ai +++ b/forge-gui/res/ai/Cautious.ai @@ -1,23 +1,32 @@ +# Aggro preferences (enabling these will generally make the AI attack more aggressively) PLAY_AGGRO=false USE_BERSERK_AGGRESSIVELY=false +# The amount of cards at which to stop considering mulligan MULLIGAN_THRESHOLD=4 + +# Only works when AI cheating is enabled in preferences, otherwise does nothing CHEAT_WITH_MANA_ON_SHUFFLE=true +# Planechase logic DEFAULT_MAX_PLANAR_DIE_ROLLS_PER_TURN=1 DEFAULT_MIN_TURN_TO_ROLL_PLANAR_DIE=3 DEFAULT_PLANAR_DIE_ROLL_CHANCE=50 PLANAR_DIE_ROLL_HESITATION_CHANCE=10 +# Timings for moving equipment to other targets MOVE_EQUIPMENT_TO_BETTER_CREATURES=from_useless_only MOVE_EQUIPMENT_CREATURE_EVAL_THRESHOLD=60 PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=true +# Currently disabled PREDICT_SPELLS_FOR_MAIN2=true 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 MIN_SPELL_CMC_TO_COUNTER=2 ALWAYS_COUNTER_OTHER_COUNTERSPELLS=true ALWAYS_COUNTER_DAMAGE_SPELLS=true @@ -25,5 +34,13 @@ ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS=true ALWAYS_COUNTER_REMOVAL_SPELLS=true ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS=None +# Storm spell logic PRIORITY_REDUCTION_FOR_STORM_SPELLS=9 MIN_COUNT_FOR_STORM_SPELLS=1 + +# Strip Mine, Wasteland, Ghost Quarter logic +STRIPMINE_MIN_LANDS_IN_HAND_TO_ACTIVATE=1 +STRIPMINE_MIN_LANDS_FOR_NO_TIMING_CHECK=9999 +STRIPMINE_MIN_LANDS_OTB_FOR_NO_TEMPO_CHECK=8 +STRIPMINE_MAX_LANDS_TO_ATTEMPT_MANALOCKING=3 +STRIPMINE_HIGH_PRIORITY_ON_SKIPPED_LANDDROP=true \ No newline at end of file diff --git a/forge-gui/res/ai/Default.ai b/forge-gui/res/ai/Default.ai index ff00d598a5e..52024c4e199 100644 --- a/forge-gui/res/ai/Default.ai +++ b/forge-gui/res/ai/Default.ai @@ -1,23 +1,32 @@ +# Aggro preferences (enabling these will generally make the AI attack more aggressively) PLAY_AGGRO=false USE_BERSERK_AGGRESSIVELY=false -MULLIGAN_THRESHOLD=5 +# The amount of cards at which to stop considering mulligan +MULLIGAN_THRESHOLD=4 + +# Only works when AI cheating is enabled in preferences, otherwise does nothing CHEAT_WITH_MANA_ON_SHUFFLE=true +# Planechase logic DEFAULT_MAX_PLANAR_DIE_ROLLS_PER_TURN=1 DEFAULT_MIN_TURN_TO_ROLL_PLANAR_DIE=3 DEFAULT_PLANAR_DIE_ROLL_CHANCE=50 PLANAR_DIE_ROLL_HESITATION_CHANCE=10 +# Timings for moving equipment to other targets MOVE_EQUIPMENT_TO_BETTER_CREATURES=from_useless_only MOVE_EQUIPMENT_CREATURE_EVAL_THRESHOLD=60 PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=true +# Currently disabled PREDICT_SPELLS_FOR_MAIN2=true 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 MIN_SPELL_CMC_TO_COUNTER=0 ALWAYS_COUNTER_OTHER_COUNTERSPELLS=true ALWAYS_COUNTER_DAMAGE_SPELLS=true @@ -25,5 +34,13 @@ ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS=true ALWAYS_COUNTER_REMOVAL_SPELLS=true ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS=None +# Storm spell logic PRIORITY_REDUCTION_FOR_STORM_SPELLS=0 -MIN_COUNT_FOR_STORM_SPELLS=0 \ No newline at end of file +MIN_COUNT_FOR_STORM_SPELLS=0 + +# Strip Mine, Wasteland, Ghost Quarter logic +STRIPMINE_MIN_LANDS_IN_HAND_TO_ACTIVATE=1 +STRIPMINE_MIN_LANDS_FOR_NO_TIMING_CHECK=9999 +STRIPMINE_MIN_LANDS_OTB_FOR_NO_TEMPO_CHECK=6 +STRIPMINE_MAX_LANDS_TO_ATTEMPT_MANALOCKING=3 +STRIPMINE_HIGH_PRIORITY_ON_SKIPPED_LANDDROP=true diff --git a/forge-gui/res/ai/Experimental.ai b/forge-gui/res/ai/Experimental.ai index 2c1129b2d62..f2734d95556 100644 --- a/forge-gui/res/ai/Experimental.ai +++ b/forge-gui/res/ai/Experimental.ai @@ -1,23 +1,32 @@ +# Aggro preferences (enabling these will generally make the AI attack more aggressively) PLAY_AGGRO=false USE_BERSERK_AGGRESSIVELY=false +# The amount of cards at which to stop considering mulligan MULLIGAN_THRESHOLD=4 + +# Only works when AI cheating is enabled in preferences, otherwise does nothing CHEAT_WITH_MANA_ON_SHUFFLE=true +# Planechase logic DEFAULT_MAX_PLANAR_DIE_ROLLS_PER_TURN=1 DEFAULT_MIN_TURN_TO_ROLL_PLANAR_DIE=3 DEFAULT_PLANAR_DIE_ROLL_CHANCE=50 PLANAR_DIE_ROLL_HESITATION_CHANCE=10 +# Timings for moving equipment to other targets MOVE_EQUIPMENT_TO_BETTER_CREATURES=always MOVE_EQUIPMENT_CREATURE_EVAL_THRESHOLD=60 PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=true +# Currently disabled PREDICT_SPELLS_FOR_MAIN2=true 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 MIN_SPELL_CMC_TO_COUNTER=2 ALWAYS_COUNTER_OTHER_COUNTERSPELLS=true ALWAYS_COUNTER_DAMAGE_SPELLS=true @@ -25,5 +34,13 @@ ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS=true ALWAYS_COUNTER_REMOVAL_SPELLS=true ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS=None +# Storm spell logic PRIORITY_REDUCTION_FOR_STORM_SPELLS=9 -MIN_COUNT_FOR_STORM_SPELLS=1 \ No newline at end of file +MIN_COUNT_FOR_STORM_SPELLS=1 + +# Strip Mine, Wasteland, Ghost Quarter logic +STRIPMINE_MIN_LANDS_IN_HAND_TO_ACTIVATE=1 +STRIPMINE_MIN_LANDS_FOR_NO_TIMING_CHECK=9999 +STRIPMINE_MIN_LANDS_OTB_FOR_NO_TEMPO_CHECK=6 +STRIPMINE_MAX_LANDS_TO_ATTEMPT_MANALOCKING=3 +STRIPMINE_HIGH_PRIORITY_ON_SKIPPED_LANDDROP=true \ No newline at end of file diff --git a/forge-gui/res/ai/Reckless.ai b/forge-gui/res/ai/Reckless.ai index 4455129200c..d6edf7efbb5 100644 --- a/forge-gui/res/ai/Reckless.ai +++ b/forge-gui/res/ai/Reckless.ai @@ -1,23 +1,32 @@ +# Aggro preferences (enabling these will generally make the AI attack more aggressively) PLAY_AGGRO=true USE_BERSERK_AGGRESSIVELY=true +# The amount of cards at which to stop considering mulligan MULLIGAN_THRESHOLD=3 + +# Only works when AI cheating is enabled in preferences, otherwise does nothing CHEAT_WITH_MANA_ON_SHUFFLE=true +# Planechase logic DEFAULT_MAX_PLANAR_DIE_ROLLS_PER_TURN=1 DEFAULT_MIN_TURN_TO_ROLL_PLANAR_DIE=1 DEFAULT_PLANAR_DIE_ROLL_CHANCE=100 PLANAR_DIE_ROLL_HESITATION_CHANCE=0 +# Timings for moving equipment to other targets MOVE_EQUIPMENT_TO_BETTER_CREATURES=always MOVE_EQUIPMENT_CREATURE_EVAL_THRESHOLD=50 PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=false +# Currently disabled PREDICT_SPELLS_FOR_MAIN2=true 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 MIN_SPELL_CMC_TO_COUNTER=0 ALWAYS_COUNTER_OTHER_COUNTERSPELLS=true ALWAYS_COUNTER_DAMAGE_SPELLS=true @@ -25,5 +34,13 @@ ALWAYS_COUNTER_CMC_0_MANA_MAKING_PERMS=true ALWAYS_COUNTER_REMOVAL_SPELLS=true ALWAYS_COUNTER_SPELLS_FROM_NAMED_CARDS=None +# Storm spell logic PRIORITY_REDUCTION_FOR_STORM_SPELLS=0 -MIN_COUNT_FOR_STORM_SPELLS=0 \ No newline at end of file +MIN_COUNT_FOR_STORM_SPELLS=0 + +# Strip Mine, Wasteland, Ghost Quarter logic +STRIPMINE_MIN_LANDS_IN_HAND_TO_ACTIVATE=1 +STRIPMINE_MIN_LANDS_FOR_NO_TIMING_CHECK=3 +STRIPMINE_MIN_LANDS_OTB_FOR_NO_TEMPO_CHECK=4 +STRIPMINE_MAX_LANDS_TO_ATTEMPT_MANALOCKING=4 +STRIPMINE_HIGH_PRIORITY_ON_SKIPPED_LANDDROP=true \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/g/ghost_quarter.txt b/forge-gui/res/cardsfolder/g/ghost_quarter.txt index 401f14628fb..f57fcd4560a 100644 --- a/forge-gui/res/cardsfolder/g/ghost_quarter.txt +++ b/forge-gui/res/cardsfolder/g/ghost_quarter.txt @@ -2,7 +2,7 @@ Name:Ghost Quarter ManaCost:no cost Types:Land A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C} to your mana pool. -A:AB$ Destroy | Cost$ T Sac<1/CARDNAME> | ValidTgts$ Land | TgtPrompt$ Select target land. | SubAbility$ DBChange | AITgts$ Land.nonBasic | SpellDescription$ Destroy target land. Its controller may search his or her library for a basic land card, put it onto the battlefield, then shuffle his or her library. +A:AB$ Destroy | Cost$ T Sac<1/CARDNAME> | ValidTgts$ Land | TgtPrompt$ Select target land. | SubAbility$ DBChange | AILogic$ LandForLand | AITgts$ Land.nonBasic | SpellDescription$ Destroy target land. Its controller may search his or her library for a basic land card, put it onto the battlefield, then shuffle his or her library. SVar:DBChange:DB$ChangeZone | Optional$ True | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.Basic | ChangeNum$ 1 | DefinedPlayer$ TargetedController | ShuffleNonMandatory$ True SVar:RemRandomDeck:True SVar:Picture:http://www.wizards.com/global/images/magic/general/ghost_quarter.jpg