diff --git a/forge-ai/src/main/java/forge/ai/AiProps.java b/forge-ai/src/main/java/forge/ai/AiProps.java index bea832392df..1b87cc27d84 100644 --- a/forge-ai/src/main/java/forge/ai/AiProps.java +++ b/forge-ai/src/main/java/forge/ai/AiProps.java @@ -34,7 +34,8 @@ public enum AiProps { /** */ PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS ("true"), PREDICT_SPELLS_FOR_MAIN2 ("true"), /** */ RESERVE_MANA_FOR_MAIN2_CHANCE ("0"), /** */ - PLAY_AGGRO ("false"); /** */ + PLAY_AGGRO ("false"), /** */ + ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS ("false"); /** */ private final String strDefaultVal; diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 8a9aae1eab2..69075c17d51 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -44,6 +44,7 @@ import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.staticability.StaticAbility; +import forge.game.trigger.Trigger; import forge.game.zone.MagicStack; import forge.game.zone.ZoneType; import forge.item.PaperCard; @@ -846,6 +847,7 @@ public class ComputerUtilCard { public static boolean useRemovalNow(final SpellAbility sa, final Card c, final int dmg, ZoneType destination) { final Player ai = sa.getActivatingPlayer(); + final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); final Player opp = ai.getOpponent(); final Game game = ai.getGame(); final PhaseHandler ph = game.getPhaseHandler(); @@ -992,6 +994,43 @@ public class ComputerUtilCard { } } else if (c.isPlaneswalker()) { threat = 1; + } else if (aic.getBooleanProperty(AiProps.ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS) && (c.isArtifact() && !c.isCreature()) || (c.isEnchantment() && !c.isAura())) { + // non-creature artifacts and global enchantments with suspicious intrinsic abilities + boolean priority = false; + if (c.getOwner().isOpponentOf(ai) && c.getController().isOpponentOf(ai)) { + // if this thing is both owned and controlled by an opponent and it has a continuous ability, + // assume it either benefits the player or disrupts the opponent + for (final StaticAbility stAb : c.getStaticAbilities()) { + final Map params = stAb.getMapParams(); + if (params.get("Mode").equals("Continuous") && stAb.isIntrinsic() && !stAb.isTemporary()) { + priority = true; + break; + } + } + if (!priority) { + for (final Trigger t : c.getTriggers()) { + if (t.isIntrinsic() && !t.isTemporary()) { + // has a triggered ability, could be benefitting the opponent or disrupting the AI + priority = true; + break; + } + } + } + // if this thing has AILogic set to "Curse", it's probably meant as some form of disruption + if (!priority) { + for (final String sVar : c.getSVars().keySet()) { + if (c.getSVars().get(sVar).contains("AILogic$ Curse")) { + // this is a curse ability, so prioritize its removal + priority = true; + break; + } + } + } + // if it's a priority object, set its threat level to high + if (priority) { + threat = 1.0f; + } + } } else { for (final StaticAbility stAb : c.getStaticAbilities()) { final Map params = stAb.getMapParams(); diff --git a/forge-gui/res/ai/Default.ai b/forge-gui/res/ai/Default.ai index 86665c7c964..cfe5d9609c2 100644 --- a/forge-gui/res/ai/Default.ai +++ b/forge-gui/res/ai/Default.ai @@ -8,5 +8,6 @@ MOVE_EQUIPMENT_TO_BETTER_CREATURES=from_useless_only PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=true PREDICT_SPELLS_FOR_MAIN2=true RESERVE_MANA_FOR_MAIN2_CHANCE=100 +ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=false PLAY_AGGRO=false diff --git a/forge-gui/res/ai/Reckless.ai b/forge-gui/res/ai/Reckless.ai index c980ae46748..5f68167e17f 100644 --- a/forge-gui/res/ai/Reckless.ai +++ b/forge-gui/res/ai/Reckless.ai @@ -8,4 +8,5 @@ MOVE_EQUIPMENT_TO_BETTER_CREATURES=always PRIORITIZE_MOVE_EQUIPMENT_IF_USELESS=false PREDICT_SPELLS_FOR_MAIN2=true RESERVE_MANA_FOR_MAIN2_CHANCE=100 +ACTIVELY_DESTROY_ARTS_AND_NONAURA_ENCHS=false PLAY_AGGRO=true