mirror of
https://github.com/magefree/mage.git
synced 2026-01-10 04:42:07 -08:00
Merge branch 'master' of https://github.com/magefree/mage
Conflicts: Mage.Sets/src/mage/sets/avacynrestored/CavernOfSouls.java Mage.Sets/src/mage/sets/shadowmoor/ManaReflection.java
This commit is contained in:
commit
5c746e8ec2
137 changed files with 4932 additions and 633 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue