diff --git a/src/forge/Card.java b/src/forge/Card.java index 42a5af59ef8..3b558fae9b6 100644 --- a/src/forge/Card.java +++ b/src/forge/Card.java @@ -542,6 +542,7 @@ public class Card extends MyObservable { runParams.put("CounterType", counterName); AllZone.TriggerHandler.runTrigger("CounterAdded", runParams); + AllZone.GameAction.checkStateEffects(); this.updateObservers(); @@ -1423,7 +1424,7 @@ public class Card extends MyObservable { public void executeTrigger(ZCTrigger type) { for(Ability_Triggered t:zcTriggers) - if(t.trigger.equals(type) && t.isBasic()) AllZone.Stack.add(t); + if(t.trigger.equals(type) && t.isBasic()) AllZone.Stack.addSimultaneousStackEntry(t); } public void clearTriggers() { @@ -2091,6 +2092,8 @@ public class Card extends MyObservable { HashMap runParams = new HashMap(); runParams.put("Card", this); AllZone.TriggerHandler.runTrigger("Taps", runParams); + + } setTapped(true); } @@ -2101,11 +2104,13 @@ public class Card extends MyObservable { HashMap runParams = new HashMap(); runParams.put("Card", this); AllZone.TriggerHandler.runTrigger("Untaps", runParams); + } for(Command var:untapCommandList) { var.execute(); } + setTapped(false); } diff --git a/src/forge/Combat.java b/src/forge/Combat.java index 9f8bda55db5..61b43270d8c 100644 --- a/src/forge/Combat.java +++ b/src/forge/Combat.java @@ -398,6 +398,8 @@ public class Combat { HashMap runParams = new HashMap(); runParams.put("Attacker", attacker); AllZone.TriggerHandler.runTrigger("AttackerUnblocked", runParams); + + } } } @@ -624,6 +626,9 @@ public class Combat { damageMap.clear(); c.clearAssignedDamage(); } + + //This was deeper before,but that resulted in the stack entry acting like before. + } public boolean isUnblocked(Card att){ diff --git a/src/forge/CombatUtil.java b/src/forge/CombatUtil.java index 7aefe9858cb..a32c335c11c 100644 --- a/src/forge/CombatUtil.java +++ b/src/forge/CombatUtil.java @@ -1811,6 +1811,7 @@ public class CombatUtil { } a.setCreatureGotBlockedThisCombat(true); + } public static void executeExaltedAbility(Card c, int magnitude) { @@ -1846,7 +1847,7 @@ public class CombatUtil { sb.append(c).append(" - (Exalted) gets +1/+1 until EOT."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); } Player phasingPlayer = c.getController(); @@ -1864,7 +1865,7 @@ public class CombatUtil { sbUntap.append(c).append(" - (Exalted) untap."); fhUntap.setStackDescription(sbUntap.toString()); - AllZone.Stack.add(fhUntap); + AllZone.Stack.addSimultaneousStackEntry(fhUntap); // If any Finest Hours, queue up a new combat phase for (int ix = 0; ix < AllZoneUtil.getPlayerCardsInPlay(phasingPlayer, "Finest Hour").size(); ix++) { @@ -1878,7 +1879,7 @@ public class CombatUtil { sbACom.append(c).append(" - (Exalted) ").append(phasingPlayer).append(" gets Extra Combat Phase."); fhAddCombat.setStackDescription(sbACom.toString()); - AllZone.Stack.add(fhAddCombat); + AllZone.Stack.addSimultaneousStackEntry(fhAddCombat); } } @@ -1929,7 +1930,7 @@ public class CombatUtil { sb4.append("put it onto the battlefield attached to that creature, then shuffles library."); ability4.setStackDescription(sb4.toString()); - AllZone.Stack.add(ability4); + AllZone.Stack.addSimultaneousStackEntry(ability4); } // For } } diff --git a/src/forge/ComputerUtil.java b/src/forge/ComputerUtil.java index 8268d276e33..3b4b21a12a0 100644 --- a/src/forge/ComputerUtil.java +++ b/src/forge/ComputerUtil.java @@ -573,6 +573,8 @@ public class ComputerUtil } if(!cost.isPaid()) throw new RuntimeException("ComputerUtil : payManaCost() cost was not paid for " + sa.getSourceCard().getName()); + + }//payManaCost() diff --git a/src/forge/EndOfTurn.java b/src/forge/EndOfTurn.java index 8b24700a3c6..0c62316da97 100644 --- a/src/forge/EndOfTurn.java +++ b/src/forge/EndOfTurn.java @@ -47,8 +47,9 @@ public class EndOfTurn implements java.io.Serializable StringBuilder sb = new StringBuilder(); sb.append("Sacrifice ").append(card); sac.setStackDescription(sb.toString()); - - AllZone.Stack.add(sac); + + AllZone.Stack.addSimultaneousStackEntry(sac); + } if(!c.isFaceDown() && c.getKeyword().contains("At the beginning of the end step, exile CARDNAME.")) { final Card card = c; @@ -61,8 +62,9 @@ public class EndOfTurn implements java.io.Serializable StringBuilder sb = new StringBuilder(); sb.append("Exile ").append(card); exile.setStackDescription(sb.toString()); - - AllZone.Stack.add(exile); + + AllZone.Stack.addSimultaneousStackEntry(exile); + } if(!c.isFaceDown() && c.getKeyword().contains("At the beginning of the end step, destroy CARDNAME.")) { final Card card = c; @@ -75,8 +77,9 @@ public class EndOfTurn implements java.io.Serializable StringBuilder sb = new StringBuilder(); sb.append("Destroy ").append(card); destroy.setStackDescription(sb.toString()); - - AllZone.Stack.add(destroy); + + AllZone.Stack.addSimultaneousStackEntry(destroy); + } //Berserk is using this, so don't check isFaceDown() if(c.getKeyword().contains("At the beginning of the next end step, destroy CARDNAME if it attacked this turn.")) { @@ -91,8 +94,9 @@ public class EndOfTurn implements java.io.Serializable StringBuilder sb = new StringBuilder(); sb.append("Sacrifice ").append(card); sac.setStackDescription(sb.toString()); - - AllZone.Stack.add(sac); + + AllZone.Stack.addSimultaneousStackEntry(sac); + } else { c.removeExtrinsicKeyword("At the beginning of the next end step, destroy CARDNAME if it attacked this turn."); @@ -113,8 +117,9 @@ public class EndOfTurn implements java.io.Serializable StringBuilder sb = new StringBuilder(); sb.append(vale.getName()).append(" changes controllers."); change.setStackDescription(sb.toString()); - - AllZone.Stack.add(change); + + AllZone.Stack.addSimultaneousStackEntry(change); + } if(c.getName().equals("Erg Raiders") && !c.getCreatureAttackedThisTurn() && !(c.getTurnInZone() == AllZone.Phase.getTurn()) && AllZone.Phase.isPlayerTurn(c.getController())) { @@ -130,8 +135,9 @@ public class EndOfTurn implements java.io.Serializable StringBuilder sb = new StringBuilder(); sb.append(raider.getName()).append(" deals 2 damage to controller."); change.setStackDescription(sb.toString()); - - AllZone.Stack.add(change); + + AllZone.Stack.addSimultaneousStackEntry(change); + } if(c.hasKeyword("At the beginning of your end step, sacrifice this creature unless it attacked this turn.") && !c.getCreatureAttackedThisTurn() @@ -149,13 +155,18 @@ public class EndOfTurn implements java.io.Serializable StringBuilder sb = new StringBuilder(); sb.append(source.getName()).append(" - sacrifice ").append(source.getName()).append("."); change.setStackDescription(sb.toString()); - - AllZone.Stack.add(change); + + AllZone.Stack.addSimultaneousStackEntry(change); + } } + + execute(at); - + + + CardList all2 = AllZoneUtil.getCardsInPlay(); for(Card c:all2) { if(c.getCreatureAttackedThisTurn()) c.setCreatureAttackedThisTurn(false); diff --git a/src/forge/GameAction.java b/src/forge/GameAction.java index 3623cc63849..fc65e752056 100644 --- a/src/forge/GameAction.java +++ b/src/forge/GameAction.java @@ -100,6 +100,8 @@ public class GameAction { runParams.put("Destination", zone.getZoneName()); AllZone.TriggerHandler.runTrigger("ChangesZone", runParams); + + return c; } @@ -618,6 +620,8 @@ public class GameAction { HashMap runParams = new HashMap(); runParams.put("Card", c); AllZone.TriggerHandler.runTrigger("Sacrificed", runParams); + + } public void destroyNoRegeneration(Card c) { @@ -2142,7 +2146,9 @@ public class GameAction { GameActionUtil.executeVampiricEffects(crd); } } - + + + this.sacrificeDestroy(c); return true; } diff --git a/src/forge/GameActionUtil.java b/src/forge/GameActionUtil.java index 3ab4b6f1094..337429522ca 100644 --- a/src/forge/GameActionUtil.java +++ b/src/forge/GameActionUtil.java @@ -105,7 +105,7 @@ public class GameActionUtil { upkeep_Power_Surge(); upkeep_AI_Aluren(); // experimental, AI abuse aluren - + AllZone.Stack.unfreezeStack(); } @@ -114,7 +114,8 @@ public class GameActionUtil { final Player player = AllZone.Phase.getPlayerTurn(); draw_Teferi_Puzzle_Box(player); draw_Sylvan_Library(player); - AllZone.Stack.unfreezeStack(); + + AllZone.Stack.unfreezeStack(); } public static void executeTapSideEffects(Card c) { @@ -142,8 +143,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(blight.getName()).append(" - Destroy enchanted land."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } }//end Blight @@ -174,6 +176,7 @@ public class GameActionUtil { playCard_Presence_of_the_Master(c); AllZone.GameAction.checkWheneverKeyword(c,"CastSpell",null); + } public static void playCard_Cascade(final Card c) { @@ -278,8 +281,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(c).append(" - Cascade."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; Cascade.execute(); @@ -385,8 +389,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(c).append(" - Ripple."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } }; @@ -440,8 +445,9 @@ public class GameActionUtil { sb.append(card.getName()).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.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//if } } @@ -458,7 +464,9 @@ public class GameActionUtil { } }; counter.setStackDescription(source.getName()+" - counter enchantment spell."); - AllZone.Stack.add(counter); + + AllZone.Stack.addSimultaneousStackEntry(counter); + } } @@ -544,7 +552,9 @@ public class GameActionUtil { AllZone.GameAction.playSpellAbility(ability); else { ability.chooseTargetAI(); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } } @@ -571,7 +581,9 @@ public class GameActionUtil { ability2.setStackDescription(sb.toString()); int convertedManaSpell = CardUtil.getConvertedManaCost(sa.getSourceCard().getManaCost()); - if(sa.isSpell() == true && card.getCounters(Counters.CHARGE) == convertedManaSpell) AllZone.Stack.add(ability2); + if(sa.isSpell() == true && card.getCounters(Counters.CHARGE) == convertedManaSpell) + AllZone.Stack.addSimultaneousStackEntry(ability2); + } }//if } // Chalice_of_the_Void @@ -595,8 +607,9 @@ public class GameActionUtil { sb.append(" casts Demigod of Revenge, returns all cards named Demigod "); sb.append("of Revenge from your graveyard to the battlefield."); ability2.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + }//if }// Demigod of Revenge @@ -652,8 +665,9 @@ public class GameActionUtil { sb.append(" played a Spirit or Arcane spell, target player reveals his or her hand "); sb.append("and discards all cards with converted mana cost ").append(converted).append("."); ability2.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + } }//if } @@ -709,7 +723,9 @@ public class GameActionUtil { }; // ability2 ability2.setStackDescription("Dovescape Ability"); - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + } } // Dovescape @@ -734,8 +750,9 @@ public class GameActionUtil { sb.append(card.getName()).append(" - ").append(c.getController()); sb.append(" played a spell, ").append(drawer).append(" draws seven cards."); ability2.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + } } @@ -762,8 +779,9 @@ public class GameActionUtil { sb.append(card.getName()).append(" - ").append(c.getController()); sb.append(" played a spell, ").append(drawer).append(" draws three cards."); ability2.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + } @@ -793,8 +811,9 @@ public class GameActionUtil { sb.append(card.getName()).append(" - ").append(c.getController()); sb.append(" puts a 4/4 White Angel token with flying onto the battlefield."); ability2.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + } // for }// if isEnchantment() @@ -820,8 +839,9 @@ public class GameActionUtil { sb.append(" played a ").append(card.getChosenColor()).append(" spell, "); sb.append(c.getController()).append(" loses 1 life."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//if }//if @@ -888,8 +908,9 @@ public class GameActionUtil { } }; upkeepAbility.setStackDescription(sb.toString()); - - AllZone.Stack.add(upkeepAbility); + + AllZone.Stack.addSimultaneousStackEntry(upkeepAbility); + } } //upkeep_Braid_of_Fire @@ -946,7 +967,8 @@ public class GameActionUtil { }; destroyAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(destroyAbility); + AllZone.Stack.addSimultaneousStackEntry(destroyAbility); + } }//TabernacleUpkeepCost @@ -1001,7 +1023,8 @@ public class GameActionUtil { }; upkeepAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(upkeepAbility); + AllZone.Stack.addSimultaneousStackEntry(upkeepAbility); + } }//MagusTabernacleUpkeepCost @@ -1059,7 +1082,8 @@ public class GameActionUtil { }; upkeepAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(upkeepAbility); + AllZone.Stack.addSimultaneousStackEntry(upkeepAbility); + } }//upkeepCost @@ -1090,7 +1114,7 @@ public class GameActionUtil { final StringBuilder sb = new StringBuilder(); sb.append("Echo for ").append(c).append("\n"); - final Ability sacAbility = new Ability(c, c.getEchoCost()) { + final Ability sacAbility = new Ability(c, "0") { @Override public void resolve() { if(c.getController().equals(AllZone.HumanPlayer)) { @@ -1107,7 +1131,8 @@ public class GameActionUtil { }; sacAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(sacAbility); + AllZone.Stack.addSimultaneousStackEntry(sacAbility); + c.removeIntrinsicKeyword("(Echo unpaid)"); } @@ -1130,7 +1155,9 @@ public class GameActionUtil { } }; slowtrip.setStackDescription(card.getName() + " - Draw a card"); - AllZone.Stack.add(slowtrip); + + AllZone.Stack.addSimultaneousStackEntry(slowtrip); + } player.clearSlowtripList(); @@ -1151,8 +1178,9 @@ public class GameActionUtil { } }; slowtrip.setStackDescription(card.getName() + " - Draw a card"); - AllZone.Stack.add(slowtrip); - + + AllZone.Stack.addSimultaneousStackEntry(slowtrip); + } opponent.clearSlowtripList(); } @@ -1209,7 +1237,9 @@ public class GameActionUtil { } }; upkeepAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(upkeepAbility); + + AllZone.Stack.addSimultaneousStackEntry(upkeepAbility); + } }//upkeepCost @@ -1265,7 +1295,9 @@ public class GameActionUtil { } }; upkeepAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(upkeepAbility); + + AllZone.Stack.addSimultaneousStackEntry(upkeepAbility); + } }//upkeepCost @@ -1327,7 +1359,9 @@ public class GameActionUtil { } }; upkeepAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(upkeepAbility); + + AllZone.Stack.addSimultaneousStackEntry(upkeepAbility); + } }//damageUpkeepCost @@ -1401,7 +1435,8 @@ public class GameActionUtil { sacrificeCreature.setStackDescription(sb.toString()); if(abyss_getTargets(player,abyss).size() > 0) - AllZone.Stack.add(sacrificeCreature); + AllZone.Stack.addSimultaneousStackEntry(sacrificeCreature); + }//end for }//The Abyss @@ -1442,8 +1477,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(vortex.getName()).append(" - "+player+" sacrifices a land."); sacrificeLand.setStackDescription(sb.toString()); - - AllZone.Stack.add(sacrificeLand); + + AllZone.Stack.addSimultaneousStackEntry(sacrificeLand); + }//end for }//Mana_Vortex @@ -1489,7 +1525,8 @@ public class GameActionUtil { sb.append(eve.getName()).append(" - remove a scream counter and return creatures to the battlefield."); hallow.setStackDescription(sb.toString()); if(AllZone.GameAction.isCardExiled(eve)) { - AllZone.Stack.add(hallow); + AllZone.Stack.addSimultaneousStackEntry(hallow); + } }//end for }//All_Hallows_Eve @@ -1551,8 +1588,9 @@ public class GameActionUtil { 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.Stack.add(sacrificeArtifact); + + AllZone.Stack.addSimultaneousStackEntry(sacrificeArtifact); + }//end for } @@ -1601,8 +1639,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - deals 7 damage to controller"); sevenDamage.setStackDescription(sb.toString()); - - AllZone.Stack.add(sevenDamage); + + AllZone.Stack.addSimultaneousStackEntry(sevenDamage); + } else { @@ -1610,7 +1649,8 @@ public class GameActionUtil { sb.append(c.getName()).append(" - sacrifice a creature."); sacrificeCreature.setStackDescription(sb.toString()); - AllZone.Stack.add(sacrificeCreature); + AllZone.Stack.addSimultaneousStackEntry(sacrificeCreature); + } }//end for }// upkeep_Lord_of_the_Pit() @@ -1678,8 +1718,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(c.getName()).append(" - destroy 1 creature with lowest power."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//end for }// upkeep_Drop_of_Honey() @@ -1730,13 +1771,17 @@ public class GameActionUtil { } //end resolve() }; //end pay ability pay.setStackDescription("Demonic Hordes - Upkeep Cost"); - AllZone.Stack.add(pay); + + AllZone.Stack.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.Stack.add(noPay); + + AllZone.Stack.addSimultaneousStackEntry(noPay); + } } //end human else { //computer @@ -1748,10 +1793,13 @@ public class GameActionUtil { } }; computerPay.setStackDescription("Computer pays Demonic Hordes upkeep cost"); - AllZone.Stack.add(computerPay); + + AllZone.Stack.addSimultaneousStackEntry(computerPay); + } else { - AllZone.Stack.add(noPay); + AllZone.Stack.addSimultaneousStackEntry(noPay); + } } //end computer @@ -1814,8 +1862,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Wall of Reverence - ").append(player).append(" gains life equal to target creature's power."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//endOfTurn_Wall_Of_Reverence() @@ -1873,8 +1922,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append(card.getController()).append(" takes an extra turn."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } @@ -1988,6 +2038,8 @@ public class GameActionUtil { public static void executeLandfallEffects(Card c) { if(c.getName().equals("Lotus Cobra")) landfall_Lotus_Cobra(c); + + } private static boolean checkValakutCondition(Card valakutCard, Card mtn) { @@ -2098,7 +2150,8 @@ public class GameActionUtil { AllZone.InputControl.setInput(CardFactoryUtil.input_targetCreaturePlayer(DamageTgt, true, true)); } else { DamageTgt.chooseTargetAI(); - AllZone.Stack.add(DamageTgt); + AllZone.Stack.addSimultaneousStackEntry(DamageTgt); + } return true; // Tell the calling routine it's okay to call again if there are other Valakuts in play } @@ -2137,7 +2190,7 @@ public class GameActionUtil { ability.setStackDescription(sb.toString()); if(c.getController().equals(AllZone.HumanPlayer)) { - if(showLandfallDialog(c)) AllZone.Stack.add(ability); + if(showLandfallDialog(c)) AllZone.Stack.addSimultaneousStackEntry(ability); } else{ // todo: once AI has a mana pool he should choose add Ability and choose a mana as appropriate @@ -2170,9 +2223,12 @@ public class GameActionUtil { StringBuilder sb2 = new StringBuilder(); sb2.append(thisCard.getName()).append(" - gets a +1/+1 counter"); ability2.setStackDescription(sb2.toString()); - - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + } + + } //not restricted to combat damage, restricted to dealing damage to creatures @@ -2194,8 +2250,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(affected.getName()+" - Deals ").append(stuffyDamage).append(" damage to ").append(opponent); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } if(affected.getName().equals("Jackal Pup") || affected.getName().equals("Shinka Gatekeeper")) { @@ -2209,8 +2266,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(affected.getName()+" - Deals ").append(selfDamage).append(" damage to ").append(player); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } if(source.getName().equals("Spiritmonger")) { @@ -2224,8 +2282,9 @@ public class GameActionUtil { StringBuilder sb2 = new StringBuilder(); sb2.append(source.getName()).append(" - gets a +1/+1 counter"); ability2.setStackDescription(sb2.toString()); - - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + } if(affected.getKeyword().contains("Whenever CARDNAME is dealt damage, put a +1/+1 counter on it.")) { @@ -2242,7 +2301,8 @@ public class GameActionUtil { int amount = affected.getAmountOfKeyword("Whenever CARDNAME is dealt damage, put a +1/+1 counter on it."); for(int i=0 ; i < amount ; i++) - AllZone.Stack.add(ability2); + AllZone.Stack.addSimultaneousStackEntry(ability2); + } if(affected.hasStartOfKeyword("When CARDNAME is dealt damage, destroy it.")) { @@ -2265,15 +2325,18 @@ public class GameActionUtil { int amount = affected.getAmountOfKeyword("When CARDNAME is dealt damage, destroy it. It can't be regenerated."); for(int i=0 ; i < amount ; i++) - AllZone.Stack.add(ability2); + AllZone.Stack.addSimultaneousStackEntry(ability2); + } int amount = affected.getAmountOfKeyword("When CARDNAME is dealt damage, destroy it."); for(int i=0 ; i < amount ; i++) - AllZone.Stack.add(ability); AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); AllZone.Stack.addSimultaneousStackEntry(ability); } if(source.getKeyword().contains("Deathtouch") && affected.isCreature()) AllZone.GameAction.destroy(affected); + + } public static void executeSwordOfLightAndShadowEffects(final Card source) { @@ -2309,7 +2372,8 @@ public class GameActionUtil { // list = list.getType("Creature"); if(list.isEmpty()) { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + return; } @@ -2317,14 +2381,16 @@ public class GameActionUtil { Object o = GuiUtils.getChoiceOptional("Select target card", list.toArray()); if(o != null) { ability.setTargetCard((Card) o); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//if else//computer { Card best = CardFactoryUtil.AI_getBestCreature(list); ability.setTargetCard(best); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//execute() };//Command @@ -2364,8 +2430,9 @@ public class GameActionUtil { sb.append(" - gets a +1/+1 counter"); } ability2.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability2); + + AllZone.Stack.addSimultaneousStackEntry(ability2); + } } } @@ -2411,7 +2478,8 @@ public class GameActionUtil { //Backfire triggers only if its controller is damaged if(aura.getController().isPlayer(player)) - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//auras > 0 }//end c.isEnchanted() @@ -2436,8 +2504,9 @@ public class GameActionUtil { sb.append(darien.getName()).append(" - ").append(darien.getController()); sb.append(" puts ").append(damage).append(" Soldier tokens onto the battlefield."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } /*if (playerPerms.getName("Dissipation Field").size() > 0) { @@ -2482,8 +2551,9 @@ public class GameActionUtil { sb.append(lich.getName()).append(" - ").append(lich.getController()); sb.append(" sacrifices ").append(damage).append(" nontoken Permanents."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } @@ -2496,6 +2566,8 @@ public class GameActionUtil { if (player.isPlayer(AllZone.HumanPlayer)) c.setDealtDmgToHumanThisTurn(true); if (player.isPlayer(AllZone.ComputerPlayer)) c.setDealtDmgToComputerThisTurn(true); + + } private static void execute_Living_Artifact(final Player p, final int num) { @@ -2507,7 +2579,9 @@ public class GameActionUtil { } }; addCounter.setStackDescription(la.getName()+" - Put "+num+" vitality counters on "+la); - AllZone.Stack.add(addCounter); + + AllZone.Stack.addSimultaneousStackEntry(addCounter); + } } @@ -2534,7 +2608,9 @@ public class GameActionUtil { } }; ability.setStackDescription(zone+" - "+c.getController()+" gains control of "+zone); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } @@ -2574,7 +2650,8 @@ public class GameActionUtil { for (int i=0;i 0 }//upkeep_Heartmender @@ -3150,7 +3246,9 @@ public class GameActionUtil { sb.append("Ink Dissolver - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Ink_Dissolver() @@ -3238,7 +3336,9 @@ public class GameActionUtil { sb.append("Kithkin Zephyrnaut - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Kithkin_Zephyrnaut() @@ -3325,7 +3425,9 @@ public class GameActionUtil { sb.append("Leaf-Crowned Elder - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Leaf_Crowned_Elder() @@ -3408,7 +3510,9 @@ public class GameActionUtil { sb.append("Mudbutton Clanger - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Mudbutton_Clanger() @@ -3479,7 +3583,9 @@ public class GameActionUtil { sb.append("Nightshade Schemers - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Nightshade_Schemers() @@ -3565,7 +3671,9 @@ public class GameActionUtil { sb.append("Pyroclast Consul - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Pyroclast_Consul() @@ -3644,7 +3752,9 @@ public class GameActionUtil { sb.append("Sensation Gorger - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Sensation_Gorger() @@ -3717,7 +3827,9 @@ public class GameActionUtil { sb.append("Squeaking Pie Grubfellows - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Squeaking_Pie_Grubfellows() @@ -3787,7 +3899,9 @@ public class GameActionUtil { sb.append("Wandering Graybeard - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Wandering_Graybeard() @@ -3878,7 +3992,9 @@ public class GameActionUtil { sb.append("Waterspout Weavers - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Waterspout_Weavers() @@ -3948,7 +4064,9 @@ public class GameActionUtil { sb.append("Winnower Patrol - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Winnower_Patrol() @@ -4020,7 +4138,9 @@ public class GameActionUtil { sb.append("Wolf-Skull Shaman - ").append(player); sb.append(" triggers Kinship"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Wolf_Skull_Shaman() @@ -4063,7 +4183,8 @@ public class GameActionUtil { sb.append(" life and draws top card (").append(cardName).append(")."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Dark_Confidant() @@ -4100,7 +4221,9 @@ public class GameActionUtil { } };// Ability ability.setStackDescription("Oversold Cemetary returns creature from the graveyard to its owner's hand."); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } }//Oversold Cemetery @@ -4138,7 +4261,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Nether Spirit - ").append(player).append(" returns Nether Spirit to the battlefield"); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } //if }//nether spirit @@ -4189,8 +4314,9 @@ public class GameActionUtil { 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.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } } @@ -4223,8 +4349,9 @@ public class GameActionUtil { 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.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } } @@ -4296,7 +4423,8 @@ public class GameActionUtil { sb.append("battlefield and all other cards revealed this way into his or her graveyard."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } } }// upkeep_Oath of Druids() @@ -4341,7 +4469,8 @@ public class GameActionUtil { sb.append("from their graveyard to owner's hand if they have more than an opponent."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } } }//Oath of Ghouls @@ -4372,8 +4501,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Ancient Runes deals ").append(damage).append(" damage to ").append(player); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } }// if @@ -4405,8 +4535,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Karma deals ").append(damage).append(" damage to ").append(player); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } }// if @@ -4433,7 +4564,8 @@ public class GameActionUtil { ability.setStackDescription(sb.toString()); if(player.getLife() <= 10) { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }// for }// upkeep_Convalescence() @@ -4466,7 +4598,8 @@ public class GameActionUtil { ability.setStackDescription(sb.toString()); if (player.getLife() <= 5){ - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }// for @@ -4497,7 +4630,8 @@ public class GameActionUtil { 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.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + }//for }//upkeep_Dega_Sanctuary() @@ -4525,7 +4659,8 @@ public class GameActionUtil { ability.setStackDescription(sb.toString()); if(damage > 0) { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }// for }// upkeep_Power_Surge() @@ -4550,8 +4685,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Felidar Sovereign - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// if }// upkeep_Felidar_Sovereign @@ -4577,8 +4713,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Battle of Wits - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// if }// upkeep_Battle_of_Wits @@ -4604,8 +4741,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Mortal Combat - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// if }// upkeep_Mortal Combat @@ -4635,8 +4773,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Epic Struggle - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// if }// upkeep_Epic_Struggle @@ -4661,8 +4800,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Helix Pinnacle - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// if }// upkeep_Helix_Pinnacle @@ -4687,8 +4827,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Near-Death Experience - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// if }// upkeep_Near_Death_Experience @@ -4713,8 +4854,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(list.get(0)).append(" - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// if }// upkeep_Test_of_Endurance @@ -4752,8 +4894,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Barren Glory - ").append(player).append(" wins the game"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// if }// upkeep_Barren_Glory @@ -4776,7 +4919,8 @@ public class GameActionUtil { ability.setStackDescription("Sleeper Agent deals 2 damage to its controller."); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//upkeep_Sleeper_Agent @@ -4806,7 +4950,9 @@ public class GameActionUtil { } }; ability.setStackDescription(c.getName()+" - choose a new number"); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//foreach(Card) }//upkeep_Shapeshifter @@ -4890,7 +5036,9 @@ public class GameActionUtil { } }; ability.setStackDescription(c.getName()+" - you may have this creature become a copy of target creature."); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//foreach(Card) }//upkeep_Vesuvan_Doppelganger_Keyword @@ -4942,7 +5090,9 @@ public class GameActionUtil { } }; ability.setStackDescription(source.getName()+" - "+player+" taps X artifacts, creatures or lands he or she controls."); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//foreach(wire) }//upkeep_Tangle_Wire() @@ -4975,7 +5125,8 @@ public class GameActionUtil { }; ability.setStackDescription("Pillory of the Sleepless - enchanted creature's controller loses 1 life."); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } } } @@ -5020,7 +5171,8 @@ public class GameActionUtil { sb.append("Greener Pastures - ").append(mostLands).append(" puts a 1/1 green Saproling token onto the battlefield."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }//else @@ -5080,8 +5232,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append(crd).append(" - sacrifice Masticore unless you discard a card."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }//upkeep_Masticore @@ -5127,8 +5280,9 @@ public class GameActionUtil { StringBuilder sb = new StringBuilder(); sb.append("Eldrazi Monument - ").append(player).append(" sacrifices a creature."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//upkeep_Eldrazi_Monument @@ -5157,8 +5311,9 @@ public class GameActionUtil { sb.append(blaze.get(i)).append(" - has a blaze counter and deals 1 damage to "); sb.append(player).append("."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } @@ -5272,7 +5427,8 @@ public class GameActionUtil { } numCreatures[0] = count; } - AllZone.Stack.add(devour); + AllZone.Stack.addSimultaneousStackEntry(devour); + } }; @@ -5289,7 +5445,8 @@ public class GameActionUtil { };// Ability ability.setStackDescription("Dragon Broodmother - put a 1/1 red and green Dragon token onto the battlefield."); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + }// for }// upkeep_Dragon_Broodmother() @@ -5352,8 +5509,9 @@ public class GameActionUtil { 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.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//end for } @@ -5503,7 +5661,9 @@ public class GameActionUtil { }; // ability ability.setStackDescription("Mirror-Sigil Sergeant - put a token onto the battlefield that's a copy of Mirror-Sigil Sergeant."); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } // for } //upkeep_Mirror_Sigil_Sergeant diff --git a/src/forge/MagicStack.java b/src/forge/MagicStack.java index 92ecb46b5c1..60276ec90a0 100644 --- a/src/forge/MagicStack.java +++ b/src/forge/MagicStack.java @@ -16,10 +16,13 @@ import forge.card.spellability.Ability_Triggered; import forge.card.spellability.SpellAbility; import forge.card.spellability.Spell_Permanent; import forge.card.spellability.Target; +import forge.gui.GuiUtils; import forge.gui.input.Input; import forge.gui.input.Input_PayManaCost_Ability; public class MagicStack extends MyObservable { + private ArrayList simultaneousStackEntryList = new ArrayList(); + private ArrayList stack = new ArrayList(); private ArrayList frozenStack = new ArrayList(); private boolean frozen = false; @@ -422,6 +425,7 @@ public class MagicStack extends MyObservable { runParams.put("Card", sp.getSourceCard()); AllZone.TriggerHandler.runTrigger("Cycled", runParams); } + } if(sp instanceof Spell_Permanent && sp.getSourceCard().getName().equals("Mana Vortex")) { @@ -851,4 +855,91 @@ public class MagicStack extends MyObservable { return ComputerCreatureSpellCount; } + public void addSimultaneousStackEntry(SpellAbility sa) + { + simultaneousStackEntryList.add(sa); + /* + *Debug output. + System.out.println("STO add! Size:" + simultaneousStackEntryList.size()); + */ + } + + public void chooseOrderOfSimultaneousStackEntryAll() + { + /* + *Debug output. + if(simultaneousStackEntryList.size() > 0) + { + System.out.println("STO run! Size:" + simultaneousStackEntryList.size()); + } + */ + chooseOrderOfSimultaneousStackEntry(AllZone.Phase.getPlayerTurn()); + chooseOrderOfSimultaneousStackEntry(AllZone.Phase.getPlayerTurn().getOpponent()); + } + + public void chooseOrderOfSimultaneousStackEntry(Player activePlayer) + { + if(simultaneousStackEntryList.size() == 0) + return; + + ArrayList activePlayerSAs = new ArrayList(); + for(int i=0;i 1) + { + SpellAbility next = (SpellAbility) GuiUtils.getChoice("Choose which spell or ability to put on the stack next.", activePlayerSAs.toArray()); + activePlayerSAs.remove(next); + + if(next.isTrigger()) + { + System.out.println("Stack order: AllZone.GameAction.playSpellAbility(next)"); + AllZone.GameAction.playSpellAbility(next); + } + else + { + System.out.println("Stack order: AllZone.Stack.add(next)"); + add(next); + } + } + + if(activePlayerSAs.get(0).isTrigger()) + AllZone.GameAction.playSpellAbility(activePlayerSAs.get(0)); + else + add(activePlayerSAs.get(0)); + //AllZone.GameAction.playSpellAbility(activePlayerSAs.get(0)); + } + } + } diff --git a/src/forge/Phase.java b/src/forge/Phase.java index 2f26f64696d..006a24acde9 100644 --- a/src/forge/Phase.java +++ b/src/forge/Phase.java @@ -293,6 +293,8 @@ public class Phase extends MyObservable AllZone.TriggerHandler.runTrigger("Phase", runParams); } + + //This line fixes Combat Damage triggers not going off when they should AllZone.Stack.unfreezeStack(); @@ -377,6 +379,8 @@ public class Phase extends MyObservable AllZone.Phase.setNeedToNextPhase(false); AllZone.Phase.nextPhase(); } + + AllZone.Stack.chooseOrderOfSimultaneousStackEntryAll(); } private Player handleNextTurn() { @@ -513,6 +517,7 @@ public class Phase extends MyObservable // pass the priority to other player setPriorityPlayer(actingPlayer.getOpponent()); AllZone.InputControl.resetInput(); + AllZone.Stack.chooseOrderOfSimultaneousStackEntryAll(); } else{ if (AllZone.Stack.size() == 0){ @@ -523,6 +528,7 @@ public class Phase extends MyObservable else{ AllZone.Stack.resolveStack(); } + AllZone.Stack.chooseOrderOfSimultaneousStackEntryAll(); } } diff --git a/src/forge/PlayerZone_ComesIntoPlay.java b/src/forge/PlayerZone_ComesIntoPlay.java index 3965744f845..96cbe2872c8 100644 --- a/src/forge/PlayerZone_ComesIntoPlay.java +++ b/src/forge/PlayerZone_ComesIntoPlay.java @@ -158,8 +158,9 @@ public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone { sb.append(source).append(" - tap all lands "); sb.append(tisLand.getController()).append(" controls."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } CardList les = AllZoneUtil.getPlayerCardsInPlay(c.getOwner().getOpponent(), "Land Equilibrium"); @@ -181,7 +182,8 @@ public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone { CardList oLands = AllZoneUtil.getPlayerLandsInPlay(lesLand.getOwner().getOpponent()); //(pLands - 1) because this land is in play, and the ability is before it is in play if(oLands.size() <= (pLands.size() - 1)) { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } } @@ -238,10 +240,13 @@ public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone { sb.append("return Sword of the Meek from your graveyard to the battlefield, then attach it to that creature."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } } - + + + /* for (String effect : AllZone.StateBasedEffects.getStateBasedMap().keySet() ) { Command com = GameActionUtil.commands.get(effect); @@ -313,6 +318,8 @@ public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone { Command com = GameActionUtil.commands.get(effect); com.execute(); } + + } public void setTrigger(boolean b) { diff --git a/src/forge/card/abilityFactory/AbilityFactory_GainControl.java b/src/forge/card/abilityFactory/AbilityFactory_GainControl.java index dcd5a329a25..b2b11580637 100644 --- a/src/forge/card/abilityFactory/AbilityFactory_GainControl.java +++ b/src/forge/card/abilityFactory/AbilityFactory_GainControl.java @@ -341,7 +341,7 @@ public class AbilityFactory_GainControl { if(bNoRegen) sb.append(" It can't be regenerated."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); } }; diff --git a/src/forge/card/cardFactory/CardFactory.java b/src/forge/card/cardFactory/CardFactory.java index 96aa02d1580..3897ba9619e 100644 --- a/src/forge/card/cardFactory/CardFactory.java +++ b/src/forge/card/cardFactory/CardFactory.java @@ -557,7 +557,8 @@ public class CardFactory implements NewConstants { sb.append(card.getController()).append(" loses "+num+" life"); etbLoseLifeAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(etbLoseLifeAbility); + AllZone.Stack.addSimultaneousStackEntry(etbLoseLifeAbility); + } }; card.addComesIntoPlayCommand(etbLoseLife); @@ -865,7 +866,8 @@ public class CardFactory implements NewConstants { } numCreatures[0] = count; } - AllZone.Stack.add(devour); + AllZone.Stack.addSimultaneousStackEntry(devour); + } }; @@ -924,7 +926,8 @@ public class CardFactory implements NewConstants { if (ability.getTargetCard() != null){ ability.setStackDescription("Put " + card.getCounters(Counters.P1P1) + " +1/+1 counter/s from " + card + " on " + ability.getTargetCard()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } } } @@ -1126,7 +1129,8 @@ public class CardFactory implements NewConstants { sb.append("When ").append(card.getName()).append(" enters the battlefield, choose a creature type."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -1210,7 +1214,9 @@ public class CardFactory implements NewConstants { public void execute() { ability.setStackDescription("As Sarpadian Empires, Vol. VII enters the battlefield, choose white Citizen, blue Camarid, black Thrull, red Goblin, or green Saproling."); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.setText("As Sarpadian Empires, Vol. VII enters the battlefield, choose white Citizen, blue Camarid, black Thrull, red Goblin, or green Saproling.\r\n" @@ -1273,8 +1279,9 @@ public class CardFactory implements NewConstants { StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - returning creature to the battlefield"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() };//Command @@ -1385,7 +1392,9 @@ public class CardFactory implements NewConstants { Card c = (Card)o; necrogen.setTargetCard(c); once = true; - AllZone.Stack.add(necrogen); + + AllZone.Stack.addSimultaneousStackEntry(necrogen); + } } stop(); @@ -1474,7 +1483,9 @@ public class CardFactory implements NewConstants { AllZone.GameAction.exile(c); AllZone.GameAction.exile(c2); once = true; - AllZone.Stack.add(nightSoil); + + AllZone.Stack.addSimultaneousStackEntry(nightSoil); + } } } @@ -1811,7 +1822,8 @@ public class CardFactory implements NewConstants { public void execute() { ability.setStackDescription("If Mox Diamond would enter the battlefield, you may discard a land card instead. If you do, put Mox Diamond onto the battlefield. If you don't, put it into its owner's graveyard."); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; SpellAbility spell = new Spell_Permanent(card) { @@ -2151,8 +2163,9 @@ public class CardFactory implements NewConstants { sb.append("Imprint - ").append(card.getController()); sb.append(" may exile an instant card with converted mana cost 2 or less from their hand."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; @@ -2458,7 +2471,8 @@ public class CardFactory implements NewConstants { private static final long serialVersionUID = -6417019967914398902L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } };//Command @@ -2546,8 +2560,9 @@ public class CardFactory implements NewConstants { StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - choose a creature type. Creatures of that type do not untap during their controller's untap step."); comesIntoPlayAbility.setStackDescription(sb.toString()); - - AllZone.Stack.add(comesIntoPlayAbility); + + AllZone.Stack.addSimultaneousStackEntry(comesIntoPlayAbility); + } }; @@ -2810,7 +2825,8 @@ public class CardFactory implements NewConstants { private static final long serialVersionUID = 2266471224097876143L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; @@ -2879,8 +2895,9 @@ public class CardFactory implements NewConstants { StringBuilder sb = new StringBuilder(); sb.append("As ").append(card.getName()).append(" enters the battlefield, pay any amount of life."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -3147,8 +3164,9 @@ public class CardFactory implements NewConstants { sb.append("exile all creatures you control. "); sb.append("Then put that many 5/5 red Dragon creature tokens with flying onto the battlefield."); exileAll.setStackDescription(sb.toString()); - - AllZone.Stack.add(exileAll); + + AllZone.Stack.addSimultaneousStackEntry(exileAll); + } }; @@ -3176,8 +3194,9 @@ public class CardFactory implements NewConstants { sb.append("sacrifice all Dragons you control. "); sb.append("Then return the exiled cards to the battlefield under your control."); returnAll.setStackDescription(sb.toString()); - - AllZone.Stack.add(returnAll); + + AllZone.Stack.addSimultaneousStackEntry(returnAll); + } }; @@ -3205,8 +3224,9 @@ public class CardFactory implements NewConstants { sb.append(cardName).append(" - ").append(card.getController()); sb.append(" loses life equal to his or her life total."); loseAllLife.setStackDescription(sb.toString()); - - AllZone.Stack.add(loseAllLife); + + AllZone.Stack.addSimultaneousStackEntry(loseAllLife); + } }; @@ -3226,8 +3246,9 @@ public class CardFactory implements NewConstants { sb.append(cardName).append(" - ").append(card.getController()); sb.append("loses the game."); loseGame.setStackDescription(sb.toString()); - - AllZone.Stack.add(loseGame); + + AllZone.Stack.addSimultaneousStackEntry(loseGame); + } }; diff --git a/src/forge/card/cardFactory/CardFactoryUtil.java b/src/forge/card/cardFactory/CardFactoryUtil.java index d88c63c4667..adcbf3b948c 100644 --- a/src/forge/card/cardFactory/CardFactoryUtil.java +++ b/src/forge/card/cardFactory/CardFactoryUtil.java @@ -1431,7 +1431,7 @@ public class CardFactoryUtil { Object o = GuiUtils.getChoiceOptional("Select a card", sameType.toArray()); if(o != null) { //ability.setTargetCard((Card)o); - //AllZone.Stack.add(ability); + sourceCard.getController().discard(sourceCard, this); Card c1 = (Card) o; AllZone.GameAction.moveToHand(c1); @@ -1505,7 +1505,7 @@ public class CardFactoryUtil { Object o = GuiUtils.getChoiceOptional("Select a card", sameCost.toArray()); if(o != null) { //ability.setTargetCard((Card)o); - //AllZone.Stack.add(ability); + sourceCard.getController().discard(sourceCard, this); Card c1 = (Card) o; @@ -4417,7 +4417,9 @@ public class CardFactoryUtil { } }; ability.setStackDescription("Fastbond - Deals 1 damage to you."); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } @@ -4430,7 +4432,9 @@ public class CardFactoryUtil { } }; ability.setStackDescription(city.getName()+" - sacrifice "+city.getName()); - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } } diff --git a/src/forge/card/cardFactory/CardFactory_Auras.java b/src/forge/card/cardFactory/CardFactory_Auras.java index f5d63ba416c..d728ad5a62a 100644 --- a/src/forge/card/cardFactory/CardFactory_Auras.java +++ b/src/forge/card/cardFactory/CardFactory_Auras.java @@ -1521,7 +1521,8 @@ class CardFactory_Auras { private static final long serialVersionUID = 3595188622377350327L; public void execute() { - AllZone.Stack.add(attach); + AllZone.Stack.addSimultaneousStackEntry(attach); + } }; @@ -1548,7 +1549,8 @@ class CardFactory_Auras { PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, card.getController()); if(AllZone.GameAction.isCardInZone(c, play)) - AllZone.Stack.add(detach); + AllZone.Stack.addSimultaneousStackEntry(detach); + } }; // Do not remove SpellAbilities created by AbilityFactory or Keywords. @@ -2242,7 +2244,9 @@ class CardFactory_Auras { StringBuilder sb = new StringBuilder(); sb.append(card.getController()).append(" untaps up to 5 lands."); untapAbility.setStackDescription(sb.toString()); - AllZone.Stack.add(untapAbility); + + AllZone.Stack.addSimultaneousStackEntry(untapAbility); + } }; if (optionUnTapLands) { diff --git a/src/forge/card/cardFactory/CardFactory_Creatures.java b/src/forge/card/cardFactory/CardFactory_Creatures.java index ad415289099..c3383c33b33 100644 --- a/src/forge/card/cardFactory/CardFactory_Creatures.java +++ b/src/forge/card/cardFactory/CardFactory_Creatures.java @@ -189,7 +189,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = 8485080996453793968L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } };//Command ability.setStackDescription("Caller of the Claw - Put a 2/2 green Bear creature token onto the battlefield for each nontoken creature put into your graveyard from play this turn."); @@ -456,7 +457,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = 2856638426932227407L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; @@ -507,8 +509,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - choose: 3/3, 2/2 flying, 1/6 defender"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -529,8 +532,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - ").append(card.getOwner()).append(" creatures have Trample."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addDestroyCommand(destroy); @@ -552,8 +556,9 @@ public class CardFactory_Creatures { sb.append(card.getName()).append(" - ").append(card.getOwner()); sb.append(" creatures have Swampwalk."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addDestroyCommand(destroy); @@ -688,8 +693,9 @@ public class CardFactory_Creatures { sb.append(card.getName()).append(" - ").append(card.getOwner()); sb.append(" creatures have Haste."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addDestroyCommand(destroy); @@ -711,8 +717,9 @@ public class CardFactory_Creatures { sb.append(card.getName()).append(" - ").append(card.getOwner()); sb.append(" creatures have First Strike."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addDestroyCommand(destroy); @@ -734,8 +741,9 @@ public class CardFactory_Creatures { sb.append(card.getName()).append(" - ").append(card.getOwner()); sb.append(" creatures have Flying."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addDestroyCommand(destroy); @@ -828,8 +836,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getController()).append(" sacrifices Drekavac unless he discards a noncreature card"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; @@ -902,8 +911,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getController()).append(" - discards at random or sacrifices ").append(cardName); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -980,7 +990,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = 4757054648163014149L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; StringBuilder sb = new StringBuilder(); @@ -1007,8 +1018,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = -3934471871041458847L; public void execute() { - AllZone.Stack.add(ability); - + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() }; card.addComesIntoPlayCommand(intoPlay); @@ -1091,7 +1102,8 @@ public class CardFactory_Creatures { if(o != null)//should never happen, but just in case { ability.setTargetCard((Card) o); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//else }//execute() @@ -1165,8 +1177,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getController()).append(" untaps up to 5 lands."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -1227,8 +1240,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getController()).append(" untaps up to 7 lands."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -1289,8 +1303,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getController()).append(" untaps up to 7 lands."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -1371,8 +1386,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getController()).append(" untaps up to 2 lands."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -1407,8 +1423,9 @@ public class CardFactory_Creatures { sb.append(card.getController()); sb.append(" shuffles the cards from his hand into his library, then draws that many cards."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability ); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -1438,8 +1455,9 @@ public class CardFactory_Creatures { sb.append(card.getController().getOpponent()); sb.append(" gains control of all other permanents you control"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -1512,7 +1530,8 @@ public class CardFactory_Creatures { if(computer.size() != 0) { target = computer.get(0); abilityComes.setTargetCard(target); - AllZone.Stack.add(abilityComes); + AllZone.Stack.addSimultaneousStackEntry(abilityComes); + } else AllZone.GameAction.sacrifice(card); @@ -1545,8 +1564,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - returning creature to the battlefield"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() };//Command @@ -1663,7 +1683,8 @@ public class CardFactory_Creatures { //computer chooses target in Command destroy if(con.equals(AllZone.ComputerPlayer)) ability.setTargetPlayer(AllZone.HumanPlayer); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() }; card.addDestroyCommand(destroy); @@ -1707,8 +1728,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append(opponent).append(" discards cards"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() }; card.addDestroyCommand(destroy); @@ -1753,8 +1775,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append(card.getController()).append(" draws cards"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() }; @@ -1799,8 +1822,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append(card.getController()).append(" gains life"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() }; @@ -1846,8 +1870,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card).append(" - ").append(card.getController()).append(" puts tokens onto the battlefield"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() }; card.addDestroyCommand(destroy); @@ -2447,7 +2472,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = -2433442359225521472L; public void execute() { - AllZone.Stack.add(new Ability(card, "0", "Adarkar Valkyrie - Return " + target[0] + " from graveyard to the battlefield") { + + AllZone.Stack.addSimultaneousStackEntry(new Ability(card, "0", "Adarkar Valkyrie - Return " + target[0] + " from graveyard to the battlefield") { @Override public void resolve() { PlayerZone grave = AllZone.getZone(target[0]); @@ -2887,7 +2913,8 @@ public class CardFactory_Creatures { else if(ability.canPlayAI()) { ability.chooseTargetAI(); //need to add this to the stack - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//execute() @@ -3078,7 +3105,8 @@ public class CardFactory_Creatures { public void execute() { AllZone.GameAction.sacrifice(card); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } })); }//*************** END ************ END ************************** @@ -3155,7 +3183,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = 6667896040611028600L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }); @@ -3399,7 +3428,8 @@ public class CardFactory_Creatures { sb.append("Mystic Snake counters ").append(AllZone.Stack.peek().getSourceCard().getName()); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } } }; @@ -4383,9 +4413,11 @@ public class CardFactory_Creatures { if (card.getName().equals("Lost Auramancers") && card.getCounters(Counters.TIME) <= 0) { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } else if (card.getName().equals("Academy Rector")) { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }// execute() @@ -4459,7 +4491,8 @@ public class CardFactory_Creatures { ButtonUtil.disableAll(); } else if(card.getController().equals(AllZone.ComputerPlayer)) { ability.setTargetPlayer(AllZone.HumanPlayer); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//execute() };//Command @@ -4556,7 +4589,8 @@ public class CardFactory_Creatures { else //computer { abilityComes.setTargetPlayer(AllZone.HumanPlayer); - AllZone.Stack.add(abilityComes); + AllZone.Stack.addSimultaneousStackEntry(abilityComes); + }//else }//execute() };//CommandComes @@ -4578,8 +4612,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append("Laquatus's Champion - ").append(abilityComes.getTargetPlayer()).append(" regains 6 life."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute() };//Command @@ -4641,7 +4676,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = 8485080996453793968L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } };//Command ability.setStackDescription("As Meddling Mage enters the battlefield, name a nonland card."); @@ -4810,7 +4846,8 @@ public class CardFactory_Creatures { } }; ability.setStackDescription(toString() + " - you may put a token that's a copy of " + getName() + " onto the battlefield."); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + for(Entry entry : m.entrySet()) { this.addDamage(entry.getValue(), entry.getKey()); @@ -4904,7 +4941,8 @@ public class CardFactory_Creatures { public void execute() { ability.setStackDescription("Singe-Mind Ogre - target player reveals a card at random from " + "his or her hand, then loses life equal to that card's converted mana cost."); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(intoPlay); @@ -4987,7 +5025,8 @@ public class CardFactory_Creatures { public void execute() { ability.setStackDescription("Kinsbaile Borderguard enters the battlefield with a +1/+1 counter on it for each other Kithkin you control."); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; @@ -5011,7 +5050,8 @@ public class CardFactory_Creatures { public void execute() { ability2.setStackDescription("When Kinsbaile Borderguard is put into a graveyard from play, put a 1/1 white " + "Kithkin Soldier creature token onto the battlefield for each counter on it."); - AllZone.Stack.add(ability2); + AllZone.Stack.addSimultaneousStackEntry(ability2); + } }; @@ -5038,8 +5078,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - gain 2 life for each age counter on it."); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + } };//command @@ -5093,7 +5134,8 @@ public class CardFactory_Creatures { public void execute() { if(card.isKicked()) { ability.setStackDescription("Kavu Titan gets 3 +1/+1 counters and gains trample."); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//execute() };//CommandComes @@ -5161,7 +5203,8 @@ public class CardFactory_Creatures { else //computer { ability.setStackDescription("Gatekeeper of Malakir - targeting Human"); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + }//else } }//execute() @@ -5192,7 +5235,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = 4245563898487609274L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(comesIntoPlay); @@ -5232,7 +5276,8 @@ public class CardFactory_Creatures { sb.append(card.getName()).append(" - Add 2 Level counters to each creature you control with Level up."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; card.addComesIntoPlayCommand(addLevelCounters); @@ -5295,8 +5340,9 @@ public class CardFactory_Creatures { StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - chosen type gets +2/+2 and Trample until EOT"); ability.setStackDescription(sb.toString()); - - AllZone.Stack.add(ability); + + AllZone.Stack.addSimultaneousStackEntry(ability); + }//execute };//command @@ -5326,7 +5372,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = -3734151854295L; public void execute() { - AllZone.Stack.add(intoPlay); + AllZone.Stack.addSimultaneousStackEntry(intoPlay); + } }; @@ -5620,7 +5667,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = 931101364538995898L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; @@ -5802,7 +5850,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = -4300804642226899861L; public void execute() { - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }; @@ -6002,7 +6051,8 @@ public class CardFactory_Creatures { else if(list.size() != 0) { Card target = CardFactoryUtil.AI_getBestCreature(list); ability.setTargetCard(target); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); + } }//execute() }; @@ -6082,7 +6132,8 @@ public class CardFactory_Creatures { public void execute() { sacOrSac.setStackDescription("When "+cardName+" enters the battlefield, sacrifice it unless you sacrifice any number of creatures with total power 12 or greater."); - AllZone.Stack.add(sacOrSac); + AllZone.Stack.addSimultaneousStackEntry(sacOrSac); + } }; @@ -6119,7 +6170,8 @@ public class CardFactory_Creatures { //Slight hack if the cloner copies a card with triggers AllZone.TriggerHandler.removeAllFromCard(cloned[0]); - AllZone.Stack.add(copyBack); + AllZone.Stack.addSimultaneousStackEntry(copyBack); + } }; @@ -6274,7 +6326,8 @@ public class CardFactory_Creatures { private static final long serialVersionUID = 911163814565333484L; public void execute() { - AllZone.Stack.add(toPlay); + AllZone.Stack.addSimultaneousStackEntry(toPlay); + } }; diff --git a/src/forge/card/cardFactory/CardFactory_Lands.java b/src/forge/card/cardFactory/CardFactory_Lands.java index d78055d7c4a..e98b24f735e 100644 --- a/src/forge/card/cardFactory/CardFactory_Lands.java +++ b/src/forge/card/cardFactory/CardFactory_Lands.java @@ -244,7 +244,8 @@ class CardFactory_Lands { if(card.getController() == AllZone.HumanPlayer) { AllZone.InputControl.setInput(CardFactoryUtil.input_targetSpecific(a[0], creats, "Select target creature you control", false, false)); } else { - AllZone.Stack.add(a[0]); + AllZone.Stack.addSimultaneousStackEntry(a[0]); + } } }; diff --git a/src/forge/card/spellability/Ability_Mana.java b/src/forge/card/spellability/Ability_Mana.java index 68a0f7fed79..b5679d34422 100644 --- a/src/forge/card/spellability/Ability_Mana.java +++ b/src/forge/card/spellability/Ability_Mana.java @@ -111,7 +111,7 @@ abstract public class Ability_Mana extends Ability_Activated implements java.io. if (source.getName().equals("Forbidden Orchard")) { this.undoable = false; - AllZone.Stack.add(CardFactoryUtil.getForbiddenOrchardAbility(source, getActivatingPlayer().getOpponent())); + AllZone.Stack.addSimultaneousStackEntry(CardFactoryUtil.getForbiddenOrchardAbility(source, getActivatingPlayer().getOpponent())); } if(source.getType().contains("Mountain") && AllZoneUtil.isCardInPlay("Gauntlet of Might")) { @@ -167,6 +167,8 @@ abstract public class Ability_Mana extends Ability_Activated implements java.io. runParams.put("Ability_Mana", this); runParams.put("Produced", produced); AllZone.TriggerHandler.runTrigger("TapsForMana", runParams); + + }//end produceMana(String) diff --git a/src/forge/card/spellability/SpellAbility.java b/src/forge/card/spellability/SpellAbility.java index db4adde5c6d..79e12e581cb 100644 --- a/src/forge/card/spellability/SpellAbility.java +++ b/src/forge/card/spellability/SpellAbility.java @@ -40,6 +40,7 @@ public abstract class SpellAbility { private boolean spell; private boolean trigger = false; + private boolean mandatory = false; private boolean tapAbility; private boolean untapAbility; @@ -102,7 +103,7 @@ public abstract class SpellAbility { public boolean canPlayAI() { return true; } - + // This should be overridden by ALL AFs public boolean doTrigger(boolean mandatory){ return false; @@ -387,6 +388,8 @@ public abstract class SpellAbility { public void setStackDescription(String s) { stackDescription = s; + if(description == "") + description = s; } public String getStackDescription() { @@ -432,6 +435,7 @@ public abstract class SpellAbility { while(node != null){ if (node != this) sb.append(" "); + sb.append(node.getDescription().replace("CARDNAME", node.getSourceCard().getName())); node = node.getSubAbility(); @@ -589,4 +593,12 @@ public abstract class SpellAbility { public boolean isTrigger() { return trigger; } + + public void setMandatory(boolean mand) { + this.mandatory = mand; + } + + public boolean isMandatory() { + return mandatory; + } } diff --git a/src/forge/card/spellability/Spell_Permanent.java b/src/forge/card/spellability/Spell_Permanent.java index 231b5e9271e..b92df1dbf3b 100644 --- a/src/forge/card/spellability/Spell_Permanent.java +++ b/src/forge/card/spellability/Spell_Permanent.java @@ -79,7 +79,7 @@ public class Spell_Permanent extends Spell { if(computer.size() != 0) { target = computer.get(0); championAbilityComes.setTargetCard(target); - AllZone.Stack.add(championAbilityComes); + AllZone.Stack.addSimultaneousStackEntry(championAbilityComes); if(getSourceCard().getName().equals("Mistbind Clique")) { //TODO this needs to target CardList list = AllZoneUtil.getPlayerLandsInPlay(AllZone.HumanPlayer); @@ -117,7 +117,7 @@ public class Spell_Permanent extends Spell { sb.append(getSourceCard().getName()).append(" - returning card to battlefield."); ability.setStackDescription(sb.toString()); - AllZone.Stack.add(ability); + AllZone.Stack.addSimultaneousStackEntry(ability); }//execute() };//championCommandLeavesPlay diff --git a/src/forge/card/trigger/TriggerHandler.java b/src/forge/card/trigger/TriggerHandler.java index 231135079d6..2be56090dc4 100644 --- a/src/forge/card/trigger/TriggerHandler.java +++ b/src/forge/card/trigger/TriggerHandler.java @@ -283,7 +283,6 @@ public class TriggerHandler { } } } - } //Checks if the conditions are right for a single trigger to go off, and runs it if so. @@ -948,7 +947,9 @@ public class TriggerHandler { } }; wrapperAbility.setTrigger(true); - + wrapperAbility.setMandatory(isMandatory); + wrapperAbility.setDescription(wrapperAbility.getStackDescription()); + /* if(host.getController().isHuman()) { AllZone.GameAction.playSpellAbility(wrapperAbility); @@ -958,7 +959,8 @@ public class TriggerHandler { wrapperAbility.doTrigger(isMandatory); ComputerUtil.playStack(wrapperAbility); } - + */ + AllZone.Stack.addSimultaneousStackEntry(wrapperAbility); return true; }