package forge; import forge.card.abilityFactory.AbilityFactory; import forge.card.cardFactory.CardFactory; import forge.card.cardFactory.CardFactoryUtil; import forge.card.spellability.*; import forge.card.trigger.Trigger; import forge.gui.GuiUtils; import forge.gui.input.Input; import forge.gui.input.Input_PayManaCostUtil; import forge.gui.input.Input_PayManaCost_Ability; import javax.swing.*; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; /** * <p>GameActionUtil class.</p> * * @author Forge * @version $Id: $ */ public class GameActionUtil { /** * <p>executeUpkeepEffects.</p> */ public static void executeUpkeepEffects() { AllZone.getStack().freezeStack(); upkeep_Braid_Of_Fire(); upkeep_Slowtrips(); // for "Draw a card at the beginning of the next turn's upkeep." upkeep_UpkeepCost(); //sacrifice unless upkeep cost is paid upkeep_Echo(); upkeep_The_Abyss(); upkeep_Mana_Vortex(); upkeep_Yawgmoth_Demon(); upkeep_Lord_of_the_Pit(); upkeep_Drop_of_Honey(); upkeep_Demonic_Hordes(); upkeep_Fallen_Empires_Storage_Lands(); upkeep_Carnophage(); upkeep_Sangrophage(); upkeep_Dega_Sanctuary(); upkeep_Ceta_Sanctuary(); upkeep_Tangle_Wire(); upkeep_Dance_of_the_Dead(); upkeep_Shapeshifter(); upkeep_Vesuvan_Doppelganger_Keyword(); //Kinship cards upkeep_Ink_Dissolver(); upkeep_Kithkin_Zephyrnaut(); upkeep_Leaf_Crowned_Elder(); upkeep_Mudbutton_Clanger(); upkeep_Nightshade_Schemers(); upkeep_Pyroclast_Consul(); upkeep_Sensation_Gorger(); upkeep_Squeaking_Pie_Grubfellows(); upkeep_Wandering_Graybeard(); upkeep_Waterspout_Weavers(); upkeep_Winnower_Patrol(); upkeep_Wolf_Skull_Shaman(); upkeep_Sleeper_Agent(); // upkeep_Dragon_Broodmother(); //put this before bitterblossom and mycoloth, so that they will resolve FIRST //Win / Lose // Checks for can't win or can't lose happen in Player.altWinConditionMet() upkeep_Mortal_Combat(); upkeep_Near_Death_Experience(); upkeep_Test_of_Endurance(); upkeep_Helix_Pinnacle(); upkeep_Barren_Glory(); upkeep_Felidar_Sovereign(); upkeep_Karma(); upkeep_Oath_of_Druids(); upkeep_Oath_of_Ghouls(); upkeep_Suspend(); upkeep_Vanishing(); upkeep_Fading(); upkeep_Masticore(); upkeep_Eldrazi_Monument(); upkeep_Blaze_Counters(); upkeep_Dark_Confidant(); // keep this one semi-last upkeep_Power_Surge(); upkeep_AI_Aluren(); // experimental, AI abuse aluren AllZone.getStack().unfreezeStack(); } /** * <p>executeDrawStepEffects.</p> */ public static void executeDrawStepEffects() { AllZone.getStack().freezeStack(); final Player player = AllZone.getPhase().getPlayerTurn(); draw_Sylvan_Library(player); AllZone.getStack().unfreezeStack(); } /** * <p>executePlayCardEffects.</p> * * @param sa a {@link forge.card.spellability.SpellAbility} object. */ public static void executePlayCardEffects(SpellAbility sa) { // experimental: // this method check for cards that have triggered abilities whenever a // card gets played // (called in MagicStack.java) Card c = sa.getSourceCard(); playCard_Cascade(c); playCard_Ripple(c); playCard_Storm(sa); playCard_Vengevine(c); playCard_Standstill(c); playCard_Curse_of_Wizardry(c); playCard_Venser_Emblem(c); playCard_Ichneumon_Druid(c); } /** * <p>playCard_Cascade.</p> * * @param c a {@link forge.Card} object. */ public static void playCard_Cascade(final Card c) { Command Cascade = new Command() { private static final long serialVersionUID = -845154812215847505L; public void execute() { CardList humanNexus = AllZoneUtil.getPlayerCardsInPlay(AllZone.getHumanPlayer(), "Maelstrom Nexus"); CardList computerNexus = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer(), "Maelstrom Nexus"); if (humanNexus.size() > 0) { if (Phase.getPlayerSpellCount() == 1 && !c.isCopiedSpell()) { for (int i = 0; i < humanNexus.size(); i++) { DoCascade(c); } } } if (computerNexus.size() > 0) { if (Phase.getComputerSpellCount() == 1 && !c.isCopiedSpell()) { for (int i = 0; i < computerNexus.size(); i++) { DoCascade(c); } } } if (c.hasKeyword("Cascade") || c.getName().equals("Bituminous Blast")) //keyword gets cleared for Bitumonous Blast { DoCascade(c); } }// execute() void DoCascade(Card c) { final Player controller = c.getController(); final Card cascCard = c; final Ability ability = new Ability(c, "0") { @Override public void resolve() { CardList topOfLibrary = AllZoneUtil.getPlayerCardsInLibrary(controller); CardList revealed = new CardList(); if (topOfLibrary.size() == 0) return; Card cascadedCard = null; Card crd; int count = 0; while (cascadedCard == null) { crd = topOfLibrary.get(count++); revealed.add(crd); if ((!crd.isLand() && CardUtil.getConvertedManaCost(crd.getManaCost()) < CardUtil.getConvertedManaCost(cascCard.getManaCost()))) cascadedCard = crd; if (count == topOfLibrary.size()) break; }//while GuiUtils.getChoiceOptional("Revealed cards:", revealed.toArray()); if (cascadedCard != null && !cascadedCard.isUnCastable()) { if (cascadedCard.getController().isHuman()) { StringBuilder title = new StringBuilder(); title.append(cascCard.getName()).append(" - Cascade Ability"); StringBuilder question = new StringBuilder(); question.append("Cast ").append(cascadedCard.getName()).append(" without paying its mana cost?"); int answer = JOptionPane.showConfirmDialog(null, question.toString(), title.toString(), JOptionPane.YES_NO_OPTION); if (answer == JOptionPane.YES_OPTION) { AllZone.getGameAction().playCardNoCost(cascadedCard); revealed.remove(cascadedCard); } } else //computer { ArrayList<SpellAbility> choices = cascadedCard.getBasicSpells(); for (SpellAbility sa : choices) { if (sa.canPlayAI()) { ComputerUtil.playStackFree(sa); revealed.remove(cascadedCard); break; } } } } revealed.shuffle(); for (Card bottom : revealed) { AllZone.getGameAction().moveToBottomOfLibrary(bottom); } } }; StringBuilder sb = new StringBuilder(); sb.append(c).append(" - Cascade."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } }; Cascade.execute(); } /** * <p>playCard_Ripple.</p> * * @param c a {@link forge.Card} object. */ public static void playCard_Ripple(final Card c) { Command Ripple = new Command() { private static final long serialVersionUID = -845154812215847505L; public void execute() { CardList humanThrummingStone = AllZoneUtil.getPlayerCardsInPlay(AllZone.getHumanPlayer(), "Thrumming Stone"); CardList computerThrummingStone = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer(), "Thrumming Stone"); for (int i = 0; i < humanThrummingStone.size(); i++) { if (c.getController().isHuman()) c.addExtrinsicKeyword("Ripple:4"); } for (int i = 0; i < computerThrummingStone.size(); i++) { if (c.getController().isComputer()) c.addExtrinsicKeyword("Ripple:4"); } ArrayList<String> a = c.getKeyword(); for (int x = 0; x < a.size(); x++) if (a.get(x).toString().startsWith("Ripple")) { String parse = c.getKeyword().get(x).toString(); String k[] = parse.split(":"); DoRipple(c, Integer.valueOf(k[1])); } }// execute() void DoRipple(Card c, final int RippleCount) { final Player controller = c.getController(); final Card RippleCard = c; boolean Activate_Ripple = false; if (controller.isHuman()) { Object[] possibleValues = {"Yes", "No"}; AllZone.getDisplay().showMessage("Activate Ripple? "); Object q = JOptionPane.showOptionDialog(null, "Activate Ripple for " + c, "Ripple", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if (q.equals(0)) Activate_Ripple = true; } else Activate_Ripple = true; if (Activate_Ripple == true) { final Ability ability = new Ability(c, "0") { @Override public void resolve() { CardList topOfLibrary = AllZoneUtil.getPlayerCardsInLibrary(controller); CardList revealed = new CardList(); int RippleNumber = RippleCount; if (topOfLibrary.size() == 0) return; int RippleMax = 10; // Shouldn't Have more than Ripple 10, seeing as no cards exist with a ripple greater than 4 Card[] RippledCards = new Card[RippleMax]; Card crd; if (topOfLibrary.size() < RippleNumber) RippleNumber = topOfLibrary.size(); for (int i = 0; i < RippleNumber; i++) { crd = topOfLibrary.get(i); revealed.add(crd); if (crd.getName().equals(RippleCard.getName())) RippledCards[i] = crd; }//For GuiUtils.getChoiceOptional("Revealed cards:", revealed.toArray()); for (int i = 0; i < RippleMax; i++) { if (RippledCards[i] != null && !RippledCards[i].isUnCastable()) { if (RippledCards[i].getController().isHuman()) { Object[] possibleValues = {"Yes", "No"}; Object q = JOptionPane.showOptionDialog(null, "Cast " + RippledCards[i].getName() + "?", "Ripple", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues, possibleValues[0]); if (q.equals(0)) { AllZone.getGameAction().playCardNoCost(RippledCards[i]); revealed.remove(RippledCards[i]); } } else //computer { ArrayList<SpellAbility> choices = RippledCards[i].getBasicSpells(); for (SpellAbility sa : choices) { if (sa.canPlayAI() && !sa.getSourceCard().isType("Legendary")) { ComputerUtil.playStackFree(sa); revealed.remove(RippledCards[i]); break; } } } } } revealed.shuffle(); for (Card bottom : revealed) { AllZone.getGameAction().moveToBottomOfLibrary(bottom); } } }; StringBuilder sb = new StringBuilder(); sb.append(c).append(" - Ripple."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } }; Ripple.execute(); }//playCard_Ripple() /** * <p>playCard_Storm.</p> * * @param sa a {@link forge.card.spellability.SpellAbility} object. */ public static void playCard_Storm(SpellAbility sa) { Card source = sa.getSourceCard(); if (!source.isCopiedSpell() && source.hasKeyword("Storm")) { int StormNumber = Phase.getStormCount() - 1; for (int i = 0; i < StormNumber; i++) AllZone.getCardFactory().copySpellontoStack(source, source, sa, true); } }//playCard_Storm() /** * <p>playCard_Vengevine.</p> * * @param c a {@link forge.Card} object. */ public static void playCard_Vengevine(Card c) { if (c.isCreature() == true && (Phase.getPlayerCreatureSpellCount() == 2 || Phase.getComputerCreatureSpellCount() == 2)) { final Player controller = c.getController(); final PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, controller); CardList list = AllZoneUtil.getPlayerGraveyard(controller); list = list.getName("Vengevine"); if (list.size() > 0) { for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); Ability ability = new Ability(card, "0") { @Override public void resolve() { if (controller.isComputer() || GameActionUtil.showYesNoDialog(card, "Return Vengevine from the graveyard?")) { if (AllZoneUtil.isCardInPlayerGraveyard(controller, card)) { AllZone.getGameAction().moveTo(play, card); } } } }; // ability StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append("Whenever you cast a spell, if it's the second creature "); sb.append("spell you cast this turn, you may return Vengevine from your graveyard to the battlefield."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } }//if } }//playCard_Vengevine() /** * <p>playCard_Ichneumon_Druid.</p> * * @param c a {@link forge.Card} object. */ public static void playCard_Ichneumon_Druid(Card c) { if (c.isInstant() && (Phase.getPlayerInstantSpellCount() >= 2 || Phase.getComputerInstantSpellCount() >= 2)) { final Player player = c.getController(); final Player opp = player.getOpponent(); CardList list = AllZoneUtil.getPlayerCardsInPlay(opp, "Ichneumon Druid"); for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); Ability ability = new Ability(card, "0") { @Override public void resolve() { player.addDamage(4, card); } }; // ability StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append("Whenever an opponent casts an instant spell other than the first instant spell that player casts each turn, Ichneumon Druid deals 4 damage to him or her."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } }//playCard_Ichneumon_Druid() /** * <p>playCard_Venser_Emblem.</p> * * @param c a {@link forge.Card} object. */ public static void playCard_Venser_Emblem(Card c) { final Player controller = c.getController(); CardList list = AllZoneUtil.getPlayerCardsInPlay(controller); list = list.filter(new CardListFilter() { public boolean addCard(Card crd) { return crd.hasKeyword("Whenever you cast a spell, exile target permanent."); } }); for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); final SpellAbility ability = new Ability(card, "0") { public void resolve() { Card target = getTargetCard(); if (CardFactoryUtil.canTarget(card, target) && AllZoneUtil.isCardInPlay(target)) AllZone.getGameAction().exile(target); } public void chooseTargetAI() { CardList humanList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getHumanPlayer()); CardList compList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer()); CardListFilter filter = new CardListFilter() { public boolean addCard(Card c) { return CardFactoryUtil.canTarget(card, c); } }; humanList = humanList.filter(filter); compList = compList.filter(filter); if (humanList.size() > 0) { CardListUtil.sortCMC(humanList); setTargetCard(humanList.get(0)); } else if (compList.size() > 0) { CardListUtil.sortCMC(compList); compList.reverse(); setTargetCard(compList.get(0)); } } }; Input runtime = new Input() { private static final long serialVersionUID = -7620283169787412409L; @Override public void showMessage() { CardList list = AllZoneUtil.getCardsInPlay(); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return c.isPermanent() && CardFactoryUtil.canTarget(card, c); } }); stopSetNext(CardFactoryUtil.input_targetSpecific(ability, list, "Select target permanent to Exile", true, false)); }//showMessage() };//Input ability.setBeforePayMana(runtime); if (controller.isHuman()) AllZone.getGameAction().playSpellAbility(ability); else { ability.chooseTargetAI(); AllZone.getStack().addSimultaneousStackEntry(ability); } } } /** * <p>playCard_Standstill.</p> * * @param c a {@link forge.Card} object. */ public static void playCard_Standstill(Card c) { CardList list = AllZoneUtil.getCardsInPlay("Standstill"); for (int i = 0; i < list.size(); i++) { final Player drawer = c.getController().getOpponent(); final Card card = list.get(i); Ability ability2 = new Ability(card, "0") { @Override public void resolve() { // sac standstill AllZone.getGameAction().sacrifice(card); // player who didn't play spell, draws 3 cards drawer.drawCards(3); } }; // ability2 StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - ").append(c.getController()); sb.append(" played a spell, ").append(drawer).append(" draws three cards."); ability2.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability2); } } /** * <p>playCard_Curse_of_Wizardry.</p> * * @param c a {@link forge.Card} object. */ public static void playCard_Curse_of_Wizardry(final Card c) { CardList list = AllZoneUtil.getCardsInPlay("Curse of Wizardry"); if (list.size() > 0) { ArrayList<String> cl = CardUtil.getColors(c); for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); if (cl.contains(card.getChosenColor())) { Ability ability = new Ability(card, "0") { public void resolve() { c.getController().loseLife(1, card); } //resolve };//ability StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - ").append(c.getController()); sb.append(" played a ").append(card.getChosenColor()).append(" spell, "); sb.append(c.getController()).append(" loses 1 life."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } }//if }//if }//Curse of Wizardry //UPKEEP CARDS: /** * <p>payManaDuringAbilityResolve.</p> * * @param message a {@link java.lang.String} object. * @param manaCost a {@link java.lang.String} object. * @param paid a {@link forge.Command} object. * @param unpaid a {@link forge.Command} object. */ public static void payManaDuringAbilityResolve(String message, String manaCost, Command paid, Command unpaid) { // temporarily disable the Resolve flag, so the user can payMana for the resolving Ability boolean bResolving = AllZone.getStack().getResolving(); AllZone.getStack().setResolving(false); AllZone.getInputControl().setInput(new Input_PayManaCost_Ability(message, manaCost, paid, unpaid)); AllZone.getStack().setResolving(bResolving); } /** * <p>upkeep_Braid_Of_Fire.</p> */ private static void upkeep_Braid_Of_Fire() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList braids = AllZoneUtil.getPlayerCardsInPlay(player, "Braid of Fire"); for (int i = 0; i < braids.size(); i++) { final Card c = braids.get(i); final StringBuilder sb = new StringBuilder(); sb.append("Cumulative Upkeep for ").append(c).append("\n"); final Ability upkeepAbility = new Ability(c, "0") { @Override public void resolve() { c.addCounter(Counters.AGE, 1); int ageCounters = c.getCounters(Counters.AGE); Ability_Mana abMana = new Ability_Mana(c, "0", "R", ageCounters) { private static final long serialVersionUID = -2182129023960978132L; }; if (player.isComputer()) { abMana.produceMana(); } else if (GameActionUtil.showYesNoDialog(c, sb.toString())) { abMana.produceMana(); } else { AllZone.getGameAction().sacrifice(c); } } }; upkeepAbility.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(upkeepAbility); } } //upkeep_Braid_of_Fire /** * <p>upkeep_Echo.</p> */ private static void upkeep_Echo() { CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getPhase().getPlayerTurn()); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return c.hasKeyword("(Echo unpaid)"); } }); for (int i = 0; i < list.size(); i++) { final Card c = list.get(i); if (c.getIntrinsicKeyword().contains("(Echo unpaid)")) { final Command paidCommand = Command.Blank; final Command unpaidCommand = new Command() { private static final long serialVersionUID = -7354791599039157375L; public void execute() { AllZone.getGameAction().sacrifice(c); } }; final Ability aiPaid = upkeepAIPayment(c, c.getEchoCost()); final StringBuilder sb = new StringBuilder(); sb.append("Echo for ").append(c).append("\n"); final Ability sacAbility = new Ability(c, "0") { @Override public void resolve() { if (c.getController().isHuman()) { payManaDuringAbilityResolve(sb.toString(), c.getEchoCost(), paidCommand, unpaidCommand); } else //computer { if (ComputerUtil.canPayCost(aiPaid)) ComputerUtil.playNoStack(aiPaid); else AllZone.getGameAction().sacrifice(c); } } }; sacAbility.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(sacAbility); c.removeIntrinsicKeyword("(Echo unpaid)"); } } }//echo /** * <p>upkeep_Slowtrips.</p> */ private static void upkeep_Slowtrips() { // Draw a card at the beginning of the next turn's upkeep. final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = player.getSlowtripList(); for (int i = 0; i < list.size(); i++) { Card card = list.get(i); card.removeIntrinsicKeyword("Draw a card at the beginning of the next turn's upkeep."); //otherwise another slowtrip gets added final Ability slowtrip = new Ability(card, "0") { @Override public void resolve() { player.drawCard(); } }; slowtrip.setStackDescription(card.getName() + " - Draw a card"); AllZone.getStack().addSimultaneousStackEntry(slowtrip); } player.clearSlowtripList(); //Do the same for the opponent final Player opponent = player.getOpponent(); list = opponent.getSlowtripList(); for (int i = 0; i < list.size(); i++) { Card card = list.get(i); card.removeIntrinsicKeyword("Draw a card at the beginning of the next turn's upkeep."); //otherwise another slowtrip gets added final Ability slowtrip = new Ability(card, "0") { @Override public void resolve() { opponent.drawCard(); } }; slowtrip.setStackDescription(card.getName() + " - Draw a card"); AllZone.getStack().addSimultaneousStackEntry(slowtrip); } opponent.clearSlowtripList(); } /** * <p>upkeep_UpkeepCost.</p> */ private static void upkeep_UpkeepCost() { CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getPhase().getPlayerTurn()); for (int i = 0; i < list.size(); i++) { final Card c = list.get(i); final Player controller = c.getController(); ArrayList<String> a = c.getKeyword(); for (int j = 0; j < a.size(); j++) { String ability = a.get(j); //destroy if (ability.startsWith("At the beginning of your upkeep, destroy CARDNAME")) { String k[] = ability.split(" pay "); final String upkeepCost = k[1].toString(); final Command unpaidCommand = new Command() { private static final long serialVersionUID = 8942537892273123542L; public void execute() { if (c.getName().equals("Cosmic Horror")) { controller.addDamage(7, c); } AllZone.getGameAction().destroy(c); } }; final Command paidCommand = Command.Blank; final Ability aiPaid = upkeepAIPayment(c, upkeepCost); final StringBuilder sb = new StringBuilder(); sb.append("Upkeep for ").append(c).append("\n"); final Ability upkeepAbility = new Ability(c, "0") { @Override public void resolve() { if (controller.isHuman()) { payManaDuringAbilityResolve(sb.toString(), upkeepCost, paidCommand, unpaidCommand); } else //computer { if (ComputerUtil.canPayCost(aiPaid) && !c.hasKeyword("Indestructible")) ComputerUtil.playNoStack(aiPaid); else AllZone.getGameAction().destroy(c); } } }; upkeepAbility.setStackDescription(sb.toString()); upkeepAbility.setDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(upkeepAbility); }//destroy //sacrifice if (ability.startsWith("At the beginning of your upkeep, sacrifice") || ability.startsWith("Cumulative upkeep")) { String cost = "0"; final StringBuilder sb = new StringBuilder(); if (ability.startsWith("At the beginning of your upkeep, sacrifice")) { String k[] = ability.split(" pay "); cost = k[1].toString(); sb.append("Sacrifice upkeep for ").append(c).append("\n"); } if (ability.startsWith("Cumulative upkeep")) { String k[] = ability.split(":"); c.addCounter(Counters.AGE, 1); cost = CardFactoryUtil.multiplyManaCost(k[1], c.getCounters(Counters.AGE)); sb.append("Cumulative upkeep for ").append(c).append("\n"); } final String upkeepCost = cost; final Command unpaidCommand = new Command() { private static final long serialVersionUID = 5612348769167529102L; public void execute() { AllZone.getGameAction().sacrifice(c); } }; final Command paidCommand = Command.Blank; final Ability aiPaid = upkeepAIPayment(c, upkeepCost); final Ability upkeepAbility = new Ability(c, "0") { @Override public void resolve() { if (controller.isHuman()) { payManaDuringAbilityResolve(sb.toString(), upkeepCost, paidCommand, unpaidCommand); } else //computer { if (ComputerUtil.canPayCost(aiPaid)) ComputerUtil.playNoStack(aiPaid); else AllZone.getGameAction().sacrifice(c); } } }; upkeepAbility.setStackDescription(sb.toString()); upkeepAbility.setDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(upkeepAbility); }//sacrifice //destroy if (ability.startsWith("At the beginning of your upkeep, CARDNAME deals ")) { String k[] = ability.split("deals "); String s1 = k[1].substring(0, 2); final int upkeepDamage = Integer.parseInt(s1.trim()); String l[] = k[1].split(" pay "); final String upkeepCost = l[1].toString(); final Command unpaidCommand = new Command() { private static final long serialVersionUID = 1238166187561501928L; public void execute() { controller.addDamage(upkeepDamage, c); } }; final Command paidCommand = Command.Blank; final Ability aiPaid = upkeepAIPayment(c, upkeepCost); final StringBuilder sb = new StringBuilder(); sb.append("Damage upkeep for ").append(c).append("\n"); final Ability upkeepAbility = new Ability(c, "0") { @Override public void resolve() { if (controller.isHuman()) { payManaDuringAbilityResolve(sb.toString(), upkeepCost, paidCommand, unpaidCommand); } else //computer { if (ComputerUtil.canPayCost(aiPaid) && controller.predictDamage(upkeepDamage, c, false) > 0) ComputerUtil.playNoStack(aiPaid); else controller.addDamage(upkeepDamage, c); } } }; upkeepAbility.setStackDescription(sb.toString()); upkeepAbility.setDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(upkeepAbility); }//destroy } }//for }//upkeepCost /** * <p>upkeep_DamageUpkeepCost.</p> */ /*private static void upkeep_DamageUpkeepCost() { CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getPhase().getPlayerTurn()); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { ArrayList<String> a = c.getKeyword(); for (int i = 0; i < a.size(); i++) { if (a.get(i).toString().startsWith( "At the beginning of your upkeep, CARDNAME deals ")) { String k[] = a.get(i).toString().split("deals "); String s1 = k[1].substring(0, 2); s1 = s1.trim(); c.setUpkeepDamage(Integer.parseInt(s1)); System.out.println(k[1]); String l[] = k[1].split(" pay "); System.out.println(l[1]); c.setUpkeepCost(l[1]); return true; } } return false; } }); for (int i = 0; i < list.size(); i++) { final Card c = list.get(i); final Command unpaidCommand = new Command() { private static final long serialVersionUID = 8942537892273123542L; public void execute() { Player player = c.getController(); player.addDamage(c.getUpkeepDamage(), c); } }; final Command paidCommand = Command.Blank; final Ability aiPaid = upkeepAIPayment(c, c.getUpkeepCost()); final StringBuilder sb = new StringBuilder(); sb.append("Upkeep for ").append(c).append("\n"); final Ability upkeepAbility = new Ability(c, c.getUpkeepCost()) { @Override public void resolve() { if (c.getController().isHuman()) { payManaDuringAbilityResolve(sb.toString(), c.getUpkeepCost(), paidCommand, unpaidCommand); } else //computer { if (ComputerUtil.canPayCost(aiPaid)) ComputerUtil.playNoStack(aiPaid); else AllZone.getGameAction().sacrifice(c); } } }; upkeepAbility.setStackDescription(sb.toString()); upkeepAbility.setDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(upkeepAbility); } }//damageUpkeepCost */ /** * <p>upkeepAIPayment.</p> * * @param c a {@link forge.Card} object. * @param cost a {@link java.lang.String} object. * @param cost a {@link java.lang.String} object. * @return a {@link forge.card.spellability.Ability} object. */ private static Ability upkeepAIPayment(Card c, String cost) { return new Ability_Static(c, cost) { @Override public void resolve() { } }; } /** * <p>upkeep_The_Abyss.</p> */ private static void upkeep_The_Abyss() { /* * At the beginning of each player's upkeep, destroy target * nonartifact creature that player controls of his or her * choice. It can't be regenerated. */ final Player player = AllZone.getPhase().getPlayerTurn(); final CardList the = AllZoneUtil.getCardsInPlay("The Abyss"); final CardList magus = AllZoneUtil.getCardsInPlay("Magus of the Abyss"); CardList cards = new CardList(); cards.addAll(the); cards.addAll(magus); for (Card c : cards) { final Card abyss = c; final Ability sacrificeCreature = new Ability(abyss, "") { @Override public void resolve() { if (player.isHuman()) { if (abyss_getTargets(player, abyss).size() > 0) { AllZone.getInputControl().setInput(new Input() { private static final long serialVersionUID = 4820011040853968644L; public void showMessage() { AllZone.getDisplay().showMessage(abyss.getName() + " - Select one nonartifact creature to destroy"); ButtonUtil.disableAll(); } public void selectCard(Card selected, PlayerZone zone) { //probably need to restrict by controller also if (selected.isCreature() && !selected.isArtifact() && CardFactoryUtil.canTarget(abyss, selected) && zone.is(Constant.Zone.Battlefield) && zone.getPlayer().isHuman()) { AllZone.getGameAction().destroyNoRegeneration(selected); stop(); } }//selectCard() });//Input } } else { //computer CardList targets = abyss_getTargets(player, abyss); CardList indestruct = targets.getKeyword("Indestructible"); if (indestruct.size() > 0) { AllZone.getGameAction().destroyNoRegeneration(indestruct.get(0)); } else { Card target = CardFactoryUtil.AI_getWorstCreature(targets); if (null == target) { //must be nothing valid to destroy } else AllZone.getGameAction().destroyNoRegeneration(target); } } }//resolve };//sacrificeCreature StringBuilder sb = new StringBuilder(); sb.append(abyss.getName()).append(" - destroy a nonartifact creature of your choice."); sacrificeCreature.setStackDescription(sb.toString()); if (abyss_getTargets(player, abyss).size() > 0) AllZone.getStack().addSimultaneousStackEntry(sacrificeCreature); }//end for }//The Abyss /** * <p>abyss_getTargets.</p> * * @param player a {@link forge.Player} object. * @param card a {@link forge.Card} object. * @return a {@link forge.CardList} object. */ private static CardList abyss_getTargets(final Player player, Card card) { CardList creats = AllZoneUtil.getCreaturesInPlay(player); creats = creats.filter(AllZoneUtil.nonartifacts); creats = creats.getTargetableCards(card); return creats; } /** * <p>upkeep_Mana_Vortex.</p> */ private static void upkeep_Mana_Vortex() { /* * At the beginning of each player's upkeep, that player * sacrifices a land. */ final Player player = AllZone.getPhase().getPlayerTurn(); final CardList vortices = AllZoneUtil.getCardsInPlay("Mana Vortex"); for (Card c : vortices) { final Card vortex = c; final Ability sacrificeLand = new Ability(vortex, "") { @Override public void resolve() { CardList choices = AllZoneUtil.getPlayerLandsInPlay(player); player.sacrificePermanent(vortex.getName() + " - select a land to sacrifice.", choices); //if no lands in play, sacrifice all "Mana Vortex"s if (AllZoneUtil.getLandsInPlay().size() == 0) { for (Card d : vortices) { AllZone.getGameAction().sacrifice(d); } return; } }//resolve };//sacrificeCreature StringBuilder sb = new StringBuilder(); sb.append(vortex.getName()).append(" - " + player + " sacrifices a land."); sacrificeLand.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(sacrificeLand); }//end for }//Mana_Vortex /** * <p>upkeep_Yawgmoth_Demon.</p> */ private static void upkeep_Yawgmoth_Demon() { /* * At the beginning of your upkeep, you may sacrifice an artifact. If * you don't, tap Yawgmoth Demon and it deals 2 damage to you. */ final Player player = AllZone.getPhase().getPlayerTurn(); final CardList cards = AllZoneUtil.getPlayerCardsInPlay(player, "Yawgmoth Demon"); for (int i = 0; i < cards.size(); i++) { final Card c = cards.get(i); final Ability sacrificeArtifact = new Ability(c, "") { @Override public void resolve() { CardList artifacts = AllZoneUtil.getPlayerCardsInPlay(player); artifacts = artifacts.filter(AllZoneUtil.artifacts); if (player.isHuman()) { AllZone.getInputControl().setInput(new Input() { private static final long serialVersionUID = -1698502376924356936L; public void showMessage() { AllZone.getDisplay().showMessage("Yawgmoth Demon - Select one artifact to sacrifice or be dealt 2 damage"); ButtonUtil.enableOnlyCancel(); } public void selectButtonCancel() { tapAndDamage(player); stop(); } public void selectCard(Card artifact, PlayerZone zone) { //probably need to restrict by controller also if (artifact.isArtifact() && zone.is(Constant.Zone.Battlefield) && zone.getPlayer().isHuman()) { AllZone.getGameAction().sacrifice(artifact); stop(); } }//selectCard() });//Input } else { //computer Card target = CardFactoryUtil.AI_getCheapestPermanent(artifacts, c, false); if (null == target) { tapAndDamage(player); } else AllZone.getGameAction().sacrifice(target); } }//resolve private void tapAndDamage(Player player) { c.tap(); player.addDamage(2, c); } }; StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - sacrifice an artifact or "); sb.append(c.getName()).append(" becomes tapped and deals 2 damage to you."); sacrificeArtifact.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(sacrificeArtifact); }//end for } /** * <p>upkeep_Lord_of_the_Pit.</p> */ private static void upkeep_Lord_of_the_Pit() { /* * At the beginning of your upkeep, sacrifice a creature other than * Lord of the Pit. If you can't, Lord of the Pit deals 7 damage to you. */ final Player player = AllZone.getPhase().getPlayerTurn(); CardList lords = AllZoneUtil.getPlayerCardsInPlay(player, "Lord of the Pit"); lords.addAll(AllZoneUtil.getPlayerCardsInPlay(player, "Liege of the Pit")); final CardList cards = lords; for (int i = 0; i < cards.size(); i++) { final Card c = cards.get(i); if (c.isFaceDown()) continue; final Ability sacrificeCreature = new Ability(c, "") { @Override public void resolve() { //TODO: this should handle the case where you sacrifice 2 LOTPs to each other CardList creatures = AllZoneUtil.getCreaturesInPlay(player); creatures.remove(c); if (player.isHuman()) { AllZone.getInputControl().setInput(PlayerUtil.input_sacrificePermanent(creatures, c.getName() + " - Select a creature to sacrifice.")); } else { //computer Card target = CardFactoryUtil.AI_getWorstCreature(creatures); AllZone.getGameAction().sacrifice(target); } }//resolve }; final Ability sevenDamage = new Ability(c, "") { @Override public void resolve() { player.addDamage(7, c); } }; CardList creatures = AllZoneUtil.getCreaturesInPlay(player); creatures.remove(c); if (creatures.size() == 0) { //there are no creatures to sacrifice, so we must do the 7 damage StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - deals 7 damage to controller"); sevenDamage.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(sevenDamage); } else { StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - sacrifice a creature."); sacrificeCreature.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(sacrificeCreature); } }//end for }// upkeep_Lord_of_the_Pit() /** * <p>upkeep_Drop_of_Honey.</p> */ private static void upkeep_Drop_of_Honey() { /* * At the beginning of your upkeep, destroy the creature with the * least power. It can't be regenerated. If two or more creatures * are tied for least power, you choose one of them. */ final Player player = AllZone.getPhase().getPlayerTurn(); CardList drops = AllZoneUtil.getPlayerCardsInPlay(player, "Drop of Honey"); drops.addAll(AllZoneUtil.getPlayerCardsInPlay(player, "Porphyry Nodes")); final CardList cards = drops; for (int i = 0; i < cards.size(); i++) { final Card c = cards.get(i); final Ability ability = new Ability(c, "") { @Override public void resolve() { CardList creatures = AllZoneUtil.getCreaturesInPlay(); if (creatures.size() > 0) { CardListUtil.sortAttackLowFirst(creatures); int power = creatures.get(0).getNetAttack(); if (player.isHuman()) { AllZone.getInputControl().setInput(CardFactoryUtil.input_destroyNoRegeneration(getLowestPowerList(creatures), "Select creature with power: " + power + " to sacrifice.")); } else { //computer Card compyTarget = getCompyCardToDestroy(creatures); AllZone.getGameAction().destroyNoRegeneration(compyTarget); } } }//resolve private CardList getLowestPowerList(CardList original) { CardList lowestPower = new CardList(); int power = original.get(0).getNetAttack(); int i = 0; while (i < original.size() && original.get(i).getNetAttack() == power) { lowestPower.add(original.get(i)); i++; } return lowestPower; } private Card getCompyCardToDestroy(CardList original) { CardList options = getLowestPowerList(original); CardList humanCreatures = options.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getController().isHuman(); } }); if (humanCreatures.isEmpty()) { options.shuffle(); return options.get(0); } else { humanCreatures.shuffle(); return humanCreatures.get(0); } } };// Ability StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - destroy 1 creature with lowest power."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }//end for }// upkeep_Drop_of_Honey() /** * <p>upkeep_Demonic_Hordes.</p> */ private static void upkeep_Demonic_Hordes() { /* * At the beginning of your upkeep, unless you pay BBB, * tap Demonic Hordes and sacrifice a land of an opponent's choice. */ final Player player = AllZone.getPhase().getPlayerTurn(); final CardList cards = AllZoneUtil.getPlayerCardsInPlay(player, "Demonic Hordes"); for (int i = 0; i < cards.size(); i++) { final Card c = cards.get(i); final Ability noPay = new Ability(c, "B B B") { private static final long serialVersionUID = 4820011390853920644L; @Override public void resolve() { CardList playerLand = AllZoneUtil.getPlayerLandsInPlay(player); c.tap(); if (c.getController().isComputer()) { if (playerLand.size() > 0) AllZone.getInputControl().setInput(PlayerUtil.input_sacrificePermanent(playerLand, c.getName() + " - Select a land to sacrifice.")); } else { Card target = CardFactoryUtil.AI_getBestLand(playerLand); AllZone.getGameAction().sacrifice(target); } } //end resolve() }; //end noPay ability if (c.getController().isHuman()) { String question = "Pay Demonic Hordes upkeep cost?"; if (GameActionUtil.showYesNoDialog(c, question)) { final Ability pay = new Ability(c, "0") { private static final long serialVersionUID = 4820011440853920644L; public void resolve() { if (AllZone.getZone(c).is(Constant.Zone.Battlefield)) { StringBuilder cost = new StringBuilder(); cost.append("Pay cost for ").append(c).append("\r\n"); GameActionUtil.payManaDuringAbilityResolve(cost.toString(), noPay.getManaCost(), Command.Blank, Command.Blank); } } //end resolve() }; //end pay ability pay.setStackDescription("Demonic Hordes - Upkeep Cost"); AllZone.getStack().addSimultaneousStackEntry(pay); } //end choice else { StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - is tapped and you must sacrifice a land of opponent's choice"); noPay.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(noPay); } } //end human else { //computer if ((c.getController().isComputer() && (ComputerUtil.canPayCost(noPay)))) { final Ability computerPay = new Ability(c, "0") { private static final long serialVersionUID = 4820011440852868644L; public void resolve() { ComputerUtil.payManaCost(noPay); } }; computerPay.setStackDescription("Computer pays Demonic Hordes upkeep cost"); AllZone.getStack().addSimultaneousStackEntry(computerPay); } else { AllZone.getStack().addSimultaneousStackEntry(noPay); } } //end computer } //end for loop } //upkeep_Demonic_Hordes //END UPKEEP CARDS //START ENDOFTURN CARDS /** * <p>endOfTurn_Wall_Of_Reverence.</p> */ public static void endOfTurn_Wall_Of_Reverence() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Wall of Reverence"); Ability ability; for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); ability = new Ability(list.get(i), "0") { public void resolve() { CardList creats = AllZoneUtil.getCreaturesInPlay(player); creats = creats.filter(AllZoneUtil.getCanTargetFilter(card)); if (creats.size() == 0) return; if (player.isHuman()) { Object o = GuiUtils.getChoiceOptional("Select target creature for Wall of Reverence life gain", creats.toArray()); if (o != null) { Card c = (Card) o; int power = c.getNetAttack(); player.gainLife(power, card); } } else//computer { CardListUtil.sortAttack(creats); Card c = creats.get(0); if (c != null) { int power = c.getNetAttack(); player.gainLife(power, card); } } } // resolve }; // ability StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append(player).append(" gains life equal to target creature's power."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } }//endOfTurn_Wall_Of_Reverence() /** * <p>endOfTurn_Predatory_Advantage.</p> */ public static void endOfTurn_Predatory_Advantage() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player.getOpponent(), "Predatory Advantage"); for (int i = 0; i < list.size(); i++) { final Player controller = list.get(i).getController(); if ((player.isHuman() && Phase.getPlayerCreatureSpellCount() == 0) || (player.isComputer() && Phase.getComputerCreatureSpellCount() == 0)) { Ability abTrig = new Ability(list.get(i), "0") { public void resolve() { CardFactoryUtil.makeToken("Lizard", "G 2 2 Lizard", controller, "G", new String[]{"Creature", "Lizard"}, 2, 2, new String[]{""}); } }; abTrig.setTrigger(true); abTrig.setStackDescription("At the beginning of each opponent's end step, if that player didn't cast a creature spell this turn, put a 2/2 green Lizard creature token onto the battlefield."); AllZone.getGameAction().playSpellAbility(abTrig); } } } /** * <p>endOfTurn_Lighthouse_Chronologist.</p> */ public static void endOfTurn_Lighthouse_Chronologist() { final Player player = AllZone.getPhase().getPlayerTurn(); final Player opponent = player.getOpponent(); CardList list = AllZoneUtil.getPlayerCardsInPlay(opponent); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getName().equals("Lighthouse Chronologist") && c.getCounters(Counters.LEVEL) >= 7; } }); Ability ability; for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); ability = new Ability(list.get(i), "0") { public void resolve() { AllZone.getPhase().addExtraTurn(card.getController()); } }; StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append(card.getController()).append(" takes an extra turn."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } /** * <p>endOfTurn_Krovikan_Horror.</p> */ public static void endOfTurn_Krovikan_Horror() { final Player player = AllZone.getPhase().getPlayerTurn(); final Player opponent = player.getOpponent(); horrorReturn(player); horrorReturn(opponent); } /** * <p>horrorReturn.</p> * * @param player a {@link forge.Player} object. */ public static void horrorReturn(Player player) { // Find each Horror, peek at the card above it, if it's a creature return to hand CardList grave = AllZoneUtil.getPlayerGraveyard(player); if (grave.getName("Krovikan Horror").size() == 0) return; int i = 0; while (i + 1 < grave.size()) { Card c = grave.get(i); ArrayList<String> types = grave.get(i + 1).getType(); if (c.getName().equals("Krovikan Horror") && types.contains("Creature")) { if (player.isHuman()) { String question = "Return Krovikan Horror to your hand?"; if (GameActionUtil.showYesNoDialog(c, question)) { AllZone.getGameAction().moveToHand(c); grave.remove(c); } // increment counter to next occurance of Krovikan Horror // if human decides not to return Krovikan Horror to hand else i++; } // player is computer else { AllZone.getGameAction().moveToHand(c); grave.remove(c); } } else i++; } } //END ENDOFTURN CARDS /** * <p>removeAttackedBlockedThisTurn.</p> */ public static void removeAttackedBlockedThisTurn() { // resets the status of attacked/blocked this turn Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getCreaturesInPlay(player); for (int i = 0; i < list.size(); i++) { Card c = list.get(i); if (c.getCreatureAttackedThisCombat()) c.setCreatureAttackedThisCombat(false); if (c.getCreatureBlockedThisCombat()) c.setCreatureBlockedThisCombat(false); //do not reset setCreatureAttackedThisTurn(), this appears to be combat specific if (c.getCreatureGotBlockedThisCombat()) c.setCreatureGotBlockedThisCombat(false); } AllZone.getGameInfo().setAssignedFirstStrikeDamageThisCombat(false); AllZone.getGameInfo().setResolvedFirstStrikeDamageThisCombat(false); } /** * <p>showYesNoDialog.</p> * * @param c a {@link forge.Card} object. * @param question a {@link java.lang.String} object. * @return a boolean. */ public static boolean showYesNoDialog(Card c, String question) { return showYesNoDialog(c, question, false); } /** * <p>showYesNoDialog.</p> * * @param c a {@link forge.Card} object. * @param question a {@link java.lang.String} object. * @param defaultNo true if the default option should be "No", false otherwise * @return a boolean. */ public static boolean showYesNoDialog(Card c, String question, boolean defaultNo) { AllZone.getDisplay().setCard(c); StringBuilder title = new StringBuilder(); title.append(c.getName()).append(" - Ability"); if (!(question.length() > 0)) { question = "Activate card's ability?"; } int answer; if(defaultNo) { Object options[] = {"Yes", "No"}; answer = JOptionPane.showOptionDialog(null, question, title.toString(), JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[1]); } else { answer= JOptionPane.showConfirmDialog(null, question, title.toString(), JOptionPane.YES_NO_OPTION); } if (answer == JOptionPane.YES_OPTION) return true; else return false; } /** * <p>showInfoDialg.</p> * * @param message a {@link java.lang.String} object. */ public static void showInfoDialg(String message) { JOptionPane.showMessageDialog(null, message); } /** * <p>flipACoin.</p> * * @param caller a {@link forge.Player} object. * @param source a {@link forge.Card} object. * @return a boolean. */ public static boolean flipACoin(Player caller, Card source) { String choice = ""; String choices[] = {"heads", "tails"}; boolean flip = (50 > MyRandom.random.nextInt(100)); if (caller.isHuman()) { choice = (String) GuiUtils.getChoice(source.getName() + " - Call coin flip", choices); } else { choice = choices[MyRandom.random.nextInt(2)]; } if ((flip == true && choice.equals("heads")) || (flip == false && choice.equals("tails"))) { JOptionPane.showMessageDialog(null, source.getName() + " - " + caller + " wins flip.", source.getName(), JOptionPane.PLAIN_MESSAGE); return true; } else { JOptionPane.showMessageDialog(null, source.getName() + " - " + caller + " loses flip.", source.getName(), JOptionPane.PLAIN_MESSAGE); return false; } } /** * <p>executeLandfallEffects.</p> * * @param c a {@link forge.Card} object. */ public static void executeLandfallEffects(Card c) { if (c.getName().equals("Lotus Cobra")) landfall_Lotus_Cobra(c); } /** * <p>showLandfallDialog.</p> * * @param c a {@link forge.Card} object. * @return a boolean. */ private static boolean showLandfallDialog(Card c) { AllZone.getDisplay().setCard(c); String[] choices = {"Yes", "No"}; Object q = null; q = GuiUtils.getChoiceOptional("Use " + c.getName() + " Landfall?", choices); if (q == null || q.equals("No")) return false; else return true; } /** * <p>landfall_Lotus_Cobra.</p> * * @param c a {@link forge.Card} object. */ private static void landfall_Lotus_Cobra(final Card c) { Ability ability = new Ability(c, "0") { @Override public void resolve() { String color = ""; Object o = GuiUtils.getChoice("Choose mana color", Constant.Color.onlyColors); color = Input_PayManaCostUtil.getShortColorString((String) o); Ability_Mana abMana = new Ability_Mana(c, "0", color) { private static final long serialVersionUID = -2182129023960978132L; }; abMana.produceMana(); } }; StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - add one mana of any color to your mana pool."); ability.setStackDescription(sb.toString()); if (c.getController().isHuman()) { if (showLandfallDialog(c)) AllZone.getStack().addSimultaneousStackEntry(ability); } else { // TODO: once AI has a mana pool he should choose add Ability and choose a mana as appropriate } } //not restricted to combat damage, not restricted to dealing damage to creatures/players /** * <p>executeDamageDealingEffects.</p> * * @param source a {@link forge.Card} object. * @param damage a int. */ public static void executeDamageDealingEffects(final Card source, int damage) { if (damage <= 0) return; if (source.hasKeyword("Lifelink")) source.getController().gainLife(damage, source); } //restricted to combat damage and dealing damage to creatures /** * <p>executeCombatDamageToCreatureEffects.</p> * * @param source a {@link forge.Card} object. * @param affected a {@link forge.Card} object. * @param damage a int. */ public static void executeCombatDamageToCreatureEffects(final Card source, final Card affected, int damage) { if (damage <= 0) return; //placeholder for any future needs (everything that was here is converted to script) } //not restricted to combat damage, restricted to dealing damage to creatures /** * <p>executeDamageToCreatureEffects.</p> * * @param source a {@link forge.Card} object. * @param affected a {@link forge.Card} object. * @param damage a int. */ public static void executeDamageToCreatureEffects(final Card source, final Card affected, int damage) { if (damage <= 0) return; if (affected.getName().equals("Stuffy Doll")) { final Player opponent = affected.getOwner().getOpponent(); final int stuffyDamage = damage; SpellAbility ability = new Ability(affected, "0") { @Override public void resolve() { opponent.addDamage(stuffyDamage, affected); } }; StringBuilder sb = new StringBuilder(); sb.append(affected.getName() + " - Deals ").append(stuffyDamage).append(" damage to ").append(opponent); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } if (affected.hasKeyword("Whenever CARDNAME is dealt damage, put a +1/+1 counter on it.")) { Ability ability2 = new Ability(affected, "0") { @Override public void resolve() { affected.addCounter(Counters.P1P1, 1); } }; // ability2 StringBuilder sb2 = new StringBuilder(); sb2.append(affected.getName()).append(" - gets a +1/+1 counter"); ability2.setStackDescription(sb2.toString()); int amount = affected.getAmountOfKeyword("Whenever CARDNAME is dealt damage, put a +1/+1 counter on it."); for (int i = 0; i < amount; i++) AllZone.getStack().addSimultaneousStackEntry(ability2); } if (affected.hasStartOfKeyword("When CARDNAME is dealt damage, destroy it.")) { final Ability ability = new Ability(source, "0") { @Override public void resolve() { AllZone.getGameAction().destroy(affected); } }; final Ability ability2 = new Ability(source, "0") { @Override public void resolve() { AllZone.getGameAction().destroyNoRegeneration(affected); } }; StringBuilder sb = new StringBuilder(); sb.append(affected).append(" - destroy"); ability.setStackDescription(sb.toString()); ability2.setStackDescription(sb.toString()); if (affected.hasKeyword("When CARDNAME is dealt damage, destroy it. It can't be regenerated.")) { int amount = affected.getAmountOfKeyword("When CARDNAME is dealt damage, destroy it. It can't be regenerated."); for (int i = 0; i < amount; i++) AllZone.getStack().addSimultaneousStackEntry(ability2); } int amount = affected.getAmountOfKeyword("When CARDNAME is dealt damage, destroy it."); for (int i = 1; i < amount; i++) AllZone.getStack().addSimultaneousStackEntry(ability); AllZone.getStack().addSimultaneousStackEntry(ability); } if (source.hasKeyword("Deathtouch") && affected.isCreature()) AllZone.getGameAction().destroy(affected); } /** * <p>executeSwordOfLightAndShadowEffects.</p> * * @param source a {@link forge.Card} object. */ public static void executeSwordOfLightAndShadowEffects(final Card source) { final Card src = source; final Ability ability = new Ability(src, "0") { @Override public void resolve() { Card target = getTargetCard(); if (target != null) { if (AllZoneUtil.isCardInPlayerGraveyard(src.getController(), target)) { PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, src.getController()); AllZone.getGameAction().moveTo(hand, target); } } src.getController().gainLife(3, source); } }; // ability Command res = new Command() { private static final long serialVersionUID = -7433708170033536384L; public void execute() { CardList list = AllZoneUtil.getPlayerGraveyard(src.getController()); list = list.filter(AllZoneUtil.creatures); if (list.isEmpty()) { AllZone.getStack().addSimultaneousStackEntry(ability); return; } if (src.getController().isHuman()) { Object o = GuiUtils.getChoiceOptional("Select target card", list.toArray()); if (o != null) { ability.setTargetCard((Card) o); AllZone.getStack().addSimultaneousStackEntry(ability); } }//if else//computer { Card best = CardFactoryUtil.AI_getBestCreature(list); ability.setTargetCard(best); AllZone.getStack().addSimultaneousStackEntry(ability); } }//execute() };//Command StringBuilder sb = new StringBuilder(); sb.append("Sword of Light and Shadow - You gain 3 life and you may return "); sb.append("up to one target creature card from your graveyard to your hand"); ability.setStackDescription(sb.toString()); res.execute(); } //this is for cards like Sengir Vampire /** * <p>executeVampiricEffects.</p> * * @param c a {@link forge.Card} object. */ public static void executeVampiricEffects(Card c) { ArrayList<String> a = c.getKeyword(); for (int i = 0; i < a.size(); i++) { if (AllZoneUtil.isCardInPlay(c) && a.get(i).toString().startsWith( "Whenever a creature dealt damage by CARDNAME this turn is put into a graveyard, put")) { final Card thisCard = c; final String kw = a.get(i).toString(); Ability ability2 = new Ability(c, "0") { @Override public void resolve() { Counters counter = Counters.P1P1; if (kw.contains("+2/+2")) counter = Counters.P2P2; if (AllZoneUtil.isCardInPlay(thisCard)) thisCard.addCounter(counter, 1); } }; // ability2 StringBuilder sb = new StringBuilder(); sb.append(c.getName()); if (kw.contains("+2/+2")) { sb.append(" - gets a +2/+2 counter"); } else { sb.append(" - gets a +1/+1 counter"); } ability2.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability2); } } } //not restricted to just combat damage, restricted to players /** * <p>executeDamageToPlayerEffects.</p> * * @param player a {@link forge.Player} object. * @param c a {@link forge.Card} object. * @param damage a int. */ public static void executeDamageToPlayerEffects(final Player player, final Card c, final int damage) { if (damage <= 0) return; CardList playerPerms = AllZoneUtil.getPlayerCardsInPlay(player); if (playerPerms.getName("Farsight Mask").size() > 0) { final Card c1 = c; CardList l = playerPerms.filter(new CardListFilter() { public boolean addCard(Card crd) { return crd.getName().equals("Farsight Mask") && crd.isUntapped() && !c1.getController().equals(crd.getController()); } }); for (Card crd : l) playerDamage_Farsight_Mask(player, c, crd); } if (AllZoneUtil.isCardInPlay("Lich", player)) { CardList lichs = playerPerms.getName("Lich"); for (Card crd : lichs) { final Card lich = crd; SpellAbility ability = new Ability(lich, "0") { public void resolve() { for (int i = 0; i < damage; i++) { CardList nonTokens = AllZoneUtil.getPlayerCardsInPlay(player); nonTokens = nonTokens.filter(AllZoneUtil.nonToken); if (nonTokens.size() == 0) { player.altLoseConditionMet("Lich"); } else player.sacrificePermanent("Select a permanent to sacrifice", nonTokens); } } }; StringBuilder sb = new StringBuilder(); sb.append(lich.getName()).append(" - ").append(lich.getController()); sb.append(" sacrifices ").append(damage).append(" nontoken Permanents."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } if (c.getName().equals("Whirling Dervish") || c.getName().equals("Dunerider Outlaw")) playerCombatDamage_Whirling_Dervish(c); if (player.isPlayer(AllZone.getHumanPlayer())) c.setDealtDmgToHumanThisTurn(true); if (player.isPlayer(AllZone.getComputerPlayer())) c.setDealtDmgToComputerThisTurn(true); } //restricted to combat damage, restricted to players /** * <p>executeCombatDamageToPlayerEffects.</p> * * @param player a {@link forge.Player} object. * @param c a {@link forge.Card} object. * @param damage a int. */ public static void executeCombatDamageToPlayerEffects(final Player player, final Card c, final int damage) { if (damage <= 0) return; if (c.isCreature() && AllZoneUtil.isCardInPlay("Contested War Zone", player)) { CardList zones = AllZoneUtil.getPlayerCardsInPlay(player, "Contested War Zone"); for (final Card zone : zones) { Ability ability = new Ability(zone, "0") { @Override public void resolve() { if (AllZoneUtil.isCardInPlay(zone)) { AllZone.getGameAction().changeController(new CardList(zone), zone.getController(), c.getController()); } } }; ability.setStackDescription(zone + " - " + c.getController() + " gains control of " + zone); AllZone.getStack().addSimultaneousStackEntry(ability); } } if (c.hasStartOfKeyword("Poisonous")) { int KeywordPosition = c.getKeywordPosition("Poisonous"); String parse = c.getKeyword().get(KeywordPosition).toString(); String k[] = parse.split(" "); final int poison = Integer.parseInt(k[1]); final Card crd = c; Ability ability = new Ability(c, "0") { public void resolve() { final Player player = crd.getController(); final Player opponent = player.getOpponent(); if (opponent.isHuman()) AllZone.getHumanPlayer().addPoisonCounters(poison); else AllZone.getComputerPlayer().addPoisonCounters(poison); } }; StringBuilder sb = new StringBuilder(); sb.append(c); sb.append(" - Poisonous: "); sb.append(c.getController().getOpponent()); sb.append(" gets "); sb.append(poison); sb.append(" poison counters."); ability.setStackDescription(sb.toString()); ArrayList<String> keywords = c.getKeyword(); for (int i = 0; i < keywords.size(); i++) { if (keywords.get(i).startsWith("Poisonous")) AllZone.getStack().addSimultaneousStackEntry(ability); } } if (CardFactoryUtil.hasNumberEquipments(c, "Quietus Spike") > 0 && c.getNetAttack() > 0) { for (int k = 0; k < CardFactoryUtil.hasNumberEquipments(c, "Quietus Spike"); k++) { playerCombatDamage_lose_halflife_up(c); } } if (c.isEquipped()) { ArrayList<Card> equips = c.getEquippedBy(); for (Card equip : equips) { if (equip.getName().equals("Sword of Light and Shadow")) { GameActionUtil.executeSwordOfLightAndShadowEffects(equip); } } }//isEquipped if (c.getName().equals("Scalpelexis")) playerCombatDamage_Scalpelexis(c); else if (c.getName().equals("Augury Adept")) playerCombatDamage_Augury_Adept(c); else if (c.getName().equals("Spawnwrithe")) playerCombatDamage_Spawnwrithe(c); else if (c.getName().equals("Treva, the Renewer")) playerCombatDamage_Treva(c); else if (c.getName().equals("Rith, the Awakener")) playerCombatDamage_Rith(c); else if (c.isEnchantedBy("Celestial Mantle")) execute_Celestial_Mantle(c); //Unused variable //c.setDealtCombatDmgToOppThisTurn(true); }//executeCombatDamageToPlayerEffects /** * <p>execute_Celestial_Mantle.</p> * * @param enchanted a {@link forge.Card} object. */ private static void execute_Celestial_Mantle(final Card enchanted) { ArrayList<Card> auras = enchanted.getEnchantedBy(); for (final Card aura : auras) { if (aura.getName().equals("Celestial Mantle")) { Ability doubleLife = new Ability(aura, "0") { public void resolve() { int life = enchanted.getController().getLife(); enchanted.getController().setLife(life * 2, aura); } }; doubleLife.setStackDescription(aura.getName() + " - " + enchanted.getController() + " doubles his or her life total."); AllZone.getStack().addSimultaneousStackEntry(doubleLife); } } } /** * <p>playerDamage_Farsight_Mask.</p> * * @param player a {@link forge.Player} object. * @param c a {@link forge.Card} object. * @param crd a {@link forge.Card} object. * @param crd a {@link forge.Card} object. */ private static void playerDamage_Farsight_Mask(final Player player, final Card c, final Card crd) { Ability ability = new Ability(crd, "0") { public void resolve() { if (crd.isUntapped()) { player.mayDrawCard(); } } }; ability.setStackDescription("Farsight Mask - You may draw a card."); AllZone.getStack().addSimultaneousStackEntry(ability); } /** * <p>playerCombatDamage_Treva.</p> * * @param c a {@link forge.Card} object. */ private static void playerCombatDamage_Treva(Card c) { SpellAbility[] sa = c.getSpellAbility(); if (c.getController().isHuman()) AllZone.getGameAction().playSpellAbility(sa[1]); else ComputerUtil.playNoStack(sa[1]); } /** * <p>playerCombatDamage_Rith.</p> * * @param c a {@link forge.Card} object. */ private static void playerCombatDamage_Rith(Card c) { SpellAbility[] sa = c.getSpellAbility(); if (c.getController().isHuman()) AllZone.getGameAction().playSpellAbility(sa[1]); else ComputerUtil.playNoStack(sa[1]); } /** * <p>playerCombatDamage_Whirling_Dervish.</p> * * @param c a {@link forge.Card} object. */ private static void playerCombatDamage_Whirling_Dervish(Card c) { final int power = c.getNetAttack(); final Card card = c; if (power > 0) { final Ability ability2 = new Ability(c, "0") { @Override public void resolve() { card.addCounter(Counters.P1P1, 1); } };// ability2 StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - gets a +1/+1 counter."); ability2.setStackDescription(sb.toString()); Command dealtDmg = new Command() { private static final long serialVersionUID = 2200679209414069339L; public void execute() { AllZone.getStack().addSimultaneousStackEntry(ability2); } }; AllZone.getEndOfTurn().addAt(dealtDmg); } // if } /** * <p>playerCombatDamage_lose_halflife_up.</p> * * @param c a {@link forge.Card} object. */ private static void playerCombatDamage_lose_halflife_up(Card c) { final Player player = c.getController(); final Player opponent = player.getOpponent(); final Card F_card = c; if (c.getNetAttack() > 0) { Ability ability2 = new Ability(c, "0") { @Override public void resolve() { int x = 0; int y = 0; if (player.isHuman()) { y = (AllZone.getComputerPlayer().getLife() % 2); if (!(y == 0)) y = 1; else y = 0; x = (AllZone.getComputerPlayer().getLife() / 2) + y; } else { y = (AllZone.getHumanPlayer().getLife() % 2); if (!(y == 0)) y = 1; else y = 0; x = (AllZone.getHumanPlayer().getLife() / 2) + y; } opponent.loseLife(x, F_card); } };// ability2 StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - ").append(opponent); sb.append(" loses half his or her life, rounded up."); ability2.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability2); } } /** * <p>playerCombatDamage_Scalpelexis.</p> * * @param c a {@link forge.Card} object. */ private static void playerCombatDamage_Scalpelexis(Card c) { final Player player = c.getController(); final Player opponent = player.getOpponent(); if (c.getNetAttack() > 0) { Ability ability = new Ability(c, "0") { @Override public void resolve() { CardList libList = AllZoneUtil.getPlayerCardsInLibrary(opponent); int count = 0; int broken = 0; for (int i = 0; i < libList.size(); i = i + 4) { Card c1 = null; Card c2 = null; Card c3 = null; Card c4 = 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 (i + 2 < libList.size()) c3 = libList.get(i + 2); else broken = 1; if (i + 3 < libList.size()) c4 = libList.get(i + 3); else broken = 1; if (broken == 0) { if ((c1.getName().contains(c2.getName()) || c1.getName().contains(c3.getName()) || c1.getName().contains(c4.getName()) || c2.getName().contains(c3.getName()) || c2.getName().contains(c4.getName()) || c3.getName().contains(c4.getName()))) { count = count + 1; } else { broken = 1; } } } count = (count * 4) + 4; int max = count; if (libList.size() < count) max = libList.size(); for (int j = 0; j < max; j++) { Card c = libList.get(j); AllZone.getGameAction().exile(c); } } };// ability StringBuilder sb = new StringBuilder(); sb.append("Scalpelexis - ").append(opponent); sb.append(" exiles the top four cards of his or her library. "); sb.append("If two or more of those cards have the same name, repeat this process."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } /** * <p>playerCombatDamage_Spawnwrithe.</p> * * @param c a {@link forge.Card} object. */ private static void playerCombatDamage_Spawnwrithe(Card c) { final Player player = c.getController(); final Card crd = c; Ability ability2 = new Ability(c, "0") { @Override public void resolve() { CardList cl = CardFactoryUtil.makeToken("Spawnwrithe", "", crd.getController(), "2 G", new String[]{ "Creature", "Elemental"}, 2, 2, new String[]{"Trample"}); for (Card c : cl) { c.setText("Whenever Spawnwrithe deals combat damage to a player, put a token that's a copy of Spawnwrithe onto the battlefield."); c.setCopiedToken(true); } } };// ability2 StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - ").append(player).append(" puts copy onto the battlefield."); ability2.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability2); } /** * <p>playerCombatDamage_Augury_Adept.</p> * * @param c a {@link forge.Card} object. */ private static void playerCombatDamage_Augury_Adept(Card c) { final Player[] player = new Player[1]; final Card crd = c; if (c.getNetAttack() > 0) { Ability ability2 = new Ability(crd, "0") { @Override public void resolve() { player[0] = crd.getController(); PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player[0]); if (lib.size() > 0) { CardList cl = new CardList(); cl.add(lib.get(0)); GuiUtils.getChoiceOptional("Top card", cl.toArray()); } ; if (lib.size() == 0) return; Card top = lib.get(0); player[0].gainLife(CardUtil.getConvertedManaCost(top.getManaCost()), crd); AllZone.getGameAction().moveToHand(top); } };// ability2 player[0] = c.getController(); StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - ").append(player[0]); sb.append(" reveals the top card of his library and put that card into his hand. "); sb.append("He gain life equal to its converted mana cost."); ability2.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability2); } } /** * <p>upkeep_AI_Aluren.</p> */ private static void upkeep_AI_Aluren() { CardList alurens = AllZoneUtil.getCardsInPlay("Aluren"); if (alurens.size() == 0) return; CardList inHand = AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer()); inHand = inHand.getType("Creature"); CardList playable = new CardList(); for (Card c : inHand) if (CardUtil.getConvertedManaCost(c.getManaCost()) <= 3) playable.add(c); for (Card c : playable) AllZone.getGameAction().playSpellAbilityForFree(c.getSpellPermanent()); } /** * <p>upkeep_Dance_of_the_Dead.</p> */ private static void upkeep_Dance_of_the_Dead() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList dances = AllZoneUtil.getPlayerCardsInPlay(player, "Dance of the Dead"); for (Card dance : dances) { final Card source = dance; final ArrayList<Card> list = source.getEnchanting(); final Card creature = list.get(0); if (creature.isTapped()) { Ability vaultChoice = new Ability(source, "0") { @Override public void resolve() { if (GameActionUtil.showYesNoDialog(source, "Untap " + creature.getName() + "?")) { //prompt for pay mana cost, then untap final SpellAbility untap = new Ability(source, "1 B") { @Override public void resolve() { creature.untap(); } };//Ability StringBuilder sb = new StringBuilder(); sb.append("Untap ").append(creature); untap.setStackDescription(sb.toString()); AllZone.getGameAction().playSpellAbility(untap); } } }; vaultChoice.setStackDescription(source.getName() + " - Untap creature during Upkeep?"); AllZone.getStack().addSimultaneousStackEntry(vaultChoice); } } } ///////////////////////// // Start of Kinship cards ///////////////////////// /** * <p>upkeep_Ink_Dissolver.</p> */ private static void upkeep_Ink_Dissolver() { final Player player = AllZone.getPhase().getPlayerTurn(); final Player opponent = player.getOpponent(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Ink Dissolver"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Merfolk", "Wizard"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantToMillOpponent = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and opponent puts the top 3 "); question.append("cards of his library into his graveyard?"); if (showYesNoDialog(k, question.toString())) { wantToMillOpponent = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantToMillOpponent = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantToMillOpponent) opponent.mill(3); }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Ink Dissolver - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Ink_Dissolver() /** * <p>upkeep_Kithkin_Zephyrnaut.</p> */ private static void upkeep_Kithkin_Zephyrnaut() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Kithkin Zephyrnaut"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Kithkin", "Soldier"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantKithkinBuff = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card, Kithkin Zephyrnaut gets +2/+2 and "); question.append("gains flying and vigilance until end of turn?"); if (showYesNoDialog(k, question.toString())) { wantKithkinBuff = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantKithkinBuff = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantKithkinBuff) { k.addTempAttackBoost(2); k.addTempDefenseBoost(2); k.addExtrinsicKeyword("Flying"); k.addExtrinsicKeyword("Vigilance"); final Command untilEOT = new Command() { private static final long serialVersionUID = 213717084767008154L; public void execute() { k.addTempAttackBoost(-2); k.addTempDefenseBoost(-2); k.removeExtrinsicKeyword("Flying"); k.removeExtrinsicKeyword("Vigilance"); } }; AllZone.getEndOfTurn().addUntil(untilEOT); } }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Kithkin Zephyrnaut - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Kithkin_Zephyrnaut() /** * <p>upkeep_Leaf_Crowned_Elder.</p> */ private static void upkeep_Leaf_Crowned_Elder() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Leaf-Crowned Elder"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Treefolk", "Shaman"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantToPlayCard = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal and play this card without paying its mana cost?"); if (showYesNoDialog(k, question.toString())) { wantToPlayCard = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantToPlayCard = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantToPlayCard) { if (player.isHuman()) { Card c = library.get(0); AllZone.getGameAction().playCardNoCost(c); } // player isComputer() else { Card c = library.get(0); ArrayList<SpellAbility> choices = c.getBasicSpells(); for (SpellAbility sa : choices) { if (sa.canPlayAI()) { ComputerUtil.playStackFree(sa); break; } } } }// wantToPlayCard }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Leaf-Crowned Elder - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Leaf_Crowned_Elder() /** * <p>upkeep_Mudbutton_Clanger.</p> */ private static void upkeep_Mudbutton_Clanger() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Mudbutton Clanger"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Goblin", "Warrior"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantGoblinBuff = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and Mudbutton Clanger gets +1/+1 until end of turn?"); if (showYesNoDialog(k, question.toString())) { wantGoblinBuff = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantGoblinBuff = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantGoblinBuff) { k.addTempAttackBoost(1); k.addTempDefenseBoost(1); final Command untilEOT = new Command() { private static final long serialVersionUID = -103560515951630426L; public void execute() { k.addTempAttackBoost(-1); k.addTempDefenseBoost(-1); } }; AllZone.getEndOfTurn().addUntil(untilEOT); } }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Mudbutton Clanger - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Mudbutton_Clanger() /** * <p>upkeep_Nightshade_Schemers.</p> */ private static void upkeep_Nightshade_Schemers() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Nightshade Schemers"); final Player opponent = player.getOpponent(); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Faerie", "Wizard"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantOpponentLoseLife = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and opponent loses 2 life?"); if (showYesNoDialog(k, question.toString())) { wantOpponentLoseLife = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantOpponentLoseLife = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantOpponentLoseLife) opponent.loseLife(2, k); }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Nightshade Schemers - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Nightshade_Schemers() /** * <p>upkeep_Pyroclast_Consul.</p> */ private static void upkeep_Pyroclast_Consul() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Pyroclast Consul"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Elemental", "Shaman"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantDamageCreatures = false; String[] smallCreatures = {"Creature.toughnessLE2"}; CardList humanCreatures = AllZoneUtil.getCreaturesInPlay(AllZone.getHumanPlayer()); humanCreatures = humanCreatures.getValidCards(smallCreatures, k.getController(), k); humanCreatures = humanCreatures.getNotKeyword("Indestructible"); CardList computerCreatures = AllZoneUtil.getCreaturesInPlay(AllZone.getComputerPlayer()); computerCreatures = computerCreatures.getValidCards(smallCreatures, k.getController(), k); computerCreatures = computerCreatures.getNotKeyword("Indestructible"); // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and Pyroclast Consul deals 2 damage to each creature?"); if (showYesNoDialog(k, question.toString())) { wantDamageCreatures = true; } } // player isComputer() else { if (humanCreatures.size() > computerCreatures.size()) { String title = "Computer reveals"; revealTopCard(title); wantDamageCreatures = true; } } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantDamageCreatures) { CardList allCreatures = AllZoneUtil.getCreaturesInPlay(); for (final Card crd : allCreatures) { crd.addDamage(2, k); } } }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Pyroclast Consul - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Pyroclast_Consul() /** * <p>upkeep_Sensation_Gorger.</p> */ private static void upkeep_Sensation_Gorger() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Sensation Gorger"); final Player opponent = player.getOpponent(); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Goblin", "Shaman"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantDiscardThenDraw = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and have both players discard their hand and draw 4 cards?"); if (showYesNoDialog(k, question.toString())) { wantDiscardThenDraw = true; } } // player isComputer() else { if (library.size() > 4 && hand.size() < 2) { String title = "Computer reveals"; revealTopCard(title); wantDiscardThenDraw = true; } } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantDiscardThenDraw) { player.discardHand(this); opponent.discardHand(this); player.drawCards(4); opponent.drawCards(4); } }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Sensation Gorger - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Sensation_Gorger() /** * <p>upkeep_Squeaking_Pie_Grubfellows.</p> */ private static void upkeep_Squeaking_Pie_Grubfellows() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Squeaking Pie Grubfellows"); final Player opponent = player.getOpponent(); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Goblin", "Shaman"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantOpponentDiscard = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and have opponent discard a card?"); if (showYesNoDialog(k, question.toString())) { wantOpponentDiscard = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantOpponentDiscard = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantOpponentDiscard) { opponent.discard(this); } }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Squeaking Pie Grubfellows - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Squeaking_Pie_Grubfellows() /** * <p>upkeep_Wandering_Graybeard.</p> */ private static void upkeep_Wandering_Graybeard() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Wandering Graybeard"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Giant", "Wizard"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantGainLife = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and gain 4 life?"); if (showYesNoDialog(k, question.toString())) { wantGainLife = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantGainLife = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantGainLife) player.gainLife(4, k); }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Wandering Graybeard - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Wandering_Graybeard() /** * <p>upkeep_Waterspout_Weavers.</p> */ private static void upkeep_Waterspout_Weavers() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Waterspout Weavers"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Merfolk", "Wizard"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantMerfolkBuff = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and each creature you "); question.append("control gains flying until end of turn?"); if (showYesNoDialog(k, question.toString())) { wantMerfolkBuff = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantMerfolkBuff = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantMerfolkBuff) { CardList creatures = AllZoneUtil.getCreaturesInPlay(player); for (int i = 0; i < creatures.size(); i++) { if (!creatures.get(i).hasKeyword("Flying")) { creatures.get(i).addExtrinsicKeyword("Flying"); } } final Command untilEOT = new Command() { private static final long serialVersionUID = -1978446996943583910L; public void execute() { CardList creatures = AllZoneUtil.getCreaturesInPlay(player); for (int i = 0; i < creatures.size(); i++) { if (creatures.get(i).hasKeyword("Flying")) { creatures.get(i).removeExtrinsicKeyword("Flying"); } } } }; AllZone.getEndOfTurn().addUntil(untilEOT); } }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Waterspout Weavers - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Waterspout_Weavers() /** * <p>upkeep_Winnower_Patrol.</p> */ private static void upkeep_Winnower_Patrol() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Winnower Patrol"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Elf", "Warrior"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantCounter = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and put a +1/+1 counter on Winnower Patrol?"); if (showYesNoDialog(k, question.toString())) { wantCounter = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantCounter = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantCounter) k.addCounter(Counters.P1P1, 1); }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Winnower Patrol - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Winnower_Patrol() /** * <p>upkeep_Wolf_Skull_Shaman.</p> */ private static void upkeep_Wolf_Skull_Shaman() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList kinship = AllZoneUtil.getPlayerCardsInPlay(player, "Wolf-Skull Shaman"); PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); // Players would not choose to trigger Kinship ability if library is empty. // Useful for games when the "Milling = Loss Condition" check box is unchecked. if (kinship.size() == 0 || library.size() <= 0) return; final String[] shareTypes = {"Elf", "Shaman"}; final Card[] prevCardShown = {null}; final Card peek[] = {null}; for (final Card k : kinship) { Ability ability = new Ability(k, "0") { // change to triggered abilities when ready @Override public void resolve() { PlayerZone library = AllZone.getZone(Constant.Zone.Library, player); if (library.size() <= 0) return; peek[0] = library.get(0); boolean wantToken = false; // We assume that both players will want to peek, ask if they want to reveal. // We do not want to slow down the pace of the game by asking too many questions. // Dialogs outside of the Ability appear at the previous end of turn phase !!! if (peek[0].isValidCard(shareTypes, k.getController(), k)) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Your top card is ").append(peek[0].getName()); question.append(". Reveal card and put a 2/2 green Wolf creature token onto the battlefield?"); if (showYesNoDialog(k, question.toString())) { wantToken = true; } } // player isComputer() else { String title = "Computer reveals"; revealTopCard(title); wantToken = true; } } else if (player.isHuman()) { String title = "Your top card is"; revealTopCard(title); } if (wantToken) CardFactoryUtil.makeToken("Wolf", "G 2 2 Wolf", k.getController(), "G", new String[]{"Creature", "Wolf"}, 2, 2, new String[]{""}); }// resolve() private void revealTopCard(String title) { if (peek[0] != prevCardShown[0]) { GuiUtils.getChoice(title, peek[0]); prevCardShown[0] = peek[0]; } }// revealTopCard() };// ability StringBuilder sb = new StringBuilder(); sb.append("Wolf-Skull Shaman - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Wolf_Skull_Shaman() /////////////////////// // End of Kinship cards /////////////////////// /** * <p>upkeep_Dark_Confidant.</p> */ private static void upkeep_Dark_Confidant() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getName().equals("Dark Confidant") || c.getName().equals("Dark Tutelage"); } }); Ability ability; for (int i = 0; i < list.size(); i++) { final Card F_card = list.get(i); ability = new Ability(F_card, "0") { @Override public void resolve() { CardList lib = AllZoneUtil.getPlayerCardsInLibrary(player); if (lib.size() > 0) { Card toMove = lib.get(0); AllZone.getGameAction().moveToHand(toMove); player.loseLife(toMove.getCMC(), F_card); } }// resolve() };// Ability StringBuilder sb = new StringBuilder(); sb.append(F_card).append(" - ").append("At the beginning of your upkeep, reveal the top card of your library and put that card into your hand. You lose life equal to its converted mana cost."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Dark_Confidant() /** * <p>upkeep_Suspend.</p> */ public static void upkeep_Suspend() { Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInExile(player); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return c.hasSuspend(); } }); if (list.size() == 0) return; for (final Card c : list) { int counters = c.getCounters(Counters.TIME); if (counters > 0) c.subtractCounter(Counters.TIME, 1); } }//suspend /** * <p>upkeep_Vanishing.</p> */ private static void upkeep_Vanishing() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return CardFactory.hasKeyword(c, "Vanishing") != -1; } }); if (list.size() > 0) { for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); Ability ability = new Ability(card, "0") { @Override public void resolve() { card.subtractCounter(Counters.TIME, 1); } }; // ability StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - Vanishing - remove a time counter from it. "); sb.append("When the last is removed, sacrifice it.)"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } } /** * <p>upkeep_Fading.</p> */ private static void upkeep_Fading() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return CardFactory.hasKeyword(c, "Fading") != -1; } }); if (list.size() > 0) { for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); Ability ability = new Ability(card, "0") { @Override public void resolve() { int fadeCounters = card.getCounters(Counters.FADE); if (fadeCounters <= 0) AllZone.getGameAction().sacrifice(card); else card.subtractCounter(Counters.FADE, 1); } }; // ability StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - Fading - remove a fade counter from it. "); sb.append("If you can't, sacrifice it.)"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } } /** * <p>upkeep_Oath_of_Druids.</p> */ private static void upkeep_Oath_of_Druids() { CardList oathList = AllZoneUtil.getCardsInPlay("Oath of Druids"); if (oathList.isEmpty()) return; final Player player = AllZone.getPhase().getPlayerTurn(); if (AllZoneUtil.compareTypeAmountInPlay(player, "Creature") < 0) { for (int i = 0; i < oathList.size(); i++) { final Card oath = oathList.get(i); Ability ability = new Ability(oath, "0") { @Override public void resolve() { CardList libraryList = AllZoneUtil.getPlayerCardsInLibrary(player); PlayerZone battlefield = AllZone.getZone(Constant.Zone.Battlefield, player); boolean oathFlag = true; if (AllZoneUtil.compareTypeAmountInPlay(player, "Creature") < 0) { if (player.isHuman()) { StringBuilder question = new StringBuilder(); question.append("Reveal cards from the top of your library and place "); question.append("the first creature revealed onto the battlefield?"); if (!GameActionUtil.showYesNoDialog(oath, question.toString())) { oathFlag = false; } } else { // if player == Computer CardList creaturesInLibrary = AllZoneUtil.getPlayerTypeInLibrary(player, "Creature"); CardList creaturesInBattlefield = AllZoneUtil.getPlayerTypeInPlay(player, "Creature"); // if there are at least 3 creatures in library, or none in play with one in library, oath if (creaturesInLibrary.size() > 2 || (creaturesInBattlefield.size() == 0 && creaturesInLibrary.size() > 0)) oathFlag = true; else oathFlag = false; } if (oathFlag) { CardList cardsToReveal = new CardList(); int max = libraryList.size(); for (int i = 0; i < max; i++) { Card c = libraryList.get(i); cardsToReveal.add(c); if (c.isCreature()) { AllZone.getGameAction().moveTo(battlefield, c); break; } else { AllZone.getGameAction().moveToGraveyard(c); } }// for loop if (cardsToReveal.size() > 0) GuiUtils.getChoice("Revealed cards", cardsToReveal.toArray()); } } } };// Ability StringBuilder sb = new StringBuilder(); sb.append("At the beginning of each player's upkeep, that player chooses target player "); sb.append("who controls more creatures than he or she does and is his or her opponent. The "); sb.append("first player may reveal cards from the top of his or her library until he or she "); sb.append("reveals a creature card. If he or she does, that player puts that card onto the "); sb.append("battlefield and all other cards revealed this way into his or her graveyard."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } }// upkeep_Oath of Druids() /** * <p>upkeep_Oath_of_Ghouls.</p> */ private static void upkeep_Oath_of_Ghouls() { CardList oathList = AllZoneUtil.getCardsInPlay("Oath of Ghouls"); if (oathList.isEmpty()) return; final Player player = AllZone.getPhase().getPlayerTurn(); if (AllZoneUtil.compareTypeAmountInGraveyard(player, "Creature") > 0) { for (int i = 0; i < oathList.size(); i++) { Ability ability = new Ability(oathList.get(0), "0") { @Override public void resolve() { CardList graveyardCreatures = AllZoneUtil.getPlayerTypeInGraveyard(player, "Creature"); if (AllZoneUtil.compareTypeAmountInGraveyard(player, "Creature") > 0) { if (player.isHuman()) { Object o = GuiUtils.getChoiceOptional("Pick a creature to return to hand", graveyardCreatures.toArray()); if (o != null) { Card card = (Card) o; AllZone.getGameAction().moveToHand(card); } } else if (player.isComputer()) { Card card = graveyardCreatures.get(0); AllZone.getGameAction().moveToHand(card); } } } };// Ability StringBuilder sb = new StringBuilder(); sb.append("At the beginning of each player's upkeep, Oath of Ghouls returns a creature "); sb.append("from their graveyard to owner's hand if they have more than an opponent."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } }//Oath of Ghouls /** * <p>upkeep_Karma.</p> */ private static void upkeep_Karma() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList karmas = AllZoneUtil.getCardsInPlay("Karma"); CardList swamps = AllZoneUtil.getPlayerTypeInPlay(player, "Swamp"); // determine how much damage to deal the current player final int damage = swamps.size(); // if there are 1 or more Karmas on the // battlefield have each of them deal damage. if (0 < karmas.size()) { for (Card karma : karmas) { final Card src = karma; Ability ability = new Ability(src, "0") { @Override public void resolve() { if (damage > 0) { player.addDamage(damage, src); } } };// Ability if (damage > 0) { StringBuilder sb = new StringBuilder(); sb.append("Karma deals ").append(damage).append(" damage to ").append(player); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } }// if }// upkeep_Karma() /** * <p>upkeep_Dega_Sanctuary.</p> */ private static void upkeep_Dega_Sanctuary() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Dega Sanctuary"); for (Card sanc : list) { final Card source = sanc; final Ability ability = new Ability(source, "0") { public void resolve() { int gain = 0; CardList play = AllZoneUtil.getPlayerCardsInPlay(player); CardList black = play.filter(AllZoneUtil.black); CardList red = play.filter(AllZoneUtil.red); if (black.size() > 0 && red.size() > 0) gain = 4; else if (black.size() > 0 || red.size() > 0) gain = 2; player.gainLife(gain, source); } };//Ability StringBuilder sb = new StringBuilder(); sb.append(source.getName()).append(" - "); sb.append("if you control a black or red permanent, you gain 2 life. If you control a black permanent and a red permanent, you gain 4 life instead."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }//for }//upkeep_Dega_Sanctuary() /** * <p>upkeep_Ceta_Sanctuary.</p> */ private static void upkeep_Ceta_Sanctuary() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Ceta Sanctuary"); for (Card sanc : list) { final Card source = sanc; final Ability ability = new Ability(source, "0") { public void resolve() { int draw = 0; CardList play = AllZoneUtil.getPlayerCardsInPlay(player); CardList green = play.filter(AllZoneUtil.green); CardList red = play.filter(AllZoneUtil.red); if (green.size() > 0 && red.size() > 0) draw = 2; else if (green.size() > 0 || red.size() > 0) draw = 1; if (draw > 0) { player.drawCards(draw); player.discard(1, this, true); } } };//Ability StringBuilder sb = new StringBuilder(); sb.append(source).append(" - "); sb.append("At the beginning of your upkeep, if you control a red or green permanent, draw a card, then discard a card. If you control a red permanent and a green permanent, instead draw two cards, then discard a card."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }//for }//upkeep_Ceta_Sanctuary() /** * <p>upkeep_Power_Surge.</p> */ private static void upkeep_Power_Surge() { /* * At the beginning of each player's upkeep, Power Surge deals X * damage to that player, where X is the number of untapped * lands he or she controlled at the beginning of this turn. */ final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getCardsInPlay("Power Surge"); final int damage = player.getNumPowerSurgeLands(); for (Card surge : list) { final Card source = surge; Ability ability = new Ability(source, "0") { @Override public void resolve() { player.addDamage(damage, source); } };// Ability StringBuilder sb = new StringBuilder(); sb.append(source).append(" - deals ").append(damage).append(" damage to ").append(player); ability.setStackDescription(sb.toString()); if (damage > 0) { AllZone.getStack().addSimultaneousStackEntry(ability); } }// for }// upkeep_Power_Surge() /** * <p>upkeep_Felidar_Sovereign.</p> */ private static void upkeep_Felidar_Sovereign() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Felidar Sovereign"); if (0 < list.size() && player.getLife() >= 40) { final Card source = list.get(0); Ability ability = new Ability(source, "0") { @Override public void resolve() { if (player.getLife() >= 40) player.altWinConditionMet(source.getName()); } };// Ability StringBuilder sb = new StringBuilder(); sb.append("Felidar Sovereign - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// if }// upkeep_Felidar_Sovereign /** * <p>upkeep_Mortal_Combat.</p> */ private static void upkeep_Mortal_Combat() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Mortal Combat"); CardList grave = AllZoneUtil.getPlayerGraveyard(player); grave = grave.filter(AllZoneUtil.creatures); if (0 < list.size() && 20 <= grave.size()) { final Card source = list.get(0); Ability ability = new Ability(source, "0") { @Override public void resolve() { CardList grave = AllZoneUtil.getPlayerGraveyard(player); grave = grave.filter(AllZoneUtil.creatures); if (grave.size() >= 20) player.altWinConditionMet(source.getName()); } };// Ability StringBuilder sb = new StringBuilder(); sb.append("Mortal Combat - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// if }// upkeep_Mortal Combat /** * <p>upkeep_Helix_Pinnacle.</p> */ private static void upkeep_Helix_Pinnacle() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Helix Pinnacle"); for (final Card c : list) { if (c.getCounters(Counters.TOWER) < 100) continue; Ability ability = new Ability(c, "0") { @Override public void resolve() { if (c.getCounters(Counters.TOWER) >= 100) player.altWinConditionMet(c.getName()); } };// Ability StringBuilder sb = new StringBuilder(); sb.append("Helix Pinnacle - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// if }// upkeep_Helix_Pinnacle /** * <p>upkeep_Near_Death_Experience.</p> */ private static void upkeep_Near_Death_Experience() { /* * At the beginning of your upkeep, if you have exactly 1 life, you win the game. */ final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Near-Death Experience"); if (0 < list.size() && player.getLife() == 1) { final Card source = list.get(0); Ability ability = new Ability(source, "0") { @Override public void resolve() { if (player.getLife() == 1) player.altWinConditionMet(source.getName()); } };// Ability StringBuilder sb = new StringBuilder(); sb.append("Near-Death Experience - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// if }// upkeep_Near_Death_Experience /** * <p>upkeep_Test_of_Endurance.</p> */ private static void upkeep_Test_of_Endurance() { /* * At the beginning of your upkeep, if you have 50 or more life, you win the game. */ final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Test of Endurance"); if (0 < list.size() && player.getLife() >= 50) { final Card source = list.get(0); Ability ability = new Ability(source, "0") { @Override public void resolve() { if (player.getLife() >= 50) player.altWinConditionMet(source.getName()); } };// Ability StringBuilder sb = new StringBuilder(); sb.append(list.get(0)).append(" - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// if }// upkeep_Test_of_Endurance /** * <p>upkeep_Barren_Glory.</p> */ private static void upkeep_Barren_Glory() { final Player player = AllZone.getPhase().getPlayerTurn(); PlayerZone handZone = AllZone.getZone(Constant.Zone.Hand, player); CardList list = AllZoneUtil.getPlayerCardsInPlay(player); CardList playList = AllZoneUtil.getPlayerCardsInPlay(player); playList = playList.filter(new CardListFilter() { public boolean addCard(Card c) { return !c.getName().equals("Mana Pool"); } }); list = list.getName("Barren Glory"); if (playList.size() == 1 && list.size() == 1 && handZone.size() == 0) { final Card source = list.get(0); Ability ability = new Ability(source, "0") { @Override public void resolve() { CardList handList = AllZoneUtil.getCardsInZone(Constant.Zone.Hand, player); CardList playList = AllZoneUtil.getCardsInZone(Constant.Zone.Battlefield, player); playList = playList.getValidCards("Permanents".split(","), source.getController(), source); playList.remove(source); if (playList.size() == 0 && handList.size() == 0) player.altWinConditionMet(source.getName()); } };// Ability StringBuilder sb = new StringBuilder(); sb.append("Barren Glory - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// if }// upkeep_Barren_Glory /** * <p>upkeep_Sleeper_Agent.</p> */ private static void upkeep_Sleeper_Agent() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Sleeper Agent"); Ability ability; for (int i = 0; i < list.size(); i++) { final Card F_card = list.get(i); ability = new Ability(list.get(i), "0") { @Override public void resolve() { player.addDamage(2, F_card); } }; ability.setStackDescription("Sleeper Agent deals 2 damage to its controller."); AllZone.getStack().addSimultaneousStackEntry(ability); } }//upkeep_Sleeper_Agent /** * <p>upkeep_Shapeshifter.</p> */ private static void upkeep_Shapeshifter() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Shapeshifter"); list = list.filter(AllZoneUtil.nonToken); for (final Card c : list) { SpellAbility ability = new Ability(c, "0") { @Override public void resolve() { int num = 0; if (player.isHuman()) { String[] choices = new String[7]; for (int j = 0; j < 7; j++) { choices[j] = "" + j; } String answer = (String) (GuiUtils.getChoiceOptional(c.getName() + " - Choose a number", choices)); num = Integer.parseInt(answer); } else { num = 3; } c.setBaseAttack(num); c.setBaseDefense(7 - num); } }; ability.setStackDescription(c.getName() + " - choose a new number"); AllZone.getStack().addSimultaneousStackEntry(ability); }//foreach(Card) }//upkeep_Shapeshifter /** * <p>upkeep_Vesuvan_Doppelganger_Keyword.</p> */ private static void upkeep_Vesuvan_Doppelganger_Keyword() { // TODO: what about enchantments? i dont know how great this solution is final Player player = AllZone.getPhase().getPlayerTurn(); final String keyword = "At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability."; CardList list = AllZoneUtil.getPlayerCardsInPlay(player); list = list.filter(AllZoneUtil.getKeywordFilter(keyword)); for (final Card c : list) { final SpellAbility ability = new Ability(c, "0") { @Override public void resolve() { final Card[] newTarget = new Card[1]; newTarget[0] = null; final Ability switchTargets = new Ability(c, "0") { public void resolve() { if (newTarget[0] != null) { /* * 1. need to select new card - DONE * 1a. need to create the newly copied card with pic and setinfo * 2. need to add the leaves play command * 3. need to transfer the keyword * 4. need to update the clone origin of new card and old card * 5. remove clone leaves play commands from old * 5a. remove old from play * 6. add new to play */ Card newCopy = AllZone.getCardFactory().getCard(newTarget[0].getName(), player); newCopy.setCurSetCode(newTarget[0].getCurSetCode()); newCopy.setImageFilename(newTarget[0].getImageFilename()); //need to add the leaves play command (2) newCopy.addLeavesPlayCommand(c.getCloneLeavesPlayCommand()); c.removeTrigger(c.getCloneLeavesPlayCommand(), ZCTrigger.LEAVEFIELD); newCopy.setCloneLeavesPlayCommand(c.getCloneLeavesPlayCommand()); newCopy.addExtrinsicKeyword(keyword); newCopy.addColor("U", newCopy, false, true); newCopy.setCloneOrigin(c.getCloneOrigin()); newCopy.getCloneOrigin().setCurrentlyCloningCard(newCopy); c.setCloneOrigin(null); //5 PlayerZone play = AllZone.getZone(c); play.remove(c); play.add(newCopy); } } }; AllZone.getInputControl().setInput(new Input() { private static final long serialVersionUID = 5662272658873063221L; @Override public void showMessage() { AllZone.getDisplay().showMessage(c.getName() + " - Select new target creature. (Click Cancel to remain as is.)"); ButtonUtil.enableOnlyCancel(); } @Override public void selectButtonCancel() { stop(); } @Override public void selectCard(Card selectedCard, PlayerZone z) { if (z.is(Constant.Zone.Battlefield) && selectedCard.isCreature() && CardFactoryUtil.canTarget(c, selectedCard)) { newTarget[0] = selectedCard; StringBuilder sb = new StringBuilder(); sb.append(c.getCloneOrigin()).append(" - switching to copy " + selectedCard.getName() + "."); switchTargets.setStackDescription(sb.toString()); AllZone.getStack().add(switchTargets); stop(); } } }); } }; ability.setDescription("At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability."); ability.setStackDescription(c.getName() + " - you may have this creature become a copy of target creature."); AllZone.getStack().addSimultaneousStackEntry(ability); }//foreach(Card) }//upkeep_Vesuvan_Doppelganger_Keyword /** * <p>upkeep_Tangle_Wire.</p> */ private static void upkeep_Tangle_Wire() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList wires = AllZoneUtil.getCardsInPlay("Tangle Wire"); for (final Card source : wires) { SpellAbility ability = new Ability(source, "0") { @Override public void resolve() { final int num = source.getCounters(Counters.FADE); final CardList list = AllZoneUtil.getPlayerCardsInPlay(player).filter(new CardListFilter() { public boolean addCard(Card c) { return (c.isArtifact() || c.isLand() || c.isCreature()) && c.isUntapped(); } }); for (int i = 0; i < num; i++) { if (player.isComputer()) { Card toTap = CardFactoryUtil.AI_getWorstPermanent(list, false, false, false, false); if (null != toTap) { toTap.tap(); list.remove(toTap); } } else { AllZone.getInputControl().setInput(new Input() { private static final long serialVersionUID = 5313424586016061612L; public void showMessage() { if (list.size() == 0) { stop(); return; } AllZone.getDisplay().showMessage(source.getName() + " - Select " + num + " untapped artifact(s), creature(s), or land(s) you control"); ButtonUtil.disableAll(); } public void selectCard(Card card, PlayerZone zone) { if (zone.is(Constant.Zone.Battlefield, AllZone.getHumanPlayer()) && list.contains(card)) { card.tap(); list.remove(card); stop(); } } }); } } } }; ability.setStackDescription(source.getName() + " - " + player + " taps X artifacts, creatures or lands he or she controls."); AllZone.getStack().addSimultaneousStackEntry(ability); }//foreach(wire) }//upkeep_Tangle_Wire() /** * <p>upkeep_Masticore.</p> */ private static void upkeep_Masticore() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Masticore"); list.addAll(AllZoneUtil.getPlayerCardsInPlay(player, "Molten-Tail Masticore")); list.addAll(AllZoneUtil.getPlayerCardsInPlay(player, "Razormane Masticore")); Ability ability; for (int i = 0; i < list.size(); i++) { final Card crd = list.get(i); final Input discard = new Input() { private static final long serialVersionUID = 2252076866782738069L; @Override public void showMessage() { AllZone.getDisplay().showMessage(crd + " - Discard a card from your hand"); ButtonUtil.enableOnlyCancel(); } @Override public void selectCard(Card c, PlayerZone zone) { if (zone.is(Constant.Zone.Hand)) { c.getController().discard(c, null); stop(); } } @Override public void selectButtonCancel() { AllZone.getGameAction().sacrifice(crd); stop(); } };//Input ability = new Ability(crd, "0") { @Override public void resolve() { if (crd.getController().isHuman()) { if (AllZone.getHumanHand().size() == 0) AllZone.getGameAction().sacrifice(crd); else AllZone.getInputControl().setInput(discard); } else //comp { CardList list = AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer()); if (list.size() != 0) list.get(0).getController().discard(list.get(0), this); else AllZone.getGameAction().sacrifice(crd); }//else }//resolve() };//Ability StringBuilder sb = new StringBuilder(); sb.append(crd).append(" - sacrifice ").append(crd).append(" unless you discard a card."); ability.setStackDescription(sb.toString()); ability.setDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }//upkeep_Masticore /** * <p>upkeep_Eldrazi_Monument.</p> */ private static void upkeep_Eldrazi_Monument() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Eldrazi Monument"); Ability ability; for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); ability = new Ability(list.get(i), "0") { @Override public void resolve() { CardList creats = AllZoneUtil.getCreaturesInPlay(player); if (creats.size() < 1) { AllZone.getGameAction().sacrifice(card); return; } if (player.isHuman()) { Object o = GuiUtils.getChoiceOptional("Select creature to sacrifice", creats.toArray()); Card sac = (Card) o; if (sac == null) { creats.shuffle(); sac = creats.get(0); } AllZone.getGameAction().sacrifice(sac); } else//computer { CardListUtil.sortAttackLowFirst(creats); AllZone.getGameAction().sacrifice(creats.get(0)); } } };// ability StringBuilder sb = new StringBuilder(); sb.append("Eldrazi Monument - ").append(player).append(" sacrifices a creature."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } }//upkeep_Eldrazi_Monument /** * <p>upkeep_Blaze_Counters.</p> */ private static void upkeep_Blaze_Counters() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList blaze = AllZoneUtil.getPlayerCardsInPlay(player); blaze = blaze.filter(new CardListFilter() { public boolean addCard(Card c) { return c.isLand() && c.getCounters(Counters.BLAZE) > 0; } }); for (int i = 0; i < blaze.size(); i++) { final Card Source = blaze.get(i); Ability ability = new Ability(blaze.get(i), "0") { @Override public void resolve() { player.addDamage(1, Source); } };// ability StringBuilder sb = new StringBuilder(); sb.append(blaze.get(i)).append(" - has a blaze counter and deals 1 damage to "); sb.append(player).append("."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); } } /** * <p>upkeep_Dragon_Broodmother.</p> */ /* private static void upkeep_Dragon_Broodmother() { CardList list = AllZoneUtil.getCardsInPlay("Dragon Broodmother"); Ability ability; for (int i = 0; i < list.size(); i++) { final Card card = list.get(i); ability = new Ability(card, "0") { @Override public void resolve() { int multiplier = AllZoneUtil.getDoublingSeasonMagnitude(card.getController()); for (int i = 0; i < multiplier; i++) makeToken(); }// resolve() public void makeToken() { //CardList cl = CardFactoryUtil.makeToken("Dragon", "RG 1 1 Dragon", card, "RG", new String[] {"Creature", "Dragon"}, 1, 1, new String[] {"Flying"} ); final Card c = new Card(); c.setOwner(card.getController()); c.setController(card.getController()); c.setName("Dragon"); c.setImageName("RG 1 1 Dragon"); //c.setManaCost("RG"); c.addColor("RG"); c.setToken(true); c.addType("Creature"); c.addType("Dragon"); c.addIntrinsicKeyword("Flying"); c.setBaseAttack(1); c.setBaseDefense(1); //final String player = card.getController(); final int[] numCreatures = new int[1]; final SpellAbility devour = new Spell(card) { private static final long serialVersionUID = 4158780345303896275L; @Override public void resolve() { int totalCounters = numCreatures[0] * 2; c.addCounter(Counters.P1P1, totalCounters); } @Override public boolean canPlay() { return AllZone.getPhase().getPlayerTurn().equals(card.getController()) && card.isFaceDown() && !AllZone.getPhase().getPhase().equals("End of Turn") && AllZoneUtil.isCardInPlay(card); } };//devour Command intoPlay = new Command() { private static final long serialVersionUID = -9220268793346809216L; public void execute() { CardList creatsToSac = new CardList(); CardList creats = AllZoneUtil.getPlayerCardsInPlay(card.getController()); creats = creats.filter(new CardListFilter() { public boolean addCard(Card crd) { return crd.isCreature() && !crd.equals(c); } }); //System.out.println("Creats size: " + creats.size()); if (card.getController().isHuman()) { Object o = null; int creatsSize = creats.size(); for (int k = 0; k < creatsSize; k++) { o = GuiUtils.getChoiceOptional("Select creature to sacrifice", creats.toArray()); if (o == null) break; Card crd = (Card) o; creatsToSac.add(crd); creats.remove(crd); } numCreatures[0] = creatsToSac.size(); for (int m = 0; m < creatsToSac.size(); m++) { AllZone.getGameAction().sacrifice(creatsToSac.get(m)); } }//human else { int count = 0; for (int i = 0; i < creats.size(); i++) { Card crd = creats.get(i); if (crd.getNetAttack() <= 1 && crd.getNetDefense() <= 2) { AllZone.getGameAction().sacrifice(crd); count++; } } numCreatures[0] = count; } AllZone.getStack().addSimultaneousStackEntry(devour); } }; StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - gets 2 +1/+1 counter(s) per devoured creature."); devour.setStackDescription(sb.toString()); devour.setDescription("Devour 2"); c.addSpellAbility(devour); c.addComesIntoPlayCommand(intoPlay); AllZone.getGameAction().moveToPlay(c); } };// Ability ability.setStackDescription("Dragon Broodmother - put a 1/1 red and green Dragon token onto the battlefield."); AllZone.getStack().addSimultaneousStackEntry(ability); }// for }// upkeep_Dragon_Broodmother() */ /** * <p>draw_Sylvan_Library.</p> * * @param player a {@link forge.Player} object. */ private static void draw_Sylvan_Library(final Player player) { /* * At the beginning of your draw step, you may draw two additional * cards. If you do, choose two cards in your hand drawn this turn. * For each of those cards, pay 4 life or put the card on top of * your library. */ final CardList cards = AllZoneUtil.getPlayerCardsInPlay(player, "Sylvan Library"); for (final Card source : cards) { final Ability ability = new Ability(source, "") { @Override public void resolve() { final Player player = source.getController(); if (player.isHuman()) { String question = "Draw 2 additional cards?"; final String cardQuestion = "Pay 4 life and keep in hand?"; if (GameActionUtil.showYesNoDialog(source, question)) { player.drawCards(2); for (int i = 0; i < 2; i++) { final String prompt = source + " - Select a card drawn this turn: " + (2 - i) + " of 2"; AllZone.getInputControl().setInput(new Input() { private static final long serialVersionUID = -3389565833121544797L; @Override public void showMessage() { if (AllZone.getHumanHand().size() == 0) stop(); AllZone.getDisplay().showMessage(prompt); ButtonUtil.disableAll(); } @Override public void selectCard(Card card, PlayerZone zone) { if (zone.is(Constant.Zone.Hand) && true == card.getDrawnThisTurn()) { if (player.canPayLife(4) && GameActionUtil.showYesNoDialog(source, cardQuestion)) { player.payLife(4, source); //card stays in hand } else { AllZone.getGameAction().moveToLibrary(card); } stop(); } } });//end Input } } } else { //Computer, but he's too stupid to play this } }//resolve };// Ability StringBuilder sb = new StringBuilder(); sb.append("At the beginning of your draw step, you may draw two additional cards. If you do, choose two cards in your hand drawn this turn. For each of those cards, pay 4 life or put the card on top of your library."); ability.setStackDescription(sb.toString()); AllZone.getStack().addSimultaneousStackEntry(ability); }//end for } /** * <p>upkeep_Carnophage.</p> */ private static void upkeep_Carnophage() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Carnophage"); if (player.isHuman()) { for (int i = 0; i < list.size(); i++) { Card c = list.get(i); String[] choices = {"Yes", "No"}; Object choice = GuiUtils.getChoice("Pay Carnophage's upkeep?", choices); if (choice.equals("Yes")) player.loseLife(1, c); else c.tap(); } } else if (player.isComputer()) for (int i = 0; i < list.size(); i++) { Card c = list.get(i); if (AllZone.getComputerPlayer().getLife() > 1) player.loseLife(1, c); else c.tap(); } }// upkeep_Carnophage /** * <p>upkeep_Sangrophage.</p> */ private static void upkeep_Sangrophage() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList list = AllZoneUtil.getPlayerCardsInPlay(player, "Sangrophage"); if (player.isHuman()) { for (int i = 0; i < list.size(); i++) { Card c = list.get(i); String[] choices = {"Yes", "No"}; Object choice = GuiUtils.getChoice("Pay Sangrophage's upkeep?", choices); if (choice.equals("Yes")) player.loseLife(2, c); else c.tap(); } } else if (player.isComputer()) for (int i = 0; i < list.size(); i++) { Card c = list.get(i); if (AllZone.getComputerPlayer().getLife() > 2) player.loseLife(2, c); else c.tap(); } }// upkeep_Carnophage /** * <p>upkeep_Fallen_Empires_Storage_Lands.</p> */ private static void upkeep_Fallen_Empires_Storage_Lands() { final Player player = AllZone.getPhase().getPlayerTurn(); CardList all = AllZoneUtil.getPlayerCardsInPlay(player, "Bottomless Vault"); all.addAll(AllZoneUtil.getPlayerCardsInPlay(player, "Dwarven Hold")); all.addAll(AllZoneUtil.getPlayerCardsInPlay(player, "Hollow Trees")); all.addAll(AllZoneUtil.getPlayerCardsInPlay(player, "Icatian Store")); all.addAll(AllZoneUtil.getPlayerCardsInPlay(player, "Sand Silos")); for (Card land : all) { if (land.isTapped()) land.addCounter(Counters.STORAGE, 1); } } //upkeep_Fallen_Empires_Storage_Lands /** Constant <code>Conspiracy</code> */ public static Command Conspiracy = new Command() { private static final long serialVersionUID = -752798545956593342L; CardList gloriousAnthemList = new CardList(); public void execute() { //String keyword = "Defender"; CardList list = gloriousAnthemList; Card c; // reset all cards in list - aka "old" cards for (int i = 0; i < list.size(); i++) { c = list.get(i); //System.out.println("prev type: " +c.getPrevType()); c.setType(c.getPrevType()); } list.clear(); PlayerZone[] zone = new PlayerZone[4]; CardList cl = AllZoneUtil.getCardsInPlay("Conspiracy"); for (int i = 0; i < cl.size(); i++) { Card card = cl.get(i); Player player = card.getController(); zone[0] = AllZone.getZone(Constant.Zone.Hand, player); zone[1] = AllZone.getZone(Constant.Zone.Library, player); zone[2] = AllZone.getZone( Constant.Zone.Graveyard, player); zone[3] = AllZone.getZone(Constant.Zone.Battlefield, player); for (int outer = 0; outer < zone.length; outer++) { CardList creature = AllZoneUtil.getCardsInZone(zone[outer]); creature = creature.getType("Creature"); for (int j = 0; j < creature.size(); j++) { boolean art = false; boolean ench = false; c = creature.get(j); if (c.isArtifact()) art = true; if (c.isEnchantment()) ench = true; if (c.getPrevType().size() == 0) c.setPrevType(c.getType()); c.setType(new ArrayList<String>()); c.addType("Creature"); if (art) c.addType("Artifact"); if (ench) c.addType("Enchantment"); c.addType(card.getChosenType()); gloriousAnthemList.add(c); } } }// for inner }// execute() }; //Conspiracy /** Constant <code>Elspeth_Emblem</code> */ public static Command Elspeth_Emblem = new Command() { private static final long serialVersionUID = 7414127991531889390L; CardList gloriousAnthemList = new CardList(); public void execute() { String keyword = "Indestructible"; CardList list = gloriousAnthemList; Card c; // reset all cards in list - aka "old" cards for (int i = 0; i < list.size(); i++) { c = list.get(i); c.removeExtrinsicKeyword(keyword); } list.clear(); CardList emblem = AllZoneUtil.getCardsInPlay(); emblem = emblem.filter(new CardListFilter() { public boolean addCard(Card c) { return c.isEmblem() && c.hasKeyword("Artifacts, creatures, enchantments, and lands you control are indestructible."); } }); for (int i = 0; i < emblem.size(); i++) { CardList perms = AllZoneUtil.getPlayerCardsInPlay(emblem.get(i).getController()); for (int j = 0; j < perms.size(); j++) { c = perms.get(j); if (!c.hasKeyword(keyword)) { c.addExtrinsicKeyword(keyword); gloriousAnthemList.add(c); } } } }// execute() }; /** Constant <code>Favor_of_the_Mighty</code> */ public static Command Favor_of_the_Mighty = new Command() { private static final long serialVersionUID = 2920036758177137722L; private CardList pumped = new CardList(); public void execute() { //Reset old cards for (Card c : pumped) { c.removeIntrinsicKeyword("Protection from white"); c.removeIntrinsicKeyword("Protection from blue"); c.removeIntrinsicKeyword("Protection from black"); c.removeIntrinsicKeyword("Protection from red"); c.removeIntrinsicKeyword("Protection from green"); } pumped.clear(); //Find creature(s) with highest cmc int maxCMC = -1; //boolean keepLooping = true; CardList creats = AllZoneUtil.getCreaturesInPlay(); for (Card c : creats) { if (c.getCMC() > maxCMC) { pumped.clear(); pumped.add(c); maxCMC = c.getCMC(); } else if (c.getCMC() == maxCMC) { pumped.add(c); } } //Pump new cards for (Card c : pumped) { c.addIntrinsicKeyword("Protection from white"); c.addIntrinsicKeyword("Protection from blue"); c.addIntrinsicKeyword("Protection from black"); c.addIntrinsicKeyword("Protection from red"); c.addIntrinsicKeyword("Protection from green"); } } }; /** Constant <code>Koth_Emblem</code> */ public static Command Koth_Emblem = new Command() { private static final long serialVersionUID = -3233715310427996429L; CardList gloriousAnthemList = new CardList(); public void execute() { CardList list = gloriousAnthemList; Card crd; // reset all cards in list - aka "old" cards for (int i = 0; i < list.size(); i++) { crd = list.get(i); SpellAbility[] sas = crd.getSpellAbility(); for (int j = 0; j < sas.length; j++) { if (sas[j].isKothThirdAbility()) crd.removeSpellAbility(sas[j]); } } CardList emblem = AllZoneUtil.getCardsInPlay(); emblem = emblem.filter(new CardListFilter() { public boolean addCard(Card c) { return c.isEmblem() && c.hasKeyword("Mountains you control have 'tap: This land deals 1 damage to target creature or player.'"); } }); for (int i = 0; i < emblem.size(); i++) { CardList mountains = AllZoneUtil.getPlayerCardsInPlay(emblem.get(i).getController()); mountains = mountains.filter(new CardListFilter() { public boolean addCard(Card crd) { return crd.isType("Mountain"); } }); for (int j = 0; j < mountains.size(); j++) { final Card c = mountains.get(j); boolean hasAbility = false; SpellAbility[] sas = c.getSpellAbility(); for (SpellAbility sa : sas) { if (sa.isKothThirdAbility()) hasAbility = true; } if (!hasAbility) { Cost abCost = new Cost("T", c.getName(), true); Target target = new Target(c, "TgtCP"); final Ability_Activated ability = new Ability_Activated(c, abCost, target) { private static final long serialVersionUID = -7560349014757367722L; public void chooseTargetAI() { CardList list = CardFactoryUtil.AI_getHumanCreature(1, c, true); list.shuffle(); if (list.isEmpty() || AllZone.getHumanPlayer().getLife() < 5) setTargetPlayer(AllZone.getHumanPlayer()); else setTargetCard(list.get(0)); } public void resolve() { if (getTargetCard() != null) { if (AllZoneUtil.isCardInPlay(getTargetCard()) && CardFactoryUtil.canTarget(c, getTargetCard())) getTargetCard().addDamage(1, c); } else { getTargetPlayer().addDamage(1, c); } }//resolve() };//SpellAbility ability.setKothThirdAbility(true); ability.setDescription(abCost + "This land deals 1 damage to target creature or player."); c.addSpellAbility(ability); gloriousAnthemList.add(c); } } } } }; /** Constant <code>stPump</code> */ public static Command stPump = new Command() { /** StaticEffectKeyword * Syntax:[ k[0] stPump[All][Self][Other] : k[1] Which Cards the Bonus Affects : * k[2] What Bonus does the Card have : k[3] Special Conditions : k[4] Description */ private static final long serialVersionUID = -7853346190458174501L; private ArrayList<StaticEffect> storage = new ArrayList<StaticEffect>(); // storage stores the source card and the cards it gave its bonus to, to know what to remove public void execute() { // remove all static effects for (int i = 0; i < storage.size(); i++) { removeStaticEffect(storage.get(i)); } //clear the list storage = new ArrayList<StaticEffect>(); //Gather Cards on the Battlefield with the stPump Keyword CardList cards_WithKeyword = AllZoneUtil.getCardsInPlay(); cards_WithKeyword = cards_WithKeyword.getKeywordsContain("stPump"); // check each card for (int i = 0; i < cards_WithKeyword.size(); i++) { Card cardWithKeyword = cards_WithKeyword.get(i); ArrayList<String> keywords = cardWithKeyword.getKeyword(); // check each keyword of the card for (int j = 0; j < keywords.size(); j++) { String keyword = keywords.get(j); if (keyword.startsWith("stPump")) { StaticEffect se = new StaticEffect(); //create a new StaticEffect se.setSource(cardWithKeyword); se.setKeywordNumber(j); //get the affected cards String k[] = keyword.split(":", 5); if (specialConditionsMet(cardWithKeyword, k[3])) { //special Conditions are Threshold, etc. final String affected = k[1]; final String specific[] = affected.split(","); CardList affectedCards = AffectedCards(cardWithKeyword, k); // options are All, Self, Enchanted etc. affectedCards = affectedCards.getValidCards(specific, cardWithKeyword.getController(), cardWithKeyword); se.setAffectedCards(affectedCards); String[] pt = k[2].split("/"); Card cardWithXValue; String xString = cardWithKeyword.getSVar("X").split("$")[0]; Card cardWithYValue; String yString = cardWithKeyword.getSVar("Y").split("$")[0]; if (xString.startsWith("Imprinted") && !cardWithKeyword.getImprinted().isEmpty()) { cardWithXValue = cardWithKeyword.getImprinted().get(0); } else cardWithXValue = cardWithKeyword; if (yString.startsWith("Imprinted") && !cardWithKeyword.getImprinted().isEmpty()) { cardWithYValue = cardWithKeyword.getImprinted().get(0); } else cardWithYValue = cardWithKeyword; int x = 0; if (pt[0].contains("X") || pt[1].contains("X")) x = CardFactoryUtil.xCount(cardWithXValue, cardWithKeyword.getSVar("X").split("\\$")[1]); se.setXValue(x); int y = 0; if (pt[1].contains("Y")) y = CardFactoryUtil.xCount(cardWithYValue, cardWithKeyword.getSVar("Y").split("\\$")[1]); se.setYValue(y); addStaticEffects(cardWithKeyword, affectedCards, k[2], x, y); //give the boni to the affected cards storage.add(se); // store the information } } } } }// execute() void addStaticEffects(Card source, CardList affectedCards, String Keyword_Details, int xValue, int yValue) { int powerbonus = 0; int toughnessbonus = 0; String[] Keyword = Keyword_Details.split("/", 3); Keyword[0] = Keyword[0].replace("+", ""); Keyword[1] = Keyword[1].replace("+", ""); if (!Keyword[0].contains("X")) powerbonus = Integer.valueOf(Keyword[0]); else powerbonus = xValue; // the xCount takes places before if (Keyword[1].contains("X")) toughnessbonus = xValue; else if (Keyword[1].contains("Y")) toughnessbonus = yValue; else toughnessbonus = Integer.valueOf(Keyword[1]); for (int i = 0; i < affectedCards.size(); i++) { Card affectedCard = affectedCards.get(i); affectedCard.addSemiPermanentAttackBoost(powerbonus); affectedCard.addSemiPermanentDefenseBoost(toughnessbonus); if (Keyword.length > 2) { String Keywords[] = Keyword[2].split(" & "); for (int j = 0; j < Keywords.length; j++) { String keyword = Keywords[j]; if (keyword.startsWith("SVar=")) { String sVar = source.getSVar(keyword.split("SVar=")[1]); if (sVar.startsWith("AB")) { // grant the ability AbilityFactory AF = new AbilityFactory(); SpellAbility sa = AF.getAbility(sVar, affectedCard); sa.setType("Temporary"); affectedCard.addSpellAbility(sa); } else if (sVar.startsWith("Mode")){ // grant a Trigger StringBuilder triggerName = new StringBuilder("From "); triggerName.append(source.getName()).append(" (").append(source.getUniqueNumber()).append("): ").append(keyword.split("SVar=")[1]); Trigger actualTrigger = forge.card.trigger.TriggerHandler.parseTrigger(triggerName.toString(),sVar,affectedCard); affectedCard.addTrigger(actualTrigger); AllZone.getTriggerHandler().registerTrigger(actualTrigger); } else { // Copy this SVar affectedCard.setSVar(keyword.split("SVar=")[1], sVar); } } else if (keyword.startsWith("Types=")) { String[] tmptypes = keyword.split("="); String[] types = tmptypes[1].split(","); if (types[0].equals("ChosenType")) { types[0] = source.getChosenType(); } for (String type : types) affectedCard.addType(type); } else if (keyword.startsWith("Keyword=")) { String sVar = source.getSVar(keyword.split("Keyword=")[1]); affectedCard.addExtrinsicKeyword(sVar); } else if (keyword.startsWith("ForceSVar=")) { String sVar = source.getSVar(keyword.split("SVar=")[1]); affectedCard.setSVar(keyword.split("SVar=")[1],sVar); } else affectedCard.addExtrinsicKeyword(keyword); } } } } void removeStaticEffect(StaticEffect se) { Card source = se.getSource(); CardList affected = se.getAffectedCards(); int KeywordNumber = se.getKeywordNumber(); int xValue = se.getXValue(); // the old xValue has to be removed, not the actual one! int yValue = se.getYValue(); // the old xValue has to be removed, not the actual one! String parse = source.getKeyword().get(KeywordNumber).toString(); String k[] = parse.split(":"); for (int i = 0; i < affected.size(); i++) { removeStaticEffect(source, affected.get(i), k, xValue, yValue); } } void removeStaticEffect(Card source, Card affectedCard, String[] Keyword_Details, int xValue, int yValue) { int powerbonus = 0; int toughnessbonus = 0; String[] Keyword = Keyword_Details[2].split("/", 3); Keyword[0] = Keyword[0].replace("+", ""); Keyword[1] = Keyword[1].replace("+", ""); if (!Keyword[0].contains("X")) powerbonus = Integer.valueOf(Keyword[0]); else powerbonus = xValue; if (Keyword[1].contains("X")) toughnessbonus = xValue; else if (Keyword[1].contains("Y")) toughnessbonus = yValue; else toughnessbonus = Integer.valueOf(Keyword[1]); affectedCard.addSemiPermanentAttackBoost(powerbonus * -1); affectedCard.addSemiPermanentDefenseBoost(toughnessbonus * -1); if (Keyword.length > 2) { String Keywords[] = Keyword[2].split(" & "); for (int j = 0; j < Keywords.length; j++) { String keyword = Keywords[j]; if (keyword.startsWith("SVar=")) { String sVar = source.getSVar(keyword.split("SVar=")[1]); if (sVar.startsWith("AB")) { // remove granted abilities SpellAbility[] spellAbility = affectedCard.getSpellAbility(); for (SpellAbility s : spellAbility) { if (s.getType().equals("Temporary")) affectedCard.removeSpellAbility(s); } } else if (sVar.startsWith("Mode")) { // remove granted triggers StringBuilder triggerName = new StringBuilder("From "); triggerName.append(source.getName()).append(" (").append(source.getUniqueNumber()).append("): ").append(keyword.split("SVar=")[1]); Trigger actualTrigger = affectedCard.getNamedTrigger(triggerName.toString()); affectedCard.removeTrigger(actualTrigger); AllZone.getTriggerHandler().removeRegisteredTrigger(actualTrigger); } } else if (keyword.startsWith("Types=")) { String[] tmptypes = keyword.split("="); String[] types = tmptypes[1].split(","); if (types[0].equals("ChosenType")) { types[0] = source.getChosenType(); } for (String type : types) affectedCard.removeType(type); } else if (keyword.startsWith("Keyword=")) { String sVar = source.getSVar(keyword.split("Keyword=")[1]); affectedCard.removeExtrinsicKeyword(sVar); } affectedCard.removeExtrinsicKeyword(keyword); } } } CardList AffectedCards(Card SourceCard, String[] Keyword_Details) { // [Self], [All], [Other] CardList Cards_inZone = new CardList(); String Range = Keyword_Details[0]; if (Range.contains("Self")) { Cards_inZone.add(SourceCard); } if (Range.contains("All")) { Cards_inZone.addAll(AllZoneUtil.getCardsInPlay()); //this is a hack for Quick Sliver if (Keyword_Details.length >= 2 && (Keyword_Details[2].contains("Flash") || Keyword_Details[2].contains("CARDNAME can't be countered."))) { Cards_inZone.addAll(AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer())); Cards_inZone.addAll(AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer())); Cards_inZone.addAll(AllZoneUtil.getCardsInGraveyard()); } //hack for Molten Disaster /* // TODO for future use if(Keyword_Details.length >= 2 && Keyword_Details[2].contains("Split second")) { Cards_inZone.add(AllZone.getStack().getSpellCardsOnStack()); } */ } if (Range.contains("Enchanted")) { if (SourceCard.getEnchanting().size() > 0) Cards_inZone.addAll(SourceCard.getEnchanting().toArray()); } if (Range.contains("Equipped")) { if (SourceCard.getEquipping().size() > 0) Cards_inZone.addAll(SourceCard.getEquipping().toArray()); } return Cards_inZone; } }; // Special Conditions /** * <p>specialConditionsMet.</p> * * @param SourceCard a {@link forge.Card} object. * @param SpecialConditions a {@link java.lang.String} object. * @return a boolean. */ public static boolean specialConditionsMet(Card SourceCard, String SpecialConditions) { if (SpecialConditions.contains("CardsInHandMore")) { CardList SpecialConditionsCardList = AllZoneUtil.getPlayerHand(SourceCard.getController()); String Condition = SpecialConditions.split("/")[1]; if (SpecialConditionsCardList.size() < Integer.valueOf(Condition)) return false; } if (SpecialConditions.contains("OppHandEmpty")) { CardList oppHand = AllZoneUtil.getPlayerHand(SourceCard.getController().getOpponent()); if (!(oppHand.size() == 0)) return false; } if (SpecialConditions.contains("TopCardOfLibraryIsBlack")) { PlayerZone lib = AllZone.getZone(Constant.Zone.Library, SourceCard.getController()); if (!(lib.get(0).isBlack())) return false; } if (SpecialConditions.contains("LibraryLE")) { CardList Library = AllZoneUtil.getPlayerCardsInLibrary(SourceCard.getController()); String maxnumber = SpecialConditions.split("/")[1]; if (Library.size() > Integer.valueOf(maxnumber)) return false; } if (SpecialConditions.contains("LifeGE")) { int life = SourceCard.getController().getLife(); String maxnumber = SpecialConditions.split("/")[1]; if (!(life >= Integer.valueOf(maxnumber))) return false; } if (SpecialConditions.contains("OppCreatureInPlayGE")) { CardList OppInPlay = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getController().getOpponent()); OppInPlay = OppInPlay.getType("Creature"); String maxnumber = SpecialConditions.split("/")[1]; if (!(OppInPlay.size() >= Integer.valueOf(maxnumber))) return false; } if (SpecialConditions.contains("LandYouCtrlLE")) { CardList LandInPlay = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getController()); LandInPlay = LandInPlay.getType("Land"); String maxnumber = SpecialConditions.split("/")[1]; if (!(LandInPlay.size() <= Integer.valueOf(maxnumber))) return false; } if (SpecialConditions.contains("LandOppCtrlLE")) { CardList OppLandInPlay = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getController().getOpponent()); OppLandInPlay = OppLandInPlay.getType("Land"); String maxnumber = SpecialConditions.split("/")[1]; if (!(OppLandInPlay.size() <= Integer.valueOf(maxnumber))) return false; } if (SpecialConditions.contains("OppCtrlMoreCreatures")) { CardList CreaturesInPlayYou = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getController()); CreaturesInPlayYou = CreaturesInPlayYou.getType("Creature"); CardList CreaturesInPlayOpp = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getController().getOpponent()); CreaturesInPlayOpp = CreaturesInPlayOpp.getType("Creature"); if (CreaturesInPlayYou.size() > CreaturesInPlayOpp.size()) return false; } if (SpecialConditions.contains("OppCtrlMoreLands")) { CardList LandsInPlayYou = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getController()); LandsInPlayYou = LandsInPlayYou.getType("Land"); CardList LandsInPlayOpp = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getController().getOpponent()); LandsInPlayOpp = LandsInPlayOpp.getType("Land"); if (LandsInPlayYou.size() > LandsInPlayOpp.size()) return false; } if (SpecialConditions.contains("EnchantedControllerCreaturesGE")) { CardList EnchantedControllerInPlay = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getEnchantingCard().getController()); EnchantedControllerInPlay = EnchantedControllerInPlay.getType("Creature"); String maxnumber = SpecialConditions.split("/")[1]; if (!(EnchantedControllerInPlay.size() >= Integer.valueOf(maxnumber))) return false; } if (SpecialConditions.contains("OppLifeLE")) { int life = SourceCard.getController().getOpponent().getLife(); String maxnumber = SpecialConditions.split("/")[1]; if (!(life <= Integer.valueOf(maxnumber))) return false; } if (SpecialConditions.contains("Threshold")) { if (!SourceCard.getController().hasThreshold()) return false; } if (SpecialConditions.contains("Imprint")) { if (SourceCard.getImprinted().isEmpty()) return false; } if (SpecialConditions.contains("Hellbent")) { CardList Handcards = AllZoneUtil.getPlayerHand(SourceCard.getController()); if (Handcards.size() > 0) return false; } if (SpecialConditions.contains("Metalcraft")) { CardList CardsinPlay = AllZoneUtil.getPlayerCardsInPlay(SourceCard.getController()); CardsinPlay = CardsinPlay.getType("Artifact"); if (CardsinPlay.size() < 3) return false; } if (SpecialConditions.contains("isPresent")) { // is a card of a certain type/color present? String Requirements = SpecialConditions.replaceAll("isPresent ", ""); CardList CardsinPlay = AllZoneUtil.getCardsInPlay(); String Conditions[] = Requirements.split(","); CardsinPlay = CardsinPlay.getValidCards(Conditions, SourceCard.getController(), SourceCard); if (CardsinPlay.isEmpty()) return false; } if (SpecialConditions.contains("isInGraveyard")) { // is a card of a certain type/color present in yard? String Requirements = SpecialConditions.replaceAll("isInGraveyard ", ""); CardList CardsinYards = AllZoneUtil.getCardsInGraveyard(); String Conditions[] = Requirements.split(","); CardsinYards = CardsinYards.getValidCards(Conditions, SourceCard.getController(), SourceCard); if (CardsinYards.isEmpty()) return false; } if (SpecialConditions.contains("isNotPresent")) { // is no card of a certain type/color present? String Requirements = SpecialConditions.replaceAll("isNotPresent ", ""); CardList CardsinPlay = AllZoneUtil.getCardsInPlay(); String Conditions[] = Requirements.split(","); CardsinPlay = CardsinPlay.getValidCards(Conditions, SourceCard.getController(), SourceCard); if (!CardsinPlay.isEmpty()) return false; } if (SpecialConditions.contains("isEquipped")) { if (!SourceCard.isEquipped()) return false; } if (SpecialConditions.contains("isEnchanted")) { if (!SourceCard.isEnchanted()) return false; } if (SpecialConditions.contains("isUntapped")) { if (!SourceCard.isUntapped()) return false; } if (SpecialConditions.contains("isValid")) { // does this card meet the valid description? String Requirements = SpecialConditions.replaceAll("isValid ", ""); if (!SourceCard.isValid(Requirements, SourceCard.getController(), SourceCard)) return false; } if (SpecialConditions.contains("isYourTurn")) { if (!AllZone.getPhase().isPlayerTurn(SourceCard.getController())) return false; } if (SpecialConditions.contains("notYourTurn")) { if (!AllZone.getPhase().isPlayerTurn(SourceCard.getController().getOpponent())) return false; } if (SpecialConditions.contains("OppPoisoned")) { if (SourceCard.getController().getOpponent().getPoisonCounters() == 0) return false; } if (SpecialConditions.contains("OppNotPoisoned")) { if (SourceCard.getController().getOpponent().getPoisonCounters() > 0) return false; } return true; } /** Constant <code>stLandManaAbilities</code> */ public static Command stLandManaAbilities = new Command() { private static final long serialVersionUID = 8005448956536998277L; public void execute() { HashMap<String, String> produces = new HashMap<String, String>(); /* * for future use boolean naked = AllZoneUtil.isCardInPlay("Naked Singularity"); boolean twist = AllZoneUtil.isCardInPlay("Reality Twist"); //set up what they produce produces.put("Forest", naked || twist ? "B" : "G"); produces.put("Island", naked == true ? "G" : "U"); if(naked) produces.put("Mountain", "U"); else if(twist) produces.put("Mountain", "W"); else produces.put("Mountain", "R"); produces.put("Plains", naked || twist ? "R" : "W"); if(naked) produces.put("Swamp", "W"); else if(twist) produces.put("Swamp", "G"); else produces.put("Swamp", "B"); */ produces.put("Forest", "G"); produces.put("Island", "U"); produces.put("Mountain", "R"); produces.put("Plains", "W"); produces.put("Swamp", "B"); CardList lands = AllZoneUtil.getCardsInGame(); lands = lands.filter(AllZoneUtil.lands); //remove all abilities granted by this Command for (Card land : lands) { ArrayList<Ability_Mana> sas = land.getManaAbility(); for (SpellAbility sa : sas) { if (sa.getType().equals("BasicLandTypeMana")) { land.removeSpellAbility(sa); } } } //add all appropriate mana abilities based on current types for (Card land : lands) { if (land.isType("Swamp")) { AbilityFactory AF = new AbilityFactory(); SpellAbility sa = AF.getAbility("AB$ Mana | Cost$ T | Produced$ " + produces.get("Swamp") + " | SpellDescription$ Add " + produces.get("Swamp") + " to your mana pool.", land); sa.setType("BasicLandTypeMana"); land.addSpellAbility(sa); } if (land.isType("Forest")) { AbilityFactory AF = new AbilityFactory(); SpellAbility sa = AF.getAbility("AB$ Mana | Cost$ T | Produced$ " + produces.get("Forest") + " | SpellDescription$ Add " + produces.get("Forest") + " to your mana pool.", land); sa.setType("BasicLandTypeMana"); land.addSpellAbility(sa); } if (land.isType("Island")) { AbilityFactory AF = new AbilityFactory(); SpellAbility sa = AF.getAbility("AB$ Mana | Cost$ T | Produced$ " + produces.get("Island") + " | SpellDescription$ Add " + produces.get("Island") + " to your mana pool.", land); sa.setType("BasicLandTypeMana"); land.addSpellAbility(sa); } if (land.isType("Mountain")) { AbilityFactory AF = new AbilityFactory(); SpellAbility sa = AF.getAbility("AB$ Mana | Cost$ T | Produced$ " + produces.get("Mountain") + " | SpellDescription$ Add " + produces.get("Mountain") + " to your mana pool.", land); sa.setType("BasicLandTypeMana"); land.addSpellAbility(sa); } if (land.isType("Plains")) { AbilityFactory AF = new AbilityFactory(); SpellAbility sa = AF.getAbility("AB$ Mana | Cost$ T | Produced$ " + produces.get("Plains") + " | SpellDescription$ Add " + produces.get("Plains") + " to your mana pool.", land); sa.setType("BasicLandTypeMana"); land.addSpellAbility(sa); } } }// execute() };//stLandManaAbilities /* /** Constant <code>stSetPT</code> public static Command stSetPT = new Command() { /* * Syntax: K:stSetPT:power:toughness:Description * or (for Angry Mob/Gaea's Liege) * K:stSetPT:power:toughness:condition:altPower:altToughness:Description * or (for Levels) * K:stSetPT:power:toughness:condition:altPower:altToughness:condition2:altPower2:altToughness2:Description private static final long serialVersionUID = -8019071015309088017L; public void execute() { //gather cards in all zones based on rule 112.6a CardList Cards_WithKeyword = AllZoneUtil.getCardsInGame(); Cards_WithKeyword = Cards_WithKeyword.filter(new CardListFilter() { public boolean addCard(Card c) { if (c.getKeyword().toString().contains("stSetPT")) return true; return false; } }); // For each card found, find the keywords which are the stSetPT Keywords for (int i = 0; i < Cards_WithKeyword.size(); i++) { Card card = Cards_WithKeyword.get(i); ArrayList<String> a = card.getKeyword(); for (int x = 0; x < a.size(); x++) { if (a.get(x).toString().startsWith("stSetPT")) { String parse = card.getKeyword().get(x).toString(); String k[] = parse.split(":"); /*for(int z = 0; z < k.length; z++) { System.out.println("k["+z+"]: "+k[z]); } if (k.length < 2) { System.out.println("Error in stSetPT for: " + card.getName()); } else { //TODO - add some checking here...? int power = 0; int toughness = 0; int altPower = 0; int altToughness = 0; boolean altCondition = false; int altPower2 = 0; int altToughness2 = 0; boolean altCondition2 = false; //double condition (for level creatures) if (k.length > 6) { String condition2 = k[6]; if (condition2.startsWith("LevelGE")) { condition2 = condition2.replace("LevelGE", ""); int levelReq = Integer.parseInt(condition2); //System.out.println("condition2, got level: "+levelReq); if (card.getCounters(Counters.LEVEL) >= levelReq) { altCondition2 = true; } } } //single condition (for Gaea's Liege/Angry Mob) if (k.length > 3) { String condition = k[3]; if (condition.equals("isAttacking") && card.isAttacking()) { altCondition = true; } else if (condition.equals("isYourTurn") && AllZone.getPhase().isPlayerTurn(card.getController())) { altCondition = true; } else if (condition.startsWith("LevelGE")) { condition = condition.replace("LevelGE", ""); int levelReq = Integer.parseInt(condition); //System.out.println("condition, got level: "+levelReq); if (card.getCounters(Counters.LEVEL) >= levelReq) { altCondition = true; } } } if (altCondition2) { if (k.length > 6) { altPower2 = k[7].matches("[0-9][0-9]?") ? Integer.parseInt(k[7]) : CardFactoryUtil.xCount(card, k[7]); } if (k.length > 7) { altToughness2 = k[8].matches("[0-9][0-9]?") ? Integer.parseInt(k[8]) : CardFactoryUtil.xCount(card, k[8]); } card.setBaseAttack(altPower2); card.setBaseDefense(altToughness2); } else if (altCondition) { //System.out.println("In alt condition"); //System.out.println("Setting power for ("+card.getName()+") to: "+altPower); //System.out.println("Setting toughness for ("+card.getName()+") to: "+altToughness); if (k.length > 4) { altPower = k[4].matches("[0-9][0-9]?") ? Integer.parseInt(k[4]) : CardFactoryUtil.xCount(card, k[4]); } if (k.length > 5) { altToughness = k[5].matches("[0-9][0-9]?") ? Integer.parseInt(k[5]) : CardFactoryUtil.xCount(card, k[5]); } card.setBaseAttack(altPower); card.setBaseDefense(altToughness); } else { //use the base power/toughness to calculate //System.out.println("Setting power for ("+card.getName()+") to: "+power); //System.out.println("Setting toughness for ("+card.getName()+") to: "+toughness); power = k[1].matches("[0-9][0-9]?") ? Integer.parseInt(k[1]) : CardFactoryUtil.xCount(card, k[1]); toughness = k[2].matches("[0-9][0-9]?") ? Integer.parseInt(k[2]) : CardFactoryUtil.xCount(card, k[2]); card.setBaseAttack(power); card.setBaseDefense(toughness); } } } } } }// execute() };//stSetPT */ /** Constant <code>Coat_of_Arms</code> */ public static Command Coat_of_Arms = new Command() { private static final long serialVersionUID = 583505612126735693L; CardList gloriousAnthemList = new CardList(); public void execute() { CardList list = gloriousAnthemList; // reset all cards in list - aka "old" cards for (int i2 = 0; i2 < list.size(); i2++) { list.get(i2).addSemiPermanentAttackBoost(-1); list.get(i2).addSemiPermanentDefenseBoost(-1); } // add +1/+1 to cards list.clear(); PlayerZone[] zone = getZone("Coat of Arms"); // for each zone found add +1/+1 to each card for (int outer = 0; outer < zone.length; outer++) { CardList creature = AllZoneUtil.getCardsInPlay(); for (int i = 0; i < creature.size(); i++) { final Card crd = creature.get(i); CardList Type = AllZoneUtil.getCardsInPlay(); Type = Type.filter(new CardListFilter() { public boolean addCard(Card card) { return !card.equals(crd) && card.isCreature() && !crd.getName().equals("Mana Pool"); } }); CardList Already_Added = new CardList(); for (int x = 0; x < Type.size(); x++) { Already_Added.clear(); for (int x2 = 0; x2 < Type.get(x).getType().size(); x2++) { if (!Already_Added.contains(Type.get(x))) { if (!Type.get(x).getType().get(x2).equals("Creature") && !Type.get(x).getType().get(x2).equals("Legendary") && !Type.get(x).getType().get(x2).equals("Artifact")) { if (crd.isType(Type.get(x).getType().get(x2)) || crd.hasKeyword("Changeling") || Type.get(x).hasKeyword("Changeling")) { Already_Added.add(Type.get(x)); crd.addSemiPermanentAttackBoost(1); crd.addSemiPermanentDefenseBoost(1); gloriousAnthemList.add(crd); } } } } } }// for inner }// for outer }// execute }; // Coat of Arms /** * stores the Command */ public static Command Umbra_Stalker = new Command() { private static final long serialVersionUID = -3500747003228938898L; public void execute() { // get all creatures CardList cards = AllZoneUtil.getCardsInPlay("Umbra Stalker"); for (Card c : cards) { Player player = c.getController(); CardList grave = AllZoneUtil.getPlayerGraveyard(player); int pt = CardFactoryUtil.getNumberOfManaSymbolsByColor("B", grave); c.setBaseAttack(pt); c.setBaseDefense(pt); } }// execute() }; /** Constant <code>Ajani_Avatar_Token</code> */ public static Command Ajani_Avatar_Token = new Command() { private static final long serialVersionUID = 3027329837165436727L; public void execute() { CardList list = AllZoneUtil.getCardsInPlay(); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getName().equals("Avatar") && c.getImageName().equals("W N N Avatar"); } }); for (int i = 0; i < list.size(); i++) { Card card = list.get(i); int n = card.getController().getLife(); card.setBaseAttack(n); card.setBaseDefense(n); }// for }// execute }; // Ajani Avatar /** Constant <code>Old_Man_of_the_Sea</code> */ public static Command Old_Man_of_the_Sea = new Command() { private static final long serialVersionUID = 8076177362922156784L; public void execute() { CardList list = AllZoneUtil.getCardsInPlay("Old Man of the Sea"); for (Card oldman : list) { if (!oldman.getGainControlTargets().isEmpty()) { if (oldman.getNetAttack() < oldman.getGainControlTargets().get(0).getNetAttack()) { ArrayList<Command> coms = oldman.getGainControlReleaseCommands(); for (int i = 0; i < coms.size(); i++) { coms.get(i).execute(); } } } } } };//Old Man of the Sea /** Constant <code>Homarid</code> */ public static Command Homarid = new Command() { private static final long serialVersionUID = 7156319758035295773L; public void execute() { CardList list = AllZoneUtil.getCardsInPlay("Homarid"); for (Card homarid : list) { int tide = homarid.getCounters(Counters.TIDE); if (tide == 4) { homarid.setCounter(Counters.TIDE, 0, true); } } }// execute() }; /** Constant <code>Liu_Bei</code> */ public static Command Liu_Bei = new Command() { private static final long serialVersionUID = 4235093010715735727L; public void execute() { CardList list = AllZoneUtil.getCardsInPlay("Liu Bei, Lord of Shu"); if (list.size() > 0) { for (int i = 0; i < list.size(); i++) { Card c = list.get(i); if (getsBonus(c)) { c.setBaseAttack(4); c.setBaseDefense(6); } else { c.setBaseAttack(2); c.setBaseDefense(4); } } } }// execute() private boolean getsBonus(Card c) { CardList list = AllZoneUtil.getPlayerCardsInPlay(c.getController()); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getName().equals("Guan Yu, Sainted Warrior") || c.getName().equals("Zhang Fei, Fierce Warrior"); } }); return list.size() > 0; } }; //Liu_Bei /** Constant <code>Sound_the_Call_Wolf</code> */ public static Command Sound_the_Call_Wolf = new Command() { private static final long serialVersionUID = 4614281706799537283L; public void execute() { CardList list = AllZoneUtil.getCardsInPlay(); list = list.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getName().equals("Wolf") && c.hasKeyword("This creature gets +1/+1 for each card named Sound the Call in each graveyard."); } }); for (int i = 0; i < list.size(); i++) { Card c = list.get(i); c.setBaseAttack(1 + countSoundTheCalls()); c.setBaseDefense(c.getBaseAttack()); } } private int countSoundTheCalls() { CardList list = AllZoneUtil.getCardsInGraveyard(); list = list.getName("Sound the Call"); return list.size(); } }; //Sound_the_Call_Wolf /** Constant <code>Tarmogoyf</code> */ public static Command Tarmogoyf = new Command() { private static final long serialVersionUID = 5895665460018262987L; public void execute() { // get all creatures CardList list = AllZoneUtil.getCardsInPlay("Tarmogoyf"); for (int i = 0; i < list.size(); i++) { Card c = list.get(i); c.setBaseAttack(countDiffTypes()); c.setBaseDefense(c.getBaseAttack() + 1); } }// execute() private int countDiffTypes() { CardList list = AllZoneUtil.getCardsInGraveyard(); int count = 0; for (int q = 0; q < list.size(); q++) { if (list.get(q).isCreature()) { count++; break; } } for (int q = 0; q < list.size(); q++) { if (list.get(q).isSorcery()) { count++; break; } } for (int q = 0; q < list.size(); q++) { if (list.get(q).isInstant()) { count++; break; } } for (int q = 0; q < list.size(); q++) { if (list.get(q).isArtifact()) { count++; break; } } for (int q = 0; q < list.size(); q++) { if (list.get(q).isEnchantment()) { count++; break; } } for (int q = 0; q < list.size(); q++) { if (list.get(q).isLand()) { count++; break; } } for (int q = 0; q < list.size(); q++) { if (list.get(q).isPlaneswalker()) { count++; break; } } for (int q = 0; q < list.size(); q++) { if (list.get(q).isTribal()) { count++; break; } } return count; } }; /** Constant <code>Muraganda_Petroglyphs</code> */ public static Command Muraganda_Petroglyphs = new Command() { private static final long serialVersionUID = -6715848091817213517L; CardList gloriousAnthemList = new CardList(); public void execute() { CardList list = gloriousAnthemList; Card c; // reset all cards in list - aka "old" cards for (int i = 0; i < list.size(); i++) { c = list.get(i); c.addSemiPermanentAttackBoost(-2); c.addSemiPermanentDefenseBoost(-2); } // add +2/+2 to vanilla cards list.clear(); PlayerZone[] zone = getZone("Muraganda Petroglyphs"); // for each zone found add +2/+2 to each vanilla card for (int outer = 0; outer < zone.length; outer++) { CardList creature = AllZoneUtil.getCreaturesInPlay(); for (int i = 0; i < creature.size(); i++) { c = creature.get(i); if (((c.getAbilityText().trim().equals("") || c.isFaceDown()) && c.getUnhiddenKeyword().size() == 0)) { c.addSemiPermanentAttackBoost(2); c.addSemiPermanentDefenseBoost(2); gloriousAnthemList.add(c); } }// for inner }// for outer }// execute() }; // Muraganda_Petroglyphs /** Constant <code>Meddling_Mage</code> */ public static Command Meddling_Mage = new Command() { private static final long serialVersionUID = 738264163993370439L; CardList gloriousAnthemList = new CardList(); public void execute() { CardList list = gloriousAnthemList; Card c; // reset all cards in list - aka "old" cards for (int i = 0; i < list.size(); i++) { c = list.get(i); //c.removeIntrinsicKeyword("This card can't be cast"); c.setUnCastable(false); } list.clear(); CardList cl = AllZoneUtil.getCardsInPlay("Meddling Mage"); for (int i = 0; i < cl.size(); i++) { final Card crd = cl.get(i); CardList spells = new CardList(); spells.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getHumanPlayer())); spells.addAll(AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer())); spells.addAll(AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer())); spells.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getComputerPlayer())); spells = spells.filter(new CardListFilter() { public boolean addCard(Card c) { return !c.isLand() && c.getName().equals( crd.getNamedCard()); } }); for (int j = 0; j < spells.size(); j++) { c = spells.get(j); if (!c.isLand()) { //c.addIntrinsicKeyword("This card can't be cast"); c.setUnCastable(true); gloriousAnthemList.add(c); } }// for inner }// for outer }// execute() }; // Meddling_Mage /** Constant <code>Gaddock_Teeg</code> */ public static Command Gaddock_Teeg = new Command() { private static final long serialVersionUID = -479252814191086571L; CardList gloriousAnthemList = new CardList(); public void execute() { CardList list = gloriousAnthemList; Card c; // reset all cards in list - aka "old" cards for (int i = 0; i < list.size(); i++) { c = list.get(i); //c.removeIntrinsicKeyword("This card can't be cast"); c.setUnCastable(false); } list.clear(); CardList cl = AllZoneUtil.getCardsInPlay("Gaddock Teeg"); for (int i = 0; i < cl.size(); i++) { CardList spells = new CardList(); spells.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getHumanPlayer())); spells.addAll(AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer())); spells.addAll(AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer())); spells.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getComputerPlayer())); spells = spells.filter(new CardListFilter() { public boolean addCard(Card c) { boolean isXNonCreature = false; if (c.getSpellAbility().length > 0) { if (c.getSpellAbility()[0].isXCost()) isXNonCreature = true; } return !c.isLand() && !c.isCreature() && (CardUtil.getConvertedManaCost(c.getManaCost()) >= 4 || isXNonCreature); } }); for (int j = 0; j < spells.size(); j++) { c = spells.get(j); if (!c.isLand()) { c.setUnCastable(true); gloriousAnthemList.add(c); } }// for inner }// for outer }// execute() }; // /** Constant <code>Iona_Shield_of_Emeria</code> */ public static Command Iona_Shield_of_Emeria = new Command() { private static final long serialVersionUID = 7349652597673216545L; CardList gloriousAnthemList = new CardList(); public void execute() { CardList list = gloriousAnthemList; Card c; // reset all cards in list - aka "old" cards for (int i = 0; i < list.size(); i++) { c = list.get(i); //c.removeIntrinsicKeyword("This card can't be cast"); c.setUnCastable(false); } list.clear(); CardList cl = AllZoneUtil.getCardsInPlay("Iona, Shield of Emeria"); for (int i = 0; i < cl.size(); i++) { final Card crd = cl.get(i); Player controller = cl.get(i).getController(); Player opp = controller.getOpponent(); CardList spells = new CardList(); spells.addAll(AllZoneUtil.getPlayerGraveyard(opp)); spells.addAll(AllZoneUtil.getPlayerHand(opp)); spells = spells.filter(new CardListFilter() { public boolean addCard(Card c) { return !c.isLand() && CardUtil.getColors(c).contains( crd.getChosenColor()); } }); for (int j = 0; j < spells.size(); j++) { c = spells.get(j); if (!c.isLand()) { c.setUnCastable(true); gloriousAnthemList.add(c); } }// for inner }// for outer }// execute() }; //end Iona, Shield of Emeria // returns all PlayerZones that has at least 1 Glorious Anthem // if Computer has 2 Glorious Anthems, AllZone.getComputerPlay() will be // returned twice /** * <p>getZone.</p> * * @param cardName a {@link java.lang.String} object. * @return an array of {@link forge.PlayerZone} objects. */ private static PlayerZone[] getZone(String cardName) { CardList all = AllZoneUtil.getCardsInPlay(); ArrayList<PlayerZone> zone = new ArrayList<PlayerZone>(); for (int i = 0; i < all.size(); i++) { Card c = all.get(i); if (c.getName().equals(cardName) && !c.isFaceDown()) zone.add(AllZone.getZone(c)); } PlayerZone[] z = new PlayerZone[zone.size()]; zone.toArray(z); return z; } /** Constant <code>commands</code> */ public static HashMap<String, Command> commands = new HashMap<String, Command>(); static { //Please add cards in alphabetical order so they are easier to find commands.put("Ajani_Avatar_Token", Ajani_Avatar_Token); commands.put("Coat_of_Arms", Coat_of_Arms); commands.put("Conspiracy", Conspiracy); commands.put("Elspeth_Emblem", Elspeth_Emblem); commands.put("Favor_of_the_Mighty", Favor_of_the_Mighty); commands.put("Gaddock_Teeg", Gaddock_Teeg); commands.put("Homarid", Homarid); commands.put("Iona_Shield_of_Emeria", Iona_Shield_of_Emeria); commands.put("Koth_Emblem", Koth_Emblem); commands.put("Liu_Bei", Liu_Bei); commands.put("Meddling_Mage", Meddling_Mage); commands.put("Muraganda_Petroglyphs", Muraganda_Petroglyphs); commands.put("Old_Man_of_the_Sea", Old_Man_of_the_Sea); commands.put("Sound_the_Call_Wolf", Sound_the_Call_Wolf); commands.put("Tarmogoyf", Tarmogoyf); commands.put("Umbra_Stalker", Umbra_Stalker); ///The commands above are in alphabetical order by cardname. } /** Constant <code>stAnimate</code> */ public static Command stAnimate = new Command() { /** stAnimate * Syntax:[ k[0] stAnimate[All][Self][Enchanted] : k[1] AnimateValid : * k[2] P/T/Keyword : k[3] extra types : k[4] extra colors : * k[5] Abilities : k[6] Special Conditions : k[7] Description * */ private static final long serialVersionUID = -1404133561787349004L; // storage stores the source card and the cards it gave its bonus to, to know what to remove private ArrayList<StaticEffect> storage = new ArrayList<StaticEffect>(); public void execute() { // remove all static effects for (int i = 0; i < storage.size(); i++) { removeStaticEffect(storage.get(i)); } //clear the list storage = new ArrayList<StaticEffect>(); //Gather Cards on the Battlefield with the stPump Keyword CardList cards = AllZoneUtil.getCardsInPlay(); cards.getKeywordsContain("stAnimate"); // check each card for (int i = 0; i < cards.size(); i++) { Card cardWithKeyword = cards.get(i); ArrayList<String> keywords = cardWithKeyword.getKeyword(); // check each keyword of the card for (int j = 0; j < keywords.size(); j++) { String keyword = keywords.get(j); if (keyword.startsWith("stAnimate")) { StaticEffect se = new StaticEffect(); //create a new StaticEffect se.setSource(cardWithKeyword); se.setKeywordNumber(j); //get the affected cards String k[] = keyword.split(":", 8); if (specialConditionsMet(cardWithKeyword, k[6])) { //special conditions are isPresent, isValid final String affected = k[1]; final String specific[] = affected.split(","); CardList affectedCards = getAffectedCards(cardWithKeyword, k, specific); // options are All, Self, Enchanted etc. se.setAffectedCards(affectedCards); String[] pt = k[2].split("/"); if (!k[2].equals("no changes") && pt.length > 1) { int x = 0; if (pt[0].contains("X") || pt[1].contains("X")) x = CardFactoryUtil.xCount(cardWithKeyword, cardWithKeyword.getSVar("X").split("\\$")[1]); se.setXValue(x); int y = 0; if (pt[1].contains("Y")) y = CardFactoryUtil.xCount(cardWithKeyword, cardWithKeyword.getSVar("Y").split("\\$")[1]); se.setYValue(y); } ArrayList<String> types = new ArrayList<String>(); if (!k[3].equalsIgnoreCase("no types")) { types.addAll(Arrays.asList(k[3].split(","))); if (types.contains("Overwrite")) { types.remove("Overwrite"); se.setOverwriteTypes(true); } if (types.contains("KeepSupertype")) { types.remove("KeepSupertype"); se.setKeepSupertype(true); } if (types.contains("RemoveSubTypes")) { types.remove("RemoveSubTypes"); se.setRemoveSubTypes(true); } } String colors = ""; if (!k[4].equalsIgnoreCase("no colors")) { colors = k[4]; if (colors.contains(",Overwrite") || colors.contains("Overwrite")) { colors = colors.replace(",Overwrite", ""); colors = colors.replace("Overwrite", ""); se.setOverwriteColors(true); } colors = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(k[4].split(",")))); } if (k[2].contains("Overwrite")) { se.setOverwriteKeywords(true); } if (k[5].contains("Overwrite")) { se.setOverwriteAbilities(true); } addStaticEffects(se, cardWithKeyword, affectedCards, k[2], types, colors); //give the boni to the affected cards storage.add(se); // store the information } } } } }// execute() private void addStaticEffects(StaticEffect se, Card source, CardList affectedCards, String details, ArrayList<String> types, String colors) { for (int i = 0; i < affectedCards.size(); i++) { Card affectedCard = affectedCards.get(i); if (!details.equals("no changes")) { String[] keyword = details.split("/", 3); String powerStr = keyword[0]; String toughStr = keyword[1]; //copied from stSetPT power/toughness if (!powerStr.equals("no change")) { int power = powerStr.matches("[0-9][0-9]?") ? Integer.parseInt(powerStr) : CardFactoryUtil.xCount(affectedCard, powerStr); se.addOriginalPT(affectedCard, affectedCard.getBaseAttack(), affectedCard.getBaseDefense()); affectedCard.setBaseAttack(power); } if (!toughStr.equals("no change")) { int toughness = toughStr.matches("[0-9][0-9]?") ? Integer.parseInt(toughStr) : CardFactoryUtil.xCount(affectedCard, toughStr); se.addOriginalPT(affectedCard, affectedCard.getBaseAttack(), affectedCard.getBaseDefense()); affectedCard.setBaseDefense(toughness); } if (se.isOverwriteKeywords()) { se.addOriginalKeywords(affectedCard, affectedCard.getIntrinsicKeyword()); affectedCard.clearAllKeywords(); } else { if (keyword.length != 2) { int index = 2; if (keyword.length == 1) index = 0; String keywords[] = keyword[index].split(" & "); for (int j = 0; j < keywords.length; j++) { String kw = keywords[j]; affectedCard.addExtrinsicKeyword(kw); } } } } if (se.isOverwriteTypes()) { se.addOriginalTypes(affectedCard, affectedCard.getType()); if (!se.isKeepSupertype()) { affectedCard.clearAllTypes(); } else { ArrayList<String> acTypes = affectedCard.getType(); for (String t : acTypes) { if (!CardUtil.isASuperType(t)) affectedCard.removeType(t); } } } if (se.isRemoveSubTypes()) { se.addOriginalTypes(affectedCard, affectedCard.getType()); ArrayList<String> acTypes = affectedCard.getType(); for (String t : acTypes) { if (CardUtil.isASubType(t)) affectedCard.removeType(t); } } for (String type : types) { if (!affectedCard.isType(type)) { affectedCard.addType(type); se.addType(affectedCard, type); } else { se.removeType(affectedCard, type); } } //Abilities if (se.isOverwriteAbilities()) { se.addOriginalAbilities(affectedCard, affectedCard.getAllButFirstSpellAbility()); affectedCard.clearAllButFirstSpellAbility(); } else { //TODO - adding SpellAbilities statically here not supported at this time } long t = affectedCard.addColor(colors, affectedCard, !se.isOverwriteColors(), true); se.addTimestamp(affectedCard, t); }//end for } void removeStaticEffect(StaticEffect se) { Card source = se.getSource(); CardList affected = se.getAffectedCards(); int num = se.getKeywordNumber(); String parse = source.getKeyword().get(num).toString(); String k[] = parse.split(":"); for (int i = 0; i < affected.size(); i++) { Card c = affected.get(i); removeStaticEffect(se, source, c, k); } se.clearAllTypes(); se.clearTimestamps(); } private void removeStaticEffect(StaticEffect se, Card source, Card affectedCard, String[] details) { String[] kw = details[2].split("/", 3); if (!details[2].equals("no changes")) { if (!kw[0].equals("no change")) affectedCard.setBaseAttack(se.getOriginalPower(affectedCard)); if (!kw[1].equals("no change")) affectedCard.setBaseDefense(se.getOriginalToughness(affectedCard)); } for (String type : se.getTypes(affectedCard)) { affectedCard.removeType(type); } if (se.isOverwriteTypes()) { for (String type : se.getOriginalTypes(affectedCard)) { if (!se.isKeepSupertype() || (se.isKeepSupertype() && !CardUtil.isASuperType(type))) { affectedCard.addType(type); } } } if (se.isRemoveSubTypes()) { for (String type : se.getOriginalTypes(affectedCard)) { if (CardUtil.isASubType(type)) affectedCard.addType(type); } } if (se.isOverwriteKeywords()) { for (String keyw : se.getOriginalKeywords(affectedCard)) affectedCard.addIntrinsicKeyword(keyw); } else { if (kw.length != 2) { int index = 2; if (kw.length == 1) index = 0; String keywords[] = kw[index].split(" & "); for (int j = 0; j < keywords.length; j++) { String keyw = keywords[j]; affectedCard.removeExtrinsicKeyword(keyw); } } } //Abilities if (se.isOverwriteAbilities()) { for (SpellAbility sa : se.getOriginalAbilities(affectedCard)) affectedCard.addSpellAbility(sa); } else { //TODO - adding SpellAbilities statically here not supported at this time } affectedCard.removeColor(se.getColorDesc(), affectedCard, !se.isOverwriteColors(), se.getTimestamp(affectedCard)); }//end removeStaticEffects private CardList getAffectedCards(Card source, String[] details, String[] specific) { // [Self], [All], [Enchanted] CardList affected = new CardList(); String range = details[0].replaceFirst("stAnimate", ""); if (range.equals("Self")) { affected.add(source); } else if (range.equals("All")) { affected.addAll(AllZoneUtil.getCardsInPlay()); } else if (range.equals("Enchanted")) { if (source.getEnchanting().size() > 0) { affected.addAll(source.getEnchanting().toArray()); } } affected = affected.getValidCards(specific, source.getController(), source); return affected; }//end getAffectedCards() }; /** * <p>doPowerSink.</p> * * @param p a {@link forge.Player} object. */ public static void doPowerSink(Player p) { //get all lands with mana abilities CardList lands = AllZoneUtil.getPlayerLandsInPlay(p); lands = lands.filter(new CardListFilter() { public boolean addCard(Card c) { return c.getManaAbility().size() > 0; } }); //tap them for (Card c : lands) c.tap(); //empty mana pool if (p.isHuman()) AllZone.getManaPool().clearPool(); else AllZone.getComputerManaPool().clearPool(); } }//end class GameActionUtil