Using ITargetable instead of Object to return targets of an ability

This commit is contained in:
Maxmtg
2013-06-18 08:21:26 +00:00
parent 28a94982fe
commit 25edd60ac5
23 changed files with 269 additions and 242 deletions

1
.gitattributes vendored
View File

@@ -13994,6 +13994,7 @@ src/main/java/forge/GameLog.java -text
src/main/java/forge/GameLogEntry.java -text src/main/java/forge/GameLogEntry.java -text
src/main/java/forge/GameLogEntryType.java -text src/main/java/forge/GameLogEntryType.java -text
src/main/java/forge/GameLogFormatter.java -text src/main/java/forge/GameLogFormatter.java -text
src/main/java/forge/ITargetable.java -text
src/main/java/forge/ImageCache.java svneol=native#text/plain src/main/java/forge/ImageCache.java svneol=native#text/plain
src/main/java/forge/ImageLoader.java -text src/main/java/forge/ImageLoader.java -text
src/main/java/forge/Singletons.java svneol=native#text/plain src/main/java/forge/Singletons.java svneol=native#text/plain

View File

@@ -19,7 +19,6 @@ package forge;
import java.util.ArrayList; import java.util.ArrayList;
import forge.card.spellability.SpellAbility;
import forge.game.Game; import forge.game.Game;
import forge.game.player.Player; import forge.game.player.Player;
import forge.util.MyObservable; import forge.util.MyObservable;
@@ -32,7 +31,7 @@ import forge.util.MyObservable;
* @author Forge * @author Forge
* @version $Id: Player.java 10091 2011-08-30 16:11:21Z Sloth $ * @version $Id: Player.java 10091 2011-08-30 16:11:21Z Sloth $
*/ */
public abstract class GameEntity extends MyObservable { public abstract class GameEntity extends MyObservable implements ITargetable {
private String name = ""; private String name = "";
private int preventNextDamage = 0; private int preventNextDamage = 0;
@@ -267,17 +266,6 @@ public abstract class GameEntity extends MyObservable {
return false; return false;
} }
/**
* Can target.
*
* @param sa
* the sa
* @return a boolean
*/
public boolean canBeTargetedBy(final SpellAbility sa) {
return false;
}
/** /**
* Checks if is valid. * Checks if is valid.
* *

View File

@@ -0,0 +1,7 @@
package forge;
import forge.card.spellability.SpellAbility;
public interface ITargetable {
boolean canBeTargetedBy(final SpellAbility sa);
}

View File

@@ -14,6 +14,7 @@ import forge.CardLists;
import forge.CardUtil; import forge.CardUtil;
import forge.Constant; import forge.Constant;
import forge.CounterType; import forge.CounterType;
import forge.ITargetable;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostBeingPaid;
@@ -571,8 +572,8 @@ public class AbilityUtils {
* a {@link forge.card.spellability.SpellAbility} object. * a {@link forge.card.spellability.SpellAbility} object.
* @return a {@link java.util.ArrayList} object. * @return a {@link java.util.ArrayList} object.
*/ */
public static ArrayList<Object> getDefinedObjects(final Card card, final String def, final SpellAbility sa) { public static List<ITargetable> getDefinedObjects(final Card card, final String def, final SpellAbility sa) {
final ArrayList<Object> objects = new ArrayList<Object>(); final ArrayList<ITargetable> objects = new ArrayList<ITargetable>();
final String defined = (def == null) ? "Self" : def; final String defined = (def == null) ? "Self" : def;
objects.addAll(AbilityUtils.getDefinedPlayers(card, defined, sa)); objects.addAll(AbilityUtils.getDefinedPlayers(card, defined, sa));

View File

@@ -9,6 +9,7 @@ import java.util.StringTokenizer;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import forge.Card; import forge.Card;
import forge.ITargetable;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.AbilitySub; import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
@@ -162,7 +163,7 @@ import forge.game.player.Player;
return tgt != null ? tgt.getTargetSAs() : AbilityUtils.getDefinedSpellAbilities(sa.getSourceCard(), sa.getParam("Defined"), sa); return tgt != null ? tgt.getTargetSAs() : AbilityUtils.getDefinedSpellAbilities(sa.getSourceCard(), sa.getParam("Defined"), sa);
} }
protected List<Object> getTargetObjects(SpellAbility sa) { protected List<ITargetable> getTargetObjects(SpellAbility sa) {
final Target tgt = sa.getTarget(); final Target tgt = sa.getTarget();
return tgt != null ? tgt.getTargets() : AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa); return tgt != null ? tgt.getTargets() : AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa);
} }

View File

