package magic.model.mstatic;
import java.util.Set;
import magic.model.MagicAbility;
import magic.model.MagicAbilityList;
import magic.model.MagicAmount;
import magic.model.MagicCardDefinition;
import magic.model.MagicChangeCardDefinition;
import magic.model.MagicColor;
import magic.model.MagicCounterType;
import magic.model.MagicGame;
import magic.model.MagicPermanent;
import magic.model.MagicCard;
import magic.model.MagicManaCost;
import magic.model.MagicPlayer;
import magic.model.MagicPowerToughness;
import magic.model.MagicSubType;
import magic.model.MagicType;
import magic.model.action.PutStateTriggerOnStackAction;
import magic.model.action.RemoveStaticAction;
import magic.model.condition.MagicCondition;
import magic.model.event.MagicEvent;
import magic.model.event.MagicSourceEvent;
import magic.model.target.MagicPermanentTargetFilter;
import magic.model.target.MagicTargetFilter;
import magic.model.target.MagicTargetFilterFactory;
public abstract class MagicStatic extends MagicDummyModifier implements MagicChangeCardDefinition {
public static final boolean UntilEOT = true;
public static final boolean Forever = !UntilEOT;
//permanents affected by the static effect
private MagicTargetFilter<MagicPermanent> filter;
//layer where this effect operate
private final MagicLayer layer;
private final boolean isUntilEOT;
protected MagicStatic(final MagicLayer aLayer, final MagicTargetFilter<MagicPermanent> aFilter, final boolean aIsUntilEOT) {
filter = aFilter;
layer = aLayer;
isUntilEOT = aIsUntilEOT;
}
protected MagicStatic(final MagicLayer aLayer, final MagicTargetFilter<MagicPermanent> aFilter) {
this(aLayer, aFilter, Forever);
}
protected MagicStatic(final MagicLayer aLayer, final boolean aIsUntilEOT) {
this(aLayer, MagicTargetFilterFactory.NONE, aIsUntilEOT);
}
protected MagicStatic(final MagicLayer aLayer) {
this(aLayer, MagicTargetFilterFactory.NONE, Forever);
}
@Override
public void change(final MagicCardDefinition cdef) {
cdef.addStatic(this);
}
public final MagicLayer getLayer() {
return layer;
}
public final boolean isUntilEOT() {
return isUntilEOT;
}
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
if (filter == MagicTargetFilterFactory.NONE) {
return source == target && condition(game, source, target);
} else {
return filter.accept(source, source.getController(), target) && condition(game, source, target);
}
}
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return true;
}
public static boolean acceptLinked(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
if (source.isEquipment()) {
return source.getEquippedCreature() == target;
} else if (source.isEnchantment()) {
return source.getEnchantedPermanent() == target;
} else {
return source.getPairedCreature() == target ||
(source == target && source.isPaired());
}
}
public static MagicStatic genPTStatic(final MagicTargetFilter<MagicPermanent> affected, final MagicAmount count, final MagicPowerToughness given) {
return new MagicStatic(MagicLayer.ModPT, affected) {
@Override
public void modPowerToughness(final MagicPermanent source, final MagicPermanent permanent, final MagicPowerToughness pt) {
final int amt = count.getAmount(source, source.getController());
pt.add(given.power() * amt, given.toughness() * amt);
}
};
}
public static MagicStatic genPTStatic(final MagicTargetFilter<MagicPermanent> affected, final int givenPower, final int givenToughness) {
return new MagicStatic(MagicLayer.ModPT, affected) {
@Override
public void modPowerToughness(final MagicPermanent source, final MagicPermanent permanent, final MagicPowerToughness pt) {
pt.add(givenPower, givenToughness);
}
};
}
public static MagicStatic genPTStatic(final MagicCondition condition, final int givenPower, final int givenToughness) {
return new MagicStatic(MagicLayer.ModPT) {
@Override
public void modPowerToughness(final MagicPermanent source, final MagicPermanent permanent, final MagicPowerToughness pt) {
pt.add(givenPower, givenToughness);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return condition.accept(source);
}
};
}
public static MagicStatic genPTStatic(final MagicCondition condition, final MagicTargetFilter<MagicPermanent> filter, final int givenPower, final int givenToughness) {
return new MagicStatic(MagicLayer.ModPT, filter) {
@Override
public void modPowerToughness(final MagicPermanent source, final MagicPermanent permanent, final MagicPowerToughness pt) {
pt.add(givenPower, givenToughness);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return condition.accept(source);
}
};
}
public static MagicStatic genPTStatic(final int givenPower, final int givenToughness) {
return new MagicStatic(MagicLayer.ModPT) {
@Override
public void modPowerToughness(final MagicPermanent source, final MagicPermanent permanent, final MagicPowerToughness pt) {
pt.add(givenPower, givenToughness);
}
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicStatic.acceptLinked(game, source, target);
}
};
}
public static MagicStatic genPTSetStatic(final int givenPower, final int givenToughness) {
return new MagicStatic(MagicLayer.SetPT) {
@Override
public void modPowerToughness(final MagicPermanent source, final MagicPermanent permanent, final MagicPowerToughness pt) {
pt.set(givenPower, givenToughness);
}
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicStatic.acceptLinked(game, source, target);
}
};
}
public static MagicStatic genABStatic(final MagicTargetFilter<MagicPermanent> filter, final MagicAbilityList abilityList) {
return new MagicStatic(MagicLayer.Ability, filter) {
@Override
public void modAbilityFlags(final MagicPermanent source, final MagicPermanent permanent, final Set<MagicAbility> flags) {
abilityList.giveAbility(permanent, flags);
}
};
}
public static MagicStatic genABStatic(final MagicCondition condition, final MagicTargetFilter<MagicPermanent> filter, final MagicAbilityList abilityList) {
return new MagicStatic(MagicLayer.AbilityCond, filter) {
@Override
public void modAbilityFlags(final MagicPermanent source, final MagicPermanent permanent, final Set<MagicAbility> flags) {
abilityList.giveAbility(permanent, flags);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return condition.accept(source);
}
};
}
public static MagicStatic genABStatic(final MagicCondition condition, final MagicAbilityList abilityList) {
return new MagicStatic(MagicLayer.AbilityCond) {
@Override
public void modAbilityFlags(final MagicPermanent source, final MagicPermanent permanent, final Set<MagicAbility> flags) {
abilityList.giveAbility(permanent, flags);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return condition.accept(source);
}
};
}
public static MagicStatic linkedABStatic(final MagicCondition condition, final MagicAbilityList abilityList) {
return new MagicStatic(MagicLayer.Ability) {
@Override
public void modAbilityFlags(final MagicPermanent source, final MagicPermanent permanent, final Set<MagicAbility> flags) {
abilityList.giveAbility(permanent, flags);
}
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicStatic.acceptLinked(game, source, target) && condition.accept(source);
}
};
}
public static MagicStatic linkedABStatic(final MagicAbilityList abilityList) {
return new MagicStatic(MagicLayer.Ability) {
@Override
public void modAbilityFlags(final MagicPermanent source, final MagicPermanent permanent, final Set<MagicAbility> flags) {
abilityList.giveAbility(permanent, flags);
}
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicStatic.acceptLinked(game, source, target);
}
};
}
public static MagicStatic genABGameStatic(final MagicTargetFilter<MagicPermanent> filter, final MagicAbilityList abilityList) {
return new MagicStatic(MagicLayer.Ability, filter) {
@Override
public void modAbilityFlags(final MagicPermanent source, final MagicPermanent permanent, final Set<MagicAbility> flags) {
abilityList.giveAbility(permanent, flags);
}
};
}
public static MagicStatic genTypeStatic(final int givenTypeFlags) {
return new MagicStatic(MagicLayer.Type) {
@Override
public int getTypeFlags(final MagicPermanent permanent,final int flags) {
return flags | givenTypeFlags;
}
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicStatic.acceptLinked(game, source, target);
}
};
}
public static MagicStatic genSTStatic(final Set<MagicSubType> givenSubTypeFlags) {
return new MagicStatic(MagicLayer.Type) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent, final Set<MagicSubType> flags) {
flags.addAll(givenSubTypeFlags);
}
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicStatic.acceptLinked(game, source, target);
}
};
}
public static MagicStatic AddLinkedColor(final int givenColorFlags) {
return new MagicStatic(MagicLayer.Color) {
@Override
public int getColorFlags(final MagicPermanent permanent, final int flags) {
return flags | givenColorFlags;
}
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicStatic.acceptLinked(game, source, target);
}
};
}
public static MagicStatic SetLinkedColor(final int givenColorFlags) {
return new MagicStatic(MagicLayer.Color) {
@Override
public int getColorFlags(final MagicPermanent permanent, final int flags) {
return givenColorFlags;
}
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return MagicStatic.acceptLinked(game, source, target);
}
};
}
public static MagicStatic ControlEnchanted = new MagicStatic(MagicLayer.Control) {
@Override
public MagicPlayer getController(final MagicPermanent source, final MagicPermanent target, final MagicPlayer player) {
return source.getController();
}
@Override
public boolean accept(final MagicGame game, final MagicPermanent source, final MagicPermanent target) {
return source.getEnchantedPermanent() == target;
}
};
public static MagicStatic ControlAsLongAsSourceIsOnBattlefield(final MagicPlayer you, final MagicPermanent target) {
final MagicTargetFilter<MagicPermanent> filter = new MagicPermanentTargetFilter(target);
return new MagicStatic(MagicLayer.Control,filter) {
@Override
public MagicPlayer getController(final MagicPermanent source, final MagicPermanent permanent, final MagicPlayer player) {
return source.getController();
}
};
}
public static MagicStatic ControlAsLongAsYouControlSource(final MagicPlayer you, final MagicPermanent target) {
final MagicTargetFilter<MagicPermanent> filter = new MagicPermanentTargetFilter(target);
return new MagicStatic(MagicLayer.Control,filter) {
@Override
public MagicPlayer getController(final MagicPermanent source, final MagicPermanent permanent, final MagicPlayer player) {
return source.getController();
}
@Override
public boolean condition(final MagicGame game, final MagicPermanent source, final MagicPermanent target) {
if (you.getIndex() != source.getController().getIndex()) {
//remove this static after the update
game.addDelayedAction(new RemoveStaticAction(source, this));
return false;
} else {
return true;
}
}
};
}
public static MagicStatic ControlAsLongAsYouControlSourceAndSourceIsTapped(final MagicPlayer you, final MagicPermanent target) {
final MagicTargetFilter<MagicPermanent> filter = new MagicPermanentTargetFilter(target);
return new MagicStatic(MagicLayer.Control,filter) {
@Override
public MagicPlayer getController(final MagicPermanent source, final MagicPermanent permanent, final MagicPlayer player) {
return source.getController();
}
@Override
public boolean condition(final MagicGame game, final MagicPermanent source, final MagicPermanent target) {
if (you.getIndex() != source.getController().getIndex() || source.isUntapped()) {
//remove this static after the update
game.addDelayedAction(new RemoveStaticAction(source, this));
return false;
} else {
return true;
}
}
};
}
public static MagicStatic ControlAsLongAsSourceIsTapped(final MagicPlayer you, final MagicPermanent target) {
final MagicTargetFilter<MagicPermanent> filter = new MagicPermanentTargetFilter(target);
return new MagicStatic(MagicLayer.Control,filter) {
@Override
public MagicPlayer getController(final MagicPermanent source, final MagicPermanent permanent, final MagicPlayer player) {
return source.getController();
}
@Override
public boolean condition(final MagicGame game, final MagicPermanent source, final MagicPermanent target) {
if (source.isUntapped()) {
//remove this static after the update
game.addDelayedAction(new RemoveStaticAction(source, this));
return false;
} else {
return true;
}
}
};
}
public static MagicStatic Unleash = new MagicStatic(MagicLayer.Ability) {
@Override
public void modAbilityFlags(final MagicPermanent source, final MagicPermanent permanent, final Set<MagicAbility> flags) {
flags.add(MagicAbility.CannotBlock);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return source.hasCounters(MagicCounterType.PlusOne);
}
};
public static MagicStatic SwitchPT = new MagicStatic(MagicLayer.SwitchPT, MagicStatic.UntilEOT) {
@Override
public void modPowerToughness(final MagicPermanent source, final MagicPermanent permanent, final MagicPowerToughness pt) {
pt.set(pt.toughness(),pt.power());
}
};
public static MagicStatic Zombie = new MagicStatic(MagicLayer.Type) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent,final Set<MagicSubType> flags) {
flags.add(MagicSubType.Zombie);
}
};
public static MagicStatic Vampire = new MagicStatic(MagicLayer.Type) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent,final Set<MagicSubType> flags) {
flags.add(MagicSubType.Vampire);
}
};
public static MagicStatic Spirit = new MagicStatic(MagicLayer.Type) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent, final Set<MagicSubType> flags) {
flags.add(MagicSubType.Spirit);
}
};
public static MagicStatic IsBlack = new MagicStatic(MagicLayer.Color) {
@Override
public int getColorFlags(final MagicPermanent permanent,final int flags) {
return MagicColor.Black.getMask();
}
};
public static MagicStatic IsWhite = new MagicStatic(MagicLayer.Color) {
@Override
public int getColorFlags(final MagicPermanent permanent, final int flags) {
return MagicColor.White.getMask();
}
};
public static MagicStatic AddBlack = new MagicStatic(MagicLayer.Color) {
@Override
public int getColorFlags(final MagicPermanent permanent,final int flags) {
return flags | MagicColor.Black.getMask();
}
};
public static MagicStatic Artifact = new MagicStatic(MagicLayer.Type) {
@Override
public int getTypeFlags(final MagicPermanent permanent,final int flags) {
return flags | MagicType.Artifact.getMask();
}
};
public static MagicStatic AllCreatureTypesUntilEOT = new MagicStatic(MagicLayer.Type, UntilEOT) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent, final Set<MagicSubType> flags) {
flags.addAll(MagicSubType.ALL_CREATURES);
}
};
public static MagicStatic Bestowed = new MagicStatic(MagicLayer.Type) {
@Override
public int getTypeFlags(final MagicPermanent permanent,final int flags) {
return flags & ~MagicType.Creature.getMask();
}
@Override
public void modSubTypeFlags(final MagicPermanent permanent,final Set<MagicSubType> flags) {
flags.removeAll(MagicSubType.ALL_CREATURES);
flags.add(MagicSubType.Aura);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return source.getEnchantedPermanent().isValid();
}
};
public static MagicStatic Nightmare = new MagicStatic(MagicLayer.Type) {
@Override
public void modSubTypeFlags(final MagicPermanent permanent,final Set<MagicSubType> flags) {
flags.add(MagicSubType.Nightmare);
}
};
public static MagicStatic AsLongAsCond(final MagicPermanent chosen, final int P, final int T, final MagicCondition cond) {
final long id = chosen.getId();
return new MagicStatic(MagicLayer.ModPT) {
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return target.getId() == id && condition(game, source, target);
}
@Override
public void modPowerToughness(final MagicPermanent source, final MagicPermanent permanent, final MagicPowerToughness pt) {
pt.add(P,T);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
if (cond.accept(source)) {
return true;
} else {
//remove this static after the update
game.addDelayedAction(new RemoveStaticAction(source, this));
return false;
}
}
};
}
public static MagicStatic AsLongAsCond(final MagicPermanent chosen, final MagicAbility ability, final MagicCondition cond) {
final long id = chosen.getId();
return new MagicStatic(MagicLayer.Ability) {
@Override
public boolean accept(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return target.getId() == id && condition(game, source, target);
}
@Override
public void modAbilityFlags(final MagicPermanent source,final MagicPermanent permanent,final Set<MagicAbility> flags) {
permanent.addAbility(ability, flags);
}
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
if (cond.accept(source)) {
return true;
} else {
//remove this static after the update
game.addDelayedAction(new RemoveStaticAction(source, this));
return false;
}
}
};
}
public static MagicStatic StateTrigger(final MagicCondition cond, final MagicSourceEvent effect) {
return new MagicStatic(MagicLayer.Game) {
@Override
public boolean condition(final MagicGame game,final MagicPermanent source,final MagicPermanent target) {
return cond.accept(source);
}
@Override
public void modGame(final MagicPermanent source, final MagicGame game) {
final MagicEvent event = effect.getTriggerEvent(source);
if (event.isValid()) {
game.doAction(new PutStateTriggerOnStackAction(event));
}
}
};
}
public static MagicStatic YourCostReduction(final MagicTargetFilter<MagicCard> filter, int n) {
return new MagicStatic(MagicLayer.CostReduction) {
@Override
public MagicManaCost reduceCost(final MagicPermanent source, final MagicCard card, final MagicManaCost cost) {
if (filter.accept(source, source.getController(), card) && source.isFriend(card)) {
return cost.reduce(n);
} else {
return cost;
}
}
};
}
}