Modal double-faced cards - fixed game error on usage with some replacement effects (example: Diluvian Primordial, closes #12176) (#12184)

This commit is contained in:
Susucre 2024-04-25 21:40:57 +02:00 committed by GitHub
parent 1ae48593a8
commit 36d6547bf8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 339 additions and 38 deletions

View file

@ -0,0 +1,42 @@
package org.mage.test.cards.cost.splitcards;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class SplitCardsReboundTest extends CardTestPlayerBase {
@Ignore // Cast Through Time is broken on Split Cards.
@Test
public void test_FireIce() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Cast Through Time"); // Instant and sorcery spells you control have rebound.
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
addCard(Zone.HAND, playerA, "Fire // Ice");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fire");
addTargetAmount(playerA, playerB, 2);
checkExileCount("in exile", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Fire // Ice", 1);
setChoice(playerA, true); // yes to Rebound trigger
setChoice(playerA, "Cast Ice"); // choose the side to cast
addTarget(playerA, "Mountain");
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
execute();
assertLife(playerB, 20 - 2);
assertGraveyardCount(playerA, "Fire // Ice", 1);
assertTapped("Mountain", true);
assertTapped("Swamp", false);
}
}

View file

@ -0,0 +1,83 @@
package org.mage.test.cards.single.gtc;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class DiluvianPrimordialTest extends CardTestPlayerBase {
/**
* {@link mage.cards.d.DiluvianPrimordial Diluvian Primordial} {5}{U}{U}
* Creature Avatar
* Flying
* When Diluvian Primordial enters the battlefield, for each opponent, you may cast up to one target instant or sorcery card from that players graveyard without paying its mana cost. If a spell cast this way would be put into a graveyard, exile it instead.
* 5/5
*/
private static final String primordial = "Diluvian Primordial";
// Bug: NPE on casting Valakut Awakening
@Test
public void test_MDFC() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, primordial);
addCard(Zone.BATTLEFIELD, playerA, "Island", 7);
addCard(Zone.GRAVEYARD, playerB, "Valakut Awakening"); // MDFC Instant / Land
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, primordial);
addTarget(playerA, "Valakut Awakening");
setChoice(playerA, true); // Yes to "You may"
setChoice(playerA, TestPlayer.CHOICE_SKIP); // No choice for Awakening's effect
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertExileCount(playerB, "Valakut Awakening", 1);
}
@Test
public void test_Split() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, primordial);
addCard(Zone.BATTLEFIELD, playerA, "Island", 7);
addCard(Zone.GRAVEYARD, playerB, "Fire // Ice");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, primordial);
addTarget(playerA, "Fire // Ice");
setChoice(playerA, true); // Yes to "You may"
setChoice(playerA, "Cast Ice"); // Choose what part of the card to cast
addTarget(playerA, primordial);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertExileCount(playerB, "Fire // Ice", 1);
assertTapped(primordial, true);
}
@Test
public void test_Adventure() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, primordial);
addCard(Zone.BATTLEFIELD, playerA, "Island", 7);
addCard(Zone.GRAVEYARD, playerB, "Twice Upon a Time"); // Adventure with Sorcery on main face
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, primordial);
addTarget(playerA, "Twice Upon a Time");
setChoice(playerA, true); // Yes to "You may"
setChoice(playerA, "Cast Unlikely Meeting"); // Cast Adventure side
addTarget(playerA, TestPlayer.TARGET_SKIP); // not searching for a Doctor
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertExileCount(playerB, "Twice Upon a Time", 1);
}
}

View file

@ -1,13 +1,21 @@
package org.mage.test.cards.triggers;
import mage.cards.Card;
import mage.cards.ModalDoubleFacedCard;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
import java.util.Objects;
import java.util.Optional;
/**
*
* @author LevelX2
*/
public class ReturnToHandEffectsTest extends CardTestPlayerBase {
@ -80,6 +88,91 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
}
/**
* Assumes there is exactly 1 permanent with the cardName, and checks its permanent zcc and card zcc
*/
private void checkZCCPermanent(String info, Player player, Game game, String cardName, int permanentZCC, int cardZCC, boolean checkMDFC, int leftZCC, int rightZCC) {
Optional<Permanent> optPermanent = game
.getBattlefield()
.getAllActivePermanents()
.stream()
.filter(Objects::nonNull)
.filter(p -> p.getName().equals(cardName))
.findFirst();
if (!optPermanent.isPresent()) {
Assert.fail(info + " — no permanent named \"" + cardName + "\" found on battlefield");
}
Permanent permanent = optPermanent.get();
Assert.assertEquals(info + " — permanent zcc for \"" + cardName + "\"", permanentZCC, permanent.getZoneChangeCounter(game));
Card card = game.getCard(permanent.getId()).getMainCard();
if (card == null) {
Assert.fail(info + " — missing card for permanent \"" + cardName + "\"");
}
Assert.assertEquals(info + " — card zcc for \"" + cardName + "\"", cardZCC, card.getZoneChangeCounter(game));
if (checkMDFC) {
Assert.assertEquals(info + " — left card zcc for \"" + cardName + "\"", leftZCC, ((ModalDoubleFacedCard) card).getLeftHalfCard().getZoneChangeCounter(game));
Assert.assertEquals(info + " — right card zcc for \"" + cardName + "\"", rightZCC, ((ModalDoubleFacedCard) card).getRightHalfCard().getZoneChangeCounter(game));
}
}
private void checkZCCNormalPermanent(String info, Player player, Game game, String cardName, int permanentZCC, int cardZCC) {
checkZCCPermanent(info, player, game, cardName, permanentZCC, cardZCC, false, cardZCC, cardZCC);
}
private void checkZCCMDFCPermanent(String info, Player player, Game game, String cardName, int permanentZCC, int mainCardZCC, int leftCardZCC, int rightCardZCC) {
checkZCCPermanent(info, player, game, cardName, permanentZCC, mainCardZCC, true, leftCardZCC, rightCardZCC);
}
/**
* Assumes there is exactly 1 card in player's graveyard with the cardName, and checks its card zcc
*/
private void checkZCCCardInGraveyard(String info, Player player, Game game, String cardName, int cardZCC) {
Optional<Card> optCard = game
.getPlayer(player.getId())
.getGraveyard()
.getCards(game)
.stream()
.filter(Objects::nonNull)
.filter(p -> p.getName().equals(cardName))
.findFirst();
if (!optCard.isPresent()) {
Assert.fail(info + " — no card named \"" + cardName + "\" found in graveyard");
}
Card card = optCard.get();
Assert.assertEquals(info + " — card zcc for \"" + cardName + "\"", cardZCC, card.getZoneChangeCounter(game));
}
/**
* Assumes there is exactly 1 card in player's hand with the cardName, and checks its card zcc
*/
private void checkZCCCardInHand(String info, Player player, Game game, String cardName, int cardZCC, boolean checkMDFC, int leftZCC, int rightZCC) {
Optional<Card> optCard = game
.getPlayer(player.getId())
.getHand()
.getCards(game)
.stream()
.filter(Objects::nonNull)
.filter(p -> p.getName().equals(cardName))
.findFirst();
if (!optCard.isPresent()) {
Assert.fail(info + " — no card named \"" + cardName + "\" found in hand");
}
Card card = optCard.get();
Assert.assertEquals(info + " — card zcc for \"" + cardName + "\"", cardZCC, card.getZoneChangeCounter(game));
if (checkMDFC) {
Assert.assertEquals(info + " — left card zcc for \"" + cardName + "\"", leftZCC, ((ModalDoubleFacedCard) card).getLeftHalfCard().getZoneChangeCounter(game));
Assert.assertEquals(info + " — right card zcc for \"" + cardName + "\"", rightZCC, ((ModalDoubleFacedCard) card).getRightHalfCard().getZoneChangeCounter(game));
}
}
private void checkZCCNormalCardInHand(String info, Player player, Game game, String cardName, int cardZCC) {
checkZCCCardInHand(info, player, game, cardName, cardZCC, false, cardZCC, cardZCC);
}
private void checkZCCMDFCCardInHand(String info, Player player, Game game, String cardName, int mainZCC, int leftZCC, int rightZCC) {
checkZCCCardInHand(info, player, game, cardName, mainZCC, true, leftZCC, rightZCC);
}
@Test
public void testZendikon() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
@ -90,12 +183,17 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Mountain");
runCode("1: check zcc permanent", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Mountain", 2, 2));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Mountain");
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Mountain", 4));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 2 for perm, 3 for card
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Wind Zendikon", 1);
@ -114,12 +212,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Vale");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Tangled Vale");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Vale", 2, 1, 1, 2));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Vale");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 2, 2, 4));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 2 for perm, 1 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Wind Zendikon", 1);
@ -138,12 +243,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Riverglide Pathway");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Riverglide Pathway");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("1: check zcc pre disfigure", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Riverglide Pathway", 2, 1, 2, 1));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Riverglide Pathway");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("2: check zcc post disfigure", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Riverglide Pathway", 2, 4, 2));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 2 for perm, 1 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Wind Zendikon", 1);
@ -162,12 +274,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lavaglide Pathway");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wind Zendikon", "Lavaglide Pathway");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Lavaglide Pathway", 2, 1, 1, 2));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Lavaglide Pathway");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Riverglide Pathway", 2, 2, 4));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 2 for perm, 1 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Wind Zendikon", 1);
@ -186,12 +305,17 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dryad Sophisticate");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Dryad Sophisticate");
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Dryad Sophisticate", 3, 3));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Dryad Sophisticate");
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Dryad Sophisticate", 5));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 3 for perm, 4 for card
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Demonic Vigor", 1);
@ -210,12 +334,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tangled Florahedron");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 3, 2, 3, 2));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Florahedron");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("2: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 3, 5, 3));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 3 for perm, 2 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Demonic Vigor", 1);
@ -234,18 +365,26 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
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");
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Dryad Sophisticate", 3, 3));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Dryad Sophisticate", true);
runCode("2: check zcc card", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Dryad Sophisticate", 5));
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");
runCode("3: check zcc", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Dryad Sophisticate", 7, 7));
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Dryad Sophisticate", true);
runCode("4: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Dryad Sophisticate", 9));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 7 for perm, 8 for card
assertGraveyardCount(playerA, "Disfigure", 2);
assertGraveyardCount(playerA, "Demonic Vigor", 2);
@ -264,18 +403,29 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
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");
// TODO: investigate why MDFC zcc moves separatedly.
runCode("1: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 3, 2, 3, 2));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Tangled Florahedron", true);
// TODO: investigate why MDFC zcc moves separatedly.
runCode("2: check zcc card", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 3, 5, 3));
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Tangled Florahedron");
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Demonic Vigor", "Tangled Florahedron", true);
// TODO: investigate why MDFC zcc moves separatedly.
runCode("3: check zcc", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 7, 4, 7, 4));
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Tangled Florahedron");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disfigure", "Tangled Florahedron", true);
// TODO: investigate why MDFC zcc moves separatedly.
runCode("4: check zcc card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 5, 9, 5));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 7 for perm, 4 for card (?!)
assertGraveyardCount(playerA, "Disfigure", 2);
assertGraveyardCount(playerA, "Demonic Vigor", 2);
@ -291,22 +441,30 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Demonic Vigor");
addCard(Zone.HAND, playerA, "Disfigure");
addCard(Zone.HAND, playerA, "Makeshift Mannequin");
addCard(Zone.HAND, playerA, "Coat with Venom");
addCard(Zone.HAND, playerA, "Coat with Venom"); // target for triggering the Makeshift Mannequin's sacrifice
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.PRECOMBAT_MAIN, playerA, "Demonic Vigor", "Carrion Feeder", true);
runCode("1: check zcc", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Carrion Feeder", 3, 3));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Disfigure", "Carrion Feeder");
waitStackResolved(1, PhaseStep.BEGIN_COMBAT, 1);
runCode("2: check graveyard zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCCardInGraveyard(info, player, game, "Carrion Feeder", 4));
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");
runCode("3: check zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCNormalPermanent(info, player, game, "Carrion Feeder", 5, 5));
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Coat with Venom", "Carrion Feeder", true);
runCode("4: check graveyard zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
(String info, Player player, Game game) -> checkZCCCardInGraveyard(info, player, game, "Carrion Feeder", 6));
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// ZCC is 3 for perm, 6 for card, so should not return
// Vigor tries to return the Carrion Feeder card with zcc 4, so 6 doesn't return.
assertGraveyardCount(playerA, "Disfigure", 1);
assertGraveyardCount(playerA, "Demonic Vigor", 1);