package forge.card.spellability;
import forge.*;
import forge.card.abilityFactory.AbilityFactory;
import forge.card.cardFactory.CardFactory;
import forge.card.cardFactory.CardFactoryUtil;
import forge.card.trigger.Trigger;
import forge.gui.input.Input;
import java.util.ArrayList;
import java.util.HashMap;
/**
* <p>Spell_Permanent class.</p>
*
* @author Forge
* @version $Id: $
*/
public class Spell_Permanent extends Spell {
/** Constant <code>serialVersionUID=2413495058630644447L</code> */
private static final long serialVersionUID = 2413495058630644447L;
private boolean willChampion = false;
private String championValid = null;
private String championValidDesc = "";
final Input championInputComes = new Input() {
private static final long serialVersionUID = -7503268232821397107L;
@Override
public void showMessage() {
CardList choice = (CardList) championGetCreature.execute();
stopSetNext(CardFactoryUtil.input_targetChampionSac(getSourceCard(), championAbilityComes, choice,
"Select another " + championValidDesc + " you control to exile", false, false));
ButtonUtil.disableAll(); //target this card means: sacrifice this card
}
};
private final CommandReturn championGetCreature = new CommandReturn() {
public Object execute() {
CardList cards = AllZoneUtil.getPlayerCardsInPlay(getSourceCard().getController());
return cards.getValidCards(championValid, getSourceCard().getController(), getSourceCard());
}
};//CommandReturn
final SpellAbility championAbilityComes = new Ability(getSourceCard(), "0") {
@Override
public void resolve() {
Card source = getSourceCard();
Player controller = source.getController();
CardList creature = (CardList) championGetCreature.execute();
if (creature.size() == 0) {
AllZone.getGameAction().sacrifice(source);
return;
} else if (controller.isHuman()) {
AllZone.getInputControl().setInput(championInputComes);
} else { //Computer
CardList computer = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
computer = computer.getValidCards(championValid, controller, source);
computer.remove(source);
computer.shuffle();
if (computer.size() != 0) {
Card c = computer.get(0);
source.setChampionedCard(c);
if (AllZoneUtil.isCardInPlay(c)) {
AllZone.getGameAction().exile(c);
}
//Run triggers
HashMap<String, Object> runParams = new HashMap<String, Object>();
runParams.put("Card", source);
runParams.put("Championed", source.getChampionedCard());
AllZone.getTriggerHandler().runTrigger("Championed", runParams);
} else
AllZone.getGameAction().sacrifice(getSourceCard());
}//computer
}//resolve()
};
Command championCommandComes = new Command() {
private static final long serialVersionUID = -3580408066322945328L;
public void execute() {
StringBuilder sb = new StringBuilder();
sb.append(getSourceCard()).append(" - When CARDNAME enters the battlefield, sacrifice it unless you exile another Faerie you control.");
championAbilityComes.setStackDescription(sb.toString());
AllZone.getStack().addSimultaneousStackEntry(championAbilityComes);
}//execute()
};//championCommandComes
Command championCommandLeavesPlay = new Command() {
private static final long serialVersionUID = -5903638227914705191L;
public void execute() {
SpellAbility ability = new Ability(getSourceCard(), "0") {
@Override
public void resolve() {
Card c = getSourceCard().getChampionedCard();
if (c != null && !c.isToken() && AllZoneUtil.isCardExiled(c)) {
AllZone.getGameAction().moveToPlay(c);
}
}//resolve()
};//SpellAbility
StringBuilder sb = new StringBuilder();
sb.append(getSourceCard()).append(" - When CARDNAME leaves the battlefield, exiled card returns to the battlefield.");
ability.setStackDescription(sb.toString());
AllZone.getStack().addSimultaneousStackEntry(ability);
}//execute()
};//championCommandLeavesPlay
///////
////////////////////
/**
* <p>Constructor for Spell_Permanent.</p>
*
* @param sourceCard a {@link forge.Card} object.
*/
public Spell_Permanent(Card sourceCard) {
// Add Costs for all SpellPermanents
this(sourceCard, new Cost(sourceCard.getManaCost(), sourceCard.getName(), false), null);
}//Spell_Permanent()
/**
* <p>Constructor for Spell_Permanent.</p>
*
* @param sourceCard a {@link forge.Card} object.
* @param cost a {@link forge.card.spellability.Cost} object.
* @param tgt a {@link forge.card.spellability.Target} object.
*/
public Spell_Permanent(Card sourceCard, Cost cost, Target tgt) {
this(sourceCard, cost, tgt, true);
}//Spell_Permanent()
public Spell_Permanent(Card sourceCard, Cost cost, Target tgt, boolean setDesc) {
super(sourceCard, cost, tgt);
if (CardFactory.hasKeyword(sourceCard, "Champion") != -1) {
int n = CardFactory.hasKeyword(sourceCard, "Champion");
String toParse = sourceCard.getKeyword().get(n).toString();
String parsed[] = toParse.split(":");
willChampion = true;
championValid = parsed[1];
if (parsed.length > 2) {
championValidDesc = parsed[2];
} else championValidDesc = championValid;
}
if (sourceCard.isCreature()) {
StringBuilder sb = new StringBuilder();
sb.append(sourceCard.getName()).append(" - Creature ").append(sourceCard.getNetAttack());
sb.append(" / ").append(sourceCard.getNetDefense());
setStackDescription(sb.toString());
} else setStackDescription(sourceCard.getName());
if (setDesc)
setDescription(getStackDescription());
if (willChampion) {
sourceCard.addComesIntoPlayCommand(championCommandComes);
sourceCard.addLeavesPlayCommand(championCommandLeavesPlay);
}
}//Spell_Permanent()
/** {@inheritDoc} */
@Override
public boolean canPlay() {
Card source = getSourceCard();
if (AllZone.getStack().isSplitSecondOnStack() || source.isUnCastable()) return false;
Player turn = AllZone.getPhase().getPlayerTurn();
if (source.getName().equals("Serra Avenger")) {
if (turn.equals(source.getController()) && turn.getTurn() <= 3)
return false;
} else if (source.getName().equals("Blizzard")) {
CardList lands = AllZoneUtil.getPlayerLandsInPlay(source.getController());
lands = lands.getType("Snow");
if (lands.size() == 0) return false;
}
// Flash handled by super.canPlay
return super.canPlay();
}
/** {@inheritDoc} */
@Override
public boolean canPlayAI() {
Card card = getSourceCard();
//check on legendary
if (card.isType("Legendary")) {
CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
if (list.containsName(card.getName()))
return false;
}
if (card.isPlaneswalker()) {
CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
list = list.getType("Planeswalker");
for (int i = 0; i < list.size(); i++) {
String subtype = card.getType().get(card.getType().size() - 1);
CardList cl = list.getType(subtype);
if (cl.size() > 0) {
return false;
}
}
}
if (card.isType("World")) {
CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
list = list.getType("World");
if (list.size() > 0) return false;
}
if (card.isCreature()
&& card.getNetDefense() <= 0
&& !card.hasStartOfKeyword("etbCounter")
&& !card.getText().contains("Modular"))
return false;
if (willChampion) {
Object o = championGetCreature.execute();
if (o == null) return false;
CardList cl = (CardList) championGetCreature.execute();
if ((o == null) || !(cl.size() > 0) || !AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand))
return false;
}
if (!checkETBEffects(card, this, null))
return false;
return super.canPlayAI();
}//canPlayAI()
/**
* <p>checkETBEffects.</p>
*
* @param card a {@link forge.Card} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @param api a {@link java.lang.String} object.
* @return a boolean.
*/
public static boolean checkETBEffects(Card card, SpellAbility sa, String api) {
// Trigger play improvements
ArrayList<Trigger> triggers = card.getTriggers();
for (Trigger tr : triggers) {
// These triggers all care for ETB effects
HashMap<String, String> params = tr.getMapParams();
if (!params.get("Mode").equals("ChangesZone"))
continue;
if (!params.get("Destination").equals("Battlefield"))
continue;
if (params.containsKey("ValidCard") && !params.get("ValidCard").contains("Self"))
continue;
if (!tr.requirementsCheck())
continue;
if (tr.getOverridingAbility() != null) // Don't look at Overriding Abilities yet
continue;
// Maybe better considerations
AbilityFactory af = new AbilityFactory();
SpellAbility exSA = af.getAbility(card.getSVar(params.get("Execute")), card);
if (api != null && !af.getAPI().equals(api))
continue;
exSA.setActivatingPlayer(sa.getActivatingPlayer());
// Run non-mandatory trigger.
// These checks only work if the Executing SpellAbility is an Ability_Sub.
if (exSA instanceof Ability_Sub && !exSA.doTrigger(false)) {
// AI would not run this trigger if given the chance
// if trigger is mandatory, return false
if (params.get("OptionalDecider") == null) {
return false;
}
// else
// otherwise, return false 50% of the time?
}
}
return true;
}
/** {@inheritDoc} */
@Override
public void resolve() {
Card c = getSourceCard();
AllZone.getGameAction().moveToPlay(c);
}
}