Pulled from trunk.

This commit is contained in:
BursegSardaukar 2015-11-01 16:43:47 -05:00
parent 3792ed38e3
commit 82a388175c
946 changed files with 28830 additions and 8311 deletions

View file

@ -73,15 +73,20 @@ public class PreventRepeatedActionsTest extends CardTestPlayerBaseAI {
*/
@Test
public void testBasaltMonolith() {
addCard(Zone.HAND, playerA, "Phyrexian Vault", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
// Basalt Monolith doesn't untap during your untap step.
// {T}: Add {3} to your mana pool.
// {3}: Untap Basalt Monolith.
addCard(Zone.BATTLEFIELD, playerA, "Basalt Monolith", 1);
addCard(Zone.BATTLEFIELD, playerA, "Basalt Monolith", 1, true);
setStopAt(1, PhaseStep.END_TURN);
setStopAt(5, PhaseStep.END_TURN);
execute();
assertTapped("Basalt Monolith", false);
// {2}, {T}, Sacrifice a creature: Draw a card.
assertPermanentCount(playerA, "Phyrexian Vault", 1);
assertTapped("Basalt Monolith", true);
assertTappedCount("Plains", false, 3);
}
/**

View file

@ -0,0 +1,118 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.activated;
import mage.abilities.common.LicidAbility;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.keyword.HasteAbility;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author emerald0000
*/
public class LicidAbilityTest extends CardTestPlayerBase {
/**
* Activate on another creature
*/
@Test
public void BasicUsageTest() {
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox");
// {R}, {T}: Enraging Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {R} to end this effect.
// Enchanted creature has haste.
addCard(Zone.BATTLEFIELD, playerA, "Enraging Licid");
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
activateAbility(1, PhaseStep.UPKEEP, playerA, "{R},", "Pillarfield Ox");
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
assertAbility(playerA, "Pillarfield Ox", HasteAbility.getInstance(), true);
assertAbility(playerA, "Enraging Licid", new LicidAbility(new ColoredManaCost(ColoredManaSymbol.R), new ColoredManaCost(ColoredManaSymbol.R)), false);
assertType("Enraging Licid", CardType.ENCHANTMENT, true);
assertType("Enraging Licid", CardType.CREATURE, false);
}
/**
* Use special action to remove the continuous effect
*/
@Test
@Ignore("Test player can't activate special actions yet")
public void SpecialActionTest() {
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox");
// {R}, {T}: Enraging Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {R} to end this effect.
// Enchanted creature has haste.
addCard(Zone.BATTLEFIELD, playerA, "Enraging Licid");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
activateAbility(1, PhaseStep.UPKEEP, playerA, "{R},", "Pillarfield Ox");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: End");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertActionCount(playerA, 0);
assertAbility(playerA, "Pillarfield Ox", HasteAbility.getInstance(), false);
assertAbility(playerA, "Enraging Licid", new LicidAbility(new ColoredManaCost(ColoredManaSymbol.R), new ColoredManaCost(ColoredManaSymbol.R)), true);
assertType("Enraging Licid", CardType.ENCHANTMENT, false);
assertType("Enraging Licid", CardType.CREATURE, true);
}
/**
* Licid should die if enchanted creature dies
*/
@Test
@Ignore("Enraging Licid doesn't die when its enchanted creature dies due to similarity to Bestow")
public void EnchantedCreatureDiesTest() {
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox");
// {R}, {T}: Enraging Licid loses this ability and becomes an Aura enchantment with enchant creature. Attach it to target creature. You may pay {R} to end this effect.
// Enchanted creature has haste.
addCard(Zone.BATTLEFIELD, playerA, "Enraging Licid");
// Destroy target nonblack creature.
addCard(Zone.HAND, playerB, "Doom Blade");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
activateAbility(1, PhaseStep.UPKEEP, playerA, "{R},", "Pillarfield Ox");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Doom Blade", "Pillarfield Ox");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, 2); // Pillarfield Ox + Enraging Licid
}
}

View file

@ -9,23 +9,19 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*
* @author LevelX2
*/
public class MasterBiomancerTest extends CardTestPlayerBase {
/* Master Biomancer {2}{G}{U}
* Creature - Elf Wizard
* 2/4
* Each other creature you control enters the battlefield with a number of additional +1/+1 counters
* Each other creature you control enters the battlefield with a number of additional +1/+1 counters
* on it equal to Master Biomancer's power and as a Mutant in addition to its other types.
*
*/
@Test
public void testCreatureGetsCounters() {
// a creature enters the battlefield and gets a counter for each point of power of Master Biomancer
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
addCard(Zone.BATTLEFIELD, playerA, "Master Biomancer", 1);
addCard(Zone.HAND, playerA, "Mindeye Drake");
@ -52,12 +48,12 @@ public class MasterBiomancerTest extends CardTestPlayerBase {
// a creature enters the battlefield and gets a counter for each point of power of Master Biomancer
// doubled by Corpsejack Menace (when he ist cast, his own ability will not apply)
// http://blogs.magicjudges.org/rulestips/2013/03/corpsejack-menace-and-master-biomancer/
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Master Biomancer", 1);
// If one or more +1/+1 counters would be placed on a creature you control, twice that many +1/+1 counters are placed on it instead.
addCard(Zone.HAND, playerA, "Corpsejack Menace");
addCard(Zone.HAND, playerA, "Mindeye Drake");
@ -83,30 +79,28 @@ public class MasterBiomancerTest extends CardTestPlayerBase {
assertPowerToughness(playerA, "Mindeye Drake", 6, 9);
}
/**
* Progenitor Mimic
* Creature - Shapeshifter
* 0/0
* You may have Progenitor Mimic enter the battlefield as a copy of any creature on
* the battlefield except it gains "At the beginning of your upkeep, if this creature
* isn't a token, put a token onto the battlefield that's a copy of this creature."
* Progenitor Mimic Creature - Shapeshifter 0/0 You may have Progenitor
* Mimic enter the battlefield as a copy of any creature on the battlefield
* except it gains "At the beginning of your upkeep, if this creature isn't
* a token, put a token onto the battlefield that's a copy of this
* creature."
*
* If Progenitor Mimic comes into play, it gets two +1/+1 counters from
* the Master Biomancer already in play. It copies the Master Biomancer and
* is therfore a 4/6 creature.
* The Token generated next round from Progenitor Mimic has to get 2 + 4 counters
* and is therefore a 8/10 creature.
* If Progenitor Mimic comes into play, it gets two +1/+1 counters from the
* Master Biomancer already in play. It copies the Master Biomancer and is
* therfore a 4/6 creature. The Token generated next round from Progenitor
* Mimic has to get 2 + 4 counters and is therefore a 8/10 creature.
*/
@Test
public void testWithProgenitorMimic() {
// a creature enters the battlefield and gets a counter for each point of power of Master Biomancer
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
addCard(Zone.BATTLEFIELD, playerA, "Master Biomancer", 1);
// You may have Progenitor Mimic enter the battlefield as a copy of any creature on the battlefield
// except it gains "At the beginning of your upkeep, if this creature isn't a token,
// put a token onto the battlefield that's a copy of this creature."
addCard(Zone.HAND, playerA, "Progenitor Mimic");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Progenitor Mimic");

View file

@ -16,7 +16,10 @@ public class ProteanHydraTest extends CardTestPlayerBase {
@Test
public void testEnteringWithCounters() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
addCard(Zone.HAND, playerA, "Protean Hydra");
// Protean Hydra enters the battlefield with X +1/+1 counters on it.
// If damage would be dealt to Protean Hydra, prevent that damage and remove that many +1/+1 counters from it.
// Whenever a +1/+1 counter is removed from Protean Hydra, put two +1/+1 counters on it at the beginning of the next end step.
addCard(Zone.HAND, playerA, "Protean Hydra"); // CREATURE - {X}{G}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Protean Hydra");

View file

@ -0,0 +1,59 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.enters;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class SearchEntersBattlefieldTest extends CardTestPlayerBase {
@Test
public void testLandAfterFetchUntapped() {
addCard(Zone.HAND, playerA, "Verdant Catacombs");
addCard(Zone.LIBRARY, playerA, "Forest");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Verdant Catacombs");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Pay");
setChoice(playerA, "Forest");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, "Verdant Catacombs", 1);
assertPermanentCount(playerA, "Forest", 1);
assertTapped("Forest", false);
}
}

View file

@ -26,13 +26,10 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.enters;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -40,17 +37,15 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*
* @author LevelX2
*/
public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase {
/**
* Valakut, the Molten Pinnacle
* Land
* Valakut, the Molten Pinnacle enters the battlefield tapped.
* Whenever a Mountain enters the battlefield under your control, if you control at least five other Mountains, you may have Valakut, the Molten Pinnacle deal 3 damage to target creature or player.
* {T}: Add {R} to your mana pool.
* Valakut, the Molten Pinnacle Land Valakut, the Molten Pinnacle enters the
* battlefield tapped. Whenever a Mountain enters the battlefield under your
* control, if you control at least five other Mountains, you may have
* Valakut, the Molten Pinnacle deal 3 damage to target creature or player.
* {T}: Add {R} to your mana pool.
*/
@Test
public void onlyFourMountainsNoDamage() {
@ -85,13 +80,11 @@ public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 17);
}
// Scapeshift {2}{G}{G}
// Sorcery
// Sacrifice any number of lands. Search your library for that many land cards, put them onto the battlefield tapped, then shuffle your library.
// Scapeshift {2}{G}{G}
// Sorcery
// Sacrifice any number of lands. Search your library for that many land cards, put them onto the battlefield tapped, then shuffle your library.
@Test
public void sixEnterWithScapeshiftDamageToPlayerB() {
@ -113,7 +106,6 @@ public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 2); // 6 * 3 damage = 18
}
@Test
@ -166,4 +158,36 @@ public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase {
assertLife(playerB, 2); // 6 * 3 damage = 18
}
/**
* Some lands aren't triggering Valakut, the Molten Pinnacle with Prismatic
* Omen and 6+ lands in play. So far I've noticed that Misty Rainforest and
* basic Island did not trigger Valakut, but an additional copy of Valakut
* did.
*/
@Test
public void withPrismaticOmen() {
// Valakut, the Molten Pinnacle enters the battlefield tapped.
// Whenever a Mountain enters the battlefield under your control, if you control at least five other Mountains,
// you may have Valakut, the Molten Pinnacle deal 3 damage to target creature or player.
// {T}: Add {R} to your mana pool.
addCard(Zone.BATTLEFIELD, playerA, "Valakut, the Molten Pinnacle");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
addCard(Zone.HAND, playerA, "Forest", 1);
// Lands you control are every basic land type in addition to their other types.
addCard(Zone.BATTLEFIELD, playerA, "Prismatic Omen");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest");
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertLife(playerA, 20);
assertLife(playerB, 17);
}
}

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
@ -40,31 +39,31 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
public class ConspireTest extends CardTestPlayerBase {
/**
* 702.77. Conspire
* 702.77a Conspire is a keyword that represents two abilities. The first is a static ability that functions
* while the spell with conspire is on the stack. The second is a triggered ability that functions
* while the spell with conspire is on the stack. Conspire means As an additional cost to cast
* this spell, you may tap two untapped creatures you control that each share a color with it and
* When you cast this spell, if its conspire cost was paid, copy it. If the spell has any targets, you
* may choose new targets for the copy. Paying a spells conspire cost follows the rules for
* paying additional costs in rules 601.2b and 601.2eg.
*
* 702.77b If a spell has multiple instances of conspire, each is paid separately and triggers based on
* its own payment, not any other instance of conspire
*
*/
/**
* Burn Trail
* Sorcery, 3R (4)
* Burn Trail deals 3 damage to target creature or player.
*
* Conspire (As you cast this spell, you may tap two untapped creatures you
* control that share a color with it. When you do, copy it and you may
* choose a new target for the copy.)
* 702.77. Conspire 702.77a Conspire is a keyword that represents two
* abilities. The first is a static ability that functions while the spell
* with conspire is on the stack. The second is a triggered ability that
* functions while the spell with conspire is on the stack. Conspire means
* As an additional cost to cast this spell, you may tap two untapped
* creatures you control that each share a color with it and When you cast
* this spell, if its conspire cost was paid, copy it. If the spell has any
* targets, you may choose new targets for the copy. Paying a spells
* conspire cost follows the rules for paying additional costs in rules
* 601.2b and 601.2eg.
*
* 702.77b If a spell has multiple instances of conspire, each is paid
* separately and triggers based on its own payment, not any other instance
* of conspire
*
*/
/**
* Burn Trail Sorcery, 3R (4) Burn Trail deals 3 damage to target creature
* or player.
*
* Conspire (As you cast this spell, you may tap two untapped creatures you
* control that share a color with it. When you do, copy it and you may
* choose a new target for the copy.)
*
*/
@Test
public void testConspire() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
@ -72,7 +71,6 @@ public class ConspireTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
addCard(Zone.HAND, playerA, "Burn Trail");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Burn Trail", playerB);
setChoice(playerA, "Yes");
@ -93,7 +91,6 @@ public class ConspireTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
addCard(Zone.HAND, playerA, "Burn Trail");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Burn Trail", playerB);
setChoice(playerA, "No");
@ -107,4 +104,50 @@ public class ConspireTest extends CardTestPlayerBase {
}
@Test
public void testWortTheRaidmother() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 7);
// When Wort, the Raidmother enters the battlefield, put two 1/1 red and green Goblin Warrior creature tokens onto the battlefield.
// Each red or green instant or sorcery spell you cast has conspire.
// (As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.)
addCard(Zone.HAND, playerA, "Wort, the Raidmother");
addCard(Zone.HAND, playerA, "Lightning Bolt");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wort, the Raidmother");// {4}{R/G}{R/G}
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
setChoice(playerA, "Yes");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Wort, the Raidmother", 1);
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertLife(playerB, 14);
}
@Test
public void testWortTheRaidmotherWithConspireSpell() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 10);
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin", 2);
// When Wort, the Raidmother enters the battlefield, put two 1/1 red and green Goblin Warrior creature tokens onto the battlefield.
// Each red or green instant or sorcery spell you cast has conspire.
// (As you cast the spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.)
addCard(Zone.HAND, playerA, "Wort, the Raidmother");
addCard(Zone.HAND, playerA, "Burn Trail");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wort, the Raidmother"); // {4}{R/G}{R/G}
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Burn Trail", playerB);
setChoice(playerA, "Yes"); // use Conspire from Burn Trail itself
setChoice(playerA, "Yes"); // use Conspire gained from Wort, the Raidmother
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Wort, the Raidmother", 1);
assertLife(playerB, 11);
assertLife(playerA, 20);
assertGraveyardCount(playerA, "Burn Trail", 1);
}
}

