diff --git a/src/main/java/forge/card/ability/ai/CounterAi.java b/src/main/java/forge/card/ability/ai/CounterAi.java index 1600901e869..2cf860964d1 100644 --- a/src/main/java/forge/card/ability/ai/CounterAi.java +++ b/src/main/java/forge/card/ability/ai/CounterAi.java @@ -8,7 +8,6 @@ import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; -import forge.card.spellability.TargetChooser; import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; @@ -50,7 +49,7 @@ public class CounterAi extends SpellAbilityAi { } tgt.resetTargets(); - if (TargetChooser.matchSpellAbility(sa, topSA, tgt)) { + if (sa.canTargetSpellAbility(topSA)) { tgt.addTarget(topSA); } else { return false; @@ -120,7 +119,7 @@ public class CounterAi extends SpellAbilityAi { } tgt.resetTargets(); - if (TargetChooser.matchSpellAbility(sa, topSA, tgt)) { + if (sa.canTargetSpellAbility(topSA)) { tgt.addTarget(topSA); } else { return false; diff --git a/src/main/java/forge/card/ability/ai/DamageDealAi.java b/src/main/java/forge/card/ability/ai/DamageDealAi.java index b2f0ba01005..baac5c59c1d 100644 --- a/src/main/java/forge/card/ability/ai/DamageDealAi.java +++ b/src/main/java/forge/card/ability/ai/DamageDealAi.java @@ -15,7 +15,6 @@ import forge.card.cost.Cost; import forge.card.spellability.AbilitySub; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; -import forge.card.spellability.TargetChooser; import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; @@ -143,7 +142,7 @@ public class DamageDealAi extends DamageAiBase { final ArrayList objects = tgt.getTargets(); if (saMe.hasParam("TargetUnique")) { - objects.addAll(TargetChooser.getUniqueTargets(saMe)); + objects.addAll(saMe.getUniqueTargets()); } for (final Object o : objects) { if (o instanceof Card) { diff --git a/src/main/java/forge/card/spellability/SpellAbility.java b/src/main/java/forge/card/spellability/SpellAbility.java index e3e27b0fe20..e8b29b17765 100644 --- a/src/main/java/forge/card/spellability/SpellAbility.java +++ b/src/main/java/forge/card/spellability/SpellAbility.java @@ -1313,7 +1313,7 @@ public abstract class SpellAbility implements ISpellAbility { return false; } if (entity.isValid(this.getTarget().getValidTgts(), this.getActivatingPlayer(), this.getSourceCard()) - && (!this.getTarget().isUniqueTargets() || !TargetChooser.getUniqueTargets(this).contains(entity)) + && (!this.getTarget().isUniqueTargets() || !this.getUniqueTargets().contains(entity)) && entity.canBeTargetedBy(this)) { return true; } @@ -1679,4 +1679,92 @@ public abstract class SpellAbility implements ISpellAbility { public void setCopied(boolean isCopied0) { this.isCopied = isCopied0; } + + /** + * Gets the unique targets. + * + * @param ability + * the ability + * @return the unique targets + */ + public final ArrayList getUniqueTargets() { + final ArrayList targets = new ArrayList(); + SpellAbility child = this; + while (child instanceof AbilitySub) { + child = ((AbilitySub) child).getParent(); + if (child != null && child.getTarget() != null) { + targets.addAll(child.getTarget().getTargets()); + } + } + + return targets; + } + + public boolean canTargetSpellAbility(final SpellAbility topSA) { + final Target tgt = this.getTarget(); + final String saType = tgt.getTargetSpellAbilityType(); + + if (null == saType) { + // just take this to mean no restrictions - carry on. + } else if (topSA instanceof Spell) { + if (!saType.contains("Spell")) { + return false; + } + } else if (topSA.isTrigger()) { + if (!saType.contains("Triggered")) { + return false; + } + } else if (topSA instanceof AbilityActivated) { + if (!saType.contains("Activated")) { + return false; + } + } else { + return false; //Static ability? Whatever. + } + + final String splitTargetRestrictions = tgt.getSAValidTargeting(); + if (splitTargetRestrictions != null) { + // TODO What about spells with SubAbilities with Targets? + + final Target matchTgt = topSA.getTarget(); + + if (matchTgt == null) { + return false; + } + + boolean result = false; + + for (final Object o : matchTgt.getTargets()) { + if (matchesValid(o, splitTargetRestrictions.split(","))) { + result = true; + break; + } + } + + if (!result) { + return false; + } + } + + return topSA.getSourceCard().isValid(tgt.getValidTgts(), this.getActivatingPlayer(), this.getSourceCard()); + } + + + private boolean matchesValid(final Object o, final String[] valids) { + final Card srcCard = this.getSourceCard(); + final Player activatingPlayer = this.getActivatingPlayer(); + if (o instanceof Card) { + final Card c = (Card) o; + return c.isValid(valids, activatingPlayer, srcCard); + } + + if (o instanceof Player) { + Player p = (Player) o; + if (p.isValid(valids, activatingPlayer, srcCard)) { + return true; + } + } + + return false; + } } diff --git a/src/main/java/forge/card/spellability/TargetChooser.java b/src/main/java/forge/card/spellability/TargetChooser.java index 64ecd9b766f..81a84ac61ce 100644 --- a/src/main/java/forge/card/spellability/TargetChooser.java +++ b/src/main/java/forge/card/spellability/TargetChooser.java @@ -158,25 +158,7 @@ public class TargetChooser { return chooseTargets(); } - /** - * Gets the unique targets. - * - * @param ability - * the ability - * @return the unique targets - */ - public static final ArrayList getUniqueTargets(final SpellAbility ability) { - final ArrayList targets = new ArrayList(); - SpellAbility child = ability; - while (child instanceof AbilitySub) { - child = ((AbilitySub) child).getParent(); - if (child != null && child.getTarget() != null) { - targets.addAll(child.getTarget().getTargets()); - } - } - - return targets; - } + // these have been copied over from CardFactoryUtil as they need two extra // parameters for target selection. @@ -204,7 +186,7 @@ public class TargetChooser { choices.remove(tgt.getSourceCard()); } } - ArrayList objects = getUniqueTargets(this.ability); + ArrayList objects = this.ability.getUniqueTargets(); if (tgt.isUniqueTargets()) { for (final Object o : objects) { @@ -419,7 +401,7 @@ public class TargetChooser { } for (int i = 0; i < choosables.size(); i++) { - if (!TargetChooser.matchSpellAbility(ability, choosables.get(i), getTgt())) { + if (!ability.canTargetSpellAbility(choosables.get(i))) { choosables.remove(i); } } @@ -439,70 +421,4 @@ public class TargetChooser { * a {@link forge.card.spellability.Target} object. * @return a boolean. */ - public static boolean matchSpellAbility(final SpellAbility sa, final SpellAbility topSA, final Target tgt) { - final String saType = tgt.getTargetSpellAbilityType(); - - if (null == saType) { - // just take this to mean no restrictions - carry on. - } else if (topSA instanceof Spell) { - if (!saType.contains("Spell")) { - return false; - } - } else if (topSA.isTrigger()) { - if (!saType.contains("Triggered")) { - return false; - } - } else if (topSA instanceof AbilityActivated) { - if (!saType.contains("Activated")) { - return false; - } - } else { - return false; //Static ability? Whatever. - } - - final String splitTargetRestrictions = tgt.getSAValidTargeting(); - if (splitTargetRestrictions != null) { - // TODO What about spells with SubAbilities with Targets? - - final Target matchTgt = topSA.getTarget(); - - if (matchTgt == null) { - return false; - } - - boolean result = false; - - for (final Object o : matchTgt.getTargets()) { - if (TargetChooser.matchesValid(o, splitTargetRestrictions.split(","), sa)) { - result = true; - break; - } - } - - if (!result) { - return false; - } - } - - return topSA.getSourceCard().isValid(tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard()); - } - - - private static boolean matchesValid(final Object o, final String[] valids, final SpellAbility sa) { - final Card srcCard = sa.getSourceCard(); - final Player activatingPlayer = sa.getActivatingPlayer(); - if (o instanceof Card) { - final Card c = (Card) o; - return c.isValid(valids, activatingPlayer, srcCard); - } - - if (o instanceof Player) { - Player p = (Player) o; - if (p.isValid(valids, sa.getActivatingPlayer(), sa.getSourceCard())) { - return true; - } - } - - return false; - } } diff --git a/src/main/java/forge/game/zone/MagicStack.java b/src/main/java/forge/game/zone/MagicStack.java index 6dbd0b6ba8e..9253d8a6824 100644 --- a/src/main/java/forge/game/zone/MagicStack.java +++ b/src/main/java/forge/game/zone/MagicStack.java @@ -42,7 +42,6 @@ import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityStackInstance; import forge.card.spellability.Target; import forge.card.spellability.TargetChoices; -import forge.card.spellability.TargetChooser; import forge.card.trigger.Trigger; import forge.card.trigger.TriggerType; import forge.control.input.InputPayManaExecuteCommands; @@ -885,7 +884,7 @@ public class MagicStack extends MyObservable { } else if (o instanceof SpellAbility) { final SpellAbility tgtSA = (SpellAbility) o; - invalidTarget = !(TargetChooser.matchSpellAbility(sa, tgtSA, tgt)); + invalidTarget = !(sa.canTargetSpellAbility(tgtSA)); // TODO Remove target? if (invalidTarget) { choices.removeTarget(tgtSA);