mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
- Convert Ancestral Vision to AF_Draw and remove from AI decks since Suspend currently returns false.
2896 lines
94 KiB
Java
2896 lines
94 KiB
Java
|
|
package forge;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.Hashtable;
|
|
import java.util.Iterator;
|
|
import java.util.Random;
|
|
import java.util.Map.Entry;
|
|
|
|
import com.esotericsoftware.minlog.Log;
|
|
|
|
public class Card extends MyObservable {
|
|
private static int nextUniqueNumber;
|
|
private int uniqueNumber = nextUniqueNumber++;
|
|
|
|
private long value;
|
|
|
|
//private Collection keyword = new TreeSet();
|
|
//private ArrayList<String> keyword = new ArrayList<String>();
|
|
private ArrayList<String> intrinsicAbility = new ArrayList<String>();
|
|
private ArrayList<String> intrinsicKeyword = new ArrayList<String>();
|
|
private ArrayList<String> extrinsicKeyword = new ArrayList<String>();
|
|
private ArrayList<String> otherExtrinsicKeyword = new ArrayList<String>();
|
|
private ArrayList<String> HiddenExtrinsicKeyword = new ArrayList<String>(); //Hidden keywords won't be displayed on the card
|
|
private ArrayList<String> prevIntrinsicKeyword = new ArrayList<String>();
|
|
private ArrayList<Card> attached = new ArrayList<Card>();
|
|
private ArrayList<Card> equippedBy = new ArrayList<Card>(); //which equipment cards are equipping this card?
|
|
//equipping size will always be 0 or 1
|
|
private ArrayList<Card> equipping = new ArrayList<Card>(); //if this card is of the type equipment, what card is it currently equipping?
|
|
private ArrayList<Card> enchantedBy = new ArrayList<Card>(); //which auras enchanted this card?
|
|
//enchanting size will always be 0 or 1
|
|
private ArrayList<Card> enchanting = new ArrayList<Card>(); //if this card is an Aura, what card is it enchanting?
|
|
private ArrayList<String> type = new ArrayList<String>();
|
|
private ArrayList<String> prevType = new ArrayList<String>();
|
|
private ArrayList<String> ChoicesMade = new ArrayList<String>();
|
|
private ArrayList<String> Targets_for_Choices = new ArrayList<String>();
|
|
private ArrayList<SpellAbility> spellAbility = new ArrayList<SpellAbility>();
|
|
private ArrayList<Ability_Mana> manaAbility = new ArrayList<Ability_Mana>();
|
|
private ArrayList<Card_Color> cardColor = new ArrayList<Card_Color>();
|
|
|
|
private HashMap<Card, Integer> receivedDamageFromThisTurn = new HashMap<Card, Integer>();
|
|
private HashMap<Card, Integer> assignedDamageHashMap = new HashMap<Card, Integer>();
|
|
|
|
private boolean unCastable;
|
|
private boolean drawnThisTurn = false;
|
|
private boolean tapped;
|
|
private boolean sickness = true; //summoning sickness
|
|
private boolean token = false;
|
|
private boolean copiedToken = false;
|
|
private boolean copiedSpell = false;
|
|
private boolean SpellwithChoices = false;
|
|
private boolean SpellCopyingCard = false;
|
|
private boolean creatureAttackedThisCombat = false;
|
|
private boolean creatureBlockedThisCombat = false;
|
|
private boolean creatureGotBlockedThisCombat = false;
|
|
private boolean dealtCombatDmgToOppThisTurn = false;
|
|
private boolean dealtDmgToOppThisTurn = false;
|
|
private boolean sirenAttackOrDestroy = false;
|
|
private boolean exaltedBonus = false;
|
|
private boolean faceDown = false;
|
|
private boolean sacrificeAtEOT = false;
|
|
private boolean kicked = false;
|
|
private boolean reflectedLand = false;
|
|
private boolean levelUp = false;
|
|
private boolean bounceAtUntap = false;
|
|
private boolean finishedEnteringBF = false;
|
|
|
|
private boolean firstStrike = false;
|
|
private boolean doubleStrike = false;
|
|
|
|
private boolean flashback = false;
|
|
private boolean unearth = false;
|
|
private boolean unearthed;
|
|
|
|
private boolean madness = false;
|
|
private boolean suspendCast = false;
|
|
private boolean suspend = false;
|
|
|
|
//for Vanguard / Manapool / Emblems etc.
|
|
private boolean isImmutable = false;
|
|
|
|
private int exaltedMagnitude = 0;
|
|
|
|
private int baseAttack;
|
|
private int baseDefense;
|
|
|
|
private int damage;
|
|
|
|
private int nShield;
|
|
private int preventNextDamage = 0;
|
|
|
|
private int turnInZone;
|
|
|
|
private int tempAttackBoost = 0;
|
|
private int tempDefenseBoost = 0;
|
|
|
|
private int semiPermanentAttackBoost = 0;
|
|
private int semiPermanentDefenseBoost = 0;
|
|
|
|
private int otherAttackBoost = 0;
|
|
private int otherDefenseBoost = 0;
|
|
|
|
private int randomPicture = 0;
|
|
|
|
private int upkeepDamage = 0;
|
|
|
|
private int X = 0;
|
|
|
|
private int xManaCostPaid = 0;
|
|
|
|
private int multiKickerMagnitude = 0;
|
|
|
|
private Player owner = null;
|
|
private Player controller = null;
|
|
private String name = "";
|
|
private String imageName = "";
|
|
private String rarity = "";
|
|
private String text = "";
|
|
private String manaCost = "";
|
|
private String upkeepCost = "";
|
|
private String tabernacleUpkeepCost = "";
|
|
private String magusTabernacleUpkeepCost = "";
|
|
private String echoCost = "";
|
|
private String madnessCost = "";
|
|
private String chosenType = "";
|
|
private String chosenColor = "";
|
|
private String namedCard = "";
|
|
private String topCardName = "";
|
|
private String reflectableMana = "";
|
|
private ArrayList<Card> gainControlTargets = new ArrayList<Card>();
|
|
private ArrayList<Command> gainControlReleaseCommands = new ArrayList<Command>();;
|
|
|
|
|
|
private ArrayList<Ability_Triggered> zcTriggers = new ArrayList<Ability_Triggered>();
|
|
/*private ArrayList<Command> comesIntoPlayCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> destroyCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> leavesPlayCommandList = new ArrayList<Command>();*/
|
|
private ArrayList<Command> turnFaceUpCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> equipCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> unEquipCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> enchantCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> unEnchantCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> untapCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> changeControllerCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> replaceMoveToGraveyardCommandList = new ArrayList<Command>();
|
|
private ArrayList<Command> cycleCommandList = new ArrayList<Command>();
|
|
|
|
private Hashtable<Counters, Integer> counters = new Hashtable<Counters, Integer>();
|
|
private Hashtable<String, String> SVars = new Hashtable<String, String>();
|
|
|
|
//hacky code below, used to limit the number of times an ability
|
|
//can be used per turn like Vampire Bats
|
|
//should be put in SpellAbility, but it is put here for convienance
|
|
//this is make public just to make things easy
|
|
//this code presumes that each card only has one ability that can be
|
|
//used a limited number of times per turn
|
|
//CardFactory.SSP_canPlay(Card) uses these variables
|
|
|
|
private int abilityTurnUsed; //What turn did this card last use this ability?
|
|
private int abilityUsed; //How many times has this ability been used?
|
|
|
|
public void setAbilityTurnUsed(int i) {
|
|
abilityTurnUsed = i;
|
|
}
|
|
|
|
public int getAbilityTurnUsed() {
|
|
return abilityTurnUsed;
|
|
}
|
|
|
|
public void setAbilityUsed(int i) {
|
|
abilityUsed = i;
|
|
}
|
|
|
|
public int getAbilityUsed() {
|
|
return abilityUsed;
|
|
}
|
|
|
|
//****************TOhaveDOne:Use somehow
|
|
public void setX(int i) {
|
|
X = i;
|
|
}
|
|
|
|
public int getX() {
|
|
return X;
|
|
}
|
|
|
|
//***************/
|
|
|
|
public void addXManaCostPaid(int n)
|
|
{
|
|
xManaCostPaid += n;
|
|
}
|
|
|
|
public void setXManaCostPaid(int n)
|
|
{
|
|
xManaCostPaid = n;
|
|
}
|
|
|
|
public int getXManaCostPaid()
|
|
{
|
|
return xManaCostPaid;
|
|
}
|
|
|
|
//used to see if an attacking creature with a triggering attack ability triggered this phase:
|
|
public void setCreatureAttackedThisCombat(boolean b) {
|
|
creatureAttackedThisCombat = b;
|
|
}
|
|
|
|
public boolean getCreatureAttackedThisCombat() {
|
|
return creatureAttackedThisCombat;
|
|
}
|
|
|
|
public void setCreatureBlockedThisCombat(boolean b) {
|
|
creatureBlockedThisCombat = b;
|
|
}
|
|
|
|
public boolean getCreatureBlockedThisCombat() {
|
|
return creatureBlockedThisCombat;
|
|
}
|
|
|
|
public void setCreatureGotBlockedThisCombat(boolean b) {
|
|
creatureGotBlockedThisCombat = b;
|
|
}
|
|
|
|
public boolean getCreatureGotBlockedThisCombat() {
|
|
return creatureGotBlockedThisCombat;
|
|
}
|
|
|
|
public void setDealtCombatDmgToOppThisTurn(boolean b) {
|
|
dealtCombatDmgToOppThisTurn = b;
|
|
}
|
|
|
|
public boolean getDealtCombatDmgToOppThisTurn() {
|
|
return dealtCombatDmgToOppThisTurn;
|
|
}
|
|
|
|
public boolean canAnyPlayerActivate() {
|
|
for(SpellAbility s : spellAbility)
|
|
{
|
|
if (s.getRestrictions().getAnyPlayer())
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void setDealtDmgToOppThisTurn(boolean b) {
|
|
dealtDmgToOppThisTurn = b;
|
|
}
|
|
|
|
public boolean getDealtDmgToOppThisTurn() {
|
|
return dealtDmgToOppThisTurn;
|
|
}
|
|
|
|
public void setSirenAttackOrDestroy(boolean b) {
|
|
sirenAttackOrDestroy = b;
|
|
}
|
|
|
|
public boolean getSirenAttackOrDestroy() {
|
|
return sirenAttackOrDestroy;
|
|
}
|
|
|
|
public boolean getSacrificeAtEOT() {
|
|
return sacrificeAtEOT || getKeyword().contains("At the beginning of the end step, sacrifice CARDNAME.");
|
|
}
|
|
|
|
public void setSacrificeAtEOT(boolean sacrificeAtEOT) {
|
|
this.sacrificeAtEOT = sacrificeAtEOT;
|
|
}
|
|
|
|
public boolean getBounceAtUntap() {
|
|
return bounceAtUntap;
|
|
}
|
|
|
|
public void setBounceAtUntap(boolean bounce) {
|
|
this.bounceAtUntap = bounce;
|
|
}
|
|
|
|
public boolean getFinishedEnteringBF() {
|
|
return finishedEnteringBF;
|
|
}
|
|
|
|
public void setFinishedEnteringBF(boolean b) {
|
|
this.finishedEnteringBF = b;
|
|
}
|
|
|
|
public boolean hasFirstStrike() {
|
|
return firstStrike || getKeyword().contains("First Strike");
|
|
}
|
|
|
|
public void setFirstStrike(boolean firstStrike) {
|
|
this.firstStrike = firstStrike;
|
|
}
|
|
|
|
public void setDoubleStrike(boolean doubleStrike) {
|
|
this.doubleStrike = doubleStrike;
|
|
}
|
|
|
|
public boolean hasDoubleStrike() {
|
|
return doubleStrike || getKeyword().contains("Double Strike");
|
|
}
|
|
|
|
public boolean hasSecondStrike() {
|
|
return !hasFirstStrike() || (hasFirstStrike() && hasDoubleStrike());
|
|
};
|
|
|
|
//for Planeswalker abilities and Combat Damage (like Wither), Doubling Season gets ignored.
|
|
public void addCounterFromNonEffect(Counters counterName, int n) {
|
|
if(counters.containsKey(counterName)) {
|
|
Integer aux = counters.get(counterName) + n;
|
|
counters.put(counterName, aux);
|
|
} else {
|
|
counters.put(counterName, Integer.valueOf(n));
|
|
}
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void addCounter(Counters counterName, int n) {
|
|
int multiplier = AllZoneUtil.getDoublingSeasonMagnitude(this.getController());
|
|
if(counters.containsKey(counterName)) {
|
|
Integer aux = counters.get(counterName) + (multiplier * n);
|
|
counters.put(counterName, aux);
|
|
} else {
|
|
counters.put(counterName, Integer.valueOf(multiplier * n));
|
|
}
|
|
|
|
if (counterName.equals(Counters.P1P1) || counterName.equals(Counters.M1M1)){
|
|
// +1/+1 counters should erase -1/-1 counters
|
|
int plusOneCounters = 0;
|
|
int minusOneCounters = 0;
|
|
|
|
Counters p1Counter = Counters.P1P1;
|
|
Counters m1Counter = Counters.M1M1;
|
|
if (counters.containsKey(p1Counter))
|
|
plusOneCounters = counters.get(p1Counter);
|
|
if (counters.containsKey(m1Counter))
|
|
minusOneCounters = counters.get(m1Counter);
|
|
|
|
if (plusOneCounters == minusOneCounters){
|
|
counters.remove(m1Counter);
|
|
counters.remove(p1Counter);
|
|
}
|
|
if (plusOneCounters > minusOneCounters){
|
|
counters.remove(m1Counter);
|
|
counters.put(p1Counter, (Integer)(plusOneCounters - minusOneCounters));
|
|
}
|
|
else{
|
|
counters.put(m1Counter, (Integer)(minusOneCounters - plusOneCounters));
|
|
counters.remove(p1Counter);
|
|
}
|
|
}
|
|
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void subtractCounter(Counters counterName, int n) {
|
|
if(counters.containsKey(counterName)) {
|
|
Integer aux = counters.get(counterName) - n;
|
|
if (aux < 0)
|
|
aux = 0;
|
|
counters.put(counterName, aux);
|
|
if(counterName.equals(Counters.TIME) && aux == 0)
|
|
{
|
|
boolean hasVanish = CardFactory.hasKeyword(this, "Vanishing") != -1;
|
|
|
|
if(hasVanish && AllZone.GameAction.isCardInPlay(this))
|
|
AllZone.GameAction.sacrifice(this);
|
|
if(hasSuspend() && AllZone.GameAction.isCardExiled(this))
|
|
{
|
|
final Card c = this;
|
|
|
|
c.setSuspendCast(true);
|
|
|
|
// TODO(sol): haste should wear off when player loses control. need to figure out where to add that.
|
|
Command intoPlay = new Command() {
|
|
private static final long serialVersionUID = -4514610171270596654L;
|
|
|
|
public void execute() {
|
|
if(AllZone.GameAction.isCardInPlay(c) && c.isCreature())
|
|
c.addExtrinsicKeyword("Haste");
|
|
}//execute()
|
|
};
|
|
|
|
c.addComesIntoPlayCommand(intoPlay);
|
|
AllZone.GameAction.playCardNoCost(c);
|
|
if (AllZone.getZone(c) != null)
|
|
AllZone.getZone(c).remove(c);
|
|
}
|
|
}
|
|
this.updateObservers();
|
|
}
|
|
}
|
|
|
|
public int getCounters(Counters counterName) {
|
|
if(counters.containsKey(counterName)) {
|
|
return counters.get(counterName);
|
|
} else return 0;
|
|
}
|
|
|
|
public boolean hasCounters()
|
|
{
|
|
return counters.size() > 0;
|
|
}
|
|
|
|
public void setCounter(Counters counterName, int n, boolean bSetValue) {
|
|
if (bSetValue) // sometimes you just need to set the value without being affected by DoublingSeason
|
|
counters.put(counterName, Integer.valueOf(n));
|
|
else{
|
|
int num = getCounters(counterName);
|
|
if(num < n) // if counters on card is less than the setting value, addCounters
|
|
addCounter(counterName, n - num);
|
|
else
|
|
subtractCounter(counterName, num - n);
|
|
}
|
|
this.updateObservers();
|
|
}
|
|
|
|
/**
|
|
* hasLevelUp() - checks to see if a creature has the "Level up" ability introduced in Rise of the Eldrazi
|
|
* @return true if this creature can "Level up", false otherwise
|
|
*/
|
|
public boolean hasLevelUp() {
|
|
return levelUp;
|
|
}
|
|
|
|
public void setLevelUp(boolean b)
|
|
{
|
|
levelUp = b;
|
|
}
|
|
|
|
public String getSVar(String Var) {
|
|
if(SVars.containsKey(Var)) return SVars.get(Var);
|
|
else return "";
|
|
}
|
|
|
|
public void setSVar(String Var, String str) {
|
|
if(SVars.containsKey(Var)) SVars.remove(Var);
|
|
|
|
SVars.put(Var, str);
|
|
}
|
|
|
|
public Hashtable<String, String> getSVars()
|
|
{
|
|
return SVars;
|
|
}
|
|
|
|
public void setSVars(Hashtable<String, String> newSVars)
|
|
{
|
|
SVars = newSVars;
|
|
}
|
|
|
|
public int sumAllCounters() {
|
|
Object[] values = counters.values().toArray();
|
|
int count = 0;
|
|
int num = 0;
|
|
for(int i = 0; i < values.length; i++) {
|
|
num = (Integer) values[i];
|
|
count += num;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public int getNetPTCounters() {
|
|
return getCounters(Counters.P1P1) - getCounters(Counters.M1M1);
|
|
}
|
|
|
|
public int getTurnInZone() {
|
|
return turnInZone;
|
|
}
|
|
|
|
public void setTurnInZone(int turn) {
|
|
turnInZone = turn;
|
|
}
|
|
|
|
public void setEchoCost(String s) {
|
|
echoCost = s;
|
|
}
|
|
|
|
public String getEchoCost() {
|
|
return echoCost;
|
|
}
|
|
|
|
public void setManaCost(String s) {
|
|
manaCost = s;
|
|
}
|
|
|
|
public String getManaCost() {
|
|
return manaCost;
|
|
}
|
|
|
|
public void addColor(String s){
|
|
if (s.equals(""))
|
|
s = "0";
|
|
cardColor.add(new Card_Color(new ManaCost(s), this, false, true));
|
|
}
|
|
|
|
public long addColor(String s, Card c, boolean addToColors, boolean bIncrease){
|
|
if (bIncrease)
|
|
Card_Color.increaseTimestamp();
|
|
cardColor.add(new Card_Color(new ManaCost(s), c, addToColors, false));
|
|
return Card_Color.getTimestamp();
|
|
}
|
|
|
|
public void removeColor(String s, Card c, boolean addTo, long timestamp){
|
|
Card_Color removeCol = null;
|
|
for(Card_Color cc : cardColor)
|
|
if (cc.equals(s, c, addTo, timestamp))
|
|
removeCol = cc;
|
|
|
|
if (removeCol != null)
|
|
cardColor.remove(removeCol);
|
|
}
|
|
|
|
public Card_Color getColor(){
|
|
if (this.isImmutable()){
|
|
return new Card_Color(this);
|
|
}
|
|
Card_Color colors = null;
|
|
ArrayList<Card_Color> globalChanges = AllZone.GameInfo.getColorChanges();
|
|
colors = determineColor(globalChanges);
|
|
colors.fixColorless();
|
|
return colors;
|
|
}
|
|
|
|
|
|
public void setColor(ArrayList<Card_Color> colors){
|
|
cardColor = colors;
|
|
}
|
|
|
|
|
|
Card_Color determineColor(ArrayList<Card_Color> globalChanges){
|
|
Card_Color colors = new Card_Color(this);
|
|
int i = cardColor.size() - 1;
|
|
int j = globalChanges.size() - 1;
|
|
// if both have changes, see which one is most recent
|
|
while(i >= 0 && j >= 0){
|
|
Card_Color cc = null;
|
|
if (cardColor.get(i).getStamp() > globalChanges.get(j).getStamp()){
|
|
// Card has a more recent color stamp
|
|
cc = cardColor.get(i);
|
|
i--;
|
|
}
|
|
else{
|
|
// Global effect has a more recent color stamp
|
|
cc = globalChanges.get(j);
|
|
j--;
|
|
}
|
|
|
|
for (String s : cc.toStringArray())
|
|
colors.addToCardColor(s);
|
|
if (!cc.getAdditional())
|
|
return colors;
|
|
}
|
|
while(i >= 0){
|
|
Card_Color cc = cardColor.get(i);
|
|
i--;
|
|
for(String s : cc.toStringArray())
|
|
colors.addToCardColor(s);
|
|
if (!cc.getAdditional())
|
|
return colors;
|
|
}
|
|
while(j >= 0){
|
|
Card_Color cc = globalChanges.get(j);
|
|
j--;
|
|
for(String s : cc.toStringArray())
|
|
colors.addToCardColor(s);
|
|
if (!cc.getAdditional())
|
|
return colors;
|
|
}
|
|
|
|
return colors;
|
|
}
|
|
|
|
public int getCMC()
|
|
{
|
|
return CardUtil.getConvertedManaCost(manaCost);
|
|
}
|
|
|
|
public void setUpkeepCost(String s) {
|
|
upkeepCost = s;
|
|
}
|
|
|
|
public String getUpkeepCost() {
|
|
return upkeepCost;
|
|
}
|
|
|
|
public boolean hasUpkeepCost() {
|
|
return upkeepCost.length() > 0 && !upkeepCost.equals("0");
|
|
}
|
|
|
|
public void setTabernacleUpkeepCost(String s) {
|
|
tabernacleUpkeepCost = s;
|
|
}
|
|
|
|
public String getTabernacleUpkeepCost() {
|
|
return tabernacleUpkeepCost;
|
|
}
|
|
|
|
public void setMagusTabernacleUpkeepCost(String s) {
|
|
magusTabernacleUpkeepCost = s;
|
|
}
|
|
|
|
public String getMagusTabernacleUpkeepCost() {
|
|
return magusTabernacleUpkeepCost;
|
|
}
|
|
|
|
//used for cards like Belbe's Portal, Conspiracy, Cover of Darkness, etc.
|
|
public String getChosenType() {
|
|
return chosenType;
|
|
}
|
|
|
|
public void setChosenType(String s) {
|
|
chosenType = s;
|
|
}
|
|
|
|
public String getChosenColor() {
|
|
return chosenColor;
|
|
}
|
|
|
|
public void setChosenColor(String s) {
|
|
chosenColor = s;
|
|
}
|
|
|
|
//used for cards like Meddling Mage...
|
|
public String getNamedCard() {
|
|
return namedCard;
|
|
}
|
|
|
|
public void setNamedCard(String s) {
|
|
namedCard = s;
|
|
}
|
|
|
|
public String getTopCardName() {
|
|
return topCardName;
|
|
}
|
|
|
|
public void setTopCardName(String s) {
|
|
topCardName = s;
|
|
}
|
|
|
|
public void setDrawnThisTurn(boolean b) {
|
|
drawnThisTurn = b;
|
|
}
|
|
|
|
public boolean getDrawnThisTurn() {
|
|
return drawnThisTurn;
|
|
}
|
|
|
|
public String getReflectableMana() {
|
|
return reflectableMana;
|
|
}
|
|
|
|
public void setReflectableMana(String s) {
|
|
reflectableMana = s;
|
|
}
|
|
|
|
/**
|
|
* get a list of Cards this card has gained control of
|
|
*
|
|
* used primarily with AbilityFactory_GainControl
|
|
*
|
|
* @return a list of cards this card has gained control of
|
|
*/
|
|
public ArrayList<Card> getGainControlTargets() {
|
|
return gainControlTargets;
|
|
}
|
|
|
|
/**
|
|
* add a Card to the list of Cards this card has gained control of
|
|
*
|
|
* used primarily with AbilityFactory_GainControl
|
|
*/
|
|
public void addGainControlTarget(Card c) {
|
|
gainControlTargets.add(c);
|
|
}
|
|
|
|
/**
|
|
* clear the list of Cards this card has gained control of
|
|
*
|
|
* used primarily with AbilityFactory_GainControl
|
|
*/
|
|
public void clearGainControlTargets() {
|
|
gainControlTargets.clear();
|
|
}
|
|
|
|
/**
|
|
* get the commands to be executed to lose control of Cards this
|
|
* card has gained control of
|
|
*
|
|
* used primarily with AbilityFactory_GainControl (Old Man of the Sea specifically)
|
|
*/
|
|
public ArrayList<Command> getGainControlReleaseCommands() {
|
|
return gainControlReleaseCommands;
|
|
}
|
|
|
|
/**
|
|
* set a command to be executed to lose control of Cards this
|
|
* card has gained control of
|
|
*
|
|
* used primarily with AbilityFactory_GainControl (Old Man of the Sea specifically)
|
|
*
|
|
* @param c the Command to be executed
|
|
*/
|
|
public void addGainControlReleaseCommand(Command c) {
|
|
gainControlReleaseCommands.add(c);
|
|
}
|
|
|
|
public void clearGainControlReleaseCommands() {
|
|
gainControlReleaseCommands.clear();
|
|
}
|
|
|
|
public String getSpellText() {
|
|
return text;
|
|
}
|
|
|
|
public void setText(String t) {
|
|
text = t;
|
|
}
|
|
|
|
// get the text that should be displayed
|
|
public String getText() {
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append(this.getAbilityText());
|
|
String NonAbilityText = getNonAbilityText();
|
|
if (NonAbilityText.length() > 0) {
|
|
sb.append("\r\n \r\nNon ability features: \r\n");
|
|
sb.append(NonAbilityText);
|
|
}
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
// get the text that does not belong to a cards abilities (and is not really there ruleswise)
|
|
public String getNonAbilityText() {
|
|
StringBuilder sb = new StringBuilder();
|
|
ArrayList<String> keyword = getHiddenExtrinsicKeyword();
|
|
|
|
sb.append(keywordsToText(keyword));
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
// convert a keyword list to the String that should be displayed ingame
|
|
public String keywordsToText(ArrayList<String> keyword) {
|
|
StringBuilder sb = new StringBuilder();
|
|
StringBuilder sbLong = new StringBuilder();
|
|
StringBuilder sbMana = new StringBuilder();
|
|
|
|
for (int i = 0; i < keyword.size(); i++) {
|
|
if (!keyword.get(i).toString().contains("CostChange")
|
|
&&
|
|
!keyword.get(i).toString().contains("Whenever CARDNAME blocks a creature, destroy that creature at end of combat")
|
|
&&
|
|
!keyword.get(i).toString().contains("Whenever CARDNAME becomes blocked by a creature, destroy that creature at end of combat")
|
|
&&
|
|
!keyword.get(i).toString().contains("Permanents don't untap during their controllers' untap steps")
|
|
&&
|
|
!keyword.get(i).toString().contains("PreventAllDamageBy"))
|
|
{
|
|
if (keyword.get(i).toString().contains("WheneverKeyword")) {
|
|
String k[] = keyword.get(i).split(":");
|
|
sbLong.append(k[9]).append("\r\n");
|
|
} else if (keyword.get(i).toString().contains("StaticEffect")) {
|
|
String k[] = keyword.get(i).split(":");
|
|
sbLong.append(k[5]).append("\r\n");
|
|
} else if (keyword.get(i).toString().contains("stPump")) {
|
|
String k[] = keyword.get(i).split(":");
|
|
if (!k[4].contains("no text")) sbLong.append(k[4]).append("\r\n");
|
|
} else if (keyword.get(i).toString().contains("Protection:")) {
|
|
String k[] = keyword.get(i).split(":");
|
|
sbLong.append(k[2]).append("\r\n");
|
|
} else if (keyword.get(i).endsWith(".")) {
|
|
sbLong.append(keyword.get(i).toString()).append("\r\n");
|
|
} else if (keyword.get(i).contains("At the beginning of your upkeep, ")
|
|
&& keyword.get(i).contains(" unless you pay:")) {
|
|
sbLong.append(keyword.get(i).toString()).append("\r\n");
|
|
} else if (keyword.get(i).toString().contains("tap: add ")) {
|
|
sbMana.append(keyword.get(i).toString()).append("\r\n");
|
|
} else {
|
|
if (i != 0 && sb.length() != 0) sb.append(", ");
|
|
sb.append(keyword.get(i).toString());
|
|
}
|
|
}
|
|
}
|
|
if (sb.length() > 0) sb.append("\r\n\r\n");
|
|
if (sbLong.length() > 0) sbLong.append("\r\n");
|
|
sb.append(sbLong);
|
|
sb.append(sbMana);
|
|
return sb.toString();
|
|
}
|
|
|
|
//get the text of the abilities of a card
|
|
public String getAbilityText() {
|
|
if(isInstant() || isSorcery()) {
|
|
String s = getSpellText();
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
// Give spellText line breaks for easier reading
|
|
sb.append(s.replaceAll("\\\\r\\\\n", "\r\n"));
|
|
|
|
// NOTE:
|
|
if (sb.toString().contains(" (NOTE: ")) {
|
|
sb.insert(sb.indexOf("(NOTE: "), "\r\n");
|
|
}
|
|
if (sb.toString().contains("(NOTE: ") && sb.toString().endsWith(".)") && !sb.toString().endsWith("\r\n")) {
|
|
sb.append("\r\n");
|
|
}
|
|
|
|
|
|
// Add SpellAbilities
|
|
SpellAbility[] sa = getSpellAbility();
|
|
for (int i = 0; i < sa.length; i++) {
|
|
sb.append(sa[i].toString() + "\r\n");
|
|
}
|
|
|
|
// Add Keywords
|
|
ArrayList<String> kw = getKeyword();
|
|
|
|
// Ripple + Dredge + Madness + CARDNAME is {color}.
|
|
for (int i = 0; i < kw.size(); i++) {
|
|
if ((kw.get(i).startsWith("Ripple") && !sb.toString().contains("Ripple"))
|
|
|| (kw.get(i).startsWith("Dredge") && !sb.toString().contains("Dredge"))
|
|
|| (kw.get(i).startsWith("Madness") && !sb.toString().contains("Madness"))
|
|
|| (kw.get(i).startsWith("CARDNAME is ") && !sb.toString().contains("CARDNAME is "))) {
|
|
sb.append(kw.get(i).replace(":", " ")).append("\r\n");
|
|
}
|
|
}
|
|
|
|
// Draw a card. + Changeling + CARDNAME can't be countered. + Cascade
|
|
for (int i = 0; i < kw.size(); i++) {
|
|
if ((kw.get(i).contains("Draw a card.") && !sb.toString().contains("Draw a card."))
|
|
|| (kw.get(i).contains("Draw a card at the beginning of the next turn's upkeep.") && !sb.toString().contains("Draw a card at the beginning of the next turn's upkeep."))
|
|
|| (kw.get(i).contains("Changeling") && !sb.toString().contains("Changeling"))
|
|
|| (kw.get(i).contains("CARDNAME can't be countered.") && !sb.toString().contains("CARDNAME can't be countered."))
|
|
|| (kw.get(i).contains("Cascade") && !sb.toString().contains("Cascade"))) {
|
|
sb.append(kw.get(i)).append("\r\n");
|
|
}
|
|
}
|
|
|
|
// Storm
|
|
if (getKeyword().contains("Storm") && !sb.toString().contains("Storm (When you ")) {
|
|
if (sb.toString().endsWith("\r\n\r\n")) {
|
|
sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n")+3);
|
|
}
|
|
sb.append("Storm (When you cast this spell, copy it for each spell cast before it this turn.");
|
|
if (sb.toString().contains("Target") || sb.toString().contains("target")) {
|
|
sb.append(" You may choose new targets for the copies.");
|
|
}
|
|
sb.append(")\r\n");
|
|
}
|
|
|
|
// Scry
|
|
if(!sb.toString().contains("Scry")) for(int i = 0; i < getKeyword().size(); i++) {
|
|
String k = getKeyword().get(i);
|
|
if(k.startsWith("Scry")) {
|
|
String kk[] = k.split(" ");
|
|
//sb.append("Scry " + kk[1] + " (To scry X, look at the top X cards of your library, then put any number of them on the bottom of your library and the rest on top in any order.)\r\n");
|
|
sb.append("Scry ");
|
|
sb.append(kk[1]);
|
|
sb.append(" (To scry X, look at the top X cards of your library, then put any number of them on the bottom of your library and the rest on top in any order.)\r\n");
|
|
}
|
|
}
|
|
|
|
while (sb.toString().endsWith("\r\n")) {
|
|
sb.delete(sb.lastIndexOf("\r\n"), sb.lastIndexOf("\r\n")+3);
|
|
}
|
|
|
|
return sb.toString().replaceAll("CARDNAME", getName());
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
ArrayList<String> keyword = getUnhiddenKeyword();
|
|
|
|
sb.append(keywordsToText(keyword));
|
|
|
|
/*
|
|
for(int i = 0; i < keyword.size(); i++) {
|
|
if(!keyword.get(i).toString().contains("CostChange")) {
|
|
if(i != 0) sb.append(", ");
|
|
if(!keyword.get(i).toString().contains("WheneverKeyword")
|
|
&& !keyword.get(i).toString().contains("StaticEffect")) sb.append(keyword.get(i).toString());
|
|
else if(keyword.get(i).toString().contains("WheneverKeyword")) {
|
|
String k[] = keyword.get(i).split(":");
|
|
sb.append(k[9]);
|
|
}
|
|
else if(keyword.get(i).toString().contains("StaticEffect")) {
|
|
String k[] = keyword.get(i).split(":");
|
|
sb.append(k[5]);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
// Give spellText line breaks for easier reading
|
|
sb.append("\r\n");
|
|
sb.append(text.replaceAll("\\\\r\\\\n", "\r\n"));
|
|
sb.append("\r\n");
|
|
|
|
SpellAbility[] sa = getSpellAbility();
|
|
for(int i = 0; i < sa.length; i++) {
|
|
//presumes the first SpellAbility added to this card, is the "main" spell
|
|
//skip the first SpellAbility for creatures, since it says "Summon this creature"
|
|
//looks bad on the Gui card detail
|
|
if(isPermanent() && (isLand() || i != 0)
|
|
&& !(manaAbility.contains(sa[i]) && ((Ability_Mana) sa[i]).isBasic()))//prevent mana ability duplication
|
|
{
|
|
sb.append(sa[i].toString());
|
|
sb.append("\r\n");
|
|
}
|
|
}
|
|
|
|
// NOTE:
|
|
if (sb.toString().contains(" (NOTE: ")) {
|
|
sb.insert(sb.indexOf("(NOTE: "), "\r\n");
|
|
}
|
|
if (sb.toString().contains("(NOTE: ") && sb.toString().contains(".) ")) {
|
|
sb.insert(sb.indexOf(".) ")+3, "\r\n");
|
|
}
|
|
|
|
// replace tripple line feeds with double line feeds
|
|
int start;
|
|
String s = "\r\n\r\n\r\n";
|
|
while (sb.toString().contains(s)) {
|
|
start = sb.lastIndexOf(s);
|
|
if (start < 0 || start >= sb.length())
|
|
break;
|
|
sb.replace(start, start+4, "\r\n");
|
|
}
|
|
|
|
return sb.toString().replaceAll("CARDNAME", getName()).trim();
|
|
}//getText()
|
|
|
|
/* private ArrayList<Ability_Mana> addLandAbilities ()
|
|
{
|
|
ArrayList<Ability_Mana> res = new ArrayList<Ability_Mana>(manaAbility);
|
|
if (!getType().contains("Land")) return res;
|
|
ArrayList<String> types = getType();
|
|
for(int i = 0; i < basics.length; i++)
|
|
if(types.contains(basics[i]) && !res.contains("tap: add "+ ManaPool.colors.charAt(i)))
|
|
res.add(new Ability_Mana(this, "tap: add "+ ManaPool.colors.charAt(i)){});
|
|
return res;
|
|
}*/
|
|
/*ArrayList<Ability_Mana> addExtrinsicAbilities(ArrayList<Ability_Mana> have)
|
|
{
|
|
try{
|
|
if (AllZone.getZone(this).is(Constant.Zone.Play))
|
|
{
|
|
for (Card c : AllZone.getZone(Constant.Zone.Play, getController()).getCards())
|
|
if (c.getName().equals("Joiner Adept") && getType().contains("Land") || c.getName().equals("Gemhide Sliver") && getType().contains("Sliver"))
|
|
for (char ch : ManaPool.colors.toCharArray())
|
|
have.add(new Ability_Mana(this, "tap: add " + ch){});
|
|
}}
|
|
catch(NullPointerException ex){}//TOhaveDOne: fix this to something more memory-efficient than catching 2000 NullPointer Exceptions every time you open deck editor
|
|
return have;
|
|
}*/
|
|
public ArrayList<Ability_Mana> getManaAbility() {
|
|
return new ArrayList<Ability_Mana>(manaAbility);
|
|
}
|
|
|
|
// Returns basic mana abilities plus "reflected mana" abilities
|
|
public ArrayList<Ability_Mana> getAIPlayableMana() {
|
|
ArrayList<Ability_Mana> res = new ArrayList<Ability_Mana>();
|
|
for(Ability_Mana am:getManaAbility())
|
|
if(am.isBasic() && !res.contains(am)) {
|
|
res.add(am);
|
|
} else if (am.isReflectedMana() && !res.contains(am)) {
|
|
res.add(am);
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
public ArrayList<Ability_Mana> getBasicMana() {
|
|
ArrayList<Ability_Mana> res = new ArrayList<Ability_Mana>();
|
|
for(Ability_Mana am:getManaAbility())
|
|
if(am.isBasic() && !res.contains(am)) res.add(am);
|
|
return res;
|
|
}
|
|
|
|
public void clearFirstSpellAbility(){
|
|
spellAbility.remove(0);
|
|
}
|
|
|
|
public void clearSpellAbility() {
|
|
spellAbility.clear();
|
|
manaAbility.clear();
|
|
}
|
|
|
|
public void clearSpellKeepManaAbility() {
|
|
spellAbility.clear();
|
|
}
|
|
|
|
public void clearManaAbility() {
|
|
manaAbility.clear();
|
|
}
|
|
|
|
|
|
public void addFirstSpellAbility(SpellAbility a){
|
|
a.setSourceCard(this);
|
|
if(a instanceof Ability_Mana) manaAbility.add(0, (Ability_Mana) a);
|
|
else spellAbility.add(0, a);
|
|
}
|
|
|
|
public void addSpellAbility(SpellAbility a) {
|
|
a.setSourceCard(this);
|
|
if(a instanceof Ability_Mana) manaAbility.add((Ability_Mana) a);
|
|
else spellAbility.add(a);
|
|
}
|
|
|
|
public void removeSpellAbility(SpellAbility a) {
|
|
if(a instanceof Ability_Mana)
|
|
//if (a.isExtrinsic()) //never remove intrinsic mana abilities, is this the way to go??
|
|
manaAbility.remove(a);
|
|
else spellAbility.remove(a);
|
|
}
|
|
|
|
|
|
public void removeAllExtrinsicManaAbilities() {
|
|
//temp ArrayList, otherwise ConcurrentModificationExceptions occur:
|
|
ArrayList<SpellAbility> saList = new ArrayList<SpellAbility>();
|
|
|
|
for(SpellAbility var:manaAbility) {
|
|
if(var.isExtrinsic()) saList.add(var);
|
|
}
|
|
for(SpellAbility sa:saList) {
|
|
removeSpellAbility(sa);
|
|
}
|
|
}
|
|
|
|
public ArrayList<String> getIntrinsicManaAbilitiesDescriptions() {
|
|
ArrayList<String> list = new ArrayList<String>();
|
|
for(SpellAbility var:manaAbility) {
|
|
if(var.isIntrinsic()) list.add(var.toString());
|
|
}
|
|
return list;
|
|
}
|
|
|
|
public SpellAbility[] getSpellAbility() {
|
|
ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(spellAbility);
|
|
res.addAll(getManaAbility());
|
|
SpellAbility[] s = new SpellAbility[res.size()];
|
|
res.toArray(s);
|
|
return s;
|
|
}
|
|
|
|
public ArrayList<SpellAbility> getSpells() {
|
|
ArrayList<SpellAbility> s = new ArrayList<SpellAbility>(spellAbility);
|
|
ArrayList<SpellAbility> res = new ArrayList<SpellAbility>();
|
|
|
|
for(SpellAbility sa:s) {
|
|
if(sa.isSpell()) res.add(sa);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public ArrayList<SpellAbility> getBasicSpells() {
|
|
ArrayList<SpellAbility> s = new ArrayList<SpellAbility>(spellAbility);
|
|
ArrayList<SpellAbility> res = new ArrayList<SpellAbility>();
|
|
|
|
for(SpellAbility sa:s) {
|
|
if(sa.isSpell() && !sa.isFlashBackAbility() && !sa.isBuyBackAbility()) res.add(sa);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public ArrayList<SpellAbility> getAdditionalCostSpells() {
|
|
ArrayList<SpellAbility> s = new ArrayList<SpellAbility>(spellAbility);
|
|
ArrayList<SpellAbility> res = new ArrayList<SpellAbility>();
|
|
|
|
for(SpellAbility sa:s) {
|
|
if(sa.isSpell() && !sa.getAdditionalManaCost().equals("")) res.add(sa);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
//shield = regeneration
|
|
public void setShield(int n) {
|
|
nShield = n;
|
|
}
|
|
|
|
public int getShield() {
|
|
return nShield;
|
|
}
|
|
|
|
public void addShield() {
|
|
nShield++;
|
|
}
|
|
|
|
public void subtractShield() {
|
|
nShield--;
|
|
}
|
|
|
|
public void resetShield() {
|
|
nShield = 0;
|
|
}
|
|
|
|
//is this "Card" supposed to be a token?
|
|
public void setToken(boolean b) {
|
|
token = b;
|
|
}
|
|
|
|
public boolean isToken() {
|
|
return token;
|
|
}
|
|
|
|
public void setCopiedToken(boolean b)
|
|
{
|
|
copiedToken = b;
|
|
}
|
|
|
|
public boolean isCopiedToken() {
|
|
return copiedToken;
|
|
}
|
|
public void setCopiedSpell(boolean b)
|
|
{
|
|
copiedSpell = b;
|
|
}
|
|
|
|
public boolean isCopiedSpell() {
|
|
return copiedSpell;
|
|
}
|
|
public void addSpellChoice(String string)
|
|
{
|
|
ChoicesMade.add(string);
|
|
}
|
|
|
|
public ArrayList<String> getChoices() {
|
|
return ChoicesMade;
|
|
}
|
|
public String getChoice(int i) {
|
|
return ChoicesMade.get(i);
|
|
}
|
|
|
|
public void setSpellChoiceTarget(String string)
|
|
{
|
|
Targets_for_Choices.add(string);
|
|
}
|
|
|
|
public ArrayList<String> getChoiceTargets() {
|
|
return Targets_for_Choices;
|
|
}
|
|
public String getChoiceTarget(int i) {
|
|
return Targets_for_Choices.get(i);
|
|
}
|
|
|
|
public void setSpellWithChoices(boolean b)
|
|
{
|
|
SpellwithChoices = b;
|
|
}
|
|
|
|
public boolean hasChoices() {
|
|
return SpellwithChoices;
|
|
}
|
|
public void setCopiesSpells(boolean b)
|
|
{
|
|
SpellCopyingCard = b;
|
|
}
|
|
public boolean copiesSpells() {
|
|
return SpellCopyingCard;
|
|
}
|
|
public void setExaltedBonus(boolean b) {
|
|
exaltedBonus = b;
|
|
}
|
|
|
|
public boolean hasExaltedBonus() {
|
|
return exaltedBonus;
|
|
}
|
|
|
|
public void setExaltedMagnitude(int i) {
|
|
exaltedMagnitude = i;
|
|
}
|
|
|
|
public int getExaltedMagnitude() {
|
|
return exaltedMagnitude;
|
|
}
|
|
|
|
public void setIsFaceDown(boolean b) {
|
|
faceDown = b;
|
|
}
|
|
|
|
public boolean isFaceDown() {
|
|
return faceDown;
|
|
}
|
|
|
|
public void addTrigger(Command c, ZCTrigger type) {
|
|
zcTriggers.add(new Ability_Triggered(this, c, type));
|
|
}
|
|
|
|
public void removeTrigger(Command c, ZCTrigger type) {
|
|
zcTriggers.remove(new Ability_Triggered(this, c, type));
|
|
}
|
|
|
|
public void executeTrigger(ZCTrigger type) {
|
|
for(Ability_Triggered t:zcTriggers)
|
|
if(t.trigger.equals(type) && t.isBasic()) AllZone.Stack.add(t);
|
|
}
|
|
|
|
public void addComesIntoPlayCommand(Command c) {
|
|
addTrigger(c, ZCTrigger.ENTERFIELD);
|
|
}
|
|
|
|
public void removeComesIntoPlayCommand(Command c) {
|
|
removeTrigger(c, ZCTrigger.ENTERFIELD);
|
|
}
|
|
|
|
public void comesIntoPlay() {
|
|
executeTrigger(ZCTrigger.ENTERFIELD);
|
|
}
|
|
|
|
public void addTurnFaceUpCommand(Command c) {
|
|
turnFaceUpCommandList.add(c);
|
|
}
|
|
|
|
public void removeTurnFaceUpCommand(Command c) {
|
|
turnFaceUpCommandList.remove(c);
|
|
}
|
|
|
|
public void turnFaceUp() {
|
|
for(Command var:turnFaceUpCommandList)
|
|
var.execute();
|
|
}
|
|
|
|
public void addDestroyCommand(Command c) {
|
|
addTrigger(c, ZCTrigger.DESTROY);
|
|
}
|
|
|
|
public void removeDestroyCommand(Command c) {
|
|
removeTrigger(c, ZCTrigger.DESTROY);
|
|
}
|
|
|
|
public void destroy() {
|
|
executeTrigger(ZCTrigger.DESTROY);
|
|
}
|
|
|
|
public void addLeavesPlayCommand(Command c) {
|
|
addTrigger(c, ZCTrigger.LEAVEFIELD);
|
|
}
|
|
|
|
public void removeLeavesPlayCommand(Command c) {
|
|
removeTrigger(c, ZCTrigger.LEAVEFIELD);
|
|
}
|
|
|
|
public void leavesPlay() {
|
|
executeTrigger(ZCTrigger.LEAVEFIELD);
|
|
}
|
|
|
|
public void addEquipCommand(Command c) {
|
|
equipCommandList.add(c);
|
|
}
|
|
|
|
public void removeEquipCommand(Command c) {
|
|
equipCommandList.remove(c);
|
|
}
|
|
|
|
public void equip() {
|
|
for(Command var:equipCommandList)
|
|
var.execute();
|
|
}
|
|
|
|
public void addUnEquipCommand(Command c) {
|
|
unEquipCommandList.add(c);
|
|
}
|
|
|
|
public void removeUnEquipCommand(Command c) {
|
|
unEquipCommandList.remove(c);
|
|
}
|
|
|
|
public void unEquip() {
|
|
for(Command var:unEquipCommandList)
|
|
var.execute();
|
|
}
|
|
|
|
public void addEnchantCommand(Command c) {
|
|
enchantCommandList.add(c);
|
|
}
|
|
|
|
public void removeEnchantCommand(Command c) {
|
|
enchantCommandList.add(c);
|
|
}
|
|
|
|
public void enchant() {
|
|
for(Command var:enchantCommandList)
|
|
var.execute();
|
|
}
|
|
|
|
public void addUnEnchantCommand(Command c) {
|
|
unEnchantCommandList.add(c);
|
|
}
|
|
|
|
public void unEnchant() {
|
|
for(Command var:unEnchantCommandList)
|
|
var.execute();
|
|
}
|
|
|
|
public void addUntapCommand(Command c) {
|
|
untapCommandList.add(c);
|
|
}
|
|
|
|
public void addChangeControllerCommand(Command c) {
|
|
changeControllerCommandList.add(c);
|
|
}
|
|
|
|
public ArrayList<Command> getReplaceMoveToGraveyard() {
|
|
return replaceMoveToGraveyardCommandList;
|
|
}
|
|
|
|
public void addReplaceMoveToGraveyardCommand(Command c) {
|
|
replaceMoveToGraveyardCommandList.add(c);
|
|
}
|
|
|
|
public void clearReplaceMoveToGraveyardCommandList() {
|
|
replaceMoveToGraveyardCommandList.clear();
|
|
}
|
|
|
|
public void replaceMoveToGraveyard() {
|
|
for(Command var:replaceMoveToGraveyardCommandList)
|
|
var.execute();
|
|
}
|
|
|
|
public void addCycleCommand(Command c) {
|
|
cycleCommandList.add(c);
|
|
}
|
|
|
|
public void cycle() {
|
|
for(Command var:cycleCommandList)
|
|
var.execute();
|
|
}
|
|
|
|
public void setSickness(boolean b) {
|
|
sickness = b;
|
|
}
|
|
|
|
public boolean hasSickness() {
|
|
if(getKeyword().contains("Haste")) return false;
|
|
|
|
return sickness;
|
|
}
|
|
|
|
public boolean isSick() {
|
|
if(getKeyword().contains("Haste")) return false;
|
|
|
|
return sickness && isCreature();
|
|
}
|
|
|
|
public void setRarity(String s) {
|
|
rarity = s;
|
|
}
|
|
|
|
public String getRarity() {
|
|
return rarity;
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setImageName(String s) {
|
|
imageName = s;
|
|
}
|
|
|
|
public String getImageName() {
|
|
if(!imageName.equals("")) return imageName;
|
|
return name;
|
|
}
|
|
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
public Player getOwner() {
|
|
return owner;
|
|
}
|
|
|
|
public Player getController() {
|
|
return controller;
|
|
}
|
|
|
|
public void setName(String s) {
|
|
name = s;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void setOwner(Player player) {
|
|
owner = player;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void setController(Player player) {
|
|
if( null != controller && !controller.isPlayer(player)) {
|
|
for(Command var:changeControllerCommandList)
|
|
var.execute();
|
|
}
|
|
controller = player;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public ArrayList<Card> getEquippedBy() {
|
|
return equippedBy;
|
|
}
|
|
|
|
public void setEquippedBy(ArrayList<Card> list) {
|
|
equippedBy = list;
|
|
}
|
|
|
|
public ArrayList<Card> getEquipping() {
|
|
return equipping;
|
|
}
|
|
|
|
public Card getEquippingCard() {
|
|
if (equipping.size() == 0)
|
|
return null;
|
|
return equipping.get(0);
|
|
}
|
|
|
|
public void setEquipping(ArrayList<Card> list) {
|
|
equipping = list;
|
|
}
|
|
|
|
public boolean isEquipped() {
|
|
return equippedBy.size() != 0;
|
|
}
|
|
|
|
public boolean isEquipping() {
|
|
return equipping.size() != 0;
|
|
}
|
|
|
|
public void addEquippedBy(Card c) {
|
|
equippedBy.add(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void removeEquippedBy(Card c) {
|
|
equippedBy.remove(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void addEquipping(Card c) {
|
|
equipping.add(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void removeEquipping(Card c) {
|
|
equipping.remove(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void equipCard(Card c) //equipment.equipCard(cardToBeEquipped);
|
|
{
|
|
equipping.add(c);
|
|
c.addEquippedBy(this);
|
|
this.equip();
|
|
}
|
|
|
|
public void unEquipCard(Card c) //equipment.unEquipCard(equippedCard);
|
|
{
|
|
this.unEquip();
|
|
equipping.remove(c);
|
|
c.removeEquippedBy(this);
|
|
}
|
|
|
|
public void unEquipAllCards() {
|
|
while(equippedBy.size() > 0){ // while there exists equipment, unequip the first one
|
|
equippedBy.get(0).unEquipCard(this);
|
|
}
|
|
}
|
|
|
|
//
|
|
|
|
public ArrayList<Card> getEnchantedBy() {
|
|
return enchantedBy;
|
|
}
|
|
|
|
public void setEnchantedBy(ArrayList<Card> list) {
|
|
enchantedBy = list;
|
|
}
|
|
|
|
public ArrayList<Card> getEnchanting() {
|
|
return enchanting;
|
|
}
|
|
|
|
public Card getEnchantingCard() {
|
|
if (enchanting.size() == 0)
|
|
return null;
|
|
return enchanting.get(0);
|
|
}
|
|
|
|
public void setEnchanting(ArrayList<Card> list) {
|
|
enchanting = list;
|
|
}
|
|
|
|
public boolean isEnchanted() {
|
|
return enchantedBy.size() != 0;
|
|
}
|
|
|
|
public boolean isEnchanting() {;
|
|
return enchanting.size() != 0;
|
|
}
|
|
|
|
public void addEnchantedBy(Card c) {
|
|
enchantedBy.add(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void removeEnchantedBy(Card c) {
|
|
enchantedBy.remove(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
/**
|
|
* checks to see if this card is enchanted by an aura with a given name
|
|
*
|
|
* @param cardName the name of the aura
|
|
* @return true if this card is enchanted by an aura with the given name, false otherwise
|
|
*/
|
|
public boolean isEnchantedBy(String cardName) {
|
|
ArrayList<Card> allAuras = this.getEnchantedBy();
|
|
for(Card aura:allAuras) {
|
|
if(aura.getName().equals(cardName)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void addEnchanting(Card c) {
|
|
enchanting.add(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void removeEnchanting(Card c) {
|
|
enchanting.remove(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void enchantCard(Card c) {
|
|
enchanting.add(c);
|
|
c.addEnchantedBy(this);
|
|
this.enchant();
|
|
}
|
|
|
|
public void unEnchantCard(Card c) {
|
|
this.unEnchant();
|
|
enchanting.remove(c);
|
|
c.removeEnchantedBy(this);
|
|
}
|
|
|
|
public void unEnchantAllCards() {
|
|
for(int i = 0; i < equippedBy.size(); i++) {
|
|
enchantedBy.get(i).unEnchantCard(this);
|
|
}
|
|
}
|
|
|
|
//array size might equal 0, will NEVER be null
|
|
public Card[] getAttachedCards() {
|
|
Card c[] = new Card[attached.size()];
|
|
attached.toArray(c);
|
|
return c;
|
|
}
|
|
|
|
public boolean hasAttachedCards() {
|
|
return getAttachedCards().length != 0;
|
|
}
|
|
|
|
public void attachCard(Card c) {
|
|
attached.add(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void unattachCard(Card c) {
|
|
attached.remove(c);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void setType(ArrayList<String> a) {
|
|
type = new ArrayList<String>(a);
|
|
}
|
|
|
|
public void addType(String a) {
|
|
type.add(a);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void removeType(String a) {
|
|
type.remove(a);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public ArrayList<String> getType() {
|
|
return new ArrayList<String>(type);
|
|
}
|
|
|
|
public void setPrevType(ArrayList<String> a) {
|
|
prevType = new ArrayList<String>(a);
|
|
}
|
|
|
|
public void addPrevType(String a) {
|
|
prevType.add(a);
|
|
}
|
|
|
|
public void removePrevType(String a) {
|
|
prevType.remove(a);
|
|
}
|
|
|
|
public ArrayList<String> getPrevType() {
|
|
return new ArrayList<String>(prevType);
|
|
}
|
|
|
|
//values that are printed on card
|
|
public int getBaseAttack() {
|
|
return baseAttack;
|
|
}
|
|
|
|
public int getBaseDefense() {
|
|
return baseDefense;
|
|
}
|
|
|
|
//values that are printed on card
|
|
public void setBaseAttack(int n) {
|
|
baseAttack = n;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void setBaseDefense(int n) {
|
|
baseDefense = n;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public int getNetAttack() {
|
|
int total = getBaseAttack();
|
|
total += getTempAttackBoost() + getSemiPermanentAttackBoost() + getOtherAttackBoost()
|
|
+ getCounters(Counters.P1P1) + getCounters(Counters.P1P2)
|
|
+ getCounters(Counters.P1P0) - getCounters(Counters.M1M1)
|
|
+ (2*getCounters(Counters.P2P2));
|
|
return total;
|
|
}
|
|
|
|
public int getNetDefense() {
|
|
int total = getBaseDefense();
|
|
total += getTempDefenseBoost() + getSemiPermanentDefenseBoost() + getOtherDefenseBoost()
|
|
+ getCounters(Counters.P1P1) + (2*getCounters(Counters.P1P2))
|
|
- getCounters(Counters.M1M1) + getCounters(Counters.P0P1 )
|
|
- getCounters(Counters.P0M1) - (2*getCounters(Counters.P0M2))
|
|
+ (2*getCounters(Counters.P2P2));
|
|
return total;
|
|
}
|
|
|
|
public void setRandomPicture(int n) {
|
|
randomPicture = n;
|
|
}
|
|
|
|
public int getRandomPicture() {
|
|
return randomPicture;
|
|
}
|
|
|
|
public void setUpkeepDamage(int n) {
|
|
upkeepDamage = n;
|
|
}
|
|
|
|
public int getUpkeepDamage() {
|
|
return upkeepDamage;
|
|
}
|
|
|
|
public void addMultiKickerMagnitude(int n)
|
|
{
|
|
multiKickerMagnitude += n;
|
|
}
|
|
|
|
public void setMultiKickerMagnitude(int n)
|
|
{
|
|
multiKickerMagnitude = n;
|
|
}
|
|
|
|
public int getMultiKickerMagnitude()
|
|
{
|
|
return multiKickerMagnitude;
|
|
}
|
|
|
|
//public int getAttack(){return attack;}
|
|
|
|
//for cards like Giant Growth, etc.
|
|
public int getTempAttackBoost() {
|
|
return tempAttackBoost;
|
|
}
|
|
|
|
public int getTempDefenseBoost() {
|
|
return tempDefenseBoost;
|
|
}
|
|
|
|
public void addTempAttackBoost(int n) {
|
|
tempAttackBoost += n;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void addTempDefenseBoost(int n) {
|
|
tempDefenseBoost += n;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void setTempAttackBoost(int n) {
|
|
tempAttackBoost = n;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void setTempDefenseBoost(int n) {
|
|
tempDefenseBoost = n;
|
|
this.updateObservers();
|
|
}
|
|
|
|
//for cards like Glorious Anthem, etc.
|
|
public int getSemiPermanentAttackBoost() {
|
|
return semiPermanentAttackBoost;
|
|
}
|
|
|
|
public int getSemiPermanentDefenseBoost() {
|
|
return semiPermanentDefenseBoost;
|
|
}
|
|
|
|
public void addSemiPermanentAttackBoost(int n) {
|
|
semiPermanentAttackBoost += n;
|
|
}
|
|
|
|
public void addSemiPermanentDefenseBoost(int n) {
|
|
semiPermanentDefenseBoost += n;
|
|
}
|
|
|
|
public void setSemiPermanentAttackBoost(int n) {
|
|
semiPermanentAttackBoost = n;
|
|
}
|
|
|
|
public void setSemiPermanentDefenseBoost(int n) {
|
|
semiPermanentDefenseBoost = n;
|
|
}
|
|
|
|
//for cards like Relentless Rats, Master of Etherium, etc.
|
|
public int getOtherAttackBoost() {
|
|
return otherAttackBoost;
|
|
}
|
|
|
|
public int getOtherDefenseBoost() {
|
|
return otherDefenseBoost;
|
|
}
|
|
|
|
public void addOtherAttackBoost(int n) {
|
|
otherAttackBoost += n;
|
|
}
|
|
|
|
public void addOtherDefenseBoost(int n) {
|
|
otherDefenseBoost += n;
|
|
}
|
|
|
|
public void setOtherAttackBoost(int n) {
|
|
otherAttackBoost = n;
|
|
}
|
|
|
|
public void setOtherDefenseBoost(int n) {
|
|
otherDefenseBoost = n;
|
|
}
|
|
|
|
//public void setAttack(int n) {attack = n; this.updateObservers();}
|
|
//public void setDefense(int n) {defense = n; this.updateObservers();}
|
|
|
|
public boolean isUntapped() {
|
|
return !tapped;
|
|
}
|
|
|
|
public boolean isTapped() {
|
|
return tapped;
|
|
}
|
|
|
|
public void setTapped(boolean b) {
|
|
tapped = b;
|
|
updateObservers();
|
|
}
|
|
|
|
public void tap() {
|
|
if (isUntapped())
|
|
GameActionUtil.executeTapSideEffects(this);
|
|
setTapped(true);
|
|
}
|
|
|
|
public void untap() {
|
|
if( isTapped() ) {
|
|
GameActionUtil.executeUntapSideEffects(this);
|
|
}
|
|
if (isTapped() && isReflectedLand()) {
|
|
Ability_Reflected_Mana am = (Ability_Reflected_Mana) getManaAbility().get(0);
|
|
am.reset();
|
|
}
|
|
for(Command var:untapCommandList) {
|
|
var.execute();
|
|
}
|
|
setTapped(false);
|
|
}
|
|
|
|
public boolean isUnCastable() {
|
|
return unCastable;
|
|
}
|
|
|
|
public void setUnCastable(boolean b) {
|
|
unCastable = b;
|
|
updateObservers();
|
|
}
|
|
|
|
//keywords are like flying, fear, first strike, etc...
|
|
public ArrayList<String> getKeyword() {
|
|
ArrayList<String> a1 = new ArrayList<String>(getIntrinsicKeyword());
|
|
ArrayList<String> a2 = new ArrayList<String>(getExtrinsicKeyword());
|
|
ArrayList<String> a3 = new ArrayList<String>(getOtherExtrinsicKeyword());
|
|
ArrayList<String> a4 = new ArrayList<String>(getHiddenExtrinsicKeyword());
|
|
a1.addAll(a2);
|
|
a1.addAll(a3);
|
|
a1.addAll(a4);
|
|
|
|
for(Ability_Mana sa:getManaAbility())
|
|
if(sa.isBasic()) a1.add((sa).orig);
|
|
|
|
return a1;
|
|
}
|
|
|
|
//keywords are like flying, fear, first strike, etc...
|
|
// Hidden keywords will be left out
|
|
public ArrayList<String> getUnhiddenKeyword() {
|
|
ArrayList<String> a1 = new ArrayList<String>(getIntrinsicKeyword());
|
|
ArrayList<String> a2 = new ArrayList<String>(getExtrinsicKeyword());
|
|
ArrayList<String> a3 = new ArrayList<String>(getOtherExtrinsicKeyword());
|
|
a1.addAll(a2);
|
|
a1.addAll(a3);
|
|
|
|
for(Ability_Mana sa:getManaAbility())
|
|
if(sa.isBasic()) a1.add((sa).orig);
|
|
|
|
return a1;
|
|
}
|
|
|
|
public ArrayList<String> getIntrinsicAbilities()
|
|
{
|
|
return intrinsicAbility;
|
|
}
|
|
|
|
//public void setKeyword(ArrayList a) {keyword = new ArrayList(a); this.updateObservers();}
|
|
//public void addKeyword(String s) {keyword.add(s); this.updateObservers();}
|
|
//public void removeKeyword(String s) {keyword.remove(s); this.updateObservers();}
|
|
//public int getKeywordSize() {return keyword.size();}
|
|
|
|
//public String[] basics = {"Plains", "Island", "Swamp", "Mountain", "Forest"};
|
|
|
|
public ArrayList<String> getIntrinsicKeyword() {
|
|
return new ArrayList<String>(intrinsicKeyword);
|
|
}
|
|
|
|
public void setIntrinsicKeyword(ArrayList<String> a) {
|
|
intrinsicKeyword = new ArrayList<String>(a);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void setIntrinsicAbilities(ArrayList<String> a)
|
|
{
|
|
intrinsicAbility = new ArrayList<String>(a);
|
|
}
|
|
|
|
public void addIntrinsicKeyword(String s) {/*if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s){}); else*/
|
|
if (s.trim().length()!=0)
|
|
intrinsicKeyword.add((getName().trim().length()== 0 ? s :s.replaceAll(getName(), "CARDNAME")));
|
|
}
|
|
|
|
public void addIntrinsicAbility(String s)
|
|
{
|
|
if (s.trim().length() != 0)
|
|
intrinsicAbility.add(s);
|
|
}
|
|
|
|
public void addNonStackingIntrinsicKeyword(String s) {/*if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s){}); else*/
|
|
if(!getIntrinsicKeyword().contains(s)){
|
|
if (s.trim().length()!=0)
|
|
intrinsicKeyword.add((getName().trim().length()== 0 ? s :s.replaceAll(getName(), "CARDNAME")));
|
|
}
|
|
}
|
|
|
|
public void removeIntrinsicKeyword(String s) {
|
|
intrinsicKeyword.remove(s);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public int getIntrinsicKeywordSize() {
|
|
return intrinsicKeyword.size();
|
|
}
|
|
|
|
public ArrayList<String> getExtrinsicKeyword() {
|
|
return new ArrayList<String>(extrinsicKeyword);
|
|
}
|
|
|
|
public void setExtrinsicKeyword(ArrayList<String> a) {
|
|
extrinsicKeyword = new ArrayList<String>(a);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void addExtrinsicKeyword(String s) {
|
|
//if(!getKeyword().contains(s)){
|
|
if(s.startsWith("HIDDEN")) addHiddenExtrinsicKeyword(s);
|
|
else if(s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s) {
|
|
private static final long serialVersionUID = 221124403788942412L;
|
|
});
|
|
else
|
|
extrinsicKeyword.add((getName().trim().length()==0 ? s :s.replaceAll(getName(), "CARDNAME")));
|
|
//}
|
|
}
|
|
|
|
public void addStackingExtrinsicKeyword(String s) {
|
|
if(s.startsWith("HIDDEN")) addHiddenExtrinsicKeyword(s);
|
|
else if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s)
|
|
{
|
|
private static final long serialVersionUID = 2443750124751086033L;
|
|
});
|
|
else extrinsicKeyword.add(s);
|
|
}
|
|
|
|
public void removeExtrinsicKeyword(String s) {
|
|
if(s.startsWith("HIDDEN")) removeHiddenExtrinsicKeyword(s);
|
|
else extrinsicKeyword.remove(s);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public int getExtrinsicKeywordSize() {
|
|
return extrinsicKeyword.size();
|
|
}
|
|
|
|
public ArrayList<String> getOtherExtrinsicKeyword() {
|
|
return new ArrayList<String>(otherExtrinsicKeyword);
|
|
}
|
|
|
|
public void setOtherExtrinsicKeyword(ArrayList<String> a) {
|
|
otherExtrinsicKeyword = new ArrayList<String>(a);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void addOtherExtrinsicKeyword(String s) {
|
|
//if(!getKeyword().contains(s)){
|
|
if(s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s) {
|
|
|
|
private static final long serialVersionUID = -3032496855034700637L;
|
|
});
|
|
else
|
|
otherExtrinsicKeyword.add((getName().trim().length()==0 ? s :s.replaceAll(getName(), "CARDNAME")));
|
|
//}
|
|
}
|
|
|
|
public void addStackingOtherExtrinsicKeyword(String s) {
|
|
if (s.startsWith("tap: add")) manaAbility.add(new Ability_Mana(this, s)
|
|
{
|
|
private static final long serialVersionUID = 7004485151675361747L;
|
|
});
|
|
else extrinsicKeyword.add(s);
|
|
}
|
|
|
|
public void removeOtherExtrinsicKeyword(String s) {
|
|
otherExtrinsicKeyword.remove(s);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public int getOtherExtrinsicKeywordSize() {
|
|
return otherExtrinsicKeyword.size();
|
|
}
|
|
|
|
public ArrayList<String> getPrevIntrinsicKeyword() {
|
|
return new ArrayList<String>(prevIntrinsicKeyword);
|
|
}
|
|
|
|
public void setPrevIntrinsicKeyword(ArrayList<String> a) {
|
|
prevIntrinsicKeyword = new ArrayList<String>(a);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public void addPrevIntrinsicKeyword(String s) {
|
|
prevIntrinsicKeyword.add(s);
|
|
}
|
|
|
|
public void removePrevIntrinsicKeyword(String s) {
|
|
prevIntrinsicKeyword.remove(s);
|
|
this.updateObservers();
|
|
}
|
|
|
|
public int getPrevIntrinsicKeywordSize() {
|
|
return prevIntrinsicKeyword.size();
|
|
}
|
|
|
|
// Hidden Keywords will be returned without the indicator HIDDEN
|
|
public ArrayList<String> getHiddenExtrinsicKeyword() {
|
|
ArrayList<String> Keyword = new ArrayList<String>();
|
|
for (int i = 0; i < HiddenExtrinsicKeyword.size(); i++) {
|
|
String keyword = HiddenExtrinsicKeyword.get(i);
|
|
Keyword.add(keyword.replace("HIDDEN ", ""));
|
|
}
|
|
return Keyword;
|
|
}
|
|
|
|
public void addHiddenExtrinsicKeyword(String s) {
|
|
HiddenExtrinsicKeyword.add(s);
|
|
}
|
|
|
|
public void removeHiddenExtrinsicKeyword(String s) {
|
|
HiddenExtrinsicKeyword.remove(s);
|
|
//this.updateObservers();
|
|
}
|
|
|
|
public boolean isPermanent() {
|
|
return !(isInstant() || isSorcery() || isImmutable());
|
|
}
|
|
|
|
public boolean isSpell() {
|
|
return (isInstant() || isSorcery());
|
|
}
|
|
|
|
public boolean isCreature() {
|
|
return type.contains("Creature");
|
|
}
|
|
|
|
public boolean isWall() {
|
|
return type.contains("Wall");
|
|
}
|
|
|
|
public boolean isBasicLand() {
|
|
return type.contains("Basic");
|
|
}
|
|
|
|
public boolean isLand() {
|
|
return type.contains("Land");
|
|
}
|
|
|
|
public boolean isSorcery() {
|
|
return type.contains("Sorcery");
|
|
}
|
|
|
|
public boolean isInstant() {
|
|
return type.contains("Instant") /*|| getKeyword().contains("Flash")*/;
|
|
}
|
|
|
|
public boolean isArtifact() {
|
|
return type.contains("Artifact");
|
|
}
|
|
|
|
public boolean isEquipment() {
|
|
return type.contains("Equipment");
|
|
}
|
|
|
|
public boolean isPlaneswalker() {
|
|
return type.contains("Planeswalker");
|
|
}
|
|
|
|
public boolean isEmblem() {
|
|
return type.contains("Emblem");
|
|
}
|
|
|
|
public boolean isTribal() {
|
|
return type.contains("Tribal");
|
|
}
|
|
|
|
public boolean isSnow() {
|
|
return type.contains("Snow");
|
|
}
|
|
|
|
//global and local enchantments
|
|
public boolean isEnchantment() {
|
|
return typeContains("Enchantment");
|
|
}
|
|
|
|
public boolean isLocalEnchantment() {
|
|
return typeContains("Aura");
|
|
}
|
|
|
|
public boolean isAura() {
|
|
return typeContains("Aura");
|
|
}
|
|
|
|
public boolean isGlobalEnchantment() {
|
|
return typeContains("Enchantment") && (!isLocalEnchantment());
|
|
}
|
|
|
|
private boolean typeContains(String s) {
|
|
Iterator<?> it = this.getType().iterator();
|
|
while(it.hasNext())
|
|
if(it.next().toString().startsWith(s)) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
public void setUniqueNumber(int n) {
|
|
uniqueNumber = n;
|
|
this.updateObservers();
|
|
}
|
|
|
|
public int getUniqueNumber() {
|
|
return uniqueNumber;
|
|
}
|
|
|
|
public void setValue(long n)
|
|
{
|
|
value = n;
|
|
}
|
|
|
|
public long getValue()
|
|
{
|
|
return value;
|
|
}
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if(o instanceof Card) {
|
|
Card c = (Card) o;
|
|
int a = getUniqueNumber();
|
|
int b = c.getUniqueNumber();
|
|
return (a == b);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return getUniqueNumber();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return this.getName() + " (" + this.getUniqueNumber() + ")";
|
|
}
|
|
|
|
public boolean hasFlashback() {
|
|
return flashback;
|
|
}
|
|
|
|
public void setFlashback(boolean b) {
|
|
flashback = b;
|
|
}
|
|
|
|
public boolean hasUnearth() {
|
|
return unearth;
|
|
}
|
|
|
|
public void setUnearth(boolean b) {
|
|
unearth = b;
|
|
}
|
|
|
|
public boolean isUnearthed()
|
|
{
|
|
return unearthed;
|
|
}
|
|
|
|
public void setUnearthed(boolean b)
|
|
{
|
|
unearthed = b;
|
|
}
|
|
|
|
public boolean hasMadness() {
|
|
return madness;
|
|
}
|
|
|
|
public void setMadness(boolean b) {
|
|
madness = b;
|
|
}
|
|
|
|
public String getMadnessCost() {
|
|
return madnessCost;
|
|
}
|
|
|
|
public void setMadnessCost(String cost) {
|
|
madnessCost = cost;
|
|
}
|
|
|
|
public boolean hasSuspend() {
|
|
return suspend;
|
|
}
|
|
|
|
public void setSuspend(boolean b) {
|
|
suspend = b;
|
|
}
|
|
|
|
public boolean wasSuspendCast() {
|
|
return suspendCast;
|
|
}
|
|
|
|
public void setSuspendCast(boolean b) {
|
|
suspendCast = b;
|
|
}
|
|
|
|
public void setKicked(boolean b) {
|
|
kicked = b;
|
|
}
|
|
|
|
public boolean isKicked() {
|
|
return kicked;
|
|
}
|
|
|
|
public void setReflectedLand(boolean b) {
|
|
reflectedLand = b;
|
|
}
|
|
|
|
public boolean isReflectedLand() {
|
|
return reflectedLand;
|
|
}
|
|
|
|
public boolean hasKeyword(String keyword)
|
|
{
|
|
return getKeyword().contains(keyword);
|
|
}
|
|
|
|
public boolean hasStartOfKeyword(String keyword)
|
|
{
|
|
ArrayList<String> a = getKeyword();
|
|
for(int i = 0; i < a.size(); i++)
|
|
if(a.get(i).toString().startsWith(keyword)) return true;
|
|
return false;
|
|
}
|
|
|
|
public int getKeywordPosition(String k) {
|
|
ArrayList<String> a = getKeyword();
|
|
for(int i = 0; i < a.size(); i++)
|
|
if(a.get(i).toString().startsWith(k)) return i;
|
|
return -1;
|
|
}
|
|
|
|
public boolean keywordsContain(String keyword) {
|
|
ArrayList<String> a = getKeyword();
|
|
for(int i = 0; i < a.size(); i++)
|
|
if(a.get(i).toString().contains(keyword)) return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
public boolean hasAnyKeyword(String keywords[])
|
|
{
|
|
for (int i=0; i<keywords.length; i++)
|
|
if (hasKeyword(keywords[i]))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
public boolean hasAnyKeyword(ArrayList<String> keywords)
|
|
{
|
|
for (int i=0; i<keywords.size(); i++)
|
|
if (hasKeyword(keywords.get(i)))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
//This counts the number of instances of a keyword a card has
|
|
public int getAmountOfKeyword(String k) {
|
|
int count = 0;
|
|
ArrayList<String> keywords = getKeyword();
|
|
for(int j = 0; j < keywords.size(); j++) {
|
|
if(keywords.get(j).equals(k)) count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
// This is for keywords with a number like Bushido, Annihilator and Rampage. It returns the total.
|
|
public int getKeywordMagnitude(String k) {
|
|
int count = 0;
|
|
ArrayList<String> keywords = getKeyword();
|
|
for(String kw:keywords) {
|
|
if(kw.startsWith(k)) {
|
|
String[] parse = kw.split(" ");
|
|
String s = parse[1];
|
|
count += Integer.parseInt(s);
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
private String toMixedCase(String s)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
// to handle hyphenated Types
|
|
String[] types = s.split("-");
|
|
for(int i = 0; i < types.length; i++){
|
|
if (i != 0)
|
|
sb.append("-");
|
|
sb.append(types[i].substring(0,1).toUpperCase());
|
|
sb.append(types[i].substring(1).toLowerCase());
|
|
}
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
//usable to check for changelings
|
|
public boolean isType(String cardType) {
|
|
cardType = toMixedCase(cardType);
|
|
|
|
if (type.contains(cardType)
|
|
|| ( (isCreature() || isTribal())
|
|
&& CardUtil.isACreatureType(cardType) && getKeyword().contains("Changeling"))) return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
// Takes an array of arguments like Permanent.Blue+withFlying, only one of them has to be true
|
|
public boolean isValidCard(final String Restrictions[], final Player sourceController, final Card source) {
|
|
|
|
if (getName().equals("Mana Pool") || isImmutable()) return false;
|
|
|
|
for(int i = 0; i < Restrictions.length; i++) {
|
|
if(isValid(Restrictions[i],sourceController,source)) return true;
|
|
}
|
|
return false;
|
|
|
|
}//isValidCard
|
|
|
|
|
|
// Takes one argument like Permanent.Blue+withFlying
|
|
public boolean isValid(final String Restriction, final Player sourceController, final Card source) {
|
|
|
|
if (getName().equals("Mana Pool") || isImmutable()) return false;
|
|
if (Restriction.equals("False")) return false;
|
|
|
|
String incR[] = Restriction.split("\\."); // Inclusive restrictions are Card types
|
|
|
|
if (incR[0].equals("Spell") && isType("Land"))
|
|
return false;
|
|
if (incR[0].equals("Permanent") && (isType("Instant") || isType("Sorcery")))
|
|
return false;
|
|
if(!incR[0].equals("Card") && !incR[0].equals("Spell") && !incR[0].equals("Permanent") && !(isType(incR[0])))
|
|
return false; //Check for wrong type
|
|
|
|
if(incR.length > 1) {
|
|
final String excR = incR[1];
|
|
String exR[] = excR.split("\\+"); // Exclusive Restrictions are ...
|
|
for(int j = 0; j < exR.length; j++)
|
|
if(hasProperty(exR[j],sourceController,source) == false) return false;
|
|
}
|
|
return true;
|
|
}//isValidCard(String Restriction)
|
|
|
|
// Takes arguments like Blue or withFlying
|
|
public boolean hasProperty(String Property, final Player sourceController, final Card source) {
|
|
if (Property.contains("White") || // ... Card colors
|
|
Property.contains("Blue") ||
|
|
Property.contains("Black") ||
|
|
Property.contains("Red") ||
|
|
Property.contains("Green") ||
|
|
Property.contains("Colorless"))
|
|
{
|
|
if(Property.startsWith("non"))
|
|
{
|
|
if (CardUtil.getColors(this).contains(Property.substring(3).toLowerCase())) return false;
|
|
}
|
|
else
|
|
if (!CardUtil.getColors(this).contains(Property.toLowerCase())) return false;
|
|
}
|
|
else if (Property.contains("MultiColor")) // ... Card is multicolored
|
|
{
|
|
if (Property.startsWith("non") && (CardUtil.getColors(this).size() > 1)) return false;
|
|
if (!Property.startsWith("non") && (CardUtil.getColors(this).size() <= 1)) return false;
|
|
}
|
|
|
|
else if (Property.contains("MonoColor")) // ... Card is monocolored
|
|
{
|
|
if (Property.startsWith("non") && (CardUtil.getColors(this).size() == 1 && !isColorless())) return false;
|
|
if (!Property.startsWith("non") && (CardUtil.getColors(this).size() > 1 || isColorless())) return false;
|
|
}
|
|
|
|
else if (Property.startsWith("YouCtrl")) { if (!getController().isPlayer(sourceController)) return false; }
|
|
else if (Property.startsWith("YouDontCtrl")) { if (getController().isPlayer(sourceController)) return false; }
|
|
else if (Property.startsWith("YouOwn")) { if (!getOwner().isPlayer(sourceController)) return false; }
|
|
else if (Property.startsWith("YouDontOwn")) { if (getOwner().isPlayer(sourceController)) return false; }
|
|
|
|
else if (Property.startsWith("ControllerControls")) {
|
|
String type = Property.substring(18);
|
|
CardList list = AllZoneUtil.getPlayerCardsInPlay(getController());
|
|
if (list.getType(type).isEmpty()) return false;
|
|
}
|
|
|
|
else if (Property.startsWith("Other")) { if(this.equals(source)) return false; }
|
|
else if (Property.startsWith("Self")) { if(!this.equals(source)) return false; }
|
|
|
|
else if (Property.startsWith("Attached")) {
|
|
if (!equipping.contains(source) && !enchanting.contains(source)) return false; }
|
|
else if (Property.startsWith("SharesColorWith")) { if(!sharesColorWith(source)) return false; }
|
|
|
|
else if (Property.startsWith("with")) // ... Card keywords
|
|
{
|
|
if (Property.startsWith("without") && getKeyword().contains(Property.substring(7))) return false;
|
|
if (!Property.startsWith("without") && !getKeyword().contains(Property.substring(4))) return false;
|
|
}
|
|
|
|
else if (Property.startsWith("tapped"))
|
|
{ if(!isTapped()) return false;}
|
|
else if (Property.startsWith("untapped"))
|
|
{ if(!isUntapped()) return false;}
|
|
else if (Property.startsWith("faceDown"))
|
|
{ if(!isFaceDown()) return false;}
|
|
else if (Property.startsWith("enteredBattlefieldThisTurn"))
|
|
{ if(!(getTurnInZone() == AllZone.Phase.getTurn())) return false;}
|
|
|
|
else if (Property.startsWith("enchanted"))
|
|
{ if(!isEnchanted()) return false;}
|
|
else if (Property.startsWith("unenchanted"))
|
|
{ if(isEnchanted()) return false;}
|
|
else if (Property.startsWith("enchanting"))
|
|
{ if(!isEnchanting()) return false;}
|
|
|
|
else if (Property.startsWith("equipped"))
|
|
{ if(!isEquipped()) return false;}
|
|
else if (Property.startsWith("unequipped"))
|
|
{ if(isEquipped()) return false;}
|
|
else if (Property.startsWith("equipping"))
|
|
{ if(!isEquipping()) return false;}
|
|
|
|
else if (Property.startsWith("token"))
|
|
{ if(!isToken()) return false;}
|
|
else if (Property.startsWith("nonToken"))
|
|
{ if(isToken()) return false;}
|
|
|
|
else if (Property.startsWith("power") || // 8/10
|
|
Property.startsWith("toughness") ||
|
|
Property.startsWith("cmc"))
|
|
{
|
|
int x = 0;
|
|
int y = 0;
|
|
int z = 0;
|
|
|
|
if (Property.startsWith("power") )
|
|
{
|
|
z = 7;
|
|
y = getNetAttack();
|
|
}
|
|
else if (Property.startsWith("toughness"))
|
|
{
|
|
z = 11;
|
|
y = getNetDefense();
|
|
}
|
|
else if (Property.startsWith("cmc"))
|
|
{
|
|
z = 5;
|
|
y = getCMC();
|
|
}
|
|
|
|
if (Property.substring(z).equals("X")) {
|
|
x = CardFactoryUtil.xCount(source, source.getSVar("X"));
|
|
}
|
|
else
|
|
x = Integer.parseInt(Property.substring(z));
|
|
|
|
if (!compare(y, Property, x))
|
|
return false;
|
|
}
|
|
|
|
else if (Property.startsWith("counters")) // syntax example: countersGE9 P1P1 or countersLT12TIME (greater number than 99 not supported)
|
|
{
|
|
int number = 0;
|
|
if (Property.substring(10,11).equals("X"))
|
|
number = CardFactoryUtil.xCount(source, getSVar("X"));
|
|
else
|
|
number = Integer.parseInt(Property.substring(10,11));
|
|
|
|
String type = Property.substring(11);
|
|
String comparator = Property.substring(8,10); // comparator = EQ, LE, GE etc.
|
|
int actualnumber = getCounters(Counters.getType(type));
|
|
|
|
if (!compare(actualnumber, comparator, number))
|
|
return false;
|
|
}
|
|
|
|
else if (Property.startsWith("attacking")) { if(!isAttacking()) return false;}
|
|
|
|
else if (Property.startsWith("notattacking")) { if(isAttacking()) return false;}
|
|
|
|
else if (Property.startsWith("blocking")) { if(!isBlocking()) return false;}
|
|
|
|
else if (Property.startsWith("notblocking")) { if(isBlocking()) return false;}
|
|
|
|
else if (Property.startsWith("blocked")) { if(!AllZone.Combat.isBlocked(this)) return false;}
|
|
|
|
else if(Property.startsWith("named")) //by name
|
|
{ if(!getName().equals(Property.substring(5))) return false;}
|
|
else if(Property.startsWith("non")) // ... Other Card types
|
|
{ if(isType(Property.substring(3))) return false;}
|
|
else
|
|
if(!isType(Property)) return false;
|
|
return true;
|
|
}//hasProperty
|
|
|
|
public static boolean compare(int leftSide, String comp, int rightSide){
|
|
// should this function be somewhere else?
|
|
// leftSide COMPARED to rightSide:
|
|
if (comp.contains("LT")) return leftSide < rightSide;
|
|
|
|
else if (comp.contains("LE")) return leftSide <= rightSide;
|
|
|
|
else if (comp.contains("EQ")) return leftSide == rightSide;
|
|
|
|
else if (comp.contains("GE")) return leftSide >= rightSide;
|
|
|
|
else if (comp.contains("GT")) return leftSide > rightSide;
|
|
|
|
else if (comp.contains("NE")) return leftSide != rightSide; // not equals
|
|
|
|
return false;
|
|
}
|
|
|
|
public void setImmutable(boolean isImmutable) {
|
|
this.isImmutable = isImmutable;
|
|
}
|
|
|
|
public boolean isImmutable() {
|
|
return isImmutable;
|
|
}
|
|
|
|
/*
|
|
* there are easy checkers for Color. The CardUtil functions should
|
|
* be made part of the Card class, so calling out is not necessary
|
|
*/
|
|
|
|
public boolean isBlack() {
|
|
return CardUtil.getColors(this).contains(Constant.Color.Black);
|
|
}
|
|
|
|
public boolean isBlue() {
|
|
return CardUtil.getColors(this).contains(Constant.Color.Blue);
|
|
}
|
|
|
|
public boolean isRed() {
|
|
return CardUtil.getColors(this).contains(Constant.Color.Red);
|
|
}
|
|
|
|
public boolean isGreen() {
|
|
return CardUtil.getColors(this).contains(Constant.Color.Green);
|
|
}
|
|
|
|
public boolean isWhite() {
|
|
return CardUtil.getColors(this).contains(Constant.Color.White);
|
|
}
|
|
|
|
public boolean isColorless() {
|
|
return CardUtil.getColors(this).contains(Constant.Color.Colorless);
|
|
}
|
|
|
|
public boolean sharesColorWith(final Card c1) {
|
|
boolean shares = false;
|
|
shares = shares || (isBlack() && c1.isBlack());
|
|
shares = shares || (isBlue() && c1.isBlue());
|
|
shares = shares || (isGreen() && c1.isGreen());
|
|
shares = shares || (isRed() && c1.isRed());
|
|
shares = shares || (isWhite() && c1.isWhite());
|
|
return shares;
|
|
}
|
|
|
|
public boolean isAttacking() {
|
|
CardList attackers = new CardList(AllZone.Combat.getAttackers());
|
|
attackers.addAll(AllZone.pwCombat.getAttackers());
|
|
return attackers.contains(this);
|
|
}
|
|
|
|
public boolean isBlocking() {
|
|
CardList blockers = AllZone.Combat.getAllBlockers();
|
|
blockers.add(AllZone.pwCombat.getAllBlockers());
|
|
return blockers.contains(this);
|
|
}
|
|
|
|
///////////////////////////
|
|
//
|
|
// Damage code
|
|
//
|
|
//////////////////////////
|
|
|
|
//all damage to cards is now handled in Card.java, no longer AllZone.GameAction...
|
|
public void addReceivedDamageFromThisTurn(Card c, int damage) {
|
|
receivedDamageFromThisTurn.put(c, damage);
|
|
}
|
|
|
|
public void setReceivedDamageFromThisTurn(HashMap<Card, Integer> receivedDamageFromThisTurn) {
|
|
this.receivedDamageFromThisTurn = receivedDamageFromThisTurn;
|
|
}
|
|
|
|
public HashMap<Card, Integer> getReceivedDamageFromThisTurn() {
|
|
return receivedDamageFromThisTurn;
|
|
}
|
|
|
|
public void resetReceivedDamageFromThisTurn() {
|
|
receivedDamageFromThisTurn.clear();
|
|
}
|
|
|
|
//the amount of damage needed to kill the creature
|
|
public int getKillDamage() {
|
|
return getNetDefense() + preventNextDamage - getDamage();
|
|
}
|
|
|
|
public void setDamage(int n) {
|
|
//if(this.getKeyword().contains("Prevent all damage that would be dealt to CARDNAME.")) n = 0;
|
|
damage = n;
|
|
}
|
|
|
|
public int getDamage() {
|
|
return damage;
|
|
}
|
|
|
|
public void addAssignedDamage(int damage, Card sourceCard) {
|
|
if(damage < 0) damage = 0;
|
|
|
|
int assignedDamage = damage;
|
|
addReceivedDamageFromThisTurn(sourceCard, damage);
|
|
|
|
if(!CardFactoryUtil.canDamage(sourceCard, this)) assignedDamage = 0;
|
|
|
|
Log.debug(this + " - was assigned " + assignedDamage + " damage, by " + sourceCard);
|
|
if(!assignedDamageHashMap.containsKey(sourceCard)) assignedDamageHashMap.put(sourceCard, assignedDamage);
|
|
else {
|
|
assignedDamageHashMap.put(sourceCard, assignedDamageHashMap.get(sourceCard) + assignedDamage);
|
|
}
|
|
|
|
Log.debug("***");
|
|
/*
|
|
if(sourceCards.size() > 1)
|
|
System.out.println("(MULTIPLE blockers):");
|
|
System.out.println("Assigned " + damage + " damage to " + card);
|
|
for (int i=0;i<sourceCards.size();i++){
|
|
System.out.println(sourceCards.get(i).getName() + " assigned damage to " + card.getName());
|
|
}
|
|
System.out.println("***");
|
|
*/
|
|
}
|
|
|
|
public void clearAssignedDamage() {
|
|
assignedDamageHashMap.clear();
|
|
}
|
|
|
|
public int getTotalAssignedDamage() {
|
|
int total = 0;
|
|
|
|
Collection<Integer> c = assignedDamageHashMap.values();
|
|
|
|
Iterator<Integer> itr = c.iterator();
|
|
while(itr.hasNext())
|
|
total += itr.next();
|
|
|
|
return total;
|
|
}
|
|
|
|
public HashMap<Card, Integer> getAssignedDamageHashMap() {
|
|
return assignedDamageHashMap;
|
|
}
|
|
|
|
public void addCombatDamage(HashMap<Card, Integer> map) {
|
|
CardList list = new CardList();
|
|
|
|
for(Entry<Card, Integer> entry : map.entrySet()){
|
|
Card source = entry.getKey();
|
|
list.add(source);
|
|
int damageToAdd = entry.getValue();
|
|
|
|
damageToAdd = preventDamage(damageToAdd, source, true);
|
|
|
|
if (damageToAdd > 0) {
|
|
if(isCreature() && source.getName().equals("Mirri the Cursed") ) {
|
|
final Card thisCard = source;
|
|
Ability ability2 = new Ability(thisCard, "0") {
|
|
@Override
|
|
public void resolve() {
|
|
thisCard.addCounter(Counters.P1P1, 1);
|
|
}
|
|
}; // ability2
|
|
|
|
StringBuilder sb2 = new StringBuilder();
|
|
sb2.append(thisCard.getName()).append(" - gets a +1/+1 counter");
|
|
ability2.setStackDescription(sb2.toString());
|
|
|
|
AllZone.Stack.add(ability2);
|
|
}
|
|
if(source.getKeyword().contains("Deathtouch") && isCreature()) {
|
|
AllZone.GameAction.destroy(this);
|
|
}
|
|
}
|
|
map.put(source, damageToAdd);
|
|
}
|
|
|
|
if(AllZoneUtil.isCardInPlay(this)) {
|
|
addDamage(map);
|
|
}
|
|
|
|
for(Entry<Card, Integer> entry : map.entrySet()){
|
|
Card source = entry.getKey();
|
|
CombatUtil.executeCombatDamageEffects(source);
|
|
}
|
|
}
|
|
|
|
//This should be also usable by the AI to forecast an effect (so it must not change the game state)
|
|
public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat) {
|
|
|
|
if(AllZoneUtil.isCardInPlay("Leyline of Punishment")) return damage;
|
|
|
|
int restDamage = damage;
|
|
Player player = source.getController();
|
|
|
|
if(isCombat) {
|
|
if(getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."))return 0;
|
|
if(getKeyword().contains("Prevent all combat damage that would be dealt to CARDNAME."))return 0;
|
|
if(source.getKeyword().contains("Prevent all combat damage that would be dealt to and dealt by CARDNAME."))return 0;
|
|
if(source.getKeyword().contains("Prevent all combat damage that would be dealt by CARDNAME."))return 0;
|
|
}
|
|
if(getKeyword().contains("Prevent all damage that would be dealt to CARDNAME."))return 0;
|
|
if(getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME."))return 0;
|
|
if(source.getKeyword().contains("Prevent all damage that would be dealt to and dealt by CARDNAME."))return 0;
|
|
if(source.getKeyword().contains("Prevent all damage that would be dealt by CARDNAME."))return 0;
|
|
|
|
if(hasStartOfKeyword("Absorb")) {
|
|
int absorbed = this.getKeywordMagnitude("Absorb");
|
|
if (restDamage > absorbed) restDamage = restDamage - absorbed;
|
|
else return 0;
|
|
}
|
|
|
|
if(hasStartOfKeyword("PreventAllDamageBy")) {
|
|
String valid = getKeyword().get(getKeywordPosition("PreventAllDamageBy"));
|
|
valid = valid.split(" ", 2)[1];
|
|
if (source.isValid(valid,this.getController(),this))
|
|
return 0;
|
|
}
|
|
|
|
/* Should use the PreventAllDamageBy
|
|
if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifact creatures.")
|
|
&& source.isCreature() && source.isArtifact()))return 0;
|
|
if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by artifacts.")
|
|
&& source.isArtifact()))return 0;
|
|
if((getKeyword().contains("Prevent all damage that would be dealt to CARDNAME by creatures.")
|
|
&& source.isCreature()))return 0;
|
|
*/
|
|
|
|
// specific Cards
|
|
if(isCreature()) { //and not a planeswalker
|
|
if((source.isCreature() && AllZoneUtil.isCardInPlay("Well-Laid Plans") && source.sharesColorWith(this)))return 0;
|
|
|
|
if((!isCombat && AllZoneUtil.isCardInPlay("Mark of Asylum", player)))return 0;
|
|
|
|
if((AllZoneUtil.isCardInPlay("Light of Sanction", player) && source.getController().isPlayer(player)))
|
|
return 0;
|
|
|
|
if (AllZoneUtil.isCardInPlay("Plated Pegasus") && source.isSpell()
|
|
&& restDamage > 0) restDamage = restDamage - 1;
|
|
} //Creature end
|
|
|
|
if (AllZoneUtil.isCardInPlay("Energy Storm") && source.isSpell()) return 0;
|
|
|
|
return restDamage;
|
|
}
|
|
|
|
public int preventDamage(final int damage, Card source, boolean isCombat) {
|
|
|
|
if(AllZoneUtil.isCardInPlay("Leyline of Punishment")) return damage;
|
|
|
|
int restDamage = damage;
|
|
|
|
restDamage = staticDamagePrevention(restDamage, source, isCombat);
|
|
|
|
if(restDamage >= preventNextDamage) {
|
|
restDamage = restDamage - preventNextDamage;
|
|
preventNextDamage = 0;
|
|
}
|
|
else {
|
|
restDamage = 0;
|
|
preventNextDamage = preventNextDamage - restDamage;
|
|
}
|
|
|
|
return restDamage;
|
|
}
|
|
|
|
public void addDamage(HashMap<Card, Integer> sourcesMap) {
|
|
for(Entry<Card, Integer> entry : sourcesMap.entrySet()) {
|
|
addDamageWithoutPrevention(entry.getValue(), entry.getKey()); // damage prevention is already checked!
|
|
}
|
|
}
|
|
|
|
public void addDamage(final int damageIn, final Card source) {
|
|
int damageToAdd = damageIn;
|
|
damageToAdd = preventDamage(damageToAdd, source, false);
|
|
|
|
addDamageWithoutPrevention(damageToAdd,source);
|
|
}
|
|
|
|
public void addDamageWithoutPrevention(final int damageIn, final Card source) {
|
|
int damageToAdd = damageIn;
|
|
|
|
if( damageToAdd == 0 ) return; //Rule 119.8
|
|
|
|
if(this.isPlaneswalker()) {
|
|
this.subtractCounter(Counters.LOYALTY, damageToAdd);
|
|
}
|
|
|
|
if((source.getKeyword().contains("Wither") || source.getKeyword().contains("Infect")) && this.isCreature()) {
|
|
this.addCounterFromNonEffect(Counters.M1M1, damageToAdd);
|
|
damageToAdd = 0;
|
|
}
|
|
|
|
if(source.getName().equals("Spiritmonger")) {
|
|
Ability ability2 = new Ability(source, "0") {
|
|
@Override
|
|
public void resolve() {
|
|
source.addCounter(Counters.P1P1, 1);
|
|
}
|
|
}; // ability2
|
|
|
|
StringBuilder sb2 = new StringBuilder();
|
|
sb2.append(source.getName()).append(" - gets a +1/+1 counter");
|
|
ability2.setStackDescription(sb2.toString());
|
|
|
|
AllZone.Stack.add(ability2);
|
|
}
|
|
|
|
if(this.getName().equals("Fungusaur")) {
|
|
Ability ability2 = new Ability(this, "0") {
|
|
@Override
|
|
public void resolve() {
|
|
addCounter(Counters.P1P1, 1);
|
|
}
|
|
}; // ability2
|
|
|
|
StringBuilder sb2 = new StringBuilder();
|
|
sb2.append(this.getName()).append(" - gets a +1/+1 counter");
|
|
ability2.setStackDescription(sb2.toString());
|
|
|
|
AllZone.Stack.add(ability2);
|
|
}
|
|
|
|
if(source.getKeyword().contains("Deathtouch") && this.isCreature()) {
|
|
AllZone.GameAction.destroy(this);
|
|
//AllZone.Combat.removeFromCombat(card);
|
|
}
|
|
|
|
System.out.println("Adding " + damageToAdd + " damage to " + getName());
|
|
Log.debug("Adding " + damageToAdd + " damage to " + getName());
|
|
if(AllZoneUtil.isCardInPlay(this) && CardFactoryUtil.canDamage(source, this)) {
|
|
damage += damageToAdd;
|
|
}
|
|
|
|
if(source.getKeyword().contains("Lifelink") && CardFactoryUtil.canDamage(source, this)) GameActionUtil.executeLifeLinkEffects(source, damageToAdd);
|
|
|
|
if(isEnchantedBy("Mortal Wound")) {
|
|
AllZone.GameAction.destroy(this);
|
|
}
|
|
|
|
CardList cl = CardFactoryUtil.getAurasEnchanting(source, "Guilty Conscience");
|
|
for(Card c:cl) {
|
|
GameActionUtil.executeGuiltyConscienceEffects(source, c, damageToAdd);
|
|
}
|
|
}
|
|
private ArrayList<SetInfo> Sets = new ArrayList<SetInfo>();
|
|
private String curSetCode = "";
|
|
|
|
public void addSet(SetInfo sInfo)
|
|
{
|
|
Sets.add(sInfo);
|
|
}
|
|
|
|
public ArrayList<SetInfo> getSets()
|
|
{
|
|
return Sets;
|
|
}
|
|
|
|
public void setSets(ArrayList<SetInfo> siList)
|
|
{
|
|
Sets = siList;
|
|
}
|
|
|
|
public void setCurSetCode(String setCode) {
|
|
curSetCode = setCode;
|
|
}
|
|
|
|
public String getCurSetCode() {
|
|
return curSetCode;
|
|
}
|
|
|
|
public void setRandomSetCode() {
|
|
if (Sets.size() < 1)
|
|
return;
|
|
|
|
Random r = new Random();
|
|
SetInfo si = Sets.get(r.nextInt(Sets.size()));
|
|
|
|
curSetCode = si.Code;
|
|
}
|
|
|
|
public String getSetImageName(String setCode) {
|
|
return "/" + setCode + "/" + getImageName();
|
|
}
|
|
|
|
public String getCurSetImage() {
|
|
return getSetImageName(curSetCode);
|
|
}
|
|
|
|
public String getCurSetRarity() {
|
|
for (int i=0; i<Sets.size(); i++)
|
|
if (Sets.get(i).Code.equals(curSetCode))
|
|
return Sets.get(i).Rarity;
|
|
|
|
return "";
|
|
}
|
|
|
|
}//end Card class
|