From 821b0d069f3b1615b1680edb929b2cc459d01dce Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:51:34 +0200 Subject: [PATCH] Return to battlefield transfromed - fixed that it was able to return non transformable cards, fixed #12066 (#12072) --- .../cards/copy/CleverImpersonatorTest.java | 32 ++++++++++++------- .../lci/OjerAxonilDeepestMightTest.java | 31 ++++++++++++++++++ .../src/main/java/mage/game/ZonesHandler.java | 18 +++++++---- .../main/java/mage/players/PlayerImpl.java | 8 +++++ 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java index a390ef48ff2..6d18f7535e4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CleverImpersonatorTest.java @@ -123,14 +123,23 @@ public class CleverImpersonatorTest extends CardTestPlayerBase { } /** - * So I copied Jace, Vryns Prodigy with Clever Impersonator (it was tapped - * and I needed a blocker for a token...), and Jace got to survive until the - * next turn. When I looted, he flipped, and I got an error message I - * couldn't get rid of, forcing me to concede. I'm not sure what the correct - * outcome is rules-wise. + * 712.14a. If a spell or ability puts a transforming double-faced card onto the battlefield "transformed" + * or "converted," it enters the battlefield with its back face up. If a player is instructed to put a card + * that isn't a transforming double-faced card onto the battlefield transformed or converted, that card stays in + * its current zone. + *
+ * * So I copied Jace, Vryns Prodigy with Clever Impersonator (it was tapped
+ * * and I needed a blocker for a token...), and Jace got to survive until the
+ * * next turn. When I looted, he flipped, and I got an error message I
+ * * couldn't get rid of, forcing me to concede. I'm not sure what the correct
+ * * outcome is rules-wise.
*/
@Test
public void testCopyCreatureOfFlipPlaneswalker() {
+ setStrictChooseMode(true);
+ skipInitShuffling();
+
+ addCard(Zone.LIBRARY, playerA, "Swamp"); // for discard
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
// {T}: Draw a card, then discard a card. If there are five or more cards in your graveyard, exile Jace, Vryn's Prodigy, then return him to the battefield transformed under his owner's control.
@@ -143,23 +152,24 @@ public class CleverImpersonatorTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clever Impersonator");
- setChoice(playerA, "Jace, Vryn's Prodigy");
- setChoice(playerA, "Jace, Vryn's Prodigy[only copy]"); // keep the copied Jace
+ setChoice(playerA, true); // yes to copy
+ setChoice(playerA, "Jace, Vryn's Prodigy"); // copy Jace
+ setChoice(playerA, "Jace, Vryn's Prodigy[only copy]"); // keep the copied Jace under legend rule
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw a card");
- setChoice(playerA, "Pillarfield Ox");
+ setChoice(playerA, "Swamp");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Jace, Vryn's Prodigy", 1);
- assertPermanentCount(playerA, "Pillarfield Ox", 1);
-
+ assertPermanentCount(playerA, "Pillarfield Ox", 0);
+ assertExileCount(playerA, "Clever Impersonator", 1); // Clone does not come back as per 712.14a..
}
/**
* Reported bug:
- * Could not use Clever Impersonator to copy Dawn's Reflection
+ * Could not use Clever Impersonator to copy Dawn's Reflection
*/
@Test
public void dawnsReflectionCopiedByImpersonator() {
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/OjerAxonilDeepestMightTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/OjerAxonilDeepestMightTest.java
index 72e06471c00..b5601a7cc66 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/OjerAxonilDeepestMightTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/OjerAxonilDeepestMightTest.java
@@ -212,6 +212,37 @@ public class OjerAxonilDeepestMightTest extends CardTestPlayerBase {
assertTapped(ojer, true);
}
+ /**
+ * 712.14a. If a spell or ability puts a transforming double-faced card onto the battlefield "transformed"
+ * or "converted," it enters the battlefield with its back face up. If a player is instructed to put a card
+ * that isn't a transforming double-faced card onto the battlefield transformed or converted, that card stays in
+ * its current zone.
+ */
+ @Test
+ public void test_CloneDoNotTransform() {
+ setStrictChooseMode(true);
+
+ addCard(Zone.BATTLEFIELD, playerA, ojer, 1);
+ addCard(Zone.HAND, playerA, "Sakashima the Impostor", 1); // Clone keeping its name for easier test.
+ addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 6);
+ addCard(Zone.HAND, playerA, "Doom Blade", 1);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sakashima the Impostor");
+ setChoice(playerA, true); // yes to clone
+ setChoice(playerA, ojer); // clone Ojer
+
+ checkPermanentCount("Sakashima in play", 1, PhaseStep.BEGIN_COMBAT, playerA, "Sakashima the Impostor", 1);
+ checkPT("PT 4/4 so copy happened", 1, PhaseStep.BEGIN_COMBAT, playerA, "Sakashima the Impostor", 4, 4);
+
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Doom Blade", "Sakashima the Impostor");
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+
+ assertPermanentCount(playerA, ojer, 1);
+ assertGraveyardCount(playerA, "Sakashima the Impostor", 1); // is not transformable, so didn't return.
+ }
+
@Test
public void test_watching_Chandra_emblem_damage() {
setStrictChooseMode(true);
diff --git a/Mage/src/main/java/mage/game/ZonesHandler.java b/Mage/src/main/java/mage/game/ZonesHandler.java
index d741e831cf9..f234e74a580 100644
--- a/Mage/src/main/java/mage/game/ZonesHandler.java
+++ b/Mage/src/main/java/mage/game/ZonesHandler.java
@@ -334,13 +334,19 @@ public final class ZonesHandler {
isGoodToMove = true;
} else if (event.getToZone().equals(Zone.BATTLEFIELD)) {
// non-permanents can't move to battlefield
- // "return to battlefield transformed" abilities uses game state value instead "info.transformed", so check it too
- // TODO: possible bug with non permanent on second side like Life // Death, see https://github.com/magefree/mage/issues/11573
- // need to check second side here, not status only
// TODO: possible bug with Nightbound, search all usage of getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED and insert additional check Ability.checkCard
- boolean wantToPutTransformed = card.isTransformable()
- && Boolean.TRUE.equals(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()));
- isGoodToMove = card.isPermanent(game) || wantToPutTransformed;
+ /*
+ * 712.14a. If a spell or ability puts a transforming double-faced card onto the battlefield "transformed"
+ * or "converted," it enters the battlefield with its back face up. If a player is instructed to put a card
+ * that isn't a transforming double-faced card onto the battlefield transformed or converted, that card stays in
+ * its current zone.
+ */
+ boolean wantToTransform = Boolean.TRUE.equals(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()));
+ if (wantToTransform) {
+ isGoodToMove = card.isTransformable() && card.getSecondCardFace().isPermanent(game);
+ } else {
+ isGoodToMove = card.isPermanent(game);
+ }
} else {
// other zones allows to move
isGoodToMove = true;
diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java
index d465f350a48..82eb398d3eb 100644
--- a/Mage/src/main/java/mage/players/PlayerImpl.java
+++ b/Mage/src/main/java/mage/players/PlayerImpl.java
@@ -4708,6 +4708,14 @@ public abstract class PlayerImpl implements Player, Serializable {
List