Fixing several tests. Working towards enabling assertAllCommandsUsed() inside execute().

This commit is contained in:
Alex Vasile 2022-05-29 21:03:57 -06:00
parent 80f6db1245
commit 01be1b1a6b
34 changed files with 419 additions and 285 deletions

View file

@ -8,47 +8,49 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
* {@link mage.cards.l.LinvalaKeeperOfSilence Linvala, Keeper of Silence}
* {2}{W}{W}
* Legendary Creature Angel
* Flying
* Activated abilities of creatures your opponents control cant be activated.
*
* Created by Derek M on 3/6/2017. * Created by Derek M on 3/6/2017.
*/ */
public class LinvalaKeeperOfSilenceTest extends CardTestPlayerBase { public class LinvalaKeeperOfSilenceTest extends CardTestPlayerBase {
/* /**
* Reported bug: Linvala, Keeper of Silence, played by my opponent, did not prevent me from activating abilities with the "tap" symbol. * Reported bug: Linvala, Keeper of Silence, played by my opponent,
* Examples included Jagged-Scar Archers and Imperious Perfect; * did not prevent me from activating abilities with the "tap" symbol.
* Examples included Jagged-Scar Archers and Imperious Perfect;
*/ */
@Test @Test
public void linvalaSilencesActivatedAbilities() public void linvalaSilencesActivatedAbilities() {
{
String linvala = "Linvala, Keeper of Silence"; String linvala = "Linvala, Keeper of Silence";
String jScarArcher = "Jagged-Scar Archers"; String jScarArcher = "Jagged-Scar Archers";
String imperiousPerfect = "Imperious Perfect"; String imperiousPerfect = "Imperious Perfect";
/*
Linvala, Keeper of Silence {2}{W}{W}
Legendary Creature - Angel 3/4
Flying
Activated abilities of creatures your opponents control can't be activated.
*/
addCard(Zone.BATTLEFIELD, playerA, linvala); addCard(Zone.BATTLEFIELD, playerA, linvala);
/* /*
{1}{G}{G} Elf Archer * / * * {1}{G}{G} Elf Archer * / *
Jagged-Scar Archers's power and toughness are each equal to the number of Elves you control. * Jagged-Scar Archers's power and toughness are each equal to the number of Elves you control.
Tap: Jagged-Scar Archers deals damage equal to its power to target creature with flying. * Tap: Jagged-Scar Archers deals damage equal to its power to target creature with flying.
*/ */
addCard(Zone.BATTLEFIELD, playerB, jScarArcher); addCard(Zone.BATTLEFIELD, playerB, jScarArcher);
/* /*
{2}{G} Creature - Elf Warrior 2/2 * {2}{G} Creature - Elf Warrior 2/2 Other
Other Elf creatures you control get +1/+1. * Elf creatures you control get +1/+1.
{G}, Tap: Create a 1/1 green Elf Warrior creature token. * {G}, Tap: Create a 1/1 green Elf Warrior creature token.
*/ */
addCard(Zone.BATTLEFIELD, playerB, imperiousPerfect); addCard(Zone.BATTLEFIELD, playerB, imperiousPerfect);
addCard(Zone.BATTLEFIELD, playerB, "Forest", 2); addCard(Zone.BATTLEFIELD, playerB, "Forest", 2);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{G}:"); // Imperious Perfect: create 1/1 elf warrior token // Imperious Perfect: create 1/1 elf warrior token
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerB, "Jagged", linvala); // Jagged-scar: deal damage to Linvala equal to elves in play checkPlayableAbility("Can't use activated abilities", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "{G}:", false);
// Jagged-scar: deal damage to Linvala equal to elves in play
checkPlayableAbility("Can't use activated abilities", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Jagged", false);
setStopAt(3, PhaseStep.BEGIN_COMBAT); setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute(); execute();

View file

@ -20,14 +20,12 @@ public class SearchEntersBattlefieldTest extends CardTestPlayerBase {
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Verdant Catacombs"); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Verdant Catacombs");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Pay"); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Pay");
setChoice(playerA, "Forest"); addTarget(playerA, "Forest");
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
assertGraveyardCount(playerA, "Verdant Catacombs", 1); assertGraveyardCount(playerA, "Verdant Catacombs", 1);
assertPermanentCount(playerA, "Forest", 1); assertPermanentCount(playerA, "Forest", 1);
assertTapped("Forest", false); assertTapped("Forest", false);
} }
} }

View file

@ -89,7 +89,8 @@ public class JumpStartTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Experimental Frenzy"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Experimental Frenzy");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Direct Current with jump-start", playerB); castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Direct Current with jump-start", playerB);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB); checkPlayableAbility("Can't cast lightning bolt", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast Lightning", false);
// castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
@ -99,12 +100,9 @@ public class JumpStartTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Direct Current", 0); assertGraveyardCount(playerA, "Direct Current", 0);
assertExileCount(playerA, "Direct Current", 1); assertExileCount(playerA, "Direct Current", 1);
assertHandCount(playerA, "Lightning Bolt", 1); // prevented to cast from hand by Experimental Frenzy
assertGraveyardCount(playerA, "Lightning Bolt", 1); // Discarded by using jump-start assertGraveyardCount(playerA, "Lightning Bolt", 1); // Discarded by using jump-start
assertLife(playerA, 20); assertLife(playerA, 20);
assertLife(playerB, 18); assertLife(playerB, 18);
} }
} }

View file

@ -553,13 +553,13 @@ public class KickerTest extends CardTestPlayerBase {
assertAllCommandsUsed(); assertAllCommandsUsed();
} }
/**
* Bug: When I cast Orim's Chant with Kicker cost, the player can play spells
* anyway during the turn.
* It seems like the kicker cost trigger an "instead" creatures can't attack.
*/
@Test @Test
public void test_Single_OrimsChants() { public void test_Single_OrimsChants() {
// bug:
// When I cast Orim's Chant with Kicker cost, the player can play spells
// anyway during the turn. It seems like the kicker cost trigger an
// "instead" creatures can't attack.
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin", 1); // Haste 1/1 addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin", 1); // Haste 1/1
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// Kicker {W} (You may pay an additional {W} as you cast this spell.) // Kicker {W} (You may pay an additional {W} as you cast this spell.)
@ -577,11 +577,19 @@ public class KickerTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA); castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
// attack must be restricted, so no attack commands available // Attack must be restricted, so no attack commands available
//setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute();
//assertAllCommandsUsed(); try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerA must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack with Raging Golin, but got:\n" + e.getMessage());
}
}
assertGraveyardCount(playerA, "Orim's Chant", 1); assertGraveyardCount(playerA, "Orim's Chant", 1);
assertGraveyardCount(playerB, "Lightning Bolt", 0); assertGraveyardCount(playerB, "Lightning Bolt", 0);

View file

@ -87,31 +87,4 @@ public class MiracleTest extends CardTestPlayerBase {
assertLife(playerB, 15); assertLife(playerB, 15);
} }
/**
* Test that you can't cast a card by miracle if you put it back to library before casting
*/
@Test
public void testMiracleWontWorkFromLibrary() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
addCard(Zone.LIBRARY, playerA, "Plains");
addCard(Zone.LIBRARY, playerA, "Forest");
addCard(Zone.LIBRARY, playerA, "Thunderous Wrath");
addCard(Zone.HAND, playerA, "Brainstorm");
skipInitShuffling();
castSpell(1, PhaseStep.UPKEEP, playerA, "Brainstorm");
addTarget(playerA, "Thunderous Wrath");
addTarget(playerA, "Plains");
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.DRAW);
execute();
// check Thunderous Wrath was not played
assertLife(playerA, 20);
assertLife(playerB, 20);
}
} }

View file

