Merge branch 'master' into feature/implement-spdr-piloted-by-peni

This commit is contained in:
theelk801 2025-09-05 18:15:31 -04:00
commit 04bc7b8b2a
1185 changed files with 32207 additions and 8890 deletions

View file

@ -116,7 +116,7 @@ public class CopyAITest extends CardTestPlayerBaseWithAIHelps {
//
addCard(Zone.GRAVEYARD, playerB, "Balduvian Bears", 1); // 2/2
// copy (AI must choose most valueable permanent - own)
// copy (AI must choose most valuable permanent - own)
aiPlayPriority(1, PhaseStep.PRECOMBAT_MAIN, playerA);
setStopAt(1, PhaseStep.END_TURN);

View file

@ -20,8 +20,9 @@ import java.util.List;
* <p>
* TODO: add tests and implement best choice selection on timeout
* (AI must make any good/bad choice on timeout with game log - not a skip)
*
* TODO: AI do not support game sims from triggered (it's run, but do not use results)
* <p>
* TODO: AI do not support game simulations for target options in triggered
*
* @author JayDi85
*/
@ -213,4 +214,30 @@ public class SimulationPerformanceAITest extends CardTestPlayerBaseAI {
// 4 damage to x2 bears and 1 damage to damaged bear
runManyTargetOptionsInActivate("5 target creatures with one damaged", 5, 3, true, 20);
}
@Test
@Ignore // TODO: enable and fix random error with too many sim nodes (depends on machine performance?)
public void test_ElderDeepFiend_TooManyUpToChoices() {
// bug: game freeze with 100% CPU usage
// https://github.com/magefree/mage/issues/9518
int cardsCount = 2; // 2+ cards will generate too much target options for simulations
// Boulderfall deals 5 damage divided as you choose among any number of targets.
// Flash
// Emerge {5}{U}{U} (You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's mana value.)
// When you cast this spell, tap up to four target permanents.
addCard(Zone.HAND, playerA, "Elder Deep-Fiend", cardsCount); // {8}
addCard(Zone.BATTLEFIELD, playerA, "Island", 8 * cardsCount);
//
addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears", 2);
addCard(Zone.BATTLEFIELD, playerB, "Kitesail Corsair", 2);
addCard(Zone.BATTLEFIELD, playerB, "Alpha Tyrranax", 2);
addCard(Zone.BATTLEFIELD, playerB, "Abbey Griffin", 2);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Elder Deep-Fiend", cardsCount); // ai must cast it
}
}

View file

@ -28,6 +28,8 @@ public class SimulationStabilityAITest extends CardTestPlayerBaseWithAIHelps {
@Before
public void prepare() {
// WARNING, for some reason java 8 sometime can't compile and run test with updated AI settings, so it's ok to freeze on it
// comment it to enable AI code debug
Assert.assertFalse("AI stability tests must be run under release config", ComputerPlayer.COMPUTER_DISABLE_TIMEOUT_IN_GAME_SIMULATIONS);
}

View file

@ -0,0 +1,84 @@
package org.mage.test.AI.basic;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBaseWithAIHelps;
/**
* Make sure AI can simulate priority with triggers resolve
*
* @author JayDi85
*/
public class SimulationTriggersAITest extends CardTestPlayerBaseWithAIHelps {
@Test
@Ignore
// TODO: trigger's target options supported on priority sim, but do not used for some reason
// see addTargetOptions, node.children, ComputerPlayer6->targets, etc
public void test_DeepglowSkate_MustBeSimulated() {
// make sure targets choosing on trigger use same game sims and best results
// When Deepglow Skate enters the battlefield, double the number of each kind of counter on any number
// of target permanents.
addCard(Zone.HAND, playerA, "Deepglow Skate", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
//
addCard(Zone.BATTLEFIELD, playerA, "Ajani, Adversary of Tyrants", 1); // x4 loyalty
addCard(Zone.BATTLEFIELD, playerA, "Ajani, Caller of the Pride", 1); // x4 loyalty
//
// This creature enters with a -1/-1 counter on it.
addCard(Zone.BATTLEFIELD, playerA, "Bloodied Ghost", 1); // 3/3
//
// Players can't activate planeswalkers' loyalty abilities.
addCard(Zone.BATTLEFIELD, playerA, "The Immortal Sun", 1); // disable planeswalkers usage by AI
// AI must cast boost and ignore doubling of -1/-1 counters on own creatures due bad score
aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, playerA);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Deepglow Skate", 1);
assertCounterCount(playerA, "Ajani, Adversary of Tyrants", CounterType.LOYALTY, 4 * 2);
assertCounterCount(playerA, "Ajani, Caller of the Pride", CounterType.LOYALTY, 4 * 2);
assertCounterCount(playerA, "Bloodied Ghost", CounterType.M1M1, 1); // make sure AI will not double bad counters
}
@Test
public void test_DeepglowSkate_PerformanceOnTooManyChoices() {
// bug: game freeze with 100% CPU usage
// https://github.com/magefree/mage/issues/9438
int cardsCount = 2; // 2+ cards will generate too much target options for simulations
int boostMultiplier = (int) Math.pow(2, cardsCount);
// When Deepglow Skate enters the battlefield, double the number of each kind of counter on any number
// of target permanents.
addCard(Zone.HAND, playerA, "Deepglow Skate", cardsCount); // {4}{U}
addCard(Zone.BATTLEFIELD, playerA, "Island", 5 * cardsCount);
//
addCard(Zone.BATTLEFIELD, playerA, "Ajani, Adversary of Tyrants", 1); // x4 loyalty
addCard(Zone.BATTLEFIELD, playerA, "Ajani, Caller of the Pride", 1); // x4 loyalty
addCard(Zone.BATTLEFIELD, playerB, "Ajani Goldmane", 1); // x4 loyalty
addCard(Zone.BATTLEFIELD, playerB, "Ajani, Inspiring Leader", 1); // x5 loyalty
//
// Players can't activate planeswalkers' loyalty abilities.
addCard(Zone.BATTLEFIELD, playerA, "The Immortal Sun", 1); // disable planeswalkers usage by AI
// AI must cast multiple booster spells and double only own counters and only good
aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, playerA);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Deepglow Skate", cardsCount);
assertCounterCount(playerA, "Ajani, Adversary of Tyrants", CounterType.LOYALTY, 4 * boostMultiplier);
assertCounterCount(playerA, "Ajani, Caller of the Pride", CounterType.LOYALTY, 4 * boostMultiplier);
assertCounterCount(playerB, "Ajani Goldmane", CounterType.LOYALTY, 4);
assertCounterCount(playerB, "Ajani, Inspiring Leader", CounterType.LOYALTY, 5);
}
}

View file

@ -69,6 +69,7 @@ public class ValakutTheMoltenPinnacleTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scapeshift");
setChoice(playerA, "Forest^Forest^Forest^Forest^Forest^Forest"); // to sac
setChoice(playerA, TestPlayer.CHOICE_SKIP);
addTarget(playerA, "Mountain^Mountain^Mountain^Mountain^Mountain^Mountain"); // to search
setChoice(playerA, "Whenever a Mountain", 6 - 1); // x6 triggers from valakut
addTarget(playerA, playerB, 6); // to deal damage

View file

@ -337,4 +337,20 @@ public class BargainTest extends CardTestPlayerBase {
assertLife(playerA, 20 + 3);
assertTappedCount("Forest", true, 7);
}
@Test
public void testCantBargainWithRestriction() {
setStrictChooseMode(true);
// Players cant pay life or sacrifice nonland permanents to cast spells or activate abilities.
addCard(Zone.BATTLEFIELD, playerB, "Yasharn, Implacable Earth");
addCard(Zone.HAND, playerA, glutton);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
addCard(Zone.BATTLEFIELD, playerA, relic);
checkPlayableAbility("restricted by Yasharn", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hamlet Glutton", false);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
}
}

View file

@ -61,32 +61,37 @@ public class CumulativeUpkeepTest extends CardTestPlayerBase {
// Whenever Kor Celebrant or another creature you control enters, you gain 1 life.
addCard(Zone.HAND, playerB, "Kor Celebrant", 1); // Creature {2}{W}
addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
//
// Cumulative upkeep {2}
// When Illusions of Grandeur enters the battlefield, you gain 20 life.
// At the beginning of your upkeep, put an age counter on this permanent,
// then sacrifice it unless you pay its upkeep cost for each age counter on it.
// When Illusions of Grandeur leaves the battlefield, you lose 20 life.
addCard(Zone.HAND, playerA, "Illusions of Grandeur"); // Enchantment {3}{U}
// At the beginning of your upkeep, you may exchange control of target nonland permanent you control and target nonland permanent an opponent controls with an equal or lesser converted mana cost.
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
//
// At the beginning of your upkeep, you may exchange control of target nonland permanent you control
// and target nonland permanent an opponent controls with an equal or lesser converted mana cost.
addCard(Zone.HAND, playerA, "Puca's Mischief"); // Enchantment {3}{U}
// turn 1, 2 - prepare cumulative upkeep and gain life triggers
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Illusions of Grandeur");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Kor Celebrant");
// Illusions of Grandeur - CumulativeUpkeepAbility: Cumulative upkeep {2}
setChoice(playerA, true); // Pay {2}?
// turn 3 - upkeep trigger and prepare control card
setChoice(playerA, true); // use upkeep cost {2}
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Puca's Mischief");
setChoice(playerA, "Cumulative upkeep"); // Triggered list (total 2) which trigger goes first on the stack
addTarget(playerA, "Illusions of Grandeur"); // Own target permanent of Puca's Mischief
addTarget(playerA, "Kor Celebrant"); // Opponent's target permanent of Puca's Mischief
setChoice(playerA, true); // At the beginning of your upkeep, you may exchange control of target nonland permanent you control and target nonland permanent an opponent controls with an equal or lesser converted mana cost.
setChoice(playerA, false); // Pay {2}{2}?
// turn 5 - multiple upkeep triggers
// first put upkeep, then put change control - so control will be resolved before upkeep cost
setChoice(playerA, "Cumulative upkeep");
// resolve change control first
addTarget(playerA, "Illusions of Grandeur"); // own target
addTarget(playerA, "Kor Celebrant"); // opponent target
setChoice(playerA, true); // yes, resolve change control
// resolve upkeep
setChoice(playerA, false); // no, do not pay upkeep cost
checkPermanentCounters("Age counters", 5, PhaseStep.PRECOMBAT_MAIN, playerB, "Illusions of Grandeur", CounterType.AGE, 2);

View file

@ -55,7 +55,7 @@ public class DisguiseTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dog Walker using Disguise");
runCode("face up on stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
Assert.assertEquals("stack, server - can't find spell", 1, currentGame.getStack().size());
SpellAbility spellAbility = (SpellAbility) currentGame.getStack().getFirst().getStackAbility();
SpellAbility spellAbility = (SpellAbility) currentGame.getStack().getFirstOrNull().getStackAbility();
Assert.assertEquals("stack, server - can't find spell", "Cast Dog Walker using Disguise", spellAbility.getName());
CardView spellView = getGameView(playerA).getStack().values().stream().findFirst().orElse(null);
Assert.assertNotNull("stack, client: can't find spell", spellView);

View file

@ -40,7 +40,7 @@ public class DisturbTest extends CardTestPlayerBase {
checkStackObject("on stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hook-Haunt Drifter using Disturb", 1);
runCode("check stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
// Stack must contain another card side, so spell/card characteristics must be diff from main side (only mana value is same)
Spell spell = (Spell) game.getStack().getFirst();
Spell spell = (Spell) game.getStack().getFirstOrNull();
Assert.assertEquals("Hook-Haunt Drifter", spell.getName());
Assert.assertEquals(1, spell.getCardType(game).size());
Assert.assertEquals(CardType.CREATURE, spell.getCardType(game).get(0));
@ -91,7 +91,7 @@ public class DisturbTest extends CardTestPlayerBase {
checkStackObject("on stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Waildrifter using Disturb", 1);
runCode("check stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
// Stack must contain another card side, so spell/card characteristics must be diff from main side (only mana value is same)
Spell spell = (Spell) game.getStack().getFirst();
Spell spell = (Spell) game.getStack().getFirstOrNull();
Assert.assertEquals("Waildrifter", spell.getName());
Assert.assertEquals(1, spell.getCardType(game).size());
Assert.assertEquals(CardType.CREATURE, spell.getCardType(game).get(0));
@ -187,7 +187,7 @@ public class DisturbTest extends CardTestPlayerBase {
// cast with disturb
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hook-Haunt Drifter using Disturb");
runCode("check stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
Spell spell = (Spell) game.getStack().getFirst();
Spell spell = (Spell) game.getStack().getFirstOrNull();
Assert.assertEquals("mana value must be from main side", 2, spell.getManaValue());
Assert.assertEquals("mana cost to pay must be modified", "{U}", spell.getSpellAbility().getManaCostsToPay().getText());
});

View file

@ -4,6 +4,7 @@ package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -27,7 +28,9 @@ public class EscalateTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Savage Alliance", "mode=2Silvercoat Lion");
setModeChoice(playerA, "2");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
@ -52,7 +55,9 @@ public class EscalateTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Collective Defiance", playerB);
setModeChoice(playerA, "3"); // deal 3 dmg to opponent
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -78,10 +83,12 @@ public class EscalateTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Collective Defiance"); // {1}{R}{R} sorcery
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Collective Defiance", "mode=2Gaddock Teeg");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Collective Defiance", "mode=2Gaddock Teeg^mode=3targetPlayer=PlayerB");
setModeChoice(playerA, "2"); // deal 4 dmg to target creature (gaddock teeg)
setModeChoice(playerA, "3"); // deal 3 dmg to opponent
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -109,8 +116,6 @@ public class EscalateTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Collective Defiance"); // {1}{R}{R} sorcery
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Collective Defiance", "mode=2Wall of Omens");
setModeChoice(playerA, "1"); // opponent discards hand and draws that many
setModeChoice(playerA, "2"); // deal 4 dmg to target creature (Wall of Omens)
@ -120,6 +125,8 @@ public class EscalateTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Spell Queller");
addTarget(playerB, "Collective Defiance");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

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;
@ -81,4 +82,243 @@ public class ForetellTest extends CardTestPlayerBase {
assertExileCount(playerA, "Lightning Bolt", 1); // foretold card in exile
assertPowerToughness(playerA, "Dream Devourer", 2, 3); // +2 power boost from trigger due to foretell of Lightning Bolt
}
// Tests needed to check watcher scope issue (see issue #7493 and issue #13774)
private static final String scornEffigy = "Scorn Effigy"; // {3} 2/3 foretell {0}
private static final String poisonCup = "Poison the Cup"; // {1}{B}{B} instant destroy target creature
// Foretell {1}{B}, if spell was foretold, scry 2
private static final String flamespeaker = "Flamespeaker Adept"; // {2}{R} 2/3
// Whenever you scry, gets +2/+0 and first strike until end of turn
private static final String chancemetElves = "Chance-Met Elves"; // {2}{G} 3/2
// Whenever you scry, gets a +1/+1 counter, triggers once per turn
private static final String cardE = "Elite Vanguard";
private static final String cardD = "Devilthorn Fox";
private static final String cardC = "Canopy Gorger";
private static final String cardB = "Barbtooth Wurm";
private static final String cardA = "Alaborn Trooper";
private void setupLibrariesEtc() {
// make a library of 5 cards, bottom : E D C B A : top
skipInitShuffling();
removeAllCardsFromLibrary(playerA);
addCard(Zone.LIBRARY, playerA, cardE);
addCard(Zone.LIBRARY, playerA, cardD);
addCard(Zone.LIBRARY, playerA, cardC);
addCard(Zone.LIBRARY, playerA, cardB);
addCard(Zone.LIBRARY, playerA, cardA);
removeAllCardsFromLibrary(playerB);
addCard(Zone.LIBRARY, playerB, cardE);
addCard(Zone.LIBRARY, playerB, cardD);
addCard(Zone.LIBRARY, playerB, cardC);
addCard(Zone.LIBRARY, playerB, cardB);
addCard(Zone.LIBRARY, playerB, cardA);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 5);
addCard(Zone.BATTLEFIELD, playerA, flamespeaker);
addCard(Zone.BATTLEFIELD, playerB, chancemetElves);
addCard(Zone.HAND, playerA, scornEffigy);
}
@Test
public void testForetellWatcherPlayerA() {
setupLibrariesEtc();
addCard(Zone.HAND, playerA, poisonCup);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, scornEffigy);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell");
checkExileCount("foretold in exile", 2, PhaseStep.PRECOMBAT_MAIN, playerA, poisonCup, 1);
// turn 3, draw card A
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell {1}{B}", chancemetElves);
// foretold, so scry 2 (cards B and C)
addTarget(playerA, cardB); // scrying B bottom (C remains on top)
setStrictChooseMode(true);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertPowerToughness(playerA, scornEffigy, 2, 3);
assertGraveyardCount(playerA, poisonCup, 1);
assertGraveyardCount(playerB, chancemetElves, 1);
assertPowerToughness(playerA, flamespeaker, 4, 3);
}
@Test
public void testForetellWatcherPlayerB() {
setupLibrariesEtc();
addCard(Zone.HAND, playerB, poisonCup);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, scornEffigy);
// turn 2, draw card A
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Foretell");
checkExileCount("foretold in exile", 2, PhaseStep.PRECOMBAT_MAIN, playerB, poisonCup, 1);
// turn 4, draw card B
activateAbility(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Foretell {1}{B}", flamespeaker);
// foretold, so scry 2 (cards C and D)
addTarget(playerB, cardD); // scrying D bottom (C remains on top)
setStrictChooseMode(true);
setStopAt(4, PhaseStep.END_TURN);
execute();
assertPowerToughness(playerA, scornEffigy, 2, 3);
assertGraveyardCount(playerB, poisonCup, 1);
assertGraveyardCount(playerA, flamespeaker, 1);
assertPowerToughness(playerB, chancemetElves, 4, 3);
}
@Test
public void testRanar() {
skipInitShuffling();
String ranar = "Ranar the Ever-Watchful"; // 2WU 2/3 Flying Vigilance
// The first card you foretell each turn costs {0} to foretell.
// Whenever one or more cards are put into exile from your hand or a spell or ability you control exiles
// one or more permanents from the battlefield, create a 1/1 white Spirit creature token with flying.
addCard(Zone.BATTLEFIELD, playerA, ranar);
addCard(Zone.BATTLEFIELD, playerA, "Sage of the Falls"); // may loot on creature ETB
addCard(Zone.HAND, playerA, poisonCup);
addCard(Zone.LIBRARY, playerA, scornEffigy);
addCard(Zone.HAND, playerA, "Wastes");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell"); // poison the cup
setChoice(playerA, true); // yes to loot
setChoice(playerA, "Wastes"); // discard
checkExileCount("Poison the Cup foretold", 1, PhaseStep.BEGIN_COMBAT, playerA, poisonCup, 1);
checkHandCardCount("scorn effigy drawn", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, scornEffigy, 1);
checkPlayableAbility("can't foretell another for free", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Foretell", false);
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell"); // scorn effigy
setChoice(playerA, false); // no loot
setStrictChooseMode(true);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Spirit Token", 2);
assertExileCount(playerA, 2);
assertGraveyardCount(playerA, "Wastes", 1);
}
@Test
public void testCosmosCharger() {
addCard(Zone.BATTLEFIELD, playerA, "Cosmos Charger");
// Foretelling cards from your hand costs {1} less and can be done on any players turn.
addCard(Zone.HAND, playerA, scornEffigy);
addCard(Zone.BATTLEFIELD, playerA, "Wastes");
activateAbility(2, PhaseStep.UPKEEP, playerA, "Foretell");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.END_TURN);
execute();
assertExileCount(playerA, scornEffigy, 1);
}
@Test
public void testAlrund() {
String alrund = "Alrund, God of the Cosmos";
// Alrund gets +1/+1 for each card in your hand and each foretold card you own in exile.
addCard(Zone.BATTLEFIELD, playerA, alrund); // 1/1
addCard(Zone.HAND, playerA, scornEffigy);
addCard(Zone.HAND, playerA, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerA, "Cadaverous Bloom");
// Exile a card from your hand: Add {B}{B} or {G}{G}.
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "Exile a card from your hand: Add {B}{B}");
setChoice(playerA, "Lightning Bolt");
activateAbility(1, PhaseStep.BEGIN_COMBAT, playerA, "Foretell");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertHandCount(playerA, 0);
assertExileCount(playerA, scornEffigy, 1);
assertPowerToughness(playerA, alrund, 2, 2);
}
private static final String valkyrie = "Ethereal Valkyrie"; // 4/4 flying
// Whenever this creature enters or attacks, draw a card, then exile a card from your hand face down.
// It becomes foretold. Its foretell cost is its mana cost reduced by {2}.
@Test
public void testEtherealValkyrie() {
skipInitShuffling();
removeAllCardsFromLibrary(playerA);
String saga = "Niko Defies Destiny";
// I - You gain 2 life for each foretold card you own in exile.
// II - Add {W}{U}. Spend this mana only to foretell cards or cast spells that have foretell.
String crab = "Fortress Crab"; // 3U 1/6
String puma = "Stonework Puma"; // {3} 2/2
addCard(Zone.BATTLEFIELD, playerA, valkyrie);
addCard(Zone.HAND, playerA, saga);
addCard(Zone.HAND, playerA, crab);
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 5);
addCard(Zone.LIBRARY, playerA, "Wastes");
addCard(Zone.LIBRARY, playerA, puma);
attack(1, playerA, valkyrie, playerB);
addTarget(playerA, crab); // exile becomes foretold
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, saga); // gain 2 life
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
checkExileCount("crab foretold", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, crab, 1);
checkPlayableAbility("can't cast foretold same turn", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Foretell", false);
waitStackResolved(3, PhaseStep.PRECOMBAT_MAIN);
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, puma);
activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Foretell");
setStrictChooseMode(true);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertLife(playerA, 22);
assertLife(playerB, 16);
assertCounterCount(saga, CounterType.LORE, 2);
assertPowerToughness(playerA, crab, 1, 6);
assertPowerToughness(playerA, valkyrie, 4, 4);
assertPowerToughness(playerA, puma, 2, 2);
assertHandCount(playerA, 1);
assertHandCount(playerA, "Wastes", 1);
assertTappedCount("Tundra", true, 5);
}
@Test
public void testForetoldNotForetell() {
skipInitShuffling();
removeAllCardsFromLibrary(playerA);
addCard(Zone.LIBRARY, playerA, "Wastes");
addCard(Zone.LIBRARY, playerA, "Darksteel Citadel");
addCard(Zone.BATTLEFIELD, playerA, valkyrie);
addCard(Zone.BATTLEFIELD, playerA, "Dream Devourer");
addCard(Zone.HAND, playerA, "Papercraft Decoy");
attack(1, playerA, valkyrie, playerB);
addTarget(playerA, "Papercraft Decoy"); // exile becomes foretold
checkPT("Dream Devourer not boosted", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Dream Devourer", 0, 3);
checkPlayableAbility("Can't cast this turn", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Foretell", false);
checkHandCardCount("card drawn", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Darksteel Citadel", 1);
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Foretell");
setStrictChooseMode(true);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertLife(playerA, 20);
assertLife(playerB, 16);
assertPowerToughness(playerA, "Papercraft Decoy", 2, 1);
assertPowerToughness(playerA, "Dream Devourer", 0, 3);
assertHandCount(playerA, 2);
}
}

View file

@ -3,6 +3,7 @@ package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -50,6 +51,7 @@ public class KickerWithAnyNumberModesAbilityTest extends CardTestPlayerBase {
setChoice(playerA, true); // use kicker
setModeChoice(playerA, "2");
setModeChoice(playerA, "1");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
addTarget(playerA, playerA); // gain x life
addTarget(playerA, "Balduvian Bears"); // get counters
@ -79,6 +81,7 @@ public class KickerWithAnyNumberModesAbilityTest extends CardTestPlayerBase {
setChoice(playerA, true); // use kicker
setModeChoice(playerA, "2");
setModeChoice(playerA, "1");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
addTarget(playerA, playerA); // gain x life
addTarget(playerA, "Balduvian Bears"); // get counters
@ -108,6 +111,7 @@ public class KickerWithAnyNumberModesAbilityTest extends CardTestPlayerBase {
setChoice(playerA, true); // use kicker
setModeChoice(playerA, "2");
setModeChoice(playerA, "1");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
addTarget(playerA, playerA); // gain x life
addTarget(playerA, "Balduvian Bears"); // get counters
@ -139,6 +143,7 @@ public class KickerWithAnyNumberModesAbilityTest extends CardTestPlayerBase {
setChoice(playerA, true); // use kicker
setModeChoice(playerA, "2");
setModeChoice(playerA, "1");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
addTarget(playerA, playerA); // gain x life
addTarget(playerA, "Balduvian Bears"); // get counters

View file

@ -1,15 +1,12 @@
package org.mage.test.cards.abilities.keywords;
import mage.abilities.keyword.IntimidateAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class LandfallTest extends CardTestPlayerBase {
@ -26,9 +23,12 @@ public class LandfallTest extends CardTestPlayerBase {
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary");
addTarget(playerA, playerA);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary");
addTarget(playerA, playerA);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
@ -43,7 +43,6 @@ public class LandfallTest extends CardTestPlayerBase {
* If you Hive Mind an opponent's Rest for the Weary and redirect its target
* to yourself when it's not your turn, the game spits out this message and
* rolls back to before Rest for the Weary was cast.
*
*/
@Test
public void testHiveMind() {
@ -57,15 +56,17 @@ public class LandfallTest extends CardTestPlayerBase {
// Landfall - If you had a land enter the battlefield under your control this turn, that player gains 8 life instead.
addCard(Zone.HAND, playerA, "Rest for the Weary", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest for the Weary", playerA);
setChoice(playerB, true); // change target of copied spell
addTarget(playerB, playerB);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerA, "Rest for the Weary", 1);
assertLife(playerA, 24);
assertLife(playerB, 24);
}
@Test
@ -76,6 +77,7 @@ public class LandfallTest extends CardTestPlayerBase {
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -104,10 +106,14 @@ public class LandfallTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
// prepare landfall
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Searing Blaze");
addTarget(playerA, playerB);
addTarget(playerA, "Silvercoat Lion");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -133,6 +139,7 @@ public class LandfallTest extends CardTestPlayerBase {
attack(2, playerB, "Silvercoat Lion");
castSpell(2, PhaseStep.DECLARE_ATTACKERS, playerB, "Groundswell", "Silvercoat Lion");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.END_COMBAT);
execute();
@ -179,6 +186,7 @@ public class LandfallTest extends CardTestPlayerBase {
attack(2, playerB, "Silvercoat Lion");
castSpell(2, PhaseStep.DECLARE_ATTACKERS, playerB, "Groundswell", "Silvercoat Lion");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.END_COMBAT);
execute();

View file

@ -0,0 +1,89 @@
package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author TheElk801
*/
public class MayhemTest extends CardTestPlayerBase {
private static final String islanders = "Spider-Islanders";
@Test
public void testCastRegular() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
addCard(Zone.HAND, playerA, islanders);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, islanders);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, islanders, 1);
}
private static final String imp = "Putrid Imp";
@Test
public void testCastDiscarded() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerA, imp);
addCard(Zone.HAND, playerA, islanders);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Discard");
setChoice(playerA, islanders);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, islanders + " with Mayhem");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, islanders, 1);
}
@Test
public void testCantCastGraveyard() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.GRAVEYARD, playerA, islanders);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, islanders + " with Mayhem");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
try {
execute();
} catch (Throwable e) {
Assert.assertEquals(
"Should fail to be able to cast " + islanders + " with mayhem as it wasn't discarded this turn",
"Can't find ability to activate command: Cast " + islanders + " with Mayhem", e.getMessage()
);
}
}
@Test
public void testCantCastDiscardedPreviously() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerA, imp);
addCard(Zone.HAND, playerA, islanders);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Discard");
setChoice(playerA, islanders);
castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, islanders + " with Mayhem");
setStrictChooseMode(true);
setStopAt(3, PhaseStep.END_TURN);
try {
execute();
} catch (Throwable e) {
Assert.assertEquals(
"Should fail to be able to cast " + islanders + " with mayhem as it wasn't discarded this turn",
"Can't find ability to activate command: Cast " + islanders + " with Mayhem", e.getMessage()
);
}
}
}

