mirror of
https://github.com/correl/mage.git
synced 2024-11-28 19:19:55 +00:00
[KHC] Fix Ethereal Valkyrie and added tests. Closes #9361
This commit is contained in:
parent
19a896df57
commit
65122676e5
2 changed files with 228 additions and 5 deletions
|
@ -136,7 +136,7 @@ class EtherealValkyrieEffect extends OneShotEffect {
|
|||
foretellAbility = new ForetellAbility(exileCard, leftHalfCost, rightHalfCost);
|
||||
} else if (exileCard instanceof ModalDoubleFacesCard) {
|
||||
ModalDoubleFacesCardHalf leftHalfCard = ((ModalDoubleFacesCard) exileCard).getLeftHalfCard();
|
||||
if (!leftHalfCard.isLand(game)) {
|
||||
if (!leftHalfCard.isLand(game)) { // Only MDFC cards with a left side a land have a land on the right side too
|
||||
String leftHalfCost = CardUtil.reduceCost(leftHalfCard.getManaCost(), 2).getText();
|
||||
game.getState().setValue(exileCard.getMainCard().getId().toString() + "Foretell Cost", leftHalfCost);
|
||||
ModalDoubleFacesCardHalf rightHalfCard = ((ModalDoubleFacesCard) exileCard).getRightHalfCard();
|
||||
|
@ -154,14 +154,21 @@ class EtherealValkyrieEffect extends OneShotEffect {
|
|||
game.getState().setValue(exileCard.getMainCard().getId().toString() + "Foretell Cost", creatureCost);
|
||||
game.getState().setValue(exileCard.getMainCard().getId().toString() + "Foretell Split Cost", spellCost);
|
||||
foretellAbility = new ForetellAbility(exileCard, creatureCost, spellCost);
|
||||
} else {
|
||||
} else if (!exileCard.isLand()){
|
||||
// normal card
|
||||
String costText = CardUtil.reduceCost(exileCard.getManaCost(), 2).getText();
|
||||
game.getState().setValue(exileCard.getId().toString() + "Foretell Cost", costText);
|
||||
foretellAbility = new ForetellAbility(exileCard, costText);
|
||||
}
|
||||
|
||||
// All card types (including lands) must be exiled
|
||||
UUID exileId = CardUtil.getExileZoneId(exileCard.getMainCard().getId().toString() + "foretellAbility", game);
|
||||
controller.moveCardsToExile(exileCard, source, game, true, exileId, " Foretell Turn Number: " + game.getTurnNum());
|
||||
exileCard.setFaceDown(true, game);
|
||||
|
||||
// all done pre-processing so stick the foretell cost effect onto the main card
|
||||
// note that the card is not foretell'd into exile, it is put into exile and made foretold
|
||||
// If the card is a non-land, it will not be exiled.
|
||||
if (foretellAbility != null) {
|
||||
// copy source and use it for the foretold effect on the exiled card
|
||||
// bug #8673
|
||||
|
@ -169,9 +176,6 @@ class EtherealValkyrieEffect extends OneShotEffect {
|
|||
copiedSource.newId();
|
||||
copiedSource.setSourceId(exileCard.getId());
|
||||
game.getState().setValue(exileCard.getMainCard().getId().toString() + "Foretell Turn Number", game.getTurnNum());
|
||||
UUID exileId = CardUtil.getExileZoneId(exileCard.getMainCard().getId().toString() + "foretellAbility", game);
|
||||
controller.moveCardsToExile(exileCard, source, game, true, exileId, " Foretell Turn Number: " + game.getTurnNum());
|
||||
exileCard.setFaceDown(true, game);
|
||||
foretellAbility.setSourceId(exileCard.getId());
|
||||
foretellAbility.setControllerId(exileCard.getOwnerId());
|
||||
game.getState().addOtherAbility(exileCard, foretellAbility);
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
package org.mage.test.cards.single.khc;
|
||||
|
||||
import mage.abilities.keyword.ForecastAbility;
|
||||
import mage.cards.basiclands.Mountain;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* {@link mage.cards.e.EtherealValkyrie Ethereal Valkyrie}
|
||||
* <p>
|
||||
* Whenever Ethereal Valkyrie enters the battlefield or attacks, draw a card, then exile a card from your hand face down.
|
||||
* It becomes foretold.
|
||||
* Its foretell cost is its mana cost reduced by {2}.
|
||||
* (On a later turn, you may cast it for its foretell cost, even if this creature has left the battlefield.)
|
||||
*
|
||||
* @author Alex-Vasile
|
||||
*/
|
||||
public class EtherealValkyrieTest extends CardTestPlayerBase {
|
||||
|
||||
// {4}{W}{U}
|
||||
private static final String etherealValkyrie = "Ethereal Valkyrie";
|
||||
// Suspend 4—{U}
|
||||
// Target player draws three cards.
|
||||
private static final String ancestralVision = "Ancestral Vision";
|
||||
// {5}{R} Creature-Land MDFC
|
||||
private static final String akoumWarrior = "Akoum Warrior";
|
||||
private static final String akoumTeeth = "Akoum Teeth";
|
||||
// {3}{U}{U}-{1}{U} Creature-Creature MDFC
|
||||
private static final String alrund = "Alrund, God of the Cosmos";
|
||||
private static final String hakka = "Hakka, Whispering Raven";
|
||||
// MDFC with where both sides are lands
|
||||
private static final String blightclimbPathway = "Brightclimb Pathway";
|
||||
private static final String grimclimbPathway = "Grimclimb Pathway";
|
||||
// {3}
|
||||
// {T}: Add one mana of any color
|
||||
private static final String alloyMyr = "Alloy Myr";
|
||||
// Land
|
||||
private static final String exoticOrchard = "Exotic Orchard";
|
||||
|
||||
/**
|
||||
* Test that a regular card is playable.
|
||||
*/
|
||||
@Test
|
||||
public void testRegularCard() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.HAND, playerA, etherealValkyrie);
|
||||
addCard(Zone.HAND, playerA, alloyMyr); // The one to exile with ETB ability
|
||||
|
||||
setStrictChooseMode(true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, etherealValkyrie);
|
||||
addTarget(playerA, alloyMyr);
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, alloyMyr, 1);
|
||||
|
||||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell");
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, alloyMyr, 0);
|
||||
assertPermanentCount(playerA, alloyMyr, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reported Bug: When you only have lands in hand the game enters a permanent rollback state.
|
||||
* https://github.com/magefree/mage/issues/9361
|
||||
*/
|
||||
@Test
|
||||
public void testLand() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.HAND, playerA, etherealValkyrie);
|
||||
addCard(Zone.HAND, playerA, exoticOrchard);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, etherealValkyrie);
|
||||
addTarget(playerA, exoticOrchard);
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, exoticOrchard, 1);
|
||||
|
||||
checkPlayableAbility("Can't fortell land", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Foretell", false);
|
||||
|
||||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
}
|
||||
|
||||
/**
|
||||
* MDFC cards where both sides are lands should be exiled, but not fortell-able.
|
||||
*/
|
||||
@Test
|
||||
public void testMDFCDualLand() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.HAND, playerA, etherealValkyrie);
|
||||
|
||||
addCard(Zone.HAND, playerA, blightclimbPathway);
|
||||
|
||||
|
||||
setStrictChooseMode(true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, etherealValkyrie);
|
||||
addTarget(playerA, blightclimbPathway);
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, blightclimbPathway, 1);
|
||||
checkPlayableAbility("Can't fortell land", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Foretell", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* MDFC cards where only one side is a land should let you fortell its non-land side.
|
||||
*/
|
||||
@Test
|
||||
public void testMDFCNonLandLand() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.HAND, playerA, etherealValkyrie, 1);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||
addCard(Zone.HAND, playerA, akoumWarrior);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, etherealValkyrie);
|
||||
addTarget(playerA, akoumWarrior);
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, akoumWarrior, 1);
|
||||
|
||||
// TODO: Add functionality to test for this programmatically by changing assertAbilityCount
|
||||
showAvailableAbilities("Should only be 1 Foretell ability", 3, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell {3}{R}");
|
||||
|
||||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, akoumWarrior, 0);
|
||||
assertPermanentCount(playerA, akoumWarrior, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* MDFC cards where only one side is a land should let you fortell its non-land side.
|
||||
*/
|
||||
@Test
|
||||
public void testMDFCCreatureCreature() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 8);
|
||||
addCard(Zone.HAND, playerA, etherealValkyrie, 2);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||
addCard(Zone.HAND, playerA, alrund);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.HAND, playerA, alrund);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, etherealValkyrie);
|
||||
addTarget(playerA, alrund);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, etherealValkyrie);
|
||||
addTarget(playerA, alrund);
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, alrund, 2);
|
||||
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell {1}");
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell {U}");
|
||||
|
||||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, alrund, 0);
|
||||
assertPermanentCount(playerA, alrund, 1);
|
||||
assertPermanentCount(playerA, hakka, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a Suspend card, which should not be playable from exile with foretell.
|
||||
*/
|
||||
@Test
|
||||
public void testSuspendCard() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.HAND, playerA, etherealValkyrie);
|
||||
addCard(Zone.HAND, playerA, ancestralVision);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, etherealValkyrie);
|
||||
addTarget(playerA, ancestralVision);
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
assertExileCount(playerA, ancestralVision, 1);
|
||||
|
||||
checkPlayableAbility("Can't fortell suspend-only card", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Foretell", false);
|
||||
|
||||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue