From c34c6a59df72205bc5ce086f84a7c00d71638bc9 Mon Sep 17 00:00:00 2001 From: Alex Vasile <48962821+Alex-Vasile@users.noreply.github.com> Date: Wed, 27 Jul 2022 08:05:10 -0400 Subject: [PATCH] Test for Copied Gilded Drake reverting control when killed (#9198) --- Mage.Sets/src/mage/cards/g/GildedDrake.java | 31 ++++++----- .../mage/cards/k/KikiJikiMirrorBreaker.java | 18 +++---- .../mage/cards/r/ReflectionOfKikiJiki.java | 6 +++ .../cards/control/ExchangeControlTest.java | 51 +++++++++++++++++++ .../ExchangeControlTargetEffect.java | 9 ++-- 5 files changed, 85 insertions(+), 30 deletions(-) diff --git a/Mage.Sets/src/mage/cards/g/GildedDrake.java b/Mage.Sets/src/mage/cards/g/GildedDrake.java index 10938bacf2..ba9ed15f10 100644 --- a/Mage.Sets/src/mage/cards/g/GildedDrake.java +++ b/Mage.Sets/src/mage/cards/g/GildedDrake.java @@ -72,24 +72,23 @@ class GildedDrakeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent sourceObject = game.getPermanent(source.getSourceId()); - if (sourceObject != null) { - if (targetPointer.getFirst(game, source) != null) { - Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source)); - if (targetPermanent != null) { - ContinuousEffect effect = new ExchangeControlTargetEffect(Duration.EndOfGame, "", true); - effect.setTargetPointer(targetPointer); - game.addEffect(effect, source); - return true; - } - } - sourceObject.sacrifice(source, game); - } + if (controller == null) { + return false; + } + Permanent sourceObject = game.getPermanent(source.getSourceId()); + if (sourceObject == null) { + return false; + } + + if (targetPointer.getFirst(game, source) == null || game.getPermanent(targetPointer.getFirst(game, source)) == null) { + sourceObject.sacrifice(source, game); return true; } - return false; + + ContinuousEffect effect = new ExchangeControlTargetEffect(Duration.EndOfGame, "", true); + effect.setTargetPointer(targetPointer); + game.addEffect(effect, source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java b/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java index ba97b5e26e..b83bddb849 100644 --- a/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java +++ b/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java @@ -84,18 +84,14 @@ class KikiJikiMirrorBreakerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - if (permanent != null) { - CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true); - effect.setTargetPointer(new FixedTarget(permanent, game)); - effect.apply(game, source); - for (Permanent addedToken : effect.getAddedPermanents()) { - SacrificeTargetEffect sacrificeEffect = new SacrificeTargetEffect("Sacrifice the token at the beginning of the next end step", source.getControllerId()); - sacrificeEffect.setTargetPointer(new FixedTarget(addedToken.getId())); - game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(sacrificeEffect), source); - } - return true; + if (permanent == null) { + return false; } - return false; + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true); + effect.setTargetPointer(new FixedTarget(permanent, game)); + effect.apply(game, source); + effect.sacrificeTokensCreatedAtNextEndStep(game, source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/r/ReflectionOfKikiJiki.java b/Mage.Sets/src/mage/cards/r/ReflectionOfKikiJiki.java index 2a4dd54719..51abc490f5 100644 --- a/Mage.Sets/src/mage/cards/r/ReflectionOfKikiJiki.java +++ b/Mage.Sets/src/mage/cards/r/ReflectionOfKikiJiki.java @@ -18,6 +18,7 @@ import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; @@ -82,6 +83,11 @@ class ReflectionOfKikiJikiEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); + if (permanent == null) { + return false; + } + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, null, true); effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); effect.apply(game, source); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/control/ExchangeControlTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/control/ExchangeControlTest.java index f7c64be294..b95b18e43f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/control/ExchangeControlTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/control/ExchangeControlTest.java @@ -5,6 +5,7 @@ import mage.constants.PhaseStep; import mage.constants.Zone; import mage.game.permanent.Permanent; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -277,6 +278,56 @@ public class ExchangeControlTest extends CardTestPlayerBase { assertGraveyardCount(playerB, "Lightning Bolt", 1); assertGraveyardCount(playerB, "Silvercoat Lion", 1); assertGraveyardCount(playerA, "Gilded Drake", 1); + } + /** + * 1. Kiki-Jiki copied Gilded Drake. + * 2. Gilded Drake copy is exchanged for another creature. + * 3. After the exchange occurs, Gilded Drake is killed by any means. + * 4. Exchange creature is returned to previous controller (possible owner) during the next phase. + *
+ * See https://github.com/magefree/mage/issues/8742
+ */
+ @Ignore
+ @Test
+ public void testGildedDrakeCopyExchange() {
+ addCard(Zone.BATTLEFIELD, playerA, "Kiki-Jiki, Mirror Breaker");
+ addCard(Zone.HAND, playerA, "Gilded Drake");
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
+
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
+
+ addCard(Zone.BATTLEFIELD, playerB, "Dwarven Trader"); // Exchange target
+ addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // Exchange target
+
+ setStrictChooseMode(true);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gilded Drake");
+ addTarget(playerA, "Dwarven Trader"); // Target for Gilded Drake
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true); // Skip the cast and grab the ETB
+
+ // Copy the drake
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}", "Gilded Drake", "When {this}");
+ addTarget(playerA, "Silvercoat Lion"); // Target for Gilded Drake
+
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+
+ // Destroy both of the Drakes
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt");
+ addTarget(playerA, "Gilded Drake");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt");
+ addTarget(playerA, "Gilded Drake");
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Kiki-Jiki, Mirror Breaker", 1);
+ assertPermanentCount(playerA, "Dwarven Trader", 1); // Original's exhange target
+ assertPermanentCount(playerA, "Silvercoat Lion", 1); // Copy's exchange target
+
+ assertPermanentCount(playerA, "Gilded Drake", 0);
+ assertPermanentCount(playerB, "Gilded Drake", 0);
}
}
diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/ExchangeControlTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/ExchangeControlTargetEffect.java
index 2394f9dab5..4abd6ee491 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/continuous/ExchangeControlTargetEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/ExchangeControlTargetEffect.java
@@ -28,7 +28,7 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl {
private boolean withSecondTarget;
private boolean destroyAttachedAuras;
private Map