View file

@ -96,7 +96,7 @@ public class CyclingTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, "Decree of Pain");
// Protection from black
// Cycling {2} ({2}, Discard this card: Draw a card.)
addCard(Zone.BATTLEFIELD, playerB, "Disciple Of Grace");
addCard(Zone.BATTLEFIELD, playerB, "Disciple of Grace");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling {3}{B}{B}");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Cycling {2}");
@ -108,7 +108,7 @@ public class CyclingTest extends CardTestPlayerBase {
assertHandCount(playerB, 0);
assertGraveyardCount(playerA, "Decree of Pain", 1);
assertPermanentCount(playerB, "Disciple Of Grace", 1);
assertPermanentCount(playerB, "Disciple of Grace", 1);
}

View file

@ -49,76 +49,103 @@ public class FlashbackTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
addCard(Zone.HAND, playerA, "Snapcaster Mage", 1);
// Destroy all artifacts and enchantments. You gain 2 life for each permanent destroyed this way.
addCard(Zone.GRAVEYARD, playerA, "Fracturing Gust");
addCard(Zone.BATTLEFIELD, playerA, "Berserkers' Onslaught", 1);
addCard(Zone.BATTLEFIELD, playerB, "Darksteel Citadel", 1);
// When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Fracturing Gust");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback {2}{G/W}{G/W}{G/W}"); // now snapcaster mage is died so -13/-13
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Snapcaster Mage", 1);
assertGraveyardCount(playerA, "Berserkers' Onslaught", 1);
assertPermanentCount(playerB, "Darksteel Citadel", 1);
assertExileCount("Fracturing Gust", 1);
}
/**
* My opponent put Iona on the battlefield using Unburial Rites, but my game
* log didn't show me the color he has chosen.
*
*
*/
@Test
public void testUnburialRites() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 8);
// Return target creature card from your graveyard to the battlefield.
// Flashback {3}{W}
// Flashback {3}{W}
addCard(Zone.HAND, playerA, "Unburial Rites", 1); // Sorcery - {4}{B}
// Flying
// As Iona, Shield of Emeria enters the battlefield, choose a color.
// Your opponents can't cast spells of the chosen color.
addCard(Zone.GRAVEYARD, playerA, "Iona, Shield of Emeria");
// As Lurebound Scarecrow enters the battlefield, choose a color.
// When you control no permanents of the chosen color, sacrifice Lurebound Scarecrow.
// When you control no permanents of the chosen color, sacrifice Lurebound Scarecrow.
addCard(Zone.GRAVEYARD, playerA, "Lurebound Scarecrow"); // Enchantment - {2}{U}
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Unburial Rites", "Iona, Shield of Emeria");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Unburial Rites", "Iona, Shield of Emeria");
setChoice(playerA, "Red");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback {3}{W}");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback {3}{W}");
addTarget(playerA, "Lurebound Scarecrow");
setChoice(playerA, "White");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Iona, Shield of Emeria", 1);
assertPermanentCount(playerA, "Lurebound Scarecrow", 1);
assertHandCount(playerB, "Lightning Bolt", 1);
assertExileCount("Unburial Rites", 1);
}
/**
*
*/
@Test
public void testFlashbackWithConverge() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.HAND, playerA, "Snapcaster Mage", 1);
// Converge - Put a 1/1 white Kor Ally creature token onto the battlefield for each color of mana spent to cast Unified Front.
addCard(Zone.GRAVEYARD, playerA, "Unified Front"); // {3}{W}
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}");
// When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Unified Front");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback {3}{W}");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Snapcaster Mage", 1);
assertPermanentCount(playerA, "Kor Ally", 4);
assertExileCount("Unified Front", 1);
}
}

View file

@ -400,4 +400,56 @@ public class ManifestTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "", 2);
}
/**
* I sacrificed a manifested face-down Smothering Abomination to Nantuko
* Husk and it made me draw a card.
*
*/
@Test
public void testDiesTriggeredAbilitiesOfManifestedCreatures() {
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
// Sacrifice a creature: Nantuko Husk gets +2/+2 until end of turn.
addCard(Zone.BATTLEFIELD, playerB, "Nantuko Husk", 1);
// {1}{B}, {T}, Sacrifice another creature: Manifest the top card of your library.
addCard(Zone.BATTLEFIELD, playerB, "Qarsi High Priest", 1);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
// Devoid
// Flying
// At the beginning of your upkeep, sacrifice a creature
// Whenever you sacrifice a creature, draw a card.
addCard(Zone.LIBRARY, playerB, "Mountain", 1);
addCard(Zone.LIBRARY, playerB, "Smothering Abomination", 1);
addCard(Zone.LIBRARY, playerB, "Mountain", 1);
skipInitShuffling();
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{B},{T}, Sacrifice another creature");
setChoice(playerB, "Silvercoat Lion");
activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Sacrifice a creature");
setChoice(playerB, "");
setStopAt(2, PhaseStep.END_TURN);
execute();
// no life gain
assertLife(playerA, 20);
assertLife(playerB, 20);
assertPermanentCount(playerB, "Qarsi High Priest", 1);
assertPermanentCount(playerB, "Nantuko Husk", 1);
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
assertGraveyardCount(playerB, "Smothering Abomination", 1);
assertPowerToughness(playerB, "Nantuko Husk", 4, 4);
assertHandCount(playerB, "Mountain", 1);
}
}

View file

@ -195,8 +195,7 @@ public class PersistTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "Glen Elendra Archmage", 1);
assertPowerToughness(playerB, "Glen Elendra Archmage", 1, 1);
assertPermanentCount(playerA, "Glen Elendra Archmage", 1);
assertPowerToughness(playerA, "Glen Elendra Archmage", 1, 1);
assertGraveyardCount(playerA, "Clever Impersonator", 1);
}
@Test

View file

@ -115,7 +115,7 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
// You may exile a green card with converted mana cost X from your hand rather than pay Nourishing Shoal's mana cost.
// You gain X life.
addCard(Zone.HAND, playerA, "Nourishing Shoal", 1);
addCard(Zone.HAND, playerA, "Nourishing Shoal", 1); // {X}{G}{G}
addCard(Zone.HAND, playerA, "Giant Growth", 1);
// You may put a creature card from your hand onto the battlefield. That creature gains haste. Sacrifice that creature at the beginning of the next end step.
// Splice onto Arcane {2}{R}{R} (As you cast an Arcane spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell.)

View file

@ -49,6 +49,8 @@ public class SuspendTest extends CardTestPlayerBase {
public void testEpochrasite() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// Epochrasite enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand.
// When Epochrasite dies, exile it with three time counters on it and it gains suspend.
addCard(Zone.HAND, playerA, "Epochrasite", 1);
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
@ -145,4 +147,20 @@ public class SuspendTest extends CardTestPlayerBase {
assertCounterOnExiledCardCount("Deep-Sea Kraken", CounterType.TIME, 8); // -1 from spell of player B
}
@Test
public void testAncestralVisionCantBeCastDirectly() {
// Suspend 4-{U}
// Target player draws three cards.
addCard(Zone.HAND, playerA, "Ancestral Vision", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ancestral Vision", playerA);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertHandCount(playerA, 1);
assertHandCount(playerA, "Ancestral Vision", 1);
}
}

View file

@ -44,23 +44,35 @@ public class TransformTest extends CardTestPlayerBase {
addCard(Zone.LIBRARY, playerA, "Forest");
addCard(Zone.BATTLEFIELD, playerA, "Forest", 6);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
// 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.
addCard(Zone.HAND, playerA, "Nissa, Vastwood Seer");
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");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{G}{G}", "Swamp");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "+1: Reveal");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Forest", 7);
assertGraveyardCount(playerB, "Rootrunner", 1);
assertPermanentCount(playerA, "Nissa, Vastwood Seer", 0);
assertPermanentCount(playerA, "Nissa, Sage Animist", 1);
assertCounterCount("Nissa, Sage Animist", CounterType.LOYALTY, 3);
assertCounterCount("Nissa, Sage Animist", CounterType.LOYALTY, 4);
assertPermanentCount(playerA, "Forest", 6);
assertPermanentCount(playerA, "Swamp", 1);
}
@Test

View file

@ -2,6 +2,7 @@ package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -238,7 +239,8 @@ public class UndyingTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Tatterkite", 1);
assertPermanentCount(playerA, "Mikaeus, the Unhallowed", 1);
assertPowerToughness(playerA, "Tatterkite", 3, 2);
assertCounterCount("Tatterkite", CounterType.P1P1, 1);
assertPowerToughness(playerA, "Tatterkite", 4, 3);
}

View file

@ -36,7 +36,6 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*
* @author LevelX2
*/
public class MovingCounterTest extends CardTestPlayerBase {
/**
@ -51,12 +50,11 @@ public class MovingCounterTest extends CardTestPlayerBase {
// Move any number of +1/+1 counters from target creature onto another target creature with the same controller.
addCard(Zone.HAND, playerA, "Bioshift", 1);
// Protean Hydra enters the battlefield with X +1/+1 counters on it.
// If damage would be dealt to Protean Hydra, prevent that damage and remove that many +1/+1 counters from it.
// Whenever a +1/+1 counter is removed from Protean Hydra, put two +1/+1 counters on it at the beginning of the next end step.
addCard(Zone.HAND, playerA, "Protean Hydra", 1);
// Protean Hydra enters the battlefield with X +1/+1 counters on it.
// If damage would be dealt to Protean Hydra, prevent that damage and remove that many +1/+1 counters from it.
// Whenever a +1/+1 counter is removed from Protean Hydra, put two +1/+1 counters on it at the beginning of the next end step.
addCard(Zone.HAND, playerA, "Protean Hydra", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Protean Hydra");
setChoice(playerA, "X=4");
@ -67,14 +65,45 @@ public class MovingCounterTest extends CardTestPlayerBase {
execute();
assertGraveyardCount(playerA, "Bioshift", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPowerToughness(playerA, "Silvercoat Lion", 4, 4); // added 2 counters
assertPermanentCount(playerA, "Protean Hydra", 1);
assertPermanentCount(playerA, "Protean Hydra", 1);
assertPowerToughness(playerA, "Protean Hydra", 6, 6); // started with 4, removed 2, added 4 at end = 6
}
}
/**
* I'm having an issue when using Bioshift to move only a portion of
* counters to another creature. When I attempt to do this, it moves all of
* the counters (and in some cases with my Simic deck) kills the creature.
*/
@Test
public void testFateTransfer() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
// Noxious Hatchling enters the battlefield with four -1/-1 counters on it.
// Wither (This deals damage to creatures in the form of -1/-1 counters.)
// Whenever you cast a black spell, remove a -1/-1 counter from Noxious Hatchling.
// Whenever you cast a green spell, remove a -1/-1 counter from Noxious Hatchling.
addCard(Zone.HAND, playerA, "Noxious Hatchling", 1);// 6/6
addCard(Zone.BATTLEFIELD, playerA, "Ruin Processor", 1); // Creature 7/8
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
// Move all counters from target creature onto another target creature.
addCard(Zone.HAND, playerB, "Fate Transfer", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Noxious Hatchling");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, "Fate Transfer", "Noxious Hatchling^Ruin Processor");
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertGraveyardCount(playerB, "Fate Transfer", 1);
assertPowerToughness(playerA, "Noxious Hatchling", 6, 6);
assertPowerToughness(playerA, "Ruin Processor", 3, 4);
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.oneshot.exile;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class OblivionSowerTest extends CardTestPlayerBase {
/**
* When putting lands into play from an opponent's exile zone using Oblivion
* Sower, the BFZ dual lands behave exactly the opposite way of how they
* should: if you control less than two basics, they enter the battlefield
* untapped, and if you control more, they enter tapped.
*/
@Test
public void testPlayLandsFromExile() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
// When you cast Oblivion Sower, target opponent exiles the top four cards of his or her library, then you may put any number of land cards that player owns from exile onto the battlefield under your control.
addCard(Zone.HAND, playerA, "Oblivion Sower"); // Creature - 5/8
// Canopy Vista enters the battlefield tapped unless you control two or more basic lands.
addCard(Zone.LIBRARY, playerB, "Canopy Vista", 3);
addCard(Zone.LIBRARY, playerB, "Silvercoat Lion", 1);
skipInitShuffling();
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oblivion Sower");
addTarget(playerA, "Canopy Vista^Canopy Vista^Canopy Vista");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertHandCount(playerA, "Oblivion Sower", 0);
assertPermanentCount(playerA, "Oblivion Sower", 1);
assertExileCount("Silvercoat Lion", 1);
assertPermanentCount(playerA, "Canopy Vista", 3);
assertTappedCount("Canopy Vista", false, 3);
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.oneshot.sacrifice;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class TradingPostTest extends CardTestPlayerBase {
/**
* Trading Post doesn't let me sacrifice a creature owned by my opponent,
* but controlled by me. I get an error message saying You cannot sacrifice
* this creature.
*/
@Test
public void testSacrifice() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
// {1}, {T}, Discard a card: You gain 4 life.
// {1}, {T}, Pay 1 life: Put a 0/1 white Goat creature token onto the battlefield.
// {1}, {T}, Sacrifice a creature: Return target artifact card from your graveyard to your hand.
// {1}, {T}, Sacrifice an artifact: Draw a card.
addCard(Zone.BATTLEFIELD, playerA, "Trading Post", 1);
// Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. (It can attack and this turn.)
addCard(Zone.HAND, playerA, "Act of Treason"); // Sorcery {2}{R}
addCard(Zone.GRAVEYARD, playerA, "Helm of Possession");
addCard(Zone.BATTLEFIELD, playerB, "Savannah Lions");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Act of Treason", "Savannah Lions");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1},{T}, Sacrifice a creature", "Helm of Possession", "Act of Treason", StackClause.WHILE_NOT_ON_STACK);
setChoice(playerA, "Savannah Lions");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Act of Treason", 1);
assertPermanentCount(playerB, "Savannah Lions", 0);
assertGraveyardCount(playerB, "Savannah Lions", 1);
assertTapped("Trading Post", true);
assertHandCount(playerA, 1);
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.other;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class DevastationTideTest extends CardTestPlayerBase {
@Test
public void testReturnNonLandPermanents() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
addCard(Zone.HAND, playerA, "Devastation Tide"); // {3}{U}{U}
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // Creature
addCard(Zone.BATTLEFIELD, playerA, "Vampiric Rites"); // Enchantment
addCard(Zone.BATTLEFIELD, playerA, "Hedron Archive"); // Artifact
addCard(Zone.BATTLEFIELD, playerA, "Karn Liberated"); // Planeswalker
addCard(Zone.BATTLEFIELD, playerA, "Nimbus Maze", 1); // Land
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // Creature
addCard(Zone.BATTLEFIELD, playerB, "Vampiric Rites"); // Enchantment
addCard(Zone.BATTLEFIELD, playerB, "Hedron Archive"); // Artifact
addCard(Zone.BATTLEFIELD, playerB, "Karn Liberated"); // Planeswalker
addCard(Zone.BATTLEFIELD, playerB, "Nimbus Maze", 1); // Land
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Devastation Tide");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertHandCount(playerA, "Silvercoat Lion", 1);
assertHandCount(playerA, "Vampiric Rites", 1);
assertHandCount(playerA, "Hedron Archive", 1);
assertHandCount(playerA, "Karn Liberated", 1);
assertHandCount(playerA, "Nimbus Maze", 0);
assertHandCount(playerB, "Silvercoat Lion", 1);
assertHandCount(playerB, "Vampiric Rites", 1);
assertHandCount(playerB, "Hedron Archive", 1);
assertHandCount(playerB, "Karn Liberated", 1);
assertHandCount(playerB, "Nimbus Maze", 0);
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.abilities.other;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class ImpelledGiantTest extends CardTestPlayerBase {
@Test
public void testGainsPower() {
addCard(Zone.BATTLEFIELD, playerA, "Impelled Giant");
addCard(Zone.BATTLEFIELD, playerA, "Hurloon Minotaur");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tap an untapped red creature you control other than Impelled Giant");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertTapped("Hurloon Minotaur", true);
assertPowerToughness(playerA, "Impelled Giant", 5, 3);
}
}

View file

@ -51,8 +51,10 @@ public class MycosynthGolemTest extends CardTestPlayerBase {
public void testSpellsAffinity() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
// Affinity for artifacts
// Artifact creature spells you cast have affinity for artifacts.
addCard(Zone.BATTLEFIELD, playerA, "Mycosynth Golem");
addCard(Zone.HAND, playerA, "Alpha Myr");
addCard(Zone.HAND, playerA, "Alpha Myr"); // Creature - Myr 2/1
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Alpha Myr");

View file

@ -66,6 +66,9 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
@Test
public void testSpellsReturnToHand() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
// Lifelink
// Instant and sorcery spells you control have lifelink.
// {2}{U/R}{U/R}: The next time you cast an instant or sorcery spell from your hand this turn, put that card into your hand instead of your graveyard as it resolves.
addCard(Zone.BATTLEFIELD, playerA, "Soulfire Grand Master");
addCard(Zone.HAND, playerA, "Lightning Bolt");
@ -199,7 +202,6 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
* Test that if Soulfire Grand Master has left the battlefield spell has no
* longer lifelink
*/
@Test
public void testSoulfireLeft() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
@ -231,7 +233,6 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
* the elemental, so stoke didnt resolve, but i still got the life from
* lifelink.
*/
@Test
public void testSoulfireStokeTheFlames() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8);
@ -296,7 +297,6 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
* Constructed.
*
*/
@Test
public void testWithDeflectingPalm() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);

View file

@ -0,0 +1,39 @@
package org.mage.test.cards.conditional;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author tobz
*/
public class RazorvergeThicketTest extends CardTestPlayerBase {
@Test
public void testEntersTappedForThreeLands() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.HAND, playerA, "Razorverge Thicket");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Razorverge Thicket");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertTapped("Razorverge Thicket", true);
}
@Test
public void testEntersUntappedForTwoLands() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.HAND, playerA, "Razorverge Thicket");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Razorverge Thicket");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertTapped("Razorverge Thicket", false);
}
}

