Advertisement
Guest User

Card.java

a guest
Jan 27th, 2012
457
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 243.20 KB | None | 0 0
  1. /*
  2.  * Forge: Play Magic: the Gathering.
  3.  * Copyright (C) 2011  Forge Team
  4.  *
  5.  * This program is free software: you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation, either version 3 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18. package forge;
  19.  
  20. import java.util.ArrayList;
  21. import java.util.Arrays;
  22. import java.util.Collection;
  23. import java.util.Collections;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.Map;
  27. import java.util.Map.Entry;
  28. import java.util.Random;
  29. import java.util.Set;
  30. import java.util.TreeMap;
  31.  
  32. import com.esotericsoftware.minlog.Log;
  33.  
  34. import forge.Constant.Zone;
  35. import forge.card.CardCharacteristics;
  36. import forge.card.cardfactory.CardFactoryUtil;
  37. import forge.card.cost.Cost;
  38. import forge.card.mana.ManaCost;
  39. import forge.card.replacement.ReplacementEffect;
  40. import forge.card.spellability.AbilityMana;
  41. import forge.card.spellability.AbilityTriggered;
  42. import forge.card.spellability.SpellAbility;
  43. import forge.card.spellability.SpellPermanent;
  44. import forge.card.staticability.StaticAbility;
  45. import forge.card.trigger.Trigger;
  46. import forge.item.CardDb;
  47. import forge.util.MyRandom;
  48.  
  49. /**
  50.  * <p>
  51.  * Card class.
  52.  * </p>
  53.  *
  54.  * Can now be used as keys in Tree data structures. The comparison is based
  55.  * entirely on getUniqueNumber().
  56.  *
  57.  * @author Forge
  58.  * @version $Id$
  59.  */
  60. public class Card extends GameEntity implements Comparable<Card> {
  61.     private static int nextUniqueNumber = 1;
  62.     private int uniqueNumber = Card.nextUniqueNumber++;
  63.  
  64.     private long value;
  65.  
  66.     private final Map<String, CardCharacteristics> characteristicsMap = new HashMap<String, CardCharacteristics>();
  67.     private String curCharacteristics = "Original";
  68.     private String preTFDCharacteristic = "Original";
  69.  
  70.     private boolean isDoubleFaced = false;
  71.     private boolean isFlip = false;
  72.     private String otherTransformable = "";
  73.  
  74.     private Zone castFrom = null;
  75.  
  76.     /**
  77.      * Instantiates a new card.
  78.      */
  79.     public Card() {
  80.         this.characteristicsMap.put("Original", new CardCharacteristics());
  81.         this.characteristicsMap.put("FaceDown", CardUtil.getFaceDownCharacteristic());
  82.     }
  83.  
  84.     /**
  85.      * Sets the state.
  86.      *
  87.      * @param state
  88.      *            the state
  89.      * @return true, if successful
  90.      */
  91.     public boolean setState(final String state) {
  92.         if (state.equals("FaceDown") && this.isDoubleFaced) {
  93.             return false; // Doublefaced cards can't be turned face-down.
  94.         }
  95.  
  96.         if (!this.characteristicsMap.containsKey(state)) {
  97.             System.out.println(this.getName() + " tried to switch to non-existant state \"" + state + "\"!");
  98.             return false; // Nonexistant state.
  99.         }
  100.  
  101.         if (state.equals(this.curCharacteristics)) {
  102.             return false;
  103.         }
  104.  
  105.         String cur = this.curCharacteristics;
  106.  
  107.         this.curCharacteristics = state;
  108.  
  109.         if ((cur.equals("Original") && state.equals("Transformed"))
  110.                 || (cur.equals("Transformed") && state.equals("Original"))) {
  111.             HashMap<String, Object> runParams = new HashMap<String, Object>();
  112.             runParams.put("Mode", "Transformed");
  113.             runParams.put("Transformer", this);
  114.             AllZone.getTriggerHandler().runTrigger("Transformed", runParams);
  115.         }
  116.  
  117.         return true;
  118.     }
  119.  
  120.     /**
  121.      * Gets the states.
  122.      *
  123.      * @return the states
  124.      */
  125.     public Set<String> getStates() {
  126.         return this.characteristicsMap.keySet();
  127.     }
  128.  
  129.     /**
  130.      * Gets the cur state.
  131.      *
  132.      * @return the cur state
  133.      */
  134.     public String getCurState() {
  135.         return this.curCharacteristics;
  136.     }
  137.  
  138.     /**
  139.      * Switch states.
  140.      *
  141.      * @param from
  142.      *            the from
  143.      * @param to
  144.      *            the to
  145.      */
  146.     public void switchStates(final String from, final String to) {
  147.         final CardCharacteristics tmp = this.characteristicsMap.get(from);
  148.         this.characteristicsMap.put(from, this.characteristicsMap.get(to));
  149.         this.characteristicsMap.put(to, tmp);
  150.     }
  151.  
  152.     /**
  153.      * Clear states.
  154.      *
  155.      * @param state
  156.      *            the state
  157.      */
  158.     public void clearStates(final String state) {
  159.         this.characteristicsMap.remove(state);
  160.     }
  161.  
  162.     /**
  163.      * Turn face down.
  164.      *
  165.      * @return true, if successful
  166.      */
  167.     public boolean turnFaceDown() {
  168.         if (!this.isDoubleFaced) {
  169.             this.preTFDCharacteristic = this.curCharacteristics;
  170.             return this.setState("FaceDown");
  171.         }
  172.  
  173.         return false;
  174.     }
  175.  
  176.     /**
  177.      * Turn face up.
  178.      *
  179.      * @return true, if successful
  180.      */
  181.     public boolean turnFaceUp() {
  182.         if (this.curCharacteristics.equals("FaceDown")) {
  183.             return this.setState(this.preTFDCharacteristic);
  184.         }
  185.  
  186.         return false;
  187.     }
  188.  
  189.     /**
  190.      * Checks if is cloned.
  191.      *
  192.      * @return true, if is cloned
  193.      */
  194.     public boolean isCloned() {
  195.         for (final String state : this.characteristicsMap.keySet()) {
  196.             if (state.equals("Cloner")) {
  197.                 return true;
  198.             }
  199.         }
  200.         return false;
  201.     }
  202.  
  203.     /**
  204.      * Gets the state.
  205.      *
  206.      * @param state
  207.      *            the state
  208.      * @return the state
  209.      */
  210.     public CardCharacteristics getState(final String state) {
  211.         return this.characteristicsMap.get(state);
  212.     }
  213.  
  214.     /**
  215.      * Gets the characteristics.
  216.      *
  217.      * @return the characteristics
  218.      */
  219.     public CardCharacteristics getCharacteristics() {
  220.         return this.characteristicsMap.get(this.curCharacteristics);
  221.     }
  222.  
  223.     /**
  224.      * addAlternateState.
  225.      *
  226.      * @param state
  227.      *            the state
  228.      */
  229.     public final void addAlternateState(final String state) {
  230.         this.characteristicsMap.put(state, new CardCharacteristics());
  231.     }
  232.  
  233.     /*
  234.      * (non-Javadoc)
  235.      *
  236.      * @see forge.GameEntity#getName()
  237.      */
  238.     @Override
  239.     public final String getName() {
  240.         return this.getCharacteristics().getName();
  241.     }
  242.  
  243.     /*
  244.      * (non-Javadoc)
  245.      *
  246.      * @see forge.GameEntity#setName(java.lang.String)
  247.      */
  248.     @Override
  249.     public final void setName(final String name0) {
  250.         this.getCharacteristics().setName(name0);
  251.     }
  252.  
  253.     /**
  254.      *
  255.      * isInAlternateState.
  256.      *
  257.      * @return boolean
  258.      */
  259.     public final boolean isInAlternateState() {
  260.         return !(this.curCharacteristics.equals("Original") || this.curCharacteristics.equals("Cloned"));
  261.     }
  262.  
  263.     /**
  264.      *
  265.      * hasAlternateState.
  266.      *
  267.      * @return boolean
  268.      */
  269.     public final boolean hasAlternateState() {
  270.         return this.characteristicsMap.keySet().size() > 2;
  271.     }
  272.  
  273.     /**
  274.      * Checks if is double faced.
  275.      *
  276.      * @return the isDoubleFaced
  277.      */
  278.     public final boolean isDoubleFaced() {
  279.         return this.isDoubleFaced;
  280.     }
  281.  
  282.     /**
  283.      * Sets the double faced.
  284.      *
  285.      * @param isDoubleFaced0
  286.      *            the isDoubleFaced to set
  287.      */
  288.     public final void setDoubleFaced(final boolean isDoubleFaced0) {
  289.         this.isDoubleFaced = isDoubleFaced0;
  290.     }
  291.  
  292.     /**
  293.      * Checks if is flip.
  294.      *
  295.      * @return the isFlip
  296.      */
  297.     public final boolean isFlip() {
  298.         return this.isFlip;
  299.     }
  300.  
  301.     /**
  302.      * Sets the flip.
  303.      *
  304.      * @param isFlip0
  305.      *            the isFlip to set
  306.      */
  307.     public final void setFlip(final boolean isFlip0) {
  308.         this.isFlip = isFlip0;
  309.     }
  310.  
  311.     /**
  312.      * Checks if this is transformable (i.e. Licids.)
  313.      *
  314.      * @return a boolean
  315.      */
  316.     public final String isTransformable() {
  317.         return this.otherTransformable;
  318.     }
  319.  
  320.     /**
  321.      * Sets whether or not this card is transformable, but non-flip and not
  322.      * double-faced.
  323.      *
  324.      * @param otherTransformable0
  325.      *            a String
  326.      */
  327.     public final void setTransformable(final String otherTransformable0) {
  328.         this.otherTransformable = otherTransformable0;
  329.     }
  330.  
  331.     private Map<Counters, Integer> counters = new TreeMap<Counters, Integer>();
  332.     private final Map<String, Object> triggeringObjects = new TreeMap<String, Object>();
  333.     private ArrayList<String> extrinsicKeyword = new ArrayList<String>();
  334.     // Hidden keywords won't be displayed on the card
  335.     private final ArrayList<String> hiddenExtrinsicKeyword = new ArrayList<String>();
  336.     private ArrayList<String> prevIntrinsicKeyword = new ArrayList<String>();
  337.     private final ArrayList<Card> attachedByMindsDesire = new ArrayList<Card>();
  338.     // which equipment cards are equipping this card?
  339.     private ArrayList<Card> equippedBy = new ArrayList<Card>();
  340.     // equipping size will always be 0 or 1
  341.     // if this card is of the type equipment, what card is it currently
  342.     // equipping?
  343.     private ArrayList<Card> equipping = new ArrayList<Card>();
  344.     // which auras enchanted this card?
  345.  
  346.     // if this card is an Aura, what Entity is it enchanting?
  347.     private GameEntity enchanting = null;
  348.     private ArrayList<String> prevType = new ArrayList<String>();
  349.     private final ArrayList<String> choicesMade = new ArrayList<String>();
  350.     private final ArrayList<String> targetsForChoices = new ArrayList<String>();
  351.  
  352.     // changes by AF animate and continuous static effects
  353.     private ArrayList<CardType> changedCardTypes = new ArrayList<CardType>();
  354.     private ArrayList<CardKeywords> changedCardKeywords = new ArrayList<CardKeywords>();
  355.  
  356.     private final ArrayList<Object> rememberedObjects = new ArrayList<Object>();
  357.     private final ArrayList<Card> imprintedCards = new ArrayList<Card>();
  358.     private Card championedCard = null;
  359.     private final CardList devouredCards = new CardList();
  360.  
  361.     private Map<Card, Integer> receivedDamageFromThisTurn = new TreeMap<Card, Integer>();
  362.     private Map<Card, Integer> dealtDamageToThisTurn = new TreeMap<Card, Integer>();
  363.     private final Map<Card, Integer> assignedDamageMap = new TreeMap<Card, Integer>();
  364.  
  365.     private boolean drawnThisTurn = false;
  366.     private boolean tapped = false;
  367.     private boolean sickness = true; // summoning sickness
  368.     private boolean token = false;
  369.     private boolean copiedToken = false;
  370.     private boolean copiedSpell = false;
  371.     private boolean spellWithChoices = false;
  372.     private boolean spellCopyingCard = false;
  373.     private boolean creatureAttackedThisTurn = false;
  374.     private boolean creatureAttackedLastHumanTurn = false;
  375.     private boolean creatureAttackedLastComputerTurn = false;
  376.     private boolean creatureAttackedThisCombat = false;
  377.     private boolean creatureBlockedThisCombat = false;
  378.     private boolean creatureBlockedThisTurn = false;
  379.     private boolean creatureGotBlockedThisCombat = false;
  380.     private boolean creatureGotBlockedThisTurn = false;
  381.     private boolean dealtDmgToHumanThisTurn = false;
  382.     private boolean dealtDmgToComputerThisTurn = false;
  383.     private boolean dealtDmgToHumanThisGame = false;
  384.     private boolean dealtDmgToComputerThisGame = false;
  385.     private boolean dealtCombatDmgToHumanThisTurn = false;
  386.     private boolean dealtCombatDmgToComputerThisTurn = false;
  387.     private boolean sirenAttackOrDestroy = false;
  388.     private final ArrayList<Card> mustBlockCards = new ArrayList<Card>();
  389.  
  390.     private boolean canMorph = false;
  391.     private boolean kicked = false;
  392.     private boolean evoked = false;
  393.  
  394.     private boolean levelUp = false;
  395.     private boolean bounceAtUntap = false;
  396.  
  397.     private boolean unearth = false;
  398.     private boolean unearthed;
  399.  
  400.     private boolean madness = false;
  401.     private boolean suspendCast = false;
  402.     private boolean suspend = false;
  403.  
  404.     private boolean phasedOut = false;
  405.     private boolean directlyPhasedOut = true;
  406.  
  407.     // for Vanguard / Manapool / Emblems etc.
  408.     private boolean isImmutable = false;
  409.  
  410.     private long timestamp = -1; // permanents on the battlefield
  411.  
  412.     // stack of set power/toughness
  413.     private ArrayList<CardPowerToughness> newPT = new ArrayList<CardPowerToughness>();
  414.     private int baseLoyalty = 0;
  415.     private String baseAttackString = null;
  416.     private String baseDefenseString = null;
  417.  
  418.     private int damage;
  419.  
  420.     // regeneration
  421.     private int nShield;
  422.     private int regeneratedThisTurn = 0;
  423.  
  424.     private int turnInZone;
  425.  
  426.     private int tempAttackBoost = 0;
  427.     private int tempDefenseBoost = 0;
  428.  
  429.     private int semiPermanentAttackBoost = 0;
  430.     private int semiPermanentDefenseBoost = 0;
  431.  
  432.     private int randomPicture = 0;
  433.  
  434.     private int xManaCostPaid = 0;
  435.  
  436.     private int xLifePaid = 0;
  437.  
  438.     private int multiKickerMagnitude = 0;
  439.     private int replicateMagnitude = 0;
  440.  
  441.     private int sunburstValue = 0;
  442.     private String colorsPaid = "";
  443.  
  444.     private Player owner = null;
  445.     private ArrayList<Object> controllerObjects = new ArrayList<Object>();
  446.  
  447.     // private String rarity = "";
  448.     private String text = "";
  449.     private String echoCost = "";
  450.     private String madnessCost = "";
  451.     private String chosenType = "";
  452.     // private String chosenColor = "";
  453.     private ArrayList<String> chosenColor = new ArrayList<String>();
  454.     private String namedCard = "";
  455.     private int chosenNumber;
  456.     private Player chosenPlayer;
  457.     private ArrayList<Card> chosenCard = new ArrayList<Card>();
  458.  
  459.     private Card cloneOrigin = null;
  460.     private final ArrayList<Card> clones = new ArrayList<Card>();
  461.     private final ArrayList<Card> gainControlTargets = new ArrayList<Card>();
  462.     private final ArrayList<Command> gainControlReleaseCommands = new ArrayList<Command>();
  463.  
  464.     private final ArrayList<AbilityTriggered> zcTriggers = new ArrayList<AbilityTriggered>();
  465.     private final ArrayList<Command> equipCommandList = new ArrayList<Command>();
  466.     private final ArrayList<Command> unEquipCommandList = new ArrayList<Command>();
  467.     private final ArrayList<Command> enchantCommandList = new ArrayList<Command>();
  468.     private final ArrayList<Command> unEnchantCommandList = new ArrayList<Command>();
  469.     private final ArrayList<Command> untapCommandList = new ArrayList<Command>();
  470.     private final ArrayList<Command> changeControllerCommandList = new ArrayList<Command>();
  471.  
  472.     private static String[] storableSVars = { "ChosenX" };
  473.  
  474.     private final ArrayList<Card> hauntedBy = new ArrayList<Card>();
  475.     private Card haunting = null;
  476.  
  477.     private Map<String, String> sVars = new TreeMap<String, String>();
  478.  
  479.     /**
  480.      *
  481.      * TODO Write javadoc for this method.
  482.      *
  483.      * @return a String array
  484.      */
  485.     public static String[] getStorableSVars() {
  486.         return Card.storableSVars;
  487.     }
  488.  
  489.     // hacky code below, used to limit the number of times an ability
  490.     // can be used per turn like Vampire Bats
  491.     // should be put in SpellAbility, but it is put here for convenience
  492.     // this is make public just to make things easy
  493.     // this code presumes that each card only has one ability that can be
  494.     // used a limited number of times per turn
  495.     // CardFactory.SSP_canPlay(Card) uses these variables
  496.  
  497.     // Only used with Replicate
  498.     private int abilityUsed;
  499.  
  500.     /**
  501.      *
  502.      * Resets the unique number for this Card to 1.
  503.      */
  504.     public static void resetUniqueNumber() {
  505.         Card.nextUniqueNumber = 1;
  506.     }
  507.  
  508.     /**
  509.      *
  510.      * TODO Write javadoc for this method.
  511.      *
  512.      * @param c
  513.      *            a Card object
  514.      */
  515.     public final void addDevoured(final Card c) {
  516.         this.devouredCards.add(c);
  517.     }
  518.  
  519.     /**
  520.      *
  521.      * TODO Write javadoc for this method.
  522.      */
  523.     public final void clearDevoured() {
  524.         this.devouredCards.clear();
  525.     }
  526.  
  527.     /**
  528.      *
  529.      * TODO Write javadoc for this method.
  530.      *
  531.      * @return a CardList object
  532.      */
  533.     public final CardList getDevoured() {
  534.         return this.devouredCards;
  535.     }
  536.  
  537.     /**
  538.      * <p>
  539.      * addRemembered.
  540.      * </p>
  541.      *
  542.      * @param o
  543.      *            a {@link java.lang.Object} object.
  544.      */
  545.     public final void addRemembered(final Object o) {
  546.         this.rememberedObjects.add(o);
  547.     }
  548.  
  549.     /**
  550.      * <p>
  551.      * getRemembered.
  552.      * </p>
  553.      *
  554.      * @return a {@link java.util.ArrayList} object.
  555.      */
  556.     public final ArrayList<Object> getRemembered() {
  557.         return this.rememberedObjects;
  558.     }
  559.  
  560.     /**
  561.      * <p>
  562.      * clearRemembered.
  563.      * </p>
  564.      */
  565.     public final void clearRemembered() {
  566.         this.rememberedObjects.clear();
  567.     }
  568.  
  569.     /**
  570.      * <p>
  571.      * addImprinted.
  572.      * </p>
  573.      *
  574.      * @param c
  575.      *            a {@link forge.Card} object.
  576.      */
  577.     public final void addImprinted(final Card c) {
  578.         this.imprintedCards.add(c);
  579.     }
  580.  
  581.     /**
  582.      * <p>
  583.      * addImprinted.
  584.      * </p>
  585.      *
  586.      * @param list
  587.      *            a {@link java.util.ArrayList} object.
  588.      */
  589.     public final void addImprinted(final ArrayList<Card> list) {
  590.         this.imprintedCards.addAll(list);
  591.     }
  592.  
  593.     /**
  594.      * <p>
  595.      * getImprinted.
  596.      * </p>
  597.      *
  598.      * @return a {@link java.util.ArrayList} object.
  599.      */
  600.     public final ArrayList<Card> getImprinted() {
  601.         return this.imprintedCards;
  602.     }
  603.  
  604.     /**
  605.      * <p>
  606.      * clearImprinted.
  607.      * </p>
  608.      */
  609.     public final void clearImprinted() {
  610.         this.imprintedCards.clear();
  611.     }
  612.  
  613.     /**
  614.      * <p>
  615.      * Setter for the field <code>championedCard</code>.
  616.      * </p>
  617.      *
  618.      * @param c
  619.      *            a {@link forge.Card} object.
  620.      * @since 1.0.15
  621.      */
  622.     public final void setChampionedCard(final Card c) {
  623.         this.championedCard = c;
  624.     }
  625.  
  626.     /**
  627.      * <p>
  628.      * Getter for the field <code>championedCard</code>.
  629.      * </p>
  630.      *
  631.      * @return a {@link forge.Card} object.
  632.      * @since 1.0.15
  633.      */
  634.     public final Card getChampionedCard() {
  635.         return this.championedCard;
  636.     }
  637.  
  638.     /**
  639.      * <p>
  640.      * addTrigger.
  641.      * </p>
  642.      *
  643.      * @param t
  644.      *            a {@link forge.card.trigger.Trigger} object.
  645.      * @return a {@link forge.card.trigger.Trigger} object.
  646.      */
  647.     public final Trigger addTrigger(final Trigger t) {
  648.         final Trigger newtrig = t.getCopy();
  649.         newtrig.setHostCard(this);
  650.         this.getCharacteristics().getTriggers().add(newtrig);
  651.         return newtrig;
  652.     }
  653.  
  654.     /**
  655.      *
  656.      * moveTrigger.
  657.      *
  658.      * @param t
  659.      *            a Trigger
  660.      */
  661.     public final void moveTrigger(final Trigger t) {
  662.         t.setHostCard(this);
  663.         if (!this.getCharacteristics().getTriggers().contains(t)) {
  664.             this.getCharacteristics().getTriggers().add(t);
  665.         }
  666.     }
  667.  
  668.     /**
  669.      * <p>
  670.      * removeTrigger.
  671.      * </p>
  672.      *
  673.      * @param t
  674.      *            a {@link forge.card.trigger.Trigger} object.
  675.      */
  676.     public final void removeTrigger(final Trigger t) {
  677.         this.getCharacteristics().getTriggers().remove(t);
  678.     }
  679.  
  680.     /**
  681.      * <p>
  682.      * Getter for the field <code>triggers</code>.
  683.      * </p>
  684.      *
  685.      * @return a {@link java.util.ArrayList} object.
  686.      */
  687.     public final ArrayList<Trigger> getTriggers() {
  688.         return this.getCharacteristics().getTriggers();
  689.     }
  690.  
  691.     /**
  692.      * <p>
  693.      * getNamedTrigger.
  694.      * </p>
  695.      *
  696.      * @param name
  697.      *            a {@link java.lang.String} object.
  698.      * @return a {@link forge.card.trigger.Trigger} object.
  699.      */
  700.     public final Trigger getNamedTrigger(final String name) {
  701.         for (final Trigger t : this.getCharacteristics().getTriggers()) {
  702.             if ((t.getName() != null) && t.getName().equals(name)) {
  703.                 return t;
  704.             }
  705.         }
  706.  
  707.         return null;
  708.     }
  709.  
  710.     /**
  711.      * <p>
  712.      * Setter for the field <code>triggers</code>.
  713.      * </p>
  714.      *
  715.      * @param trigs
  716.      *            a {@link java.util.ArrayList} object.
  717.      */
  718.     public final void setTriggers(final ArrayList<Trigger> trigs) {
  719.         final ArrayList<Trigger> copyList = new ArrayList<Trigger>();
  720.         for (final Trigger t : trigs) {
  721.             if (t.getIsIntrinsic()) {
  722.                 final Trigger newtrig = t.getCopy();
  723.                 newtrig.setHostCard(this);
  724.                 copyList.add(newtrig);
  725.             }
  726.         }
  727.  
  728.         this.getCharacteristics().setTriggers(copyList);
  729.     }
  730.  
  731.     /**
  732.      * <p>
  733.      * clearTriggersNew.
  734.      * </p>
  735.      */
  736.     public final void clearTriggersNew() {
  737.         this.getCharacteristics().getTriggers().clear();
  738.     }
  739.  
  740.     /**
  741.      * <p>
  742.      * getTriggeringObject.
  743.      * </p>
  744.      *
  745.      * @param typeIn
  746.      *            a {@link java.lang.String} object.
  747.      * @return a {@link java.lang.Object} object.
  748.      */
  749.     public final Object getTriggeringObject(final String typeIn) {
  750.         return this.triggeringObjects.get(typeIn);
  751.     }
  752.  
  753.     /**
  754.      * field <code>abilityUsed</code>.
  755.      *
  756.      * @param i
  757.      *            a int.
  758.      */
  759.     public final void setAbilityUsed(final int i) {
  760.         this.abilityUsed = i;
  761.     }
  762.  
  763.     /**
  764.      * <p>
  765.      * Getter for the field <code>abilityUsed</code>.
  766.      * </p>
  767.      *
  768.      * @return a int.
  769.      */
  770.     public final int getAbilityUsed() {
  771.         return this.abilityUsed;
  772.     }
  773.  
  774.     /**
  775.      * <p>
  776.      * Getter for the field <code>sunburstValue</code>.
  777.      * </p>
  778.      *
  779.      * @return a int.
  780.      */
  781.     public final int getSunburstValue() {
  782.         return this.sunburstValue;
  783.     }
  784.  
  785.     /**
  786.      * <p>
  787.      * Setter for the field <code>colorsPaid</code>.
  788.      * </p>
  789.      *
  790.      * @param s
  791.      *            a String
  792.      */
  793.     public final void setColorsPaid(final String s) {
  794.         this.colorsPaid = s;
  795.     }
  796.  
  797.     /**
  798.      * <p>
  799.      * Getter for the field <code>colorsPaid</code>.
  800.      * </p>
  801.      *
  802.      * @return a String.
  803.      */
  804.     public final String getColorsPaid() {
  805.         return this.colorsPaid;
  806.     }
  807.  
  808.     /**
  809.      * <p>
  810.      * Setter for the field <code>sunburstValue</code>.
  811.      * </p>
  812.      *
  813.      * @param valueIn
  814.      *            a int.
  815.      */
  816.     public final void setSunburstValue(final int valueIn) {
  817.         this.sunburstValue = valueIn;
  818.     }
  819.  
  820.     /**
  821.      * <p>
  822.      * addXManaCostPaid.
  823.      * </p>
  824.      *
  825.      * @param n
  826.      *            a int.
  827.      */
  828.     public final void addXManaCostPaid(final int n) {
  829.         this.xManaCostPaid += n;
  830.     }
  831.  
  832.     /**
  833.      * <p>
  834.      * Setter for the field <code>xManaCostPaid</code>.
  835.      * </p>
  836.      *
  837.      * @param n
  838.      *            a int.
  839.      */
  840.     public final void setXManaCostPaid(final int n) {
  841.         this.xManaCostPaid = n;
  842.     }
  843.  
  844.     /**
  845.      * <p>
  846.      * Getter for the field <code>xManaCostPaid</code>.
  847.      * </p>
  848.      *
  849.      * @return a int.
  850.      */
  851.     public final int getXManaCostPaid() {
  852.         return this.xManaCostPaid;
  853.     }
  854.  
  855.     /**
  856.      * <p>
  857.      * Setter for the field <code>xLifePaid</code>.
  858.      * </p>
  859.      *
  860.      * @param n
  861.      *            a int.
  862.      */
  863.     public final void setXLifePaid(final int n) {
  864.         this.xLifePaid = n;
  865.     }
  866.  
  867.     /**
  868.      * <p>
  869.      * Getter for the field <code>xLifePaid</code>.
  870.      * </p>
  871.      *
  872.      * @return a int.
  873.      */
  874.     public final int getXLifePaid() {
  875.         return this.xLifePaid;
  876.     }
  877.  
  878.     // used to see if an attacking creature with a triggering attack ability
  879.     // triggered this phase:
  880.     /**
  881.      * <p>
  882.      * Setter for the field <code>creatureAttackedThisCombat</code>.
  883.      * </p>
  884.      *
  885.      * @param b
  886.      *            a boolean.
  887.      */
  888.     public final void setCreatureAttackedThisCombat(final boolean b) {
  889.         this.creatureAttackedThisCombat = b;
  890.         if (b) {
  891.             this.setCreatureAttackedThisTurn(true);
  892.             this.getController().setAttackedWithCreatureThisTurn(true);
  893.         }
  894.     }
  895.  
  896.     /**
  897.      * <p>
  898.      * Getter for the field <code>creatureAttackedThisCombat</code>.
  899.      * </p>
  900.      *
  901.      * @return a boolean.
  902.      */
  903.     public final boolean getCreatureAttackedThisCombat() {
  904.         return this.creatureAttackedThisCombat;
  905.     }
  906.  
  907.     /**
  908.      * <p>
  909.      * Setter for the field <code>creatureAttackedThisTurn</code>.
  910.      * </p>
  911.      *
  912.      * @param b
  913.      *            a boolean.
  914.      */
  915.     public final void setCreatureAttackedThisTurn(final boolean b) {
  916.         this.creatureAttackedThisTurn = b;
  917.     }
  918.  
  919.     /**
  920.      * <p>
  921.      * Getter for the field <code>creatureAttackedThisTurn</code>.
  922.      * </p>
  923.      *
  924.      * @return a boolean.
  925.      */
  926.     public final boolean getCreatureAttackedThisTurn() {
  927.         return this.creatureAttackedThisTurn;
  928.     }
  929.  
  930.     /**
  931.      * <p>
  932.      * Setter for the field <code>creatureAttackedLastTurn</code>.
  933.      * </p>
  934.      *
  935.      * @param b
  936.      *            a boolean.
  937.      */
  938.     public final void setCreatureAttackedLastHumanTurn(final boolean b) {
  939.         this.creatureAttackedLastHumanTurn = b;
  940.     }
  941.  
  942.     /**
  943.      * <p>
  944.      * Getter for the field <code>creatureAttackedLastTurn</code>.
  945.      * </p>
  946.      *
  947.      * @return a boolean.
  948.      */
  949.     public final boolean getCreatureAttackedLastHumanTurn() {
  950.         return this.creatureAttackedLastHumanTurn;
  951.     }
  952.  
  953.     /**
  954.      * <p>
  955.      * Setter for the field <code>creatureAttackedLastTurn</code>.
  956.      * </p>
  957.      *
  958.      * @param b
  959.      *            a boolean.
  960.      */
  961.     public final void setCreatureAttackedLastComputerTurn(final boolean b) {
  962.         this.creatureAttackedLastComputerTurn = b;
  963.     }
  964.  
  965.     /**
  966.      * <p>
  967.      * Getter for the field <code>creatureAttackedLastTurn</code>.
  968.      * </p>
  969.      *
  970.      * @return a boolean.
  971.      */
  972.     public final boolean getCreatureAttackedLastComputerTurn() {
  973.         return this.creatureAttackedLastComputerTurn;
  974.     }
  975.  
  976.     /**
  977.      * <p>
  978.      * Setter for the field <code>creatureBlockedThisCombat</code>.
  979.      * </p>
  980.      *
  981.      * @param b
  982.      *            a boolean.
  983.      */
  984.     public final void setCreatureBlockedThisCombat(final boolean b) {
  985.         this.creatureBlockedThisCombat = b;
  986.         if (b) {
  987.             this.setCreatureBlockedThisTurn(true);
  988.         }
  989.     }
  990.  
  991.     /**
  992.      * <p>
  993.      * Getter for the field <code>creatureBlockedThisCombat</code>.
  994.      * </p>
  995.      *
  996.      * @return a boolean.
  997.      */
  998.     public final boolean getCreatureBlockedThisCombat() {
  999.         return this.creatureBlockedThisCombat;
  1000.     }
  1001.  
  1002.     /**
  1003.      * <p>
  1004.      * Setter for the field <code>creatureBlockedThisTurn</code>.
  1005.      * </p>
  1006.      *
  1007.      * @param b
  1008.      *            a boolean.
  1009.      */
  1010.     public final void setCreatureBlockedThisTurn(final boolean b) {
  1011.         this.creatureBlockedThisTurn = b;
  1012.     }
  1013.  
  1014.     /**
  1015.      * <p>
  1016.      * Getter for the field <code>creatureBlockedThisTurn</code>.
  1017.      * </p>
  1018.      *
  1019.      * @return a boolean.
  1020.      */
  1021.     public final boolean getCreatureBlockedThisTurn() {
  1022.         return this.creatureBlockedThisTurn;
  1023.     }
  1024.  
  1025.     /**
  1026.      * <p>
  1027.      * Setter for the field <code>creatureGotBlockedThisCombat</code>.
  1028.      * </p>
  1029.      *
  1030.      * @param b
  1031.      *            a boolean.
  1032.      */
  1033.     public final void setCreatureGotBlockedThisCombat(final boolean b) {
  1034.         this.creatureGotBlockedThisCombat = b;
  1035.         if (b) {
  1036.             this.setCreatureGotBlockedThisTurn(true);
  1037.         }
  1038.     }
  1039.  
  1040.     /**
  1041.      * <p>
  1042.      * Getter for the field <code>creatureGotBlockedThisCombat</code>.
  1043.      * </p>
  1044.      *
  1045.      * @return a boolean.
  1046.      */
  1047.     public final boolean getCreatureGotBlockedThisCombat() {
  1048.         return this.creatureGotBlockedThisCombat;
  1049.     }
  1050.  
  1051.     /**
  1052.      * <p>
  1053.      * Setter for the field <code>creatureGotBlockedThisTurn</code>.
  1054.      * </p>
  1055.      *
  1056.      * @param b
  1057.      *            a boolean.
  1058.      */
  1059.     public final void setCreatureGotBlockedThisTurn(final boolean b) {
  1060.         this.creatureGotBlockedThisTurn = b;
  1061.     }
  1062.  
  1063.     /**
  1064.      * <p>
  1065.      * Getter for the field <code>creatureGotBlockedThisTurn</code>.
  1066.      * </p>
  1067.      *
  1068.      * @return a boolean.
  1069.      */
  1070.     public final boolean getCreatureGotBlockedThisTurn() {
  1071.         return this.creatureGotBlockedThisTurn;
  1072.     }
  1073.  
  1074.     /**
  1075.      * <p>
  1076.      * canAnyPlayerActivate.
  1077.      * </p>
  1078.      *
  1079.      * @return a boolean.
  1080.      */
  1081.     public final boolean canAnyPlayerActivate() {
  1082.         for (final SpellAbility s : this.getCharacteristics().getSpellAbility()) {
  1083.             if (s.getRestrictions().isAnyPlayer()) {
  1084.                 return true;
  1085.             }
  1086.         }
  1087.         return false;
  1088.     }
  1089.  
  1090.     /**
  1091.      * <p>
  1092.      * Setter for the field <code>dealtDmgToHumanThisTurn</code>.
  1093.      * </p>
  1094.      *
  1095.      * @param b
  1096.      *            a boolean.
  1097.      */
  1098.     public final void setDealtDmgToHumanThisTurn(final boolean b) {
  1099.         this.dealtDmgToHumanThisTurn = b;
  1100.         if (b) {
  1101.             this.setDealtDmgToHumanThisGame(true);
  1102.         }
  1103.     }
  1104.  
  1105.     /**
  1106.      * <p>
  1107.      * Getter for the field <code>dealtDmgToHumanThisTurn</code>.
  1108.      * </p>
  1109.      *
  1110.      * @return a boolean.
  1111.      */
  1112.     public final boolean getDealtDmgToHumanThisTurn() {
  1113.         return this.dealtDmgToHumanThisTurn;
  1114.     }
  1115.  
  1116.     /**
  1117.      * <p>
  1118.      * Setter for the field <code>dealtDmgToComputerThisTurn</code>.
  1119.      * </p>
  1120.      *
  1121.      * @param b
  1122.      *            a boolean.
  1123.      */
  1124.     public final void setDealtDmgToComputerThisTurn(final boolean b) {
  1125.         this.dealtDmgToComputerThisTurn = b;
  1126.         if (b) {
  1127.             this.setDealtDmgToComputerThisGame(true);
  1128.         }
  1129.     }
  1130.  
  1131.     /**
  1132.      * <p>
  1133.      * Getter for the field <code>dealtCombatDmgToComputerThisGame</code>.
  1134.      * </p>
  1135.      *
  1136.      * @return a boolean.
  1137.      */
  1138.     public final boolean getDealtDmgToComputerThisTurn() {
  1139.         return this.dealtDmgToComputerThisTurn;
  1140.     }
  1141.  
  1142.     /**
  1143.      * <p>
  1144.      * Setter for the field <code>dealtDmgToHumanThisGame</code>.
  1145.      * </p>
  1146.      *
  1147.      * @param b
  1148.      *            a boolean.
  1149.      */
  1150.     public final void setDealtDmgToHumanThisGame(final boolean b) {
  1151.         this.dealtDmgToHumanThisGame = b;
  1152.     }
  1153.  
  1154.     /**
  1155.      * <p>
  1156.      * Getter for the field <code>dealtDmgToHumanThisGame</code>.
  1157.      * </p>
  1158.      *
  1159.      * @return a boolean.
  1160.      */
  1161.     public final boolean getDealtDmgToHumanThisGame() {
  1162.         return this.dealtDmgToHumanThisGame;
  1163.     }
  1164.  
  1165.     /**
  1166.      * <p>
  1167.      * Setter for the field <code>dealtDmgToComputerThisGame</code>.
  1168.      * </p>
  1169.      *
  1170.      * @param b
  1171.      *            a boolean.
  1172.      */
  1173.     public final void setDealtDmgToComputerThisGame(final boolean b) {
  1174.         this.dealtDmgToComputerThisGame = b;
  1175.     }
  1176.  
  1177.     /**
  1178.      * <p>
  1179.      * Getter for the field <code>dealtCombatDmgToComputerThisGame</code>.
  1180.      * </p>
  1181.      *
  1182.      * @return a boolean.
  1183.      */
  1184.     public final boolean getDealtDmgToComputerThisGame() {
  1185.         return this.dealtDmgToComputerThisGame;
  1186.     }
  1187.  
  1188.     /**
  1189.      * <p>
  1190.      * Setter for the field <code>dealtCombatDmgToHumanThisTurn</code>.
  1191.      * </p>
  1192.      *
  1193.      * @param b
  1194.      *            a boolean.
  1195.      */
  1196.     public final void setDealtCombatDmgToHumanThisTurn(final boolean b) {
  1197.         this.dealtCombatDmgToHumanThisTurn = b;
  1198.     }
  1199.  
  1200.     /**
  1201.      * <p>
  1202.      * Getter for the field <code>dealtDmgToHumanThisTurn</code>.
  1203.      * </p>
  1204.      *
  1205.      * @return a boolean.
  1206.      */
  1207.     public final boolean getDealtCombatDmgToHumanThisTurn() {
  1208.         return this.dealtCombatDmgToHumanThisTurn;
  1209.     }
  1210.  
  1211.     /**
  1212.      * <p>
  1213.      * Setter for the field <code>dealtCombatDmgToComputerThisTurn</code>.
  1214.      * </p>
  1215.      *
  1216.      * @param b
  1217.      *            a boolean.
  1218.      */
  1219.     public final void setDealtCombatDmgToComputerThisTurn(final boolean b) {
  1220.         this.dealtCombatDmgToComputerThisTurn = b;
  1221.     }
  1222.  
  1223.     /**
  1224.      * <p>
  1225.      * Getter for the field <code>dealtDmgToComputerThisTurn</code>.
  1226.      * </p>
  1227.      *
  1228.      * @return a boolean.
  1229.      */
  1230.     public final boolean getDealtCombatDmgToComputerThisTurn() {
  1231.         return this.dealtCombatDmgToComputerThisTurn;
  1232.     }
  1233.  
  1234.     /**
  1235.      * <p>
  1236.      * Setter for the field <code>sirenAttackOrDestroy</code>.
  1237.      * </p>
  1238.      *
  1239.      * @param b
  1240.      *            a boolean.
  1241.      */
  1242.     public final void setSirenAttackOrDestroy(final boolean b) {
  1243.         this.sirenAttackOrDestroy = b;
  1244.     }
  1245.  
  1246.     /**
  1247.      * <p>
  1248.      * Getter for the field <code>sirenAttackOrDestroy</code>.
  1249.      * </p>
  1250.      *
  1251.      * @return a boolean.
  1252.      */
  1253.     public final boolean getSirenAttackOrDestroy() {
  1254.         return this.sirenAttackOrDestroy;
  1255.     }
  1256.  
  1257.     /**
  1258.      * a Card that this Card must block if able in an upcoming combat. This is
  1259.      * cleared at the end of each turn.
  1260.      *
  1261.      * @param c
  1262.      *            Card to block
  1263.      *
  1264.      * @since 1.1.6
  1265.      */
  1266.     public final void addMustBlockCard(final Card c) {
  1267.         this.mustBlockCards.add(c);
  1268.     }
  1269.  
  1270.     /**
  1271.      * get the Card that this Card must block this combat.
  1272.      *
  1273.      * @return the Cards to block (if able)
  1274.      *
  1275.      * @since 1.1.6
  1276.      */
  1277.     public final ArrayList<Card> getMustBlockCards() {
  1278.         return this.mustBlockCards;
  1279.     }
  1280.  
  1281.     /**
  1282.      * clear the list of Cards that this Card must block this combat.
  1283.      *
  1284.      * @since 1.1.6
  1285.      */
  1286.     public final void clearMustBlockCards() {
  1287.         this.mustBlockCards.clear();
  1288.     }
  1289.  
  1290.     /**
  1291.      * <p>
  1292.      * Getter for the field <code>clones</code>.
  1293.      * </p>
  1294.      *
  1295.      * @return a {@link java.util.ArrayList} object.
  1296.      */
  1297.     public final ArrayList<Card> getClones() {
  1298.         return this.clones;
  1299.     }
  1300.  
  1301.     /**
  1302.      * <p>
  1303.      * Setter for the field <code>clones</code>.
  1304.      * </p>
  1305.      *
  1306.      * @param c
  1307.      *            a {@link java.util.ArrayList} object.
  1308.      */
  1309.     public final void setClones(final ArrayList<Card> c) {
  1310.         this.clones.clear();
  1311.         this.clones.addAll(c);
  1312.     }
  1313.  
  1314.     /**
  1315.      * <p>
  1316.      * addClone.
  1317.      * </p>
  1318.      *
  1319.      * @param c
  1320.      *            a {@link forge.Card} object.
  1321.      */
  1322.     public final void addClone(final Card c) {
  1323.         this.clones.add(c);
  1324.     }
  1325.  
  1326.     /**
  1327.      * <p>
  1328.      * addClones.
  1329.      * </p>
  1330.      *
  1331.      * @param c
  1332.      *            a {@link java.util.ArrayList} object.
  1333.      */
  1334.     public final void addClones(final ArrayList<Card> c) {
  1335.         this.clones.addAll(c);
  1336.     }
  1337.  
  1338.     /**
  1339.      * <p>
  1340.      * clearClones.
  1341.      * </p>
  1342.      */
  1343.     public final void clearClones() {
  1344.         this.clones.clear();
  1345.     }
  1346.  
  1347.     /**
  1348.      * <p>
  1349.      * Getter for the field <code>cloneOrigin</code>.
  1350.      * </p>
  1351.      *
  1352.      * @return a {@link forge.Card} object.
  1353.      */
  1354.     public final Card getCloneOrigin() {
  1355.         return this.cloneOrigin;
  1356.     }
  1357.  
  1358.     /**
  1359.      * <p>
  1360.      * Setter for the field <code>cloneOrigin</code>.
  1361.      * </p>
  1362.      *
  1363.      * @param name
  1364.      *            a {@link forge.Card} object.
  1365.      */
  1366.     public final void setCloneOrigin(final Card name) {
  1367.         this.cloneOrigin = name;
  1368.     }
  1369.  
  1370.     /**
  1371.      * <p>
  1372.      * Getter for the field <code>sacrificeAtEOT</code>.
  1373.      * </p>
  1374.      *
  1375.      * @return a boolean.
  1376.      */
  1377.     public final boolean getSacrificeAtEOT() {
  1378.         return this.hasKeyword("At the beginning of the end step, sacrifice CARDNAME.");
  1379.     }
  1380.  
  1381.     /**
  1382.      * <p>
  1383.      * Getter for the field <code>bounceAtUntap</code>.
  1384.      * </p>
  1385.      *
  1386.      * @return a boolean.
  1387.      */
  1388.     public final boolean getBounceAtUntap() {
  1389.         return this.bounceAtUntap;
  1390.     }
  1391.  
  1392.     /**
  1393.      * <p>
  1394.      * Setter for the field <code>bounceAtUntap</code>.
  1395.      * </p>
  1396.      *
  1397.      * @param bounce
  1398.      *            a boolean.
  1399.      */
  1400.     public final void setBounceAtUntap(final boolean bounce) {
  1401.         this.bounceAtUntap = bounce;
  1402.     }
  1403.  
  1404.     /**
  1405.      * <p>
  1406.      * hasFirstStrike.
  1407.      * </p>
  1408.      *
  1409.      * @return a boolean.
  1410.      */
  1411.     public final boolean hasFirstStrike() {
  1412.         return this.hasKeyword("First Strike");
  1413.     }
  1414.  
  1415.     /**
  1416.      * <p>
  1417.      * hasDoubleStrike.
  1418.      * </p>
  1419.      *
  1420.      * @return a boolean.
  1421.      */
  1422.     public final boolean hasDoubleStrike() {
  1423.         return this.hasKeyword("Double Strike");
  1424.     }
  1425.  
  1426.     /**
  1427.      * <p>
  1428.      * hasSecondStrike.
  1429.      * </p>
  1430.      *
  1431.      * @return a boolean.
  1432.      */
  1433.     public final boolean hasSecondStrike() {
  1434.         return this.hasDoubleStrike() || !this.hasFirstStrike();
  1435.     }
  1436.  
  1437.     /**
  1438.      * Can have counters placed on it.
  1439.      *
  1440.      * @param counterName
  1441.      *            the counter name
  1442.      * @return true, if successful
  1443.      */
  1444.     public final boolean canHaveCountersPlacedOnIt(final Counters counterName) {
  1445.         if (this.hasKeyword("CARDNAME can't have counters placed on it.")) {
  1446.             return false;
  1447.         }
  1448.         if (this.isCreature() && counterName.equals(Counters.M1M1)) {
  1449.             for (final Card c : AllZoneUtil.getCreaturesInPlay(this.getController())) { // look
  1450.                                                                                         // for
  1451.                                                                                         // Melira,
  1452.                                                                                         // Sylvok
  1453.                                                                                         // Outcast
  1454.                 if (c.hasKeyword("Creatures you control can't have -1/-1 counters placed on them.")) {
  1455.                     return false;
  1456.                 }
  1457.             }
  1458.  
  1459.         }
  1460.         return true;
  1461.     }
  1462.  
  1463.     // for costs (like Planeswalker abilities) Doubling Season gets ignored.
  1464.     /**
  1465.      * <p>
  1466.      * addCounterFromNonEffect.
  1467.      * </p>
  1468.      *
  1469.      * @param counterName
  1470.      *            a {@link forge.Counters} object.
  1471.      * @param n
  1472.      *            a int.
  1473.      */
  1474.     public final void addCounterFromNonEffect(final Counters counterName, final int n) {
  1475.         if (!this.canHaveCountersPlacedOnIt(counterName)) {
  1476.             return;
  1477.         }
  1478.         if (this.counters.containsKey(counterName)) {
  1479.             final Integer aux = this.counters.get(counterName) + n;
  1480.             this.counters.put(counterName, aux);
  1481.         } else {
  1482.             this.counters.put(counterName, Integer.valueOf(n));
  1483.         }
  1484.  
  1485.         // Run triggers
  1486.         final Map<String, Object> runParams = new TreeMap<String, Object>();
  1487.         runParams.put("Card", this);
  1488.         runParams.put("CounterType", counterName);
  1489.         for (int i = 0; i < n; i++) {
  1490.             AllZone.getTriggerHandler().runTrigger("CounterAdded", runParams);
  1491.         }
  1492.  
  1493.         if (counterName.equals(Counters.P1P1) || counterName.equals(Counters.M1M1)) {
  1494.             // +1/+1 counters should erase -1/-1 counters
  1495.             int plusOneCounters = 0;
  1496.             int minusOneCounters = 0;
  1497.  
  1498.             final Counters p1Counter = Counters.P1P1;
  1499.             final Counters m1Counter = Counters.M1M1;
  1500.             if (this.counters.containsKey(p1Counter)) {
  1501.                 plusOneCounters = this.counters.get(p1Counter);
  1502.             }
  1503.             if (this.counters.containsKey(m1Counter)) {
  1504.                 minusOneCounters = this.counters.get(m1Counter);
  1505.             }
  1506.  
  1507.             if (plusOneCounters == minusOneCounters) {
  1508.                 this.counters.remove(m1Counter);
  1509.                 this.counters.remove(p1Counter);
  1510.             }
  1511.             if (plusOneCounters > minusOneCounters) {
  1512.                 this.counters.remove(m1Counter);
  1513.                 this.counters.put(p1Counter, (plusOneCounters - minusOneCounters));
  1514.             } else {
  1515.                 this.counters.put(m1Counter, (minusOneCounters - plusOneCounters));
  1516.                 this.counters.remove(p1Counter);
  1517.             }
  1518.         }
  1519.  
  1520.         this.updateObservers();
  1521.     }
  1522.  
  1523.     /**
  1524.      * <p>
  1525.      * addCounter.
  1526.      * </p>
  1527.      *
  1528.      * @param counterName
  1529.      *            a {@link forge.Counters} object.
  1530.      * @param n
  1531.      *            a int.
  1532.      */
  1533.     public final void addCounter(final Counters counterName, final int n) {
  1534.         if (!this.canHaveCountersPlacedOnIt(counterName)) {
  1535.             return;
  1536.         }
  1537.         final int multiplier = AllZoneUtil.getDoublingSeasonMagnitude(this.getController());
  1538.         if (this.counters.containsKey(counterName)) {
  1539.             final Integer aux = this.counters.get(counterName) + (multiplier * n);
  1540.             this.counters.put(counterName, aux);
  1541.         } else {
  1542.             this.counters.put(counterName, Integer.valueOf(multiplier * n));
  1543.         }
  1544.  
  1545.         // Run triggers
  1546.         final Map<String, Object> runParams = new TreeMap<String, Object>();
  1547.         runParams.put("Card", this);
  1548.         runParams.put("CounterType", counterName);
  1549.         for (int i = 0; i < (multiplier * n); i++) {
  1550.             AllZone.getTriggerHandler().runTrigger("CounterAdded", runParams);
  1551.         }
  1552.  
  1553.         if (counterName.equals(Counters.P1P1) || counterName.equals(Counters.M1M1)) {
  1554.             // +1/+1 counters should erase -1/-1 counters
  1555.             int plusOneCounters = 0;
  1556.             int minusOneCounters = 0;
  1557.  
  1558.             final Counters p1Counter = Counters.P1P1;
  1559.             final Counters m1Counter = Counters.M1M1;
  1560.             if (this.counters.containsKey(p1Counter)) {
  1561.                 plusOneCounters = this.counters.get(p1Counter);
  1562.             }
  1563.             if (this.counters.containsKey(m1Counter)) {
  1564.                 minusOneCounters = this.counters.get(m1Counter);
  1565.             }
  1566.  
  1567.             if (plusOneCounters == minusOneCounters) {
  1568.                 this.counters.remove(m1Counter);
  1569.                 this.counters.remove(p1Counter);
  1570.             }
  1571.             if (plusOneCounters > minusOneCounters) {
  1572.                 this.counters.remove(m1Counter);
  1573.                 this.counters.put(p1Counter, (plusOneCounters - minusOneCounters));
  1574.             } else {
  1575.                 this.counters.put(m1Counter, (minusOneCounters - plusOneCounters));
  1576.                 this.counters.remove(p1Counter);
  1577.             }
  1578.         }
  1579.  
  1580.         AllZone.getGameAction().checkStateEffects();
  1581.  
  1582.         this.updateObservers();
  1583.     }
  1584.  
  1585.     /**
  1586.      * <p>
  1587.      * subtractCounter.
  1588.      * </p>
  1589.      *
  1590.      * @param counterName
  1591.      *            a {@link forge.Counters} object.
  1592.      * @param n
  1593.      *            a int.
  1594.      */
  1595.     public final void subtractCounter(final Counters counterName, final int n) {
  1596.         if (this.counters.containsKey(counterName)) {
  1597.             Integer aux = this.counters.get(counterName) - n;
  1598.             if (aux < 0) {
  1599.                 aux = 0;
  1600.             }
  1601.             this.counters.put(counterName, aux);
  1602.             if (counterName.equals(Counters.TIME) && (aux == 0)) {
  1603.                 final boolean hasVanish = CardFactoryUtil.hasKeyword(this, "Vanishing") != -1;
  1604.  
  1605.                 if (hasVanish && AllZoneUtil.isCardInPlay(this)) {
  1606.                     AllZone.getGameAction().sacrifice(this);
  1607.                 }
  1608.  
  1609.                 if (this.hasSuspend() && AllZoneUtil.isCardExiled(this)) {
  1610.                     final Card c = this;
  1611.  
  1612.                     c.setSuspendCast(true);
  1613.                     // set activating player for base spell ability
  1614.                     c.getSpellAbility()[0].setActivatingPlayer(c.getOwner());
  1615.                     // Any trigger should cause the phase not to skip
  1616.                     AllZone.getPhaseHandler().setSkipPhase(false);
  1617.                     AllZone.getGameAction().playCardNoCost(c);
  1618.                 }
  1619.             }
  1620.  
  1621.             AllZone.getGameAction().checkStateEffects();
  1622.  
  1623.             this.updateObservers();
  1624.         }
  1625.     }
  1626.  
  1627.     /**
  1628.      * <p>
  1629.      * Getter for the field <code>counters</code>.
  1630.      * </p>
  1631.      *
  1632.      * @param counterName
  1633.      *            a {@link forge.Counters} object.
  1634.      * @return a int.
  1635.      */
  1636.     public final int getCounters(final Counters counterName) {
  1637.         if (this.counters.containsKey(counterName)) {
  1638.             return this.counters.get(counterName);
  1639.         } else {
  1640.             return 0;
  1641.         }
  1642.     }
  1643.  
  1644.     // get all counters from a card
  1645.     /**
  1646.      * <p>
  1647.      * Getter for the field <code>counters</code>.
  1648.      * </p>
  1649.      *
  1650.      * @return a Map object.
  1651.      * @since 1.0.15
  1652.      */
  1653.     public final Map<Counters, Integer> getCounters() {
  1654.         return this.counters;
  1655.     }
  1656.  
  1657.     /**
  1658.      * <p>
  1659.      * hasCounters.
  1660.      * </p>
  1661.      *
  1662.      * @return a boolean.
  1663.      */
  1664.     public final boolean hasCounters() {
  1665.         return this.counters.size() > 0;
  1666.     }
  1667.  
  1668.     /**
  1669.      *
  1670.      * getNumberOfCounters.
  1671.      *
  1672.      * @return int
  1673.      */
  1674.     public final int getNumberOfCounters() {
  1675.         int number = 0;
  1676.         for (final Integer i : this.counters.values()) {
  1677.             number += i.intValue();
  1678.         }
  1679.         return number;
  1680.     }
  1681.  
  1682.     /**
  1683.      * <p>
  1684.      * setCounter.
  1685.      * </p>
  1686.      *
  1687.      * @param counterName
  1688.      *            a {@link forge.Counters} object.
  1689.      * @param n
  1690.      *            a int.
  1691.      * @param bSetValue
  1692.      *            a boolean.
  1693.      */
  1694.     public final void setCounter(final Counters counterName, final int n, final boolean bSetValue) {
  1695.         if (!this.canHaveCountersPlacedOnIt(counterName)) {
  1696.             return;
  1697.         }
  1698.         // sometimes you just need to set the value without being affected by
  1699.         // DoublingSeason
  1700.         if (bSetValue) {
  1701.             this.counters.put(counterName, Integer.valueOf(n));
  1702.         } else {
  1703.             final int num = this.getCounters(counterName);
  1704.             // if counters on card is less than the setting value, addCounters
  1705.             if (num < n) {
  1706.                 this.addCounter(counterName, n - num);
  1707.             } else {
  1708.                 this.subtractCounter(counterName, num - n);
  1709.             }
  1710.         }
  1711.         this.updateObservers();
  1712.     }
  1713.  
  1714.     // get all counters from a card
  1715.     /**
  1716.      * <p>
  1717.      * Setter for the field <code>counters</code>.
  1718.      * </p>
  1719.      *
  1720.      * @param allCounters
  1721.      *            a Map object.
  1722.      * @since 1.0.15
  1723.      */
  1724.     public final void setCounters(final Map<Counters, Integer> allCounters) {
  1725.         this.counters = allCounters;
  1726.     }
  1727.  
  1728.     // get all counters from a card
  1729.     /**
  1730.      * <p>
  1731.      * clearCounters.
  1732.      * </p>
  1733.      *
  1734.      * @since 1.0.15
  1735.      */
  1736.     public final void clearCounters() {
  1737.         this.counters = new TreeMap<Counters, Integer>();
  1738.     }
  1739.  
  1740.     /**
  1741.      * hasLevelUp() - checks to see if a creature has the "Level up" ability
  1742.      * introduced in Rise of the Eldrazi.
  1743.      *
  1744.      * @return true if this creature can "Level up", false otherwise
  1745.      */
  1746.     public final boolean hasLevelUp() {
  1747.         return this.levelUp;
  1748.     }
  1749.  
  1750.     /**
  1751.      * <p>
  1752.      * Setter for the field <code>levelUp</code>.
  1753.      * </p>
  1754.      *
  1755.      * @param b
  1756.      *            a boolean.
  1757.      */
  1758.     public final void setLevelUp(final boolean b) {
  1759.         this.levelUp = b;
  1760.     }
  1761.  
  1762.     /**
  1763.      * <p>
  1764.      * getSVar.
  1765.      * </p>
  1766.      *
  1767.      * @param var
  1768.      *            a {@link java.lang.String} object.
  1769.      * @return a {@link java.lang.String} object.
  1770.      */
  1771.     public final String getSVar(final String var) {
  1772.         if (this.sVars.containsKey(var)) {
  1773.             return this.sVars.get(var);
  1774.         } else {
  1775.             return "";
  1776.         }
  1777.     }
  1778.  
  1779.     /**
  1780.      * <p>
  1781.      * setSVar.
  1782.      * </p>
  1783.      *
  1784.      * @param var
  1785.      *            a {@link java.lang.String} object.
  1786.      * @param str
  1787.      *            a {@link java.lang.String} object.
  1788.      */
  1789.     public final void setSVar(final String var, final String str) {
  1790.         if (this.sVars.containsKey(var)) {
  1791.             this.sVars.remove(var);
  1792.         }
  1793.  
  1794.         this.sVars.put(var, str);
  1795.     }
  1796.  
  1797.     /**
  1798.      * <p>
  1799.      * getSVars.
  1800.      * </p>
  1801.      *
  1802.      * @return a Map object.
  1803.      */
  1804.     public final Map<String, String> getSVars() {
  1805.         return this.sVars;
  1806.     }
  1807.  
  1808.     /**
  1809.      * <p>
  1810.      * setSVars.
  1811.      * </p>
  1812.      *
  1813.      * @param newSVars
  1814.      *            a Map object.
  1815.      */
  1816.     public final void setSVars(final Map<String, String> newSVars) {
  1817.         this.sVars = newSVars;
  1818.     }
  1819.  
  1820.     /**
  1821.      * <p>
  1822.      * sumAllCounters.
  1823.      * </p>
  1824.      *
  1825.      * @return a int.
  1826.      */
  1827.     public final int sumAllCounters() {
  1828.         final Object[] values = this.counters.values().toArray();
  1829.         int count = 0;
  1830.         int num = 0;
  1831.         for (final Object value2 : values) {
  1832.             num = (Integer) value2;
  1833.             count += num;
  1834.         }
  1835.         return count;
  1836.     }
  1837.  
  1838.     /**
  1839.      * <p>
  1840.      * getNetPTCounters.
  1841.      * </p>
  1842.      *
  1843.      * @return a int.
  1844.      */
  1845.     public final int getNetPTCounters() {
  1846.         return this.getCounters(Counters.P1P1) - this.getCounters(Counters.M1M1);
  1847.     }
  1848.  
  1849.     /**
  1850.      * <p>
  1851.      * Getter for the field <code>turnInZone</code>.
  1852.      * </p>
  1853.      *
  1854.      * @return a int.
  1855.      */
  1856.     public final int getTurnInZone() {
  1857.         return this.turnInZone;
  1858.     }
  1859.  
  1860.     /**
  1861.      * <p>
  1862.      * Setter for the field <code>turnInZone</code>.
  1863.      * </p>
  1864.      *
  1865.      * @param turn
  1866.      *            a int.
  1867.      */
  1868.     public final void setTurnInZone(final int turn) {
  1869.         this.turnInZone = turn;
  1870.     }
  1871.  
  1872.     /**
  1873.      * <p>
  1874.      * Setter for the field <code>echoCost</code>.
  1875.      * </p>
  1876.      *
  1877.      * @param s
  1878.      *            a {@link java.lang.String} object.
  1879.      */
  1880.     public final void setEchoCost(final String s) {
  1881.         this.echoCost = s;
  1882.     }
  1883.  
  1884.     /**
  1885.      * <p>
  1886.      * Getter for the field <code>echoCost</code>.
  1887.      * </p>
  1888.      *
  1889.      * @return a {@link java.lang.String} object.
  1890.      */
  1891.     public final String getEchoCost() {
  1892.         return this.echoCost;
  1893.     }
  1894.  
  1895.     /**
  1896.      * <p>
  1897.      * Setter for the field <code>manaCost</code>.
  1898.      * </p>
  1899.      *
  1900.      * @param s
  1901.      *            a {@link java.lang.String} object.
  1902.      */
  1903.     public final void setManaCost(final String s) {
  1904.         this.getCharacteristics().setManaCost(s);
  1905.     }
  1906.  
  1907.     /**
  1908.      * <p>
  1909.      * Getter for the field <code>manaCost</code>.
  1910.      * </p>
  1911.      *
  1912.      * @return a {@link java.lang.String} object.
  1913.      */
  1914.     public final String getManaCost() {
  1915.         return this.getCharacteristics().getManaCost();
  1916.     }
  1917.  
  1918.     /**
  1919.      * <p>
  1920.      * addColor.
  1921.      * </p>
  1922.      *
  1923.      * @param s
  1924.      *            a {@link java.lang.String} object.
  1925.      */
  1926.     public final void addColor(String s) {
  1927.         if (s.equals("")) {
  1928.             s = "0";
  1929.         }
  1930.         this.getCharacteristics().getCardColor().add(new CardColor(new ManaCost(s), this, false, true));
  1931.     }
  1932.  
  1933.     /**
  1934.      * <p>
  1935.      * addColor.
  1936.      * </p>
  1937.      *
  1938.      * @param s
  1939.      *            a {@link java.lang.String} object.
  1940.      * @param c
  1941.      *            a {@link forge.Card} object.
  1942.      * @param addToColors
  1943.      *            a boolean.
  1944.      * @param bIncrease
  1945.      *            a boolean.
  1946.      * @return a long.
  1947.      */
  1948.     public final long addColor(final String s, final Card c, final boolean addToColors, final boolean bIncrease) {
  1949.         if (bIncrease) {
  1950.             CardColor.increaseTimestamp();
  1951.         }
  1952.         this.getCharacteristics().getCardColor().add(new CardColor(new ManaCost(s), c, addToColors, false));
  1953.         return CardColor.getTimestamp();
  1954.     }
  1955.  
  1956.     /**
  1957.      * <p>
  1958.      * removeColor.
  1959.      * </p>
  1960.      *
  1961.      * @param s
  1962.      *            a {@link java.lang.String} object.
  1963.      * @param c
  1964.      *            a {@link forge.Card} object.
  1965.      * @param addTo
  1966.      *            a boolean.
  1967.      * @param timestampIn
  1968.      *            a long.
  1969.      */
  1970.     public final void removeColor(final String s, final Card c, final boolean addTo, final long timestampIn) {
  1971.         CardColor removeCol = null;
  1972.         for (final CardColor cc : this.getCharacteristics().getCardColor()) {
  1973.             if (cc.equals(s, c, addTo, timestampIn)) {
  1974.                 removeCol = cc;
  1975.             }
  1976.         }
  1977.  
  1978.         if (removeCol != null) {
  1979.             this.getCharacteristics().getCardColor().remove(removeCol);
  1980.         }
  1981.     }
  1982.  
  1983.     /**
  1984.      * <p>
  1985.      * determineColor.
  1986.      * </p>
  1987.      *
  1988.      * @return a {@link forge.CardColor} object.
  1989.      */
  1990.     public final CardColor determineColor() {
  1991.         if (this.isImmutable()) {
  1992.             return new CardColor(this);
  1993.         }
  1994.         CardColor colors = null;
  1995.         final ArrayList<CardColor> globalChanges = AllZone.getColorChanger().getColorChanges();
  1996.         colors = this.determineColor(globalChanges);
  1997.         colors.fixColorless();
  1998.         return colors;
  1999.     }
  2000.  
  2001.     /**
  2002.      * <p>
  2003.      * setColor.
  2004.      * </p>
  2005.      *
  2006.      * @param colors
  2007.      *            a {@link java.util.ArrayList} object.
  2008.      */
  2009.     public final void setColor(final ArrayList<CardColor> colors) {
  2010.         this.getCharacteristics().setCardColor(colors);
  2011.     }
  2012.  
  2013.     /**
  2014.      * <p>
  2015.      * getColor.
  2016.      * </p>
  2017.      *
  2018.      * @return a {@link java.util.ArrayList} object.
  2019.      */
  2020.     public final ArrayList<CardColor> getColor() {
  2021.         return this.getCharacteristics().getCardColor();
  2022.     }
  2023.  
  2024.     /**
  2025.      *
  2026.      * TODO Write javadoc for this method.
  2027.      *
  2028.      * @param globalChanges
  2029.      *            an ArrayList<CardColor>
  2030.      * @return a CardColor
  2031.      */
  2032.     final CardColor determineColor(final ArrayList<CardColor> globalChanges) {
  2033.         final CardColor colors = new CardColor(this);
  2034.         int i = this.getCharacteristics().getCardColor().size() - 1;
  2035.         int j = -1;
  2036.         if (globalChanges != null) {
  2037.             j = globalChanges.size() - 1;
  2038.         }
  2039.         // if both have changes, see which one is most recent
  2040.         while ((i >= 0) && (j >= 0)) {
  2041.             CardColor cc = null;
  2042.             if (this.getCharacteristics().getCardColor().get(i).getStamp() > globalChanges.get(j).getStamp()) {
  2043.                 // Card has a more recent color stamp
  2044.                 cc = this.getCharacteristics().getCardColor().get(i);
  2045.                 i--;
  2046.             } else {
  2047.                 // Global effect has a more recent color stamp
  2048.                 cc = globalChanges.get(j);
  2049.                 j--;
  2050.             }
  2051.  
  2052.             for (final String s : cc.toStringArray()) {
  2053.                 colors.addToCardColor(s);
  2054.             }
  2055.             if (!cc.getAdditional()) {
  2056.                 return colors;
  2057.             }
  2058.         }
  2059.         while (i >= 0) {
  2060.             final CardColor cc = this.getCharacteristics().getCardColor().get(i);
  2061.             i--;
  2062.             for (final String s : cc.toStringArray()) {
  2063.                 colors.addToCardColor(s);
  2064.             }
  2065.             if (!cc.getAdditional()) {
  2066.                 return colors;
  2067.             }
  2068.         }
  2069.         while (j >= 0) {
  2070.             final CardColor cc = globalChanges.get(j);
  2071.             j--;
  2072.             for (final String s : cc.toStringArray()) {
  2073.                 colors.addToCardColor(s);
  2074.             }
  2075.             if (!cc.getAdditional()) {
  2076.                 return colors;
  2077.             }
  2078.         }
  2079.  
  2080.         return colors;
  2081.     }
  2082.  
  2083.     /**
  2084.      * <p>
  2085.      * getCMC.
  2086.      * </p>
  2087.      *
  2088.      * @return a int.
  2089.      */
  2090.     public final int getCMC() {
  2091.         return CardUtil.getConvertedManaCost(this.getCharacteristics().getManaCost());
  2092.     }
  2093.  
  2094.     /**
  2095.      * <p>
  2096.      * Getter for the field <code>chosenPlayer</code>.
  2097.      * </p>
  2098.      *
  2099.      * @return a Player
  2100.      * @since 1.1.6
  2101.      */
  2102.     public final Player getChosenPlayer() {
  2103.         return this.chosenPlayer;
  2104.     }
  2105.  
  2106.     /**
  2107.      * <p>
  2108.      * Setter for the field <code>chosenNumber</code>.
  2109.      * </p>
  2110.      *
  2111.      * @param p
  2112.      *            an int
  2113.      * @since 1.1.6
  2114.      */
  2115.     public final void setChosenPlayer(final Player p) {
  2116.         this.chosenPlayer = p;
  2117.     }
  2118.  
  2119.     /**
  2120.      * <p>
  2121.      * Getter for the field <code>chosenNumber</code>.
  2122.      * </p>
  2123.      *
  2124.      * @return an int
  2125.      */
  2126.     public final int getChosenNumber() {
  2127.         return this.chosenNumber;
  2128.     }
  2129.  
  2130.     /**
  2131.      * <p>
  2132.      * Setter for the field <code>chosenNumber</code>.
  2133.      * </p>
  2134.      *
  2135.      * @param i
  2136.      *            an int
  2137.      */
  2138.     public final void setChosenNumber(final int i) {
  2139.         this.chosenNumber = i;
  2140.     }
  2141.  
  2142.     // used for cards like Belbe's Portal, Conspiracy, Cover of Darkness, etc.
  2143.     /**
  2144.      * <p>
  2145.      * Getter for the field <code>chosenType</code>.
  2146.      * </p>
  2147.      *
  2148.      * @return a {@link java.lang.String} object.
  2149.      */
  2150.     public final String getChosenType() {
  2151.         return this.chosenType;
  2152.     }
  2153.  
  2154.     /**
  2155.      * <p>
  2156.      * Setter for the field <code>chosenType</code>.
  2157.      * </p>
  2158.      *
  2159.      * @param s
  2160.      *            a {@link java.lang.String} object.
  2161.      */
  2162.     public final void setChosenType(final String s) {
  2163.         this.chosenType = s;
  2164.     }
  2165.  
  2166.     /**
  2167.      * <p>
  2168.      * Getter for the field <code>chosenColor</code>.
  2169.      * </p>
  2170.      *
  2171.      * @return an ArrayList<String> object.
  2172.      */
  2173.     public final ArrayList<String> getChosenColor() {
  2174.         return this.chosenColor;
  2175.     }
  2176.  
  2177.     /**
  2178.      * <p>
  2179.      * Setter for the field <code>chosenColor</code>.
  2180.      * </p>
  2181.      *
  2182.      * @param s
  2183.      *            an ArrayList<String> object.
  2184.      */
  2185.     public final void setChosenColor(final ArrayList<String> s) {
  2186.         this.chosenColor = s;
  2187.     }
  2188.  
  2189.     /**
  2190.      * <p>
  2191.      * Getter for the field <code>chosenCard</code>.
  2192.      * </p>
  2193.      *
  2194.      * @return an ArrayList<Card> object.
  2195.      */
  2196.     public final ArrayList<Card> getChosenCard() {
  2197.         return this.chosenCard;
  2198.     }
  2199.  
  2200.     /**
  2201.      * <p>
  2202.      * Setter for the field <code>chosenCard</code>.
  2203.      * </p>
  2204.      *
  2205.      * @param c
  2206.      *            an ArrayList<String> object.
  2207.      */
  2208.     public final void setChosenCard(final ArrayList<Card> c) {
  2209.         this.chosenCard = c;
  2210.     }
  2211.  
  2212.     // used for cards like Meddling Mage...
  2213.     /**
  2214.      * <p>
  2215.      * Getter for the field <code>namedCard</code>.
  2216.      * </p>
  2217.      *
  2218.      * @return a {@link java.lang.String} object.
  2219.      */
  2220.     public final String getNamedCard() {
  2221.         return this.namedCard;
  2222.     }
  2223.  
  2224.     /**
  2225.      * <p>
  2226.      * Setter for the field <code>namedCard</code>.
  2227.      * </p>
  2228.      *
  2229.      * @param s
  2230.      *            a {@link java.lang.String} object.
  2231.      */
  2232.     public final void setNamedCard(final String s) {
  2233.         this.namedCard = s;
  2234.     }
  2235.  
  2236.     /**
  2237.      * <p>
  2238.      * Setter for the field <code>drawnThisTurn</code>.
  2239.      * </p>
  2240.      *
  2241.      * @param b
  2242.      *            a boolean.
  2243.      */
  2244.     public final void setDrawnThisTurn(final boolean b) {
  2245.         this.drawnThisTurn = b;
  2246.     }
  2247.  
  2248.     /**
  2249.      * <p>
  2250.      * Getter for the field <code>drawnThisTurn</code>.
  2251.      * </p>
  2252.      *
  2253.      * @return a boolean.
  2254.      */
  2255.     public final boolean getDrawnThisTurn() {
  2256.         return this.drawnThisTurn;
  2257.     }
  2258.  
  2259.     /**
  2260.      * get a list of Cards this card has gained control of.
  2261.      * <p/>
  2262.      * used primarily with AbilityFactory_GainControl
  2263.      *
  2264.      * @return a list of cards this card has gained control of
  2265.      */
  2266.     public final ArrayList<Card> getGainControlTargets() {
  2267.         return this.gainControlTargets;
  2268.     }
  2269.  
  2270.     /**
  2271.      * add a Card to the list of Cards this card has gained control of.
  2272.      * <p/>
  2273.      * used primarily with AbilityFactory_GainControl
  2274.      *
  2275.      * @param c
  2276.      *            a {@link forge.Card} object.
  2277.      */
  2278.     public final void addGainControlTarget(final Card c) {
  2279.         this.gainControlTargets.add(c);
  2280.     }
  2281.  
  2282.     /**
  2283.      * clear the list of Cards this card has gained control of.
  2284.      * <p/>
  2285.      * used primarily with AbilityFactory_GainControl
  2286.      */
  2287.     public final void clearGainControlTargets() {
  2288.         this.gainControlTargets.clear();
  2289.     }
  2290.  
  2291.     /**
  2292.      * get the commands to be executed to lose control of Cards this card has
  2293.      * gained control of.
  2294.      * <p/>
  2295.      * used primarily with AbilityFactory_GainControl (Old Man of the Sea
  2296.      * specifically)
  2297.      *
  2298.      * @return a {@link java.util.ArrayList} object.
  2299.      */
  2300.     public final ArrayList<Command> getGainControlReleaseCommands() {
  2301.         return this.gainControlReleaseCommands;
  2302.     }
  2303.  
  2304.     /**
  2305.      * set a command to be executed to lose control of Cards this card has
  2306.      * gained control of.
  2307.      * <p/>
  2308.      * used primarily with AbilityFactory_GainControl (Old Man of the Sea
  2309.      * specifically)
  2310.      *
  2311.      * @param c
  2312.      *            the Command to be executed
  2313.      */
  2314.     public final void addGainControlReleaseCommand(final Command c) {
  2315.         this.gainControlReleaseCommands.add(c);
  2316.     }
  2317.  
  2318.     /**
  2319.      * <p>
  2320.      * clearGainControlReleaseCommands.
  2321.      * </p>
  2322.      */
  2323.     public final void clearGainControlReleaseCommands() {
  2324.         this.gainControlReleaseCommands.clear();
  2325.     }
  2326.  
  2327.     /**
  2328.      * <p>
  2329.      * getSpellText.
  2330.      * </p>
  2331.      *
  2332.      * @return a {@link java.lang.String} object.
  2333.      */
  2334.     public final String getSpellText() {
  2335.         return this.text;
  2336.     }
  2337.  
  2338.     /**
  2339.      * <p>
  2340.      * Setter for the field <code>text</code>.
  2341.      * </p>
  2342.      *
  2343.      * @param t
  2344.      *            a {@link java.lang.String} object.
  2345.      */
  2346.     public final void setText(final String t) {
  2347.         this.text = t;
  2348.     }
  2349.  
  2350.     // get the text that should be displayed
  2351.     /**
  2352.      * <p>
  2353.      * Getter for the field <code>text</code>.
  2354.      * </p>
  2355.      *
  2356.      * @return a {@link java.lang.String} object.
  2357.      */
  2358.     public String getText() {
  2359.         final StringBuilder sb = new StringBuilder();
  2360.         sb.append(this.getAbilityText());
  2361.         final String nonAbilityText = this.getNonAbilityText();
  2362.         if (nonAbilityText.length() > 0) {
  2363.             sb.append("\r\n \r\nNon ability features: \r\n");
  2364.             sb.append(nonAbilityText.replaceAll("CARDNAME", this.getName()));
  2365.         }
  2366.  
  2367.         // Remembered cards
  2368.         if (this.rememberedObjects.size() > 0) {
  2369.             sb.append("\r\nRemembered: \r\n");
  2370.             for (final Object o : this.rememberedObjects) {
  2371.                 if (o instanceof Card) {
  2372.                     final Card c = (Card) o;
  2373.                     if (c.isFaceDown()) {
  2374.                         sb.append("Face Down ");
  2375.                     } else {
  2376.                         sb.append(c.getName());
  2377.                     }
  2378.                     sb.append("(");
  2379.                     sb.append(c.getUniqueNumber());
  2380.                     sb.append(")");
  2381.                 } else {
  2382.                     sb.append(o.toString());
  2383.                 }
  2384.                 sb.append("\r\n");
  2385.             }
  2386.         }
  2387.  
  2388.         if (this.hauntedBy.size() != 0) {
  2389.             sb.append("Haunted by: ");
  2390.             for (final Card c : this.hauntedBy) {
  2391.                 sb.append(c).append(",");
  2392.             }
  2393.             sb.deleteCharAt(sb.length() - 1);
  2394.             sb.append("\r\n");
  2395.         }
  2396.  
  2397.         if (this.haunting != null) {
  2398.             sb.append("Haunting: ").append(this.haunting);
  2399.             sb.append("\r\n");
  2400.         }
  2401.  
  2402.         if (this.characteristicsMap.get("Cloner") != null) {
  2403.             sb.append("\r\nCloned by: ").append(this.characteristicsMap.get("Cloner").getName()).append(" (")
  2404.                     .append(this.getUniqueNumber()).append(")");
  2405.         }
  2406.  
  2407.         return sb.toString();
  2408.     }
  2409.  
  2410.     // get the text that does not belong to a cards abilities (and is not really
  2411.     // there rules-wise)
  2412.     /**
  2413.      * <p>
  2414.      * getNonAbilityText.
  2415.      * </p>
  2416.      *
  2417.      * @return a {@link java.lang.String} object.
  2418.      */
  2419.     public final String getNonAbilityText() {
  2420.         final StringBuilder sb = new StringBuilder();
  2421.         final ArrayList<String> keyword = this.getHiddenExtrinsicKeyword();
  2422.  
  2423.         sb.append(this.keywordsToText(keyword));
  2424.  
  2425.         return sb.toString();
  2426.     }
  2427.  
  2428.     // convert a keyword list to the String that should be displayed ingame
  2429.     /**
  2430.      * <p>
  2431.      * keywordsToText.
  2432.      * </p>
  2433.      *
  2434.      * @param keyword
  2435.      *            a {@link java.util.ArrayList} object.
  2436.      * @return a {@link java.lang.String} object.
  2437.      */
  2438.     public final String keywordsToText(final ArrayList<String> keyword) {
  2439.         final StringBuilder sb = new StringBuilder();
  2440.         final StringBuilder sbLong = new StringBuilder();
  2441.         final StringBuilder sbMana = new StringBuilder();
  2442.  
  2443.         for (int i = 0; i < keyword.size(); i++) {
  2444.             if (!keyword.get(i).toString().contains("Permanents don't untap during their controllers' untap steps")
  2445.                     && !keyword.get(i).toString().contains("PreventAllDamageBy")
  2446.                     && !keyword.get(i).toString().contains("CantBlock")
  2447.                     && !keyword.get(i).toString().contains("CantBeBlockedBy")) {
  2448.                 if (keyword.get(i).toString().contains("CostChange")) {
  2449.                     final String[] k = keyword.get(i).split(":");
  2450.                     if (k[k.length - 1].toString().startsWith("Desc|")) {
  2451.                         final String[] kk = k[k.length - 1].split("\\|");
  2452.                         sbLong.append(kk[1]).append("\r\n");
  2453.                     }
  2454.                 } else if (keyword.get(i).toString().contains("StaticEffect")) {
  2455.                     final String[] k = keyword.get(i).split(":");
  2456.                     sbLong.append(k[5]).append("\r\n");
  2457.                 } else if (keyword.get(i).toString().contains("Protection:")) {
  2458.                     final String[] k = keyword.get(i).split(":");
  2459.                     sbLong.append(k[2]).append("\r\n");
  2460.                 } else if (keyword.get(i).toString().contains("Creatures can't attack unless their controller pays")) {
  2461.                     final String[] k = keyword.get(i).split(":");
  2462.                     if (!k[3].equals("no text")) {
  2463.                         sbLong.append(k[3]).append("\r\n");
  2464.                     }
  2465.                 } else if (keyword.get(i).startsWith("Enchant")) {
  2466.                     String k = keyword.get(i);
  2467.                     k = k.replace("Curse", "");
  2468.                     sbLong.append(k).append("\r\n");
  2469.                 } else if (keyword.get(i).startsWith("Soulshift") || keyword.get(i).startsWith("Cumulative upkeep")
  2470.                         || keyword.get(i).startsWith("Echo") || keyword.get(i).startsWith("Fading")
  2471.                         || keyword.get(i).startsWith("Ripple") || keyword.get(i).startsWith("Unearth")
  2472.                         || keyword.get(i).startsWith("Vanishing") || keyword.get(i).startsWith("Madness")
  2473.                         || keyword.get(i).startsWith("Devour") || keyword.get(i).startsWith("Morph")) {
  2474.                     String k = keyword.get(i);
  2475.                     k = k.replace(":", " ");
  2476.                     sbLong.append(k).append("\r\n");
  2477.                 } else if (keyword.get(i).startsWith("Champion")) {
  2478.                     final String k = this.getKeyword().get(i);
  2479.                     final String[] kk = k.split(":");
  2480.                     String types = kk[1];
  2481.                     if (kk.length > 2) {
  2482.                         types = kk[2];
  2483.                     }
  2484.                     if (kk[1].equals("Creature")) {
  2485.                         kk[1] = kk[1].toLowerCase();
  2486.                     }
  2487.                     sbLong.append("Champion a");
  2488.                     if (kk[1].toLowerCase().startsWith("a") || kk[1].toLowerCase().startsWith("e")
  2489.                             || kk[1].toLowerCase().startsWith("i") || kk[1].toLowerCase().startsWith("o")
  2490.                             || kk[1].toLowerCase().startsWith("u")) {
  2491.                         sbLong.append("n");
  2492.                     }
  2493.                     sbLong.append(" ").append(types);
  2494.                     sbLong.append(" (When this enters the battlefield, sacrifice it unless you exile another ");
  2495.                     sbLong.append(types);
  2496.                     sbLong.append(" you control. When this leaves the battlefield, ");
  2497.                     sbLong.append("that card returns to the battlefield.)\r\n");
  2498.                 } else if (keyword.get(i).endsWith(".") && !keyword.get(i).startsWith("Haunt")) {
  2499.                     sbLong.append(keyword.get(i).toString()).append("\r\n");
  2500.                 } else if (keyword.get(i).contains("At the beginning of your upkeep, ")
  2501.                         && keyword.get(i).contains(" unless you pay")) {
  2502.                     sbLong.append(keyword.get(i).toString()).append("\r\n");
  2503.                 } else if (keyword.get(i).toString().contains("tap: add ")) {
  2504.                     sbMana.append(keyword.get(i).toString()).append("\r\n");
  2505.                 } else if (keyword.get(i).contains("Bloodthirst")) {
  2506.                     final String k = keyword.get(i);
  2507.                     final String[] kk = k.split(" ");
  2508.                     sbLong.append(keyword.get(i)).append(
  2509.                             " (If an opponent was dealt damage this turn, this creature enters the battlefield with ");
  2510.                     sbLong.append(kk[1]).append(" +1/+1 counter");
  2511.                     if (kk[1].equals("X")) {
  2512.                         sbLong.append("s on it, where X is the damage dealt to your opponents this turn.)");
  2513.                         sbLong.append("\r\n");
  2514.                     } else {
  2515.                         if (Integer.parseInt(kk[1]) > 1) {
  2516.                             sbLong.append("s");
  2517.                         }
  2518.                         sbLong.append(" on it.)").append("\r\n");
  2519.                     }
  2520.                 } else if (keyword.get(i).startsWith("Modular")) {
  2521.                     final String numCounters = keyword.get(i).split(" ")[1];
  2522.                     sbLong.append(keyword.get(i));
  2523.                     sbLong.append(" (This enters the battlefield with ");
  2524.                     sbLong.append(numCounters);
  2525.                     sbLong.append(" +1/+1 counters on it. When it's put into a graveyard, ");
  2526.                     sbLong.append("you may put its +1/+1 counters on target artifact creature.)");
  2527.                 } else if (keyword.get(i).startsWith("Provoke")) {
  2528.                     sbLong.append(keyword.get(i));
  2529.                     sbLong.append(" (When this attacks, you may have target creature ");
  2530.                     sbLong.append("defending player controls untap and block it if able.)");
  2531.                 } else if (keyword.get(i).startsWith("MayEffectFromOpeningHand")) {
  2532.                     continue;
  2533.                 } else if (keyword.get(i).contains("Haunt")) {
  2534.                     sb.append("\r\nHaunt (");
  2535.                     if (this.isCreature()) {
  2536.                         sb.append("When this creature dies, exile it haunting target creature.");
  2537.                     } else {
  2538.                         sb.append("When this spell card is put into a graveyard after resolving, ");
  2539.                         sb.append("exile it haunting target creature.");
  2540.                     }
  2541.                     sb.append(")");
  2542.                     continue;
  2543.                 } else if (keyword.get(i).equals("Convoke")) {
  2544.                     if (sb.length() != 0) {
  2545.                         sb.append("\r\n");
  2546.                     }
  2547.                     sb.append("Convoke (Each creature you tap while casting this spell reduces its cost by 1 or by one mana of that creature's color.)");
  2548.                 } else {
  2549.                     if ((i != 0) && (sb.length() != 0)) {
  2550.                         sb.append(", ");
  2551.                     }
  2552.                     sb.append(keyword.get(i).toString());
  2553.                 }
  2554.             }
  2555.         }
  2556.         if (sb.length() > 0) {
  2557.             sb.append("\r\n");
  2558.             if (sbLong.length() > 0) {
  2559.                 sb.append("\r\n");
  2560.             }
  2561.         }
  2562.         if (sbLong.length() > 0) {
  2563.             sbLong.append("\r\n");
  2564.         }
  2565.         sb.append(sbLong);
  2566.         sb.append(sbMana);
  2567.         return sb.toString();
  2568.     }
  2569.  
  2570.     // get the text of the abilities of a card
  2571.     /**
  2572.      * <p>
  2573.      * getAbilityText.
  2574.      * </p>
  2575.      *
  2576.      * @return a {@link java.lang.String} object.
  2577.      */
  2578.     public String getAbilityText() {
  2579.         if (this.isInstant() || this.isSorcery()) {
  2580.             final StringBuilder sb = this.abilityTextInstantSorcery();
  2581.  
  2582.             if (this.haunting != null) {
  2583.                 sb.append("Haunting: ").append(this.haunting);
  2584.                 sb.append("\r\n");
  2585.             }
  2586.  
  2587.             while (sb.toString().endsWith("\r\n")) {
  2588.                 sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
  2589.             }
  2590.  
  2591.             return sb.toString().replaceAll("CARDNAME", this.getName());
  2592.         }
  2593.  
  2594.         final StringBuilder sb = new StringBuilder();
  2595.         final ArrayList<String> keyword = this.getUnhiddenKeyword();
  2596.  
  2597.         sb.append(this.keywordsToText(keyword));
  2598.  
  2599.         // Give spellText line breaks for easier reading
  2600.         sb.append("\r\n");
  2601.         sb.append(this.text.replaceAll("\\\\r\\\\n", "\r\n"));
  2602.         sb.append("\r\n");
  2603.  
  2604.         // Triggered abilities
  2605.         for (final Trigger trig : this.getCharacteristics().getTriggers()) {
  2606.             if (!trig.isSecondary()) {
  2607.                 sb.append(trig.toString() + "\r\n");
  2608.             }
  2609.         }
  2610.  
  2611.         // Replacement effects
  2612.         for (final ReplacementEffect replacementEffect : this.getCharacteristics().getReplacementEffects()) {
  2613.             sb.append(replacementEffect.toString() + "\r\n");
  2614.         }
  2615.  
  2616.         // static abilities
  2617.         for (final StaticAbility stAb : this.getCharacteristics().getStaticAbilities()) {
  2618.             sb.append(stAb.toString() + "\r\n");
  2619.         }
  2620.  
  2621.         final ArrayList<String> addedManaStrings = new ArrayList<String>();
  2622.         final SpellAbility[] abilities = this.getSpellAbility();
  2623.         boolean primaryCost = true;
  2624.         for (final SpellAbility sa : abilities) {
  2625.             // only add abilities not Spell portions of cards
  2626.             if (!this.isPermanent()) {
  2627.                 continue;
  2628.             }
  2629.  
  2630.             if ((sa instanceof SpellPermanent) && primaryCost && !this.isAura()) {
  2631.                 // For Alt costs, make sure to display the cost!
  2632.                 primaryCost = false;
  2633.                 continue;
  2634.             }
  2635.  
  2636.             final String sAbility = sa.toString();
  2637.  
  2638.             if (sa instanceof AbilityMana) {
  2639.                 if (addedManaStrings.contains(sAbility)) {
  2640.                     continue;
  2641.                 }
  2642.                 addedManaStrings.add(sAbility);
  2643.             }
  2644.  
  2645.             if ((sa instanceof SpellPermanent) && !this.isAura()) {
  2646.                 sb.insert(0, "\r\n");
  2647.                 sb.insert(0, sAbility);
  2648.             } else if (!sAbility.endsWith(this.getName())) {
  2649.                 sb.append(sAbility);
  2650.                 sb.append("\r\n");
  2651.             }
  2652.         }
  2653.  
  2654.         // NOTE:
  2655.         if (sb.toString().contains(" (NOTE: ")) {
  2656.             sb.insert(sb.indexOf("(NOTE: "), "\r\n");
  2657.         }
  2658.         if (sb.toString().contains("(NOTE: ") && sb.toString().contains(".) ")) {
  2659.             sb.insert(sb.indexOf(".) ") + 3, "\r\n");
  2660.         }
  2661.  
  2662.         // replace triple line feeds with double line feeds
  2663.         int start;
  2664.         final String s = "\r\n\r\n\r\n";
  2665.         while (sb.toString().contains(s)) {
  2666.             start = sb.lastIndexOf(s);
  2667.             if ((start < 0) || (start >= sb.length())) {
  2668.                 break;
  2669.             }
  2670.             sb.replace(start, start + 4, "\r\n");
  2671.         }
  2672.  
  2673.         return sb.toString().replaceAll("CARDNAME", this.getName()).trim();
  2674.     } // getText()
  2675.  
  2676.     /**
  2677.      * TODO: Write javadoc for this method.
  2678.      *
  2679.      * @return
  2680.      */
  2681.     private StringBuilder abilityTextInstantSorcery() {
  2682.         final String s = this.getSpellText();
  2683.         final StringBuilder sb = new StringBuilder();
  2684.  
  2685.         // Give spellText line breaks for easier reading
  2686.         sb.append(s.replaceAll("\\\\r\\\\n", "\r\n"));
  2687.  
  2688.         // NOTE:
  2689.         if (sb.toString().contains(" (NOTE: ")) {
  2690.             sb.insert(sb.indexOf("(NOTE: "), "\r\n");
  2691.         }
  2692.         if (sb.toString().contains("(NOTE: ") && sb.toString().endsWith(".)") && !sb.toString().endsWith("\r\n")) {
  2693.             sb.append("\r\n");
  2694.         }
  2695.  
  2696.         // Add SpellAbilities
  2697.         final SpellAbility[] sa = this.getSpellAbility();
  2698.         for (final SpellAbility element : sa) {
  2699.             sb.append(element.toString() + "\r\n");
  2700.         }
  2701.  
  2702.         // Add Keywords
  2703.         final ArrayList<String> kw = this.getKeyword();
  2704.  
  2705.         // Triggered abilities
  2706.         for (final Trigger trig : this.getCharacteristics().getTriggers()) {
  2707.             if (!trig.isSecondary()) {
  2708.                 sb.append(trig.toString() + "\r\n");
  2709.             }
  2710.         }
  2711.  
  2712.         // Replacement effects
  2713.         for (final ReplacementEffect replacementEffect : this.getCharacteristics().getReplacementEffects()) {
  2714.             sb.append(replacementEffect.toString() + "\r\n");
  2715.         }
  2716.  
  2717.         // static abilities
  2718.         for (final StaticAbility stAb : this.getCharacteristics().getStaticAbilities()) {
  2719.             final String stAbD = stAb.toString();
  2720.             if (!stAbD.equals("")) {
  2721.                 sb.append(stAbD + "\r\n");
  2722.             }
  2723.         }
  2724.  
  2725.         // Ripple + Dredge + Madness + CARDNAME is {color} + Recover.
  2726.         for (int i = 0; i < kw.size(); i++) {
  2727.             final String keyword = kw.get(i);
  2728.             if ((keyword.startsWith("Ripple") && !sb.toString().contains("Ripple"))
  2729.                     || (keyword.startsWith("Dredge") && !sb.toString().contains("Dredge"))
  2730.                     || (keyword.startsWith("Madness") && !sb.toString().contains("Madness"))
  2731.                     || (keyword.startsWith("CARDNAME is ") && !sb.toString().contains("CARDNAME is "))
  2732.                     || (keyword.startsWith("Recover") && !sb.toString().contains("Recover"))) {
  2733.                 sb.append(keyword.replace(":", " ")).append("\r\n");
  2734.             }
  2735.             if ((keyword.equals("CARDNAME can't be countered.") && !sb.toString().contains(
  2736.                     "CARDNAME can't be countered."))
  2737.                     || keyword.startsWith("Cascade")
  2738.                     || (keyword.startsWith("Epic") && !sb.toString().contains("Epic"))
  2739.                     || (keyword.startsWith("Split second") && !sb.toString().contains("Split second"))
  2740.                     || (keyword.startsWith("Multikicker") && !sb.toString().contains("Multikicker"))) {
  2741.                 sb.append(kw.get(i)).append("\r\n");
  2742.             }
  2743.             if (keyword.startsWith("Flashback")) {
  2744.                 sb.append("Flashback");
  2745.                 if (keyword.contains(" ")) {
  2746.                     final Cost fbCost = new Cost(keyword.substring(10), this.getName(), true);
  2747.                     if (!fbCost.isOnlyManaCost()) {
  2748.                         sb.append(" -");
  2749.                     }
  2750.                     sb.append(" " + fbCost.toString()).delete(sb.length() - 2, sb.length());
  2751.                     if (!fbCost.isOnlyManaCost()) {
  2752.                         sb.append(".");
  2753.                     }
  2754.                 }
  2755.                 sb.append("\r\n");
  2756.             }
  2757.             if (keyword.startsWith("Storm")) {
  2758.                 if (sb.toString().contains("Target") || sb.toString().contains("target")) {
  2759.                     sb.insert(
  2760.                             sb.indexOf("Storm (When you cast this spell, copy it for each spell cast before it this turn.") + 81,
  2761.                             " You may choose new targets for the copies.");
  2762.                 }
  2763.             }
  2764.             /*
  2765.              * if (keyword.startsWith("Storm")) { if
  2766.              * (sb.toString().endsWith("\r\n\r\n")) {
  2767.              * sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3); }
  2768.              * sb.append(
  2769.              * "Storm (When you cast this spell, copy it for each spell cast before it this turn."
  2770.              * ); if (sb.toString().contains("Target") ||
  2771.              * sb.toString().contains("target")) {
  2772.              * sb.append(" You may choose new targets for the copies."); }
  2773.              * sb.append(")\r\n"); }
  2774.              */
  2775.             if (keyword.contains("Replicate") && !sb.toString().contains("you paid its replicate cost.")) {
  2776.                 if (sb.toString().endsWith("\r\n\r\n")) {
  2777.                     sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
  2778.                 }
  2779.                 sb.append(keyword);
  2780.                 sb.append(" (When you cast this spell, copy it for each time you paid its replicate cost.");
  2781.                 if (sb.toString().contains("Target") || sb.toString().contains("target")) {
  2782.                     sb.append(" You may choose new targets for the copies.");
  2783.                 }
  2784.                 sb.append(")\r\n");
  2785.             }
  2786.             if (keyword.startsWith("Haunt")) {
  2787.                 if (sb.toString().endsWith("\r\n\r\n")) {
  2788.                     sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
  2789.                 }
  2790.                 sb.append("Haunt (");
  2791.                 if (this.isCreature()) {
  2792.                     sb.append("When this creature dies, exile it haunting target creature.");
  2793.                 } else {
  2794.                     sb.append("When this spell card is put into a graveyard after resolving, ");
  2795.                     sb.append("exile it haunting target creature.");
  2796.                 }
  2797.                 sb.append(")\r\n");
  2798.             }
  2799.             if (keyword.equals("Convoke")) {
  2800.                 if (sb.toString().endsWith("\r\n\r\n")) {
  2801.                     sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
  2802.                 }
  2803.                 sb.append("Convoke (Each creature you tap while casting this spell reduces its cost by 1 or by one mana of that creature's color.)\r\n");
  2804.             }
  2805.             if (keyword.equals("Remove CARDNAME from your deck before playing if you're not playing for ante.")) {
  2806.                 if (sb.toString().endsWith("\r\n\r\n")) {
  2807.                     sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n") + 3);
  2808.                 }
  2809.                 sb.append("Remove CARDNAME from your deck before playing if you're not playing for ante.\r\n");
  2810.             }
  2811.             if (keyword.equals("Rebound")) {
  2812.                 sb.append(keyword)
  2813.                         .append("(If you cast this spell from your hand, exile it as it resolves. At the beginning of your next upkeep, you may cast this card from exile without paying its mana cost.)\r\n");
  2814.             }
  2815.         }
  2816.         return sb;
  2817.     }
  2818.  
  2819.     /**
  2820.      * <p>
  2821.      * Getter for the field <code>manaAbility</code>.
  2822.      * </p>
  2823.      *
  2824.      * @return a {@link java.util.ArrayList} object.
  2825.      */
  2826.     public final ArrayList<AbilityMana> getManaAbility() {
  2827.         return new ArrayList<AbilityMana>(this.getCharacteristics().getManaAbility());
  2828.     }
  2829.  
  2830.     // Returns basic mana abilities plus "reflected mana" abilities
  2831.     /**
  2832.      * <p>
  2833.      * getAIPlayableMana.
  2834.      * </p>
  2835.      *
  2836.      * @return a {@link java.util.ArrayList} object.
  2837.      */
  2838.     public final ArrayList<AbilityMana> getAIPlayableMana() {
  2839.         final ArrayList<AbilityMana> res = new ArrayList<AbilityMana>();
  2840.         for (final AbilityMana am : this.getManaAbility()) {
  2841.  
  2842.             // if a mana ability has a mana cost the AI will miscalculate
  2843.             final Cost cost = am.getPayCosts();
  2844.             if (!cost.hasNoManaCost()) {
  2845.                 continue;
  2846.             }
  2847.  
  2848.             if ((am.isBasic() || am.isReflectedMana()) && !res.contains(am)) {
  2849.                 res.add(am);
  2850.             }
  2851.  
  2852.         }
  2853.  
  2854.         return res;
  2855.  
  2856.     }
  2857.  
  2858.     /**
  2859.      * <p>
  2860.      * getBasicMana.
  2861.      * </p>
  2862.      *
  2863.      * @return a {@link java.util.ArrayList} object.
  2864.      */
  2865.     public final ArrayList<AbilityMana> getBasicMana() {
  2866.         final ArrayList<AbilityMana> res = new ArrayList<AbilityMana>();
  2867.         for (final AbilityMana am : this.getManaAbility()) {
  2868.             if (am.isBasic() && !res.contains(am)) {
  2869.                 res.add(am);
  2870.             }
  2871.         }
  2872.         return res;
  2873.     }
  2874.  
  2875.     /**
  2876.      * <p>
  2877.      * clearFirstSpellAbility.
  2878.      * </p>
  2879.      */
  2880.     public final void clearFirstSpell() {
  2881.         for (int i = 0; i < this.getCharacteristics().getSpellAbility().size(); i++) {
  2882.             if (this.getCharacteristics().getSpellAbility().get(i).isSpell()) {
  2883.                 this.getCharacteristics().getSpellAbility().remove(i);
  2884.                 return;
  2885.             }
  2886.         }
  2887.     }
  2888.  
  2889.     /**
  2890.      * <p>
  2891.      * clearAllButFirstSpellAbility.
  2892.      * </p>
  2893.      */
  2894.     public final void clearAllButFirstSpellAbility() {
  2895.         if (!this.getCharacteristics().getSpellAbility().isEmpty()) {
  2896.             final SpellAbility first = this.getCharacteristics().getSpellAbility().get(0);
  2897.             this.getCharacteristics().getSpellAbility().clear();
  2898.             this.getCharacteristics().getSpellAbility().add(first);
  2899.         }
  2900.         this.getCharacteristics().getManaAbility().clear();
  2901.     }
  2902.  
  2903.     /**
  2904.      * <p>
  2905.      * getAllButFirstSpellAbility.
  2906.      * </p>
  2907.      *
  2908.      * @return a {@link java.util.ArrayList} object.
  2909.      */
  2910.     public final ArrayList<SpellAbility> getAllButFirstSpellAbility() {
  2911.         final ArrayList<SpellAbility> sas = new ArrayList<SpellAbility>();
  2912.         sas.addAll(this.getCharacteristics().getSpellAbility());
  2913.         if (!sas.isEmpty()) {
  2914.             final SpellAbility first = this.getCharacteristics().getSpellAbility().get(0);
  2915.             sas.remove(first);
  2916.         }
  2917.         sas.addAll(this.getCharacteristics().getManaAbility());
  2918.  
  2919.         return sas;
  2920.     }
  2921.  
  2922.     /**
  2923.      * <p>
  2924.      * clearSpellAbility.
  2925.      * </p>
  2926.      */
  2927.     public final void clearSpellAbility() {
  2928.         this.getCharacteristics().getSpellAbility().clear();
  2929.         this.getCharacteristics().getManaAbility().clear();
  2930.     }
  2931.  
  2932.     /**
  2933.      * <p>
  2934.      * getSpellPermanent.
  2935.      * </p>
  2936.      *
  2937.      * @return a {@link forge.card.spellability.SpellPermanent} object.
  2938.      */
  2939.     public final SpellPermanent getSpellPermanent() {
  2940.         for (final SpellAbility sa : this.getCharacteristics().getSpellAbility()) {
  2941.             if (sa instanceof SpellPermanent) {
  2942.                 return (SpellPermanent) sa;
  2943.             }
  2944.         }
  2945.         return null;
  2946.     }
  2947.  
  2948.     /**
  2949.      * <p>
  2950.      * clearSpellKeepManaAbility.
  2951.      * </p>
  2952.      */
  2953.     public final void clearSpellKeepManaAbility() {
  2954.         this.getCharacteristics().getSpellAbility().clear();
  2955.     }
  2956.  
  2957.     /**
  2958.      * <p>
  2959.      * clearManaAbility.
  2960.      * </p>
  2961.      */
  2962.     public final void clearManaAbility() {
  2963.         this.getCharacteristics().getManaAbility().clear();
  2964.     }
  2965.  
  2966.     /**
  2967.      * <p>
  2968.      * addFirstSpellAbility.
  2969.      * </p>
  2970.      *
  2971.      * @param a
  2972.      *            a {@link forge.card.spellability.SpellAbility} object.
  2973.      */
  2974.     public final void addFirstSpellAbility(final SpellAbility a) {
  2975.         a.setSourceCard(this);
  2976.         if (a instanceof AbilityMana) {
  2977.             this.getCharacteristics().getManaAbility().add(0, (AbilityMana) a);
  2978.         } else {
  2979.             this.getCharacteristics().getSpellAbility().add(0, a);
  2980.         }
  2981.     }
  2982.  
  2983.     /**
  2984.      * <p>
  2985.      * addSpellAbility.
  2986.      * </p>
  2987.      *
  2988.      * @param a
  2989.      *            a {@link forge.card.spellability.SpellAbility} object.
  2990.      */
  2991.     public final void addSpellAbility(final SpellAbility a) {
  2992.         a.setSourceCard(this);
  2993.         if (a instanceof AbilityMana) {
  2994.             this.getCharacteristics().getManaAbility().add((AbilityMana) a);
  2995.         } else {
  2996.             this.getCharacteristics().getSpellAbility().add(a);
  2997.         }
  2998.     }
  2999.  
  3000.     /**
  3001.      * <p>
  3002.      * removeSpellAbility.
  3003.      * </p>
  3004.      *
  3005.      * @param a
  3006.      *            a {@link forge.card.spellability.SpellAbility} object.
  3007.      */
  3008.     public final void removeSpellAbility(final SpellAbility a) {
  3009.         if (a instanceof AbilityMana) {
  3010.             // if (a.isExtrinsic()) //never remove intrinsic mana abilities, is
  3011.             // this the way to go??
  3012.             this.getCharacteristics().getManaAbility().remove(a);
  3013.         } else {
  3014.             this.getCharacteristics().getSpellAbility().remove(a);
  3015.         }
  3016.     }
  3017.  
  3018.     /**
  3019.      * <p>
  3020.      * removeAllExtrinsicManaAbilities.
  3021.      * </p>
  3022.      */
  3023.     public final void removeAllExtrinsicManaAbilities() {
  3024.         // temp ArrayList, otherwise ConcurrentModificationExceptions occur:
  3025.         final ArrayList<SpellAbility> saList = new ArrayList<SpellAbility>();
  3026.  
  3027.         for (final SpellAbility var : this.getCharacteristics().getManaAbility()) {
  3028.             if (var.isExtrinsic()) {
  3029.                 saList.add(var);
  3030.             }
  3031.         }
  3032.         for (final SpellAbility sa : saList) {
  3033.             this.removeSpellAbility(sa);
  3034.         }
  3035.     }
  3036.  
  3037.     /**
  3038.      * <p>
  3039.      * getIntrinsicManaAbilitiesDescriptions.
  3040.      * </p>
  3041.      *
  3042.      * @return a {@link java.util.ArrayList} object.
  3043.      */
  3044.     public final ArrayList<String> getIntrinsicManaAbilitiesDescriptions() {
  3045.         final ArrayList<String> list = new ArrayList<String>();
  3046.         for (final SpellAbility var : this.getCharacteristics().getManaAbility()) {
  3047.             if (var.isIntrinsic()) {
  3048.                 list.add(var.toString());
  3049.             }
  3050.         }
  3051.         return list;
  3052.     }
  3053.  
  3054.     /**
  3055.      * <p>
  3056.      * Getter for the field <code>spellAbility</code>.
  3057.      * </p>
  3058.      *
  3059.      * @return an array of {@link forge.card.spellability.SpellAbility} objects.
  3060.      */
  3061.     public final SpellAbility[] getSpellAbility() {
  3062.         final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(this.getCharacteristics().getSpellAbility());
  3063.         res.addAll(this.getManaAbility());
  3064.         final SpellAbility[] s = new SpellAbility[res.size()];
  3065.         res.toArray(s);
  3066.         return s;
  3067.     }
  3068.  
  3069.     /**
  3070.      * <p>
  3071.      * getSpellAbilities.
  3072.      * </p>
  3073.      *
  3074.      * @return a {@link java.util.ArrayList} object.
  3075.      */
  3076.     public final ArrayList<SpellAbility> getSpellAbilities() {
  3077.         final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(this.getCharacteristics().getSpellAbility());
  3078.         res.addAll(this.getManaAbility());
  3079.         return res;
  3080.     }
  3081.  
  3082.     /**
  3083.      *
  3084.      * getAllSpellAbilities.
  3085.      *
  3086.      * @return ArrayList<SpellAbility>
  3087.      */
  3088.     public final ArrayList<SpellAbility> getAllSpellAbilities() {
  3089.         final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>();
  3090.  
  3091.         for (final String key : this.characteristicsMap.keySet()) {
  3092.             res.addAll(this.getState(key).getSpellAbility());
  3093.         }
  3094.  
  3095.         return res;
  3096.     }
  3097.  
  3098.     /**
  3099.      * <p>
  3100.      * getSpells.
  3101.      * </p>
  3102.      *
  3103.      * @return a {@link java.util.ArrayList} object.
  3104.      */
  3105.     public final ArrayList<SpellAbility> getSpells() {
  3106.         final ArrayList<SpellAbility> s = new ArrayList<SpellAbility>(this.getCharacteristics().getSpellAbility());
  3107.         final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>();
  3108.  
  3109.         for (final SpellAbility sa : s) {
  3110.             if (sa.isSpell()) {
  3111.                 res.add(sa);
  3112.             }
  3113.         }
  3114.         return res;
  3115.     }
  3116.  
  3117.     /**
  3118.      * <p>
  3119.      * getBasicSpells.
  3120.      * </p>
  3121.      *
  3122.      * @return a {@link java.util.ArrayList} object.
  3123.      */
  3124.     public final ArrayList<SpellAbility> getBasicSpells() {
  3125.         final ArrayList<SpellAbility> s = new ArrayList<SpellAbility>(this.getCharacteristics().getSpellAbility());
  3126.         final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>();
  3127.  
  3128.         for (final SpellAbility sa : s) {
  3129.             if (sa.isSpell() && !sa.isFlashBackAbility() && !sa.isBuyBackAbility()) {
  3130.                 res.add(sa);
  3131.             }
  3132.         }
  3133.         return res;
  3134.     }
  3135.  
  3136.     /**
  3137.      * <p>
  3138.      * getAdditionalCostSpells.
  3139.      * </p>
  3140.      *
  3141.      * @return a {@link java.util.ArrayList} object.
  3142.      */
  3143.     public final ArrayList<SpellAbility> getAdditionalCostSpells() {
  3144.         final ArrayList<SpellAbility> s = new ArrayList<SpellAbility>(this.getCharacteristics().getSpellAbility());
  3145.         final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>();
  3146.  
  3147.         for (final SpellAbility sa : s) {
  3148.             if (sa.isSpell() && !sa.getAdditionalManaCost().equals("")) {
  3149.                 res.add(sa);
  3150.             }
  3151.         }
  3152.         return res;
  3153.     }
  3154.  
  3155.     // shield = regeneration
  3156.     /**
  3157.      * <p>
  3158.      * setShield.
  3159.      * </p>
  3160.      *
  3161.      * @param n
  3162.      *            a int.
  3163.      */
  3164.     public final void setShield(final int n) {
  3165.         this.nShield = n;
  3166.     }
  3167.  
  3168.     /**
  3169.      * <p>
  3170.      * getShield.
  3171.      * </p>
  3172.      *
  3173.      * @return a int.
  3174.      */
  3175.     public final int getShield() {
  3176.         return this.nShield;
  3177.     }
  3178.  
  3179.     /**
  3180.      * <p>
  3181.      * addShield.
  3182.      * </p>
  3183.      */
  3184.     public final void addShield() {
  3185.         this.nShield++;
  3186.     }
  3187.  
  3188.     /**
  3189.      * <p>
  3190.      * subtractShield.
  3191.      * </p>
  3192.      */
  3193.     public final void subtractShield() {
  3194.         this.nShield--;
  3195.     }
  3196.  
  3197.     /**
  3198.      * Adds the regenerated this turn.
  3199.      */
  3200.     public final void addRegeneratedThisTurn() {
  3201.         this.regeneratedThisTurn += 1;
  3202.     }
  3203.  
  3204.     /**
  3205.      * Gets the regenerated this turn.
  3206.      *
  3207.      * @return the regenerated this turn
  3208.      */
  3209.     public final int getRegeneratedThisTurn() {
  3210.         return this.regeneratedThisTurn;
  3211.     }
  3212.  
  3213.     /**
  3214.      * Sets the regenerated this turn.
  3215.      *
  3216.      * @param n
  3217.      *            the new regenerated this turn
  3218.      */
  3219.     public final void setRegeneratedThisTurn(final int n) {
  3220.         this.regeneratedThisTurn = n;
  3221.     }
  3222.  
  3223.     /**
  3224.      * <p>
  3225.      * resetShield.
  3226.      * </p>
  3227.      */
  3228.     public final void resetShield() {
  3229.         this.nShield = 0;
  3230.     }
  3231.  
  3232.     /**
  3233.      * <p>
  3234.      * canBeShielded.
  3235.      * </p>
  3236.      *
  3237.      * @return a boolean.
  3238.      */
  3239.     public final boolean canBeShielded() {
  3240.         return !this.hasKeyword("CARDNAME can't be regenerated.");
  3241.     }
  3242.  
  3243.     // is this "Card" supposed to be a token?
  3244.     /**
  3245.      * <p>
  3246.      * Setter for the field <code>token</code>.
  3247.      * </p>
  3248.      *
  3249.      * @param b
  3250.      *            a boolean.
  3251.      */
  3252.     public final void setToken(final boolean b) {
  3253.         this.token = b;
  3254.     }
  3255.  
  3256.     /**
  3257.      * <p>
  3258.      * isToken.
  3259.      * </p>
  3260.      *
  3261.      * @return a boolean.
  3262.      */
  3263.     public final boolean isToken() {
  3264.         return this.token;
  3265.     }
  3266.  
  3267.     /**
  3268.      * <p>
  3269.      * Setter for the field <code>copiedToken</code>.
  3270.      * </p>
  3271.      *
  3272.      * @param b
  3273.      *            a boolean.
  3274.      */
  3275.     public final void setCopiedToken(final boolean b) {
  3276.         this.copiedToken = b;
  3277.     }
  3278.  
  3279.     /**
  3280.      * <p>
  3281.      * isCopiedToken.
  3282.      * </p>
  3283.      *
  3284.      * @return a boolean.
  3285.      */
  3286.     public final boolean isCopiedToken() {
  3287.         return this.copiedToken;
  3288.     }
  3289.  
  3290.     /**
  3291.      * <p>
  3292.      * Setter for the field <code>copiedSpell</code>.
  3293.      * </p>
  3294.      *
  3295.      * @param b
  3296.      *            a boolean.
  3297.      */
  3298.     public final void setCopiedSpell(final boolean b) {
  3299.         this.copiedSpell = b;
  3300.     }
  3301.  
  3302.     /**
  3303.      * <p>
  3304.      * isCopiedSpell.
  3305.      * </p>
  3306.      *
  3307.      * @return a boolean.
  3308.      */
  3309.     public final boolean isCopiedSpell() {
  3310.         return this.copiedSpell;
  3311.     }
  3312.  
  3313.     /**
  3314.      * <p>
  3315.      * addSpellChoice.
  3316.      * </p>
  3317.      *
  3318.      * @param string
  3319.      *            a {@link java.lang.String} object.
  3320.      */
  3321.     public final void addSpellChoice(final String string) {
  3322.         this.choicesMade.add(string);
  3323.     }
  3324.  
  3325.     /**
  3326.      * <p>
  3327.      * getChoices.
  3328.      * </p>
  3329.      *
  3330.      * @return a {@link java.util.ArrayList} object.
  3331.      */
  3332.     public final ArrayList<String> getChoices() {
  3333.         return this.choicesMade;
  3334.     }
  3335.  
  3336.     /**
  3337.      * <p>
  3338.      * getChoice.
  3339.      * </p>
  3340.      *
  3341.      * @param i
  3342.      *            a int.
  3343.      * @return a {@link java.lang.String} object.
  3344.      */
  3345.     public final String getChoice(final int i) {
  3346.         return this.choicesMade.get(i);
  3347.     }
  3348.  
  3349.     /**
  3350.      * <p>
  3351.      * setSpellChoiceTarget.
  3352.      * </p>
  3353.      *
  3354.      * @param string
  3355.      *            a {@link java.lang.String} object.
  3356.      */
  3357.     public final void setSpellChoiceTarget(final String string) {
  3358.         this.targetsForChoices.add(string);
  3359.     }
  3360.  
  3361.     /**
  3362.      * <p>
  3363.      * getChoiceTargets.
  3364.      * </p>
  3365.      *
  3366.      * @return a {@link java.util.ArrayList} object.
  3367.      */
  3368.     public final ArrayList<String> getChoiceTargets() {
  3369.         return this.targetsForChoices;
  3370.     }
  3371.  
  3372.     /**
  3373.      * <p>
  3374.      * getChoiceTarget.
  3375.      * </p>
  3376.      *
  3377.      * @param i
  3378.      *            a int.
  3379.      * @return a {@link java.lang.String} object.
  3380.      */
  3381.     public final String getChoiceTarget(final int i) {
  3382.         return this.targetsForChoices.get(i);
  3383.     }
  3384.  
  3385.     /**
  3386.      * <p>
  3387.      * setSpellWithChoices.
  3388.      * </p>
  3389.      *
  3390.      * @param b
  3391.      *            a boolean.
  3392.      */
  3393.     public final void setSpellWithChoices(final boolean b) {
  3394.         this.spellWithChoices = b;
  3395.     }
  3396.  
  3397.     /**
  3398.      * <p>
  3399.      * hasChoices.
  3400.      * </p>
  3401.      *
  3402.      * @return a boolean.
  3403.      */
  3404.     public final boolean hasChoices() {
  3405.         return this.spellWithChoices;
  3406.     }
  3407.  
  3408.     /**
  3409.      * <p>
  3410.      * setCopiesSpells.
  3411.      * </p>
  3412.      *
  3413.      * @param b
  3414.      *            a boolean.
  3415.      */
  3416.     public final void setCopiesSpells(final boolean b) {
  3417.         this.spellCopyingCard = b;
  3418.     }
  3419.  
  3420.     /**
  3421.      * <p>
  3422.      * copiesSpells.
  3423.      * </p>
  3424.      *
  3425.      * @return a boolean.
  3426.      */
  3427.     public final boolean copiesSpells() {
  3428.         return this.spellCopyingCard;
  3429.     }
  3430.  
  3431.     /**
  3432.      * <p>
  3433.      * isFaceDown.
  3434.      * </p>
  3435.      *
  3436.      * @return a boolean.
  3437.      */
  3438.     public final boolean isFaceDown() {
  3439.         return this.curCharacteristics.equals("FaceDown");
  3440.     }
  3441.  
  3442.     /**
  3443.      * <p>
  3444.      * setCanMorph.
  3445.      * </p>
  3446.      *
  3447.      * @param b
  3448.      *            a boolean.
  3449.      */
  3450.     public final void setCanMorph(final boolean b) {
  3451.         this.canMorph = b;
  3452.     }
  3453.  
  3454.     /**
  3455.      * <p>
  3456.      * getCanMorph.
  3457.      * </p>
  3458.      *
  3459.      * @return a boolean.
  3460.      */
  3461.     public final boolean getCanMorph() {
  3462.         return this.canMorph;
  3463.     }
  3464.  
  3465.     /**
  3466.      * <p>
  3467.      * addTrigger.
  3468.      * </p>
  3469.      *
  3470.      * @param c
  3471.      *            a {@link forge.Command} object.
  3472.      * @param typeIn
  3473.      *            a {@link forge.ZCTrigger} object.
  3474.      */
  3475.     public final void addTrigger(final Command c, final ZCTrigger typeIn) {
  3476.         this.zcTriggers.add(new AbilityTriggered(this, c, typeIn));
  3477.     }
  3478.  
  3479.     /**
  3480.      * <p>
  3481.      * removeTrigger.
  3482.      * </p>
  3483.      *
  3484.      * @param c
  3485.      *            a {@link forge.Command} object.
  3486.      * @param typeIn
  3487.      *            a {@link forge.ZCTrigger} object.
  3488.      */
  3489.     public final void removeTrigger(final Command c, final ZCTrigger typeIn) {
  3490.         this.zcTriggers.remove(new AbilityTriggered(this, c, typeIn));
  3491.     }
  3492.  
  3493.     /**
  3494.      * <p>
  3495.      * executeTrigger.
  3496.      * </p>
  3497.      *
  3498.      * @param type
  3499.      *            a {@link forge.ZCTrigger} object.
  3500.      */
  3501.     public final void executeTrigger(final ZCTrigger type) {
  3502.         for (final AbilityTriggered t : this.zcTriggers) {
  3503.             if (t.getTrigger().equals(type) && t.isBasic()) {
  3504.                 t.execute();
  3505.             }
  3506.         }
  3507.     }
  3508.  
  3509.     /**
  3510.      * <p>
  3511.      * clearTriggers.
  3512.      * </p>
  3513.      */
  3514.     public final void clearTriggers() {
  3515.         this.zcTriggers.clear();
  3516.     }
  3517.  
  3518.     /**
  3519.      * <p>
  3520.      * addComesIntoPlayCommand.
  3521.      * </p>
  3522.      *
  3523.      * @param c
  3524.      *            a {@link forge.Command} object.
  3525.      */
  3526.     public final void addComesIntoPlayCommand(final Command c) {
  3527.         this.addTrigger(c, ZCTrigger.ENTERFIELD);
  3528.     }
  3529.  
  3530.     /**
  3531.      * <p>
  3532.      * removeComesIntoPlayCommand.
  3533.      * </p>
  3534.      *
  3535.      * @param c
  3536.      *            a {@link forge.Command} object.
  3537.      */
  3538.     public final void removeComesIntoPlayCommand(final Command c) {
  3539.         this.removeTrigger(c, ZCTrigger.ENTERFIELD);
  3540.     }
  3541.  
  3542.     /**
  3543.      * <p>
  3544.      * comesIntoPlay.
  3545.      * </p>
  3546.      */
  3547.     public final void comesIntoPlay() {
  3548.         this.executeTrigger(ZCTrigger.ENTERFIELD);
  3549.     }
  3550.  
  3551.     /**
  3552.      * <p>
  3553.      * addDestroyCommand.
  3554.      * </p>
  3555.      *
  3556.      * @param c
  3557.      *            a {@link forge.Command} object.
  3558.      */
  3559.     public final void addDestroyCommand(final Command c) {
  3560.         this.addTrigger(c, ZCTrigger.DESTROY);
  3561.     }
  3562.  
  3563.     /**
  3564.      * <p>
  3565.      * removeDestroyCommand.
  3566.      * </p>
  3567.      *
  3568.      * @param c
  3569.      *            a {@link forge.Command} object.
  3570.      */
  3571.     public final void removeDestroyCommand(final Command c) {
  3572.         this.removeTrigger(c, ZCTrigger.DESTROY);
  3573.     }
  3574.  
  3575.     /**
  3576.      * <p>
  3577.      * destroy.
  3578.      * </p>
  3579.      */
  3580.     public final void destroy() {
  3581.         this.executeTrigger(ZCTrigger.DESTROY);
  3582.     }
  3583.  
  3584.     /**
  3585.      * <p>
  3586.      * addLeavesPlayCommand.
  3587.      * </p>
  3588.      *
  3589.      * @param c
  3590.      *            a {@link forge.Command} object.
  3591.      */
  3592.     public final void addLeavesPlayCommand(final Command c) {
  3593.         this.addTrigger(c, ZCTrigger.LEAVEFIELD);
  3594.     }
  3595.  
  3596.     /**
  3597.      * <p>
  3598.      * removeLeavesPlayCommand.
  3599.      * </p>
  3600.      *
  3601.      * @param c
  3602.      *            a {@link forge.Command} object.
  3603.      */
  3604.     public final void removeLeavesPlayCommand(final Command c) {
  3605.         this.removeTrigger(c, ZCTrigger.LEAVEFIELD);
  3606.     }
  3607.  
  3608.     /**
  3609.      * <p>
  3610.      * leavesPlay.
  3611.      * </p>
  3612.      */
  3613.     public final void leavesPlay() {
  3614.         this.executeTrigger(ZCTrigger.LEAVEFIELD);
  3615.     }
  3616.  
  3617.     /**
  3618.      * <p>
  3619.      * addEquipCommand.
  3620.      * </p>
  3621.      *
  3622.      * @param c
  3623.      *            a {@link forge.Command} object.
  3624.      */
  3625.     public final void addEquipCommand(final Command c) {
  3626.         this.equipCommandList.add(c);
  3627.     }
  3628.  
  3629.     /**
  3630.      * <p>
  3631.      * removeEquipCommand.
  3632.      * </p>
  3633.      *
  3634.      * @param c
  3635.      *            a {@link forge.Command} object.
  3636.      */
  3637.     public final void removeEquipCommand(final Command c) {
  3638.         this.equipCommandList.remove(c);
  3639.     }
  3640.  
  3641.     /**
  3642.      * <p>
  3643.      * equip.
  3644.      * </p>
  3645.      */
  3646.     public final void equip() {
  3647.         for (final Command var : this.equipCommandList) {
  3648.             var.execute();
  3649.         }
  3650.     }
  3651.  
  3652.     /**
  3653.      * <p>
  3654.      * addUnEquipCommand.
  3655.      * </p>
  3656.      *
  3657.      * @param c
  3658.      *            a {@link forge.Command} object.
  3659.      */
  3660.     public final void addUnEquipCommand(final Command c) {
  3661.         this.unEquipCommandList.add(c);
  3662.     }
  3663.  
  3664.     /**
  3665.      * <p>
  3666.      * removeUnEquipCommand.
  3667.      * </p>
  3668.      *
  3669.      * @param c
  3670.      *            a {@link forge.Command} object.
  3671.      */
  3672.     public final void removeUnEquipCommand(final Command c) {
  3673.         this.unEquipCommandList.remove(c);
  3674.     }
  3675.  
  3676.     /**
  3677.      * <p>
  3678.      * unEquip.
  3679.      * </p>
  3680.      */
  3681.     public final void unEquip() {
  3682.         for (final Command var : this.unEquipCommandList) {
  3683.             var.execute();
  3684.         }
  3685.     }
  3686.  
  3687.     /**
  3688.      * <p>
  3689.      * addEnchantCommand.
  3690.      * </p>
  3691.      *
  3692.      * @param c
  3693.      *            a {@link forge.Command} object.
  3694.      */
  3695.     public final void addEnchantCommand(final Command c) {
  3696.         this.enchantCommandList.add(c);
  3697.     }
  3698.  
  3699.     /**
  3700.      * <p>
  3701.      * clearEnchantCommand.
  3702.      * </p>
  3703.      */
  3704.     public final void clearEnchantCommand() {
  3705.         this.enchantCommandList.clear();
  3706.     }
  3707.  
  3708.     /**
  3709.      * <p>
  3710.      * enchant.
  3711.      * </p>
  3712.      */
  3713.     public final void enchant() {
  3714.         for (final Command var : this.enchantCommandList) {
  3715.             var.execute();
  3716.         }
  3717.     }
  3718.  
  3719.     /**
  3720.      * <p>
  3721.      * addUnEnchantCommand.
  3722.      * </p>
  3723.      *
  3724.      * @param c
  3725.      *            a {@link forge.Command} object.
  3726.      */
  3727.     public final void addUnEnchantCommand(final Command c) {
  3728.         this.unEnchantCommandList.add(c);
  3729.     }
  3730.  
  3731.     /**
  3732.      * <p>
  3733.      * clearUnEnchantCommand.
  3734.      * </p>
  3735.      */
  3736.     public final void clearUnEnchantCommand() {
  3737.         this.unEnchantCommandList.clear();
  3738.     }
  3739.  
  3740.     /**
  3741.      * <p>
  3742.      * unEnchant.
  3743.      * </p>
  3744.      */
  3745.     public final void unEnchant() {
  3746.         for (final Command var : this.unEnchantCommandList) {
  3747.             var.execute();
  3748.         }
  3749.     }
  3750.  
  3751.     /**
  3752.      * <p>
  3753.      * addUntapCommand.
  3754.      * </p>
  3755.      *
  3756.      * @param c
  3757.      *            a {@link forge.Command} object.
  3758.      */
  3759.     public final void addUntapCommand(final Command c) {
  3760.         this.untapCommandList.add(c);
  3761.     }
  3762.  
  3763.     /**
  3764.      * <p>
  3765.      * addChangeControllerCommand.
  3766.      * </p>
  3767.      *
  3768.      * @param c
  3769.      *            a {@link forge.Command} object.
  3770.      */
  3771.     public final void addChangeControllerCommand(final Command c) {
  3772.         this.changeControllerCommandList.add(c);
  3773.     }
  3774.  
  3775.     /**
  3776.      * <p>
  3777.      * Setter for the field <code>sickness</code>.
  3778.      * </p>
  3779.      *
  3780.      * @param b
  3781.      *            a boolean.
  3782.      */
  3783.     public final void setSickness(final boolean b) {
  3784.         this.sickness = b;
  3785.     }
  3786.  
  3787.     /**
  3788.      * <p>
  3789.      * hasSickness.
  3790.      * </p>
  3791.      *
  3792.      * @return a boolean.
  3793.      */
  3794.     public final boolean hasSickness() {
  3795.         return !this.hasKeyword("Haste") && this.sickness;
  3796.     }
  3797.  
  3798.     /**
  3799.      *
  3800.      * isSick.
  3801.      *
  3802.      * @return boolean
  3803.      */
  3804.     public final boolean isSick() {
  3805.         return !this.hasKeyword("Haste") && this.sickness && this.isCreature();
  3806.     }
  3807.  
  3808.     /**
  3809.      * <p>
  3810.      * Setter for the field <code>imageName</code>.
  3811.      * </p>
  3812.      *
  3813.      * @param s
  3814.      *            a {@link java.lang.String} object.
  3815.      */
  3816.     public final void setImageName(final String s) {
  3817.         this.getCharacteristics().setImageName(s);
  3818.     }
  3819.  
  3820.     /**
  3821.      * <p>
  3822.      * Getter for the field <code>imageName</code>.
  3823.      * </p>
  3824.      *
  3825.      * @return a {@link java.lang.String} object.
  3826.      */
  3827.     public final String getImageName() {
  3828.         if (!this.getCharacteristics().getImageName().equals("")) {
  3829.             return this.getCharacteristics().getImageName();
  3830.         }
  3831.         return this.getName();
  3832.     }
  3833.  
  3834.     /**
  3835.      * <p>
  3836.      * Getter for the field <code>owner</code>.
  3837.      * </p>
  3838.      *
  3839.      * @return a {@link forge.Player} object.
  3840.      */
  3841.     public final Player getOwner() {
  3842.         return this.owner;
  3843.     }
  3844.  
  3845.     /**
  3846.      * Get the controller for this card.
  3847.      *
  3848.      * @return a {@link forge.Player} object.
  3849.      */
  3850.     public final Player getController() {
  3851.         if (this.controllerObjects.size() == 0) {
  3852.             return this.owner;
  3853.         }
  3854.         final Object topController = this.controllerObjects.get(this.controllerObjects.size() - 1);
  3855.         if (topController instanceof Player) {
  3856.             return (Player) topController;
  3857.         } else {
  3858.             return ((Card) topController).getController();
  3859.         }
  3860.     }
  3861.  
  3862.     /**
  3863.      *
  3864.      * TODO Write javadoc for this method.
  3865.      *
  3866.      * @param controllerObject
  3867.      *            an Object
  3868.      */
  3869.     public final void addController(final Object controllerObject) {
  3870.         final Object prevController = this.controllerObjects.size() == 0 ? this.owner : this.controllerObjects
  3871.                 .get(this.controllerObjects.size() - 1);
  3872.         if (!controllerObject.equals(prevController)) {
  3873.             if (controllerObject instanceof Player) {
  3874.                 for (int i = 0; i < this.controllerObjects.size(); i++) {
  3875.                     if (this.controllerObjects.get(i) instanceof Player) {
  3876.                         this.controllerObjects.remove(i);
  3877.                     }
  3878.                 }
  3879.             }
  3880.             this.controllerObjects.add(controllerObject);
  3881.             if ((AllZone.getGameAction() != null) && (prevController != null)) {
  3882.                 AllZone.getGameAction().controllerChangeZoneCorrection(this);
  3883.             }
  3884.  
  3885.             if (prevController != null) {
  3886.                 for (final Command c : this.changeControllerCommandList) {
  3887.                     c.execute();
  3888.                 }
  3889.             }
  3890.  
  3891.             this.updateObservers();
  3892.         }
  3893.     }
  3894.  
  3895.     /**
  3896.      *
  3897.      * TODO Write javadoc for this method.
  3898.      *
  3899.      * @param controllerObject
  3900.      *            a Object
  3901.      */
  3902.     public final void removeController(final Object controllerObject) {
  3903.         final Object currentController = this.getController();
  3904.         this.controllerObjects.remove(controllerObject);
  3905.  
  3906.         if (!currentController.equals(this.getController())) {
  3907.             AllZone.getGameAction().controllerChangeZoneCorrection(this);
  3908.  
  3909.             for (final Command c : this.changeControllerCommandList) {
  3910.                 c.execute();
  3911.             }
  3912.  
  3913.             this.updateObservers();
  3914.         }
  3915.     }
  3916.  
  3917.     /**
  3918.      *
  3919.      * TODO Write javadoc for this method.
  3920.      */
  3921.     public final void clearControllers() {
  3922.         this.controllerObjects.clear();
  3923.     }
  3924.  
  3925.     /**
  3926.      *
  3927.      * TODO Write javadoc for this method.
  3928.      *
  3929.      * @return an ArrayList<Object>
  3930.      */
  3931.     public final ArrayList<Object> getControllerObjects() {
  3932.         return this.controllerObjects;
  3933.     }
  3934.  
  3935.     /**
  3936.      *
  3937.      * TODO Write javadoc for this method.
  3938.      *
  3939.      * @param in
  3940.      *            an Object
  3941.      */
  3942.     public final void setControllerObjects(final ArrayList<Object> in) {
  3943.         this.controllerObjects = in;
  3944.     }
  3945.  
  3946.     /**
  3947.      * <p>
  3948.      * Setter for the field <code>owner</code>.
  3949.      * </p>
  3950.      *
  3951.      * @param player
  3952.      *            a {@link forge.Player} object.
  3953.      */
  3954.     public final void setOwner(final Player player) {
  3955.         this.owner = player;
  3956.         this.updateObservers();
  3957.     }
  3958.  
  3959.     /**
  3960.      * <p>
  3961.      * Setter for the field <code>controller</code>.
  3962.      * </p>
  3963.      *
  3964.      * @return the equipped by
  3965.      */
  3966.     /*
  3967.      * public void setController(Player player) { boolean sameController =
  3968.      * controller == null ? false : controller.isPlayer(player); controller =
  3969.      * player; if (null != controller && !sameController) { for (Command var :
  3970.      * changeControllerCommandList) var.execute(); } this.updateObservers(); }
  3971.      */
  3972.  
  3973.     /**
  3974.      * <p>
  3975.      * Getter for the field <code>equippedBy</code>.
  3976.      * </p>
  3977.      *
  3978.      * @return a {@link java.util.ArrayList} object.
  3979.      */
  3980.     public final ArrayList<Card> getEquippedBy() {
  3981.         return this.equippedBy;
  3982.     }
  3983.  
  3984.     /**
  3985.      * <p>
  3986.      * Setter for the field <code>equippedBy</code>.
  3987.      * </p>
  3988.      *
  3989.      * @param list
  3990.      *            a {@link java.util.ArrayList} object.
  3991.      */
  3992.     public final void setEquippedBy(final ArrayList<Card> list) {
  3993.         this.equippedBy = list;
  3994.     }
  3995.  
  3996.     /**
  3997.      * <p>
  3998.      * Getter for the field <code>equipping</code>.
  3999.      * </p>
  4000.      *
  4001.      * @return a {@link java.util.ArrayList} object.
  4002.      */
  4003.     public final ArrayList<Card> getEquipping() {
  4004.         return this.equipping;
  4005.     }
  4006.  
  4007.     /**
  4008.      * <p>
  4009.      * getEquippingCard.
  4010.      * </p>
  4011.      *
  4012.      * @return a {@link forge.Card} object.
  4013.      */
  4014.     public final Card getEquippingCard() {
  4015.         if (this.equipping.size() == 0) {
  4016.             return null;
  4017.         }
  4018.         return this.equipping.get(0);
  4019.     }
  4020.  
  4021.     /**
  4022.      * <p>
  4023.      * Setter for the field <code>equipping</code>.
  4024.      * </p>
  4025.      *
  4026.      * @param list
  4027.      *            a {@link java.util.ArrayList} object.
  4028.      */
  4029.     public final void setEquipping(final ArrayList<Card> list) {
  4030.         this.equipping = list;
  4031.     }
  4032.  
  4033.     /**
  4034.      * <p>
  4035.      * isEquipped.
  4036.      * </p>
  4037.      *
  4038.      * @return a boolean.
  4039.      */
  4040.     public final boolean isEquipped() {
  4041.         return !this.equippedBy.isEmpty();
  4042.     }
  4043.  
  4044.     /**
  4045.      * <p>
  4046.      * isEquipping.
  4047.      * </p>
  4048.      *
  4049.      * @return a boolean.
  4050.      */
  4051.     public final boolean isEquipping() {
  4052.         return this.equipping.size() != 0;
  4053.     }
  4054.  
  4055.     /**
  4056.      * <p>
  4057.      * addEquippedBy.
  4058.      * </p>
  4059.      *
  4060.      * @param c
  4061.      *            a {@link forge.Card} object.
  4062.      */
  4063.     public final void addEquippedBy(final Card c) {
  4064.         this.equippedBy.add(c);
  4065.         this.updateObservers();
  4066.     }
  4067.  
  4068.     /**
  4069.      * <p>
  4070.      * removeEquippedBy.
  4071.      * </p>
  4072.      *
  4073.      * @param c
  4074.      *            a {@link forge.Card} object.
  4075.      */
  4076.     public final void removeEquippedBy(final Card c) {
  4077.         this.equippedBy.remove(c);
  4078.         this.updateObservers();
  4079.     }
  4080.  
  4081.     /**
  4082.      * <p>
  4083.      * addEquipping.
  4084.      * </p>
  4085.      *
  4086.      * @param c
  4087.      *            a {@link forge.Card} object.
  4088.      */
  4089.     public final void addEquipping(final Card c) {
  4090.         this.equipping.add(c);
  4091.         this.setTimestamp(AllZone.getNextTimestamp());
  4092.         this.updateObservers();
  4093.     }
  4094.  
  4095.     /**
  4096.      * <p>
  4097.      * removeEquipping.
  4098.      * </p>
  4099.      *
  4100.      * @param c
  4101.      *            a {@link forge.Card} object.
  4102.      */
  4103.     public final void removeEquipping(final Card c) {
  4104.         this.equipping.remove(c);
  4105.         this.updateObservers();
  4106.     }
  4107.  
  4108.     /**
  4109.      * <p>
  4110.      * equipCard.
  4111.      * </p>
  4112.      * equipment.equipCard(cardToBeEquipped)
  4113.      *
  4114.      * @param c
  4115.      *            a {@link forge.Card} object.
  4116.      */
  4117.     public final void equipCard(final Card c) {
  4118.         this.addEquipping(c);
  4119.         c.addEquippedBy(this);
  4120.         this.equip();
  4121.     }
  4122.  
  4123.     /**
  4124.      * <p>
  4125.      * unEquipCard.
  4126.      * </p>
  4127.      *
  4128.      * @param c
  4129.      *            a {@link forge.Card} object.
  4130.      */
  4131.     public final void unEquipCard(final Card c) // equipment.unEquipCard(equippedCard);
  4132.     {
  4133.         this.unEquip();
  4134.         this.equipping.remove(c);
  4135.         c.removeEquippedBy(this);
  4136.  
  4137.         // Run triggers
  4138.         final Map<String, Object> runParams = new TreeMap<String, Object>();
  4139.         runParams.put("Equipment", this);
  4140.         runParams.put("Card", c);
  4141.         AllZone.getTriggerHandler().runTrigger("Unequip", runParams);
  4142.     }
  4143.  
  4144.     /**
  4145.      * <p>
  4146.      * unEquipAllCards.
  4147.      * </p>
  4148.      */
  4149.     public final void unEquipAllCards() {
  4150.         // while there exists equipment, unequip the first one
  4151.         while (this.equippedBy.size() > 0) {
  4152.             this.equippedBy.get(0).unEquipCard(this);
  4153.         }
  4154.     }
  4155.  
  4156.     /**
  4157.      * <p>
  4158.      * Getter for the field <code>enchanting</code>.
  4159.      * </p>
  4160.      *
  4161.      * @return a {@link forge.GameEntity} object.
  4162.      */
  4163.     public final GameEntity getEnchanting() {
  4164.         return this.enchanting;
  4165.     }
  4166.  
  4167.     /**
  4168.      * <p>
  4169.      * getEnchantingCard.
  4170.      * </p>
  4171.      *
  4172.      * @return a {@link forge.Card} object.
  4173.      */
  4174.     public final Card getEnchantingCard() {
  4175.         if ((this.enchanting != null) && (this.enchanting instanceof Card)) {
  4176.             return (Card) this.enchanting;
  4177.         }
  4178.         return null;
  4179.     }
  4180.  
  4181.     /**
  4182.      * <p>
  4183.      * getEnchantingPlayer.
  4184.      * </p>
  4185.      *
  4186.      * @return a {@link forge.Player} object.
  4187.      */
  4188.     public final Player getEnchantingPlayer() {
  4189.         if ((this.enchanting != null) && (this.enchanting instanceof Player)) {
  4190.             return (Player) this.enchanting;
  4191.         }
  4192.         return null;
  4193.     }
  4194.  
  4195.     /**
  4196.      * <p>
  4197.      * Setter for the field <code>enchanting</code>.
  4198.      * </p>
  4199.      *
  4200.      * @param e
  4201.      *            a GameEntity object.
  4202.      */
  4203.     public final void setEnchanting(final GameEntity e) {
  4204.         this.enchanting = e;
  4205.     }
  4206.  
  4207.     /**
  4208.      * <p>
  4209.      * isEnchanting.
  4210.      * </p>
  4211.      *
  4212.      * @return a boolean.
  4213.      */
  4214.     public final boolean isEnchanting() {
  4215.         return this.enchanting != null;
  4216.     }
  4217.  
  4218.     /**
  4219.      * <p>
  4220.      * isEnchanting.
  4221.      * </p>
  4222.      *
  4223.      * @return a boolean.
  4224.      */
  4225.     public final boolean isEnchantingCard() {
  4226.         return this.getEnchantingCard() != null;
  4227.     }
  4228.  
  4229.     /**
  4230.      * <p>
  4231.      * isEnchanting.
  4232.      * </p>
  4233.      *
  4234.      * @return a boolean.
  4235.      */
  4236.     public final boolean isEnchantingPlayer() {
  4237.         return this.getEnchantingPlayer() != null;
  4238.     }
  4239.  
  4240.     /**
  4241.      * checks to see if this card is enchanted by an aura with a given name.
  4242.      *
  4243.      * @param cardName
  4244.      *            the name of the aura
  4245.      * @return true if this card is enchanted by an aura with the given name,
  4246.      *         false otherwise
  4247.      */
  4248.     public final boolean isEnchantedBy(final String cardName) {
  4249.         final ArrayList<Card> allAuras = this.getEnchantedBy();
  4250.         for (final Card aura : allAuras) {
  4251.             if (aura.getName().equals(cardName)) {
  4252.                 return true;
  4253.             }
  4254.         }
  4255.         return false;
  4256.     }
  4257.  
  4258.     /**
  4259.      * <p>
  4260.      * addEnchanting.
  4261.      * </p>
  4262.      *
  4263.      * @param e
  4264.      *            a {@link forge.GameEntity} object.
  4265.      */
  4266.     public final void addEnchanting(final GameEntity e) {
  4267.         this.enchanting = e;
  4268.         this.setTimestamp(AllZone.getNextTimestamp());
  4269.         this.updateObservers();
  4270.     }
  4271.  
  4272.     /**
  4273.      * <p>
  4274.      * removeEnchanting.
  4275.      * </p>
  4276.      *
  4277.      * @param e
  4278.      *            a {@link forge.GameEntity} object.
  4279.      */
  4280.     public final void removeEnchanting(final GameEntity e) {
  4281.         if (this.enchanting.equals(e)) {
  4282.             this.enchanting = null;
  4283.             this.updateObservers();
  4284.         }
  4285.     }
  4286.  
  4287.     /**
  4288.      * <p>
  4289.      * enchant.
  4290.      * </p>
  4291.      *
  4292.      * @param entity
  4293.      *            a {@link forge.GameEntity} object.
  4294.      */
  4295.     public final void enchantEntity(final GameEntity entity) {
  4296.         this.addEnchanting(entity);
  4297.         entity.addEnchantedBy(this);
  4298.         this.enchant();
  4299.     }
  4300.  
  4301.     /**
  4302.      * <p>
  4303.      * unEnchant.
  4304.      * </p>
  4305.      *
  4306.      * @param gameEntity
  4307.      *            a {@link forge.GameEntity} object.
  4308.      */
  4309.     public final void unEnchantEntity(final GameEntity gameEntity) {
  4310.         if ((this.enchanting != null) && this.enchanting.equals(gameEntity)) {
  4311.             this.unEnchant();
  4312.             this.enchanting = null;
  4313.             gameEntity.removeEnchantedBy(this);
  4314.         }
  4315.     }
  4316.  
  4317.     // array size might equal 0, will NEVER be null
  4318.     /**
  4319.      * <p>
  4320.      * getAttachedCards.
  4321.      * </p>
  4322.      *
  4323.      * @return an array of {@link forge.Card} objects.
  4324.      */
  4325.     public final Card[] getAttachedCardsByMindsDesire() {
  4326.         final Card[] c = new Card[this.attachedByMindsDesire.size()];
  4327.         this.attachedByMindsDesire.toArray(c);
  4328.         return c;
  4329.     }
  4330.  
  4331.     /**
  4332.      * <p>
  4333.      * hasAttachedCards.
  4334.      * </p>
  4335.      *
  4336.      * @return a boolean.
  4337.      */
  4338.     public final boolean hasAttachedCardsByMindsDesire() {
  4339.         return this.getAttachedCardsByMindsDesire().length != 0;
  4340.     }
  4341.  
  4342.     /**
  4343.      * <p>
  4344.      * attachCard.
  4345.      * </p>
  4346.      *
  4347.      * @param c
  4348.      *            a {@link forge.Card} object.
  4349.      */
  4350.     public final void attachCardByMindsDesire(final Card c) {
  4351.         this.attachedByMindsDesire.add(c);
  4352.         this.updateObservers();
  4353.     }
  4354.  
  4355.     /**
  4356.      * <p>
  4357.      * unattachCard.
  4358.      * </p>
  4359.      *
  4360.      * @param c
  4361.      *            a {@link forge.Card} object.
  4362.      */
  4363.     public final void unattachCardByMindDesire(final Card c) {
  4364.         this.attachedByMindsDesire.remove(c);
  4365.         this.updateObservers();
  4366.     }
  4367.  
  4368.     /**
  4369.      * <p>
  4370.      * Setter for the field <code>type</code>.
  4371.      * </p>
  4372.      *
  4373.      * @param a
  4374.      *            a {@link java.util.ArrayList} object.
  4375.      */
  4376.     public final void setType(final ArrayList<String> a) {
  4377.         this.getCharacteristics().setType(new ArrayList<String>(a));
  4378.     }
  4379.  
  4380.     /**
  4381.      * <p>
  4382.      * addType.
  4383.      * </p>
  4384.      *
  4385.      * @param a
  4386.      *            a {@link java.lang.String} object.
  4387.      */
  4388.     public final void addType(final String a) {
  4389.         this.getCharacteristics().getType().add(a);
  4390.     }
  4391.  
  4392.     /**
  4393.      * <p>
  4394.      * removeType.
  4395.      * </p>
  4396.      *
  4397.      * @param a
  4398.      *            a {@link java.lang.String} object.
  4399.      */
  4400.     public final void removeType(final String a) {
  4401.         this.getCharacteristics().getType().remove(a);
  4402.     }
  4403.  
  4404.     /**
  4405.      * <p>
  4406.      * Getter for the field <code>type</code>.
  4407.      * </p>
  4408.      *
  4409.      * @return a {@link java.util.ArrayList} object.
  4410.      */
  4411.     public final ArrayList<String> getType() {
  4412.  
  4413.         // see if type changes are in effect
  4414.         if (!this.changedCardTypes.isEmpty()) {
  4415.  
  4416.             final ArrayList<String> newType = new ArrayList<String>(this.getCharacteristics().getType());
  4417.             final ArrayList<CardType> types = this.changedCardTypes;
  4418.             Collections.sort(types); // sorts types by timeStamp
  4419.  
  4420.             for (final CardType ct : types) {
  4421.                 final ArrayList<String> removeTypes = new ArrayList<String>();
  4422.                 if (ct.getRemoveType() != null) {
  4423.                     removeTypes.addAll(ct.getRemoveType());
  4424.                 }
  4425.                 // remove old types
  4426.                 for (int i = 0; i < newType.size(); i++) {
  4427.                     final String t = newType.get(i);
  4428.                     if (ct.isRemoveSuperTypes() && CardUtil.isASuperType(t)) {
  4429.                         removeTypes.add(t);
  4430.                     }
  4431.                     if (ct.isRemoveCardTypes() && CardUtil.isACardType(t)) {
  4432.                         removeTypes.add(t);
  4433.                     }
  4434.                     if (ct.isRemoveSubTypes() && CardUtil.isASubType(t)) {
  4435.                         removeTypes.add(t);
  4436.                     }
  4437.                     if (ct.isRemoveCreatureTypes() && (CardUtil.isACreatureType(t) || t.equals("AllCreatureTypes"))) {
  4438.                         removeTypes.add(t);
  4439.                     }
  4440.                 }
  4441.                 newType.removeAll(removeTypes);
  4442.                 // add new types
  4443.                 if (ct.getType() != null) {
  4444.                     newType.addAll(ct.getType());
  4445.                 }
  4446.  
  4447.             }
  4448.  
  4449.             return newType;
  4450.         }
  4451.  
  4452.         // nothing changed
  4453.         return new ArrayList<String>(this.getCharacteristics().getType());
  4454.     }
  4455.  
  4456.     /**
  4457.      *
  4458.      * TODO Write javadoc for this method.
  4459.      *
  4460.      * @param types
  4461.      *            a ArrayList<CardType>
  4462.      */
  4463.     public final void setChangedCardTypes(final ArrayList<CardType> types) {
  4464.         this.changedCardTypes = types;
  4465.     }
  4466.  
  4467.     /**
  4468.      *
  4469.      * TODO Write javadoc for this method.
  4470.      *
  4471.      * @return ArrayList<CardType>
  4472.      */
  4473.     public final ArrayList<CardType> getChangedCardTypes() {
  4474.         return this.changedCardTypes;
  4475.     }
  4476.  
  4477.     /**
  4478.      *
  4479.      * TODO Write javadoc for this method.
  4480.      *
  4481.      * @param types
  4482.      *            ArrayList<String>
  4483.      * @param removeTypes
  4484.      *            ArrayList<String>
  4485.      * @param removeSuperTypes
  4486.      *            boolean
  4487.      * @param removeCardTypes
  4488.      *            boolean
  4489.      * @param removeSubTypes
  4490.      *            boolean
  4491.      * @param removeCreatureTypes
  4492.      *            boolean
  4493.      * @param timestamp
  4494.      *            long
  4495.      */
  4496.     public final void addChangedCardTypes(final ArrayList<String> types, final ArrayList<String> removeTypes,
  4497.             final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes,
  4498.             final boolean removeCreatureTypes, final long timestamp) {
  4499.  
  4500.         this.changedCardTypes.add(new CardType(types, removeTypes, removeSuperTypes, removeCardTypes, removeSubTypes,
  4501.                 removeCreatureTypes, timestamp));
  4502.     }
  4503.  
  4504.     /**
  4505.      *
  4506.      * TODO Write javadoc for this method.
  4507.      *
  4508.      * @param types
  4509.      *            String[]
  4510.      * @param removeTypes
  4511.      *            String[]
  4512.      * @param removeSuperTypes
  4513.      *            boolean
  4514.      * @param removeCardTypes
  4515.      *            boolean
  4516.      * @param removeSubTypes
  4517.      *            boolean
  4518.      * @param removeCreatureTypes
  4519.      *            boolean
  4520.      * @param timestamp
  4521.      *            long
  4522.      */
  4523.     public final void addChangedCardTypes(final String[] types, final String[] removeTypes,
  4524.             final boolean removeSuperTypes, final boolean removeCardTypes, final boolean removeSubTypes,
  4525.             final boolean removeCreatureTypes, final long timestamp) {
  4526.         ArrayList<String> typeList = null;
  4527.         ArrayList<String> removeTypeList = null;
  4528.         if (types != null) {
  4529.             typeList = new ArrayList<String>(Arrays.asList(types));
  4530.         }
  4531.  
  4532.         if (removeTypes != null) {
  4533.             removeTypeList = new ArrayList<String>(Arrays.asList(removeTypes));
  4534.         }
  4535.  
  4536.         this.addChangedCardTypes(typeList, removeTypeList, removeSuperTypes, removeCardTypes, removeSubTypes,
  4537.                 removeCreatureTypes, timestamp);
  4538.     }
  4539.  
  4540.     /**
  4541.      *
  4542.      * TODO Write javadoc for this method.
  4543.      *
  4544.      * @param timestamp
  4545.      *            long
  4546.      */
  4547.     public final void removeChangedCardTypes(final long timestamp) {
  4548.         for (int i = 0; i < this.changedCardTypes.size(); i++) {
  4549.             final CardType cardT = this.changedCardTypes.get(i);
  4550.             if (cardT.getTimestamp() == timestamp) {
  4551.                 this.changedCardTypes.remove(cardT);
  4552.             }
  4553.         }
  4554.     }
  4555.  
  4556.     /**
  4557.      * <p>
  4558.      * clearAllTypes.
  4559.      * </p>
  4560.      *
  4561.      * @return a {@link java.util.ArrayList} object.
  4562.      */
  4563.     public final ArrayList<String> clearAllTypes() {
  4564.         final ArrayList<String> originalTypes = new ArrayList<String>();
  4565.         originalTypes.addAll(this.getCharacteristics().getType());
  4566.         this.getCharacteristics().getType().clear();
  4567.         return originalTypes;
  4568.     }
  4569.  
  4570.     /**
  4571.      * <p>
  4572.      * Setter for the field <code>prevType</code>.
  4573.      * </p>
  4574.      *
  4575.      * @param a
  4576.      *            a {@link java.util.ArrayList} object.
  4577.      */
  4578.     public final void setPrevType(final ArrayList<String> a) {
  4579.         this.prevType = new ArrayList<String>(a);
  4580.     }
  4581.  
  4582.     /**
  4583.      * <p>
  4584.      * addPrevType.
  4585.      * </p>
  4586.      *
  4587.      * @param a
  4588.      *            a {@link java.lang.String} object.
  4589.      */
  4590.     public final void addPrevType(final String a) {
  4591.         this.prevType.add(a);
  4592.     }
  4593.  
  4594.     /**
  4595.      * <p>
  4596.      * removePrevType.
  4597.      * </p>
  4598.      *
  4599.      * @param a
  4600.      *            a {@link java.lang.String} object.
  4601.      */
  4602.     public final void removePrevType(final String a) {
  4603.         this.prevType.remove(a);
  4604.     }
  4605.  
  4606.     /**
  4607.      * <p>
  4608.      * Getter for the field <code>prevType</code>.
  4609.      * </p>
  4610.      *
  4611.      * @return a {@link java.util.ArrayList} object.
  4612.      */
  4613.     public final ArrayList<String> getPrevType() {
  4614.         return new ArrayList<String>(this.prevType);
  4615.     }
  4616.  
  4617.     // values that are printed on card
  4618.     /**
  4619.      * <p>
  4620.      * Getter for the field <code>baseLoyalty</code>.
  4621.      * </p>
  4622.      *
  4623.      * @return a int.
  4624.      */
  4625.     public final int getBaseLoyalty() {
  4626.         return this.baseLoyalty;
  4627.     }
  4628.  
  4629.     // values that are printed on card
  4630.     /**
  4631.      * <p>
  4632.      * Setter for the field <code>baseLoyalty</code>.
  4633.      * </p>
  4634.      *
  4635.      * @param n
  4636.      *            a int.
  4637.      */
  4638.     public final void setBaseLoyalty(final int n) {
  4639.         this.baseLoyalty = n;
  4640.     }
  4641.  
  4642.     // values that are printed on card
  4643.     /**
  4644.      * <p>
  4645.      * Getter for the field <code>baseAttack</code>.
  4646.      * </p>
  4647.      *
  4648.      * @return a int.
  4649.      */
  4650.     public final int getBaseAttack() {
  4651.         return this.getCharacteristics().getBaseAttack();
  4652.     }
  4653.  
  4654.     /**
  4655.      * <p>
  4656.      * Getter for the field <code>baseDefense</code>.
  4657.      * </p>
  4658.      *
  4659.      * @return a int.
  4660.      */
  4661.     public final int getBaseDefense() {
  4662.         return this.getCharacteristics().getBaseDefense();
  4663.     }
  4664.  
  4665.     // values that are printed on card
  4666.     /**
  4667.      * <p>
  4668.      * Setter for the field <code>baseAttack</code>.
  4669.      * </p>
  4670.      *
  4671.      * @param n
  4672.      *            a int.
  4673.      */
  4674.     public final void setBaseAttack(final int n) {
  4675.         this.getCharacteristics().setBaseAttack(n);
  4676.     }
  4677.  
  4678.     /**
  4679.      * <p>
  4680.      * Setter for the field <code>baseDefense</code>.
  4681.      * </p>
  4682.      *
  4683.      * @param n
  4684.      *            a int.
  4685.      */
  4686.     public final void setBaseDefense(final int n) {
  4687.         this.getCharacteristics().setBaseDefense(n);
  4688.     }
  4689.  
  4690.     // values that are printed on card
  4691.     /**
  4692.      * <p>
  4693.      * Getter for the field <code>baseAttackString</code>.
  4694.      * </p>
  4695.      *
  4696.      * @return a {@link java.lang.String} object.
  4697.      */
  4698.     public final String getBaseAttackString() {
  4699.         return (null == this.baseAttackString) ? "" + this.getBaseAttack() : this.baseAttackString;
  4700.     }
  4701.  
  4702.     /**
  4703.      * <p>
  4704.      * Getter for the field <code>baseDefenseString</code>.
  4705.      * </p>
  4706.      *
  4707.      * @return a {@link java.lang.String} object.
  4708.      */
  4709.     public final String getBaseDefenseString() {
  4710.         return (null == this.baseDefenseString) ? "" + this.getBaseDefense() : this.baseDefenseString;
  4711.     }
  4712.  
  4713.     // values that are printed on card
  4714.     /**
  4715.      * <p>
  4716.      * Setter for the field <code>baseAttackString</code>.
  4717.      * </p>
  4718.      *
  4719.      * @param s
  4720.      *            a {@link java.lang.String} object.
  4721.      */
  4722.     public final void setBaseAttackString(final String s) {
  4723.         this.baseAttackString = s;
  4724.     }
  4725.  
  4726.     /**
  4727.      * <p>
  4728.      * Setter for the field <code>baseDefenseString</code>.
  4729.      * </p>
  4730.      *
  4731.      * @param s
  4732.      *            a {@link java.lang.String} object.
  4733.      */
  4734.     public final void setBaseDefenseString(final String s) {
  4735.         this.baseDefenseString = s;
  4736.     }
  4737.  
  4738.     /**
  4739.      *
  4740.      * TODO Write javadoc for this method.
  4741.      *
  4742.      * @param pt
  4743.      *            ArrayList<CardPowerToughness>
  4744.      */
  4745.     public final void setNewPT(final ArrayList<CardPowerToughness> pt) {
  4746.         this.newPT = pt;
  4747.     }
  4748.  
  4749.     /**
  4750.      *
  4751.      * TODO Write javadoc for this method.
  4752.      *
  4753.      * @return ArrayList<CardPowerToughness>
  4754.      */
  4755.     public final ArrayList<CardPowerToughness> getNewPT() {
  4756.         return this.newPT;
  4757.     }
  4758.  
  4759.     /**
  4760.      *
  4761.      * TODO Write javadoc for this method.
  4762.      *
  4763.      * @return int
  4764.      */
  4765.     public final int getSetPower() {
  4766.         if (this.newPT.isEmpty()) {
  4767.             return -1;
  4768.         }
  4769.  
  4770.         final CardPowerToughness latestPT = this.getLatestPT();
  4771.  
  4772.         return latestPT.getPower();
  4773.     }
  4774.  
  4775.     /**
  4776.      *
  4777.      * TODO Write javadoc for this method.
  4778.      *
  4779.      * @return int
  4780.      */
  4781.     public final int getSetToughness() {
  4782.         if (this.newPT.isEmpty()) {
  4783.             return -1;
  4784.         }
  4785.  
  4786.         final CardPowerToughness latestPT = this.getLatestPT();
  4787.  
  4788.         return latestPT.getToughness();
  4789.     }
  4790.  
  4791.     /**
  4792.      *
  4793.      * TODO Write javadoc for this method.
  4794.      *
  4795.      * @return CardPowerToughness
  4796.      */
  4797.     public final CardPowerToughness getLatestPT() {
  4798.         CardPowerToughness latestPT = new CardPowerToughness(-1, -1, 0);
  4799.         long max = 0;
  4800.  
  4801.         for (final CardPowerToughness pt : this.newPT) {
  4802.             if (pt.getTimestamp() >= max) {
  4803.                 max = pt.getTimestamp();
  4804.                 latestPT = pt;
  4805.             }
  4806.         }
  4807.  
  4808.         return latestPT;
  4809.     }
  4810.  
  4811.     /**
  4812.      *
  4813.      * TODO Write javadoc for this method.
  4814.      *
  4815.      * @param power
  4816.      *            int
  4817.      * @param toughness
  4818.      *            int
  4819.      * @param timestamp
  4820.      *            int
  4821.      */
  4822.     public final void addNewPT(final int power, final int toughness, final long timestamp) {
  4823.         this.newPT.add(new CardPowerToughness(power, toughness, timestamp));
  4824.     }
  4825.  
  4826.     /**
  4827.      *
  4828.      * TODO Write javadoc for this method.
  4829.      *
  4830.      * @param timestamp
  4831.      *            long
  4832.      */
  4833.     public final void removeNewPT(final long timestamp) {
  4834.         for (int i = 0; i < this.newPT.size(); i++) {
  4835.             final CardPowerToughness cardPT = this.newPT.get(i);
  4836.             if (cardPT.getTimestamp() == timestamp) {
  4837.                 this.newPT.remove(cardPT);
  4838.             }
  4839.         }
  4840.     }
  4841.  
  4842.     /**
  4843.      *
  4844.      * TODO Write javadoc for this method.
  4845.      *
  4846.      * @return int
  4847.      */
  4848.     public final int getCurrentPower() {
  4849.         int total = this.getBaseAttack();
  4850.         final int setPower = this.getSetPower();
  4851.         if (setPower != -1) {
  4852.             total = setPower;
  4853.         }
  4854.  
  4855.         return total;
  4856.     }
  4857.  
  4858.     /**
  4859.      * <p>
  4860.      * getUnswitchedAttack.
  4861.      * </p>
  4862.      *
  4863.      * @return a int.
  4864.      */
  4865.     public final int getUnswitchedAttack() {
  4866.         int total = this.getCurrentPower();
  4867.  
  4868.         total += ((this.getTempAttackBoost() + this.getSemiPermanentAttackBoost() + this.getCounters(Counters.P1P1)
  4869.                 + this.getCounters(Counters.P1P2) + this.getCounters(Counters.P1P0)) - this.getCounters(Counters.M1M1))
  4870.                 + ((2 * this.getCounters(Counters.P2P2)) - (2 * this.getCounters(Counters.M2M1))
  4871.                         - (2 * this.getCounters(Counters.M2M2)) - this.getCounters(Counters.M1M0));
  4872.         return total;
  4873.     }
  4874.  
  4875.     /**
  4876.      * <p>
  4877.      * getNetAttack.
  4878.      * </p>
  4879.      *
  4880.      * @return a int.
  4881.      */
  4882.     public final int getNetAttack() {
  4883.         if ((this.getAmountOfKeyword("CARDNAME's power and toughness are switched") % 2) != 0) {
  4884.             return this.getUnswitchedDefense();
  4885.         } else {
  4886.             return this.getUnswitchedAttack();
  4887.         }
  4888.     }
  4889.  
  4890.     /**
  4891.      *
  4892.      * TODO Write javadoc for this method.
  4893.      *
  4894.      * @return an int
  4895.      */
  4896.     public final int getCurrentToughness() {
  4897.         int total = this.getBaseDefense();
  4898.  
  4899.         final int setToughness = this.getSetToughness();
  4900.         if (setToughness != -1) {
  4901.             total = setToughness;
  4902.         }
  4903.  
  4904.         return total;
  4905.     }
  4906.  
  4907.     /**
  4908.      * <p>
  4909.      * getUnswitchedDefense.
  4910.      * </p>
  4911.      *
  4912.      * @return a int.
  4913.      */
  4914.     public final int getUnswitchedDefense() {
  4915.         int total = this.getCurrentToughness();
  4916.  
  4917.         total += (((((this.getTempDefenseBoost() + this.getSemiPermanentDefenseBoost()
  4918.                 + this.getCounters(Counters.P1P1) + (2 * this.getCounters(Counters.P1P2))) - this
  4919.                 .getCounters(Counters.M1M1)) + this.getCounters(Counters.P0P1)) - (2 * this.getCounters(Counters.M0M2))) + (2 * this
  4920.                 .getCounters(Counters.P2P2)))
  4921.                 - this.getCounters(Counters.M0M1)
  4922.                 - this.getCounters(Counters.M2M1)
  4923.                 - (2 * this.getCounters(Counters.M2M2));
  4924.         return total;
  4925.     }
  4926.  
  4927.     /**
  4928.      * <p>
  4929.      * getNetDefense.
  4930.      * </p>
  4931.      *
  4932.      * @return a int.
  4933.      */
  4934.     public final int getNetDefense() {
  4935.         if ((this.getAmountOfKeyword("CARDNAME's power and toughness are switched") % 2) != 0) {
  4936.             return this.getUnswitchedAttack();
  4937.         } else {
  4938.             return this.getUnswitchedDefense();
  4939.         }
  4940.     }
  4941.  
  4942.     // How much combat damage does the card deal
  4943.     /**
  4944.      * <p>
  4945.      * getNetCombatDamage.
  4946.      * </p>
  4947.      *
  4948.      * @return a int.
  4949.      */
  4950.     public final int getNetCombatDamage() {
  4951.         if (this.hasKeyword("CARDNAME assigns no combat damage")) {
  4952.             return 0;
  4953.         }
  4954.  
  4955.         if (AllZoneUtil.isCardInPlay("Doran, the Siege Tower")) {
  4956.             return this.getNetDefense();
  4957.         }
  4958.         return this.getNetAttack();
  4959.     }
  4960.  
  4961.     /**
  4962.      * <p>
  4963.      * Setter for the field <code>randomPicture</code>.
  4964.      * </p>
  4965.      *
  4966.      * @param n
  4967.      *            a int.
  4968.      */
  4969.     public final void setRandomPicture(final int n) {
  4970.         this.randomPicture = n;
  4971.     }
  4972.  
  4973.     /**
  4974.      * <p>
  4975.      * Getter for the field <code>randomPicture</code>.
  4976.      * </p>
  4977.      *
  4978.      * @return a int.
  4979.      */
  4980.     public final int getRandomPicture() {
  4981.         return this.randomPicture;
  4982.     }
  4983.  
  4984.     /**
  4985.      * <p>
  4986.      * addMultiKickerMagnitude.
  4987.      * </p>
  4988.      *
  4989.      * @param n
  4990.      *            a int.
  4991.      */
  4992.     public final void addMultiKickerMagnitude(final int n) {
  4993.         this.multiKickerMagnitude += n;
  4994.     }
  4995.  
  4996.     /**
  4997.      * <p>
  4998.      * Setter for the field <code>multiKickerMagnitude</code>.
  4999.      * </p>
  5000.      *
  5001.      * @param n
  5002.      *            a int.
  5003.      */
  5004.     public final void setMultiKickerMagnitude(final int n) {
  5005.         this.multiKickerMagnitude = n;
  5006.     }
  5007.  
  5008.     /**
  5009.      * <p>
  5010.      * Getter for the field <code>multiKickerMagnitude</code>.
  5011.      * </p>
  5012.      *
  5013.      * @return a int.
  5014.      */
  5015.     public final int getMultiKickerMagnitude() {
  5016.         return this.multiKickerMagnitude;
  5017.     }
  5018.  
  5019.     /**
  5020.      * <p>
  5021.      * addReplicateMagnitude.
  5022.      * </p>
  5023.      *
  5024.      * @param n
  5025.      *            a int.
  5026.      */
  5027.     public final void addReplicateMagnitude(final int n) {
  5028.         this.replicateMagnitude += n;
  5029.     }
  5030.  
  5031.     /**
  5032.      * <p>
  5033.      * Setter for the field <code>replicateMagnitude</code>.
  5034.      * </p>
  5035.      *
  5036.      * @param n
  5037.      *            a int.
  5038.      */
  5039.     public final void setReplicateMagnitude(final int n) {
  5040.         this.replicateMagnitude = n;
  5041.     }
  5042.  
  5043.     /**
  5044.      * <p>
  5045.      * Getter for the field <code>replicateMagnitude</code>.
  5046.      * </p>
  5047.      *
  5048.      * @return a int.
  5049.      */
  5050.     public final int getReplicateMagnitude() {
  5051.         return this.replicateMagnitude;
  5052.     }
  5053.  
  5054.     // for cards like Giant Growth, etc.
  5055.     /**
  5056.      * <p>
  5057.      * Getter for the field <code>tempAttackBoost</code>.
  5058.      * </p>
  5059.      *
  5060.      * @return a int.
  5061.      */
  5062.     public final int getTempAttackBoost() {
  5063.         return this.tempAttackBoost;
  5064.     }
  5065.  
  5066.     /**
  5067.      * <p>
  5068.      * Getter for the field <code>tempDefenseBoost</code>.
  5069.      * </p>
  5070.      *
  5071.      * @return a int.
  5072.      */
  5073.     public final int getTempDefenseBoost() {
  5074.         return this.tempDefenseBoost;
  5075.     }
  5076.  
  5077.     /**
  5078.      * <p>
  5079.      * addTempAttackBoost.
  5080.      * </p>
  5081.      *
  5082.      * @param n
  5083.      *            a int.
  5084.      */
  5085.     public final void addTempAttackBoost(final int n) {
  5086.         this.tempAttackBoost += n;
  5087.     }
  5088.  
  5089.     /**
  5090.      * <p>
  5091.      * addTempDefenseBoost.
  5092.      * </p>
  5093.      *
  5094.      * @param n
  5095.      *            a int.
  5096.      */
  5097.     public final void addTempDefenseBoost(final int n) {
  5098.         this.tempDefenseBoost += n;
  5099.     }
  5100.  
  5101.     /**
  5102.      * <p>
  5103.      * Setter for the field <code>tempAttackBoost</code>.
  5104.      * </p>
  5105.      *
  5106.      * @param n
  5107.      *            a int.
  5108.      */
  5109.     public final void setTempAttackBoost(final int n) {
  5110.         this.tempAttackBoost = n;
  5111.     }
  5112.  
  5113.     /**
  5114.      * <p>
  5115.      * Setter for the field <code>tempDefenseBoost</code>.
  5116.      * </p>
  5117.      *
  5118.      * @param n
  5119.      *            a int.
  5120.      */
  5121.     public final void setTempDefenseBoost(final int n) {
  5122.         this.tempDefenseBoost = n;
  5123.     }
  5124.  
  5125.     // for cards like Glorious Anthem, etc.
  5126.     /**
  5127.      * <p>
  5128.      * Getter for the field <code>semiPermanentAttackBoost</code>.
  5129.      * </p>
  5130.      *
  5131.      * @return a int.
  5132.      */
  5133.     public final int getSemiPermanentAttackBoost() {
  5134.         return this.semiPermanentAttackBoost;
  5135.     }
  5136.  
  5137.     /**
  5138.      * <p>
  5139.      * Getter for the field <code>semiPermanentDefenseBoost</code>.
  5140.      * </p>
  5141.      *
  5142.      * @return a int.
  5143.      */
  5144.     public final int getSemiPermanentDefenseBoost() {
  5145.         return this.semiPermanentDefenseBoost;
  5146.     }
  5147.  
  5148.     /**
  5149.      * <p>
  5150.      * addSemiPermanentAttackBoost.
  5151.      * </p>
  5152.      *
  5153.      * @param n
  5154.      *            a int.
  5155.      */
  5156.     public final void addSemiPermanentAttackBoost(final int n) {
  5157.         this.semiPermanentAttackBoost += n;
  5158.     }
  5159.  
  5160.     /**
  5161.      * <p>
  5162.      * addSemiPermanentDefenseBoost.
  5163.      * </p>
  5164.      *
  5165.      * @param n
  5166.      *            a int.
  5167.      */
  5168.     public final void addSemiPermanentDefenseBoost(final int n) {
  5169.         this.semiPermanentDefenseBoost += n;
  5170.     }
  5171.  
  5172.     /**
  5173.      * <p>
  5174.      * Setter for the field <code>semiPermanentAttackBoost</code>.
  5175.      * </p>
  5176.      *
  5177.      * @param n
  5178.      *            a int.
  5179.      */
  5180.     public final void setSemiPermanentAttackBoost(final int n) {
  5181.         this.semiPermanentAttackBoost = n;
  5182.     }
  5183.  
  5184.     /**
  5185.      * <p>
  5186.      * Setter for the field <code>semiPermanentDefenseBoost</code>.
  5187.      * </p>
  5188.      *
  5189.      * @param n
  5190.      *            a int.
  5191.      */
  5192.     public final void setSemiPermanentDefenseBoost(final int n) {
  5193.         this.semiPermanentDefenseBoost = n;
  5194.     }
  5195.  
  5196.     /**
  5197.      * <p>
  5198.      * isUntapped.
  5199.      * </p>
  5200.      *
  5201.      * @return a boolean.
  5202.      */
  5203.     public final boolean isUntapped() {
  5204.         return !this.tapped;
  5205.     }
  5206.  
  5207.     /**
  5208.      * <p>
  5209.      * isTapped.
  5210.      * </p>
  5211.      *
  5212.      * @return a boolean.
  5213.      */
  5214.     public final boolean isTapped() {
  5215.         return this.tapped;
  5216.     }
  5217.  
  5218.     /**
  5219.      * <p>
  5220.      * Setter for the field <code>tapped</code>.
  5221.      * </p>
  5222.      *
  5223.      * @param b
  5224.      *            a boolean.
  5225.      */
  5226.     public final void setTapped(final boolean b) {
  5227.         this.tapped = b;
  5228.         this.updateObservers();
  5229.     }
  5230.  
  5231.     /**
  5232.      * <p>
  5233.      * tap.
  5234.      * </p>
  5235.      */
  5236.     public final void tap() {
  5237.         if (this.isUntapped()) {
  5238.             // Run triggers
  5239.             final Map<String, Object> runParams = new TreeMap<String, Object>();
  5240.             runParams.put("Card", this);
  5241.             AllZone.getTriggerHandler().runTrigger("Taps", runParams);
  5242.         }
  5243.         this.setTapped(true);
  5244.     }
  5245.  
  5246.     /**
  5247.      * <p>
  5248.      * untap.
  5249.      * </p>
  5250.      */
  5251.     public final void untap() {
  5252.         if (this.isTapped()) {
  5253.             // Run triggers
  5254.             final Map<String, Object> runParams = new TreeMap<String, Object>();
  5255.             runParams.put("Card", this);
  5256.             AllZone.getTriggerHandler().runTrigger("Untaps", runParams);
  5257.  
  5258.         }
  5259.  
  5260.         for (final Command var : this.untapCommandList) {
  5261.             var.execute();
  5262.         }
  5263.  
  5264.         this.setTapped(false);
  5265.     }
  5266.  
  5267.     // keywords are like flying, fear, first strike, etc...
  5268.     /**
  5269.      * <p>
  5270.      * getKeyword.
  5271.      * </p>
  5272.      *
  5273.      * @return a {@link java.util.ArrayList} object.
  5274.      */
  5275.     public final ArrayList<String> getKeyword() {
  5276.         final ArrayList<String> keywords = this.getUnhiddenKeyword();
  5277.         final ArrayList<String> a4 = new ArrayList<String>(this.getHiddenExtrinsicKeyword());
  5278.         keywords.addAll(a4);
  5279.  
  5280.         return keywords;
  5281.     }
  5282.  
  5283.     /**
  5284.      * Gets the keyword amount.
  5285.      *
  5286.      * @param keyword
  5287.      *            the keyword
  5288.      * @return the keyword amount
  5289.      */
  5290.     public final int getKeywordAmount(final String keyword) {
  5291.         int res = 0;
  5292.         for (final String k : this.getKeyword()) {
  5293.             if (k.equals(keyword)) {
  5294.                 res++;
  5295.             }
  5296.         }
  5297.  
  5298.         return res;
  5299.     }
  5300.  
  5301.     /**
  5302.      * Sets the changed card keywords.
  5303.      *
  5304.      * @param kw
  5305.      *            the new changed card keywords
  5306.      */
  5307.     public final void setChangedCardKeywords(final ArrayList<CardKeywords> kw) {
  5308.         this.changedCardKeywords = kw;
  5309.     }
  5310.  
  5311.     /**
  5312.      * Gets the changed card keywords.
  5313.      *
  5314.      * @return the changed card keywords
  5315.      */
  5316.     public final ArrayList<CardKeywords> getChangedCardKeywords() {
  5317.         return this.changedCardKeywords;
  5318.     }
  5319.  
  5320.     /**
  5321.      * Adds the changed card keywords.
  5322.      *
  5323.      * @param keywords
  5324.      *            the keywords
  5325.      * @param removeKeywords
  5326.      *            the remove keywords
  5327.      * @param removeAllKeywords
  5328.      *            the remove all keywords
  5329.      * @param timestamp
  5330.      *            the timestamp
  5331.      */
  5332.     public final void addChangedCardKeywords(final ArrayList<String> keywords, final ArrayList<String> removeKeywords,
  5333.             final boolean removeAllKeywords, final long timestamp) {
  5334.  
  5335.         this.changedCardKeywords.add(new CardKeywords(keywords, removeKeywords, removeAllKeywords, timestamp));
  5336.     }
  5337.  
  5338.     /**
  5339.      * Adds the changed card keywords.
  5340.      *
  5341.      * @param keywords
  5342.      *            the keywords
  5343.      * @param removeKeywords
  5344.      *            the remove keywords
  5345.      * @param removeAllKeywords
  5346.      *            the remove all keywords
  5347.      * @param timestamp
  5348.      *            the timestamp
  5349.      */
  5350.     public final void addChangedCardKeywords(final String[] keywords, final String[] removeKeywords,
  5351.             final boolean removeAllKeywords, final long timestamp) {
  5352.         ArrayList<String> keywordsList = null;
  5353.         ArrayList<String> removeKeywordsList = null;
  5354.         if (keywords != null) {
  5355.             keywordsList = new ArrayList<String>(Arrays.asList(keywords));
  5356.         }
  5357.  
  5358.         if (removeKeywords != null) {
  5359.             removeKeywordsList = new ArrayList<String>(Arrays.asList(removeKeywords));
  5360.         }
  5361.  
  5362.         this.addChangedCardKeywords(keywordsList, removeKeywordsList, removeAllKeywords, timestamp);
  5363.     }
  5364.  
  5365.     /**
  5366.      * Removes the changed card keywords.
  5367.      *
  5368.      * @param timestamp
  5369.      *            the timestamp
  5370.      */
  5371.     public final void removeChangedCardKeywords(final long timestamp) {
  5372.         for (int i = 0; i < this.changedCardKeywords.size(); i++) {
  5373.             final CardKeywords cardK = this.changedCardKeywords.get(i);
  5374.             if (cardK.getTimestamp() == timestamp) {
  5375.                 this.changedCardKeywords.remove(cardK);
  5376.             }
  5377.         }
  5378.     }
  5379.  
  5380.     // Hidden keywords will be left out
  5381.     /**
  5382.      * <p>
  5383.      * getUnhiddenKeyword.
  5384.      * </p>
  5385.      *
  5386.      * @return a {@link java.util.ArrayList} object.
  5387.      */
  5388.     public final ArrayList<String> getUnhiddenKeyword() {
  5389.         final ArrayList<String> keywords = new ArrayList<String>(this.getIntrinsicKeyword());
  5390.         final ArrayList<String> a2 = new ArrayList<String>(this.getExtrinsicKeyword());
  5391.         keywords.addAll(a2);
  5392.  
  5393.         // see if keyword changes are in effect
  5394.         if (!this.changedCardKeywords.isEmpty()) {
  5395.  
  5396.             final ArrayList<CardKeywords> newKeywords = this.changedCardKeywords;
  5397.             Collections.sort(newKeywords); // sorts newKeywords by timeStamp
  5398.  
  5399.             for (final CardKeywords ck : newKeywords) {
  5400.  
  5401.                 if (ck.isRemoveAllKeywords()) {
  5402.                     keywords.clear();
  5403.                 } else if (ck.getRemoveKeywords() != null) {
  5404.                     keywords.removeAll(ck.getRemoveKeywords());
  5405.                 }
  5406.  
  5407.                 if (ck.getKeywords() != null) {
  5408.                     keywords.addAll(ck.getKeywords());
  5409.                 }
  5410.  
  5411.             }
  5412.         }
  5413.  
  5414.         return keywords;
  5415.     }
  5416.  
  5417.     /**
  5418.      * <p>
  5419.      * getIntrinsicAbilities.
  5420.      * </p>
  5421.      *
  5422.      * @return a {@link java.util.ArrayList} object.
  5423.      */
  5424.     public final ArrayList<String> getIntrinsicAbilities() {
  5425.         return this.getCharacteristics().getIntrinsicAbility();
  5426.     }
  5427.  
  5428.     /**
  5429.      * <p>
  5430.      * Getter for the field <code>intrinsicKeyword</code>.
  5431.      * </p>
  5432.      *
  5433.      * @return a {@link java.util.ArrayList} object.
  5434.      */
  5435.     public final ArrayList<String> getIntrinsicKeyword() {
  5436.         return new ArrayList<String>(this.getCharacteristics().getIntrinsicKeyword());
  5437.     }
  5438.  
  5439.     /**
  5440.      * <p>
  5441.      * clearIntrinsicKeyword.
  5442.      * </p>
  5443.      */
  5444.     public final void clearIntrinsicKeyword() {
  5445.         this.getCharacteristics().getIntrinsicKeyword().clear();
  5446.     }
  5447.  
  5448.     /**
  5449.      * <p>
  5450.      * Setter for the field <code>intrinsicKeyword</code>.
  5451.      * </p>
  5452.      *
  5453.      * @param a
  5454.      *            a {@link java.util.ArrayList} object.
  5455.      */
  5456.     public final void setIntrinsicKeyword(final ArrayList<String> a) {
  5457.         this.getCharacteristics().setIntrinsicKeyword(new ArrayList<String>(a));
  5458.     }
  5459.  
  5460.     /**
  5461.      * <p>
  5462.      * clearAllKeywords.
  5463.      * </p>
  5464.      */
  5465.     public final void clearAllKeywords() {
  5466.         this.getCharacteristics().getIntrinsicKeyword().clear();
  5467.         this.extrinsicKeyword.clear();
  5468.         // Hidden keywords won't be displayed on the card
  5469.         this.hiddenExtrinsicKeyword.clear();
  5470.     }
  5471.  
  5472.     /**
  5473.      * <p>
  5474.      * setIntrinsicAbilities.
  5475.      * </p>
  5476.      *
  5477.      * @param a
  5478.      *            a {@link java.util.ArrayList} object.
  5479.      */
  5480.     public final void setIntrinsicAbilities(final ArrayList<String> a) {
  5481.         this.getCharacteristics().setIntrinsicAbility(new ArrayList<String>(a));
  5482.     }
  5483.  
  5484.     /**
  5485.      * <p>
  5486.      * addIntrinsicKeyword.
  5487.      * </p>
  5488.      *
  5489.      * @param s
  5490.      *            a {@link java.lang.String} object.
  5491.      */
  5492.     public final void addIntrinsicKeyword(final String s) {
  5493.         if (s.trim().length() != 0) {
  5494.             this.getCharacteristics().getIntrinsicKeyword().add(s);
  5495.             // intrinsicKeyword.add((getName().trim().length()== 0 ? s
  5496.             // :s.replaceAll(getName(), "CARDNAME")));
  5497.         }
  5498.     }
  5499.  
  5500.     /**
  5501.      * <p>
  5502.      * addIntrinsicAbility.
  5503.      * </p>
  5504.      *
  5505.      * @param s
  5506.      *            a {@link java.lang.String} object.
  5507.      */
  5508.     public final void addIntrinsicAbility(final String s) {
  5509.         if (s.trim().length() != 0) {
  5510.             this.getCharacteristics().getIntrinsicAbility().add(s);
  5511.         }
  5512.     }
  5513.  
  5514.     /**
  5515.      * <p>
  5516.      * addNonStackingIntrinsicKeyword.
  5517.      * </p>
  5518.      *
  5519.      * @param s
  5520.      *            a {@link java.lang.String} object.
  5521.      */
  5522.     public final void addNonStackingIntrinsicKeyword(final String s) {
  5523.         if (!this.getIntrinsicKeyword().contains(s) && (s.trim().length() != 0)) {
  5524.             this.getCharacteristics().getIntrinsicKeyword()
  5525.                     .add((this.getName().trim().length() == 0 ? s : s.replaceAll(this.getName(), "CARDNAME")));
  5526.         }
  5527.     }
  5528.  
  5529.     /**
  5530.      * <p>
  5531.      * removeIntrinsicKeyword.
  5532.      * </p>
  5533.      *
  5534.      * @param s
  5535.      *            a {@link java.lang.String} object.
  5536.      */
  5537.     public final void removeIntrinsicKeyword(final String s) {
  5538.         this.getCharacteristics().getIntrinsicKeyword().remove(s);
  5539.     }
  5540.  
  5541.     /**
  5542.      * <p>
  5543.      * getIntrinsicKeywordSize.
  5544.      * </p>
  5545.      *
  5546.      * @return a int.
  5547.      */
  5548.     public final int getIntrinsicKeywordSize() {
  5549.         return this.getCharacteristics().getIntrinsicKeyword().size();
  5550.     }
  5551.  
  5552.     /**
  5553.      * <p>
  5554.      * Getter for the field <code>extrinsicKeyword</code>.
  5555.      * </p>
  5556.      *
  5557.      * @return a {@link java.util.ArrayList} object.
  5558.      */
  5559.     public ArrayList<String> getExtrinsicKeyword() {
  5560.         return new ArrayList<String>(this.extrinsicKeyword);
  5561.     }
  5562.  
  5563.     /**
  5564.      * <p>
  5565.      * Setter for the field <code>extrinsicKeyword</code>.
  5566.      * </p>
  5567.      *
  5568.      * @param a
  5569.      *            a {@link java.util.ArrayList} object.
  5570.      */
  5571.     public final void setExtrinsicKeyword(final ArrayList<String> a) {
  5572.         this.extrinsicKeyword = new ArrayList<String>(a);
  5573.     }
  5574.  
  5575.     /**
  5576.      * <p>
  5577.      * addExtrinsicKeyword.
  5578.      * </p>
  5579.      *
  5580.      * @param s
  5581.      *            a {@link java.lang.String} object.
  5582.      */
  5583.     public void addExtrinsicKeyword(final String s) {
  5584.         // if(!hasKeyword(s)){
  5585.         if (s.startsWith("HIDDEN")) {
  5586.             this.addHiddenExtrinsicKeyword(s);
  5587.         } else {
  5588.             this.extrinsicKeyword.add(s);
  5589.             // extrinsicKeyword.add((getName().trim().length()==0 ? s
  5590.             // :s.replaceAll(getName(), "CARDNAME")));
  5591.             // }
  5592.         }
  5593.     }
  5594.  
  5595.     /**
  5596.      * <p>
  5597.      * addStackingExtrinsicKeyword.
  5598.      * </p>
  5599.      *
  5600.      * @param s
  5601.      *            a {@link java.lang.String} object.
  5602.      */
  5603.     public final void addStackingExtrinsicKeyword(final String s) {
  5604.         if (s.startsWith("HIDDEN")) {
  5605.             this.addHiddenExtrinsicKeyword(s);
  5606.         } else {
  5607.             this.extrinsicKeyword.add(s);
  5608.         }
  5609.     }
  5610.  
  5611.     /**
  5612.      * <p>
  5613.      * removeExtrinsicKeyword.
  5614.      * </p>
  5615.      *
  5616.      * @param s
  5617.      *            a {@link java.lang.String} object.
  5618.      */
  5619.     public void removeExtrinsicKeyword(final String s) {
  5620.         if (s.startsWith("HIDDEN")) {
  5621.             this.removeHiddenExtrinsicKeyword(s);
  5622.         } else {
  5623.             this.extrinsicKeyword.remove(s);
  5624.         }
  5625.     }
  5626.  
  5627.     /**
  5628.      * Removes the all extrinsic keyword.
  5629.      *
  5630.      * @param s
  5631.      *            the s
  5632.      */
  5633.     public void removeAllExtrinsicKeyword(final String s) {
  5634.         final ArrayList<String> strings = new ArrayList<String>();
  5635.         strings.add(s);
  5636.         if (s.startsWith("HIDDEN")) {
  5637.             this.hiddenExtrinsicKeyword.removeAll(strings);
  5638.         } else {
  5639.             this.extrinsicKeyword.removeAll(strings);
  5640.         }
  5641.     }
  5642.  
  5643.     /**
  5644.      * <p>
  5645.      * getExtrinsicKeywordSize.
  5646.      * </p>
  5647.      *
  5648.      * @return a int.
  5649.      */
  5650.     public int getExtrinsicKeywordSize() {
  5651.         return this.extrinsicKeyword.size();
  5652.     }
  5653.  
  5654.     /**
  5655.      * <p>
  5656.      * Getter for the field <code>prevIntrinsicKeyword</code>.
  5657.      * </p>
  5658.      *
  5659.      * @return a {@link java.util.ArrayList} object.
  5660.      */
  5661.     public final ArrayList<String> getPrevIntrinsicKeyword() {
  5662.         return new ArrayList<String>(this.prevIntrinsicKeyword);
  5663.     }
  5664.  
  5665.     /**
  5666.      * <p>
  5667.      * Setter for the field <code>prevIntrinsicKeyword</code>.
  5668.      * </p>
  5669.      *
  5670.      * @param a
  5671.      *            a {@link java.util.ArrayList} object.
  5672.      */
  5673.     public final void setPrevIntrinsicKeyword(final ArrayList<String> a) {
  5674.         this.prevIntrinsicKeyword = new ArrayList<String>(a);
  5675.         this.updateObservers();
  5676.     }
  5677.  
  5678.     /**
  5679.      * <p>
  5680.      * addPrevIntrinsicKeyword.
  5681.      * </p>
  5682.      *
  5683.      * @param s
  5684.      *            a {@link java.lang.String} object.
  5685.      */
  5686.     public final void addPrevIntrinsicKeyword(final String s) {
  5687.         this.prevIntrinsicKeyword.add(s);
  5688.     }
  5689.  
  5690.     /**
  5691.      * <p>
  5692.      * removePrevIntrinsicKeyword.
  5693.      * </p>
  5694.      *
  5695.      * @param s
  5696.      *            a {@link java.lang.String} object.
  5697.      */
  5698.     public final void removePrevIntrinsicKeyword(final String s) {
  5699.         this.prevIntrinsicKeyword.remove(s);
  5700.         this.updateObservers();
  5701.     }
  5702.  
  5703.     /**
  5704.      * <p>
  5705.      * getPrevIntrinsicKeywordSize.
  5706.      * </p>
  5707.      *
  5708.      * @return a int.
  5709.      */
  5710.     public final int getPrevIntrinsicKeywordSize() {
  5711.         return this.prevIntrinsicKeyword.size();
  5712.     }
  5713.  
  5714.     // Hidden Keywords will be returned without the indicator HIDDEN
  5715.     /**
  5716.      * <p>
  5717.      * getHiddenExtrinsicKeyword.
  5718.      * </p>
  5719.      *
  5720.      * @return a {@link java.util.ArrayList} object.
  5721.      */
  5722.     public final ArrayList<String> getHiddenExtrinsicKeyword() {
  5723.         final ArrayList<String> keywords = new ArrayList<String>();
  5724.         for (int i = 0; i < this.hiddenExtrinsicKeyword.size(); i++) {
  5725.             final String keyword = this.hiddenExtrinsicKeyword.get(i);
  5726.             keywords.add(keyword.substring(7));
  5727.         }
  5728.         return keywords;
  5729.     }
  5730.  
  5731.     /**
  5732.      * <p>
  5733.      * addHiddenExtrinsicKeyword.
  5734.      * </p>
  5735.      *
  5736.      * @param s
  5737.      *            a {@link java.lang.String} object.
  5738.      */
  5739.     public final void addHiddenExtrinsicKeyword(final String s) {
  5740.         this.hiddenExtrinsicKeyword.add(s);
  5741.     }
  5742.  
  5743.     /**
  5744.      * <p>
  5745.      * removeHiddenExtrinsicKeyword.
  5746.      * </p>
  5747.      *
  5748.      * @param s
  5749.      *            a {@link java.lang.String} object.
  5750.      */
  5751.     public final void removeHiddenExtrinsicKeyword(final String s) {
  5752.         this.hiddenExtrinsicKeyword.remove(s);
  5753.         // this.updateObservers();
  5754.     }
  5755.  
  5756.     /**
  5757.      * <p>
  5758.      * setStaticAbilityStrings.
  5759.      * </p>
  5760.      *
  5761.      * @param a
  5762.      *            a {@link java.util.ArrayList} object.
  5763.      */
  5764.     public final void setStaticAbilityStrings(final ArrayList<String> a) {
  5765.         this.getCharacteristics().setStaticAbilityStrings(new ArrayList<String>(a));
  5766.     }
  5767.  
  5768.     /**
  5769.      * Gets the static ability strings.
  5770.      *
  5771.      * @return the static ability strings
  5772.      */
  5773.     public final ArrayList<String> getStaticAbilityStrings() {
  5774.         return this.getCharacteristics().getStaticAbilityStrings();
  5775.     }
  5776.  
  5777.     /**
  5778.      * <p>
  5779.      * addStaticAbilityStrings.
  5780.      * </p>
  5781.      *
  5782.      * @param s
  5783.      *            a {@link java.lang.String} object.
  5784.      */
  5785.     public final void addStaticAbilityString(final String s) {
  5786.         if (s.trim().length() != 0) {
  5787.             this.getCharacteristics().getStaticAbilityStrings().add(s);
  5788.         }
  5789.     }
  5790.  
  5791.     /**
  5792.      * Sets the static abilities.
  5793.      *
  5794.      * @param a
  5795.      *            the new static abilities
  5796.      */
  5797.     public final void setStaticAbilities(final ArrayList<StaticAbility> a) {
  5798.         this.getCharacteristics().setStaticAbilities(new ArrayList<StaticAbility>(a));
  5799.     }
  5800.  
  5801.     /**
  5802.      * Gets the static abilities.
  5803.      *
  5804.      * @return the static abilities
  5805.      */
  5806.     public final ArrayList<StaticAbility> getStaticAbilities() {
  5807.         return new ArrayList<StaticAbility>(this.getCharacteristics().getStaticAbilities());
  5808.     }
  5809.  
  5810.     /**
  5811.      * Adds the static ability.
  5812.      *
  5813.      * @param s
  5814.      *            the s
  5815.      */
  5816.     public final void addStaticAbility(final String s) {
  5817.  
  5818.         if (s.trim().length() != 0) {
  5819.             final StaticAbility stAb = new StaticAbility(s, this);
  5820.             this.getCharacteristics().getStaticAbilities().add(stAb);
  5821.         }
  5822.     }
  5823.  
  5824.     /**
  5825.      * <p>
  5826.      * isPermanent.
  5827.      * </p>
  5828.      *
  5829.      * @return a boolean.
  5830.      */
  5831.     public final boolean isPermanent() {
  5832.         return !(this.isInstant() || this.isSorcery() || this.isImmutable());
  5833.     }
  5834.  
  5835.     /**
  5836.      * <p>
  5837.      * isSpell.
  5838.      * </p>
  5839.      *
  5840.      * @return a boolean.
  5841.      */
  5842.     public final boolean isSpell() {
  5843.         return (this.isInstant() || this.isSorcery() || (this.isAura() && !AllZoneUtil.getCardsIn(Zone.Battlefield)
  5844.                 .contains(this)));
  5845.     }
  5846.  
  5847.     /**
  5848.      * <p>
  5849.      * isCreature.
  5850.      * </p>
  5851.      *
  5852.      * @return a boolean.
  5853.      */
  5854.     public final boolean isCreature() {
  5855.         return this.typeContains("Creature");
  5856.     }
  5857.  
  5858.     /**
  5859.      * <p>
  5860.      * isWall.
  5861.      * </p>
  5862.      *
  5863.      * @return a boolean.
  5864.      */
  5865.     public final boolean isWall() {
  5866.         return this.typeContains("Wall");
  5867.     }
  5868.  
  5869.     /**
  5870.      * <p>
  5871.      * isBasicLand.
  5872.      * </p>
  5873.      *
  5874.      * @return a boolean.
  5875.      */
  5876.     public final boolean isBasicLand() {
  5877.         return this.typeContains("Basic");
  5878.     }
  5879.  
  5880.     /**
  5881.      * <p>
  5882.      * isLand.
  5883.      * </p>
  5884.      *
  5885.      * @return a boolean.
  5886.      */
  5887.     public final boolean isLand() {
  5888.         return this.typeContains("Land");
  5889.     }
  5890.  
  5891.     /**
  5892.      * <p>
  5893.      * isSorcery.
  5894.      * </p>
  5895.      *
  5896.      * @return a boolean.
  5897.      */
  5898.     public final boolean isSorcery() {
  5899.         return this.typeContains("Sorcery");
  5900.     }
  5901.  
  5902.     /**
  5903.      * <p>
  5904.      * isInstant.
  5905.      * </p>
  5906.      *
  5907.      * @return a boolean.
  5908.      */
  5909.     public final boolean isInstant() {
  5910.         return this.typeContains("Instant");
  5911.     }
  5912.  
  5913.     /**
  5914.      * <p>
  5915.      * isArtifact.
  5916.      * </p>
  5917.      *
  5918.      * @return a boolean.
  5919.      */
  5920.     public final boolean isArtifact() {
  5921.         return this.typeContains("Artifact");
  5922.     }
  5923.  
  5924.     /**
  5925.      * <p>
  5926.      * isEquipment.
  5927.      * </p>
  5928.      *
  5929.      * @return a boolean.
  5930.      */
  5931.     public final boolean isEquipment() {
  5932.         return this.typeContains("Equipment");
  5933.     }
  5934.  
  5935.     /**
  5936.      * <p>
  5937.      * isPlaneswalker.
  5938.      * </p>
  5939.      *
  5940.      * @return a boolean.
  5941.      */
  5942.     public final boolean isPlaneswalker() {
  5943.         return this.typeContains("Planeswalker");
  5944.     }
  5945.  
  5946.     /**
  5947.      * <p>
  5948.      * isEmblem.
  5949.      * </p>
  5950.      *
  5951.      * @return a boolean.
  5952.      */
  5953.     public final boolean isEmblem() {
  5954.         return this.typeContains("Emblem");
  5955.     }
  5956.  
  5957.     /**
  5958.      * <p>
  5959.      * isTribal.
  5960.      * </p>
  5961.      *
  5962.      * @return a boolean.
  5963.      */
  5964.     public final boolean isTribal() {
  5965.         return this.typeContains("Tribal");
  5966.     }
  5967.  
  5968.     /**
  5969.      * <p>
  5970.      * isSnow.
  5971.      * </p>
  5972.      *
  5973.      * @return a boolean.
  5974.      */
  5975.     public final boolean isSnow() {
  5976.         return this.typeContains("Snow");
  5977.     }
  5978.  
  5979.     // global and local enchantments
  5980.     /**
  5981.      * <p>
  5982.      * isEnchantment.
  5983.      * </p>
  5984.      *
  5985.      * @return a boolean.
  5986.      */
  5987.     public final boolean isEnchantment() {
  5988.         return this.typeContains("Enchantment");
  5989.     }
  5990.  
  5991.     /**
  5992.      * <p>
  5993.      * isAura.
  5994.      * </p>
  5995.      *
  5996.      * @return a boolean.
  5997.      */
  5998.     public final boolean isAura() {
  5999.         return this.typeContains("Aura");
  6000.     }
  6001.  
  6002.     /**
  6003.      * <p>
  6004.      * isGlobalEnchantment.
  6005.      * </p>
  6006.      *
  6007.      * @return a boolean.
  6008.      */
  6009.     public final boolean isGlobalEnchantment() {
  6010.         return this.typeContains("Enchantment") && (!this.isAura());
  6011.     }
  6012.  
  6013.     private boolean typeContains(final String s) {
  6014.         final Iterator<?> it = this.getType().iterator();
  6015.         while (it.hasNext()) {
  6016.             if (it.next().toString().startsWith(s)) {
  6017.                 return true;
  6018.             }
  6019.         }
  6020.  
  6021.         return false;
  6022.     }
  6023.  
  6024.     /**
  6025.      * <p>
  6026.      * Setter for the field <code>uniqueNumber</code>.
  6027.      * </p>
  6028.      *
  6029.      * @param n
  6030.      *            a int.
  6031.      */
  6032.     public final void setUniqueNumber(final int n) {
  6033.         this.uniqueNumber = n;
  6034.         this.updateObservers();
  6035.     }
  6036.  
  6037.     /**
  6038.      * <p>
  6039.      * Getter for the field <code>uniqueNumber</code>.
  6040.      * </p>
  6041.      *
  6042.      * @return a int.
  6043.      */
  6044.     public final int getUniqueNumber() {
  6045.         return this.uniqueNumber;
  6046.     }
  6047.  
  6048.     /**
  6049.      * <p>
  6050.      * Setter for the field <code>value</code>.
  6051.      * </p>
  6052.      *
  6053.      * @param n
  6054.      *            a long.
  6055.      */
  6056.     public final void setValue(final long n) {
  6057.         this.value = n;
  6058.     }
  6059.  
  6060.     /**
  6061.      * <p>
  6062.      * Getter for the field <code>value</code>.
  6063.      * </p>
  6064.      *
  6065.      * @return a long.
  6066.      */
  6067.     public final long getValue() {
  6068.         return this.value;
  6069.     }
  6070.  
  6071.     /** {@inheritDoc} */
  6072.     @Override
  6073.     public final int compareTo(final Card that) {
  6074.         /*
  6075.          * Return a negative integer of this < that, a positive integer if this
  6076.          * > that, and zero otherwise.
  6077.          */
  6078.  
  6079.         if (that == null) {
  6080.             /*
  6081.              * "Here we can arbitrarily decide that all non-null Cards are
  6082.              * `greater than' null Cards. It doesn't really matter what we
  6083.              * return in this case, as long as it is consistent. I rather think
  6084.              * of null as being lowly." --Braids
  6085.              */
  6086.             return +1;
  6087.         } else if (this.getUniqueNumber() > that.getUniqueNumber()) {
  6088.             return +1;
  6089.         } else if (this.getUniqueNumber() < that.getUniqueNumber()) {
  6090.             return -1;
  6091.         } else {
  6092.             return 0;
  6093.         }
  6094.     }
  6095.  
  6096.     /** {@inheritDoc} */
  6097.     @Override
  6098.     public final boolean equals(final Object o) {
  6099.         if (o instanceof Card) {
  6100.             final Card c = (Card) o;
  6101.             final int a = this.getUniqueNumber();
  6102.             final int b = c.getUniqueNumber();
  6103.             return (a == b);
  6104.         }
  6105.         return false;
  6106.     }
  6107.  
  6108.     /** {@inheritDoc} */
  6109.     @Override
  6110.     public final int hashCode() {
  6111.         return this.getUniqueNumber();
  6112.     }
  6113.  
  6114.     /** {@inheritDoc} */
  6115.     @Override
  6116.     public final String toString() {
  6117.         return this.getName() + " (" + this.getUniqueNumber() + ")";
  6118.     }
  6119.  
  6120.     /**
  6121.      * <p>
  6122.      * hasUnearth.
  6123.      * </p>
  6124.      *
  6125.      * @return a boolean.
  6126.      */
  6127.     public final boolean hasUnearth() {
  6128.         return this.unearth;
  6129.     }
  6130.  
  6131.     /**
  6132.      * <p>
  6133.      * Setter for the field <code>unearth</code>.
  6134.      * </p>
  6135.      *
  6136.      * @param b
  6137.      *            a boolean.
  6138.      */
  6139.     public final void setUnearth(final boolean b) {
  6140.         this.unearth = b;
  6141.     }
  6142.  
  6143.     /**
  6144.      * <p>
  6145.      * isUnearthed.
  6146.      * </p>
  6147.      *
  6148.      * @return a boolean.
  6149.      */
  6150.     public final boolean isUnearthed() {
  6151.         return this.unearthed;
  6152.     }
  6153.  
  6154.     /**
  6155.      * <p>
  6156.      * Setter for the field <code>unearthed</code>.
  6157.      * </p>
  6158.      *
  6159.      * @param b
  6160.      *            a boolean.
  6161.      */
  6162.     public final void setUnearthed(final boolean b) {
  6163.         this.unearthed = b;
  6164.     }
  6165.  
  6166.     /**
  6167.      * <p>
  6168.      * hasMadness.
  6169.      * </p>
  6170.      *
  6171.      * @return a boolean.
  6172.      */
  6173.     public final boolean hasMadness() {
  6174.         return this.madness;
  6175.     }
  6176.  
  6177.     /**
  6178.      * <p>
  6179.      * Setter for the field <code>madness</code>.
  6180.      * </p>
  6181.      *
  6182.      * @param b
  6183.      *            a boolean.
  6184.      */
  6185.     public final void setMadness(final boolean b) {
  6186.         this.madness = b;
  6187.     }
  6188.  
  6189.     /**
  6190.      * <p>
  6191.      * Getter for the field <code>madnessCost</code>.
  6192.      * </p>
  6193.      *
  6194.      * @return a {@link java.lang.String} object.
  6195.      */
  6196.     public final String getMadnessCost() {
  6197.         return this.madnessCost;
  6198.     }
  6199.  
  6200.     /**
  6201.      * <p>
  6202.      * Setter for the field <code>madnessCost</code>.
  6203.      * </p>
  6204.      *
  6205.      * @param cost
  6206.      *            a {@link java.lang.String} object.
  6207.      */
  6208.     public final void setMadnessCost(final String cost) {
  6209.         this.madnessCost = cost;
  6210.     }
  6211.  
  6212.     /**
  6213.      * <p>
  6214.      * hasSuspend.
  6215.      * </p>
  6216.      *
  6217.      * @return a boolean.
  6218.      */
  6219.     public final boolean hasSuspend() {
  6220.         return this.suspend;
  6221.     }
  6222.  
  6223.     /**
  6224.      * <p>
  6225.      * Setter for the field <code>suspend</code>.
  6226.      * </p>
  6227.      *
  6228.      * @param b
  6229.      *            a boolean.
  6230.      */
  6231.     public final void setSuspend(final boolean b) {
  6232.         this.suspend = b;
  6233.     }
  6234.  
  6235.     /**
  6236.      * <p>
  6237.      * wasSuspendCast.
  6238.      * </p>
  6239.      *
  6240.      * @return a boolean.
  6241.      */
  6242.     public final boolean wasSuspendCast() {
  6243.         return this.suspendCast;
  6244.     }
  6245.  
  6246.     /**
  6247.      * <p>
  6248.      * Setter for the field <code>suspendCast</code>.
  6249.      * </p>
  6250.      *
  6251.      * @param b
  6252.      *            a boolean.
  6253.      */
  6254.     public final void setSuspendCast(final boolean b) {
  6255.         this.suspendCast = b;
  6256.     }
  6257.  
  6258.     /**
  6259.      * <p>
  6260.      * Setter for the field <code>kicked</code>.
  6261.      * </p>
  6262.      *
  6263.      * @param b
  6264.      *            a boolean.
  6265.      */
  6266.     public final void setKicked(final boolean b) {
  6267.         this.kicked = b;
  6268.     }
  6269.  
  6270.     /**
  6271.      * <p>
  6272.      * isKicked.
  6273.      * </p>
  6274.      *
  6275.      * @return a boolean.
  6276.      */
  6277.     public final boolean isKicked() {
  6278.         return this.kicked;
  6279.     }
  6280.  
  6281.     /**
  6282.      * Checks if is phased out.
  6283.      *
  6284.      * @return true, if is phased out
  6285.      */
  6286.     public final boolean isPhasedOut() {
  6287.         return this.phasedOut;
  6288.     }
  6289.  
  6290.     /**
  6291.      * Sets the phased out.
  6292.      *
  6293.      * @param phasedOut
  6294.      *            the new phased out
  6295.      */
  6296.     public final void setPhasedOut(final boolean phasedOut) {
  6297.         this.phasedOut = phasedOut;
  6298.     }
  6299.  
  6300.     /**
  6301.      * Phase.
  6302.      */
  6303.     public final void phase() {
  6304.         this.phase(true);
  6305.     }
  6306.  
  6307.     /**
  6308.      * Phase.
  6309.      *
  6310.      * @param direct
  6311.      *            the direct
  6312.      */
  6313.     public final void phase(final boolean direct) {
  6314.         final boolean phasingIn = this.isPhasedOut();
  6315.  
  6316.         if (!this.switchPhaseState()) {
  6317.             // Switch Phase State returns False if the Permanent can't Phase Out
  6318.             return;
  6319.         }
  6320.  
  6321.         if (!phasingIn) {
  6322.             this.setDirectlyPhasedOut(direct);
  6323.         }
  6324.  
  6325.         for (final Card eq : this.getEquippedBy()) {
  6326.             if (eq.isPhasedOut() == phasingIn) {
  6327.                 eq.phase(false);
  6328.             }
  6329.         }
  6330.  
  6331.         for (final Card aura : this.getEnchantedBy()) {
  6332.             if (aura.isPhasedOut() == phasingIn) {
  6333.                 aura.phase(false);
  6334.             }
  6335.         }
  6336.     }
  6337.  
  6338.     private boolean switchPhaseState() {
  6339.         if (!this.phasedOut && this.hasKeyword("CARDNAME can't phase out.")) {
  6340.             return false;
  6341.         }
  6342.  
  6343.         this.phasedOut = !this.phasedOut;
  6344.         if (this.phasedOut && this.isToken()) {
  6345.             // 702.23k Phased-out tokens cease to exist as a state-based action.
  6346.             // See rule 704.5d.
  6347.             // 702.23d The phasing event doesn't actually cause a permanent to
  6348.             // change zones or control,
  6349.             // even though it's treated as though it's not on the battlefield
  6350.             // and not under its controller's control while it's phased out.
  6351.             // Zone-change triggers don't trigger when a permanent phases in or
  6352.             // out.
  6353.  
  6354.             // Suppressed Exiling is as close as we can get to
  6355.             // "ceasing to exist"
  6356.             AllZone.getTriggerHandler().suppressMode("ChangesZone");
  6357.             AllZone.getGameAction().exile(this);
  6358.             AllZone.getTriggerHandler().clearSuppression("ChangesZone");
  6359.         }
  6360.         return true;
  6361.     }
  6362.  
  6363.     /**
  6364.      * Checks if is directly phased out.
  6365.      *
  6366.      * @return true, if is directly phased out
  6367.      */
  6368.     public final boolean isDirectlyPhasedOut() {
  6369.         return this.directlyPhasedOut;
  6370.     }
  6371.  
  6372.     /**
  6373.      * Sets the directly phased out.
  6374.      *
  6375.      * @param direct
  6376.      *            the new directly phased out
  6377.      */
  6378.     public final void setDirectlyPhasedOut(final boolean direct) {
  6379.         this.directlyPhasedOut = direct;
  6380.     }
  6381.  
  6382.     /**
  6383.      * <p>
  6384.      * isReflectedLand.
  6385.      * </p>
  6386.      *
  6387.      * @return a boolean.
  6388.      */
  6389.     public final boolean isReflectedLand() {
  6390.         for (final AbilityMana am : this.getCharacteristics().getManaAbility()) {
  6391.             if (am.isReflectedMana()) {
  6392.                 return true;
  6393.             }
  6394.         }
  6395.  
  6396.         return false;
  6397.     }
  6398.  
  6399.     /**
  6400.      * <p>
  6401.      * hasKeyword.
  6402.      * </p>
  6403.      *
  6404.      * @param keyword
  6405.      *            a {@link java.lang.String} object.
  6406.      * @return a boolean.
  6407.      */
  6408.     @Override
  6409.     public final boolean hasKeyword(final String keyword) {
  6410.         String kw = new String(keyword);
  6411.         if (kw.startsWith("HIDDEN")) {
  6412.             kw = kw.substring(7);
  6413.         }
  6414.         return this.getKeyword().contains(kw);
  6415.     }
  6416.  
  6417.     /**
  6418.      * <p>
  6419.      * hasStartOfKeyword.
  6420.      * </p>
  6421.      *
  6422.      * @param keyword
  6423.      *            a {@link java.lang.String} object.
  6424.      * @return a boolean.
  6425.      */
  6426.     public final boolean hasStartOfKeyword(final String keyword) {
  6427.         final ArrayList<String> a = this.getKeyword();
  6428.         for (int i = 0; i < a.size(); i++) {
  6429.             if (a.get(i).toString().startsWith(keyword)) {
  6430.                 return true;
  6431.             }
  6432.         }
  6433.         return false;
  6434.     }
  6435.  
  6436.     /**
  6437.      * <p>
  6438.      * hasStartOfKeyword.
  6439.      * </p>
  6440.      *
  6441.      * @param keyword
  6442.      *            a {@link java.lang.String} object.
  6443.      * @return a boolean.
  6444.      */
  6445.     public final boolean hasStartOfUnHiddenKeyword(final String keyword) {
  6446.         final ArrayList<String> a = this.getUnhiddenKeyword();
  6447.         for (int i = 0; i < a.size(); i++) {
  6448.             if (a.get(i).toString().startsWith(keyword)) {
  6449.                 return true;
  6450.             }
  6451.         }
  6452.         return false;
  6453.     }
  6454.  
  6455.     /**
  6456.      * <p>
  6457.      * getKeywordPosition.
  6458.      * </p>
  6459.      *
  6460.      * @param k
  6461.      *            a {@link java.lang.String} object.
  6462.      * @return a int.
  6463.      */
  6464.     public final int getKeywordPosition(final String k) {
  6465.         final ArrayList<String> a = this.getKeyword();
  6466.         for (int i = 0; i < a.size(); i++) {
  6467.             if (a.get(i).toString().startsWith(k)) {
  6468.                 return i;
  6469.             }
  6470.         }
  6471.         return -1;
  6472.     }
  6473.  
  6474.     /**
  6475.      * <p>
  6476.      * keywordsContain.
  6477.      * </p>
  6478.      *
  6479.      * @param keyword
  6480.      *            a {@link java.lang.String} object.
  6481.      * @return a boolean.
  6482.      */
  6483.     public final boolean keywordsContain(final String keyword) {
  6484.         final ArrayList<String> a = this.getKeyword();
  6485.         for (int i = 0; i < a.size(); i++) {
  6486.             if (a.get(i).toString().contains(keyword)) {
  6487.                 return true;
  6488.             }
  6489.         }
  6490.         return false;
  6491.     }
  6492.  
  6493.     /**
  6494.      * <p>
  6495.      * hasAnyKeyword.
  6496.      * </p>
  6497.      *
  6498.      * @param keywords
  6499.      *            an array of {@link java.lang.String} objects.
  6500.      * @return a boolean.
  6501.      */
  6502.     public final boolean hasAnyKeyword(final String[] keywords) {
  6503.         for (final String keyword : keywords) {
  6504.             if (this.hasKeyword(keyword)) {
  6505.                 return true;
  6506.             }
  6507.         }
  6508.  
  6509.         return false;
  6510.     }
  6511.  
  6512.     /**
  6513.      * <p>
  6514.      * hasAnyKeyword.
  6515.      * </p>
  6516.      *
  6517.      * @param keywords
  6518.      *            a {@link java.util.ArrayList} object.
  6519.      * @return a boolean.
  6520.      */
  6521.     public final boolean hasAnyKeyword(final ArrayList<String> keywords) {
  6522.         for (int i = 0; i < keywords.size(); i++) {
  6523.             if (this.hasKeyword(keywords.get(i))) {
  6524.                 return true;
  6525.             }
  6526.         }
  6527.  
  6528.         return false;
  6529.     }
  6530.  
  6531.     // This counts the number of instances of a keyword a card has
  6532.     /**
  6533.      * <p>
  6534.      * getAmountOfKeyword.
  6535.      * </p>
  6536.      *
  6537.      * @param k
  6538.      *            a {@link java.lang.String} object.
  6539.      * @return a int.
  6540.      */
  6541.     public final int getAmountOfKeyword(final String k) {
  6542.         int count = 0;
  6543.         final ArrayList<String> keywords = this.getKeyword();
  6544.         for (int j = 0; j < keywords.size(); j++) {
  6545.             if (keywords.get(j).equals(k)) {
  6546.                 count++;
  6547.             }
  6548.         }
  6549.  
  6550.         return count;
  6551.     }
  6552.  
  6553.     // This is for keywords with a number like Bushido, Annihilator and Rampage.
  6554.     // It returns the total.
  6555.     /**
  6556.      * <p>
  6557.      * getKeywordMagnitude.
  6558.      * </p>
  6559.      *
  6560.      * @param k
  6561.      *            a {@link java.lang.String} object.
  6562.      * @return a int.
  6563.      */
  6564.     public final int getKeywordMagnitude(final String k) {
  6565.         int count = 0;
  6566.         final ArrayList<String> keywords = this.getKeyword();
  6567.         for (final String kw : keywords) {
  6568.             if (kw.startsWith(k)) {
  6569.                 final String[] parse = kw.split(" ");
  6570.                 final String s = parse[1];
  6571.                 count += Integer.parseInt(s);
  6572.             }
  6573.         }
  6574.         return count;
  6575.     }
  6576.  
  6577.     private String toMixedCase(final String s) {
  6578.         if (s.equals("")) {
  6579.             return s;
  6580.         }
  6581.         final StringBuilder sb = new StringBuilder();
  6582.         // to handle hyphenated Types
  6583.         final String[] types = s.split("-");
  6584.         for (int i = 0; i < types.length; i++) {
  6585.             if (i != 0) {
  6586.                 sb.append("-");
  6587.             }
  6588.             sb.append(types[i].substring(0, 1).toUpperCase());
  6589.             sb.append(types[i].substring(1).toLowerCase());
  6590.         }
  6591.  
  6592.         return sb.toString();
  6593.     }
  6594.  
  6595.     // usable to check for changelings
  6596.     /**
  6597.      * <p>
  6598.      * isType.
  6599.      * </p>
  6600.      *
  6601.      * @param cardType
  6602.      *            a {@link java.lang.String} object.
  6603.      * @return a boolean.
  6604.      */
  6605.     public final boolean isType(String cardType) {
  6606.         cardType = this.toMixedCase(cardType);
  6607.  
  6608.         if (this.typeContains(cardType)
  6609.                 || ((this.isCreature() || this.isTribal()) && CardUtil.isACreatureType(cardType) && this
  6610.                         .typeContains("AllCreatureTypes"))) {
  6611.             return true;
  6612.         }
  6613.         return false;
  6614.     } // isType
  6615.  
  6616.     // Takes one argument like Permanent.Blue+withFlying
  6617.     /**
  6618.      * <p>
  6619.      * isValid.
  6620.      * </p>
  6621.      *
  6622.      * @param restriction
  6623.      *            a {@link java.lang.String} object.
  6624.      * @param sourceController
  6625.      *            a {@link forge.Player} object.
  6626.      * @param source
  6627.      *            a {@link forge.Card} object.
  6628.      * @return a boolean.
  6629.      */
  6630.     @Override
  6631.     public final boolean isValid(final String restriction, final Player sourceController, final Card source) {
  6632.  
  6633.         if (this.isImmutable()) {
  6634.             return false;
  6635.         }
  6636.  
  6637.         // Inclusive restrictions are Card types
  6638.         final String[] incR = restriction.split("\\.", 2);
  6639.  
  6640.         if (incR[0].equals("Spell") && !this.isSpell()) {
  6641.             return false;
  6642.         }
  6643.         if (incR[0].equals("Permanent") && (this.isInstant() || this.isSorcery())) {
  6644.             return false;
  6645.         }
  6646.         if (!incR[0].equals("card") && !incR[0].equals("Card") && !incR[0].equals("Spell")
  6647.                 && !incR[0].equals("Permanent") && !(this.isType(incR[0]))) {
  6648.             return false; // Check for wrong type
  6649.         }
  6650.  
  6651.         if (incR.length > 1) {
  6652.             final String excR = incR[1];
  6653.             final String[] exR = excR.split("\\+"); // Exclusive Restrictions
  6654.                                                     // are ...
  6655.             for (int j = 0; j < exR.length; j++) {
  6656.                 if (!this.hasProperty(exR[j], sourceController, source)) {
  6657.                     return false;
  6658.                 }
  6659.             }
  6660.         }
  6661.         return true;
  6662.     } // isValid(String Restriction)
  6663.  
  6664.     // Takes arguments like Blue or withFlying
  6665.     /**
  6666.      * <p>
  6667.      * hasProperty.
  6668.      * </p>
  6669.      *
  6670.      * @param property
  6671.      *            a {@link java.lang.String} object.
  6672.      * @param sourceController
  6673.      *            a {@link forge.Player} object.
  6674.      * @param source
  6675.      *            a {@link forge.Card} object.
  6676.      * @return a boolean.
  6677.      */
  6678.     @Override
  6679.     public boolean hasProperty(final String property, final Player sourceController, final Card source) {
  6680.         // by name can also have color names, so needs to happen before colors.
  6681.         if (property.startsWith("named")) {
  6682.             if (!this.getName().equals(property.substring(5))) {
  6683.                 return false;
  6684.             }
  6685.         } else if (property.startsWith("notnamed")) {
  6686.             if (this.getName().equals(property.substring(8))) {
  6687.                 return false;
  6688.             }
  6689.         } else if (property.startsWith("sameName")) {
  6690.             if (!this.getName().equals(source.getName())) {
  6691.                 return false;
  6692.             }
  6693.         } else if (property.equals("NamedCard")) {
  6694.             if (!this.getName().equals(source.getNamedCard())) {
  6695.                 return false;
  6696.             }
  6697.         } else if (property.equals("ChosenCard")) {
  6698.             if (!source.getChosenCard().contains(this)) {
  6699.                 return false;
  6700.             }
  6701.         }
  6702.         // ... Card colors
  6703.         else if (property.contains("White") || property.contains("Blue") || property.contains("Black")
  6704.                 || property.contains("Red") || property.contains("Green") || property.contains("Colorless")) {
  6705.             if (property.startsWith("non")) {
  6706.                 if (CardUtil.getColors(this).contains(property.substring(3).toLowerCase())) {
  6707.                     return false;
  6708.                 }
  6709.             } else if (!CardUtil.getColors(this).contains(property.toLowerCase())) {
  6710.                 return false;
  6711.             }
  6712.         } else if (property.contains("MultiColor")) // ... Card is multicolored
  6713.         {
  6714.             if (property.startsWith("non") && (CardUtil.getColors(this).size() > 1)) {
  6715.                 return false;
  6716.             }
  6717.             if (!property.startsWith("non") && (CardUtil.getColors(this).size() <= 1)) {
  6718.                 return false;
  6719.             }
  6720.         } else if (property.contains("MonoColor")) {
  6721.             // ... Card is monocolored
  6722.             if (property.startsWith("non") && ((CardUtil.getColors(this).size() == 1) && !this.isColorless())) {
  6723.                 return false;
  6724.             }
  6725.             if (!property.startsWith("non") && ((CardUtil.getColors(this).size() > 1) || this.isColorless())) {
  6726.                 return false;
  6727.             }
  6728.         } else if (property.equals("ChosenColor")) {
  6729.             // Should this match All chosen colors, or any? Default to first
  6730.             // chosen for now until it matters.
  6731.             if (source.getChosenColor().size() == 0) {
  6732.                 return false;
  6733.             }
  6734.             if (!CardUtil.getColors(this).contains(source.getChosenColor().get(0))) {
  6735.                 return false;
  6736.             }
  6737.         } else if (property.equals("DoubleFaced")) {
  6738.             if (!this.isDoubleFaced) {
  6739.                 return false;
  6740.             }
  6741.         } else if (property.equals("Flip")) {
  6742.             if (!this.isFlip) {
  6743.                 return false;
  6744.             }
  6745.         } else if (property.startsWith("YouCtrl")) {
  6746.             if (!this.getController().isPlayer(sourceController)) {
  6747.                 return false;
  6748.             }
  6749.         } else if (property.startsWith("YouDontCtrl")) {
  6750.             if (this.getController().isPlayer(sourceController)) {
  6751.                 return false;
  6752.             }
  6753.         } else if (property.startsWith("EnchantedPlayerCtrl")) {
  6754.             final Object o = source.getEnchanting();
  6755.             if (o instanceof Player) {
  6756.                 if (!this.getController().isPlayer((Player) o)) {
  6757.                     return false;
  6758.                 }
  6759.             } else { // source not enchanting a player
  6760.                 return false;
  6761.             }
  6762.         } else if (property.startsWith("YouOwn")) {
  6763.             if (!this.getOwner().isPlayer(sourceController)) {
  6764.                 return false;
  6765.             }
  6766.         } else if (property.startsWith("YouDontOwn")) {
  6767.             if (this.getOwner().isPlayer(sourceController)) {
  6768.                 return false;
  6769.             }
  6770.         } else if (property.startsWith("OwnerDoesntControl")) {
  6771.             if (this.getOwner().isPlayer(this.getController())) {
  6772.                 return false;
  6773.             }
  6774.         } else if (property.startsWith("ControllerControls")) {
  6775.             final String type = property.substring(18);
  6776.             final CardList list = this.getController().getCardsIn(Zone.Battlefield);
  6777.             if (list.getType(type).isEmpty()) {
  6778.                 return false;
  6779.             }
  6780.         } else if (property.startsWith("Other")) {
  6781.             if (this.equals(source)) {
  6782.                 return false;
  6783.             }
  6784.         } else if (property.startsWith("Self")) {
  6785.             if (!this.equals(source)) {
  6786.                 return false;
  6787.             }
  6788.         } else if (property.startsWith("AttachedBy")) {
  6789.             if (!this.equippedBy.contains(source) && !this.getEnchantedBy().contains(source)) {
  6790.                 return false;
  6791.             }
  6792.         } else if (property.equals("Attached")) {
  6793.             if (!this.equipping.contains(source) && !source.equals(this.enchanting)) {
  6794.                 return false;
  6795.             }
  6796.         } else if (property.startsWith("AttachedTo")) {
  6797.             final String restriction = property.split("AttachedTo ")[1];
  6798.             if (((this.enchanting == null) || !this.enchanting.isValid(restriction, sourceController, source))
  6799.                     && (this.equipping.isEmpty() || !this.equipping.get(0).isValid(restriction, sourceController,
  6800.                             source))) {
  6801.                 return false;
  6802.             }
  6803.         } else if (property.startsWith("EnchantedBy")) {
  6804.             if (!this.getEnchantedBy().contains(source) && !this.equals(source.getEnchanting())) {
  6805.                 return false;
  6806.             }
  6807.         } else if (property.startsWith("NotEnchantedBy")) {
  6808.             if (this.getEnchantedBy().contains(source)) {
  6809.                 return false;
  6810.             }
  6811.         } else if (property.startsWith("Enchanted")) {
  6812.             if (!source.equals(this.enchanting)) {
  6813.                 return false;
  6814.             }
  6815.         } else if (property.startsWith("EquippedBy")) {
  6816.             if (!this.equippedBy.contains(source)) {
  6817.                 return false;
  6818.             }
  6819.         } else if (property.startsWith("Equipped")) {
  6820.             if (!this.equipping.contains(source)) {
  6821.                 return false;
  6822.             }
  6823.         } else if (property.startsWith("HauntedBy")) {
  6824.             if (!this.hauntedBy.contains(source)) {
  6825.                 return false;
  6826.             }
  6827.         } else if (property.startsWith("Above")) { // "Are Above" Source
  6828.             final CardList list = this.getOwner().getCardsIn(Zone.Graveyard);
  6829.             if (!list.getAbove(source, this)) {
  6830.                 return false;
  6831.             }
  6832.         } else if (property.startsWith("DirectlyAbove")) { // "Are Directly Above"
  6833.                                                            // Source
  6834.             final CardList list = this.getOwner().getCardsIn(Zone.Graveyard);
  6835.             if (!list.getDirectlyAbove(source, this)) {
  6836.                 return false;
  6837.             }
  6838.         } else if (property.startsWith("TopGraveyardCreature")) {
  6839.             CardList list = this.getOwner().getCardsIn(Zone.Graveyard);
  6840.             list = list.getType("Creature");
  6841.             list.reverse();
  6842.             if (list.isEmpty() || !this.equals(list.get(0))) {
  6843.                 return false;
  6844.             }
  6845.         } else if (property.startsWith("TopGraveyard")) {
  6846.             final CardList list = this.getOwner().getCardsIn(Zone.Graveyard);
  6847.             list.reverse();
  6848.             if (list.isEmpty() || !this.equals(list.get(0))) {
  6849.                 return false;
  6850.             }
  6851.         } else if (property.startsWith("TopLibrary")) {
  6852.             final CardList list = this.getOwner().getCardsIn(Zone.Library);
  6853.             if (list.isEmpty() || !this.equals(list.get(0))) {
  6854.                 return false;
  6855.             }
  6856.         } else if (property.startsWith("Cloned")) {
  6857.             if ((this.cloneOrigin == null) || !this.cloneOrigin.equals(source)) {
  6858.                 return false;
  6859.             }
  6860.         } else if (property.startsWith("DamagedBy")) {
  6861.             if (!this.receivedDamageFromThisTurn.containsKey(source)) {
  6862.                 return false;
  6863.             }
  6864.         } else if (property.startsWith("Damaged")) {
  6865.             if (!this.dealtDamageToThisTurn.containsKey(source)) {
  6866.                 return false;
  6867.             }
  6868.         } else if (property.startsWith("SharesColorWith")) {
  6869.             if (property.equals("SharesColorWith")) {
  6870.                 if (!this.sharesColorWith(source)) {
  6871.                     return false;
  6872.                 }
  6873.             } else {
  6874.                 final String restriction = property.split("SharesColorWith ")[1];
  6875.                 if (restriction.equals("TopCardOfLibrary")) {
  6876.                     final CardList list = sourceController.getCardsIn(Zone.Library);
  6877.                     if (list.isEmpty() || !this.sharesColorWith(list.get(0))) {
  6878.                         return false;
  6879.                     }
  6880.                 } else {
  6881.                     boolean shares = false;
  6882.                     for (final Card card : sourceController.getCardsIn(Constant.Zone.Battlefield)) {
  6883.                         if (card.isValid(restriction, sourceController, source) && this.sharesColorWith(card)) {
  6884.                             shares = true;
  6885.                         }
  6886.                     }
  6887.                     if (!shares) {
  6888.                         return false;
  6889.                     }
  6890.                 }
  6891.             }
  6892.         } else if (property.startsWith("sharesCreatureTypeWith")) {
  6893.             if (property.equals("sharesCreatureTypeWith")) {
  6894.                 if (!this.sharesCreatureTypeWith(source)) {
  6895.                     return false;
  6896.                 }
  6897.             } else {
  6898.                 final String restriction = property.split("sharesCreatureTypeWith ")[1];
  6899.                 if (restriction.equals("TopCardOfLibrary")) {
  6900.                     final CardList list = sourceController.getCardsIn(Zone.Library);
  6901.                     if (list.isEmpty() || !this.sharesCreatureTypeWith(list.get(0))) {
  6902.                         return false;
  6903.                     }
  6904.                 } else {
  6905.                     boolean shares = false;
  6906.                     for (final Card card : sourceController.getCardsIn(Constant.Zone.Battlefield)) {
  6907.                         if (card.isValid(restriction, sourceController, source) && this.sharesCreatureTypeWith(card)) {
  6908.                             shares = true;
  6909.                         }
  6910.                     }
  6911.                     if (!shares) {
  6912.                         return false;
  6913.                     }
  6914.                 }
  6915.             }
  6916.         } else if (property.startsWith("sharesTypeWith")) {
  6917.             if (!this.sharesTypeWith(source)) {
  6918.                 return false;
  6919.             }
  6920.         } else if (property.startsWith("withFlashback")) {
  6921.             boolean fb = false;
  6922.             if (this.hasStartOfUnHiddenKeyword("Flashback")) {
  6923.                 fb = true;
  6924.             }
  6925.             for (final SpellAbility sa : this.getSpellAbilities()) {
  6926.                 if (sa.isFlashBackAbility()) {
  6927.                     fb = true;
  6928.                 }
  6929.             }
  6930.             if (!fb) {
  6931.                 return false;
  6932.             }
  6933.         } else if (property.startsWith("with")) {
  6934.             // ... Card keywords
  6935.             if (property.startsWith("without") && this.hasStartOfUnHiddenKeyword(property.substring(7))) {
  6936.                 return false;
  6937.             }
  6938.             if (!property.startsWith("without") && !this.hasStartOfUnHiddenKeyword(property.substring(4))) {
  6939.                 return false;
  6940.             }
  6941.         } else if (property.startsWith("tapped")) {
  6942.             if (!this.isTapped()) {
  6943.                 return false;
  6944.             }
  6945.         } else if (property.startsWith("untapped")) {
  6946.             if (!this.isUntapped()) {
  6947.                 return false;
  6948.             }
  6949.         } else if (property.startsWith("faceDown")) {
  6950.             if (!this.isFaceDown()) {
  6951.                 return false;
  6952.             }
  6953.         } else if (property.startsWith("faceUp")) {
  6954.             if (this.isFaceDown()) {
  6955.                 return false;
  6956.             }
  6957.         } else if (property.startsWith("hasLevelUp")) {
  6958.             if (!this.hasLevelUp()) {
  6959.                 return false;
  6960.             }
  6961.         } else if (property.startsWith("enteredBattlefieldThisTurn")) {
  6962.             if (!(this.getTurnInZone() == AllZone.getPhaseHandler().getTurn())) {
  6963.                 return false;
  6964.             }
  6965.         } else if (property.startsWith("notEnteredBattlefieldThisTurn")) {
  6966.             if (this.getTurnInZone() == AllZone.getPhaseHandler().getTurn()) {
  6967.                 return false;
  6968.             }
  6969.         } else if (property.startsWith("dealtDamageToYouThisTurn")) {
  6970.             if (!(this.dealtDmgToHumanThisTurn && sourceController.isHuman())
  6971.                     && !(this.dealtDmgToComputerThisTurn && sourceController.isComputer())) {
  6972.                 return false;
  6973.             }
  6974.         } else if (property.startsWith("controllerWasDealtCombatDamageByThisTurn")) {
  6975.             if (!(source.dealtCombatDmgToHumanThisTurn && this.getController().isPlayer(AllZone.getHumanPlayer()))
  6976.                     && !(source.dealtCombatDmgToComputerThisTurn && this.getController().isPlayer(
  6977.                             AllZone.getComputerPlayer()))) {
  6978.                 return false;
  6979.             }
  6980.         } else if (property.startsWith("controllerWasDealtDamageByThisTurn")) {
  6981.             if (!(source.dealtDmgToHumanThisTurn && this.getController().isPlayer(AllZone.getHumanPlayer()))
  6982.                     && !(source.dealtDmgToComputerThisTurn && this.getController()
  6983.                             .isPlayer(AllZone.getComputerPlayer()))) {
  6984.                 return false;
  6985.             }
  6986.         } else if (property.startsWith("wasDealtDamageThisTurn")) {
  6987.             if ((this.getReceivedDamageFromThisTurn().keySet()).isEmpty()) {
  6988.                 return false;
  6989.             }
  6990.         } else if (property.startsWith("attackedThisTurn")) {
  6991.             if (!this.getCreatureAttackedThisTurn()) {
  6992.                 return false;
  6993.             }
  6994.         } else if (property.startsWith("attackedLastTurn")) {
  6995.             if (this.getController().isComputer() && !this.getCreatureAttackedLastComputerTurn()) {
  6996.                 return false;
  6997.             }
  6998.             if (this.getController().isHuman() && !this.getCreatureAttackedLastHumanTurn()) {
  6999.                 return false;
  7000.             }
  7001.         } else if (property.startsWith("blockedThisTurn")) {
  7002.             if (!this.getCreatureBlockedThisTurn()) {
  7003.                 return false;
  7004.             }
  7005.         } else if (property.startsWith("gotBlockedThisTurn")) {
  7006.             if (!this.getCreatureGotBlockedThisTurn()) {
  7007.                 return false;
  7008.             }
  7009.         } else if (property.startsWith("notAttackedThisTurn")) {
  7010.             if (this.getCreatureAttackedThisTurn()) {
  7011.                 return false;
  7012.             }
  7013.         } else if (property.startsWith("notAttackedLastTurn")) {
  7014.             if (this.getController().isComputer() && this.getCreatureAttackedLastComputerTurn()) {
  7015.                 return false;
  7016.             }
  7017.             if (this.getController().isHuman() && this.getCreatureAttackedLastHumanTurn()) {
  7018.                 return false;
  7019.             }
  7020.         } else if (property.startsWith("notBlockedThisTurn")) {
  7021.             if (this.getCreatureBlockedThisTurn()) {
  7022.                 return false;
  7023.             }
  7024.         } else if (property.startsWith("greatestPower")) {
  7025.             final CardList list = AllZoneUtil.getCreaturesInPlay();
  7026.             for (final Card crd : list) {
  7027.                 if (crd.getNetAttack() > this.getNetAttack()) {
  7028.                     return false;
  7029.                 }
  7030.             }
  7031.         } else if (property.startsWith("leastPower")) {
  7032.             final CardList list = AllZoneUtil.getCreaturesInPlay();
  7033.             for (final Card crd : list) {
  7034.                 if (crd.getNetAttack() < this.getNetAttack()) {
  7035.                     return false;
  7036.                 }
  7037.             }
  7038.         } else if (property.startsWith("greatestCMC")) {
  7039.             final CardList list = AllZoneUtil.getCreaturesInPlay();
  7040.             for (final Card crd : list) {
  7041.                 if (crd.getCMC() > this.getCMC()) {
  7042.                     return false;
  7043.                 }
  7044.             }
  7045.         } else if (property.startsWith("lowestCMC")) {
  7046.             final CardList list = AllZoneUtil.getCardsIn(Constant.Zone.Battlefield);
  7047.             for (final Card crd : list) {
  7048.                 if (!crd.isLand() && !crd.isImmutable() && (crd.getCMC() < this.getCMC())) {
  7049.                     return false;
  7050.                 }
  7051.             }
  7052.         } else if (property.startsWith("enchanted")) {
  7053.             if (!this.isEnchanted()) {
  7054.                 return false;
  7055.             }
  7056.         } else if (property.startsWith("unenchanted")) {
  7057.             if (this.isEnchanted()) {
  7058.                 return false;
  7059.             }
  7060.         } else if (property.startsWith("enchanting")) {
  7061.             if (!this.isEnchanting()) {
  7062.                 return false;
  7063.             }
  7064.         } else if (property.startsWith("equipped")) {
  7065.             if (!this.isEquipped()) {
  7066.                 return false;
  7067.             }
  7068.         } else if (property.startsWith("unequipped")) {
  7069.             if (this.isEquipped()) {
  7070.                 return false;
  7071.             }
  7072.         } else if (property.startsWith("equipping")) {
  7073.             if (!this.isEquipping()) {
  7074.                 return false;
  7075.             }
  7076.         } else if (property.startsWith("token")) {
  7077.             if (!this.isToken()) {
  7078.                 return false;
  7079.             }
  7080.         } else if (property.startsWith("nonToken")) {
  7081.             if (this.isToken()) {
  7082.                 return false;
  7083.             }
  7084.         } else if (property.startsWith("hasXCost")) {
  7085.             if (this.getSpellAbility().length > 0) {
  7086.                 if (!this.getSpellAbility()[0].isXCost()) {
  7087.                     return false;
  7088.                 }
  7089.             }
  7090.  
  7091.         } else if (property.startsWith("power") || property.startsWith("toughness") || property.startsWith("cmc")) {
  7092.             int x = 0;
  7093.             int y = 0;
  7094.             String rhs = "";
  7095.  
  7096.             if (property.startsWith("power")) {
  7097.                 rhs = property.substring(7);
  7098.                 y = this.getNetAttack();
  7099.             } else if (property.startsWith("toughness")) {
  7100.                 rhs = property.substring(11);
  7101.                 y = this.getNetDefense();
  7102.             } else if (property.startsWith("cmc")) {
  7103.                 rhs = property.substring(5);
  7104.                 y = this.getCMC();
  7105.             }
  7106.             try {
  7107.                 x = Integer.parseInt(rhs);
  7108.             } catch (final NumberFormatException e) {
  7109.                 x = CardFactoryUtil.xCount(source, source.getSVar(rhs));
  7110.             }
  7111.  
  7112.             if (!AllZoneUtil.compare(y, property, x)) {
  7113.                 return false;
  7114.             }
  7115.         }
  7116.  
  7117.         // syntax example: countersGE9 P1P1 or countersLT12TIME (greater number
  7118.         // than 99 not supported)
  7119.         /*
  7120.          * slapshot5 - fair warning, you cannot use numbers with 2 digits
  7121.          * (greater number than 9 not supported you can use X and the
  7122.          * SVar:X:Number$12 to get two digits. This will need a better fix, and
  7123.          * I have the beginnings of a regex below
  7124.          */
  7125.         else if (property.startsWith("counters")) {
  7126.             /*
  7127.              * Pattern p = Pattern.compile("[a-z]*[A-Z][A-Z][X0-9]+.*$");
  7128.              * String[] parse = ???
  7129.              * System.out.println("Parsing completed of: "+Property); for(int i
  7130.              * = 0; i < parse.length; i++) {
  7131.              * System.out.println("parse["+i+"]: "+parse[i]); }
  7132.              */
  7133.  
  7134.             // TODO get a working regex out of this pattern so the amount of
  7135.             // digits doesn't matter
  7136.             int number = 0;
  7137.             final String[] splitProperty = property.split("_");
  7138.             final String strNum = splitProperty[1].substring(2);
  7139.             final String comparator = splitProperty[1].substring(0, 2);
  7140.             String counterType = "";
  7141.             try {
  7142.                 number = Integer.parseInt(strNum);
  7143.             } catch (final NumberFormatException e) {
  7144.                 number = CardFactoryUtil.xCount(source, source.getSVar(strNum));
  7145.             }
  7146.             counterType = splitProperty[2];
  7147.  
  7148.             final int actualnumber = this.getCounters(Counters.getType(counterType));
  7149.  
  7150.             if (!AllZoneUtil.compare(actualnumber, comparator, number)) {
  7151.                 return false;
  7152.             }
  7153.         } else if (property.startsWith("attacking")) {
  7154.             if (!this.isAttacking()) {
  7155.                 return false;
  7156.             }
  7157.         } else if (property.startsWith("notattacking")) {
  7158.             if (this.isAttacking()) {
  7159.                 return false;
  7160.             }
  7161.         } else if (property.equals("blocking")) {
  7162.             if (!this.isBlocking()) {
  7163.                 return false;
  7164.             }
  7165.         } else if (property.startsWith("blockingSource")) {
  7166.             if (!this.isBlocking(source)) {
  7167.                 return false;
  7168.             }
  7169.         } else if (property.startsWith("notblocking")) {
  7170.             if (this.isBlocking()) {
  7171.                 return false;
  7172.             }
  7173.         } else if (property.equals("blocked")) {
  7174.             if (!AllZone.getCombat().isBlocked(this)) {
  7175.                 return false;
  7176.             }
  7177.         } else if (property.startsWith("blockedBySource")) {
  7178.             if (!this.isBlockedBy(source)) {
  7179.                 return false;
  7180.             }
  7181.         } else if (property.startsWith("unblocked")) {
  7182.             if (!AllZone.getCombat().isUnblocked(this)) {
  7183.                 return false;
  7184.             }
  7185.         } else if (property.startsWith("kicked")) {
  7186.             if (!this.isKicked()) {
  7187.                 return false;
  7188.             }
  7189.         } else if (property.startsWith("notkicked")) {
  7190.             if (this.isKicked()) {
  7191.                 return false;
  7192.             }
  7193.         } else if (property.startsWith("evoked")) {
  7194.             if (!this.isEvoked()) {
  7195.                 return false;
  7196.             }
  7197.         } else if (property.equals("HasDevoured")) {
  7198.             if (this.devouredCards.size() == 0) {
  7199.                 return false;
  7200.             }
  7201.         } else if (property.equals("HasNotDevoured")) {
  7202.             if (this.devouredCards.size() != 0) {
  7203.                 return false;
  7204.             }
  7205.         } else if (property.startsWith("non")) {
  7206.             // ... Other Card types
  7207.             if (this.isType(property.substring(3))) {
  7208.                 return false;
  7209.             }
  7210.         } else if (property.equals("CostsPhyrexianMana")) {
  7211.             if (!this.getCharacteristics().getManaCost().contains("P")) {
  7212.                 return false;
  7213.             }
  7214.         } else if (property.equals("IsRemembered")) {
  7215.             if (!source.getRemembered().contains(this)) {
  7216.                 return false;
  7217.             }
  7218.         } else if (property.equals("hasActivatedAbilityWithTapCost")) {
  7219.             boolean hasIt = false;
  7220.             for (final SpellAbility sa : this.getSpellAbilities()) {
  7221.                 if (sa.isAbility() && (sa.getPayCosts() != null) && sa.getPayCosts().getTap()) {
  7222.                     hasIt = true;
  7223.                 }
  7224.             }
  7225.             if (!hasIt) {
  7226.                 return false;
  7227.             }
  7228.         } else if (property.equals("NoAbilities")) {
  7229.             if (!((this.getAbilityText().trim().equals("") || this.isFaceDown()) && (this.getUnhiddenKeyword().size() == 0))) {
  7230.                 return false;
  7231.             }
  7232.         } else if (property.equals("SameNameAsImprinted")) {
  7233.             boolean b = false;
  7234.             for (final Card card : source.getImprinted()) {
  7235.                 if (this.getName().equals(card.getName())) {
  7236.                     b = true;
  7237.                 }
  7238.             }
  7239.             if (!b) {
  7240.                 return false;
  7241.             }
  7242.         } else if (property.startsWith("wasCastFrom")) {
  7243.             final String strZone = property.substring(11);
  7244.             final Zone realZone = Constant.Zone.smartValueOf(strZone);
  7245.             if (realZone != this.getCastFrom()) {
  7246.                 return false;
  7247.             }
  7248.         } else if (property.startsWith("wasNotCastFrom")) {
  7249.             final String strZone = property.substring(14);
  7250.             final Zone realZone = Constant.Zone.smartValueOf(strZone);
  7251.             if (realZone == this.getCastFrom()) {
  7252.                 return false;
  7253.             }
  7254.         } else {
  7255.             if (property.equals("ChosenType")) {
  7256.                 if (!this.isType(source.getChosenType())) {
  7257.                     return false;
  7258.                 }
  7259.             } else {
  7260.                 if (!this.isType(property)) {
  7261.                     return false;
  7262.                 }
  7263.             }
  7264.         }
  7265.         return true;
  7266.     } // hasProperty
  7267.  
  7268.     /**
  7269.      * <p>
  7270.      * setImmutable.
  7271.      * </p>
  7272.      *
  7273.      * @param isImmutable
  7274.      *            a boolean.
  7275.      */
  7276.     public final void setImmutable(final boolean isImmutable) {
  7277.         this.isImmutable = isImmutable;
  7278.     }
  7279.  
  7280.     /**
  7281.      * <p>
  7282.      * isImmutable.
  7283.      * </p>
  7284.      *
  7285.      * @return a boolean.
  7286.      */
  7287.     public final boolean isImmutable() {
  7288.         return this.isImmutable;
  7289.     }
  7290.  
  7291.     /*
  7292.      * there are easy checkers for Color. The CardUtil functions should be made
  7293.      * part of the Card class, so calling out is not necessary
  7294.      */
  7295.  
  7296.     /**
  7297.      * <p>
  7298.      * isColor.
  7299.      * </p>
  7300.      *
  7301.      * @param col
  7302.      *            a {@link java.lang.String} object.
  7303.      * @return a boolean.
  7304.      */
  7305.     public final boolean isColor(final String col) {
  7306.         return CardUtil.getColors(this).contains(col);
  7307.     }
  7308.  
  7309.     /**
  7310.      * <p>
  7311.      * isBlack.
  7312.      * </p>
  7313.      *
  7314.      * @return a boolean.
  7315.      */
  7316.     public final boolean isBlack() {
  7317.         return CardUtil.getColors(this).contains(Constant.Color.BLACK);
  7318.     }
  7319.  
  7320.     /**
  7321.      * <p>
  7322.      * isBlue.
  7323.      * </p>
  7324.      *
  7325.      * @return a boolean.
  7326.      */
  7327.     public final boolean isBlue() {
  7328.         return CardUtil.getColors(this).contains(Constant.Color.BLUE);
  7329.     }
  7330.  
  7331.     /**
  7332.      * <p>
  7333.      * isRed.
  7334.      * </p>
  7335.      *
  7336.      * @return a boolean.
  7337.      */
  7338.     public final boolean isRed() {
  7339.         return CardUtil.getColors(this).contains(Constant.Color.RED);
  7340.     }
  7341.  
  7342.     /**
  7343.      * <p>
  7344.      * isGreen.
  7345.      * </p>
  7346.      *
  7347.      * @return a boolean.
  7348.      */
  7349.     public final boolean isGreen() {
  7350.         return CardUtil.getColors(this).contains(Constant.Color.GREEN);
  7351.     }
  7352.  
  7353.     /**
  7354.      * <p>
  7355.      * isWhite.
  7356.      * </p>
  7357.      *
  7358.      * @return a boolean.
  7359.      */
  7360.     public final boolean isWhite() {
  7361.         return CardUtil.getColors(this).contains(Constant.Color.WHITE);
  7362.     }
  7363.  
  7364.     /**
  7365.      * <p>
  7366.      * isColorless.
  7367.      * </p>
  7368.      *
  7369.      * @return a boolean.
  7370.      */
  7371.     public final boolean isColorless() {
  7372.         return CardUtil.getColors(this).contains(Constant.Color.COLORLESS);
  7373.     }
  7374.  
  7375.     /**
  7376.      * <p>
  7377.      * sharesColorWith.
  7378.      * </p>
  7379.      *
  7380.      * @param c1
  7381.      *            a {@link forge.Card} object.
  7382.      * @return a boolean.
  7383.      */
  7384.     public final boolean sharesColorWith(final Card c1) {
  7385.         boolean shares = false;
  7386.         shares |= (this.isBlack() && c1.isBlack());
  7387.         shares |= (this.isBlue() && c1.isBlue());
  7388.         shares |= (this.isGreen() && c1.isGreen());
  7389.         shares |= (this.isRed() && c1.isRed());
  7390.         shares |= (this.isWhite() && c1.isWhite());
  7391.         return shares;
  7392.     }
  7393.  
  7394.     /**
  7395.      * <p>
  7396.      * sharesCreatureTypeWith.
  7397.      * </p>
  7398.      *
  7399.      * @param c1
  7400.      *            a {@link forge.Card} object.
  7401.      * @return a boolean.
  7402.      */
  7403.     public final boolean sharesCreatureTypeWith(final Card c1) {
  7404.  
  7405.         for (final String type : this.getType()) {
  7406.             if (type.equals("AllCreatureTypes") && c1.hasACreatureType()) {
  7407.                 return true;
  7408.             }
  7409.             if (CardUtil.isACreatureType(type) && c1.isType(type)) {
  7410.                 return true;
  7411.             }
  7412.         }
  7413.         return false;
  7414.     }
  7415.  
  7416.     /**
  7417.      * <p>
  7418.      * sharesTypeWith.
  7419.      * </p>
  7420.      *
  7421.      * @param c1
  7422.      *            a {@link forge.Card} object.
  7423.      * @return a boolean.
  7424.      */
  7425.     public final boolean sharesTypeWith(final Card c1) {
  7426.  
  7427.         for (final String type : this.getType()) {
  7428.             if (c1.isType(type)) {
  7429.                 return true;
  7430.             }
  7431.         }
  7432.         return false;
  7433.     }
  7434.  
  7435.     /**
  7436.      * <p>
  7437.      * hasACreatureType.
  7438.      * </p>
  7439.      *
  7440.      * @return a boolean.
  7441.      */
  7442.     public final boolean hasACreatureType() {
  7443.         for (final String type : this.getType()) {
  7444.             if (CardUtil.isACreatureType(type)) {
  7445.                 return true;
  7446.             }
  7447.         }
  7448.         return false;
  7449.     }
  7450.  
  7451.     /**
  7452.      * <p>
  7453.      * isAttacking.
  7454.      * </p>
  7455.      *
  7456.      * @return a boolean.
  7457.      */
  7458.     public final boolean isAttacking() {
  7459.         return AllZone.getCombat().isAttacking(this);
  7460.     }
  7461.  
  7462.     /**
  7463.      * <p>
  7464.      * isBlocking.
  7465.      * </p>
  7466.      *
  7467.      * @return a boolean.
  7468.      */
  7469.     public final boolean isBlocking() {
  7470.         final CardList blockers = AllZone.getCombat().getAllBlockers();
  7471.         return blockers.contains(this);
  7472.     }
  7473.  
  7474.     /**
  7475.      * <p>
  7476.      * isBlocking.
  7477.      * </p>
  7478.      *
  7479.      * @param attacker
  7480.      *            a {@link forge.Card} object.
  7481.      * @return a boolean.
  7482.      */
  7483.     public final boolean isBlocking(final Card attacker) {
  7484.         return attacker.equals(AllZone.getCombat().getAttackerBlockedBy(this));
  7485.     }
  7486.  
  7487.     /**
  7488.      * <p>
  7489.      * isBlockedBy.
  7490.      * </p>
  7491.      *
  7492.      * @param blocker
  7493.      *            a {@link forge.Card} object.
  7494.      * @return a boolean.
  7495.      */
  7496.     public final boolean isBlockedBy(final Card blocker) {
  7497.         return this.equals(AllZone.getCombat().getAttackerBlockedBy(blocker));
  7498.     }
  7499.  
  7500.     // /////////////////////////
  7501.     //
  7502.     // Damage code
  7503.     //
  7504.     // ////////////////////////
  7505.  
  7506.     // all damage to cards is now handled in Card.java, no longer
  7507.     // AllZone.getGameAction()...
  7508.     /**
  7509.      * <p>
  7510.      * addReceivedDamageFromThisTurn.
  7511.      * </p>
  7512.      *
  7513.      * @param c
  7514.      *            a {@link forge.Card} object.
  7515.      * @param damage
  7516.      *            a int.
  7517.      */
  7518.     public final void addReceivedDamageFromThisTurn(final Card c, final int damage) {
  7519.         this.receivedDamageFromThisTurn.put(c, damage);
  7520.     }
  7521.  
  7522.     /**
  7523.      * <p>
  7524.      * Setter for the field <code>receivedDamageFromThisTurn</code>.
  7525.      * </p>
  7526.      *
  7527.      * @param receivedDamageList
  7528.      *            a Map object.
  7529.      */
  7530.     public final void setReceivedDamageFromThisTurn(final Map<Card, Integer> receivedDamageList) {
  7531.         this.receivedDamageFromThisTurn = receivedDamageList;
  7532.     }
  7533.  
  7534.     /**
  7535.      * <p>
  7536.      * Getter for the field <code>receivedDamageFromThisTurn</code>.
  7537.      * </p>
  7538.      *
  7539.      * @return a Map object.
  7540.      */
  7541.     public final Map<Card, Integer> getReceivedDamageFromThisTurn() {
  7542.         return this.receivedDamageFromThisTurn;
  7543.     }
  7544.  
  7545.     /**
  7546.      * <p>
  7547.      * resetReceivedDamageFromThisTurn.
  7548.      * </p>
  7549.      */
  7550.     public final void resetReceivedDamageFromThisTurn() {
  7551.         this.receivedDamageFromThisTurn.clear();
  7552.     }
  7553.  
  7554.     /**
  7555.      * <p>
  7556.      * addDealtDamageToThisTurn.
  7557.      * </p>
  7558.      *
  7559.      * @param c
  7560.      *            a {@link forge.Card} object.
  7561.      * @param damage
  7562.      *            a int.
  7563.      */
  7564.     public final void addDealtDamageToThisTurn(final Card c, final int damage) {
  7565.         this.dealtDamageToThisTurn.put(c, damage);
  7566.     }
  7567.  
  7568.     /**
  7569.      * <p>
  7570.      * Setter for the field <code>dealtDamageToThisTurn</code>.
  7571.      * </p>
  7572.      *
  7573.      * @param dealtDamageList
  7574.      *            a {@link java.util.Map} object.
  7575.      */
  7576.     public final void setDealtDamageToThisTurn(final Map<Card, Integer> dealtDamageList) {
  7577.         this.dealtDamageToThisTurn = dealtDamageList;
  7578.     }
  7579.  
  7580.     /**
  7581.      * <p>
  7582.      * Getter for the field <code>dealtDamageToThisTurn</code>.
  7583.      * </p>
  7584.      *
  7585.      * @return a {@link java.util.Map} object.
  7586.      */
  7587.     public final Map<Card, Integer> getDealtDamageToThisTurn() {
  7588.         return this.dealtDamageToThisTurn;
  7589.     }
  7590.  
  7591.     /**
  7592.      * <p>
  7593.      * resetDealtDamageToThisTurn.
  7594.      * </p>
  7595.      */
  7596.     public final void resetDealtDamageToThisTurn() {
  7597.         this.dealtDamageToThisTurn.clear();
  7598.     }
  7599.  
  7600.     // how much damage is enough to kill the creature (for AI)
  7601.     /**
  7602.      * <p>
  7603.      * getEnoughDamageToKill.
  7604.      * </p>
  7605.      *
  7606.      * @param maxDamage
  7607.      *            a int.
  7608.      * @param source
  7609.      *            a {@link forge.Card} object.
  7610.      * @param isCombat
  7611.      *            a boolean.
  7612.      * @return a int.
  7613.      */
  7614.     public final int getEnoughDamageToKill(final int maxDamage, final Card source, final boolean isCombat) {
  7615.         return this.getEnoughDamageToKill(maxDamage, source, isCombat, false);
  7616.     }
  7617.  
  7618.     /**
  7619.      * <p>
  7620.      * getEnoughDamageToKill.
  7621.      * </p>
  7622.      *
  7623.      * @param maxDamage
  7624.      *            a int.
  7625.      * @param source
  7626.      *            a {@link forge.Card} object.
  7627.      * @param isCombat
  7628.      *            a boolean.
  7629.      * @param noPrevention
  7630.      *            a boolean.
  7631.      * @return a int.
  7632.      */
  7633.     public final int getEnoughDamageToKill(final int maxDamage, final Card source, final boolean isCombat,
  7634.             final boolean noPrevention) {
  7635.         final int killDamage = this.getKillDamage();
  7636.  
  7637.         if (this.hasKeyword("Indestructible") || (this.getShield() > 0)) {
  7638.             if (!(source.hasKeyword("Wither") || source.hasKeyword("Infect"))) {
  7639.                 return maxDamage + 1;
  7640.             }
  7641.         } else if (source.hasKeyword("Deathtouch")) {
  7642.             for (int i = 1; i <= maxDamage; i++) {
  7643.                 if (noPrevention) {
  7644.                     if (this.staticReplaceDamage(i, source, isCombat) > 0) {
  7645.                         return i;
  7646.                     }
  7647.                 } else if (this.predictDamage(i, source, isCombat) > 0) {
  7648.                     return i;
  7649.                 }
  7650.             }
  7651.         }
  7652.  
  7653.         for (int i = 1; i <= maxDamage; i++) {
  7654.             if (noPrevention) {
  7655.                 if (this.staticReplaceDamage(i, source, isCombat) >= killDamage) {
  7656.                     return i;
  7657.                 }
  7658.             } else {
  7659.                 if (this.predictDamage(i, source, isCombat) >= killDamage) {
  7660.                     return i;
  7661.                 }
  7662.             }
  7663.         }
  7664.  
  7665.         return maxDamage + 1;
  7666.     }
  7667.  
  7668.     // the amount of damage needed to kill the creature (for AI)
  7669.     /**
  7670.      * <p>
  7671.      * getKillDamage.
  7672.      * </p>
  7673.      *
  7674.      * @return a int.
  7675.      */
  7676.     public final int getKillDamage() {
  7677.         int killDamage = this.getLethalDamage() + this.getPreventNextDamage();
  7678.         if ((killDamage > this.getPreventNextDamage())
  7679.                 && this.hasStartOfKeyword("When CARDNAME is dealt damage, destroy it.")) {
  7680.             killDamage = 1 + this.getPreventNextDamage();
  7681.         }
  7682.  
  7683.         return killDamage;
  7684.     }
  7685.  
  7686.     // this is the minimal damage a trampling creature has to assign to a
  7687.     // blocker
  7688.     /**
  7689.      * <p>
  7690.      * getLethalDamage.
  7691.      * </p>
  7692.      *
  7693.      * @return a int.
  7694.      */
  7695.     public final int getLethalDamage() {
  7696.         final int lethalDamage = this.getNetDefense() - this.getDamage() - this.getTotalAssignedDamage();
  7697.  
  7698.         return lethalDamage;
  7699.     }
  7700.  
  7701.     /**
  7702.      * <p>
  7703.      * Setter for the field <code>damage</code>.
  7704.      * </p>
  7705.      *
  7706.      * @param n
  7707.      *            a int.
  7708.      */
  7709.     public final void setDamage(final int n) {
  7710.         // if
  7711.         // (this.hasKeyword("Prevent all damage that would be dealt to CARDNAME."))
  7712.         // n = 0;
  7713.         this.damage = n;
  7714.     }
  7715.  
  7716.     /**
  7717.      * <p>
  7718.      * Getter for the field <code>damage</code>.
  7719.      * </p>
  7720.      *
  7721.      * @return a int.
  7722.      */
  7723.     public final int getDamage() {
  7724.         return this.damage;
  7725.     }
  7726.  
  7727.     /**
  7728.      * <p>
  7729.      * addAssignedDamage.
  7730.      * </p>
  7731.      *
  7732.      * @param damage
  7733.      *            a int.
  7734.      * @param sourceCard
  7735.      *            a {@link forge.Card} object.
  7736.      */
  7737.     public final void addAssignedDamage(int damage, final Card sourceCard) {
  7738.         if (damage < 0) {
  7739.             damage = 0;
  7740.         }
  7741.  
  7742.         final int assignedDamage = damage;
  7743.  
  7744.         Log.debug(this + " - was assigned " + assignedDamage + " damage, by " + sourceCard);
  7745.         if (!this.assignedDamageMap.containsKey(sourceCard)) {
  7746.             this.assignedDamageMap.put(sourceCard, assignedDamage);
  7747.         } else {
  7748.             this.assignedDamageMap.put(sourceCard, this.assignedDamageMap.get(sourceCard) + assignedDamage);
  7749.         }
  7750.  
  7751.         Log.debug("***");
  7752.         /*
  7753.          * if(sourceCards.size() > 1)
  7754.          * System.out.println("(MULTIPLE blockers):");
  7755.          * System.out.println("Assigned " + damage + " damage to " + card); for
  7756.          * (int i=0;i<sourceCards.size();i++){
  7757.          * System.out.println(sourceCards.get(i).getName() +
  7758.          * " assigned damage to " + card.getName()); }
  7759.          * System.out.println("***");
  7760.          */
  7761.     }
  7762.  
  7763.     /**
  7764.      * <p>
  7765.      * clearAssignedDamage.
  7766.      * </p>
  7767.      */
  7768.     public final void clearAssignedDamage() {
  7769.         this.assignedDamageMap.clear();
  7770.     }
  7771.  
  7772.     /**
  7773.      * <p>
  7774.      * getTotalAssignedDamage.
  7775.      * </p>
  7776.      *
  7777.      * @return a int.
  7778.      */
  7779.     public final int getTotalAssignedDamage() {
  7780.         int total = 0;
  7781.  
  7782.         final Collection<Integer> c = this.assignedDamageMap.values();
  7783.  
  7784.         final Iterator<Integer> itr = c.iterator();
  7785.         while (itr.hasNext()) {
  7786.             total += itr.next();
  7787.         }
  7788.  
  7789.         return total;
  7790.     }
  7791.  
  7792.     /**
  7793.      * <p>
  7794.      * Getter for the field <code>assignedDamageMap</code>.
  7795.      * </p>
  7796.      *
  7797.      * @return a {@link java.util.Map} object.
  7798.      */
  7799.     public final Map<Card, Integer> getAssignedDamageMap() {
  7800.         return this.assignedDamageMap;
  7801.     }
  7802.  
  7803.     /**
  7804.      * <p>
  7805.      * addCombatDamage.
  7806.      * </p>
  7807.      *
  7808.      * @param map
  7809.      *            a {@link java.util.Map} object.
  7810.      */
  7811.     public final void addCombatDamage(final Map<Card, Integer> map) {
  7812.         final CardList list = new CardList();
  7813.  
  7814.         for (final Entry<Card, Integer> entry : map.entrySet()) {
  7815.             final Card source = entry.getKey();
  7816.             list.add(source);
  7817.             int damageToAdd = entry.getValue();
  7818.  
  7819.             damageToAdd = this.replaceDamage(damageToAdd, source, true);
  7820.             damageToAdd = this.preventDamage(damageToAdd, source, true);
  7821.  
  7822.             if ((damageToAdd > 0) && this.isCreature()) {
  7823.                 GameActionUtil.executeCombatDamageToCreatureEffects(source, this, damageToAdd);
  7824.             }
  7825.             map.put(source, damageToAdd);
  7826.         }
  7827.  
  7828.         if (AllZoneUtil.isCardInPlay(this)) {
  7829.             this.addDamage(map);
  7830.         }
  7831.     }
  7832.  
  7833.     // This function helps the AI calculate the actual amount of damage an
  7834.     // effect would deal
  7835.     /**
  7836.      * <p>
  7837.      * predictDamage.
  7838.      * </p>
  7839.      *
  7840.      * @param damage
  7841.      *            a int.
  7842.      * @param possiblePrevention
  7843.      *            a int.
  7844.      * @param source
  7845.      *            a {@link forge.Card} object.
  7846.      * @param isCombat
  7847.      *            a boolean.
  7848.      * @return a int.
  7849.      */
  7850.     public final int predictDamage(final int damage, final int possiblePrevention, final Card source,
  7851.             final boolean isCombat) {
  7852.  
  7853.         int restDamage = damage;
  7854.  
  7855.         restDamage = this.staticReplaceDamage(restDamage, source, isCombat);
  7856.  
  7857.         restDamage = this.staticDamagePrevention(restDamage, possiblePrevention, source, isCombat);
  7858.  
  7859.         return restDamage;
  7860.     }
  7861.  
  7862.     // This should be also usable by the AI to forecast an effect (so it must
  7863.     // not change the game state)
  7864.     /**
  7865.      * <p>
  7866.      * staticDamagePrevention.
  7867.      * </p>
  7868.      *
  7869.      * @param damage
  7870.      *            a int.
  7871.      * @param possiblePrvenetion
  7872.      *            a int.
  7873.      * @param source
  7874.      *            a {@link forge.Card} object.
  7875.      * @param isCombat
  7876.      *            a boolean.
  7877.      * @return a int.
  7878.      */
  7879.     public final int staticDamagePrevention(final int damage, final int possiblePrvenetion, final Card source,
  7880.             final boolean isCombat) {
  7881.  
  7882.         if (AllZoneUtil.isCardInPlay("Leyline of Punishment")) {
  7883.             return damage;
  7884.         }
  7885.  
  7886.         int restDamage = damage - possiblePrvenetion;
  7887.  
  7888.         restDamage = this.staticDamagePrevention(restDamage, source, isCombat);
  7889.  
  7890.         return restDamage;
  7891.     }
  7892.  
  7893.     // This should be also usable by the AI to forecast an effect (so it must
  7894.     // not change the game state)
  7895.     /**
  7896.      * <p>
  7897.      * staticDamagePrevention.
  7898.      * </p>
  7899.      *
  7900.      * @param damageIn
  7901.      *            a int.
  7902.      * @param source
  7903.      *            a {@link forge.Card} object.
  7904.      * @param isCombat
  7905.      *            a boolean.
  7906.      * @return a int.
  7907.      */
  7908.     @Override
  7909.     public final int staticDamagePrevention(final int damageIn, final Card source, final boolean isCombat) {
  7910.  
  7911.         if (AllZoneUtil.isCardInPlay("Leyline of Punishment")) {
  7912.             return damageIn;
  7913.         }
  7914.  
  7915.         int restDamage = damageIn;
  7916.  
  7917.         if (this.hasProtectionFrom(source)) {
  7918.             return 0;
  7919.         }
  7920.  
  7921.         if (isCombat) {
  7922.             if (this.hasKeyword("Prevent all combat damage that would be dealt to and dealt by CARDNAME.")) {
  7923.                 return 0;
  7924.             }
  7925.             if (this.hasKeyword("Prevent all combat damage that would be dealt to CARDNAME.")) {
  7926.                 return 0;
  7927.             }
  7928.             if (source.hasKeyword("Prevent all combat damage that would be dealt to and dealt by CARDNAME.")) {
  7929.                 return 0;
  7930.             }
  7931.             if (source.hasKeyword("Prevent all combat damage that would be dealt by CARDNAME.")) {
  7932.                 return 0;
  7933.             }
  7934.         }
  7935.         if (this.hasKeyword("Prevent all damage that would be dealt to CARDNAME.")) {
  7936.             return 0;
  7937.         }
  7938.         if (this.hasKeyword("Prevent all damage that would be dealt to and dealt by CARDNAME.")) {
  7939.             return 0;
  7940.         }
  7941.         if (source.hasKeyword("Prevent all damage that would be dealt to and dealt by CARDNAME.")) {
  7942.             return 0;
  7943.         }
  7944.         if (source.hasKeyword("Prevent all damage that would be dealt by CARDNAME.")) {
  7945.             return 0;
  7946.         }
  7947.  
  7948.         if (this.hasStartOfKeyword("Absorb")) {
  7949.             final int absorbed = this.getKeywordMagnitude("Absorb");
  7950.             if (restDamage > absorbed) {
  7951.                 restDamage = restDamage - absorbed;
  7952.             } else {
  7953.                 return 0;
  7954.             }
  7955.         }
  7956.  
  7957.         if (this.hasStartOfKeyword("PreventAllDamageBy")) {
  7958.             String valid = this.getKeyword().get(this.getKeywordPosition("PreventAllDamageBy"));
  7959.             valid = valid.split(" ", 2)[1];
  7960.             if (source.isValid(valid, this.getController(), this)) {
  7961.                 return 0;
  7962.             }
  7963.         }
  7964.  
  7965.         // Prevent Damage static abilities
  7966.         final CardList allp = AllZoneUtil.getCardsIn(Zone.Battlefield);
  7967.         for (final Card ca : allp) {
  7968.             final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities();
  7969.             for (final StaticAbility stAb : staticAbilities) {
  7970.                 restDamage = stAb.applyAbility("PreventDamage", source, this, restDamage, isCombat);
  7971.             }
  7972.         }
  7973.  
  7974.         // specific Cards
  7975.         if (this.isCreature()) { // and not a planeswalker
  7976.             if (this.getName().equals("Swans of Bryn Argoll")) {
  7977.                 return 0;
  7978.             }
  7979.  
  7980.             if ((source.isCreature() && AllZoneUtil.isCardInPlay("Well-Laid Plans") && source.sharesColorWith(this))) {
  7981.                 return 0;
  7982.             }
  7983.         } // Creature end
  7984.  
  7985.         if (restDamage > 0) {
  7986.             return restDamage;
  7987.         } else {
  7988.             return 0;
  7989.         }
  7990.     }
  7991.  
  7992.     /**
  7993.      * <p>
  7994.      * preventDamage.
  7995.      * </p>
  7996.      *
  7997.      * @param damage
  7998.      *            a int.
  7999.      * @param source
  8000.      *            a {@link forge.Card} object.
  8001.      * @param isCombat
  8002.      *            a boolean.
  8003.      * @return a int.
  8004.      */
  8005.     @Override
  8006.     public final int preventDamage(final int damage, final Card source, final boolean isCombat) {
  8007.  
  8008.         if (AllZoneUtil.isCardInPlay("Leyline of Punishment")) {
  8009.             return damage;
  8010.         }
  8011.  
  8012.         int restDamage = damage;
  8013.  
  8014.         if (this.getName().equals("Swans of Bryn Argoll")) {
  8015.             source.getController().drawCards(restDamage);
  8016.             return 0;
  8017.         }
  8018.  
  8019.         restDamage = this.staticDamagePrevention(restDamage, source, isCombat);
  8020.  
  8021.         if (restDamage == 0) {
  8022.             return 0;
  8023.         }
  8024.  
  8025.         if (this.hasKeyword("If damage would be dealt to CARDNAME, "
  8026.                 + "prevent that damage. Remove a +1/+1 counter from CARDNAME.")) {
  8027.             restDamage = 0;
  8028.             this.subtractCounter(Counters.P1P1, 1);
  8029.         }
  8030.  
  8031.         if (restDamage >= this.getPreventNextDamage()) {
  8032.             restDamage = restDamage - this.getPreventNextDamage();
  8033.             this.setPreventNextDamage(0);
  8034.         } else {
  8035.             this.setPreventNextDamage(this.getPreventNextDamage() - restDamage);
  8036.             restDamage = 0;
  8037.         }
  8038.  
  8039.         if (this.getName().equals("Phyrexian Hydra")) {
  8040.             this.addCounter(Counters.M1M1, restDamage);
  8041.             return 0;
  8042.         }
  8043.  
  8044.         return restDamage;
  8045.     }
  8046.  
  8047.     // This should be also usable by the AI to forecast an effect (so it must
  8048.     // not change the game state)
  8049.     /**
  8050.      * <p>
  8051.      * staticReplaceDamage.
  8052.      * </p>
  8053.      *
  8054.      * @param damage
  8055.      *            a int.
  8056.      * @param source
  8057.      *            a {@link forge.Card} object.
  8058.      * @param isCombat
  8059.      *            a boolean.
  8060.      * @return a int.
  8061.      */
  8062.     @Override
  8063.     public final int staticReplaceDamage(final int damage, final Card source, final boolean isCombat) {
  8064.  
  8065.         int restDamage = damage;
  8066.  
  8067.         if (AllZoneUtil.isCardInPlay("Sulfuric Vapors") && source.isSpell() && source.isRed()) {
  8068.             final int amount = AllZoneUtil.getCardsIn(Zone.Battlefield, "Sulfuric Vapors").size();
  8069.             for (int i = 0; i < amount; i++) {
  8070.                 restDamage += 1;
  8071.             }
  8072.         }
  8073.  
  8074.         if (AllZoneUtil.isCardInPlay("Pyromancer's Swath", source.getController())
  8075.                 && (source.isInstant() || source.isSorcery()) && this.isCreature()) {
  8076.             final int amount = source.getController().getCardsIn(Zone.Battlefield, "Pyromancer's Swath").size();
  8077.             for (int i = 0; i < amount; i++) {
  8078.                 restDamage += 2;
  8079.             }
  8080.         }
  8081.  
  8082.         if (AllZoneUtil.isCardInPlay("Furnace of Rath") && this.isCreature()) {
  8083.             final int amount = AllZoneUtil.getCardsIn(Zone.Battlefield, "Furnace of Rath").size();
  8084.             for (int i = 0; i < amount; i++) {
  8085.                 restDamage += restDamage;
  8086.             }
  8087.         }
  8088.  
  8089.         if (AllZoneUtil.isCardInPlay("Gratuitous Violence", source.getController()) && source.isCreature()
  8090.                 && this.isCreature()) {
  8091.             final int amount = source.getController().getCardsIn(Zone.Battlefield, "Gratuitous Violence").size();
  8092.             for (int i = 0; i < amount; i++) {
  8093.                 restDamage += restDamage;
  8094.             }
  8095.         }
  8096.  
  8097.         if (AllZoneUtil.isCardInPlay("Fire Servant", source.getController()) && source.isRed()
  8098.                 && (source.isInstant() || source.isSorcery())) {
  8099.             final int amount = source.getController().getCardsIn(Zone.Battlefield, "Fire Servant").size();
  8100.             for (int i = 0; i < amount; i++) {
  8101.                 restDamage += restDamage;
  8102.             }
  8103.         }
  8104.  
  8105.         if (AllZoneUtil.isCardInPlay("Benevolent Unicorn") && source.isSpell() && this.isCreature()) {
  8106.             final int amount = AllZoneUtil.getCardsIn(Zone.Battlefield, "Benevolent Unicorn").size();
  8107.             for (int i = 0; i < amount; i++) {
  8108.                 if (restDamage > 0) {
  8109.                     restDamage -= 1;
  8110.                 }
  8111.             }
  8112.         }
  8113.  
  8114.         if (AllZoneUtil.isCardInPlay("Lashknife Barrier", this.getController()) && this.isCreature()) {
  8115.             final int amount = this.getController().getCardsIn(Zone.Battlefield, "Lashknife Barrier").size();
  8116.             for (int i = 0; i < amount; i++) {
  8117.                 if (restDamage > 0) {
  8118.                     restDamage -= 1;
  8119.                 }
  8120.             }
  8121.         }
  8122.  
  8123.         if (AllZoneUtil.isCardInPlay("Divine Presence") && this.isCreature() && (restDamage > 3)) {
  8124.  
  8125.             restDamage = 3;
  8126.         }
  8127.  
  8128.         if (this.getName().equals("Phytohydra")) {
  8129.             return 0;
  8130.         }
  8131.  
  8132.         return restDamage;
  8133.     }
  8134.  
  8135.     /**
  8136.      * <p>
  8137.      * replaceDamage.
  8138.      * </p>
  8139.      *
  8140.      * @param damageIn
  8141.      *            a int.
  8142.      * @param source
  8143.      *            a {@link forge.Card} object.
  8144.      * @param isCombat
  8145.      *            a boolean.
  8146.      * @return a int.
  8147.      */
  8148.     @Override
  8149.     public final int replaceDamage(final int damageIn, final Card source, final boolean isCombat) {
  8150.         // Replacement effects
  8151.         final HashMap<String, Object> repParams = new HashMap<String, Object>();
  8152.         repParams.put("Event", "DamageDone");
  8153.         repParams.put("Affected", this);
  8154.         repParams.put("DamageSource", source);
  8155.         repParams.put("DamageAmount", damageIn);
  8156.         repParams.put("IsCombat", isCombat);
  8157.  
  8158.         if (AllZone.getReplacementHandler().run(repParams)) {
  8159.             return 0;
  8160.         }
  8161.  
  8162.         final CardList auras = new CardList(this.getEnchantedBy().toArray());
  8163.  
  8164.         if (auras.containsName("Treacherous Link")) {
  8165.             this.getController().addDamage(damageIn, source);
  8166.             return 0;
  8167.         }
  8168.  
  8169.         return damageIn;
  8170.     }
  8171.  
  8172.     /**
  8173.      * <p>
  8174.      * addDamage.
  8175.      * </p>
  8176.      *
  8177.      * @param sourcesMap
  8178.      *            a {@link java.util.Map} object.
  8179.      */
  8180.     public final void addDamage(final Map<Card, Integer> sourcesMap) {
  8181.         for (final Entry<Card, Integer> entry : sourcesMap.entrySet()) {
  8182.             // damage prevention is already checked!
  8183.             this.addDamageAfterPrevention(entry.getValue(), entry.getKey(), true);
  8184.         }
  8185.     }
  8186.  
  8187.     /**
  8188.      * <p>
  8189.      * addDamageAfterPrevention.
  8190.      * </p>
  8191.      * This function handles damage after replacement and prevention effects are
  8192.      * applied.
  8193.      *
  8194.      * @param damageIn
  8195.      *            a int.
  8196.      * @param source
  8197.      *            a {@link forge.Card} object.
  8198.      * @param isCombat
  8199.      *            a boolean.
  8200.      */
  8201.     @Override
  8202.     public final void addDamageAfterPrevention(final int damageIn, final Card source, final boolean isCombat) {
  8203.         final int damageToAdd = damageIn;
  8204.         boolean wither = false;
  8205.  
  8206.         if (damageToAdd == 0) {
  8207.             return; // Rule 119.8
  8208.         }
  8209.  
  8210.         System.out.println("Adding " + damageToAdd + " damage to " + this.getName());
  8211.         Log.debug("Adding " + damageToAdd + " damage to " + this.getName());
  8212.  
  8213.         this.addReceivedDamageFromThisTurn(source, damageToAdd);
  8214.         source.addDealtDamageToThisTurn(this, damageToAdd);
  8215.  
  8216.         GameActionUtil.executeDamageDealingEffects(source, damageToAdd);
  8217.  
  8218.         // Run triggers
  8219.         final Map<String, Object> runParams = new TreeMap<String, Object>();
  8220.         runParams.put("DamageSource", source);
  8221.         runParams.put("DamageTarget", this);
  8222.         runParams.put("DamageAmount", damageToAdd);
  8223.         runParams.put("IsCombatDamage", isCombat);
  8224.         AllZone.getTriggerHandler().runTrigger("DamageDone", runParams);
  8225.  
  8226.         if (this.isPlaneswalker()) {
  8227.             this.subtractCounter(Counters.LOYALTY, damageToAdd);
  8228.             return;
  8229.         }
  8230.  
  8231.         if ((source.hasKeyword("Wither") || source.hasKeyword("Infect"))) {
  8232.             wither = true;
  8233.         }
  8234.  
  8235.         GameActionUtil.executeDamageToCreatureEffects(source, this, damageToAdd);
  8236.  
  8237.         if (AllZoneUtil.isCardInPlay(this) && wither) {
  8238.             this.addCounter(Counters.M1M1, damageToAdd);
  8239.         }
  8240.         if (source.hasKeyword("Deathtouch") && this.isCreature()) {
  8241.             AllZone.getGameAction().destroy(this);
  8242.         } else if (AllZoneUtil.isCardInPlay(this) && !wither) {
  8243.             this.damage += damageToAdd;
  8244.         }
  8245.  
  8246.     }
  8247.  
  8248.     private String curSetCode = "";
  8249.  
  8250.     /**
  8251.      * <p>
  8252.      * addSet.
  8253.      * </p>
  8254.      *
  8255.      * @param sInfo
  8256.      *            a {@link forge.SetInfo} object.
  8257.      */
  8258.     public final void addSet(final SetInfo sInfo) {
  8259.         this.getCharacteristics().getSets().add(sInfo);
  8260.     }
  8261.  
  8262.     /**
  8263.      * <p>
  8264.      * getSets.
  8265.      * </p>
  8266.      *
  8267.      * @return a {@link java.util.ArrayList} object.
  8268.      */
  8269.     public final ArrayList<SetInfo> getSets() {
  8270.         return this.getCharacteristics().getSets();
  8271.     }
  8272.  
  8273.     /**
  8274.      * <p>
  8275.      * setSets.
  8276.      * </p>
  8277.      *
  8278.      * @param siList
  8279.      *            a {@link java.util.ArrayList} object.
  8280.      */
  8281.     public final void setSets(final ArrayList<SetInfo> siList) {
  8282.         this.getCharacteristics().setSets(siList);
  8283.     }
  8284.  
  8285.     /**
  8286.      * <p>
  8287.      * Setter for the field <code>curSetCode</code>.
  8288.      * </p>
  8289.      *
  8290.      * @param setCode
  8291.      *            a {@link java.lang.String} object.
  8292.      */
  8293.     public final void setCurSetCode(final String setCode) {
  8294.         this.curSetCode = setCode;
  8295.     }
  8296.  
  8297.     /**
  8298.      * <p>
  8299.      * Getter for the field <code>curSetCode</code>.
  8300.      * </p>
  8301.      *
  8302.      * @return a {@link java.lang.String} object.
  8303.      */
  8304.     public final String getCurSetCode() {
  8305.         return this.curSetCode;
  8306.     }
  8307.  
  8308.     /**
  8309.      * <p>
  8310.      * setRandomSetCode.
  8311.      * </p>
  8312.      */
  8313.     public final void setRandomSetCode() {
  8314.         if (this.getCharacteristics().getSets().size() < 1) {
  8315.             return;
  8316.         }
  8317.  
  8318.         final Random r = MyRandom.getRandom();
  8319.         final SetInfo si = this.getCharacteristics().getSets()
  8320.                 .get(r.nextInt(this.getCharacteristics().getSets().size()));
  8321.  
  8322.         this.curSetCode = si.getCode();
  8323.     }
  8324.  
  8325.     /**
  8326.      * <p>
  8327.      * getSetImageName.
  8328.      * </p>
  8329.      *
  8330.      * @param setCode
  8331.      *            a {@link java.lang.String} object.
  8332.      * @return a {@link java.lang.String} object.
  8333.      */
  8334.     public final String getSetImageName(final String setCode) {
  8335.         return "/" + setCode + "/" + this.getImageName();
  8336.     }
  8337.  
  8338.     /**
  8339.      * <p>
  8340.      * getCurSetImage.
  8341.      * </p>
  8342.      *
  8343.      * @return a {@link java.lang.String} object.
  8344.      */
  8345.     public final String getCurSetImage() {
  8346.         return this.getSetImageName(this.curSetCode);
  8347.     }
  8348.  
  8349.     /**
  8350.      * <p>
  8351.      * getCurSetRarity.
  8352.      * </p>
  8353.      *
  8354.      * @return a {@link java.lang.String} object.
  8355.      */
  8356.     public final String getCurSetRarity() {
  8357.         for (int i = 0; i < this.getCharacteristics().getSets().size(); i++) {
  8358.             if (this.getCharacteristics().getSets().get(i).getCode().equals(this.curSetCode)) {
  8359.                 return this.getCharacteristics().getSets().get(i).getRarity();
  8360.             }
  8361.         }
  8362.  
  8363.         return "";
  8364.     }
  8365.  
  8366.     /**
  8367.      * <p>
  8368.      * getCurSetURL.
  8369.      * </p>
  8370.      *
  8371.      * @return a {@link java.lang.String} object.
  8372.      */
  8373.     public final String getCurSetURL() {
  8374.         for (int i = 0; i < this.getCharacteristics().getSets().size(); i++) {
  8375.             if (this.getCharacteristics().getSets().get(i).getCode().equals(this.curSetCode)) {
  8376.                 return this.getCharacteristics().getSets().get(i).getUrl();
  8377.             }
  8378.         }
  8379.  
  8380.         return "";
  8381.     }
  8382.  
  8383.     /**
  8384.      * <p>
  8385.      * getMostRecentSet.
  8386.      * </p>
  8387.      *
  8388.      * @return a {@link java.lang.String} object.
  8389.      */
  8390.     public final String getMostRecentSet() {
  8391.         return CardDb.instance().getCard(this.getName()).getSet();
  8392.     }
  8393.  
  8394.     /**
  8395.      * <p>
  8396.      * setImageFilename.
  8397.      * </p>
  8398.      *
  8399.      * @param iFN
  8400.      *            a {@link java.lang.String} object.
  8401.      */
  8402.     public final void setImageFilename(final String iFN) {
  8403.         this.getCharacteristics().setImageFilename(iFN);
  8404.     }
  8405.  
  8406.     /**
  8407.      * <p>
  8408.      * getImageFilename.
  8409.      * </p>
  8410.      *
  8411.      * @return a {@link java.lang.String} object.
  8412.      */
  8413.     public final String getImageFilename() {
  8414.         return this.getCharacteristics().getImageFilename();
  8415.     }
  8416.  
  8417.     /**
  8418.      * <p>
  8419.      * Setter for the field <code>evoked</code>.
  8420.      * </p>
  8421.      *
  8422.      * @param evokedIn
  8423.      *            a boolean.
  8424.      */
  8425.     public final void setEvoked(final boolean evokedIn) {
  8426.         this.evoked = evokedIn;
  8427.     }
  8428.  
  8429.     /**
  8430.      * <p>
  8431.      * isEvoked.
  8432.      * </p>
  8433.      *
  8434.      * @return a boolean.
  8435.      */
  8436.     public final boolean isEvoked() {
  8437.         return this.evoked;
  8438.     }
  8439.  
  8440.     /**
  8441.      *
  8442.      * TODO Write javadoc for this method.
  8443.      *
  8444.      * @param t
  8445.      *            a long
  8446.      */
  8447.     public final void setTimestamp(final long t) {
  8448.         this.timestamp = t;
  8449.     }
  8450.  
  8451.     /**
  8452.      *
  8453.      * TODO Write javadoc for this method.
  8454.      *
  8455.      * @return a long
  8456.      */
  8457.     public final long getTimestamp() {
  8458.         return this.timestamp;
  8459.     }
  8460.  
  8461.     /**
  8462.      *
  8463.      * TODO Write javadoc for this method.
  8464.      *
  8465.      * @return an int
  8466.      */
  8467.     public final int getFoil() {
  8468.         if (this.sVars.containsKey("Foil")) {
  8469.             return Integer.parseInt(this.sVars.get("Foil"));
  8470.         }
  8471.         return 0;
  8472.     }
  8473.  
  8474.     /**
  8475.      *
  8476.      * TODO Write javadoc for this method.
  8477.      *
  8478.      * @param f
  8479.      *            an int
  8480.      */
  8481.     public final void setFoil(final int f) {
  8482.         this.sVars.put("Foil", Integer.toString(f));
  8483.     }
  8484.  
  8485.     /**
  8486.      * Adds the haunted by.
  8487.      *
  8488.      * @param c
  8489.      *            the c
  8490.      */
  8491.     public final void addHauntedBy(final Card c) {
  8492.         this.hauntedBy.add(c);
  8493.         if (c != null) {
  8494.             c.setHaunting(this);
  8495.         }
  8496.     }
  8497.  
  8498.     /**
  8499.      * Gets the haunted by.
  8500.      *
  8501.      * @return the haunted by
  8502.      */
  8503.     public final ArrayList<Card> getHauntedBy() {
  8504.         return this.hauntedBy;
  8505.     }
  8506.  
  8507.     /**
  8508.      * Removes the haunted by.
  8509.      *
  8510.      * @param c
  8511.      *            the c
  8512.      */
  8513.     public final void removeHauntedBy(final Card c) {
  8514.         this.hauntedBy.remove(c);
  8515.     }
  8516.  
  8517.     /**
  8518.      * Gets the haunting.
  8519.      *
  8520.      * @return the haunting
  8521.      */
  8522.     public final Card getHaunting() {
  8523.         return this.haunting;
  8524.     }
  8525.  
  8526.     /**
  8527.      * Sets the haunting.
  8528.      *
  8529.      * @param c
  8530.      *            the new haunting
  8531.      */
  8532.     public final void setHaunting(final Card c) {
  8533.         this.haunting = c;
  8534.     }
  8535.  
  8536.     /**
  8537.      * Gets the damage done this turn.
  8538.      *
  8539.      * @return the damage done this turn
  8540.      */
  8541.     public final int getDamageDoneThisTurn() {
  8542.         int sum = 0;
  8543.         for (final Card c : this.dealtDamageToThisTurn.keySet()) {
  8544.             sum += this.dealtDamageToThisTurn.get(c);
  8545.         }
  8546.  
  8547.         return sum;
  8548.     }
  8549.  
  8550.     /**
  8551.      * Checks if is card colors overridden.
  8552.      *
  8553.      * @return the cardColorsOverridden
  8554.      */
  8555.     public final boolean isCardColorsOverridden() {
  8556.         return this.getCharacteristics().isCardColorsOverridden();
  8557.     }
  8558.  
  8559.     /**
  8560.      * Sets the card colors overridden.
  8561.      *
  8562.      * @param cardColorsOverridden0
  8563.      *            the cardColorsOverridden to set
  8564.      */
  8565.     public final void setCardColorsOverridden(final boolean cardColorsOverridden0) {
  8566.         this.getCharacteristics().setCardColorsOverridden(cardColorsOverridden0);
  8567.     }
  8568.  
  8569.     /*
  8570.      * (non-Javadoc)
  8571.      *
  8572.      * @see forge.GameEntity#hasProtectionFrom(forge.Card)
  8573.      */
  8574.     @Override
  8575.     public boolean hasProtectionFrom(final Card source) {
  8576.         if (source == null) {
  8577.             return false;
  8578.         }
  8579.  
  8580.         if (this.isImmutable()) {
  8581.             return true;
  8582.         }
  8583.  
  8584.         if (this.getKeyword() != null) {
  8585.             final ArrayList<String> list = this.getKeyword();
  8586.  
  8587.             String kw = "";
  8588.             for (int i = 0; i < list.size(); i++) {
  8589.                 kw = list.get(i);
  8590.  
  8591.                 if (kw.equals("Protection from white") && source.isWhite() && !source.getName().contains("White Ward")) {
  8592.                     return true;
  8593.                 }
  8594.                 if (kw.equals("Protection from blue") && source.isBlue() && !source.getName().contains("Blue Ward")) {
  8595.                     return true;
  8596.                 }
  8597.                 if (kw.equals("Protection from black") && source.isBlack() && !source.getName().contains("Black Ward")) {
  8598.                     return true;
  8599.                 }
  8600.                 if (kw.equals("Protection from red") && source.isRed() && !source.getName().contains("Red Ward")) {
  8601.                     return true;
  8602.                 }
  8603.                 if (kw.equals("Protection from green") && source.isGreen() && !source.getName().contains("Green Ward")) {
  8604.                     return true;
  8605.                 }
  8606.  
  8607.                 if (kw.equals("Protection from creatures") && source.isCreature()) {
  8608.                     return true;
  8609.                 }
  8610.  
  8611.                 if (kw.equals("Protection from artifacts") && source.isArtifact()) {
  8612.                     return true;
  8613.                 }
  8614.  
  8615.                 if (kw.equals("Protection from enchantments") && source.isEnchantment()
  8616.                         && !source.getName().contains("Tattoo Ward")) {
  8617.                     return true;
  8618.                 }
  8619.  
  8620.                 if (kw.equals("Protection from everything")) {
  8621.                     return true;
  8622.                 }
  8623.  
  8624.                 if (kw.equals("Protection from colored spells")
  8625.                         && (source.isInstant() || source.isSorcery() || source.isAura())
  8626.                         && CardFactoryUtil.isColored(source)) {
  8627.                     return true;
  8628.                 }
  8629.  
  8630.                 if (kw.equals("Protection from Dragons") && source.isType("Dragon")) {
  8631.                     return true;
  8632.                 }
  8633.                 if (kw.equals("Protection from Demons") && source.isType("Demon")) {
  8634.                     return true;
  8635.                 }
  8636.                 if (kw.equals("Protection from Goblins") && source.isType("Goblin")) {
  8637.                     return true;
  8638.                 }
  8639.                 if (kw.equals("Protection from Clerics") && source.isType("Cleric")) {
  8640.                     return true;
  8641.                 }
  8642.                 if (kw.equals("Protection from Gorgons") && source.isType("Gorgon")) {
  8643.                     return true;
  8644.                 }
  8645.  
  8646.                 if (kw.startsWith("Protection:")) { // uses isValid
  8647.                     final String characteristic = kw.split(":")[1];
  8648.                     final String[] characteristics = characteristic.split(",");
  8649.                     if (source.isValid(characteristics, this.getController(), this)) {
  8650.                         return true;
  8651.                     }
  8652.                 }
  8653.  
  8654.             }
  8655.         }
  8656.         return false;
  8657.     }
  8658.  
  8659.     /**
  8660.      *
  8661.      * is In Zone.
  8662.      *
  8663.      * @param zone
  8664.      *            Constant.Zone
  8665.      * @return boolean
  8666.      */
  8667.     public boolean isInZone(final Constant.Zone zone) {
  8668.         return AllZone.isCardInZone(this, zone);
  8669.     }
  8670.  
  8671.     /**
  8672.      * Can target.
  8673.      *
  8674.      * @param sa
  8675.      *            the sa
  8676.      * @return a boolean
  8677.      */
  8678.     @Override
  8679.     public final boolean canBeTargetedBy(final SpellAbility sa) {
  8680.  
  8681.         if (sa == null) {
  8682.             return true;
  8683.         }
  8684.  
  8685.         // CantTarget static abilities
  8686.         final CardList allp = AllZoneUtil.getCardsIn(Zone.Battlefield);
  8687.         for (final Card ca : allp) {
  8688.             final ArrayList<StaticAbility> staticAbilities = ca.getStaticAbilities();
  8689.             for (final StaticAbility stAb : staticAbilities) {
  8690.                 if (stAb.applyAbility("CantTarget", this, sa)) {
  8691.                     return false;
  8692.                 }
  8693.             }
  8694.         }
  8695.  
  8696.         // keywords don't work outside battlefield
  8697.         if (!this.isInZone(Constant.Zone.Battlefield)) {
  8698.             return true;
  8699.         }
  8700.  
  8701.         if (this.hasProtectionFrom(sa.getSourceCard())) {
  8702.             return false;
  8703.         }
  8704.  
  8705.         if (this.getKeyword() != null) {
  8706.             final ArrayList<String> list = this.getKeyword();
  8707.             final Card source = sa.getSourceCard();
  8708.  
  8709.             String kw = "";
  8710.             for (int i = 0; i < list.size(); i++) {
  8711.                 kw = list.get(i);
  8712.                 if (kw.equals("Shroud")) {
  8713.                     return false;
  8714.                 }
  8715.  
  8716.                 if (kw.equals("Hexproof")) {
  8717.                     if (!sa.getActivatingPlayer().equals(this.getController())) {
  8718.                         return false;
  8719.                     }
  8720.                 }
  8721.  
  8722.                 if (kw.equals("CARDNAME can't be the target of Aura spells.")
  8723.                         || kw.equals("CARDNAME can't be enchanted.")) {
  8724.                     if (source.isAura() && sa.isSpell()) {
  8725.                         return false;
  8726.                     }
  8727.                 }
  8728.  
  8729.                 if (kw.equals("CARDNAME can't be the target of red spells or abilities from red sources.")) {
  8730.                     if (source.isRed()) {
  8731.                         return false;
  8732.                     }
  8733.                 }
  8734.  
  8735.                 if (kw.equals("CARDNAME can't be the target of black spells.")) {
  8736.                     if (source.isBlack() && sa.isSpell()) {
  8737.                         return false;
  8738.                     }
  8739.                 }
  8740.  
  8741.                 if (kw.equals("CARDNAME can't be the target of blue spells.")) {
  8742.                     if (source.isBlue() && sa.isSpell()) {
  8743.                         return false;
  8744.                     }
  8745.                 }
  8746.  
  8747.                 if (kw.equals("CARDNAME can't be the target of spells.")) {
  8748.                     if (sa.isSpell()) {
  8749.                         return false;
  8750.                     }
  8751.                 }
  8752.             }
  8753.         }
  8754.         return true;
  8755.     }
  8756.  
  8757.     /**
  8758.      * Gets the replacement effects.
  8759.      *
  8760.      * @return the replacement effects
  8761.      */
  8762.     public ArrayList<ReplacementEffect> getReplacementEffects() {
  8763.         return this.getCharacteristics().getReplacementEffects();
  8764.     }
  8765.  
  8766.     /**
  8767.      * Sets the replacement effects.
  8768.      *
  8769.      * @param res
  8770.      *            the new replacement effects
  8771.      */
  8772.     public void setReplacementEffects(final ArrayList<ReplacementEffect> res) {
  8773.         this.getCharacteristics().getReplacementEffects().clear();
  8774.         for (final ReplacementEffect replacementEffect : res) {
  8775.             this.addReplacementEffect(replacementEffect);
  8776.         }
  8777.     }
  8778.  
  8779.     /**
  8780.      * Adds the replacement effect.
  8781.      *
  8782.      * @param replacementEffect
  8783.      *            the rE
  8784.      */
  8785.     public void addReplacementEffect(final ReplacementEffect replacementEffect) {
  8786.         final ReplacementEffect replacementEffectCopy = replacementEffect.getCopy();
  8787.         replacementEffectCopy.setHostCard(this);
  8788.         this.getCharacteristics().getReplacementEffects().add(replacementEffectCopy);
  8789.     }
  8790.  
  8791.     /**
  8792.      * Returns what zone this card was cast from (from what zone it was moved to
  8793.      * the stack).
  8794.      *
  8795.      * @return the castFrom
  8796.      */
  8797.     public Zone getCastFrom() {
  8798.         return this.castFrom;
  8799.     }
  8800.  
  8801.     /**
  8802.      * @param castFrom0
  8803.      *            the castFrom to set
  8804.      */
  8805.     public void setCastFrom(final Zone castFrom0) {
  8806.         this.castFrom = castFrom0;
  8807.     }
  8808.  
  8809. } // end Card class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement