Fix ReturnToHandAttachedEffect with MDFCs (#10452)

* Add tests for ReturnToHandAttachedEffect

* Temporary fix for returning attached MDFC to hand
This commit is contained in:
xenohedron 2023-06-16 22:43:34 -04:00 committed by GitHub
parent a6c19c4335
commit 045bbbf04f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 230 additions and 1 deletions

View file

@ -80,4 +80,231 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
}
@Test
public void testZendikon() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.HAND, playerA, "Mountain", 1);
addCard(Zone.HAND, playerA, "Wind Zendikon");
addCard(Zone.HAND, playerA, "Disfigure");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Mountain");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Mountain");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 2 for perm, 3 for card
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Wind Zendikon", 1);
assertGraveyardCount(playerA, "Mountain", 0);
assertHandCount(playerA, "Mountain", 1);
}
@Test
public void testZendikonMDFC() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.HAND, playerA, "Tangled Florahedron");
addCard(Zone.HAND, playerA, "Wind Zendikon");
addCard(Zone.HAND, playerA, "Disfigure");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Vale");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Tangled Vale");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Vale");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 2 for perm, 1 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Wind Zendikon", 1);
assertGraveyardCount(playerA, "Tangled Florahedron", 0);
assertHandCount(playerA, "Tangled Florahedron", 1);
}
@Test
public void testZendikonPathwayTop() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.HAND, playerA, "Riverglide Pathway");
addCard(Zone.HAND, playerA, "Wind Zendikon");
addCard(Zone.HAND, playerA, "Disfigure");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Riverglide Pathway");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Riverglide Pathway");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Riverglide Pathway");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 2 for perm, 1 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Wind Zendikon", 1);
assertGraveyardCount(playerA, "Riverglide Pathway", 0);
assertHandCount(playerA, "Riverglide Pathway", 1);
}
@Test
public void testZendikonPathwayBottom() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.HAND, playerA, "Riverglide Pathway");
addCard(Zone.HAND, playerA, "Wind Zendikon");
addCard(Zone.HAND, playerA, "Disfigure");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lavaglide Pathway");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Lavaglide Pathway");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Lavaglide Pathway");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 2 for perm, 1 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Wind Zendikon", 1);
assertGraveyardCount(playerA, "Riverglide Pathway", 0);
assertHandCount(playerA, "Riverglide Pathway", 1);
}
@Test
public void testDemonicVigor() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.HAND, playerA, "Dryad Sophisticate");
addCard(Zone.HAND, playerA, "Demonic Vigor");
addCard(Zone.HAND, playerA, "Disfigure");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dryad Sophisticate");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Dryad Sophisticate");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 3 for perm, 4 for card
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Demonic Vigor", 1);
assertGraveyardCount(playerA, "Dryad Sophisticate", 0);
assertHandCount(playerA, "Dryad Sophisticate", 1);
}
@Test
public void testDemonicVigorMDFC() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.HAND, playerA, "Tangled Florahedron");
addCard(Zone.HAND, playerA, "Demonic Vigor");
addCard(Zone.HAND, playerA, "Disfigure");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Florahedron");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Florahedron");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 3 for perm, 2 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Demonic Vigor", 1);
assertGraveyardCount(playerA, "Tangled Florahedron", 0);
assertHandCount(playerA, "Tangled Florahedron", 1);
}
@Test
public void testDemonicVigorAgain() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.HAND, playerA, "Dryad Sophisticate");
addCard(Zone.HAND, playerA, "Demonic Vigor", 2);
addCard(Zone.HAND, playerA, "Disfigure", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dryad Sophisticate");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Dryad Sophisticate");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Dryad Sophisticate");
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Dryad Sophisticate");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 7 for perm, 8 for card
assertGraveyardCount(playerA, "Disfigure", 2);
assertGraveyardCount(playerA, "Demonic Vigor", 2);
assertGraveyardCount(playerA, "Dryad Sophisticate", 0);
assertHandCount(playerA, "Dryad Sophisticate", 1);
}
@Test
public void testDemonicVigorMDFCAgain() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.HAND, playerA, "Tangled Florahedron");
addCard(Zone.HAND, playerA, "Demonic Vigor", 2);
addCard(Zone.HAND, playerA, "Disfigure", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Florahedron");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Florahedron");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Tangled Florahedron");
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Tangled Florahedron");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 7 for perm, 4 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 2);
assertGraveyardCount(playerA, "Demonic Vigor", 2);
assertGraveyardCount(playerA, "Tangled Florahedron", 0);
assertHandCount(playerA, "Tangled Florahedron", 1);
}
@Test
public void testDemonicVigorZoneChange() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8);
addCard(Zone.HAND, playerA, "Carrion Feeder");
addCard(Zone.HAND, playerA, "Demonic Vigor");
addCard(Zone.HAND, playerA, "Disfigure");
addCard(Zone.HAND, playerA, "Makeshift Mannequin");
addCard(Zone.HAND, playerA, "Coat with Venom");
setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Carrion Feeder");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Carrion Feeder");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Carrion Feeder");
waitStackResolved(1, PhaseStep.BEGIN_COMBAT, 1);
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Makeshift Mannequin", "Carrion Feeder");
waitStackResolved(1, PhaseStep.BEGIN_COMBAT, 1);
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Coat with Venom", "Carrion Feeder");
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 3 for perm, 6 for card, so should not return
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Demonic Vigor", 1);
assertGraveyardCount(playerA, "Makeshift Mannequin", 1);
assertGraveyardCount(playerA, "Carrion Feeder", 1);
assertPermanentCount(playerA, "Carrion Feeder", 0);
assertHandCount(playerA, "Carrion Feeder", 0);
}
}

View file

@ -3,6 +3,7 @@ package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.ModalDoubleFacedCard;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
@ -36,7 +37,8 @@ public class ReturnToHandAttachedEffect extends OneShotEffect {
return false;
}
Card card = permanent.getMainCard();
if (permanent.getZoneChangeCounter(game) + 1 != card.getZoneChangeCounter(game)) {
// TODO: Once MDFC ZCC increments are fixed properly, can remove this special case. For now must allow so effect works.
if (permanent.getZoneChangeCounter(game) + 1 != card.getZoneChangeCounter(game) && !(card instanceof ModalDoubleFacedCard)) {
return false;
}
return player.moveCards(card, Zone.HAND, source, game);