View file

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.mage.test.cards.conditional;
import mage.constants.PhaseStep;
@ -14,10 +10,10 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
* @author jeff
*/
public class RootwaterMatriarchTest extends CardTestPlayerBase {
@Test
public void testTargetFail() {
addCard(Zone.BATTLEFIELD, playerA, "Rootwater Matriarch");
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
@ -25,73 +21,73 @@ public class RootwaterMatriarchTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Rootwater Matriarch", 1);
assertPermanentCount(playerB, "Memnite", 1);
}
@Test
public void testTargetSuccess() {
// {T}: Gain control of target creature for as long as that creature is enchanted
addCard(Zone.BATTLEFIELD, playerA, "Rootwater Matriarch");
addCard(Zone.BATTLEFIELD, playerA, "Island");
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
addCard(Zone.HAND, playerA, "Flight");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flight", "Memnite");
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{T}: Gain control of target creature for as long as that creature is enchanted.", "Memnite");
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertPermanentCount(playerA, "Rootwater Matriarch", 1);
assertPermanentCount(playerA, "Memnite", 1);
}
@Test
public void testGainControlEnchantedTargetAndRWLeavesPlay() {
addCard(Zone.BATTLEFIELD, playerA, "Rootwater Matriarch");
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
addCard(Zone.HAND, playerA, "Unsummon");
addCard(Zone.HAND, playerA, "Flight");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flight", "Memnite");
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{T}: Gain control of target creature for as long as that creature is enchanted.", "Memnite");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Unsummon", "Rootwater Matriarch");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Rootwater Matriarch", 0);
assertPermanentCount(playerA, "Memnite", 1);
}
@Test
public void testGainControlEnchantedTargetAndAuraIsDisenchanted() {
addCard(Zone.BATTLEFIELD, playerA, "Rootwater Matriarch");
addCard(Zone.BATTLEFIELD, playerA, "Island");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
addCard(Zone.HAND, playerA, "Disenchant");
addCard(Zone.HAND, playerA, "Flight");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flight", "Memnite");
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{T}: Gain control of target creature for as long as that creature is enchanted.", "Memnite");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disenchant", "Flight");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Rootwater Matriarch", 1);
assertPermanentCount(playerB, "Memnite", 1);
}

View file

@ -7,11 +7,12 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* Tests the effect:
* - Exile target creature you control, then return that card to the battlefield under your control
* Tests the effect: - Exile target creature you control, then return that card
* to the battlefield under your control
*
* This effect grants you permanent control over the returned creature.
* So you mail steal opponent's creature with "Act of Treason" and then use this effect for permanent control effect.
* This effect grants you permanent control over the returned creature. So you
* mail steal opponent's creature with "Act of Treason" and then use this effect
* for permanent control effect.
*
* @author noxx
*/
@ -67,7 +68,7 @@ public class ExileAndReturnUnderYourControl extends CardTestPlayerBase {
Assert.assertTrue("player A should play with top card revealed", playerA.isTopCardRevealed());
Assert.assertFalse("player B should play NOT with top card revealed", playerB.isTopCardRevealed());
}
@Test
public void testVillainousWealthExilesBoost() {
// Villainous Wealth {X}{B}{G}{U}
@ -76,14 +77,14 @@ public class ExileAndReturnUnderYourControl extends CardTestPlayerBase {
// their mana costs.
addCard(Zone.HAND, playerA, "Villainous Wealth");
addCard(Zone.HAND, playerA, "Master of Pearls");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
// Secret Plans {G}{U}
// Face-down creatures you control get +0/+1.
// Whenever a permanent you control is turned face up, draw a card.
// Whenever a permanent you control is turned face up, draw a card.
addCard(Zone.LIBRARY, playerB, "Secret Plans");
skipInitShuffling(); // to keep this card on top of library
@ -101,9 +102,50 @@ public class ExileAndReturnUnderYourControl extends CardTestPlayerBase {
assertExileCount(playerB, 2);
assertExileCount("Secret Plans", 0);
assertPermanentCount(playerA, "Secret Plans", 1);
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 3);
}
assertPowerToughness(playerA, "", 2, 3);
}
/**
* My opponent cast Villainous Wealth and took control of my Sylvan Library.
* On his next turn, when Sylvan Library's trigger resolved, he kept the two
* extra cards without paying life.
*/
@Test
public void testVillainousWealthExilesSylvanLibrary() {
// Villainous Wealth {X}{B}{G}{U}
// Target opponent exiles the top X cards of his or her library. You may cast any number
// of nonland cards with converted mana cost X or less from among them without paying
// their mana costs.
addCard(Zone.HAND, playerA, "Villainous Wealth");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
// At the beginning of your draw step, you may draw two additional cards.
// If you do, choose two cards in your hand drawn this turn.
// For each of those cards, pay 4 life or put the card on top of your library.
addCard(Zone.LIBRARY, playerB, "Sylvan Library");
skipInitShuffling(); // to keep this card on top of library
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Villainous Wealth", playerB);
setChoice(playerA, "X=3");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sylvan Library");
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
execute();
assertGraveyardCount(playerA, "Villainous Wealth", 1);
assertExileCount(playerB, 2);
assertExileCount("Sylvan Library", 0);
assertPermanentCount(playerA, "Sylvan Library", 1);
assertHandCount(playerB, 1);
assertHandCount(playerA, 3);
assertLife(playerA, 12);
assertLife(playerB, 20);
}
}

View file

@ -27,7 +27,6 @@
*/
package org.mage.test.cards.control;
import mage.abilities.keyword.HasteAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
@ -37,15 +36,15 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*
* @author LevelX2
*/
public class ItThatBetraysTest extends CardTestPlayerBase {
/**
* https://github.com/magefree/mage/issues/796
*
* When an opponent sacrifices a fetchland and you have an It That Betrays in play,
* sacrificing the fetchland that comes under your control from its ability returns
* it to play under your control, allowing you to fetch infinite lands.
* When an opponent sacrifices a fetchland and you have an It That Betrays
* in play, sacrificing the fetchland that comes under your control from its
* ability returns it to play under your control, allowing you to fetch
* infinite lands.
*
*/
@Test
@ -62,7 +61,7 @@ public class ItThatBetraysTest extends CardTestPlayerBase {
assertLife(playerA, 19);
assertLife(playerB, 19);
// Going to graveyard if player B sacrifices it
assertGraveyardCount(playerA, "Flooded Strand", 1);
}
@ -71,7 +70,7 @@ public class ItThatBetraysTest extends CardTestPlayerBase {
@Test
public void testExileItThatBetraysEffect() {
addCard(Zone.BATTLEFIELD, playerA, "Flooded Strand", 1);
addCard(Zone.BATTLEFIELD, playerA, "Rest in Peace", 1);
addCard(Zone.BATTLEFIELD, playerB, "It That Betrays");
@ -83,7 +82,7 @@ public class ItThatBetraysTest extends CardTestPlayerBase {
assertLife(playerA, 19);
assertLife(playerB, 20);
// Player B now controls a Flooded Strand, even though it went to exile
assertPermanentCount(playerB, "Flooded Strand", 1);
}

View file

@ -0,0 +1,73 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.control;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class WillbreakerTest extends CardTestPlayerBase {
/**
* http://www.slightlymagic.net/forum/viewtopic.php?f=70&t=17664&start=120#p186736
*
* I tried to activate Retribution of the Ancients while I only controlled
* Nantuko Husk and Willbreaker without +1/+1 counters on them. The program
* didn't let me activate the RotA, even though the creature you choose
* doesn't need to have any counters on it (X can be 0, doesn't say
* otherwise on the card and it isn't a target requirement). It asked me to
* pay B, then choose a creature I controlled, which I did... and then
* nothing happened.
*
*/
@Test
public void testRetributionOfTheAncientsZeroCounter() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
// {B}, Remove X +1/+1 counters from among creatures you control: Target creature gets -X/-X until end of turn.
addCard(Zone.BATTLEFIELD, playerA, "Retribution of the Ancients", 1); // Enchantment {B}
// Whenever a creature an opponent controls becomes the target of a spell or ability you control, gain control of that creature for as long as you control Willbreaker.
addCard(Zone.BATTLEFIELD, playerA, "Willbreaker", 1);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B},Remove", "Silvercoat Lion");
setChoice(playerA, "X=0");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Willbreaker", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
}
}

View file

@ -29,6 +29,7 @@ package org.mage.test.cards.copy;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -72,4 +73,109 @@ public class CleverImpersonatorTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "Gilded Drake", 1);
assertPermanentCount(playerB, "Pillarfield Ox", 1);
}
/**
* Copy a planeswalker on the battlefield
*/
@Test
public void testCopyPlaneswalker() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
// You may have Clever Impersonator enter the battlefield as a copy of any nonland permanent on the battlefield.
addCard(Zone.HAND, playerA, "Clever Impersonator", 1); // {2}{U}{U}
// +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 dies, return it to the battlefield under your control at the beginning of the next end step.";
addCard(Zone.BATTLEFIELD, playerB, "Liliana, Defiant Necromancer", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clever Impersonator");
setChoice(playerA, "Liliana, Defiant Necromancer");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+2: Each player discards a card");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertHandCount(playerA, "Clever Impersonator", 0);
assertCounterCount(playerB, "Liliana, Defiant Necromancer", CounterType.LOYALTY, 3); // 3
assertPermanentCount(playerB, "Liliana, Defiant Necromancer", 1);
assertPermanentCount(playerA, "Liliana, Defiant Necromancer", 1);
assertCounterCount(playerA, "Liliana, Defiant Necromancer", CounterType.LOYALTY, 5); // 3 + 2
}
/**
* I had an Alesha, Who Smiles at Death returning a Clever Impersonator who
* was supposed to copy a flipped Liliana, Defiant Necromancer, but it
* entered the battlefield with 0 loyalty and died immediately. If I am not
* mistaken it should have entered with 3 loyalty (see Gatherer entry).
*/
@Test
public void testCopyPlaneswalkerFromGraveyard() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// First strike
// Whenever Alesha, Who Smiles at Death attacks, you may pay {W/B}{W/B}. If you do, return target creature card with power 2 or less from your graveyard to the battlefield tapped and attacking.
addCard(Zone.BATTLEFIELD, playerA, "Alesha, Who Smiles at Death", 1); // {2}{R} - 3/2
// You may have Clever Impersonator enter the battlefield as a copy of any nonland permanent on the battlefield.
addCard(Zone.GRAVEYARD, playerA, "Clever Impersonator", 1); // {2}{U}{U}
// +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 dies, return it to the battlefield under your control at the beginning of the next end step.";
addCard(Zone.BATTLEFIELD, playerB, "Liliana, Defiant Necromancer", 1);
attack(1, playerA, "Alesha, Who Smiles at Death");
addTarget(playerA, "Clever Impersonator");
setChoice(playerA, "Liliana, Defiant Necromancer");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "+2: Each player discards a card");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertTapped("Alesha, Who Smiles at Death", true);
assertLife(playerB, 17);
assertGraveyardCount(playerA, "Clever Impersonator", 0);
assertCounterCount(playerB, "Liliana, Defiant Necromancer", CounterType.LOYALTY, 3); // 3
assertPermanentCount(playerB, "Liliana, Defiant Necromancer", 1);
assertPermanentCount(playerA, "Liliana, Defiant Necromancer", 1);
assertCounterCount(playerA, "Liliana, Defiant Necromancer", CounterType.LOYALTY, 5); // 3 + 2
}
/**
* So I copied Jace, Vryns Prodigy with Clever Impersonator (it was tapped
* and I needed a blocker for a token...), and Jace got to survive until the
* next turn. When I looted, he flipped, and I got an error message I
* couldn't get rid of, forcing me to concede. I'm not sure what the correct
* outcome is rules-wise.
*/
@Test
public void testCopyCreatureOfFlipPlaneswalker() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
// {T}: Draw a card, then discard a card. If there are five or more cards in your graveyard, exile Jace, Vryn's Prodigy, then return him to the battefield transformed under his owner's control.
addCard(Zone.BATTLEFIELD, playerA, "Jace, Vryn's Prodigy", 1); // {2}{R} - 3/2
// You may have Clever Impersonator enter the battlefield as a copy of any nonland permanent on the battlefield.
addCard(Zone.HAND, playerA, "Clever Impersonator", 1); // {2}{U}{U}
addCard(Zone.GRAVEYARD, playerA, "Mountain", 4);
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clever Impersonator");
setChoice(playerA, "Jace, Vryn's Prodigy");
addTarget(playerA, "Jace, Vryn's Prodigy[only copy]"); // keep the copied Jace
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw a card");
setChoice(playerA, "Pillarfield Ox");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Jace, Vryn's Prodigy", 1);
assertPermanentCount(playerA, "Pillarfield Ox", 1);
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.copy;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class InfiniteReflectionTest extends CardTestPlayerBase {
/**
*
*/
@Test
public void testCopyAsEnters() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 9);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
// addCard(Zone.BATTLEFIELD, playerA, "Birds of Paradise", 1);
// addCard(Zone.HAND, playerA, "Nantuko Husk", 1);// {2}{B}
addCard(Zone.GRAVEYARD, playerA, "Pillarfield Ox", 1);
// Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost.
addCard(Zone.HAND, playerA, "Reanimate", 1); // {B}
// Enchant creature
// When Infinite Reflection enters the battlefield attached to a creature, each other nontoken creature you control becomes a copy of that creature.
// Nontoken creatures you control enter the battlefield as a copy of enchanted creature.
addCard(Zone.HAND, playerA, "Infinite Reflection", 1); // {5}{U}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Infinite Reflection", "Silvercoat Lion");
// castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nantuko Husk");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Pillarfield Ox");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Silvercoat Lion", 2);
}
}

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.copy;
import mage.constants.PhaseStep;
@ -39,16 +38,13 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*/
public class IsochronScepterTest extends CardTestPlayerBase {
/**
* Isochron Scepter
* Artifact, 2 (2)
* Imprint When Isochron Scepter enters the battlefield, you may exile an
* instant card with converted mana cost 2 or less from your hand.
* {2}, {T}: You may copy the exiled card. If you do, you may cast the copy
* without paying its mana cost.
*
*/
* Isochron Scepter Artifact, 2 (2) Imprint When Isochron Scepter enters
* the battlefield, you may exile an instant card with converted mana cost 2
* or less from your hand. {2}, {T}: You may copy the exiled card. If you
* do, you may cast the copy without paying its mana cost.
*
*/
@Test
public void testImprint() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
@ -64,9 +60,9 @@ public class IsochronScepterTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Isochron Scepter", 1);
assertExileCount("Lightning Bolt", 1);
assertLife(playerB, 20);
}
@Test
public void testCopyCard() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
@ -86,7 +82,7 @@ public class IsochronScepterTest extends CardTestPlayerBase {
assertExileCount("Lightning Bolt", 1);
assertGraveyardCount(playerA, "Lightning Bolt", 0);
assertLife(playerB, 17);
}
@Test
@ -108,20 +104,33 @@ public class IsochronScepterTest extends CardTestPlayerBase {
assertExileCount("Lightning Bolt", 1);
assertGraveyardCount(playerA, "Lightning Bolt", 0);
assertLife(playerB, 20);
}
/**
* Not sure if it's triggered by just casting Angel's Grace or by casting it
* from an Isochron Scepter, but when the bug happens neither player is able
* to play spells or activate abilities anymore for the rest of the game.
*
* Maybe something related to Split Second?
*/
@Test
public void testAngelsGrace() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.HAND, playerA, "Isochron Scepter");
// Split second (As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.)
// You can't lose the game this turn and your opponents can't win the game this turn.
// Until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead.
addCard(Zone.HAND, playerA, "Angel's Grace");
addCard(Zone.BATTLEFIELD, playerB, "Dross Crocodile", 4);
addCard(Zone.BATTLEFIELD, playerB, "Dross Crocodile", 4);// 5/1
addCard(Zone.HAND, playerB, "Lightning Bolt", 2);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
addTarget(playerA, "Angel's Grace");
attack(2, playerB, "Dross Crocodile");
attack(2, playerB, "Dross Crocodile");
attack(2, playerB, "Dross Crocodile");
@ -131,24 +140,34 @@ public class IsochronScepterTest extends CardTestPlayerBase {
setChoice(playerA, "Yes");
setChoice(playerA, "Yes");
setStopAt(2, PhaseStep.END_COMBAT);
// Damage life loss is reduced to 0 because of Angel's Grace effect active
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
// Spells can be cast again
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Dross Crocodile");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Isochron Scepter", 1);
assertExileCount("Angel's Grace", 1);
assertGraveyardCount(playerA, "Angel's Grace", 0);
assertLife(playerA, 1);
assertLife(playerB, 20);
assertGraveyardCount(playerB, "Lightning Bolt", 2);
assertGraveyardCount(playerB, "Dross Crocodile", 1);
assertPermanentCount(playerB, "Dross Crocodile", 3);
assertPermanentCount(playerA, "Isochron Scepter", 1);
}
/**
* Resolving a Silence cast from exile via Isochron Scepter during my opponent's upkeep does
* not prevent that opponent from casting spells that turn.
*
* Resolving a Silence cast from exile via Isochron Scepter during my
* opponent's upkeep does not prevent that opponent from casting spells that
* turn.
*
*/
@Test
public void testSilence() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
@ -160,7 +179,7 @@ public class IsochronScepterTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
addTarget(playerA, "Silence");
activateAbility(2, PhaseStep.UPKEEP, playerA, "{2},{T}:");
setChoice(playerA, "Yes");
setChoice(playerA, "Yes");
@ -175,6 +194,6 @@ public class IsochronScepterTest extends CardTestPlayerBase {
assertHandCount(playerB, "Silvercoat Lion", 1);
assertPermanentCount(playerB, "Silvercoat Lion", 0);
}
}
}

View file

@ -157,7 +157,7 @@ public class KikiJikiMirrorBreakerTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
addCard(Zone.BATTLEFIELD, playerB, "Kiki-Jiki, Mirror Breaker", 1);
// {T}: Draw two cards. Target opponent gains control of Humble Defector. Activate this ability only during your turn.
// You may have Body Double enter the battlefield as a copy of any creature card in a graveyard.
addCard(Zone.HAND, playerB, "Body Double", 1); // {4}{U}
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Body Double");

View file

@ -202,6 +202,9 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
addCard(Zone.BATTLEFIELD, playerA, "Llanowar Elves");
addCard(Zone.HAND, playerA, "Phantasmal Image");
// As Lurebound Scarecrow enters the battlefield, choose a color.
// When you control no permanents of the chosen color, sacrifice Lurebound Scarecrow.
addCard(Zone.HAND, playerA, "Lurebound Scarecrow");
setChoice(playerA, "Green");
@ -324,7 +327,7 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Phantasmal Image");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Phantasmal Image"); // not targeted
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Veil of Secrecy", "Frost Titan"); // so it's no longer targetable
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Veil of Secrecy", "Frost Titan"); // so it's no longer targetable
setChoice(playerB, "Frost Titan");
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Terror", "Frost Titan"); // of player Bs Phantasmal Image copying Frost Titan
@ -346,7 +349,7 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
}
// I've casted a Phantasmal Image targeting opponent's Wurmcoil Engine
// When my Phantasmal Image died, it didn't triggered the Wurmcoil Engine's last ability
// When my Phantasmal Image died, it didn't triggered the Wurmcoil Engine's last ability
// (When Wurmcoil Engine dies, put a 3/3 colorless Wurm artifact creature token with deathtouch and
// a 3/3 colorless Wurm artifact creature token with lifelink onto the battlefield.)
@Test
@ -418,31 +421,39 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
}
/**
* Action
* Game State 1 -----------------> Game State 2
* (On 'field) (Move to GY) (In graveyard)
*
* LTB abilities such as Persist are expceptional in that they trigger based on their existence and
* state of objects before the event (Game State 1, when the card is on the battlefield) rather than
* after (Game State 2, when the card is in the graveyard). It doesn't matter that the LTB ability
* doesn't exist in Game State 2. [CR 603.6d]
*
* 603.6d Normally, objects that exist immediately after an event are checked to see if the event matched any trigger conditions.
* Continuous effects that exist at that time are used to determine what the trigger conditions are and what the objects involved
* in the event look like. However, some triggered abilities must be treated specially. Leaves-the-battlefield abilities, abilities
* that trigger when a permanent phases out, abilities that trigger when an object that all players can see is put into a hand or
* library, abilities that trigger specifically when an object becomes unattached, abilities that trigger when a player loses control
* of an object, and abilities that trigger when a player planeswalks away from a plane will trigger based on their existence, and
* the appearance of objects, prior to the event rather than afterward. The game has to look back in time to determine if these abilities trigger.
*
* Example: Two creatures are on the battlefield along with an artifact that has the ability Whenever a creature dies, you gain 1 life.
* Someone plays a spell that destroys all artifacts, creatures, and enchantments. The artifacts ability triggers twice, even though
* the artifact goes to its owners graveyard at the same time as the creatures.
*
* Action Game State 1 -----------------> Game State 2 (On 'field) (Move to
* GY) (In graveyard)
*
* LTB abilities such as Persist are expceptional in that they trigger based
* on their existence and state of objects before the event (Game State 1,
* when the card is on the battlefield) rather than after (Game State 2,
* when the card is in the graveyard). It doesn't matter that the LTB
* ability doesn't exist in Game State 2. [CR 603.6d]
*
* 603.6d Normally, objects that exist immediately after an event are
* checked to see if the event matched any trigger conditions. Continuous
* effects that exist at that time are used to determine what the trigger
* conditions are and what the objects involved in the event look like.
* However, some triggered abilities must be treated specially.
* Leaves-the-battlefield abilities, abilities that trigger when a permanent
* phases out, abilities that trigger when an object that all players can
* see is put into a hand or library, abilities that trigger specifically
* when an object becomes unattached, abilities that trigger when a player
* loses control of an object, and abilities that trigger when a player
* planeswalks away from a plane will trigger based on their existence, and
* the appearance of objects, prior to the event rather than afterward. The
* game has to look back in time to determine if these abilities trigger.
*
* Example: Two creatures are on the battlefield along with an artifact that
* has the ability Whenever a creature dies, you gain 1 life. Someone
* plays a spell that destroys all artifacts, creatures, and enchantments.
* The artifacts ability triggers twice, even though the artifact goes to
* its owners graveyard at the same time as the creatures.
*
*/
@Test
public void testPersist() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
// When Kitchen Finks enters the battlefield, you gain 2 life.
// Persist (When this creature dies, if it had no -1/-1 counters on it, return it to the battlefield under its owner's control with a -1/-1 counter on it.)
addCard(Zone.HAND, playerA, "Kitchen Finks");
@ -452,21 +463,20 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
// 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."
// it gains "When this creature becomes the target of a spell or ability, sacrifice it."
addCard(Zone.HAND, playerB, "Phantasmal Image");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitchen Finks");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitchen Finks");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Phantasmal Image"); // not targeted
setChoice(playerB, "Kitchen Finks");
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Public Execution", "Kitchen Finks");
setChoice(playerB, "Kitchen Finks");
setStopAt(2, PhaseStep.END_TURN);
execute();
@ -480,13 +490,13 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
assertHandCount(playerB, "Phantasmal Image", 0);
assertGraveyardCount(playerB, "Phantasmal Image", 0);
assertPermanentCount(playerB, "Kitchen Finks", 1);
assertPowerToughness(playerB, "Kitchen Finks", 2, 1);
assertPowerToughness(playerB, "Kitchen Finks", 2, 1);
}
@Test
public void testUndying() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// Undying (When this creature dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it.)
addCard(Zone.HAND, playerA, "Butcher Ghoul");
@ -495,21 +505,20 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
// 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."
// it gains "When this creature becomes the target of a spell or ability, sacrifice it."
addCard(Zone.HAND, playerB, "Phantasmal Image");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Butcher Ghoul");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Butcher Ghoul");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Phantasmal Image"); // not targeted
setChoice(playerB, "Butcher Ghoul");
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Public Execution", "Butcher Ghoul");
setChoice(playerB, "Butcher Ghoul");
setStopAt(2, PhaseStep.END_TURN);
execute();
@ -523,29 +532,25 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
assertHandCount(playerB, "Phantasmal Image", 0);
assertGraveyardCount(playerB, "Phantasmal Image", 0);
assertPermanentCount(playerB, "Butcher Ghoul", 1);
assertPowerToughness(playerB, "Butcher Ghoul", 2, 2);
assertPowerToughness(playerB, "Butcher Ghoul", 2, 2);
}
/**
* 12:29: Attacker: Wurmcoil Engine [466] (6/6) blocked by Wurmcoil Engine
* [4ed] (6/6)
* 12:29: yespair gains 6 life
* 12:29: HipSomHap gains 6 life
* 12:29: Wurmcoil Engine [4ed] died
* 12:29: Ability triggers: Wurmcoil Engine [4ed] - When Wurmcoil Engine [4ed] dies, put a a 3/3 colorless
* [4ed] (6/6) 12:29: yespair gains 6 life 12:29: HipSomHap gains 6 life
* 12:29: Wurmcoil Engine [4ed] died 12:29: Ability triggers: Wurmcoil
* Engine [4ed] - When Wurmcoil Engine [4ed] dies, put a a 3/3 colorless
* Wurm artifact creature token with deathtouch onto the battlefield. Put a
* a 3/3 colorless Wurm artifact creature token with lifelink onto the
* battlefield.
* 12:29: Phantasmal Image [466] died
* 12:29: HipSomHap puts a Wurm [7d0] token onto the battlefield
* 12:29: HipSomHap puts a Wurm [186] token onto the battlefield
* battlefield. 12:29: Phantasmal Image [466] died 12:29: HipSomHap puts a
* Wurm [7d0] token onto the battlefield 12:29: HipSomHap puts a Wurm [186]
* token onto the battlefield
*
* To the best of my knowledge, the Phantasmal Image [466], which entered
* the battlefield as a Wurmcoil Engine, should grant tokens through the
* Dies-trigger as well, right?
*/
@Test
public void testDiesTriggered2() {
addCard(Zone.BATTLEFIELD, playerB, "Wurmcoil Engine");
@ -570,5 +575,5 @@ public class PhantasmalImageTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Wurm", 2);
assertPermanentCount(playerB, "Wurm", 2);
}
}
}

View file

@ -36,10 +36,8 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*
* @author LevelX2
*/
public class PhyrexianMetamorphTest extends CardTestPlayerBase {
@Test
public void testCopyCreature() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
@ -48,7 +46,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
// You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types.
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP}
addCard(Zone.HAND, playerA, "Cloudshift");
//Flying
// Vanishing 3 (This permanent enters the battlefield with three time counters on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it.)
// When Aven Riftwatcher enters the battlefield or leaves the battlefield, you gain 2 life.
@ -68,13 +66,13 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
assertLife(playerA, 24);
assertLife(playerB, 20);
assertGraveyardCount(playerA, "Cloudshift", 1);
assertPermanentCount(playerA, "Ponyback Brigade", 1);
assertPermanentCount(playerA, "Goblin", 3);
}
}
/**
* An opponent cast Phyrexian Metamorph and cloned another opponent's
@ -84,7 +82,6 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
* to choose a new creature to clone when the Phyrexian Metamorph re-entered
* the battlefield.
*/
@Test
public void testFlickerWithBrago() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
@ -93,9 +90,9 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP}
// Flying
// When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control.
// When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control.
addCard(Zone.BATTLEFIELD, playerA, "Brago, King Eternal"); // 2/4
// Creatures you control have haste.
// Cascade, cascade
addCard(Zone.BATTLEFIELD, playerB, "Maelstrom Wanderer"); // 7/5
@ -106,19 +103,19 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
setChoice(playerA, "Maelstrom Wanderer");
attack(3, playerA, "Brago, King Eternal");
addTarget(playerA, "Maelstrom Wanderer");
addTarget(playerA, "Maelstrom Wanderer");
setChoice(playerA, "Ponyback Brigade");
setStopAt(3, PhaseStep.END_COMBAT);
execute();
assertLife(playerA, 20);
assertLife(playerB, 18);
assertPermanentCount(playerA, "Ponyback Brigade", 1);
assertPermanentCount(playerA, "Goblin", 3);
}
}
/**
* I had a Harmonic Sliver, my opponent played Phyrexian Metamorph copying
@ -126,7 +123,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
* destroying ability, where it should have had two of them and triggered
* twice (the Metamorph might have nothing to do with this)
*/
@Test
@Test
public void testHarmonicSliver() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
@ -137,7 +134,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Kitesail", 1);
// All Slivers have "When this permanent enters the battlefield, destroy target artifact or enchantment."
addCard(Zone.BATTLEFIELD, playerB, "Harmonic Sliver"); // 2/4
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Phyrexian Metamorph");
setChoice(playerA, "Harmonic Sliver");
addTarget(playerA, "Alloy Myr");
@ -145,66 +142,116 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertPermanentCount(playerA, "Harmonic Sliver", 1);
assertGraveyardCount(playerB, "Alloy Myr", 1);
assertGraveyardCount(playerB, "Kitesail", 1);
}
}
/**
* If a Harmonic Sliver enters the battlefield
* the controller has to destroy one artifacts or enchantments
* If a Harmonic Sliver enters the battlefield the controller has to destroy
* one artifacts or enchantments
*/
@Test
public void testHarmonicSliverNative1() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// All Slivers have "When this permanent enters the battlefield, destroy target artifact or enchantment."
addCard(Zone.HAND, playerA, "Harmonic Sliver");
addCard(Zone.BATTLEFIELD, playerB, "Alloy Myr", 2); // 2/2
// All Slivers have "When this permanent enters the battlefield, destroy target artifact or enchantment."
addCard(Zone.HAND, playerA, "Harmonic Sliver");
addCard(Zone.BATTLEFIELD, playerB, "Alloy Myr", 2); // 2/2
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harmonic Sliver");
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertPermanentCount(playerA, "Harmonic Sliver", 1);
assertGraveyardCount(playerB, "Alloy Myr", 1);
}
}
/**
* If a Harmonic Sliver enters the battlefield and there is already one on the battlefield
* the controller has to destroy two artifacts or enchantments
* If a Harmonic Sliver enters the battlefield and there is already one on
* the battlefield the controller has to destroy two artifacts or
* enchantments
*/
@Test
public void testHarmonicSliverNative2() {
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.HAND, playerA, "Harmonic Sliver");
addCard(Zone.HAND, playerA, "Harmonic Sliver");
addCard(Zone.BATTLEFIELD, playerB, "Alloy Myr", 1);
addCard(Zone.BATTLEFIELD, playerB, "Kitesail", 1);
// All Slivers have "When this permanent enters the battlefield, destroy target artifact or enchantment."
addCard(Zone.BATTLEFIELD, playerB, "Harmonic Sliver"); // 2/4
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harmonic Sliver");
addTarget(playerA, "Alloy Myr");
addTarget(playerA, "Kitesail");
setStopAt(1, PhaseStep.END_COMBAT);
execute();
assertPermanentCount(playerA, "Harmonic Sliver", 1);
assertGraveyardCount(playerB, "Alloy Myr", 1);
assertGraveyardCount(playerB, "Kitesail", 1);
}
}
/**
* I cast Show and Tell, and put Sheoldred, Whispering One into play and my
* opponent put Phyrexian Metamorph into play and he was able to clone my
* Sheoldred, Whispering One.
*
* 6/1/2011 If Phyrexian Metamorph somehow enters the battlefield at the
* same time as another permanent (due to Mass Polymorph or Liliana Vess's
* third ability, for example), Phyrexian Metamorph can't become a copy of
* that permanent. You may only choose a permanent that's already on the
* battlefield.
*
* 400.6. If an object would move from one zone to another, determine what
* event is moving the object. If the object is moving to a public zone, all
* players look at it to see if it has any abilities that would affect the
* move. Then any appropriate replacement effects, whether they come from
* that object or from elsewhere, are applied to that event. If any effects
* or rules try to do two or more contradictory or mutually exclusive things
* to a particular object, that object's controller -- or its owner if it
* has no controller -- chooses which effect to apply, and what that effect
* does. (Note that multiple instances of the same thing may be mutually
* exclusive; for example, two simultaneous "destroy" effects.) Then the
* event moves the object.
*/
@Test
public void testShowAndTell() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
// Each player may put an artifact, creature, enchantment, or land card from his or her hand onto the battlefield.
addCard(Zone.HAND, playerA, "Show and Tell"); // SORCERY {2}{U}
// Swampwalk
// At the beginning of your upkeep, return target creature card from your graveyard to the battlefield.
// At the beginning of each opponent's upkeep, that player sacrifices a creature.
addCard(Zone.HAND, playerA, "Sheoldred, Whispering One");
addCard(Zone.HAND, playerB, "Phyrexian Metamorph");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Show and Tell");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Sheoldred, Whispering One", 1);
assertPermanentCount(playerB, "Sheoldred, Whispering One", 0);
assertGraveyardCount(playerB, "Phyrexian Metamorph", 1);
}
}

View file

@ -60,12 +60,11 @@ public class VesuvaTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Glimmerpost", 1);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Glimmerpost");
playLand(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Glimmerpost");
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Vesuva");
setChoice(playerA, "Glimmerpost");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
@ -75,31 +74,31 @@ public class VesuvaTest extends CardTestPlayerBase {
assertLife(playerA, 24); // 20 + 1 + 3
assertLife(playerB, 22); // 20 + 2
}
@Test
public void testDarkDepth() {
// Dark Depths enters the battlefield with ten ice counters on it.
// {3}: Remove an ice counter from Dark Depths.
// When Dark Depths has no ice counters on it, sacrifice it. If you do, put a legendary 20/20 black Avatar creature token with flying and "This creature is indestructible" named Marit Lage onto the battlefield.
addCard(Zone.BATTLEFIELD, playerB, "Dark Depths", 1);
// You may have Vesuva enter the battlefield tapped as a copy of any land on the battlefield.
addCard(Zone.HAND, playerA, "Vesuva", 1);
addCard(Zone.HAND, playerA, "Vesuva", 1);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Vesuva");
setChoice(playerA, "Dark Depths");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Dark Depths", 1);
assertPermanentCount(playerB, "Dark Depths", 1);
assertPermanentCount(playerA, "Dark Depths", 1);
Permanent darkDepth = getPermanent("Dark Depths", playerA);
if (darkDepth != null) {
Assert.assertEquals(darkDepth.getCounters().getCount("ice"), 10);
Assert.assertEquals(10, darkDepth.getCounters().getCount("ice"));
}
assertTappedCount("Dark Depths", true, 1);
}
}

View file

@ -0,0 +1,125 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.enchantments;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class OathOfLiegesTest extends CardTestPlayerBase {
@Test
public void testSearchLandOwner() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is his or her opponent.
// The first player may search his or her library for a basic land card, put that card onto the battlefield, then shuffle his or her library.
addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
addCard(Zone.LIBRARY, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
addTarget(playerA, playerB);
addTarget(playerA, "Plains");
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerA, "Oath of Lieges", 1);
assertPermanentCount(playerA, "Plains", 3);
}
@Test
public void testSearchLandOpponent() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is his or her opponent.
// The first player may search his or her library for a basic land card, put that card onto the battlefield, then shuffle his or her library.
addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
addCard(Zone.BATTLEFIELD, playerB, "Plains", 1);
addCard(Zone.LIBRARY, playerB, "Plains", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
addTarget(playerB, playerA);
addTarget(playerB, "Plains");
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerA, "Oath of Lieges", 1);
assertPermanentCount(playerA, "Plains", 2);
assertPermanentCount(playerB, "Plains", 2);
}
@Test
public void testSearchLandOwnerCopy() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is his or her opponent.
// The first player may search his or her library for a basic land card, put that card onto the battlefield, then shuffle his or her library.
addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
addCard(Zone.LIBRARY, playerA, "Plains", 3);
addCard(Zone.HAND, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
addCard(Zone.HAND, playerB, "Copy Enchantment", 1); // {2}{U}
addCard(Zone.LIBRARY, playerB, "Plains", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Copy Enchantment");
setChoice(playerB, "Oath of Lieges");
// turn 3
addTarget(playerA, playerB);
addTarget(playerA, "Plains"); // 3rd land
addTarget(playerA, "Plains"); // second trigger will fail because target player has no longer more lands than controller
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains"); // 4th land
// turn 4
addTarget(playerB, playerA);
addTarget(playerB, "Plains");
addTarget(playerB, "Plains"); // second trigger will fail because target player has no longer more lands than controller
setStopAt(4, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerB, "Oath of Lieges", 1);
assertPermanentCount(playerA, "Oath of Lieges", 1);
assertPermanentCount(playerB, "Plains", 1);
assertPermanentCount(playerA, "Plains", 4);
}
}

View file

