From 18600a53a93ff659c406d5da43900a9e00599546 Mon Sep 17 00:00:00 2001 From: Steven Knipe Date: Thu, 16 Nov 2023 18:09:02 -0800 Subject: [PATCH] Add new/Enable existing tests --- .../cards/abilities/keywords/BlitzTest.java | 42 +++++ .../cards/abilities/keywords/EchoTest.java | 36 +++++ .../abilities/keywords/SpectacleTest.java | 143 ++++++++++++++++++ .../cards/abilities/keywords/SquadTest.java | 2 - .../cards/copy/CopyPermanentSpellTest.java | 3 +- .../cards/copy/CostTagCopyCloneTests.java | 108 +++++++++++++ 6 files changed, 330 insertions(+), 4 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SpectacleTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/copy/CostTagCopyCloneTests.java diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BlitzTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BlitzTest.java index 6f847caca02..a3f74a9f86f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BlitzTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BlitzTest.java @@ -67,6 +67,48 @@ public class BlitzTest extends CardTestPlayerBase { assertHandCount(playerA, 1); } + @Test + public void testBlitzCopy() { + //Copying the spell on the stack must include the Blitz ability activation + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 6); + addCard(Zone.HAND, playerA, decoy); + addCard(Zone.HAND, playerA, "Double Major"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, decoy + withBlitz); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Double Major",decoy); + + setChoice(playerA, ""); //stack triggers + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, decoy, 0); + assertGraveyardCount(playerA, decoy, 1); + assertGraveyardCount(playerA, "Double Major", 1); + assertHandCount(playerA, 2); + } + @Test + public void testBlitzClone() { + //Copying the creature permanent must not include Blitz activation + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 8); + addCard(Zone.HAND, playerA, decoy); + addCard(Zone.HAND, playerA, "Clone"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, decoy + withBlitz); + waitStackResolved(1,PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clone"); + setChoice(playerA,true); + setChoice(playerA,decoy); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, decoy, 1); + assertGraveyardCount(playerA, decoy, 1); + assertHandCount(playerA, 1); + } @Test public void testNoBlitz() { addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EchoTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EchoTest.java index 81b83740107..833f64b98e6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EchoTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/EchoTest.java @@ -70,5 +70,41 @@ public class EchoTest extends CardTestPlayerBase { assertTappedCount("Mountain", true, 0); } + //Deranged Hermit has been cloned with Phantasmal Image. + //The Phantasmal Image version of the Deranged Hermit had to pay the echo cost multiple times. + @Test + public void testEchoTriggerClone() { + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 15); + // Deranged Hermit {3}{G}{G} + // Echo + addCard(Zone.HAND, playerA, "Deranged Hermit"); + addCard(Zone.HAND, playerA, "Phantasmal Image"); + addCard(Zone.HAND, playerA, "Double Major"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Deranged Hermit"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Double Major", "Deranged Hermit"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Phantasmal Image"); + setChoice(playerA, true); + setChoice(playerA, "Deranged Hermit"); + + setChoice(playerA, ""); //stack triggers + setChoice(playerA, ""); + + setChoice(playerA, true); //Pay echo costs + setChoice(playerA, true); + setChoice(playerA, true); + + setStrictChooseMode(true); + setStopAt(3, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + assertPermanentCount(playerA, "Deranged Hermit", 3); + assertTappedCount("Tropical Island", true, 15); + + } } \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SpectacleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SpectacleTest.java new file mode 100644 index 00000000000..ab9795b06ca --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SpectacleTest.java @@ -0,0 +1,143 @@ + +package org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author notgreat + */ +public class SpectacleTest extends CardTestPlayerBase { + @Test + public void testWithoutSpectacleBasic() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, "Spikewheel Acrobat"); // {3}{R} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spikewheel Acrobat"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + setStrictChooseMode(true); + execute(); + + assertPermanentCount(playerA,"Spikewheel Acrobat",1); + assertTappedCount("Mountain",true,4); + } + @Test + public void testWithoutSpectacleTriggerAfterDamage() { + // Rafter Demon {2}{B}{R} + // Spectacle {3}{B}{R} + // When Rafter Demon enters the battlefield, if its spectacle cost was paid, each opponent discards a card. + addCard(Zone.BATTLEFIELD, playerA, "Badlands", 6); + addCard(Zone.HAND, playerA, "Lightning Bolt"); // {R} + addCard(Zone.HAND, playerA, "Rafter Demon"); // {2}{B}{R} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); + waitStackResolved(1,PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rafter Demon"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + setStrictChooseMode(true); + execute(); + + assertPermanentCount(playerA,"Rafter Demon",1); + assertTappedCount("Badlands",true,5); + assertGraveyardCount(playerA, "Lightning Bolt", 1); + assertLife(playerB, 17); + assertGraveyardCount(playerB, 0); + } + + @Test + public void testWithSpectacle() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + addCard(Zone.HAND, playerA, "Lightning Bolt"); // {R} + addCard(Zone.HAND, playerA, "Spikewheel Acrobat"); // Surge {2}{R} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt",playerB); + waitStackResolved(1,PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spikewheel Acrobat with spectacle"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + setStrictChooseMode(true); + execute(); + + assertPermanentCount(playerA,"Spikewheel Acrobat",1); + assertTappedCount("Mountain",true,4); + assertLife(playerB, 17); + } + + @Test + public void testRafterDemonCopyClone() { + addCard(Zone.BATTLEFIELD, playerA, "Badlands", 3); + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 4); + addCard(Zone.BATTLEFIELD, playerA, "Wastes", 5); + // Rafter Demon {2}{B}{R} + // Spectacle {3}{B}{R} + // When Rafter Demon enters the battlefield, if its spectacle cost was paid, each opponent discards a card. + addCard(Zone.HAND, playerA, "Rafter Demon"); + addCard(Zone.HAND, playerA, "Lightning Bolt"); + addCard(Zone.HAND, playerB, "Darksteel Relic",5); + + addCard(Zone.HAND, playerA, "Double Major"); + addCard(Zone.HAND, playerA, "Clone"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rafter Demon with spectacle"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Double Major"); + addTarget(playerA, "Rafter Demon"); + addTarget(playerB, "Darksteel Relic",2); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkGraveyardCount("Discard x2", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Darksteel Relic", 2); + checkPermanentCount("Rafter Demon x2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rafter Demon", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clone"); + setChoice(playerA, true); // copy + setChoice(playerA, "Rafter Demon"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + setStrictChooseMode(true); + execute(); + + assertGraveyardCount(playerA, "Lightning Bolt", 1); + assertGraveyardCount(playerB, 2); + assertHandCount(playerB, "Darksteel Relic", 3); + assertPermanentCount(playerA, "Rafter Demon", 3); + + assertLife(playerB, 17); + } + + @Test + public void SnapcasterMageWithSpectacle() { + //Should not be castable with Spectacle on flashback, since that's two alternative casts at once + addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3+2+2); + + addCard(Zone.HAND, playerA, "Snapcaster Mage", 1); + addCard(Zone.HAND, playerA, "Skewer the Critics", 1); + addCard(Zone.HAND, playerA, "Snapcaster Mage", 1); + addCard(Zone.HAND, playerA, "Pyretic Ritual", 1); + + setStrictChooseMode(true); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Skewer the Critics", playerB); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage"); + addTarget(playerA, "Skewer the Critics"); + + checkPlayableAbility("No flashback with Spectacle available", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback", false ); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Pyretic Ritual", true); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback"); + addTarget(playerA, playerB); + + setStopAt(1, PhaseStep.END_TURN); + setStrictChooseMode(true); + execute(); + + assertLife(playerB, 20-3-3); + assertTappedCount("Volcanic Island", true, 3+2+2); + assertExileCount("Skewer the Critics", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SquadTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SquadTest.java index ab461dbc6f1..5718d39f313 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SquadTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SquadTest.java @@ -280,9 +280,7 @@ public class SquadTest extends CardTestPlayerBase { assertPermanentCount(playerA, flagellant, 3); // One original + its squad buddy + the squad buddy from the additional trigger } - @Ignore @Test - //TODO: Enable after fixing clones activating it if they have the same zcc. Also affects Kicker public void test_CloneMustNotCopySquad() { addCard(Zone.BATTLEFIELD, playerA, swamp, 8); // 3 + 2 + 3 addCard(Zone.BATTLEFIELD, playerA, "Island", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyPermanentSpellTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyPermanentSpellTest.java index 78e94cca589..2e9825b07cd 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyPermanentSpellTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyPermanentSpellTest.java @@ -113,7 +113,6 @@ public class CopyPermanentSpellTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Aether Figment", 3, 3, Filter.ComparisonScope.All); } - @Ignore // currently fails @Test public void testSurgeTrigger() { makeTester(); @@ -121,7 +120,7 @@ public class CopyPermanentSpellTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Memnite"); addCard(Zone.HAND, playerA, "Reckless Bushwhacker"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Memnite"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Memnite", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reckless Bushwhacker with surge"); setStopAt(1, PhaseStep.END_TURN); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CostTagCopyCloneTests.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CostTagCopyCloneTests.java new file mode 100644 index 00000000000..5fc7b4ec198 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CostTagCopyCloneTests.java @@ -0,0 +1,108 @@ +package org.mage.test.cards.copy; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; +/** + * @author notgreat + */ +public class CostTagCopyCloneTests extends CardTestPlayerBase { + + @Test + public void KickerETBCountersClone() { + addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 11); + addCard(Zone.HAND, playerA, "Aether Figment"); + addCard(Zone.HAND, playerA, "Clone"); + addCard(Zone.HAND, playerA, "Shrivel"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Aether Figment"); + setChoice(playerA, true); // with Kicker + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, false); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clone"); + setChoice(playerA, true); // use copy + setChoice(playerA, "Aether Figment"); // copy target + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, false); + + // since Clone wasn't kicked, it's a 1/1. Cast Shrivel to easily separate + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shrivel"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, false); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Aether Figment", 1); + assertGraveyardCount(playerA, "Clone", 1); + } + @Test + public void XCountersCopyClone() { + addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 7); + addCard(Zone.HAND, playerA, "Endless One"); + addCard(Zone.HAND, playerA, "Clone"); + addCard(Zone.HAND, playerA, "Double Major"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Endless One"); + setChoice(playerA, "X=1"); // with Kicker + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Double Major"); + addTarget(playerA, "Endless One"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clone"); + setChoice(playerA, true); + setChoice(playerA, "Endless One"); // since Clone wasn't kicked, it's a 0/0 and dies + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Endless One", 2); + assertGraveyardCount(playerA, "Clone", 1); + } + @Test + public void ETBXClone() { + addCard(Zone.BATTLEFIELD, playerA, "Tundra", 4+4); + addCard(Zone.HAND, playerA, "Defenders of Humanity"); + addCard(Zone.HAND, playerA, "Clever Impersonator"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Defenders of Humanity"); + setChoice(playerA, "X=1"); // with Kicker + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, false); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clever Impersonator"); + setChoice(playerA, true); + setChoice(playerA, "Defenders of Humanity"); //clones don't copy X + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, false); + + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA,"Defenders of Humanity",2); + assertPermanentCount(playerA,"Astartes Warrior Token",1); + } + @Test + public void ETBXCopy() { + addCard(Zone.BATTLEFIELD, playerA, "Tundra", 4+1); + addCard(Zone.HAND, playerA, "Defenders of Humanity"); + addCard(Zone.BATTLEFIELD, playerA, "Overloaded Mage-Ring"); + + assertPermanentCount(playerA,"Astartes Warrior Token",0); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Defenders of Humanity"); + setChoice(playerA, "X=1"); // with Kicker + + activateAbility(1,PhaseStep.PRECOMBAT_MAIN,playerA, + "{1}, {T}, Sacrifice {this}: Copy target spell you control.", + "Defenders of Humanity"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA,"Defenders of Humanity",2); + assertPermanentCount(playerA,"Astartes Warrior Token",2); + } +}