Conflicts:
	Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java
	Mage.Sets/src/mage/sets/shadowmoor/ManaReflection.java
This commit is contained in:
betasteward 2015-03-01 22:02:33 -05:00
commit 5c746e8ec2
137 changed files with 4932 additions and 633 deletions

View file

@ -192,6 +192,9 @@ public class CursesTest extends CardTestPlayerBase {
@Test
public void testCurseOfMisfortune1() {
removeAllCardsFromLibrary(playerA);
// At the beginning of your upkeep, you may search your library for a Curse card that doesn't have the same name as a
// Curse attached to enchanted player, put it onto the battlefield attached to that player, then shuffle your library.
addCard(Zone.LIBRARY, playerA, "Curse of Misfortunes", 2);
addCard(Zone.HAND, playerA, "Curse of Misfortunes");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);

View file

@ -231,5 +231,45 @@ public class BestowTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Nyxborn Rollicker", 0);
assertGraveyardCount(playerA, "Nyxborn Rollicker", 1);
}
}
/**
* Test that CMC of a spell cast with bestowed is correct
* Disdainful Stroke doesn't check converted mana cost correctly. Opponent was
* able to use it to counter a Hypnotic Siren cast with Bestow.
*/
@Test
public void bestowCheckForCorrectCMC() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 7);
// Enchantment Creature Siren
// 1/1
// Bestow {5}{U}{U} (If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.)
// Flying
// You control enchanted creature.
// Enchanted creature gets +1/+1 and has flying.
addCard(Zone.HAND, playerA, "Hypnotic Siren");
// Instant {1}{U}
// Counter target spell with converted mana cost 4 or greater.
addCard(Zone.HAND, playerB, "Disdainful Stroke");
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hypnotic Siren using bestow", "Silvercoat Lion");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Disdainful Stroke", "Hypnotic Siren");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
//
assertHandCount(playerA, "Hypnotic Siren", 0);
assertGraveyardCount(playerA, "Hypnotic Siren", 0);
assertHandCount(playerB, "Disdainful Stroke", 1);
assertPermanentCount(playerA, "Hypnotic Siren", 1);
// because cast with bestow, Boon Satyr may not be tapped
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPowerToughness(playerA, "Silvercoat Lion", 3,3);
}
}

View file

@ -0,0 +1,85 @@
/*
* 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.keywords;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class EchoTest extends CardTestPlayerBase {
/*
* I flickered an Avalanche Riders with its Echo trigger on the stack with Restoration Angel.
* When the trigger resolved, my Riders was sacrificed, even though it should have been
* considered a new permanent.
*/
@Test
public void testEchoTriggerChecksIdentity() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
// Avalanche Riders Creature - Human Nomad 2/2
// Haste
// Echo (At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep, sacrifice it unless you pay its echo cost.)
// When Avalanche Riders enters the battlefield, destroy target land.
addCard(Zone.HAND, playerA, "Avalanche Riders");
// Restoration Angel {3}{W}
// Flash
// Flying
// When Restoration Angel enters the battlefield, you may exile target non-Angel creature you control,
// then return that card to the battlefield under your control.
addCard(Zone.HAND, playerA, "Restoration Angel");
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Avalanche Riders");
castSpell(3, PhaseStep.UPKEEP, playerA, "Restoration Angel", null, "Echo {3}{R} <i>(At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep, sacrifice it unless you pay its echo cost.)</i>");
addTarget(playerA, "Avalanche Riders");
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertLife(playerB, 20);
assertPermanentCount(playerA, "Avalanche Riders", 1);
assertPermanentCount(playerA, "Restoration Angel", 1);
assertPermanentCount(playerB, "Mountain", 0);
}
}

View file

@ -76,4 +76,109 @@ public class UndyingTest extends CardTestPlayerBase {
assertPowerToughness(playerA, "Elite Vanguard", 3, 2);
}
/**
* Tests "Threads of Disloyalty enchanting Strangleroot Geist: after geist died it returns to the bf under opponent's control."
*/
@Test
public void testUndyingControlledReturnsToOwner() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
// Strangleroot Geist 2/1
// Haste
// Undying
// (When it 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, "Strangleroot Geist");
addCard(Zone.HAND, playerA, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
// Threads of Disloyalty {1}{U}{U}
// Enchant creature with converted mana cost 2 or less
// You control enchanted creature.
addCard(Zone.HAND, playerB, "Threads of Disloyalty");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Strangleroot Geist");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Threads of Disloyalty", "Strangleroot Geist");
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Strangleroot Geist");
setStopAt(2, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerB, "Threads of Disloyalty", 1);
assertGraveyardCount(playerA, "Lightning Bolt",1);
assertPermanentCount(playerB, "Strangleroot Geist", 0);
assertPermanentCount(playerA, "Strangleroot Geist", 1);
assertPowerToughness(playerA, "Strangleroot Geist", 3, 2);
}
/**
* Tests "Target creature with Undying will be exiled by Anafenza before it returns to battlefield
*
* Anafenza the foremost doesn't exile an undying creature when dying at the same time as
* that undying one. The undying comes back to the field when he shouldn't.
*/
@Test
public void testReplacementEffectPreventsReturnOfUndying() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// Butcher Ghoul
// Creature - Zombie, 1/1 {1}{B}
// 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");
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
addCard(Zone.HAND, playerB, "Lightning Bolt");
// Anafenza, the Foremost
// Whenever Anafenza, the Foremost attacks, put a +1/+1 counter on another target tapped creature you control.
// If a creature card would be put into an opponent's graveyard from anywhere, exile it instead.
addCard(Zone.BATTLEFIELD, playerB, "Anafenza, the Foremost");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Butcher Ghoul");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Butcher Ghoul");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerB, "Anafenza, the Foremost", 1);
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertPermanentCount(playerA, "Butcher Ghoul", 0);
assertExileCount("Butcher Ghoul", 1);
}
/**
* Tests "Target creature with Undying will be exiled by Anafenza before it returns to battlefield
* if both leave the battlefield at the same time
*
* Anafenza the foremost doesn't exile an undying creature when dying at the same time as
* that undying one. The undying comes back to the field when he shouldn't.
*/
@Test
public void testReplacementEffectPreventsReturnOfUndyingWrath() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// Butcher Ghoul
// Creature - Zombie, 1/1 {1}{B}
// 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");
addCard(Zone.BATTLEFIELD, playerB, "Plains", 4);
// Destroy all creatures. They can't be regenerated.
addCard(Zone.HAND, playerB, "Wrath of God");
// Anafenza, the Foremost
// Whenever Anafenza, the Foremost attacks, put a +1/+1 counter on another target tapped creature you control.
// If a creature card would be put into an opponent's graveyard from anywhere, exile it instead.
addCard(Zone.BATTLEFIELD, playerB, "Anafenza, the Foremost");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Butcher Ghoul");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Wrath of God");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, "Anafenza, the Foremost", 1);
assertGraveyardCount(playerB, "Wrath of God", 1);
assertPermanentCount(playerA, "Butcher Ghoul", 0);
assertExileCount("Butcher Ghoul", 1);
}
}

View file

@ -11,7 +11,7 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
public class MorticianBeetleTest extends CardTestPlayerBase {
/**
* Checks that pro black can still be sacrificed
* Checks that creature with protection black can still be sacrificed
*/
@Test
public void testSacrifice() {

View file

@ -185,5 +185,42 @@ public class CavernOfSoulsTest extends CardTestPlayerBase {
// 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.
*
*/
@Test
public void testCastWithColorlessManaCanBeCountered() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.HAND, playerA, "Cavern of Souls");
// Sorcery {X}{W}{W}
// Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for or one mana of that creature's color.)
// Return X target creature cards with converted mana cost 2 or less from your graveyard to the battlefield.
addCard(Zone.HAND, playerA, "Return to the Ranks");
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion");
// {1}{U} Remove Soul - Counter target creature spell.
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);
execute();
// check it was countered
assertGraveyardCount(playerA, "Return to the Ranks", 1);
assertGraveyardCount(playerB, "Counterspell", 1);
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
assertPermanentCount(playerA, "Silvercoat Lion", 0);
}
}

View file

@ -531,7 +531,7 @@ public class TestPlayer extends ComputerPlayer {
boolean result = true;
for (int i = 1; i < groups.length; i++) {
String group = groups[i];
if (group.startsWith("spellOnStack") || group.startsWith("spellOnTopOfStack") || group.startsWith("!spellOnStack")) {
if (group.startsWith("spellOnStack") || group.startsWith("spellOnTopOfStack") || group.startsWith("!spellOnStack") || group.startsWith("target=null") ) {
break;
}
if (ability instanceof SpellAbility && ((SpellAbility) ability).getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) {

View file

@ -548,6 +548,25 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
Assert.assertEquals("(Battlefield) Tapped state is not equal (" + cardName + ")", tapped, found.isTapped());
}
/**
* Assert whether a permanent is attacking or not
*
* @param cardName Name of the permanent that should be checked.
* @param attacking Whether the permanent is attacking or not
*/
public void assertAttacking(String cardName, boolean attacking) throws AssertionError {
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getLogName().equals(cardName)) {
found = permanent;
}
}
Assert.assertNotNull("There is no such permanent on the battlefield, cardName=" + cardName, found);
Assert.assertEquals("(Battlefield) Attacking state is not equal (" + cardName + ")", attacking, found.isAttacking());
}
/**
* Assert card count in player's hand.
*