View file

@ -16,6 +16,7 @@ import mage.filter.predicate.mageobject.*;
import mage.game.permanent.Permanent;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -319,6 +320,7 @@ public class PrototypeTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, epiphany);
setModeChoice(playerA, "3"); // Return target nonland permanent to its owner's hand.
setModeChoice(playerA, "4"); // Create a token that's a copy of target creature you control.
setModeChoice(playerA, TestPlayer.MODE_SKIP);
addTarget(playerA, automaton);
addTarget(playerA, automaton);
@ -340,6 +342,7 @@ public class PrototypeTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, epiphany);
setModeChoice(playerA, "3"); // Return target nonland permanent to its owner's hand.
setModeChoice(playerA, "4"); // Create a token that's a copy of target creature you control.
setModeChoice(playerA, TestPlayer.MODE_SKIP);
addTarget(playerA, automaton);
addTarget(playerA, automaton);

View file

@ -8,6 +8,7 @@ import mage.game.permanent.Permanent;
import mage.watchers.common.SaddledMountWatcher;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -90,6 +91,7 @@ public class SaddleTest extends CardTestPlayerBase {
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Saddle");
setChoice(playerA, bear); // to saddle cost
setChoice(playerA, TestPlayer.CHOICE_SKIP);
attack(1, playerA, possum, playerB);
setChoice(playerA, bear); // to return
@ -116,6 +118,7 @@ public class SaddleTest extends CardTestPlayerBase {
// turn 1 - saddle x2 and trigger on attack
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Saddle");
setChoice(playerA, bear + "^" + lion);
setChoice(playerA, TestPlayer.CHOICE_SKIP);
attack(1, playerA, possum, playerB);
setChoice(playerA, elf); // to return (try to choose a wrong creature, so game must not allow to choose it)

View file

@ -3,6 +3,7 @@ package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -24,8 +25,9 @@ public class SpreeTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, bear, 1);
addCard(Zone.HAND, playerA, accident);
setModeChoice(playerA, "1");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, accident, bear);
setModeChoice(playerA, "1");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
@ -41,8 +43,9 @@ public class SpreeTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1 + 1);
addCard(Zone.HAND, playerA, accident);
setModeChoice(playerA, "2");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, accident);
setModeChoice(playerA, "2");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
@ -58,9 +61,10 @@ public class SpreeTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, bear, 1);
addCard(Zone.HAND, playerA, accident);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, accident, bear);
setModeChoice(playerA, "1");
setModeChoice(playerA, "2");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, accident, bear);
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
@ -80,9 +84,10 @@ public class SpreeTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, electromancer, 1);
addCard(Zone.HAND, playerA, accident);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, accident, bear);
setModeChoice(playerA, "1");
setModeChoice(playerA, "2");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, accident, bear);
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);

View file

@ -1,6 +1,5 @@
package org.mage.test.cards.abilities.keywords;
import mage.cards.s.SpringOfEternalPeace;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.Zone;
@ -384,7 +383,6 @@ public class TransformTest extends CardTestPlayerBase {
assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2);
assertTappedCount("Plains", true, 2);
assertTappedCount("Wastes", true, 1);
}
@Test
@ -413,8 +411,32 @@ public class TransformTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Ravager of the Fells", 0);
assertPermanentCount(playerA, "Huntmaster of the Fells", 1);
assertPowerToughness(playerA, "Huntmaster of the Fells", 2, 2);
}
@Test
public void testWildsongHowlerTrigger() {
// The only Daybound/Nightbound card with a Transforms trigger on the back side
removeAllCardsFromLibrary(playerA);
addCard(Zone.HAND, playerA, "Howlpack Piper", 2); // Creature {2}{R}{G}
addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 50);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Howlpack Piper");
setChoice(playerA, true); //Transform trigger
addTarget(playerA, "Silvercoat Lion");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Howlpack Piper");
setChoice(playerA, true); //ETB trigger
addTarget(playerA, "Silvercoat Lion");
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
setStrictChooseMode(true);
execute();
assertPermanentCount(playerA, "Wildsong Howler", 2);
assertPermanentCount(playerA, "Howlpack Piper", 0); // They should be both transformed
assertHandCount(playerA, "Silvercoat Lion", 3);
assertHandCount(playerA, 3); //The two Silvercoat Lions from triggers and 1 from natural card draw
}
/**

View file

@ -5,22 +5,31 @@ import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author notgreat
*/
public class OneShotNonTargetTest extends CardTestPlayerBase {
@Test
public void YorionChooseAfterTriggerTest() {
// When Yorion enters the battlefield, exile any number of other nonland permanents you own and control.
// Return those cards to the battlefield at the beginning of the next end step.
addCard(Zone.HAND, playerA, "Yorion, Sky Nomad");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 7);
//
// When Resolute Reinforcements enters the battlefield, create a 1/1 white Soldier creature token.
addCard(Zone.HAND, playerA, "Resolute Reinforcements");
// prepare yori and put trigger on stack
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yorion, Sky Nomad");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, true);
checkPermanentCount("Yorion on battlefield", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yorion, Sky Nomad", 1);
// prepare another create before yori trigger resolve
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Resolute Reinforcements");
setChoice(playerA, "Resolute Reinforcements");
setChoice(playerA, "Resolute Reinforcements"); // 1 of 2 target for yori trigger
setChoice(playerA, TestPlayer.CHOICE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
@ -30,6 +39,7 @@ public class OneShotNonTargetTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Resolute Reinforcements", 1);
assertTappedCount("Plains", true, 7);
}
@Test
public void NonTargetAdjusterTest() {
addCard(Zone.HAND, playerA, "Temporal Firestorm");
@ -52,21 +62,30 @@ public class OneShotNonTargetTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Python", 0);
assertGraveyardCount(playerA, "Watchwolf", 1);
}
@Test
public void ModeSelectionTest() {
addCard(Zone.HAND, playerA, "SOLDIER Military Program");
// At the beginning of combat on your turn, choose one. If you control a commander, you may choose both instead.
// * Create a 1/1 white Soldier creature token.
// * Put a +1/+1 counter on each of up to two Soldiers you control.
addCard(Zone.HAND, playerA, "SOLDIER Military Program"); // {2}{W}
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.BATTLEFIELD, playerA, "Squire", 1);
addCard(Zone.BATTLEFIELD, playerA, "Squire", 1); // 1/2
// prepare mode ability
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "SOLDIER Military Program");
// turn 1 combat - put counter
setModeChoice(playerA, "2");
setChoice(playerA, "Squire");
setChoice(playerA, TestPlayer.CHOICE_SKIP);
// turn 3 combat - create token
setModeChoice(playerA, "1");
// turn 5 combat - put counter
setModeChoice(playerA, "2");
setChoice(playerA, "Squire^Soldier Token");
setChoice(playerA, "Squire");
setChoice(playerA, "Soldier Token");
setStrictChooseMode(true);
setStopAt(5, PhaseStep.END_TURN);

View file

@ -0,0 +1,55 @@
package org.mage.test.cards.continuous;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class AddCardSubtypeAllEffectTest extends CardTestPlayerBase {
/*
Kudo, King Among Bears
{G}{W}
Legendary Creature Bear
Other creatures have base power and toughness 2/2 and are Bears in addition to their other types.
2/2
*/
private static final String kudo = "Kudo, King Among Bears";
/*
Fugitive Wizard
{U}
Creature Human Wizard
1/1
*/
private static final String fugitive = "Fugitive Wizard";
@Test
public void testAddCardSubtypeAllEffect() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, fugitive, 3);
addCard(Zone.BATTLEFIELD, playerB, fugitive, 3);
addCard(Zone.BATTLEFIELD, playerA, kudo);
addCard(Zone.BATTLEFIELD, playerA, "Savannah", 2);
setStopAt(1, PhaseStep.END_TURN);
execute();
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(fugitive)) {
assertTrue(permanent.hasSubtype(SubType.BEAR, currentGame));
assertTrue(permanent.hasSubtype(SubType.WIZARD, currentGame));
assertTrue(permanent.hasSubtype(SubType.HUMAN, currentGame));
assertEquals(2, permanent.getPower().getModifiedBaseValue());
assertEquals(2, permanent.getToughness().getModifiedBaseValue());
}
}
assertSubtype(kudo, SubType.BEAR);
}
}

View file