@@ -14,6 +14,7 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardPredicates; import forge.CardPredicates;
import forge.CardUtil; import forge.CardUtil;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
@@ -611,7 +612,7 @@ public class AttachAi extends SpellAbilityAi {
protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, final boolean mandatory) { protected boolean doTriggerAINoCost(final Player ai, final SpellAbility sa, final boolean mandatory) {
final Card card = sa.getSourceCard(); final Card card = sa.getSourceCard();
// Check if there are any valid targets // Check if there are any valid targets
ArrayList<Object> targets = new ArrayList<Object>(); List<ITargetable> targets = new ArrayList<ITargetable>();
final Target tgt = sa.getTarget(); final Target tgt = sa.getTarget();
if (tgt == null) { if (tgt == null) {
targets = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa); targets = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa);

View File

@@ -7,6 +7,7 @@ import com.google.common.base.Predicate;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
@@ -78,17 +79,17 @@ public class ChooseSourceAi extends SpellAbilityAi {
} }
final Card threatSource = topStack.getSourceCard(); final Card threatSource = topStack.getSourceCard();
ArrayList<Object> objects = new ArrayList<Object>(); List<? extends ITargetable> objects = new ArrayList<ITargetable>();
final Target threatTgt = topStack.getTarget(); final Target threatTgt = topStack.getTarget();
if (threatTgt == null) { if (threatTgt == null) {
if (topStack.hasParam("Defined")) { if (topStack.hasParam("Defined")) {
objects = AbilityUtils.getDefinedObjects(threatSource, topStack.getParam("Defined"), topStack); objects = AbilityUtils.getDefinedObjects(threatSource, topStack.getParam("Defined"), topStack);
} else if (topStack.hasParam("ValidPlayers")) { } else if (topStack.hasParam("ValidPlayers")) {
objects.addAll(AbilityUtils.getDefinedPlayers(threatSource, topStack.getParam("ValidPlayers"), topStack)); objects = AbilityUtils.getDefinedPlayers(threatSource, topStack.getParam("ValidPlayers"), topStack);
} }
} else { } else {
objects.addAll(threatTgt.getTargetPlayers()); objects = threatTgt.getTargetPlayers();
} }
if (!objects.contains(ai) || topStack.hasParam("NoPrevention")) { if (!objects.contains(ai) || topStack.hasParam("NoPrevention")) {
return false; return false;

View File

@@ -1,6 +1,5 @@
package forge.card.ability.ai; package forge.card.ability.ai;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
@@ -8,6 +7,7 @@ import com.google.common.base.Predicate;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost; import forge.card.cost.Cost;
@@ -146,7 +146,7 @@ public class DamageDealAi extends DamageAiBase {
final Card source = saMe.getSourceCard(); final Card source = saMe.getSourceCard();
List<Card> hPlay = CardLists.getValidCards(pl.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, source); List<Card> hPlay = CardLists.getValidCards(pl.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), ai, source);
final ArrayList<Object> objects = tgt.getTargets(); final List<ITargetable> objects = tgt.getTargets();
if (saMe.hasParam("TargetUnique")) { if (saMe.hasParam("TargetUnique")) {
objects.addAll(saMe.getUniqueTargets()); objects.addAll(saMe.getUniqueTargets());
} }
@@ -359,7 +359,7 @@ public class DamageDealAi extends DamageAiBase {
*/ */
private boolean damageChooseNontargeted(Player ai, final SpellAbility saMe, final int dmg) { private boolean damageChooseNontargeted(Player ai, final SpellAbility saMe, final int dmg) {
// TODO: Improve circumstances where the Defined Damage is unwanted // TODO: Improve circumstances where the Defined Damage is unwanted
final ArrayList<Object> objects = AbilityUtils.getDefinedObjects(saMe.getSourceCard(), saMe.getParam("Defined"), saMe); final List<ITargetable> objects = AbilityUtils.getDefinedObjects(saMe.getSourceCard(), saMe.getParam("Defined"), saMe);
boolean urgent = false; // can it wait? boolean urgent = false; // can it wait?
boolean positive = false; boolean positive = false;

View File

@@ -6,6 +6,7 @@ import java.util.List;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardPredicates; import forge.CardPredicates;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost; import forge.card.cost.Cost;
@@ -52,8 +53,7 @@ public class DamagePreventAi extends SpellAbilityAi {
if (tgt == null) { if (tgt == null) {
// As far as I can tell these Defined Cards will only have one of // As far as I can tell these Defined Cards will only have one of
// them // them
final ArrayList<Object> objects = AbilityUtils.getDefinedObjects(sa.getSourceCard(), final List<ITargetable> objects = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa);
sa.getParam("Defined"), sa);
// react to threats on the stack // react to threats on the stack
if (!game.getStack().isEmpty()) { if (!game.getStack().isEmpty()) {

View File

@@ -1,9 +1,11 @@
package forge.card.ability.ai; package forge.card.ability.ai;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.Random; import java.util.Random;
import forge.Card; import forge.Card;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cost.Cost; import forge.card.cost.Cost;
@@ -66,7 +68,7 @@ public class UnattachAllAi extends SpellAbilityAi {
final Card card = sa.getSourceCard(); final Card card = sa.getSourceCard();
final Player opp = ai.getOpponent(); final Player opp = ai.getOpponent();
// Check if there are any valid targets // Check if there are any valid targets
ArrayList<Object> targets = new ArrayList<Object>(); List<ITargetable> targets = new ArrayList<ITargetable>();
final Target tgt = sa.getTarget(); final Target tgt = sa.getTarget();
if (tgt == null) { if (tgt == null) {
targets = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa); targets = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa);

View File

@@ -7,6 +7,7 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.Command; import forge.Command;
import forge.GameEntity; import forge.GameEntity;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
@@ -37,7 +38,7 @@ public class AttachEffect extends SpellAbilityEffect {
Card source = sa.getSourceCard(); Card source = sa.getSourceCard();
Card card = sa.getSourceCard(); Card card = sa.getSourceCard();
final List<Object> targets = getTargetObjects(sa); final List<ITargetable> targets = getTargetObjects(sa);
if (sa.hasParam("Object")) { if (sa.hasParam("Object")) {
card = AbilityUtils.getDefinedCards(source, sa.getParam("Object"), sa).get(0); card = AbilityUtils.getDefinedCards(source, sa.getParam("Object"), sa).get(0);
@@ -60,7 +61,7 @@ public class AttachEffect extends SpellAbilityEffect {
sb.append(" Attach to "); sb.append(" Attach to ");
final List<Object> targets = getTargetObjects(sa); final List<ITargetable> targets = getTargetObjects(sa);
// Should never allow more than one Attachment per card // Should never allow more than one Attachment per card
for (final Object o : targets) { for (final Object o : targets) {

View File

@@ -5,9 +5,11 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
@@ -188,18 +190,20 @@ public class ChooseSourceEffect extends SpellAbilityEffect {
} }
ArrayList<Object> objects = new ArrayList<Object>(); final List<? extends ITargetable> objects;
final Target threatTgt = abilityOnStack.getTarget(); final Target threatTgt = abilityOnStack.getTarget();
if (threatTgt == null) { if (threatTgt == null) {
if (abilityOnStack.hasParam("Defined")) { if (abilityOnStack.hasParam("Defined")) {
objects = AbilityUtils.getDefinedObjects(source, abilityOnStack.getParam("Defined"), abilityOnStack); objects = AbilityUtils.getDefinedObjects(source, abilityOnStack.getParam("Defined"), abilityOnStack);
} else if (abilityOnStack.hasParam("ValidPlayers")) { } else if (abilityOnStack.hasParam("ValidPlayers")) {
objects.addAll(AbilityUtils.getDefinedPlayers(source, abilityOnStack.getParam("ValidPlayers"), abilityOnStack)); objects = AbilityUtils.getDefinedPlayers(source, abilityOnStack.getParam("ValidPlayers"), abilityOnStack);
} } else
objects = Lists.<ITargetable>newArrayList();
} else { } else {
objects.addAll(threatTgt.getTargetPlayers()); objects = threatTgt.getTargetPlayers();
} }
if (!objects.contains(ai) || abilityOnStack.hasParam("NoPrevention")) { if (!objects.contains(ai) || abilityOnStack.hasParam("NoPrevention")) {
continue; continue;
} }

View File

@@ -1,11 +1,11 @@
package forge.card.ability.effects; package forge.card.ability.effects;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import forge.Card; import forge.Card;
import forge.CardUtil; import forge.CardUtil;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
@@ -25,7 +25,7 @@ public class DamageDealEffect extends SpellAbilityEffect {
final int dmg = AbilityUtils.calculateAmount(sa.getSourceCard(), damage, sa); final int dmg = AbilityUtils.calculateAmount(sa.getSourceCard(), damage, sa);
List<Object> tgts = getTargetObjects(sa); List<ITargetable> tgts = getTargetObjects(sa);
if (tgts.isEmpty()) if (tgts.isEmpty())
return ""; return "";
@@ -73,7 +73,7 @@ public class DamageDealEffect extends SpellAbilityEffect {
final boolean combatDmg = sa.hasParam("CombatDamage"); final boolean combatDmg = sa.hasParam("CombatDamage");
final boolean removeDamage = sa.hasParam("Remove"); final boolean removeDamage = sa.hasParam("Remove");
ArrayList<Object> tgts; List<ITargetable> tgts;
if (sa.getTarget() == null) { if (sa.getTarget() == null) {
tgts = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa) ; tgts = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa) ;
} else { } else {

View File

@@ -1,10 +1,10 @@
package forge.card.ability.effects; package forge.card.ability.effects;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
@@ -65,7 +65,7 @@ public class DamageEachEffect extends SpellAbilityEffect {
sources = CardLists.getValidCards(sources, sa.getParam("ValidCards"), card.getController(), card); sources = CardLists.getValidCards(sources, sa.getParam("ValidCards"), card.getController(), card);
} }
ArrayList<Object> tgts = new ArrayList<Object>(); final List<ITargetable> tgts;
if (sa.getTarget() == null) { if (sa.getTarget() == null) {
tgts = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("DefinedPlayers"), sa); tgts = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("DefinedPlayers"), sa);
} else { } else {

View File

@@ -5,6 +5,7 @@ import java.util.List;
import forge.Card; import forge.Card;
import forge.CardUtil; import forge.CardUtil;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
@@ -16,7 +17,7 @@ public class DamagePreventEffect extends SpellAbilityEffect {
protected String getStackDescription(SpellAbility sa) { protected String getStackDescription(SpellAbility sa) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
final List<Object> tgts = getTargetObjects(sa); final List<ITargetable> tgts = getTargetObjects(sa);
sb.append("Prevent the next "); sb.append("Prevent the next ");
sb.append(sa.getParam("Amount")); sb.append(sa.getParam("Amount"));
@@ -65,7 +66,7 @@ public class DamagePreventEffect extends SpellAbilityEffect {
Card host = sa.getSourceCard(); Card host = sa.getSourceCard();
int numDam = AbilityUtils.calculateAmount(host, sa.getParam("Amount"), sa); int numDam = AbilityUtils.calculateAmount(host, sa.getParam("Amount"), sa);
ArrayList<Object> tgts; final List<ITargetable> tgts;
final ArrayList<Card> untargetedCards = new ArrayList<Card>(); final ArrayList<Card> untargetedCards = new ArrayList<Card>();
if (sa.getTarget() == null) { if (sa.getTarget() == null) {
tgts = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa); tgts = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa);

View File

@@ -7,6 +7,7 @@ import org.apache.commons.lang3.StringUtils;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.GameEntity; import forge.GameEntity;
import forge.ITargetable;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.Game; import forge.game.Game;
@@ -142,7 +143,7 @@ public class UnattachAllEffect extends SpellAbilityEffect {
protected String getStackDescription(SpellAbility sa) { protected String getStackDescription(SpellAbility sa) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("Unattach all valid Equipment and Auras from "); sb.append("Unattach all valid Equipment and Auras from ");
final List<Object> targets = getTargetObjects(sa); final List<ITargetable> targets = getTargetObjects(sa);
sb.append(StringUtils.join(targets, " ")); sb.append(StringUtils.join(targets, " "));
return sb.toString(); return sb.toString();
} }
@@ -154,7 +155,7 @@ public class UnattachAllEffect extends SpellAbilityEffect {
public void resolve(SpellAbility sa) { public void resolve(SpellAbility sa) {
Card source = sa.getSourceCard(); Card source = sa.getSourceCard();
final Game game = sa.getActivatingPlayer().getGame(); final Game game = sa.getActivatingPlayer().getGame();
final List<Object> targets = getTargetObjects(sa); final List<ITargetable> targets = getTargetObjects(sa);
// If Cast Targets will be checked on the Stack // If Cast Targets will be checked on the Stack
for (final Object o : targets) { for (final Object o : targets) {

View File

@@ -18,11 +18,13 @@
package forge.card.spellability; package forge.card.spellability;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import forge.Card; import forge.Card;
import forge.CardCharacteristicName; import forge.CardCharacteristicName;
import forge.ITargetable;
import forge.card.CardType; import forge.card.CardType;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.cost.CostPartMana; import forge.card.cost.CostPartMana;
@@ -202,7 +204,7 @@ public class HumanPlaySpellAbility {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append(ability.getSourceCard().getName()); sb.append(ability.getSourceCard().getName());
if (ability.getTarget() != null) { if (ability.getTarget() != null) {
final ArrayList<Object> targets = ability.getTarget().getTargets(); final List<ITargetable> targets = ability.getTarget().getTargets();
if (targets.size() > 0) { if (targets.size() > 0) {
sb.append(" - Targeting "); sb.append(" - Targeting ");
for (final Object o : targets) { for (final Object o : targets) {

View File

@@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
import forge.Card; import forge.Card;
import forge.GameEntity; import forge.GameEntity;
import forge.ITargetable;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.cost.Cost; import forge.card.cost.Cost;
@@ -48,7 +49,7 @@ import forge.util.TextUtil;
* @author Forge * @author Forge
* @version $Id$ * @version $Id$
*/ */
public abstract class SpellAbility implements ISpellAbility { public abstract class SpellAbility implements ISpellAbility, ITargetable {
// choices for constructor isPermanent argument // choices for constructor isPermanent argument
private String description = ""; private String description = "";
@@ -890,79 +891,6 @@ public abstract class SpellAbility implements ISpellAbility {
return this.subAbility; return this.subAbility;
} }
/**
* <p>
* Getter for the field <code>targetCard</code>.
* </p>
*
* @return a {@link forge.Card} object.
*/
public Card getTargetCard() {
if (this.targetCard == null) {
final Target tgt = this.getTarget();
if (tgt != null) {
final List<Card> list = tgt.getTargetCards();
if (!list.isEmpty()) {
return list.get(0);
}
}
return null;
}
return this.targetCard;
}
/**
* <p>
* Setter for the field <code>targetCard</code>.
* </p>
*
* @param card
* a {@link forge.Card} object.
*/
public void setTargetCard(final Card card) {
if (card == null) {
System.out.println(this.getSourceCard()
+ " - SpellAbility.setTargetCard() called with null for target card.");
return;
}
final Target tgt = this.getTarget();
if (tgt != null) {
tgt.addTarget(card);
} else {
this.targetCard = card;
}
String desc = "";
if (!card.isFaceDown()) {
desc = this.getSourceCard().getName() + " - targeting " + card;
} else {
desc = this.getSourceCard().getName() + " - targeting Morph(" + card.getUniqueNumber() + ")";
}
this.setStackDescription(desc);
}
/**
* <p>
* Getter for the field <code>targetPlayer</code>.
* </p>
*
* @return a {@link forge.game.player.Player} object.
*/
public Player getTargetPlayer() {
final Target tgt = this.getTarget();
if (tgt != null) {
final List<Player> list = tgt.getTargetPlayers();
if (!list.isEmpty()) {
return list.get(0);
}
}
return null;
}
/** /**
* <p> * <p>
* isBasicAbility. * isBasicAbility.
@@ -1211,25 +1139,6 @@ public abstract class SpellAbility implements ISpellAbility {
this.delve = isDelve0; this.delve = isDelve0;
} }
/**
* Gets the chosen target.
*
* @return the chosenTarget
*/
public Target getChosenTarget() {
return this.chosenTarget;
}
/**
* Sets the chosen target.
*
* @param chosenTarget0
* the chosenTarget to set
*/
public void setChosenTarget(final Target chosenTarget0) {
this.chosenTarget = chosenTarget0;
}
/** /**
* Adds the tapped for convoke. * Adds the tapped for convoke.
* *
@@ -1368,6 +1277,178 @@ public abstract class SpellAbility implements ISpellAbility {
return null; return null;
} }
/**
* TODO: Write javadoc for this method.
* @return
*/
public boolean isUndoable() {
return this.undoable && this.payCosts.isUndoable() && this.getSourceCard().isInPlay();
}
/**
* TODO: Write javadoc for this method.
*/
public void undo() {
if (isUndoable()) {
this.payCosts.refundPaidCost(sourceCard);
}
}
/**
* TODO: Write javadoc for this method.
* @param b
*/
public void setUndoable(boolean b) {
this.undoable = b;
}
/**
* @return the isCopied
*/
public boolean isCopied() {
return isCopied;
}
/**
* @param isCopied0 the isCopied to set
*/
public void setCopied(boolean isCopied0) {
this.isCopied = isCopied0;
}
/**
* Returns whether variable was present in the announce list.
*/
public boolean isAnnouncing(String variable) {
String announce = getParam("Announce");
if (StringUtils.isBlank(announce)) return false;
String[] announcedOnes = TextUtil.split(announce, ',');
for(String a : announcedOnes) {
if( a.trim().equalsIgnoreCase(variable))
return true;
}
return false;
}
public boolean isXCost() {
CostPartMana cm = payCosts != null ? getPayCosts().getCostMana() : null;
return cm != null && cm.getAmountOfX() > 0;
}
public boolean isBasicLandAbility() {
return basicLandAbility;
}
public void setBasicLandAbility(boolean basicLandAbility) {
this.basicLandAbility = basicLandAbility; // TODO: Add 0 to parameter's name.
}
public boolean isTemporary() {
return temporary;
}
public void setTemporary(boolean temporary) {
this.temporary = temporary; // TODO: Add 0 to parameter's name.
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// THE CODE BELOW IS RELATED TO TARGETING. It shall await extraction to other class from here
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* <p>
* Getter for the field <code>targetCard</code>.
* </p>
*
* @return a {@link forge.Card} object.
*/
public Card getTargetCard() {
if (this.targetCard == null) {
final Target tgt = this.getTarget();
if (tgt != null) {
final List<Card> list = tgt.getTargetCards();
if (!list.isEmpty()) {
return list.get(0);
}
}
return null;
}
return this.targetCard;
}
/**
* <p>
* Setter for the field <code>targetCard</code>.
* </p>
*
* @param card
* a {@link forge.Card} object.
*/
public void setTargetCard(final Card card) {
if (card == null) {
System.out.println(this.getSourceCard()
+ " - SpellAbility.setTargetCard() called with null for target card.");
return;
}
final Target tgt = this.getTarget();
if (tgt != null) {
tgt.addTarget(card);
} else {
this.targetCard = card;
}
String desc = "";
if (!card.isFaceDown()) {
desc = this.getSourceCard().getName() + " - targeting " + card;
} else {
desc = this.getSourceCard().getName() + " - targeting Morph(" + card.getUniqueNumber() + ")";
}
this.setStackDescription(desc);
}
/**
* <p>
* Getter for the field <code>targetPlayer</code>.
* </p>
*
* @return a {@link forge.game.player.Player} object.
*/
public Player getTargetPlayer() {
final Target tgt = this.getTarget();
if (tgt != null) {
final List<Player> list = tgt.getTargetPlayers();
if (!list.isEmpty()) {
return list.get(0);
}
}
return null;
}
/**
* Gets the chosen target.
*
* @return the chosenTarget
*/
public Target getChosenTarget() {
return this.chosenTarget;
}
/**
* Sets the chosen target.
*
* @param chosenTarget0
* the chosenTarget to set
*/
public void setChosenTarget(final Target chosenTarget0) {
this.chosenTarget = chosenTarget0;
}
/** /**
* <p> * <p>
* findTargetCards. * findTargetCards.
@@ -1415,7 +1496,7 @@ public abstract class SpellAbility implements ISpellAbility {
* @return a {@link forge.card.spellability.SpellAbility} object. * @return a {@link forge.card.spellability.SpellAbility} object.
*/ */
public SpellAbility getSATargetingCard() { public SpellAbility getSATargetingCard() {
Target tgt = this.getTarget(); Target tgt = this.getTarget();
if (tgt != null && tgt.getTargetCards() != null && !tgt.getTargetCards().isEmpty()) { if (tgt != null && tgt.getTargetCards() != null && !tgt.getTargetCards().isEmpty()) {
return this; return this;
@@ -1434,7 +1515,7 @@ public abstract class SpellAbility implements ISpellAbility {
*/ */
public SpellAbility getParentTargetingCard() { public SpellAbility getParentTargetingCard() {
SpellAbility parent = this.getParent(); SpellAbility parent = this.getParent();
while (parent != null) { while (parent != null) {
Target tgt = parent.getTarget(); Target tgt = parent.getTarget();
if (tgt != null && tgt.getTargetCards() != null && !tgt.getTargetCards().isEmpty()) { if (tgt != null && tgt.getTargetCards() != null && !tgt.getTargetCards().isEmpty()) {
@@ -1471,15 +1552,15 @@ public abstract class SpellAbility implements ISpellAbility {
*/ */
public SpellAbility getParentTargetingSA() { public SpellAbility getParentTargetingSA() {
SpellAbility parent = this.getParent(); SpellAbility parent = this.getParent();
while (parent != null) { while (parent != null) {
Target tgt = parent.getTarget(); Target tgt = parent.getTarget();
if (tgt != null && tgt.getTargetSAs() != null && !tgt.getTargetSAs().isEmpty()) { if (tgt != null && tgt.getTargetSAs() != null && !tgt.getTargetSAs().isEmpty()) {
break; break;
} }
parent = parent.getParent(); parent = parent.getParent();
} }
return parent; return parent;
} }
@@ -1511,56 +1592,17 @@ public abstract class SpellAbility implements ISpellAbility {
public SpellAbility getParentTargetingPlayer() { public SpellAbility getParentTargetingPlayer() {
SpellAbility parent = this.getParent(); SpellAbility parent = this.getParent();
while (parent != null) { while (parent != null) {
Target tgt = parent.getTarget(); Target tgt = parent.getTarget();
if (tgt != null && tgt.getTargetPlayers() != null && !tgt.getTargetPlayers().isEmpty()) { if (tgt != null && tgt.getTargetPlayers() != null && !tgt.getTargetPlayers().isEmpty()) {
break; break;
} }
parent = parent.getParent(); parent = parent.getParent();
} }
return parent; return parent;
} }
/**
* TODO: Write javadoc for this method.
* @return
*/
public boolean isUndoable() {
return this.undoable && this.payCosts.isUndoable() && this.getSourceCard().isInPlay();
}
/**
* TODO: Write javadoc for this method.
*/
public void undo() {
if (isUndoable()) {
this.payCosts.refundPaidCost(sourceCard);
}
}
/**
* TODO: Write javadoc for this method.
* @param b
*/
public void setUndoable(boolean b) {
this.undoable = b;
}
/**
* @return the isCopied
*/
public boolean isCopied() {
return isCopied;
}
/**
* @param isCopied0 the isCopied to set
*/
public void setCopied(boolean isCopied0) {
this.isCopied = isCopied0;
}
/** /**
* Gets the unique targets. * Gets the unique targets.
* *
@@ -1568,8 +1610,8 @@ public abstract class SpellAbility implements ISpellAbility {
* the ability * the ability
* @return the unique targets * @return the unique targets
*/ */
public final List<Object> getUniqueTargets() { public final List<ITargetable> getUniqueTargets() {
final List<Object> targets = new ArrayList<Object>(); final List<ITargetable> targets = new ArrayList<ITargetable>();
SpellAbility child = this.getParent(); SpellAbility child = this.getParent();
while (child != null) { while (child != null) {
if (child.getTarget() != null) { if (child.getTarget() != null) {
@@ -1579,11 +1621,16 @@ public abstract class SpellAbility implements ISpellAbility {
} }
return targets; return targets;
} }
@Override
public boolean canBeTargetedBy(SpellAbility sa) {
return sa.canBeTargetedBy(this);
}
public boolean canTargetSpellAbility(final SpellAbility topSA) { public boolean canTargetSpellAbility(final SpellAbility topSA) {
final Target tgt = this.getTarget(); final Target tgt = this.getTarget();
final String saType = tgt.getTargetSpellAbilityType(); final String saType = tgt.getTargetSpellAbilityType();
if (null == saType) { if (null == saType) {
// just take this to mean no restrictions - carry on. // just take this to mean no restrictions - carry on.
} else if (topSA instanceof Spell) { } else if (topSA instanceof Spell) {
@@ -1601,31 +1648,31 @@ public abstract class SpellAbility implements ISpellAbility {
} else { } else {
return false; //Static ability? Whatever. return false; //Static ability? Whatever.
} }
final String splitTargetRestrictions = tgt.getSAValidTargeting(); final String splitTargetRestrictions = tgt.getSAValidTargeting();
if (splitTargetRestrictions != null) { if (splitTargetRestrictions != null) {
// TODO What about spells with SubAbilities with Targets? // TODO What about spells with SubAbilities with Targets?
final Target matchTgt = topSA.getTarget(); final Target matchTgt = topSA.getTarget();
if (matchTgt == null) { if (matchTgt == null) {
return false; return false;
} }
boolean result = false; boolean result = false;
for (final Object o : matchTgt.getTargets()) { for (final Object o : matchTgt.getTargets()) {
if (matchesValid(o, splitTargetRestrictions.split(","))) { if (matchesValid(o, splitTargetRestrictions.split(","))) {
result = true; result = true;
break; break;
} }
} }
if (!result) { if (!result) {
return false; return false;
} }
} }
if (tgt.isSingleTarget()) { if (tgt.isSingleTarget()) {
final ArrayList<TargetChoices> choices = topSA.getAllTargetChoices(); final ArrayList<TargetChoices> choices = topSA.getAllTargetChoices();
int totalTargets = 0; int totalTargets = 0;
@@ -1641,11 +1688,10 @@ public abstract class SpellAbility implements ISpellAbility {
return false; return false;
} }
} }
return topSA.getSourceCard().isValid(tgt.getValidTgts(), this.getActivatingPlayer(), this.getSourceCard()); return topSA.getSourceCard().isValid(tgt.getValidTgts(), this.getActivatingPlayer(), this.getSourceCard());
} }
private boolean matchesValid(final Object o, final String[] valids) { private boolean matchesValid(final Object o, final String[] valids) {
final Card srcCard = this.getSourceCard(); final Card srcCard = this.getSourceCard();
final Player activatingPlayer = this.getActivatingPlayer(); final Player activatingPlayer = this.getActivatingPlayer();
@@ -1653,49 +1699,14 @@ public abstract class SpellAbility implements ISpellAbility {
final Card c = (Card) o; final Card c = (Card) o;
return c.isValid(valids, activatingPlayer, srcCard); return c.isValid(valids, activatingPlayer, srcCard);
} }
if (o instanceof Player) { if (o instanceof Player) {
Player p = (Player) o; Player p = (Player) o;
if (p.isValid(valids, activatingPlayer, srcCard)) { if (p.isValid(valids, activatingPlayer, srcCard)) {
return true; return true;
} }
} }
return false; return false;
} }
/**
* Returns whether variable was present in the announce list.
*/
public boolean isAnnouncing(String variable) {
String announce = getParam("Announce");
if (StringUtils.isBlank(announce)) return false;
String[] announcedOnes = TextUtil.split(announce, ',');
for(String a : announcedOnes) {
if( a.trim().equalsIgnoreCase(variable))
return true;
}
return false;
}
public boolean isXCost() {
CostPartMana cm = payCosts != null ? getPayCosts().getCostMana() : null;
return cm != null && cm.getAmountOfX() > 0;
}
public boolean isBasicLandAbility() {
return basicLandAbility;
}
public void setBasicLandAbility(boolean basicLandAbility) {
this.basicLandAbility = basicLandAbility; // TODO: Add 0 to parameter's name.
}
public boolean isTemporary() {
return temporary;
}
public void setTemporary(boolean temporary) {
this.temporary = temporary; // TODO: Add 0 to parameter's name.
}
} }

View File

@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import forge.Card; import forge.Card;
import forge.ITargetable;
import forge.card.CardType; import forge.card.CardType;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.game.Game; import forge.game.Game;
@@ -518,9 +519,9 @@ public class Target {
* *
* @return a {@link java.util.ArrayList} object. * @return a {@link java.util.ArrayList} object.
*/ */
public final ArrayList<Object> getTargets() { public final List<ITargetable> getTargets() {
if (this.choice == null) { if (this.choice == null) {
return new ArrayList<Object>(); return new ArrayList<ITargetable>();
} }
return this.choice.getTargets(); return this.choice.getTargets();
@@ -557,7 +558,7 @@ public class Target {
* @return a {@link java.lang.String} object. * @return a {@link java.lang.String} object.
*/ */
public final String getTargetedString() { public final String getTargetedString() {
final ArrayList<Object> tgts = this.getTargets(); final List<ITargetable> tgts = this.getTargets();
final StringBuilder sb = new StringBuilder(""); final StringBuilder sb = new StringBuilder("");
for (final Object o : tgts) { for (final Object o : tgts) {
if (o instanceof Player) { if (o instanceof Player) {

View File

@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import forge.Card; import forge.Card;
import forge.ITargetable;
import forge.game.player.Player; import forge.game.player.Player;
/** /**
@@ -233,8 +234,8 @@ public class TargetChoices {
* *
* @return a {@link java.util.ArrayList} object. * @return a {@link java.util.ArrayList} object.
*/ */
public final ArrayList<Object> getTargets() { public final List<ITargetable> getTargets() {
final ArrayList<Object> tgts = new ArrayList<Object>(); final ArrayList<ITargetable> tgts = new ArrayList<ITargetable>();
tgts.addAll(this.targetPlayers); tgts.addAll(this.targetPlayers);
tgts.addAll(this.targetCards); tgts.addAll(this.targetCards);
tgts.addAll(this.targetSAs); tgts.addAll(this.targetSAs);
@@ -250,8 +251,8 @@ public class TargetChoices {
* @return a {@link java.lang.String} object. * @return a {@link java.lang.String} object.
*/ */
public final String getTargetedString() { public final String getTargetedString() {
final ArrayList<Object> tgts = this.getTargets(); final List<ITargetable> tgts = this.getTargets();
final StringBuilder sb = new StringBuilder(""); final StringBuilder sb = new StringBuilder();
for (final Object o : tgts) { for (final Object o : tgts) {
if (o instanceof Player) { if (o instanceof Player) {
final Player p = (Player) o; final Player p = (Player) o;

View File

@@ -24,6 +24,7 @@ import com.google.common.base.Predicate;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.ITargetable;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.game.Game; import forge.game.Game;
@@ -151,7 +152,7 @@ public class TargetSelection {
choices.remove(tgt.getSourceCard()); choices.remove(tgt.getSourceCard());
} }
} }
List<Object> targetedObjects = this.ability.getUniqueTargets(); List<ITargetable> targetedObjects = this.ability.getUniqueTargets();
if (tgt.isUniqueTargets()) { if (tgt.isUniqueTargets()) {
for (final Object o : targetedObjects) { for (final Object o : targetedObjects) {

View File

@@ -33,6 +33,7 @@ import forge.CardPredicates;
import forge.Constant; import forge.Constant;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.CardUtil; import forge.CardUtil;
import forge.ITargetable;
import forge.card.CardType; import forge.card.CardType;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
@@ -1287,10 +1288,10 @@ public class ComputerUtil {
* @return a {@link java.util.ArrayList} object. * @return a {@link java.util.ArrayList} object.
* @since 1.0.15 * @since 1.0.15
*/ */
public static ArrayList<Object> predictThreatenedObjects(final Player aiPlayer, final SpellAbility saviour, public static List<ITargetable> predictThreatenedObjects(final Player aiPlayer, final SpellAbility saviour,
final SpellAbility topStack) { final SpellAbility topStack) {
ArrayList<Object> objects = new ArrayList<Object>(); List<ITargetable> objects = new ArrayList<ITargetable>();
final ArrayList<Object> threatened = new ArrayList<Object>(); final List<ITargetable> threatened = new ArrayList<ITargetable>();
ApiType saviourApi = saviour.getApi(); ApiType saviourApi = saviour.getApi();
if (topStack == null) { if (topStack == null) {

View File

@@ -35,6 +35,7 @@ import forge.CardLists;
import forge.CardPredicates; import forge.CardPredicates;
import forge.Command; import forge.Command;
import forge.FThreads; import forge.FThreads;
import forge.ITargetable;
import forge.Singletons; import forge.Singletons;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.GameLogEntryType; import forge.GameLogEntryType;
@@ -679,7 +680,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
fizzle = true; fizzle = true;
// With multi-targets, as long as one target is still legal, // With multi-targets, as long as one target is still legal,
// we'll try to go through as much as possible // we'll try to go through as much as possible
final ArrayList<Object> tgts = tgt.getTargets(); final List<ITargetable> tgts = tgt.getTargets();
final TargetChoices choices = tgt.getTargetChoices(); final TargetChoices choices = tgt.getTargetChoices();
for (final Object o : tgts) { for (final Object o : tgts) {
boolean invalidTarget = false; boolean invalidTarget = false;