forked from External/mage
Merge pull request #14061
* move setPT to Card * Create DoubleFacedCard and DoubleFacedCardHalf to share code between … * Create Transforming Double Face Card class * allow putting either permanent side of a double faced card to the bat… * refactor exile and return transforming card * update ModalDoubleFacedCard references to DoubleFacedCard where relev… * update for GUI * refactor a disturb card * refactor more disturb cards for test coverage * refactor a transform card * refactor more transform cards for test coverage * fix Archangel Avacyn * fix cantPlayTDFCBackSide inconsistency * fix Double Faced Cards having triggers and static abilities when tran… * fix Double Faced Cards card view erroring when flipping in client * fix test_Copy_AsSpell_Backside inconsistency * enable Spider-Man MDFC * convert TDFC with saga as the front and add card references to Transf… * refactor More Than Meets the Eye Card * refactor a battle * refactor a craft card * update comment on PeterParkerTest * Merge branch 'master' into rework-dfc * fix Saga TDFC Azusa's Many Journeys * fix double faced cards adding permanent triggers / effects to game * move permanents entering map into Battlefield * convert Room cards for new Permanent structure * fix disturb not exiling * Merge branch 'master' into rework-dfc * fix Eddie Brock Power/Toughness * fix Miles Morales ability on main card * fix verify conditions for siege and day/night cards * change room characteristics to text effect to match game rules * update verify test to skip DoubleFacedCard in missing card test * accidentally removed transform condition * Merge branch 'master' into rework-dfc * fix verify * CardUtil - remove unnecessary line from castSingle method
This commit is contained in:
parent
29557f4334
commit
69e20b1061
121 changed files with 3020 additions and 2225 deletions
|
|
@ -200,23 +200,8 @@ public class IncubateTest extends CardTestPlayerBase {
|
|||
setChoice(playerA, true); // use copy
|
||||
setChoice(playerA, "Phyrexian Token");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after copy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Phyrexian Token", 2);
|
||||
|
||||
// kill original token
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy");
|
||||
addTarget(playerA, "Phyrexian Token[no copy]");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after kill", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Phyrexian Token", 1);
|
||||
showBattlefield("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
|
||||
// try to transform back side (nothing happen)
|
||||
// 701.28c
|
||||
// If a spell or ability instructs a player to transform a permanent that isn’t represented by a
|
||||
// transforming token or a transforming double-faced card, nothing happens.
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target transform", "Phyrexian Token");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after transform", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Incubator Token", 0);
|
||||
checkPermanentCount("after transform", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Phyrexian Token", 1);
|
||||
checkPermanentCount("after copy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Phyrexian Token", 1);
|
||||
// copy dies to state based actions
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,290 @@
|
|||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.common.SagaAbility;
|
||||
import mage.abilities.common.WerewolfFrontTriggeredAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TransformTest extends CardTestPlayerBase {
|
||||
|
||||
|
||||
/*
|
||||
Silvercoat Lion
|
||||
{1}{W}
|
||||
Creature - Cat
|
||||
|
||||
2/2
|
||||
*/
|
||||
private static final String silvercoatLion = "Silvercoat Lion";
|
||||
|
||||
/*
|
||||
Lightning Bolt
|
||||
{R}
|
||||
Instant
|
||||
Lightning Bolt deals 3 damage to any target.
|
||||
*/
|
||||
private static final String lightningBolt = "Lightning Bolt";
|
||||
|
||||
/*
|
||||
Azusa's Many Journeys
|
||||
{1}{G}
|
||||
Enchantment - Saga
|
||||
(As this Saga enters and after your draw step, add a lore counter.)
|
||||
I - You may play an additional land this turn.
|
||||
II - You gain 3 life.
|
||||
III - Exile this Saga, then return it to the battlefield transformed under your control.
|
||||
Likeness of the Seeker
|
||||
|
||||
Enchantment Creature - Human Monk
|
||||
Whenever Likeness of the Seeker becomes blocked, untap up to three lands you control.
|
||||
3/3
|
||||
*/
|
||||
private static final String azusasManyJourneys = "Azusa's Many Journeys";
|
||||
private static final String likenessOfTheSeeker = "Likeness of the Seeker";
|
||||
|
||||
/*
|
||||
Liliana, Heretical Healer
|
||||
{1}{B}{B}
|
||||
Legendary Creature - Human Cleric
|
||||
Lifelink
|
||||
Whenever another nontoken creature you control dies, exile Liliana Heretical Healer, then return her to the battlefield transformed under her owner's control. If you do, put a 2/2 black Zombie creature token onto the battlefield.
|
||||
2/3
|
||||
|
||||
Liliana, Defiant Necromancer
|
||||
Legendary Planeswalker - Liliana
|
||||
+2: Each player discards a card.
|
||||
-X: Return target nonlegendary creature with converted mana cost X from your graveyard to the battlefield.
|
||||
-8: You get an emblem with "Whenever a creature you control dies, return it to the battlefield under your control at the beginning of the next end step."
|
||||
*/
|
||||
private static final String lilianaHereticalHealer = "Liliana, Heretical Healer";
|
||||
private static final String lilianaDefiantNecromancer = "Liliana, Defiant Necromancer";
|
||||
|
||||
/*
|
||||
Languish
|
||||
{2}{B}{B}
|
||||
Sorcery
|
||||
All creatures get -4/-4 until end of turn.
|
||||
*/
|
||||
private static final String languish = "Languish";
|
||||
|
||||
/*
|
||||
Nissa, Vastwood Seer
|
||||
{2}{G}
|
||||
Legendary Creature - Elf Scout
|
||||
When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library.
|
||||
Whenever a land enters the battlefield under your control, if you control seven or more lands, exile Nissa, then return her to the battlefield transformed under her owner's control.
|
||||
2/2
|
||||
|
||||
Nissa, Sage Animist
|
||||
Legendary Planeswalker - Nissa
|
||||
+1: Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand.
|
||||
-2: Put a legendary 4/4 green Elemental creature token named Ashaya, the Awoken World onto the battlefield.
|
||||
-7: Untap up to six target lands. They become 6/6 Elemental creatures. They're still lands.
|
||||
*/
|
||||
private static final String nissaVastwoodSeer = "Nissa, Vastwood Seer";
|
||||
private static final String nissaSageAnimist = "Nissa, Sage Animist";
|
||||
|
||||
/*
|
||||
Fireball
|
||||
{X}{R}
|
||||
Sorcery
|
||||
Fireball deals X damage divided evenly, rounded down, among any number of target creatures and/or players.
|
||||
Fireball costs {1} more to cast for each target beyond the first.
|
||||
*/
|
||||
private static final String fireball = "Fireball";
|
||||
|
||||
/*
|
||||
Infernal Scarring
|
||||
{1}{B}
|
||||
Enchantment - Aura
|
||||
Enchant creature
|
||||
Enchanted creature gets +2/+0 and has "When this creature dies, draw a card."
|
||||
*/
|
||||
private static final String infernalScarring = "Infernal Scarring";
|
||||
|
||||
/*
|
||||
Autumnal Gloom
|
||||
{2}{G}
|
||||
Enchantment
|
||||
{B}: Put the top card of your library into your graveyard.
|
||||
Delirium - At the beginning of your end step, if there are four or more card types among cards in your graveyard, transform Autumnal Gloom.
|
||||
|
||||
Ancient of the Equinox
|
||||
Creature - Treefolk
|
||||
Trample, hexproof
|
||||
4/4
|
||||
*/
|
||||
private static final String autumnalGloom = "Autumnal Gloom";
|
||||
private static final String ancientOfTheEquinox = "Ancient of the Equinox";
|
||||
|
||||
/*
|
||||
Huntmaster of the Fells
|
||||
{2}{R}{G}
|
||||
Creature - Human Werewolf
|
||||
Whenever this creature enters the battlefield or transforms into Huntmaster of the Fells, put a 2/2 green Wolf creature token onto the battlefield and you gain 2 life.
|
||||
At the beginning of each upkeep, if no spells were cast last turn, transform Huntmaster of the Fells.
|
||||
2/2
|
||||
|
||||
Ravager of the Fells
|
||||
Creature - Werewolf
|
||||
Trample
|
||||
Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls.
|
||||
At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ravager of the Fells.
|
||||
4/4
|
||||
*/
|
||||
private static final String huntmasterOfTheFells = "Huntmaster of the Fells";
|
||||
private static final String ravagerOfTheFells = "Ravager of the Fells";
|
||||
|
||||
/*
|
||||
Eldrazi Displacer
|
||||
{2}{W}
|
||||
Creature - Eldrazi
|
||||
Devoid
|
||||
{2}{C}: Exile another target creature, then return it to the battlefield tapped under its owner's control.
|
||||
3/3
|
||||
*/
|
||||
private static final String eldraziDisplacer = "Eldrazi Displacer";
|
||||
|
||||
/*
|
||||
Howlpack Piper
|
||||
{3}{G}
|
||||
Creature - Human Werewolf
|
||||
This spell can't be countered.
|
||||
{1}{G}, {T}: You may put a creature card from your hand onto the battlefield. If it's a Wolf or Werewolf, untap Howlpack Piper. Activate only as a sorcery.
|
||||
Daybound
|
||||
2/2
|
||||
|
||||
Wildsong Howler
|
||||
Creature - Werewolf
|
||||
Whenever this creature enters the battlefield or transforms into Wildsong Howler, look at the top six cards of your library. You may reveal a creature card from among them and put it into your hand. Put the rest on the bottom of your library in a random order.
|
||||
Nightbound
|
||||
4/4
|
||||
*/
|
||||
private static final String howlpackPiper = "Howlpack Piper";
|
||||
private static final String wildsongHowler = "Wildsong Howler";
|
||||
|
||||
/*
|
||||
Thing in the Ice
|
||||
{1}{U}
|
||||
Creature - Horror
|
||||
Defender
|
||||
Thing in the Ice enters the battlefield with four ice counters on it.
|
||||
Whenever you cast an instant or sorcery spell, remove an ice counter from Thing in the Ice. Then if it has no ice counters on it, transform it.
|
||||
|
||||
Awoken Horror
|
||||
Creature - Kraken Horror
|
||||
When this creature transforms into Awoken Horrow, return all non-Horror creatures to their owners' hands.
|
||||
7/8
|
||||
*/
|
||||
private static final String thingInTheIce = "Thing in the Ice";
|
||||
private static final String awokenHorror = "Awoken Horror";
|
||||
|
||||
/*
|
||||
Banners Raised
|
||||
{R}
|
||||
Instant
|
||||
Creatures you control get +1/+0 until end of turn.
|
||||
*/
|
||||
private static final String bannersRaised = "Banners Raised";
|
||||
|
||||
/*
|
||||
Phantasmal Image
|
||||
{1}{U}
|
||||
Creature - Illusion
|
||||
You may have Phantasmal Image enter the battlefield as a copy of any creature on the battlefield, except it's an Illusion in addition to its other types and it gains "When this creature becomes the target of a spell or ability, sacrifice it."
|
||||
*/
|
||||
private static final String phantasmalImage = "Phantasmal Image";
|
||||
|
||||
/*
|
||||
Delver of Secrets
|
||||
{U}
|
||||
Creature - Human Wizard
|
||||
At the beginning of your upkeep, look at the top card of your library. You may reveal that card. If an instant or sorcery card is revealed this way, transform Delver of Secrets.
|
||||
1/1
|
||||
|
||||
Insectile Aberration
|
||||
Creature - Human Insect
|
||||
Flying
|
||||
3/2
|
||||
*/
|
||||
private static final String delverOfSecrets = "Delver of Secrets";
|
||||
private static final String insectileAberration = "Insectile Aberration";
|
||||
|
||||
/*
|
||||
Moonmist
|
||||
{1}{G}
|
||||
Instant
|
||||
Transform all Humans. Prevent all combat damage that would be dealt this turn by creatures other than Werewolves and Wolves. <i>(Only double-faced cards can be transformed.)</i>
|
||||
*/
|
||||
private static final String moonmist = "Moonmist";
|
||||
|
||||
/*
|
||||
Maskwood Nexus
|
||||
{4}
|
||||
Artifact
|
||||
Creatures you control are every creature type. The same is true for creature spells you control and creature cards you own that aren't on the battlefield.
|
||||
{3}, {T}: Create a 2/2 blue Shapeshifter creature token with changeling.
|
||||
*/
|
||||
private static final String maskwoodNexus = "Maskwood Nexus";
|
||||
|
||||
/*
|
||||
Dress Down
|
||||
{1}{U}
|
||||
Enchantment
|
||||
Flash
|
||||
When Dress Down enters the battlefield, draw a card.
|
||||
Creatures lose all abilities.
|
||||
At the beginning of the end step, sacrifice Dress Down.
|
||||
*/
|
||||
private static final String dressDown = "Dress Down";
|
||||
|
||||
/*
|
||||
Baithook Angler
|
||||
{1}{U}
|
||||
Creature - Human Peasant
|
||||
Disturb {1}{U}
|
||||
2/1
|
||||
|
||||
Hook-Haunt Drifter
|
||||
Creature - Spirit
|
||||
Flying
|
||||
If Hook-Haunt Drifter would be put into a graveyard from anywhere, exile it instead.
|
||||
1/2
|
||||
*/
|
||||
private static final String baithookAngler = "Baithook Angler";
|
||||
private static final String hookHauntDrifter = "Hook-Haunt Drifter";
|
||||
|
||||
/*
|
||||
Croaking Counterpart
|
||||
{1}{G}{U}
|
||||
Sorcery
|
||||
Create a token that's a copy of target non-Frog creature, except it's a 1/1 green Frog.
|
||||
Flashback {3}{G}{U}
|
||||
*/
|
||||
private static final String croakingCounterpart = "Croaking Counterpart";
|
||||
|
||||
/*
|
||||
Abnormal Endurance
|
||||
{1}{B}
|
||||
Instant
|
||||
Until end of turn, target creature gets +2/+0 and gains "When this creature dies, return it to the battlefield tapped under its owner's control."
|
||||
*/
|
||||
private static final String abnormalEndurance = "Abnormal Endurance";
|
||||
|
||||
@Test
|
||||
public void NissaVastwoodSeerTest() {
|
||||
|
||||
|
|
@ -22,13 +295,13 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
// When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library.
|
||||
// Whenever a land you control enters, if you control seven or more lands, exile Nissa, then return her to the battlefield transformed under her owner's control.
|
||||
|
||||
addCard(Zone.HAND, playerA, "Nissa, Vastwood Seer");
|
||||
addCard(Zone.HAND, playerA, nissaVastwoodSeer);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Forest", 2);
|
||||
// {G}{G}, Sacrifice Rootrunner: Put target land on top of its owner's library.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Rootrunner"); // {2}{G}{G}
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nissa, Vastwood Seer", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nissaVastwoodSeer, true);
|
||||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest");
|
||||
|
||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{G}{G}", "Swamp");
|
||||
|
|
@ -40,38 +313,38 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
|
||||
assertGraveyardCount(playerB, "Rootrunner", 1);
|
||||
|
||||
assertPermanentCount(playerA, "Nissa, Vastwood Seer", 0);
|
||||
assertPermanentCount(playerA, "Nissa, Sage Animist", 1);
|
||||
assertPermanentCount(playerA, nissaVastwoodSeer, 0);
|
||||
assertPermanentCount(playerA, nissaSageAnimist, 1);
|
||||
|
||||
assertCounterCount("Nissa, Sage Animist", CounterType.LOYALTY, 4);
|
||||
assertCounterCount(nissaSageAnimist, CounterType.LOYALTY, 4);
|
||||
assertPermanentCount(playerA, "Forest", 6);
|
||||
assertPermanentCount(playerA, "Swamp", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void LilianaHereticalHealer() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, silvercoatLion, 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
|
||||
// Lifelink
|
||||
// Whenever another nontoken creature you control dies, exile Liliana Heretical Healer, then return her to the battlefield transformed under her owner's control. If you do, put a 2/2 black Zombie creature token onto the battlefield.
|
||||
addCard(Zone.HAND, playerA, "Liliana, Heretical Healer");
|
||||
addCard(Zone.HAND, playerA, lilianaHereticalHealer);
|
||||
|
||||
addCard(Zone.HAND, playerB, "Lightning Bolt");
|
||||
addCard(Zone.HAND, playerB, lightningBolt);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Liliana, Heretical Healer");
|
||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, "Lightning Bolt", "Silvercoat Lion");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lilianaHereticalHealer);
|
||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, lightningBolt, silvercoatLion);
|
||||
|
||||
setStopAt(1, PhaseStep.DECLARE_ATTACKERS);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
|
||||
assertGraveyardCount(playerB, "Lightning Bolt", 1);
|
||||
assertGraveyardCount(playerA, silvercoatLion, 1);
|
||||
assertGraveyardCount(playerB, lightningBolt, 1);
|
||||
|
||||
assertPermanentCount(playerA, "Liliana, Heretical Healer", 0);
|
||||
assertPermanentCount(playerA, "Liliana, Defiant Necromancer", 1);
|
||||
assertCounterCount("Liliana, Defiant Necromancer", CounterType.LOYALTY, 3);
|
||||
assertPermanentCount(playerA, lilianaHereticalHealer, 0);
|
||||
assertPermanentCount(playerA, lilianaDefiantNecromancer, 1);
|
||||
assertCounterCount(lilianaDefiantNecromancer, CounterType.LOYALTY, 3);
|
||||
|
||||
assertPermanentCount(playerA, "Zombie Token", 1);
|
||||
}
|
||||
|
|
@ -84,45 +357,45 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
*/
|
||||
@Test
|
||||
public void LilianaHereticalHealer2() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, silvercoatLion, 1);
|
||||
|
||||
// Lifelink
|
||||
// Whenever another nontoken creature you control dies, exile Liliana Heretical Healer, then return her to the battlefield transformed under her owner's control. If you do, put a 2/2 black Zombie creature token onto the battlefield.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Liliana, Heretical Healer");
|
||||
addCard(Zone.BATTLEFIELD, playerA, lilianaHereticalHealer);
|
||||
|
||||
// All creatures get -4/-4 until end of turn.
|
||||
addCard(Zone.HAND, playerB, "Languish");
|
||||
addCard(Zone.HAND, playerB, languish);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 4);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Languish");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, languish);
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Languish", 1);
|
||||
assertPermanentCount(playerA, "Liliana, Defiant Necromancer", 0);
|
||||
assertGraveyardCount(playerB, languish, 1);
|
||||
assertPermanentCount(playerA, lilianaDefiantNecromancer, 0);
|
||||
assertPermanentCount(playerA, "Zombie Token", 0);
|
||||
|
||||
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
|
||||
assertGraveyardCount(playerA, "Liliana, Heretical Healer", 1);
|
||||
assertGraveyardCount(playerA, silvercoatLion, 1);
|
||||
assertGraveyardCount(playerA, lilianaHereticalHealer, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestEnchantmentToCreature() {
|
||||
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion", 1);
|
||||
addCard(Zone.GRAVEYARD, playerA, "Lightning Bolt", 1);
|
||||
addCard(Zone.GRAVEYARD, playerA, "Fireball", 1);
|
||||
addCard(Zone.GRAVEYARD, playerA, "Infernal Scarring", 1);
|
||||
addCard(Zone.GRAVEYARD, playerA, silvercoatLion, 1);
|
||||
addCard(Zone.GRAVEYARD, playerA, lightningBolt, 1);
|
||||
addCard(Zone.GRAVEYARD, playerA, fireball, 1);
|
||||
addCard(Zone.GRAVEYARD, playerA, infernalScarring, 1);
|
||||
|
||||
// {B}: Put the top card of your library into your graveyard.
|
||||
// <i>Delirium</i> &mdash At the beginning of your end step, if there are four or more card types among cards in your graveyard, transform Autumnal Gloom.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Autumnal Gloom");
|
||||
addCard(Zone.BATTLEFIELD, playerA, autumnalGloom);
|
||||
|
||||
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Autumnal Gloom", 0);
|
||||
assertPermanentCount(playerA, "Ancient of the Equinox", 1);
|
||||
assertPermanentCount(playerA, autumnalGloom, 0);
|
||||
assertPermanentCount(playerA, ancientOfTheEquinox, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -138,6 +411,7 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
*/
|
||||
@Test
|
||||
public void testCultOfTheWaxingMoon() {
|
||||
setStrictChooseMode(true);
|
||||
// Whenever a permanent you control transforms into a non-Human creature, put a 2/2 green Wolf creature token onto the battlefield.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Cult of the Waxing Moon");
|
||||
// {1}{G} - Human Werewolf
|
||||
|
|
@ -151,6 +425,7 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, "Cult of the Waxing Moon", 1);
|
||||
assertPermanentCount(playerA, "Timber Shredder", 1); // Night-side card of Hinterland Logger, Werewolf (non-human)
|
||||
assertPermanentCount(playerA, "Wolf Token", 1); // wolf token created
|
||||
assertAbilityCount(playerA, "Timber Shredder", WerewolfFrontTriggeredAbility.class, 0); // no front face ability
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -184,18 +459,42 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testStartledAwakeMoonmist() {
|
||||
addCard(Zone.HAND, playerA, "Startled Awake");
|
||||
addCard(Zone.HAND, playerA, "Moonmist");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 11);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Maskwood Nexus");
|
||||
public void testPersistentNightmareTrigger() {
|
||||
// Target opponent puts the top thirteen cards of their library into their graveyard.
|
||||
// {3}{U}{U}: Put Startled Awake from your graveyard onto the battlefield transformed. Activate this ability only any time you could cast a sorcery.
|
||||
addCard(Zone.HAND, playerA, "Startled Awake"); // SORCERY {2}{U}{U}"
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 9);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Startled Awake", playerB);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{U}{U}");
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Moonmist");
|
||||
attack(3, playerA, "Persistent Nightmare");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.COMBAT_DAMAGE);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, 13);
|
||||
assertGraveyardCount(playerA, "Startled Awake", 0);
|
||||
assertPermanentCount(playerA, "Persistent Nightmare", 0); // Night-side card of Startled Awake
|
||||
assertHandCount(playerA, "Startled Awake", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartledAwakeMoonmist() {
|
||||
addCard(Zone.HAND, playerA, "Startled Awake");
|
||||
addCard(Zone.HAND, playerA, moonmist);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 11);
|
||||
addCard(Zone.BATTLEFIELD, playerA, maskwoodNexus);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Startled Awake", playerB);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{U}{U}");
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, moonmist);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -241,6 +540,25 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerB, "Lambholt Pacifist", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisturbExile() {
|
||||
addCard(Zone.GRAVEYARD, playerA, baithookAngler);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
|
||||
addCard(Zone.HAND, playerB, lightningBolt);
|
||||
|
||||
// Disturb {1}{U}
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hookHauntDrifter + " using Disturb");
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, lightningBolt, hookHauntDrifter);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, hookHauntDrifter, 0);
|
||||
assertExileCount(playerA, baithookAngler, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror Mockery copies the front face of a Transformed card rather than
|
||||
* the current face.
|
||||
|
|
@ -251,7 +569,7 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
* Trespasser.
|
||||
*/
|
||||
@Test
|
||||
public void testTransformCopyrnansformed() {
|
||||
public void testTransformCopyTransformed() {
|
||||
// Skulk (This creature can't be blocked by creatures with greater power.)
|
||||
// When Uninvited Geist deals combat damage to a player, transform it.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Uninvited Geist"); // Creature 2/2 {2}{U}
|
||||
|
|
@ -272,7 +590,7 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
setStopAt(3, PhaseStep.COMBAT_DAMAGE);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 15);
|
||||
assertLife(playerB, 20 - 2 - 3);
|
||||
|
||||
assertPermanentCount(playerB, "Mirror Mockery", 1);
|
||||
assertPermanentCount(playerA, "Unimpeded Trespasser", 1);
|
||||
|
|
@ -293,16 +611,16 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
// Transformed side: Avacyn, the Purifier - Creature 6/5
|
||||
// Flying
|
||||
// When this creature transforms into Avacyn, the Purifier, it deals 3 damage to each other creature and each opponent.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
addCard(Zone.BATTLEFIELD, playerA, silvercoatLion);
|
||||
addCard(Zone.HAND, playerA, lightningBolt);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
|
||||
// Devoid
|
||||
// {2}{C}: Exile another target creature, then return it to the battlefield tapped under its owner's control.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Eldrazi Displacer", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, eldraziDisplacer, 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wastes", 3);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, lightningBolt, silvercoatLion);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true);
|
||||
|
||||
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}{C}", "Archangel Avacyn");
|
||||
|
|
@ -310,10 +628,10 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 1);
|
||||
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
|
||||
assertGraveyardCount(playerA, lightningBolt, 1);
|
||||
assertGraveyardCount(playerA, silvercoatLion, 1);
|
||||
|
||||
assertPermanentCount(playerB, "Eldrazi Displacer", 1);
|
||||
assertPermanentCount(playerB, eldraziDisplacer, 1);
|
||||
assertPermanentCount(playerA, "Avacyn, the Purifier", 0);
|
||||
assertPermanentCount(playerA, "Archangel Avacyn", 1);
|
||||
}
|
||||
|
|
@ -355,20 +673,20 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
// Ravager of the Fells
|
||||
// Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls.
|
||||
// At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ravager of the Fells.
|
||||
addCard(Zone.HAND, playerA, "Huntmaster of the Fells"); // Creature {2}{R}{G}
|
||||
addCard(Zone.HAND, playerA, huntmasterOfTheFells); // Creature {2}{R}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
|
||||
// Devoid
|
||||
// {2}{C}: Exile another target creature, then return it to the battlefield tapped under its owner's control.
|
||||
addCard(Zone.HAND, playerB, "Eldrazi Displacer", 1); // Creature {2}{W}
|
||||
addCard(Zone.HAND, playerB, eldraziDisplacer, 1); // Creature {2}{W}
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wastes", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Huntmaster of the Fells");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Eldrazi Displacer");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, huntmasterOfTheFells);
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, eldraziDisplacer);
|
||||
|
||||
activateAbility(4, PhaseStep.UPKEEP, playerB, "{2}{C}", "Huntmaster of the Fells", "At the beginning of each upkeep");
|
||||
activateAbility(4, PhaseStep.UPKEEP, playerB, "{2}{C}", huntmasterOfTheFells, "At the beginning of each upkeep");
|
||||
|
||||
setStopAt(4, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
|
|
@ -376,11 +694,11 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
assertLife(playerA, 24);
|
||||
assertPermanentCount(playerA, "Wolf Token", 2);
|
||||
|
||||
assertPermanentCount(playerB, "Eldrazi Displacer", 1);
|
||||
assertPermanentCount(playerB, eldraziDisplacer, 1);
|
||||
|
||||
assertPermanentCount(playerA, "Ravager of the Fells", 0);
|
||||
assertPermanentCount(playerA, "Huntmaster of the Fells", 1);
|
||||
assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2);
|
||||
assertPermanentCount(playerA, ravagerOfTheFells, 0);
|
||||
assertPermanentCount(playerA, huntmasterOfTheFells, 1);
|
||||
assertPowerToughness(playerA, huntmasterOfTheFells, 2, 2);
|
||||
assertTappedCount("Plains", true, 2);
|
||||
assertTappedCount("Wastes", true, 1);
|
||||
}
|
||||
|
|
@ -392,50 +710,50 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
// Ravager of the Fells
|
||||
// Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls.
|
||||
// At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ravager of the Fells.
|
||||
addCard(Zone.HAND, playerA, "Huntmaster of the Fells"); // Creature {2}{R}{G}
|
||||
addCard(Zone.HAND, playerA, "Silvercoat Lion", 2);
|
||||
addCard(Zone.HAND, playerA, huntmasterOfTheFells); // Creature {2}{R}{G}
|
||||
addCard(Zone.HAND, playerA, silvercoatLion, 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Huntmaster of the Fells", true);
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion", true);
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, huntmasterOfTheFells, true);
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, silvercoatLion, true);
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, silvercoatLion);
|
||||
setStopAt(4, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 24);
|
||||
assertLife(playerB, 18);
|
||||
assertPermanentCount(playerA, "Wolf Token", 2);
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 2);
|
||||
assertPermanentCount(playerA, "Ravager of the Fells", 0);
|
||||
assertPermanentCount(playerA, "Huntmaster of the Fells", 1);
|
||||
assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2);
|
||||
assertPermanentCount(playerA, silvercoatLion, 2);
|
||||
assertPermanentCount(playerA, ravagerOfTheFells, 0);
|
||||
assertPermanentCount(playerA, huntmasterOfTheFells, 1);
|
||||
assertPowerToughness(playerA, huntmasterOfTheFells, 2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWildsongHowlerTrigger() {
|
||||
// The only Daybound/Nightbound card with a Transforms trigger on the back side
|
||||
removeAllCardsFromLibrary(playerA);
|
||||
addCard(Zone.HAND, playerA, "Howlpack Piper", 2); // Creature {2}{R}{G}
|
||||
addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 50);
|
||||
addCard(Zone.HAND, playerA, howlpackPiper, 2); // Creature {2}{R}{G}
|
||||
addCard(Zone.LIBRARY, playerA, silvercoatLion, 50);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Howlpack Piper");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, howlpackPiper);
|
||||
setChoice(playerA, true); //Transform trigger
|
||||
addTarget(playerA, "Silvercoat Lion");
|
||||
addTarget(playerA, silvercoatLion);
|
||||
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Howlpack Piper");
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, howlpackPiper);
|
||||
setChoice(playerA, true); //ETB trigger
|
||||
addTarget(playerA, "Silvercoat Lion");
|
||||
addTarget(playerA, silvercoatLion);
|
||||
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||
setStrictChooseMode(true);
|
||||
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Wildsong Howler", 2);
|
||||
assertPermanentCount(playerA, "Howlpack Piper", 0); // They should be both transformed
|
||||
assertHandCount(playerA, "Silvercoat Lion", 3);
|
||||
assertPermanentCount(playerA, wildsongHowler, 2);
|
||||
assertPermanentCount(playerA, howlpackPiper, 0); // They should be both transformed
|
||||
assertHandCount(playerA, silvercoatLion, 3);
|
||||
assertHandCount(playerA, 3); //The two Silvercoat Lions from triggers and 1 from natural card draw
|
||||
}
|
||||
|
||||
|
|
@ -455,37 +773,37 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
// Thing in the Ice enters the battlefield with four ice counters on it.
|
||||
// Whenever you cast an instant or sorcery spell, remove an ice counter from Thing in the Ice.
|
||||
// Then if it has no ice counters on it, transform it.
|
||||
addCard(Zone.HAND, playerA, "Thing in the Ice"); // Creature {1}{U}
|
||||
addCard(Zone.HAND, playerA, thingInTheIce); // Creature {1}{U}
|
||||
// Creatures you control get +1/+0 until end of turn.
|
||||
addCard(Zone.HAND, playerA, "Banners Raised", 4); // Creature {R}
|
||||
addCard(Zone.HAND, playerA, bannersRaised, 4); // Creature {R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
|
||||
// You may have Phantasmal Image enter the battlefield as a copy of any creature
|
||||
// on the battlefield, except it's an Illusion in addition to its other types and
|
||||
// it has "When this creature becomes the target of a spell or ability, sacrifice it."
|
||||
addCard(Zone.HAND, playerB, "Phantasmal Image", 1); // Creature {1}{U}
|
||||
addCard(Zone.HAND, playerB, phantasmalImage, 1); // Creature {1}{U}
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Thing in the Ice");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Banners Raised");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Banners Raised");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Banners Raised");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Banners Raised");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, thingInTheIce);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bannersRaised);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bannersRaised);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bannersRaised);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bannersRaised);
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Phantasmal Image");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, phantasmalImage);
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertGraveyardCount(playerA, "Banners Raised", 4);
|
||||
assertPermanentCount(playerA, "Thing in the Ice", 0);
|
||||
assertPermanentCount(playerA, "Awoken Horror", 1);
|
||||
assertPowerToughness(playerA, "Awoken Horror", 7, 8);
|
||||
assertGraveyardCount(playerA, bannersRaised, 4);
|
||||
assertPermanentCount(playerA, thingInTheIce, 0);
|
||||
assertPermanentCount(playerA, awokenHorror, 1);
|
||||
assertPowerToughness(playerA, awokenHorror, 7, 8);
|
||||
|
||||
assertPermanentCount(playerB, "Awoken Horror", 1);
|
||||
assertPowerToughness(playerB, "Awoken Horror", 7, 8);
|
||||
assertPermanentCount(playerB, awokenHorror, 1);
|
||||
assertPowerToughness(playerB, awokenHorror, 7, 8);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -493,45 +811,45 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
public void testMoonmistDelver() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||
addCard(Zone.HAND, playerA, "Delver of Secrets");
|
||||
addCard(Zone.HAND, playerA, "Moonmist", 2);
|
||||
addCard(Zone.HAND, playerA, delverOfSecrets);
|
||||
addCard(Zone.HAND, playerA, moonmist, 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Delver of Secrets");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, delverOfSecrets);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Moonmist");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, moonmist);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Delver of Secrets", 0);
|
||||
assertPermanentCount(playerA, "Insectile Aberration", 1);
|
||||
assertPermanentCount(playerA, delverOfSecrets, 0);
|
||||
assertPermanentCount(playerA, insectileAberration, 1);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Moonmist");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, moonmist);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Delver of Secrets", 1);
|
||||
assertPermanentCount(playerA, "Insectile Aberration", 0);
|
||||
assertPermanentCount(playerA, delverOfSecrets, 1);
|
||||
assertPermanentCount(playerA, insectileAberration, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoonmistHuntmasterDressdown() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Huntmaster of the Fells"); //Has on-transform triggers
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Maskwood Nexus"); //Make back side human
|
||||
addCard(Zone.BATTLEFIELD, playerA, huntmasterOfTheFells); //Has on-transform triggers
|
||||
addCard(Zone.BATTLEFIELD, playerA, maskwoodNexus); //Make back side human
|
||||
|
||||
|
||||
addCard(Zone.HAND, playerA, "Dress Down"); //Creatures lose all abilities
|
||||
addCard(Zone.HAND, playerA, "Moonmist", 2);
|
||||
addCard(Zone.HAND, playerA, dressDown); //Creatures lose all abilities
|
||||
addCard(Zone.HAND, playerA, moonmist, 2);
|
||||
|
||||
castSpell(1, PhaseStep.UPKEEP, playerA, "Dress Down");
|
||||
castSpell(1, PhaseStep.UPKEEP, playerA, dressDown);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Moonmist");
|
||||
checkPermanentCount("Huntmaster flipped", 1, PhaseStep.BEGIN_COMBAT, playerA, "Ravager of the Fells", 1);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Moonmist");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, moonmist);
|
||||
checkPermanentCount("Huntmaster flipped", 1, PhaseStep.BEGIN_COMBAT, playerA, ravagerOfTheFells, 1);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, moonmist);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -539,8 +857,71 @@ public class TransformTest extends CardTestPlayerBase {
|
|||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
assertGraveyardCount(playerA, "Dress Down", 1);
|
||||
assertPermanentCount(playerA, "Huntmaster of the Fells", 1);
|
||||
assertGraveyardCount(playerA, dressDown, 1);
|
||||
assertPermanentCount(playerA, huntmasterOfTheFells, 1);
|
||||
assertPermanentCount(playerA, 6+1+1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTokenCopyTransformed() {
|
||||
addCard(Zone.GRAVEYARD, playerA, baithookAngler);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Breeding Pool", 5);
|
||||
addCard(Zone.HAND, playerA, croakingCounterpart);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hook-Haunt Drifter using Disturb");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, croakingCounterpart, hookHauntDrifter);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
for (Permanent token : currentGame.getBattlefield().getActivePermanents(playerA.getId(), currentGame)) {
|
||||
if (!(token instanceof PermanentToken)) {
|
||||
continue;
|
||||
}
|
||||
assertTrue(token.getSubtype(currentGame).contains(SubType.FROG));
|
||||
assertEquals(ObjectColor.GREEN, token.getColor(currentGame));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFrontSaga() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, azusasManyJourneys);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, azusasManyJourneys, 0);
|
||||
assertPermanentCount(playerA, likenessOfTheSeeker, 1);
|
||||
assertPowerToughness(playerA, likenessOfTheSeeker, 3, 3);
|
||||
assertAbilityCount(playerA, likenessOfTheSeeker, SagaAbility.class, 0); // does not have saga ability
|
||||
assertLife(playerA, 20 + 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* testing if a double faced card gains a death trigger, it still works correctly
|
||||
*/
|
||||
@Test
|
||||
public void testDiesTrigger() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, baithookAngler);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
addCard(Zone.HAND, playerA, abnormalEndurance);
|
||||
|
||||
addCard(Zone.HAND, playerB, lightningBolt);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
|
||||
|
||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, lightningBolt, baithookAngler);
|
||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, abnormalEndurance, baithookAngler, lightningBolt);
|
||||
|
||||
setStopAt(1, PhaseStep.DECLARE_ATTACKERS);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, baithookAngler, 0);
|
||||
assertGraveyardCount(playerB, lightningBolt, 1);
|
||||
|
||||
assertPermanentCount(playerA, baithookAngler, 1);
|
||||
assertTrue(getPermanent(baithookAngler, playerA).isTapped());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,13 @@ package org.mage.test.cards.copy;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
|
|
@ -85,4 +88,22 @@ public class CopyCreatureCardToTokenImplTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, "Thrashing Brontodon", 1);
|
||||
assertType("Thrashing Brontodon", CardType.ARTIFACT, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTokenCopyTransformedHasSecondFaceWithModifications() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
String hookHauntDrifter = "Hook-Haunt Drifter";
|
||||
addCard(Zone.GRAVEYARD, playerA, "Baithook Angler");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Faerie Artisans", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Breeding Pool", 5);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hook-Haunt Drifter using Disturb");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
Permanent token = getPermanent(hookHauntDrifter, playerB);
|
||||
assertTrue(token.getCardType(currentGame).contains(CardType.ARTIFACT));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -907,6 +907,32 @@ public class ModalDoubleFacedCardsTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Copy_AsSpell_Backside() {
|
||||
addCard(Zone.HAND, playerA, "Alrund, God of the Cosmos", 1); // {3}{U}{U}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
//
|
||||
// Copy target creature spell you control, except it isn't legendary if the spell is legendary.
|
||||
addCard(Zone.HAND, playerA, "Double Major", 1); // {G}{U}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
|
||||
// cast mdf card
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 2);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hakka, Whispering Raven");
|
||||
// prepare copy of spell
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Double Major", "Hakka, Whispering Raven", "Hakka, Whispering Raven");
|
||||
checkStackSize("before copy spell", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 2);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA, true);
|
||||
checkStackSize("after copy spell", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 2);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hakka, Whispering Raven", 2);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Copy_AsCloneFromPermanent() {
|
||||
addCard(Zone.HAND, playerA, "Akoum Warrior", 1); // {5}{R}
|
||||
|
|
@ -1138,8 +1164,8 @@ public class ModalDoubleFacedCardsTest extends CardTestPlayerBase {
|
|||
Assert.assertNotNull(permanent);
|
||||
|
||||
// MDFC on battlefield has only one side (not transformable)
|
||||
Assert.assertFalse("server must not be transformable", permanent.isTransformable());
|
||||
Assert.assertNull("server must have not other side", permanent.getOtherFace());
|
||||
// Assert.assertFalse("server must not be transformable", permanent.isTransformable());
|
||||
// Assert.assertNull("server must have not other side", permanent.getOtherFace());
|
||||
|
||||
List<String> rules = permanent.getRules(game);
|
||||
Assert.assertTrue("server must ignore side 2 - untap ability", rules.stream().noneMatch(r -> r.contains("Untap")));
|
||||
|
|
|
|||
|
|
@ -1,19 +1,191 @@
|
|||
package org.mage.test.cards.cost.splitcards;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.EmptyNames;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.view.CardView;
|
||||
import mage.view.GameView;
|
||||
import mage.view.PlayerView;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.player.TestPlayer;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author oscscull
|
||||
*/
|
||||
public class RoomCardTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Bottomless Pool // Locker Room
|
||||
{U}
|
||||
Enchantment - Room
|
||||
When you unlock this door, return up to one target creature to its owner's hand.
|
||||
(You may cast either half. That door unlocks on the battlefield. As a sorcery, you may pay the mana cost of a locked door to unlock it.)
|
||||
<strong>Locker Room</strong>
|
||||
{4}{U}
|
||||
<strong>Enchantment -- Room</strong>
|
||||
Whenever one or more creatures you control deal combat damage to a player, draw a card.
|
||||
(You may cast either half. That door unlocks on the battlefield. As a sorcery, you may pay the mana cost of a locked door to unlock it.)
|
||||
*/
|
||||
private static final String bottomlessPoolLockerRoom = "Bottomless Pool // Locker Room";
|
||||
private static final String bottomlessPool = "Bottomless Pool";
|
||||
public static final String lockerRoom = "Locker Room";
|
||||
|
||||
|
||||
@Test
|
||||
public void testCardViewLeftHalf() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool, true);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
|
||||
runCode("print card view", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(playerA);
|
||||
PlayerView playerView = gameView.getPlayers().stream().findFirst().orElse(null);
|
||||
assertNotNull(playerView, "Player view must be found");
|
||||
CardView cardView = playerView.getBattlefield().values()
|
||||
.stream()
|
||||
.filter(pv -> pv.getName().equals(bottomlessPool))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
assertNotNull(cardView, "Locker Room card view must be found on battlefield");
|
||||
// permanent should have 3 abilities
|
||||
// unlock ability + unlock trigger from right half + info
|
||||
assertEquals(3, cardView.getRules().size(), "Locker Room must have 3 rules, has: " + cardView.getRules().size());
|
||||
assertEquals("{U}", cardView.getManaCostStr(), "Mana cost must be from left half");
|
||||
StringBuilder sb = new StringBuilder("\n" + cardView.getName());
|
||||
sb.append("\n - Types: ").append(cardView.getCardTypes());
|
||||
sb.append("\n - Subtypes: ").append(cardView.getSubTypes());
|
||||
sb.append("\n - Mana Cost: ").append(cardView.getManaCostStr());
|
||||
sb.append("\n - Abilities: ");
|
||||
cardView.getRules().forEach(rule -> sb.append("\n * ").append(rule));
|
||||
logger.info(sb.toString());
|
||||
});
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCardViewRightHalf() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lockerRoom, true);
|
||||
|
||||
runCode("print card view", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(playerA);
|
||||
PlayerView playerView = gameView.getPlayers().stream().findFirst().orElse(null);
|
||||
assertNotNull(playerView, "Player view must be found");
|
||||
CardView cardView = playerView.getBattlefield().values()
|
||||
.stream()
|
||||
.filter(pv -> pv.getName().equals(lockerRoom))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
assertNotNull(cardView, "Locker Room card view must be found on battlefield");
|
||||
// permanent should have 3 abilities
|
||||
// unlock ability + unlock trigger from left half + info
|
||||
assertEquals(3, cardView.getRules().size(), "Locker Room must have 3 rules, has: " + cardView.getRules().size());
|
||||
assertEquals("{4}{U}", cardView.getManaCostStr(), "Mana cost must be from right half");
|
||||
StringBuilder sb = new StringBuilder("\n" + cardView.getName());
|
||||
sb.append("\n - Types: ").append(cardView.getCardTypes());
|
||||
sb.append("\n - Subtypes: ").append(cardView.getSubTypes());
|
||||
sb.append("\n - Mana Cost: ").append(cardView.getManaCostStr());
|
||||
sb.append("\n - Abilities: ");
|
||||
cardView.getRules().forEach(rule -> sb.append("\n * ").append(rule));
|
||||
logger.info(sb.toString());
|
||||
});
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCardViewBothHalves() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool, true);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{U}: Unlock the right half.");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
runCode("print card view", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(playerA);
|
||||
PlayerView playerView = gameView.getPlayers().stream().findFirst().orElse(null);
|
||||
assertNotNull(playerView, "Player view must be found");
|
||||
CardView cardView = playerView.getBattlefield().values()
|
||||
.stream()
|
||||
.filter(pv -> pv.getName().equals(bottomlessPoolLockerRoom))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
assertNotNull(cardView, "Locker Room card view must be found on battlefield");
|
||||
// permanent should have 3 abilities
|
||||
// 1 ability from both halves
|
||||
// no unlock abilities
|
||||
// 1 info
|
||||
String manaCost = getPermanent(bottomlessPoolLockerRoom)
|
||||
.getManaCost()
|
||||
.stream()
|
||||
.map(Objects::toString)
|
||||
.reduce("", String::concat);
|
||||
assertEquals(3, cardView.getRules().size(), "Locker Room must have 3 rules, has: " + cardView.getRules().size());
|
||||
assertEquals(manaCost, cardView.getManaCostStr(), "Mana cost must be combined from both halves");
|
||||
StringBuilder sb = new StringBuilder("\n" + cardView.getName());
|
||||
sb.append("\n - Types: ").append(cardView.getCardTypes());
|
||||
sb.append("\n - Subtypes: ").append(cardView.getSubTypes());
|
||||
sb.append("\n - Mana Cost: ").append(cardView.getManaCostStr());
|
||||
sb.append("\n - Abilities: ");
|
||||
cardView.getRules().forEach(rule -> sb.append("\n * ").append(rule));
|
||||
logger.info(sb.toString());
|
||||
});
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCardViewFullyLocked() {
|
||||
setStrictChooseMode(true);
|
||||
addCard(Zone.BATTLEFIELD, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
|
||||
runCode("print card view", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(playerA);
|
||||
PlayerView playerView = gameView.getPlayers().stream().findFirst().orElse(null);
|
||||
assertNotNull(playerView, "Player view must be found");
|
||||
CardView cardView = playerView.getBattlefield().values()
|
||||
.stream()
|
||||
.filter(pv -> pv.getName().isEmpty())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
assertNotNull(cardView, "Locked room card view must be found on battlefield");
|
||||
// permanent should have 3 abilities
|
||||
// 1 info
|
||||
// two unlock abilities
|
||||
assertEquals(3, cardView.getRules().size(), "Locked room must have 3 rules, has: " + cardView.getRules().size());
|
||||
assertEquals("", cardView.getManaCostStr(), "Mana cost must be empty");
|
||||
StringBuilder sb = new StringBuilder("\n" + cardView.getName());
|
||||
sb.append("\n - Types: ").append(cardView.getCardTypes());
|
||||
sb.append("\n - Subtypes: ").append(cardView.getSubTypes());
|
||||
sb.append("\n - Mana Cost: ").append(cardView.getManaCostStr());
|
||||
sb.append("\n - Abilities: ");
|
||||
cardView.getRules().forEach(rule -> sb.append("\n * ").append(rule));
|
||||
logger.info(sb.toString());
|
||||
});
|
||||
|
||||
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
}
|
||||
|
||||
// Bottomless pool is cast. It unlocks, and the trigger to return a creature
|
||||
// should bounce one of two grizzly bears.
|
||||
@Test
|
||||
|
|
@ -23,13 +195,13 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner’s hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 2);
|
||||
|
||||
checkPlayableAbility("playerA can cast Bottomless Pool", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
|
||||
"Cast Bottomless Pool", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
|
||||
// Target one of playerB's "Grizzly Bears" with the return effect.
|
||||
addTarget(playerA, "Grizzly Bears");
|
||||
|
|
@ -43,11 +215,11 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// Verify that one "Grizzly Bears" has been returned to playerB's hand.
|
||||
assertHandCount(playerB, "Grizzly Bears", 1);
|
||||
// Verify that "Bottomless Pool" is on playerA's battlefield.
|
||||
assertPermanentCount(playerA, "Bottomless Pool", 1);
|
||||
assertPermanentCount(playerA, bottomlessPool, 1);
|
||||
// Verify that "Bottomless Pool" is an Enchantment.
|
||||
assertType("Bottomless Pool", CardType.ENCHANTMENT, true);
|
||||
assertType(bottomlessPool, CardType.ENCHANTMENT, true);
|
||||
// Verify that "Bottomless Pool" has the Room subtype.
|
||||
assertSubtype("Bottomless Pool", SubType.ROOM);
|
||||
assertSubtype(bottomlessPool, SubType.ROOM);
|
||||
}
|
||||
|
||||
// Locker room is cast. It enters, and gives a coastal piracy effect that
|
||||
|
|
@ -59,7 +231,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner’s hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
|
||||
|
||||
// Cards to be drawn
|
||||
|
|
@ -68,7 +240,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// 2 attackers
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Locker Room");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lockerRoom);
|
||||
attack(1, playerA, "Memnite");
|
||||
attack(1, playerA, "Memnite");
|
||||
// After combat damage, Memnites dealt combat damage to playerB (1 damage * 2).
|
||||
|
|
@ -83,9 +255,9 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
|
||||
// Assertions after the first execute() (Locker Room and creatures are on
|
||||
// battlefield, combat resolved):
|
||||
assertPermanentCount(playerA, "Locker Room", 1);
|
||||
assertType("Locker Room", CardType.ENCHANTMENT, true);
|
||||
assertSubtype("Locker Room", SubType.ROOM);
|
||||
assertPermanentCount(playerA, lockerRoom, 1);
|
||||
assertType(lockerRoom, CardType.ENCHANTMENT, true);
|
||||
assertSubtype(lockerRoom, SubType.ROOM);
|
||||
assertPermanentCount(playerA, "Memnite", 2);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -102,13 +274,13 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner’s hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
|
||||
// 2 creatures owned by player A
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Locker Room");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPlayableAbility("playerA can unlock Bottomless Pool", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
|
||||
"{U}: Unlock the left half.", true);
|
||||
|
|
@ -125,12 +297,12 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, "Memnite", 1);
|
||||
// Verify that one "Memnite" has been returned to playerA's hand.
|
||||
assertHandCount(playerA, "Memnite", 1);
|
||||
// Verify that "Bottomless Pool // Locker Room" is on playerA's battlefield.
|
||||
assertPermanentCount(playerA, "Bottomless Pool // Locker Room", 1);
|
||||
// Verify that "Bottomless Pool // Locker Room" is an Enchantment.
|
||||
assertType("Bottomless Pool // Locker Room", CardType.ENCHANTMENT, true);
|
||||
// Verify that "Bottomless Pool // Locker Room" has the Room subtype.
|
||||
assertSubtype("Bottomless Pool // Locker Room", SubType.ROOM);
|
||||
// Verify that bottomlessPoolLockerRoom is on playerA's battlefield.
|
||||
assertPermanentCount(playerA, bottomlessPoolLockerRoom, 1);
|
||||
// Verify that bottomlessPoolLockerRoom is an Enchantment.
|
||||
assertType(bottomlessPoolLockerRoom, CardType.ENCHANTMENT, true);
|
||||
// Verify that bottomlessPoolLockerRoom has the Room subtype.
|
||||
assertSubtype(bottomlessPoolLockerRoom, SubType.ROOM);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -140,7 +312,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner’s hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.HAND, playerA, "Felidar Guardian");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
|
|
@ -148,7 +320,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creatures owned by player A
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
// resolve spell cast
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
// unlock and trigger bounce on Memnite
|
||||
|
|
@ -160,7 +332,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
// etb and flicker on Bottomless Pool
|
||||
setChoice(playerA, "Yes");
|
||||
addTarget(playerA, "Bottomless Pool");
|
||||
addTarget(playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
||||
|
|
@ -187,7 +359,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner’s hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.HAND, playerA, "Felidar Guardian");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
|
|
@ -196,7 +368,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Memnite", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Black Knight", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
// resolve spell cast
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
// unlock and trigger bounce on Memnite
|
||||
|
|
@ -208,7 +380,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
// etb and flicker on Bottomless Pool
|
||||
setChoice(playerA, "Yes");
|
||||
addTarget(playerA, "Bottomless Pool");
|
||||
addTarget(playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
// can unlock again
|
||||
checkPlayableAbility("playerA can unlock Bottomless Pool", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
|
||||
|
|
@ -228,7 +400,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// Verify that one "Black Knight" has been returned to playerA's hand.
|
||||
assertHandCount(playerA, "Black Knight", 1);
|
||||
// Verify that "Bottomless Pool" is on playerA's battlefield.
|
||||
assertPermanentCount(playerA, "Bottomless Pool", 1);
|
||||
assertPermanentCount(playerA, bottomlessPool, 1);
|
||||
// Verify that "Felidar Guardian" is on playerA's battlefield.
|
||||
assertPermanentCount(playerA, "Felidar Guardian", 1);
|
||||
}
|
||||
|
|
@ -240,11 +412,11 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner’s hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Erratic Apparition", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
// resolve spell cast
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
setChoice(playerA, "When you unlock"); // x2 triggers
|
||||
|
|
@ -262,8 +434,8 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
|
||||
// Assertions:
|
||||
// Verify that "Bottomless Pool // Locker Room" is on playerA's battlefield.
|
||||
assertPermanentCount(playerA, "Bottomless Pool // Locker Room", 1);
|
||||
// Verify that bottomlessPoolLockerRoom is on playerA's battlefield.
|
||||
assertPermanentCount(playerA, bottomlessPoolLockerRoom, 1);
|
||||
// Verify that "Erratic Apparition" is on playerA's battlefield.
|
||||
assertPermanentCount(playerA, "Erratic Apparition", 1);
|
||||
// Verify that "Erratic Apparition" has been pumped twice (etb + fully unlock)
|
||||
|
|
@ -277,17 +449,17 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner’s hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.HAND, playerA, "See Double");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Ornithopter", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
// Copy spell on the stack
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "See Double");
|
||||
setModeChoice(playerA, "1");
|
||||
addTarget(playerA, "Bottomless Pool");
|
||||
addTarget(playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 3);
|
||||
addTarget(playerA, "Memnite");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
|
@ -303,7 +475,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// Verify that one "Ornithopter" has been returned to playerA's hand.
|
||||
assertHandCount(playerA, "Ornithopter", 1);
|
||||
// Verify that 2 "Bottomless Pool" are on playerA's battlefield.
|
||||
assertPermanentCount(playerA, "Bottomless Pool", 2);
|
||||
assertPermanentCount(playerA, bottomlessPool, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -313,13 +485,13 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner's hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.HAND, playerA, "Clever Impersonator");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Ornithopter", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, "Memnite");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
|
@ -327,7 +499,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clever Impersonator");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
setChoice(playerA, "Yes");
|
||||
setChoice(playerA, "Bottomless Pool");
|
||||
setChoice(playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA,
|
||||
|
|
@ -347,7 +519,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
assertHandCount(playerA, "Ornithopter", 1);
|
||||
// Verify that the original "Bottomless Pool" is on playerA's battlefield, and a
|
||||
// clone.
|
||||
assertPermanentCount(playerA, "Bottomless Pool", 2);
|
||||
assertPermanentCount(playerA, bottomlessPool, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -366,11 +538,11 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// {U}{U}, Sacrifice this creature: Counter target spell with the same name as a
|
||||
// card exiled with this creature.
|
||||
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.HAND, playerA, "Twiddle");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mindreaver", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
addCard(Zone.LIBRARY, playerA, "Bottomless Pool // Locker Room", 1);
|
||||
addCard(Zone.LIBRARY, playerA, bottomlessPoolLockerRoom, 1);
|
||||
addCard(Zone.LIBRARY, playerA, "Plains", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Twiddle");
|
||||
|
|
@ -384,10 +556,10 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
addTarget(playerA, playerA);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA,
|
||||
"{U}{U}, Sacrifice {this}:");
|
||||
addTarget(playerA, "Bottomless Pool");
|
||||
addTarget(playerA, bottomlessPool);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -424,7 +596,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// Target creature and all other creatures with the same name as that creature
|
||||
// get -3/-3 until end of turn.
|
||||
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room", 4);
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom, 4);
|
||||
addCard(Zone.HAND, playerA, "Cackling Counterpart");
|
||||
addCard(Zone.HAND, playerA, "Bile Blight");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 17);
|
||||
|
|
@ -432,17 +604,17 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Opalescence");
|
||||
|
||||
// Cast Bottomless Pool (unlocked left half)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Locker Room (unlocked right half)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Locker Room");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Bottomless Pool then unlock Locker Room (both halves unlocked)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
|
@ -451,7 +623,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
|
||||
// Create a fully locked room using Cackling Counterpart
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cackling Counterpart");
|
||||
addTarget(playerA, "Bottomless Pool // Locker Room");
|
||||
addTarget(playerA, bottomlessPoolLockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Bile Blight targeting the fully locked room
|
||||
|
|
@ -468,21 +640,21 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// then -2/-2 after Bile Blight (dies)
|
||||
assertPermanentCount(playerA, EmptyNames.FULLY_LOCKED_ROOM.getTestCommand(), 0);
|
||||
// Token, so nothing should be in grave
|
||||
assertGraveyardCount(playerA, "Bottomless Pool // Locker Room", 0);
|
||||
assertGraveyardCount(playerA, bottomlessPoolLockerRoom, 0);
|
||||
|
||||
// Other rooms should NOT be affected by Bile Blight since they have different
|
||||
// names
|
||||
// Bottomless Pool: 1/1 base + 1/1 from anthem = 2/2
|
||||
assertPowerToughness(playerA, "Bottomless Pool", 2, 2);
|
||||
assertPowerToughness(playerA, bottomlessPool, 2, 2);
|
||||
// Locker Room: 5/5 base + 1/1 from anthem = 6/6
|
||||
assertPowerToughness(playerA, "Locker Room", 6, 6);
|
||||
assertPowerToughness(playerA, lockerRoom, 6, 6);
|
||||
// Bottomless Pool // Locker Room: 6/6 base + 1/1 from anthem = 7/7
|
||||
assertPowerToughness(playerA, "Bottomless Pool // Locker Room", 7, 7);
|
||||
assertPowerToughness(playerA, bottomlessPoolLockerRoom, 7, 7);
|
||||
|
||||
// Verify remaining rooms are still on battlefield
|
||||
assertPermanentCount(playerA, "Bottomless Pool", 1);
|
||||
assertPermanentCount(playerA, "Locker Room", 1);
|
||||
assertPermanentCount(playerA, "Bottomless Pool // Locker Room", 1);
|
||||
assertPermanentCount(playerA, bottomlessPool, 1);
|
||||
assertPermanentCount(playerA, lockerRoom, 1);
|
||||
assertPermanentCount(playerA, bottomlessPoolLockerRoom, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -515,7 +687,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// Target creature and all other creatures with the same name as that creature
|
||||
// get -3/-3 until end of turn.
|
||||
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room", 4);
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom, 4);
|
||||
addCard(Zone.HAND, playerA, "Cackling Counterpart");
|
||||
addCard(Zone.HAND, playerA, "Bile Blight");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 17);
|
||||
|
|
@ -523,17 +695,17 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Opalescence");
|
||||
|
||||
// Cast Bottomless Pool (unlocked left half)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Locker Room (unlocked right half)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Locker Room");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Bottomless Pool then unlock Locker Room (both halves unlocked)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
|
@ -542,12 +714,12 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
|
||||
// Create a fully locked room using Cackling Counterpart
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cackling Counterpart");
|
||||
addTarget(playerA, "Bottomless Pool // Locker Room");
|
||||
addTarget(playerA, bottomlessPoolLockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Bile Blight targeting the half locked room
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bile Blight");
|
||||
addTarget(playerA, "Locker Room");
|
||||
addTarget(playerA, lockerRoom);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -559,21 +731,21 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// since they share the "Locker Room" name component
|
||||
|
||||
// Locker Room: 5/5 base + 1/1 from anthem - 3/3 from Bile Blight = 3/3
|
||||
assertPowerToughness(playerA, "Locker Room", 3, 3);
|
||||
assertPowerToughness(playerA, lockerRoom, 3, 3);
|
||||
// Bottomless Pool // Locker Room: 6/6 base + 1/1 from anthem - 3/3 from Bile
|
||||
// Blight = 4/4
|
||||
assertPowerToughness(playerA, "Bottomless Pool // Locker Room", 4, 4);
|
||||
assertPowerToughness(playerA, bottomlessPoolLockerRoom, 4, 4);
|
||||
|
||||
// Other rooms should NOT be affected
|
||||
// Bottomless Pool: 1/1 base + 1/1 from anthem = 2/2 (unaffected)
|
||||
assertPowerToughness(playerA, "Bottomless Pool", 2, 2);
|
||||
assertPowerToughness(playerA, bottomlessPool, 2, 2);
|
||||
// Fully locked room: 0/0 base + 1/1 from anthem = 1/1 (unaffected)
|
||||
assertPowerToughness(playerA, EmptyNames.FULLY_LOCKED_ROOM.getTestCommand(), 1, 1);
|
||||
|
||||
// Verify all rooms are still on battlefield
|
||||
assertPermanentCount(playerA, "Bottomless Pool", 1);
|
||||
assertPermanentCount(playerA, "Locker Room", 1);
|
||||
assertPermanentCount(playerA, "Bottomless Pool // Locker Room", 1);
|
||||
assertPermanentCount(playerA, bottomlessPool, 1);
|
||||
assertPermanentCount(playerA, lockerRoom, 1);
|
||||
assertPermanentCount(playerA, bottomlessPoolLockerRoom, 1);
|
||||
assertPermanentCount(playerA, EmptyNames.FULLY_LOCKED_ROOM.getTestCommand(), 1);
|
||||
}
|
||||
|
||||
|
|
@ -607,7 +779,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// Target creature and all other creatures with the same name as that creature
|
||||
// get -3/-3 until end of turn.
|
||||
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room", 4);
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom, 4);
|
||||
addCard(Zone.HAND, playerA, "Cackling Counterpart");
|
||||
addCard(Zone.HAND, playerA, "Bile Blight");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 17);
|
||||
|
|
@ -615,17 +787,17 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Opalescence");
|
||||
|
||||
// Cast Bottomless Pool (unlocked left half)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Locker Room (unlocked right half)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Locker Room");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Bottomless Pool then unlock Locker Room (both halves unlocked)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
|
@ -634,12 +806,12 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
|
||||
// Create a fully locked room using Cackling Counterpart
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cackling Counterpart");
|
||||
addTarget(playerA, "Bottomless Pool // Locker Room");
|
||||
addTarget(playerA, bottomlessPoolLockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Bile Blight targeting the fully locked room
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bile Blight");
|
||||
addTarget(playerA, "Bottomless Pool // Locker Room");
|
||||
addTarget(playerA, bottomlessPoolLockerRoom);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -647,27 +819,27 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
|
||||
// Assertions:
|
||||
// All rooms except the fully locked room should be affected by Bile Blight
|
||||
// since they all share name components with "Bottomless Pool // Locker Room"
|
||||
// since they all share name components with bottomlessPoolLockerRoom
|
||||
|
||||
// Bottomless Pool: 1/1 base + 1/1 from anthem - 3/3 from Bile Blight = -1/-1
|
||||
// (dies)
|
||||
assertPermanentCount(playerA, "Bottomless Pool", 0);
|
||||
assertGraveyardCount(playerA, "Bottomless Pool // Locker Room", 1);
|
||||
assertPermanentCount(playerA, bottomlessPool, 0);
|
||||
assertGraveyardCount(playerA, bottomlessPoolLockerRoom, 1);
|
||||
|
||||
// Locker Room: 5/5 base + 1/1 from anthem - 3/3 from Bile Blight = 3/3
|
||||
assertPowerToughness(playerA, "Locker Room", 3, 3);
|
||||
assertPowerToughness(playerA, lockerRoom, 3, 3);
|
||||
|
||||
// Bottomless Pool // Locker Room: 6/6 base + 1/1 from anthem - 3/3 from Bile
|
||||
// Blight = 4/4
|
||||
assertPowerToughness(playerA, "Bottomless Pool // Locker Room", 4, 4);
|
||||
assertPowerToughness(playerA, bottomlessPoolLockerRoom, 4, 4);
|
||||
|
||||
// Fully locked room should NOT be affected (different name)
|
||||
// Fully locked room: 0/0 base + 1/1 from anthem = 1/1 (unaffected)
|
||||
assertPowerToughness(playerA, EmptyNames.FULLY_LOCKED_ROOM.getTestCommand(), 1, 1);
|
||||
|
||||
// Verify remaining rooms are still on battlefield
|
||||
assertPermanentCount(playerA, "Locker Room", 1);
|
||||
assertPermanentCount(playerA, "Bottomless Pool // Locker Room", 1);
|
||||
assertPermanentCount(playerA, lockerRoom, 1);
|
||||
assertPermanentCount(playerA, bottomlessPoolLockerRoom, 1);
|
||||
assertPermanentCount(playerA, EmptyNames.FULLY_LOCKED_ROOM.getTestCommand(), 1);
|
||||
}
|
||||
|
||||
|
|
@ -678,7 +850,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// creature to its owner's hand.
|
||||
// Locker Room {4}{U} Whenever one or more creatures you control deal combat
|
||||
// damage to a player, draw a card.
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.HAND, playerA, "Counterspell");
|
||||
addCard(Zone.HAND, playerA, "Campus Renovation");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||
|
|
@ -689,16 +861,16 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1);
|
||||
|
||||
// Cast Bottomless Pool
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
|
||||
// Counter it while on stack
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Counterspell");
|
||||
addTarget(playerA, "Bottomless Pool");
|
||||
addTarget(playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Use Campus Renovation to return it from graveyard
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Campus Renovation");
|
||||
addTarget(playerA, "Bottomless Pool // Locker Room");
|
||||
addTarget(playerA, bottomlessPoolLockerRoom);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -749,26 +921,26 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// As Pithing Needle enters, choose a card name.
|
||||
// Activated abilities of sources with the chosen name can't be activated.
|
||||
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.HAND, playerA, "Pithing Needle");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Opalescence");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Diviner's Wand");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 20);
|
||||
|
||||
// Cast Bottomless Pool (unlocked left half only)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Equip Diviner's Wand
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {3}");
|
||||
addTarget(playerA, "Bottomless Pool");
|
||||
addTarget(playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Pithing Needle naming the locked side
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pithing Needle");
|
||||
setChoice(playerA, "Locker Room");
|
||||
setChoice(playerA, lockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Validate that the room can activate the gained ability
|
||||
|
|
@ -789,7 +961,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
|
||||
// Verify the room is now fully unlocked
|
||||
assertPermanentCount(playerA, "Bottomless Pool // Locker Room", 1);
|
||||
assertPermanentCount(playerA, bottomlessPoolLockerRoom, 1);
|
||||
}
|
||||
|
||||
// Test converting one permanent into one room, then another (the room halves
|
||||
|
|
@ -813,14 +985,14 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// or
|
||||
// land until end of turn.
|
||||
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.HAND, playerA, "Surgical Suite // Hospital Room");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mirage Mirror");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 20);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite", 1);
|
||||
|
||||
// Cast Bottomless Pool (unlocked left half only)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
|
@ -832,7 +1004,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}: {this} becomes a copy");
|
||||
addTarget(playerA, "Bottomless Pool // Locker Room");
|
||||
addTarget(playerA, bottomlessPoolLockerRoom);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{U}: Unlock the right half.");
|
||||
|
||||
|
|
@ -848,7 +1020,7 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
|
||||
// Verify unlocked Bottomless pool
|
||||
assertPermanentCount(playerA, "Bottomless Pool // Locker Room", 1);
|
||||
assertPermanentCount(playerA, bottomlessPoolLockerRoom, 1);
|
||||
// Verify unlocked Surgical Suite
|
||||
assertPermanentCount(playerA, "Surgical Suite", 1);
|
||||
// Verify mirage mirror is Hospital Room
|
||||
|
|
@ -873,32 +1045,33 @@ public class RoomCardTest extends CardTestPlayerBase {
|
|||
// other types,
|
||||
// and it has "{2}{U}{U}: Return Sakashima the Impostor to its owner's hand at
|
||||
// the beginning of the next end step."
|
||||
String sakashimaTheImpostor = "Sakashima the Impostor";
|
||||
|
||||
addCard(Zone.HAND, playerA, "Bottomless Pool // Locker Room");
|
||||
addCard(Zone.HAND, playerA, bottomlessPoolLockerRoom);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 10);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Opalescence");
|
||||
addCard(Zone.HAND, playerA, sakashimaTheImpostor);
|
||||
|
||||
addCard(Zone.HAND, playerB, "Sakashima the Impostor");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 10);
|
||||
|
||||
// Cast Bottomless Pool (unlocked left half only)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bottomlessPool);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// Cast Sakashima copying the room
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Sakashima the Impostor");
|
||||
setChoice(playerB, "Yes"); // Choose to copy
|
||||
waitStackResolved(2, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sakashimaTheImpostor);
|
||||
setChoice(playerA, "Yes"); // Choose to copy
|
||||
setChoice(playerA, bottomlessPool);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{U}: Unlock the right half.");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
setStopAt(2, PhaseStep.END_TURN);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
// Verify Sakashima entered and is copying the room
|
||||
assertPermanentCount(playerB, "Sakashima the Impostor", 1);
|
||||
// Verify Sakashima dies to state-based actions
|
||||
// copies room and because sakashima has no unlocked designations, its mana value is 0
|
||||
// opalescence makes it a 0/0 and it dies
|
||||
assertPermanentCount(playerA, sakashimaTheImpostor, 0);
|
||||
assertGraveyardCount(playerA, sakashimaTheImpostor, 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +36,8 @@ public class EtherealValkyrieTest extends CardTestPlayerBase {
|
|||
private static final String alloyMyr = "Alloy Myr";
|
||||
// Land
|
||||
private static final String exoticOrchard = "Exotic Orchard";
|
||||
// {U} Creature-Planeswalker TDFC
|
||||
private static final String tamiyo = "Tamiyo, Inquisitive Student";
|
||||
|
||||
/**
|
||||
* Test that a regular card is playable.
|
||||
|
|
@ -202,4 +204,27 @@ public class EtherealValkyrieTest extends CardTestPlayerBase {
|
|||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a TDFC, which should be castable.
|
||||
*/
|
||||
@Test
|
||||
public void testTransformingDoubleFacedCard() {
|
||||
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, tamiyo);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, etherealValkyrie);
|
||||
addTarget(playerA, tamiyo);
|
||||
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell {U}");
|
||||
|
||||
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
execute();
|
||||
assertPermanentCount(playerA, tamiyo, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package org.mage.test.cards.single.spm;
|
|||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
|
@ -33,7 +32,6 @@ public class GwenStacyTest extends CardTestPlayerBase {
|
|||
private static final String ghostSpider = "Ghost-Spider";
|
||||
|
||||
@Test
|
||||
@Ignore("Enable after transform mdfc rework")
|
||||
public void testGhostSpider() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import mage.constants.PhaseStep;
|
|||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
|
@ -18,19 +17,20 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
public class PeterParkerTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
Peter Parker
|
||||
{1}{W}
|
||||
Legendary Creature - Human Scientist Hero
|
||||
When Peter Parker enters, create a 2/1 green Spider creature token with reach.
|
||||
{1}{G}{W}{U}: Transform Peter Parker. Activate only as a sorcery.
|
||||
Amazing Spider-Man
|
||||
{1}{G}{W}{U}
|
||||
Legendary Creature - Spider Human Hero
|
||||
Vigilance, reach
|
||||
Each legendary spell you cast that's one or more colors has web-slinging {G}{W}{U}.
|
||||
4/4
|
||||
*/
|
||||
Peter Parker
|
||||
{1}{W}
|
||||
Legendary Creature - Human Scientist Hero
|
||||
When Peter Parker enters, create a 2/1 green Spider creature token with reach.
|
||||
{1}{G}{W}{U}: Transform Peter Parker. Activate only as a sorcery.
|
||||
Amazing Spider-Man
|
||||
{1}{G}{W}{U}
|
||||
Legendary Creature - Spider Human Hero
|
||||
Vigilance, reach
|
||||
Each legendary spell you cast that's one or more colors has web-slinging {G}{W}{U}.
|
||||
4/4
|
||||
*/
|
||||
private static final String peterParker = "Peter Parker";
|
||||
public static final String amazingSpiderMan = "Amazing Spider-Man";
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -73,8 +73,16 @@ public class PeterParkerTest extends CardTestPlayerBase {
|
|||
*/
|
||||
private static final String balduvianBears = "Balduvian Bears";
|
||||
|
||||
/*
|
||||
Unsummon
|
||||
{U}
|
||||
Instant
|
||||
Return target creature to its owner's hand.
|
||||
*/
|
||||
private static final String unsummon = "Unsummon";
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore("Enable after MDFC rework")
|
||||
public void testAmazingSpiderMan() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
|
|
@ -91,7 +99,7 @@ public class PeterParkerTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 8);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Amazing Spider-Man", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, amazingSpiderMan, true);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "tap all"); // tap bears, addCard command isn't working to set tapped
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
|
|
@ -112,4 +120,131 @@ public class PeterParkerTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransform() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCustomCardWithAbility("tap all creatures", playerA, new SimpleActivatedAbility(
|
||||
new TapAllEffect(new FilterCreaturePermanent(SubType.BEAR, "bears")),
|
||||
new ManaCostsImpl<>("")
|
||||
));
|
||||
|
||||
addCard(Zone.HAND, playerA, peterParker);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
|
||||
addCard(Zone.HAND, playerA, adelbertSteiner);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "tap all"); // tap bears, addCard command isn't working to set tapped
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, peterParker, true);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{G}{W}{U}: Transform");
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, adelbertSteiner + " with Web-slinging");
|
||||
setChoice(playerA, balduvianBears); // return to hand
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, amazingSpiderMan, 1);
|
||||
assertPermanentCount(playerA, adelbertSteiner, 1);
|
||||
assertPermanentCount(playerA, balduvianBears, 0);
|
||||
assertHandCount(playerA, balduvianBears, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* test that MDFC doesn't have static ability from one side after transforming
|
||||
*/
|
||||
@Test
|
||||
public void testTransformLosesWebSlinging() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCustomCardWithAbility("tap all creatures", playerA, new SimpleActivatedAbility(
|
||||
new TapAllEffect(new FilterCreaturePermanent(SubType.BEAR, "bears")),
|
||||
new ManaCostsImpl<>("")
|
||||
));
|
||||
addCustomEffect_TargetTransform(playerA);
|
||||
|
||||
addCard(Zone.HAND, playerA, peterParker);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
|
||||
addCard(Zone.HAND, playerA, adelbertSteiner);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "tap all"); // tap bears, addCard command isn't working to set tapped
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, peterParker, true);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{G}{W}{U}: Transform"); // transform to Spider-Man
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
checkPlayableAbility("card in hand has web-slinging", 1, PhaseStep.PRECOMBAT_MAIN,
|
||||
playerA, "Cast " + adelbertSteiner + " with Web-slinging", true);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target transform", amazingSpiderMan);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
checkPlayableAbility("card in hand does not have web-slinging", 1, PhaseStep.PRECOMBAT_MAIN,
|
||||
playerA, "Cast " + adelbertSteiner + " with Web-slinging", false);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, amazingSpiderMan, 0);
|
||||
assertPermanentCount(playerA, peterParker, 1);
|
||||
assertHandCount(playerA, adelbertSteiner, 1);
|
||||
assertPermanentCount(playerA, balduvianBears, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* test showing if a transformed MDFC gets re-cast, it won't trigger effects from the other face
|
||||
*/
|
||||
@Test
|
||||
public void testTransformCastSecondSideDoesntTriggerFront() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCustomCardWithAbility("tap all creatures", playerA, new SimpleActivatedAbility(
|
||||
new TapAllEffect(new FilterCreaturePermanent(SubType.BEAR, "bears")),
|
||||
new ManaCostsImpl<>("")
|
||||
));
|
||||
addCustomEffect_TargetTransform(playerA);
|
||||
|
||||
addCard(Zone.HAND, playerA, peterParker);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 8);
|
||||
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
|
||||
addCard(Zone.HAND, playerA, adelbertSteiner);
|
||||
addCard(Zone.HAND, playerA, unsummon);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "tap all"); // tap bears, addCard command isn't working to set tapped
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, amazingSpiderMan, true);
|
||||
|
||||
checkPlayableAbility("card in hand has web-slinging", 1, PhaseStep.PRECOMBAT_MAIN,
|
||||
playerA, "Cast " + adelbertSteiner + " with Web-slinging", true);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target transform", amazingSpiderMan);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
checkPlayableAbility("card in hand does not have web-slinging", 1, PhaseStep.PRECOMBAT_MAIN,
|
||||
playerA, "Cast " + adelbertSteiner + " with Web-slinging", false);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, unsummon, peterParker, true);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, amazingSpiderMan);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, amazingSpiderMan, 1);
|
||||
assertPermanentCount(playerA, peterParker, 0);
|
||||
assertHandCount(playerA, adelbertSteiner, 1);
|
||||
assertPermanentCount(playerA, balduvianBears, 1);
|
||||
assertPermanentCount(playerA, "Spider Token", 0);
|
||||
currentGame.getState().getTriggers().forEach(
|
||||
(key, value) -> logger.info(key + " - " + value)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -213,14 +213,12 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
|||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Vale", 2, 2, 2, 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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 4, 4, 4));
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -244,14 +242,12 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
|||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Riverglide Pathway", 2, 2, 2, 2));
|
||||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Riverglide Pathway", 4, 4, 4));
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -275,14 +271,12 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
|||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Lavaglide Pathway", 2, 2, 2, 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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Riverglide Pathway", 4, 4, 4));
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -335,14 +329,12 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
|||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 3, 3, 3, 3));
|
||||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 5, 5, 5));
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -403,25 +395,25 @@ 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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 3, 3, 3, 3));
|
||||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 5, 5, 5));
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Tangled Florahedron");
|
||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCPermanent(info, player, game, "Tangled Florahedron", 7, 7, 7, 7));
|
||||
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
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));
|
||||
(String info, Player player, Game game) -> checkZCCMDFCCardInHand(info, player, game, "Tangled Florahedron", 9, 9, 9));
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -458,20 +450,19 @@ public class ReturnToHandEffectsTest extends CardTestPlayerBase {
|
|||
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));
|
||||
runCode("4: check hand zcc", 1, PhaseStep.BEGIN_COMBAT, playerA,
|
||||
(String info, Player player, Game game) -> checkZCCNormalCardInHand(info, player, game, "Carrion Feeder", 7));
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
// 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);
|
||||
assertGraveyardCount(playerA, "Makeshift Mannequin", 1);
|
||||
assertGraveyardCount(playerA, "Carrion Feeder", 1);
|
||||
assertGraveyardCount(playerA, "Carrion Feeder", 0);
|
||||
assertPermanentCount(playerA, "Carrion Feeder", 0);
|
||||
assertHandCount(playerA, "Carrion Feeder", 0);
|
||||
assertHandCount(playerA, "Carrion Feeder", 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousEffectsList;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.DoubleFacedCard;
|
||||
import mage.cards.DoubleFacedCardHalf;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.cards.decks.DeckCardLists;
|
||||
import mage.cards.decks.importer.DeckImporter;
|
||||
|
|
@ -773,6 +775,12 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
if (gameZone == Zone.BATTLEFIELD) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
Card newCard = cardInfo.createCard();
|
||||
if (newCard instanceof DoubleFacedCard) {
|
||||
DoubleFacedCardHalf rightHalf = ((DoubleFacedCard) newCard).getRightHalfCard();
|
||||
if (rightHalf.getName().equals(cardName) && rightHalf.isPermanent()) {
|
||||
newCard = rightHalf;
|
||||
}
|
||||
}
|
||||
getBattlefieldCards(player).add(new PutToBattlefieldInfo(
|
||||
newCard,
|
||||
tapped
|
||||
|
|
@ -781,7 +789,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
// TODO: is it bugged with double faced cards (wrong ref)?
|
||||
// add to all players
|
||||
String aliasId = player.generateAliasName(aliasName, useAliasMultiNames, i + 1);
|
||||
currentGame.getPlayers().values().forEach(pl -> ((TestPlayer) pl).addAlias(aliasId, newCard.getId()));
|
||||
Card finalNewCard = newCard;
|
||||
currentGame.getPlayers().values().forEach(pl -> ((TestPlayer) pl).addAlias(aliasId, finalNewCard.getId()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public class CardUtilTest extends CardTestPlayerBase {
|
|||
// MDFC where both sides should be playable
|
||||
private static final String birgi = "Birgi, God of Storytelling"; // {2}{R}, frontside of Harnfel
|
||||
private static final String harnfel = "Harnfel, Horn of Bounty"; // {4}{R}, backside of Birgi
|
||||
|
||||
private static final String tamiyo = "Tamiyo, Inquisitive Student"; // {U}, TDFC
|
||||
/**
|
||||
* Test that it will for trigger for discarding a MDFC but will only let you cast the nonland side.
|
||||
*/
|
||||
|
|
@ -122,4 +122,29 @@ public class CardUtilTest extends CardTestPlayerBase {
|
|||
Assert.assertEquals("12345", CardUtil.substring(str, 8, ending));
|
||||
Assert.assertEquals("12345", CardUtil.substring(str, 9, ending));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that it will for trigger for discarding a TDFC but will only let you cast the front side.
|
||||
*/
|
||||
@Test
|
||||
public void cantPlayTDFCBackSide() {
|
||||
addCard(Zone.HAND, playerA, changeOfFortune);
|
||||
addCard(Zone.HAND, playerA, tamiyo);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, oskar);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||
|
||||
skipInitShuffling();
|
||||
setStrictChooseMode(true);
|
||||
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}", 4);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, changeOfFortune);
|
||||
setChoice(playerA, "Yes");
|
||||
// only option is to cast front side, so auto chosen
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertPermanentCount(playerA, tamiyo, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue