card class clean up.

cards will determine their ability to flip or transform by presence of a matching altername state
This commit is contained in:
Maxmtg
2013-04-09 09:54:44 +00:00
parent eca7b00013
commit 9099176144
11 changed files with 67 additions and 416 deletions

View File

@@ -38,7 +38,6 @@ import forge.CardPredicates.Presets;
import forge.card.CardCharacteristics;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.CardSplitType;
import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType;
import forge.card.cardfactory.CardFactoryUtil;
@@ -89,10 +88,6 @@ public class Card extends GameEntity implements Comparable<Card> {
private CardCharacteristicName curCharacteristics = CardCharacteristicName.Original;
private CardCharacteristicName preTFDCharacteristic = CardCharacteristicName.Original;
private boolean isDoubleFaced = false;
private boolean isFlipCard = false;
private CardCharacteristicName otherTransformable = null;
private ZoneType castFrom = null;
private final CardDamageHistory damageHistory = new CardDamageHistory();
@@ -141,7 +136,6 @@ public class Card extends GameEntity implements Comparable<Card> {
private boolean copiedToken = false;
private boolean copiedSpell = false;
private boolean spellWithChoices = false;
private boolean spellCopyingCard = false;
private ArrayList<Card> mustBlockCards = null;
@@ -288,7 +282,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return true, if successful
*/
public boolean setState(final CardCharacteristicName state) {
if (state == CardCharacteristicName.FaceDown && this.isDoubleFaced) {
if (state == CardCharacteristicName.FaceDown && this.isDoubleFaced()) {
return false; // Doublefaced cards can't be turned face-down.
}
@@ -358,7 +352,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return true, if successful
*/
public boolean turnFaceDown() {
if (!this.isDoubleFaced) {
if (!this.isDoubleFaced()) {
this.preTFDCharacteristic = this.curCharacteristics;
return this.setState(CardCharacteristicName.FaceDown);
}
@@ -392,20 +386,6 @@ public class Card extends GameEntity implements Comparable<Card> {
return false;
}
/**
* Checks if is cloned.
*
* @return true, if is cloned
*/
public boolean isCloned() {
for (final CardCharacteristicName state : this.characteristicsMap.keySet()) {
if (state == CardCharacteristicName.Cloner) {
return true;
}
}
return false;
}
/**
* Gets the state.
*
@@ -477,76 +457,25 @@ public class Card extends GameEntity implements Comparable<Card> {
return this.characteristicsMap.keySet().size() > 2;
}
/**
* Checks if is double faced.
*
* @return the isDoubleFaced
*/
public final boolean isDoubleFaced() {
return this.isDoubleFaced;
return characteristicsMap.containsKey(CardCharacteristicName.Transformed);
}
/**
* Sets the double faced.
*
* @param isDoubleFaced0
* the isDoubleFaced to set
*/
public final void setDoubleFaced(final boolean isDoubleFaced0) {
this.isDoubleFaced = isDoubleFaced0;
}
/**
* Checks if is flip card.
*
* @return the isFlipCard
*/
public final boolean isFlipCard() {
return this.isFlipCard;
return characteristicsMap.containsKey(CardCharacteristicName.Flipped);
}
public final boolean isSplitCard() {
return cardRules != null && cardRules.getSplitType() == CardSplitType.Split;
return characteristicsMap.containsKey(CardCharacteristicName.LeftSplit);
}
/**
* Sets the flip card.
* Checks if is cloned.
*
* @param isFlip0
* the isFlip to set
* @return true, if is cloned
*/
public final void setFlipCard(final boolean isFlip0) {
this.isFlipCard = isFlip0;
}
/**
*
* Checks if card status is flipped.
*
* @return the flipped
*/
public final boolean isFlipped() {
return curCharacteristics == CardCharacteristicName.Flipped;
}
/**
* Checks if this is transformable (i.e. Licids.)
*
* @return a boolean
*/
public final CardCharacteristicName isTransformable() {
return this.otherTransformable;
}
/**
* Sets whether or not this card is transformable, but non-flip and not
* double-faced.
*
* @param otherTransformable0
* a String
*/
public final void setTransformable(final CardCharacteristicName otherTransformable0) {
this.otherTransformable = otherTransformable0;
public boolean isCloned() {
return characteristicsMap.containsKey(CardCharacteristicName.Cloner);
}
/**
@@ -2390,9 +2319,8 @@ public class Card extends GameEntity implements Comparable<Card> {
}
final ArrayList<String> addedManaStrings = new ArrayList<String>();
final SpellAbility[] abilities = this.getSpellAbility();
boolean primaryCost = true;
for (final SpellAbility sa : abilities) {
for (final SpellAbility sa : this.getSpellAbilities()) {
// only add abilities not Spell portions of cards
if (!this.isPermanent()) {
continue;
@@ -2465,8 +2393,7 @@ public class Card extends GameEntity implements Comparable<Card> {
}
// Add SpellAbilities
final SpellAbility[] sa = this.getSpellAbility();
for (final SpellAbility element : sa) {
for (final SpellAbility element : this.getSpellAbilities()) {
sb.append(element.toString() + "\r\n");
}
@@ -2681,23 +2608,10 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return a SpellAbility object.
*/
public final SpellAbility getFirstSpellAbility() {
final ArrayList<SpellAbility> sas = this.getCharacteristics().getSpellAbility();
if (!sas.isEmpty()) {
return sas.get(0);
final List<SpellAbility> sas = this.getCharacteristics().getSpellAbility();
return sas.isEmpty() ? null : sas.get(0);
}
return null;
}
/**
* <p>
* clearSpellAbility.
* </p>
*/
public final void clearSpellAbility() {
this.getCharacteristics().getSpellAbility().clear();
this.getCharacteristics().getManaAbility().clear();
}
/**
* <p>
@@ -2715,15 +2629,6 @@ public class Card extends GameEntity implements Comparable<Card> {
return null;
}
/**
* <p>
* clearSpellKeepManaAbility.
* </p>
*/
public final void clearSpellKeepManaAbility() {
this.getCharacteristics().getSpellAbility().clear();
}
/**
* <p>
* addSpellAbility.
@@ -2761,20 +2666,6 @@ public class Card extends GameEntity implements Comparable<Card> {
}
}
/**
* <p>
* Getter for the field <code>spellAbility</code>.
* </p>
*
* @return an array of {@link forge.card.spellability.SpellAbility} objects.
*/
public final SpellAbility[] getSpellAbility() {
final ArrayList<SpellAbility> res = getSpellAbilities();
final SpellAbility[] s = new SpellAbility[res.size()];
res.toArray(s);
return s;
}
/**
* <p>
* getSpellAbilities.
@@ -2795,7 +2686,7 @@ public class Card extends GameEntity implements Comparable<Card> {
*
* @return a {@link java.util.ArrayList} object.
*/
public final ArrayList<SpellAbility> getNonManaSpellAbilities() {
public final List<SpellAbility> getNonManaSpellAbilities() {
return this.getCharacteristics().getSpellAbility();
}
@@ -2853,18 +2744,6 @@ public class Card extends GameEntity implements Comparable<Card> {
}
// shield = regeneration
/**
* <p>
* setShield.
* </p>
*
* @param n
* a int.
*/
public final void setShield(final int n) {
this.nShield = n;
}
/**
* <p>
* getShield.
@@ -3033,29 +2912,6 @@ public class Card extends GameEntity implements Comparable<Card> {
return this.spellWithChoices;
}
/**
* <p>
* setCopiesSpells.
* </p>
*
* @param b
* a boolean.
*/
public final void setCopiesSpells(final boolean b) {
this.spellCopyingCard = b;
}
/**
* <p>
* copiesSpells.
* </p>
*
* @return a boolean.
*/
public final boolean copiesSpells() {
return this.spellCopyingCard;
}
/**
* <p>
* isFaceDown.
@@ -5194,204 +5050,36 @@ public class Card extends GameEntity implements Comparable<Card> {
return stAb;
}
/**
* <p>
* isPermanent.
* </p>
*
* @return a boolean.
*/
public final boolean isPermanent() {
return !(this.isInstant() || this.isSorcery() || this.isImmutable());
}
/**
* <p>
* isSpell.
* </p>
*
* @return a boolean.
*/
public final boolean isSpell() {
return (this.isInstant() || this.isSorcery() || (this.isAura() && !this.isInZone((ZoneType.Battlefield))));
}
/**
* <p>
* isCreature.
* </p>
*
* @return a boolean.
*/
public final boolean isCreature() {
return this.typeContains("Creature");
}
public final boolean isEmblem() { return this.typeContains("Emblem"); }
/**
* <p>
* isWall.
* </p>
*
* @return a boolean.
*/
public final boolean isWall() {
return this.typeContains("Wall");
}
public final boolean isLand() { return this.typeContains("Land"); }
public final boolean isBasicLand() { return this.typeContains("Basic"); }
public final boolean isSnow() { return this.typeContains("Snow"); }
/**
* <p>
* isBasicLand.
* </p>
*
* @return a boolean.
*/
public final boolean isBasicLand() {
return this.typeContains("Basic");
}
public final boolean isTribal() { return this.typeContains("Tribal"); }
public final boolean isSorcery() { return this.typeContains("Sorcery"); }
public final boolean isInstant() { return this.typeContains("Instant"); }
/**
* <p>
* isLand.
* </p>
*
* @return a boolean.
*/
public final boolean isLand() {
return this.typeContains("Land");
}
public final boolean isCreature() { return this.typeContains("Creature"); }
public final boolean isArtifact() { return this.typeContains("Artifact"); }
public final boolean isEquipment() { return this.typeContains("Equipment"); }
public final boolean isScheme() { return this.typeContains("Scheme"); }
/**
* <p>
* isSorcery.
* </p>
*
* @return a boolean.
*/
public final boolean isSorcery() {
return this.typeContains("Sorcery");
}
/**
* <p>
* isInstant.
* </p>
*
* @return a boolean.
*/
public final boolean isInstant() {
return this.typeContains("Instant");
}
public final boolean isPlaneswalker() { return this.typeContains("Planeswalker"); }
/**
* <p>
* isArtifact.
* </p>
*
* @return a boolean.
*/
public final boolean isArtifact() {
return this.typeContains("Artifact");
}
public final boolean isEnchantment() { return this.typeContains("Enchantment"); }
public final boolean isAura() { return this.typeContains("Aura"); }
/**
* <p>
* isEquipment.
* </p>
*
* @return a boolean.
*/
public final boolean isEquipment() {
return this.typeContains("Equipment");
}
/**
* <p>
* isScheme.
* </p>
*
* @return a boolean.
*/
public final boolean isScheme() {
return this.typeContains("Scheme");
}
/**
* <p>
* isPlaneswalker.
* </p>
*
* @return a boolean.
*/
public final boolean isPlaneswalker() {
return this.typeContains("Planeswalker");
}
/**
* <p>
* isEmblem.
* </p>
*
* @return a boolean.
*/
public final boolean isEmblem() {
return this.typeContains("Emblem");
}
/**
* <p>
* isTribal.
* </p>
*
* @return a boolean.
*/
public final boolean isTribal() {
return this.typeContains("Tribal");
}
/**
* <p>
* isSnow.
* </p>
*
* @return a boolean.
*/
public final boolean isSnow() {
return this.typeContains("Snow");
}
// global and local enchantments
/**
* <p>
* isEnchantment.
* </p>
*
* @return a boolean.
*/
public final boolean isEnchantment() {
return this.typeContains("Enchantment");
}
/**
* <p>
* isAura.
* </p>
*
* @return a boolean.
*/
public final boolean isAura() {
return this.typeContains("Aura");
}
/**
* <p>
* isGlobalEnchantment.
* </p>
*
* @return a boolean.
*/
public final boolean isGlobalEnchantment() {
return this.typeContains("Enchantment") && (!this.isAura());
}
private boolean typeContains(final String s) {
final Iterator<?> it = this.getType().iterator();
@@ -6115,11 +5803,11 @@ public class Card extends GameEntity implements Comparable<Card> {
return false;
}
} else if (property.equals("DoubleFaced")) {
if (!this.isDoubleFaced) {
if (!this.isDoubleFaced()) {
return false;
}
} else if (property.equals("Flip")) {
if (!this.isFlipCard) {
if (!this.isFlipCard()) {
return false;
}
} else if (property.startsWith("YouCtrl")) {
@@ -7002,11 +6690,10 @@ public class Card extends GameEntity implements Comparable<Card> {
return false;
}
} else if (property.startsWith("hasXCost")) {
if (this.getSpellAbility().length > 0) {
if (!this.getSpellAbility()[0].isXCost()) {
SpellAbility sa1 = this.getFirstSpellAbility();
if( sa1 != null && !sa1.isXCost()) {
return false;
}
}
} else if (property.startsWith("suspended")) {
if (!this.hasSuspend() || !Singletons.getModel().getGame().isCardExiled(this)
|| !(this.getCounters(CounterType.getType("TIME")) >= 1)) {

View File

@@ -138,9 +138,7 @@ public final class CardUtil {
newCopy.setCurSetCode(in.getCurSetCode());
newCopy.setOwner(in.getOwner());
newCopy.setController(in.getController(), 0);
newCopy.setFlipCard(in.isFlipCard());
newCopy.setDoubleFaced(in.isDoubleFaced());
newCopy.getCharacteristics().copy(in.getState(in.getCurState()));
newCopy.getCharacteristics().copyFrom(in.getState(in.getCurState()));
newCopy.setBaseAttack(in.getNetAttack());
newCopy.setBaseDefense(in.getNetDefense());
newCopy.setType(new ArrayList<String>(in.getType()));

View File

@@ -223,8 +223,7 @@ public class StaticEffects {
// remove abilities
if (params.containsKey("AddAbility") || params.containsKey("GainsAbilitiesOf")) {
final SpellAbility[] spellAbility = affectedCard.getSpellAbility();
for (final SpellAbility s : spellAbility) {
for (final SpellAbility s : affectedCard.getSpellAbilities()) {
if (s.getType().equals("Temporary")) {
affectedCard.removeSpellAbility(s);
}

View File

@@ -43,7 +43,7 @@ public class CardCharacteristics {
private int baseAttack = 0;
private int baseDefense = 0;
private ArrayList<String> intrinsicKeyword = new ArrayList<String>();
private final ArrayList<SpellAbility> spellAbility = new ArrayList<SpellAbility>();
private final List<SpellAbility> spellAbility = new ArrayList<SpellAbility>();
private final List<SpellAbility> manaAbility = new ArrayList<SpellAbility>();
private ArrayList<String> intrinsicAbility = new ArrayList<String>();
private ArrayList<Trigger> triggers = new ArrayList<Trigger>();
@@ -203,7 +203,7 @@ public class CardCharacteristics {
*
* @return the spellAbility
*/
public final ArrayList<SpellAbility> getSpellAbility() {
public final List<SpellAbility> getSpellAbility() {
return this.spellAbility;
}
@@ -388,7 +388,7 @@ public class CardCharacteristics {
* @param source
* a Map object.
*/
public final void copy(final CardCharacteristics source) {
public final void copyFrom(final CardCharacteristics source) {
// Makes a "deeper" copy of a CardCharacteristics object
// String name : just copy reference

View File

@@ -126,17 +126,8 @@ public final class AbilityFactory {
Target abTgt = mapParams.containsKey("ValidTgts") ? readTarget(hostCard, mapParams) : null;
if (api == ApiType.CopySpellAbility) {
if (abTgt != null) {
if (api == ApiType.CopySpellAbility || api == ApiType.Counter || api == ApiType.ChangeTargets) {
// Since all "CopySpell" ABs copy things on the Stack no need for it to be everywhere
abTgt.setZone(ZoneType.Stack);
}
hostCard.setCopiesSpells(true);
}
else if (api == ApiType.Counter || api == ApiType.ChangeTargets) {
// Since all "Counter" or "ChangeTargets" abilities only target the Stack Zone
// No need to have each of those scripts have that info
if (abTgt != null) {

View File

@@ -159,15 +159,12 @@ public class CloneEffect extends SpellAbilityEffect {
if (keepName) {
tgtCard.setName(originalName);
}
tgtCard.setFlipCard(true);
//keep the Clone card image for the cloned card
tgtCard.setImageKey(imageFileName);
if (!tgtCard.isFlipped()) {
if (tgtCard.getCurState() != CardCharacteristicName.Flipped) {
tgtCard.setState(CardCharacteristicName.Original);
}
} else {
tgtCard.setFlipCard(false);
}
//Clean up copy of cloned state

View File

@@ -358,17 +358,9 @@ public class CardFactory {
// 1. The states we may have:
CardSplitType st = rules.getSplitType();
switch ( st ) {
case Split:
if ( st == CardSplitType.Split) {
card.addAlternateState(CardCharacteristicName.LeftSplit);
card.setState(CardCharacteristicName.LeftSplit);
break;
case Transform: card.setDoubleFaced(true);break;
case Flip: card.setFlipCard(true); break;
case None: break;
default: card.setTransformable(st.getChangedStateName()); break;
}
readCardFace(card, rules.getMainPart());
@@ -458,8 +450,6 @@ public class CardFactory {
public static Card copyStats(final Card sim) {
final Card c = new Card();
c.setFlipCard(sim.isFlipCard());
c.setDoubleFaced(sim.isDoubleFaced());
c.setCurSetCode(sim.getCurSetCode());
final CardCharacteristicName origState = sim.getCurState();
@@ -527,7 +517,7 @@ public class CardFactory {
// get CardCharacteristics for desired state
CardCharacteristics characteristics = from.getState(stateToCopy);
to.getCharacteristics().copy(characteristics);
to.getCharacteristics().copyFrom(characteristics);
// handle triggers and replacement effect through Card class interface
to.setTriggers(characteristics.getTriggers());
to.setReplacementEffects(characteristics.getReplacementEffects());

View File

@@ -394,10 +394,6 @@ public class CardFactoryCreatures {
}
private static void getCard_SurturedGhoul(final Card card) {
final int[] numCreatures = new int[1];
final int[] sumPower = new int[1];
final int[] sumToughness = new int[1];
final Command intoPlay = new Command() {
private static final long serialVersionUID = -75234586897814L;
@@ -406,8 +402,7 @@ public class CardFactoryCreatures {
int intermSumPower = 0;
int intermSumToughness = 0;
// intermSumPower = intermSumToughness = 0;
List<Card> creats =
CardLists.filter(card.getController().getCardsIn(ZoneType.Graveyard), new Predicate<Card>() {
List<Card> creats = CardLists.filter(card.getController().getCardsIn(ZoneType.Graveyard), new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.isCreature() && !c.equals(card);
@@ -415,10 +410,9 @@ public class CardFactoryCreatures {
});
if (card.getController().isHuman()) {
if (creats.size() > 0) {
final List<Card> selection = GuiChoose.noneOrMany("Select creatures to sacrifice", creats);
if (!creats.isEmpty()) {
final List<Card> selection = GuiChoose.noneOrMany("Select creatures to exile", creats);
numCreatures[0] = selection.size();
for (int m = 0; m < selection.size(); m++) {
intermSumPower += selection.get(m).getBaseAttack();
intermSumToughness += selection.get(m).getBaseDefense();
@@ -428,24 +422,19 @@ public class CardFactoryCreatures {
} // human
else {
int count = 0;
for (int i = 0; i < creats.size(); i++) {
final Card c = creats.get(i);
if ((c.getNetAttack() <= 2) && (c.getNetDefense() <= 3)) {
intermSumPower += c.getBaseAttack();
intermSumToughness += c.getBaseDefense();
Singletons.getModel().getGame().getAction().exile(c);
count++;
}
// is this needed?
card.getController().getZone(ZoneType.Battlefield).updateObservers();
}
numCreatures[0] = count;
}
sumPower[0] = intermSumPower;
sumToughness[0] = intermSumToughness;
card.setBaseAttack(sumPower[0]);
card.setBaseDefense(sumToughness[0]);
card.setBaseAttack(intermSumPower);
card.setBaseDefense(intermSumToughness);
}
};
// Do not remove SpellAbilities created by AbilityFactory or

View File

@@ -184,7 +184,7 @@ public class CardFactoryUtil {
}
};
morphDown.setManaCost(new ManaCost(new ManaCostParser("3")));
morphDown.setManaCost(ManaCost.THREE);
morphDown.setDescription("(You may cast this face down as a 2/2 creature for 3.)");
morphDown.setStackDescription("Morph - Creature 2/2");
morphDown.setCastFaceDown(true);
@@ -800,7 +800,7 @@ public class CardFactoryUtil {
return true;
}
for (final SpellAbility sa : c.getSpellAbility()) {
for (final SpellAbility sa : c.getSpellAbilities()) {
final ZoneType restrictZone = sa.getRestrictions().getZone();
if (zone.is(restrictZone)) {
return true;
@@ -2397,7 +2397,7 @@ public class CardFactoryUtil {
final String parse = card.getKeyword().get(n).toString();
final String[] k = parse.split("kicker ");
final SpellAbility sa = card.getSpellAbility()[0];
final SpellAbility sa = card.getFirstSpellAbility();
sa.setMultiKickerManaCost(new ManaCost(new ManaCostParser(k[1])));
}
}
@@ -2408,7 +2408,7 @@ public class CardFactoryUtil {
final String parse = card.getKeyword().get(n).toString();
final String[] k = parse.split("cate ");
final SpellAbility sa = card.getSpellAbility()[0];
final SpellAbility sa = card.getFirstSpellAbility();
sa.setIsReplicate(true);
sa.setReplicateManaCost(new ManaCost(new ManaCostParser(k[1])));
}
@@ -2583,19 +2583,19 @@ public class CardFactoryUtil {
// AddCost
if (!card.getSVar("FullCost").equals("")) {
final SpellAbility[] abilities = card.getSpellAbility();
if ((abilities.length > 0) && abilities[0].isSpell()) {
final SpellAbility sa1 = card.getFirstSpellAbility();
if (sa1 != null && sa1.isSpell()) {
final String altCost = card.getSVar("FullCost");
final Cost abCost = new Cost(card, altCost, abilities[0].isAbility());
abilities[0].setPayCosts(abCost);
final Cost abCost = new Cost(card, altCost, sa1.isAbility());
sa1.setPayCosts(abCost);
}
}
// AltCost
if (!card.getSVar("AltCost").equals("")) {
final SpellAbility[] abilities = card.getSpellAbility();
if ((abilities.length > 0) && abilities[0].isSpell()) {
card.addSpellAbility(makeAltCost(card, abilities[0]));
final SpellAbility sa1 = card.getFirstSpellAbility();
if (sa1 != null && sa1.isSpell()) {
card.addSpellAbility(makeAltCost(card, sa1));
}
}

View File

@@ -712,7 +712,7 @@ public class ComputerUtil {
final Player controller = card.getController();
final List<Card> l = controller.getCardsIn(ZoneType.Battlefield);
for (final Card c : l) {
for (final SpellAbility sa : c.getSpellAbility()) {
for (final SpellAbility sa : c.getSpellAbilities()) {
// This try/catch should fix the "computer is thinking" bug
try {
@@ -778,7 +778,7 @@ public class ComputerUtil {
final Player controller = card.getController();
final List<Card> l = controller.getCardsIn(ZoneType.Battlefield);
for (final Card c : l) {
for (final SpellAbility sa : c.getSpellAbility()) {
for (final SpellAbility sa : c.getSpellAbilities()) {
// if SA is from AF_Counter don't add to getPlayable
// This try/catch should fix the "computer is thinking" bug
try {
@@ -1015,7 +1015,7 @@ public class ComputerUtil {
all.addAll(ai.getCardsIn(ZoneType.Hand));
for (final Card c : all) {
for (final SpellAbility sa : c.getSpellAbility()) {
for (final SpellAbility sa : c.getSpellAbilities()) {
if (sa.getApi() == ApiType.Pump && sa.hasParam("KW") && sa.getParam("KW").contains("Haste")) {
return true;
}

View File

@@ -731,11 +731,11 @@ public class CombatUtil {
}
}
if (attacker.hasKeyword("CARDNAME can't be blocked by Walls.") && blocker.isWall()) {
if (attacker.hasKeyword("CARDNAME can't be blocked by Walls.") && blocker.isType("Wall")) {
return false;
}
if (attacker.hasKeyword("CARDNAME can't be blocked except by Walls.") && !blocker.isWall()) {
if (attacker.hasKeyword("CARDNAME can't be blocked except by Walls.") && !blocker.isType("Wall")) {
return false;
}