@ -0,0 +1,88 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.enchantments;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class ParadoxHazeTest extends CardTestPlayerBase {
@Test
public void testNormal() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 8);
// Enchant player
// At the beginning of enchanted player's first upkeep each turn, that player gets an additional upkeep step after this step.
addCard(Zone.HAND, playerA, "Paradox Haze", 1); // {2}{U}
// At the beginning of each upkeep, put a 1/1 green Saproling creature token onto the battlefield.
addCard(Zone.HAND, playerA, "Verdant Force", 1); // {5}{G}{G}{G}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Paradox Haze", playerA);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Verdant Force");
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerA, "Paradox Haze", 1);
assertPermanentCount(playerA, "Verdant Force", 1);
assertPermanentCount(playerA, "Saproling", 3);// 1 from turn 2 and 2 from turn 3
}
@Test
public void testCopied() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 8);
// Enchant player
// At the beginning of enchanted player's first upkeep each turn, that player gets an additional upkeep step after this step.
addCard(Zone.HAND, playerA, "Paradox Haze", 1); // {2}{U}
// You may have Copy Enchantment enter the battlefield as a copy of any enchantment on the battlefield.
addCard(Zone.HAND, playerA, "Copy Enchantment", 1); // {2}{U}
// At the beginning of each upkeep, put a 1/1 green Saproling creature token onto the battlefield.
addCard(Zone.HAND, playerA, "Verdant Force", 1); // {5}{G}{G}{G}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Paradox Haze", playerA);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Copy Enchantment");
setChoice(playerA, "Paradox Haze");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Verdant Force");
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerA, "Paradox Haze", 2);
assertPermanentCount(playerA, "Verdant Force", 1);
assertPermanentCount(playerA, "Saproling", 4); // 1 from turn 2 and 3 from turn 3
}
}

View file

@ -0,0 +1,88 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.enchantments;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class SkullclampTest extends CardTestPlayerBase {
/**
* Skullclamp and the creature it's attached to are destroyed by same
* Pernicious Deed activation. AFAIK Skullclamp should trigger, but it
* doesn't.
*
* 400.7e Abilities of Auras that trigger when the enchanted permanent
* leaves the battlefield can find the new object that Aura became in its
* owners graveyard if it was put into that graveyard at the same time the
* enchanted permanent left the battlefield. It can also find the new object
* that Aura became in its owners graveyard as a result of being put there
* as a state-based action for not being attached to a permanent. (See rule
* 704.5n.)
*
*/
@Test
public void testPerniciousDeed() {
// Equipped creature gets +1/-1.
// Whenever equipped creature dies, draw two cards.
// Equip {1}
addCard(Zone.BATTLEFIELD, playerA, "Skullclamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
// {X}, Sacrifice Pernicious Deed: Destroy each artifact, creature, and enchantment with converted mana cost X or less.
addCard(Zone.BATTLEFIELD, playerB, "Pernicious Deed"); // Enchantment
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Silvercoat Lion");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "{X},Sacrifice");
setChoice(playerB, "X=2");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, "Skullclamp", 1);
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
assertGraveyardCount(playerB, "Pernicious Deed", 1);
assertPermanentCount(playerA, "Pillarfield Ox", 1);
assertHandCount(playerA, 2);
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.enchantments;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class SpreadingSeasTest extends CardTestPlayerBase {
/**
* Played Spreading Seas on opps manland (e.g. Blinkmoth Nexus) . He
* activated it on response, seas resolves but the manland loses creature
* type what should not happened.
*
* 305.7. If an effect changes a lands subtype to one or more of the basic
* land types, the land no longer has its old land type. It loses all
* abilities generated from its rules text and its old land types, and it
* gains the appropriate mana ability for each new basic land type. Note
* that this doesnt remove any abilities that were granted to the land by
* other effects. Changing a lands subtype doesnt add or remove any card
* types (such as creature) or supertypes (such as basic, legendary, and
* snow) the land may have. If a land gains one or more land types in
* addition to its own, it keeps its land types and rules text, and it gains
* the new land types and mana abilities.
*
*/
@Test
public void testCreatureTypeStays() {
// Enchant land
// When Spreading Seas enters the battlefield, draw a card.
// Enchanted land is an Island.
addCard(Zone.HAND, playerA, "Spreading Seas", 1); // {1}{U}
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerB, "Island", 1);
// Tap: Add 1 to your mana pool.
// {1}: Blinkmoth Nexus becomes a 1/1 Blinkmoth artifact creature with flying until end of turn. It's still a land.
// {1}, {T}: Target Blinkmoth gets +1/+1 until end of turn.
addCard(Zone.BATTLEFIELD, playerB, "Blinkmoth Nexus");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spreading Seas", "Blinkmoth Nexus");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}:", NO_TARGET, "Spreading Seas");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertHandCount(playerA, "Spreading Seas", 0);
assertGraveyardCount(playerA, "Spreading Seas", 0);
assertPowerToughness(playerB, "Blinkmoth Nexus", 1, 1);
assertPermanentCount(playerA, "Spreading Seas", 1);
assertHandCount(playerA, 1);
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.modal;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class ModalTriggeredAbilityTest extends CardTestPlayerBase {
@Test
public void testBlizzardSpecterReturn() {
// Flying
// Whenever Blizzard Specter deals combat damage to a player, choose one
// - That player returns a permanent he or she controls to its owner's hand;
// or that player discards a card.
addCard(Zone.BATTLEFIELD, playerB, "Blizzard Specter");
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
addCard(Zone.HAND, playerA, "Pillarfield Ox");
attack(2, playerB, "Blizzard Specter");
setModeChoice(playerB, "1");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertHandCount(playerA, "Silvercoat Lion", 1);
assertHandCount(playerA, "Pillarfield Ox", 1);
assertLife(playerA, 18);
assertLife(playerB, 20);
}
@Test
public void testBlizzardSpecterDiscard() {
// Flying
// Whenever Blizzard Specter deals combat damage to a player, choose one
// - That player returns a permanent he or she controls to its owner's hand;
// or that player discards a card.
addCard(Zone.BATTLEFIELD, playerB, "Blizzard Specter");
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
addCard(Zone.HAND, playerA, "Pillarfield Ox");
attack(2, playerB, "Blizzard Specter");
setModeChoice(playerB, "2");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertHandCount(playerA, "Silvercoat Lion", 0);
assertHandCount(playerA, "Pillarfield Ox", 0);
assertGraveyardCount(playerA, "Pillarfield Ox", 1);
assertLife(playerA, 18);
assertLife(playerB, 20);
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.planeswalker;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class RedirectDamageToPlaneswalkerTest extends CardTestPlayerBase {
@Test
public void testDirectDamage() {
// +2: Look at the top card of target player's library. You may put that card on the bottom of that player's library.
// 0: Draw three cards, then put two cards from your hand on top of your library in any order.
// 1: Return target creature to its owner's hand.
addCard(Zone.BATTLEFIELD, playerA, "Jace, the Mind Sculptor"); // starts with 3 Loyality counters
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
addCard(Zone.HAND, playerB, "Lightning Bolt");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+2:", playerB);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
setChoice(playerB, "Yes");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Jace, the Mind Sculptor", 1);
assertCounterCount("Jace, the Mind Sculptor", CounterType.LOYALTY, 2); // 3 + 2 - 3 = 2
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertLife(playerA, 20);
assertLife(playerB, 20);
}
}

View file

@ -6,22 +6,30 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* Pillar of Flame:
* Pillar of Flame deals 2 damage to target creature or player. If a creature dealt damage this way would die this turn, exile it instead.
* Pillar of Flame: Pillar of Flame deals 2 damage to target creature or player.
* If a creature dealt damage this way would die this turn, exile it instead.
*
* @author LevelX2
*/
public class PillarOfFlameTest extends CardTestPlayerBase {
/**
* Tests when cast Pillar of Flame targeting opponent there is no influence on dying creature of opponent
* Tests when cast Pillar of Flame targeting opponent there is no influence
* on dying creature of opponent
*/
@Test
public void testNotTriggeringExileItInstead() {
addCard(Zone.BATTLEFIELD, playerA, "Lightning Mauler");
addCard(Zone.BATTLEFIELD, playerA, "Rakdos Cackler");
// Soulbond
// As long as Lightning Mauler is paired with another creature, both creatures have haste.
addCard(Zone.BATTLEFIELD, playerA, "Lightning Mauler"); // 2/1
// Unleash (You may have this creature enter the battlefield with a +1/+1 counter on it. It can't block as long as it has a +1/+1 counter on it.)
addCard(Zone.BATTLEFIELD, playerA, "Rakdos Cackler"); // 1/1
// Pillar of Flame deals 2 damage to target creature or player.
// If a creature dealt damage this way would die this turn, exile it instead.
addCard(Zone.HAND, playerA, "Pillar of Flame");
// Soulbond
// As long as Stonewright is paired with another creature, each of those creatures has "{R}: This creature gets +1/+0 until end of turn."
addCard(Zone.HAND, playerA, "Stonewright");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
@ -49,7 +57,8 @@ public class PillarOfFlameTest extends CardTestPlayerBase {
}
/**
* Tests when cast Pillar of Flame targeting creature it goes to exile if dying later
* Tests when cast Pillar of Flame targeting creature it goes to exile if
* dying later
*/
@Test
public void testTriggeringExileItInstead() {

View file

@ -6,8 +6,8 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* Torpor Orb:
* Creatures entering the battlefield don't cause abilities to trigger.
* Torpor Orb: Creatures entering the battlefield don't cause abilities to
* trigger.
*
* @author noxx
*/
@ -15,7 +15,10 @@ public class TorporOrbTest extends CardTestPlayerBase {
@Test
public void testWallOfOmens() {
// Creatures entering the battlefield don't cause abilities to trigger.
addCard(Zone.BATTLEFIELD, playerA, "Torpor Orb");
// Defender
// When Wall of Omens enters the battlefield, draw a card.
addCard(Zone.HAND, playerA, "Wall of Omens");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
@ -33,7 +36,8 @@ public class TorporOrbTest extends CardTestPlayerBase {
}
/**
* Treacherous Pit-Dweller doesnt function properly with Torpor Orb and Hushwing Gryff
* Treacherous Pit-Dweller doesnt function properly with Torpor Orb and
* Hushwing Gryff
*/
@Test
public void testPitTweller() {
@ -42,8 +46,8 @@ public class TorporOrbTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
attack(2, playerB, "Treacherous Pit-Dweller");
attack(2, playerB, "Treacherous Pit-Dweller");
castSpell(2, PhaseStep.DECLARE_ATTACKERS, playerA, "Lightning Bolt", "Treacherous Pit-Dweller");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
@ -53,9 +57,9 @@ public class TorporOrbTest extends CardTestPlayerBase {
assertLife(playerB, 20);
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertPermanentCount(playerB, "Treacherous Pit-Dweller", 1);
assertPowerToughness(playerB, "Treacherous Pit-Dweller", 5,4);
assertPowerToughness(playerB, "Treacherous Pit-Dweller", 5, 4);
}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.replacement.entersBattlefield;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class LivingLoreTest extends CardTestPlayerBase {
/**
* That the +1/+1 counters are added to Living Lore before state based
* actions take place
*/
@Test
public void testCountersAdded() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
addCard(Zone.HAND, playerA, "Living Lore"); //{3}{U}
addCard(Zone.GRAVEYARD, playerA, "Natural Connection", 1); // {2}{G}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Living Lore");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Living Lore", 1);
assertPowerToughness(playerA, "Living Lore", 3, 3);
}
}

View file

@ -1,4 +1,4 @@
package org.mage.test.cards.replacement.prevent;
package org.mage.test.cards.replacement.redirect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
@ -6,15 +6,17 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* Harm's Way:
* The next 2 damage that a source of your choice would deal to you and/or permanents you control this turn is dealt to target creature or player instead.
* Harm's Way: The next 2 damage that a source of your choice would deal to you
* and/or permanents you control this turn is dealt to target creature or player
* instead.
*
* @author noxx
*/
public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
/**
* Tests that 2 of 3 damage is redirected while 1 damage is still dealt to original target
* Tests that 2 of 3 damage is redirected while 1 damage is still dealt to
* original target
*/
@Test
public void testRedirectTwoDamage() {
@ -51,7 +53,7 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
attack(2, playerB, "Craw Wurm");
castSpell(2, PhaseStep.DECLARE_BLOCKERS, playerA, "Harm's Way", playerB);
setChoice(playerA, "Craw Wurm");
setStopAt(2, PhaseStep.END_TURN);
execute();
@ -79,8 +81,11 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Magma Phoenix");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harm's Way", playerB);
setChoice(playerA, "Magma Phoenix");
/** When Magma Phoenix dies, Magma Phoenix deals 3 damage to each creature and each player **/
setChoice(playerA, "Magma Phoenix");
/**
* When Magma Phoenix dies, Magma Phoenix deals 3 damage to each
* creature and each player *
*/
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Magma Phoenix");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
@ -91,4 +96,38 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
assertLife(playerB, 15); // 3 damage from dying Phoenix directly and 2 redirected damage from playerA
}
/**
* Tests that not preventable damage is redirected
*/
@Test
public void testRedirectNotPreventableDamage() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
// <i>Ferocious</i> If you control a creature with power 4 or greater, damage can't be prevented this turn.
// Wild Slash deals 2 damage to target creature or player.
addCard(Zone.HAND, playerA, "Wild Slash"); // {R}
addCard(Zone.BATTLEFIELD, playerA, "Serra Angel");
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
// The next 2 damage that a source of your choice would deal to you and/or permanents
// you control this turn is dealt to target creature or player instead.
addCard(Zone.HAND, playerB, "Harm's Way"); // {W}
addCard(Zone.BATTLEFIELD, playerB, "Plains");
addCard(Zone.BATTLEFIELD, playerB, "Birds of Paradise");
// the 2 damage can't be prevented and have to be redirected to Silvercoat Lion of player A
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wild Slash", "Birds of Paradise");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Harm's Way", "Silvercoat Lion", "Wild Slash");
setChoice(playerB, "Wild Slash");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Wild Slash", 1);
assertGraveyardCount(playerB, "Harm's Way", 1);
assertPermanentCount(playerB, "Birds of Paradise", 1);
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
assertLife(playerA, 20);
assertLife(playerB, 20);
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.replacement.redirect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class ShamenEnKorTest extends CardTestPlayerBase {
/**
* Tests that 2 of 3 damage is redirected while 1 damage is still dealt to
* original target
*/
@Test
public void testFirstAbilityNonCombatDamage() {
addCard(Zone.HAND, playerA, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
// {0}: The next 1 damage that would be dealt to Shaman en-Kor this turn is dealt to target creature you control instead.
// {1}{W}: The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to Shaman en-Kor instead.
addCard(Zone.BATTLEFIELD, playerB, "Shaman en-Kor"); // 1/2
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Shaman en-Kor");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{0}: The next 1 damage", "Silvercoat Lion", "Lightning Bolt");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{0}: The next 1 damage", "Silvercoat Lion", "Lightning Bolt");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertPermanentCount(playerB, "Shaman en-Kor", 1);
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
}
@Test
public void testSecondAbilityNonCombatDamage() {
addCard(Zone.HAND, playerA, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
// {0}: The next 1 damage that would be dealt to Shaman en-Kor this turn is dealt to target creature you control instead.
// {1}{W}: The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to Shaman en-Kor instead.
addCard(Zone.BATTLEFIELD, playerB, "Shaman en-Kor"); // 1/2
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{W}: The next time", "Silvercoat Lion", "Lightning Bolt");
setChoice(playerB, "Lightning Bolt");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertPermanentCount(playerB, "Silvercoat Lion", 1);
assertGraveyardCount(playerB, "Shaman en-Kor", 1);
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.replacement.redirect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class WardOfPietyTest extends CardTestPlayerBase {
@Test
public void testNonCombatDamageToPlayer() {
addCard(Zone.HAND, playerB, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
// Enchant creature
// {1}{W}: The next 1 damage that would be dealt to enchanted creature this turn is dealt to target creature or player instead.
addCard(Zone.HAND, playerA, "Ward of Piety"); // {1}{W}
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // 2/2
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ward of Piety", "Silvercoat Lion");
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{1}{W}: The next 1 damage", playerB);
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "{1}{W}: The next 1 damage", playerB);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", "Silvercoat Lion");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertPermanentCount(playerA, "Ward of Piety", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertLife(playerA, 20);
assertLife(playerB, 18);
}
}

View file

@ -192,4 +192,104 @@ public class OmniscienceTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Pillarfield Ox", 1);
}
/**
* If another effect (e.g. Future Sight) allows you to cast nonland cards
* from zones other than your hand, Xmage incorrectly lets you cast those
* cards without paying their mana costs. Omniscience only lets you cast
* spells from your hand without paying their mana costs.
*/
@Test
public void testCastingWithFutureSight() {
// You may cast nonland cards from your hand without paying their mana costs.
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
// Play with the top card of your library revealed.
// You may play the top card of your library.
addCard(Zone.BATTLEFIELD, playerA, "Future Sight", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 1);
skipInitShuffling();
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion");
setChoice(playerA, "Yes");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertLife(playerA, 20);
assertLife(playerB, 20);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertTapped("Plains", true); // plains have to be tapped because {2} have to be paid
}
/**
* If a spell has an additional cost (optional or mandatory, e.g. Entwine),
* Omniscience incorrectly allows you cast the spell as if that cost had
* been paid without paying that spell's mana cost. 117.9d If an alternative
* cost is being paid to cast a spell, any additional costs, cost increases,
* and cost reductions that affect that spell are applied to that
* alternative cost. (See rule 601.2f.)
*/
@Test
public void testCastingWithCyclonicRiftWithOverload() {
// You may cast nonland cards from your hand without paying their mana costs.
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// Choose one - Barbed Lightning deals 3 damage to target creature; or Barbed Lightning deals 3 damage to target player.
// Entwine {2} (Choose both if you pay the entwine cost.)
addCard(Zone.HAND, playerA, "Barbed Lightning", 1);
// Creature - 3/3 Swampwalk
addCard(Zone.BATTLEFIELD, playerB, "Bog Wraith", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning", "Bog Wraith");
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Barbed Lightning", 1);
assertGraveyardCount(playerB, "Bog Wraith", 1);
assertLife(playerA, 20);
assertLife(playerB, 17);
assertTapped("Plains", true); // plains have to be tapped because {2} from Entwine have to be paid
}
/**
* If a spell has an unpayable cost (e.g. Ancestral Vision, which has no
* mana cost), Omniscience should allow you to cast that spell without
* paying its mana cost. In the case of Ancestral Vision, for example, Xmage
* only gives you the option to suspend Ancestral Vision. 117.6a If an
* unpayable cost is increased by an effect or an additional cost is
* imposed, the cost is still unpayable. If an alternative cost is applied
* to an unpayable cost, including an effect that allows a player to cast a
* spell without paying its mana cost, the alternative cost may be paid.
*/
@Test
public void testCastingUnpayableCost() {
// You may cast nonland cards from your hand without paying their mana costs.
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
// Suspend 4-{U}
// Target player draws three cards.
addCard(Zone.HAND, playerA, "Ancestral Vision", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ancestral Vision", playerA);
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Ancestral Vision", 1);
assertHandCount(playerA, 3);
assertLife(playerA, 20);
assertLife(playerB, 20);
}
}

View file

@ -33,8 +33,9 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
}
/**
* Tests "Cavern of Souls" with "Human" creature type chosen.
* Then tests casting Azure Drake (should fail) and Elite Vanguard (should be ok as it has "Human" subtype)
* Tests "Cavern of Souls" with "Human" creature type chosen. Then tests
* casting Azure Drake (should fail) and Elite Vanguard (should be ok as it
* has "Human" subtype)
*/
@Test
public void testNoCastBecauseOfCreatureType() {
@ -87,6 +88,9 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
@Test
public void testDrakeCantBeCountered() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
// As Cavern of Souls enters the battlefield, choose a creature type.
// {T}: Add {1} to your mana pool.
// {T}: Add one mana of any color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered.
addCard(Zone.HAND, playerA, "Cavern of Souls");
addCard(Zone.HAND, playerA, "Azure Drake");
@ -108,6 +112,7 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Azure Drake", 0);
assertPermanentCount(playerA, "Azure Drake", 1);
}
/**
* Tests spell can be countered if cast with colorless mana from Cavern
*/
@ -136,59 +141,59 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Azure Drake", 1);
assertPermanentCount(playerA, "Azure Drake", 0);
}
/**
* Tests conditional mana from Cavern in pool will still work if Cavern got back to hand and is played again with other creature type
* Tests conditional mana from Cavern in pool will still work if Cavern got
* back to hand and is played again with other creature type
*/
@Test
public void testConditionlManaWorksIfCavernIsReplayed() {
addCard(Zone.HAND, playerA, "Cavern of Souls");
addCard(Zone.HAND, playerA, "Gladecover Scout"); // Elf costing {G}
// addCard(Zone.HAND, playerA, "Fume Spitter"); // Horror costing {B}
// Instant - {U}{U} - Return target permanent to its owner's hand.
addCard(Zone.HAND, playerB, "Boomerang");
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls");
setChoice(playerA, "Elf");
// getting green mana for Elf into pool
activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add 1 mana of any one color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered.");
setChoice(playerA, "Green");
setChoice(playerA, "Green");
// return cavern to hand
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerB, "Boomerang", "Cavern of Souls");
// playing the cavern again choose different creature type
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls");
setChoice(playerA, "Horror");
// the green mana usable for Elf should be in the mana pool
// the green mana usable for Elf should be in the mana pool
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Gladecover Scout");
activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add 1 mana of any one color to your mana pool. Spend this mana only to cast a creature spell of the chosen type, and that spell can't be countered.");
setChoice(playerA, "Black");
setChoice(playerA, "Black");
// the black mana usable for Horror should be in the mana pool
// the black mana usable for Horror should be in the mana pool
// castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Fume Spitter");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, "Boomerang", 1);
assertPermanentCount(playerA, "Cavern of Souls", 1);
// Check the elf was cast
assertPermanentCount(playerA, "Gladecover Scout", 1);
// Check Horror on the Battlefield
// assertPermanentCount(playerA, "Fume Spitter", 1);
}
}
/**
* Return to the Ranks cannot be countered if mana produced by Cavern of Souls
* was used to pay X. Can be bug also for all other spells with X in their cost, not sure.
* Return to the Ranks cannot be countered if mana produced by Cavern of
* Souls was used to pay X. Can be bug also for all other spells with X in
* their cost, not sure.
*
*/
@Test
@ -205,12 +210,11 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Counterspell");
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls");
setChoice(playerA, "Drake");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Return to the Ranks", "Silvercoat Lion");
setChoice(playerA, "X=1");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Counterspell", "Return to the Ranks");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
@ -223,11 +227,12 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Silvercoat Lion", 0);
}
/**
* Cavern of Souls can produce any colour of mana with its second ability when Contamination is in play.
* Cavern of Souls can produce any colour of mana with its second ability
* when Contamination is in play.
*/
@Test
@Test
public void testUseWithConversionInPlay() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.HAND, playerA, "Cavern of Souls");
@ -235,8 +240,6 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Desert Drake");
addCard(Zone.BATTLEFIELD, playerB, "Contamination", 1);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cavern of Souls");
setChoice(playerA, "Drake");
@ -249,5 +252,5 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Desert Drake", 0);
}
}

View file

@ -2,6 +2,8 @@ package org.mage.test.cards.triggers;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -13,14 +15,16 @@ public class FathomMageTest extends CardTestPlayerBase {
/**
* Fathom Mage - Creature Human Wizard 1/1, 2UG
*
* Evolve (Whenever a creature enters the battlefield under your control, if that creature has greater power or toughness than this creature, put a +1/+1 counter on this creature.)
* Whenever a +1/+1 counter is placed on Fathom Mage, you may draw a card.
* Evolve (Whenever a creature enters the battlefield under your control, if
* that creature has greater power or toughness than this creature, put a
* +1/+1 counter on this creature.) Whenever a +1/+1 counter is placed on
* Fathom Mage, you may draw a card.
*
*
*/
@Test
public void testDrawCardsAddedCounters() {
// card draw triggered ability will trigger once for each of those counters from Blessings of Nature.
// card draw triggered ability will trigger once for each of those counters from Blessings of Nature.
addCard(Zone.HAND, playerA, "Blessings of Nature");
addCard(Zone.BATTLEFIELD, playerA, "Fathom Mage", 1);
@ -38,20 +42,26 @@ public class FathomMageTest extends CardTestPlayerBase {
@Test
public void testDrawCardsEntersTheBattlefield() {
// card draw triggered ability will trigger once for each of those counters from Master Biomancer.
// card draw triggered ability will trigger once for each of those counters from Master Biomancer.
addCard(Zone.HAND, playerA, "Fathom Mage");
// Each other creature you control enters the battlefield with a number of additional +1/+1 counters on it equal to
// Master Biomancer's power and as a Mutant in addition to its other types.
addCard(Zone.BATTLEFIELD, playerA, "Master Biomancer", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fathom Mage");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fathom Mage"); // {2}{G}{U}
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Fathom Mage", 1);
assertPowerToughness(playerA, "Fathom Mage", 3, 3);
Permanent fathomMage = getPermanent("Fathom Mage", playerA);
Assert.assertEquals("Fathom Mage has to be a Mutant", true, fathomMage.getSubtype().contains("Mutant"));
assertHandCount(playerA, 2);
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.triggers;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class MelekIzzetParagonTest extends CardTestPlayerBase {
/**
* Wenn Melek, Izzet Paragon liegt und man einen Red/Blue Sun's Zenith von
* der Bib spielt, wird er nicht kopiert, auch wenn der Effekt auf dem Stack
* sichtbar ist.
*
* Meine Theorie ist, dass die Kopie beim in die Bib mischen den Originalen
* nimmt und er daher nicht mehr dem Stack ist um selbst verrechnet zu
* werden
*
*/
@Test
public void testCopyZenith() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
// Play with the top card of your library revealed.
// You may cast the top card of your library if it's an instant or sorcery card.
// Whenever you cast an instant or sorcery spell from your library, copy it. You may choose new targets for the copy.
addCard(Zone.BATTLEFIELD, playerA, "Melek, Izzet Paragon");
// Red Sun's Zenith deals X damage to target creature or player.
// If a creature dealt damage this way would die this turn, exile it instead.
// Shuffle Red Sun's Zenith into its owner's library.
addCard(Zone.LIBRARY, playerA, "Red Sun's Zenith"); // {X}{R}
skipInitShuffling();
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Red Sun's Zenith", playerB);
setChoice(playerA, "X=4");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Red Sun's Zenith", 0);
assertLife(playerA, 20);
assertLife(playerB, 12);
}
}

View file

@ -90,17 +90,21 @@ public class OblivionRingTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
addCard(Zone.HAND, playerA, "Oblivion Ring");
addCard(Zone.BATTLEFIELD, playerA, "Jace Beleren");
// Exile target artifact or enchantment.
addCard(Zone.HAND, playerA, "Revoke Existence");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-1: Target player draws one card", playerA);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-1: Target player draws a card", playerA);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oblivion Ring");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Revoke Existence", "Oblivion Ring");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "-1: Target player draws one card", playerA);
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "-1: Target player draws a card", playerA);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertExileCount("Oblivion Ring", 1);
assertGraveyardCount(playerA, "Revoke Existence", 1);
assertPermanentCount(playerA, "Oblivion Ring", 0);
assertGraveyardCount(playerA, "Jace Beleren", 0);
assertPermanentCount(playerA, "Jace Beleren", 1); // returns back
assertHandCount(playerA, 2); // can use ability twice
}