@ -1,7 +1,13 @@
package org.mage.test.cards.continuous;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.permanent.token.FoodToken;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -18,12 +24,14 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*/
public class AngelOfJubilationTest extends CardTestPlayerBase {
public static final String angelOfJubilation = "Angel of Jubilation";
/**
* Tests boosting other non black creatures
*/
@Test
public void testBoost() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerA, "Devout Chaplain");
addCard(Zone.BATTLEFIELD, playerA, "Corpse Traders");
@ -33,7 +41,7 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 20);
assertPowerToughness(playerA, "Angel of Jubilation", 3, 3);
assertPowerToughness(playerA, angelOfJubilation, 3, 3);
assertPowerToughness(playerA, "Devout Chaplain", 3, 3);
assertPowerToughness(playerA, "Corpse Traders", 3, 3);
}
@ -43,14 +51,14 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
*/
@Test
public void testNoBoostOnBattlefieldLeave() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerA, "Devout Chaplain");
addCard(Zone.BATTLEFIELD, playerA, "Corpse Traders");
addCard(Zone.HAND, playerA, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Angel of Jubilation");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", angelOfJubilation);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -58,14 +66,14 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 20);
assertPermanentCount(playerA, "Angel of Jubilation", 0);
assertPermanentCount(playerA, angelOfJubilation, 0);
assertPowerToughness(playerA, "Devout Chaplain", 2, 2);
assertPowerToughness(playerA, "Corpse Traders", 3, 3);
}
@Test
public void testOpponentCantSacrificeCreatures() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerB, "Nantuko Husk");
addCard(Zone.BATTLEFIELD, playerB, "Corpse Traders");
@ -81,7 +89,7 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
@Test
public void testOpponentCanSacrificeNonCreaturePermanents() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerA, "Savannah Lions");
addCard(Zone.BATTLEFIELD, playerB, "Barrin, Master Wizard");
addCard(Zone.BATTLEFIELD, playerB, "Nantuko Husk");
@ -89,20 +97,20 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Food Chain");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}, Sacrifice a permanent: Return target creature to its owner's hand.");
addTarget(playerB, "Angel of Jubilation"); // return to hand
addTarget(playerB, angelOfJubilation); // return to hand
setChoice(playerB, "Food Chain"); // sacrifice cost
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Angel of Jubilation", 0);
assertPermanentCount(playerA, angelOfJubilation, 0);
assertPermanentCount(playerB, "Food Chain", 0);
}
@Test
public void testOpponentCantSacrificeCreaturesAsPartOfPermanentsOptions() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerB, "Barrin, Master Wizard");
addCard(Zone.BATTLEFIELD, playerB, "Nantuko Husk");
addCard(Zone.BATTLEFIELD, playerB, "Llanowar Elves", 2);
@ -115,13 +123,13 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Angel of Jubilation", 1);
assertPermanentCount(playerA, angelOfJubilation, 1);
assertPermanentCount(playerB, "Nantuko Husk", 1);
}
@Test
public void testOpponentCantSacrificeAll() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerB, "Nantuko Husk");
addCard(Zone.BATTLEFIELD, playerB, "Corpse Traders");
addCard(Zone.HAND, playerB, "Soulblast");
@ -142,7 +150,7 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
@Test
public void testOpponentCantSacrificeCreatureSource() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerB, "Children of Korlis");
checkPlayableAbility("Can't sac", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Sacrifice", false);
@ -155,7 +163,7 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
@Test
public void testOpponentCanSacrificeAllLands() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerB, "Tomb of Urami");
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 4);
@ -169,7 +177,7 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
@Test
public void testOpponentCanSacrificeNonCreatureSource() {
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerA, "Tundra");
addCard(Zone.BATTLEFIELD, playerB, "Wasteland");
@ -195,7 +203,7 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
setStrictChooseMode(true);
// Other nonblack creatures you control get +1/+1.
// Players can't pay life or sacrifice creatures to cast spells or activate abilities
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
// Indestructible
@ -234,7 +242,7 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
setStrictChooseMode(true);
// Other nonblack creatures you control get +1/+1.
// Players can't pay life or sacrifice creatures to cast spells or activate abilities
addCard(Zone.BATTLEFIELD, playerA, "Angel of Jubilation");
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
// Pay 7 life: Draw seven cards.
addCard(Zone.BATTLEFIELD, playerB, "Griselbrand");
@ -244,4 +252,90 @@ public class AngelOfJubilationTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
}
@Test
public void testCanSacrificeTriggeredAbility() {
/*
Unscrupulous Contractor
{2}{B}
Creature Human Assassin
When this creature enters, you may sacrifice a creature. When you do, target player draws two cards and loses 2 life.
Plot {2}{B}
3/2
*/
String contractor = "Unscrupulous Contractor";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
String cub = "Bear Cub";
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.HAND, playerA, contractor);
addCard(Zone.HAND, playerB, contractor);
addCard(Zone.BATTLEFIELD, playerA, cub);
addCard(Zone.BATTLEFIELD, playerB, cub);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, contractor);
setChoice(playerA, true);
setChoice(playerA, cub);
addTarget(playerA, playerA);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, contractor);
setChoice(playerB, true);
setChoice(playerB, cub);
addTarget(playerB, playerB);
setStopAt(2, PhaseStep.END_TURN);
execute();
assertHandCount(playerA, 2);
assertLife(playerA, 20 - 2);
assertGraveyardCount(playerA, cub, 1);
assertHandCount(playerB, 1 + 2); //draw + contractor effect
assertLife(playerB, 20 - 2);
assertGraveyardCount(playerB, cub, 1);
}
@Test
public void canSacToMondrakWithArtifacts() {
setStrictChooseMode(true);
//Mondrak, Glory Dominus
//{2}{W}{W}
//Legendary Creature Phyrexian Horror
//If one or more tokens would be created under your control, twice that many of those tokens are created instead.
//{1}{W/P}{W/P}, Sacrifice two other artifacts and/or creatures: Put an indestructible counter on Mondrak.
String mondrak = "Mondrak, Glory Dominus";
Ability ability = new SimpleActivatedAbility(
Zone.ALL,
new CreateTokenEffect(new FoodToken(), 2),
new ManaCostsImpl<>("")
);
addCustomCardWithAbility("Token-maker", playerA, ability);
addCard(Zone.BATTLEFIELD, playerA, mondrak);
addCard(Zone.BATTLEFIELD, playerA, angelOfJubilation);
addCard(Zone.BATTLEFIELD, playerA, "Bear Cub", 2);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
checkPlayableAbility("Can't activate Mondrak", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W/P}{W/P}, Sacrifice", false);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "create two");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{W/P}{W/P}, Sacrifice");
setChoice(playerA, "Food Token", 2);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertCounterCount(playerA, mondrak, CounterType.INDESTRUCTIBLE, 1);
assertPermanentCount(playerA, "Bear Cub", 2);
assertPermanentCount(playerA, "Food Token", 2);
}
}

View file

@ -0,0 +1,69 @@
package org.mage.test.cards.continuous;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class BecomesColorEffectTest extends CardTestPlayerBase {
/*
Ancient Kavu
{3}{R}
Creature Kavu
{2}: This creature becomes colorless until end of turn.
Those with the ability to change their nature survived Phyrexias biological attacks. Everything else died.
3/3
*/
String kavu = "Ancient Kavu";
/*
Alchor's Tomb
{4}
Artifact
{2}, {T}: Target permanent you control becomes the color of your choice. (This effect lasts indefinitely.)
*/
String alchorsTomb = "Alchor's Tomb";
/*
*/
@Test
public void testBecomesColorSource() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, kavu);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
checkColor("Ancient Kavu is red", 1, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "R", true);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}: {this}");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkColor("Ancient Kavu is colorless", 1, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "C", true);
checkColor("Ancient Kavu is red again", 2, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "R", true);
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
}
@Test
public void testBecomesColorTarget() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, kavu);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerA, alchorsTomb);
checkColor("Ancient Kavu is red", 1, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "R", true);
// make Ancient Kavu green
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}, {T}: Target permanent", kavu);
setChoice(playerA, "Green");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkColor("Ancient Kavu is green", 1, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "G", true);
checkColor("Ancient Kavu is still green the following turn", 2, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "G", true);
// activate Ancient Kavu's ability to override green color until end of turn
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}: {this}");
checkColor("Ancient Kavu is colorless", 3, PhaseStep.POSTCOMBAT_MAIN, playerA, kavu, "C", true);
// next turn it should be green again
checkColor("Ancient Kavu is green again", 4, PhaseStep.PRECOMBAT_MAIN, playerA, kavu, "G", true);
setStopAt(4, PhaseStep.BEGIN_COMBAT);
execute();
}
}

View file

@ -0,0 +1,87 @@
package org.mage.test.cards.continuous;
import mage.ObjectColor;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.filter.predicate.mageobject.ToughnessPredicate;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
import java.util.Collections;
public class BecomesCreatureEffectTest extends CardTestPlayerBase {
/*
Ambush Commander
{3}{G}{G}
Creature Elf
Forests you control are 1/1 green Elf creatures that are still lands.
{1}{G}, Sacrifice an Elf: Target creature gets +3/+3 until end of turn.
2/2
*/
String ambushCommander = "Ambush Commander";
/*
Dryad Arbor
Land Creature Forest Dryad
1/1
*/
String dryadArbor = "Dryad Arbor";
/*
Frogify
{1}{U}
Enchantment Aura
Enchant creature
Enchanted creature loses all abilities and is a blue Frog creature with base power and toughness 1/1.
(It loses all other card types and creature types.)
*/
String frogify = "Frogify";
@Test
public void testBecomesCreatureAllEffect() {
FilterPermanent filter = new FilterPermanent();
filter.add(CardType.CREATURE.getPredicate());
filter.add(SubType.ELF.getPredicate());
filter.add(new PowerPredicate(ComparisonType.EQUAL_TO, 1));
filter.add(new ToughnessPredicate(ComparisonType.EQUAL_TO, 1));
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
addCard(Zone.BATTLEFIELD, playerA, dryadArbor);
addCard(Zone.HAND, playerA, ambushCommander);
runCode("Check forests are not 1/1 Elves", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
int numElves = game.getBattlefield().getActivePermanents(filter, player.getId(), game).size();
Assert.assertEquals("No 1/1 elves should be present", 0, numElves);
});
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ambushCommander);
runCode("Check forests are 1/1 Elves", 1, PhaseStep.BEGIN_COMBAT, playerA, (info, player, game) -> {
int numElves = game.getBattlefield().getActivePermanents(filter, player.getId(), game).size();
// 5 forests + dryad arbor
Assert.assertEquals("There should be 6 1/1 elves present", 6, numElves);
});
setStopAt(1, PhaseStep.END_TURN);
execute();
}
@Test
public void testBecomesCreatureAttachedEffect() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, dryadArbor);
addCard(Zone.HAND, playerA, frogify);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, frogify, dryadArbor);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAbilities(playerA, dryadArbor, Collections.emptyList());
assertPowerToughness(playerA, dryadArbor, 1, 1);
assertType(dryadArbor, CardType.CREATURE, SubType.FROG);
assertNotSubtype(dryadArbor, SubType.DRYAD);
assertNotType(dryadArbor, CardType.LAND);
assertColor(playerA, dryadArbor, ObjectColor.BLUE, true);
assertColor(playerA, dryadArbor, ObjectColor.GREEN, false);
}
}

View file

@ -0,0 +1,45 @@
package org.mage.test.cards.continuous;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class BecomesCreatureIfVehicleEffectTest extends CardTestPlayerBase {
/*
Aerial Modification
{4}{W}
Enchantment Aura
Enchant creature or Vehicle
As long as enchanted permanent is a Vehicle, its a creature in addition to its other types.
Enchanted creature gets +2/+2 and has flying.
*/
String aerialMod = "Aerial Modification";
/*
Goliath Truck
{4}
Artifact Vehicle
Stowage Whenever this Vehicle attacks, put two +1/+1 counters on another target attacking creature.
Crew 2 (Tap any number of creatures you control with total power 2 or more: This Vehicle becomes an artifact creature until end of turn.)
4/4
*/
String goliathTruck = "Goliath Truck";
@Test
public void testBecomesCreatureIfVehicleEffect() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, goliathTruck);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
addCard(Zone.HAND, playerA, aerialMod);
checkType("Goliath Truck is not a creature", 1, PhaseStep.PRECOMBAT_MAIN, playerA, goliathTruck, CardType.CREATURE, false);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aerialMod, goliathTruck);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertType(goliathTruck, CardType.CREATURE, true);
}
}

View file

@ -3,6 +3,7 @@ package org.mage.test.cards.continuous;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -22,7 +23,9 @@ public class OracleEnVecNextTurnTest extends CardTestPlayerBase {
// 1 - activate
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target opponent", playerB);
setChoice(playerB, "Balduvian Bears^Angelic Wall");
setChoice(playerB, "Balduvian Bears");
setChoice(playerB, "Angelic Wall");
setChoice(playerB, TestPlayer.CHOICE_SKIP);
//
checkLife("turn 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, 20);
checkPermanentCount("turn 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Balduvian Bears", 1);

View file

@ -235,7 +235,7 @@ public class TakeControlWhileSearchingLibraryTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Buried Alive");
setChoice(playerB, true); // continue after new control
addTarget(playerB, "Balduvian Bears");
addTarget(playerB, TestPlayer.TARGET_SKIP);
//addTarget(playerB, TestPlayer.TARGET_SKIP);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkGraveyardCount("after grave a", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 0);
checkGraveyardCount("after grave b", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Balduvian Bears", 0);

View file

@ -23,7 +23,6 @@ public class RemoveCounterCostTest extends CardTestPlayerBase {
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}, Remove two +1/+1 counters");
setChoice(playerA, "Novijen Sages"); // counters to remove
setChoice(playerA, TestPlayer.CHOICE_SKIP);
setChoice(playerA, "X=2"); // counters to remove
setStrictChooseMode(true);

View file

@ -427,18 +427,20 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
String savageBeating = "Savage Beating";
skipInitShuffling();
addCard(Zone.LIBRARY, playerA, savageBeating, 2);
addCard(Zone.LIBRARY, playerA, savageBeating, 2); // to free cast
addCard(Zone.HAND, playerA, jeleva);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
// prepare and exile cards from libs
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, jeleva);
// attack and use free cast from exile
attack(3, playerA, jeleva);
setChoice(playerA, true); // opt to use Jeleva ability
setChoice(playerA, savageBeating); // choose to cast Savage Beating for free
setChoice(playerA, false); // opt not to pay entwine cost
setChoice(playerA, savageBeating); // to free cast
setChoice(playerA, true); // confirm free cast
setChoice(playerA, false); // ignore entwine cost
setModeChoice(playerA, "1"); // use first mode of Savage Beating granting double strike
setStopAt(3, PhaseStep.END_COMBAT);
@ -448,6 +450,5 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
assertTapped(jeleva, true);
assertLife(playerB, 18);
assertAbility(playerA, jeleva, DoubleStrikeAbility.getInstance(), true);
}
}

View file

@ -945,7 +945,7 @@ public class ModalDoubleFacedCardsTest extends CardTestPlayerBase {
// cast as copy of mdf card
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Zam Wesell");
addTarget(playerA, playerB); // target opponent
addTarget(playerA, "Akoum Warrior"); // creature card to copy
setChoice(playerA, "Akoum Warrior"); // creature card to copy
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akoum Warrior", 1);

View file

@ -20,7 +20,7 @@ import java.util.stream.Stream;
*/
public class DungeonTest extends CardTestPlayerBase {
private static final String TOMB_OF_ANNIHILATION = "Tomb of Annihilation";
private static final String TOMB_OF_ANNIHILATION = "Tomb of Annihilation"; // TODO: miss test
private static final String LOST_MINE_OF_PHANDELVER = "Lost Mine of Phandelver";
private static final String DUNGEON_OF_THE_MAD_MAGE = "Dungeon of the Mad Mage";
private static final String FLAMESPEAKER_ADEPT = "Flamespeaker Adept";

View file

@ -157,4 +157,29 @@ public class EmblemsTest extends CardTestPlayerBase {
assertHandCount(playerA, 0);
}
@Test
public void testJayaFieryNegotiator() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Jaya, Fiery Negotiator");
addCard(Zone.HAND, playerA, "Wrenn's Resolve");
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
addCard(Zone.LIBRARY, playerA, "Lightning Bolt", 2);
skipInitShuffling();
addCounters(1, PhaseStep.UPKEEP, playerA, "Jaya, Fiery Negotiator", CounterType.LOYALTY, 6);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-8: You get an emblem");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wrenn's Resolve");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
setChoice(playerA, false, 2);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertExileCount(playerA, 6 - 1);
assertLife(playerB, 20 - 3 * 3);
}
}

View file

@ -4,6 +4,7 @@ package org.mage.test.cards.modal;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -25,7 +26,7 @@ public class OneOrBothTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox");
setModeChoice(playerA, "1");
setModeChoice(playerA, null);
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -47,7 +48,7 @@ public class OneOrBothTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox");
setModeChoice(playerA, "2");
setModeChoice(playerA, null);
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

View file

@ -6,6 +6,7 @@ import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -39,7 +40,7 @@ public class OneOrMoreTest extends CardTestPlayerBase {
addTarget(playerA, "Silvercoat Lion"); // for 3
addTarget(playerA, "Silvercoat Lion"); // for 4
addTarget(playerA, playerB); // for 5
setModeChoice(playerA, null);
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
@ -76,7 +77,7 @@ public class OneOrMoreTest extends CardTestPlayerBase {
addTarget(playerA, "Silvercoat Lion"); // for 3
addTarget(playerA, "Silvercoat Lion"); // for 4
addTarget(playerA, playerB); // for 5
setModeChoice(playerA, null);
setModeChoice(playerA, TestPlayer.MODE_SKIP);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);

View file

@ -3,7 +3,9 @@ package org.mage.test.cards.modal;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -61,25 +63,17 @@ public class PawPrintsTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Season of Gathering");
setModeChoice(playerA, "1");
setModeChoice(playerA, "2");
setModeChoice(playerA, "3"); // Will be unused
setModeChoice(playerA, "3"); // no more paws for mode 3, see exception below
addTarget(playerA, "Memnite"); // for 1
setChoice(playerA, "Enchantment");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
// Add one more counter from Hardened Scales, which was still on the battlefield when the counter placing effect triggered
assertPowerToughness(playerA, "Memnite", 3, 3);
assertCounterCount("Memnite", CounterType.P1P1, 2);
// But not anymore...
assertPermanentCount(playerA, "Hardened Scales", 0);
assertGraveyardCount(playerA, "Hardened Scales", 1);
// Draw effect didnt trigger
assertHandCount(playerA, 0);
try {
execute();
} catch (AssertionError e) {
Assert.assertTrue("mode 3 must not be able to choose due total paws cost", e.getMessage().contains("Can't use mode: 3"));
}
}
@Test

View file

@ -282,9 +282,9 @@ public class AttachmentTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Show and Tell");
setChoice(playerA, true);
setChoice(playerB, false);
setChoice(playerA, true); // yes, put from hand to battle
addTarget(playerA, "Aether Tunnel");
setChoice(playerB, false); // no, do not put
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

View file

@ -0,0 +1,51 @@
package org.mage.test.cards.single._5ed;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class AnHavvaConstableTest extends CardTestPlayerBase {
/*
An-Havva Constable
{1}{G}{G}
Creature Human
An-Havva Constables toughness is equal to 1 plus the number of green creatures on the battlefield.
2/1+*
*/
private static final String constable = "An-Havva Constable";
/*
Bear Cub
{1}{G}
Creature Bear
2/2
*/
private static final String cub = "Bear Cub";
@Test
public void testAnHavva() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
addCard(Zone.BATTLEFIELD, playerA, constable);
addCard(Zone.HAND, playerA, constable);
addCard(Zone.BATTLEFIELD, playerA, cub, 2);
addCard(Zone.BATTLEFIELD, playerB, cub, 3);
addCard(Zone.HAND, playerA, "Lightning Bolt");
checkPT("An-Havva Constable has toughness 7", 1, PhaseStep.PRECOMBAT_MAIN, playerA, constable, 2, 1 + 6);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", cub);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPT("An-Havva Constable has toughness 6", 1, PhaseStep.PRECOMBAT_MAIN, playerA, constable, 2, 1 + 5);
setStopAt(1, PhaseStep.END_TURN);
execute();
playerA.getHand().getCards(currentGame).stream()
.filter(card -> card.getName().equals(constable))
.findFirst().
ifPresent(card -> Assert.assertEquals(6, card.getToughness().getValue()));
}
}

View file

@ -0,0 +1,58 @@
package org.mage.test.cards.single.acr;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class AdrestiaTest extends CardTestPlayerBase {
/*
Adrestia
{3}
Legendary Artifact Vehicle
Islandwalk (This creature cant be blocked as long as defending player controls an Island.)
Whenever Adrestia attacks, if an Assassin crewed it this turn, draw a card. Adrestia becomes an Assassin in addition to its other types until end of turn.
Crew 1
*/
private static final String adrestia = "Adrestia";
/*
Nekrataal
{2}{B}{B}
Creature Human Assassin
First strike
When this creature enters, destroy target nonartifact, nonblack creature. That creature cant be regenerated.
2/1
*/
private static final String nekrataal = "Nekrataal";
@Test
public void testAdrestia() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, adrestia);
addCard(Zone.BATTLEFIELD, playerA, nekrataal);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Crew");
setChoice(playerA, nekrataal);
attack(1, playerA, adrestia);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertSubtype(adrestia, SubType.VEHICLE);
assertType(adrestia, CardType.CREATURE, true);
assertType(adrestia, CardType.ARTIFACT, true);
assertSubtype(adrestia, SubType.ASSASSIN);
assertHandCount(playerA, 1);
}
}

View file

@ -50,6 +50,9 @@ public class MantleOfTheAncientsTest extends CardTestPlayerBase {
addTarget(playerA, "Gate Smasher^Aether Tunnel");
addTarget(playerA, TestPlayer.TARGET_SKIP);
showBattlefield("after", 1, PhaseStep.END_TURN, playerA);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();

View file

@ -314,15 +314,14 @@ public class ShareTheSpoilsTest extends CardTestCommander4Players {
// Cast an adventure card from hand
castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerA, "Dizzying Swoop");
addTarget(playerA, "Prosper, Tome-Bound");
addTarget(playerA, TestPlayer.TARGET_SKIP); // tap 1 of 2 targets
//addTarget(playerA, TestPlayer.TARGET_SKIP); // only 1 creature, so tap 1 of 2, no need in skip
waitStackResolved(5, PhaseStep.PRECOMBAT_MAIN);
// Make sure the creature card can't be played from exile since there isn't the {W}{W} for it
checkPlayableAbility("creature cast", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Ardenvale Tactician", false);
setStopAt(5, PhaseStep.POSTCOMBAT_MAIN);
setStrictChooseMode(true);
setStopAt(5, PhaseStep.POSTCOMBAT_MAIN);
execute();
// 1 exiled with Share the Spoils

View file

@ -189,9 +189,9 @@ public class ApproachOfTheSecondSunTest extends CardTestPlayerBase {
// first may have been cast from anywhere.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Finale of Promise", true);
setChoice(playerA, "X=7"); // each with mana value X or less
addTarget(playerA, TARGET_SKIP); // skip instant target
addTarget(playerA, "Approach of the Second Sun"); // use sorcery target
setChoice(playerA, "Yes"); // You may cast
addTarget(playerA, TARGET_SKIP); // up to one target instant card
addTarget(playerA, "Approach of the Second Sun"); // and/or up to one target sorcery card from your graveyard
checkLife("Approach of the Second Sun cast from graveyard gains life", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 27);
checkLibraryCount("Approach of the Second Sun cast from graveyard goes to library",
1, PhaseStep.PRECOMBAT_MAIN, playerA, "Approach of the Second Sun", 1);
@ -200,9 +200,9 @@ public class ApproachOfTheSecondSunTest extends CardTestPlayerBase {
// The second Approach of the Second Sun that you cast must be cast from your hand,
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Finale of Promise", true);
setChoice(playerA, "X=7"); // each with mana value X or less
setChoice(playerA, "Yes"); // You may cast
addTarget(playerA, TARGET_SKIP); // up to one target instant card
addTarget(playerA, "Approach of the Second Sun"); // and/or up to one target sorcery card from your graveyard
setChoice(playerA, "Yes"); // You may cast
checkLife("Approach of the Second Sun cast from graveyard gains life", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 34);
checkLibraryCount("Approach of the Second Sun cast from graveyard goes to library",
1, PhaseStep.PRECOMBAT_MAIN, playerA, "Approach of the Second Sun", 2);

View file

@ -0,0 +1,53 @@
package org.mage.test.cards.single.avr;
import mage.abilities.common.SimpleActivatedAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class DarkImpostorTest extends CardTestPlayerBase {
/*
Dark Impostor
{2}{B}
Creature Vampire Assassin
{4}{B}{B}: Exile target creature and put a +1/+1 counter on this creature.
This creature has all activated abilities of all creature cards exiled with it.
2/2
*/
public static final String darkImposter = "Dark Impostor";
/*
Deathrite Shaman
{B/G}
Creature Elf Shaman
{T}: Exile target land card from a graveyard. Add one mana of any color.
{B}, {T}: Exile target instant or sorcery card from a graveyard. Each opponent loses 2 life.
{G}, {T}: Exile target creature card from a graveyard. You gain 2 life.
1/2
*/
public static final String deathriteShaman = "Deathrite Shaman";
@Test
public void testDarkImpostor() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, darkImposter);
addCard(Zone.BATTLEFIELD, playerA, deathriteShaman);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{B}{B}");
addTarget(playerA, deathriteShaman);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAbilityCount(playerA, darkImposter, SimpleActivatedAbility.class, 4); // own ability + 3 other from deathrite
}
}

View file

@ -4,6 +4,7 @@ package org.mage.test.cards.single.bfz;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -27,7 +28,7 @@ public class BrutalExpulsionTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brutal Expulsion", "mode=2Augmenting Automaton");
setModeChoice(playerA, "2");
setModeChoice(playerA, null); // ignore last one mode
setModeChoice(playerA, TestPlayer.MODE_SKIP); // ignore last one mode
//addTarget(playerA, "mode=2Augmenting Automaton"); // doesn't work with mode
setStopAt(1, PhaseStep.END_COMBAT);
@ -56,7 +57,7 @@ public class BrutalExpulsionTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brutal Expulsion", "mode=2Kiora, the Crashing Wave");
setModeChoice(playerA, "2");
setModeChoice(playerA, null); // ignore last one mode
setModeChoice(playerA, TestPlayer.MODE_SKIP); // ignore last one mode
setStopAt(1, PhaseStep.END_COMBAT);
execute();
@ -116,7 +117,7 @@ public class BrutalExpulsionTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brutal Expulsion", "mode=2Gideon, Ally of Zendikar");
setModeChoice(playerA, "2");
setModeChoice(playerA, null); // ignore last one mode
setModeChoice(playerA, TestPlayer.MODE_SKIP); // ignore last one mode
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", "Gideon, Ally of Zendikar");
setStopAt(1, PhaseStep.END_COMBAT);

View file

@ -0,0 +1,51 @@
package org.mage.test.cards.single.big;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class EsotericDuplicatorTest extends CardTestPlayerBase {
/*
Esoteric Duplicator
{2}{U}
Artifact Clue
Whenever you sacrifice this artifact or another artifact, you may pay {2}. If you do, at the beginning of the next end step, create a token thats a copy of that artifact.
{2}, Sacrifice this artifact: Draw a card.
*/
private static final String esotericDuplicator = "Esoteric Duplicator";
/*
Sculpting Steel
{3}
Artifact
You may have Sculpting Steel enter the battlefield as a copy of any artifact on the battlefield.
*/
private static final String sculptingSteel = "Sculpting Steel";
@Test
public void testEsotericDuplicator() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, esotericDuplicator);
addCard(Zone.HAND, playerA, sculptingSteel);
addCard(Zone.BATTLEFIELD, playerA, "Island", 7);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sculptingSteel);
setChoice(playerA, true);
setChoice(playerA, esotericDuplicator);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}, Sacrifice"); // Sacrifice duplicator
setChoice(playerA, true); // duplicate
setStopAt(2, PhaseStep.UPKEEP);
execute();
assertPermanentCount(playerA, esotericDuplicator, 1);
}
}

View file

@ -0,0 +1,34 @@
package org.mage.test.cards.single.c13;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class ActOfAuthorityEffectTest extends CardTestPlayerBase {
/*
Act of Authority
{1}{W}{W}
Enchantment
When this enchantment enters, you may exile target artifact or enchantment.
At the beginning of your upkeep, you may exile target artifact or enchantment. If you do, its controller gains control of this enchantment.
*/
private static final String actOfAuthority = "Act of Authority";
@Test
public void testActOfAuthority() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, actOfAuthority);
addCard(Zone.BATTLEFIELD, playerB, actOfAuthority + "@actB");
setChoice(playerA, true); // upkeep
addTarget(playerA, "@actB");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerB, actOfAuthority, 1);
}
}

View file

@ -27,8 +27,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// attack and cast first time (free)
attack(1, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Grizzly Bears"); // commander choice
setChoice(playerA, true); // cast commander
waitStackResolved(1, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 1", 1, PhaseStep.COMBAT_DAMAGE, playerA, "Grizzly Bears", 1);
checkPermanentTapped("after 1", 1, PhaseStep.COMBAT_DAMAGE, playerA, "Forest", true, 0);
@ -40,8 +40,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// turn 3 - second cast (1x tax)
attack(3, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Grizzly Bears"); // commander choice
setChoice(playerA, true); // cast commander
waitStackResolved(3, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 2", 3, PhaseStep.COMBAT_DAMAGE, playerA, "Grizzly Bears", 1);
checkPermanentTapped("after 2", 3, PhaseStep.COMBAT_DAMAGE, playerA, "Forest", true, 2); // 1x tax
@ -53,8 +53,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// turn 5 - third cast (2x tax)
attack(5, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Grizzly Bears"); // commander choice
setChoice(playerA, true); // cast commander
waitStackResolved(5, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 3", 5, PhaseStep.COMBAT_DAMAGE, playerA, "Grizzly Bears", 1);
checkPermanentTapped("after 3", 5, PhaseStep.COMBAT_DAMAGE, playerA, "Forest", true, 2 * 2); // 2x tax
@ -85,8 +85,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// attack and cast first time (free)
attack(1, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Akoum Warrior"); // commander choice
setChoice(playerA, true); // cast commander
waitStackResolved(1, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 1", 1, PhaseStep.COMBAT_DAMAGE, playerA, "Akoum Warrior", 1);
checkPermanentTapped("after 1", 1, PhaseStep.COMBAT_DAMAGE, playerA, "Mountain", true, 0);
@ -98,8 +98,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// turn 3 - second cast (1x tax)
attack(3, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Akoum Warrior"); // commander choice
setChoice(playerA, true); // cast commander
waitStackResolved(3, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 2", 3, PhaseStep.COMBAT_DAMAGE, playerA, "Akoum Warrior", 1);
checkPermanentTapped("after 2", 3, PhaseStep.COMBAT_DAMAGE, playerA, "Mountain", true, 2); // 1x tax
@ -111,8 +111,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// turn 5 - third cast (2x tax)
attack(5, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Akoum Warrior"); // commander choice
setChoice(playerA, true); // cast commander
waitStackResolved(5, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 3", 5, PhaseStep.COMBAT_DAMAGE, playerA, "Akoum Warrior", 1);
checkPermanentTapped("after 3", 5, PhaseStep.COMBAT_DAMAGE, playerA, "Mountain", true, 2 * 2); // 2x tax
@ -144,8 +144,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// attack and cast first time (free)
attack(1, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Birgi, God of Storytelling"); // commander choice
setChoice(playerA, true); // cast commander
setChoice(playerA, "Cast Birgi, God of Storytelling"); // spell choice
waitStackResolved(1, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 1", 1, PhaseStep.COMBAT_DAMAGE, playerA, "Birgi, God of Storytelling", 1);
@ -158,8 +158,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// turn 3 - second cast, LEFT side (1x tax)
attack(3, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Birgi, God of Storytelling"); // commander choice
setChoice(playerA, true); // cast commander
setChoice(playerA, "Cast Birgi, God of Storytelling"); // spell choice
waitStackResolved(3, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 2", 3, PhaseStep.COMBAT_DAMAGE, playerA, "Birgi, God of Storytelling", 1);
@ -172,8 +172,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// turn 5 - third cast, RIGHT side (2x tax)
attack(5, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Birgi, God of Storytelling"); // commander choice
setChoice(playerA, true); // cast commander
setChoice(playerA, "Cast Harnfel, Horn of Bounty"); // spell choice
waitStackResolved(5, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 3", 5, PhaseStep.COMBAT_DAMAGE, playerA, "Harnfel, Horn of Bounty", 1);
@ -186,8 +186,8 @@ public class GeodeGolemTest extends CardTestCommanderDuelBase {
// turn 7 - fourth cast, RIGHT side (3x tax)
attack(7, playerA, "Geode Golem");
setChoice(playerA, true); // cast commander
setChoice(playerA, "Birgi, God of Storytelling"); // commander choice
setChoice(playerA, true); // cast commander
setChoice(playerA, "Cast Harnfel, Horn of Bounty"); // spell choice
waitStackResolved(7, PhaseStep.COMBAT_DAMAGE);
checkPermanentCount("after 4", 7, PhaseStep.COMBAT_DAMAGE, playerA, "Harnfel, Horn of Bounty", 1);

View file

@ -0,0 +1,36 @@
package org.mage.test.cards.single.c18;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author notgreat
*/
public class RavenousSlimeTest extends CardTestPlayerBase {
@Test
public void testRavenousSlime() {
addCustomEffect_TargetDestroy(playerA);
addCard(Zone.BATTLEFIELD, playerA, "Ravenous Slime");
addCard(Zone.BATTLEFIELD, playerB, "Runeclaw Bear");
addCard(Zone.BATTLEFIELD, playerB, "Centaur Courser");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy", "Runeclaw Bear");
checkPT("Ravenous Slime ate Runeclaw Bear", 1, PhaseStep.BEGIN_COMBAT, playerA, "Ravenous Slime", 3, 3);
attack(1, playerA, "Ravenous Slime");
block(1, playerB, "Centaur Courser", "Ravenous Slime");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertExileCount(playerB, "Runeclaw Bear", 1);
assertExileCount(playerB, "Centaur Courser", 1);
assertGraveyardCount(playerA, "Ravenous Slime", 1);
}
}

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.single.clu;
import mage.constants.PhaseStep;
@ -6,6 +5,7 @@ import mage.constants.Zone;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -41,7 +41,6 @@ public class SludgeTitanTest extends CardTestPlayerBase {
addCard(Zone.LIBRARY, playerA, divination, 5);
attack(1, playerA, titan, playerB);
setChoice(playerA, playerA.CHOICE_SKIP);
setStopAt(1, PhaseStep.DECLARE_BLOCKERS);
execute();
@ -49,29 +48,6 @@ public class SludgeTitanTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, divination, 5);
}
@Test
public void testNoValidChoiceInvalid() {
setStrictChooseMode(true);
skipInitShuffling();
addCard(Zone.BATTLEFIELD, playerA, titan);
addCard(Zone.LIBRARY, playerA, divination, 5);
attack(1, playerA, titan, playerB);
setChoice(playerA, divination); // invalid, titan doesn't allow for choosing sorcery
setStopAt(1, PhaseStep.DECLARE_BLOCKERS);
try {
execute();
Assert.fail("must throw exception on execute");
} catch (Throwable e) {
if (!e.getMessage().startsWith("Missing CHOICE def")) {
Assert.fail("Unexpected exception " + e.getMessage());
}
}
}
@Test
public void testCreatureOnly_ChooseNone() {
setStrictChooseMode(true);
@ -81,7 +57,7 @@ public class SludgeTitanTest extends CardTestPlayerBase {
addCard(Zone.LIBRARY, playerA, piker, 5);
attack(1, playerA, titan, playerB);
setChoice(playerA, playerA.CHOICE_SKIP);
setChoice(playerA, TestPlayer.CHOICE_SKIP);
setStopAt(1, PhaseStep.DECLARE_BLOCKERS);
execute();
@ -207,6 +183,8 @@ public class SludgeTitanTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, titan);
addCard(Zone.LIBRARY, playerA, brownscale, 5);
// must able to select only 1 creature, so after first choice it must auto-finish
// if you see miss choice here then something broken in TestPlayer's choose method
attack(1, playerA, titan, playerB);
setChoice(playerA, brownscale);

View file

@ -0,0 +1,57 @@
package org.mage.test.cards.single.dft;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class AatchikEmeraldRadianTest extends CardTestPlayerBase {
/*
Aatchik, Emerald Radian
{3}{B}{B}{G}
Legendary Creature Insect Druid
When Aatchik enters, create a 1/1 green Insect creature token for each artifact and/or creature card in your graveyard.
Whenever another Insect you control dies, put a +1/+1 counter on Aatchik. Each opponent loses 1 life.
3/3
*/
private static final String aatchik = "Aatchik, Emerald Radian";
/*
Springheart Nantuko
{1}{G}
Enchantment Creature Insect Monk
Bestow {1}{G}
Enchanted creature gets +1/+1.
Landfall Whenever a land you control enters, you may pay {1}{G} if this permanent is attached to a creature you control.
If you do, create a token thats a copy of that creature. If you didnt create a token this way, create a 1/1 green Insect creature token.
1/1
*/
private static final String nantuko = "Springheart Nantuko";
@Test
public void testOpponentCreatingTokens() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, aatchik);
addCard(Zone.BATTLEFIELD, playerB, aatchik);
addCard(Zone.GRAVEYARD, playerA, aatchik);
addCard(Zone.GRAVEYARD, playerB, aatchik);
addCard(Zone.BATTLEFIELD, playerA, "Bayou", 9);
addCard(Zone.HAND, playerA, nantuko);
addCard(Zone.HAND, playerA, "Bayou");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nantuko + " using bestow");
addTarget(playerA, aatchik);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bayou");
setChoice(playerA, true);
setChoice(playerA, aatchik);
setChoice(playerA, "When {this} enters");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertTokenCount(playerB, "Insect Token", 0);
assertTokenCount(playerA, "Insect Token", 1);
}
}

View file

@ -0,0 +1,77 @@
package org.mage.test.cards.single.dis;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.UntapAllControllerEffect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
import static org.junit.Assert.assertEquals;
public class ExperimentKrajTest extends CardTestPlayerBase {
/*
Experiment Kraj
{2}{G}{G}{U}{U}
Legendary Creature Ooze Mutant
Experiment Kraj has all activated abilities of each other creature with a +1/+1 counter on it.
{T}: Put a +1/+1 counter on target creature.
*/
private static final String experimentKraj = "Experiment Kraj";
/*
Stoneforge Mystic
{1}{W}
Creature Kor Artificer
When this creature enters, you may search your library for an Equipment card, reveal it, put it into your hand, then shuffle.
{1}{W}, {T}: You may put an Equipment card from your hand onto the battlefield.
*/
private static final String stoneforgeMystic = "Stoneforge Mystic";
/*
Noble Hierarch
{G}
Creature Human Druid
Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.)
{T}: Add {G}, {W}, or {U}.
*/
private static final String nobleHierarch = "Noble Hierarch";
@Test
public void testExperimentKraj() {
setStrictChooseMode(true);
Ability ability = new SimpleActivatedAbility(
Zone.ALL,
new UntapAllControllerEffect(StaticFilters.FILTER_CONTROLLED_A_CREATURE),
new ManaCostsImpl<>("")
);
addCustomCardWithAbility("Untap creatures", playerA, ability);
addCard(Zone.BATTLEFIELD, playerA, experimentKraj);
addCard(Zone.BATTLEFIELD, playerA, stoneforgeMystic);
addCard(Zone.BATTLEFIELD, playerB, nobleHierarch);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Put a +1/+1", stoneforgeMystic);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Put a +1/+1", nobleHierarch);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertEquals("Kraj should have 5 activated abilities", 5, getPermanent(experimentKraj).getAbilities(currentGame)
.stream()
.filter(Ability::isActivatedAbility)
.count());
}
}

View file

@ -2,7 +2,6 @@ package org.mage.test.cards.single.dmu;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -76,4 +75,26 @@ public class KarnsSylexTest extends CardTestPlayerBase {
assertLife(playerB, 20 - 3);
assertGraveyardCount(playerA, "Lightning Bolt", 1);
}
/**
* Test that it does not work with mana abilities, e.g. Thran Portal, with Yasharn, Implacable Earth.
*/
@Test
public void blockedManaAbilitiesWithYasharn() {
addCard(Zone.HAND, playerA, "Thran Portal");
addCard(Zone.HAND, playerA, "Lightning Bolt");
addCard(Zone.BATTLEFIELD, playerA, karnsSylex);
addCard(Zone.BATTLEFIELD, playerA, "Yasharn, Implacable Earth");
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Thran Portal");
setChoice(playerA, "Thran");
setChoice(playerA, "Mountain");
checkPlayableAbility("restricted by Yasharn", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", false);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 20);
assertLife(playerB, 20);
}
}

View file

@ -5,8 +5,6 @@ import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
import java.lang.annotation.Target;
/**
* {@link mage.cards.t.ThranPortal Thran Portal}
* Land Gate

View file

@ -0,0 +1,67 @@
package org.mage.test.cards.single.dsk;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class UnidentifiedHovershipTest extends CardTestPlayerBase {
/*
Unidentified Hovership
{1}{W}{W}
Artifact - Vehicle
Flying
When this Vehicle enters, exile up to one target creature with toughness 5 or less.
When this Vehicle leaves the battlefield, the exiled card's owner manifests dread.
Crew 1
2/2
*/
private static final String unidentifiedHovership = "Unidentified Hovership";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
/*
Naturalize
{1}{G}
Instant
Destroy target artifact or enchantment.
*/
private static final String naturalize = "Naturalize";
@Test
public void testUnidentifiedHovership() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, unidentifiedHovership);
addCard(Zone.HAND, playerB, naturalize);
addCard(Zone.BATTLEFIELD, playerB, bearCub);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.BATTLEFIELD, playerB, "Forest", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, unidentifiedHovership);
addTarget(playerA, bearCub);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, naturalize, unidentifiedHovership);
setChoice(playerB, "Mountain");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerB, 2 + 1); // forests + face down
assertGraveyardCount(playerA, unidentifiedHovership, 1);
assertGraveyardCount(playerB, 1 + 1); // naturalize + manifest
assertExileCount(playerB, bearCub, 1);
}
}

View file

@ -78,7 +78,7 @@ public class TamiyoFieldResearcherTest extends CardTestPlayerBase {
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Choose up to two");
addTarget(playerA, "Bronze Sable");
addTarget(playerA, TestPlayer.TARGET_SKIP);
//addTarget(playerA, TestPlayer.TARGET_SKIP); // there are only 1 creature, so choose 1 of 2, no need in skip
attack(1, playerA, "Bronze Sable");
@ -240,7 +240,7 @@ public class TamiyoFieldResearcherTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tamiyo, Field Researcher", true);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Choose up to two");
addTarget(playerA, "Bronze Sable");
addTarget(playerA, TestPlayer.TARGET_SKIP);
//addTarget(playerA, TestPlayer.TARGET_SKIP); // there are only 1 creature, so choose 1 of 2, no need in skip
attack(2, playerB, "Bronze Sable");

View file

@ -0,0 +1,75 @@
package org.mage.test.cards.single.fic;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.UntapAllControllerEffect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class UriangerAugureltTest extends CardTestPlayerBase {
private static final String urianger = "Urianger Augurelt";
private static final String arcaneSignet = "Arcane Signet";
private static final String howlingMine = "Howling Mine";
private static final String thoughtVessel = "Thought Vessel";
private static final String benalishKnight = "Benalish Knight";
@Test
public void uriangerAugureltTest() {
setStrictChooseMode(true);
skipInitShuffling();
removeAllCardsFromLibrary(playerA);
Ability ability = new SimpleActivatedAbility(
Zone.ALL,
new UntapAllControllerEffect(StaticFilters.FILTER_CONTROLLED_A_CREATURE),
new ManaCostsImpl<>("")
);
addCustomCardWithAbility("Untap creatures", playerA, ability);
addCard(Zone.BATTLEFIELD, playerA, urianger);
addCard(Zone.LIBRARY, playerA, "Plains", 3);
addCard(Zone.LIBRARY, playerA, arcaneSignet);
addCard(Zone.LIBRARY, playerA, howlingMine);
addCard(Zone.LIBRARY, playerA, thoughtVessel);
addCard(Zone.LIBRARY, playerA, benalishKnight);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Draw Arcanum</i>");
setChoice(playerA, true, 4);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Draw Arcanum</i>");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Draw Arcanum</i>");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Draw Arcanum</i>");
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "<i>Play Arcanum</i>");
waitStackResolved(3, PhaseStep.PRECOMBAT_MAIN);
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, benalishKnight, true);
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, arcaneSignet, true);
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, howlingMine, true);
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, thoughtVessel, true);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, benalishKnight, 1);
assertPermanentCount(playerA, arcaneSignet, 1);
assertPermanentCount(playerA, howlingMine, 1);
assertPermanentCount(playerA, thoughtVessel, 1);
assertLife(playerA, 20 + 2 * 4);
}
}

View file

@ -0,0 +1,66 @@
package org.mage.test.cards.single.fin;
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;
public class AettirAndPriwenTest extends CardTestPlayerBase {
/*
Aettir and Priwen
{6}
Legendary Artifact Equipment
Equipped creature has base power and toughness X/X, where X is your life total.
Equip {5}
*/
private static final String aettir = "Aettir and Priwen";
/*
Bear Cub
{1}{G}
Creature Bear
2/2
*/
private static final String cub = "Bear Cub";
/*
Lightning Bolt
{R}
Instant
Lightning Bolt deals 3 damage to any target.
*/
public static final String bolt = "Lightning Bolt";
@Test
public void testAettirAndPriwen() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, aettir);
addCard(Zone.BATTLEFIELD, playerA, cub);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 7);
addCard(Zone.HAND, playerA, bolt, 2);
checkPowerToughness(2, cub, 1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{5}: Equip");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPowerToughness(20, cub, 1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bolt, playerA);
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
checkPowerToughness(20 - 3, cub, 1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bolt, playerA);
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
checkPowerToughness(20 - 3 * 2, cub, 1, PhaseStep.POSTCOMBAT_MAIN);
checkPowerToughness(20 - 3 * 2, cub, 2, PhaseStep.PRECOMBAT_MAIN);
}
void checkPowerToughness(int xValue, String name, int turnNum, PhaseStep phaseStep) {
runCode("Checking P/T is " + xValue, turnNum, phaseStep, playerA, (info, player, game) -> {
Permanent permanent = getPermanent(name, player);
Assert.assertEquals(xValue, permanent.getPower().getModifiedBaseValue());
Assert.assertEquals(xValue, permanent.getToughness().getModifiedBaseValue());
});
}
}

View file

@ -0,0 +1,91 @@
package org.mage.test.cards.single.fin;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author JayDi85
*/
public class GarnetPrincessOfAlexandriaTest extends CardTestPlayerBase {
@Test
public void test_Targets_0() {
// 2/2
// Whenever Garnet attacks, you may remove a lore counter from each of any number of Sagas you control.
// Put a +1/+1 counter on Garnet for each lore counter removed this way.
addCard(Zone.BATTLEFIELD, playerA, "Garnet, Princess of Alexandria");
// nothing to select after attack
attack(1, playerA, "Garnet, Princess of Alexandria", playerB);
//setChoice(playerA, TestPlayer.CHOICE_SKIP); // no valid choices, so do not show choose dialog
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerB, 20 - 2);
}
@Test
public void test_Targets_1() {
// 2/2
// Whenever Garnet attacks, you may remove a lore counter from each of any number of Sagas you control.
// Put a +1/+1 counter on Garnet for each lore counter removed this way.
addCard(Zone.BATTLEFIELD, playerA, "Garnet, Princess of Alexandria");
//
// (As this Saga enters and after your draw step, add a lore counter. Sacrifice after IV.)
// I, II, III, IV -- Stampede! -- Other creatures you control get +1/+0 until end of turn.
addCard(Zone.HAND, playerA, "Summon: Choco/Mog"); // {2}{W}
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
// prepare x1 saga
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Summon: Choco/Mog");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// can select 1 target only
attack(1, playerA, "Garnet, Princess of Alexandria", playerB);
setChoice(playerA, "Summon: Choco/Mog");
setStrictChooseMode(true);
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
execute();
// 2/2 attack + 1/1 saga's boost + 1/0 counter remove boost
assertCounterCount(playerA, "Summon: Choco/Mog", CounterType.LORE, 0);
assertLife(playerB, 20 - 2 - 1 - 1);
}
@Test
public void test_Targets_2() {
// 2/2
// Whenever Garnet attacks, you may remove a lore counter from each of any number of Sagas you control.
// Put a +1/+1 counter on Garnet for each lore counter removed this way.
addCard(Zone.BATTLEFIELD, playerA, "Garnet, Princess of Alexandria");
//
// (As this Saga enters and after your draw step, add a lore counter. Sacrifice after IV.)
// I, II, III, IV -- Stampede! -- Other creatures you control get +1/+0 until end of turn.
addCard(Zone.HAND, playerA, "Summon: Choco/Mog", 2); // {2}{W}
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3 * 2);
// prepare x2 sagas
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Summon: Choco/Mog");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Summon: Choco/Mog");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
// can select 2 targets
attack(1, playerA, "Garnet, Princess of Alexandria", playerB);
setChoice(playerA, "Summon: Choco/Mog", 2); // x2 targets
setStrictChooseMode(true);
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
execute();
// 2/2 attack + x2 1/1 saga's boost + x2 1/0 counter remove boost
assertCounterCount(playerA, "Summon: Choco/Mog", CounterType.LORE, 0);
assertLife(playerB, 20 - 2 - 2 - 2);
}
}

View file

@ -27,13 +27,13 @@ public class WandOfVertebraeTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, wandOfVertebrae);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.GRAVEYARD, playerA, lavaCoil);
setStrictChooseMode(true);
addCard(Zone.GRAVEYARD, playerA, "Grizzly Bears", 10);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}, {T}");
addTarget(playerA, lavaCoil);
addTarget(playerA, TestPlayer.TARGET_SKIP); // must choose 1 of 5
setStrictChooseMode(true);
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();

View file

@ -20,9 +20,9 @@ public class DiluvianPrimordialTest extends CardTestPlayerBase {
*/
private static final String primordial = "Diluvian Primordial";
// Bug: NPE on casting Valakut Awakening
@Test
public void test_MDFC() {
// possible bug: NPE on casting Valakut Awakening
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, primordial);
@ -32,7 +32,7 @@ public class DiluvianPrimordialTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, primordial);
addTarget(playerA, "Valakut Awakening");
setChoice(playerA, true); // Yes to "You may"
setChoice(playerA, TestPlayer.CHOICE_SKIP); // No choice for Awakening's effect
//setChoice(playerA, TestPlayer.CHOICE_SKIP); // no need in skip, cause no valid choices for Awakening's effect
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();

View file

@ -0,0 +1,80 @@
package org.mage.test.cards.single.kld;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.target.common.TargetPermanentOrPlayer;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class AnimationModuleTest extends CardTestPlayerBase {
/*
Animation Module
{1}
Artifact
Whenever one or more +1/+1 counters are put on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token.
{3}, {T}: Choose a counter on target permanent or player. Give that permanent or player another counter of that kind.
*/
private static final String animationModule = "Animation Module";
@Test
public void testGivePermanentCounter() {
setStrictChooseMode(true);
Ability ability = new SimpleActivatedAbility(
new AddCountersTargetEffect(CounterType.P1P1.createInstance()),
new ManaCostsImpl<>("")
);
ability.addTarget(new TargetPermanentOrPlayer(1));
addCustomCardWithAbility("add counter", playerA, ability);
addCard(Zone.BATTLEFIELD, playerA, animationModule);
addCard(Zone.BATTLEFIELD, playerA, "Island", 10);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "put", animationModule);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
setChoice(playerA, true); //pay to create servo
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{3}, {T}: Choose a counter", animationModule);
setChoice(playerA, true); //pay to create servo
setStopAt(1, PhaseStep.END_TURN);
execute();
assertCounterCount(playerA, animationModule, CounterType.P1P1, 2);
assertPermanentCount(playerA, "Servo Token", 2);
}
@Test
public void testGivePlayerCounter() {
setStrictChooseMode(true);
Ability ability = new SimpleActivatedAbility(
new AddCountersTargetEffect(CounterType.ENERGY.createInstance()),
new ManaCostsImpl<>("")
);
ability.addTarget(new TargetPermanentOrPlayer(1));
addCustomCardWithAbility("add counter", playerA, ability);
addCard(Zone.BATTLEFIELD, playerA, animationModule);
addCard(Zone.BATTLEFIELD, playerA, "Island", 10);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "put", playerA);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{3}, {T}: Choose a counter", playerA);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertCounterCount(playerA, CounterType.ENERGY, 2);
}
}

View file

@ -4,6 +4,7 @@ import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -32,9 +33,10 @@ public class RipplesOfPotentialTest extends CardTestPlayerBase {
setChoice(playerA, "Blast Zone^Arcbound Javelineer^Chandra, Pyromaster^Atraxa's Skitterfang");
// Phase out choice
setChoice(playerA, "Blast Zone^Arcbound Javelineer^Chandra, Pyromaster");
setChoice(playerA, TestPlayer.CHOICE_SKIP); // keep Atraxa's Skitterfang
setChoice(playerA, false); // Atraxa's Skitterfang ability - do not remove oil
setStrictChooseMode(true);
setChoice(playerA, false); // Atraxa's Skitterfang ability
setStopAt(1, PhaseStep.END_TURN);
execute();

View file

@ -0,0 +1,78 @@
package org.mage.test.cards.single.lci;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class AbuelosAwakeningTest extends CardTestPlayerBase {
/*
Abuelo's Awakening
{X}{3}{W}
Sorcery
Return target artifact or non-Aura enchantment card from your graveyard to the battlefield with X additional +1/+1 counters on it.
Its a 1/1 Spirit creature with flying in addition to its other types.
*/
public static final String abuelosAwakening = "Abuelo's Awakening";
/*
Talisman of Progress
{2}
Artifact
{T}: Add {C}.
{T}: Add {W} or {U}. This artifact deals 1 damage to you.
*/
public static final String talisman = "Talisman of Progress";
/*
Lightning Bolt
{R}
Instant
Lightning Bolt deals 3 damage to any target.
*/
public static final String bolt = "Lightning Bolt";
@Test
public void testAbuelosAwakening() {
setStrictChooseMode(true);
addCard(Zone.GRAVEYARD, playerA, talisman);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
addCard(Zone.HAND, playerA, abuelosAwakening);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, abuelosAwakening, talisman);
setChoiceAmount(playerA, 2);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertCounterCount(playerA, talisman, CounterType.P1P1, 2);
assertType(talisman, CardType.CREATURE, true);
assertSubtype(talisman, SubType.SPIRIT);
assertBasePowerToughness(playerA, talisman, 1, 1);
}
@Test
public void testAbuelosAwakeningDies() {
setStrictChooseMode(true);
addCard(Zone.GRAVEYARD, playerA, talisman);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
addCard(Zone.HAND, playerA, abuelosAwakening);
addCard(Zone.HAND, playerB, bolt);
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, abuelosAwakening, talisman);
setChoiceAmount(playerA, 2);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, bolt, talisman);
setStopAt(2, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, talisman, 0);
assertGraveyardCount(playerA, talisman, 1);
}
}

