Files
forge/src/forge/CardFactory.java

11150 lines
484 KiB
Java

package forge;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.swing.JOptionPane;
import forge.error.ErrorViewer;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
import com.esotericsoftware.minlog.Log;
public class CardFactory implements NewConstants {
// String cardname is the key, Card is the value
private Map<String, Card> map = new HashMap<String, Card>();
private CardList allCards = new CardList();
private HashSet<String> removedCardList;
private Card blankCard = new Card(); //new code
// The Following "Cards" are used by the Whenever Keyword
public Card HumanNullCard = new Card();
public Card ComputerNullCard = new Card();
public CardFactory(String filename) {
this(new File(filename));
}
public CardList CopiedList = new CardList();
public CardFactory(File file) {
SpellAbility spell = new SpellAbility(SpellAbility.Spell, blankCard) {
//neither computer nor human play can play this card
@Override
public boolean canPlay() {
return false;
}
@Override
public void resolve() {}
};
blankCard.addSpellAbility(spell);
spell.setManaCost("1");
blankCard.setName("Removed Card");
//owner and controller will be wrong sometimes
//but I don't think it will matter
//theoretically blankCard will go to the wrong graveyard
blankCard.setOwner(Constant.Player.Human);
blankCard.setController(Constant.Player.Human);
HumanNullCard.setOwner(Constant.Player.Human);
HumanNullCard.setController(Constant.Player.Human);
ComputerNullCard.setOwner(Constant.Player.Computer);
ComputerNullCard.setController(Constant.Player.Computer);
removedCardList = new HashSet<String>(FileUtil.readFile(ForgeProps.getFile(REMOVED)));
try {
readCards(file);
// initialize CardList allCards
Iterator<String> it = map.keySet().iterator();
Card c;
while(it.hasNext()) {
c = getCard(it.next().toString(), Constant.Player.Human);
allCards.add(c);
//System.out.println("cardName: " + c.getName());
}
} catch(Exception ex) {
ErrorViewer.showError(ex);
}
}// constructor
public CardList getAllCards() {
return new CardList(allCards.toArray());
}// getAllCards()
private void readCards(File file) {
map.clear();
//ReadCard read = new ReadCard(ForgeProps.getFile(CARDS));
ReadCard read = new ReadCard(ForgeProps.getFile(CARDSFOLDER));
try {
read.run();
// javax.swing.SwingUtilities.invokeAndWait(read);
} catch(Exception ex) {
ErrorViewer.showError(ex);
throw new RuntimeException("CardFactory : readCards() thread error - " + ex.getMessage());
}
ArrayList<Card> simpleList = read.getCards();
Card s;
Iterator<Card> it = simpleList.iterator();
while(it.hasNext()) {
s = it.next();
map.put(s.getName(), s);
//System.out.println("cardName: " + s.getName());
}
}// readCard()
final public Card dynamicCopyCard(Card in)
{
if(in.getType().contains("Creature")) {
Card card2 = new Card();
card2 = CardFactory_Creatures.getCard(in, in.getName(), in.getOwner(), this);
return card2;
} else if(in.getType().contains("Aura")) {
Card card2 = new Card();
card2 = CardFactory_Auras.getCard(in, in.getName(), in.getOwner());
return card2;
} else if(in.getType().contains("Equipment")) {
Card card2 = new Card();
card2 = CardFactory_Equipment.getCard(in, in.getName(), in.getOwner());
return card2;
} else if(in.getType().contains("Planeswalker")) {
Card card2 = new Card();
card2 = CardFactory_Planeswalkers.getCard(in, in.getName(), in.getOwner());
return card2;
} else if(in.getType().contains("Land")) {
Card card2 = new Card();
card2 = CardFactory_Lands.getCard(in, in.getName(), in.getOwner());
return card2;
}
else
{
Card out = getCard(in.getName(), in.getOwner());
out.setUniqueNumber(in.getUniqueNumber());
return out;
}
}
final public Card copyCard(Card in) {
Card out = getCard(in.getName(), in.getOwner());
out.setUniqueNumber(in.getUniqueNumber());
return out;
}
final public Card copyCardintoNew(Card in) {
Card out = getCard(in.getName(), in.getOwner());
PlayerZone Hplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
PlayerZone Cplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
CardList all = AllZone.CardFactory.getAllCards();
CardList tokens = new CardList(Hplay.getCards());
tokens.add(new CardList(Cplay.getCards()));
tokens = tokens.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isToken();
}
});
all.add(tokens);
all.add(CopiedList);
int Unumber = 0;
for(int i = 0; i < all.size(); i++) {
if(all.get(i).getUniqueNumber() > Unumber) Unumber = all.get(i).getUniqueNumber();
}
out.setUniqueNumber(Unumber + 4); // +4 because +1 didn't work lol.
out.setCopiedSpell(true);
CopiedList.add(out);
return out;
}
final void copySpellontoStack(Card Source, Card in, boolean CopyDetails) {
Card c = AllZone.CardFactory.copyCardintoNew(in);
SpellAbility[] sa = c.getSpellAbility();
c.setController(Source.getController());
if(CopyDetails == true) {
c.addXManaCostPaid(in.getXManaCostPaid());
c.addMultiKickerMagnitude(in.getMultiKickerMagnitude());
if(in.isKicked()) c.setKicked(true);
if(c.hasChoices()) {
for(int i = 0; i < in.getChoices().size(); i++) {
c.addSpellChoice(in.getChoice(i));
}
for(int i = 0; i < in.getChoiceTargets().size(); i++) {
c.setSpellChoiceTarget(in.getChoiceTarget(i));
}
}
}
for(int i = 0; i < sa.length; i++) {
if(in.getAbilityUsed() == i) {
if(c.isKicked() && !sa[i].isKickerAbility()) {
} else {
if(in.getSpellAbility()[i].getTargetCard() != null)
sa[i].setTargetCard(in.getSpellAbility()[i].getTargetCard());
if(in.getSpellAbility()[i].getTargetPlayer() != null) {
if(in.getSpellAbility()[i].getTargetPlayer().equals(Constant.Player.Human)
|| (in.getSpellAbility()[i].getTargetPlayer().equals(Constant.Player.Computer)))
sa[i].setTargetPlayer(in.getSpellAbility()[i].getTargetPlayer());
}
if(Source.getController().equals(Constant.Player.Human)) AllZone.GameAction.playSpellAbility(sa[i]);
else {
if(sa[i].canPlayAI()) {
ComputerUtil.playStackFree(sa[i]);
}
}
}
}
}
}
/*
final public Card getCard(String cardName, String owner) {
cardName = AllZone.NameChanger.getOriginalName(cardName);
return getCard2(cardName, owner);
}
*/
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//this is the new getCard() method, you have to remove the old getCard()
final public Card getCard(String cardName, String owner) {
if(removedCardList.contains(cardName) || cardName.equals(blankCard.getName())) return blankCard;
return getCard2(cardName, owner);
}
final static int hasKeyword(Card c, String k) {
ArrayList<String> a = c.getKeyword();
for(int i = 0; i < a.size(); i++)
if(a.get(i).toString().startsWith(k)) return i;
return -1;
}
private final int shouldManaAbility(Card c) {
ArrayList<String> a = c.getIntrinsicKeyword();
for(int i = 0; i < a.size(); i++)
if(a.get(i).toString().contains(": add ") || a.get(i).toString().contains(": Add ") ) return i;
return -1;
}
final private Card getCard2(final String cardName, final String owner) {
//o should be Card object
Object o = map.get(cardName);
if(o == null) throw new RuntimeException("CardFactory : getCard() invalid card name - " + cardName);
final Card card = copyStats(o);
card.setOwner(owner);
card.setController(owner);
//may have to change the spell
//this is so permanents like creatures and artifacts have a "default" spell
if(!card.isLand()) card.addSpellAbility(new Spell_Permanent(card));
//look for "Comes into play tapped." in the "no text" line
//of card.txt and add the appropriate code to make that happen
while(card.getKeyword().contains("Comes into play tapped."))
{
card.removeIntrinsicKeyword("Comes into play tapped.");
card.addIntrinsicKeyword("CARDNAME enters the battlefield tapped.");
}
if(card.getKeyword().contains("CARDNAME enters the battlefield tapped.")) {
card.addComesIntoPlayCommand(new Command() {
private static final long serialVersionUID = 203335252453049234L;
public void execute() {
System.out.println("Executing previous keyword");
card.tap();
}
});
}//if "Comes into play tapped."
if(card.getKeyword().contains("CARDNAME enters the battlefield tapped unless you control two or fewer other lands.")) {
card.addComesIntoPlayCommand(new Command() {
private static final long serialVersionUID = 6436821515525468682L;
public void execute() {
CardList lands = AllZoneUtil.getPlayerLandsInPlay(card.getController());
lands.remove(card);
if(!(lands.size() <= 2)) {
card.tap();
}
}
});
}
if (hasKeyword(card, "CARDNAME enters the battlefield tapped unless you control a") != -1)
{
int n = hasKeyword(card, "CARDNAME enters the battlefield tapped unless you control a");
String parse = card.getKeyword().get(n).toString();
String splitString;
if (parse.contains(" or a "))
splitString = " or a ";
else
splitString = " or an ";
final String types[] = parse.substring(60, parse.length() - 1).split(splitString);
card.addComesIntoPlayCommand(new Command()
{
private static final long serialVersionUID = 403635232455049834L;
public void execute()
{
PlayerZone pzICtrl = AllZone.getZone(Constant.Zone.Play, card.getOwner());
CardList clICtrl = new CardList(pzICtrl.getCards());
boolean fnd = false;
for (int i = 0; i < clICtrl.size(); i++)
{
Card c = clICtrl.get(i);
for (int j = 0; j < types.length; j++)
if (c.getType().contains(types[j].trim()))
fnd = true;
}
if (!fnd)
card.tap();
}
});
}
if(hasKeyword(card,"spCounter") != -1) {
//System.out.println("Processing spCounter for card " + card.getName());
ComputerAI_counterSpells2.KeywordedCounterspells.add(card.getName());
String keyword = card.getKeyword().get(hasKeyword(card,"spCounter"));
if(keyword.contains("X"))
{
keyword = keyword.replace("X", card.getSVar("X"));
}
card.removeIntrinsicKeyword(keyword);
String[] splitkeyword = keyword.split(":");
final String TargetType = splitkeyword[1];
final String TargetingRestrictions = splitkeyword[2];
final String Destination = splitkeyword[3];
final String ExtraActions = splitkeyword[4];
final String[] SplitTargetingRestrictions = TargetingRestrictions.split(" ");
final String[] SplitExtraActions = ExtraActions.split(" ");
SpellAbility spCounterAbility = new Spell(card)
{
private static final long serialVersionUID = 9763720166553L;
@Override
public boolean canPlayAI()
{
System.out.println("AI is pondering us...");
return canPlay();
}
@Override
public boolean canPlay()
{
if(AllZone.Stack.size() == 0)
{
return false;
}
boolean fullResult = true;
SpellAbility sa = AllZone.Stack.peek();
Card tgtCard = sa.getSourceCard();
if(TargetType.equals("Spell"))
{
if(sa.isAbility())
{
System.out.println(card.getName() + " can only counter spells, not abilities.");
return false;
}
}
else if(TargetType.equals("Ability"))
{
if(sa.isSpell())
{
System.out.println(card.getName() + " can only counter abilities, not spells.");
return false;
}
}
else if(TargetType.equals("SpellOrAbility"))
{
//Do nothing. This block is only for clarity and enforcing parameters.
}
else
{
throw new IllegalArgumentException("Invalid target type for card " + card.getName());
}
for(int i=0;i<SplitTargetingRestrictions.length;i++)
{
boolean subResult = false;
if(TargetingRestrictions.equals("None"))
{
return true;
}
String RestrictionID = SplitTargetingRestrictions[i].substring(0,SplitTargetingRestrictions[i].indexOf('('));
String Parameters = SplitTargetingRestrictions[i].substring(SplitTargetingRestrictions[i].indexOf('(')+1);
Parameters = Parameters.substring(0,Parameters.length()-1);
String[] SplitParameters = Parameters.split(",");
System.out.println(card.getName() + " currently checking restriction '" + RestrictionID + "'");
if(RestrictionID.equals("Color"))
{
for(int p=0;p<SplitParameters.length;p++)
{
System.out.println("Parameter: " + SplitParameters[p]);
if(SplitParameters[p].startsWith("Non-"))
{
subResult |= !CardUtil.getColors(tgtCard).contains(SplitParameters[p].substring(4).toLowerCase());
}
else
{
subResult |= CardUtil.getColors(tgtCard).contains(SplitParameters[p].toLowerCase());
}
}
}
else if(RestrictionID.equals("Type"))
{
for(int p=0;p<SplitParameters.length;p++)
{
System.out.println("Parameter: " + SplitParameters[p]);
if(SplitParameters[p].startsWith("Non-"))
{
System.out.println(SplitParameters[p].substring(4));
subResult |= !tgtCard.getType().contains(SplitParameters[p].substring(4));
}
else
{
subResult |= tgtCard.getType().contains(SplitParameters[p]);
}
}
}
else if(RestrictionID.equals("CMC"))
{
String mode = SplitParameters[0];
int value = Integer.parseInt(SplitParameters[1]);
System.out.println(mode);
System.out.println(Integer.toString(value));
if(mode.equals("<"))
{
subResult |= (CardUtil.getConvertedManaCost(tgtCard) < value);
}
else if(mode.equals(">"))
{
subResult |= (CardUtil.getConvertedManaCost(tgtCard) > value);
}
else if(mode.equals("=="))
{
subResult |= (CardUtil.getConvertedManaCost(tgtCard) == value);
}
else if(mode.equals("!="))
{
subResult |= (CardUtil.getConvertedManaCost(tgtCard) != value);
}
else if(mode.equals("<="))
{
subResult |= (CardUtil.getConvertedManaCost(tgtCard) <= value);
}
else if(mode.equals(">="))
{
subResult |= (CardUtil.getConvertedManaCost(tgtCard) >= value);
}
else
{
throw new IllegalArgumentException("spCounter: Invalid mode parameter to CMC restriction in card " + card.getName());
}
}
else if(RestrictionID.equals("Targets"))
{
if(sa.getTargetCard() == null)
{
return false;
}
for(int p=0;p<SplitParameters.length;p++)
{
System.out.println("Parameter: " + SplitParameters[p]);
if(SplitParameters[p].startsWith("My-")) //Targets my <type> permanent
{
if(sa.getTargetCard().getController() != card.getController())
{
return false;
}
if(SplitParameters[p].contains("Non-"))
{
subResult |= !sa.getTargetCard().getType().contains(SplitParameters[p].substring(7));
}
else
{
subResult |= (sa.getTargetCard().getType().contains(SplitParameters[p].substring(3)));
}
}
else if(SplitParameters[p].startsWith("Opp-")) //Targets opponent's <type> permanent
{
if(sa.getTargetCard().getController() == card.getController())
{
return false;
}
if(SplitParameters[p].contains("Non-"))
{
subResult |= !(sa.getTargetCard().getType().contains(SplitParameters[p].substring(8)));
}
else
{
subResult |= (sa.getTargetCard().getType().contains(SplitParameters[p].substring(4)));
}
}
else
{
if(SplitParameters[p].contains("Non-"))
{
subResult |= !(sa.getTargetCard().getType().contains(SplitParameters[p].substring(4)));
}
else
{
subResult |= (sa.getTargetCard().getType().contains(SplitParameters[p]));
}
}
}
}
System.out.println("Sub: " + Boolean.toString(subResult));
fullResult &= subResult;
} //End Targeting parsing
System.out.println("Success: " + Boolean.toString(fullResult));
return fullResult;
}
@Override
public void resolve()
{
System.out.println("Resolving " + card.getName());
SpellAbility sa = AllZone.Stack.pop();
System.out.println("Send countered spell to " + Destination);
if(Destination.equals("None") || TargetType.contains("Ability")) //For Ability-targeting counterspells
{
}
else if(Destination.equals("Graveyard"))
{
AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
}
else if(Destination.equals("Exile"))
{
AllZone.GameAction.exile(sa.getSourceCard());
}
else if(Destination.equals("Topdeck"))
{
AllZone.GameAction.moveToTopOfLibrary(sa.getSourceCard());
}
else if(Destination.equals("Hand"))
{
AllZone.GameAction.moveToHand(sa.getSourceCard());
}
else if(Destination.equals("BottomDeck"))
{
AllZone.GameAction.moveToBottomOfLibrary(sa.getSourceCard());
}
else if(Destination.equals("Shuffle"))
{
AllZone.GameAction.moveToBottomOfLibrary(sa.getSourceCard());
AllZone.GameAction.shuffle(sa.getSourceCard().getController());
}
else
{
throw new IllegalArgumentException("spCounter: Invalid Destination argument for card " + card.getName());
}
for(int ea = 0;ea<SplitExtraActions.length;ea++)
{
if(ExtraActions.equals("None"))
{
break;
}
String ActionID = SplitExtraActions[ea].substring(0,SplitExtraActions[ea].indexOf('('));
String Target = "";
String ActionParams = SplitExtraActions[ea].substring(SplitExtraActions[ea].indexOf('(')+1);
ActionParams = ActionParams.substring(0,ActionParams.length()-1);
String[] SplitActionParams = ActionParams.split(",");
System.out.println("Extra Action: " + ActionID);
System.out.println("Parameters: " + ActionParams);
if(ActionID.startsWith("My-"))
{
ActionID = ActionID.substring(3);
Target = card.getController();
}
else if(ActionID.startsWith("Opp-"))
{
ActionID = ActionID.substring(4);
Target = AllZone.GameAction.getOpponent(card.getController());
}
else if(ActionID.startsWith("CC-"))
{
ActionID = ActionID.substring(3);
Target = sa.getSourceCard().getController();
}
if(ActionID.equals("Draw"))
{
AllZone.GameAction.drawCards(Target, Integer.parseInt(SplitActionParams[0]));
}
else if(ActionID.equals("Discard"))
{
AllZone.GameAction.discard(Target, Integer.parseInt(SplitActionParams[0]), this);
}
else if(ActionID.equals("LoseLife"))
{
AllZone.GameAction.getPlayerLife(Target).subtractLife(Integer.parseInt(SplitActionParams[0]), card);
}
else if(ActionID.equals("GainLife"))
{
AllZone.GameAction.gainLife(Target, Integer.parseInt(SplitActionParams[0]));
}
else
{
throw new IllegalArgumentException("spCounter: Invalid Extra Action for card " + card.getName());
}
}
}
};
card.clearSpellAbility();
card.addSpellAbility(spCounterAbility);
} //spCounter
// Support for using string variables to define Count$ for X or Y
// Or just about any other String that a card object needs at any given time
// TODO: To Be Removed
while(hasKeyword(card, "SVar") != -1) {
int n = hasKeyword(card, "SVar");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":", 3);
if(k.length > 2) card.setSVar(k[1], k[2]);
}
}
if (card.isType("World")) // Enforce the "World rule"
{
Command intoPlay = new Command() {
private static final long serialVersionUID = 6536398032388958127L;
public void execute() {
CardList CardsinPlay = new CardList();
CardsinPlay.addAll(AllZone.Human_Play.getCards());
CardsinPlay.addAll(AllZone.Computer_Play.getCards());
CardsinPlay = CardsinPlay.getType("World");
CardsinPlay = CardsinPlay.filter(new CardListFilter() {
public boolean addCard(Card c) {
if(!c.equals(card)) return true;
return false;
}
});
for(int i = 0; i < CardsinPlay.size(); i++)
AllZone.GameAction.sacrificeDestroy(CardsinPlay.get(i));
}//execute()
};//Command
card.addComesIntoPlayCommand(intoPlay);
}
if (hasKeyword(card, "When CARDNAME enters the battlefield, return a land you control to its owner's hand.") != -1)
{
int n = hasKeyword(card, "When CARDNAME enters the battlefield, return a land you control to its owner's hand.");
if (n!= -1)
{
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
if(getSourceCard().getController().equals(Constant.Player.Computer))
setTargetCard(card);//CardFactoryUtil.getRandomCard(new CardList(AllZone.Computer_Play.getCards()).getType("Land")));
Card c = getTargetCard();
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, c.getOwner());
if(AllZone.GameAction.isCardInPlay(c)) {
AllZone.getZone(c).remove(c);
if(!c.isToken()) {
Card newCard = AllZone.CardFactory.getCard(c.getName(), c.getOwner());
hand.add(newCard);
}
}
}
};
Command intoPlay = new Command() {
private static final long serialVersionUID = 2045940121508110423L;
public void execute() {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
CardList choice = new CardList(play.getCards()).getType("Land");
if (!choice.isEmpty()) {
AllZone.InputControl.setInput(CardFactoryUtil.input_targetSpecific(ability, choice,
"Select a land you control.", false, false));
ButtonUtil.disableAll();
}
}//execute()
};//Command
card.addComesIntoPlayCommand(intoPlay);
}
}
if (hasKeyword(card, "Multikicker") != -1)
{
int n = hasKeyword(card, "Multikicker");
if (n!= -1)
{
String parse = card.getKeyword().get(n).toString();
String k[] = parse.split("kicker ");
SpellAbility sa = card.getSpellAbility()[0];
sa.setIsMultiKicker(true);
sa.setMultiKickerManaCost(k[1]);
}
}
//Creatures with self-regenerate abilities
//-1 means keyword "RegenerateMe" not found
while(hasKeyword(card, "RegenerateMe") != -1) {
int n = hasKeyword(card, "RegenerateMe");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
final Command untilEOT = new Command() {
private static final long serialVersionUID = -7619842476705984912L;
public void execute() {
card.setShield(0);
}
};
final SpellAbility a1 = new Ability(card, manacost) {
@Override
public boolean canPlayAI() {
if(CardFactoryUtil.AI_isMainPhase()) {
if(CardFactoryUtil.AI_doesCreatureAttack(card)) {
//"Fuzzy logic" to determine if using a regenerate ability might be helpful because
//we can't wait to decide to play this ability during combat, like the human can
//weight[] is a set of probability percentages to be averaged later
int weight[] = new int[3];
// cards with real keywords (flying, trample, etc) are probably more desireable
if(card.getKeyword().size() > 0) weight[0] = 75;
else weight[0] = 0;
// if there are many cards in hand, then maybe it's not such a great idea to waste mana
CardList HandList = new CardList(AllZone.getZone(Constant.Zone.Hand,
Constant.Player.Computer).getCards());
if(HandList.size() >= 4) weight[1] = 25;
else weight[1] = 75;
// compare the highest converted mana cost of cards in hand to the number of lands
// if there's spare mana, then regeneration might be viable
int hCMC = 0;
for(int i = 0; i < HandList.size(); i++)
if(CardUtil.getConvertedManaCost(HandList.getCard(i).getManaCost()) > hCMC) hCMC = CardUtil.getConvertedManaCost(HandList.getCard(
i).getManaCost());
CardList LandList = new CardList(AllZone.getZone(Constant.Zone.Play,
Constant.Player.Computer).getCards());
LandList = LandList.getType("Land");
//most regenerate abilities cost 2 or less
if(hCMC + 2 >= LandList.size()) weight[2] = 50;
else weight[2] = 0;
// ultimately, it's random fate that dictates if this was the right play
int aw = (weight[0] + weight[1] + weight[2]) / 3;
Random r = new Random();
if(r.nextInt(100) <= aw) return true;
}
}
return false;
}
@Override
public void resolve() {
card.addShield();
AllZone.EndOfTurn.addUntil(untilEOT);
}
}; //SpellAbility
card.addSpellAbility(a1);
String Desc = "";
Desc = "Regenerate " + cardName;
a1.setDescription(manacost + ": " + Desc);
a1.setStackDescription(Desc);
a1.setBeforePayMana(new Input_PayManaCost(a1));
} //if (should RegenerateMe)
} //while - card has more RegenerateMe - Jungle Troll has two Regenerate keywords
if (hasKeyword(card, "spDiscard") != -1)
{
int n = hasKeyword(card, "spDiscard");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean Tgt = k[0].contains("Tgt");
final boolean Opp = k[0].contains("Opp");
final String DiscardMethod = k[1];
final int NumCards[] = {-1138};
final String NumCardsX[] = {"none"};
final String UnlessType[] = {"none"};
if (k[2].length() > 1)
{
String kk[] = k[2].split("/");
if (kk[1].startsWith("UnlessDiscardType"))
{
String jk[] = kk[1].split("\\.");
UnlessType[0] = jk[1];
NumCards[0] = Integer.parseInt(kk[0]);
}
}
else if (k[2].matches("X"))
{
String xy = card.getSVar(k[2]);
if (xy.startsWith("Count$"))
{
String kk[] = xy.split("\\$");
NumCardsX[0] = kk[1];
}
}
else if (k[2].matches("[0-9]"))
{
NumCards[0] = Integer.parseInt(k[2]);
}
final String Drawback[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if (k[3].contains("Drawback$"))
{
String kk[] = k[3].split("\\$");
Drawback[0] = kk[1];
if (k.length > 4) spDesc[0] = k[4];
if (k.length > 5) stDesc[0] = k[5];
}
else
{
if (k.length > 3) spDesc[0] = k[3];
if (k.length > 4) stDesc[0] = k[4];
}
SpellAbility spDiscard = new Spell(card)
{
private static final long serialVersionUID = 837472987492L;
private int getNumCards() {
if(NumCards[0] != -1138) return NumCards[0];
if(!NumCardsX[0].equals("none")) return CardFactoryUtil.xCount(card, NumCardsX[0]);
return 0;
}
public boolean canPlayAI()
{
int nCards = getNumCards();
PlayerZone pzH = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Human);
int numHHand = pzH.size();
if (numHHand >= nCards)
{
if (Tgt)
setTargetPlayer(Constant.Player.Human);
return true;
}
return false;
}
public void resolve()
{
int nCards = getNumCards();
String discardingPlayer = "";
if (Tgt)
discardingPlayer = getTargetPlayer();
else if (Opp)
discardingPlayer = AllZone.GameAction.getOpponent(card.getController());
if (DiscardMethod.equals("OppChoose") || DiscardMethod.equals("TgtChoose"))
{
//String opp = AllZone.GameAction.getOpponent(card.getController());
if (!UnlessType[0].equals("none"))
AllZone.GameAction.discardUnless(discardingPlayer, nCards, UnlessType[0], this);
else
AllZone.GameAction.discard(discardingPlayer, nCards, this);
}
else if (DiscardMethod.equals("AtRandom"))
{
AllZone.GameAction.discardRandom(discardingPlayer, nCards, this);
}
else if (DiscardMethod.equals("Hand"))
{
AllZone.GameAction.discardHand(discardingPlayer, this);
}
else if (DiscardMethod.startsWith("RevealYouChoose"))
{
PlayerZone pzH = AllZone.getZone(Constant.Zone.Hand, discardingPlayer);
if (pzH.size() != 0)
{
CardList dPHand = new CardList(pzH.getCards());
CardList dPChHand = new CardList(dPHand.toArray());
if (DiscardMethod.contains("/")) // Restrict card choices
{
int dot = DiscardMethod.indexOf("/");
String dV = DiscardMethod.substring(dot + 1);
String dValid[] = dV.split(",");
dPChHand = dPHand.getValidCards(dValid);
}
if (card.getController().equals(Constant.Player.Computer))
{
//AI
for (int i=0; i<nCards; i++)
{
if (dPChHand.size() > 0)
{
CardList dChoices = new CardList();
if (DiscardMethod.contains("Creature") && !DiscardMethod.contains("nonCreature")) {
Card c = CardFactoryUtil.AI_getBestCreature(dPChHand);
if (c!=null)
dChoices.add(CardFactoryUtil.AI_getBestCreature(dPChHand));
}
CardListUtil.sortByTextLen(dPChHand);
dChoices.add(dPChHand.get(0));
CardListUtil.sortCMC(dPChHand);
dChoices.add(dPChHand.get(0));
Card dC = dChoices.get(CardUtil.getRandomIndex(dChoices));
dPChHand.remove(dC);
CardList dCs = new CardList();
dCs.add(dC);
AllZone.Display.getChoiceOptional("Computer has chosen", dCs.toArray());
AllZone.GameAction.discard(dC, this);
}
}
}
else
{
//human
AllZone.Display.getChoiceOptional("Revealed computer hand", dPHand.toArray());
for (int i=0; i<nCards; i++)
{
if (dPChHand.size() > 0)
{
Card dC = AllZone.Display.getChoice("Choose a card to be discarded", dPChHand.toArray());
dPChHand.remove(dC);
AllZone.GameAction.discard(dC, this);
}
}
}
}
}
if (!Drawback[0].equals("none"))
{
CardFactoryUtil.doDrawBack(Drawback[0], nCards, card.getController(), AllZone.GameAction.getOpponent(card.getController()), discardingPlayer, card, card, this);
}
}
};
if (Tgt)
spDiscard.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spDiscard));
spDiscard.setDescription(spDesc[0]);
spDiscard.setStackDescription(stDesc[0]);
card.clearSpellAbility();
card.addSpellAbility(spDiscard);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbDiscard = spDiscard.copy();
bbDiscard.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
StringBuilder sb = new StringBuilder();
sb.append("Buyback ").append(bbCost).append(" (You may pay an additional ").append(bbCost);
sb.append(" as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbDiscard.setDescription(sb.toString());
// bbDiscard.setDescription("Buyback " + bbCost + " (You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbDiscard.setIsBuyBackAbility(true);
if (Tgt)
bbDiscard.setBeforePayMana(CardFactoryUtil.input_targetPlayer(bbDiscard));
card.addSpellAbility(bbDiscard);
}
}//spDiscardTgt
if (hasKeyword(card, "spAllPump") != -1)
{
int n = hasKeyword(card, "spAllPump");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String Scope[] = k[1].split("/");
final int NumAttack[] = {-1138};
final String AttackX[] = {"none"};
final int NumDefense[] = {-1138};
final String DefenseX[] = {"none"};
final String Keyword[] = {"none"};
String ptk[] = k[2].split("/");
if (ptk.length == 1)
Keyword[0] = ptk[0];
if (ptk.length >= 2)
{
if (ptk[0].matches("[\\+\\-][XY]"))
{
String xy = card.getSVar(ptk[0].replaceAll("[\\+\\-]", ""));
if (xy.startsWith("Count$"))
{
String kk[] = xy.split("\\$");
AttackX[0] = kk[1];
if (ptk[0].contains("-"))
{
if (AttackX[0].contains("/"))
AttackX[0] = AttackX[0].replace("/", "/Negative");
else
AttackX[0] += "/Negative";
}
}
}
else if (ptk[0].matches("[\\+\\-][0-9]"))
NumAttack[0] = Integer.parseInt(ptk[0].replace("+", ""));
if (ptk[1].matches("[\\+\\-][XY]"))
{
String xy = card.getSVar(ptk[1].replaceAll("[\\+\\-]", ""));
if (xy.startsWith("Count$"))
{
String kk[] = xy.split("\\$");
DefenseX[0] = kk[1];
if (ptk[1].contains("-"))
{
if (DefenseX[0].contains("/"))
DefenseX[0] = DefenseX[0].replace("/", "/Negative");
else
DefenseX[0] += "/Negative";
}
}
}
else if (ptk[1].matches("[\\+\\-][0-9]"))
NumDefense[0] = Integer.parseInt(ptk[1].replace("+", ""));
}
if (ptk.length == 3)
Keyword[0] = ptk[2];
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if (k.length > 3)
{
if (k[3].contains("Drawback$"))
{
String kk[] = k[3].split("\\$");
DrawBack[0] = kk[1];
if (k.length > 4) spDesc[0] = k[4];
if (k.length > 5) stDesc[0] = k[5];
}
else
{
if (k.length > 3) spDesc[0] = k[3];
if (k.length > 4) stDesc[0] = k[4];
}
}
SpellAbility spAllPump = new Spell(card)
{
private static final long serialVersionUID = 837472987492L;
private int getNumAttack() {
if(NumAttack[0] != -1138) return NumAttack[0];
if(!AttackX[0].equals("none")) return CardFactoryUtil.xCount(card, AttackX[0]);
return 0;
}
private int getNumDefense() {
if(NumDefense[0] != -1138) return NumDefense[0];
if(!DefenseX[0].equals("none")) return CardFactoryUtil.xCount(card, DefenseX[0]);
return 0;
}
private int getNumKeyword()
{
if (!Keyword[0].equals("none"))
return Keyword[0].split(" & ").length;
else return 0;
}
private CardList getScopeList()
{
CardList l = new CardList();
if (Scope[0].contains("YouCtrl"))
l.addAll(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards());
if (Scope[0].contains("All")) {
l.addAll(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards());
l.addAll(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards());
}
String fc[] = {"Creature"};
l = l.getValidCards(fc);
if (Scope.length > 1)
{
String v = Scope[1];
if (v.length() > 0)
l = l.getValidCards(v.split(","));
}
return l;
}
public boolean canPlayAI()
{
//Log.debug("spAllPump", "Phase - " + AllZone.Phase.getPhase());
String curPhase = AllZone.Phase.getPhase();
if (curPhase.equals(Constant.Phase.Main2))
return false;
CardList sl = getScopeList();
int NumScope = sl.size();
int defense = getNumDefense();
int attack = getNumAttack();
int key = getNumKeyword();
int th = (attack + defense + key) / 2; // Benefit Threshold
if (NumScope > th) // have enough creatures in play
{
Combat c = ComputerUtil.getAttackers();
if (c.getAttackers().length >= th) // have enough creatures that will attack
{
int ndead = 0;
for (int i=0; i<sl.size(); i++) // check to see if this will kill any creatures
if ((sl.get(i).getNetDefense() + defense) < 1)
ndead++;
if (!(ndead > (sl.size() / 2))) // don't kill more than half of the creatures
return true;
}
}
return false;
}
public void resolve()
{
final int attack = getNumAttack();
final int defense = getNumDefense();
final CardList sl = getScopeList();
Log.debug("spAllPump", "Phase - " + AllZone.Phase.getPhase());
final Command untilEOT = new Command()
{
private static final long serialVersionUID = 92848209484928L;
public void execute()
{
for (int i=0; i<sl.size(); i++)
{
Card c = sl.get(i);
if (AllZone.GameAction.isCardInPlay(c))
{
c.addTempAttackBoost(-attack);
c.addTempDefenseBoost(-defense);
if (!Keyword[0].equals("none"))
{
String kws[] = Keyword[0].split(" & ");
for (int j=0; j<kws.length; j++)
c.removeExtrinsicKeyword(kws[j]);
}
}
}
}
}; // untilEOT command
for (int i=0; i<sl.size(); i++)
{
Card c = sl.get(i);
if (AllZone.GameAction.isCardInPlay(c))
{
c.addTempAttackBoost(attack);
c.addTempDefenseBoost(defense);
if (!Keyword[0].equals("none"))
{
String kws[] = Keyword[0].split(" & ");
for (int j=0; j<kws.length; j++)
c.addExtrinsicKeyword(kws[j]);
}
}
}
AllZone.EndOfTurn.addUntil(untilEOT);
if (!DrawBack[0].equals("none"))
CardFactoryUtil.doDrawBack(DrawBack[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), card.getController(), card, card, this);
} // resolve
}; // spAllPump
spAllPump.setDescription(spDesc[0]);
spAllPump.setStackDescription(stDesc[0]);
card.clearSpellAbility();
card.addSpellAbility(spAllPump);
card.setSVar("PlayMain1", "TRUE");
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbAllPump = spAllPump.copy();
bbAllPump.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
StringBuilder sb = new StringBuilder();
sb.append("Buyback ").append(bbCost).append(" (You may pay an additional ").append(bbCost);
sb.append(" as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbAllPump.setDescription(sb.toString());
// bbAllPump.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbAllPump.setIsBuyBackAbility(true);
card.addSpellAbility(bbAllPump);
}
}//spAllPump
while (hasKeyword(card, "abAllPump") != -1)
{
int n = hasKeyword(card, "abAllPump");
if (n != -1)
{
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmpCost[] = k[0].replace("abAllPump", "").split(" ", 2);
final Target abTgt = new Target(tmpCost[0]);
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true);
final String Scope[] = k[1].split("/");
final int NumAttack[] = {-1138};
final String AttackX[] = {"none"};
final int NumDefense[] = {-1138};
final String DefenseX[] = {"none"};
final String Keyword[] = {"none"};
String ptk[] = k[2].split("/");
if (ptk.length == 1)
Keyword[0] = ptk[0];
if (ptk.length >= 2)
{
if (ptk[0].matches("[\\+\\-][XY]"))
{
String xy = card.getSVar(ptk[0].replaceAll("[\\+\\-]", ""));
if (xy.startsWith("Count$"))
{
String kk[] = xy.split("\\$");
AttackX[0] = kk[1];
if (ptk[0].contains("-"))
{
if (AttackX[0].contains("/"))
AttackX[0] = AttackX[0].replace("/", "/Negative");
else
AttackX[0] += "/Negative";
}
}
}
else if (ptk[0].matches("[\\+\\-][0-9]"))
NumAttack[0] = Integer.parseInt(ptk[0].replace("+", ""));
if (ptk[1].matches("[\\+\\-][XY]"))
{
String xy = card.getSVar(ptk[1].replaceAll("[\\+\\-]", ""));
if (xy.startsWith("Count$"))
{
String kk[] = xy.split("\\$");
DefenseX[0] = kk[1];
if (ptk[1].contains("-"))
{
if (DefenseX[0].contains("/"))
DefenseX[0] = DefenseX[0].replace("/", "/Negative");
else
DefenseX[0] += "/Negative";
}
}
}
else if (ptk[1].matches("[\\+\\-][0-9]"))
NumDefense[0] = Integer.parseInt(ptk[1].replace("+", ""));
}
if (ptk.length == 3)
Keyword[0] = ptk[2];
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if (k.length > 3)
{
if (k[3].contains("Drawback$"))
{
String kk[] = k[3].split("\\$");
DrawBack[0] = kk[1];
if (k.length > 4) spDesc[0] = k[4];
if (k.length > 5) stDesc[0] = k[5];
}
else
{
if (k.length > 3) spDesc[0] = k[3];
if (k.length > 4) stDesc[0] = k[4];
}
}
SpellAbility abAllPump = new Ability_Activated(card, abCost, abTgt)
{
private static final long serialVersionUID = 7783282947592874L;
private int getNumAttack() {
if(NumAttack[0] != -1138) return NumAttack[0];
if(!AttackX[0].equals("none")) return CardFactoryUtil.xCount(card, AttackX[0]);
return 0;
}
private int getNumDefense() {
if(NumDefense[0] != -1138) return NumDefense[0];
if(!DefenseX[0].equals("none")) return CardFactoryUtil.xCount(card, DefenseX[0]);
return 0;
}
private int getNumKeyword()
{
if (!Keyword[0].equals("none"))
return Keyword[0].split(" & ").length;
else return 0;
}
private CardList getScopeList()
{
CardList l = new CardList();
if (Scope[0].contains("YouCtrl"))
l.addAll(AllZone.getZone(Constant.Zone.Play, card.getController()).getCards());
if (Scope[0].contains("All")) {
l.addAll(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards());
l.addAll(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards());
}
String fc[] = {"Creature"};
l = l.getValidCards(fc);
if (Scope.length > 1)
{
String v = Scope[1];
if (v.length() > 0)
l = l.getValidCards(v.split(","));
}
return l;
}
@Override
public boolean canPlay() {
if (abCost.getTap() && (card.isTapped() || card.isSick()))
return false;
return (CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
@Override
public boolean canPlayAI()
{
//Log.debug("spAllPump", "Phase - " + AllZone.Phase.getPhase());
String curPhase = AllZone.Phase.getPhase();
if (curPhase.equals(Constant.Phase.Main2))
return false;
// temporarily disabled until AI is improved
if (abCost.getSacCost()) return false;
if (abCost.getSubCounter()) return false;
if (abCost.getLifeCost()) return false;
if (abCost.getTap() && (card.isTapped() || card.isSick()))
return false;
CardList sl = getScopeList();
int NumScope = sl.size();
int defense = getNumDefense();
int attack = getNumAttack();
int key = getNumKeyword();
int th = (attack + defense + key) / 2; // Benefit Threshold
if (NumScope > th) // have enough creatures in play
{
Combat c = ComputerUtil.getAttackers();
if (c.getAttackers().length >= th) // have enough creatures that will attack
{
int ndead = 0;
for (int i=0; i<sl.size(); i++) // check to see if this will kill any creatures
if ((sl.get(i).getNetDefense() + defense) < 1)
ndead++;
if (!(ndead > (sl.size() / 2))) // don't kill more than half of the creatures
return true;
}
}
return false;
}
@Override
public void resolve()
{
final int attack = getNumAttack();
final int defense = getNumDefense();
final CardList sl = getScopeList();
//Log.debug("spAllPump", "Phase - " + AllZone.Phase.getPhase());
final Command untilEOT = new Command()
{
private static final long serialVersionUID = 92848209484928L;
public void execute()
{
for (int i=0; i<sl.size(); i++)
{
Card c = sl.get(i);
if (AllZone.GameAction.isCardInPlay(c))
{
c.addTempAttackBoost(-attack);
c.addTempDefenseBoost(-defense);
if (!Keyword[0].equals("none"))
{
String kws[] = Keyword[0].split(" & ");
for (int j=0; j<kws.length; j++)
c.removeExtrinsicKeyword(kws[j]);
}
}
}
}
}; // untilEOT command
for (int i=0; i<sl.size(); i++)
{
Card c = sl.get(i);
if (AllZone.GameAction.isCardInPlay(c))
{
c.addTempAttackBoost(attack);
c.addTempDefenseBoost(defense);
if (!Keyword[0].equals("none"))
{
String kws[] = Keyword[0].split(" & ");
for (int j=0; j<kws.length; j++)
c.addExtrinsicKeyword(kws[j]);
}
}
}
AllZone.EndOfTurn.addUntil(untilEOT);
if (!DrawBack[0].equals("none"))
CardFactoryUtil.doDrawBack(DrawBack[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), card.getController(), card, card, this);
} // resolve
}; // abAllPump
abAllPump.setDescription(abCost.toString() + spDesc[0]);
abAllPump.setStackDescription(stDesc[0]);
card.addSpellAbility(abAllPump);
}
}
while(hasKeyword(card, "abPump") != -1) {
int n = hasKeyword(card, "abPump");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmp = k[0].replace("abPump", "");
String[] tmpCost = tmp.split(" ", 2);
final boolean bPumpEquipped = (tmpCost[0].equals("Equipped"));
final Target abTgt = new Target(tmpCost[0]);
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true);
final int NumAttack[] = {-1138};
final String AttackX[] = {"none"};
final int NumDefense[] = {-1138};
final String DefenseX[] = {"none"};
final String Keyword[] = {"none"};
String ptk[] = k[1].split("/");
if(ptk.length == 1) // keyword only
Keyword[0] = ptk[0];
if(ptk.length >= 2) // power/toughness
{
if(ptk[0].matches("[\\+\\-][XY]")) {
String xy = card.getSVar(ptk[0].replaceAll("[\\+\\-]", ""));
if(xy.startsWith("Count$")) {
String kk[] = xy.split("\\$");
AttackX[0] = kk[1];
if(ptk[0].contains("-")) // handle "-X" or "-Y"
if(AttackX[0].contains("/")) // already contains math element
AttackX[0] = AttackX[0].replace("/", "/Negative"); // insert into existing math element
else AttackX[0] += "/Negative"; // add math element
}
} else if(ptk[0].matches("[\\+\\-][0-9]"))
NumAttack[0] = Integer.parseInt(ptk[0].replace("+", ""));
if(ptk[1].matches("[\\+\\-][XY]")) {
String xy = card.getSVar(ptk[1].replaceAll("[\\+\\-]", ""));
if(xy.startsWith("Count$")) {
String kk[] = xy.split("\\$");
DefenseX[0] = kk[1];
if(ptk[1].contains("-")) //handle "-X" or "-Y"
if(DefenseX[0].contains("/")) // already contains math element
DefenseX[0] = DefenseX[0].replace("/", "/Negative"); // insert into existing math element
else DefenseX[0] += "/Negative"; // add math element
}
} else if(ptk[1].matches("[\\+\\-][0-9]")) NumDefense[0] = Integer.parseInt(ptk[1].replace(
"+", ""));
}
if(ptk.length == 3) // power/toughness/keyword
Keyword[0] = ptk[2];
String dK = Keyword[0];
if (Keyword[0].contains(" & "))
{
int amp = Keyword[0].lastIndexOf("&");
StringBuffer sbk = new StringBuffer(Keyword[0]);
sbk.replace(amp, amp + 1, "and");
dK = sbk.toString();
dK = dK.replace(" & ", ", ");
}
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
String d = "none";
StringBuilder sbD = new StringBuilder();
if(abTgt.doesTarget())
sbD.append("Target creature");
else if (bPumpEquipped)
sbD.append("Equipped creature");
else
sbD.append(cardName);
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && Keyword[0].equals("none")) {
// pt boost
sbD.append(" gets ");
if(NumAttack[0] > 0 || (NumAttack[0] == 0 && NumDefense[0] > 0)) // +0/+1
sbD.append("+");
else if(NumAttack[0] < 0 || (NumAttack[0] == 0 && NumDefense[0] < 0)) // -0/-1
sbD.append("-");
sbD.append(Math.abs(NumAttack[0]) + "/");
if(NumDefense[0] > 0 || (NumDefense[0] == 0 && NumAttack[0] > 0)) // +1/+0
sbD.append("+");
else if(NumDefense[0] < 0 || (NumDefense[0] == 0 && NumAttack[0] < 0)) // -1/-0
sbD.append("-");
sbD.append(Math.abs(NumDefense[0]));
sbD.append(" until end of turn.");
}
if((AttackX[0].equals("none") && NumAttack[0] == -1138)
&& (DefenseX[0].equals("none") && NumDefense[0] == -1138) && !Keyword[0].equals("none")) {
// k boost
sbD.append(" gains ");
sbD.append(dK);
sbD.append(" until end of turn.");
}
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && !Keyword[0].equals("none")) {
// ptk boost
sbD.append(" gets ");
if(NumAttack[0] > 0 || (NumAttack[0] == 0 && NumDefense[0] > 0)) // +0/+1
sbD.append("+");
else if(NumAttack[0] < 0 || (NumAttack[0] == 0 && NumDefense[0] < 0)) // -0/-1
sbD.append("-");
sbD.append(Math.abs(NumAttack[0]) + "/");
if(NumDefense[0] > 0 || (NumDefense[0] == 0 && NumAttack[0] > 0)) // +1/+0
sbD.append("+");
else if(NumDefense[0] < 0 || (NumDefense[0] == 0 && NumAttack[0] < 0)) // -1/-0
sbD.append("-");
sbD.append(Math.abs(NumDefense[0]));
sbD.append(" and gains ");
sbD.append(dK);
sbD.append(" until end of turn.");
}
//if (!sbD.toString().isEmpty())
if(sbD.toString().trim().length() != 0) d = sbD.toString();
if(k.length > 2) {
if(k[2].contains("Drawback$")) {
String kk[] = k[2].split("\\$");
DrawBack[0] = kk[1];
if(k.length > 3) d = k[3];
} else if(k.length > 2) d = k[2];
}
if(!d.equals("none")) {
spDesc[0] = abCost.toString() + d;
stDesc[0] = d;
}
// start ability here:
final SpellAbility ability = new Ability_Activated(card, abCost, abTgt) {
private static final long serialVersionUID = -1118592153328758083L;
private int defense;
private String keyword;
private int getNumAttack() {
if(NumAttack[0] != -1138) return NumAttack[0];
if(!AttackX[0].equals("none")) return CardFactoryUtil.xCount(card, AttackX[0]);
return 0;
}
private int getNumDefense() {
if(NumDefense[0] != -1138) return NumDefense[0];
if(!DefenseX[0].equals("none")) return CardFactoryUtil.xCount(card, DefenseX[0]);
return 0;
}
@Override
public boolean canPlayAI() {
// temporarily disabled until AI is improved
if (abCost.getSacCost()) return false;
if (abCost.getLifeCost()) return false;
if (abCost.getSubCounter()){
// instead of never removing counters, we will have a random possibility of failure.
// all the other tests still need to pass if a counter will be removed
Counters count = abCost.getCounterType();
double chance = .66;
if (count.equals("P1P1")){ // 10% chance to remove +1/+1 to pump
chance = .1;
}
else if (count.equals("CHARGE")){ // 50% chance to remove +1/+1 to pump
chance = .5;
}
Random r = new Random();
if(r.nextFloat() > chance)
return false;
}
if (bPumpEquipped && card.getEquippingCard() == null) return false;
if (!ComputerUtil.canPayCost(this))
return false;
defense = getNumDefense();
keyword = Keyword[0];
if(AllZone.Phase.getPhase().equals(Constant.Phase.Main2)) return false;
if(!abTgt.doesTarget()) {
Card creature;
if (bPumpEquipped)
creature = card.getEquippingCard();
else
creature = card;
if((creature.getNetDefense() + defense > 0) && (!creature.getKeyword().contains(keyword))) {
if(creature.hasSickness() && keyword.contains("Haste"))
return true;
else if (creature.hasSickness() ^ keyword.contains("Haste"))
return false;
else {
Random r = new Random();
if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
return CardFactoryUtil.AI_doesCreatureAttack(creature);
}
}
}
CardList list = getCreatures();
if(!list.isEmpty()) {
boolean goodt = false;
Card t = new Card();
while(goodt == false && !list.isEmpty()) // loop until we find a target that is best and won't die when targeted or until no more creatures
{
t = CardFactoryUtil.AI_getBestCreature(list);
if((t.getNetDefense() + defense) > 0) // handle negative defense pumps
goodt = true;
else list.remove(t);
}
if(goodt == true) {
Random r = new Random();
if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) {
setTargetCard(t);
return true;
}
}
}
return false;
}
@Override
public boolean canPlay() {
return (Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
private CardList getCreatures() {
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
if(c.isCreature()) {
if(c.hasSickness() && keyword.contains("Haste")) // AI_doesCreatureAttack would have prevented the effect from granting haste, because it assumes the creature would already have it
return CardFactoryUtil.canTarget(card, c);
return (CardFactoryUtil.AI_doesCreatureAttack(c))
&& (CardFactoryUtil.canTarget(card, c))
&& (!keyword.equals("none") && !c.hasAnyKeyword(keyword.split(" & ")))
&& (!(!c.hasSickness()) && keyword.contains("Haste")); // if creature doesn't have sickness, the haste keyword won't help
}
return false;
}
});
if (abCost.getSacCost() && abCost.getSacThis()) // if sacrifice <this>, don't self-target
list.remove(card);
return list;
}//getCreatures()
@Override
public void resolve() {
final Card[] creature = new Card[1];
if(abTgt.doesTarget())
creature[0] = getTargetCard();
else if (bPumpEquipped)
creature[0] = card.getEquippingCard();
else
creature[0] = card;
if(creature[0] != null && AllZone.GameAction.isCardInPlay(creature[0])
&& (!abTgt.doesTarget() || CardFactoryUtil.canTarget(card, getTargetCard()))) {
final int a = getNumAttack();
final int d = getNumDefense();
final Command EOT = new Command() {
private static final long serialVersionUID = -8840812331316327448L;
public void execute() {
if(AllZone.GameAction.isCardInPlay(creature[0])) {
creature[0].addTempAttackBoost(-1 * a);
creature[0].addTempDefenseBoost(-1 * d);
if(!Keyword[0].equals("none"))
{
String[] kws = Keyword[0].split(" & ");
for (int i=0; i<kws.length; i++)
creature[0].removeExtrinsicKeyword(kws[i]);
}
}
}
};
creature[0].addTempAttackBoost(a);
creature[0].addTempDefenseBoost(d);
if(!Keyword[0].equals("none"))
{
String[] kws = Keyword[0].split(" & ");
for (int i=0; i<kws.length; i++)
creature[0].addExtrinsicKeyword(kws[i]);
}
card.setAbilityUsed(card.getAbilityUsed() + 1);
AllZone.EndOfTurn.addUntil(EOT);
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], 0,
card.getController(),
AllZone.GameAction.getOpponent(card.getController()), null, card,
creature[0], this);
}//if (card is in play)
}//resolve()
};//SpellAbility
ability.setDescription(spDesc[0]);
ability.setStackDescription(stDesc[0]);
if(!abTgt.doesTarget())
ability.setTargetCard(card);
card.addSpellAbility(ability);
}
}//while
if(hasKeyword(card, "Untap") != -1) {
int n = hasKeyword(card, "Untap");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.addSpellAbility(CardFactoryUtil.ability_Untap(card, manacost));
}
}
if(hasKeyword(card, "Remove three spore counters") != -1) {
int n = hasKeyword(card, "Remove three spore counters");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
card.addSpellAbility(CardFactoryUtil.ability_Spore_Saproling(card));
}
}//Spore Saproling
if (hasKeyword(card, "abAddReflectedMana") != -1) {
int n = hasKeyword(card,"abAddReflectedMana");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String[] k = parse.split(":");
// Reflecting Pool, Exotic Orchard, Fellwar Stone
card.setReflectedLand(true);
//
final Ability_Mana reflectedManaAbility = CardFactoryUtil.getReflectedManaAbility(card, k[1], k[2]);
card.addSpellAbility(reflectedManaAbility);
} // ReflectingPool
if(hasKeyword(card, "spDamageTgt") != -1) {
int n = hasKeyword(card, "spDamageTgt");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
card.clearSpellAbility();
String k[] = parse.split(":");
final boolean TgtCreature[] = {false};
final boolean TgtPlayer[] = {false};
final boolean TgtCP[] = {false};
final boolean TgtOpp[] = {false};
final boolean usesXCost[] = {false};
if(k[0].contains("CP")) TgtCP[0] = true;
else if(k[0].contains("P")) TgtPlayer[0] = true;
else if(k[0].contains("C")) TgtCreature[0] = true;
else if(k[0].contains("Opp")) TgtOpp[0] = true;
// how much damage
final int NumDmg[] = {-1};
final String NumDmgX[] = {"none"};
if(k[1].matches("X")) {
String x = card.getSVar(k[1]);
if(x.startsWith("Count$")) {
String kk[] = x.split("\\$");
NumDmgX[0] = kk[1];
}
if (x.equals("Count$xPaid"))
{
usesXCost[0] = true;
}
} else if(k[1].matches("[0-9][0-9]?")) NumDmg[0] = Integer.parseInt(k[1]);
//drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if(k.length > 2) {
if(k[2].contains("Drawback$")) {
String kk[] = k[2].split("\\$");
DrawBack[0] = kk[1];
if(k.length > 3) spDesc[0] = k[3];
if(k.length > 4) stDesc[0] = k[4];
} else {
if(k.length > 2) spDesc[0] = k[2];
if(k.length > 3) stDesc[0] = k[3];
}
}
final SpellAbility DamageTgt = new Spell(card) {
private static final long serialVersionUID = 7239608350643325111L;
private int damage;
public int getNumDamage() {
if(NumDmg[0] != -1) return NumDmg[0];
if(!NumDmgX[0].equals("none")) return CardFactoryUtil.xCount(card, NumDmgX[0]);
return 0;
}
public int getNumXDamage()
{
return card.getXManaCostPaid();
}
boolean shouldTgtP() {
PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer);
CardList hand = new CardList(compHand.getCards());
if(hand.size() >= 7) // anti-discard-at-EOT
return true;
if(AllZone.Human_Life.getLife() < (10 + damage)) // if damage from this spell would drop the human to less than 10 life
return true;
return false;
}
Card chooseTgtC() {
// Combo alert!!
PlayerZone compy = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
CardList cPlay = new CardList(compy.getCards());
if(cPlay.size() > 0) for(int i = 0; i < cPlay.size(); i++)
if(cPlay.get(i).getName().equals("Stuffy Doll")) return cPlay.get(i);
PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
CardList hPlay = new CardList(human.getCards());
hPlay = hPlay.filter(new CardListFilter() {
public boolean addCard(Card c) {
// will include creatures already dealt damage
return c.isCreature() && ((c.getNetDefense() + c.getDamage()) <= damage)
&& CardFactoryUtil.canTarget(card, c);
}
});
if(hPlay.size() > 0) {
Card best = hPlay.get(0);
if(hPlay.size() > 1) {
for(int i = 1; i < hPlay.size(); i++) {
Card b = hPlay.get(i);
// choose best overall creature?
if(b.getSpellAbility().length > best.getSpellAbility().length
|| b.getKeyword().size() > best.getKeyword().size()
|| b.getNetAttack() > best.getNetAttack()) best = b;
}
}
return best;
}
return null;
}
@Override
public boolean canPlayAI() {
damage = getNumDamage();
if (damage == 0)
return false;
if(TgtCP[0] == true) {
if(shouldTgtP() == true) {
setTargetPlayer(Constant.Player.Human);
return true;
}
Card c = chooseTgtC();
if(c != null) {
setTargetCard(c);
return true;
}
}
if(TgtPlayer[0] == true || TgtOpp[0] == true) {
setTargetPlayer(Constant.Player.Human);
return true;
}
if(TgtCreature[0] == true) {
Card c = chooseTgtC();
if(c != null) {
setTargetCard(c);
return true;
}
}
return false;
}
@Override
public void resolve() {
damage = getNumDamage();
if (usesXCost[0])
damage = getNumXDamage();
String tgtP = "";
if(TgtOpp[0] == true) setTargetPlayer(AllZone.GameAction.getOpponent(card.getController()));
if(getTargetCard() != null) {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
Card c = getTargetCard();
//c.addDamage(damage);
AllZone.GameAction.addDamage(c, card, damage);
tgtP = c.getController();
if(!DrawBack[0].equals("none"))
CardFactoryUtil.doDrawBack(DrawBack[0], damage,
card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtP,
card, getTargetCard(), this);
}
} else {
tgtP = getTargetPlayer();
AllZone.GameAction.addDamage(tgtP, card, damage);
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], damage,
card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtP,
card, null, this);
}
}// resolove
}; //spellAbility
card.setSVar("PlayMain1", "TRUE");
if(!spDesc[0].equals("none")) DamageTgt.setDescription(spDesc[0]);
else {
String s;
s = card.getName() + " deals " + NumDmg[0] + " damage to target";
if(TgtCP[0]) s = s + " creature or player.";
else if(TgtCreature[0]) s = s + " creature.";
else if(TgtPlayer[0]) s = s + " player.";
DamageTgt.setDescription(s);
}
if(!stDesc[0].equals("none")) DamageTgt.setStackDescription(stDesc[0]);
else DamageTgt.setStackDescription(card.getName() + " - deals " + NumDmg[0] + " damage.");
if(TgtCP[0]) DamageTgt.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(DamageTgt,
true, false));
else if(TgtCreature[0]) DamageTgt.setBeforePayMana(CardFactoryUtil.input_targetCreature(DamageTgt));
else if(TgtPlayer[0]) DamageTgt.setBeforePayMana(CardFactoryUtil.input_targetPlayer(DamageTgt));
card.addSpellAbility(DamageTgt);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbDamageTgt = DamageTgt.copy();
bbDamageTgt.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
bbDamageTgt.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbDamageTgt.setIsBuyBackAbility(true);
if (TgtCP[0] == true)
bbDamageTgt.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(bbDamageTgt, true, false));
else if (TgtCreature[0])
bbDamageTgt.setBeforePayMana(CardFactoryUtil.input_targetCreature(bbDamageTgt));
else if (TgtPlayer[0])
bbDamageTgt.setBeforePayMana(CardFactoryUtil.input_targetPlayer(bbDamageTgt));
card.addSpellAbility(bbDamageTgt);
}
}
}// spDamageTgt
//Keyword for spells, that damage all creatures
if (hasKeyword(card, "spDamageAll") != -1)
{
int n = hasKeyword(card, "spDamageAll");
if (n != -1)
{
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
final int NumDam[] = {-1};
final String NumDamX[] = {"none"};
final boolean DmgPlayer[] = {false};
String k[] = parse.split(":");
String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor
// non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
//non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
if (Targets.startsWith("Player")) {
Targets = Targets.replaceFirst("Player,", "");
DmgPlayer[0] = true;
} // if Players are affected they have to be at the start
final String Tgts[] = Targets.split(",");
if (k[2].matches("X"))
{
String x = card.getSVar(k[2]);
if (x.startsWith("Count$"))
{
String kk[] = x.split("\\$");
NumDamX[0] = kk[1];
}
}
else if (k[2].matches("[0-9][0-9]?"))
NumDam[0] = Integer.parseInt(k[2]);
// drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
if (k.length > 3)
{
if (k[3].contains("Drawback$"))
{
String kk[] = k[3].split("\\$");
DrawBack[0] = kk[1];
spDesc[0] = k[4];
}
else
spDesc[0] = k[3];
}
else
spDesc[0] = "cardName deals " + NumDam[0] + " damage to each creature and player.";
final SpellAbility spDmgAll = new Spell(card)
{
private static final long serialVersionUID = -2598054704232863475L;
public int getNumDam()
{
if (NumDam[0] != -1)
return NumDam[0];
if (! NumDamX[0].equals("none"))
return CardFactoryUtil.xCount(card, NumDamX[0]);
return 0;
}
public boolean canPlayAI()
{
int ndam = getNumDam();
if (DmgPlayer[0] && AllZone.Computer_Life.getLife() <= ndam)
return false; // The AI will not kill itself
if (DmgPlayer[0] && AllZone.Human_Life.getLife() <= ndam && AllZone.Computer_Life.getLife() > ndam)
return true; // The AI will kill the human if possible
CardList human = new CardList(AllZone.Human_Play.getCards());
CardList computer = new CardList(AllZone.Computer_Play.getCards());
human = human.getValidCards(Tgts);
human = human.canBeDamagedBy(card);
human = human.getNotKeyword("Indestructible");
human = human.filter(new CardListFilter() {
public boolean addCard(Card c) {
return (c.getKillDamage() <= getNumDam());
}
}); // leaves all creatures that will be destroyed
int humanvalue = CardListUtil.sumCMC(human);
humanvalue += human.size();
humanvalue += CardListUtil.sumAttack(human.getTokens());
// X = total converted mana cost + number of permanents + total power of tokens (Human)
if (!DmgPlayer[0] && AllZone.Computer_Life.getLife() < 7) humanvalue += CardListUtil.sumAttack(human);
// in Low Life Emergency (and not hurting itself) X = X + total power of human creatures
computer = computer.getValidCards(Tgts);
computer = computer.canBeDamagedBy(card);
computer = computer.getNotKeyword("Indestructible");
computer = computer.filter(new CardListFilter() {
public boolean addCard(Card c) {
return (c.getKillDamage() <= getNumDam());
}
}); // leaves all creatures that will be destroyed
int computervalue = CardListUtil.sumCMC(computer);
computervalue += computer.size();
computervalue += CardListUtil.sumAttack(computer.getTokens());
// Y = total converted mana cost + number of permanents + total power of tokens (Computer)
// the computer will play the spell if Y < X - 3
return AllZone.Phase.getPhase().equals(Constant.Phase.Main2) &&
(computervalue < humanvalue - 3);
}
public void resolve()
{
int ndam = getNumDam();
CardList all = new CardList();
all.addAll(AllZone.Human_Play.getCards());
all.addAll(AllZone.Computer_Play.getCards());
all = all.getValidCards(Tgts);
for(int i = 0; i < all.size(); i++) {
if(CardFactoryUtil.canDamage(card, all.get(i))) all.get(i).addDamage(ndam, card);
}
if (DmgPlayer[0] == true) {
AllZone.GameAction.addDamage(Constant.Player.Computer, card, ndam);
AllZone.GameAction.addDamage(Constant.Player.Human, card, ndam);
}
// if (!DrawBack[0].equals("none"))
// CardFactoryUtil.doDrawBack(DrawBack[0], ndam, card.getController(), AllZone.GameAction.getOpponent(card.getController()), null, card, null);
}//resolve()
};//SpellAbility spDmgAll
spDmgAll.setDescription(spDesc[0]);
spDmgAll.setStackDescription(spDesc[0]);
card.clearSpellAbility();
card.addSpellAbility(spDmgAll);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbspDmgAll = spDmgAll.copy();
bbspDmgAll.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
bbspDmgAll.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbspDmgAll.setIsBuyBackAbility(true);
card.addSpellAbility(bbspDmgAll);
}
}
}//spDamageAll
while(hasKeyword(card, "abDamage") != -1) {
int n = hasKeyword(card, "abDamage");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmpCost[] = k[0].replace("abDamage", "").split(" ", 2);
int drawBack = 2;
final Target abTgt = new Target(tmpCost[0]);
if (abTgt.canTgtValid()){
int valid = drawBack;
// Looks like VTSelection is used for the Message box, should improve the message
abTgt.setVTSelection("Select a target: " + k[valid]);
abTgt.setValidTgts(k[valid].split(","));
drawBack++;
}
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true);
final int NumDmg[] = {-1};
final String NumDmgX[] = {"none"};
if(k[1].matches("X")) {
String x = card.getSVar(k[1]);
if(x.startsWith("Count$")) {
String kk[] = x.split("\\$");
NumDmgX[0] = kk[1];
}
}
else if(k[1].matches("[0-9][0-9]?"))
NumDmg[0] = Integer.parseInt(k[1]);
//drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if(k.length > drawBack) {
if(k[drawBack].contains("Drawback$")) {
String kk[] = k[drawBack].split("\\$");
DrawBack[0] = kk[1];
if(k.length > drawBack+1) spDesc[0] = k[drawBack+1];
if(k.length > drawBack+2) stDesc[0] = k[drawBack+2];
} else {
if(k.length > drawBack) spDesc[0] = k[drawBack];
if(k.length > drawBack+1) stDesc[0] = k[drawBack+1];
}
} else {
StringBuilder sb = new StringBuilder();
sb.append(card.getName());
sb.append(" deals " + NumDmg[0] + " damage to ");
sb.append(abTgt.targetString());
spDesc[0] = sb.toString();
stDesc[0] = card.getName() + " -" + sb.toString();
}
spDesc[0] = abCost.toString() + spDesc[0];
// Damage ability starts here
final SpellAbility abDamage = new Ability_Activated(card, abCost, abTgt) {
private static final long serialVersionUID = -7560349014757367722L;
private int damage;
public int getNumDamage() {
if(NumDmg[0] != -1) return NumDmg[0];
if(!NumDmgX[0].equals("none")) return CardFactoryUtil.xCount(card, NumDmgX[0]);
return 0;
}
boolean shouldTgtP() {
PlayerZone compHand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer);
CardList hand = new CardList(compHand.getCards());
if(hand.size() > 7) // anti-discard-at-EOT
return true;
if(AllZone.Human_Life.getLife() - damage < 10) // if damage from this spell would drop the human to less than 10 life
return true;
return false;
}
Card chooseTgtC() {
// Combo alert!!
PlayerZone compy = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
CardList cPlay = new CardList(compy.getCards());
if(cPlay.size() > 0) for(int i = 0; i < cPlay.size(); i++)
if(cPlay.get(i).getName().equals("Stuffy Doll")) return cPlay.get(i);
PlayerZone human = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
CardList hPlay = new CardList(human.getCards());
hPlay = hPlay.filter(new CardListFilter() {
public boolean addCard(Card c) {
// will include creatures already dealt damage
return c.isCreature() && ((c.getNetDefense() + c.getDamage()) <= damage)
&& CardFactoryUtil.canTarget(card, c);
}
});
if(hPlay.size() > 0) {
Card best = hPlay.get(0);
if(hPlay.size() > 1) {
for(int i = 1; i < hPlay.size(); i++) {
Card b = hPlay.get(i);
// choose best overall creature?
if(b.getSpellAbility().length > best.getSpellAbility().length
|| b.getKeyword().size() > best.getKeyword().size()
|| b.getNetAttack() > best.getNetAttack()) best = b;
}
}
return best;
}
return null;
}
@Override
public boolean canPlay(){
return (Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
@Override
public boolean canPlayAI() {
// temporarily disabled until better AI
if (abCost.getSacCost()) return false;
if (abCost.getSubCounter()) return false;
if (abCost.getLifeCost()) return false;
if (!ComputerUtil.canPayCost(this))
return false;
damage = getNumDamage();
Random r = new Random(); // prevent run-away activations
boolean rr = false;
if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
rr = true;
if(abTgt.canTgtCreaturePlayer()) {
if(shouldTgtP()) {
setTargetPlayer(Constant.Player.Human);
return rr;
}
Card c = chooseTgtC();
if(c != null) {
setTargetCard(c);
return rr;
}
}
if(abTgt.canTgtPlayer()/* || TgtOpp[0] == true */) {
setTargetPlayer(Constant.Player.Human);
return rr;
}
if(abTgt.canTgtCreature()) {
Card c = chooseTgtC();
if(c != null) {
setTargetCard(c);
return rr;
}
}
return false;
}
@Override
public void resolve() {
int damage = getNumDamage();
String tgtP = "";
//if(TgtOpp[0] == true) {
// tgtP = AllZone.GameAction.getOpponent(card.getController());
// setTargetPlayer(tgtP);
//}
Card c = getTargetCard();
if(c != null) {
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c)) {
AllZone.GameAction.addDamage(c, card, damage);
tgtP = c.getController();
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], damage,
card.getController(), AllZone.GameAction.getOpponent(card.getController()),
tgtP, card, c, this);
}
} else {
tgtP = getTargetPlayer();
AllZone.GameAction.addDamage(tgtP, card, damage);
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], damage,
card.getController(), AllZone.GameAction.getOpponent(card.getController()),
tgtP, card, null, this);
}
}//resolve()
};//Ability_Activated
abDamage.setDescription(spDesc[0]);
abDamage.setStackDescription(stDesc[0]);
card.addSpellAbility(abDamage);
}
}//abDamageTgt
// Generic destroy target card
if(hasKeyword(card, "spDestroyTgt") != -1) {
int n = hasKeyword(card, "spDestroyTgt");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor
// non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
//non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
final String Tgts[] = Targets.split(",");
String tmpDesc = card.getText().substring(15);
int i = tmpDesc.indexOf(".");
tmpDesc = tmpDesc.substring(0, i);
final String Selec = "Select target " + tmpDesc + " to destroy.";
final boolean NoRegen[] = {false};
final String Drawback[] = {"none"};
if (k.length > 2)
{
if (k[2].equals("NoRegen"))
NoRegen[0] = true;
else if (k[2].startsWith("Drawback$"))
Drawback[0] = k[2];
if (k.length > 3)
{
if (k[3].startsWith("Drawback$"))
Drawback[0] = k[3];
}
if (!Drawback[0].equals("none"))
{
String kk[] = Drawback[0].split("\\$");
Drawback[0] = kk[1];
}
}
card.clearSpellAbility();
final SpellAbility spDstryTgt = new Spell(card) {
private static final long serialVersionUID = 142142142142L;
@Override
public boolean canPlayAI() {
CardList results = new CardList();
CardList choices = getTargets();
choices = choices.filter(new CardListFilter(){
public boolean addCard(Card c)
{
return !c.getKeyword().contains("Indestructible");
}
});
if(choices.size() > 0) {
for(int i = 0; i < Tgts.length; i++) {
if(Tgts[i].startsWith("Artifact")) {
if(CardFactoryUtil.AI_getBestArtifact(choices) != null) results.add(CardFactoryUtil.AI_getBestArtifact(choices));
} else if(Tgts[i].startsWith("Creature")) {
if(CardFactoryUtil.AI_getBestCreature(choices) != null) results.add(CardFactoryUtil.AI_getBestCreature(choices));
} else if(Tgts[i].startsWith("Enchantment")) {
if(CardFactoryUtil.AI_getBestEnchantment(choices, card, true) != null) results.add(CardFactoryUtil.AI_getBestEnchantment(
choices, card, true));
} else if(Tgts[i].startsWith("Land")) {
if(CardFactoryUtil.AI_getBestLand(choices) != null) results.add(CardFactoryUtil.AI_getBestLand(choices));
} else if(Tgts[i].startsWith("Permanent")) {
if(CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true) != null) results.add(CardFactoryUtil.AI_getMostExpensivePermanent(
choices, card, true));
}
}
}
if(results.size() > 0) {
results.shuffle();
setTargetCard(results.get(0));
return true;
}
return false;
}
CardList getTargets() {
CardList tmpList = new CardList();
tmpList.addAll(AllZone.Human_Play.getCards());
tmpList = tmpList.getValidCards(Tgts);
tmpList = tmpList.getTargetableCards(card);
return tmpList;
}
@Override
public void resolve()
{
Card tgtC = getTargetCard();
if(AllZone.GameAction.isCardInPlay(tgtC) && CardFactoryUtil.canTarget(card, tgtC))
{
if(NoRegen[0])
AllZone.GameAction.destroyNoRegeneration(tgtC);
else
AllZone.GameAction.destroy(tgtC);
if (!Drawback[0].equals("none"))
CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtC.getController(), card, tgtC, this);
}
}
}; //SpDstryTgt
Input InGetTarget = CardFactoryUtil.input_targetValid(spDstryTgt, Tgts, Selec);
spDstryTgt.setBeforePayMana(InGetTarget);
spDstryTgt.setDescription(card.getSpellText());
card.setText("");
card.setSVar("PlayMain1", "TRUE");
card.addSpellAbility(spDstryTgt);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbDstryTgt = spDstryTgt.copy();
bbDstryTgt.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
StringBuilder sb = new StringBuilder();
sb.append("Buyback ").append(bbCost).append(" (You may pay an additional ").append(bbCost);
sb.append(" as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbDstryTgt.setDescription(sb.toString());
// bbDstryTgt.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbDstryTgt.setIsBuyBackAbility(true);
bbDstryTgt.setBeforePayMana(CardFactoryUtil.input_targetValid(bbDstryTgt, Tgts, Selec));
card.addSpellAbility(bbDstryTgt);
}
}//spDestroyTgt
// Generic destroy target ___ activated ability
if (hasKeyword(card, "abDestroyTgtV") != -1)
{
int n = hasKeyword(card, "abDestroyTgtV");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmpCost = k[0].substring(13);
final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName(), true);
final Target tgtDstryTgt = new Target("TgtV");
final String Tgts[] = k[1].split(",");
tgtDstryTgt.setValidTgts(Tgts);
final boolean NoRegen[] = {false};
final String Drawback[] = {"none"};
final String spDesc[] = {"none"};
if (k[2].equals("NoRegen"))
{
NoRegen[0] = true;
if (k.length > 3)
{
if (k[3].startsWith("Drawback$"))
Drawback[0] = k[3].substring(9);
else
spDesc[0] = k[3];
}
}
else if (k[2].startsWith("Drawback$"))
{
Drawback[0] = k[2].substring(9);
if (k.length > 3)
spDesc[0] = k[3];
}
else
spDesc[0] = k[2];
String tmpDesc = spDesc[0].substring(15);
int i = tmpDesc.indexOf(".");
tmpDesc = tmpDesc.substring(0, i);
//final String Selec = "Select target " + tmpDesc + " to destroy.";
tgtDstryTgt.setVTSelection("Select target " + tmpDesc + " to destroy.");
spDesc[0] = abCost.toString() + spDesc[0];
final SpellAbility AbDstryTgt = new Ability_Activated(card, abCost, tgtDstryTgt)
{
private static final long serialVersionUID = -141142183348756081L;
@Override
public boolean canPlayAI() {
if (!ComputerUtil.canPayCost(this))
return false;
CardList hCards = getTargets();
hCards = hCards.filter(new CardListFilter(){
public boolean addCard(Card c)
{
return !c.getKeyword().contains("Indestructible");
}
});
Random r = new Random();
boolean rr = false;
if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
rr = true;
if(hCards.size() > 0) {
Card c = null;
CardList dChoices = new CardList();
for(int i = 0; i < Tgts.length; i++) {
if (Tgts[i].startsWith("Creature"))
{
c = CardFactoryUtil.AI_getBestCreature(hCards);
if (c != null)
dChoices.add(c);
}
CardListUtil.sortByTextLen(hCards);
dChoices.add(hCards.get(0));
CardListUtil.sortCMC(hCards);
dChoices.add(hCards.get(0));
}
c = dChoices.get(CardUtil.getRandomIndex(dChoices));
setTargetCard(c);
return rr;
}
return false;
}
CardList getTargets() {
CardList tmpList = new CardList();
tmpList.addAll(AllZone.Human_Play.getCards());
tmpList = tmpList.getValidCards(Tgts);
tmpList = tmpList.getTargetableCards(card);
return tmpList;
}
@Override
public boolean canPlay(){
return (Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
@Override
public void resolve()
{
Card tgtC = getTargetCard();
if(AllZone.GameAction.isCardInPlay(tgtC) && CardFactoryUtil.canTarget(card, tgtC))
{
if(NoRegen[0])
AllZone.GameAction.destroyNoRegeneration(tgtC);
else
AllZone.GameAction.destroy(tgtC);
if (!Drawback[0].equals("none"))
CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtC.getController(), card, tgtC, this);
}
}
}; //AbDstryTgt
AbDstryTgt.setDescription(spDesc[0]);
card.addSpellAbility(AbDstryTgt);
card.setSVar("PlayMain1", "TRUE");
}
// Generic enters the battlefield destroy target
if (hasKeyword(card, "etbDestroyTgt") != -1)
{
int n = hasKeyword(card, "etbDestroyTgt");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean May[] = {false};
if (k[0].contains("May"))
May[0] = true;
String Targets = k[1];
final String Tgts[] = Targets.split(",");
String tmpDesc = card.getSpellText();
int i = tmpDesc.indexOf("destroy target ");
tmpDesc = tmpDesc.substring(i + 15);
i = tmpDesc.indexOf(".");
tmpDesc = tmpDesc.substring(0, i);
final String Selec = "Select target " + tmpDesc + " to destroy.";
final boolean NoRegen[] = {false};
final String Drawback[] = {"none"};
if (k.length > 2)
{
if (k[2].equals("NoRegen"))
{
NoRegen[0] = true;
if (k.length > 3)
Drawback[0] = k[3];
}
else
Drawback[0] = k[2];
}
if (!Drawback[0].equals("none"))
{
String kk[] = Drawback[0].split("\\$");
Drawback[0] = kk[1];
}
final boolean Evoke[] = {false};
if (card.getSVar("Evoke").length() > 0)
Evoke[0] = true;
card.setSVar("PlayMain1", "TRUE");
card.clearSpellAbility();
// over-rides the default Spell_Permanent
// enables the AI to play the card when appropriate
SpellAbility spETBDestroyTgt = new Spell_Permanent(card)
{
private static final long serialVersionUID = -1148528222969323318L;
@Override
public boolean canPlayAI()
{
Random r = new Random();
CardList hCards = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards());
hCards = hCards.getValidCards(Tgts);
hCards = hCards.getTargetableCards(card);
if (hCards.size() > 0)
return true;
CardList cCards = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards());
cCards = cCards.getValidCards(Tgts);
cCards = cCards.getTargetableCards(card);
if (cCards.size() == 0)
return true;
else
{
if (r.nextInt(100) > 67)
return true;
}
return false;
}
};
card.addSpellAbility(spETBDestroyTgt);
// performs the destruction
final SpellAbility saDestroyTgt = new Ability(card, "0")
{
@Override
public void resolve()
{
Card c = getTargetCard();
if (c == null)
return;
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c))
{
if(c.isToken())
AllZone.getZone(c).remove(c);
else
AllZone.GameAction.destroy(c);
if (!Drawback[0].equals("none"))
CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), c.getController(), card, c, this);
}
}
};
saDestroyTgt.setStackDescription(card.getName() + " - destroy target " + Selec + ".");
// when the card enters the battlefield, enable the human to target
// or the AI decides on a target
Command etbDestroyTgt = new Command()
{
private static final long serialVersionUID = 9072052875006010497L;
public void execute()
{
CardList hCards = new CardList(AllZone.Human_Play.getCards());
CardList cCards = new CardList(AllZone.Computer_Play.getCards());
hCards = hCards.getValidCards(Tgts);
hCards = hCards.getTargetableCards(card);
cCards = cCards.getValidCards(Tgts);
cCards = cCards.getTargetableCards(card);
if(hCards.size() > 0 || cCards.size() > 0)
{
if (card.getController().equals(Constant.Player.Human))
{
Input inDT = CardFactoryUtil.input_targetValid(saDestroyTgt, Tgts, Selec);
AllZone.InputControl.setInput(inDT);
if (May[0] == true)
ButtonUtil.enableOnlyCancel();
else
ButtonUtil.disableAll();
}
else
{
Card c = new Card();
CardList dChoices = new CardList();
if(hCards.size() > 0)
{
for (int i=0; i<Tgts.length; i++)
{
if (Tgts[i].startsWith("Creature"))
{
c = CardFactoryUtil.AI_getBestCreature(hCards);
if (c != null)
dChoices.add(c);
}
CardListUtil.sortByTextLen(hCards);
dChoices.add(hCards.get(0));
CardListUtil.sortCMC(hCards);
dChoices.add(hCards.get(0));
}
c = dChoices.get(CardUtil.getRandomIndex(dChoices));
saDestroyTgt.setTargetCard(c);
AllZone.Stack.add(saDestroyTgt);
}
else if (cCards.size() > 0 && May[0] == false)
{
for (int i=0; i<Tgts.length; i++)
{
if (Tgts[i].startsWith("Creature"))
{
c = CardFactoryUtil.AI_getWorstCreature(cCards);
if (c != null)
dChoices.add(c);
}
CardListUtil.sortByTextLen(cCards);
dChoices.add(cCards.get(cCards.size() - 1));
CardListUtil.sortCMC(cCards);
dChoices.add(cCards.get(cCards.size() - 1));
}
c = dChoices.get(CardUtil.getRandomIndex(dChoices));
saDestroyTgt.setTargetCard(c);
AllZone.Stack.add(saDestroyTgt);
}
}
}
}
};
card.addComesIntoPlayCommand(etbDestroyTgt);
// handle SVar:Evoke:{cost}
if (Evoke[0] == true)
{
String EvCost = card.getSVar("Evoke");
SpellAbility evDestroyTgt = new Spell_Evoke(card, EvCost)
{
private static final long serialVersionUID = 5261598836419831953L;
@Override
public boolean canPlayAI() {
return false;
}
};
card.addSpellAbility(evDestroyTgt);
}
} // etbDestoryTgt
// Generic destroy all card
if(hasKeyword(card, "spDestroyAll") != -1) {
int n = hasKeyword(card, "spDestroyAll");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor
// non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
//non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
final String Tgts[] = Targets.split(",");
final boolean NoRegen[] = {false};
final String Drawback[] = {"none"};
if (k.length > 2)
{
if (k[2].equals("NoRegen"))
NoRegen[0] = true;
else if (k[2].startsWith("Drawback$"))
Drawback[0] = k[2];
if (k.length > 3)
{
if (k[3].startsWith("Drawback$"))
Drawback[0] = k[3];
}
if (!Drawback[0].equals("none"))
{
String kk[] = Drawback[0].split("\\$");
Drawback[0] = kk[1];
}
}
card.clearSpellAbility();
final SpellAbility spDstryAll = new Spell(card) {
private static final long serialVersionUID = 132554543614L;
@Override
public boolean canPlayAI() {
CardList human = new CardList(AllZone.Human_Play.getCards());
CardList computer = new CardList(AllZone.Computer_Play.getCards());
human = human.getValidCards(Tgts);
human = human.getNotKeyword("Indestructible");
int humanvalue = CardListUtil.sumCMC(human);
humanvalue += human.size();
humanvalue += CardListUtil.sumAttack(human.getTokens());
humanvalue += human.getType("Land").size(); // X = total converted mana cost + number of permanents + number of lands + total power of tokens (Human)
if (AllZone.Computer_Life.getLife() < 7) { humanvalue += CardListUtil.sumAttack(human); } // in Low Life Emergency X = X + total power of human creatures
computer = computer.getValidCards(Tgts);
computer = computer.getNotKeyword("Indestructible");
int computervalue = CardListUtil.sumCMC(computer);
computervalue += computer.size();
computervalue += CardListUtil.sumAttack(computer.getTokens());
computervalue += computer.getType("Land").size(); // Y = total converted mana cost + number of permanents + number of lands + total power of tokens (Computer)
// the computer will play the spell if Y < X - 3
return AllZone.Phase.getPhase().equals(Constant.Phase.Main2) &&
(computervalue < humanvalue - 3);
}
@Override
public void resolve() {
CardList all = new CardList();
all.addAll(AllZone.Human_Play.getCards());
all.addAll(AllZone.Computer_Play.getCards());
all = all.getValidCards(Tgts);
CardListUtil.sortByIndestructible(all);
CardListUtil.sortByDestroyEffect(all);
for(int i = 0; i < all.size(); i++) {
Card c = all.get(i);
if(NoRegen[0])
AllZone.GameAction.destroyNoRegeneration(c);
else
AllZone.GameAction.destroy(c);
}
if (!Drawback[0].equals("none"))
{
// drawbacks for DestroyAll spells usually involve the
// number of permanents that were actually destroyed
int nDestroyed = 0;
CardList afterAll = new CardList();
afterAll.addAll(AllZone.Human_Play.getCards());
afterAll.addAll(AllZone.Computer_Play.getCards());
afterAll = afterAll.getValidCards(Tgts);
ArrayList<Integer> slD = new ArrayList<Integer>();
for (int i=0; i<afterAll.size(); i++)
slD.add(afterAll.get(i).getUniqueNumber());
for (int i=0; i<all.size(); i++)
{
if (!slD.contains(all.get(i).getUniqueNumber()))
nDestroyed++;
}
Log.error("nDestroyed: " + nDestroyed);
CardFactoryUtil.doDrawBack(Drawback[0], nDestroyed, card.getController(), AllZone.GameAction.getOpponent(card.getController()), null, card, null, this);
}
}// resolve()
}; //SpDstryAll
spDstryAll.setDescription(card.getSpellText());
card.setText("");
card.addSpellAbility(spDstryAll);
}//spDestroyAll
// Generic bounce target card
if(hasKeyword(card, "spBounceTgt") != -1) {
int n = hasKeyword(card, "spBounceTgt");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor
// non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
//non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
final String Tgts[] = Targets.split(",");
final String Destination = k[2];
final String Drawback[] = {"none"};
if (k.length > 3)
{
if (k[3].contains("Drawback$")){
String kk[] = k[3].split("\\$");
Drawback[0] = kk[1];
}
}
final String Selec[] = {"Select a target "};
String tgtType = "";
if (Destination.equals("Hand"))
{
tgtType = card.getSpellText().substring("Return target ".length());
int i = tgtType.indexOf(" to its owner's hand.");
tgtType = tgtType.substring(0, i);
Selec[0] += tgtType + " to return.";
}
else if (Destination.equals("Exile"))
{
tgtType = card.getSpellText().substring("Exile target ".length());
int i = tgtType.indexOf(".");
tgtType = tgtType.substring(0, i);
Selec[0] += tgtType + " to exile.";
}
else if (Destination.equals("TopofLibrary"))
{
tgtType = card.getSpellText().substring("Put target ".length());
int i = tgtType.indexOf(" on top of its owner's library.");
tgtType = tgtType.substring(0, i);
Selec[0] += tgtType + " to put on top of the library.";
}
else if (Destination.equals("BottomofLibrary"))
{
tgtType = card.getSpellText().substring("Put target ".length());
int i = tgtType.indexOf(" on the bottom of its owner's library.");
tgtType = tgtType.substring(0, i);
Selec[0] += tgtType + " to put on the bottom of the library.";
}
else
{
Selec[0] = card.getSpellText();
}
card.clearSpellAbility();
final SpellAbility spBnceTgt = new Spell(card) {
private static final long serialVersionUID = 152897134770L;
@Override
public boolean canPlayAI() {
if (AllZone.Phase.getTurn() <= 3) return false;
CardList results = new CardList();
CardList choices = getTargets();
if(choices.size() > 0) {
for(int i = 0; i < Tgts.length; i++) {
if(Tgts[i].startsWith("Artifact")) {
if(CardFactoryUtil.AI_getBestArtifact(choices) != null) results.add(CardFactoryUtil.AI_getBestArtifact(choices));
} else if(Tgts[i].startsWith("Creature")) {
if(CardFactoryUtil.AI_getBestCreature(choices) != null) results.add(CardFactoryUtil.AI_getBestCreature(choices));
} else if(Tgts[i].startsWith("Enchantment")) {
if(CardFactoryUtil.AI_getBestEnchantment(choices, card, true) != null) results.add(CardFactoryUtil.AI_getBestEnchantment(
choices, card, true));
} else if(Tgts[i].startsWith("Land")) {
if(CardFactoryUtil.AI_getBestLand(choices) != null) results.add(CardFactoryUtil.AI_getBestLand(choices));
} else if(Tgts[i].startsWith("Permanent")) {
if(CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true) != null) results.add(CardFactoryUtil.AI_getMostExpensivePermanent(
choices, card, true));
}
}
}
if(results.size() > 0) {
results.shuffle();
setTargetCard(results.get(0));
return true;
}
return false;
}
CardList getTargets() {
CardList tmpList = new CardList();
tmpList.addAll(AllZone.Human_Play.getCards());
tmpList = tmpList.getValidCards(Tgts);
tmpList = tmpList.getTargetableCards(card);
return tmpList;
}
@Override
public void resolve()
{
Card tgtC = getTargetCard();
if(AllZone.GameAction.isCardInPlay(tgtC)
&& CardFactoryUtil.canTarget(card, tgtC))
{
if(getTargetCard().isToken())
AllZone.getZone(tgtC).remove(tgtC);
else
{
if(Destination.equals("TopofLibrary"))
AllZone.GameAction.moveToTopOfLibrary(tgtC);
else if(Destination.equals("BottomofLibrary"))
AllZone.GameAction.moveToBottomOfLibrary(tgtC);
else if(Destination.equals("ShuffleIntoLibrary"))
{
AllZone.GameAction.moveToTopOfLibrary(tgtC);
AllZone.GameAction.shuffle(tgtC.getOwner());
}
else if(Destination.equals("Exile"))
AllZone.GameAction.removeFromGame(tgtC);
else if(Destination.equals("Hand"))
{
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, tgtC.getOwner());
AllZone.GameAction.moveTo(hand, tgtC);
}
}
if (!Drawback[0].equals("none"))
CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtC.getController(), card, tgtC, this);
}
}
}; //SpBnceTgt
Input InGetTarget = CardFactoryUtil.input_targetValid(spBnceTgt, Tgts, Selec[0]);
card.setSVar("PlayMain1", "TRUE");
spBnceTgt.setBeforePayMana(InGetTarget);
spBnceTgt.setDescription(card.getSpellText());
card.setText("");
card.addSpellAbility(spBnceTgt);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbBnceTgt = spBnceTgt.copy();
bbBnceTgt.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
StringBuilder sb = new StringBuilder();
sb.append("Buyback ").append(bbCost).append(" (You may pay an additional ").append(bbCost);
sb.append(" as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbBnceTgt.setDescription(sb.toString());
// bbBnceTgt.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbBnceTgt.setIsBuyBackAbility(true);
bbBnceTgt.setBeforePayMana(CardFactoryUtil.input_targetValid(bbBnceTgt, Tgts, Selec[0]));
card.addSpellAbility(bbBnceTgt);
}
}//spBounceTgt
// Generic bounce when enters the battlefield
if (hasKeyword(card, "etbBounceTgt") != -1)
{
int n = hasKeyword(card, "etbBounceTgt");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean May[] = {false};
if (k[0].contains("May"))
May[0] = true;
final String Tgts[] = k[1].split(",");
final String Destination = k[2];
final String Selec[] = {"Select a target "};
String tgtType = card.getSpellText();
int i = 0;
if (Destination.equals("Hand"))
{
i = tgtType.indexOf("return target ");
tgtType = tgtType.substring(i + "return target ".length());
i = tgtType.indexOf(" to its owner's hand.");
tgtType = tgtType.substring(0, i);
Selec[0] += tgtType + " to return.";
}
else if (Destination.equals("Exile"))
{
i = tgtType.indexOf("exile target ");
tgtType = tgtType.substring(i + "exile target ".length());
i = tgtType.indexOf(".");
tgtType = tgtType.substring(0, i);
Selec[0] += tgtType + " to exile.";
}
else if (Destination.equals("TopofLibrary"))
{
i = tgtType.indexOf("put target ".length());
tgtType = tgtType.substring(i + "put target ".length());
i = tgtType.indexOf(" on top of its owner's library.");
tgtType = tgtType.substring(0, i);
Selec[0] += tgtType + " to put on top of the library.";
}
else
{
Selec[0] = card.getSpellText();
}
final String Drawback[] = {"none"};
if (k.length > 3)
{
if (k[3].startsWith("Drawback"))
Drawback[0] = k[3].substring("Drawback$".length());
}
final boolean Evoke[] = {false};
if (card.getSVar("Evoke").length() > 0)
Evoke[0] = true;
card.setSVar("PlayMain1", "TRUE");
card.clearSpellAbility();
// over-rides the default Spell_Permanent
// enables the AI to play the card when appropriate
SpellAbility spETBBounceTgt = new Spell_Permanent(card)
{
private static final long serialVersionUID = -1548526222769333358L;
@Override
public boolean canPlayAI()
{
Random r = new Random();
CardList hCards = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Human).getCards());
hCards = hCards.getValidCards(Tgts);
hCards = hCards.getTargetableCards(card);
if (hCards.size() > 0)
return true;
CardList cCards = new CardList(AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer).getCards());
cCards = cCards.getValidCards(Tgts);
cCards = cCards.getTargetableCards(card);
if (cCards.size() == 0)
return true;
else
{
if (r.nextInt(100) > 67)
return true;
}
return false;
}
};
card.addSpellAbility(spETBBounceTgt);
// performs the bounce
final SpellAbility saBounceTgt = new Ability(card, "0")
{
@Override
public void resolve()
{
Card tgtC = getTargetCard();
if (tgtC == null)
return;
if (AllZone.GameAction.isCardInPlay(tgtC) && CardFactoryUtil.canTarget(card, tgtC))
{
if (tgtC.isToken())
AllZone.getZone(tgtC).remove(tgtC);
else
{
if (Destination.equals("TopofLibrary"))
AllZone.GameAction.moveToTopOfLibrary(tgtC);
else if (Destination.equals("ShuffleIntoLibrary"))
{
AllZone.GameAction.moveToTopOfLibrary(tgtC);
AllZone.GameAction.shuffle(tgtC.getOwner());
}
else if (Destination.equals("Exile"))
AllZone.GameAction.removeFromGame(tgtC);
else if (Destination.equals("Hand"))
AllZone.GameAction.moveToHand(tgtC);
}
if (!Drawback[0].equals("none"))
CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtC.getController(), card, tgtC, this);
}
}
}; //saBounceTgt
saBounceTgt.setStackDescription(card.getName() + " - bounce target.");
// when the card enters the battlefield, enable the human to target
// or the AI decides on a target
Command etbBounceTgt = new Command()
{
private static final long serialVersionUID = 829702746298938287L;
public void execute()
{
CardList hCards = new CardList(AllZone.Human_Play.getCards());
CardList cCards = new CardList(AllZone.Computer_Play.getCards());
hCards = hCards.getValidCards(Tgts);
hCards = hCards.getTargetableCards(card);
cCards = cCards.getValidCards(Tgts);
cCards = cCards.getTargetableCards(card);
if (hCards.size() > 0 || cCards.size() > 0)
{
if (card.getController().equals(Constant.Player.Human))
{
Input inDT = CardFactoryUtil.input_targetValid(saBounceTgt, Tgts, Selec[0]);
AllZone.InputControl.setInput(inDT);
if (May[0] == true)
ButtonUtil.enableOnlyCancel();
else
ButtonUtil.disableAll();
}
else
{
Card c = new Card();
CardList dChoices = new CardList();
if (hCards.size() > 0)
{
for (int i=0; i<Tgts.length; i++)
{
if (Tgts[i].startsWith("Creature"))
{
c = CardFactoryUtil.AI_getBestCreature(hCards);
if (c != null)
dChoices.add(c);
}
CardListUtil.sortByTextLen(hCards);
dChoices.add(hCards.get(0));
CardListUtil.sortCMC(hCards);
dChoices.add(hCards.get(0));
}
c = dChoices.get(CardUtil.getRandomIndex(dChoices));
saBounceTgt.setTargetCard(c);
AllZone.Stack.add(saBounceTgt);
}
else if (cCards.size() > 0 && May[0] == false)
{
for (int i=0; i<Tgts.length; i++)
{
if (Tgts[i].startsWith("Creature"))
{
c = CardFactoryUtil.AI_getWorstCreature(cCards);
if (c != null)
dChoices.add(c);
}
CardListUtil.sortByTextLen(cCards);
dChoices.add(cCards.get(cCards.size() - 1));
CardListUtil.sortCMC(cCards);
dChoices.add(cCards.get(cCards.size() - 1));
}
c = dChoices.get(CardUtil.getRandomIndex(dChoices));
saBounceTgt.setTargetCard(c);
AllZone.Stack.add(saBounceTgt);
}
}
}
}
}; // etbBounceTgt
card.addComesIntoPlayCommand(etbBounceTgt);
// handle SVar:Evoke:{cost}
if (Evoke[0] == true)
{
String EvCost = card.getSVar("Evoke");
SpellAbility evBounceTgt = new Spell_Evoke(card, EvCost)
{
private static final long serialVersionUID = 865327909209183746L;
@Override
public boolean canPlayAI() {
return false;
}
};
card.addSpellAbility(evBounceTgt);
}
} // etbBounceTgt
// Generic bounce all card
if(hasKeyword(card, "spBounceAll") != -1) {
int n = hasKeyword(card, "spBounceAll");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor
// non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
//non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
final String Tgts[] = Targets.split(",");
final String Destination = k[2];
card.clearSpellAbility();
final SpellAbility spBnceAll = new Spell(card) {
private static final long serialVersionUID = 897326872601L;
@Override
public boolean canPlayAI() {
CardList human = new CardList(AllZone.Human_Play.getCards());
CardList computer = new CardList(AllZone.Computer_Play.getCards());
human = human.getValidCards(Tgts);
int humanvalue = CardListUtil.sumCMC(human);
humanvalue += human.getType("Land").size();
humanvalue += CardListUtil.sumAttack(human.getTokens()); // X = total converted mana cost + number of lands c (Human)
if(!Destination.equals("Hand")) humanvalue += human.size(); // if the Destination is not Hand card advantage counts
if(Destination.equals("Hand")) humanvalue += CardListUtil.sumDefense(human.getTokens()); // if the Destination is Hand tokens are more important
if (AllZone.Computer_Life.getLife() < 7) { humanvalue += CardListUtil.sumAttack(human); } // in Low Life Emergency X = X + total power of human creatures
computer = computer.getValidCards(Tgts);
int computervalue = CardListUtil.sumCMC(computer);
computervalue += computer.getType("Land").size();
computervalue += CardListUtil.sumAttack(computer.getTokens()); // Y = total converted mana cost + number of lands + total power of tokens (Computer)
if(!Destination.equals("Hand")) computervalue += computer.size(); // if the Destination is not Hand card advantage counts
if(Destination.equals("Hand")) computervalue += CardListUtil.sumDefense(computer.getTokens()); // if the Destination is Hand tokens are more important
// the computer will play the spell if Y < X - 2
return AllZone.Phase.getPhase().equals(Constant.Phase.Main2) &&
(computervalue < humanvalue - 2);
}
@Override
public void resolve() {
CardList all = new CardList();
all.addAll(AllZone.Human_Play.getCards());
all.addAll(AllZone.Computer_Play.getCards());
all = all.getValidCards(Tgts);
for(int i = 0; i < all.size(); i++) {
Card c = all.get(i);
if(c.isToken()) AllZone.getZone(c).remove(c);
else {
if(Destination.equals("TopofLibrary")) AllZone.GameAction.moveToTopOfLibrary(c);
else if(Destination.equals("BottomofLibrary")) AllZone.GameAction.moveToBottomOfLibrary(c);
else if(Destination.equals("ShuffleIntoLibrary")) {
AllZone.GameAction.moveToTopOfLibrary(c);
AllZone.GameAction.shuffle(c.getOwner());
}
else if(Destination.equals("Exile")) AllZone.GameAction.removeFromGame(c);
else if(Destination.equals("Hand")) {
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, c.getOwner());
AllZone.GameAction.moveTo(hand, c);
}
}
}
}// resolve()
}; //SpBnceAll
spBnceAll.setDescription(card.getSpellText());
card.setText("");
card.addSpellAbility(spBnceAll);
}//spBounceAll
/**
* Generic return target card(s) from graveyard to Hand or Battlefield cards
* spReturnTgt:{Num Cards/Parameters}:{Type}:{To Zone}:{DrawBack}:{Spell Desc}
*
* DrawBack and Buyback is not yet implemented.
*/
if (hasKeyword(card, "spReturnTgt") != -1) {
int n = hasKeyword(card, "spReturnTgt");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean returnUpTo[] = {false};
String np[] = k[1].split("/");
final int numCardsToReturn = Integer.parseInt(np[0]);
if (np.length > 1) {
if (np[1].equals("UpTo")) {
returnUpTo[0] = true;
}
}
// Artifact, Creature, Enchantment, Land, Permanent, Instant, Sorcery
// White, Blue, Black, Red, Green, Colorless, MultiColor
// non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
// non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
String Targets = k[2];
final String Tgts[] = Targets.split(",");
final String Destination = k[3];
String desc = "";
final String Drawback[] = {"none"};
if (k.length > 4) {
if (k[4].contains("Drawback$")){
String kk[] = k[4].split("\\$");
Drawback[0] = kk[1];
} else {
desc = k[4];
}
}
if (k.length > 5) {
desc = k[5];
}
card.clearSpellAbility();
final SpellAbility spRtrnTgt = new Spell(card) {
private static final long serialVersionUID = 7970018872459137897L;
@Override
public boolean canPlay() {
if (returnUpTo[0]) return true;
return getGraveyardList().size() >= numCardsToReturn;
}
@Override
public boolean canPlayAI() {
if (AllZone.Phase.getTurn() <= 3) return false;
CardList results = new CardList();
CardList choices = getGraveyardList();
if (choices.size() > 0) {
for (int nctr = 0; nctr < numCardsToReturn; nctr ++) {
for (int i = 0; i < Tgts.length; i++) {
if (Tgts[i].startsWith("Artifact")) {
if (CardFactoryUtil.AI_getBestArtifact(choices) != null) {
Card c = CardFactoryUtil.AI_getBestArtifact(choices);
results.add(c);
choices.remove(c);
}
} else if (Tgts[i].startsWith("Creature")) {
if (CardFactoryUtil.AI_getBestCreature(choices) != null) {
Card c = CardFactoryUtil.AI_getBestCreature(choices);
results.add(c);
choices.remove(c);
}
} else if (Tgts[i].startsWith("Enchantment")) {
if (CardFactoryUtil.AI_getBestEnchantment(choices, card, true) != null) {
Card c = CardFactoryUtil.AI_getBestEnchantment(choices, card, true);
results.add(c);
choices.remove(c);
}
} else if (Tgts[i].startsWith("Land")) {
if (CardFactoryUtil.AI_getBestLand(choices) != null) {
Card c = CardFactoryUtil.AI_getBestLand(choices);
results.add(c);
choices.remove(c);
}
} else if (Tgts[i].startsWith("Permanent")) {
if (CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true) != null) {
Card c = CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true);
results.add(c);
choices.remove(c);
}
} else if (Tgts[i].startsWith("Instant")) {
if (CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true) != null) {
// Card c = CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true);
Card c = CardFactoryUtil.getRandomCard(choices);
results.add(c);
choices.remove(c);
}
} else if (Tgts[i].startsWith("Sorcery")) {
if (CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true) != null) {
// Card c = CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true);
Card c = CardFactoryUtil.getRandomCard(choices);
results.add(c);
choices.remove(c);
}
} else {
if (CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true) != null) {
// Card c = CardFactoryUtil.AI_getMostExpensivePermanent(choices, card, true);
Card c = CardFactoryUtil.getRandomCard(choices);
results.add(c);
choices.remove(c);
}
}
}// for i
}// for nctr
}// if choices
if (results.size() >= numCardsToReturn) {
results.shuffle();
CardList targets = new CardList();
for (int i = 0; i < numCardsToReturn; i++) {
targets.add(results.get(i));
}
setTargetList(targets);
return true;
}
return false;
}// canPlayAI()
@Override
public void resolve() {
CardList targets = getTargetList();
PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController());
String player = card.getController();
for (Card c:targets) {
if (AllZone.GameAction.isCardInZone(c, grave)) {
if (Destination.equals("Hand")) {
PlayerZone zone = AllZone.getZone(Constant.Zone.Hand, player);
AllZone.GameAction.moveTo(zone, c);
}
else if (Destination.equals("Battlefield")) {
PlayerZone zone = AllZone.getZone(Constant.Zone.Play, player);
AllZone.GameAction.moveTo(zone, c);
}
else if (Destination.equals("TopofLibrary")) {
// PlayerZone zone = AllZone.getZone(Constant.Zone.Play, player);
AllZone.GameAction.moveToTopOfLibrary(c);
}
}
}
}// resolve()
CardList getGraveyardList() {
String player = card.getController();
PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player);
CardList list = new CardList(grave.getCards());
list = list.getValidCards(Tgts);
// AI will not use a Boggart Birth Rite to return a Boggart Birth Rite.
// In testing the AI targeted a Sage's Knowledge with a Deja Vu.
// Fixed this by having AI pick a random Instant or Sorcery
// rather than picking the card with highest casting cost.
if (card.getController().equals(Constant.Player.Computer)) {
list = list.getNotName(card.getName());
if (Destination.equals("Battlefield")) {
list = list.getNotKeyword("At the beginning of the end step, destroy CARDNAME.");
list = list.getNotKeyword("At the beginning of the end step, exile CARDNAME.");
list = list.getNotKeyword("At the beginning of the end step, sacrifice CARDNAME.");
}
/* // I failed to solve the problem above with this code.
CardList tmp = list;
for (int i = 0; i < tmp.size(); i++) {
ArrayList<String> kw = tmp.get(i).getKeyword();
for (int j = 0; j < kw.size(); j++) {
if (kw.get(j).toString().startsWith("spReturnTgt")) {
list.remove(kw.get(j));
}
}
}
*/
}
return list;
}// getGraveyardList()
};// spRtrnTgt
Input target = new Input() {
private static final long serialVersionUID = 816838038180106359L;
@Override
public void showMessage() {
CardList grave = getGraveyardList();
CardList targets = new CardList();
if (returnUpTo[0]) {
for (int i = 0; i < numCardsToReturn; i++) {
if (grave.size() > 0) {
Object o = AllZone.Display.getChoiceOptional("Select a card", grave.toArray());
if (o == null) break;
Card c = (Card) o;
targets.add(c);
grave.remove(c);
}
}
} else if (grave.size() > numCardsToReturn) {
for (int i = 0; i < numCardsToReturn; i++) {
Object o = AllZone.Display.getChoice("Select a card", grave.toArray());
Card c = (Card) o;
targets.add(c);
grave.remove(c);
}
} else if (grave.size() == numCardsToReturn) {
targets = grave;
}
if (targets.size() > 0) {
spRtrnTgt.setTargetList(targets);
stopSetNext(new Input_PayManaCost(spRtrnTgt));
} else stop();
}// showMessage()
public CardList getGraveyardList() {
CardList list = new CardList();
PlayerZone zone = AllZone.getZone(Constant.Zone.Graveyard, card.getController());
list.addAll(zone.getCards());
list = list.getValidCards(Tgts);
return list;
}
};// Input
if (desc.length() > 0) {
spRtrnTgt.setDescription(desc);
}
spRtrnTgt.setBeforePayMana(target);
card.addSpellAbility(spRtrnTgt);
if (Destination.equals("Hand")) {
card.setSVar("PlayMain1", "TRUE");
}
}// spReturnTgt
// Generic Tutor cards
if(hasKeyword(card, "spTutor") != -1) {
int n = hasKeyword(card, "spTutor");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String Targets = k[1]; // Artifact, Creature, Enchantment, Land, Permanent, White, Blue, Black, Red, Green, Colorless, MultiColor
// non-Artifact, non-Creature, non-Enchantment, non-Land, non-Permanent,
//non-White, non-Blue, non-Black, non-Red, non-Green, non-Colorless, non-MultiColor
final String Tgts[] = Targets.split(",");
final String Destination = k[2];
card.clearSpellAbility();
final SpellAbility spTtr = new Spell(card) {
private static final long serialVersionUID = 209109273165L;
@Override
public boolean canPlayAI() {
CardList list = AllZoneUtil.getPlayerCardsInLibrary(Constant.Player.Computer);
list = list.getValidCards(Tgts);
if (list.size() > 0) return true;
return false;
}
@Override
public void resolve() {
String player = card.getController();
if(player.equals(Constant.Player.Human)) humanResolve();
else computerResolve();
}
public void computerResolve() {
CardList list = AllZoneUtil.getPlayerCardsInLibrary(Constant.Player.Computer);
list = list.getValidCards(Tgts);
if(list.size() != 0) {
//comp will just grab the first one it finds, but tries to avoid another copy of same tutor
if (list.getNotName(card.getName()).size() != 0)
{
list = list.getNotName(card.getName());
}
Card c = list.get(0);
AllZone.GameAction.shuffle(card.getController());
AllZone.Computer_Library.remove(c);
if (Destination.equals("Hand")) AllZone.Computer_Hand.add(c); //move to hand
if (Destination.equals("TopOfLibrary")) AllZone.Computer_Library.add(c, 0); //move to top of library
if (Destination.equals("ThirdFromTopOfLibrary")) AllZone.Computer_Library.add(c, 2); //move to third from top of library
if (Destination.equals("Battlefield")) AllZone.getZone(Constant.Zone.Play, "Computer").add(c); //move to battlezone
if (!Targets.startsWith("Card") && !Destination.equals("Battlefield")) {
CardList l = new CardList();
l.add(c);
AllZone.Display.getChoiceOptional("Computer picked:", l.toArray());
}
}
}//computerResolve()
public void humanResolve() {
CardList list = AllZoneUtil.getPlayerCardsInLibrary(Constant.Player.Human);
list = list.getValidCards(Tgts);
if(list.size() != 0) {
Object o = AllZone.Display.getChoiceOptional("Select a card", list.toArray());
AllZone.GameAction.shuffle(card.getController());
if(o != null) {
AllZone.Human_Library.remove(o);
if (Destination.equals("Hand")) AllZone.Human_Hand.add((Card) o); //move to hand
if (Destination.equals("TopOfLibrary")) AllZone.Human_Library.add((Card) o, 0); //move to top of library
if (Destination.equals("ThirdFromTopOfLibrary")) AllZone.Human_Library.add((Card) o, 2); //move to third from top of library
if (Destination.equals("Battlefield")) AllZone.getZone(Constant.Zone.Play, "Human").add((Card) o); //move to battlezone
}
}//if
}//resolve()
}; // spell ability SpTutorTgt
spTtr.setDescription(card.getSpellText());
card.setText("");
card.addSpellAbility(spTtr);
}//spTutor
while(hasKeyword(card, "abDrawCards") != -1) {
int n = hasKeyword(card, "abDrawCards");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmp = k[0].replace("abDrawCards", "");
String[] tmpCost = tmp.split(" ", 2);
final Target abTgt;
if (tmpCost[0].equals(""))
abTgt = null;
else{
abTgt = new Target(tmpCost[0]);
abTgt.setValidTgts("player".split(","));
abTgt.setVTSelection("Target a player to draw cards");
}
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true);
final int NumCards[] = {-1};
final String NumCardsX[] = {"none"};
if(k[1].matches("X")) {
String x = card.getSVar(k[1]);
if(x.startsWith("Count$")) {
String kk[] = x.split("\\$");
NumCardsX[0] = kk[1];
}
} else if(k[1].matches("[0-9][0-9]?")) NumCards[0] = Integer.parseInt(k[1]);
// drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if(k.length > 2) {
if(k[2].contains("Drawback$")) {
String kk[] = k[2].split("\\$");
DrawBack[0] = kk[1];
if(k.length > 3) spDesc[0] = k[3];
if(k.length > 4) stDesc[0] = k[4];
} else {
if(k.length > 2) spDesc[0] = k[2];
if(k.length > 3) stDesc[0] = k[3];
}
}
spDesc[0] = abCost.toString() + spDesc[0];
final Ability_Activated abDraw = new Ability_Activated(card, abCost, abTgt) {
private static final long serialVersionUID = -206739246009089196L;
private int ncards;
public int getNumCards() {
if(NumCards[0] != -1) return NumCards[0];
if(!NumCardsX[0].equals("none")) return CardFactoryUtil.xCount(card, NumCardsX[0]);
return 0;
}
@Override
public boolean canPlayAI() {
ncards = getNumCards();
int handSize = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).size();
int hl = AllZone.getZone(Constant.Zone.Library, Constant.Player.Human).size();
int cl = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer).size();
if (abCost.getSacCost() && handSize > 2) return false;
if (abCost.getSubCounter() && handSize > 3) return false;
if (abCost.getLifeCost() && handSize > 2) return false;
if (!ComputerUtil.canPayCost(this)) return false;
Random r = new Random();
// prevent run-away activations - first time will always return true
boolean rr = false;
if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) rr = true;
if(((hl - ncards) < 2) && abTgt != null) // attempt to deck the human
{
setTargetPlayer(Constant.Player.Human);
return true && rr;
}
if(((handSize + ncards) <= 7) && !((cl - ncards) < 1) && (r.nextInt(10) > 4)) {
setTargetPlayer(Constant.Player.Computer);
return true && rr;
}
return false;
}
@Override
public boolean canPlay(){
return (Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
@Override
public void resolve() {
ncards = getNumCards();
String TgtPlayer = (abTgt == null) ? card.getController() : getTargetPlayer();
for(int i = 0; i < ncards; i++)
AllZone.GameAction.drawCard(TgtPlayer);
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], ncards,
card.getController(), AllZone.GameAction.getOpponent(card.getController()),
TgtPlayer, card, null, this);
}
};
abDraw.setDescription(spDesc[0]);
abDraw.setStackDescription(stDesc[0]);
if (abTgt != null)
abDraw.setTarget(abTgt);
abDraw.setPayCosts(abCost);
card.addSpellAbility(abDraw);
}
if(hasKeyword(card, "spDrawCards") != -1) {
int n = hasKeyword(card, "spDrawCards");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean Tgt[] = {false};
Tgt[0] = k[0].contains("Tgt");
final int NumCards[] = {-1};
final String NumCardsX[] = {"none"};
if(k[1].matches("X")) {
String x = card.getSVar(k[1]);
if(x.startsWith("Count$")) {
String kk[] = x.split("\\$");
NumCardsX[0] = kk[1];
}
} else if(k[1].matches("[0-9][0-9]?")) NumCards[0] = Integer.parseInt(k[1]);
// drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if(k.length > 2) {
if(k[2].contains("Drawback$")) {
String kk[] = k[2].split("\\$");
DrawBack[0] = kk[1];
if(k.length > 3) spDesc[0] = k[3];
if(k.length > 4) stDesc[0] = k[4];
} else {
if(k.length > 2) spDesc[0] = k[2];
if(k.length > 3) stDesc[0] = k[3];
}
}
final SpellAbility spDraw = new Spell(card) {
private static final long serialVersionUID = -7049779241008089696L;
private int ncards;
public int getNumCards() {
if(NumCards[0] != -1) return NumCards[0];
if(!NumCardsX[0].equals("none")) return CardFactoryUtil.xCount(card, NumCardsX[0]);
return 0;
}
@Override
public boolean canPlayAI() {
ncards = getNumCards();
int h = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).size();
int hl = AllZone.getZone(Constant.Zone.Library, Constant.Player.Human).size();
int cl = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer).size();
Random r = new Random();
if(((hl - ncards) < 2) && Tgt[0]) // attempt to deck the human if possible
{
setTargetPlayer(Constant.Player.Human);
return true;
}
if(((h + ncards) <= 7) && !((cl - ncards) < 1) && (r.nextInt(10) > 4)) {
setTargetPlayer(Constant.Player.Computer);
return true;
}
return false;
}
@Override
public void resolve() {
ncards = getNumCards();
String TgtPlayer = card.getController();
if(Tgt[0]) TgtPlayer = getTargetPlayer();
for(int i = 0; i < ncards; i++)
AllZone.GameAction.drawCard(TgtPlayer);
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], ncards,
card.getController(), AllZone.GameAction.getOpponent(card.getController()), TgtPlayer,
card, null, this);
}
};
if(Tgt[0]) spDraw.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spDraw));
if(!spDesc[0].equals("none")) spDraw.setDescription(spDesc[0]);
else spDraw.setDescription("Draw " + NumCards[0] + " cards.");
if(!stDesc[0].equals("none")) spDraw.setStackDescription(stDesc[0]);
else spDraw.setStackDescription("You draw " + NumCards[0] + " cards.");
card.clearSpellAbility();
card.addSpellAbility(spDraw);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbDraw = spDraw.copy();
bbDraw.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
bbDraw.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbDraw.setIsBuyBackAbility(true);
if (Tgt[0] == true)
bbDraw.setBeforePayMana(CardFactoryUtil.input_targetPlayer(bbDraw));
card.addSpellAbility(bbDraw);
}
}//spDrawCards
if (hasKeyword(card, "spLoseLife") != -1)
{
int n = hasKeyword(card, "spLoseLife");
if (n != -1)
{
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean Tgt[] = {false};
Tgt[0] = k[0].contains("Tgt");
final int NumLife[] = {-1};
final String NumLifeX[] = {"none"};
if (k[1].matches("X"))
{
String x = card.getSVar(k[1]);
if (x.startsWith("Count$"))
{
String kk[] = x.split("\\$");
NumLifeX[0] = kk[1];
}
}
else if (k[1].matches("[0-9][0-9]?"))
NumLife[0] = Integer.parseInt(k[1]);
// drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if (k.length > 2)
{
if (k[2].contains("Drawback$"))
{
String kk[] = k[2].split("\\$");
DrawBack[0] = kk[1];
if (k.length > 3)
spDesc[0] = k[3];
if (k.length > 4)
stDesc[0] = k[4];
}
else
{
if (k.length > 2)
spDesc[0] = k[2];
if (k.length > 3)
stDesc[0] = k[3];
}
}
else
{
if (Tgt[0] == true)
{
spDesc[0] = "Target player loses " + NumLife[0] + " life.";
stDesc[0] = cardName + " - target player loses life";
}
else
{
spDesc[0] = "You lose " + NumLife[0] + " life.";
stDesc[0] = cardName + " - you lose life";
}
}
final SpellAbility spLoseLife = new Spell(card)
{
private static final long serialVersionUID = -8361697584661592092L;
public int getNumLife()
{
if (NumLife[0] != -1)
return NumLife[0];
if (! NumLifeX[0].equals("none"))
return CardFactoryUtil.xCount(card, NumLifeX[0]);
return 0;
}
public boolean canPlayAI()
{
if (Tgt[0] == true)
{
setTargetPlayer(Constant.Player.Human);
return true;
}
else // pretty much just for Stronghold Discipline...
{ // assumes there's a good Drawback$ that makes losing life worth it
int nlife = getNumLife();
if ((AllZone.Computer_Life.getLife() - nlife) > 10)
return true;
else
return false;
}
}
public void resolve()
{
int nlife = getNumLife();
String TgtPlayer;
if (Tgt[0] == true)
TgtPlayer = getTargetPlayer();
else
TgtPlayer = card.getController();
AllZone.GameAction.getPlayerLife(TgtPlayer).subtractLife(nlife,card);
if (!DrawBack[0].equals("none"))
CardFactoryUtil.doDrawBack(DrawBack[0], nlife, card.getController(), AllZone.GameAction.getOpponent(card.getController()), TgtPlayer, card, null, this);
}//resolve()
};//SpellAbility
if (Tgt[0] == true)
spLoseLife.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spLoseLife));
spLoseLife.setDescription(spDesc[0]);
spLoseLife.setStackDescription(stDesc[0]);
card.clearSpellAbility();
card.addSpellAbility(spLoseLife);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbLoseLife = spLoseLife.copy();
bbLoseLife.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
StringBuilder sb = new StringBuilder();
sb.append("Buyback ").append(bbCost).append(" (You may pay an additional ").append(bbCost);
sb.append(" as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbLoseLife.setDescription(sb.toString());
// bbLoseLife.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbLoseLife.setIsBuyBackAbility(true);
if (Tgt[0] == true)
bbLoseLife.setBeforePayMana(CardFactoryUtil.input_targetPlayer(bbLoseLife));
card.addSpellAbility(bbLoseLife);
}
}
}//spLoseLife
if (hasKeyword(card, "abLoseLife") != -1)
{
// abLoseLife{Tgt} <abCost>:<lifeLoss>:{Drawback$<Drawback>}:<SADesc>:<StackDesc>
int n = hasKeyword(card, "abLoseLife");
if (n != -1)
{
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmp = k[0].replace("abLoseLife", "");
String[] tmpCost = tmp.split(" ", 2);
final Target abTgt;
if (tmpCost[0].equals(""))
abTgt = null;
else{
abTgt = new Target(tmpCost[0]+"V");
abTgt.setValidTgts("player".split(","));
abTgt.setVTSelection("Target a player to lose life");
}
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true);
final int NumLife[] = {-1};
final String NumLifeX[] = {"none"};
int lifePos = 1;
int drawbackPos = 2;
if (k[lifePos].matches("X"))
{
String x = card.getSVar(k[1]);
if (x.startsWith("Count$"))
{
String kk[] = x.split("\\$");
NumLifeX[0] = kk[1];
}
}
else if (k[lifePos].matches("[0-9][0-9]?"))
NumLife[0] = Integer.parseInt(k[1]);
// drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if (k.length > drawbackPos)
{
if (k[drawbackPos].contains("Drawback$"))
{
String kk[] = k[drawbackPos].split("\\$");
DrawBack[0] = kk[1];
if (k.length > drawbackPos+1)
spDesc[0] = k[drawbackPos+1];
if (k.length > drawbackPos+2)
stDesc[0] = k[drawbackPos+2];
}
else
{
if (k.length > drawbackPos)
spDesc[0] = k[drawbackPos];
if (k.length > drawbackPos+1)
stDesc[0] = k[drawbackPos+1];
}
}
else
{
if (abTgt != null)
{
spDesc[0] = "Target player loses " + NumLife[0] + " life.";
stDesc[0] = cardName + " - target player loses life";
}
else
{
spDesc[0] = "You lose " + NumLife[0] + " life.";
stDesc[0] = cardName + " - you lose life";
}
}
final Ability_Activated abLoseLife = new Ability_Activated(card, abCost, abTgt)
{
private static final long serialVersionUID = -936369754466156082L;
public int getNumLife()
{
if (NumLife[0] != -1)
return NumLife[0];
if (! NumLifeX[0].equals("none"))
return CardFactoryUtil.xCount(card, NumLifeX[0]);
return 0;
}
public boolean canPlayAI()
{
int nlife = getNumLife();
int life = AllZone.GameAction.getPlayerLife(Constant.Player.Human).getLife();
if (abCost.getSacCost() && life > nlife + 4) return false;
if (abCost.getSubCounter() && life > nlife + 6) return false;
if (abCost.getLifeCost() && life >= AllZone.GameAction.getPlayerLife(Constant.Player.Computer).getLife())
return false;
Random r = new Random();
boolean rr = false; // prevent run-away activations - first time will always return true
if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
rr = true;
if (abTgt != null)
{
setTargetPlayer(Constant.Player.Human);
return true && rr;
}
else
{ // assumes there's a good Drawback$ that makes losing life worth it
if ((AllZone.Computer_Life.getLife() - nlife) >= 10)
return true && rr;
else
return false;
}
}
public void resolve()
{
int nlife = getNumLife();
String TgtPlayer;
if (abTgt != null)
TgtPlayer = getTargetPlayer();
else
TgtPlayer = card.getController();
AllZone.GameAction.getPlayerLife(TgtPlayer).subtractLife(nlife,card);
if (!DrawBack[0].equals("none"))
CardFactoryUtil.doDrawBack(DrawBack[0], nlife, card.getController(), AllZone.GameAction.getOpponent(card.getController()), TgtPlayer, card, null, this);
}//resolve()
};//SpellAbility
if (abTgt != null)
abLoseLife.setTarget(abTgt);
abLoseLife.setPayCosts(abCost);
abLoseLife.setDescription(abCost.toString() + spDesc[0]);
abLoseLife.setStackDescription(stDesc[0]);
card.addSpellAbility(abLoseLife);
}
}// abLoseLife
if (hasKeyword(card, "spGainLife") != -1)
{
int n = hasKeyword(card, "spGainLife");
if (n != -1)
{
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final boolean Tgt[] = {false};
Tgt[0] = k[0].contains("Tgt");
final int NumLife[] = {-1};
final String NumLifeX[] = {"none"};
if (k[1].matches("X"))
{
String x = card.getSVar(k[1]);
if (x.startsWith("Count$"))
{
String kk[] = x.split("\\$");
NumLifeX[0] = kk[1];
}
}
else if (k[1].matches("[0-9][0-9]?"))
NumLife[0] = Integer.parseInt(k[1]);
// drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if (k.length > 2)
{
if (k[2].contains("Drawback$"))
{
String kk[] = k[2].split("\\$");
DrawBack[0] = kk[1];
if (k.length > 3)
spDesc[0] = k[3];
if (k.length > 4)
stDesc[0] = k[4];
}
else
{
if (k.length > 2)
spDesc[0] = k[2];
if (k.length > 3)
stDesc[0] = k[3];
}
}
else
{
if (Tgt[0] == true)
{
spDesc[0] = "Target player gains " + NumLife[0] + " life.";
stDesc[0] = cardName + " - target player gains " + NumLife[0] + " life";
}
else
{
spDesc[0] = "You gain " + NumLife[0] + " life.";
stDesc[0] = cardName + " - you gain " + NumLife[0] + " life";
}
}
final SpellAbility spGainLife = new Spell(card)
{
private static final long serialVersionUID = -8361697584661592092L;
public int getNumLife()
{
if (NumLife[0] != -1)
return NumLife[0];
if (! NumLifeX[0].equals("none"))
return CardFactoryUtil.xCount(card, NumLifeX[0]);
return 0;
}
public boolean canPlayAI()
{
if (Tgt[0] == true)
setTargetPlayer(Constant.Player.Computer);
if (AllZone.Computer_Life.getLife() < 10)
return true;
else
{
Random r = new Random();
return (r.nextFloat() < .6667);
}
}
public void resolve()
{
int nlife = getNumLife();
String TgtPlayer;
if (Tgt[0] == true)
TgtPlayer = getTargetPlayer();
else
TgtPlayer = card.getController();
AllZone.GameAction.gainLife(TgtPlayer, nlife);
if (!DrawBack[0].equals("none"))
CardFactoryUtil.doDrawBack(DrawBack[0], nlife, card.getController(), AllZone.GameAction.getOpponent(card.getController()), TgtPlayer, card, null, this);
}//resolve()
};//SpellAbility
if (Tgt[0] == true)
spGainLife.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spGainLife));
spGainLife.setDescription(spDesc[0]);
spGainLife.setStackDescription(stDesc[0]);
card.clearSpellAbility();
card.addSpellAbility(spGainLife);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbGainLife = spGainLife.copy();
bbGainLife.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
bbGainLife.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbGainLife.setIsBuyBackAbility(true);
if (Tgt[0] == true)
bbGainLife.setBeforePayMana(CardFactoryUtil.input_targetPlayer(bbGainLife));
card.addSpellAbility(bbGainLife);
}
}
}//spGainLife
if (hasKeyword(card, "abGainLife") != -1)
{
int n = hasKeyword(card, "abGainLife");
if (n != -1)
{
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmp = k[0].replace("abGainLife", "");
String[] tmpCost = tmp.split(" ", 2);
int inc = 0;
final Target abTgt;
if (tmpCost[0].equals(""))
abTgt = null;
else{
abTgt = new Target(tmpCost[0]);
abTgt.setValidTgts(k[1].split(","));
abTgt.setVTSelection("Target a player to gain life");
inc++;
}
final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true);
final int NumLife[] = {-1};
final String NumLifeX[] = {"none"};
int lifePos = 1 + inc;
int drawbackPos = 2 + inc;
if (k[lifePos].matches("X"))
{
String x = card.getSVar(k[lifePos]);
if (x.startsWith("Count$"))
{
String kk[] = x.split("\\$");
NumLifeX[0] = kk[1];
}
}
else if (k[lifePos].matches("[0-9][0-9]?"))
NumLife[0] = Integer.parseInt(k[lifePos]);
// drawbacks and descriptions
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
if (k.length > drawbackPos)
{
if (k[drawbackPos].contains("Drawback$"))
{
String kk[] = k[drawbackPos].split("\\$");
DrawBack[0] = kk[1];
if (k.length > drawbackPos+1)
spDesc[0] = k[drawbackPos+1];
if (k.length > drawbackPos+2)
stDesc[0] = k[drawbackPos+2];
}
else
{
if (k.length > drawbackPos)
spDesc[0] = k[drawbackPos];
if (k.length > drawbackPos+1)
stDesc[0] = k[drawbackPos+1];
}
}
else
{
if (abTgt != null)
{
spDesc[0] = "Target player gains " + NumLife[0] + " life.";
stDesc[0] = cardName + " - target player gains life";
}
else
{
spDesc[0] = "You gain " + NumLife[0] + " life.";
stDesc[0] = cardName + " - you gain life";
}
}
final Ability_Activated abGainLife = new Ability_Activated(card, abCost, abTgt)
{
private static final long serialVersionUID = -936369754466156082L;
public int getNumLife()
{
if (NumLife[0] != -1)
return NumLife[0];
if (! NumLifeX[0].equals("none"))
return CardFactoryUtil.xCount(card, NumLifeX[0]);
return 0;
}
public boolean canPlay(){
return (Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
public boolean canPlayAI()
{
int life = AllZone.GameAction.getPlayerLife(Constant.Player.Computer).getLife();
if (abCost.getSacCost() && life > 5) return false;
if (abCost.getSubCounter() && life > 5) return false;
if (abCost.getLifeCost() && life > 5) return false;
if (!ComputerUtil.canPayCost(this))
return false;
Random r = new Random();
boolean rr = false; // prevent run-away activations - first time will always return true
if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
rr = true;
if (abTgt != null)
setTargetPlayer(Constant.Player.Computer);
if (AllZone.Computer_Life.getLife() < 10)
return true && rr;
else
return ((r.nextFloat() < .6667) && rr);
}
public void resolve()
{
int nlife = getNumLife();
String TgtPlayer = (abTgt != null) ? getTargetPlayer() : getActivatingPlayer();
AllZone.GameAction.gainLife(TgtPlayer, nlife);
if (!DrawBack[0].equals("none"))
CardFactoryUtil.doDrawBack(DrawBack[0], nlife, card.getController(), AllZone.GameAction.getOpponent(card.getController()), TgtPlayer, card, null, this);
}//resolve()
};//SpellAbility
abGainLife.setDescription(abCost.toString() + spDesc[0]);
abGainLife.setStackDescription(stDesc[0]);
if (abTgt != null)
abGainLife.setTarget(abTgt);
abGainLife.setPayCosts(abCost);
card.addSpellAbility(abGainLife);
}
}// abGainLife
if(hasKeyword(card, "SearchRebel") != -1) {
int n = hasKeyword(card, "SearchRebel");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.addSpellAbility(CardFactoryUtil.ability_Rebel_Search(card, manacost));
}
}//Rebel search
if(hasKeyword(card, "SearchMerc") != -1) {
int n = hasKeyword(card, "SearchMerc");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.addSpellAbility(CardFactoryUtil.ability_Merc_Search(card, manacost));
}
}//Merc search
if(hasKeyword(card, "Morph") != -1) {
int n = hasKeyword(card, "Morph");
if(n != -1) {
card.setPrevIntrinsicKeyword(card.getIntrinsicKeyword());
card.setPrevType(card.getType());
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
int attack = card.getBaseAttack();
int defense = card.getBaseDefense();
String orgManaCost = card.getManaCost();
card.addSpellAbility(CardFactoryUtil.ability_Morph_Up(card, manacost, orgManaCost, attack, defense));
card.addSpellAbility(CardFactoryUtil.ability_Morph_Down(card));
}
}//Morph
if(hasKeyword(card, "Flashback") != -1) {
int n = hasKeyword(card, "Flashback");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
//card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.addSpellAbility(CardFactoryUtil.ability_Flashback(card, manacost, "0"));
}
}//flashback
if(hasKeyword(card, "Unearth") != -1) {
int n = hasKeyword(card, "Unearth");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
//card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.addSpellAbility(CardFactoryUtil.ability_Unearth(card, manacost));
card.setUnearth(true);
}
}//unearth
if(hasKeyword(card, "Madness") != -1) {
int n = hasKeyword(card, "Madness");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
//card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
card.setMadness(true);
card.setMadnessCost(k[1]);
}
}//madness
if(hasKeyword(card, "Suspend") != -1) {
// Suspend:<TimeCounters>:<Cost>
int n = hasKeyword(card, "Suspend");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
card.setSuspend(true);
String k[] = parse.split(":");
final int timeCounters = Integer.parseInt(k[1]);
final String cost = k[2];
card.addSpellAbility(CardFactoryUtil.ability_suspend(card, cost, timeCounters));
}
}//madness
if(hasKeyword(card, "Devour") != -1) {
int n = hasKeyword(card, "Devour");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String magnitude = k[1];
final int multiplier = Integer.parseInt(magnitude);
//final String player = card.getController();
final int[] numCreatures = new int[1];
final SpellAbility devour = new Spell(card) {
private static final long serialVersionUID = 4888189840817163900L;
@Override
public void resolve() {
int totalCounters = numCreatures[0] * multiplier;
card.addCounter(Counters.P1P1, totalCounters);
if(card.getName().equals("Skullmulcher")) {
for(int i = 0; i < numCreatures[0]; i++) {
AllZone.GameAction.drawCard(card.getController());
}
} else if(card.getName().equals("Caldera Hellion")) {
PlayerZone hPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
PlayerZone cPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
CardList creatures = new CardList();
creatures.addAll(hPlay.getCards());
creatures.addAll(cPlay.getCards());
creatures = creatures.getType("Creature");
for(int i = 0; i < creatures.size(); i++) {
Card crd = creatures.get(i);
if(CardFactoryUtil.canDamage(card, crd)) crd.addDamage(3, card);
}
}
}
@Override
public boolean canPlay() {
return AllZone.Phase.getActivePlayer().equals(card.getController()) && card.isFaceDown()
&& !AllZone.Phase.getPhase().equals("End of Turn")
&& AllZone.GameAction.isCardInPlay(card);
}
};//devour
Command intoPlay = new Command() {
private static final long serialVersionUID = -7530312713496897814L;
public void execute() {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
CardList creats = new CardList(play.getCards());
creats = creats.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isCreature() && !c.equals(card);
}
});
//System.out.println("Creats size: " + creats.size());
if(card.getController().equals(Constant.Player.Human)) {
if (creats.size() > 0)
{
List<Card> selection = AllZone.Display.getChoicesOptional("Select creatures to sacrifice", creats.toArray());
numCreatures[0] = selection.size();
for(int m = 0; m < selection.size(); m++) {
AllZone.GameAction.sacrifice(selection.get(m));
}
}
}//human
else {
int count = 0;
for(int i = 0; i < creats.size(); i++) {
Card c = creats.get(i);
if(c.getNetAttack() <= 1 && c.getNetDefense() <= 2) {
AllZone.GameAction.sacrifice(c);
count++;
}
//is this needed?
AllZone.Computer_Play.updateObservers();
}
numCreatures[0] = count;
}
AllZone.Stack.add(devour);
}
};
devour.setStackDescription(card.getName() + " - gets " + magnitude
+ " +1/+1 counter(s) per devoured creature.");
devour.setDescription("Devour " + magnitude);
card.addSpellAbility(devour);
card.addComesIntoPlayCommand(intoPlay);
//card.addSpellAbility(CardFactoryUtil.ability_Devour(card, magnitude));
}
}//Devour
while(hasKeyword(card, "Modular") != -1) {
int n = hasKeyword(card, "Modular");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
final int m = Integer.parseInt(parse.substring(8));
String t = card.getSpellText();
if(!t.equals("")) t += "\r\n";
card.setText(t
+ parse
+ " (This enters the battlefield with "
+ m
+ " +1/+1 counters on it. When it's put into a graveyard, you may put its +1/+1 counters on target artifact creature.)");//Erm help? Isn't there a normal way to do this?...
card.addComesIntoPlayCommand(new Command() {
private static final long serialVersionUID = 339412525059881775L;
public void execute() {
card.addCounter(Counters.P1P1, m);
}
});
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
if(card.getController().equals(Constant.Player.Computer)) {
CardList choices = new CardList(AllZone.Computer_Play.getCards()).filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isCreature() && c.isArtifact();
}
});
if(choices.size() != 0) CardFactoryUtil.AI_getBestCreature(choices).addCounter(
Counters.P1P1, getSourceCard().getCounters(Counters.P1P1));
} else {
final SpellAbility ability = this;
AllZone.InputControl.setInput(new Input() {
private static final long serialVersionUID = 2322926875771867901L;
@Override
public void showMessage() {
AllZone.Display.showMessage("Select target artifact creature");
ButtonUtil.enableOnlyCancel();
}
@Override
public void selectButtonCancel() {
stop();
}
@Override
public void selectCard(Card card2, PlayerZone zone) {
if(card2.isCreature() && card2.isArtifact() && zone.is(Constant.Zone.Play)
&& CardFactoryUtil.canTarget(ability, card)) {
card2.addCounter(Counters.P1P1, ability.getSourceCard().getCounters(
Counters.P1P1));//combining input and resolve is skirting rules and hacky at best, but non-stackability of destroyCommand Inputs turns into a major problem when the keyword is mainly used during the simultaneous destruction of combat.
stop();
}
}
});
}//else
}//resolve()
};
card.addDestroyCommand(new Command() {
private static final long serialVersionUID = 304026662487997331L;
public void execute() {
ability.setStackDescription("Put " + card.getCounters(Counters.P1P1)
+ " +1/+1 counter/s from " + card + " on target artifact creature.");
AllZone.Stack.push(ability);
}
});
}
}//while shouldModular
int spike = hasKeyword(card, "Spike");
if(spike != -1) {
String parse = card.getKeyword().get(spike).toString();
card.removeIntrinsicKeyword(parse);
final Ability_Cost cost = new Ability_Cost("2 SubCounter<1/P1P1>", card.getName(), true);
final Target tgt = new Target("TgtC");
final int m = Integer.parseInt(parse.substring(6));
String t = card.getSpellText();
if(!t.equals("")) t += "\r\n";
card.setText(t
+ parse
+ " (This enters the battlefield with "
+ m
+ " +1/+1 counters on it.)");
card.addComesIntoPlayCommand(new Command() {
private static final long serialVersionUID = -2292898970576123040L;
public void execute() {
card.addCounter(Counters.P1P1, m);
}
});//ComesIntoPlayCommand
final Ability_Activated ability = new Ability_Activated(card, cost, tgt) {
private static final long serialVersionUID = -1680422554249396500L;
@Override
public boolean canPlay() {
return (Cost_Payment.canPayAdditionalCosts(cost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}//canPlay()
@Override
public boolean canPlayAI() {
return getCreature().size() != 0 && ComputerUtil.canPayCost(this)
&& !CardFactoryUtil.AI_doesCreatureAttack(card);
}//canPlayAI()
@Override
public void chooseTargetAI() {
Card best = CardFactoryUtil.AI_getBestCreature(getCreature());
setTargetCard(best);
card.subtractCounter(Counters.P1P1, 1);
}//chooseTargetAI()
CardList getCreature() {
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isCreature()
&& CardFactoryUtil.canTarget(card, c)
&& c.getNetAttack() > card.getNetAttack()
&& c != card;
}
});
return list;
}//getCreature()
@Override
public void resolve() {
if (AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
getTargetCard().addCounter(Counters.P1P1, 1);
}
}//resolve()
};//SpellAbility
StringBuffer sb = new StringBuffer();
sb.append("Put a +1/+1 counter from ").append(card.getName()).append(" on target creature.");
ability.setStackDescription(sb.toString());
ability.setDescription(cost.toString() + " Put a +1/+1 counter on target creature");
card.addSpellAbility(ability);
} // if Spike
int etbCounter = hasKeyword(card, "etbCounter"); // etbCounter:CounterType:CounterAmount
// enters the battlefield with CounterAmount of CounterType
if(etbCounter != -1) {
String parse = card.getKeyword().get(etbCounter).toString();
card.removeIntrinsicKeyword(parse);
String p[] = parse.split(":");
final Counters counter = Counters.valueOf(p[1]);
final int numCounters = Integer.parseInt(p[2]);
StringBuilder sb = new StringBuilder(card.getSpellText());
if (sb.length() != 0)
sb.append("\n");
sb.append(card.getName());
sb.append(" enters the battlefield with ");
sb.append(numCounters);
sb.append(" ");
sb.append(counter.getName());
sb.append(" counters on it.");
card.setText(sb.toString());
card.addComesIntoPlayCommand(new Command() {
private static final long serialVersionUID = -2292898970576123040L;
public void execute() {
card.addCounter(counter, numCounters);
}
});//ComesIntoPlayCommand
} // if etbCounter
// Generic target creature pump
if(hasKeyword(card, "spPumpTgt") != -1) {
int n = hasKeyword(card, "spPumpTgt");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final int NumAttack[] = {-1138};
final String AttackX[] = {"none"};
final int NumDefense[] = {-1138};
final String DefenseX[] = {"none"};
final String Keyword[] = {"none"};
final boolean curse[] = {false};
curse[0] = k[0].contains("Curse");
String ptk[] = k[1].split("/");
if(ptk.length == 1) Keyword[0] = ptk[0];
if(ptk.length >= 2) {
if(ptk[0].matches("[\\+\\-][XY]")) {
String xy = card.getSVar(ptk[0].replaceAll("[\\+\\-]", ""));
if(xy.startsWith("Count$")) {
String kk[] = xy.split("\\$");
AttackX[0] = kk[1];
if(ptk[0].contains("-")) if(AttackX[0].contains("/")) AttackX[0] = AttackX[0].replace("/",
"/Negative");
else AttackX[0] += "/Negative";
}
} else if(ptk[0].matches("[\\+\\-][0-9]")) NumAttack[0] = Integer.parseInt(ptk[0].replace("+", ""));
if(ptk[1].matches("[\\+\\-][XY]")) {
String xy = card.getSVar(ptk[1].replaceAll("[\\+\\-]", ""));
if(xy.startsWith("Count$")) {
String kk[] = xy.split("\\$");
DefenseX[0] = kk[1];
if(ptk[1].contains("-")) if(DefenseX[0].contains("/")) DefenseX[0] = DefenseX[0].replace(
"/", "/Negative");
else DefenseX[0] += "/Negative";
}
} else if(ptk[1].matches("[\\+\\-][0-9]")) NumDefense[0] = Integer.parseInt(ptk[1].replace("+", ""));
}
if(ptk.length == 3) Keyword[0] = ptk[2];
String dK = Keyword[0];
if (Keyword[0].contains(" & "))////////////////
{
int amp = Keyword[0].lastIndexOf("&");
StringBuffer sbk = new StringBuffer(Keyword[0]);
sbk.replace(amp, amp + 1, "and");
dK = sbk.toString();
dK = dK.replace(" & ", ", ");
}
final String DrawBack[] = {"none"};
final String spDesc[] = {"none"};
final String stDesc[] = {"none"};
//String d = new String("none");
StringBuilder sb = new StringBuilder();
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && Keyword[0].equals("none")) {
// pt boost
sb.append("Target creature gets ");
if(NumAttack[0] > 0 || (NumAttack[0] == 0 && NumDefense[0] > 0)) // +0/+1
sb.append("+");
else if(NumAttack[0] < 0 || (NumAttack[0] == 0 && NumDefense[0] < 0)) // -0/-1
sb.append("-");
sb.append(Math.abs(NumAttack[0]) + "/");
if(NumDefense[0] > 0 || (NumDefense[0] == 0 && NumAttack[0] > 0)) // +1/+0
sb.append("+");
else if(NumDefense[0] < 0 || (NumDefense[0] == 0 && NumAttack[0] < 0)) // -1/-0
sb.append("-");
sb.append(Math.abs(NumDefense[0]) + " until end of turn.");
}
if((AttackX[0].equals("none") && NumAttack[0] == -1138)
&& (DefenseX[0].equals("none") && NumDefense[0] == -1138) && !Keyword[0].equals("none")) {
// k boost
sb.append("Target creature gains " + dK + " until end of turn.");
}
if((AttackX[0].equals("none") && !(NumAttack[0] == -1138))
&& (DefenseX[0].equals("none") && !(NumDefense[0] == -1138)) && !Keyword[0].equals("none")) {
// ptk boost
sb.append("Target creature gets ");
if(NumAttack[0] > 0 || (NumAttack[0] == 0 && NumDefense[0] > 0)) // +0/+1
sb.append("+");
else if(NumAttack[0] < 0 || (NumAttack[0] == 0 && NumDefense[0] < 0)) // -0/-1
sb.append("-");
sb.append(Math.abs(NumAttack[0]) + "/");
if(NumDefense[0] > 0 || (NumDefense[0] == 0 && NumAttack[0] > 0)) // +1/+0
sb.append("+");
else if(NumDefense[0] < 0 || (NumDefense[0] == 0 && NumAttack[0] < 0)) // -1/-0
sb.append("-");
sb.append(Math.abs(NumDefense[0]));
sb.append(" and gains " + dK + " until end of turn.");
}
if(k.length > 2) {
if(k[2].contains("Drawback$")) {
String kk[] = k[2].split("\\$");
DrawBack[0] = kk[1];
if(k.length > 3) spDesc[0] = k[3];
if(k.length > 4) stDesc[0] = k[4];
} else {
if(k.length > 2) spDesc[0] = k[2];
if(k.length > 3) stDesc[0] = k[3];
}
} else if(!sb.toString().equals("none")) {
spDesc[0] = sb.toString();
stDesc[0] = sb.toString();
}
SpellAbility spPump = new Spell(card) {
private static final long serialVersionUID = 42244224L;
private int getNumAttack() {
if(NumAttack[0] != -1138) return NumAttack[0];
if(!AttackX[0].equals("none")) return CardFactoryUtil.xCount(card, AttackX[0]);
return 0;
}
private int getNumDefense() {
if(NumDefense[0] != -1138) return NumDefense[0];
if(!DefenseX[0].equals("none")) return CardFactoryUtil.xCount(card, DefenseX[0]);
return 0;
}
@Override
public boolean canPlayAI() {
int defense = getNumDefense();
String curPhase = AllZone.Phase.getPhase();
if(curPhase.equals(Constant.Phase.Main2) && !(curse[0] && NumDefense[0] < 0))
return false;
boolean goodt = false;
Card t = new Card();
if (curse[0]) { // Curse means spells with negative effect
CardList list = new CardList(AllZone.Human_Play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return CardFactoryUtil.canTarget(card, c) && c.isCreature();
}
});
if (NumDefense[0] < 0 && !list.isEmpty()) { // with spells that give -X/-X, compi will try to destroy a creature
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
if (c.getNetDefense() <= -NumDefense[0] ) return true; // can kill indestructible creatures
return (c.getKillDamage() <= -NumDefense[0] && !c.hasKeyword("Indestructible"));
}
}); // leaves all creatures that will be destroyed
} // -X/-X end
if (!list.isEmpty()) {
t = CardFactoryUtil.AI_getBestCreature(list);
goodt = true;
}
}
else { // no Curse means spell with positive effect
CardList list = getCreatures();
if(!list.isEmpty()) {
while(goodt == false && !list.isEmpty()) {
t = CardFactoryUtil.AI_getBestCreature(list);
if((t.getNetDefense() + defense) > 0) goodt = true;
else list.remove(t);
}
}
}
if(goodt == true) {
setTargetCard(t);
return true;
}
return false;
}
CardList getCreatures() {
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
if(c.isCreature()) {
if(c.hasSickness() && Keyword[0].contains("Haste"))
return CardFactoryUtil.canTarget(card, c);
return (CardFactoryUtil.AI_doesCreatureAttack(c))
&& (CardFactoryUtil.canTarget(card, c))
&& (!Keyword[0].equals("none") && !c.hasAnyKeyword(Keyword[0].split(" & ")))
&& (!(!c.hasSickness()) && Keyword[0].contains("Haste"));
}
return false;
}
});
return list;
}
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
final Card[] creature = new Card[1];
creature[0] = getTargetCard();
final int a = getNumAttack();
final int d = getNumDefense();
final Command untilEOT = new Command() {
private static final long serialVersionUID = -42244224L;
public void execute() {
if(AllZone.GameAction.isCardInPlay(creature[0])) {
creature[0].addTempAttackBoost(-1 * a);
creature[0].addTempDefenseBoost(-1 * d);
if(!Keyword[0].equals("none"))
{
String[] kws = Keyword[0].split(" & ");
for (int i=0; i<kws.length; i++)
creature[0].removeExtrinsicKeyword(kws[i]);
}
}
}
};
creature[0].addTempAttackBoost(a);
creature[0].addTempDefenseBoost(d);
if(!Keyword[0].equals("none"))
{
String[] kws = Keyword[0].split(" & ");
for (int i=0; i<kws.length; i++)
creature[0].addExtrinsicKeyword(kws[i]);
}
AllZone.EndOfTurn.addUntil(untilEOT);
if(!DrawBack[0].equals("none")) CardFactoryUtil.doDrawBack(DrawBack[0], 0,
card.getController(), AllZone.GameAction.getOpponent(card.getController()),
creature[0].getController(), card, creature[0], this);
}
}//resolve
};//SpellAbility
spPump.setBeforePayMana(CardFactoryUtil.input_targetCreature(spPump));
spPump.setDescription(spDesc[0]);
spPump.setStackDescription(stDesc[0]);
card.setSVar("PlayMain1", "TRUE");
card.clearSpellAbility();
card.addSpellAbility(spPump);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbPump = spPump.copy();
bbPump.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost));
bbPump.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbPump.setIsBuyBackAbility(true);
bbPump.setBeforePayMana(CardFactoryUtil.input_targetCreature(bbPump));
card.addSpellAbility(bbPump);
}
}// spPumpTgt
while(shouldManaAbility(card) != -1) {
int n = shouldManaAbility(card);
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
final Ability_Mana ability = new Ability_Mana(card, parse) {
private static final long serialVersionUID = -113811381138L;
@Override
public boolean canPlayAI() {
return false;
}
};
//ability.setDescription(parse);
card.addSpellAbility(ability);
}
}
while(hasKeyword(card,"paintap") != -1)
{
String toParse = card.getIntrinsicKeyword().get(hasKeyword(card,"paintap"));
card.removeIntrinsicKeyword(toParse);
String[] splitkeyword = toParse.split(":");
final int amountHurt = Integer.parseInt(splitkeyword[1]);
final String manaGenerated = splitkeyword[2];
StringBuilder sb = new StringBuilder();
sb.append("tap: add ").append(manaGenerated).append(" to your mana pool. CARDNAME deals ").append(amountHurt).append(" damage to you.");
final String abilityDescriptionString = sb.toString();
// final Ability_Mana addMana = new Ability_Mana(card, "tap: add " + manaGenerated + " to your mana pool. CARDNAME deals " + amountHurt + " damage to you.") {
final Ability_Mana addMana = new Ability_Mana(card, abilityDescriptionString) {
private static final long serialVersionUID = -259088242789L;
@Override
public void resolve()
{
//AllZone.GameAction.getPlayerLife(getController()).subtractLife(amountHurt,card);
AllZone.GameAction.addDamage(card.getController(), card, amountHurt);
super.resolve();
}
@Override
public String mana() {
return manaGenerated;
}
};
card.addSpellAbility(addMana);
}//paintap
////////////////////////////////////////////////////////////////
if (card.getKeyword().contains("When CARDNAME enters the battlefield, draw a card.") ||
card.getKeyword().contains("When CARDNAME enters the battlefield, draw two cards.")) {
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
int drawCardsNum = 1;
if (card.getKeyword().contains("When CARDNAME enters the battlefield, draw two cards.")) {
drawCardsNum = 2;
}
for (int i = 0; i < drawCardsNum; i++) {
AllZone.GameAction.drawCard(card.getController());
}//for loop
}//resolve()
};//SpellAbility
Command intoPlay = new Command() {
private static final long serialVersionUID = 1707519783018941582L;
public void execute() {
StringBuilder sb = new StringBuilder();
sb.append(card.getName());
sb.append(" - ");
sb.append(card.getController());
sb.append(" draws ");
if (card.getKeyword().contains("When CARDNAME enters the battlefield, draw a card.")) {
sb.append("a card.");
} else sb.append("two cards.");
ability.setStackDescription(sb.toString());
AllZone.Stack.add(ability);
}
};
card.addComesIntoPlayCommand(intoPlay);
}//end if
if (card.getKeyword().contains("When CARDNAME enters the battlefield, you may search your library for up to three cards named CARDNAME, reveal them, and put them into your hand. If you do, shuffle your library."))
{
final SpellAbility ability = new Ability(card, "0")
{
public void resolve()
{
CardList list = AllZoneUtil.getPlayerCardsInLibrary(card.getController());
list = list.getName(cardName);
if (list.size() < 1)
return;
if (card.getController().equals(Constant.Player.Human))
{
List<Card> selection = AllZone.Display.getChoicesOptional("Select cards to fetch from Library", list.toArray());
for(int m = 0; m < selection.size(); m++) {
AllZone.Human_Library.remove(selection.get(m));
AllZone.Human_Hand.add(selection.get(m));
}
}
else
{
for (Card c:list)
{
AllZone.Computer_Library.remove(c);
AllZone.Computer_Hand.add(c);
}
StringBuilder sb = new StringBuilder();
sb.append("Opponent fetches and reveals ");
sb.append(list.size());
sb.append(" copies of ");
sb.append(cardName);
sb.append(".");
JOptionPane.showMessageDialog(null, sb.toString(), "", JOptionPane.INFORMATION_MESSAGE);
}
AllZone.GameAction.shuffle(card.getController());
}
};
Command intoPlay = new Command() {
private static final long serialVersionUID = 8374287903074067063L;
public void execute() {
StringBuilder sb = new StringBuilder();
sb.append(card.getName());
sb.append(" - ");
sb.append(" search your library for up to three cards named ");
sb.append(cardName);
sb.append(", reveal them, and put them into your hand. If you do, shuffle your library.");
ability.setStackDescription(sb.toString());
AllZone.Stack.add(ability);
}
};
card.addComesIntoPlayCommand(intoPlay);
}
if(hasKeyword(card, "spMakeToken") != -1) {
int n = hasKeyword(card, "spMakeToken");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
final String[] k = parse.split("<>");
final String numString = k[1].equals("X") ? card.getSVar("X") : k[1];
final boolean xString = k[1].equals("X") ? true : false;
final String name = k[2];
final String imageName = k[3];
final String controllerString = k[4];
final String manaCost = k[5];
final String[] types = k[6].split(";");
final int attack = Integer.valueOf(k[7]);
final int defense = Integer.valueOf(k[8]);
final String[] keywords = k[9].split(";");
SpellAbility spell = new Spell(card) {
private static final long serialVersionUID = -5286946184688616830L;
@Override
public boolean canPlayAI() {
if(xString && CardFactoryUtil.xCount(card, numString) > 0) {
return false;
}
else{
return true;
}
}
@Override
public void resolve() {
String controller = (controllerString.equals("Controller") ? card.getController() : AllZone.GameAction.getOpponent(card.getController()));
if(keywords[0].equals("None")) keywords[0] = "";
int num = xString ? CardFactoryUtil.xCount(card, numString) : Integer.valueOf(numString);
for(int i = 0; i < num; i ++ ){
CardFactoryUtil.makeToken(name, imageName, controller, manaCost, types, attack, defense, keywords);
}
}
};
card.clearSpellAbility();
card.addSpellAbility(spell);
}//end MakeToken
if(hasKeyword(card, "abMakeToken") != -1) {
int n = hasKeyword(card, "abMakeToken");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
final String[] k = parse.split("<>");
final String numString = k[1].equals("X") ? card.getSVar("X") : k[1];
final boolean xString = k[1].equals("X") ? true : false;
final String name = k[2];
final String imageName = k[3];
final String controllerString = k[4];
final String manaCost = k[5];
final String[] types = k[6].split(";");
final int attack = Integer.valueOf(k[7]);
final int defense = Integer.valueOf(k[8]);
final String[] keywords = k[9].split(";");
final String abDesc = k[10];
String fullCost = k[0].substring(11);
final Ability_Cost abCost = new Ability_Cost(fullCost, card.getName(), true);
final String spDesc[] = {"none"};
spDesc[0] = abCost.toString()+ " - " + abDesc;
final SpellAbility abMakeToken = new Ability_Activated(card, abCost, null) {
private static final long serialVersionUID = -1415539558367883075L;
public boolean canPlayAI() {
if (!ComputerUtil.canPayCost(this)) return false;
if(xString && CardFactoryUtil.xCount(card, numString) == 0) {
return false;
}
else {
Random r = new Random();
boolean rr = false;
if( r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()) ) {
rr = true;
}
return rr;
}
}
@Override
public boolean canPlay(){
return Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay();
}
@Override
public void resolve() {
String controller = (controllerString.equals("Controller") ? card.getController() : AllZone.GameAction.getOpponent(card.getController()));
if(keywords[0].equals("None")) keywords[0] = "";
int num = xString ? CardFactoryUtil.xCount(card, numString) : Integer.valueOf(numString);
for(int i = 0; i < num; i ++ ){
CardFactoryUtil.makeToken(name, imageName, controller, manaCost, types, attack, defense, keywords);
}
}
};//end abMakeToken ability
abMakeToken.setDescription(spDesc[0]);
abMakeToken.setStackDescription(card+" - "+abDesc);
card.addSpellAbility(abMakeToken);
card.setSVar("PlayMain1", "TRUE");
}// end abMakeToken keyword
if(hasKeyword(card, "etbMakeToken") != -1) {
int n = hasKeyword(card, "etbMakeToken");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
final String[] k = parse.split("<>");
final String numString = k[1].equals("X") ? card.getSVar("X") : k[1];
final boolean xString = k[1].equals("X") ? true : false;
final String name = k[2];
final String imageName = k[3];
final String controllerString = k[4];
final String manaCost = k[5];
final String[] types = k[6].split(";");
final int attack = Integer.valueOf(k[7]);
final int defense = Integer.valueOf(k[8]);
final String[] keywords = k[9].split(";");
final String abDesc = k[10];
final SpellAbility ability = new Ability(card, "0") {
@Override
public boolean canPlayAI() {
if(xString && CardFactoryUtil.xCount(card, numString) > 0) {
return false;
}
else{
return true;
}
}
@Override
public void resolve() {
String controller = (controllerString.equals("Controller") ? card.getController() : AllZone.GameAction.getOpponent(card.getController()));
if(keywords[0].equals("None")) keywords[0] = "";
int num = xString ? CardFactoryUtil.xCount(card, numString) : Integer.valueOf(numString);
for(int i = 0; i < num; i ++ ){
CardFactoryUtil.makeToken(name, imageName, controller, manaCost, types, attack, defense, keywords);
}
}
};
final Command cip = new Command() {
private static final long serialVersionUID = 903342987065874979L;
public void execute() {
ability.setStackDescription(card+" - "+abDesc);
AllZone.Stack.add(ability);
}
};
card.addComesIntoPlayCommand(cip);
}//end etbMakeToken
// Generic tap target ___ activated ability
//abTapTgt {Ability_Cost}:{Valid Targets}:{Description}
if (hasKeyword(card, "abTapTgt") != -1)
{
int n = hasKeyword(card, "abTapTgt");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmpCost = k[0].substring(8);
final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName(), true);
final Target tapTargets = new Target("TgtV");
final String Tgts[] = k[1].split(",");
tapTargets.setValidTgts(Tgts);
final String abDesc[] = {"none"};
abDesc[0] = k[2];
String tmpDesc = abDesc[0].substring(11);
int i = tmpDesc.indexOf(".");
tmpDesc = tmpDesc.substring(0, i);
tapTargets.setVTSelection("Select target " + tmpDesc + " to tap.");
abDesc[0] = abCost.toString() + abDesc[0];
final SpellAbility AbTapTgt = new Ability_Activated(card, abCost, tapTargets) {
private static final long serialVersionUID = 2794477584289098775L;
@Override
public boolean canPlayAI() {
//TODO: perhaps this can borrow from the Crowd Favorites AI...
if (!ComputerUtil.canPayCost(this))
return false;
CardList hCards = getTargets();
Random r = new Random();
boolean rr = false;
if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
rr = true;
if(hCards.size() > 0) {
Card c = null;
CardList dChoices = new CardList();
for(int i = 0; i < Tgts.length; i++) {
if (Tgts[i].startsWith("Creature")) {
c = CardFactoryUtil.AI_getBestCreature(hCards);
if (c != null)
dChoices.add(c);
}
CardListUtil.sortByTextLen(hCards);
dChoices.add(hCards.get(0));
CardListUtil.sortCMC(hCards);
dChoices.add(hCards.get(0));
}
c = dChoices.get(CardUtil.getRandomIndex(dChoices));
setTargetCard(c);
return rr;
}
return false;
}
CardList getTargets() {
CardList tmpList = AllZoneUtil.getPlayerCardsInPlay(Constant.Player.Human);
tmpList = tmpList.getValidCards(Tgts);
tmpList = tmpList.getTargetableCards(card);
tmpList = tmpList.filter(AllZoneUtil.tapped);
return tmpList;
}
@Override
public boolean canPlay() {
return (Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
@Override
public void resolve() {
Card tgtC = getTargetCard();
if(AllZone.GameAction.isCardInPlay(tgtC)
&& CardFactoryUtil.canTarget(card, tgtC)) {
tgtC.tap();
}
}
}; //AbTapTgt
AbTapTgt.setDescription(abDesc[0]);
card.addSpellAbility(AbTapTgt);
card.setSVar("PlayMain1", "TRUE");
}//End abTapTgt
// Generic tap target ___ activated ability
//abTapAll {Ability_Cost}:{Valid Targets}:{Description}
if (hasKeyword(card, "abTapAll") != -1)
{
int n = hasKeyword(card, "abTapAll");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmpCost = k[0].substring(8);
final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName(), true);
//final Target tapTargets = new Target("TgtV");
String Targets = k[1];
final String Tgts[] = Targets.split(",");
//tapTargets.setValidTgts(Tgts);
final String abDesc[] = {"none"};
final String stackDesc[] = {"none"};
stackDesc[0] = k[2];
String tmpDesc = stackDesc[0].substring(8);
int i = tmpDesc.indexOf(".");
tmpDesc = tmpDesc.substring(0, i);
//tapTargets.setVTSelection("Select target " + tmpDesc + " to tap.");
abDesc[0] = abCost.toString() + stackDesc[0];
final SpellAbility AbTapAll = new Ability_Activated(card, abCost, null) {
private static final long serialVersionUID = 2161279836590135215L;
@Override
public boolean canPlayAI() {
if (!ComputerUtil.canPayCost(this))
return false;
CardList hCards = getTargets();
Random r = new Random();
boolean rr = false;
if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
rr = true;
if(hCards.size() > 0) {
CardList human = hCards.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.getController().equals(Constant.Player.Human);
}
});
CardList compy = hCards.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.getController().equals(Constant.Player.Human);
}
});
if(human.size() > compy.size()) {
return rr;
}
}
return false;
}
private CardList getTargets() {
CardList tmpList = AllZoneUtil.getCardsInPlay();
tmpList = tmpList.getValidCards(Tgts);
tmpList = tmpList.getTargetableCards(card);
tmpList = tmpList.filter(AllZoneUtil.tapped);
return tmpList;
}
@Override
public boolean canPlay() {
return (Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
@Override
public void resolve() {
CardList tgts = getTargets();
for(Card c:tgts) {
if(AllZone.GameAction.isCardInPlay(c)
&& CardFactoryUtil.canTarget(card, c)) {
c.tap();
}
}
}
}; //AbTapTgt
AbTapAll.setDescription(abDesc[0]);
AbTapAll.setStackDescription(card.getName()+" - "+stackDesc[0]);
card.addSpellAbility(AbTapAll);
card.setSVar("PlayMain1", "TRUE");
}//End abTapAll
// Generic untap target ___ activated ability
//abUntapTgt {Ability_Cost}:{Valid Targets}:{Description}
if (hasKeyword(card, "abUntapTgt") != -1)
{
int n = hasKeyword(card, "abUntapTgt");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
String tmpCost = k[0].substring(10);
final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName(), true);
final Target untapTargets = new Target("TgtV");
final String Tgts[] = k[1].split(",");
untapTargets.setValidTgts(Tgts);
final String abDesc[] = {"none"};
abDesc[0] = k[2];
String tmpDesc = abDesc[0].substring(13);
int i = tmpDesc.indexOf(".");
tmpDesc = tmpDesc.substring(0, i);
untapTargets.setVTSelection("Select target " + tmpDesc + " to untap.");
abDesc[0] = abCost.toString() + abDesc[0];
final SpellAbility AbUntapTgt = new Ability_Activated(card, abCost, untapTargets) {
private static final long serialVersionUID = 6286367744794697322L;
@Override
public boolean canPlayAI() {
if (!ComputerUtil.canPayCost(this))
return false;
CardList hCards = getTargets();
Random r = new Random();
boolean rr = false;
if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
rr = true;
if(hCards.size() > 0) {
Card c = null;
CardList dChoices = new CardList();
for(int i = 0; i < Tgts.length; i++) {
if (Tgts[i].startsWith("Creature")) {
c = CardFactoryUtil.AI_getBestCreature(hCards);
if (c != null)
dChoices.add(c);
}
CardListUtil.sortByTextLen(hCards);
dChoices.add(hCards.get(0));
CardListUtil.sortCMC(hCards);
dChoices.add(hCards.get(0));
}
c = dChoices.get(CardUtil.getRandomIndex(dChoices));
setTargetCard(c);
return rr;
}
return false;
}
CardList getTargets() {
CardList tmpList = AllZoneUtil.getPlayerCardsInPlay(Constant.Player.Human);
tmpList = tmpList.getValidCards(Tgts);
tmpList = tmpList.getTargetableCards(card);
tmpList = tmpList.filter(AllZoneUtil.untapped);
return tmpList;
}
@Override
public boolean canPlay() {
return (Cost_Payment.canPayAdditionalCosts(abCost, this) && CardFactoryUtil.canUseAbility(card) && super.canPlay());
}
@Override
public void resolve() {
Card tgtC = getTargetCard();
if(AllZone.GameAction.isCardInPlay(tgtC)
&& CardFactoryUtil.canTarget(card, tgtC)) {
tgtC.untap();
}
}
}; //AbTapTgt
AbUntapTgt.setDescription(abDesc[0]);
card.addSpellAbility(AbUntapTgt);
}//End abUntapTgt
//**************************************************
// AbilityFactory cards
ArrayList<String> IA = card.getIntrinsicAbilities();
if (IA.size() > 0)
{
if (card.isInstant() || card.isSorcery())
card.clearSpellAbility();
for (int i=0; i<IA.size(); i++)
{
AbilityFactory AF = new AbilityFactory();
SpellAbility sa = AF.getAbility(IA.get(i), card);
card.addSpellAbility(sa);
String bbCost = card.getSVar("Buyback");
if (!bbCost.equals(""))
{
SpellAbility bbSA = sa.copy();
String newCost = CardUtil.addManaCosts(card.getManaCost(), bbCost);
bbSA.setManaCost(newCost);
if (bbSA.payCosts != null)
bbSA.payCosts.setMana(newCost); // abCost value needs to be increased for paying spells
StringBuilder sb = new StringBuilder();
sb.append("Buyback ").append(bbCost).append(" (You may pay an additional ").append(bbCost);
sb.append(" as you cast this spell. If you do, put this card into your hand as it resolves.)");
bbSA.setDescription(sb.toString());
bbSA.setIsBuyBackAbility(true);
card.addSpellAbility(bbSA);
}
}
}
//******************************************************************
//************** Link to different CardFactories *******************
Card card2 = null;
if(card.getType().contains("Creature")) {
card2 = CardFactory_Creatures.getCard(card, cardName, owner, this);
} else if(card.getType().contains("Aura")) {
card2 = CardFactory_Auras.getCard(card, cardName, owner);
} else if(card.getType().contains("Equipment")) {
card2 = CardFactory_Equipment.getCard(card, cardName, owner);
} else if(card.getType().contains("Planeswalker")) {
card2 = CardFactory_Planeswalkers.getCard(card, cardName, owner);
} else if(card.getType().contains("Land")) {
card2 = CardFactory_Lands.getCard(card, cardName, owner);
} else if (card.getType().contains("Instant")) {
card2 = CardFactory_Instants.getCard(card, cardName, owner);
} else if (card.getType().contains("Sorcery")) {
card2 = CardFactory_Sorceries.getCard(card, cardName, owner);
}
if (card2 != null)
return postFactoryKeywords(card2);
//*************** START *********** START **************************
else if(cardName.equals("Pyrohemia")) {
SpellAbility ability = new Ability(card, "R") {
@Override
public boolean canPlayAI() {
CardList human = new CardList(AllZone.Human_Play.getCards());
CardList computer = new CardList(AllZone.Computer_Play.getCards());
human = human.getType("Creature");
computer = computer.getType("Creature");
return AllZone.Computer_Life.getLife() > 2 && !(human.size() == 0 && 0 < computer.size());
}
@Override
public void resolve() {
//get all creatures
CardList list = new CardList();
list.addAll(AllZone.Human_Play.getCards());
list.addAll(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
for(int i = 0; i < list.size(); i++) {
if(CardFactoryUtil.canDamage(card, list.get(i))) list.get(i).addDamage(1, card);
}
//AllZone.Human_Life.subtractLife(1,card);
AllZone.GameAction.addDamage(Constant.Player.Human, card, 1);
//AllZone.Computer_Life.subtractLife(1,card);
AllZone.GameAction.addDamage(Constant.Player.Computer, card, 1);
}//resolve()
};//SpellAbility
ability.setDescription("R: Pyrohemia deals 1 damage to each creature and each player.");
ability.setStackDescription(card + " deals 1 damage to each creature and each player.");
card.clearSpellAbility();
card.addSpellAbility(new Spell_Permanent(card) {
private static final long serialVersionUID = 5596915641671666843L;
@Override
public boolean canPlayAI() {
//get all creatures
CardList list = new CardList();
list.addAll(AllZone.Human_Play.getCards());
list.addAll(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
return 0 < list.size();
}
});
card.addSpellAbility(ability);
card.setSVar("PlayMain1", "TRUE");
}
//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Pestilence")) {
SpellAbility ability = new Ability(card, "B") {
@Override
public boolean canPlayAI() {
CardList human = new CardList(AllZone.Human_Play.getCards());
CardList computer = new CardList(AllZone.Computer_Play.getCards());
human = human.getType("Creature");
computer = computer.getType("Creature");
return AllZone.Computer_Life.getLife() > 2 && !(human.size() == 0 && 0 < computer.size());
}
@Override
public void resolve() {
//get all creatures
CardList list = new CardList();
list.addAll(AllZone.Human_Play.getCards());
list.addAll(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
for(int i = 0; i < list.size(); i++) {
if(CardFactoryUtil.canDamage(card, list.get(i))) list.get(i).addDamage(1, card);
}
//AllZone.Human_Life.subtractLife(1,card);
//AllZone.Computer_Life.subtractLife(1,card);
AllZone.GameAction.addDamage(Constant.Player.Human, card, 1);
AllZone.GameAction.addDamage(Constant.Player.Computer, card, 1);
}//resolve()
};//SpellAbility
ability.setDescription("B: Pestilence deals 1 damage to each creature and each player.");
ability.setStackDescription(card + " deals 1 damage to each creature and each player.");
card.clearSpellAbility();
card.addSpellAbility(new Spell_Permanent(card) {
private static final long serialVersionUID = -4163089323122672307L;
@Override
public boolean canPlayAI() {
//get all creatures
CardList list = new CardList();
list.addAll(AllZone.Human_Play.getCards());
list.addAll(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
return 0 < list.size();
}
});
card.addSpellAbility(ability);
card.setSVar("PlayMain1", "TRUE");
}
//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Bridge from Below")) {
SpellAbility spell = new Spell_Permanent(card) {
private static final long serialVersionUID = 7254358703158629514L;
@Override
public boolean canPlayAI() {
return false;
}
};
card.clearSpellAbility();
card.addSpellAbility(spell);
}
//*************** END ************ END *************************
//*************** START *********** START **************************
else if(cardName.equals("Nevinyrral's Disk")) {
SpellAbility summoningSpell = new Spell_Permanent(card) {
private static final long serialVersionUID = -8859376851358601934L;
@Override
public boolean canPlayAI() {
boolean nevinyrralInPlay = false;
CardList inPlay = new CardList();
inPlay.addAll(AllZone.Computer_Play.getCards());
for(int i = 0; i < inPlay.size(); ++i) {
if(inPlay.getCard(i).getName().equals("Nevinyrral's Disk")) {
nevinyrralInPlay = true;
}
}
return !nevinyrralInPlay && (0 < CardFactoryUtil.AI_getHumanCreature(card, false).size());
}
};
card.clearSpellAbility();
card.addSpellAbility(summoningSpell);
card.addComesIntoPlayCommand(new Command() {
private static final long serialVersionUID = -2504426622672629123L;
public void execute() {
card.tap();
}
});
final SpellAbility ability = new Ability_Tap(card, "1") {
private static final long serialVersionUID = 4175577092552330100L;
@Override
public void resolve() {
CardList all = new CardList();
all.addAll(AllZone.Human_Play.getCards());
all.addAll(AllZone.Computer_Play.getCards());
all = filter(all);
for(int i = 0; i < all.size(); i++)
AllZone.GameAction.destroy(all.get(i));
}
private CardList filter(CardList list) {
return list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isArtifact() || c.isCreature() || c.isEnchantment();
}
});
}//filter()
@Override
public boolean canPlayAI() {
CardList human = new CardList(AllZone.Human_Play.getCards());
CardList computer = new CardList(AllZone.Computer_Play.getCards());
human = human.getType("Creature");
computer = computer.getType("Creature");
//the computer will at least destroy 2 more human creatures
return AllZone.Phase.getPhase().equals(Constant.Phase.Main2) &&
(computer.size() < human.size() - 1 || AllZone.Computer_Life.getLife() < 7);
}
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("1, tap: Destroy all artifacts, creatures, and enchantments.");
ability.setStackDescription("Destroy all artifacts, creatures, and enchantments.");
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Conspiracy") || cardName.equals("Cover of Darkness")
|| cardName.equals("Door of Destinies") || cardName.equals("Engineered Plague")
|| cardName.equals("Shared Triumph") || cardName.equals("Belbe's Portal")
|| cardName.equals("Steely Resolve")) {
final String[] input = new String[1];
final String player = card.getController();
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
if(player.equals(Constant.Player.Human)) {
input[0] = JOptionPane.showInputDialog(null, "Which creature type?", "Pick type",
JOptionPane.QUESTION_MESSAGE);
if(!CardUtil.isCreatureType(input[0])) input[0] = "";
//TODO: some more input validation, case-sensitivity, etc.
input[0] = input[0].trim(); //this is to prevent "cheating", and selecting multiple creature types,eg "Goblin Soldier"
} else {
String chosenType = CardFactoryUtil.chooseCreatureTypeAI(card);
if(!chosenType.equals("")) input[0] = chosenType;
else input[0] = "Sliver"; //what to put here for the AI???
}
card.setChosenType(input[0]);
}
};//ability
Command intoPlay = new Command() {
private static final long serialVersionUID = 5634360316643996274L;
public void execute() {
ability.setStackDescription("When " + card.getName()
+ " comes into play, choose a creature type.");
AllZone.Stack.add(ability);
}
};
card.addComesIntoPlayCommand(intoPlay);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Sarpadian Empires, Vol. VII")) {
final String[] choices = {"Citizen", "Camarid", "Thrull", "Goblin", "Saproling"};
final String player = card.getController();
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
String type = "";
String imageName = "";
String color = "";
if(player.equals(Constant.Player.Computer)) {
type = "Thrull";
imageName = "B 1 1 Thrull";
color = "B";
} else if(player.equals(Constant.Player.Human)) {
Object q = AllZone.Display.getChoiceOptional("Select type of creature", choices);
if(q != null){
if(q.equals("Citizen")) {
type = "Citizen";
imageName = "W 1 1 Citizen";
color = "W";
} else if(q.equals("Camarid")) {
type = "Camarid";
imageName = "U 1 1 Camarid";
color = "U";
} else if(q.equals("Thrull")) {
type = "Thrull";
imageName = "B 1 1 Thrull";
color = "B";
} else if(q.equals("Goblin")) {
type = "Goblin";
imageName = "R 1 1 Goblin";
color = "R";
} else if(q.equals("Saproling")) {
type = "Saproling";
imageName = "G 1 1 Saproling";
color = "G";
}
}
}
card.setChosenType(type);
final String t = type;
final String in = imageName;
final String col = color;
//card.setChosenType(input[0]);
final Ability_Tap a1 = new Ability_Tap(card, "3") {
private static final long serialVersionUID = -2114111483117171609L;
@Override
public void resolve() {
CardFactoryUtil.makeToken(t, in, card, col, new String[] {"Creature", t}, 1, 1,
new String[] {""});
}
};
// a1.setDescription("3, Tap: Put a 1/1 creature token of the chosen color and type onto the battlefield.");
a1.setStackDescription(card.getName() + " - " + card.getController() + " puts a 1/1" + t
+ " token into play");
card.addSpellAbility(a1);
}
};//ability
Command intoPlay = new Command() {
private static final long serialVersionUID = 7202704600935499188L;
public void execute() {
ability.setStackDescription("As Sarpadian Empires, Vol. VII enters the battlefield, choose white Citizen, blue Camarid, black Thrull, red Goblin, or green Saproling.");
AllZone.Stack.add(ability);
}
};
card.setText("As Sarpadian Empires, Vol. VII enters the battlefield, choose white Citizen, blue Camarid, black Thrull, red Goblin, or green Saproling.\r\n"
+ "3, Tap: Put a 1/1 creature token of the chosen color and type onto the battlefield.\r\n"
+ card.getText()); // In the slight chance that there may be a need to add a note to this card.
card.addComesIntoPlayCommand(intoPlay);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Eternity Vessel")) {
Command intoPlay = new Command() {
private static final long serialVersionUID = 7202704600935499188L;
public void execute() {
int player = 0;
if(card.getController() == "Human") {
player = AllZone.Human_Life.getLife();
} else {
player = AllZone.Computer_Life.getLife();
}
card.addCounter(Counters.CHARGE, player);
}
};
card.addComesIntoPlayCommand(intoPlay);
}//*************** END ************ END **************************
/* converted to keyword
//*************** START *********** START **************************
else if(cardName.equals("Dragon Roost")) {
final SpellAbility ability = new Ability(card, "5 R R") {
@Override
public void resolve() {
CardFactoryUtil.makeToken("Dragon", "R 5 5 Dragon", card, "R", new String[] {
"Creature", "Dragon"}, 5, 5, new String[] {"Flying"});
}//resolve()
};
ability.setDescription("5RR: Put a 5/5 red Dragon creature token with flying into play.");
ability.setStackDescription("Dragon Roost - Put a 5/5 red Dragon creature token with flying into play.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
*/
/* converted to keyword
//*************** START *********** START **************************
else if(cardName.equals("The Hive")) {
final SpellAbility ability = new Ability_Tap(card, "5") {
private static final long serialVersionUID = -1091111822316858416L;
@Override
public void resolve() {
CardFactoryUtil.makeToken("Wasp", "C 1 1 Wasp", card, "", new String[] {
"Artifact", "Creature", "Insect"}, 1, 1, new String[] {"Flying"});
}//resolve()
};
ability.setDescription("5, tap: Put a 1/1 Insect artifact creature token with flying named Wasp into play.");
ability.setStackDescription("The Hive - Put a 1/1 token with flying into play.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
*/
/*
//*************** START *********** START **************************
else if(cardName.equals("Mobilization")) {
final SpellAbility ability = new Ability(card, "2 W") {
@Override
public void resolve() {
CardFactoryUtil.makeToken("Soldier", "W 1 1 Soldier", card, "W", new String[] {
"Creature", "Soldier"}, 1, 1, new String[] {""});
}//resolve()
};
ability.setDescription("2W: Put a 1/1 white Soldier creature token into play.");
ability.setStackDescription("Mobilization - Put a 1/1 Soldier token into play.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
*/
/* converted to keyword
//*************** START *********** START **************************
else if(cardName.equals("Centaur Glade")) {
final SpellAbility ability = new Ability(card, "2 G G") {
@Override
public void resolve() {
CardFactoryUtil.makeToken("Centaur", "G 3 3 Centaur", card, "G", new String[] {
"Creature", "Centaur"}, 3, 3, new String[] {""});
}//resolve()
};
ability.setDescription("2GG: Put a 3/3 green Centaur creature token into play.");
ability.setStackDescription("Centaur Glade - Put a 3/3 token into play.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
*/
//*************** START *********** START **************************
else if(cardName.equals("Oblivion Ring")) {
final CommandReturn getPerm = new CommandReturn() {
public Object execute() {
//get all creatures
CardList tempList = new CardList();
tempList.addAll(AllZone.Human_Play.getCards());
tempList.addAll(AllZone.Computer_Play.getCards());
CardList list = new CardList();
for(int i = 0; i < tempList.size(); i++) {
if(tempList.get(i).isPermanent() && !tempList.get(i).isLand()
&& CardFactoryUtil.canTarget(card, tempList.get(i))) list.add(tempList.get(i));
}
//remove "this card"
list.remove(card);
return list;
}
};//CommandReturn
final SpellAbility abilityComes = new Ability(card, "0") {
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
AllZone.GameAction.removeFromGame(getTargetCard());
}
}//resolve()
};
final Input inputComes = new Input() {
private static final long serialVersionUID = -3613946694360326887L;
@Override
public void showMessage() {
CardList choice = (CardList) getPerm.execute();
stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice,
"Select target permanent to remove from the game", true, false));
ButtonUtil.disableAll();//to disable the Cancel button
}
};
Command commandComes = new Command() {
private static final long serialVersionUID = -6250376920501373535L;
public void execute() {
CardList perm = (CardList) getPerm.execute();
String s = card.getController();
if(perm.size() == 0) return;
else if(s.equals(Constant.Player.Human)) AllZone.InputControl.setInput(inputComes);
else //computer
{
Card target;
//try to target human creature
CardList human = CardFactoryUtil.AI_getHumanCreature(card, true);
target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty
// try to target human permanent
if(target == null) {
int convertedCost = 0;
CardList tempList = new CardList();
tempList.addAll(AllZone.Human_Play.getCards());
for(int i = 0; i < tempList.size(); i++) {
if(tempList.get(i).isPermanent()
&& !tempList.get(i).isLand()
&& CardFactoryUtil.canTarget(card, tempList.get(i))
&& (CardUtil.getConvertedManaCost(tempList.get(i).getManaCost()) > convertedCost)) {
target = tempList.get(i);
convertedCost = CardUtil.getConvertedManaCost(tempList.get(i).getManaCost());
}
}
}
//target something cheaper (manacost 0?) instead:
if(target == null) {
CardList humanPerms = new CardList();
humanPerms.addAll(AllZone.Human_Play.getCards());
humanPerms = humanPerms.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isPermanent() && !c.isLand() && CardFactoryUtil.canTarget(card, c);
}
});
if(humanPerms.size() > 0) target = humanPerms.get(0);
}
if(target == null) {
//must target computer creature
CardList computer = new CardList(AllZone.Computer_Play.getCards());
computer = computer.getType("Creature");
computer.remove(card);
computer.shuffle();
if(computer.size() != 0) target = computer.get(0);
else target = card;
}
abilityComes.setTargetCard(target);
AllZone.Stack.add(abilityComes);
}//else
}//execute()
};//CommandComes
Command commandLeavesPlay = new Command() {
private static final long serialVersionUID = 6997038208952910355L;
public void execute() {
Object o = abilityComes.getTargetCard();
if(o == null || ((Card) o).isToken() || !AllZone.GameAction.isCardRemovedFromGame((Card) o)) return;
SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
//copy card to reset card attributes like attack and defense
Card c = abilityComes.getTargetCard();
if(!c.isToken()) {
c = AllZone.CardFactory.dynamicCopyCard(c);
c.setController(c.getOwner());
PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner());
PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, c.getOwner());
removed.remove(c);
if (c.isTapped())
c.untap();
play.add(c);
}
}//resolve()
};//SpellAbility
ability.setStackDescription("Oblivion Ring - returning permanent to play.");
AllZone.Stack.add(ability);
}//execute()
};//Command
card.addComesIntoPlayCommand(commandComes);
card.addLeavesPlayCommand(commandLeavesPlay);
card.setSVar("PlayMain1", "TRUE");
card.clearSpellAbility();
card.addSpellAbility(new Spell_Permanent(card) {
private static final long serialVersionUID = -3250095291930182087L;
@Override
public boolean canPlayAI() {
Object o = getPerm.execute();
if(o == null) return false;
CardList cList = new CardList(AllZone.Human_Play.getCards());
cList = cList.filter(new CardListFilter()
{
public boolean addCard(Card crd)
{
return CardFactoryUtil.canTarget(card, crd) && crd.isPermanent() && !crd.isLand();
}
});
CardList cl = (CardList) getPerm.execute();
return (o != null) && cList.size() > 0 && cl.size() > 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand);
}
});
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Oubliette")) {
final SpellAbility enchantment = new Spell(card) {
private static final long serialVersionUID = -6751177094537759827L;
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
AllZone.GameAction.removeFromGame(getTargetCard());
//put permanent into play
Card c = getSourceCard();
AllZone.getZone(Constant.Zone.Play, c.getController()).add(c);
}
}//resolve()
@Override
public boolean canPlayAI() {
//try to target human creature
CardList human = CardFactoryUtil.AI_getHumanCreature(card, true);
Card target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty
if(target == null) return false;
else {
setTargetCard(target);
return true;
}
}//canPlayAI()
};//SpellAbility enchantment
/*
@SuppressWarnings("unused") // target
final Input target = new Input()
{
private static final long serialVersionUID = -251660220889858176L;
//showMessage() is always the first method called
public void showMessage()
{
AllZone.Display.showMessage("Select creature to remove from the game (sorry no phasing yet).");
ButtonUtil.enableOnlyCancel();
}
public void selectButtonCancel() {stop();}
public void selectCard(Card c, PlayerZone zone)
{
if(!CardFactoryUtil.canTarget(enchantment, c)){
AllZone.Display.showMessage("Cannot target this card (Shroud? Protection?).");
}
else if(zone.is(Constant.Zone.Play) && c.isCreature())
{
enchantment.setTargetCard(c);
stopSetNext(new Input_PayManaCost(enchantment));
}
}
};//Input target
*/
Command commandLeavesPlay = new Command() {
private static final long serialVersionUID = -2535098005246027777L;
public void execute() {
Object o = enchantment.getTargetCard();
if(o == null || ((Card) o).isToken() || !AllZone.GameAction.isCardRemovedFromGame((Card) o)) return;
SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
//copy card to reset card attributes like attack and defense
Card c = enchantment.getTargetCard();
if(!c.isToken()) {
c = AllZone.CardFactory.copyCard(c);
c.setController(c.getOwner());
PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner());
play.add(c);
}
}//resolve()
};//SpellAbility
ability.setStackDescription(card.getName() + " - returning creature to play");
AllZone.Stack.add(ability);
}//execute()
};//Command
card.addLeavesPlayCommand(commandLeavesPlay);
card.clearSpellAbility();
card.addSpellAbility(enchantment);
card.setSVar("PlayMain1", "TRUE");
enchantment.setBeforePayMana(CardFactoryUtil.input_targetCreature(enchantment));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Test Destroy")) {
final SpellAbility spell = new Spell(card) {
private static final long serialVersionUID = 6637283804612570910L;
@Override
public boolean canPlayAI() {
return false;
}
@Override
public void resolve() {
AllZone.GameAction.destroy(getTargetCard());
}//resolve()
};
card.clearSpellAbility();
spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell, "All"));
card.addSpellAbility(spell);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Take Possession")) {
final SpellAbility spell = new Spell(card) {
private static final long serialVersionUID = -7359291736123492910L;
@Override
public boolean canPlayAI() {
return 0 < CardFactoryUtil.AI_getHumanCreature(card, true).size();
}
@Override
public void chooseTargetAI() {
Card best = CardFactoryUtil.AI_getBestCreature(CardFactoryUtil.AI_getHumanCreature(card, true));
setTargetCard(best);
}
@Override
public void resolve() {
Card c = getTargetCard();
c.setController(card.getController());
((PlayerZone_ComesIntoPlay) AllZone.Human_Play).setTriggers(false);
((PlayerZone_ComesIntoPlay) AllZone.Computer_Play).setTriggers(false);
PlayerZone from = AllZone.getZone(c);
PlayerZone to = AllZone.getZone(Constant.Zone.Play, card.getController());
from.remove(c);
to.add(c);
((PlayerZone_ComesIntoPlay) AllZone.Human_Play).setTriggers(true);
((PlayerZone_ComesIntoPlay) AllZone.Computer_Play).setTriggers(true);
}//resolve()
};
card.clearSpellAbility();
spell.setBeforePayMana(CardFactoryUtil.input_targetType(spell, "All"));
card.addSpellAbility(spell);
card.setSVar("PlayMain1", "TRUE");
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Belbe's Portal")) {
final SpellAbility ability = new Ability_Tap(card, "3") {
private static final long serialVersionUID = 3790805878629855813L;
@Override
public boolean canPlayAI() {
return getCreature().size() != 0;
}
@Override
public void chooseTargetAI() {
card.tap();
Card target = CardFactoryUtil.AI_getBestCreature(getCreature());
setTargetCard(target);
}
CardList getCreature() {
CardList list = new CardList(AllZone.Computer_Hand.getCards());
list = list.getType(card.getChosenType());
return list;
}
@Override
public void resolve() {
Card c = getTargetCard();
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController());
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
if(AllZone.GameAction.isCardInZone(c, hand)) {
hand.remove(c);
play.add(c);
}
}
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("3, tap: Put a creature card of the chosen type from your hand into play.");
final Command paid = new Command() {
private static final long serialVersionUID = 4258139342966165260L;
public void execute() {
AllZone.InputControl.resetInput();
AllZone.Stack.add(ability);
}
};
final Command unpaid = new Command() {
private static final long serialVersionUID = 5792270994683837097L;
public void execute() {
card.untap();
}
};
final Input target = new Input() {
private static final long serialVersionUID = -3180364352114242238L;
@Override
public void showMessage() {
ButtonUtil.enableOnlyCancel();
AllZone.Display.showMessage("Select creature from your hand to put into play");
}
@Override
public void selectCard(Card c, PlayerZone zone) {
if(c.isCreature() && zone.is(Constant.Zone.Hand, Constant.Player.Human)
&& c.getType().contains(card.getChosenType())) {
card.tap();
ability.setTargetCard(c);//since setTargetCard() changes stack description
ability.setStackDescription("Put into play " + c);
AllZone.InputControl.setInput(new Input_PayManaCost_Ability(ability.getManaCost(), paid,
unpaid));
}
}
@Override
public void selectButtonCancel() {
card.untap();
stop();
}
};//Input target
ability.setBeforePayMana(target);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("That Which Was Taken")) {
final SpellAbility ability = new Ability_Tap(card, "4") {
private static final long serialVersionUID = -8996435083734446340L;
@Override
public void resolve() {
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c))
//c.addExtrinsicKeyword("Indestructible");
c.addCounter(Counters.DIVINITY, 1);
}
@Override
public boolean canPlayAI() {
CardList perms = getPerms();
return perms.size()>0;
}
@Override
public void chooseTargetAI() {
//Card c = CardFactoryUtil.AI_getBestCreature(getCreatures());
CardList a = getPerms();
if (a.size()>0) {
//CardListUtil.sortAttack(a);
//CardListUtil.sortFlying(a);
setTargetCard(a.get(0));
}
}
CardList getPerms() {
CardList list = new CardList();
list.addAll(AllZone.Computer_Play.getCards());
list = list.filter(new CardListFilter(){
public boolean addCard(Card c)
{
return c.getCounters(Counters.DIVINITY) == 0 && (CardUtil.getConvertedManaCost(c.getManaCost()) > 3 || c.getNetAttack() > 4) &&
!c.getName().equals("That Which Was Taken");
}
});
return list;
}
};//SpellAbility
Input target = new Input() {
private static final long serialVersionUID = 137806881250205274L;
@Override
public void showMessage() {
AllZone.Display.showMessage("Select target permanent");
ButtonUtil.enableOnlyCancel();
}
@Override
public void selectButtonCancel() {
stop();
}
@Override
public void selectCard(Card c, PlayerZone zone) {
if(zone.is(Constant.Zone.Play) && c != card)//cannot target self
{
ability.setTargetCard(c);
stopSetNext(new Input_PayManaCost(ability));
}
}
};//Input -- target
ability.setBeforePayMana(target);
ability.setDescription("4, tap: Tap a divinity counter on target permanent other than That Which Was Taken.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Midsummer Revel")) {
final SpellAbility ability = new Ability(card, "G") {
@Override
public boolean canPlayAI() {
if(card.getCounters(Counters.VERSE) > 0) return true;
return false;
}
@Override
public void resolve() {
for(int i = 0; i < card.getCounters(Counters.VERSE); i++) {
CardFactoryUtil.makeToken("Beast", "G 3 3 Beast", card, "G", new String[] {
"Creature", "Beast"}, 3, 3, new String[] {""});
}
AllZone.GameAction.sacrifice(card);
}
};
card.addSpellAbility(ability);
ability.setStackDescription(cardName
+ " puts X 3/3 green Beast creature tokens onto the battlefield");
ability.setDescription("G, Sacrifice Midsummer Revel: Put X 3/3 green Beast creature tokens onto the battlefield, where X is the number of verse counters on Midsummer Revel.");
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Necrogenesis")) {
final SpellAbility necrogen = new Ability(card, "2") {
private static final long serialVersionUID = 1299216756153970592L;
@Override
public void resolve() {
Card c = getTargetCard();
if (AllZone.getZone(c).is(Constant.Zone.Graveyard)){
// target is still in the grave, ability resolves
AllZone.GameAction.exile(c);
CardFactoryUtil.makeTokenSaproling(card.getController());
}
}
@Override
public boolean canPlayAI(){
return false;
}
@Override
public boolean canPlay(){
CardList list = new CardList(AllZone.Human_Graveyard.getCards());
list.addAll(AllZone.Computer_Graveyard.getCards());
return list.getType("Creature").size() > 0 && super.canPlay();
}
};
Input necroTarget = new Input() {
boolean once = false;
private static final long serialVersionUID = 8243511353958609599L;
@Override
public void showMessage() {
CardList list = new CardList(AllZone.Human_Graveyard.getCards());
list.addAll(AllZone.Computer_Graveyard.getCards());
list = list.getType("Creature");
if (list.size() == 0 || once) {
once = false;
stop();
}
else {
Object o = AllZone.Display.getChoice("Choose card to exile", list.toArray());
if (o!=null)
{
Card c = (Card)o;
necrogen.setTargetCard(c);
once = true;
AllZone.Stack.add(necrogen);
}
}
stop();
}
};
necrogen.setDescription("2: Exile target creature card in a graveyard. Put a 1/1 green Saproling creature token into play.");
necrogen.setStackDescription(card.getController()
+ " exiles target creature card in a graveyard. Puts a 1/1 green Saproling creature token into play.");
necrogen.setAfterPayMana(necroTarget);
card.addSpellAbility(necrogen);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Night Soil")) {
final SpellAbility nightSoil = new Ability(card, "1") {
@Override
public void resolve() {
CardFactoryUtil.makeTokenSaproling(card.getController());
}
@Override
public boolean canPlayAI(){
return false;
}
@Override
public boolean canPlay(){
CardList grave = new CardList(AllZone.Human_Graveyard.getCards());
CardList aiGrave = new CardList(AllZone.Computer_Graveyard.getCards());
return (grave.getType("Creature").size() > 1 || aiGrave.getType("Creature").size() > 1) && super.canPlay();
}
};
Input soilTarget = new Input() {
boolean once = false;
private static final long serialVersionUID = 8243511353958609599L;
@Override
public void showMessage() {
CardList grave = new CardList(AllZone.Human_Graveyard.getCards());
CardList aiGrave = new CardList(AllZone.Computer_Graveyard.getCards());
grave = grave.getType("Creature");
aiGrave = aiGrave.getType("Creature");
if (once || (grave.size() < 2 && aiGrave.size() < 2)) {
once = false;
stop();
}
else {
CardList chooseGrave;
if (grave.size() < 2)
chooseGrave = aiGrave;
else if (aiGrave.size() < 2)
chooseGrave = grave;
else{
chooseGrave = aiGrave;
chooseGrave.addAll(grave.toArray());
}
Object o = AllZone.Display.getChoice("Choose first card to exile", chooseGrave.toArray());
if (o!=null)
{
CardList newGrave;
Card c = (Card)o;
if (c.getOwner().equals("Human")){
newGrave = new CardList(AllZone.Human_Graveyard.getCards());
}
else {
newGrave = new CardList(AllZone.Computer_Graveyard.getCards());
}
newGrave = newGrave.getType("Creature");
newGrave.remove(c);
Object o2 = AllZone.Display.getChoice("Choose second card to exile", newGrave.toArray());
if (o2!=null)
{
Card c2 = (Card)o2;
newGrave.remove(c2);
AllZone.GameAction.exile(c);
AllZone.GameAction.exile(c2);
once = true;
AllZone.Stack.add(nightSoil);
}
}
}
stop();
}
};
nightSoil.setDescription("1, Exile target creature card in a graveyard: Put a 1/1 green Saproling creature token into play.");
nightSoil.setStackDescription(card.getController()
+ " put a 1/1 green Saproling creature token into play.");
nightSoil.setAfterPayMana(soilTarget);
card.addSpellAbility(nightSoil);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Yawgmoth's Bargain")) {
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
AllZone.GameAction.drawCard(card.getController());
}
@Override
public boolean canPlayAI() {
return false;
}
};//SpellAbility
ability.setDescription("Pay 1 life: Draw a card.");
ability.setStackDescription(card.getName() + " - Pay 1 life: Draw a card.");
card.addSpellAbility(ability);
//instead of paying mana, pay life and add to stack
//Input showMessage() is always the first method called
Input payLife = new Input() {
private static final long serialVersionUID = 8660593629867722192L;
@Override
public void showMessage() {
boolean paid = AllZone.GameAction.payLife(card.getController(), 1, card);
//this order is very important, do not change
stop();
if (paid)
AllZone.Stack.push(ability);
}
};//Input
ability.setBeforePayMana(payLife);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Necropotence")) {
final CardList necroCards = new CardList();
final Command necro = new Command() {
private static final long serialVersionUID = 4511445425867383336L;
public void execute() {
//put cards removed by Necropotence into player's hand
if(necroCards.size() > 0) {
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController());
for(int i = 0; i < necroCards.size(); i++) {
hand.add(necroCards.get(i));
}
necroCards.clear();
}
}
};
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController());
if(library.size() != 0) {
Card c = library.get(0);
library.remove(0);
necroCards.add(c); //add card to necro so that it goes into hand at end of turn
AllZone.EndOfTurn.addAt(necro);
}
}
@Override
public boolean canPlayAI() {
return false;
}
};//SpellAbility
ability.setDescription("1 life: Set aside the top card of your library face down. At the end of your turn, put that card into your hand.");
ability.setStackDescription(card.getName()
+ " - 1 life: Set aside the top card of your library face down. At the end of your turn, put that card into your hand.");
card.addSpellAbility(ability);
//instead of paying mana, pay life and add to stack
//Input showMessage() is always the first method called
Input payLife = new Input() {
private static final long serialVersionUID = -3846772748411690084L;
@Override
public void showMessage() {
boolean paid = AllZone.GameAction.payLife(card.getController(), 1, card);
//this order is very important, do not change
stop();
if (paid)
AllZone.Stack.push(ability);
}
};//Input
ability.setBeforePayMana(payLife);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Hoofprints of the Stag")) {
Command intoPlay = new Command() {
private static final long serialVersionUID = -7275454992618058248L;
public boolean firstTime = true;
public void execute() {
if(firstTime) {
card.setCounter(Counters.HOOFPRINT, 0, false);
}
firstTime = false;
}
};
card.addComesIntoPlayCommand(intoPlay);
final SpellAbility a2 = new Ability(card, "2 W") {
@Override
public void resolve() {
card.subtractCounter(Counters.HOOFPRINT, 4);
CardFactoryUtil.makeToken("Elemental", "W 4 4 Elemental", card, "W", new String[] {
"Creature", "Elemental"}, 4, 4, new String[] {"Flying"});
}
@Override
public boolean canPlay() {
SpellAbility sa;
for(int i = 0; i < AllZone.Stack.size(); i++) {
sa = AllZone.Stack.peek(i);
if(sa.getSourceCard().equals(card)) return false;
}
return card.getCounters(Counters.HOOFPRINT) >= 4
&& AllZone.getZone(card).is(Constant.Zone.Play)
&& AllZone.Phase.getActivePlayer().equals(card.getController())
&& !AllZone.Phase.getPhase().equals("End of Turn");
}//canPlay()
@Override
public boolean canPlayAI() {
return true;
}
};//spellAbility
a2.setDescription("2 W, Remove four hoofprint counters from Hoofprints of the Stag: Put a 4/4 white Elemental creature token with flying into play. Play this ability only during your turn.");
a2.setStackDescription(card.getName()
+ " - put a 4/4 white Elemental creature token with flying into play.");
card.addSpellAbility(a2);
}//*************** END ************ END **************************
/*
//*************** START *********** START **************************
else if(cardName.equals("Goblin Trenches")) {
final String player = card.getController();
final SpellAbility ability = new Ability(card, "2") {
@Override
public boolean canPlay() {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
CardList lands = new CardList();
lands.addAll(play.getCards());
lands = lands.getType("Land");
if(lands.size() >= 1 && AllZone.GameAction.isCardInPlay(card)) return true;
else return false;
}
@Override
public void chooseTargetAI() {
Card c = getTappedLand(); //first, try to get a tapped land to sac
if(c != null) {
setTargetCard(c);
} else {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
CardList lands = new CardList();
lands.addAll(play.getCards());
lands = lands.getType("Land");
c = lands.get(0);
setTargetCard(c);
}
}
public Card getTappedLand() {
//target creature that is going to attack
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
CardList lands = new CardList();
lands.addAll(play.getCards());
lands = lands.getType("Land");
for(int i = 0; i < lands.size(); i++) {
if(lands.get(i).isTapped()) return lands.get(i);
}
return null;
}//getAttacker()
@Override
public boolean canPlayAI() {
String phase = AllZone.Phase.getPhase();
return phase.equals(Constant.Phase.Main2);
}
@Override
public void resolve() {
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c)) {
AllZone.GameAction.sacrifice(c);
makeToken();
makeToken();
}
}//resolve
public void makeToken() {
CardFactoryUtil.makeToken("Goblin Soldier", "RW 1 1 Goblin Soldier", card, "RW", new String[] {
"Creature", "Goblin", "Soldier"}, 1, 1, new String[] {""});
}
};
Input runtime = new Input() {
private static final long serialVersionUID = -7823269301012427007L;
@Override
public void showMessage() {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
CardList lands = new CardList();
lands.addAll(play.getCards());
lands = lands.getType("Land");
stopSetNext(CardFactoryUtil.input_targetSpecific(ability, lands, "Select a land to sacrifice",
false, false));
}//showMessage()
};//Input
card.addSpellAbility(ability);
ability.setDescription("2, Sacrifice a land: Put two 1/1 red and white Goblin Soldier creature tokens into play.");
ability.setStackDescription(card.getName()
+ " - put two 1/1 red and white Goblin Soldier creature tokens into play.");
ability.setBeforePayMana(runtime);
}//*************** END ************ END **************************
*/
//*************** START *********** START **************************
else if(cardName.equals("Hatching Plans")) {
final Ability ability = new Ability(card, "0") {
@Override
public void resolve() {
AllZone.GameAction.drawCards(card.getController(), 3);
//AllZone.GameAction.drawCard(card.getController());
//AllZone.GameAction.drawCard(card.getController());
}
};
Command draw3Cards = new Command() {
private static final long serialVersionUID = -4919203791300685078L;
public void execute() {
ability.setStackDescription(card.getName() + " - draw three cards.");
AllZone.Stack.add(ability);
}
};
card.addDestroyCommand(draw3Cards);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Dragon Blood")) {
Ability_Tap ability = new Ability_Tap(card, "3") {
private static final long serialVersionUID = -8095802059752537764L;
@Override
public void resolve() {
if(getTargetCard() != null && getTargetCard().isCreature()
&& CardFactoryUtil.canTarget(card, getTargetCard())) getTargetCard().addCounter(
Counters.P1P1, 1);
}
@Override
public boolean canPlayAI() {
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.getType("Creature");
if(list.size() > 0) {
setTargetCard(CardFactoryUtil.AI_getBestCreature(list));
return (getTargetCard() != null);
}
return false;
}
};
ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability));
ability.setDescription("3, tap: Put a +1/+1 counter on target creature.");
StringBuilder sb = new StringBuilder();
sb.append(card).append(": put a +1/+1 counter on target Creature.");
ability.setStackDescription(sb.toString());
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("AEther Vial")) {
//final int[] converted = null;
final Ability_Tap ability = new Ability_Tap(card, "0") {
private static final long serialVersionUID = 1854859213307704018L;
@Override
public boolean canPlay() {
return card.getCounters(Counters.CHARGE) > 0;
}
@Override
public void resolve() {
String player = card.getController();
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player);
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
//converted[0] = card.getCounters(Counters.CHARGE);
//System.out.println("converted: " + converted[0]);
CardList list = new CardList(hand.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return CardUtil.getConvertedManaCost(c.getManaCost()) == card.getCounters(Counters.CHARGE)
&& c.isCreature();
}
});
if(list.size() > 0) {
if(player.equals(Constant.Player.Human)) {
Object o = AllZone.Display.getChoiceOptional("Pick creature to put into play",
list.toArray());
if(o != null) {
Card c = (Card) o;
hand.remove(c);
play.add(c);
}
} else {
Card c = list.get(0);
if(AllZone.GameAction.isCardInZone(c, hand)) {
hand.remove(c);
play.add(c);
}
}
}
}
};
ability.setDescription("Tap: You may put a creature card with converted mana cost equal to the number of charge counters on AEther Vial from your hand into play.");
ability.setStackDescription(card.getName()
+ " - put creature card with converted mana cost equal to the number of charge counters into play.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("AEther Spellbomb")) {
Ability_Cost abCost = new Ability_Cost("U Sac<1/CARDNAME>", cardName, true);
String[] valid = {"Creature"};
Target abTgt = new Target("TgtV", "Target a creature to bounce", valid);
final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt) {
private static final long serialVersionUID = 1L;
@Override
public boolean canPlay() {
return AllZone.GameAction.isCardInPlay(card);
}
@Override
public boolean canPlayAI() {
CardList humanPlay = new CardList(AllZone.Human_Play.getCards());
humanPlay = humanPlay.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isCreature() && CardFactoryUtil.canTarget(card, c);
}
});
if(humanPlay.size() > 0) setTargetCard(CardFactoryUtil.AI_getBestCreature(humanPlay));
return ((AllZone.Computer_Hand.size() > 2) && (getTargetCard() != null));
}
@Override
public void resolve() {
final Card[] target = new Card[1];
target[0] = getTargetCard();
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, target[0].getOwner());
if(AllZone.GameAction.isCardInPlay(target[0]) && CardFactoryUtil.canTarget(card, target[0])) {
if(!target[0].isToken()) AllZone.GameAction.moveTo(hand, target[0]);
else AllZone.getZone(target[0]).remove(target[0]);
}
}//resolve()
};//SpellAbility
ability.setDescription("U, Sacrifice AEther Spellbomb: Return target creature to its owner's hand.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Lifespark Spellbomb")) {
Ability_Cost abCost = new Ability_Cost("G Sac<1/CARDNAME>", cardName, true);
String[] valid = {"Land"};
Target abTgt = new Target("TgtV", "Target a land to animate", valid);
final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt) {
private static final long serialVersionUID = -5744842090293912606L;
@Override
public boolean canPlay() {
return AllZone.GameAction.isCardInPlay(card);
}
@Override
public boolean canPlayAI() {
CardList land = new CardList(AllZone.Computer_Play.getCards());
land = land.getType("Land");
CardList basic = land.getType("Basic");
if(basic.size() < 3) return false;
Card[] basic_1 = basic.toArray();
for(Card var:basic_1)
if(var.isTapped()) basic.remove(var);
basic.shuffle();
if(basic.size() == 0) return false;
if(basic.get(0) != null) {
setTargetCard(basic.get(0));
return true;
}
return false;
}//canPlayAI()
@Override
public void resolve() {
//in case ability is played twice
final int[] oldAttack = new int[1];
final int[] oldDefense = new int[1];
final Card card[] = new Card[1];
card[0] = getTargetCard();
oldAttack[0] = card[0].getBaseAttack();
oldDefense[0] = card[0].getBaseDefense();
card[0].setBaseAttack(3);
card[0].setBaseDefense(3);
card[0].addType("Creature");
//EOT
final Command untilEOT = new Command() {
private static final long serialVersionUID = 7236360479349324099L;
public void execute() {
card[0].setBaseAttack(oldAttack[0]);
card[0].setBaseDefense(oldDefense[0]);
card[0].removeType("Creature");
card[0].unEquipAllCards();
}
};
AllZone.EndOfTurn.addUntil(untilEOT);
}//resolve()
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("G, Sacrifice Lifespark Spellbomb: Target land becomes a 3/3 Creature until end of turn. It is still a land.");
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Necrogen Spellbomb")) {
Ability_Cost abCost = new Ability_Cost("B Sac<1/CARDNAME>", cardName, true);
String[] valid = {"player"};
Target abTgt = new Target("TgtV","Target player discards a card", valid);
final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt) {
private static final long serialVersionUID = -5712428914792877529L;
@Override
public boolean canPlay() {
return AllZone.GameAction.isCardInPlay(card);
}
@Override
public boolean canPlayAI() {
setTargetPlayer(Constant.Player.Human);
return (MyRandom.random.nextBoolean() && AllZone.Human_Hand.size() > 0);
}
@Override
public void resolve() {
String s = getTargetPlayer();
StringBuilder sb = new StringBuilder();
sb.append("Necrogen Spellbomb - ").append(s).append(" discards a card");
setStackDescription(sb.toString());
// setStackDescription("Necrogen Spellbomb - " + s + " discards a card");
if(Constant.Player.Computer.equals(getTargetPlayer())) AllZone.GameAction.discardRandom(getTargetPlayer(), this);
else AllZone.InputControl.setInput(CardFactoryUtil.input_discard(this));
}//resolve()
};//SpellAbility
ability.setDescription("B, Sacrifice Necrogen Spellbomb: Target player discards a card.");
card.addSpellAbility(ability);
} //*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Sensei's Divining Top")) {
//ability2: Draw card, and put divining top on top of library
final SpellAbility ability2 = new Ability_Tap(card, "0") {
private static final long serialVersionUID = -2523015092351744208L;
@Override
public void resolve() {
String player = card.getController();
String owner = card.getOwner();
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, owner);
AllZone.GameAction.drawCard(player);
play.remove(card);
lib.add(card, 0); //move divining top to top of library
card.untap();
}
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
if(AllZone.getZone(card).is(Constant.Zone.Play)) return true;
else return false;
}//canPlay()
};//SpellAbility ability2
ability2.setBeforePayMana(new Input() {
private static final long serialVersionUID = -4773496833654414458L;
@Override
public void showMessage() {
AllZone.Stack.push(ability2);
stop();
}//showMessage()
});
//ability (rearrange top 3 cards) :
final SpellAbility ability1 = new Ability(card, "1") {
@Override
public void resolve() {
String player = card.getController();
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
if(lib.size() < 3) return;
CardList topThree = new CardList();
//show top 3 cards:
topThree.add(lib.get(0));
topThree.add(lib.get(1));
topThree.add(lib.get(2));
for(int i = 1; i <= 3; i++) {
String Title = "Put on top: ";
if(i == 2) Title = "Put second from top: ";
if(i == 3) Title = "Put third from top: ";
Object o = AllZone.Display.getChoiceOptional(Title, topThree.toArray());
if(o == null) break;
Card c_1 = (Card) o;
topThree.remove(c_1);
lib.remove(c_1);
lib.add(c_1, i - 1);
}
}
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
if(AllZone.getZone(card).is(Constant.Zone.Play)) return true;
else return false;
}//canPlay()
};//SpellAbility ability1
ability1.setDescription("1: Look at the top three cards of your library, then put them back in any order.");
ability1.setStackDescription("Sensei's Divining Top - rearrange top 3 cards");
card.addSpellAbility(ability1);
ability1.setBeforePayMana(new Input_PayManaCost(ability1));
ability2.setDescription("tap: Draw a card, then put Sensei's Divining Top on top of its owner's library.");
ability2.setStackDescription("Sensei's Divining Top - draw a card, then put back on owner's library");
ability2.setBeforePayMana(new Input_NoCost_TapAbility((Ability_Tap) ability2));
card.addSpellAbility(ability2);
}
//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Quicksilver Amulet")) {
final SpellAbility ability = new Ability_Tap(card, "4") {
private static final long serialVersionUID = 4414609319033894302L;
@Override
public boolean canPlayAI() {
return (getCreature().size() > 0);
}
@Override
public void chooseTargetAI() {
card.tap();
Card target = CardFactoryUtil.AI_getBestCreature(getCreature());
setTargetCard(target);
}
CardList getCreature() {
CardList list = new CardList(AllZone.Computer_Hand.getCards());
list = list.getType("Creature");
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return (c.getCMC() > 4);
}
});
return list;
}
@Override
public void resolve() {
Card c = getTargetCard();
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController());
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
if(AllZone.GameAction.isCardInZone(c, hand)) {
hand.remove(c);
play.add(c);
}
}
};
ability.setBeforePayMana(new Input() {
private static final long serialVersionUID = -1647181037510967127L;
@Override
public void showMessage() {
String controller = card.getController();
CardList creats = new CardList(AllZone.getZone(Constant.Zone.Hand, controller).getCards());
creats = creats.filter(new CardListFilter() {
public boolean addCard(Card c) {
PlayerZone zone = AllZone.getZone(c);
return c.isCreature() && zone.is(Constant.Zone.Hand);
}
});
stopSetNext(CardFactoryUtil.input_targetSpecific(ability, creats, "Select a creature", false,
false));
}
});
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Chalice of the Void")) {
Command intoPlay = new Command() {
private static final long serialVersionUID = -7679939432259603542L;
public void execute() {
int XCounters = card.getXManaCostPaid();
card.addCounter(Counters.CHARGE, XCounters);
}
};
card.addComesIntoPlayCommand(intoPlay);
}
//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Counterbalance")) {
String player = card.getController();
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController());
Card topCard = lib.get(0);
SpellAbility sa = AllZone.Stack.peek();
int convertedManaTopCard = CardUtil.getConvertedManaCost(topCard.getManaCost());
int convertedManaSpell = CardUtil.getConvertedManaCost(sa.getSourceCard().getManaCost());
CardList showTop = new CardList();
showTop.add(topCard);
AllZone.Display.getChoiceOptional("Revealed top card: ", showTop.toArray());
if(convertedManaTopCard == convertedManaSpell) {
AllZone.Stack.pop();
AllZone.GameAction.moveToGraveyard(sa.getSourceCard());
}
}
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
String player = card.getController();
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
if(AllZone.Stack.size() == 0 || lib.size() == 0) return false;
//see if spell is on stack and that opponent played it
String opponent = AllZone.GameAction.getOpponent(card.getController());
SpellAbility sa = AllZone.Stack.peek();
if(AllZone.getZone(card).is(Constant.Zone.Play) && sa.isSpell()
&& opponent.equals(sa.getSourceCard().getController())
&& CardFactoryUtil.isCounterable(sa.getSourceCard())) return true;
else return false;
}//canPlay()
};//SpellAbility ability
ability.setStackDescription("Counterbalance - " + player
+ " reveals top card and counters spell if it has the same converted manacost");
//ability.setBeforePayMana(new Input_PayManaCost(ability));
card.addSpellAbility(ability);
}
//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Aluren")) {
final Ability ability1 = new Ability(card, "0") {
@Override
public void resolve() {
//String player = card.getController();
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, Constant.Player.Human);
PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
if(hand.size() == 0) return;
CardList creatures = new CardList();
for(int i = 0; i < hand.size(); i++) {
if(hand.get(i).getType().contains("Creature")
&& CardUtil.getConvertedManaCost(hand.get(i).getManaCost()) <= 3) creatures.add(hand.get(i));
}
if(creatures.size() == 0) return;
Object o = AllZone.Display.getChoiceOptional("Select target creature to play",
creatures.toArray());
if(o != null) {
Card c = (Card) o;
hand.remove(c);
play.add(c);
c.setSickness(true);
}
}
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
if(AllZone.getZone(card).is(Constant.Zone.Play)) return true;
else return false;
}//canPlay()
};//SpellAbility ability1
ability1.setDescription("Any player may play creature cards with converted mana cost 3 or less without paying their mana cost any time he or she could play an instant.");
ability1.setStackDescription("Aluren - Play creature with converted manacost 3 or less for free.");
ability1.setAnyPlayer(true);
card.addSpellAbility(ability1);
}
//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Survival of the Fittest")) {
SpellAbility ability = new Ability(card, "G") {
@Override
public void resolve() {
String player = card.getController();
if(player.equals(Constant.Player.Human)) humanResolve();
else computerResolve();
}//resolve()
public void humanResolve() {
CardList handCreatures = new CardList(AllZone.Human_Hand.getCards());
handCreatures = handCreatures.getType("Creature");
if(handCreatures.size() == 0) return;
Object discard = AllZone.Display.getChoiceOptional("Select Creature to discard",
handCreatures.toArray());
if(discard != null) {
CardList creatures = new CardList(AllZone.Human_Library.getCards());
creatures = creatures.getType("Creature");
if(creatures.size() != 0) {
Object check = AllZone.Display.getChoiceOptional("Select Creature",
creatures.toArray());
if(check != null) {
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController());
AllZone.GameAction.moveTo(hand, (Card) check);
}
AllZone.GameAction.shuffle(Constant.Player.Human);
}
AllZone.GameAction.discard((Card) discard, this);
}
}
public void computerResolve() {
//TODO
}
@Override
public boolean canPlayAI() {
return false;
}
};//SpellAbility
//card.clearSpellAbility();
ability.setDescription("G: Discard a creature card: Search your library for a creature card, reveal that card, and put it into your hand. Then shuffle your library.");
ability.setStackDescription("Survival of the Fittest - search for a creature card and put into hand");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Volrath's Dungeon")) {
final SpellAbility dungeon = new Ability(card, "0") {
// todo(sol) discard really needs to happen as a cost but in resolution for now :(
@Override
public void chooseTargetAI() {
setTargetPlayer(Constant.Player.Human);
}
@Override
public boolean canPlay() {
return Phase.canCastSorcery(Constant.Player.Human) && AllZone.GameAction.isCardInPlay(card) && super.canPlay() &&
AllZone.getZone(Constant.Zone.Hand, Constant.Player.Human).getCards().length > 0;
}
@Override
public void resolve() {
String player = getActivatingPlayer();
String target = getTargetPlayer();
CardList playerHand = new CardList(AllZone.getZone(Constant.Zone.Hand, player).getCards());
CardList targetHand = new CardList(AllZone.getZone(Constant.Zone.Hand, target).getCards());
if(playerHand.size() == 0) return;
if (player == Constant.Player.Human){
if (!humanDiscard(playerHand, false))
return;
}
else if (player == Constant.Player.Computer){
if (!computerDiscard(playerHand, false))
return;
}
if (targetHand.size() == 0) return;
if (target == Constant.Player.Human){
if (!humanDiscard(targetHand, true))
return;
}
else if (target == Constant.Player.Computer){
if (!computerDiscard(targetHand, true))
return;
}
}
public boolean humanDiscard(CardList hand, boolean toLibrary)
{
String destination = "discard";
if (toLibrary)
destination = "place on top of library.";
Object discard = AllZone.Display.getChoiceOptional("Select Card to " + destination,
hand.toArray());
if(discard == null) return false;
Card card = (Card)discard;
if (toLibrary)
AllZone.GameAction.moveToTopOfLibrary(card);
else
AllZone.GameAction.discard(card, this);
return true;
}
public boolean computerDiscard(CardList hand, boolean toLibrary)
{
if (toLibrary)
AllZone.GameAction.AI_handToLibrary("Top");
else
AllZone.GameAction.AI_discard(this);
return true;
}
@Override
public boolean canPlayAI() {
return (card.getController().equals(Constant.Player.Computer) && Phase.canCastSorcery(Constant.Player.Computer)
&& AllZone.getZone(Constant.Zone.Hand, Constant.Player.Computer).getCards().length > 0
&& AllZone.getZone(Constant.Zone.Hand, getTargetPlayer()).getCards().length > 0);
}
};//SpellAbility dungeon
final SpellAbility bail = new Ability(card, "0") {
// Life payment really should happen on activation, maybe can do with a popup?
@Override
public void resolve() {
String player = getActivatingPlayer();
if (AllZone.GameAction.payLife(player, 5, card))
AllZone.GameAction.destroy(card);
}
@Override
public boolean canPlay() {
if(AllZone.Human_Life.getLife() >= 5 && AllZone.GameAction.isPlayerTurn(Constant.Player.Human) && super.canPlay())
return true;
else return false;
}
@Override
public boolean canPlayAI() {
if (card.getController().equals(Constant.Player.Human) && AllZone.Computer_Life.getLife() >= 9 &&
AllZone.GameAction.isPlayerTurn(Constant.Player.Computer) &&
AllZone.GameAction.isCardInPlay(card))
return true;
else return false;
}
};//SpellAbility pay bail
dungeon.setBeforePayMana(CardFactoryUtil.input_targetPlayer(dungeon));
dungeon.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
dungeon.setDescription("Discard a card: Target player puts a card from his or her hand on top of his or her library. Activate this ability only any time you could cast a sorcery.");
dungeon.setStackDescription("CARDNAME - Target player chooses a card in hand and puts on top of library.");
bail.setAnyPlayer(true);
bail.setDescription("Pay 5 Life: Destroy Volrath's Dungeon. Any player may activate this ability but only during his or her turn.");
bail.setStackDescription("Destroy CARDNAME.");
card.addSpellAbility(dungeon);
card.addSpellAbility(bail);
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Ior Ruin Expedition")) {
final SpellAbility ability = new Ability(card, "0") {
@Override
public boolean canPlay() {
return card.getCounters(Counters.QUEST) >= 3 && AllZone.GameAction.isCardInPlay(card)
&& !AllZone.Stack.getSourceCards().contains(card);//in play and not already activated(Sac cost problems)
}
@Override
public boolean canPlayAI() {
return (AllZone.Computer_Hand.size() < 6) && (AllZone.Computer_Library.size() > 0);
}
@Override
public void resolve() {
AllZone.GameAction.drawCard(card.getController());
AllZone.GameAction.drawCard(card.getController());
AllZone.GameAction.sacrifice(getSourceCard());
}
};
ability.setDescription("Remove three quest counters from Ior Ruin Expedition and sacrifice it: Draw two cards.");
ability.setStackDescription(card.getName() + " - Draw two cards.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Khalni Heart Expedition")) {
final SpellAbility ability = new Ability(card, "0") {
@Override
public boolean canPlay() {
return card.getCounters(Counters.QUEST) >= 3 && AllZone.GameAction.isCardInPlay(card)
&& !AllZone.Stack.getSourceCards().contains(card);//in play and not already activated(Sac cost problems)
}
@Override
public boolean canPlayAI() {
return (AllZone.Computer_Library.size() > 0);
}
@Override
public void resolve() {
// Sacrifice this first, otherwise the land search triggers
// the landfall ability
AllZone.GameAction.sacrifice(getSourceCard());
// Put two basic lands into play tapped
AllZone.GameAction.searchLibraryTwoBasicLand(card.getController(),
Constant.Zone.Play, true, Constant.Zone.Play, true);
}
};
ability.setDescription("Remove three quest counters from Khalni Heart Expedition and sacrifice it: search your library for two basic lands and put them onto the battlefield tapped.");
ability.setStackDescription(card.getName() + " - Search for land.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
/*
//*************** START *********** START **************************
else if(cardName.equals("Earthcraft")) {
final SpellAbility a1 = new Ability(card, "0") {
private static final long serialVersionUID = 6787319311700905218L;
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
String controller = card.getController();
PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller);
CardList creats = new CardList();
creats.addAll(play.getCards());
creats = creats.getType("Creature");
creats = creats.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isUntapped();
}
});
if(creats.size() > 0 && AllZone.GameAction.isCardInPlay(card)) return true;
else return false;
}
@Override
public void resolve() {
if(getTargetCard() == null) return;
String player = card.getController();
if(player.equals(Constant.Player.Human)) humanResolve();
//else
// computerResolve();
}
public void humanResolve() {
String controller = card.getController();
PlayerZone play = AllZone.getZone(Constant.Zone.Play, controller);
CardList creats = new CardList();
creats.addAll(play.getCards());
creats = creats.getType("Creature");
creats = creats.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isUntapped() && !c.equals(card);
}
});
if(creats.size() == 1) {
creats.get(0).tap();
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) getTargetCard().untap();
} else if(creats.size() > 1) {
Object o = AllZone.Display.getChoice("Select creature to tap", creats.toArray());
if(o != null) {
Card c1 = (Card) o;
c1.tap();
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) getTargetCard().untap();
}
}
}//humanResolve
};//a1
//card.clearSpellAbility();
card.addSpellAbility(a1);
a1.setDescription("Tap an untapped creature you control: untap target basic land.");
Input runtime = new Input() {
private static final long serialVersionUID = -2287693175821059029L;
@Override
public void showMessage() {
CardList all = new CardList();
all.addAll(AllZone.Human_Play.getCards());
all.addAll(AllZone.Computer_Play.getCards());
all = all.filter(new CardListFilter() {
public boolean addCard(Card c) {
return (c.isBasicLand()) && CardFactoryUtil.canTarget(card, c) && c.isTapped();
}
});
stopSetNext(CardFactoryUtil.input_targetSpecific(a1, all, "Select target basic land", true,
false));
}
};
a1.setBeforePayMana(runtime);
final SpellAbility a2 = new Ability(card,"0")
{
public void resolve() {
CardList list = CardFactoryUtil.getCards("Squirrel Nest",Constant.Player.Human);
list = list.filter(new CardListFilter()
{
public boolean addCard(Card crd)
{
CardList l = new CardList(crd.getEnchanting().toArray());
if (l.size()>0 && l.get(0).isBasicLand() && l.get(0).isUntapped())
return true;
else
return false;
}
});
if (list.size() == 0)
return;
CardList l = new CardList(list.get(0).getEnchanting().toArray());
if (l.size() > 0) {
Card basicLand = l.get(0);
int max = 10;
for (int i=0;i<max;i++)
{
basicLand.tap();
CardList tokens = CardFactoryUtil.makeToken("Squirrel", "G 1 1 Squirrel", basicLand, "G", new String[] {
"Creature", "Squirrel"}, 1, 1, new String[] {""});
if (i < (max-1))
{
tokens.get(0).tap();
basicLand.untap();
}
else
{
;
}
}
}
}
public boolean canPlayAI()
{
return false;
}
public boolean canPlay()
{
CardList list = CardFactoryUtil.getCards("Squirrel Nest", Constant.Player.Human);
list = list.filter(new CardListFilter()
{
public boolean addCard(Card crd)
{
CardList l = new CardList(crd.getEnchanting().toArray());
if (l.size()>0 && l.get(0).isBasicLand() && l.get(0).isUntapped())
return true;
else
return false;
}
});
return super.canPlay() && list.size() > 0;
}
};
card.addSpellAbility(a2);
a2.setDescription("(Shortcut 10x)");
a2.setStackDescription(card + " - add 10 Squirrel tokens using Squirrel Nest");
final SpellAbility a3 = new Ability(card,"0")
{
public void resolve() {
CardList list = CardFactoryUtil.getCards("Squirrel Nest",Constant.Player.Human);
list = list.filter(new CardListFilter()
{
public boolean addCard(Card crd)
{
CardList l = new CardList(crd.getEnchanting().toArray());
if (l.size()>0 && l.get(0).isBasicLand() && l.get(0).isUntapped())
return true;
else
return false;
}
});
if (list.size() == 0)
return;
CardList l = new CardList(list.get(0).getEnchanting().toArray());
if (l.size() > 0) {
Card basicLand = l.get(0);
int max = 30;
for (int i=0;i<max;i++)
{
basicLand.tap();
CardList tokens = CardFactoryUtil.makeToken("Squirrel", "G 1 1 Squirrel", basicLand, "G", new String[] {
"Creature", "Squirrel"}, 1, 1, new String[] {""});
if (i < (max-1))
{
tokens.get(0).tap();
basicLand.untap();
}
else
{
;
}
}
}
}
public boolean canPlayAI()
{
return false;
}
public boolean canPlay()
{
CardList list = CardFactoryUtil.getCards("Squirrel Nest", Constant.Player.Human);
list = list.filter(new CardListFilter()
{
public boolean addCard(Card crd)
{
CardList l = new CardList(crd.getEnchanting().toArray());
if (l.size()>0 && l.get(0).isBasicLand() && l.get(0).isUntapped())
return true;
else
return false;
}
});
return super.canPlay() && list.size() > 0;
}
};
card.addSpellAbility(a3);
a3.setDescription("(Shortcut 30x)");
a3.setStackDescription(card + " - add 30 Squirrel tokens using Squirrel Nest");
}//*************** END ************ END **************************
*/
//*************** START *********** START **************************
else if(cardName.equals("Mox Diamond")) {
final Input discard = new Input() {
private static final long serialVersionUID = -1319202902385425204L;
@Override
public void showMessage() {
AllZone.Display.showMessage("Discard a land card (or select Mox Diamond to sacrifice it)");
ButtonUtil.enableOnlyCancel();
}
@Override
public void selectCard(Card c, PlayerZone zone) {
if(zone.is(Constant.Zone.Hand) && c.isLand()) {
AllZone.GameAction.discard(c, null);
stop();
} else if(c.equals(card)) {
AllZone.GameAction.sacrifice(card);
stop();
}
}
};//Input
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
if(card.getController().equals(Constant.Player.Human)) {
if(AllZone.Human_Hand.getCards().length == 0) AllZone.GameAction.sacrifice(card);
else AllZone.InputControl.setInput(discard);
} else {
CardList list = new CardList(AllZone.Computer_Hand.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return (c.isLand());
}
});
AllZone.GameAction.discard(list.get(0), this);
}//else
}//resolve()
};//SpellAbility
Command intoPlay = new Command() {
private static final long serialVersionUID = -7679939432259603542L;
public void execute() {
ability.setStackDescription("If Mox Diamond would come into play, you may discard a land card instead. If you do, put Mox Diamond into play. If you don't, put it into its owner's graveyard.");
AllZone.Stack.add(ability);
}
};
SpellAbility spell = new Spell_Permanent(card) {
private static final long serialVersionUID = -1818766848857998431L;
//could never get the AI to work correctly
//it always played the same card 2 or 3 times
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController());
CardList list = new CardList(hand.getCards());
list.remove(card);
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return (c.isLand());
}
});
return list.size() != 0 && super.canPlay();
}//canPlay()
};
card.addComesIntoPlayCommand(intoPlay);
card.clearSpellKeepManaAbility();
card.addSpellAbility(spell);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Standstill")) {
card.clearSpellAbility();
card.addSpellAbility(new Spell_Permanent(card) {
private static final long serialVersionUID = 6912683989507840172L;
@Override
public boolean canPlayAI() {
PlayerZone compPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
PlayerZone humPlay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
CardList compCreats = new CardList(compPlay.getCards());
compCreats = compCreats.getType("Creature");
CardList humCreats = new CardList(humPlay.getCards());
humCreats = humCreats.getType("Creature");
//only play standstill if comp controls more creatures than human
//this needs some additional rules, maybe add all power + toughness and compare
if(compCreats.size() > humCreats.size()) return true;
else return false;
}
});
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Legacy Weapon")) {
final Ability ability = new Ability(card, "W U B R G") {
@Override
public void resolve() {
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c)) {
AllZone.GameAction.removeFromGame(c);
}
}
@Override
public void chooseTargetAI() {
PlayerZone hplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
CardList human = new CardList(hplay.getCards());
human = human.filter(new CardListFilter() {
public boolean addCard(Card c) {
return CardFactoryUtil.canTarget(card, c);
}
});
if(human.size() != 0) {
setTargetCard(CardFactoryUtil.AI_getMostExpensivePermanent(human, card, true));
}
}
@Override
public boolean canPlayAI() {
PlayerZone hplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
CardList human = new CardList(hplay.getCards());
human = human.filter(new CardListFilter() {
public boolean addCard(Card c) {
return CardFactoryUtil.canTarget(card, c);
}
});
return human.size() > 0;
}
};//ability
Input target = new Input() {
private static final long serialVersionUID = -7279903055386088569L;
@Override
public void showMessage() {
AllZone.Display.showMessage("Select target permanent for " + ability.getSourceCard());
ButtonUtil.enableOnlyCancel();
}
@Override
public void selectButtonCancel() {
stop();
}
@Override
public void selectCard(Card crd, PlayerZone zone) {
if(zone.is(Constant.Zone.Play) && CardFactoryUtil.canTarget(card, crd)) {
ability.setTargetCard(crd);
stopSetNext(new Input_PayManaCost(ability));
}
}
};//Input
ability.setDescription("W U B R G: Exile target permanent.");
ability.setBeforePayMana(target);
card.addSpellAbility(ability);
}//*************** END ************ END **************************
/*
//*************** START *********** START **************************
else if(cardName.equals("Voltaic Key")) {
final Ability_Tap ability = new Ability_Tap(card, "1") {
private static final long serialVersionUID = 6097818373831898299L;
@Override
public void resolve() {
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c) && c.isTapped()) c.untap();
}
@Override
public boolean canPlayAI() {
return false;
}
};//ability
Input target = new Input() {
private static final long serialVersionUID = -7279903055386088569L;
@Override
public void showMessage() {
AllZone.Display.showMessage("Select target tapped artifact for " + ability.getSourceCard());
ButtonUtil.enableOnlyCancel();
}
@Override
public void selectButtonCancel() {
stop();
}
@Override
public void selectCard(Card crd, PlayerZone zone) {
if(zone.is(Constant.Zone.Play) && CardFactoryUtil.canTarget(card, crd) && crd.isArtifact()
&& crd.isTapped()) {
ability.setTargetCard(crd);
stopSetNext(new Input_PayManaCost(ability));
}
}
};//Input
ability.setDescription("1, tap: Untap target artifact.");
ability.setBeforePayMana(target);
card.addSpellAbility(ability);
}//*************** END ************ END **************************
*/
//*************** START ************ START **************************
else if(cardName.equals("Ashnod's Transmogrant")) {
final String[] Tgts = { "Creature.nonArtifact" };
Ability_Cost abCost = new Ability_Cost("T Sac<1/CARDNAME>", cardName, true);
Target abTgt = new Target("TgtV", "Target a non-Artifact Creature to Transmogrify", Tgts);
final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt){
private static final long serialVersionUID = -401631574059431293L;
@Override
public void resolve() {
Card crd = getTargetCard();
// if it's not a valid target on resolution, spell fizzles
if (crd == null || !AllZone.GameAction.isCardInPlay(crd) || !crd.isValidCard(Tgts))
return;
crd.addCounter(Counters.P1P1, 1);
// trick to get Artifact on the card type side of the type line
ArrayList<String> types = crd.getType();
types.add(0, "Artifact");
crd.setType(types);
}
@Override
public boolean canPlayAI() {
CardList list = new CardList(AllZone.Computer_Play.getCards()).filter(new CardListFilter() {
public boolean addCard(Card c) {
return !c.isArtifact() && c.isCreature();
}
});
Card crd = CardFactoryUtil.AI_getBestCreature(list);
if(crd != null) setTargetCard(crd);
return (getTargetCard() != null);
}
};
ability.setDescription(abCost.toString() + "Put a +1/+1 counter on target nonartifact creature. That creature becomes an artifact in addition to its other types.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START ************ START **************************
else if(cardName.equals("Gemstone Array")) {
final Ability store = new Ability(card, "2") {
@Override
public void resolve() {
card.addCounter(Counters.CHARGE, 1);
}
@Override
public boolean canPlayAI() {
return AllZone.Phase.is(Constant.Phase.Main2, Constant.Player.Computer);
}
};
store.setDescription("2: Put a charge counter on Gemstone Array.");
store.setStackDescription("Put a charge counter on Gemstone Array");
card.addSpellAbility(store);
final Ability_Mana retrieve = new Ability_Mana(card,
"0, Remove a charge counter from Gemstone Array: Add one mana of any color to your mana pool.") {
private static final long serialVersionUID = -2938965362221626028L;
@Override
public void undo() {
card.addCounter(Counters.CHARGE, 1);
}
//@Override
public String mana() {
return this.choices_made[0].toString();
}
@Override
public boolean canPlay() {
if(choices_made[0] == null) choices_made[0] = "1";
return super.canPlay() && card.getCounters(Counters.CHARGE) > 0;
}
@Override
public void resolve() {
card.subtractCounter(Counters.CHARGE, 1);
super.resolve();
}
};
retrieve.choices_made = new String[1];
retrieve.setBeforePayMana(new Input() {
private static final long serialVersionUID = 376497609786542558L;
@Override
public void showMessage() {
retrieve.choices_made[0] = Input_PayManaCostUtil.getShortColorString((String)(AllZone.Display.getChoiceOptional(
"Select a Color", Constant.Color.onlyColors)));
AllZone.Stack.add(retrieve);
stop();
}
});
card.addSpellAbility(retrieve);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Door to Nothingness")) {
Ability_Tap ab1 = new Ability_Tap(card, "G G R R B B U U W W") {
private static final long serialVersionUID = 6665327569823149191L;
@Override
public void resolve() {
// Win / Lose
final String player = getTargetPlayer();
PlayerZone playZone = AllZone.getZone(Constant.Zone.Play, player);
PlayerZone OpplayZone = AllZone.getZone(Constant.Zone.Play, AllZone.GameAction.getOpponent(player));
CardList Platinumlist = new CardList(OpplayZone.getCards());
Platinumlist = Platinumlist.getName("Platinum Angel");
CardList Abyssallist = new CardList(playZone.getCards());
Abyssallist = Abyssallist.getName("Abyssal Persecutor");
if(Platinumlist.size() == 0 && Abyssallist.size() == 0) {
AllZone.GameAction.getPlayerLife(getTargetPlayer()).setLife(0);
if (getTargetPlayer().equals(Constant.Player.Computer)) {
int gameNumber = 0;
if (Constant.Runtime.WinLose.getWin()==1)
gameNumber = 1;
Constant.Runtime.WinLose.setWinMethod(gameNumber,"Door to Nothingness");
}
}
}
@Override
public boolean canPlayAI() {
return true;
}
};
ab1.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
ab1.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ab1));
ab1.setDescription("WWUUBBRRGG, tap, sacrifice Door to Nothingness: Target player loses the game.");
card.addSpellAbility(ab1);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Seal of Cleansing") || cardName.equals("Seal of Primordium")) {
final Ability ability = new Ability(card, "0") {
@Override
public boolean canPlayAI() {
return getArtEnchantments().size() != 0;
}
@Override
public void chooseTargetAI() {
CardList list = getArtEnchantments();
if(list.size() > 0) {
CardListUtil.sortCMC(list);
setTargetCard(list.get(0));
AllZone.GameAction.sacrifice(card);
}
}//chooseTargetAI()
CardList getArtEnchantments() {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
CardList list = new CardList(play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isArtifact() || c.isEnchantment();
}
});
return list;
}//getArtEnchantments()
@Override
public void resolve() {
if(getTargetCard() != null) {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) AllZone.GameAction.destroy(getTargetCard());
}
}//resolve()
};//SpellAbility
Input runtime = new Input() {
private static final long serialVersionUID = -1750678113925588670L;
@Override
public void showMessage() {
//card.addSpellAbility(ability);
//ability.setDescription("Sacrifice " + cardName + ": destroy target artifact or enchantment.");
PlayerZone hplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Human);
PlayerZone cplay = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
CardList choices = new CardList();
choices.addAll(hplay.getCards());
choices.addAll(cplay.getCards());
choices = choices.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isEnchantment() || c.isArtifact();
}
});
stopSetNext(CardFactoryUtil.input_targetSpecific(ability, choices,
"Destroy target artifact or enchantment", new Command() {
private static final long serialVersionUID = -4987328870651000691L;
public void execute() {
AllZone.GameAction.sacrifice(card);
}
}, true, false));
}
};
ability.setDescription("Sacrifice " + card.getName() + ": destroy target artifact or enchantment.");
ability.setBeforePayMana(runtime);
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Seal of Fire") || cardName.equals("Moonglove Extract")) {
final Ability ability = new Ability(card, "0") {
@Override
public boolean canPlayAI() {
return getCreature().size() != 0 || AllZone.Human_Life.getLife() < 4;
}
@Override
public void chooseTargetAI() {
if(AllZone.Human_Life.getLife() < 4) setTargetPlayer(Constant.Player.Human);
else {
CardList list = getCreature();
list.shuffle();
setTargetCard(list.get(0));
}
AllZone.GameAction.sacrifice(card);
}//chooseTargetAI()
CardList getCreature() {
//toughness of 1
CardList list = CardFactoryUtil.AI_getHumanCreature(2, card, true);
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
//only get 1/1 flyers or 2/1 or bigger creatures
return (2 <= c.getNetAttack()) || c.getKeyword().contains("Flying");
}
});
return list;
}//getCreature()
@Override
public void resolve() {
if(getTargetCard() != null) {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard()))
getTargetCard().addDamage(2, card);
} else AllZone.GameAction.addDamage(getTargetPlayer(), card, 2);
}//resolve()
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("Sacrifice " + cardName + ": "+cardName+" deals 2 damage to target creature or player.");
ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, new Command() {
private static final long serialVersionUID = 4180346673509230280L;
public void execute() {
AllZone.GameAction.sacrifice(card);
}
}, true, false));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Seal of Removal")) {
final Ability ability = new Ability(card, "0") {
@Override
public boolean canPlayAI() {
return getCreature().size() != 0;
}
@Override
public void chooseTargetAI() {
CardList list = getCreature();
list.shuffle();
setTargetCard(list.get(0));
AllZone.GameAction.sacrifice(card);
}//chooseTargetAI()
CardList getCreature() {
CardList list = new CardList(AllZone.Human_Play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isCreature()
&& (c.getNetAttack() >= 3 || c.getKeyword().contains("Flying") || c.isEnchanted())
&& CardFactoryUtil.canTarget(card, c);
}
});
return list;
}//getCreature()
@Override
public void resolve() {
if(getTargetCard() != null) {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, getTargetCard().getOwner());
AllZone.GameAction.moveTo(hand, getTargetCard());
}
}
}//resolve()
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("Sacrifice Seal of Removal: return target creature to its owner's hand.");
ability.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability, new Command() {
private static final long serialVersionUID = 2565599788533507611L;
public void execute() {
AllZone.GameAction.sacrifice(card);
}
}));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Kaervek's Spite")) {
final SpellAbility spell = new Spell(card) {
private static final long serialVersionUID = -6259614160639535500L;
@Override
public boolean canPlayAI() {
if(AllZone.Human_Life.getLife() <= 5) return true;
PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer);
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer);
CardList playList = new CardList(play.getCards());
CardList libList = new CardList(lib.getCards());
playList = playList.getName("Academy Rector");
libList = libList.getName("Barren Glory");
return (AllZone.Human_Life.getLife() <= 5) || (playList.size() == 1 && libList.size() >= 1);
}
@Override
public void resolve() {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
PlayerZone hand = AllZone.getZone(Constant.Zone.Play, card.getController());
CardList list = new CardList(play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return !c.getName().equals("Mana Pool");
}
});
CardList handList = new CardList(hand.getCards());
for(Card c:list) {
AllZone.GameAction.sacrifice(c);
}
AllZone.GameAction.discardRandom(card.getController(), handList.size(), this);
PlayerLife life = AllZone.GameAction.getPlayerLife(getTargetPlayer());
life.subtractLife(5,card);
}
};
spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
card.clearSpellAbility();
card.addSpellAbility(spell);
/*
final Command sac = new Command(){
private static final long serialVersionUID = 1643946454479782123L;
public void execute() {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController());
PlayerZone hand = AllZone.getZone(Constant.Zone.Play, card.getController());
CardList list = new CardList(play.getCards());
list = list.filter(new CardListFilter()
{
public boolean addCard(Card c) {
return !c.getName().equals("Mana Pool");
}
});
CardList handList = new CardList(hand.getCards());
for (Card c : list)
{
AllZone.GameAction.sacrifice(c);
}
AllZone.GameAction.discardRandom(card.getController(), handList.size());
}
};
*/
spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Staff of Domination")) {
/*
final Ability_Tap ability2 = new Ability_Tap(card, "2") {
private static final long serialVersionUID = -5513078874305811825L;
@Override
public boolean canPlayAI() {
return AllZone.Phase.getPhase().equals(Constant.Phase.Main2);
}
@Override
public void resolve() {
AllZone.GameAction.gainLife(card.getController(), 1);
}
};//SpellAbility
ability2.setDescription("2, tap: You gain 1 life.");
// ability2.setStackDescription(cardName + " - You gain 1 life.");
StringBuilder sb2 = new StringBuilder();
sb2.append(cardName).append(" - You gain 1 life.");
ability2.setStackDescription(sb2.toString());
*/
final SpellAbility ability3 = new Ability_Tap(card, "3") {
private static final long serialVersionUID = 1125696151526415705L;
@Override
public boolean canPlayAI() {
return getTapped().size() != 0;
}
@Override
public void chooseTargetAI() {
card.tap();
Card target = CardFactoryUtil.AI_getBestCreature(getTapped());
setTargetCard(target);
}
CardList getTapped() {
CardList list = new CardList(AllZone.Computer_Play.getCards());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isCreature() && c.isTapped();
}
});
return list;
}//getTapped()
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
Card c = getTargetCard();
if(c.isTapped()) c.untap();
}
}//resolve()
};//SpellAbility
ability3.setDescription("3, tap: Untap target creature.");
ability3.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability3));
/*
final SpellAbility ability4 = new Ability_Tap(card, "4") {
private static final long serialVersionUID = 8102011024731535257L;
@Override
public boolean canPlayAI() {
return false;
}
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
Card c = getTargetCard();
if(c.isUntapped()) c.tap();
}
}//resolve()
};//SpellAbility
ability4.setDescription("4, tap: Tap target creature.");
ability4.setBeforePayMana(CardFactoryUtil.input_targetCreature(ability4));
*/
/*
final Ability_Tap ability5 = new Ability_Tap(card, "5") {
private static final long serialVersionUID = -8459438547823091716L;
@Override
public boolean canPlayAI() {
return true;
}
@Override
public void resolve() {
AllZone.GameAction.drawCard(card.getController());
}
};//SpellAbility
ability5.setDescription("5, tap: Draw a card.");
// ability5.setStackDescription(card.getName() + " - draw a card.");
StringBuilder sb5 = new StringBuilder();
sb5.append(card.getName()).append(" - draw a card.");
ability5.setStackDescription(sb5.toString());
*/
//card.addSpellAbility(ability2);
card.addSpellAbility(ability3);
//card.addSpellAbility(ability4);
//card.addSpellAbility(ability5);
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Goblin Charbelcher")) {
final Ability_Tap ability = new Ability_Tap(card, "3") {
private static final long serialVersionUID = -840041589720758423L;
@Override
public void resolve() {
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, card.getController());
CardList topOfLibrary = new CardList(lib.getCards());
CardList revealed = new CardList();
if(topOfLibrary.size() == 0) return;
int damage = 0;
int count = 0;
Card c = null;
Card crd;
while(c == null) {
revealed.add(topOfLibrary.get(count));
crd = topOfLibrary.get(count++);
if(crd.isLand() || count == topOfLibrary.size()) {
c = crd;
damage = count;
if(crd.getName().equals("Mountain")) damage = damage * 2;
}
}//while
AllZone.Display.getChoiceOptional("Revealed cards:", revealed.toArray());
if(getTargetCard() != null) {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
getTargetCard().addDamage(damage, card);
}
} else AllZone.GameAction.addDamage(getTargetPlayer(), card, damage);
}
};
ability.setDescription("3, tap: Reveal cards from the top of your library until you reveal a land card. Goblin Charbelcher deals damage equal to the number of nonland cards revealed this way to target creature or player. If the revealed land card was a Mountain, Goblin Charbelcher deals double that damage instead. Put the revealed cards on the bottom of your library in any order.");
ability.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
ability.setBeforePayMana(CardFactoryUtil.input_targetCreaturePlayer(ability, true, false));
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Thopter Foundry")) {
final String player = card.getController();
final SpellAbility ability = new Ability(card, "1") {
@Override
public void chooseTargetAI() {
Card c;
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
CardList meek = new CardList();
meek.addAll(play.getCards());
meek = meek.getName("Sword of the Meek");
if(meek.size() >= 1) c = meek.get(0);
else c = getArtifact();
if(c != null) setTargetCard(c);
}
public Card getArtifact() {
//target creature that is going to attack
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
CardList arts = new CardList();
arts.addAll(play.getCards());
arts = arts.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isArtifact()
&& !c.isToken()
&& (CardUtil.getConvertedManaCost(c.getManaCost()) <= 1 && !c.equals(card) || c.getName().equals(
"Sword of the Meek"));
}
});
if(arts.size() > 0) {
arts.shuffle();
return arts.get(0);
} else return null;
}
@Override
public boolean canPlayAI() {
String phase = AllZone.Phase.getPhase();
return phase.equals(Constant.Phase.Main2) && getArtifact() != null;
}
@Override
public void resolve() {
Card c = getTargetCard();
if(AllZone.GameAction.isCardInPlay(c)) {
AllZone.GameAction.sacrifice(c);
makeToken();
AllZone.GameAction.gainLife(card.getController(), 1);
}
}//resolve
public void makeToken() {
CardFactoryUtil.makeToken("Thopter", "U 1 1 Thopter", card, "U", new String[] {
"Artifact", "Creature", "Thopter"}, 1, 1, new String[] {"Flying"});
}
};
Input runtime = new Input() {
private static final long serialVersionUID = 3557158378851031238L;
@Override
public void showMessage() {
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
CardList arts = new CardList();
arts.addAll(play.getCards());
arts = arts.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isArtifact() && !c.isToken();
}
});
stopSetNext(CardFactoryUtil.input_targetSpecific(ability, arts,
"Select a non-token Artifact to sacrifice", false, false));
}//showMessage()
};//Input
card.addSpellAbility(ability);
ability.setDescription("1, Sacrifice a nontoken artifact: Put a 1/1 blue Thopter artifact creature token with flying onto the battlefield. You gain 1 life.");
ability.setStackDescription(card.getName()
+ " - Put a 1/1 blue Thopter artifact creature token with flying onto the battlefield. You gain 1 life.");
ability.setBeforePayMana(runtime);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Time Vault")) {
final Ability_Cost abCost = new Ability_Cost("T", cardName, true);
final Ability_Activated ability = new Ability_Activated(card, abCost, null){
private static final long serialVersionUID = 5784473766585071504L;
@Override
public void resolve() {
//System.out.println("Turn: " + AllZone.Phase.getTurn());
AllZone.Phase.addExtraTurn(card.getController());
}
};
card.addSpellAbility(ability);
ability.setStackDescription(card + " - take an extra turn after this one.");
ability.setDescription("Tap: Take an extra turn after this one.");
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Millstone") || cardName.equals("Tower of Murmurs")) {
final int millCards = cardName.equals("Millstone") ? 2 : 8;
final String cost = cardName.equals("Millstone") ? "2" : "8";
final String desc = cardName.equals("Millstone") ?
"2, tap: Target player puts the top two cards of his or her library into his or her graveyard." :
"8, tap: Target player puts the top eight cards of his or her library into his or her graveyard.";
Ability_Tap ab1 = new Ability_Tap(card, cost) {
private static final long serialVersionUID = 42470566751344693L;
@Override
public boolean canPlayAI() {
String player = getTargetPlayer();
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
CardList libList = new CardList(lib.getCards());
return libList.size() > 0;
}
@Override
public void resolve() {
AllZone.GameAction.mill(getTargetPlayer(), millCards);
}
};
ab1.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
ab1.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ab1));
ab1.setDescription(desc);
card.addSpellAbility(ab1);
}//*************** END ************ END **************************
//*************** START *********** START **************************
if(cardName.equals("Serpent Generator")) {
final SpellAbility ability = new Ability_Tap(card, "4") {
private static final long serialVersionUID = 8428205362391909464L;
@Override
public void resolve() {
CardFactoryUtil.makeToken(
"Snake",
"C 1 1 Snake",
card,
"",
new String[] {"Artifact", "Creature", "Snake"},
1,
1,
new String[] {"Whenever this creature deals damage to a player, that player gets a poison counter."});
}
};
ability.setStackDescription("Put a 1/1 colorless Snake artifact creature token onto the battlefield. This creature has \"Whenever this creature deals damage to a player, that player gets a poison counter.\"");
ability.setDescription("4, Tap: Put a 1/1 colorless Snake artifact creature token onto the battlefield. This creature has \"Whenever this creature deals damage to a player, that player gets a poison counter.\" (A player with ten or more poison counters loses the game.)");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Illusions of Grandeur")) {
final SpellAbility gainLife = new Ability(card, "0") {
@Override
public void resolve() {
Card c = card;
AllZone.GameAction.gainLife(c.getController(), 20);
}
};
final SpellAbility loseLife = new Ability(card, "0") {
@Override
public void resolve() {
Card c = card;
PlayerLife life = AllZone.GameAction.getPlayerLife(c.getController());
life.subtractLife(20,card);
}
};
Command intoPlay = new Command() {
private static final long serialVersionUID = 502892931516451254L;
public void execute() {
gainLife.setStackDescription(card.getController() + " gains 20 life");
AllZone.Stack.add(gainLife);
}
};
Command leavesPlay = new Command() {
private static final long serialVersionUID = 5772999389072757369L;
public void execute() {
loseLife.setStackDescription(card.getController() + " loses 20 life");
AllZone.Stack.add(loseLife);
}
};
card.addComesIntoPlayCommand(intoPlay);
card.addLeavesPlayCommand(leavesPlay);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Isochron Scepter"))
{
final Ability_Tap freeCast = new Ability_Tap(card, "2")
{
private static final long serialVersionUID = 4455819149429678456L;
@Override
public void resolve() {
if(getSourceCard().getAttachedCards().length == 0)
{
//AllZone.Display.showMessage("You have not exiled a card.");
return;
}
Card c = copyCard(getSourceCard().getAttachedCards()[0]);
if(getSourceCard().getController().equals(Constant.Player.Computer))
{
for(SpellAbility sa:getSourceCard().getAttachedCards()[0].getSpellAbility())
if(sa.canPlayAI())
{
ComputerUtil.playStackFree(sa);
return;
}
}
else AllZone.GameAction.playCardNoCost(c);
}
public boolean canPlay()
{
if (!super.canPlay())
return false;
if (getSourceCard().getAttachedCards().length > 0)
{
Card c = copyCard(getSourceCard().getAttachedCards()[0]);
if (ComputerAI_counterSpells2.KeywordedCounterspells.contains(c.getName()))
{
SpellAbility sa = c.getSpellAbility()[0];
return sa.canPlay();
}
else return true;
}
else
return false;
}
public boolean canPlayAI()
{
if (getSourceCard().getAttachedCards().length == 0)
return false;
for(SpellAbility sa:getSourceCard().getAttachedCards()[0].getSpellAbility())
if(sa.canPlayAI())
return true;
return false;
}
};
freeCast.setDescription("2, Tap: You may copy the exiled card. If you do, you may cast the copy without paying its mana cost");
freeCast.setStackDescription("Copy the exiled card and cast the copy without paying its mana cost.");
final Input exile = new Input() {
private static final long serialVersionUID = -6392468000100283596L;
@Override
public void showMessage() {
AllZone.Display.showMessage("You may exile an Instant with converted mana cost two or less from your hand");
ButtonUtil.enableOnlyCancel();
}
@Override
public void selectCard(Card c, PlayerZone zone) {
if(zone.is(Constant.Zone.Hand) && c.isInstant() && CardUtil.getConvertedManaCost(c) <= 2)
{
AllZone.GameAction.moveTo(AllZone.Human_Removed, c);
card.attachCard(c);
stop();
}
}
@Override
public void selectButtonCancel() {
stop();
}
};//Input
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
if(card.getController().equals(Constant.Player.Human)) {
if(AllZone.Human_Hand.getCards().length > 0)
AllZone.InputControl.setInput(exile);
} else {
CardList list = new CardList(AllZone.Computer_Hand.getCards())
.filter(
new CardListFilter(){
public boolean addCard(Card c)
{
return c.isInstant()
&& CardUtil.getConvertedManaCost(c) <=2 ;
}
});
CardListUtil.sortCMC(list);
list.reverse();
Card c = list.get(0);
AllZone.GameAction.moveTo(AllZone.Human_Removed, c);
card.attachCard(c);
}//else
}//resolve()
};//SpellAbility
Command intoPlay = new Command() {
private static final long serialVersionUID = 9202753910259054021L;
public void execute() {
ability.setStackDescription("Imprint - " + card.getController()
+ " may exile an instant card with converted mana cost 2 or less from their hand.");
AllZone.Stack.add(ability);
}
};
SpellAbility spell = new Spell_Permanent(card) {
private static final long serialVersionUID = -2940969025405788931L;
//could never get the AI to work correctly
//it always played the same card 2 or 3 times
@Override
public boolean canPlayAI() {
for(Card c : AllZone.Computer_Hand.getCards())
if(c.isInstant() && CardUtil.getConvertedManaCost(c) <=2)
return true;
return false;
}
};
card.addComesIntoPlayCommand(intoPlay);
card.clearSpellAbility();
card.addSpellAbility(spell);
card.addSpellAbility(freeCast);
}
//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Helix Pinnacle"))
{
final Ability ability = new Ability(card, "0")
{
public void resolve()
{
getSourceCard().addCounter(Counters.TOWER, Integer.parseInt(getManaCost()));
}
public boolean canPlayAI()
{
int m = (int)Math.pow(2, CardFactoryUtil.getCards("Doubling Season", Constant.Player.Computer).size());
int n = Math.max(1, Math.min((100-getSourceCard().getCounters(Counters.TOWER))/m,
ComputerUtil.getAvailableMana().size())) ;
setManaCost(n + "");
return !(new CardList(AllZone.Computer_Hand.getCards()).containsName("Doubling Season") && n>=5 )
&& m*n >= Math.min(20, 100 - getSourceCard().getCounters(Counters.TOWER));
//Persuming if AI cast the Pinnacle, it has green mana
}
};
ability.setBeforePayMana(new Input()
{
private static final long serialVersionUID = 43786418486732L;
public void showMessage()
{
String s = JOptionPane.showInputDialog("What would you like X to be?");
try {
Integer.parseInt(s);
ability.setManaCost(s);
stopSetNext(new Input_PayManaCost(ability));
}
catch(NumberFormatException e){
AllZone.Display.showMessage("\"" + s + "\" is not a number.");
showMessage();
}
}
});
ability.setDescription("X: Put X tower counters on Helix Pinnacle.");
ability.setStackDescription("Put X counters on Helix Pinnacle");
card.addSpellAbility(ability);
}
//*************** END ************ END **************************
/*
//*****************************START*******************************
else if(cardName.equals("Icy Manipulator") || cardName.equals("Ring of Gix")) {
// The Rules state that this can target a tapped card, but it won't do anything
final Ability_Tap ability = new Ability_Tap(card, "1") {
private static final long serialVersionUID = 6349074398830621348L;
public boolean canPlayAI() {
return false;
}
public void chooseTargetAI() {
//setTargetCard(c);
}//chooseTargetAI()
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())) {
getTargetCard().tap();
}
}
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("1, tap: Tap target artifact, creature or land.");
ability.setBeforePayMana(CardFactoryUtil.input_targetType(ability, "Artifact;Creature;Land"));
}//end Icy Manipulator
//****************END*******END***********************
*/
/*
//*****************************START*******************************
else if(cardName.equals("Jandor's Saddlebags")) {
/* Assuing the Rules state that this can target an untapped card,
* but it won't do anything useful
*
* This would bring the ruling in line with Icy Manipulator
*
final Ability_Tap ability = new Ability_Tap(card, "3") {
private static final long serialVersionUID = 6349074098650621348L;
@Override
public boolean canPlayAI() {
return false;
}
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())) {
getTargetCard().untap();
}
}
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("3, tap: Untap target creature.");
ability.setBeforePayMana(CardFactoryUtil.input_targetType(ability, "Creature"));
}//****************END*******END***********************
*/
//*************** START *********** START **************************
else if(cardName.equals("Bottle of Suleiman")) {
/*
* Sacrifice Bottle of Suleiman: Flip a coin. If you lose the flip,
* Bottle of Suleiman deals 5 damage to you. If you win the flip,
* put a 5/5 colorless Djinn artifact creature token with flying
* onto the battlefield.
*/
Ability_Cost abCost = new Ability_Cost("1 Sac<1/CARDNAME>", cardName, true);
final SpellAbility ability = new Ability_Activated(card, abCost, null) {
private static final long serialVersionUID = -5741302550353410000L;
@Override
public boolean canPlayAI() {
PlayerLife life = AllZone.GameAction.getPlayerLife(Constant.Player.Computer);
if( life.getLife() > 10 ) {
return true;
}
CardList play = new CardList(AllZone.Computer_Play.getCards());
play = play.getType("Creature");
if( play.size() == 0 ) {
return true;
}
return false;
}
@Override
public void resolve() {
final String player = AllZone.Phase.getActivePlayer();
String choice = "";
String choices[] = {"heads","tails"};
boolean flip = MyRandom.percentTrue(50);
if(card.getController().equals(Constant.Player.Human)) {
choice = (String) AllZone.Display.getChoice("Choose one", choices);
}
else {
choice = choices[MyRandom.random.nextInt(2)];
}
if( (flip == true && choice.equals("heads")) || (flip == false && choice.equals("tails"))) {
JOptionPane.showMessageDialog(null, "Bottle of Suleiman - Win! - "+player+" puts a 5/5 Flying Djinn in play.", "Bottle of Suleiman", JOptionPane.PLAIN_MESSAGE);
CardFactoryUtil.makeToken("Djinn", "C 5 5 Djinn", card, "", new String[] {"Creature", "Artifact", "Djinn"}, 5, 5, new String[] {"Flying"});
}
else{
JOptionPane.showMessageDialog(null, "Bottle of Suleiman - Lose - Bottle does 5 damage to "+player+".", "Bottle of Suleiman", JOptionPane.PLAIN_MESSAGE);
AllZone.GameAction.addDamage(card.getController(), card, 5);
}
}
};//SpellAbility
card.addSpellAbility(ability);
ability.setDescription("1, Sacrifice Bottle of Suleiman: Flip a coin. Win: Put 5/5 Djinn in play. Lose: Does 5 damage to you.");
ability.setStackDescription("Bottle of Suleiman - flip a coin");
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Lodestone Bauble")) {
/* 1, Tap, Sacrifice Lodestone Bauble: Put up to four target basic
* land cards from a player's graveyard on top of his or her library
* in any order. That player draws a card at the beginning of the next
* turn's upkeep.
*/
final Ability_Tap ability = new Ability_Tap(card, "1") {
private static final long serialVersionUID = -6711849408085138636L;
@Override
public boolean canPlayAI() {
return getComputerLands().size() >= 4;
}
@Override
public void chooseTargetAI() {
setTargetPlayer(Constant.Player.Computer);
}//chooseTargetAI()
@Override
public void resolve() {
final int limit = 4; //at most, this can target 4 cards
final String player = getTargetPlayer();
PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, player);
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
CardList lands = new CardList(grave.getCards());
lands = lands.filter(basicLands);
//this should probably be card.getController().equals(Constant.Player.Human) instead of player
//if(player.equals(Constant.Player.Human)) {
if(card.getController().equals(Constant.Player.Human)){
//now, select up to four lands
int end = -1;
end = Math.min(lands.size(), limit);
//TODO - maybe pop a message box here that no basic lands found (if necessary)
for(int i = 1; i <= end; i++) {
String Title = "Put on top of library: ";
if(i == 2) Title = "Put second from top of library: ";
if(i == 3) Title = "Put third from top of library: ";
if(i == 4) Title = "Put fourth from top of library: ";
Object o = AllZone.Display.getChoiceOptional(Title, lands.toArray());
if(o == null) break;
Card c_1 = (Card) o;
lands.remove(c_1); //remove from the display list
grave.remove(c_1); //remove from graveyard
lib.add(c_1, i - 1); //add to library
}
}
else { //Computer
//based on current AI, computer should always target himself.
CardList list = getComputerLands();
int max = list.size();
if (max > limit) max = limit;
for(int i=0;i<max;i++) {
grave.remove(list.get(i));
lib.add(list.get(i), i);
}
}
//now, sacrifice Lodestone Bauble
AllZone.GameAction.sacrifice(card);
/*
* TODO - this draw is at End of Turn. It should be at the beginning of next
* upkeep when a mechanism is in place
*/
final Command draw = new Command() {
private static final long serialVersionUID = 8293374203043368969L;
public void execute() {
AllZone.GameAction.drawCard(getTargetPlayer());
}
};
AllZone.EndOfTurn.addAt(draw);
}
private CardList getComputerLands() {
CardList list = new CardList(AllZone.Computer_Graveyard.getCards());
//probably no need to sort the list...
return list.filter(basicLands);
}
private CardListFilter basicLands = new CardListFilter() {
public boolean addCard(Card c) {
//the isBasicLand() check here may be sufficient...
return c.isLand() && c.isBasicLand();
}
};
};//ability
//ability.setStackDescription("Put up to 4 basic lands from target player's graveyeard to the top of their library. Draw a card at beginning of next upkeep.");
card.addSpellAbility(ability);
ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Grindstone")) {
Ability_Tap ab1 = new Ability_Tap(card, "3") {
private static final long serialVersionUID = -6281219446216L;
@Override
public boolean canPlayAI() {
String player = getTargetPlayer();
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
CardList libList = new CardList(lib.getCards());
CardList list = AllZoneUtil.getCardsInPlay("Painter's Servant");
return libList.size() > 0 && list.size() > 0;
}
@Override
public void resolve() {
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, getTargetPlayer());
PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, getTargetPlayer());
CardList libList = new CardList(lib.getCards());
int count = 0;
int broken = 0;
for(int i = 0; i < libList.size(); i = i + 2) {
Card c1 = null;
Card c2 = null;
if(i < libList.size()) c1 = libList.get(i);
else broken = 1;
if(i + 1 < libList.size()) c2 = libList.get(i + 1);
else broken = 1;
if(broken == 0) {
ArrayList<String> C2Color = CardUtil.getColors(c2);
broken = 1;
for(int x = 0; x < C2Color.size(); x++) {
if(CardUtil.getColors(c1).contains(C2Color.get(x)) && C2Color.get(x) != Constant.Color.Colorless) {
count = count + 1;
broken = 0;
}
}
}
}
count = (count * 2) + 2;
int max = count;
if(libList.size() < count) max = libList.size();
for(int j = 0; j < max; j++) {
Card c = libList.get(j);
lib.remove(c);
grave.add(c);
}
}
};
ab1.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
ab1.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ab1));
card.addSpellAbility(ab1);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Keening Stone")) {
/*
* 5, Tap: Target player puts the top X cards of his or her
* library into his or her graveyard, where X is the number of
* cards in that player's graveyard.
*/
Ability_Tap ab1 = new Ability_Tap(card, "5") {
private static final long serialVersionUID = -6282104343089446216L;
@Override
public boolean canPlayAI() {
String player = getTargetPlayer();
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
CardList libList = new CardList(lib.getCards());
return libList.size() > 0;
}
@Override
public void resolve() {
String player = getTargetPlayer();
AllZone.GameAction.mill(player,
AllZone.getZone(Constant.Zone.Graveyard, player).size());
}
};
ab1.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
ab1.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ab1));
card.addSpellAbility(ab1);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Dreamstone Hedron")) {
final Ability_Tap ability = new Ability_Tap(card, "3") {
private static final long serialVersionUID = 4493940591347356773L;
@Override
public boolean canPlayAI() {
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer);
return lib.size() > 0;
}
@Override
public void resolve() {
final String player = card.getController();
AllZone.GameAction.sacrifice(card);
AllZone.GameAction.drawCards(player, 3);
}
};
ability.setDescription("3, tap: Sacrifice Dreamstone Hedron: Draw 3 cards.");
ability.setStackDescription(cardName+" - Draw 3 cards.");
ability.setBeforePayMana(new Input_PayManaCost(ability));
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Slate of Ancestry")) {
/*
* 4, Tap, Discard your hand: Draw a card for each creature you control.
*/
final Ability_Tap ability = new Ability_Tap(card, "4") {
private static final long serialVersionUID = 5135410670684913401L;
@Override
public void resolve() {
final String player = card.getController();
// Discard hand into graveyard
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player);
Card[] c = hand.getCards();
for(int i = 0; i < c.length; i++)
AllZone.GameAction.discard(c[i], this);
// Draw a card for each creature
CardList creatures = AllZoneUtil.getCreaturesInPlay(player);
for(int i = 0; i < creatures.size(); i++)
AllZone.GameAction.drawCard(player);
}//resolve()
@Override
public boolean canPlayAI() {
CardList creatures = AllZoneUtil.getCreaturesInPlay(Constant.Player.Computer);
CardList hand = AllZoneUtil.getPlayerHand(Constant.Player.Computer);
return creatures.size() > hand.size();
}
};//Ability_Tap
ability.setDescription("4, tap: Discard your hand: Draw a card for each creature you control.");
ability.setStackDescription(cardName+" - discard hand and draw 1 card for every creature you control.");
ability.setBeforePayMana(new Input_PayManaCost(ability));
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Glasses of Urza")) {
final Ability_Tap ability = new Ability_Tap(card, "0") {
private static final long serialVersionUID = -3857979945891501990L;
@Override
public void resolve() {
final String player = getTargetPlayer();
CardList hand = AllZoneUtil.getPlayerHand(player);
if (hand.size() > 0) {
AllZone.Display.getChoice("Target player's hand", hand.toArray());
} else {
StringBuilder sb = new StringBuilder();
sb.append(getTargetPlayer()).append("'s hand is empty!");
javax.swing.JOptionPane.showMessageDialog(null, sb.toString(), "Target player's hand", JOptionPane.INFORMATION_MESSAGE);
}
}//resolve()
@Override
public boolean canPlayAI() {
return false;
}
};//SpellAbility
ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability));
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Everflowing Chalice")) {
final Ability_Mana addMana = new Ability_Mana(card, "tap: add 1 to your mana pool for each charge counter on Everflowing Chalice.") {
private static final long serialVersionUID = -2661488839088242789L;
@Override
public String mana() {
return Integer.toString(card.getCounters(Counters.CHARGE));
}
};
final Ability addChargeCounters = new Ability(card, "0") {
@Override
public void resolve() {
card.addCounter(Counters.CHARGE, card.getMultiKickerMagnitude());
card.setMultiKickerMagnitude(0);
}
};
StringBuilder sb = new StringBuilder();
sb.append(cardName);
sb.append(" enters the battlefield with a charge counter on it for each time it was kicked.");
addChargeCounters.setStackDescription(sb.toString());
final Command comesIntoPlay = new Command() {
private static final long serialVersionUID = 4245563898487609274L;
public void execute() {
AllZone.Stack.add(addChargeCounters);
}
};
card.addSpellAbility(addMana);
card.addComesIntoPlayCommand(comesIntoPlay);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Chromatic Star")) {
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
AllZone.GameAction.drawCard(card.getController());
}
};
Command destroy = new Command() {
private static final long serialVersionUID = 7982507967024313067L;
public void execute() {
ability.setStackDescription(card.getName() + " - " + card.getController() + " draws a card");
AllZone.Stack.add(ability);
}
};
card.addDestroyCommand(destroy);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Feldon's Cane")) {
/*
* Tap, Exile Feldon's Cane: Shuffle your graveyard into your library.
*/
final Ability_Tap ability = new Ability_Tap(card, "0") {
private static final long serialVersionUID = -1299603105585632846L;
@Override
public void resolve() {
final String player = card.getController();
CardList grave = AllZoneUtil.getPlayerGraveyard(player);
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
//exile Feldon's Cane
AllZone.GameAction.removeFromGame(card);
for(Card c:grave) {
lib.add(c);
}
AllZone.getZone(Constant.Zone.Graveyard, player).reset();
AllZone.GameAction.shuffle(player);
}
@Override
public boolean canPlayAI() {
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, Constant.Player.Computer);
return lib.size() < 5;
}
};//SpellAbility
ability.setStackDescription(cardName+" - Player shuffles grave into library.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Curse of Wizardry")) {
final Ability ability = new Ability(card, "0") {
@Override
public void resolve() {
if(card.getController().equals(Constant.Player.Human)) {
String color = "";
String[] colors = Constant.Color.Colors;
colors[colors.length - 1] = null;
Object o = AllZone.Display.getChoice("Choose color", colors);
color = (String) o;
card.setChosenColor(color);
} else {
CardList list = AllZoneUtil.getPlayerCardsInLibrary(Constant.Player.Human);
list.add(AllZoneUtil.getPlayerHand(Constant.Player.Human));
if(list.size() > 0) {
String color = CardFactoryUtil.getMostProminentColor(list);
if(!color.equals("")) card.setChosenColor(color);
else card.setChosenColor("black");
} else {
card.setChosenColor("black");
}
}
}
};
Command comesIntoPlay = new Command() {
private static final long serialVersionUID = -6417019967914398902L;
public void execute() {
AllZone.Stack.add(ability);
}
};//Command
ability.setStackDescription("As "+cardName+" enters the battlefield, choose a color.");
card.addComesIntoPlayCommand(comesIntoPlay);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Arena of the Ancients")) {
/*
* When Arena of the Ancients enters the battlefield, tap
* all legendary creatures.
*/
final SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
CardList legends = AllZoneUtil.getTypeInPlay("Legendary");
legends = legends.filter(AllZoneUtil.creatures);
for(int i = 0; i < legends.size(); i++) {
Card c = legends.get(i);
if(c.isUntapped()) c.tap();
}
}
};//ability
Command intoPlay = new Command() {
private static final long serialVersionUID = 3564466123797650567L;
public void execute() {
ability.setStackDescription("When " + card.getName()
+ " comes into play, tap all Legendary creatures.");
AllZone.Stack.add(ability);
}
};
card.addComesIntoPlayCommand(intoPlay);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Expedition Map")) {
final Ability_Tap ability = new Ability_Tap(card, "2") {
private static final long serialVersionUID = -5796728507926918991L;
@Override
public boolean canPlayAI() {
return AllZoneUtil.getPlayerTypeInLibrary(Constant.Player.Computer,
"Land").size() >= 1;
}
@Override
public void resolve() {
AllZone.GameAction.searchLibraryLand("Land",
card.getController(), Constant.Zone.Hand, false);
AllZone.GameAction.sacrifice(card);
}
};//ability
ability.setDescription("2, tap, sacrifice Expedition Map: Search your library for a land card, reveal it, and put it into your hand. Then shuffle your library.");
ability.setStackDescription("Sacrifice Expedition Map: search your library for a land and put it into your hand.");
ability.setManaCost("2");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Tormod's Crypt")) {
/*
* Tap, Sacrifice Tormod's Crypt: Exile all cards from target player's graveyard.
*/
final Ability_Tap ability = new Ability_Tap(card, "0") {
private static final long serialVersionUID = -8877371657709894494L;
@Override
public void resolve() {
if (card.getController().equals(Constant.Player.Computer))
setTargetPlayer(Constant.Player.Human);
final String player = getTargetPlayer();
CardList grave = AllZoneUtil.getPlayerGraveyard(player);
//sac tormod's crypt
AllZone.GameAction.sacrifice(card);
for(Card c:grave) {
AllZone.GameAction.removeFromGame(c);
}
AllZone.getZone(Constant.Zone.Graveyard, player).reset();
AllZone.GameAction.shuffle(player);
}
@Override
public boolean canPlayAI() {
PlayerZone grave = AllZone.getZone(Constant.Zone.Library, Constant.Player.Human);
return grave.size() < 15;
}
};//SpellAbility
ability.setDescription("Tap, Sacrifice Tormod's Crypt: Exile all cards from target player's graveyard.");
ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability));
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Journey to Nowhere")) {
final CommandReturn getPerm = new CommandReturn() {
public Object execute() {
//get all creatures
CardList tempList = new CardList();
tempList.addAll(AllZone.Human_Play.getCards());
tempList.addAll(AllZone.Computer_Play.getCards());
CardList list = new CardList();
for(int i = 0; i < tempList.size(); i++) {
if(tempList.get(i).isPermanent() && tempList.get(i).isCreature()
&& CardFactoryUtil.canTarget(card, tempList.get(i))) list.add(tempList.get(i));
}//for
//remove "this card"
list.remove(card);
return list;
}//execute
};//CommandReturn
final SpellAbility abilityComes = new Ability(card, "0") {
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())
&& CardFactoryUtil.canTarget(card, getTargetCard())) {
AllZone.GameAction.removeFromGame(getTargetCard());
}//if
}//resolve()
};//abilityComes
final Input inputComes = new Input() {
private static final long serialVersionUID = -3613946694360326887L;
@Override
public void showMessage() {
CardList choice = (CardList) getPerm.execute();
stopSetNext(CardFactoryUtil.input_targetSpecific(abilityComes, choice,
"Select target creature to remove from the game", true, false));
ButtonUtil.disableAll();//to disable the Cancel button
}//showMessage
};//inputComes
Command commandComes = new Command() {
private static final long serialVersionUID = -6250376920501373535L;
public void execute() {
CardList perm = (CardList) getPerm.execute();
String s = card.getController();
if(perm.size() == 0) return;
else if(s.equals(Constant.Player.Human)) AllZone.InputControl.setInput(inputComes);
else //computer
{
Card target;
//try to target human creature
CardList human = CardFactoryUtil.AI_getHumanCreature(card, true);
target = CardFactoryUtil.AI_getBestCreature(human);//returns null if list is empty
// try to target human permanent
if(target == null) {
int convertedCost = 0;
CardList tempList = new CardList();
tempList.addAll(AllZone.Human_Play.getCards());
for(int i = 0; i < tempList.size(); i++) {
if(tempList.get(i).isPermanent()
&& !tempList.get(i).isLand()
&& CardFactoryUtil.canTarget(card, tempList.get(i))
&& (CardUtil.getConvertedManaCost(tempList.get(i).getManaCost()) > convertedCost)) {
target = tempList.get(i);
convertedCost = CardUtil.getConvertedManaCost(tempList.get(i).getManaCost());
}//if
}//for
}//if
//target something cheaper (manacost 0?) instead:
if(target == null) {
CardList humanPerms = new CardList();
humanPerms.addAll(AllZone.Human_Play.getCards());
humanPerms = humanPerms.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.isPermanent() && !c.isLand() && CardFactoryUtil.canTarget(card, c);
}
});
if(humanPerms.size() > 0) target = humanPerms.get(0);
}//if
if(target == null) {
//must target computer creature
CardList computer = new CardList(AllZone.Computer_Play.getCards());
computer = computer.getType("Creature");
computer.remove(card);
computer.shuffle();
if(computer.size() != 0) target = computer.get(0);
else target = card;
}//if
abilityComes.setTargetCard(target);
AllZone.Stack.add(abilityComes);
}//else
}//execute()
};//CommandComes
Command commandLeavesPlay = new Command() {
private static final long serialVersionUID = 6997038208952910355L;
public void execute() {
Object o = abilityComes.getTargetCard();
if(o == null || ((Card) o).isToken() || !AllZone.GameAction.isCardRemovedFromGame((Card) o)) return;
SpellAbility ability = new Ability(card, "0") {
@Override
public void resolve() {
//copy card to reset card attributes like attack and defense
Card c = abilityComes.getTargetCard();
if(!c.isToken()) {
c = AllZone.CardFactory.dynamicCopyCard(c);
c.setController(c.getOwner());
PlayerZone play = AllZone.getZone(Constant.Zone.Play, c.getOwner());
PlayerZone removed = AllZone.getZone(Constant.Zone.Removed_From_Play, c.getOwner());
removed.remove(c);
if (c.isTapped()) c.untap();
play.add(c);
}//if
}//resolve()
};//SpellAbility
ability.setStackDescription("Journey To Nowhere - returning creature to play.");
AllZone.Stack.add(ability);
}//execute()
};//Command
card.addComesIntoPlayCommand(commandComes);
card.addLeavesPlayCommand(commandLeavesPlay);
card.setSVar("PlayMain1", "TRUE");
card.clearSpellAbility();
card.addSpellAbility(new Spell_Permanent(card) {
private static final long serialVersionUID = -3250095291930182087L;
@Override
public boolean canPlayAI() {
Object o = getPerm.execute();
if(o == null) return false;
CardList cList = new CardList(AllZone.Human_Play.getCards());
cList = cList.filter(new CardListFilter() {
public boolean addCard(Card crd) {
return CardFactoryUtil.canTarget(card, crd) && crd.isCreature();
}
});
CardList cl = (CardList) getPerm.execute();
return (o != null) && cList.size() > 0 && cl.size() > 0 && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand);
}//canPlayAI
});//addSpellAbility
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Recurring Nightmare")) {
/*
* Sacrifice a creature, Return Recurring Nightmare to its owner's
* hand: Return target creature card from your graveyard to the
* battlefield. Activate this ability only any time you could cast
* a sorcery.
*/
final Ability ability = new Ability(card, "0") {
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
return super.canPlay() && Phase.canCastSorcery(card.getController());
}
@Override
public void resolve() {
if(AllZone.GameAction.isCardInPlay(getTargetCard())) {
//choose a card from graveyard
String player = card.getController();
CardList grave = AllZoneUtil.getPlayerGraveyard(player);
grave = grave.filter(AllZoneUtil.creatures);
final String title = "Select creature";
Object o = AllZone.Display.getChoiceOptional(title, grave.toArray());
if(null != o) {
Card toReturn = (Card) o;
PlayerZone play = AllZone.getZone(Constant.Zone.Play, player);
AllZone.GameAction.moveTo(play, toReturn);
}
//sacrifice the creature (target card)
AllZone.GameAction.sacrifice(getTargetCard());
//return Recurring Nightmare to player's hand
AllZone.GameAction.moveToHand(card);
}
}
};//Ability
Input target = new Input() {
private static final long serialVersionUID = 8486351837945158454L;
public void showMessage() {
AllZone.Display.showMessage("Select target creature to sacrifice");
ButtonUtil.enableOnlyCancel();
}
public void selectButtonCancel() {stop();}
public void selectCard(Card c, PlayerZone zone) {
if(c.isCreature() && zone.is(Constant.Zone.Play, Constant.Player.Human)) {
ability.setTargetCard(c);
AllZone.Stack.add(ability);
stop();
}
}//selectCard()
};//Input
card.addSpellAbility(ability);
ability.setBeforePayMana(target);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Mirror Universe")) {
/*
* Tap, Sacrifice Mirror Universe: Exchange life totals with
* target opponent. Activate this ability only during your upkeep.
*/
final Ability_Tap ability = new Ability_Tap(card, "0") {
private static final long serialVersionUID = -1409850598108909739L;
@Override
public void resolve() {
String player = card.getController();
String opponent = AllZone.GameAction.getOpponent(player);
PlayerLife playerLife = AllZone.GameAction.getPlayerLife(player);
PlayerLife opponentLife = AllZone.GameAction.getPlayerLife(opponent);
int tmp = playerLife.getLife();
playerLife.setLife(opponentLife.getLife());
opponentLife.setLife(tmp);
AllZone.GameAction.sacrifice(card);
}
@Override
public boolean canPlay() {
//TODO: This should be limited to Upkeep when we have a phase for that
return super.canPlay() && AllZone.Phase.getPhase().equals(Constant.Phase.Main1);
}
@Override
public boolean canPlayAI() {
PlayerLife compy = AllZone.GameAction.getPlayerLife(Constant.Player.Computer);
PlayerLife human = AllZone.GameAction.getPlayerLife(Constant.Player.Human);
if(compy.getLife() < 5 && human.getLife() > 5) {
return true;
}
else if(compy.getLife() == 1) {
return true;
}
else if((human.getLife() - compy.getLife()) > 10) {
return true;
}
else return false;
}
};//SpellAbility
ability.setStackDescription(cardName+" - Exchange life totals with target opponent.");
card.addSpellAbility(ability);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Jade Statue")) {
/*
* 2: Jade Statue becomes a 3/6 Golem artifact creature until
* end of combat. Activate this ability only during combat.
*/
final long[] timeStamp = new long[1];
final SpellAbility a1 = new Ability(card, "2") {
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
return Phase.canPlayDuringCombat();
}
@Override
public void resolve() {
Card c = card;
String[] types = { "Creature", "Golem" };
String[] keywords = { };
timeStamp[0] = CardFactoryUtil.activateManland(c, 3, 6, types, keywords, "4");
final Command untilEOC = new Command() {
private static final long serialVersionUID = -8432597117196682284L;
long stamp = timeStamp[0];
public void execute() {
Card c = card;
String[] types = { "Creature", "Golem" };
String[] keywords = { };
CardFactoryUtil.revertManland(c, types, keywords, "4", stamp);
}
};
AllZone.EndOfCombat.addUntil(untilEOC);
}
};//SpellAbility
//card.clearSpellKeepManaAbility();
card.addSpellAbility(a1);
a1.setStackDescription(card + " becomes a 3/6 Golem creature until End of Combat");
Command paid1 = new Command() {
private static final long serialVersionUID = 1531378274457977155L;
public void execute() {
AllZone.Stack.add(a1);
}
};
a1.setBeforePayMana(new Input_PayManaCost_Ability(a1.getManaCost(), paid1));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Jester's Cap")) {
/*
* 2, Tap, Sacrifice Jester's Cap: Search target player's library
* for three cards and exile them. Then that player shuffles his
* or her library.
*/
final Ability_Tap ability = new Ability_Tap(card, "2") {
private static final long serialVersionUID = 222308932796127795L;
@Override
public boolean canPlayAI() {
//TODO
return false;
}
@Override
public void resolve() {
String target = getTargetPlayer();
String player = card.getController();
PlayerZone zone = AllZone.getZone(Constant.Zone.Library, target);
if(player.equals(Constant.Player.Human)) {
AllZoneUtil.exileNCardsFromZone(zone, null, 3, true);
}
else { //computer
}
AllZone.GameAction.sacrifice(card);
}
};//Ability
card.addSpellAbility(ability);
ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if (cardName.equals("An-Zerrin Ruins")) {
final Ability_Static comesIntoPlayAbility = new Ability_Static(card, "0") {
@Override
public void resolve() {
String chosenType = "";
if(card.getController().equals(Constant.Player.Human)) {
chosenType = JOptionPane.showInputDialog(null, "Enter a creature type:", card.getName(),
JOptionPane.QUESTION_MESSAGE);
}
else {
//not implemented for AI
}
if (!CardUtil.isCreatureType(chosenType)) chosenType = "";
card.setChosenType(chosenType);
}//resolve()
}; //comesIntoPlayAbility
Command intoPlay = new Command() {
private static final long serialVersionUID = 2985015252466920757L;
public void execute() {
comesIntoPlayAbility.setStackDescription(card.getName()+" - choose a creature type. Creatures of that type do not untap during their controller's untap step.");
AllZone.Stack.add(comesIntoPlayAbility);
}
};
card.addComesIntoPlayCommand(intoPlay);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Tumble Magnet")) {
/*
* Tumble Magnet enters the battlefield with three charge
* counters on it.
* Tap, Remove a charge counter from Tumble Magnet: Tap target
* artifact or creature.
*/
final Ability_Tap ability = new Ability_Tap(card, "0") {
private static final long serialVersionUID = -5513092896385146010L;
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean canPlay() {
return card.getCounters(Counters.CHARGE) > 0;
}
@Override
public void resolve() {
Card target = getTargetCard();
//remove charge counter
card.subtractCounter(Counters.CHARGE, 1);
card.tap();
if(CardFactoryUtil.canTarget(card, target) && AllZoneUtil.isCardInPlay(target)) {
target.tap();
}
}
};//Ability
card.addSpellAbility(ability);
ability.setBeforePayMana(CardFactoryUtil.input_targetType(ability, "Creature;Artifact"));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Barl's Cage")) {
Target target = new Target("TgtV");
target.setVTSelection("Select target creature.");
final String Tgts[] = {"Creature"};
target.setValidTgts(Tgts);
final Ability_Cost cost = new Ability_Cost("3", card.getName(), true);
final SpellAbility ability = new Ability_Activated(card, cost, target) {
private static final long serialVersionUID = 8941566961041310961L;
@Override
public boolean canPlayAI() {
Card c = getCreature();
if(c == null) return false;
else {
setTargetCard(c);
return true;
}
}//canPlayAI()
//may return null
public Card getCreature() {
CardList tappedCreatures = AllZoneUtil.getCreaturesInPlay();
tappedCreatures = tappedCreatures.filter(AllZoneUtil.tapped);
tappedCreatures = tappedCreatures.filter(AllZoneUtil.getCanTargetFilter(card));
if(tappedCreatures.isEmpty()) return null;
return CardFactoryUtil.AI_getBestCreature(tappedCreatures);
}
@Override
public void resolve() {
Card target = getTargetCard();
if(AllZone.GameAction.isCardInPlay(target)
&& CardFactoryUtil.canTarget(card, target)) {
target.addExtrinsicKeyword("This card doesn't untap during your next untap step.");
}//is card in play?
}//resolve()
};//SpellAbility
card.addSpellAbility(ability);
}//*************** END ************ END **************************
// Cards with Cycling abilities
// -1 means keyword "Cycling" not found
if(hasKeyword(card, "Cycling") != -1) {
int n = hasKeyword(card, "Cycling");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.addSpellAbility(CardFactoryUtil.ability_cycle(card, manacost));
}
}//Cycling
while(hasKeyword(card, "TypeCycling") != -1) {
int n = hasKeyword(card, "TypeCycling");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String type = k[1];
final String manacost = k[2];
card.addSpellAbility(CardFactoryUtil.ability_typecycle(card, manacost, type));
}
}//TypeCycling
if(hasKeyword(card, "Transmute") != -1) {
int n = hasKeyword(card, "Transmute");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.addSpellAbility(CardFactoryUtil.ability_transmute(card, manacost));
}
}//transmute
while(hasKeyword(card, "Soulshift") != -1) {
int n = hasKeyword(card, "Soulshift");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.addSpellAbility(CardFactoryUtil.soul_desc(card, manacost));
card.addDestroyCommand(CardFactoryUtil.ability_Soulshift(card, manacost));
}
}//Soulshift
if(hasKeyword(card, "Echo") != -1) {
int n = hasKeyword(card, "Echo");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
//card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
final String manacost = k[1];
card.setEchoCost(manacost);
final Command intoPlay = new Command() {
private static final long serialVersionUID = -7913835645603984242L;
public void execute() {
card.addIntrinsicKeyword("(Echo unpaid)");
}
};
card.addComesIntoPlayCommand(intoPlay);
}
}//echo
if(hasKeyword(card,"HandSize") != -1) {
String toParse = card.getKeyword().get(hasKeyword(card,"HandSize"));
card.removeIntrinsicKeyword(toParse);
String parts[] = toParse.split(" ");
final String Mode = parts[1];
final int Amount;
if(parts[2].equals("INF")) {
Amount = -1;
}
else {
Amount = Integer.parseInt(parts[2]);
}
final String Target = parts[3];
final Command entersPlay,leavesPlay, controllerChanges;
entersPlay = new Command() {
private static final long serialVersionUID = 98743547743456L;
public void execute() {
card.setSVar("HSStamp","" + Input_Cleanup.GetHandSizeStamp());
if(card.getController() == Constant.Player.Human) {
//System.out.println("Human played me! Mode(" + Mode + ") Amount(" + Amount + ") Target(" + Target + ")" );
if(Target.equals("Self")) {
Input_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
}
else if(Target.equals("Opponent")) {
Computer_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
}
else if(Target.equals("All")) {
Computer_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
Input_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
}
}
else
{
//System.out.println("Compy played me! Mode(" + Mode + ") Amount(" + Amount + ") Target(" + Target + ")" );
if(Target.equals("Self")) {
Computer_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
}
else if(Target.equals("Opponent")) {
Input_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
}
else if(Target.equals("All")) {
Computer_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
Input_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
}
}
}
};
leavesPlay = new Command() {
private static final long serialVersionUID = -6843545358873L;
public void execute() {
if(card.getController() == Constant.Player.Human) {
if(Target.equals("Self")) {
Input_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
}
else if(Target.equals("Opponent")) {
Computer_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
}
else if(Target.equals("All")) {
Computer_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
Input_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
}
}
else
{
if(Target.equals("Self")) {
Computer_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
}
else if(Target.equals("Opponent")) {
Input_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
}
else if(Target.equals("All")) {
Computer_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
Input_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
}
}
}
};
controllerChanges = new Command() {
private static final long serialVersionUID = 778987998465463L;
public void execute() {
Log.debug("HandSize", "Control changed: " + card.getController());
if(card.getController().equals(Constant.Player.Human)) {
Input_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
Computer_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
Computer_Cleanup.sortHandSizeOperations();
}
else if(card.getController().equals(Constant.Player.Computer)) {
Computer_Cleanup.removeHandSizeOperation(Integer.parseInt(card.getSVar("HSStamp")));
Input_Cleanup.addHandSizeOperation(new HandSizeOp(Mode,Amount,Integer.parseInt(card.getSVar("HSStamp"))));
Input_Cleanup.sortHandSizeOperations();
}
}
};
card.addComesIntoPlayCommand(entersPlay);
card.addLeavesPlayCommand(leavesPlay);
card.addChangeControllerCommand(controllerChanges);
} //HandSize
if (card.getManaCost().contains("X"))
{
SpellAbility sa = card.getSpellAbility()[0];
sa.setIsXCost(true);
if (card.getManaCost().startsWith("X X"))
sa.setXManaCost("2");
else if (card.getManaCost().startsWith("X"))
sa.setXManaCost("1");
}//X
return postFactoryKeywords(card);
}//getCard2
public Card postFactoryKeywords(Card card){
// this function should handle any keywords that need to be added after a spell goes through the factory
card.addColor(card.getManaCost());
int cardnameSpot = hasKeyword(card, "CARDNAME is ");
if (cardnameSpot != -1){
String color = "1";
while(cardnameSpot != -1){
if(cardnameSpot != -1) {
String parse = card.getKeyword().get(cardnameSpot).toString();
card.removeIntrinsicKeyword(parse);
color += " " + Input_PayManaCostUtil.getShortColorString(parse.replace("CARDNAME is ","").replace(".", ""));
cardnameSpot = hasKeyword(card, "CARDNAME is ");
}
}
card.addColor(color);
}
if(hasKeyword(card, "Fading") != -1) {
int n = hasKeyword(card, "Fading");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
String k[] = parse.split(":");
final int power = Integer.parseInt(k[1]);
card.addComesIntoPlayCommand(CardFactoryUtil.fading(card, power));
// todo: come up with better way to add description
card.addSpellAbility(CardFactoryUtil.fading_desc(card, power));
}
}//Fading
if(hasKeyword(card, "Vanishing") != -1) {
int n = hasKeyword(card, "Vanishing");
if(n != -1) {
String parse = card.getKeyword().get(n).toString();
String k[] = parse.split(":");
final int power = Integer.parseInt(k[1]);
card.addComesIntoPlayCommand(CardFactoryUtil.vanishing(card, power));
// todo: come up with better way to add description
card.addSpellAbility(CardFactoryUtil.vanish_desc(card, power));
}
}//Vanishing
// Spell has Additional Cost. Reuse Ability_Cost
if (hasKeyword(card, "ACost") != -1){
int n = hasKeyword(card, "ACost");
String parse = card.getKeyword().get(n).toString();
card.removeIntrinsicKeyword(parse);
String k[] = parse.split(":");
Ability_Cost cost = new Ability_Cost(k[1], card.getName(), false);
StringBuilder sb = new StringBuilder(cost.toString());
sb.append("\n");
sb.append(card.getText());
card.setText(sb.toString());
// loop through each of the cards spells and add abCost to it
ArrayList<SpellAbility> spells = card.getSpells();
for(SpellAbility sa : spells){
if (sa instanceof Spell){
sa.setPayCosts(cost);
}
}
}
return card;
}
// copies stats like attack, defense, etc..
public static Card copyStats(Object o) {
Card sim = (Card) o;
Card c = new Card();
c.setBaseAttack(sim.getBaseAttack());
c.setBaseDefense(sim.getBaseDefense());
c.setIntrinsicKeyword(sim.getKeyword());
c.setName(sim.getName());
c.setImageName(sim.getImageName());
c.setType(sim.getType());
c.setText(sim.getSpellText());
c.setManaCost(sim.getManaCost());
c.addColor(sim.getManaCost());
c.setSVars(sim.getSVars());
c.setIntrinsicAbilities(sim.getIntrinsicAbilities());
return c;
}// copyStats()
public static void main(String[] args) {
CardFactory f = new CardFactory(ForgeProps.getFile(CARDSFOLDER));
Card c = f.getCard("Arc-Slogger", "d");
System.out.println(c.getOwner());
}
}