From 00c51626823e63df4c1b1f318aa5142beeb92a67 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Tue, 30 Jun 2020 19:20:59 -0400 Subject: [PATCH] fixed some Idol of Endurance bugs, updated tests --- .../src/mage/cards/i/IdolOfEndurance.java | 31 ++++++--- .../cards/single/IdolOfEnduranceTest.java | 64 ++++++++++++++++++- 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/Mage.Sets/src/mage/cards/i/IdolOfEndurance.java b/Mage.Sets/src/mage/cards/i/IdolOfEndurance.java index f57ff0ec57a..7c6b09e686d 100644 --- a/Mage.Sets/src/mage/cards/i/IdolOfEndurance.java +++ b/Mage.Sets/src/mage/cards/i/IdolOfEndurance.java @@ -91,16 +91,20 @@ class IdolOfEnduranceExileEffect extends OneShotEffect { .filter(Objects::nonNull) .map(card -> new MageObjectReference(card, game)) .collect(Collectors.toSet()); - game.getState().setValue("" + mor.getSourceId() + mor.getZoneChangeCounter(), morSet); - game.addDelayedTriggeredAbility(new IdolOfEnduranceDelayedTrigger(morSet), source); + String exileId = "idolOfEndurance_" + mor.getSourceId() + mor.getZoneChangeCounter(); + if (game.getState().getValue(exileId) == null) { + game.getState().setValue(exileId, new HashSet()); + } + ((Set) game.getState().getValue(exileId)).addAll(morSet); + game.addDelayedTriggeredAbility(new IdolOfEnduranceDelayedTrigger(exileId), source); return true; } } class IdolOfEnduranceDelayedTrigger extends DelayedTriggeredAbility { - IdolOfEnduranceDelayedTrigger(Set morSet) { - super(new IdolOfEnduranceLeaveEffect(morSet), Duration.Custom, true, false); + IdolOfEnduranceDelayedTrigger(String exileId) { + super(new IdolOfEnduranceLeaveEffect(exileId), Duration.Custom, true, false); this.usesStack = false; this.setRuleVisible(false); } @@ -133,15 +137,16 @@ class IdolOfEnduranceDelayedTrigger extends DelayedTriggeredAbility { class IdolOfEnduranceLeaveEffect extends OneShotEffect { - private final Set morSet = new HashSet<>(); + private final String exileId; - IdolOfEnduranceLeaveEffect(Set morSet) { + IdolOfEnduranceLeaveEffect(String exileId) { super(Outcome.Benefit); - this.morSet.addAll(morSet); + this.exileId = exileId; } private IdolOfEnduranceLeaveEffect(final IdolOfEnduranceLeaveEffect effect) { super(effect); + this.exileId = effect.exileId; } @Override @@ -152,6 +157,14 @@ class IdolOfEnduranceLeaveEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Object object = game.getState().getValue(exileId); + if (!(object instanceof Set)) { + return false; + } + Set morSet = (Set) object; return player != null && player.moveCards( morSet.stream() .map(mor -> mor.getCard(game)) @@ -198,7 +211,9 @@ class IdolOfEnduranceCastFromExileEffect extends AsThoughEffectImpl { if (watcher == null || !watcher.checkPermission(affectedControllerId, source, game)) { return false; } - Object value = game.getState().getValue("" + source.getSourceId() + source.getSourceObjectZoneChangeCounter()); + Object value = game.getState().getValue( + "idolOfEndurance_" + source.getSourceId() + source.getSourceObjectZoneChangeCounter() + ); if (!(value instanceof Set)) { discard(); return false; diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/IdolOfEnduranceTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/IdolOfEnduranceTest.java index 63834e0496d..11a1386b05f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/IdolOfEnduranceTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/IdolOfEnduranceTest.java @@ -11,12 +11,15 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class IdolOfEnduranceTest extends CardTestPlayerBase { private static final String idol = "Idol of Endurance"; + private static final String dsnchnt = "Disenchant"; private static final String key = "Voltaic Key"; private static final String sqr = "Squire"; private static final String glrskr = "Glory Seeker"; + private static final String pnhrmcn = "Panharmonicon"; + private static final String bnyrdwrm = "Boneyard Wurm"; @Test - public void testIdol() { + public void testIdolCast() { addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.HAND, playerA, idol); addCard(Zone.GRAVEYARD, playerA, sqr); @@ -35,7 +38,7 @@ public class IdolOfEnduranceTest extends CardTestPlayerBase { } @Test - public void testIdol2() { + public void testIdolCast2() { addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.HAND, playerA, idol); addCard(Zone.GRAVEYARD, playerA, sqr); @@ -59,6 +62,63 @@ public class IdolOfEnduranceTest extends CardTestPlayerBase { assertPermanentCount(playerA, glrskr, 0); } + @Test + public void testIdolLeaves() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 7); + addCard(Zone.HAND, playerA, idol); + addCard(Zone.HAND, playerA, dsnchnt); + addCard(Zone.GRAVEYARD, playerA, sqr); + addCard(Zone.GRAVEYARD, playerA, glrskr); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, idol); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}"); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sqr); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, dsnchnt, idol); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, sqr, 1); + assertPermanentCount(playerA, idol, 0); + assertGraveyardCount(playerA, glrskr, 1); + } + + @Test + public void testIdolPanharmonicon() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 7); + addCard(Zone.BATTLEFIELD, playerA, pnhrmcn); + addCard(Zone.BATTLEFIELD, playerA, bnyrdwrm, 2); + addCard(Zone.HAND, playerA, idol); + addCard(Zone.HAND, playerA, dsnchnt); + addCard(Zone.GRAVEYARD, playerA, sqr); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, idol); + + // Boneyard Wurm will die between triggers + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W}"); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bnyrdwrm); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, dsnchnt, idol); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, bnyrdwrm, 1); + assertPermanentCount(playerA, idol, 0); + assertGraveyardCount(playerA, sqr, 1); + assertGraveyardCount(playerA, bnyrdwrm, 1); + } + @Test public void testIdolTwice() { addCard(Zone.BATTLEFIELD, playerA, "Plains", 8);