View file

@ -0,0 +1,44 @@
package org.mage.test.cards.single.lci;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class DireBlunderbussTest extends CardTestPlayerBase {
/*
Dire Blunderbuss
Color Indicator: RedArtifact Equipment
Equipped creature gets +3/+0 and has Whenever this creature attacks, you may sacrifice an artifact other than Dire Blunderbuss. When you do, this creature deals damage equal to its power to target creature.
Equip {1}
*/
private static final String direBlunderBuss = "Dire Blunderbuss";
@Test
public void DireBlunderbussTest() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, "Forest");
addCard(Zone.BATTLEFIELD, playerA, direBlunderBuss);
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears");
addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears@bearsB");
addCard(Zone.BATTLEFIELD, playerA, "Tormod's Crypt");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Balduvian Bears");
attack(1, playerA, "Balduvian Bears");
setChoice(playerA, true);
setChoice(playerA, "Tormod's Crypt");
addTarget(playerA, "@bearsB");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerB, "Balduvian Bears", 1);
assertLife(playerB, 20 - 2 - 3);
}
}

View file

@ -0,0 +1,44 @@
package org.mage.test.cards.single.lci;
import mage.ObjectColor;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class EatenByPiranhasTest extends CardTestPlayerBase {
/*
Eaten by Piranhas
{1}{U}
Enchantment Aura
Flash (You may cast this spell any time you could cast an instant.)
Enchant creature
Enchanted creature loses all abilities and is a black Skeleton creature with base power and toughness 1/1. (It loses all other colors, card types, and creature types.)
*/
private static final String eatenByPiranhas = "Eaten by Piranhas";
@Test
public void testEatenByPiranhas() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerB, eatenByPiranhas);
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, eatenByPiranhas);
addTarget(playerB, "Balduvian Bears");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertType("Balduvian Bears", CardType.CREATURE, SubType.SKELETON);
assertPowerToughness(playerA, "Balduvian Bears", 1, 1);
assertColor(playerA, "Balduvian Bears", ObjectColor.BLACK, true);
}
}

View file

@ -0,0 +1,55 @@
package org.mage.test.cards.single.leg;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class AlAbarasCarpetTest extends CardTestPlayerBase {
/*
Al-abara's Carpet
{5}
Artifact
{5}, {T}: Prevent all damage that would be dealt to you this turn by attacking creatures without flying.
*/
private static final String alabarasCarpet = "Al-abara's Carpet";
/*
Storm Crow
{1}{U}
Creature Bird
Flying (This creature cant be blocked except by creatures with flying or reach.)
1/2
*/
private static final String stormCrow = "Storm Crow";
/*
Balduvian Bears
{1}{G}
Creature Bear
2/2
*/
private static final String balduvianBears = "Balduvian Bears";
@Test
public void testCarpet() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, alabarasCarpet);
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
addCard(Zone.BATTLEFIELD, playerB, balduvianBears);
addCard(Zone.BATTLEFIELD, playerB, stormCrow);
attack(2, playerB, balduvianBears);
attack(2, playerB, stormCrow);
activateAbility(2, PhaseStep.DECLARE_ATTACKERS, playerA, "{5}, {T}");
setStopAt(2, PhaseStep.END_TURN);
execute();
assertLife(playerA, 20 - 1);
}
}

View file

@ -0,0 +1,83 @@
package org.mage.test.cards.single.ltr;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBaseWithAIHelps;
/**
* @author JayDi85
*/
public class BreakingOfTheFellowshipTest extends CardTestPlayerBaseWithAIHelps {
@Test
public void test_PossibleTargets() {
// Target creature an opponent controls deals damage equal to its power to another target creature that player controls.
addCard(Zone.HAND, playerA, "Breaking of the Fellowship"); // {1}{R}
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
//
addCard(Zone.HAND, playerB, "Grizzly Bears"); // 2/2, {1}{G}
addCard(Zone.HAND, playerB, "Spectral Bears"); // 3/3, {1}{G}
addCard(Zone.BATTLEFIELD, playerB, "Forest", 2 * 2);
// turn 1 - no targets, can't play
checkPlayableAbility("no targets - can't cast", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Breaking of the Fellowship", false);
// turn 3 - 1 of 2 targets, can't play
castSpell(3 - 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Grizzly Bears");
checkPlayableAbility("1 of 2 targets - can't cast", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Breaking of the Fellowship", false);
// turn 5 - 2 of 2 targets, can play
castSpell(5 - 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Spectral Bears");
checkPlayableAbility("2 of 2 targets - can cast", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Breaking of the Fellowship", true);
castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerA, "Breaking of the Fellowship", "Grizzly Bears^Spectral Bears");
setStrictChooseMode(true);
setStopAt(5, PhaseStep.END_TURN);
execute();
assertDamageReceived(playerB, "Spectral Bears", 2);
}
@Test
public void test_Normal_AI() {
// Target creature an opponent controls deals damage equal to its power to another target creature that player controls.
addCard(Zone.HAND, playerA, "Breaking of the Fellowship"); // {1}{R}
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
//
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears"); // 2/2
addCard(Zone.BATTLEFIELD, playerB, "Spectral Bears"); // 3/3
// AI must choose 3/3 to kill 2/2
aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, playerA);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerB, "Grizzly Bears", 1);
}
@Test
public void test_Protection_AI() {
// Target creature an opponent controls deals damage equal to its power to another target creature that player controls.
addCard(Zone.HAND, playerA, "Breaking of the Fellowship"); // {1}{R}
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
//
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears"); // 2/2
addCard(Zone.BATTLEFIELD, playerB, "Spectral Bears"); // 3/3
addCard(Zone.BATTLEFIELD, playerB, "Lavinia of the Tenth"); // 4/4, Protection from red
// can't choose 4/4 to kill 3/3 due protection from red
// AI must choose 3/3 to kill 2/2
aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, playerA);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerB, "Grizzly Bears", 1);
}
}

View file

@ -2,6 +2,7 @@ package org.mage.test.cards.single.ltr;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -29,14 +30,16 @@ public class GlamdringTest extends CardTestPlayerBase {
attack(1, playerA, "Blur Sliver");
setChoice(playerA, "In Garruk's Wake"); // 9 mana, so we shouldn't be able to choose it
setChoice(playerA, "Yes");
try {
setStopAt(1, PhaseStep.FIRST_COMBAT_DAMAGE);
execute();
}
catch (AssertionError e) {
assert(e.getMessage().contains("Missing CHOICE def for turn 1, step FIRST_COMBAT_DAMAGE, PlayerA"));
Assert.assertTrue(
"catch wrong exception: " + e.getMessage(),
e.getMessage().contains("Found wrong choice command") && e.getMessage().contains("In Garruk's Wake")
);
return;
}
fail("Was able to pick [[In Garruk's Wake]] but it costs more than 2");

View file

@ -0,0 +1,63 @@
package org.mage.test.cards.single.m19;
import mage.abilities.mana.AnyColorManaAbility;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class AlpineMoonTest extends CardTestPlayerBase {
/*
Alpine Moon
{R}
Enchantment
As this enchantment enters, choose a nonbasic land card name.
Lands your opponents control with the chosen name lose all land types and abilities, and they gain {T}: Add one mana of any color.
*/
private static final String alpine = "Alpine Moon";
/*
Urborg, Tomb of Yawgmoth
Legendary Land
Each land is a Swamp in addition to its other land types.
*/
private static final String urborg = "Urborg, Tomb of Yawgmoth";
@Test
public void testAlpineMoonAfterUrborg() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, urborg);
addCard(Zone.BATTLEFIELD, playerB, alpine);
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
addCard(Zone.BATTLEFIELD, playerA, "Island");
setChoice(playerB, urborg);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertNotSubtype(urborg, SubType.SWAMP);
assertSubtype("Mountain", SubType.SWAMP);
assertSubtype("Island", SubType.SWAMP);
assertAbility(playerA, urborg, new AnyColorManaAbility(), true);
}
@Test
public void testAlpineMoonBeforeUrborg() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, urborg);
addCard(Zone.BATTLEFIELD, playerA, alpine);
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
addCard(Zone.BATTLEFIELD, playerB, "Island");
setChoice(playerA, urborg);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertNotSubtype(urborg, SubType.SWAMP);
assertSubtype("Mountain", SubType.SWAMP);
assertSubtype("Island", SubType.SWAMP);
assertAbility(playerB, urborg, new AnyColorManaAbility(), true);
}
}

View file

@ -10,6 +10,14 @@ public class EnthrallingHoldTest extends CardTestPlayerBase {
@Test
public void testTappedTarget_untapped_doesNotFizzle() {
// Traxos, Scourge of Kroog enters the battlefield tapped and doesn't untap during your untap step.
// The middle ability of Enthralling Hold affects only the choice of target as the spell is cast.
// If the creature becomes untapped before the spell resolves, it still resolves. If a player is
// allowed to change the spell's target while it's on the stack, they may choose an untapped
// creature. If you put Enthralling Hold onto the battlefield without casting it, you may attach
// it to an untapped creature.
// (2020-06-23)
addCard(Zone.BATTLEFIELD, playerB, "Traxos, Scourge of Kroog");
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
@ -26,10 +34,11 @@ public class EnthrallingHoldTest extends CardTestPlayerBase {
*/
addCard(Zone.HAND, playerA, "Twiddle");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Enthralling Hold", "Traxos, Scourge of Kroog");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Twiddle", "Traxos, Scourge of Kroog");
setChoice(playerA, true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Enthralling Hold");
addTarget(playerA, "Traxos, Scourge of Kroog");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Twiddle");
addTarget(playerA, "Traxos, Scourge of Kroog");
setChoice(playerA, true); // untap traxos
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_COMBAT);

View file

@ -100,7 +100,6 @@ public class BarrowgoyfTest extends CardTestPlayerBase {
attack(1, playerA, barrowgoyf, playerB);
setChoice(playerA, true);
setChoice(playerA, TestPlayer.CHOICE_SKIP); // decide to not return. There was no choice anyway.
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();

View file

@ -0,0 +1,98 @@
package org.mage.test.cards.single.mat;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author correl
*/
public class NahiriForgedInFuryTest extends CardTestPlayerBase {
/**
* {@link mage.cards.n.NahiriForgedInFury} {4}{R}{W}
* Legendary Creature - Kor Artificer
*
* Affinity for Equipment
*
* Whenever an equipped creature you control attacks, exile the top card of
* your library. You may play that card this turn. You may cast Equipment
* spells this way without paying their mana costs.
*/
private static final String nahiri = "Nahiri, Forged in Fury";
private final String boots = "Swiftfoot Boots";
private final String cleaver = "The Reaver Cleaver";
private final String giant = "Hill Giant";
private final String greaves = "Lightning Greaves";
private final String lions = "Savannah Lions";
private final String sword = "Sword of Feast and Famine";
@Test
public void test_CostReducedByEquipment() {
// Nahiri in hand, four equipment in play, and enough to pay RW
addCard(Zone.HAND, playerA, nahiri);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerA, boots);
addCard(Zone.BATTLEFIELD, playerA, cleaver);
addCard(Zone.BATTLEFIELD, playerA, greaves);
addCard(Zone.BATTLEFIELD, playerA, sword);
// Cast for RW (Reduced by 4)
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nahiri);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
}
@Test
public void test_EquippedAttackTriggers() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, nahiri);
addCard(Zone.BATTLEFIELD, playerA, lions);
addCard(Zone.BATTLEFIELD, playerA, giant);
addCard(Zone.BATTLEFIELD, playerA, boots);
addCard(Zone.BATTLEFIELD, playerA, greaves);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {0}", lions);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {1}", giant);
// Attack with three creatures, two of which are equipped
attack(1, playerA, nahiri);
attack(1, playerA, lions);
attack(1, playerA, giant);
// Order the 2 Nahiri triggers
setChoice(playerA, "Whenever an equipped creature you control attacks");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
// Triggered twice, exiling two cards
assertExileCount(playerA, 2);
}
@Test
public void test_CanCastExiledEquipmentForFree() {
addCard(Zone.BATTLEFIELD, playerA, nahiri);
addCard(Zone.BATTLEFIELD, playerA, greaves);
skipInitShuffling();
addCard(Zone.LIBRARY, playerA, sword);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {0}", nahiri);
// Attack with one equipped creature, exiling the sword
attack(1, playerA, nahiri);
// Cast sword for free
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, sword);
setStrictChooseMode(true);
setStopAt(2, PhaseStep.END_TURN);
execute();
}
}

View file

@ -0,0 +1,60 @@
package org.mage.test.cards.single.mh2;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class AeveProgenitorOozeTest extends CardTestPlayerBase {
/*
Aeve, Progenitor Ooze
{2}{G}{G}{G}
Legendary Creature Ooze
Storm (When you cast this spell, copy it for each spell cast before it this turn. Copies become tokens.)
Aeve isnt legendary if its a token.
Aeve enters with a +1/+1 counter on it for each other Ooze you control.
2/2
*/
private static final String aeve = "Aeve, Progenitor Ooze";
/*
Lightning Bolt
{R}
Instant
Lightning Bolt deals 3 damage to any target.
*/
public static final String bolt = "Lightning Bolt";
@Test
public void testAeve() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, aeve);
addCard(Zone.HAND, playerA, bolt);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 5);
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, playerB);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aeve);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, aeve, 2);
assertTokenCount(playerA, aeve, 1);
for (Permanent permanent : currentGame.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, playerA.getId(), currentGame)) {
if (permanent.getName().equals(aeve)) {
if (permanent instanceof PermanentToken) {
Assert.assertEquals(0, permanent.getCounters(currentGame).getCount(CounterType.P1P1));
} else {
Assert.assertEquals(1, permanent.getCounters(currentGame).getCount(CounterType.P1P1));
}
}
}
}
}

View file

@ -6,6 +6,7 @@ import mage.counters.CounterType;
import mage.players.Player;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -82,6 +83,7 @@ public class IzzetGeneratoriumTest extends CardTestPlayerBase {
checkPlayableAbility("1: condition not met before losing counters", 2, PhaseStep.UPKEEP, playerA, "{T}: Draw", false);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Final Act");
setModeChoice(playerB, "5"); // each opponent loses all counters.
setModeChoice(playerB, TestPlayer.MODE_SKIP);
waitStackResolved(2, PhaseStep.PRECOMBAT_MAIN);
runCode("energy counter is 0", 2, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> checkEnergyCount(info, player, 0));
checkPlayableAbility("2: condition met after losing counters", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw", true);

View file

@ -183,6 +183,7 @@ public class NethergoyfTest extends CardTestPlayerBaseWithAIHelps {
// The same is true for permanent spells you control and nonland permanent cards you own that arent on the battlefield.
addCard(Zone.HAND, playerA, "Encroaching Mycosynth");
// AI must be able to choose good targets combination
aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, playerA);
setStopAt(1, PhaseStep.BEGIN_COMBAT);

View file

@ -0,0 +1,59 @@
package org.mage.test.cards.single.mir;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class PhyrexianDreadnoughtTest extends CardTestPlayerBase {
/*
Phyrexian Dreadnought
{1}
Artifact Creature Phyrexian Dreadnought
Trample
When this creature enters, sacrifice it unless you sacrifice any number of creatures with total power 12 or greater.
12/12
*/
private static final String phyrexianDreadnought = "Phyrexian Dreadnought";
@Test
public void testPhyrexianDreadnoughtCanPay() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, phyrexianDreadnought);
addCard(Zone.BATTLEFIELD, playerA, phyrexianDreadnought + "@sacTarget");
addCard(Zone.BATTLEFIELD, playerA, "Island");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, phyrexianDreadnought);
setChoice(playerA, true);
setChoice(playerA, "@sacTarget");
setChoice(playerA, TestPlayer.CHOICE_SKIP);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, phyrexianDreadnought, 1);
assertGraveyardCount(playerA, phyrexianDreadnought, 1);
}
@Test
public void testPhyrexianDreadnoughtCantPay() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, phyrexianDreadnought);
addCard(Zone.BATTLEFIELD, playerA, "Island");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, phyrexianDreadnought);
setStopAt(1, PhaseStep.END_TURN);
setChoice(playerA, false);
execute();
assertGraveyardCount(playerA, phyrexianDreadnought, 1);
}
}

View file

@ -0,0 +1,93 @@
package org.mage.test.cards.single.mkc;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
import static org.junit.Assert.assertTrue;
/**
*
* @author Jmlundeen
*/
public class SereneSleuthTest extends CardTestPlayerBase {
/*
Serene Sleuth
{1}{W}
Creature - Human Detective
When Serene Sleuth enters the battlefield, investigate.
At the beginning of combat on your turn, investigate for each goaded creature you control. Then each creature you control is no longer goaded.
2/2
*/
private static final String sereneSleuth = "Serene Sleuth";
/*
Baeloth Barrityl, Entertainer
{4}{R}
Legendary Creature - Elf Shaman
Creatures your opponents control with power less than Baeloth Barrityl's power are goaded.
Whenever a goaded attacking or blocking creature dies, you create a Treasure token.
Choose a Background
2/5
*/
private static final String baelothBarritylEntertainer = "Baeloth Barrityl, Entertainer";
/*
Fugitive Wizard
{U}
Creature - Human Wizard
1/1
*/
private static final String fugitiveWizard = "Fugitive Wizard";
/*
Cloudshift
{W}
Instant
Exile target creature you control, then return that card to the battlefield under your control.
*/
private static final String cloudshift = "Cloudshift";
@Test
public void testSereneSleuth() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, baelothBarritylEntertainer);
addCard(Zone.BATTLEFIELD, playerA, fugitiveWizard);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.HAND, playerA, sereneSleuth);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sereneSleuth);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Clue Token", 1 + 1);
assertTrue("fugitive wizard is not goaded", getPermanent(fugitiveWizard).getGoadingPlayers().isEmpty());
}
@Test
public void testSereneSleuthReGoaded() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, baelothBarritylEntertainer);
addCard(Zone.BATTLEFIELD, playerA, fugitiveWizard);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerB, "Plains");
addCard(Zone.HAND, playerA, sereneSleuth);
addCard(Zone.HAND, playerB, cloudshift);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sereneSleuth);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, cloudshift, baelothBarritylEntertainer);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, "Clue Token", 1 + 1 + 1);
assertTrue("fugitive wizard is goaded", getPermanent(fugitiveWizard).getGoadingPlayers().isEmpty());
}
}

View file

@ -1,9 +1,13 @@
package org.mage.test.cards.single.mkm;
import mage.abilities.Mode;
import mage.abilities.effects.common.ExileAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
@ -21,6 +25,11 @@ public class KayaSpiritsJusticeTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, "Fyndhorn Elves");
addCard(Zone.HAND, playerA, "Thraben Inspector");
addCard(Zone.HAND, playerA, "Astrid Peth");
// Choose one or more
// Exile all artifacts.
// Exile all creatures.
// Exile all enchantments.
// Exile all graveyards.
addCard(Zone.HAND, playerA, "Farewell");
// Creates a Clue token
@ -35,6 +44,7 @@ public class KayaSpiritsJusticeTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Farewell");
setModeChoice(playerA, "2");
setModeChoice(playerA, "4");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
// Kaya's first ability triggers twice, so choose which is put on the stack:

View file

@ -1,6 +1,7 @@
package org.mage.test.cards.single.mom;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
import mage.constants.PhaseStep;
@ -47,6 +48,7 @@ public class InvasionOfFioraTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, invasion);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
setModeChoice(playerA, "1");
setModeChoice(playerA, TestPlayer.MODE_SKIP);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
checkPermanentCount("Battle on battlefield", 1, PhaseStep.PRECOMBAT_MAIN, playerA, invasion, 1);

View file

@ -0,0 +1,54 @@
package org.mage.test.cards.single.neo;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
import java.util.Arrays;
public class EaterOfVirtueTest extends CardTestPlayerBase {
/*
Eater of Virtue
{1}
Legendary Artifact Equipment
Whenever equipped creature dies, exile it.
Equipped creature gets +2/+0.
As long as a card exiled with Eater of Virtue has flying, equipped creature has flying.
The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, protection, reach, trample, and vigilance.
Equip {1}
*/
public static final String eaterOfVirtue = "Eater of Virtue";
@Test
public void testEaterOfVirtue() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, eaterOfVirtue);
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
addCard(Zone.BATTLEFIELD, playerA, "Adult Gold Dragon"); // Flying, Lifelink, Haste
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears");
addCard(Zone.HAND, playerB, "Doom Blade");
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Adult Gold Dragon");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Doom Blade", "Adult Gold Dragon");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Equip", "Balduvian Bears");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAbilities(playerA, "Balduvian Bears", Arrays.asList(FlyingAbility.getInstance(), LifelinkAbility.getInstance(), HasteAbility.getInstance()));
}
}

View file

@ -0,0 +1,58 @@
package org.mage.test.cards.single.one;
import mage.cards.Card;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestCommanderDuelBase;
import java.util.List;
import static org.junit.Assert.assertTrue;
public class EncroachingMycosynthTest extends CardTestCommanderDuelBase {
/*
Encroaching Mycosynth
{3}{U}
Artifact
Nonland permanents you control are artifacts in addition to their other types.
The same is true for permanent spells you control and nonland permanent cards you own that arent on the battlefield.
*/
private static final String encroachingMycosynth = "Encroaching Mycosynth";
private static final String balduvianBears = "Balduvian Bears";
@Test
public void testEncroachingMycosynth() {
setStrictChooseMode(true);
addCard(Zone.GRAVEYARD, playerA, balduvianBears);
addCard(Zone.HAND, playerA, balduvianBears, 2);
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.BATTLEFIELD, playerA, encroachingMycosynth);
addCard(Zone.EXILED, playerA, balduvianBears);
addCard(Zone.LIBRARY, playerA, balduvianBears);
addCard(Zone.COMMAND, playerA, balduvianBears);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, balduvianBears);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertType(balduvianBears, CardType.ARTIFACT, true);
List<Card> cards = getHandCards(playerA);
cards.addAll(getLibraryCards(playerA));
cards.addAll(getCommandCards(playerA));
cards.addAll(getExiledCards(playerA));
cards.addAll(getLibraryCards(playerA));
for (Card card : cards) {
if (!card.isLand(currentGame)) {
assertTrue(card.getCardType(currentGame).contains(CardType.ARTIFACT));
}
}
}
}

View file

@ -0,0 +1,57 @@
package org.mage.test.cards.single.one;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class NahirisSacrificeTest extends CardTestPlayerBase {
/*
Nahiri's Sacrifice
{1}{R}
Sorcery
As an additional cost to cast this spell, sacrifice an artifact or creature with mana value X.
Nahiris Sacrifice deals X damage divided as you choose among any number of target creatures.
*/
private static final String nahirisSacrifice = "Nahiri's Sacrifice";
private static final String balduvianBears = "Balduvian Bears";
@Test
public void testNahirisSacrifice() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, nahirisSacrifice);
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerB, balduvianBears + "@bearsB");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nahirisSacrifice, "@bearsB");
setChoice(playerA, "X=2");
setChoice(playerA, balduvianBears);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerB, balduvianBears, 1);
assertGraveyardCount(playerA, nahirisSacrifice, 1);
}
@Test
public void testNahirisSacrificePrevented() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, nahirisSacrifice);
addCard(Zone.BATTLEFIELD, playerA, balduvianBears);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerB, balduvianBears + "@bearsB");
addCard(Zone.BATTLEFIELD, playerB, "Yasharn, Implacable Earth");
checkPlayableAbility("Can't cast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + nahirisSacrifice, false);
setStopAt(1, PhaseStep.END_TURN);
execute();
}
}

View file

@ -0,0 +1,57 @@
package org.mage.test.cards.single.shm;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class ElsewhereFlaskTest extends CardTestPlayerBase {
/*
Elsewhere Flask
{2}
Artifact
When this artifact enters, draw a card.
Sacrifice this artifact: Choose a basic land type. Each land you control becomes that type until end of turn.
*/
private static final String elsewhereFlask = "Elsewhere Flask";
@Test
public void testElsewhereFlask() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, elsewhereFlask);
addCard(Zone.BATTLEFIELD, playerA, "Island");
addCard(Zone.BATTLEFIELD, playerA, "Forest");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
setChoice(playerA, "Swamp");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertType("Island", CardType.LAND, SubType.SWAMP);
assertType("Forest", CardType.LAND, SubType.SWAMP);
}
@Test
public void testElsewhereFlask2() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, elsewhereFlask);
addCard(Zone.BATTLEFIELD, playerA, "Island");
addCard(Zone.BATTLEFIELD, playerA, "Forest");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice");
setChoice(playerA, "Swamp");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertType("Island", CardType.LAND, SubType.ISLAND);
assertType("Forest", CardType.LAND, SubType.FOREST);
}
}

View file

@ -0,0 +1,53 @@
package org.mage.test.cards.single.spm;
import mage.abilities.keyword.MenaceAbility;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class AlienSymbiosisTest extends CardTestPlayerBase {
/*
Alien Symbiosis
{1}{B}
Enchantment - Aura
Enchant creature
Enchanted creature gets +1/+1, has menace, and is a Symbiote in addition to its other types.
You may cast this card from your graveyard by discarding a card in addition to paying its other costs.
*/
private static final String alienSymbiosis = "Alien Symbiosis";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
@Test
public void testAlienSymbiosisCastFromGrave() {
setStrictChooseMode(true);
addCard(Zone.GRAVEYARD, playerA, alienSymbiosis);
addCard(Zone.HAND, playerA, "Island");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
addCard(Zone.BATTLEFIELD, playerA, bearCub);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, alienSymbiosis, bearCub);
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPowerToughness(playerA, bearCub, 3, 3);
assertAbilityCount(playerA, bearCub, MenaceAbility.class, 1);
assertSubtype(bearCub, SubType.SYMBIOTE);
}
}

View file

@ -0,0 +1,53 @@
package org.mage.test.cards.single.spm;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class ArachnePsionicWeaverTest extends CardTestPlayerBase {
/*
Arachne, Psionic Weaver
{2}{W}
Legendary Creature - Spider Human Hero
Web-slinging {W}
As Arachne enters, look at target opponent's hand, then choose a noncreature card type.
Spells of the chosen type cost {1} more to cast.
3/3
*/
private static final String arachnePsionicWeaver = "Arachne, Psionic Weaver";
/*
Tormod's Crypt
{0}
Artifact
{tap}, Sacrifice Tormod's Crypt: Exile all cards from target player's graveyard.
*/
private static final String tormodsCrypt = "Tormod's Crypt";
@Test
public void testArachnePsionicWeaver() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, arachnePsionicWeaver);
addCard(Zone.HAND, playerA, tormodsCrypt);
addCard(Zone.HAND, playerB, tormodsCrypt);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.BATTLEFIELD, playerB, "Plains");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, arachnePsionicWeaver);
setChoice(playerA, CardType.ARTIFACT.toString());
checkPlayableAbility("Player A can't cast Tormod's", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast " + tormodsCrypt, false);
checkPlayableAbility("Player B can cast Tormod's", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cast " + tormodsCrypt, true);
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
execute();
}
}

View file

@ -0,0 +1,65 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class BlackCatCunningThiefTest extends CardTestPlayerBase {
/*
Black Cat, Cunning Thief
{3}{B}{B}
Legendary Creature - Human Rogue Villain
When Black Cat enters, look at the top nine cards of target opponent's library, exile two of them face down, then put the rest on the bottom of their library in a random order. You may play the exiled cards for as long as they remain exiled. Mana of any type can be spent to cast spells this way.
2/3
*/
private static final String blackCatCunningThief = "Black Cat, Cunning Thief";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
/*
Fugitive Wizard
{U}
Creature - Human Wizard
1/1
*/
private static final String fugitiveWizard = "Fugitive Wizard";
@Test
public void testBlackCatCunningThief() {
setStrictChooseMode(true);
skipInitShuffling();
addCard(Zone.HAND, playerA, blackCatCunningThief);
addCard(Zone.LIBRARY, playerB, bearCub);
addCard(Zone.LIBRARY, playerB, fugitiveWizard);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, blackCatCunningThief);
addTarget(playerA, playerB);
setChoice(playerA, bearCub);
setChoice(playerA, fugitiveWizard);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bearCub, true);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, fugitiveWizard);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, bearCub, 1);
assertPermanentCount(playerA, fugitiveWizard, 1);
}
}

View file

@ -0,0 +1,60 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class CarnageCrimsonChaosTest extends CardTestPlayerBase {
/*
Carnage, Crimson Chaos
{2}{B}{R}
Legendary Creature - Symbiote Villain
Trample
When Carnage enters, return target creature card with mana value 3 or less from your graveyard to the battlefield. It gains "This creature attacks each combat if able" and "When this creature deals combat damage to a player, sacrifice it."
Mayhem {B}{R}
4/3
*/
private static final String carnageCrimsonChaos = "Carnage, Crimson Chaos";
/*
Concordant Crossroads
{G}
World Enchantment
All creatures have haste.
*/
private static final String concordantCrossroads = "Concordant Crossroads";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
@Test
public void testCarnageCrimsonChaos() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, concordantCrossroads);
addCard(Zone.HAND, playerA, carnageCrimsonChaos);
addCard(Zone.GRAVEYARD, playerA, bearCub);
addCard(Zone.BATTLEFIELD, playerA, "Badlands", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, carnageCrimsonChaos);
addTarget(playerA, bearCub);
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertGraveyardCount(playerA, bearCub, 1);
assertLife(playerB, 20 - 2);
}
}

View file

@ -0,0 +1,49 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestCommander4Players;
/**
*
* @author Jmlundeen
*/
public class CheeringCrowdTest extends CardTestCommander4Players {
/*
Cheering Crowd
{1}{R/G}
Creature - Human Citizen
At the beginning of each player's first main phase, that player may put a +1/+1 counter on this creature. If they do, they add {C} for each counter on it.
2/2
*/
private static final String cheeringCrowd = "Cheering Crowd";
@Test
public void testCheeringCrowd() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, cheeringCrowd);
setChoice(playerA, true);
setChoice(playerB, true);
setChoice(playerC, true);
setChoice(playerD, true);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
checkManaPool("PlayerA should have 1 Mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "C", 1);
waitStackResolved(2, PhaseStep.PRECOMBAT_MAIN, playerD);
checkManaPool("PlayerD should have 2 Mana", 2, PhaseStep.PRECOMBAT_MAIN, playerD, "C", 2);
waitStackResolved(3, PhaseStep.PRECOMBAT_MAIN, playerC);
checkManaPool("PlayerC should have 3 Mana", 3, PhaseStep.PRECOMBAT_MAIN, playerC, "C", 3);
waitStackResolved(4, PhaseStep.PRECOMBAT_MAIN, playerB);
checkManaPool("PlayerB should have 4 Mana", 4, PhaseStep.PRECOMBAT_MAIN, playerB, "C", 4);
setStopAt(4, PhaseStep.PRECOMBAT_MAIN);
execute();
assertCounterCount(playerA, cheeringCrowd, CounterType.P1P1, 4);
}
}

View file

@ -0,0 +1,65 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class ElectroAssaultingBatteryTest extends CardTestPlayerBase {
/*
Electro, Assaulting Battery
{1}{R}{R}
Legendary Creature - Human Villain
Flying
You don't lose unspent red mana as steps and phases end.
Whenever you cast an instant or sorcery spell, add {R}.
When Electro leaves the battlefield, you may pay {X}. When you do, he deals X damage to target player.
2/3
*/
private static final String electroAssaultingBattery = "Electro, Assaulting Battery";
/*
Pyretic Ritual
{1}{R}
Instant
Add {R}{R}{R}.
*/
private static final String pyreticRitual = "Pyretic Ritual";
/*
Lightning Bolt
{R}
Instant
Lightning Bolt deals 3 damage to any target.
*/
private static final String lightningBolt = "Lightning Bolt";
@Test
public void testElectroAssaultingBattery() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, electroAssaultingBattery);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
addCard(Zone.HAND, playerA, pyreticRitual);
addCard(Zone.HAND, playerB, lightningBolt);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, pyreticRitual);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, lightningBolt, electroAssaultingBattery);
setChoice(playerA, true);
setChoiceAmount(playerA, 4); // 3 from ritual + 1 from electro
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerB, 20 - 4);
}
}

View file

@ -0,0 +1,59 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class GwenomRemorselessTest extends CardTestPlayerBase {
/*
Gwenom, Remorseless
{3}{B}{B}
Legendary Creature - Symbiote Spider Hero
Deathtouch, lifelink
Whenever Gwenom attacks, until end of turn you may look at the top card of your library any time and you may play cards from the top of your library. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost.
4/4
*/
private static final String gwenomRemorseless = "Gwenom, Remorseless";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
@Test
public void testGwenomRemorseless() {
setStrictChooseMode(true);
skipInitShuffling();
addCard(Zone.BATTLEFIELD, playerA, gwenomRemorseless);
addCard(Zone.LIBRARY, playerA, "Island");
addCard(Zone.LIBRARY, playerA, bearCub, 2);
addCard(Zone.LIBRARY, playerA, "Forest");
attack(1, playerA, gwenomRemorseless);
playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Forest");
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bearCub);
// effect ends at end of turn
checkPlayableAbility("Can't play top card", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Play Island", false);
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerA, bearCub, 1);
assertPermanentCount(playerA, gwenomRemorseless, 1);
assertPermanentCount(playerA, "Forest", 1);
assertLife(playerB, 20 - 4);
assertLife(playerA, 20 + 4 - 2);
}
}

View file

@ -0,0 +1,55 @@
package org.mage.test.cards.single.spm;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class HydroManFluidFelonTest extends CardTestPlayerBase {
/*
Hydro-Man, Fluid Felon
{U}{U}
Legendary Creature - Elemental Villain
Whenever you cast a blue spell, if Hydro-Man is a creature, he gets +1/+1 until end of turn.
At the beginning of your end step, untap Hydro-Man. Until your next turn, he becomes a land and gains "{T}: Add {U}."
2/2
*/
private static final String hydroManFluidFelon = "Hydro-Man, Fluid Felon";
/*
Fugitive Wizard
{U}
Creature - Human Wizard
1/1
*/
private static final String fugitiveWizard = "Fugitive Wizard";
@Test
public void testHydroManFluidFelon() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, fugitiveWizard);
addCard(Zone.BATTLEFIELD, playerA, hydroManFluidFelon);
addCard(Zone.BATTLEFIELD, playerA, "Island");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, fugitiveWizard, true);
checkPT("Hydro-Man is boosted", 1, PhaseStep.PRECOMBAT_MAIN, playerA, hydroManFluidFelon, 3, 3);
attack(1, playerA, hydroManFluidFelon);
setStopAt(2, PhaseStep.UPKEEP);
execute();
assertType(hydroManFluidFelon, CardType.LAND, true);
assertNotType(hydroManFluidFelon, CardType.CREATURE);
assertTapped(hydroManFluidFelon, false);
}
}

View file