@ -396,13 +396,12 @@ public class SoulbondKeywordTest extends CardTestPlayerBase {
Assert.assertEquals(eliteVanguard.getPairedCard(), null); Assert.assertEquals(eliteVanguard.getPairedCard(), null);
} }
/* /**
* Reported bug: Soulbond should use the stack, but unable to use instant speed removal since no trigger occurs * Reported bug: Soulbond should use the stack, but unable to use instant speed removal since no trigger occurs
*/ */
@Test @Test
// Soulbond does not currently use the stack, so this test will fail until then // Soulbond does not currently use the stack, so this test will fail until then
public void testRespondToSoulboundWithRemoval() { public void testRespondToSoulboundWithRemoval() {
// When Palinchron enters the battlefield, untap up to seven lands. // When Palinchron enters the battlefield, untap up to seven lands.
// {2}{U}{U}: Return Palinchron to its owner's hand. // {2}{U}{U}: Return Palinchron to its owner's hand.
addCard(Zone.BATTLEFIELD, playerA, "Palinchron"); // 4/5 flying addCard(Zone.BATTLEFIELD, playerA, "Palinchron"); // 4/5 flying

View file

@ -19,7 +19,6 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
*/ */
@Test @Test
public void testSpliceThroughTheBreach() { public void testSpliceThroughTheBreach() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
// Sorcery - Arcane {R} // Sorcery - Arcane {R}
// Lava Spike deals 3 damage to target player. // Lava Spike deals 3 damage to target player.
@ -33,7 +32,7 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
// activate splice: yes -> card with splice ability -> new target for spliced ability // activate splice: yes -> card with splice ability -> new target for spliced ability
setChoice(playerA, true); setChoice(playerA, true);
addTarget(playerA, "Through the Breach"); addTarget(playerA, "Through the Breach");
addTarget(playerA, "Silvercoat Lion"); // target for spliced ability: put from hand to battlefield setChoice(playerA, "Silvercoat Lion"); // target for spliced ability: put from hand to battlefield
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
@ -83,11 +82,12 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
/** /**
* Nourishing Shoal's interaction with Splicing Through the Breach is * Nourishing Shoal's interaction with Splicing Through the Breach is
* bugged. You should still need to pay 2RR as an additional cost, which is * bugged.
* You should still need to pay 2RR as an additional cost, which is
* not affected by the alternate casting method of Shoal, but you are able * not affected by the alternate casting method of Shoal, but you are able
* to Splice it for free. This is a very relevant bug right now due to the * to Splice it for free.
* appearance of the deck over the weekend, and it makes the deck absurdly * This is a very relevant bug right now due to the appearance of the deck
* powerful. * over the weekend, and it makes the deck absurdly powerful.
*/ */
@Test @Test
public void testSpliceThroughTheBreach2() { public void testSpliceThroughTheBreach2() {
@ -105,7 +105,7 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
// activate splice: yes -> card with splice ability -> new target for spliced ability // activate splice: yes -> card with splice ability -> new target for spliced ability
setChoice(playerA, true); setChoice(playerA, true);
addTarget(playerA, "Through the Breach"); addTarget(playerA, "Through the Breach");
addTarget(playerA, "Silvercoat Lion"); // target for spliced ability: put from hand to battlefield setChoice(playerA, "Silvercoat Lion"); // target for spliced ability: put from hand to battlefield
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();

View file

@ -24,15 +24,9 @@ public class RuneflareTrapTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Runeflare Trap"); addCard(Zone.HAND, playerB, "Runeflare Trap");
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Runeflare Trap", playerA); checkPlayableAbility("Can't Runeflare Trap", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Cast Runeflare", false);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertLife(playerA, 20);
assertLife(playerB, 20);
assertHandCount(playerB, "Runeflare Trap", 1);
} }
} }

View file

@ -7,6 +7,11 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
* {@link mage.cards.s.SatyrFiredancer Satyr Firedancer}
* {1}{R}
* Enchantment Creature Satyr
* Whenever an instant or sorcery spell you control deals damage to an opponent,
* Satyr Firedancer deals that much damage to target creature that player controls.
* *
* @author LevelX2 * @author LevelX2
*/ */
@ -14,7 +19,6 @@ public class SatyrFiredancerTest extends CardTestPlayerBase {
@Test @Test
public void testDamageFromInstantToPlayer() { public void testDamageFromInstantToPlayer() {
// Whenever an instant or sorcery spell you control deals damage to an opponent, Satyr Firedancer deals that much damage to target creature that player controls.
addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer"); addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.HAND, playerA, "Lightning Bolt"); addCard(Zone.HAND, playerA, "Lightning Bolt");
@ -34,44 +38,46 @@ public class SatyrFiredancerTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Silvercoat Lion", 1); assertGraveyardCount(playerB, "Silvercoat Lion", 1);
} }
/**
* Check that Satyr won't trigger from combat damage.
*/
@Test @Test
public void testDamageFromAttackWontTrigger() { public void testDamageFromAttackWontTrigger() {
// Whenever an instant or sorcery spell you control deals damage to an opponent, Satyr Firedancer deals that much damage to target creature that player controls.
addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer"); addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer");
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1); addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
setStrictChooseMode(true);
attack(1, playerA, "Pillarfield Ox"); attack(1, playerA, "Pillarfield Ox");
addTarget(playerA, "Silvercoat Lion");
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
assertLife(playerA, 20); assertLife(playerA, 20);
assertLife(playerB, 18); assertLife(playerB, 18);
assertGraveyardCount(playerB, "Silvercoat Lion", 0);
assertPermanentCount(playerB, "Silvercoat Lion", 1);
} }
/**
* Check that Satyr doesn't trigger from an ability.
*/
@Test @Test
public void testDamageFromOtherCreature() { public void testDamageFromAbility() {
// Whenever an instant or sorcery spell you control deals damage to an opponent, Satyr Firedancer deals that much damage to target creature that player controls.
addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer"); addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer");
// {T}: Prodigal Pyromancer deals 1 damage to any target. // {T}: Prodigal Pyromancer deals 1 damage to any target.
addCard(Zone.BATTLEFIELD, playerA, "Prodigal Pyromancer", 1); addCard(Zone.BATTLEFIELD, playerA, "Prodigal Pyromancer", 1);
setStrictChooseMode(true);
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: {this} deals", playerB); activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: {this} deals", playerB);
addTarget(playerA, playerB);
setStopAt(3, PhaseStep.END_TURN); setStopAt(3, PhaseStep.END_TURN);
execute(); execute();
assertLife(playerA, 20); assertLife(playerA, 20);
assertLife(playerB, 19); assertLife(playerB, 19);
} }
@Test @Test

View file

@ -76,13 +76,15 @@ public class SpendOtherManaTest extends CardTestPlayerBase {
* of Nissa in play. Pretty sure Oath is working usually, so here were the * of Nissa in play. Pretty sure Oath is working usually, so here were the
* conditions in my game: * conditions in my game:
* <p> * <p>
* -Cast Dark Petition with spell mastery -Attempt to cast Nissa, Voice of * 1. Cast Dark Petition with spell mastery
* Zendikar using the triple black mana from Dark Petition * 2. Attempt to cast Nissa, Voice of Zendikar using the triple black mana from Dark Petition
*/ */
@Test @Test
public void testOathOfNissaWithDarkPetition() { public void testOathOfNissaWithDarkPetition() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
// When Oath of Nissa enters the battlefield, look at the top three cards of your library. You may reveal a creature, land, or planeswalker card from among them and put it into your hand. Put the rest on the bottom of your library in any order. // When Oath of Nissa enters the battlefield, look at the top three cards of your library.
// You may reveal a creature, land, or planeswalker card from among them and put it into your hand.
// Put the rest on the bottom of your library in any order.
// You may spend mana as though it were mana of any color to cast planeswalker spells. // You may spend mana as though it were mana of any color to cast planeswalker spells.
addCard(Zone.BATTLEFIELD, playerA, "Oath of Nissa"); addCard(Zone.BATTLEFIELD, playerA, "Oath of Nissa");
addCard(Zone.GRAVEYARD, playerA, "Lightning Bolt", 2); addCard(Zone.GRAVEYARD, playerA, "Lightning Bolt", 2);
@ -97,7 +99,8 @@ public class SpendOtherManaTest extends CardTestPlayerBase {
addCard(Zone.LIBRARY, playerA, "Nissa, Voice of Zendikar"); // {1}{G}{G} addCard(Zone.LIBRARY, playerA, "Nissa, Voice of Zendikar"); // {1}{G}{G}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dark Petition"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dark Petition");
setChoice(playerA, "Nissa, Voice of Zendikar"); addTarget(playerA, "Nissa, Voice of Zendikar");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nissa, Voice of Zendikar"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nissa, Voice of Zendikar");
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);

View file

@ -11,21 +11,21 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*/ */
public class ImprisonedInTheMoonTest extends CardTestPlayerBase { public class ImprisonedInTheMoonTest extends CardTestPlayerBase {
/* /**
* Reported bug: Urza land enchanted with Imprisoned In the Moon incorrectly makes it so other Urza lands only tap for 1 <> . * Reported bug: Urza land enchanted with Imprisoned In the Moon incorrectly makes it so other Urza lands only tap for 1 <>.
* *
* Card ruling: https://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=414360 * Card ruling: https://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=414360
* If the enchanted permanent is a land and has land types, it retains those types even though it loses any intrinsic mana abilities associated with them. * If the enchanted permanent is a land and has land types, it retains those types even though it loses any intrinsic mana abilities associated with them.
* For example, a Plains enchanted by Imprisoned in the Moon is still a Plains, but it can't tap for {W}, only for {C}. * For example, a Plains enchanted by Imprisoned in the Moon is still a Plains, but it can't tap for {W}, only for {C}.
*/ */
@Test @Test
public void testEnchantUrzaLand() { public void testEnchantUrzaLand() {
// Imprisoned in the Moon - Enchantment - Aura - {2}{U} // Imprisoned in the Moon - Enchantment - Aura - {2}{U}
// Enchant creature, land, or planeswalker // Enchant creature, land, or planeswalker
// Enchanted permanent is a colorless land with "Tap: Add Colorless" and loses all other card types and abilities. // Enchanted permanent is a colorless land with "Tap: Add Colorless" and loses all other card types and abilities.
addCard(Zone.HAND, playerA, "Imprisoned in the Moon", 1); addCard(Zone.HAND, playerA, "Imprisoned in the Moon", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3); addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.BATTLEFIELD, playerB, "Urza's Mine", 1); addCard(Zone.BATTLEFIELD, playerB, "Urza's Mine", 1);
addCard(Zone.BATTLEFIELD, playerB, "Urza's Tower", 1); addCard(Zone.BATTLEFIELD, playerB, "Urza's Tower", 1);
addCard(Zone.BATTLEFIELD, playerB, "Urza's Power Plant", 1); addCard(Zone.BATTLEFIELD, playerB, "Urza's Power Plant", 1);
@ -36,14 +36,13 @@ public class ImprisonedInTheMoonTest extends CardTestPlayerBase {
addTarget(playerA, "Urza's Mine"); addTarget(playerA, "Urza's Mine");
// 6 total mana available - 3 from Tower, 2 from Powerplant, 1 from enchanted Mine // 6 total mana available - 3 from Tower, 2 from Powerplant, 1 from enchanted Mine
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Wurmcoil Engine"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Wurmcoil Engine");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Bonesplitter"); checkPlayableAbility("Can't cast Bonesplitter", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cast Bonesplitter", false);
setStopAt(2, PhaseStep.BEGIN_COMBAT); setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertPermanentCount(playerA, "Imprisoned in the Moon", 1); assertPermanentCount(playerA, "Imprisoned in the Moon", 1);
assertPermanentCount(playerB, "Wurmcoil Engine", 1); assertPermanentCount(playerB, "Wurmcoil Engine", 1);
assertHandCount(playerB,"Wurmcoil Engine", 0); assertHandCount(playerB,"Wurmcoil Engine", 0);
assertHandCount(playerB, "Bonesplitter", 1); // should never be cast - wurmcoil uses up all mana
assertPermanentCount(playerB, "Bonesplitter", 0);
} }
} }

View file

@ -83,10 +83,10 @@ public class LoosingAbilitiesTest extends CardTestPlayerBase {
} }
/** /**
* Yixlid Jailer works incorrectly with reanimation spelss - I cast Unearth * Yixlid Jailer works incorrectly with reanimation spels - I cast Unearth
* targeting Seasoned Pyromancer with a Yixlid Jailer in play, but didnt get * targeting Seasoned Pyromancer with a Yixlid Jailer in play, but didnt get
* the Pyromancer's ETB trigger. This is a bug as Jailer only affaects cards * the Pyromancer's ETB trigger.
* when they are on the battle field * This is a bug as Jailer only affaects cards when they are on the battlefield.
*/ */
@Test @Test
public void testYixlidJailerAndETBEffects() { public void testYixlidJailerAndETBEffects() {
@ -103,9 +103,14 @@ public class LoosingAbilitiesTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Unearth", 1); // Sorcery {B} addCard(Zone.HAND, playerB, "Unearth", 1); // Sorcery {B}
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1); addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1);
setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yixlid Jailer"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yixlid Jailer");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Unearth"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Unearth");
// Target card for Unearth
addTarget(playerB, "Seasoned Pyromancer");
// Discard 2 cards for Seasoned Pyromancer
setChoice(playerB, "Lightning Bolt^Lightning Bolt"); setChoice(playerB, "Lightning Bolt^Lightning Bolt");
setStopAt(2, PhaseStep.BEGIN_COMBAT); setStopAt(2, PhaseStep.BEGIN_COMBAT);

View file

@ -16,11 +16,12 @@ public class SerraAscendantTest extends CardTestPlayerBase {
/** /**
* The game goes on; they play Serra Ascendant on turn one, pass the * The game goes on; they play Serra Ascendant on turn one, pass the
* turn, you play your newly unbanned Wild Nacatl with a Stomping Ground and * turn, you play your newly unbanned Wild Nacatl with a Stomping Ground and
* also pass the turn. On turn 2, they cast a Martyr of Sands and sacrifice * also pass the turn.
* it, revealing 3 white cards to gain 9 life and end up at 29. They go to * On turn 2, they cast a Martyr of Sands and sacrifice it,
* the combat phase, declare Serra as an attacker, and you happily block * revealing 3 white cards to gain 9 life and end up at 29.
* him, thinking that this is such a bad move from them. After the damage is * They go to the combat phase, declare Serra as an attacker, and you happily block
* dealt, the Serra is still there, bigger than ever. * him, thinking that this is such a bad move from them.
* After the damage is dealt, the Serra is still there, bigger than ever.
*/ */
@Test @Test
public void testSilence() { public void testSilence() {
@ -44,7 +45,9 @@ public class SerraAscendantTest extends CardTestPlayerBase {
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains"); playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Martyr of Sands"); castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Martyr of Sands");
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}, You may reveal X white cards from your hand"); activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}, You may reveal X white cards from your hand");
setChoice(playerA,"X=3"); setChoice(playerA, "Silvercoat Lion");
setChoice(playerA, "Silvercoat Lion");
setChoice(playerA, "Silvercoat Lion");
attack(3, playerA, "Serra Ascendant"); attack(3, playerA, "Serra Ascendant");
block(3, playerB, "Wild Nacatl", "Serra Ascendant"); block(3, playerB, "Wild Nacatl", "Serra Ascendant");
@ -62,7 +65,5 @@ public class SerraAscendantTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Serra Ascendant", 1); assertPermanentCount(playerA, "Serra Ascendant", 1);
assertPowerToughness(playerA, "Serra Ascendant", 6, 6); assertPowerToughness(playerA, "Serra Ascendant", 6, 6);
} }
} }

View file

@ -7,6 +7,10 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
* {@link mage.cards.s.Silence Silence}
* {W}
* Instant
* Your opponents cant cast spells this turn.
* *
* @author LevelX2 * @author LevelX2
*/ */
@ -23,15 +27,11 @@ public class SilenceTest extends CardTestPlayerBase {
castSpell(2, PhaseStep.UPKEEP, playerA, "Silence"); castSpell(2, PhaseStep.UPKEEP, playerA, "Silence");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Silvercoat Lion"); checkPlayableAbility("Can't cast spell", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cast Silvercoat", false);
setStopAt(2, PhaseStep.BEGIN_COMBAT); setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertGraveyardCount(playerA, "Silence", 1); assertGraveyardCount(playerA, "Silence", 1);
assertHandCount(playerB, "Silvercoat Lion", 1);
assertPermanentCount(playerB, "Silvercoat Lion", 0);
} }
} }

View file

@ -2,6 +2,7 @@ package org.mage.test.cards.continuous;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -20,7 +21,18 @@ public class SplitSecondTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Counterspell", "Sudden Shock"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Counterspell", "Sudden Shock");
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute();
// TODO: Needed, see https://github.com/magefree/mage/issues/8973
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerA must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about trying to use Counterspell, but got:\n" + e.getMessage());
}
}
assertHandCount(playerA, "Counterspell", 1); assertHandCount(playerA, "Counterspell", 1);
assertGraveyardCount(playerA, "Sudden Shock", 1); assertGraveyardCount(playerA, "Sudden Shock", 1);

View file

@ -66,10 +66,10 @@ public class PlayCardsFromGraveyardTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, "Ancestral Vision"); addCard(Zone.GRAVEYARD, playerA, "Ancestral Vision");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yawgmoth's Will"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yawgmoth's Will");
// you may not suspend it from graveyard // You may not suspend it from graveyard
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Suspend"); checkPlayableAbility("Can't suspend", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Suspend", false);
// It may not be possible to cast it from graveyard // It may not be possible to cast it from graveyard
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ancestral Vision"); checkPlayableAbility("Can't cast 0 cost cards", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Ancestral", false);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
@ -85,5 +85,4 @@ public class PlayCardsFromGraveyardTest extends CardTestPlayerBase {
assertLife(playerA, 20); assertLife(playerA, 20);
assertLife(playerB, 20); assertLife(playerB, 20);
} }
} }

View file

@ -7,17 +7,18 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
* {@link mage.cards.i.IsochronScepter Isochron Scepter}
* {2}
* Artifact
* Imprint When Isochron Scepter enters the battlefield, you may exile an instant card with mana value 2 or less from your hand.
* {2}, {T}: You may copy the exiled card. If you do, you may cast the copy without paying its mana cost.
* *
* @author BetaSteward * @author BetaSteward
*/ */
public class IsochronScepterTest extends CardTestPlayerBase { public class IsochronScepterTest extends CardTestPlayerBase {
/** /**
* Isochron Scepter Artifact, 2 (2) Imprint When Isochron Scepter enters * Test that the imprinting works.
* the battlefield, you may exile an instant card with converted mana cost 2
* or less from your hand. {2}, {T}: You may copy the exiled card. If you
* do, you may cast the copy without paying its mana cost.
*
*/ */
@Test @Test
public void testImprint() { public void testImprint() {
@ -25,8 +26,11 @@ public class IsochronScepterTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Isochron Scepter"); addCard(Zone.HAND, playerA, "Isochron Scepter");
addCard(Zone.HAND, playerA, "Lightning Bolt"); addCard(Zone.HAND, playerA, "Lightning Bolt");
setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
addTarget(playerA, "Lightning Bolt"); setChoice(playerA, "Yes");
setChoice(playerA, "Lightning Bolt");
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
@ -34,9 +38,11 @@ public class IsochronScepterTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Isochron Scepter", 1); assertPermanentCount(playerA, "Isochron Scepter", 1);
assertExileCount("Lightning Bolt", 1); assertExileCount("Lightning Bolt", 1);
assertLife(playerB, 20); assertLife(playerB, 20);
} }
/**
* Test that the exiled card can be cpied.
*/
@Test @Test
public void testCopyCard() { public void testCopyCard() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
@ -68,7 +74,8 @@ public class IsochronScepterTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Lightning Bolt"); addCard(Zone.HAND, playerA, "Lightning Bolt");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
addTarget(playerA, "Lightning Bolt"); setChoice(playerA, "Lightning Bolt");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2}, {T}:"); activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2}, {T}:");
setChoice(playerA, true); setChoice(playerA, true);
setChoice(playerA, false); setChoice(playerA, false);
@ -105,7 +112,7 @@ public class IsochronScepterTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
addTarget(playerA, "Angel's Grace"); setChoice(playerA, "Angel's Grace");
attack(2, playerB, "Dross Crocodile"); attack(2, playerB, "Dross Crocodile");
attack(2, playerB, "Dross Crocodile"); attack(2, playerB, "Dross Crocodile");
@ -142,7 +149,6 @@ public class IsochronScepterTest extends CardTestPlayerBase {
* Resolving a Silence cast from exile via Isochron Scepter during my * Resolving a Silence cast from exile via Isochron Scepter during my
* opponent's upkeep does not prevent that opponent from casting spells that * opponent's upkeep does not prevent that opponent from casting spells that
* turn. * turn.
*
*/ */
@Test @Test
public void testSilence() { public void testSilence() {
@ -154,13 +160,13 @@ public class IsochronScepterTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); addCard(Zone.HAND, playerB, "Silvercoat Lion", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
addTarget(playerA, "Silence"); setChoice(playerA, "Silence");
activateAbility(2, PhaseStep.UPKEEP, playerA, "{2}, {T}:"); activateAbility(2, PhaseStep.UPKEEP, playerA, "{2}, {T}:");
setChoice(playerA, true); setChoice(playerA, true);
setChoice(playerA, true); setChoice(playerA, true);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Silvercoat Lion"); checkPlayableAbility("Can't cast Silvercoat", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cast Silvercoat", false);
setStopAt(2, PhaseStep.BEGIN_COMBAT); setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute(); execute();

View file

@ -56,14 +56,10 @@ public class FluctuatorTest extends CardTestPlayerBase {
// Cycling abilities you activate cost you up to {2} less to activate. // Cycling abilities you activate cost you up to {2} less to activate.
addCard(Zone.BATTLEFIELD, playerA, "Fluctuator"); addCard(Zone.BATTLEFIELD, playerA, "Fluctuator");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling"); checkPlayableAbility("Can't cycle", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling", false);
setChoice(playerA, "2"); // reduce 1 generic mana
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertGraveyardCount(playerA, "Akroma's Vengeance", 0);
assertHandCount(playerA, 1);
} }
/** /**

View file

@ -73,12 +73,12 @@ public class OptionalSacrificeTests extends CardTestPlayerBase {
*/ */
@Test @Test
public void testGlintHawkNoArtifactControlled() { public void testGlintHawkNoArtifactControlled() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.HAND, playerA, "Glint Hawk"); addCard(Zone.HAND, playerA, "Glint Hawk");
setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Glint Hawk"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Glint Hawk");
setChoice(playerA, false);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
@ -151,12 +151,12 @@ public class OptionalSacrificeTests extends CardTestPlayerBase {
*/ */
@Test @Test
public void testDrakeFamiliarNoEnchantmentControlled() { public void testDrakeFamiliarNoEnchantmentControlled() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 2); addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.HAND, playerA, "Drake Familiar"); addCard(Zone.HAND, playerA, "Drake Familiar");
setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Drake Familiar"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Drake Familiar");
setChoice(playerA, false);
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();

View file

@ -84,17 +84,16 @@ public class SpreadingSeasTest extends CardTestPlayerBase {
} }
/** /**
* https://github.com/magefree/mage/issues/4529 Some spell effects that * https://github.com/magefree/mage/issues/4529
* effect the use of mana abilities on lands are inoperative. Example * Some spell effects that effect the use of mana abilities on lands are inoperative.
* Spreading Seas transforms enchanted land into an island and it loses all * Example, Spreading Seas transforms enchanted land into an island and it loses all
* other abilities. The AI does not recognize this and is able to use all * other abilities.
* abilities of the enchanted land including all previous mana abilities and * The AI does not recognize this and is able to use all abilities of the enchanted
* activated abilities, in addition to now also being an island due to * land including all previous mana abilities and activated abilities,
* Spreading Sea's effect. * in addition to now also being an island due to Spreading Sea's effect.
*/ */
@Test @Test
public void testSpreadingRemovesOtherAbilities() { public void testSpreadingRemovesOtherAbilities() {
// Enchant land // Enchant land
// When Spreading Seas enters the battlefield, draw a card. // When Spreading Seas enters the battlefield, draw a card.
// Enchanted land is an Island. // Enchanted land is an Island.
@ -107,7 +106,8 @@ public class SpreadingSeasTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spreading Seas", "Kher Keep"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spreading Seas", "Kher Keep");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{1}{R}"); // Ability should not be available // Kher Keep loses all abilit
checkPlayableAbility("", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{1}{R}", false);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();

View file

@ -20,7 +20,7 @@ public class GainProtectionTest extends CardTestPlayerBase {
setChoice(playerA, "Green"); setChoice(playerA, "Green");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Apostle's Blessing", "Elite Vanguard"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Apostle's Blessing", "Elite Vanguard");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Titanic Growth", "Elite Vanguard"); checkPlayableAbility("Can't cast Titanic", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast Titanic", false);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
@ -74,13 +74,15 @@ public class GainProtectionTest extends CardTestPlayerBase {
public void testGainProtectionByEnchantment() { public void testGainProtectionByEnchantment() {
addCard(Zone.BATTLEFIELD, playerB, "Plains", 5); addCard(Zone.BATTLEFIELD, playerB, "Plains", 5);
// Flying // Flying
// When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control. // When Brago, King Eternal deals combat damage to a player,
// exile any number of target nonland permanents you control,
// then return those cards to the battlefield under their owner's control.
addCard(Zone.BATTLEFIELD, playerB, "Brago, King Eternal"); addCard(Zone.BATTLEFIELD, playerB, "Brago, King Eternal");
// Enchant creature // Enchant creature
// When Pentarch Ward enters the battlefield, draw a card. // When Pentarch Ward enters the battlefield, draw a card.
// As Pentarch Ward enters the battlefield, choose a color. // As Pentarch Ward enters the battlefield, choose a color.
// Enchanted creature has protection from the chosen color. This effect doesn't remove Pentarch Ward. // Enchanted creature has protection from the chosen color. This effect doesn't remove Pentarch Ward.
addCard(Zone.HAND, playerB, "Pentarch Ward");// "{2}{W}" addCard(Zone.HAND, playerB, "Pentarch Ward"); // "{2}{W}"
// Enchant creature // Enchant creature
// Enchanted creature gets +1/+1 and has "Whenever this creature attacks, tap target creature defending player controls." // Enchanted creature gets +1/+1 and has "Whenever this creature attacks, tap target creature defending player controls."
addCard(Zone.HAND, playerB, "Grasp of the Hieromancer"); addCard(Zone.HAND, playerB, "Grasp of the Hieromancer");
@ -88,9 +90,9 @@ public class GainProtectionTest extends CardTestPlayerBase {
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Pentarch Ward", "Brago, King Eternal"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Pentarch Ward", "Brago, King Eternal");
setChoice(playerB, "White"); setChoice(playerB, "White");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Grasp of the Hieromancer", "Brago, King Eternal"); checkPlayableAbility("Has protection", 2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Cast Grasp", false);
setStopAt(2, PhaseStep.BEGIN_COMBAT); setStopAt(2, PhaseStep.END_TURN);
execute(); execute();
assertPermanentCount(playerB, "Pentarch Ward", 1); assertPermanentCount(playerB, "Pentarch Ward", 1);
@ -99,29 +101,32 @@ public class GainProtectionTest extends CardTestPlayerBase {
} }
/** /**
* Pentarch Ward on Brago naming white. Brago combat trigger resolves * Pentarch Ward on Brago naming white.
* blinking Pentarch Ward. Brago retains protection from white even though * Brago combat trigger resolves blinking Pentarch Ward.
* Pentarch Ward is now exiled, making him unable to be re-enchanted by * Brago retains protection from white even though Pentarch Ward is now exiled,
* Pentarch Ward. * making him unable to be re-enchanted by Pentarch Ward.
*/ */
@Test @Test
public void testGainLooseProtectionByEnchantment() { public void testGainLooseProtectionByEnchantment() {
addCard(Zone.BATTLEFIELD, playerB, "Plains", 3); addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
// Flying // Flying
// When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control. // When Brago, King Eternal deals combat damage to a player,
// exile any number of target nonland permanents you control,
// then return those cards to the battlefield under their owner's control.
addCard(Zone.BATTLEFIELD, playerB, "Brago, King Eternal"); addCard(Zone.BATTLEFIELD, playerB, "Brago, King Eternal");
// Enchant creature // Enchant creature
// When Pentarch Ward enters the battlefield, draw a card. // When Pentarch Ward enters the battlefield, draw a card.
// As Pentarch Ward enters the battlefield, choose a color. // As Pentarch Ward enters the battlefield, choose a color.
// Enchanted creature has protection from the chosen color. This effect doesn't remove Pentarch Ward. // Enchanted creature has protection from the chosen color.
addCard(Zone.HAND, playerB, "Pentarch Ward");// "{2}{W}" // This effect doesn't remove Pentarch Ward.
addCard(Zone.HAND, playerB, "Pentarch Ward"); // "{2}{W}"
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Pentarch Ward", "Brago, King Eternal"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Pentarch Ward", "Brago, King Eternal");
setChoice(playerB, "White"); setChoice(playerB, "White");
attack(2, playerB, "Brago, King Eternal"); attack(2, playerB, "Brago, King Eternal");
addTarget(playerB, "Pentarch Ward"); addTarget(playerB, "Pentarch Ward");
addTarget(playerB, "Brago, King Eternal"); setChoice(playerB, "Brago, King Eternal");
setStopAt(2, PhaseStep.END_COMBAT); setStopAt(2, PhaseStep.END_COMBAT);
execute(); execute();

View file

@ -3,6 +3,7 @@ package org.mage.test.cards.replacement;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -134,8 +135,7 @@ public class DoublingSeasonTest extends CardTestPlayerBase {
} }
/** /**
* Doubling Season doesn't create two tokens from opponent's Rite of Raging * Doubling Season doesn't create two tokens from opponent's Rite of Raging Storm
* Storm
*/ */
@Test @Test
public void testDoubleRiteOfRagingStorm() { public void testDoubleRiteOfRagingStorm() {
@ -149,8 +149,6 @@ public class DoublingSeasonTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rite of the Raging Storm"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rite of the Raging Storm");
attack(2, playerB, "Lightning Rager"); // Can't attack
attack(3, playerA, "Lightning Rager"); attack(3, playerA, "Lightning Rager");
attack(3, playerA, "Lightning Rager"); attack(3, playerA, "Lightning Rager");
@ -163,7 +161,6 @@ public class DoublingSeasonTest extends CardTestPlayerBase {
assertLife(playerB, 10); assertLife(playerB, 10);
assertLife(playerA, 20); assertLife(playerA, 20);
} }
@Test @Test
@ -182,15 +179,20 @@ public class DoublingSeasonTest extends CardTestPlayerBase {
attack(2, playerB, "Lightning Rager:1"); // Can't attack attack(2, playerB, "Lightning Rager:1"); // Can't attack
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerB must have 0 actions but found 2")) {
Assert.fail("Should have thrown error about cannot attack, but got:\n" + e.getMessage());
}
}
assertPermanentCount(playerA, "Rite of the Raging Storm", 1); assertPermanentCount(playerA, "Rite of the Raging Storm", 1);
assertPermanentCount(playerB, "Lightning Rager", 2); assertPermanentCount(playerB, "Lightning Rager", 2);
assertLife(playerB, 20);
assertLife(playerA, 20);
} }
/** /**

View file

@ -14,7 +14,6 @@ public class PanharmoniconTest extends CardTestPlayerBase {
/** /**
* Check that Panharmonicon adds EtB triggers correctly. * Check that Panharmonicon adds EtB triggers correctly.
*
*/ */
@Test @Test
public void testAddsTrigger() { public void testAddsTrigger() {
@ -37,7 +36,6 @@ public class PanharmoniconTest extends CardTestPlayerBase {
/** /**
* Check that Panharmonicon doesn't add to opponents' triggers. * Check that Panharmonicon doesn't add to opponents' triggers.
*
*/ */
@Test @Test
public void testDoesntAddOpponentsTriggers() { public void testDoesntAddOpponentsTriggers() {
@ -60,7 +58,6 @@ public class PanharmoniconTest extends CardTestPlayerBase {
/** /**
* Check that Panharmonicon doesn't add to lands triggers. * Check that Panharmonicon doesn't add to lands triggers.
*
*/ */
@Test @Test
public void testDoesntAddLandsTriggers() { public void testDoesntAddLandsTriggers() {
@ -79,7 +76,6 @@ public class PanharmoniconTest extends CardTestPlayerBase {
/** /**
* Check that Panharmonicon doesn't add to non-permanents triggers. * Check that Panharmonicon doesn't add to non-permanents triggers.
*
*/ */
@Test @Test
public void testDoesntAddNonPermanentsTriggers() { public void testDoesntAddNonPermanentsTriggers() {
@ -91,9 +87,11 @@ public class PanharmoniconTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Scion of Ugin"); addCard(Zone.HAND, playerA, "Scion of Ugin");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6); addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scion of Ugin"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scion of Ugin");
setChoice(playerA, false); // Return Bladewing's Thrall from your graveyard to the battlefield? setChoice(playerA, false); // Return Bladewing's Thrall from your graveyard to the battlefield?
setChoice(playerA, true); // Should not get run since there is only one trigger. // There should only be one trigger, so no need for another choice
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute(); execute();

View file

@ -3,6 +3,7 @@ package org.mage.test.cards.restriction;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -34,7 +35,17 @@ public class CantAttackTest extends CardTestPlayerBase {
attack(3, playerA, "Myr Enforcer"); attack(3, playerA, "Myr Enforcer");
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
execute();
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerB must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack, but got:\n" + e.getMessage());
}
}
assertLife(playerA, 8); // 8 + 4 assertLife(playerA, 8); // 8 + 4
assertLife(playerB, 14); // 4 + 2 assertLife(playerB, 14); // 4 + 2
@ -53,15 +64,25 @@ public class CantAttackTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2 addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2
addCard(Zone.BATTLEFIELD, playerB, "Harbor Serpent"); // 5/5 addCard(Zone.BATTLEFIELD, playerB, "Harbor Serpent"); // 5/5
attack(2, playerB, "Harbor Serpent"); attack(2, playerB, "Harbor Serpent"); // Can't attack since there are only 4 Islands
attack(2, playerB, "Silvercoat Lion"); attack(2, playerB, "Silvercoat Lion");
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Island"); playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Island");
attack(3, playerA, "Harbor Serpent"); attack(3, playerA, "Harbor Serpent"); // Should be able to attack
attack(3, playerA, "Silvercoat Lion"); attack(3, playerA, "Silvercoat Lion");
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
execute();
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerB must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack, but got:\n" + e.getMessage());
}
}
assertLife(playerB, 13); assertLife(playerB, 13);
assertLife(playerA, 18); assertLife(playerA, 18);
@ -82,7 +103,17 @@ public class CantAttackTest extends CardTestPlayerBase {
attack(2, playerB, "Silvercoat Lion", playerA); attack(2, playerB, "Silvercoat Lion", playerA);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerB must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack, but got:\n" + e.getMessage());
}
}
assertLife(playerA, 20); assertLife(playerA, 20);
@ -114,7 +145,10 @@ public class CantAttackTest extends CardTestPlayerBase {
assertTapped("Battle-Mad Ronin", false); assertTapped("Battle-Mad Ronin", false);
} }
// Orzhov Advokist's ability does not work. Your opponents get the counters but they can still attack you. /**
* Orzhov Advokist's ability does not work.
* Your opponents get the counters but they can still attack you.
*/
@Test @Test
public void testOrzhovAdvokist() { public void testOrzhovAdvokist() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
@ -127,11 +161,20 @@ public class CantAttackTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Orzhov Advokist"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Orzhov Advokist");
setChoice(playerA, true); setChoice(playerA, true);
setChoice(playerB, true); setChoice(playerB, true);
attack(2, playerB, "Silvercoat Lion"); attack(2, playerB, "Silvercoat Lion"); // Can't attack since they put a +1/+1 counter
attack(4, playerB, "Silvercoat Lion"); attack(4, playerB, "Silvercoat Lion");
setStopAt(4, PhaseStep.POSTCOMBAT_MAIN); setStopAt(4, PhaseStep.POSTCOMBAT_MAIN);
execute(); try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerB must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack, but got:\n" + e.getMessage());
}
}
assertPermanentCount(playerA, "Orzhov Advokist", 1); assertPermanentCount(playerA, "Orzhov Advokist", 1);
assertPowerToughness(playerA, "Orzhov Advokist", 3, 6); assertPowerToughness(playerA, "Orzhov Advokist", 3, 6);
@ -140,8 +183,8 @@ public class CantAttackTest extends CardTestPlayerBase {
assertPowerToughness(playerB, "Silvercoat Lion", 4, 4); assertPowerToughness(playerB, "Silvercoat Lion", 4, 4);
} }
/* /**
Reported bug: Medomai was able to attack on an extra turn when cheated into play. * Reported bug: Medomai was able to attack on an extra turn when cheated into play.
*/ */
@Test @Test
public void testMedomaiShouldNotAttackOnExtraTurns() { public void testMedomaiShouldNotAttackOnExtraTurns() {
@ -157,9 +200,14 @@ public class CantAttackTest extends CardTestPlayerBase {
/* /*
Cauldron Dance {4}{B}{R} Instant Cauldron Dance {4}{B}{R} Instant
Cast Cauldron Dance only during combat. Cast Cauldron Dance only during combat.
Return target creature card from your graveyard to the battlefield. That creature gains haste. Return it to your hand at the beginning of the next end step. Return target creature card from your graveyard to the battlefield.
You may put a creature card from your hand onto the battlefield. That creature gains haste. Its controller sacrifices it at the beginning of the next end step. That creature gains haste.
Return it to your hand at the beginning of the next end step.
You may put a creature card from your hand onto the battlefield.
That creature gains haste.
Its controller sacrifices it at the beginning of the next end step.
*/ */
String cDance = "Cauldron Dance"; String cDance = "Cauldron Dance";
String dBlade = "Doom Blade"; // {1}{B} instant destroy target creature String dBlade = "Doom Blade"; // {1}{B} instant destroy target creature
@ -178,9 +226,19 @@ public class CantAttackTest extends CardTestPlayerBase {
addTarget(playerA, medomai); addTarget(playerA, medomai);
attack(2, playerA, medomai); attack(2, playerA, medomai);
// medomai should not have been allowed to attack, but returned to hand at beginning of next end step still // Medomai should not have been allowed to attack, but returned to hand at beginning of next end step still
setStopAt(2, PhaseStep.END_TURN); setStopAt(2, PhaseStep.END_TURN);
execute();
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerA must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack, but got:\n" + e.getMessage());
}
}
assertLife(playerB, 16); // one hit from medomai assertLife(playerB, 16); // one hit from medomai
assertGraveyardCount(playerA, dBlade, 1); assertGraveyardCount(playerA, dBlade, 1);
@ -217,7 +275,17 @@ public class CantAttackTest extends CardTestPlayerBase {
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, eFirecraft, playerB); castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, eFirecraft, playerB);
setStopAt(2, PhaseStep.END_TURN); setStopAt(2, PhaseStep.END_TURN);
execute();
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerA must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack, but got:\n" + e.getMessage());
}
}
assertLife(playerB, 12); // 1 hit from medomai and firecraft = 8 damage assertLife(playerB, 12); // 1 hit from medomai and firecraft = 8 damage
assertGraveyardCount(playerA, eFirecraft, 1); assertGraveyardCount(playerA, eFirecraft, 1);
@ -394,7 +462,17 @@ public class CantAttackTest extends CardTestPlayerBase {
attack(3, playerA, "Admiral Beckett Brass"); // Can't attack attack(3, playerA, "Admiral Beckett Brass"); // Can't attack
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
execute();
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerA must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack, but got:\n" + e.getMessage());
}
}
assertPermanentCount(playerA, "Opportunistic Dragon", 1); assertPermanentCount(playerA, "Opportunistic Dragon", 1);
assertPermanentCount(playerA, "Admiral Beckett Brass", 1); assertPermanentCount(playerA, "Admiral Beckett Brass", 1);
@ -430,7 +508,17 @@ public class CantAttackTest extends CardTestPlayerBase {
attack(4, playerB, "Admiral Beckett Brass"); // Can attack again attack(4, playerB, "Admiral Beckett Brass"); // Can attack again
setStopAt(4, PhaseStep.POSTCOMBAT_MAIN); setStopAt(4, PhaseStep.POSTCOMBAT_MAIN);
execute();
try {
execute();
assertAllCommandsUsed();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().contains("Player PlayerA must have 0 actions but found 1")) {
Assert.fail("Should have thrown error about not being able to attack, but got:\n" + e.getMessage());
}
}
assertGraveyardCount(playerB, "Terror", 1); assertGraveyardCount(playerB, "Terror", 1);
assertGraveyardCount(playerA, "Opportunistic Dragon", 1); assertGraveyardCount(playerA, "Opportunistic Dragon", 1);

View file

@ -6,14 +6,26 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
* {@link mage.cards.d.DuskDawn Dusk}
* {2}{W}{W}
* Sorcery
* Destroy all creatures with power 3 or greater.
*
* {@link mage.cards.d.DuskDawn Dawn}
* {3}{W}{W}
* Sorcery
* Aftermath (Cast this spell only from your graveyard. Then exile it.)
* Return all creature cards with power 2 or less from your graveyard to your hand.
* *
* @author Quercitron * @author Quercitron
*/ */
public class DuskDawnTest extends CardTestPlayerBase { public class DuskDawnTest extends CardTestPlayerBase {
/**
* Test that you can properly cast Dusk (regular part) from hand
*/
@Test @Test
public void testCastDusk() { public void testCastDusk() {
//Cast dusk from hand
addCard(Zone.BATTLEFIELD, playerB, "Watchwolf"); addCard(Zone.BATTLEFIELD, playerB, "Watchwolf");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
addCard(Zone.HAND, playerA, "Dusk // Dawn"); addCard(Zone.HAND, playerA, "Dusk // Dawn");
@ -22,19 +34,24 @@ public class DuskDawnTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
assertTappedCount("Plains", true, 4); // check that we paid the right side's mana // check that we paid the right side's mana
assertTappedCount("Plains", true, 4);
assertPermanentCount(playerB, "Watchwolf", 0); assertPermanentCount(playerB, "Watchwolf", 0);
assertGraveyardCount(playerB, "Watchwolf", 1); assertGraveyardCount(playerB, "Watchwolf", 1);
assertGraveyardCount(playerA, "Dusk // Dawn", 1); assertGraveyardCount(playerA, "Dusk // Dawn", 1);
} }
/**
* Test that you cannot cast Dusk (Reguar part) from graveyard.
*/
@Test @Test
public void testCastDuskFromGraveyardFail() { public void testCastDuskFromGraveyardFail() {
//Fail to cast dusk from graveyard
addCard(Zone.BATTLEFIELD, playerB, "Watchwolf"); addCard(Zone.BATTLEFIELD, playerB, "Watchwolf");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.GRAVEYARD, playerA, "Dusk // Dawn"); addCard(Zone.GRAVEYARD, playerA, "Dusk // Dawn");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dusk");
checkPlayableAbility("Can't cast Dusk", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dusk", false);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
@ -44,12 +61,11 @@ public class DuskDawnTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Dusk // Dawn", 1); assertGraveyardCount(playerA, "Dusk // Dawn", 1);
} }
/**
* Test that you can cast Dawn (Aftermath part) from graveyard.
*/
@Test @Test
public void testCastDawnFromGraveyard() { public void testCastDawnFromGraveyard() {
// Dusk
// Destroy all creatures with power 3 or greater.
// Dawn
// Return all creature cards with power less than or equal to 2 from your graveyard to your hand.
addCard(Zone.GRAVEYARD, playerA, "Dusk // Dawn"); addCard(Zone.GRAVEYARD, playerA, "Dusk // Dawn");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
addCard(Zone.GRAVEYARD, playerA, "Devoted Hero"); addCard(Zone.GRAVEYARD, playerA, "Devoted Hero");
@ -59,34 +75,32 @@ public class DuskDawnTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
// Dusk dawn should have been cast and exiled // Dusk // Dawn should have been cast and exiled
// devoted hero should be in the hand
// watchwolf should still be in the yard
assertHandCount(playerA, "Devoted Hero", 1);
assertGraveyardCount(playerA, "Devoted Hero", 0);
assertGraveyardCount(playerA, "Watchwolf", 1);
assertExileCount(playerA, "Dusk // Dawn", 1); assertExileCount(playerA, "Dusk // Dawn", 1);
assertGraveyardCount(playerA, "Dusk // Dawn", 0); assertGraveyardCount(playerA, "Dusk // Dawn", 0);
// Devoted hero should be in the hand
assertHandCount(playerA, "Devoted Hero", 1);
assertGraveyardCount(playerA, "Devoted Hero", 0);
// Watchwolf should still be in the graveyard
assertGraveyardCount(playerA, "Watchwolf", 1);
} }
// Fail to cast Dawn (Aftermath part) from hand /**
* Test that you can't cast Dawn (Aftermath part) from hand.
*/
@Test @Test
public void testCastDawnFail() { public void testCastDawnFail() {
// Dusk {2}{W}{W}
// Destroy all creatures with power 3 or greater.
// Dawn {3}{W}{W}
// Return all creature cards with power less than or equal to 2 from your graveyard to your hand.
addCard(Zone.HAND, playerA, "Dusk // Dawn"); addCard(Zone.HAND, playerA, "Dusk // Dawn");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
addCard(Zone.GRAVEYARD, playerA, "Devoted Hero"); // Creature 1/2 {W} addCard(Zone.GRAVEYARD, playerA, "Devoted Hero"); // Creature 1/2 {W}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dawn");
checkPlayableAbility("Can't cast Dawn", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dawn", false);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
// Dusk dawn shouldn't have been cast and devoted hero should still be in the yard
assertHandCount(playerA, "Dusk // Dawn", 1); assertHandCount(playerA, "Dusk // Dawn", 1);
assertGraveyardCount(playerA, "Devoted Hero", 1);
} }
} }

View file

@ -6,6 +6,11 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
* {@link mage.cards.n.NephaliaAcademy Nephalia Academy}
* Land
* If a spell or ability an opponent controls causes you to discard a card,
* you may reveal that card and put it on top of your library instead of putting it anywhere else.
* {T}: Add {C}.
* *
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/ */
@ -18,9 +23,6 @@ public class NephaliaAcademyTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Duress", 1); addCard(Zone.HAND, playerA, "Duress", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
// Nephalia Academy - Land <>
// If a spell or ability an opponent controls causes you to discard a card,
// you may reveal that card and put it on top of your library instead of putting it anywhere else.
addCard(Zone.HAND, playerB, "Giant Growth", 1); // discard fodder addCard(Zone.HAND, playerB, "Giant Growth", 1); // discard fodder
addCard(Zone.BATTLEFIELD, playerB, "Nephalia Academy", 1); addCard(Zone.BATTLEFIELD, playerB, "Nephalia Academy", 1);
@ -43,9 +45,6 @@ public class NephaliaAcademyTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Duress", 1); addCard(Zone.HAND, playerA, "Duress", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
// Nephalia Academy - Land <>
// If a spell or ability an opponent controls causes you to discard a card,
// you may reveal that card and put it on top of your library instead of putting it anywhere else.
addCard(Zone.HAND, playerB, "Giant Growth", 1); // discard fodder addCard(Zone.HAND, playerB, "Giant Growth", 1); // discard fodder
addCard(Zone.BATTLEFIELD, playerB, "Nephalia Academy", 1); addCard(Zone.BATTLEFIELD, playerB, "Nephalia Academy", 1);
@ -62,10 +61,6 @@ public class NephaliaAcademyTest extends CardTestPlayerBase {
@Test @Test
public void testShouldNotApplyToOwnDiscardSpell() { public void testShouldNotApplyToOwnDiscardSpell() {
// Nephalia Academy - Land <>
// If a spell or ability an opponent controls causes you to discard a card,
// you may reveal that card and put it on top of your library instead of putting it anywhere else.
addCard(Zone.BATTLEFIELD, playerA, "Nephalia Academy", 1); addCard(Zone.BATTLEFIELD, playerA, "Nephalia Academy", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3); addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.HAND, playerA, "Memnite", 1); // discard fodder addCard(Zone.HAND, playerA, "Memnite", 1); // discard fodder
@ -74,9 +69,11 @@ public class NephaliaAcademyTest extends CardTestPlayerBase {
// Draw three cards. Then discard a card. // Draw three cards. Then discard a card.
addCard(Zone.HAND, playerA, "Sift", 1); addCard(Zone.HAND, playerA, "Sift", 1);
setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sift"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sift");
setChoice(playerA, true); // should not be given the option to use Nephalia Academy replacement effect
setChoice(playerA, "Memnite"); setChoice(playerA, "Memnite");
// should not be given the option to use Nephalia Academy replacement effect
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();

View file

@ -6,11 +6,19 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
* {@link mage.cards.k.KarfellHarbinger Karfell Harbinger}
* {1}{U}
* Creature Zombie Wizard
* {T}: Add {U}. Spend this mana only to foretell a card from your hand or cast an instant or sorcery spell.
*
* @author TheElk801 * @author TheElk801
*/ */
public class KarfellHarbingerTest extends CardTestPlayerBase { public class KarfellHarbingerTest extends CardTestPlayerBase {
/**
* Test that spending the money on Foretell works.
*/
@Test @Test
public void testForetellMana() { public void testForetellMana() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1); addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
@ -27,6 +35,9 @@ public class KarfellHarbingerTest extends CardTestPlayerBase {
assertHandCount(playerA, "Augury Raven", 0); assertHandCount(playerA, "Augury Raven", 0);
} }
/**
* Test that spending the mana on an instant works.
*/
@Test @Test
public void testSpellMana() { public void testSpellMana() {
addCard(Zone.BATTLEFIELD, playerA, "Karfell Harbinger"); addCard(Zone.BATTLEFIELD, playerA, "Karfell Harbinger");
@ -42,12 +53,15 @@ public class KarfellHarbingerTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Obsessive Search", 1); assertGraveyardCount(playerA, "Obsessive Search", 1);
} }
/**
* Test that you can't use the mana on something else.
*/
@Test @Test
public void testOtherMana() { public void testOtherMana() {
addCard(Zone.BATTLEFIELD, playerA, "Karfell Harbinger"); addCard(Zone.BATTLEFIELD, playerA, "Karfell Harbinger");
addCard(Zone.HAND, playerA, "Flying Men"); addCard(Zone.HAND, playerA, "Flying Men");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flying Men"); checkPlayableAbility("can't cast flying man", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Flying", false);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();

View file

@ -24,11 +24,10 @@ public class NeedleDropTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", playerA); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", playerA);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", "Hill Giant"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", "Hill Giant");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Needle Drop", playerA); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Needle Drop", playerA);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Needle Drop", playerB); // castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Needle Drop", playerB); // TODO: This should produce an error but doesn't (playerA isn't a valid target)
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Needle Drop", "Hill Giant"); castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Needle Drop", "Hill Giant");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Needle Drop", "Flying Men");
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
@ -36,7 +35,6 @@ public class NeedleDropTest extends CardTestPlayerBase {
assertLife(playerA, 17); assertLife(playerA, 17);
assertLife(playerB, 20); assertLife(playerB, 20);
assertPermanentCount(playerB, "Hill Giant", 0); assertPermanentCount(playerB, "Hill Giant", 0);
assertPermanentCount(playerB, "Flying Men", 1);
} }
@Test @Test
@ -51,8 +49,7 @@ public class NeedleDropTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", "Hill Giant"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", "Hill Giant");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Needle Drop", playerB); checkPlayableAbility("Can't Needle Drop", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Needle Drop", false);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Needle Drop", "Hill Giant");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute(); execute();
@ -61,5 +58,4 @@ public class NeedleDropTest extends CardTestPlayerBase {
assertLife(playerB, 18); assertLife(playerB, 18);
assertPermanentCount(playerB, "Hill Giant", 1); assertPermanentCount(playerB, "Hill Giant", 1);
} }
} }

View file

@ -6,6 +6,12 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
* Idol of Endurance
* {2}{W}
* Artifact
* When Idol of Endurance enters the battlefield, exile all creature cards with mana value 3 or less from your graveyard until Idol of Endurance leaves the battlefield.
* {1}{W}, {T}: Until end of turn, you may cast a creature spell from among cards exiled with Idol of Endurance without paying its mana cost.
*
* @author TheElk801 * @author TheElk801
*/ */
public class IdolOfEnduranceTest extends CardTestPlayerBase { public class IdolOfEnduranceTest extends CardTestPlayerBase {
@ -18,6 +24,9 @@ public class IdolOfEnduranceTest extends CardTestPlayerBase {
private static final String pnhrmcn = "Panharmonicon"; private static final String pnhrmcn = "Panharmonicon";
private static final String bnyrdwrm = "Boneyard Wurm"; private static final String bnyrdwrm = "Boneyard Wurm";
/**
* Test that you can cast a spell for free from those exiled
*/
@Test @Test
public void testIdolCast() { public void testIdolCast() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@ -26,8 +35,12 @@ public class IdolOfEnduranceTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, idol); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, idol);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
// Exile the Squire
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}"); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
// Play for free
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sqr); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sqr);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
@ -37,6 +50,9 @@ public class IdolOfEnduranceTest extends CardTestPlayerBase {
assertPermanentCount(playerA, sqr, 1); assertPermanentCount(playerA, sqr, 1);
} }
/**
* Test that you can only cast 1 spell per activation.
*/
@Test @Test
public void testIdolCast2() { public void testIdolCast2() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@ -45,21 +61,22 @@ public class IdolOfEnduranceTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, glrskr); addCard(Zone.GRAVEYARD, playerA, glrskr);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, idol); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, idol);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}"); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
// Cast the first spell
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sqr); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sqr);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, glrskr);
// Ensure that you can't cast the second spell
checkPlayableAbility("Can't cast 2nd", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + glrskr, false);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
assertPermanentCount(playerA, sqr, 1); assertPermanentCount(playerA, sqr, 1);
assertPermanentCount(playerA, glrskr, 0);
} }
@Test @Test

