From 42f2b0a8e3b2ad9cd5d7f0c5c5cfe2beb0fe5c1b Mon Sep 17 00:00:00 2001 From: Agetian Date: Sat, 30 Sep 2017 11:26:01 +0000 Subject: [PATCH] - AI: Improvements to tap/untap logic in order to try not to target something twice for tapping/untapping. --- .../main/java/forge/ai/ability/TapAiBase.java | 15 +++++++++- .../main/java/forge/ai/ability/UntapAi.java | 29 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/TapAiBase.java b/forge-ai/src/main/java/forge/ai/ability/TapAiBase.java index fea4db58ef0..a263f41f80c 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TapAiBase.java +++ b/forge-ai/src/main/java/forge/ai/ability/TapAiBase.java @@ -156,8 +156,21 @@ public abstract class TapAiBase extends SpellAbilityAi { }); } - //try to exclude things that will already be tapped due to something on stack + //try to exclude things that will already be tapped due to something on stack or because something is + //already targeted in a parent or sub SA CardCollection toExclude = new CardCollection(); + SpellAbility saSub = sa.getRootAbility(); + while (saSub != null) { + for (Card c : tapList) { + if (saSub.getApi() == ApiType.Tap) { + if (saSub.getTargets() != null && saSub.getTargets().getTargetCards().contains(c)) { + // Was already targeted in a parent or sub SA + toExclude.add(c); + } + } + } + saSub = saSub.getSubAbility(); + } for (SpellAbilityStackInstance si : game.getStack()) { SpellAbility ab = si.getSpellAbility(false); if (ab != null && ab.getApi() == ApiType.Tap) { diff --git a/forge-ai/src/main/java/forge/ai/ability/UntapAi.java b/forge-ai/src/main/java/forge/ai/ability/UntapAi.java index 22b41bc8c31..d9058a1bad2 100644 --- a/forge-ai/src/main/java/forge/ai/ability/UntapAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/UntapAi.java @@ -16,6 +16,7 @@ import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.PlayerCollection; import forge.game.spellability.SpellAbility; +import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.TargetRestrictions; import forge.game.zone.ZoneType; @@ -167,6 +168,34 @@ public class UntapAi extends SpellAbilityAi { untapList.removeAll(toRemove); } + //try to exclude things that will already be untapped due to something on stack or because something is + //already targeted in a parent or sub SA + CardCollection toExclude = new CardCollection(); + SpellAbility saSub = sa.getRootAbility(); + while (saSub != null) { + for (Card c : untapList) { + if (saSub.getApi() == ApiType.Untap) { + if (saSub.getTargets() != null && saSub.getTargets().getTargetCards().contains(c)) { + // Was already targeted in a parent or sub SA + toExclude.add(c); + } + } + } + saSub = saSub.getSubAbility(); + } + for (SpellAbilityStackInstance si : ai.getGame().getStack()) { + SpellAbility ab = si.getSpellAbility(false); + if (ab != null && ab.getApi() == ApiType.Tap) { + for (Card c : untapList) { + // TODO: somehow ensure that the untapping SA won't be countered + if (si.getTargetChoices() != null && si.getTargetChoices().getTargetCards().contains(c)) { + toExclude.add(c); + } + } + } + } + untapList.removeAll(toExclude); + sa.resetTargets(); while (sa.getTargets().getNumTargeted() < tgt.getMaxTargets(sa.getHostCard(), sa)) { Card choice = null;