package org.mage.test.cards.cost.modification; import mage.abilities.keyword.HexproofAbility; 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; /** * Battlefield Thaumaturge: * Creature - Human Wizard * Each instant and sorcery spell you cast costs {1} less to cast for each creature it targets. * Heroic - Whenever you cast a spell that targets Battlefield Thaumaturge, Battlefield Thaumaturge gains hexproof until end of turn. * * @author Simown */ public class BattlefieldThaumaturgeTest extends CardTestPlayerBase { @Test public void testSingleTargetReduction() { addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); addCard(Zone.BATTLEFIELD, playerA, "Mountain"); addCard(Zone.BATTLEFIELD, playerA, "Island"); addCard(Zone.HAND, playerA, "Lightning Strike"); addCard(Zone.BATTLEFIELD, playerB, "Akroan Skyguard"); // Lightning Strike - {1}{R} - Lightning Strike deals 3 damage to target creature or player. // Because Battlefield Thaumaturge is on the battlefield, and the creature is targeted by the // Lightning Strike it will be payable with {R}. castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Strike", "Akroan Skyguard"); setStopAt(2, PhaseStep.END_TURN); execute(); // PlayerA still has the Battlefield Thaumaturge assertPermanentCount(playerA, "Battlefield Thaumaturge", 1); // The Akroan Skyguard has been killed by the Lightning Strike assertPermanentCount(playerB, "Akroan Skyguard", 0); assertGraveyardCount(playerB, "Akroan Skyguard", 1); // Check {R} has been used to pay, and the other land remains untapped assertTappedCount("Mountain", true, 1); assertTappedCount("Island", false, 1); } @Test public void testStriveTargetingReduction1() { addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); addCard(Zone.BATTLEFIELD, playerA, "Pharika's Chosen"); addCard(Zone.HAND, playerA, "Silence the Believers"); addCard(Zone.BATTLEFIELD, playerB, "Battlewise Hoplite"); /** * Silence the Believers - {2}{B}{B} * Exile any number of target creatures and all Auras attached to them * Strive - Silence the Believers costs {2}{B} more to cast for each target beyond the first. * Targetting a creature on both sides of the battlefield. */ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Silence the Believers", "Pharika's Chosen^Battlewise Hoplite"); setStopAt(2, PhaseStep.END_TURN); execute(); // Both creatures were exiled assertExileCount("Pharika's Chosen", 1); assertExileCount("Battlewise Hoplite", 1); // Not still on the battlefield or in the graveyard assertPermanentCount(playerA, "Pharika's Chosen", 0); assertPermanentCount(playerB, "Battlewise Hoplite", 0); assertGraveyardCount(playerA, "Pharika's Chosen", 0); assertGraveyardCount(playerB, "Battlewise Hoplite", 0); /* Cost to exile 2 permanents will be: * + {2}{B}{B} for the base spell * + {2}{B} for an additional target * - {2} for Battlefield Thaumaturge cost reducing effect * = {2}{B}{B}{B} to pay. */ // Check 3 Swamps have been tapped to pay the reduced cost assertTappedCount("Swamp", true, 3); // And 2 Forests for the colorless mana assertTappedCount("Forest", true, 2); // And the rest of the Forests remain untapped assertTappedCount("Forest", false, 2); } @Test public void testStriveTargetingReduction2() { String [] creatures = {"Battlefield Thaumaturge", "Agent of Horizons", "Blood-Toll Harpy", "Anvilwrought Raptor", "Fleshmad Steed" }; for(String creature : creatures) { addCard(Zone.BATTLEFIELD, playerA, creature); } addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); addCard(Zone.BATTLEFIELD, playerA, "Island", 5); addCard(Zone.HAND, playerA, "Launch the Fleet"); // Launch the Fleet - {W} // Strive - Launch the Fleet costs {1} more to cast for each target beyond the first. // Until end of turn, any number of target creatures each gain "Whenever this creature attacks, put a 1/1 white Soldier token onto the battlefield tapped and attacking." castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Launch the Fleet", createTargetingString(creatures)); for(String creature : creatures) { attack(3, playerA, creature); } setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); execute(); // 5 initial creatures + 5 soldier tokens + 6 lands assertPermanentCount(playerA, 16); // The initial creatures exist for(String creature : creatures) { assertPermanentCount(playerA, creature, 1); } // Each has a solider token generated while attacking assertPermanentCount(playerA, "Soldier", 5); // Battlefield Thaumaturge will have hexproof from heroic trigger Permanent battlefieldThaumaturge = getPermanent("Battlefield Thaumaturge", playerA.getId()); Assert.assertTrue("Battlefield Thaumaturge must have hexproof", battlefieldThaumaturge.getAbilities().contains(HexproofAbility.getInstance())); assertLife(playerA, 20); // 5 initial creatures + 5 soldier tokens => 16 damage assertLife(playerB, 4); /* Cost to have 5 attackers generate soldier tokens * + {W} for the base spell * + {4} for an additional targets * - {4} for Battlefield Thaumaturge cost reducing effect (reduce {1} per target) * = {W} to pay. */ assertTappedCount("Plains", true, 1); // No other mana has been tapped to pay costs assertTappedCount("Island", false, 5); } @Test public void testVariableCostReduction() { addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); addCard(Zone.BATTLEFIELD, playerA, "Island", 2); addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); addCard(Zone.HAND, playerA, "Curse of the Swine"); String [] opponentsCreatures = {"Fleecemane Lion", "Sedge Scorpion", "Boon Satyr", "Bronze Sable"}; for(String creature: opponentsCreatures) { addCard(Zone.BATTLEFIELD, playerB, creature); } /* Curse of the Swine - {X}{U}{U} * Exile X target creatures. For each creature exiled this way, * its controller puts a 2/2 green Boar creature token onto the battlefield */ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curse of the Swine"); setChoice(playerA, "X=4"); addTarget(playerA, createTargetingString(opponentsCreatures)); setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); execute(); // All the opponents creatures have been exiled from the battlefield for(String creature: opponentsCreatures) { assertPermanentCount(playerB, creature, 0); assertGraveyardCount(playerB, creature, 0); assertExileCount(creature, 1); } // All 4 creatures have been replaced by boars assertPermanentCount(playerB, "Boar", 4); /* Cost to target 4 permanents will be: * + {4}{U}{U} for the base spell with X = 4 * - {4} for Battlefield Thaumaturge cost reducing effect as 4 creatures are targetted * = {U}{U} to pay. */ // Check 2 islands have been tapped to pay the reduced cost assertTappedCount("Island", true, 2); // And the rest of the lands remain untapped assertTappedCount("Plains", false, 4); } @Test public void testMutipleTargetReduction() { String [] playerACreatures = {"Battlefield Thaumaturge", "Sedge Scorpion", "Boon Satyr"}; String [] playerBCreatures = {"Agent of Horizons", "Blood-Toll Harpy", "Anvilwrought Raptor"}; addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); // Creatures for player A for(String creature: playerACreatures) { addCard(Zone.BATTLEFIELD, playerA, creature); } addCard(Zone.HAND, playerA, "Descent of the Dragons"); // Creatures for player B for(String creature: playerBCreatures) { addCard(Zone.BATTLEFIELD, playerB, creature); } /* Descent of the Dragons - {4}{R}{R} * Destroy any number of target creatures. * For each creature destroyed this way, its controller puts a 4/4 red Dragon creature token with flying onto the battlefield. * Battlefield Thaumaturge should reduce the cost of the spell when cast, before he is destroyed and replaced with a dragon. */ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Descent of the Dragons", createTargetingString(playerACreatures) + '^' + createTargetingString(playerBCreatures)); setStopAt(1, PhaseStep.END_TURN); execute(); // All creatures have been put in the graveyard for(String creature: playerACreatures) { assertPermanentCount(playerA, creature, 0); assertGraveyardCount(playerA, creature, 1); } for(String creature: playerBCreatures) { assertPermanentCount(playerB, creature, 0); assertGraveyardCount(playerB, creature, 1); } // And each player has 3 dragons assertPermanentCount(playerA, "Dragon", 3); assertPermanentCount(playerB, "Dragon", 3); /* Cost to target 6 creatures will be * + {4}{R}{R} for the fixed cost base spell * - {4} for Battlefield Thaumaturge cost reducing effect * each creature targeted will reduce the cost by {1} so the cost * can only be reduced by {4} maximum using Battlefield Thaumaturge * even though 6 creatures are targeted. * = {R}{R} to pay. */ // Check 2 mountains have been tapped to pay the reduced cost assertTappedCount("Mountain", true, 2); // And the rest of the lands remain untapped assertTappedCount("Swamp", false, 4); } @Test public void testTargetNonCreature() { addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); addCard(Zone.HAND, playerA, "Fade into Antiquity"); addCard(Zone.BATTLEFIELD, playerB, "Heliod, God of the Sun"); // Fade into Antiquity - Sorcery - {2}{G} - Exile target artifact or enchantment. // Battlefield Thaumaturge only reduces the cost instants and sorceries where the target is a creature // No cost reduction for targeting an enchantment (devotion is too low for Heliod to be a creature) castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fade into Antiquity", "Heliod, God of the Sun"); setStopAt(1, PhaseStep.END_TURN); execute(); // PlayerA still has the Battlefield Thaumaturge assertPermanentCount(playerA, "Battlefield Thaumaturge", 1); // Heliod has been exiled assertPermanentCount(playerB, "Heliod, God of the Sun", 0); assertGraveyardCount(playerB, "Heliod, God of the Sun", 0); assertExileCount("Heliod, God of the Sun", 1); // Expect full amount paid, i.e. all lands are tapped. Cost was not reduced by Battlefield Thaumaturge, no creature was targeted. assertTappedCount("Forest", true, 3); } @Test public void testTargetWithAura() { addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); addCard(Zone.HAND, playerA, "Spectra Ward"); // Spectra Ward - {3}{W}{W} - Aura // Enchanted creature gets +2/+2 and has protection from all colors. This effect doesn't remove auras. // Battlefield Thaumaturge only reduces the cost instants and sorceries targeting creatures. // No cost reduction for targeting a creature with an Aura. castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Spectra Ward", "Battlefield Thaumaturge"); setStopAt(1, PhaseStep.END_TURN); execute(); assertPermanentCount(playerA, "Battlefield Thaumaturge", 1); assertPermanentCount(playerA, "Spectra Ward", 1); // Battlefield Thaumaturge will have hexproof from heroic trigger Permanent battlefieldThaumaturge = getPermanent("Battlefield Thaumaturge", playerA.getId()); Assert.assertTrue("Battlefield Thaumaturge must have hexproof", battlefieldThaumaturge.getAbilities().contains(HexproofAbility.getInstance())); // No cost reduction from Battlefield Thaumaturge, full amount paid assertTappedCount("Plains", true, 5); } private String createTargetingString(String [] targets) { StringBuilder targetBuilder = new StringBuilder(); for (String target : targets) { if (targetBuilder.length() > 0) { targetBuilder.append('^'); } targetBuilder.append(target); } return targetBuilder.toString(); } }