View file

@ -41,6 +41,13 @@ public class MoraugFuryOfAkoumTest extends CardTestPlayerBase {
attack(1, playerA, corpse); attack(1, playerA, corpse);
} }
/**
* If the landfall ability resolves during your precombat main phase,
* the additional combat phase will happen before your regular combat phase.
* Youll untap creatures you control at the beginning of the additional combat
* but not at the beginning of your regular combat.
* (2020-09-25)
*/
@Test @Test
public void testPrecombatLandfall() { public void testPrecombatLandfall() {
makeCombatCounter(); makeCombatCounter();
@ -54,11 +61,16 @@ public class MoraugFuryOfAkoumTest extends CardTestPlayerBase {
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, mountain); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, mountain);
attackWithAttackers(); attackWithAttackers();
// untap trigger already happened, creatures are still tapped and can't attack again
attackWithAttackers(); // 0 damage
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
execute(); execute();
// untap trigger already happened, creatures are still tapped and can't attack again
assertTapped(lion, true);
assertTapped(bear, true);
assertTapped(corpse, true);
assertLife(playerA, 20 + 2); assertLife(playerA, 20 + 2);
assertLife(playerB, 100 - 9 - 0); assertLife(playerB, 100 - 9 - 0);
} }

View file

@ -181,24 +181,28 @@ public class EntersTheBattlefieldTriggerTest extends CardTestPlayerBase {
*/ */
@Test @Test
public void testWildPair() { public void testWildPair() {
// Whenever a creature enters the battlefield, if you cast it from your hand,
// Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library. // you may search your library for a creature card with the same total power and toughness and put it onto the battlefield.
// If you do, shuffle your library.
addCard(Zone.BATTLEFIELD, playerA, "Wild Pair"); addCard(Zone.BATTLEFIELD, playerA, "Wild Pair");
addCard(Zone.HAND, playerA, "Silvercoat Lion", 1); addCard(Zone.HAND, playerA, "Silvercoat Lion", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
setChoice(playerA, "Silvercoat Lion");
addCard(Zone.LIBRARY, playerA, "Silvercoat Lion"); addCard(Zone.LIBRARY, playerA, "Silvercoat Lion");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion");
setChoice(playerA, "Yes"); // Yes for Wild Pair to find another creature
// Silvercoat Lion is the only other choice, let it be auto-chosen
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute(); execute();
assertPermanentCount(playerA, "Silvercoat Lion", 2); assertPermanentCount(playerA, "Silvercoat Lion", 2);
} }
// Test self trigger /**
* Test self trigger for Noxious Ghoul.
*/
@Test @Test
public void testNoxiousGhoul1() { public void testNoxiousGhoul1() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);

View file

@ -43,5 +43,4 @@ public class ChronozoaTest extends CardTestPlayerBase {
assertHandCount(playerA, 0); assertHandCount(playerA, 0);
} }
} }

