package org.mage.test.serverside.base.impl; import mage.constants.PhaseStep; import mage.abilities.Ability; import mage.cards.Card; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.constants.Zone; import mage.filter.Filter; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.players.Player; import org.junit.Assert; import org.mage.test.player.TestPlayer; import org.mage.test.serverside.base.CardTestAPI; import org.mage.test.serverside.base.MageTestBase; import java.util.List; import java.util.UUID; /** * API for test initialization and asserting the test results. * * @author ayratn */ public abstract class CardTestAPIImpl extends MageTestBase implements CardTestAPI { /** * Default game initialization params for red player (that plays with Mountains) */ @Override public void useRedDefault() { // *** ComputerA *** // battlefield:ComputerA:Mountain:5 addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); // hand:ComputerA:Mountain:4 addCard(Zone.HAND, playerA, "Mountain", 5); // library:ComputerA:clear:0 removeAllCardsFromLibrary(playerA); // library:ComputerA:Mountain:10 addCard(Zone.LIBRARY, playerA, "Mountain", 10); // *** ComputerB *** // battlefield:ComputerB:Plains:2 addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); // hand:ComputerB:Plains:2 addCard(Zone.HAND, playerB, "Plains", 2); // library:ComputerB:clear:0 removeAllCardsFromLibrary(playerB); // library:ComputerB:Plains:10 addCard(Zone.LIBRARY, playerB, "Plains", 10); } /** * Default game initialization params for white player (that plays with Plains) */ public void useWhiteDefault() { // *** ComputerA *** addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.HAND, playerA, "Plains", 5); removeAllCardsFromLibrary(playerA); addCard(Zone.LIBRARY, playerA, "Plains", 10); // *** ComputerB *** addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); addCard(Zone.HAND, playerB, "Plains", 2); removeAllCardsFromLibrary(playerB); addCard(Zone.LIBRARY, playerB, "Plains", 10); } /** * Removes all cards from player's library from the game. * Usually this should be used once before initialization to form the library in certain order. * * @param player {@link Player} to remove all library cards from. */ public void removeAllCardsFromLibrary(Player player) { if (player.equals(playerA)) { commandsA.put(Zone.LIBRARY, "clear"); } else if (player.equals(playerB)) { commandsB.put(Zone.LIBRARY, "clear"); } } /** * Add a card to specified zone of specified player. * * @param gameZone {@link mage.constants.Zone} to add cards to. * @param player {@link Player} to add cards for. Use either playerA or playerB. * @param cardName Card name in string format. */ @Override public void addCard(Zone gameZone, TestPlayer player, String cardName) { addCard(gameZone, player, cardName, 1, false); } /** * Add any amount of cards to specified zone of specified player. * * @param gameZone {@link mage.constants.Zone} to add cards to. * @param player {@link Player} to add cards for. Use either playerA or playerB. * @param cardName Card name in string format. * @param count Amount of cards to be added. */ @Override public void addCard(Zone gameZone, TestPlayer player, String cardName, int count) { addCard(gameZone, player, cardName, count, false); } /** * Add any amount of cards to specified zone of specified player. * * @param gameZone {@link mage.constants.Zone} to add cards to. * @param player {@link Player} to add cards for. Use either playerA or playerB. * @param cardName Card name in string format. * @param count Amount of cards to be added. * @param tapped In case gameZone is Battlefield, determines whether permanent should be tapped. * In case gameZone is other than Battlefield, {@link IllegalArgumentException} is thrown */ @Override public void addCard(Zone gameZone, TestPlayer player, String cardName, int count, boolean tapped) { if (gameZone == Zone.BATTLEFIELD) { for (int i = 0; i < count; i++) { CardInfo cardInfo = CardRepository.instance.findCard(cardName); Card card = cardInfo != null ? cardInfo.getCard() : null; if (card == null) { throw new IllegalArgumentException("[TEST] Couldn't find a card: " + cardName); } PermanentCard p = new PermanentCard(card, null, currentGame); p.setTapped(tapped); if (player.equals(playerA)) { battlefieldCardsA.add(p); } else if (player.equals(playerB)) { battlefieldCardsB.add(p); } } } else { if (tapped) { throw new IllegalArgumentException("Parameter tapped=true can be used only for Zone.BATTLEFIELD."); } List<Card> cards = getCardList(gameZone, player); for (int i = 0; i < count; i++) { CardInfo cardInfo = CardRepository.instance.findCard(cardName); Card card = cardInfo != null ? cardInfo.getCard() : null; cards.add(card); } } } /** * Returns card list containter for specified game zone and player. * * @param gameZone * @param player * @return */ private List<Card> getCardList(Zone gameZone, Player player) { if (player.equals(playerA)) { if (gameZone == Zone.HAND) { return handCardsA; } else if (gameZone == Zone.GRAVEYARD) { return graveyardCardsA; } else if (gameZone == Zone.LIBRARY) { return libraryCardsA; } } else if (player.equals(playerB)) { if (gameZone == Zone.HAND) { return handCardsB; } else if (gameZone == Zone.GRAVEYARD) { return graveyardCardsB; } else if (gameZone == Zone.LIBRARY) { return libraryCardsB; } } return null; } /** * Set player's initial life count. * * @param player {@link Player} to set life count for. * @param life Life count to set. */ @Override public void setLife(TestPlayer player, int life) { if (player.equals(playerA)) { commandsA.put(Zone.OUTSIDE, "life:" + String.valueOf(life)); } else if (player.equals(playerB)) { commandsB.put(Zone.OUTSIDE, "life:" + String.valueOf(life)); } } /** * Define turn number to stop the game on. */ @Override public void setStopOnTurn(int turn) { stopOnTurn = turn == -1 ? null : turn; stopAtStep = PhaseStep.UNTAP; } /** * Define turn number and step to stop the game on. */ @Override public void setStopAt(int turn, PhaseStep step) { stopOnTurn = turn == -1 ? null : turn; stopAtStep = step; } /** * Assert turn number after test execution. * * @param turn Expected turn number to compare with. 1-based. */ @Override public void assertTurn(int turn) throws AssertionError { Assert.assertEquals("Turn numbers are not equal", turn, currentGame.getTurnNum()); } /** * Assert game result after test execution. * * @param result Expected {@link GameResult} to compare with. */ @Override public void assertResult(Player player, GameResult result) throws AssertionError { if (player.equals(playerA)) { GameResult actual = CardTestAPI.GameResult.DRAW; switch (currentGame.getWinner()) { case "Player PlayerA is the winner": actual = CardTestAPI.GameResult.WON; break; case "Player PlayerB is the winner": actual = CardTestAPI.GameResult.LOST; break; } Assert.assertEquals("Game results are not equal", result, actual); } else if (player.equals(playerB)) { GameResult actual = CardTestAPI.GameResult.DRAW; switch (currentGame.getWinner()) { case "Player PlayerB is the winner": actual = CardTestAPI.GameResult.WON; break; case "Player PlayerA is the winner": actual = CardTestAPI.GameResult.LOST; break; } Assert.assertEquals("Game results are not equal", result, actual); } } /** * Assert player's life count after test execution. * * @param player {@link Player} to get life for comparison. * @param life Expected player's life to compare with. */ @Override public void assertLife(Player player, int life) throws AssertionError { int actual = currentGame.getPlayer(player.getId()).getLife(); Assert.assertEquals("Life amounts are not equal", life, actual); } /** * Assert creature's power and toughness by card name. * <p/> * Throws {@link AssertionError} in the following cases: * 1. no such player * 2. no such creature under player's control * 3. depending on comparison scope: * 3a. any: no creature under player's control with the specified p\t params * 3b. all: there is at least one creature with the cardName with the different p\t params * * @param player {@link Player} to get creatures for comparison. * @param cardName Card name to compare with. * @param power Expected power to compare with. * @param toughness Expected toughness to compare with. * @param scope {@link mage.filter.Filter.ComparisonScope} Use ANY, if you want "at least one creature with given name should have specified p\t" * Use ALL, if you want "all creature with gived name should have specified p\t" */ @Override public void assertPowerToughness(Player player, String cardName, int power, int toughness, Filter.ComparisonScope scope) throws AssertionError { int count = 0; int fit = 0; for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) { if (permanent.getName().equals(cardName)) { count++; if (scope == Filter.ComparisonScope.All) { Assert.assertEquals("Power is not the same (" + power + " vs. " + permanent.getPower().getValue() + ')', power, permanent.getPower().getValue()); Assert.assertEquals("Toughness is not the same (" + toughness + " vs. " + permanent.getToughness().getValue() + ')', toughness, permanent.getToughness().getValue()); } else if (scope == Filter.ComparisonScope.Any) { if (power == permanent.getPower().getValue() && toughness == permanent.getToughness().getValue()) { fit++; break; } } } } Assert.assertTrue("There is no such permanent under player's control, player=" + player.getName() + ", cardName=" + cardName, count > 0); if (scope == Filter.ComparisonScope.Any) { Assert.assertTrue("There is no such creature under player's control with specified power&toughness, player=" + player.getName() + ", cardName=" + cardName, fit > 0); } } /** * {@inheritDoc} */ @Override public void assertAbilities(Player player, String cardName, List<Ability> abilities) throws AssertionError { int count = 0; Permanent found = null; for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) { if (permanent.getName().equals(cardName)) { found = permanent; } } Assert.assertNotNull("There is no such permanent under player's control, player=" + player.getName() + ", cardName=" + cardName, found); Assert.assertTrue("There is more than one such permanent under player's control, player=" + player.getName() + ", cardName=" + cardName, count == 1); for (Ability ability : abilities) { Assert.assertTrue("No such ability=" + ability.toString() + ", player=" + player.getName() + ", cardName" + cardName, found.getAbilities().contains(ability)); } } /** * Assert permanent count under player's control. * * @param player {@link Player} which permanents should be counted. * @param count Expected count. */ @Override public void assertPermanentCount(Player player, int count) throws AssertionError { int actualCount = 0; for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) { if (permanent.getControllerId().equals(player.getId())) { actualCount++; } } Assert.assertEquals("(Battlefield) Card counts are not equal ", count, actualCount); } /** * Assert permanent count under player's control. * * @param player {@link Player} which permanents should be counted. * @param cardName Name of the cards that should be counted. * @param count Expected count. */ @Override public void assertPermanentCount(Player player, String cardName, int count) throws AssertionError { int actualCount = 0; for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) { if (permanent.getControllerId().equals(player.getId())) { if (permanent.getName().equals(cardName)) { actualCount++; } } } Assert.assertEquals("(Battlefield) Card counts are not equal (" + cardName + ')', count, actualCount); } public Permanent getPermanent(String cardName, UUID controller) { Permanent permanent0 = null; int count = 0; for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) { if (permanent.getControllerId().equals(controller)) { if (permanent.getName().equals(cardName)) { permanent0 = permanent; count++; } } } Assert.assertNotNull("Couldn't find a card with specified name: " + cardName, permanent0); Assert.assertEquals("More than one permanent was found: " + cardName + '(' + count + ')', 1, count); return permanent0; } public void playLand(Player player, String cardName) { player.addAction("play:"+cardName); } public void castSpell(Player player, String cardName) { player.addAction("cast:"+cardName); } public void addFixedTarget(Player player, String cardName, Player target) { player.addAction("cast:"+cardName + ";name=" + target.getName()); } public void addFixedTarget(Player player, String cardName, String targetName) { player.addAction("cast:"+cardName + ";name=" + targetName); } public void useAbility(Player player, String cardName) { } public void attack(Player player, String cardName) { player.addAction("attack:"+cardName); } }