mirror of
https://github.com/correl/mage.git
synced 2024-12-25 11:11:16 +00:00
[AFC] Implemented Share the Spoils (#8583)
* Preliminary implementation of Share the Spoils. * Added tracking of cards in exile to MageTestPlayerBase in order to help with testing of cards such as Share the Spoils which put and take cards out of exile a lot. * Moved Share the Spoils to the correct set list. * Fixed bug with using ’ instead of ' for card text. * Add method to assert number of cards exiled into a specific exile zone. * Further implementation of ShareTheSpoils and it's tests. * Fixed a bug in the calcualtiong of exileNUmber. (I misunderstood what the copy() method was for) * - Added a watcher which should limit player to only cast the spell once per turn. - Fixed the tests to run properly (using .LOST instead of .LOSES for the GameEvent). - A bit of cleaning up of the class * Updated tests and card to capture both conceding and losing the game through other means. * Further implementation. All parts are working (though not correctly). * All pieces are now working. But, both the spend any mana and exile a card off the top of library activate when ANY card is played from exile, not just one exiled with Share the Spoils. * Replaced changed how I move card from top of library to correct exile zone. Instead of using moveCards() and moveToAnotherZone(), I am not using moveCardsToExile(). * A new card is now properly exiled whenever one is played with Share the Spoils * Moved inner class out and passing exileId as parameter instead * Updated text based on comments * Added several more tests * Made changes to how exileId is handled based on comments * Made changes based on comments * Further changes based on comments * Add a few more tests (will have to fix them once the exile zone issue is fixed) * Added workaround for #8706 * Get most of the tests working * Simplified cardId handling * Reformat file based on comment * - Added setStrictChooseMode to all tests - Properly using checkPlayableAbility for all checks where things can't be played/cast. * Fixed a missing getMainCardId call that made difficult cards unplayable * - Simplified handling of casting only once per turn. I don't see the point to keeping the MageReference object. using a simple boolean instead - This also fixes a bug where multiple cards could be played in the same turn. * Fixed test for difficult cards. * Reworked spend mana effect based on Dead Man's chest * Added a check again a null watcher * Fixed typo in checkManaSpendingForOtherExileSource * Fixed tests to use proper checkPlayableAbility syntax. Co-authored-by: Evan Kranzler <theelk801@gmail.com>
This commit is contained in:
parent
06eeb90b3d
commit
b40bde5e12
6 changed files with 932 additions and 1 deletions
372
Mage.Sets/src/mage/cards/s/ShareTheSpoils.java
Normal file
372
Mage.Sets/src/mage/cards/s/ShareTheSpoils.java
Normal file
|
@ -0,0 +1,372 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageIdentifier;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.*;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.ManaPoolItem;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerList;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Alex-Vasile
|
||||
*/
|
||||
public final class ShareTheSpoils extends CardImpl {
|
||||
|
||||
public ShareTheSpoils(UUID ownderId, CardSetInfo setInfo) {
|
||||
super(ownderId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}");
|
||||
|
||||
// When Share the Spoils enters the battlefield or an opponent loses the game,
|
||||
// exile the top card of each player’s library.exile the top card of each player’s library.
|
||||
this.addAbility(new ShareTheSpoilsExileETBAndPlayerLossAbility());
|
||||
|
||||
// During each player’s turn, that player may play a land or cast a spell from among cards exiled with Share the Spoils,
|
||||
// and they may spend mana as though it were mana of any color to cast that spell.
|
||||
Ability castAbility = new SimpleStaticAbility(new ShareTheSpoilsPlayExiledCardEffect());
|
||||
castAbility.setIdentifier(MageIdentifier.ShareTheSpoilsWatcher);
|
||||
this.addAbility(castAbility, new ShareTheSpoilsWatcher());
|
||||
|
||||
// When they do, exile the top card of their library.
|
||||
Ability exileCardWhenPlayedACard = new ShareTheSpoilsExileCardWhenPlayACardAbility();
|
||||
this.addAbility(exileCardWhenPlayedACard);
|
||||
}
|
||||
|
||||
private ShareTheSpoils(final ShareTheSpoils card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShareTheSpoils copy() {
|
||||
return new ShareTheSpoils(this);
|
||||
}
|
||||
}
|
||||
|
||||
//-- Exile from Everyone --//
|
||||
class ShareTheSpoilsExileETBAndPlayerLossAbility extends TriggeredAbilityImpl {
|
||||
|
||||
ShareTheSpoilsExileETBAndPlayerLossAbility() {
|
||||
super(Zone.BATTLEFIELD, new ShareTheSpoilsExileCardFromEveryoneEffect());
|
||||
}
|
||||
|
||||
private ShareTheSpoilsExileETBAndPlayerLossAbility(final ShareTheSpoilsExileETBAndPlayerLossAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD ||
|
||||
event.getType() == GameEvent.EventType.LOST || // Player conceedes
|
||||
event.getType() == GameEvent.EventType.LOSES; // Player loses by all other means
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
// The card that entered the battlefield was this one
|
||||
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
|
||||
return event.getTargetId().equals(getSourceId());
|
||||
}
|
||||
|
||||
// A player lost the game
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TriggeredAbility copy() {
|
||||
return new ShareTheSpoilsExileETBAndPlayerLossAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When {this} enters the battlefield or an opponent loses the game, " +
|
||||
"exile the top card of each player's library.";
|
||||
}
|
||||
}
|
||||
|
||||
class ShareTheSpoilsExileCardFromEveryoneEffect extends OneShotEffect {
|
||||
|
||||
public ShareTheSpoilsExileCardFromEveryoneEffect() {
|
||||
super(Outcome.Exile);
|
||||
}
|
||||
|
||||
public ShareTheSpoilsExileCardFromEveryoneEffect(final ShareTheSpoilsExileCardFromEveryoneEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (source == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PlayerList players = game.getState().getPlayersInRange(source.getControllerId(), game);
|
||||
for (UUID playerId : players) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Card topLibraryCard = player.getLibrary().getFromTop(game);
|
||||
if (topLibraryCard == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean moved = player.moveCardsToExile(
|
||||
topLibraryCard,
|
||||
source,
|
||||
game,
|
||||
true,
|
||||
CardUtil.getExileZoneId(game, source),
|
||||
CardUtil.getSourceName(game, source)
|
||||
);
|
||||
|
||||
if (moved) {
|
||||
ShareTheSpoilsSpendAnyManaEffect effect = new ShareTheSpoilsSpendAnyManaEffect();
|
||||
effect.setTargetPointer(new FixedTarget(topLibraryCard, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShareTheSpoilsExileCardFromEveryoneEffect copy() {
|
||||
return new ShareTheSpoilsExileCardFromEveryoneEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
//-- Play a card Exiled by Share the Spoils --//
|
||||
class ShareTheSpoilsPlayExiledCardEffect extends AsThoughEffectImpl {
|
||||
|
||||
ShareTheSpoilsPlayExiledCardEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.PutCardInPlay);
|
||||
staticText = "During each player's turn, " +
|
||||
"that player may play a land or cast a spell from among cards exiled with {this}, " +
|
||||
"and they may spend mana as though it were mana of any color to cast that spell";
|
||||
}
|
||||
|
||||
private ShareTheSpoilsPlayExiledCardEffect(final ShareTheSpoilsPlayExiledCardEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
// Have to play on your turn
|
||||
if (!game.getActivePlayerId().equals(affectedControllerId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not in exile
|
||||
if (game.getState().getZone(CardUtil.getMainCardId(game, sourceId)) != Zone.EXILED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: This is a workaround for #8706, remove when that's fixed.
|
||||
int zoneChangeCounter = game.getState().getZoneChangeCounter(source.getSourceId());
|
||||
// Not a card exiled with this Share the Spoils
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter));
|
||||
if (exileZone == null) {
|
||||
return false;
|
||||
}
|
||||
if (!exileZone.contains(CardUtil.getMainCardId(game, sourceId))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ShareTheSpoilsWatcher watcher = game.getState().getWatcher(ShareTheSpoilsWatcher.class);
|
||||
if (watcher == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return watcher.hasNotUsedAbilityThisTurn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShareTheSpoilsPlayExiledCardEffect copy() {
|
||||
return new ShareTheSpoilsPlayExiledCardEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//-- Spend mana as any color --//
|
||||
class ShareTheSpoilsSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
|
||||
|
||||
ShareTheSpoilsSpendAnyManaEffect() {
|
||||
super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
}
|
||||
|
||||
private ShareTheSpoilsSpendAnyManaEffect(final ShareTheSpoilsSpendAnyManaEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShareTheSpoilsSpendAnyManaEffect copy() {
|
||||
return new ShareTheSpoilsSpendAnyManaEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID mainCardId = CardUtil.getMainCardId(game, sourceId);
|
||||
|
||||
if (getTargetPointer() == null) {
|
||||
return false;
|
||||
}
|
||||
UUID targetUUID = ((FixedTarget) getTargetPointer()).getTarget();
|
||||
|
||||
// Not the right card
|
||||
if (mainCardId != targetUUID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int mainCardZCC = game.getState().getZoneChangeCounter(mainCardId);
|
||||
int targetZCC = game.getState().getZoneChangeCounter(targetUUID);
|
||||
|
||||
if (mainCardZCC <= targetZCC + 1) {
|
||||
// card moved one zone, from exile to being cast
|
||||
return true;
|
||||
} else {
|
||||
// card moved zones, effect can be discarded
|
||||
this.discard();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
|
||||
return mana.getFirstAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
//-- Exile another card when a card is played that was exiled with Share the Spoils --//
|
||||
class ShareTheSpoilsExileCardWhenPlayACardAbility extends TriggeredAbilityImpl {
|
||||
|
||||
ShareTheSpoilsExileCardWhenPlayACardAbility() {
|
||||
super(Zone.BATTLEFIELD, new ShareTheSpoilsExileSingleCardEffect());
|
||||
setRuleVisible(false);
|
||||
}
|
||||
|
||||
private ShareTheSpoilsExileCardWhenPlayACardAbility(final ShareTheSpoilsExileCardWhenPlayACardAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.SPELL_CAST || event.getType() == GameEvent.EventType.LAND_PLAYED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
return event.hasApprovingIdentifier(MageIdentifier.ShareTheSpoilsWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TriggeredAbility copy() {
|
||||
return new ShareTheSpoilsExileCardWhenPlayACardAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTriggerPhrase() {
|
||||
return "When they do";
|
||||
}
|
||||
}
|
||||
|
||||
class ShareTheSpoilsExileSingleCardEffect extends OneShotEffect {
|
||||
|
||||
ShareTheSpoilsExileSingleCardEffect() {
|
||||
super(Outcome.Exile);
|
||||
staticText = ", exile the top card of their library";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (source == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Card topLibraryCard = player.getLibrary().getFromTop(game);
|
||||
if (topLibraryCard == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean moved = player.moveCardsToExile(
|
||||
topLibraryCard,
|
||||
source,
|
||||
game,
|
||||
true,
|
||||
CardUtil.getExileZoneId(game, source),
|
||||
CardUtil.getSourceName(game, source)
|
||||
);
|
||||
|
||||
if (moved) {
|
||||
ShareTheSpoilsSpendAnyManaEffect effect = new ShareTheSpoilsSpendAnyManaEffect();
|
||||
effect.setTargetPointer(new FixedTarget(topLibraryCard, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
return moved;
|
||||
}
|
||||
|
||||
private ShareTheSpoilsExileSingleCardEffect(final ShareTheSpoilsExileSingleCardEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShareTheSpoilsExileSingleCardEffect copy() {
|
||||
return new ShareTheSpoilsExileSingleCardEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ShareTheSpoilsWatcher extends Watcher {
|
||||
|
||||
private boolean usedThisTurn;
|
||||
|
||||
public ShareTheSpoilsWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() != GameEvent.EventType.SPELL_CAST && event.getType() != GameEvent.EventType.LAND_PLAYED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.hasApprovingIdentifier(MageIdentifier.ShareTheSpoilsWatcher)) {
|
||||
usedThisTurn = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
usedThisTurn = false;
|
||||
}
|
||||
|
||||
public boolean hasNotUsedAbilityThisTurn() {
|
||||
return !usedThisTurn;
|
||||
}
|
||||
}
|
|
@ -228,6 +228,8 @@ public final class ForgottenRealmsCommander extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Serum Visions", 94, Rarity.UNCOMMON, mage.cards.s.SerumVisions.class));
|
||||
cards.add(new SetCardInfo("Shadowblood Ridge", 259, Rarity.RARE, mage.cards.s.ShadowbloodRidge.class));
|
||||
cards.add(new SetCardInfo("Shamanic Revelation", 171, Rarity.RARE, mage.cards.s.ShamanicRevelation.class));
|
||||
cards.add(new SetCardInfo("Share the Spoils",34, Rarity.RARE, mage.cards.s.ShareTheSpoils.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Share the Spoils",303, Rarity.RARE, mage.cards.s.ShareTheSpoils.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Shielding Plax", 192, Rarity.COMMON, mage.cards.s.ShieldingPlax.class));
|
||||
cards.add(new SetCardInfo("Shiny Impetus", 138, Rarity.UNCOMMON, mage.cards.s.ShinyImpetus.class));
|
||||
cards.add(new SetCardInfo("Shivan Hellkite", 139, Rarity.RARE, mage.cards.s.ShivanHellkite.class));
|
||||
|
|
|
@ -0,0 +1,526 @@
|
|||
package org.mage.test.cards.single.afc;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestCommander4Players;
|
||||
|
||||
|
||||
public class ShareTheSpoilsTest extends CardTestCommander4Players {
|
||||
|
||||
private static final String shareTheSpoils = "Share the Spoils";
|
||||
|
||||
/**
|
||||
* When Share the Spoils enters the battlefield every player exiles one card.
|
||||
*/
|
||||
@Test
|
||||
public void enterTheBattleField() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, 1);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* When an opponent loses, their exiled cards are removed from the game and all other players exile a new card.
|
||||
*/
|
||||
@Test
|
||||
public void nonOwnerLoses() {
|
||||
setLife(playerD, 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Banehound", 1);
|
||||
|
||||
attack(1, playerA, "Banehound", playerD);
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, 1);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* When an opponent loses, their exiled cards are removed from the game and all other players exile a new card.
|
||||
*/
|
||||
@Test
|
||||
public void nonOwnerConcedes() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, shareTheSpoils);
|
||||
concede(1, PhaseStep.PRECOMBAT_MAIN, playerD);
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, 1);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* When owner loses, no new cards should be exiled and owner's exiled cards are removed from the game.
|
||||
*/
|
||||
@Test
|
||||
public void ownerConcedes() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
concede(1, PhaseStep.POSTCOMBAT_MAIN, playerA);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, 0);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* When owner loses, no new cards should be exiled and owner's exiled cards are removed from the game.
|
||||
*/
|
||||
@Test
|
||||
public void ownerLoses() {
|
||||
setLife(playerA, 1);
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerD, "Banehound", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
attack(2, playerD, "Banehound", playerA);
|
||||
|
||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, 0);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* During your turn, you may cast A card from the cards exiled with share the spoils.
|
||||
*/
|
||||
@Test
|
||||
public void canCastOnOwnTurn() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||
|
||||
// 3rd from the top, exiled when Tana is cast with Share the Spoils
|
||||
addCard(Zone.LIBRARY, playerA, "Reliquary Tower");
|
||||
// 2nd from the top, exile when Share the Spoils is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Tana, the Bloodsower", 1); // {2}{R}{G}
|
||||
// Topmost, draw at beginning of turn
|
||||
addCard(Zone.LIBRARY, playerA, "Exotic Orchard");
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tana, the Bloodsower");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Tana, the Bloodsower", 1);
|
||||
|
||||
assertExileCount(playerA, "Tana, the Bloodsower", 0);
|
||||
assertExileCount(playerA, "Reliquary Tower", 1);
|
||||
|
||||
assertExileCount(playerA, 1);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* During your turn, you may play A land from the cards exiled with share the spoils.
|
||||
*/
|
||||
@Test
|
||||
public void playLandOnOwnTurn() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||
|
||||
// 3rd from the top, exiled when Exotic Orchard is played with Share the Spoils
|
||||
addCard(Zone.LIBRARY, playerA, "Reliquary Tower");
|
||||
// 2nd from the top, exile when Share the Spoils is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Exotic Orchard");
|
||||
// Topmost, draw at beginning of turn
|
||||
addCard(Zone.LIBRARY, playerA, "Tana, the Bloodsower", 1); // {2}{R}{G}
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Exotic Orchard");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Exotic Orchard", 1);
|
||||
|
||||
assertExileCount(playerA, "Exotic Orchard", 0);
|
||||
assertExileCount(playerA, "Reliquary Tower", 1);
|
||||
|
||||
assertExileCount(playerA, 1);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* You cannot play a card or cast a spell when it's not your turn.
|
||||
*/
|
||||
@Test
|
||||
public void cannotCastWhenNotYourTurn() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||
|
||||
// 2nd from the top, exile when Share the Spoils is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Lightning Bolt", 1); // {R}
|
||||
// Topmost, draw at beginning of turn
|
||||
addCard(Zone.LIBRARY, playerA, "Exotic Orchard");
|
||||
|
||||
addCard(Zone.LIBRARY, playerB, "Reliquary Tower");
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
checkPlayableAbility("normal cast", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", false);
|
||||
checkPlayableAbility("before play", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Play Reliquary Tower", false);
|
||||
|
||||
setStopAt(2, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertExileCount(playerA, "Lightning Bolt", 1);
|
||||
assertExileCount(playerA, "Reliquary Tower", 0);
|
||||
|
||||
assertExileCount(playerA, 1);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
|
||||
assertGraveyardCount(playerA, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* You may cast A spell or play A card, you cannot do both, or multiple of either.
|
||||
*/
|
||||
@Test
|
||||
public void tryToCastOrPlayASecondCard() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||
|
||||
// 3rd from the top, exiled when card is played with Share the Spoils
|
||||
addCard(Zone.LIBRARY, playerA, "Lightning Bolt", 1); // {R}
|
||||
// 2nd from the top, exile when Share the Spoils is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Exotic Orchard");
|
||||
// Topmost, draw at beginning of turn
|
||||
addCard(Zone.LIBRARY, playerA, "Reliquary Tower");
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Exotic Orchard");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
// Abilities available after casting with Share the Spoils
|
||||
checkPlayableAbility("Available Abilities", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", false);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertExileCount(playerA, "Exotic Orchard", 0);
|
||||
assertExileCount(playerA, "Lightning Bolt", 1);
|
||||
|
||||
assertExileCount(playerA, 1);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the spending mana as if it were any color only works for cards exiled with Share the Spoils.
|
||||
*/
|
||||
@Test
|
||||
public void checkManaSpendingForOtherExileSource() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.HAND, playerA, "Augury Raven");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Prosper, Tome-Bound");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
|
||||
// 3rd from the top, exile at end of turn with propser
|
||||
addCard(Zone.LIBRARY, playerA, "Tana, the Bloodsower", 1); // {2}{R}{G}
|
||||
// 2nd from the top, exile when Share the Spoils is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Exotic Orchard");
|
||||
// Topmost, draw at beginning of turn
|
||||
addCard(Zone.LIBRARY, playerA, "Ardenvale Tactician"); // Adventure part is "Dizzying Swoop"
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
// Foretell Augury Raven
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Try to cast Tana, you should not be able to since there isn't the {G} for it since she was exiled by Proser
|
||||
checkPlayableAbility("normal cast", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Tana, the Bloodsower", false);
|
||||
|
||||
// Try to activate the foretell on Augury Raven, but we can't since we don't have the {U} for it.
|
||||
checkPlayableAbility("foretell creature cast", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell {1}{U}", false);
|
||||
|
||||
// Cast an adventure card from hand
|
||||
castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerA, "Dizzying Swoop");
|
||||
addTarget(playerA, "Prosper, Tome-Bound");
|
||||
waitStackResolved(5, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Make sure the creature card can't be played from exile since there isn't the {W}{W} for it
|
||||
checkPlayableAbility("creature cast", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Ardenvale Tactician", false);
|
||||
|
||||
setStopAt(5, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
// 1 exiled with Share the Spoils
|
||||
// 1 exiled Prosper (he only exiles one since we stop before the end step of playerA's second turn)
|
||||
// 1 for the foretold Augury Raven
|
||||
// 1 for the Dizzying Swoop Adventure
|
||||
assertExileCount(playerA, 4);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the more difficult types cards work properly.
|
||||
*/
|
||||
@Test
|
||||
public void checkDifficultCards() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||
|
||||
// 3rd from the top, exile Lovestruck Beast is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Ardenvale Tactician"); // Adventure, creature half {1}{W}{W}
|
||||
// 2nd from the top, exile when Share the Spoils is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Lovestruck Beast"); // Adventure, adventure half "Heart's Desire" {G}
|
||||
// Topmost, draw at beginning of turn
|
||||
addCard(Zone.LIBRARY, playerA, "Mountain");
|
||||
|
||||
// Modal dual face, cast front
|
||||
addCard(Zone.LIBRARY, playerB, "Alrund, God of the Cosmos"); // Backside is "Hakka, Whispering Raven"
|
||||
// Modal fual face, cast back
|
||||
addCard(Zone.LIBRARY, playerC, "Esika, God of the Tree"); // Backside is "The Prismatic Bridge"
|
||||
// Split card
|
||||
addCard(Zone.LIBRARY, playerD, "Fire // Ice");
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
// Cast the Adventure half of an Adventure card
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Heart's Desire");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
// Cast the Creature half of an Adventure card
|
||||
castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerA, "Ardenvale Tactician");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
// Cast split card
|
||||
castSpell(9, PhaseStep.PRECOMBAT_MAIN, playerA, "Ice");
|
||||
addTarget(playerA, "Mountain");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
// Cast front side of Modal dual face card
|
||||
castSpell(13, PhaseStep.PRECOMBAT_MAIN, playerA, "Alrund, God of the Cosmos");
|
||||
setChoice(playerA, "Land");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
// Cast back side of Modal dual face card
|
||||
castSpell(17, PhaseStep.PRECOMBAT_MAIN, playerA, "The Prismatic Bridge");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
setStopAt(17, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Ardenvale Tactician", 1);
|
||||
|
||||
assertExileCount(playerA, "Lovestruck Beast", 1);
|
||||
|
||||
// 1 from Share the Spoils exiling a card for ETB
|
||||
// 1 from casting the Adventur half of a card (Heart's Desire) and leaving it in exile
|
||||
// 1 from casting "Ice"
|
||||
// 1 from casting "Alrund, God of the Cosmos"
|
||||
// 1 from casting "The Prismatic Bridge
|
||||
assertExileCount(playerA, 5);
|
||||
// 0 since playerA cast their card and replaced it with one of their own
|
||||
assertExileCount(playerB, 0);
|
||||
// 0 since playerA cast their card and replaced it with one of their own
|
||||
assertExileCount(playerC, 0);
|
||||
// 0 since playerA cast their card and replaced it with one of their own
|
||||
assertExileCount(playerD, 0);
|
||||
|
||||
// Ice is the only card that went in here
|
||||
assertGraveyardCount(playerD, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* When Share the Spoils leaves the battlefield, the exiled cards are no longer playable.
|
||||
*/
|
||||
@Test
|
||||
public void ensureCardsNotPlayable() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
|
||||
|
||||
// 3rd from the top, exiled when card is played with Share the Spoils
|
||||
addCard(Zone.LIBRARY, playerA, "Exotic Orchard");
|
||||
// 2nd from the top, exile when Share the Spoils is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Aether Helix", 1); // {3}{G}{U}
|
||||
// Topmost, draw at beginning of turn
|
||||
addCard(Zone.LIBRARY, playerA, "Reliquary Tower");
|
||||
|
||||
// Target in graveyard for Aether Helix
|
||||
addCard(Zone.GRAVEYARD, playerA, "Aether Spellbomb");
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Aether Helix");
|
||||
addTarget(playerA, shareTheSpoils);
|
||||
addTarget(playerA, "Aether Spellbomb");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
checkPlayableAbility("before play", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Play Exotic Orchard", false);
|
||||
|
||||
setStopAt(5, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertExileCount(playerA, "Aether Helix", 0);
|
||||
assertExileCount(playerA, "Exotic Orchard", 1);
|
||||
|
||||
assertExileCount(playerA, 1);
|
||||
assertExileCount(playerB, 1);
|
||||
assertExileCount(playerC, 1);
|
||||
assertExileCount(playerD, 1);
|
||||
|
||||
assertGraveyardCount(playerA, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* When this share the spoils is destroyed and it is somehow recast, it will create a new pool of cards.
|
||||
* The previous cards are no longer playable.
|
||||
*/
|
||||
@Test
|
||||
public void checkDifferentCardPools() {
|
||||
addCard(Zone.HAND, playerA, shareTheSpoils);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 9);
|
||||
|
||||
// 3rd from the top, exiled when card is played with Share the Spoils
|
||||
addCard(Zone.LIBRARY, playerA, "Exotic Orchard");
|
||||
// 2nd from the top, exile when Share the Spoils is cast
|
||||
addCard(Zone.LIBRARY, playerA, "Aether Helix", 1); // {3}{G}{U}
|
||||
// Topmost, draw at beginning of turn
|
||||
addCard(Zone.LIBRARY, playerA, "Reliquary Tower");
|
||||
|
||||
// Target in graveyard for Aether Helix
|
||||
addCard(Zone.GRAVEYARD, playerA, "Aether Spellbomb");
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
// Casting Aether Helix from exile with Share the spoils.
|
||||
// Doing so exiles Exotic Orchard.
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Aether Helix");
|
||||
addTarget(playerA, shareTheSpoils);
|
||||
addTarget(playerA, "Aether Spellbomb");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
// Recast, exile a new set of cards
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, shareTheSpoils);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
// Exotic Orchard was exile by the first Share the Spoils, so can't be cast again with the new one
|
||||
checkPlayableAbility("before play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Play Exotic Orchard", false);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertExileCount(playerA, "Aether Helix", 0);
|
||||
assertExileCount(playerA, "Exotic Orchard", 1);
|
||||
|
||||
assertExileCount(playerA, 2);
|
||||
assertExileCount(playerB, 2);
|
||||
assertExileCount(playerC, 2);
|
||||
assertExileCount(playerD, 2);
|
||||
|
||||
assertGraveyardCount(playerA, 1);
|
||||
}
|
||||
}
|
|
@ -78,6 +78,7 @@ public abstract class MageTestPlayerBase {
|
|||
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, List<Card>> exiledCards = new HashMap<>();
|
||||
|
||||
protected Map<TestPlayer, Map<Zone, String>> commands = new HashMap<>();
|
||||
|
||||
|
@ -349,6 +350,15 @@ public abstract class MageTestPlayerBase {
|
|||
return res;
|
||||
}
|
||||
|
||||
protected List<Card> getExiledCards(TestPlayer player) {
|
||||
if (exiledCards.containsKey(player)) {
|
||||
return exiledCards.get(player);
|
||||
}
|
||||
List<Card> res = new ArrayList<>();
|
||||
exiledCards.put(player, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
protected Map<Zone, String> getCommands(TestPlayer player) {
|
||||
if (commands.containsKey(player)) {
|
||||
return commands.get(player);
|
||||
|
@ -441,6 +451,9 @@ public abstract class MageTestPlayerBase {
|
|||
case COMMAND:
|
||||
getCommandCards(controllerPlayer).add(newCard);
|
||||
break;
|
||||
case EXILED:
|
||||
getExiledCards(controllerPlayer).add(newCard);
|
||||
break;
|
||||
default:
|
||||
Assert.fail("Unsupported zone: " + putAtZone);
|
||||
}
|
||||
|
|
|
@ -238,6 +238,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
getHandCards(testPlayer).clear();
|
||||
getBattlefieldCards(testPlayer).clear();
|
||||
getGraveCards(testPlayer).clear();
|
||||
getExiledCards(testPlayer).clear();
|
||||
// Reset the turn counter for tests
|
||||
((TestPlayer) player).setInitialTurns(0);
|
||||
}
|
||||
|
@ -731,6 +732,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
return getLibraryCards(player);
|
||||
case COMMAND:
|
||||
return getCommandCards(player);
|
||||
case EXILED:
|
||||
return getExiledCards(player);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1442,7 +1445,21 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
}
|
||||
}
|
||||
}
|
||||
Assert.assertEquals("(Exile " + owner.getName() + ") Card counts are not equal (" + cardName + ')', count, actualCount);
|
||||
Assert.assertEquals("(Exile " + owner.getName() + ") Card counts are not equal (" + cardName + ").", count, actualCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert card count in a specific exile zone.
|
||||
*
|
||||
* @param exileZoneName Name of the exile zone to be counted.
|
||||
* @param count Expected count.
|
||||
* @throws AssertionError
|
||||
*/
|
||||
public void assertExileZoneCount(String exileZoneName, int count) throws AssertionError {
|
||||
ExileZone exileZone = currentGame.getExile().getExileZone(CardUtil.getExileZoneId(exileZoneName, currentGame));
|
||||
int actualCount = exileZone.getCards(currentGame).size();
|
||||
|
||||
Assert.assertEquals("(Exile \"" + exileZoneName + "\") Card counts are not equal.", count, actualCount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,6 +14,7 @@ public enum MageIdentifier {
|
|||
KessDissidentMageWatcher,
|
||||
LurrusOfTheDreamDenWatcher,
|
||||
MuldrothaTheGravetideWatcher,
|
||||
ShareTheSpoilsWatcher,
|
||||
WishWatcher,
|
||||
GlimpseTheCosmosWatcher
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue