diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 2314c4867bb..64f14a4c955 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -1705,7 +1705,7 @@ public class AiController { if (!useSimulation) { for (Entry ds : myDeck) { for (Entry cp : ds.getValue()) { - if (cp.getKey().getRules().getAiHints().getRemAIDecks()) + if (cp.getKey().getRules().getAiHints().getRemAIDecks()) result.add(cp.getKey()); } } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 115568e4ce4..008da7ec703 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -1844,4 +1844,13 @@ public class ComputerUtilCard { return AiPlayDecision.WillPlay; } + + // Determine if the AI has an AI:RemoveDeck:All or an AI:RemoveDeck:Random hint specified. + // Includes a NPE guard on getRules() which might otherwise be tripped on some cards (e.g. tokens). + public static boolean isCardRemAIDeck(final Card card) { + return card.getRules() != null && card.getRules().getAiHints().getRemAIDecks(); + } + public static boolean isCardRemRandomDeck(final Card card) { + return card.getRules() != null && card.getRules().getAiHints().getRemRandomDecks(); + } } diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index 47c408d8c79..7d7a60528fc 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -1463,7 +1463,7 @@ public class ChangeZoneAi extends SpellAbilityAi { fetchList = CardLists.filter(fetchList, new Predicate() { @Override public boolean apply(final Card c) { - if (c.getRules().getAiHints().getRemAIDecks() || c.getRules().getAiHints().getRemRandomDecks()) { + if (ComputerUtilCard.isCardRemAIDeck(c) || ComputerUtilCard.isCardRemRandomDeck(c)) { return false; } return true; diff --git a/forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java b/forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java index a6631ad51bb..eb6e3ed5d9b 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ControlGainAi.java @@ -171,7 +171,7 @@ public class ControlGainAi extends SpellAbilityAi { } // do not take control on something it doesn't know how to use - return !c.getRules().getAiHints().getRemAIDecks(); + return !ComputerUtilCard.isCardRemAIDeck(c); } }); diff --git a/forge-ai/src/main/java/forge/ai/ability/PowerExchangeAi.java b/forge-ai/src/main/java/forge/ai/ability/PowerExchangeAi.java index 028e234f365..6dd2e5aa767 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PowerExchangeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PowerExchangeAi.java @@ -37,7 +37,7 @@ public class PowerExchangeAi extends SpellAbilityAi { list = CardLists.filter(list, new Predicate() { @Override public boolean apply(final Card c) { - return !c.getRules().getAiHints().getRemAIDecks() && c.canBeTargetedBy(sa); + return !ComputerUtilCard.isCardRemAIDeck(c) && c.canBeTargetedBy(sa); } }); CardLists.sortByPowerAsc(list); diff --git a/forge-game/src/main/java/forge/game/card/CardPredicates.java b/forge-game/src/main/java/forge/game/card/CardPredicates.java index 4809a42da8d..c6180228a3d 100644 --- a/forge-game/src/main/java/forge/game/card/CardPredicates.java +++ b/forge-game/src/main/java/forge/game/card/CardPredicates.java @@ -416,8 +416,9 @@ public final class CardPredicates { public static final Predicate isRemAIDeck() { return new Predicate() { @Override - public boolean apply(final Card c) { - return c.getRules().getAiHints().getRemAIDecks(); + public boolean apply(final Card c) + { + return c.getRules() != null && c.getRules().getAiHints().getRemAIDecks(); } }; }