diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java index 9c13397692fc..4c01474b53c8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java @@ -22,7 +22,7 @@ import java.util.UUID; /** - * @author LevelX2 + * @author LevelX2, JayDi85 */ public class CopySpellTest extends CardTestPlayerBase { @@ -905,4 +905,56 @@ private void cardsMustHaveSameZoneAndZCC(Card originalCard, Card copiedCard, Str Assert.fail(infoPrefix + " - " + "cards must have same zone and zcc: " + zcc1 + " - " + zone1 + " != " + zcc2 + " - " + zone2); } } + + /** + * Bug: If Swan Song is used to counter a copied spell, no tokens are created #12883 + */ + @Test + public void test_LKI() { + // Counter target enchantment, instant, or sorcery spell. + // Its controller creates a 2/2 blue Bird creature token with flying. + addCard(Zone.HAND, playerA, "Swan Song", 1); // {U} + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + // + // Until end of turn, whenever a player casts an instant or sorcery spell, that player copies it and + // may choose new targets for the copy. + addCard(Zone.HAND, playerA, "Bonus Round", 1); // {1}{R}{R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + // + addCard(Zone.HAND, playerA, "Lightning Bolt", 1); // {R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerB, "Augmenting Automaton", 1); + + checkPermanentCount("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerA, "Bird Token", 0); + checkPermanentCount("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerB, "Grizzly Bears", 1); + checkPermanentCount("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerB, "Augmenting Automaton", 1); + + // prepare copy effect + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}", 3); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bonus Round"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // cast and duplicate bolt + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt"); + addTarget(playerA, "Grizzly Bears"); // original target + setChoice(playerA, true); // use new target + addTarget(playerA, "Augmenting Automaton"); // copy target + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true); // resolve copy trigger + checkStackObject("on copy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", 2); + + // counter copy and save Augmenting Automaton + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swan Song", "Lightning Bolt[only copy]", "Lightning Bolt", StackClause.WHILE_COPY_ON_STACK); + setChoice(playerA, false); // no change target for duplicated counter spell (non-relevant here) + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerA, "Bird Token", 1); + checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerB, "Grizzly Bears", 0); + checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, playerB, "Augmenting Automaton", 1); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index b9c5d2c9e1a3..57fc6ec6d132 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -1291,7 +1291,7 @@ private void printAliases(Game game, TestPlayer player) { private void printStack(Game game) { System.out.println("Stack objects: " + game.getStack().size()); game.getStack().forEach(stack -> { - System.out.println(stack.getStackAbility().toString()); + System.out.println(stack.getStackAbility().toString() + (stack.isCopy() ? " [copy]" : "")); }); } diff --git a/Mage/src/main/java/mage/game/stack/SpellStack.java b/Mage/src/main/java/mage/game/stack/SpellStack.java index f040f6988252..83458c5980b9 100644 --- a/Mage/src/main/java/mage/game/stack/SpellStack.java +++ b/Mage/src/main/java/mage/game/stack/SpellStack.java @@ -83,7 +83,7 @@ public boolean counter(UUID objectId, Ability source, Game game, PutCards putCar if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, source, stackObject.getControllerId()))) { // spells are removed from stack by the card movement if (!(stackObject instanceof Spell) - || stackObject.isCopy()) { // ensure that copies of stackobjects have their history recorded ie: Swan Song + || stackObject.isCopy()) { // !ensure that copies of stackobjects have their history recorded ie: Swan Song this.remove(stackObject, game); game.rememberLKI(Zone.STACK, stackObject); }