diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/StormTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/StormTest.java index de7dbf4862..fbefd4b006 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/StormTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/StormTest.java @@ -204,7 +204,7 @@ public class StormTest extends CardTestPlayerBase { * */ @Test - public void testStormAndFlshback() { + public void testStormAndFlashback() { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8); addCard(Zone.BATTLEFIELD, playerA, "Island", 1); // Geistflame deals 1 damage to target creature or player. @@ -231,4 +231,66 @@ public class StormTest extends CardTestPlayerBase { assertLife(playerB, 12); // 3 from the Geistflame + 5 from Grapeshot } + /* + * I cast Wheel of Fortune. (1st) + * I cast Mox Emerald. (2nd) + * I cast Turnabout. (3rd) + * I cast Yawgmoth's Will. (4th) + * I cast Palinchron from graveyard. (5th) + * I cast Mind's Desire from graveyard. Storm makes 2 + * copies (instead of 5). (6th) I cast Turnabout from graveyard. (7th) I + * cast Golgari Signet from exile. (8th) I cast Empty the Warrens. Storm + * makes 5 copies (instead of 8). (9th) + * + */ + @Test + public void testStormYawgmothsWill() { + + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.BATTLEFIELD, playerA, "Island", 10); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + // Each player discards his or her hand, + // then draws seven cards. + addCard(Zone.HAND, playerA, "Wheel of Fortune", 1); // {2}{R} + addCard(Zone.LIBRARY, playerA, "Mox Emerald", 1); + // Choose artifact, creature, or land. Tap all untapped permanents of the chosen type target player controls, or untap all tapped permanents of that type that player controls. + addCard(Zone.LIBRARY, playerA, "Turnabout", 1); // {2}{U}{U} + + // Until end of turn, you may play cards from your graveyard. + // If a card would be put into your graveyard from anywhere this turn, exile that card instead. + addCard(Zone.LIBRARY, playerA, "Yawgmoth's Will", 1); // {2}{B} + skipInitShuffling(); + + // Flying + // When Palinchron enters the battlefield, untap up to seven lands. + // {2}{U}{U}: Return Palinchron to its owner's hand. + addCard(Zone.HAND, playerA, "Palinchron", 1); // {5}{U}{U} + // Shuffle your library. Then exile the top card of your library. Until end of turn, you may play that card without paying its mana cost. + // Storm + addCard(Zone.HAND, playerA, "Mind's Desire", 1); // {4}{U}{U} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wheel of Fortune"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mox Emerald"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Turnabout"); + setChoice(playerA, "Land"); + setChoice(playerA, "Untap"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yawgmoth's Will"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Palinchron"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mind's Desire"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Wheel of Fortune", 1); + assertPermanentCount(playerA, "Mox Emerald", 1); + assertGraveyardCount(playerA, "Turnabout", 1); + assertPermanentCount(playerA, "Palinchron", 1); + + assertExileCount("Yawgmoth's Will", 1); + assertExileCount("Mind's Desire", 1); + + assertExileCount(playerA, 8); // 6 from Mind's Desire and the Desire and the Yawgmoth's Will + + } + } diff --git a/Mage/src/mage/abilities/keyword/ForecastAbility.java b/Mage/src/mage/abilities/keyword/ForecastAbility.java index eba53827b6..43ba532aae 100644 --- a/Mage/src/mage/abilities/keyword/ForecastAbility.java +++ b/Mage/src/mage/abilities/keyword/ForecastAbility.java @@ -70,6 +70,7 @@ public class ForecastAbility extends LimitedTimesPerTurnActivatedAbility { @Override public boolean canActivate(UUID playerId, Game game) { // May be activated only during the upkeep step of the card's owner + // Because it can only be activated from a players hand it should be ok to check here with controllerId instead of card.getOwnerId(). if (!game.getActivePlayerId().equals(controllerId) || !PhaseStep.UPKEEP.equals(game.getStep().getType())) { return false; } diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 4e49903dc5..ff69876d5b 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -154,6 +154,11 @@ public interface Game extends MageItem, Serializable { boolean canPlaySorcery(UUID playerId); + /** + * Id of the player the current turn it is. + * + * @return + */ UUID getActivePlayerId(); UUID getPriorityPlayerId(); diff --git a/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java b/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java index 1b22784e90..d78f382b52 100644 --- a/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java +++ b/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java @@ -1,31 +1,30 @@ /* -* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without modification, are -* permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this list of -* conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, this list -* of conditions and the following disclaimer in the documentation and/or other materials -* provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR -* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* The views and conclusions contained in the software and documentation are those of the -* authors and should not be interpreted as representing official policies, either expressed -* or implied, of BetaSteward_at_googlemail.com. -*/ - + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ package mage.watchers.common; import java.util.ArrayList; @@ -41,9 +40,9 @@ import mage.game.events.GameEvent; import mage.watchers.Watcher; /** -* -* @author nantuko, BetaSteward_at_googlemail.com -*/ + * + * @author nantuko, BetaSteward_at_googlemail.com + */ public class CastSpellLastTurnWatcher extends Watcher { private final Map<UUID, Integer> amountOfSpellsCastOnPrevTurn = new HashMap<>(); @@ -51,83 +50,84 @@ public class CastSpellLastTurnWatcher extends Watcher { private final List<MageObjectReference> spellsCastThisTurnInOrder = new ArrayList<>(); public CastSpellLastTurnWatcher() { - super("CastSpellLastTurnWatcher", WatcherScope.GAME); + super("CastSpellLastTurnWatcher", WatcherScope.GAME); } public CastSpellLastTurnWatcher(final CastSpellLastTurnWatcher watcher) { - super(watcher); - for (Entry<UUID, Integer> entry: watcher.amountOfSpellsCastOnCurrentTurn.entrySet()) { - amountOfSpellsCastOnCurrentTurn.put(entry.getKey(), entry.getValue()); - } - for (Entry<UUID, Integer> entry: watcher.amountOfSpellsCastOnPrevTurn.entrySet()) { - amountOfSpellsCastOnPrevTurn.put(entry.getKey(), entry.getValue()); - } + super(watcher); + for (Entry<UUID, Integer> entry : watcher.amountOfSpellsCastOnCurrentTurn.entrySet()) { + amountOfSpellsCastOnCurrentTurn.put(entry.getKey(), entry.getValue()); + } + for (Entry<UUID, Integer> entry : watcher.amountOfSpellsCastOnPrevTurn.entrySet()) { + amountOfSpellsCastOnPrevTurn.put(entry.getKey(), entry.getValue()); + } + this.spellsCastThisTurnInOrder.addAll(watcher.spellsCastThisTurnInOrder); } @Override public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.SPELL_CAST) { - spellsCastThisTurnInOrder.add(new MageObjectReference(event.getTargetId(), game)); - UUID playerId = event.getPlayerId(); - if (playerId != null) { - Integer amount = amountOfSpellsCastOnCurrentTurn.get(playerId); - if (amount == null) { - amount = 1; - } else { - amount = amount+1; - } - amountOfSpellsCastOnCurrentTurn.put(playerId, amount); - } - } + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + spellsCastThisTurnInOrder.add(new MageObjectReference(event.getTargetId(), game)); + UUID playerId = event.getPlayerId(); + if (playerId != null) { + Integer amount = amountOfSpellsCastOnCurrentTurn.get(playerId); + if (amount == null) { + amount = 1; + } else { + amount = amount + 1; + } + amountOfSpellsCastOnCurrentTurn.put(playerId, amount); + } + } } @Override public void reset() { - amountOfSpellsCastOnPrevTurn.clear(); - amountOfSpellsCastOnPrevTurn.putAll(amountOfSpellsCastOnCurrentTurn); - amountOfSpellsCastOnCurrentTurn.clear(); - spellsCastThisTurnInOrder.clear(); + amountOfSpellsCastOnPrevTurn.clear(); + amountOfSpellsCastOnPrevTurn.putAll(amountOfSpellsCastOnCurrentTurn); + amountOfSpellsCastOnCurrentTurn.clear(); + spellsCastThisTurnInOrder.clear(); } public Map<UUID, Integer> getAmountOfSpellsCastOnPrevTurn() { - return amountOfSpellsCastOnPrevTurn; + return amountOfSpellsCastOnPrevTurn; } public Map<UUID, Integer> getAmountOfSpellsCastOnCurrentTurn() { - return amountOfSpellsCastOnCurrentTurn; + return amountOfSpellsCastOnCurrentTurn; } - + public int getAmountOfSpellsAllPlayersCastOnCurrentTurn() { int totalAmount = 0; - for(Integer amount: amountOfSpellsCastOnCurrentTurn.values()) { + for (Integer amount : amountOfSpellsCastOnCurrentTurn.values()) { totalAmount += amount; } return totalAmount; } public int getAmountOfSpellsPlayerCastOnCurrentTurn(UUID playerId) { - Integer value = amountOfSpellsCastOnCurrentTurn.get(playerId); - if (value != null) { - return value; - } else { - return 0; - } + Integer value = amountOfSpellsCastOnCurrentTurn.get(playerId); + if (value != null) { + return value; + } else { + return 0; + } } public int getSpellOrder(MageObjectReference spell, Game game) { - int index = 0; - for (MageObjectReference mor : spellsCastThisTurnInOrder) { - index++; - if (mor.equals(spell)) { - return index; - } - } - return 0; + int index = 0; + for (MageObjectReference mor : spellsCastThisTurnInOrder) { + index++; + if (mor.equals(spell)) { + return index; + } + } + return 0; } @Override public CastSpellLastTurnWatcher copy() { - return new CastSpellLastTurnWatcher(this); + return new CastSpellLastTurnWatcher(this); } }