2010-11-21 10:54:59 -08:00
|
|
|
package magic.model;
|
|
|
|
|
|
|
|
import magic.ai.ArtificialScoringSystem;
|
|
|
|
import magic.data.IconImages;
|
2011-08-30 23:08:53 -07:00
|
|
|
import magic.model.action.MagicAction;
|
|
|
|
import magic.model.action.MagicAttachEquipmentAction;
|
|
|
|
import magic.model.action.MagicChangeCountersAction;
|
|
|
|
import magic.model.action.MagicChangeStateAction;
|
|
|
|
import magic.model.action.MagicDestroyAction;
|
|
|
|
import magic.model.action.MagicGainControlAction;
|
|
|
|
import magic.model.action.MagicRemoveFromPlayAction;
|
|
|
|
import magic.model.action.MagicSacrificeAction;
|
2010-11-21 10:54:59 -08:00
|
|
|
import magic.model.event.MagicActivation;
|
2011-09-09 05:45:35 -07:00
|
|
|
import magic.model.event.MagicPlayAuraEvent;
|
2010-11-21 10:54:59 -08:00
|
|
|
import magic.model.target.MagicTarget;
|
2011-09-09 05:45:35 -07:00
|
|
|
import magic.model.choice.MagicTargetChoice;
|
2011-09-17 06:11:26 -07:00
|
|
|
import magic.model.mstatic.MagicLayer;
|
2011-08-10 08:28:35 -07:00
|
|
|
|
2011-08-30 23:08:53 -07:00
|
|
|
import javax.swing.ImageIcon;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.EnumSet;
|
|
|
|
import java.util.List;
|
2010-11-21 10:54:59 -08:00
|
|
|
|
|
|
|
public class MagicPermanent implements MagicSource,MagicTarget,Comparable<MagicPermanent> {
|
|
|
|
|
|
|
|
public static final int NO_COLOR_FLAGS=-1;
|
2011-09-10 04:35:29 -07:00
|
|
|
public static final MagicPermanent NONE = new MagicPermanent(-1L, MagicCard.NONE, MagicPlayer.NONE) {
|
2011-09-04 03:48:38 -07:00
|
|
|
@Override
|
|
|
|
public boolean isValid() {
|
|
|
|
return false;
|
|
|
|
}
|
2011-09-06 02:56:34 -07:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "MagicPermanent.NONE";
|
|
|
|
}
|
2011-09-10 04:35:29 -07:00
|
|
|
@Override
|
|
|
|
public MagicPermanent copy(final MagicCopyMap copyMap) {
|
|
|
|
return this;
|
|
|
|
}
|
2011-09-03 23:49:47 -07:00
|
|
|
};
|
2010-11-21 10:54:59 -08:00
|
|
|
|
2011-09-10 04:35:29 -07:00
|
|
|
private final long id;
|
|
|
|
private final MagicCardDefinition cardDefinition;
|
2011-09-24 23:36:46 -07:00
|
|
|
private final MagicCard card;
|
2010-11-21 10:54:59 -08:00
|
|
|
private MagicPlayer controller;
|
2011-09-03 23:49:47 -07:00
|
|
|
private MagicPermanent equippedCreature = MagicPermanent.NONE;
|
2011-09-10 06:00:38 -07:00
|
|
|
private final MagicPermanentSet equipmentPermanents;
|
2011-09-03 23:49:47 -07:00
|
|
|
private MagicPermanent enchantedCreature = MagicPermanent.NONE;
|
2011-09-10 06:00:38 -07:00
|
|
|
private final MagicPermanentSet auraPermanents;
|
2011-09-03 23:49:47 -07:00
|
|
|
private MagicPermanent blockedCreature = MagicPermanent.NONE;
|
2011-09-10 06:00:38 -07:00
|
|
|
private final MagicPermanentList blockingCreatures;
|
2011-10-18 00:00:21 -07:00
|
|
|
private MagicCardList exiledCards;
|
2010-11-21 10:54:59 -08:00
|
|
|
private int counters[]=new int[MagicCounterType.NR_COUNTERS];
|
|
|
|
private int stateFlags=MagicPermanentState.Summoned.getMask();
|
|
|
|
private long turnAbilityFlags=0;
|
|
|
|
private int turnPowerIncr=0;
|
|
|
|
private int turnToughnessIncr=0;
|
|
|
|
private int turnColorFlags=NO_COLOR_FLAGS;
|
|
|
|
private int abilityPlayedThisTurn=0;
|
|
|
|
private int damage=0;
|
|
|
|
private int preventDamage=0;
|
2011-09-10 06:00:38 -07:00
|
|
|
private final int fixedScore;
|
2011-06-14 03:08:34 -07:00
|
|
|
|
|
|
|
// Allows cached retrieval of power, toughness and abilities.
|
2010-11-21 10:54:59 -08:00
|
|
|
private boolean cached=false;
|
2011-09-03 07:20:53 -07:00
|
|
|
private MagicPowerToughness cachedTurnPowerToughness;
|
2010-11-21 10:54:59 -08:00
|
|
|
private long cachedTurnAbilityFlags=0;
|
2011-06-21 02:04:08 -07:00
|
|
|
private EnumSet<MagicSubType> cachedSubTypeFlags;
|
2011-06-06 01:13:15 -07:00
|
|
|
private int cachedTypeFlags=0;
|
2010-11-21 10:54:59 -08:00
|
|
|
private int cachedColorFlags=0;
|
2011-09-12 05:05:22 -07:00
|
|
|
|
|
|
|
// remember order among blockers (blockedName + id + block order)
|
|
|
|
private String blockedName;
|
|
|
|
|
2010-11-21 10:54:59 -08:00
|
|
|
public MagicPermanent(final long id,final MagicCard card,final MagicPlayer controller) {
|
|
|
|
this.id=id;
|
|
|
|
this.card=card;
|
|
|
|
this.cardDefinition=card.getCardDefinition();
|
|
|
|
this.controller=controller;
|
|
|
|
equipmentPermanents=new MagicPermanentSet();
|
|
|
|
auraPermanents=new MagicPermanentSet();
|
|
|
|
blockingCreatures=new MagicPermanentList();
|
2011-10-18 00:00:21 -07:00
|
|
|
exiledCards = new MagicCardList();
|
2010-11-21 10:54:59 -08:00
|
|
|
fixedScore=ArtificialScoringSystem.getFixedPermanentScore(this);
|
|
|
|
}
|
|
|
|
|
2011-09-10 04:35:29 -07:00
|
|
|
private MagicPermanent(final MagicCopyMap copyMap, final MagicPermanent sourcePermanent) {
|
|
|
|
id = sourcePermanent.id;
|
|
|
|
cardDefinition = sourcePermanent.cardDefinition;
|
2011-09-10 05:02:40 -07:00
|
|
|
|
|
|
|
copyMap.put(sourcePermanent, this);
|
2011-09-10 04:35:29 -07:00
|
|
|
|
2011-09-24 23:36:46 -07:00
|
|
|
card = copyMap.copy(sourcePermanent.card);
|
|
|
|
controller = copyMap.copy(sourcePermanent.controller);
|
2011-09-10 04:35:29 -07:00
|
|
|
stateFlags=sourcePermanent.stateFlags;
|
2010-11-21 10:54:59 -08:00
|
|
|
turnColorFlags=sourcePermanent.turnColorFlags;
|
|
|
|
turnAbilityFlags=sourcePermanent.turnAbilityFlags;
|
|
|
|
turnPowerIncr=sourcePermanent.turnPowerIncr;
|
|
|
|
turnToughnessIncr=sourcePermanent.turnToughnessIncr;
|
|
|
|
counters=Arrays.copyOf(sourcePermanent.counters,MagicCounterType.NR_COUNTERS);
|
|
|
|
abilityPlayedThisTurn=sourcePermanent.abilityPlayedThisTurn;
|
|
|
|
equippedCreature=copyMap.copy(sourcePermanent.equippedCreature);
|
|
|
|
equipmentPermanents=new MagicPermanentSet(copyMap,sourcePermanent.equipmentPermanents);
|
|
|
|
enchantedCreature=copyMap.copy(sourcePermanent.enchantedCreature);
|
|
|
|
auraPermanents=new MagicPermanentSet(copyMap,sourcePermanent.auraPermanents);
|
|
|
|
blockedCreature=copyMap.copy(sourcePermanent.blockedCreature);
|
|
|
|
blockingCreatures=new MagicPermanentList(copyMap,sourcePermanent.blockingCreatures);
|
2011-10-18 00:00:21 -07:00
|
|
|
exiledCards = new MagicCardList(copyMap,sourcePermanent.exiledCards);
|
2010-11-21 10:54:59 -08:00
|
|
|
damage=sourcePermanent.damage;
|
|
|
|
preventDamage=sourcePermanent.preventDamage;
|
|
|
|
fixedScore=sourcePermanent.fixedScore;
|
2011-09-10 04:35:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public MagicPermanent copy(final MagicCopyMap copyMap) {
|
|
|
|
return new MagicPermanent(copyMap, this);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-09-05 20:36:49 -07:00
|
|
|
public MagicPermanent map(final MagicGame game) {
|
|
|
|
final MagicPlayer mappedController=controller.map(game);
|
2010-11-21 10:54:59 -08:00
|
|
|
return mappedController.getPermanents().getPermanent(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getId() {
|
|
|
|
return id;
|
|
|
|
}
|
2011-09-04 03:48:38 -07:00
|
|
|
|
|
|
|
public boolean isValid() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isInvalid() {
|
|
|
|
return !isValid();
|
|
|
|
}
|
2010-11-21 10:54:59 -08:00
|
|
|
|
2011-09-10 06:00:38 -07:00
|
|
|
long getPermanentId() {
|
2011-09-08 02:23:22 -07:00
|
|
|
final long[] input = {
|
2011-06-14 21:47:33 -07:00
|
|
|
cardDefinition.getIndex(),
|
|
|
|
stateFlags,
|
|
|
|
damage,
|
|
|
|
preventDamage,
|
2011-09-03 23:49:47 -07:00
|
|
|
equippedCreature.getId(),
|
|
|
|
enchantedCreature.getId(),
|
|
|
|
blockedCreature.getId(),
|
2011-06-14 21:47:33 -07:00
|
|
|
counters[0],
|
|
|
|
counters[1],
|
|
|
|
counters[2],
|
|
|
|
counters[3],
|
|
|
|
turnAbilityFlags,
|
|
|
|
turnPowerIncr,
|
|
|
|
turnToughnessIncr,
|
|
|
|
turnColorFlags,
|
|
|
|
abilityPlayedThisTurn,
|
2011-06-18 08:42:41 -07:00
|
|
|
damage,
|
|
|
|
preventDamage,
|
2011-06-14 21:47:33 -07:00
|
|
|
};
|
|
|
|
return magic.MurmurHash3.hash(input);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Determines uniqueness of a mana permanent, e.g. for producing mana, all Mountains are equal. */
|
|
|
|
public int getManaId() {
|
|
|
|
// Creatures or lands that can be animated are unique by default.
|
|
|
|
if (cardDefinition.hasExcludeManaOrCombat()) {
|
|
|
|
return (int)id;
|
|
|
|
}
|
|
|
|
// Uniqueness is determined by card definition and number of charge counters.
|
|
|
|
return -((cardDefinition.getIndex()<<16)+getCounters(MagicCounterType.Charge));
|
|
|
|
}
|
|
|
|
|
|
|
|
public MagicCard getCard() {
|
|
|
|
return card;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public MagicCardDefinition getCardDefinition() {
|
|
|
|
return cardDefinition;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Collection<MagicActivation> getActivations() {
|
|
|
|
return cardDefinition.getActivations();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean producesMana() {
|
|
|
|
return !cardDefinition.getManaActivations().isEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getName() {
|
|
|
|
return card.getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setController(final MagicPlayer controller) {
|
|
|
|
this.controller=controller;
|
|
|
|
}
|
|
|
|
|
|
|
|
public MagicPlayer getController() {
|
|
|
|
return controller;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setState(final MagicPermanentState state) {
|
|
|
|
stateFlags|=state.getMask();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void clearState(final MagicPermanentState state) {
|
|
|
|
stateFlags&=Integer.MAX_VALUE-state.getMask();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasState(final MagicPermanentState state) {
|
|
|
|
return state.hasState(stateFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getStateFlags() {
|
|
|
|
return stateFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setStateFlags(final int flags) {
|
|
|
|
stateFlags=flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isTapped() {
|
|
|
|
return hasState(MagicPermanentState.Tapped);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public MagicColoredType getColoredType() {
|
|
|
|
return cardDefinition.getColoredType();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTurnColorFlags(final int colorFlags) {
|
|
|
|
turnColorFlags=colorFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getTurnColorFlags() {
|
|
|
|
return turnColorFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2011-09-18 07:46:22 -07:00
|
|
|
public int getColorFlags(final MagicGame game) {
|
2010-11-21 10:54:59 -08:00
|
|
|
// Check if cached.
|
|
|
|
if (cached) {
|
|
|
|
return cachedColorFlags;
|
|
|
|
}
|
|
|
|
// Check if until end of turn color flags.
|
|
|
|
if (turnColorFlags!=NO_COLOR_FLAGS) {
|
|
|
|
return turnColorFlags;
|
|
|
|
}
|
2011-09-18 03:50:10 -07:00
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
int flags = cardDefinition.getColorFlags();
|
2011-09-18 17:40:54 -07:00
|
|
|
|
|
|
|
flags = MagicLayer.getColorFlags(game, this, flags);
|
|
|
|
|
2011-09-18 03:50:10 -07:00
|
|
|
return flags;
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public void changeCounters(final MagicCounterType counterType,final int amount) {
|
2011-06-16 06:34:47 -07:00
|
|
|
counters[counterType.ordinal()]+=amount;
|
2010-11-21 10:54:59 -08:00
|
|
|
if (cached) {
|
|
|
|
switch (counterType) {
|
|
|
|
case PlusOne:
|
2011-09-15 20:01:52 -07:00
|
|
|
cachedTurnPowerToughness.add(amount,amount);
|
2010-11-21 10:54:59 -08:00
|
|
|
break;
|
|
|
|
case MinusOne:
|
2011-09-15 20:01:52 -07:00
|
|
|
cachedTurnPowerToughness.add(-amount,-amount);
|
2010-11-21 10:54:59 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getCounters(final MagicCounterType counterType) {
|
2011-06-16 06:34:47 -07:00
|
|
|
return counters[counterType.ordinal()];
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasCounters() {
|
|
|
|
for (final int amount : counters) {
|
|
|
|
if (amount>0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
public EnumSet<MagicSubType> getSubTypeFlags(final MagicGame game) {
|
2010-11-21 10:54:59 -08:00
|
|
|
// Check if cached.
|
|
|
|
if (cached) {
|
|
|
|
return cachedSubTypeFlags;
|
|
|
|
}
|
|
|
|
|
2011-09-15 19:21:51 -07:00
|
|
|
EnumSet<MagicSubType> flags=cardDefinition.getSubTypeFlags();
|
|
|
|
|
|
|
|
if (getCardDefinition().hasAbility(MagicAbility.Changeling)) {
|
|
|
|
flags.addAll(MagicSubType.ALL_CREATURES);
|
|
|
|
}
|
|
|
|
|
2011-09-18 17:40:54 -07:00
|
|
|
flags = MagicLayer.getSubTypeFlags(game,this,flags);
|
2011-09-18 07:46:22 -07:00
|
|
|
|
2010-11-21 10:54:59 -08:00
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
public boolean hasSubType(final MagicSubType subType, final MagicGame game) {
|
|
|
|
return subType.hasSubType(getSubTypeFlags(game));
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public MagicPowerToughness getPowerToughness(final MagicGame game,final boolean turn) {
|
|
|
|
// Check if cached.
|
|
|
|
if (cached&&turn) {
|
|
|
|
return cachedTurnPowerToughness;
|
|
|
|
}
|
|
|
|
|
2011-09-18 03:50:10 -07:00
|
|
|
//get starting P/T from card def (includes CDA)
|
2011-09-18 18:40:52 -07:00
|
|
|
final MagicPowerToughness pt = cardDefinition.genPowerToughness(game, getController());
|
2011-09-17 06:11:26 -07:00
|
|
|
|
|
|
|
//apply global effects
|
|
|
|
MagicLayer.getPowerToughness(game, this, pt);
|
|
|
|
|
|
|
|
//apply turn effects
|
2010-11-21 10:54:59 -08:00
|
|
|
if (turn) {
|
2011-09-15 20:38:54 -07:00
|
|
|
pt.add(turnPowerIncr, turnToughnessIncr);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
return pt;
|
|
|
|
}
|
|
|
|
|
|
|
|
public MagicPowerToughness getPowerToughness(final MagicGame game) {
|
|
|
|
return getPowerToughness(game,true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getPower(final MagicGame game) {
|
|
|
|
return getPowerToughness(game,true).getPositivePower();
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getToughness(final MagicGame game) {
|
|
|
|
return getPowerToughness(game,true).getPositiveToughness();
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getTurnPower() {
|
|
|
|
return turnPowerIncr;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTurnPower(final int power) {
|
|
|
|
turnPowerIncr=power;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void changeTurnPower(final int amount) {
|
|
|
|
turnPowerIncr+=amount;
|
|
|
|
if (cached) {
|
2011-09-15 20:38:54 -07:00
|
|
|
cachedTurnPowerToughness.add(amount,0);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getTurnToughness() {
|
|
|
|
return turnToughnessIncr;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTurnToughness(final int toughness) {
|
|
|
|
turnToughnessIncr=toughness;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void changeTurnToughness(final int amount) {
|
|
|
|
turnToughnessIncr+=amount;
|
|
|
|
if (cached) {
|
2011-09-15 20:38:54 -07:00
|
|
|
cachedTurnPowerToughness.add(0,amount);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setTurnAbilityFlags(final long flags) {
|
|
|
|
turnAbilityFlags=flags;
|
|
|
|
if (cached) {
|
|
|
|
cachedTurnAbilityFlags|=flags;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getTurnAbilityFlags() {
|
|
|
|
return turnAbilityFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getAllAbilityFlags(final MagicGame game,final boolean turn) {
|
|
|
|
// Check if cached.
|
|
|
|
if (cached&&turn) {
|
|
|
|
return cachedTurnAbilityFlags;
|
2011-09-15 19:21:51 -07:00
|
|
|
}
|
|
|
|
long flags = getCurrentAbilityFlags(game);
|
2010-11-21 10:54:59 -08:00
|
|
|
if (turn) {
|
|
|
|
flags|=turnAbilityFlags;
|
|
|
|
}
|
|
|
|
return flags&MagicAbility.EXCLUDE_MASK;
|
|
|
|
}
|
2011-09-15 19:21:51 -07:00
|
|
|
|
|
|
|
private long getCurrentAbilityFlags(final MagicGame game) {
|
|
|
|
long flags=cardDefinition.getAbilityFlags();
|
2011-09-17 06:11:26 -07:00
|
|
|
|
|
|
|
//apply global effects
|
|
|
|
return MagicLayer.getAbilityFlags(game, this, flags);
|
2011-09-15 19:21:51 -07:00
|
|
|
}
|
2010-11-21 10:54:59 -08:00
|
|
|
|
|
|
|
public long getAllAbilityFlags(final MagicGame game) {
|
|
|
|
return getAllAbilityFlags(game,true);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean hasAbility(final MagicGame game,final MagicAbility ability) {
|
|
|
|
// Check if cached.
|
|
|
|
if (cached) {
|
|
|
|
return ability.hasAbility(cachedTurnAbilityFlags);
|
|
|
|
}
|
|
|
|
if (ability.hasAbility(turnAbilityFlags)) {
|
|
|
|
return true;
|
|
|
|
}
|
2011-09-15 19:21:51 -07:00
|
|
|
long flags = getCurrentAbilityFlags(game);
|
2010-11-21 10:54:59 -08:00
|
|
|
return ability.hasAbility(flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getScore(final MagicGame game) {
|
2011-06-16 23:18:00 -07:00
|
|
|
return fixedScore + ArtificialScoringSystem.getVariablePermanentScore(game,this);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public int getStaticScore(final MagicGame game) {
|
|
|
|
return cardDefinition.getStaticType().getScore(game,this);
|
|
|
|
}
|
|
|
|
|
2011-09-10 06:00:38 -07:00
|
|
|
void setCached(final MagicGame game,final boolean aCached) {
|
2011-09-09 23:00:32 -07:00
|
|
|
if (aCached) {
|
2010-11-21 10:54:59 -08:00
|
|
|
cachedTurnPowerToughness=getPowerToughness(game,true);
|
|
|
|
cachedTurnAbilityFlags=getAllAbilityFlags(game,true);
|
2011-09-18 07:46:22 -07:00
|
|
|
cachedSubTypeFlags=getSubTypeFlags(game);
|
|
|
|
cachedTypeFlags=getTypeFlags(game);
|
|
|
|
cachedColorFlags=getColorFlags(game);
|
2011-09-03 19:33:14 -07:00
|
|
|
}
|
2011-09-09 23:00:32 -07:00
|
|
|
this.cached=aCached;
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public int getDamage() {
|
|
|
|
return damage;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDamage(final int damage) {
|
|
|
|
this.damage=damage;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int getPreventDamage() {
|
|
|
|
return preventDamage;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setPreventDamage(final int amount) {
|
|
|
|
preventDamage=amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getLethalDamage(final int toughness) {
|
|
|
|
return toughness<=damage?0:toughness-damage;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tap symbol.
|
|
|
|
public boolean canTap(final MagicGame game) {
|
2011-06-18 08:42:41 -07:00
|
|
|
return !hasState(MagicPermanentState.Tapped) &&
|
|
|
|
(!hasState(MagicPermanentState.Summoned) ||
|
2011-09-18 07:46:22 -07:00
|
|
|
!isCreature(game) ||
|
2011-06-18 08:42:41 -07:00
|
|
|
hasAbility(game,MagicAbility.Haste)
|
|
|
|
);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Untap symbol.
|
|
|
|
public boolean canUntap(final MagicGame game) {
|
2011-06-18 08:42:41 -07:00
|
|
|
return hasState(MagicPermanentState.Tapped) &&
|
|
|
|
(!hasState(MagicPermanentState.Summoned) ||
|
2011-09-18 07:46:22 -07:00
|
|
|
!isCreature(game) ||
|
2011-06-18 08:42:41 -07:00
|
|
|
hasAbility(game,MagicAbility.Haste)
|
|
|
|
);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canRegenerate() {
|
|
|
|
return !hasState(MagicPermanentState.Regenerated)&&!hasState(MagicPermanentState.CannotBeRegenerated);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isRegenerated() {
|
|
|
|
return hasState(MagicPermanentState.Regenerated)&&!hasState(MagicPermanentState.CannotBeRegenerated);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isAttacking() {
|
|
|
|
return hasState(MagicPermanentState.Attacking);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isBlocked() {
|
|
|
|
return hasState(MagicPermanentState.Blocked);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isBlocking() {
|
|
|
|
return hasState(MagicPermanentState.Blocking);
|
|
|
|
}
|
|
|
|
|
|
|
|
public MagicPermanent getBlockedCreature() {
|
|
|
|
return blockedCreature;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setBlockedCreature(final MagicPermanent creature) {
|
2011-09-12 05:05:22 -07:00
|
|
|
if (creature.isValid()) {
|
|
|
|
blockedName = creature.getName() + creature.getId() + (100 + creature.numBlockingCreatures());
|
|
|
|
}
|
|
|
|
blockedCreature = creature;
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
2011-09-12 05:05:22 -07:00
|
|
|
public String getBlockedName() {
|
|
|
|
return blockedName;
|
|
|
|
}
|
|
|
|
|
2010-11-21 10:54:59 -08:00
|
|
|
public MagicPermanentList getBlockingCreatures() {
|
|
|
|
return blockingCreatures;
|
|
|
|
}
|
|
|
|
|
2011-09-12 05:05:22 -07:00
|
|
|
public int numBlockingCreatures() {
|
|
|
|
return blockingCreatures.size();
|
|
|
|
}
|
|
|
|
|
2010-11-21 10:54:59 -08:00
|
|
|
public void setBlockingCreatures(final MagicPermanentList creatures) {
|
|
|
|
blockingCreatures.clear();
|
|
|
|
blockingCreatures.addAll(creatures);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addBlockingCreature(final MagicPermanent creature) {
|
|
|
|
blockingCreatures.add(creature);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeBlockingCreature(final MagicPermanent creature) {
|
|
|
|
blockingCreatures.remove(creature);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeBlockingCreatures() {
|
|
|
|
blockingCreatures.clear();
|
|
|
|
}
|
|
|
|
|
2011-10-18 00:00:21 -07:00
|
|
|
public MagicCardList getExiledCards() {
|
|
|
|
return exiledCards;
|
2011-10-12 04:30:52 -07:00
|
|
|
}
|
|
|
|
|
2011-10-18 00:00:21 -07:00
|
|
|
public void addExiledCard(final MagicCard card) {
|
2011-10-19 01:27:04 -07:00
|
|
|
// only non tokens can be added
|
2011-10-14 18:57:18 -07:00
|
|
|
if (!card.isToken()) {
|
2011-10-18 00:00:21 -07:00
|
|
|
exiledCards.add(card);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeExiledCard(final MagicCard card) {
|
2011-10-19 01:27:04 -07:00
|
|
|
exiledCards.remove(card);
|
2011-10-12 04:30:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-10 06:00:38 -07:00
|
|
|
void checkState(final MagicGame game, final List<MagicAction> actions) {
|
2011-09-18 07:46:22 -07:00
|
|
|
if (isCreature(game)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
final int toughness=getToughness(game);
|
|
|
|
if (toughness<=0) {
|
|
|
|
game.logAppendMessage(controller,getName()+" is put into its owner's graveyard.");
|
2011-06-13 21:35:00 -07:00
|
|
|
actions.add(new MagicRemoveFromPlayAction(this,MagicLocationType.Graveyard));
|
2010-12-31 06:16:18 -08:00
|
|
|
} else if (hasState(MagicPermanentState.Destroyed)) {
|
2011-06-13 21:35:00 -07:00
|
|
|
actions.add(new MagicChangeStateAction(this,MagicPermanentState.Destroyed,false));
|
|
|
|
actions.add(new MagicDestroyAction(this));
|
2010-11-21 10:54:59 -08:00
|
|
|
} else if (toughness-damage<=0) {
|
2011-06-13 21:35:00 -07:00
|
|
|
actions.add(new MagicDestroyAction(this));
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
2011-09-21 20:34:53 -07:00
|
|
|
}
|
2011-10-05 06:59:20 -07:00
|
|
|
|
2011-09-21 20:34:53 -07:00
|
|
|
if (cardDefinition.isAura()) {
|
2011-09-09 05:45:35 -07:00
|
|
|
final MagicPlayAuraEvent auraEvent = (MagicPlayAuraEvent)cardDefinition.getCardEvent();
|
|
|
|
//not targeting since Aura is already attached
|
|
|
|
final MagicTargetChoice tchoice = new MagicTargetChoice(auraEvent.getTargetChoice(), false);
|
2011-09-09 05:57:09 -07:00
|
|
|
if (!enchantedCreature.isValid() ||
|
|
|
|
!game.isLegalTarget(getController(),this,tchoice,enchantedCreature) ||
|
|
|
|
enchantedCreature.hasProtectionFrom(game,this)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
game.logAppendMessage(controller,getName()+" is put into its owner's graveyard.");
|
2011-06-13 21:35:00 -07:00
|
|
|
actions.add(new MagicRemoveFromPlayAction(this,MagicLocationType.Graveyard));
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
2011-09-21 20:34:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cardDefinition.isEquipment() && equippedCreature.isValid()) {
|
|
|
|
if (isCreature(game) || !equippedCreature.isCreature(game) || equippedCreature.hasProtectionFrom(game,this)) {
|
2011-09-03 23:49:47 -07:00
|
|
|
actions.add(new MagicAttachEquipmentAction(this,MagicPermanent.NONE));
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
}
|
2011-10-05 06:59:20 -07:00
|
|
|
|
|
|
|
// +1/+1 and -1/-1 counters cancel each other out.
|
|
|
|
final int plusCounters=getCounters(MagicCounterType.PlusOne);
|
|
|
|
if (plusCounters>0) {
|
|
|
|
final int minusCounters=getCounters(MagicCounterType.MinusOne);
|
|
|
|
if (minusCounters>0) {
|
|
|
|
final int amount=-Math.min(plusCounters,minusCounters);
|
|
|
|
actions.add(new MagicChangeCountersAction(this,MagicCounterType.PlusOne,amount,false));
|
|
|
|
actions.add(new MagicChangeCountersAction(this,MagicCounterType.MinusOne,amount,false));
|
|
|
|
}
|
|
|
|
}
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
private static boolean hasProtectionFrom(final long abilityFlags,final MagicSource source, final MagicGame game) {
|
2010-11-21 10:54:59 -08:00
|
|
|
|
|
|
|
// Check if there is a protection ability.
|
|
|
|
if ((abilityFlags&MagicAbility.PROTECTION_FLAGS)==0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// From monocolored.
|
2011-05-25 21:46:18 -07:00
|
|
|
if (//source.getColoredType() == MagicColoredType.MonoColored &&
|
2011-05-25 21:01:44 -07:00
|
|
|
//added to fix bug with Raging Raving creature not able to block
|
|
|
|
//creature with protection from monocolored
|
2011-09-18 07:46:22 -07:00
|
|
|
MagicColor.isMono(source.getColorFlags(game)) &&
|
2011-05-25 21:01:44 -07:00
|
|
|
MagicAbility.ProtectionFromMonoColored.hasAbility(abilityFlags)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
final int colorFlags=source.getColorFlags(game);
|
2010-11-21 10:54:59 -08:00
|
|
|
if (colorFlags>0) {
|
|
|
|
// From all colors.
|
|
|
|
if (MagicAbility.ProtectionFromAllColors.hasAbility(abilityFlags)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// From a color.
|
|
|
|
for (final MagicColor color : MagicColor.values()) {
|
|
|
|
|
|
|
|
if (color.hasColor(colorFlags)&&color.getProtectionAbility().hasAbility(abilityFlags)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (source.isPermanent()) {
|
|
|
|
final MagicPermanent sourcePermanent=(MagicPermanent)source;
|
2011-09-18 07:46:22 -07:00
|
|
|
if (sourcePermanent.isCreature(game)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
// From creatures.
|
|
|
|
if (MagicAbility.ProtectionFromCreatures.hasAbility(abilityFlags)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// From Demons.
|
2011-09-18 07:46:22 -07:00
|
|
|
if (sourcePermanent.hasSubType(MagicSubType.Demon,game) &&
|
|
|
|
MagicAbility.ProtectionFromDemons.hasAbility(abilityFlags)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// From Dragons.
|
2011-09-18 07:46:22 -07:00
|
|
|
if (sourcePermanent.hasSubType(MagicSubType.Dragon,game) &&
|
|
|
|
MagicAbility.ProtectionFromDragons.hasAbility(abilityFlags)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
return true;
|
|
|
|
}
|
2011-09-26 01:34:26 -07:00
|
|
|
// From Vampires.
|
|
|
|
if (sourcePermanent.hasSubType(MagicSubType.Vampire,game) &&
|
|
|
|
MagicAbility.ProtectionFromVampires.hasAbility(abilityFlags)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// From Werewolves.
|
|
|
|
if (sourcePermanent.hasSubType(MagicSubType.Werewolf,game) &&
|
|
|
|
MagicAbility.ProtectionFromWerewolves.hasAbility(abilityFlags)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// From Zombies.
|
|
|
|
if (sourcePermanent.hasSubType(MagicSubType.Zombie,game) &&
|
|
|
|
MagicAbility.ProtectionFromZombies.hasAbility(abilityFlags)) {
|
|
|
|
return true;
|
|
|
|
}
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasProtectionFrom(final MagicGame game,final MagicSource source) {
|
|
|
|
final long abilityFlags=getAllAbilityFlags(game);
|
2011-09-18 07:46:22 -07:00
|
|
|
return hasProtectionFrom(abilityFlags,source,game);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canAttack(final MagicGame game) {
|
2011-09-18 07:46:22 -07:00
|
|
|
if (!isCreature(game) ||
|
2011-06-18 22:56:02 -07:00
|
|
|
!canTap(game) ||
|
|
|
|
hasState(MagicPermanentState.ExcludeFromCombat)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
final long flags=getAllAbilityFlags(game);
|
2011-06-18 22:56:02 -07:00
|
|
|
return !MagicAbility.CannotAttackOrBlock.hasAbility(flags) && !MagicAbility.Defender.hasAbility(flags);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canBeBlocked(final MagicGame game,final MagicPlayer player) {
|
|
|
|
final long flags=getAllAbilityFlags(game);
|
|
|
|
|
|
|
|
// Unblockable
|
|
|
|
if (MagicAbility.Unblockable.hasAbility(flags)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Landwalk
|
|
|
|
for (final MagicColor color : MagicColor.values()) {
|
2011-09-18 07:46:22 -07:00
|
|
|
if (color.getLandwalkAbility().hasAbility(flags) &&
|
|
|
|
player.controlsPermanentWithSubType(color.getLandSubType(),game)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2011-10-20 07:29:22 -07:00
|
|
|
// Shadow
|
|
|
|
if (MagicAbility.Shadow.hasAbility(flags) &&
|
|
|
|
!player.controlsPermanentWithAbility(MagicAbility.Shadow,game)) {
|
|
|
|
return false;
|
|
|
|
}
|
2010-11-21 10:54:59 -08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canBlock(final MagicGame game) {
|
2011-09-18 07:46:22 -07:00
|
|
|
if (!isCreature(game)||isTapped()||hasState(MagicPermanentState.ExcludeFromCombat)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
final long flags=getAllAbilityFlags(game);
|
|
|
|
return !MagicAbility.CannotAttackOrBlock.hasAbility(flags)&&!MagicAbility.CannotBlock.hasAbility(flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean canBlock(final MagicGame game,final MagicPermanent attacker) {
|
|
|
|
final long attackerFlags=attacker.getAllAbilityFlags(game);
|
2011-01-01 15:13:05 -08:00
|
|
|
|
2011-10-20 02:07:21 -07:00
|
|
|
// Fear and Intimidate
|
2011-10-07 20:14:11 -07:00
|
|
|
if (!isArtifact(game)) {
|
2011-09-18 07:46:22 -07:00
|
|
|
final int colorFlags=getColorFlags(game);
|
2011-01-01 15:13:05 -08:00
|
|
|
if (MagicAbility.Fear.hasAbility(attackerFlags)&&!MagicColor.Black.hasColor(colorFlags)) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-09-18 07:46:22 -07:00
|
|
|
if (MagicAbility.Intimidate.hasAbility(attackerFlags)&&((colorFlags&attacker.getColorFlags(game))==0)) {
|
2011-01-01 15:13:05 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2010-11-21 10:54:59 -08:00
|
|
|
|
2011-10-20 02:07:21 -07:00
|
|
|
// Shadow
|
|
|
|
final long blockerFlags = getAllAbilityFlags(game);
|
|
|
|
if (MagicAbility.Shadow.hasAbility(attackerFlags) &&
|
|
|
|
!MagicAbility.Shadow.hasAbility(blockerFlags)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-06-07 03:26:31 -07:00
|
|
|
// Flying and Reach
|
2010-11-21 10:54:59 -08:00
|
|
|
final boolean blockerFlying=MagicAbility.Flying.hasAbility(blockerFlags);
|
|
|
|
if (blockerFlying) {
|
|
|
|
if (MagicAbility.CannotBeBlockedByFlying.hasAbility(attackerFlags)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (MagicAbility.CannotBeBlockedExceptWithFlying.hasAbility(attackerFlags)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (MagicAbility.Flying.hasAbility(attackerFlags)) {
|
|
|
|
if (!blockerFlying&&!MagicAbility.Reach.hasAbility(blockerFlags)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (MagicAbility.CannotBlockWithoutFlying.hasAbility(blockerFlags)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2011-06-07 03:26:31 -07:00
|
|
|
if (MagicAbility.CannotBeBlockedExceptWithFlyingOrReach.hasAbility(attackerFlags)) {
|
|
|
|
if (!MagicAbility.Flying.hasAbility(blockerFlags) && !MagicAbility.Reach.hasAbility(blockerFlags)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2011-10-20 02:07:21 -07:00
|
|
|
|
2011-10-09 04:42:52 -07:00
|
|
|
// Subtype
|
|
|
|
if (MagicAbility.CannotBeBlockedByHumans.hasAbility(attackerFlags)) {
|
|
|
|
if (this.hasSubType(MagicSubType.Human,game)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2010-11-21 10:54:59 -08:00
|
|
|
|
|
|
|
// Protection
|
2011-09-18 07:46:22 -07:00
|
|
|
return !hasProtectionFrom(attackerFlags,this,game);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public MagicPermanent getEquippedCreature() {
|
|
|
|
return equippedCreature;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setEquippedCreature(final MagicPermanent creature) {
|
|
|
|
equippedCreature=creature;
|
|
|
|
}
|
|
|
|
|
|
|
|
public MagicPermanentSet getEquipmentPermanents() {
|
|
|
|
return equipmentPermanents;
|
|
|
|
}
|
|
|
|
|
2011-09-20 19:11:46 -07:00
|
|
|
public void addEquipment(final MagicPermanent equipment) {
|
2010-11-21 10:54:59 -08:00
|
|
|
equipmentPermanents.add(equipment);
|
|
|
|
}
|
|
|
|
|
2011-09-20 19:11:46 -07:00
|
|
|
public void removeEquipment(final MagicPermanent equipment) {
|
2010-11-21 10:54:59 -08:00
|
|
|
equipmentPermanents.remove(equipment);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isEquipped() {
|
|
|
|
return equipmentPermanents.size()>0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public MagicPermanent getEnchantedCreature() {
|
|
|
|
return enchantedCreature;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setEnchantedCreature(final MagicPermanent creature) {
|
|
|
|
enchantedCreature=creature;
|
|
|
|
}
|
|
|
|
|
|
|
|
public MagicPermanentSet getAuraPermanents() {
|
|
|
|
return auraPermanents;
|
|
|
|
}
|
|
|
|
|
2011-09-20 19:11:46 -07:00
|
|
|
public void addAura(final MagicPermanent aura) {
|
2010-11-21 10:54:59 -08:00
|
|
|
auraPermanents.add(aura);
|
|
|
|
}
|
|
|
|
|
2011-09-20 19:11:46 -07:00
|
|
|
public void removeAura(final MagicPermanent aura) {
|
2010-11-21 10:54:59 -08:00
|
|
|
auraPermanents.remove(aura);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isEnchanted() {
|
|
|
|
return auraPermanents.size()>0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getAbilityPlayedThisTurn() {
|
|
|
|
return abilityPlayedThisTurn;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setAbilityPlayedThisTurn(final int amount) {
|
|
|
|
abilityPlayedThisTurn=amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void incrementAbilityPlayedThisTurn() {
|
|
|
|
abilityPlayedThisTurn++;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void decrementAbilityPlayedThisTurn() {
|
|
|
|
abilityPlayedThisTurn--;
|
|
|
|
}
|
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
private int getTypeFlags(final MagicGame game) {
|
2011-06-06 01:13:15 -07:00
|
|
|
// Check if cached.
|
|
|
|
if (cached) {
|
|
|
|
return cachedTypeFlags;
|
|
|
|
}
|
|
|
|
|
2011-09-18 19:52:55 -07:00
|
|
|
int flags = cardDefinition.getTypeFlags();
|
2011-09-18 07:46:22 -07:00
|
|
|
|
2011-09-18 17:40:54 -07:00
|
|
|
flags = MagicLayer.getTypeFlags(game,this,flags);
|
2011-09-18 07:46:22 -07:00
|
|
|
|
2011-06-02 23:36:01 -07:00
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
public boolean hasType(final MagicType type, final MagicGame game) {
|
|
|
|
return type.hasType(getTypeFlags(game));
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isLand() {
|
|
|
|
return cardDefinition.isLand();
|
|
|
|
}
|
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
public boolean isCreature(final MagicGame game) {
|
|
|
|
return MagicType.Creature.hasType(getTypeFlags(game));
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
2011-09-18 19:52:55 -07:00
|
|
|
public boolean isEquipment() {
|
|
|
|
return cardDefinition.isEquipment();
|
|
|
|
}
|
|
|
|
|
2011-10-07 20:14:11 -07:00
|
|
|
public boolean isArtifact(final MagicGame game) {
|
|
|
|
return MagicType.Artifact.hasType(getTypeFlags(game));
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isEnchantment() {
|
|
|
|
return cardDefinition.isEnchantment();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isSpell() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isPlayer() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isPermanent() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isValidTarget(final MagicGame game,final MagicSource source) {
|
|
|
|
final long flags=getAllAbilityFlags(game);
|
|
|
|
// Can't be the target of spells or abilities.
|
|
|
|
if (MagicAbility.Shroud.hasAbility(flags)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Can't be the target of spells or abilities your opponents controls.
|
|
|
|
if (MagicAbility.CannotBeTheTarget.hasAbility(flags)&&source.getController()!=controller) {
|
|
|
|
return false;
|
|
|
|
}
|
2011-05-29 21:47:31 -07:00
|
|
|
|
|
|
|
// Can't be the target of spells or abilities player 0 controls.
|
|
|
|
if (MagicAbility.CannotBeTheTarget0.hasAbility(flags) && source.getController().getIndex() == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Can't be the target of spells or abilities player 1 controls.
|
|
|
|
if (MagicAbility.CannotBeTheTarget1.hasAbility(flags) && source.getController().getIndex() == 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-21 10:54:59 -08:00
|
|
|
// Protection.
|
2011-09-18 07:46:22 -07:00
|
|
|
return !hasProtectionFrom(flags,source,game);
|
2010-11-21 10:54:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int compareTo(final MagicPermanent permanent) {
|
|
|
|
// Important for sorting of permanent mana activations.
|
|
|
|
final int dif=cardDefinition.getIndex()-permanent.cardDefinition.getIndex();
|
|
|
|
if (dif!=0) {
|
|
|
|
return dif;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id<permanent.id) {
|
|
|
|
return -1;
|
|
|
|
} else if (id>permanent.id) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean endOfTurn(final MagicGame game) {
|
|
|
|
if (MagicPermanentState.RemoveAtEndOfTurn.hasState(stateFlags)) {
|
|
|
|
game.logAppendMessage(controller,"Exile "+this.getName()+" (end of turn).");
|
2010-12-05 10:39:58 -08:00
|
|
|
game.doAction(new MagicRemoveFromPlayAction(this,MagicLocationType.Exile));
|
2010-11-21 10:54:59 -08:00
|
|
|
return true;
|
|
|
|
} else if (MagicPermanentState.RemoveAtEndOfYourTurn.hasState(stateFlags)&&controller==game.getTurnPlayer()) {
|
|
|
|
game.logAppendMessage(controller,"Exile "+this.getName()+" (end of turn).");
|
2010-12-05 10:39:58 -08:00
|
|
|
game.doAction(new MagicRemoveFromPlayAction(this,MagicLocationType.Exile));
|
2010-11-21 10:54:59 -08:00
|
|
|
return true;
|
|
|
|
} else if (MagicPermanentState.SacrificeAtEndOfTurn.hasState(stateFlags)) {
|
|
|
|
game.logAppendMessage(controller,"Sacrifice "+this.getName()+" (end of turn).");
|
|
|
|
game.doAction(new MagicSacrificeAction(this));
|
|
|
|
return true;
|
2011-06-07 04:20:28 -07:00
|
|
|
} else if (MagicPermanentState.ReturnToOwnerAtEndOfTurn.hasState(stateFlags)) {
|
|
|
|
game.logAppendMessage(controller,"Return "+this.getName()+" to its owner (end of turn).");
|
2011-10-05 23:08:03 -07:00
|
|
|
game.doAction(new MagicChangeStateAction(this,MagicPermanentState.ReturnToOwnerAtEndOfTurn,false));
|
2011-06-07 21:10:28 -07:00
|
|
|
game.doAction(new MagicGainControlAction(card.getOwner(),this));
|
2011-06-07 04:20:28 -07:00
|
|
|
return true;
|
|
|
|
}
|
2010-11-21 10:54:59 -08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-09-18 07:46:22 -07:00
|
|
|
public ImageIcon getIcon(final MagicGame game) {
|
2010-11-21 10:54:59 -08:00
|
|
|
if (isAttacking()) {
|
|
|
|
return IconImages.ATTACK;
|
|
|
|
}
|
|
|
|
if (isBlocking()) {
|
|
|
|
return IconImages.BLOCK;
|
|
|
|
}
|
2011-09-18 07:46:22 -07:00
|
|
|
if (isCreature(game)) {
|
2010-11-21 10:54:59 -08:00
|
|
|
return IconImages.CREATURE;
|
|
|
|
}
|
|
|
|
return cardDefinition.getIcon();
|
|
|
|
}
|
2011-05-25 21:01:44 -07:00
|
|
|
}
|