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();
}
}