View file

@ -21,7 +21,7 @@ public class KaradorGhostChieftainTest extends CardTestPlayerBase {
* Test that you can cast a spell from the graveyard. * Test that you can cast a spell from the graveyard.
*/ */
@Test @Test
public void testPlayFromGraveyard() { public void testCastFromGraveyard() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
addCard(Zone.BATTLEFIELD, playerA, "Karador, Ghost Chieftain"); addCard(Zone.BATTLEFIELD, playerA, "Karador, Ghost Chieftain");
addCard(Zone.GRAVEYARD, playerA, "Raging Goblin"); addCard(Zone.GRAVEYARD, playerA, "Raging Goblin");
@ -35,25 +35,6 @@ public class KaradorGhostChieftainTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Raging Goblin", 0); assertGraveyardCount(playerA, "Raging Goblin", 0);
} }
/**
* Test that you can cast from your graveyard.
*/
@Test
public void testPlayOneFromGraveyard() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
addCard(Zone.BATTLEFIELD, playerA, "Karador, Ghost Chieftain");
addCard(Zone.GRAVEYARD, playerA, "Raging Goblin", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Raging Goblin");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Raging Goblin");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertGraveyardCount(playerA, "Raging Goblin", 1);
}
/** /**
* Test that can cast only one spell from your graveyard per turn * Test that can cast only one spell from your graveyard per turn
*/ */