View file

@ -5,7 +5,6 @@
*/
package org.mage.test.cards.triggers;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
@ -16,7 +15,6 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*
* @author LevelX2
*/
public class WorldgorgerDragonTest extends CardTestPlayerBase {
/**
@ -25,20 +23,23 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
@Test
public void testDisabledEffectOnChangeZone() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6);
// Flying
// Trample
// When Worldgorger Dragon enters the battlefield, exile all other permanents you control.
// When Worldgorger Dragon leaves the battlefield, return the exiled cards to the battlefield under their owners' control.
addCard(Zone.HAND, playerA, "Worldgorger Dragon");
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
addCard(Zone.BATTLEFIELD, playerA, "Gerrard's Battle Cry", 1);
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
// Destroy target nonartifact, nonblack creature. It can't be regenerated.
addCard(Zone.HAND, playerB, "Terror", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Worldgorger Dragon");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Terror", "Worldgorger Dragon");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
@ -47,30 +48,35 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Worldgorger Dragon", 1);
assertGraveyardCount(playerB, "Terror", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPermanentCount(playerA, "Gerrard's Battle Cry", 1);
}
/**
1. Cast Animate Dead, targeting the Dragon
2. Dragon comes into play, it's ability goes on the stack.
3. The ability resolves, and all my other permanents leave play
4. Since Animate Dead left play, Dragon goes to the graveyard
5. Since the Dragon left play, the land and Animate Dead return to play. Animate Dead triggers, targeting the Dragon.
6. In response to Animate Dead's ability going on the stack, tap the lands for mana.
7. Animate Dead resolves, Dragon comes into play, everything else leaves play.
8. Steps 4-7 repeat endlessly. Your mana pool fills.
9. You can interrupt the sequence to play an instant.
/*
* 1. Cast Animate Dead, targeting the Dragon
* 2. Dragon comes into play, it's ability goes on the stack.
* 3. The ability resolves, and all my other permanents leave play
* 4. Since Animate Dead left play, Dragon goes to the graveyard
* 5. Since the Dragon left play, the land and Animate Dead return to play. Animate Dead triggers, targeting the Dragon.
* 6. In response to Animate Dead's ability going on the stack, tap the lands for mana.
* 7. Animate Dead resolves, Dragon comes into play, everything else leaves play.
* 8. Steps 4-7 repeat endlessly. Your mana pool fills.
* 9. You can interrupt the sequence to play an instant.
*/
@Test
public void testWithAnimateDead() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// When Worldgorger Dragon enters the battlefield, exile all other permanents you control.
// When Worldgorger Dragon leaves the battlefield, return the exiled cards to the battlefield under their owners' control.
addCard(Zone.GRAVEYARD, playerA, "Worldgorger Dragon", 1);
// Enchant creature card in a graveyard
// When Animate Dead enters the battlefield, if it's on the battlefield, it loses "enchant creature card in a graveyard"
// and gains "enchant creature put onto the battlefield with Animate Dead." Return enchanted creature card to the battlefield
// under your control and attach Animate Dead to it. When Animate Dead leaves the battlefield, that creature's controller sacrifices it.
// Enchanted creature gets -1/-0.
addCard(Zone.HAND, playerA, "Animate Dead");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
// Instant {X}{R}{R}
@ -78,10 +84,9 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Volcanic Geyser", 1);
// When Staunch Defenders enters the battlefield, you gain 4 life.
addCard(Zone.BATTLEFIELD, playerA, "Staunch Defenders", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Animate Dead", "Worldgorger Dragon");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
@ -107,43 +112,44 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB, 22);
setChoice(playerA, "X=20");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertLife(playerA, 20);
assertLife(playerA, 44);
assertLife(playerB, 0);
assertGraveyardCount(playerA, "Volcanic Geyser", 1);
}
/**
* v9: Worldgorger Dragon + Animate Dead is still acting up (yey complex rules interactions!).
* The first time you return Animate Dead from Worldgorger's exile, it works like it's supposed
* to. You have to pick a creature, and it brings it back. But if you pick Worldgorger Dragon
* again, it allows you to not pick a creature, and regardless of whether you choose to skip or pick
* a different creature, it always returns the first creature you picked. Kind of hard to explain,
* but here's how to reproduce:
*
* 1) Cast Animate Dead, targeting Worldgorger Dragon
* 2) Worldgorger Dragon will exile Animate Dead, killing the dragon and returning the permanents
* 3) Select Worldgorger again
* 4) Step 2 repeats
* 5) Attempt to select a different creature. Worldgorger Dragon is returned instead.
*
* v9: Worldgorger Dragon + Animate Dead is still acting up (yey complex
* rules interactions!). The first time you return Animate Dead from
* Worldgorger's exile, it works like it's supposed to. You have to pick a
* creature, and it brings it back. But if you pick Worldgorger Dragon
* again, it allows you to not pick a creature, and regardless of whether
* you choose to skip or pick a different creature, it always returns the
* first creature you picked. Kind of hard to explain, but here's how to
* reproduce:
*
* 1) Cast Animate Dead, targeting Worldgorger Dragon 2) Worldgorger Dragon
* will exile Animate Dead, killing the dragon and returning the permanents
* 3) Select Worldgorger again 4) Step 2 repeats 5) Attempt to select a
* different creature. Worldgorger Dragon is returned instead.
*
*/
@Test
public void testWithAnimateDeadDifferentTargets() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// When Worldgorger Dragon enters the battlefield, exile all other permanents you control.
// When Worldgorger Dragon leaves the battlefield, return the exiled cards to the battlefield under their owners' control.
addCard(Zone.GRAVEYARD, playerA, "Worldgorger Dragon", 1);
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion", 1);
// When Animate Dead enters the battlefield, if it's on the battlefield, it loses "enchant creature card in a graveyard"
// and gains "enchant creature put onto the battlefield with Animate Dead." Return enchanted creature card to the battlefield
// When Animate Dead enters the battlefield, if it's on the battlefield, it loses "enchant creature card in a graveyard"
// and gains "enchant creature put onto the battlefield with Animate Dead." Return enchanted creature card to the battlefield
// under your control and attach Animate Dead to it. When Animate Dead leaves the battlefield, that creature's controller sacrifices it.
addCard(Zone.HAND, playerA, "Animate Dead");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
@ -152,43 +158,42 @@ public class WorldgorgerDragonTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Volcanic Geyser", 1);
// When Staunch Defenders enters the battlefield, you gain 4 life.
addCard(Zone.BATTLEFIELD, playerA, "Staunch Defenders", 1);
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Animate Dead", "Worldgorger Dragon");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
setChoice(playerA, "Worldgorger Dragon");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
setChoice(playerA, "Silvercoat Lion");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB, 9);
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB, 9);
setChoice(playerA, "X=9");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Volcanic Geyser", 1);
assertGraveyardCount(playerA, "Worldgorger Dragon", 1);
assertGraveyardCount(playerA, "Worldgorger Dragon", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertLife(playerA, 28);
assertLife(playerB, 11);
Assert.assertEquals("Mana pool", "[]", playerA.getManaAvailable(currentGame).toString());
}
}
}