@ -0,0 +1,78 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class InterdimensionalWebWatchTest extends CardTestPlayerBase {
/*
Interdimensional Web Watch
{4}
Artifact
When this artifact enters, exile the top two cards of your library. Until the end of your next turn, you may play those cards.
{T}: Add two mana in any combination of colors. Spend this mana only to cast spells from exile.
*/
private static final String interdimensionalWebWatch = "Interdimensional Web Watch";
/*
Lightning Bolt
{R}
Instant
Lightning Bolt deals 3 damage to any target.
*/
private static final String lightningBolt = "Lightning Bolt";
/*
Fugitive Wizard
{U}
Creature - Human Wizard
1/1
*/
private static final String fugitiveWizard = "Fugitive Wizard";
/*
Shock
{R}
Instant
Shock deals 2 damage to any target.
*/
private static final String shock = "Shock";
@Test
public void testInterdimensionalWebWatch() {
setStrictChooseMode(true);
skipInitShuffling();
addCard(Zone.LIBRARY, playerA, lightningBolt);
addCard(Zone.LIBRARY, playerA, fugitiveWizard);
addCard(Zone.HAND, playerA, interdimensionalWebWatch);
addCard(Zone.HAND, playerA, shock);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, interdimensionalWebWatch, true);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add two");
setChoiceAmount(playerA, 0, 1, 0, 1, 0); // Add {U}{R}
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPlayableAbility("Can't cast shock from hand", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
"Cast " + shock, false);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, lightningBolt, true);
addTarget(playerA, playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, fugitiveWizard);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerB, 20 - 3);
assertPermanentCount(playerA, fugitiveWizard, 1);
}
}

View file

@ -0,0 +1,65 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class JackalGeniusGeneticistTest extends CardTestPlayerBase {
/*
Jackal, Genius Geneticist
{G}{U}
Legendary Creature - Human Scientist Villain
Trample
Whenever you cast a creature spell with mana value equal to Jackal's power, copy that spell, except the copy isn't legendary. Then put a +1/+1 counter on Jackal.
1/1
*/
private static final String jackalGeniusGeneticist = "Jackal, Genius Geneticist";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
/*
Ragavan, Nimble Pilferer
{R}
Legendary Creature - Monkey Pirate
Whenever Ragavan, Nimble Pilferer deals combat damage to a player, create a Treasure token and exile the top card of that player's library. Until end of turn, you may cast that card.
Dash {1}{R}
2/1
*/
private static final String ragavanNimblePilferer = "Ragavan, Nimble Pilferer";
@Test
public void testJackalGeniusGeneticist() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, jackalGeniusGeneticist);
addCard(Zone.BATTLEFIELD, playerA, "Taiga", 3);
addCard(Zone.HAND, playerA, ragavanNimblePilferer);
addCard(Zone.HAND, playerA, bearCub);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, ragavanNimblePilferer);
setChoice(playerA, "Cast with no");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bearCub);
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerA, ragavanNimblePilferer, 2);
assertPermanentCount(playerA, bearCub, 2);
assertCounterCount(playerA, jackalGeniusGeneticist, CounterType.P1P1, 2);
}
}

View file

@ -0,0 +1,122 @@
package org.mage.test.cards.single.spm;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.UntapAllControllerEffect;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.common.FilterCreaturePermanent;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class LadyOctopusInspiredInventorTest extends CardTestPlayerBase {
/*
Lady Octopus, Inspired Inventor
{U}
Legendary Creature - Human Scientist Villain
Whenever you draw your first or second card each turn, put an ingenuity counter on Lady Octopus.
{T}: You may cast an artifact spell from your hand with mana value less than or equal to the number of ingenuity counters on Lady Octopus without paying its mana cost.
*/
private static final String ladyOctopusInspiredInventor = "Lady Octopus, Inspired Inventor";
/*
Aether Vial
{1}
Artifact
At the beginning of your upkeep, you may put a charge counter on Aether Vial.
{T}: You may put a creature card with converted mana cost equal to the number of charge counters on ther Vial from your hand onto the battlefield.
*/
private static final String aetherVial = "Aether Vial";
/*
Tormod's Crypt
{0}
Artifact
{tap}, Sacrifice Tormod's Crypt: Exile all cards from target player's graveyard.
*/
private static final String tormodsCrypt = "Tormod's Crypt";
/*
Howling Mine
{2}
Artifact
At the beginning of each player's draw step, if Howling Mine is untapped, that player draws an additional card.
*/
private static final String howlingMine = "Howling Mine";
@Test
public void testLadyOctopusInspiredInventor() {
setStrictChooseMode(true);
addCustomCardWithAbility("untap all creatures", playerA, new SimpleActivatedAbility(
new UntapAllControllerEffect(new FilterCreaturePermanent()),
new ManaCostsImpl<>("")
));
addCustomCardWithAbility("draw a card", playerA, new SimpleActivatedAbility(
new DrawCardSourceControllerEffect(1),
new ManaCostsImpl<>("")
));
addCard(Zone.BATTLEFIELD, playerA, ladyOctopusInspiredInventor);
addCard(Zone.HAND, playerA, aetherVial);
addCard(Zone.HAND, playerA, tormodsCrypt);
addCard(Zone.HAND, playerA, howlingMine);
activateDrawCardAndUntap(); // Tormod's crypt
activateDrawCardAndUntap(); // Aether Vial
activateDrawCardAndUntap(); // Howling Mine
setStopAt(1, PhaseStep.END_TURN);
execute();
assertCounterCount(playerA, ladyOctopusInspiredInventor, CounterType.INGENUITY, 2);
assertHandCount(playerA, 3);
}
private void activateDrawCardAndUntap() {
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: You may cast");
setChoice(playerA, true);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "draw a");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "untap all");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
}
@Test
public void testLadyOctopusInspiredInventorChoose() {
setStrictChooseMode(true);
addCustomCardWithAbility("draw a card", playerA, new SimpleActivatedAbility(
new DrawCardSourceControllerEffect(3),
new ManaCostsImpl<>("")
));
addCard(Zone.BATTLEFIELD, playerA, ladyOctopusInspiredInventor);
addCard(Zone.HAND, playerA, aetherVial);
addCard(Zone.HAND, playerA, tormodsCrypt);
addCard(Zone.HAND, playerA, howlingMine);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "draw ");
setChoice(playerA, "Whenever you draw your first"); // trigger stack
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: You may cast");
setChoice(playerA, tormodsCrypt);
setChoice(playerA, true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertCounterCount(playerA, ladyOctopusInspiredInventor, CounterType.INGENUITY, 2);
assertHandCount(playerA, 3 + 2);
}
}

View file

@ -0,0 +1,69 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestCommander4Players;
import static org.junit.Assert.assertTrue;
/**
*
* @author Jmlundeen
*/
public class MaximumCarnageTest extends CardTestCommander4Players {
/*
Maximum Carnage
{4}{R}
Enchantment - Saga
(As this Saga enters step and after your draw step, add a lore counter. Sacrifice after III.)
I -- Until your next turn, each creature attacks each combat if able and attacks a player other than you if able.
II -- Add {R}{R}{R}.
III -- This Saga deals 5 damage to each opponent.
*/
private static final String maximumCarnage = "Maximum Carnage";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
@Test
public void testMaximumCarnage() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, maximumCarnage);
addCard(Zone.BATTLEFIELD, playerB, bearCub);
addCard(Zone.BATTLEFIELD, playerD, bearCub);
addTarget(playerD, playerC); // must attack
addTarget(playerB, playerD); // must attack
setStopAt(4, PhaseStep.END_TURN);
execute();
}
@Test
public void testMaximumCarnageCantAttackController() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, maximumCarnage);
addCard(Zone.BATTLEFIELD, playerB, bearCub);
addCard(Zone.BATTLEFIELD, playerD, bearCub);
addTarget(playerD, playerA); // must attack
setStopAt(4, PhaseStep.END_TURN);
try {
execute();
} catch (AssertionError e) {
assertTrue("Shouldn't be able to attack playerA",
e.getMessage().contains("[targetPlayer=PlayerA], but not used"));
}
}
}

View file

@ -0,0 +1,62 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Jmlundeen
*/
public class MisterNegativeTest extends CardTestPlayerBase {
/*
Mister Negative
{5}{W}{B}
Legendary Creature - Human Villain
Vigilance, lifelink
When Mister Negative enters, you may exchange your life total with target opponent. If you lose life this way, draw that many cards.
5/5
*/
private static final String misterNegative = "Mister Negative";
@Test
public void testMisterNegative() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, misterNegative);
addCard(Zone.BATTLEFIELD, playerA, "Scrubland", 7);
setLife(playerB, 15);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, misterNegative);
addTarget(playerA, playerB);
setChoice(playerA, true);
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
assertHandCount(playerA, 5);
assertLife(playerA, 15);
assertLife(playerB, 20);
}
@Test
public void testMisterNegativeNoDraw() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, misterNegative);
addCard(Zone.BATTLEFIELD, playerA, "Scrubland", 7);
setLife(playerB, 21);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, misterNegative);
addTarget(playerA, playerB);
setChoice(playerA, true);
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
execute();
assertHandCount(playerA, 0);
assertLife(playerA, 21);
assertLife(playerB, 20);
}
}

View file

@ -0,0 +1,40 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class MultiversalPassageTest extends CardTestPlayerBase {
/*
Multiversal Passage
Land
As this land enters, choose a basic land type. Then you may pay 2 life. If you don't, it enters tapped.
This land is the chosen type.
*/
private static final String multiversalPassage = "Multiversal Passage";
@Test
public void testMultiversalPassage() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, multiversalPassage);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, multiversalPassage);
setChoice(playerA, "Swamp");
setChoice(playerA, true); // untapped
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertSubtype(multiversalPassage, SubType.SWAMP);
assertLife(playerA, 20 - 2);
}
}

View file

@ -0,0 +1,52 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class OscorpIndustriesTest extends CardTestPlayerBase {
/*
Oscorp Industries
Land
This land enters tapped.
When this land enters from a graveyard, you lose 2 life.
{T}: Add {U}, {B}, or {R}.
Mayhem
*/
private static final String oscorpIndustries = "Oscorp Industries";
/*
Thought Courier
{1}{U}
Creature - Human Wizard
{tap}: Draw a card, then discard a card.
1/1
*/
private static final String thoughtCourier = "Thought Courier";
@Test
public void testOscorpIndustries() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, oscorpIndustries);
addCard(Zone.BATTLEFIELD, playerA, thoughtCourier);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw");
setChoice(playerA, oscorpIndustries);
playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, oscorpIndustries + " with Mayhem");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 20 - 2);
assertPermanentCount(playerA, oscorpIndustries, 1);
}
}

View file

@ -0,0 +1,79 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestCommander4Players;
/**
*
* @author Jmlundeen
*/
public class ParkerLuckTest extends CardTestCommander4Players {
/*
Parker Luck
{2}{B}
Enchantment
At the beginning of your end step, two target players each reveal the top card of their library. They each lose life equal to the mana value of the card revealed by the other player. Then they each put the card they revealed into their hand.
*/
private static final String parkerLuck = "Parker Luck";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
/*
Fugitive Wizard
{U}
Creature - Human Wizard
1/1
*/
private static final String fugitiveWizard = "Fugitive Wizard";
@Test
public void testParkerLuck() {
setStrictChooseMode(true);
skipInitShuffling();
addCard(Zone.BATTLEFIELD, playerA, parkerLuck);
addCard(Zone.LIBRARY, playerD, bearCub);
addCard(Zone.LIBRARY, playerC, fugitiveWizard);
addTarget(playerA, playerC);
addTarget(playerA, playerD);
setStopAt(1, PhaseStep.CLEANUP);
execute();
assertLife(playerC, 20 - 2);
assertLife(playerD, 20 - 1);
assertHandCount(playerC, 1);
assertHandCount(playerD, 1);
}
@Test
public void testParkerLuckOneLibraryEmpty() {
setStrictChooseMode(true);
skipInitShuffling();
removeAllCardsFromLibrary(playerC);
addCard(Zone.BATTLEFIELD, playerA, parkerLuck);
addCard(Zone.LIBRARY, playerD, bearCub);
addTarget(playerA, playerC);
addTarget(playerA, playerD);
setStopAt(1, PhaseStep.CLEANUP);
execute();
assertLife(playerC, 20 - 2);
assertHandCount(playerD, 1);
}
}

View file

@ -0,0 +1,115 @@
package org.mage.test.cards.single.spm;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.TapAllEffect;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class PeterParkerTest extends CardTestPlayerBase {
/*
Peter Parker
{1}{W}
Legendary Creature - Human Scientist Hero
When Peter Parker enters, create a 2/1 green Spider creature token with reach.
{1}{G}{W}{U}: Transform Peter Parker. Activate only as a sorcery.
Amazing Spider-Man
{1}{G}{W}{U}
Legendary Creature - Spider Human Hero
Vigilance, reach
Each legendary spell you cast that's one or more colors has web-slinging {G}{W}{U}.
4/4
*/
private static final String peterParker = "Peter Parker";
/*
Absolute Virtue
{6}{W}{U}
Legendary Creature - Avatar Warrior
This spell can't be countered.
Flying
You have protection from each of your opponents.
8/8
*/
private static final String absoluteVirtue = "Absolute Virtue";
/*
Adelbert Steiner
{1}{W}
Legendary Creature - Human Knight
Lifelink
Adelbert Steiner gets +1/+1 for each Equipment you control.
2/1
*/
private static final String adelbertSteiner = "Adelbert Steiner";
/*
Chainer, Nightmare Adept
{2}{B}{R}
Legendary Creature - Human Minion
Discard a card: You may cast a creature card from your graveyard this turn. Activate this ability only once each turn.
Whenever a nontoken creature enters the battlefield under your control, if you didn't cast it from your hand, it gains haste until your next turn.
3/2
*/
private static final String chainerNightmareAdept = "Chainer, Nightmare Adept";
/*
Balduvian Bears
{1}{G}
Creature - Bear
2/2
*/
private static final String balduvianBears = "Balduvian Bears";
@Test
@Ignore("Enable after MDFC rework")
public void testAmazingSpiderMan() {
setStrictChooseMode(true);
addCustomCardWithAbility("tap all creatures", playerA, new SimpleActivatedAbility(
new TapAllEffect(new FilterCreaturePermanent(SubType.BEAR, "bears")),
new ManaCostsImpl<>("")
));
addCard(Zone.HAND, playerA, peterParker);
addCard(Zone.BATTLEFIELD, playerA, chainerNightmareAdept);
addCard(Zone.BATTLEFIELD, playerA, balduvianBears,2);
addCard(Zone.HAND, playerA, adelbertSteiner, 2);
addCard(Zone.GRAVEYARD, playerA, absoluteVirtue);
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 8);
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 8);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Amazing Spider-Man", true);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "tap all"); // tap bears, addCard command isn't working to set tapped
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, adelbertSteiner + " with Web-slinging", true);
setChoice(playerA, balduvianBears); // return to hand
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Discard a card");
setChoice(playerA, adelbertSteiner); // discard
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPlayableAbility("Bear does not have web-slinging", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
"Cast " + balduvianBears + " with Web-slinging", false);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, absoluteVirtue + " with Web-slinging");
setChoice(playerA, balduvianBears); // return to hand
setStopAt(1, PhaseStep.END_TURN);
execute();
}
}

View file

@ -0,0 +1,92 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class RhinosRampageTest extends CardTestPlayerBase {
/*
Rhino's Rampage
{R/G}
Sorcery
Target creature you control gets +1/+0 until end of turn. It fights target creature an opponent controls.
When excess damage is dealt to the creature an opponent controls this way, destroy up to one target noncreature artifact with mana value 3 or less.
*/
private static final String rhinosRampage = "Rhino's Rampage";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
/*
Fugitive Wizard
{U}
Creature - Human Wizard
1/1
*/
private static final String fugitiveWizard = "Fugitive Wizard";
/*
Tormod's Crypt
{0}
Artifact
{T}, Sacrifice Tormod's Crypt: Exile all cards from target player's graveyard.
*/
private static final String tormodsCrypt = "Tormod's Crypt";
@Test
public void testRhinosRampageExcess() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, rhinosRampage);
addCard(Zone.BATTLEFIELD, playerA, "Forest");
addCard(Zone.BATTLEFIELD, playerA, bearCub);
addCard(Zone.BATTLEFIELD, playerB, fugitiveWizard);
addCard(Zone.BATTLEFIELD, playerB, tormodsCrypt);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rhinosRampage);
addTarget(playerA, bearCub);
addTarget(playerA, fugitiveWizard);
addTarget(playerA, tormodsCrypt);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerB, fugitiveWizard, 1);
assertGraveyardCount(playerB, tormodsCrypt, 1);
}
@Test
public void testRhinosRampageNoExcess() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, rhinosRampage);
addCard(Zone.BATTLEFIELD, playerA, "Forest");
addCard(Zone.BATTLEFIELD, playerA, fugitiveWizard);
addCard(Zone.BATTLEFIELD, playerB, bearCub);
addCard(Zone.BATTLEFIELD, playerB, tormodsCrypt);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rhinosRampage);
addTarget(playerA, fugitiveWizard);
addTarget(playerA, bearCub);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, fugitiveWizard, 1);
assertGraveyardCount(playerB, bearCub, 1);
assertPermanentCount(playerB, tormodsCrypt, 1);
}
}

View file

@ -0,0 +1,81 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class SandmansQuicksandTest extends CardTestPlayerBase {
/*
Sandman's Quicksand
{1}{B}{B}
Sorcery
Mayhem {3}{B}
All creatures get -2/-2 until end of turn. If this spell's mayhem cost was paid, creatures your opponents control get -2/-2 until end of turn instead.
*/
private static final String sandmansQuicksand = "Sandman's Quicksand";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
/*
Thought Courier
{1}{U}
Creature - Human Wizard
{tap}: Draw a card, then discard a card.
1/1
*/
private static final String thoughtCourier = "Thought Courier";
@Test
public void testSandmansQuicksand() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, sandmansQuicksand);
addCard(Zone.BATTLEFIELD, playerA, bearCub);
addCard(Zone.BATTLEFIELD, playerB, bearCub);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sandmansQuicksand);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, bearCub, 1);
assertGraveyardCount(playerB, bearCub, 1);
}
@Test
public void testSandmansQuicksandMayhem() {
setStrictChooseMode(true);
addCard(Zone.HAND, playerA, sandmansQuicksand);
addCard(Zone.BATTLEFIELD, playerA, bearCub);
addCard(Zone.BATTLEFIELD, playerA, thoughtCourier);
addCard(Zone.BATTLEFIELD, playerB, bearCub);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw");
setChoice(playerA, sandmansQuicksand);
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sandmansQuicksand + " with Mayhem");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA, bearCub, 0);
assertGraveyardCount(playerB, bearCub, 1);
}
}

Some files were not shown because too many files have changed in this diff Show more