diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java new file mode 100644 index 0000000000..02d57293aa --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java @@ -0,0 +1,66 @@ +package org.mage.test.cards.continuous; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestCommander4Players; + +/** + * @author JayDi85 + */ +public class CommandersCastTest extends CardTestCommander4Players { + + // Player order: A -> D -> C -> B + + @Test + public void test_CastToBattlefieldOneTime() { + addCard(Zone.COMMAND, playerA, "Balduvian Bears", 1); // {1}{G}, 2/2, commander + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + showCommand("commanders", 1, PhaseStep.PRECOMBAT_MAIN, playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears"); + + setStopAt(1, PhaseStep.END_TURN); + setStrictChooseMode(true); + execute(); + assertAllCommandsUsed(); + + assertCommandZoneCount(playerA, "Balduvian Bears", 0); + assertPermanentCount(playerA, "Balduvian Bears", 1); + } + + @Test + public void test_CastToBattlefieldTwoTimes() { + // Player order: A -> D -> C -> B + addCard(Zone.COMMAND, playerA, "Balduvian Bears", 1); // {1}{G}, 2/2, commander + addCard(Zone.BATTLEFIELD, playerA, "Forest", 6); // 2 + 4 + // + addCard(Zone.HAND, playerB, "Lightning Bolt", 1); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + + // cast 1 + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkPermanentCount("after cast 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1); + + // destroy commander + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Balduvian Bears"); + setChoice(playerA, "Yes"); // put to command zone again + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkPermanentCount("after destroy", 1, PhaseStep.PRECOMBAT_MAIN, playerB, playerA, "Balduvian Bears", 0); + + // cast 2 + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears"); + waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN); + checkPermanentCount("after cast 2", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears", 1); + + setStopAt(1, PhaseStep.END_TURN); + setStrictChooseMode(true); + execute(); + assertAllCommandsUsed(); + + assertCommandZoneCount(playerA, "Balduvian Bears", 0); + assertPermanentCount(playerA, "Balduvian Bears", 1); + assertGraveyardCount(playerB, "Lightning Bolt", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index ebd8da1cd0..e0e3b0006b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -15,6 +15,7 @@ import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ManaOptions; import mage.cards.Card; import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.cards.decks.Deck; import mage.choices.Choice; import mage.constants.*; @@ -746,6 +747,16 @@ public class TestPlayer implements Player { wasProccessed = true; } + // show command + if (params[0].equals(SHOW_COMMAND_COMMAND) && params.length == 1) { + printStart(action.getActionName()); + CardsImpl cards = new CardsImpl(computerPlayer.getCommandersIds()); + printCards(cards.getCards(game)); + printEnd(); + actions.remove(action); + wasProccessed = true; + } + // show battlefield if (params[0].equals(SHOW_COMMAND_BATTLEFIELD) && params.length == 1) { printStart(action.getActionName()); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander4Players.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander4Players.java new file mode 100644 index 0000000000..a122945927 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander4Players.java @@ -0,0 +1,28 @@ +package org.mage.test.serverside.base; + +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; +import mage.game.CommanderFreeForAll; +import mage.game.Game; +import mage.game.GameException; +import mage.game.mulligan.VancouverMulligan; +import org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl; + +import java.io.FileNotFoundException; + +/** + * @author JayDi85 + */ +public abstract class CardTestCommander4Players extends CardTestPlayerAPIImpl { + + @Override + protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { + Game game = new CommanderFreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, new VancouverMulligan(0), 20); + // Player order: A -> D -> C -> B + playerA = createPlayer(game, playerA, "PlayerA"); + playerB = createPlayer(game, playerB, "PlayerB"); + playerC = createPlayer(game, playerC, "PlayerC"); + playerD = createPlayer(game, playerD, "PlayerD"); + return game; + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java index 5d64d3d246..45eda5e7fe 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java @@ -52,6 +52,7 @@ public abstract class MageTestPlayerBase { protected Map<TestPlayer, List<PermanentCard>> battlefieldCards = new HashMap<>(); protected Map<TestPlayer, List<Card>> graveyardCards = new HashMap<>(); protected Map<TestPlayer, List<Card>> libraryCards = new HashMap<>(); + protected Map<TestPlayer, List<Card>> commandCards = new HashMap<>(); protected Map<TestPlayer, Map<Zone, String>> commands = new HashMap<>(); @@ -211,6 +212,9 @@ public abstract class MageTestPlayerBase { } else if ("library".equalsIgnoreCase(zone)) { gameZone = Zone.LIBRARY; cards = getLibraryCards(getPlayer(nickname)); + } else if ("command".equalsIgnoreCase(zone)) { + gameZone = Zone.COMMAND; + cards = getCommandCards(getPlayer(nickname)); } else if ("player".equalsIgnoreCase(zone)) { String command = m.group(3); if ("life".equals(command)) { @@ -280,27 +284,36 @@ public abstract class MageTestPlayerBase { if (graveyardCards.containsKey(player)) { return graveyardCards.get(player); } - List<Card> grave = new ArrayList<>(); - graveyardCards.put(player, grave); - return grave; + List<Card> res = new ArrayList<>(); + graveyardCards.put(player, res); + return res; } protected List<Card> getLibraryCards(TestPlayer player) { if (libraryCards.containsKey(player)) { return libraryCards.get(player); } - List<Card> library = new ArrayList<>(); - libraryCards.put(player, library); - return library; + List<Card> res = new ArrayList<>(); + libraryCards.put(player, res); + return res; + } + + protected List<Card> getCommandCards(TestPlayer player) { + if (commandCards.containsKey(player)) { + return commandCards.get(player); + } + List<Card> res = new ArrayList<>(); + commandCards.put(player, res); + return res; } protected List<PermanentCard> getBattlefieldCards(TestPlayer player) { if (battlefieldCards.containsKey(player)) { return battlefieldCards.get(player); } - List<PermanentCard> battlefield = new ArrayList<>(); - battlefieldCards.put(player, battlefield); - return battlefield; + List<PermanentCard> res = new ArrayList<>(); + battlefieldCards.put(player, res); + return res; } protected Map<Zone, String> getCommands(TestPlayer player) { diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 5586369408..8b66bcc20a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -70,6 +70,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement // TODO: add target player param to commands public static final String SHOW_COMMAND_LIBRARY = "LIBRARY"; public static final String SHOW_COMMAND_HAND = "HAND"; + public static final String SHOW_COMMAND_COMMAND = "COMMAND"; public static final String SHOW_COMMAND_BATTLEFIELD = "BATTLEFIELD"; public static final String SHOW_COMMAND_GRAVEYEARD = "GRAVEYARD"; public static final String SHOW_COMMAND_EXILE = "EXILE"; @@ -240,7 +241,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement TestPlayer testPlayer = (TestPlayer) player; currentGame.cheat(player.getId(), getCommands(testPlayer)); currentGame.cheat(player.getId(), activePlayer.getId(), getLibraryCards(testPlayer), getHandCards(testPlayer), - getBattlefieldCards(testPlayer), getGraveCards(testPlayer)); + getBattlefieldCards(testPlayer), getGraveCards(testPlayer), getCommandCards(testPlayer)); } long t1 = System.nanoTime(); @@ -389,6 +390,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement show(showName, turnNum, step, player, SHOW_COMMAND_HAND); } + public void showCommand(String showName, int turnNum, PhaseStep step, TestPlayer player) { + show(showName, turnNum, step, player, SHOW_COMMAND_COMMAND); + } + public void showBattlefield(String showName, int turnNum, PhaseStep step, TestPlayer player) { show(showName, turnNum, step, player, SHOW_COMMAND_BATTLEFIELD); } @@ -536,6 +541,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement return getGraveCards(player); case LIBRARY: return getLibraryCards(player); + case COMMAND: + return getCommandCards(player); default: break; } diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java index 7ee0bfdcc0..30638c63a1 100644 --- a/Mage/src/main/java/mage/game/Game.java +++ b/Mage/src/main/java/mage/game/Game.java @@ -432,7 +432,7 @@ public interface Game extends MageItem, Serializable { // game cheats (for tests only) void cheat(UUID ownerId, Map<Zone, String> commands); - void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard); + void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command); // controlling the behaviour of replacement effects while permanents entering the battlefield void setScopeRelevant(boolean scopeRelevant); diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 3594cf3062..59c93e2ab1 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -2845,26 +2845,39 @@ public abstract class GameImpl implements Game, Serializable { } @Override - public void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard) { + public void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command) { Player player = getPlayer(ownerId); if (player != null) { loadCards(ownerId, library); loadCards(ownerId, hand); loadCards(ownerId, battlefield); loadCards(ownerId, graveyard); + loadCards(ownerId, command); for (Card card : library) { player.getLibrary().putOnTop(card, this); } + for (Card card : hand) { card.setZone(Zone.HAND, this); player.getHand().add(card); } + for (Card card : graveyard) { card.setZone(Zone.GRAVEYARD, this); player.getGraveyard().add(card); } + // as commander (only commander games, look at init code in GameCommanderImpl) + if (this instanceof GameCommanderImpl) { + for (Card card : command) { + player.addCommanderId(card.getId()); + // no needs in initCommander call -- it's uses on game startup (init) + } + } else { + throw new IllegalArgumentException("Command zone supports in commander test games"); + } + // warning, permanents go to battlefield without resolve, continuus effects must be init for (PermanentCard permanentCard : battlefield) { permanentCard.setZone(Zone.BATTLEFIELD, this);