View file

@ -111,9 +111,10 @@ public class MyriadTest extends CardTestMultiPlayerBase {
addCard(Zone.BATTLEFIELD, playerC, "Pillarfield Ox", 1); addCard(Zone.BATTLEFIELD, playerC, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerC, "Grizzly Bears", 1); addCard(Zone.BATTLEFIELD, playerC, "Grizzly Bears", 1);
// Equipped creature has myriad.(Whenever this creature attacks, for each opponent other than the defending player, // Equipped creature has myriad. (Whenever this creature attacks, for each opponent other than the defending
// put a token that's a copy of this creature onto the battlefield tapped and attacking that player or a planeswalker // player, put a token that's a copy of this creature onto the battlefield tapped
// they control. Exile those tokens at the end of combat.) // and attacking that player or a planeswalker they control.
// Exile those tokens at the end of combat.)
// Equip {4} // Equip {4}
addCard(Zone.BATTLEFIELD, playerD, "Blade of Selves"); addCard(Zone.BATTLEFIELD, playerD, "Blade of Selves");
addCard(Zone.BATTLEFIELD, playerD, "Island", 4); addCard(Zone.BATTLEFIELD, playerD, "Island", 4);
@ -123,20 +124,27 @@ public class MyriadTest extends CardTestMultiPlayerBase {
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Man-o'-War"); castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Man-o'-War");
addTarget(playerD, "Silvercoat Lion"); addTarget(playerD, "Silvercoat Lion");
activateAbility(6, PhaseStep.PRECOMBAT_MAIN, playerD, "Equip", "Man-o'-War"); activateAbility(6, PhaseStep.PRECOMBAT_MAIN, playerD, "Equip", "Man-o'-War");
attack(6, playerD, "Man-o'-War", playerC); attack(6, playerD, "Man-o'-War", playerC);
setChoice(playerD, "Yes"); // for playerB
setChoice(playerD, "Yes"); // for playerA
addTarget(playerD, "Silvercoat Lion"); addTarget(playerD, "Silvercoat Lion");
addTarget(playerD, "Pillarfield Ox"); addTarget(playerD, "Pillarfield Ox");
addTarget(playerD, "Grizzly Bears");
setStopAt(6, PhaseStep.POSTCOMBAT_MAIN); setStopAt(6, PhaseStep.POSTCOMBAT_MAIN);
execute(); execute();
// Tokens exiled, only original left
assertPermanentCount(playerD, "Man-o'-War", 1); assertPermanentCount(playerD, "Man-o'-War", 1);
assertPermanentCount(playerC, "Silvercoat Lion", 0);
assertPermanentCount(playerC, "Pillarfield Ox", 0); // Returned to hand by Man-o'-War
assertPermanentCount(playerC, "Grizzly Bears", 1); // not in range assertPermanentCount(playerC, "Silvercoat Lion", 0); // 1 by original and 1 by token
assertPermanentCount(playerC, "Pillarfield Ox", 0); // by token
// Still on the battlefield since only 3 Man-o'-War triggers
assertPermanentCount(playerC, "Grizzly Bears", 1);
assertHandCount(playerC, "Silvercoat Lion", 2); assertHandCount(playerC, "Silvercoat Lion", 2);
assertHandCount(playerC, "Pillarfield Ox", 1); assertHandCount(playerC, "Pillarfield Ox", 1);