View file

@ -69,4 +69,31 @@ public class CastBRGCommanderTest extends CardTestCommanderDuelBase {
}
/**
* Activating Karn Liberated 's ultimate in an edh game (human OR ai) causes
* all the command zones to lose their generals upon the new game restart
*/
@Test
public void castCommanderAfterKarnUltimate() {
// +4: Target player exiles a card from his or her hand.
// -3: Exile target permanent.
// -14: Restart the game, leaving in exile all non-Aura permanent cards exiled with Karn Liberated. Then put those cards onto the battlefield under your control.
addCard(Zone.BATTLEFIELD, playerA, "Karn Liberated", 1);
addCard(Zone.HAND, playerA, "Silvercoat Lion", 2);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+4: Target player", playerA);
addTarget(playerA, "Silvercoat Lion");
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "+4: Target player", playerA);
addTarget(playerA, "Silvercoat Lion");
activateAbility(5, PhaseStep.PRECOMBAT_MAIN, playerA, "-14: Restart");
setStopAt(5, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Karn Liberated", 0);
assertPermanentCount(playerA, "Silvercoat Lion", 2);
assertCommandZoneCount(playerA, "Prossh, Skyraider of Kher", 1);
assertCommandZoneCount(playerB, "Ob Nixilis of the Black Oath", 1);
}
}

View file

@ -370,6 +370,7 @@ public class TestPlayer implements Player {
}
for (Ability ability : computerPlayer.getPlayable(game, true)) {
if (ability.toString().startsWith(groups[0])) {
int bookmark = game.bookmarkState();
Ability newAbility = ability.copy();
if (groups.length > 1 && !groups[1].equals("target=NO_TARGET")) {
if (!addTargets(newAbility, groups, game)) {
@ -377,9 +378,13 @@ public class TestPlayer implements Player {
break;
}
}
computerPlayer.activateAbility((ActivatedAbility) newAbility, game);
actions.remove(action);
return true;
if (computerPlayer.activateAbility((ActivatedAbility) newAbility, game)) {
actions.remove(action);
return true;
} else {
game.restoreState(bookmark, ability.getRule());
}
}
}
} else if (action.getAction().startsWith("manaActivate:")) {
@ -549,7 +554,7 @@ public class TestPlayer implements Player {
if (!choices.isEmpty()) {
for (String choice : choices) {
for (int index = 0; index < rEffects.size(); index++) {
if (choice.equals(rEffects.get(index))) {
if (choice.equals(rEffects.get(Integer.toString(index)))) {
choices.remove(choice);
return index;
}
@ -808,6 +813,30 @@ public class TestPlayer implements Player {
return computerPlayer.chooseTarget(outcome, target, source, game);
}
@Override
public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
if (!targets.isEmpty()) {
for (String targetDefinition : targets) {
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
for (Card card : cards.getCards(game)) {
if (card.getName().equals(targetName) && !target.getTargets().contains(card.getId())) {
target.add(card.getId(), game);
targetFound = true;
break;
}
}
}
if (targetFound) {
targets.remove(targetDefinition);
return true;
}
}
}
return computerPlayer.chooseTarget(outcome, cards, target, source, game);
}
@Override
public TriggeredAbility chooseTriggeredAbility(List<TriggeredAbility> abilities, Game game) {
if (!choices.isEmpty()) {
@ -1770,21 +1799,6 @@ public class TestPlayer implements Player {
return computerPlayer.moveCardToExileWithInfo(card, exileId, exileName, sourceId, game, fromZone, withName);
}
@Override
public boolean putOntoBattlefieldWithInfo(Card card, Game game, Zone fromZone, UUID sourceId) {
return computerPlayer.putOntoBattlefieldWithInfo(card, game, fromZone, sourceId);
}
@Override
public boolean putOntoBattlefieldWithInfo(Card card, Game game, Zone fromZone, UUID sourceId, boolean tapped) {
return computerPlayer.putOntoBattlefieldWithInfo(card, game, fromZone, sourceId, tapped);
}
@Override
public boolean putOntoBattlefieldWithInfo(Card card, Game game, Zone fromZone, UUID sourceId, boolean tapped, boolean facedown) {
return computerPlayer.putOntoBattlefieldWithInfo(card, game, fromZone, sourceId, tapped, facedown);
}
@Override
public boolean hasOpponent(UUID playerToCheckId, Game game) {
return computerPlayer.hasOpponent(playerToCheckId, game);
@ -1886,11 +1900,6 @@ public class TestPlayer implements Player {
return computerPlayer.choose(outcome, cards, target, game);
}
@Override
public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
return computerPlayer.chooseTarget(outcome, cards, target, source, game);
}
@Override
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
return computerPlayer.chooseTargetAmount(outcome, target, source, game);
@ -1946,6 +1955,31 @@ public class TestPlayer implements Player {
return computerPlayer.scry(value, source, game);
}
@Override
public boolean moveCards(Card card, Zone toZone, Ability source, Game game) {
return computerPlayer.moveCards(card, toZone, source, game);
}
@Override
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
return computerPlayer.moveCards(card, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
}
@Override
public boolean moveCards(Cards cards, Zone toZone, Ability source, Game game) {
return computerPlayer.moveCards(cards, toZone, source, game);
}
@Override
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game) {
return computerPlayer.moveCards(cards, toZone, source, game);
}
@Override
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) {
return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
}
public void setAIPlayer(boolean AIPlayer) {
this.AIPlayer = AIPlayer;
}

View file

@ -283,7 +283,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
if (card == null) {
throw new IllegalArgumentException("[TEST] Couldn't find a card: " + cardName);
}
PermanentCard p = new PermanentCard(card, null, currentGame);
PermanentCard p = new PermanentCard(card, player.getId(), currentGame);
p.setTapped(tapped);
getBattlefieldCards(player).add(p);
}
@ -533,10 +533,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
if (flag) {
Assert.assertTrue("No such ability=" + ability.toString() + ", player=" + player.getName()
+ ", cardName" + cardName, found.getAbilities().containsRule(ability));
+ ", cardName" + cardName, found.getAbilities(currentGame).containsRule(ability));
} else {
Assert.assertFalse("Card shouldn't have such ability=" + ability.toString() + ", player=" + player.getName()
+ ", cardName" + cardName, found.getAbilities().containsRule(ability));
+ ", cardName" + cardName, found.getAbilities(currentGame).containsRule(ability));
}
}
@ -574,7 +574,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
}
}
Assert.assertEquals("(Battlefield) Card counts for " + player.getName() + " are not equal (" + cardName + ")", count, actualCount);
Assert.assertEquals("(Battlefield) Permanents counts for " + player.getName() + " are not equal (" + cardName + ")", count, actualCount);
}
@Override
@ -614,14 +614,18 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertCounterCount(String cardName, CounterType type, int count) throws AssertionError {
this.assertCounterCount(null, cardName, type, count);
}
public void assertCounterCount(Player player, String cardName, CounterType type, int count) throws AssertionError {
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName)) {
if (permanent.getName().equals(cardName) && (player == null || permanent.getControllerId().equals(player.getId()))) {
found = permanent;
break;
}
}
Assert.assertNotNull("There is no such permanent on the battlefield, cardName=" + cardName, found);
Assert.assertNotNull("There is no such permanent " + (player == null ? "" : "for player " + player.getName()) + " on the battlefield, cardName=" + cardName, found);
Assert.assertEquals("(Battlefield) Counter counts are not equal (" + cardName + ":" + type + ")", count, found.getCounters().getCount(type));
}
@ -990,6 +994,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
player.addAction(turnNum, step, "activate:" + ability + "$target=" + targetName);
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String targetName, String spellOnStack) {
this.activateAbility(turnNum, step, player, ability, targetName, spellOnStack, StackClause.WHILE_ON_STACK);
}
/**
*
* @param turnNum
@ -1000,13 +1008,13 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* NO_TARGET
* @param spellOnStack
*/
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String targetName, String spellOnStack) {
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String targetName, String spellOnStack, StackClause clause) {
StringBuilder sb = new StringBuilder("activate:").append(ability);
if (targetName != null && !targetName.isEmpty()) {
sb.append("$target=").append(targetName);
}
if (spellOnStack != null && !spellOnStack.isEmpty()) {
sb.append("$spellOnStack=").append(spellOnStack);
sb.append("$").append(StackClause.WHILE_ON_STACK.equals(clause) ? "" : "!").append("spellOnStack=").append(spellOnStack);
}
player.addAction(turnNum, step, sb.toString());
}