diff --git a/Mage.Sets/src/mage/cards/d/DesertWarfare.java b/Mage.Sets/src/mage/cards/d/DesertWarfare.java new file mode 100644 index 00000000000..68bea605cf9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DesertWarfare.java @@ -0,0 +1,146 @@ +package mage.cards.d; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.SandWarriorToken; +import mage.game.permanent.token.Token; +import mage.target.targetpointer.FixedTarget; +import mage.target.targetpointer.FixedTargets; + +/** + * @author balazskristof + */ +public final class DesertWarfare extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent( + SubType.DESERT, "you control five or more deserts" + ); + + public DesertWarfare(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + + // Whenever you sacrifice a Desert and whenever a Desert card is put into your graveyard from your hand or library, put that card onto the battlefield under your control at the beginning of your next end step. + this.addAbility(new DesertWarfareTriggeredAbility()); + + // At the beginning of combat on your turn, if you control five or more Deserts, create that many 1/1 red, green, and white Sand Warrior creature tokens. They gain haste. + this.addAbility(new ConditionalInterveningIfTriggeredAbility( + new BeginningOfCombatTriggeredAbility(new DesertWarfareTokenEffect()), + new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.OR_GREATER, 5), + "At the beginning of combat on your turn, if you control five or more Deserts, " + + "create that many 1/1 red, green, and white Sand Warrior creature tokens. They gain haste." + ).addHint(new ValueHint("Deserts you control", new PermanentsOnBattlefieldCount(filter)))); + } + + private DesertWarfare(final DesertWarfare card) { + super(card); + } + + @Override + public DesertWarfare copy() { + return new DesertWarfare(this); + } +} + +class DesertWarfareTriggeredAbility extends TriggeredAbilityImpl { + + DesertWarfareTriggeredAbility() { + super(Zone.BATTLEFIELD, null, false); + setTriggerPhrase("Whenever you sacrifice a Desert and whenever a Desert card is put into your graveyard from your hand or library, " + + "put that card onto the battlefield under your control at the beginning of your next end step."); + } + + private DesertWarfareTriggeredAbility(final DesertWarfareTriggeredAbility ability) { + super(ability); + } + + @Override + public DesertWarfareTriggeredAbility copy() { + return new DesertWarfareTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SACRIFICED_PERMANENT + || event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event instanceof ZoneChangeEvent) { + ZoneChangeEvent zce = (ZoneChangeEvent) event; + Card card = game.getCard(event.getTargetId()); + if (card == null + || !card.isOwnedBy(getControllerId()) + || !card.hasSubtype(SubType.DESERT, game) + || zce.getToZone() != Zone.GRAVEYARD + || (zce.getFromZone() != Zone.HAND + && zce.getFromZone() != Zone.LIBRARY)) { + return false; + } + } else { + Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); + if (permanent == null + || !permanent.isOwnedBy(getControllerId()) + || !permanent.hasSubtype(SubType.DESERT, game)) { + return false; + } + } + Effect effect = new ReturnToBattlefieldUnderYourControlTargetEffect(); + effect.setTargetPointer(new FixedTarget(event.getTargetId(), game)); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect, TargetController.YOU), this); + return true; + } +} + +class DesertWarfareTokenEffect extends OneShotEffect { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.DESERT); + + DesertWarfareTokenEffect() { + super(Outcome.Benefit); + staticText = "create that many 1/1 red, green, and white Sand Warrior creature tokens. " + + " They gain haste."; + } + + private DesertWarfareTokenEffect(final DesertWarfareTokenEffect effect) { + super(effect); + } + + @Override + public DesertWarfareTokenEffect copy() { + return new DesertWarfareTokenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Token token = new SandWarriorToken(); + int count = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game).size(); + token.putOntoBattlefield(count, game, source, source.getControllerId()); + game.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.WhileOnBattlefield + ).setTargetPointer(new FixedTargets(token, game)), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java index 75b160e0e42..659c385ab9f 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java @@ -96,6 +96,7 @@ public final class ModernHorizons3Commander extends ExpansionSet { cards.add(new SetCardInfo("Decoction Module", 288, Rarity.UNCOMMON, mage.cards.d.DecoctionModule.class)); cards.add(new SetCardInfo("Deepfathom Skulker", 180, Rarity.RARE, mage.cards.d.DeepfathomSkulker.class)); cards.add(new SetCardInfo("Demolition Field", 335, Rarity.UNCOMMON, mage.cards.d.DemolitionField.class)); + cards.add(new SetCardInfo("Desert Warfare", 64, Rarity.RARE, mage.cards.d.DesertWarfare.class)); cards.add(new SetCardInfo("Desert of the Indomitable", 336, Rarity.COMMON, mage.cards.d.DesertOfTheIndomitable.class)); cards.add(new SetCardInfo("Desert of the Mindful", 337, Rarity.COMMON, mage.cards.d.DesertOfTheMindful.class)); cards.add(new SetCardInfo("Disa the Restless", 1, Rarity.MYTHIC, mage.cards.d.DisaTheRestless.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/m3c/DesertWarfareTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/m3c/DesertWarfareTest.java new file mode 100644 index 00000000000..06b9dde6760 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/m3c/DesertWarfareTest.java @@ -0,0 +1,276 @@ +package org.mage.test.cards.single.m3c; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author balazskristof + */ +public class DesertWarfareTest extends CardTestPlayerBase { + + @Test + public void TestTokens() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + addCard(Zone.BATTLEFIELD, playerA, "Desert", 4); + addCard(Zone.HAND, playerA, "Desert"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + assertTokenCount(playerA, "Sand Warrior Token", 0); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + assertTokenCount(playerA, "Sand Warrior Token", 0); + + playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Desert"); + setStopAt(3, PhaseStep.BEGIN_COMBAT); + execute(); + assertTokenCount(playerA, "Sand Warrior Token", 5); + + setStopAt(4, PhaseStep.BEGIN_COMBAT); + execute(); + assertTokenCount(playerA, "Sand Warrior Token", 5); + + setStopAt(5, PhaseStep.BEGIN_COMBAT); + execute(); + assertTokenCount(playerA, "Sand Warrior Token", 10); + } + + @Test + public void TestSacrifice() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + + addCard(Zone.BATTLEFIELD, playerA, "Desert"); + addCard(Zone.BATTLEFIELD, playerA, "Akki Avalanchers"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice"); + setChoice(playerA, "Desert"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Desert", 1); + assertPermanentCount(playerA, "Desert", 0); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert", 0); + assertPermanentCount(playerA, "Desert", 1); + } + + @Test + public void TestSacrificeOpponentsTurn() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + + addCard(Zone.BATTLEFIELD, playerA, "Desert"); + addCard(Zone.BATTLEFIELD, playerA, "Akki Avalanchers"); + + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice"); + setChoice(playerA, "Desert"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert", 1); + assertPermanentCount(playerA, "Desert", 0); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert", 0); + assertPermanentCount(playerA, "Desert", 1); + } + + @Test + public void TestDestroy() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + addCard(Zone.BATTLEFIELD, playerA, "Desert"); + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 4); + addCard(Zone.HAND, playerB, "Volcanic Upheaval"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Volcanic Upheaval"); + addTarget(playerB, "Desert"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert", 1); + assertPermanentCount(playerA, "Desert", 0); + } + + @Test + public void TestDiscard() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, "Island"); + addCard(Zone.LIBRARY, playerA, "Desert"); + + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + addCard(Zone.HAND, playerA, "Mountain", 2); + addCard(Zone.HAND, playerA, "Faithless Looting"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Faithless Looting"); + setChoice(playerA, "Island^Desert"); + //setChoice(playerA, "Desert"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert", 0); + assertGraveyardCount(playerA, "Island", 1); + assertPermanentCount(playerA, "Desert", 1); + } + + @Test + public void TestDiscardOpponentsTurn() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, "Island"); + addCard(Zone.LIBRARY, playerA, "Desert"); + + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + addCard(Zone.HAND, playerA, "Mountain", 2); + addCard(Zone.HAND, playerA, "Faithless Looting"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Faithless Looting"); + setChoice(playerA, "Island"); + setChoice(playerA, "Desert"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertGraveyardCount(playerA, "Desert", 0); + assertGraveyardCount(playerA, "Island", 1); + assertPermanentCount(playerA, "Desert", 1); + } + + @Test + public void TestCycling() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + addCard(Zone.HAND, playerA, "Desert of the Fervent"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling {1}{R}"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert of the Fervent", 0); + assertPermanentCount(playerA, "Desert of the Fervent", 1); + } + + @Test + public void TestCyclingOpponentsTurn() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + addCard(Zone.HAND, playerA, "Desert of the Fervent"); + + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling {1}{R}"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert of the Fervent", 1); + assertPermanentCount(playerA, "Desert of the Fervent", 0); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert of the Fervent", 0); + assertPermanentCount(playerA, "Desert of the Fervent", 1); + } + + @Test + public void TestMill() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, "Plains"); + addCard(Zone.LIBRARY, playerA, "Island"); + addCard(Zone.LIBRARY, playerA, "Desert"); + + addCard(Zone.BATTLEFIELD, playerA, "Swamp"); + addCard(Zone.HAND, playerA, "Stitcher's Supplier"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Stitcher's Supplier"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert", 0); + assertPermanentCount(playerA, "Desert", 1); + assertGraveyardCount(playerA, "Plains", 1); + assertGraveyardCount(playerA, "Island", 1); + } + + @Test + public void TestMillOpponentsTurn() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, "Plains"); + addCard(Zone.LIBRARY, playerA, "Island"); + addCard(Zone.LIBRARY, playerA, "Desert"); + + addCard(Zone.BATTLEFIELD, playerA, "Stitcher's Supplier"); + + addCard(Zone.BATTLEFIELD, playerB, "Mountain"); + addCard(Zone.HAND, playerB, "Shock"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Shock"); + addTarget(playerB, "Stitcher's Supplier"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Desert", 0); + assertGraveyardCount(playerA, "Desert", 1); + assertGraveyardCount(playerA, "Plains", 1); + assertGraveyardCount(playerA, "Island", 1); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Desert", 1); + assertGraveyardCount(playerA, "Desert", 0); + assertGraveyardCount(playerA, "Plains", 1); + assertGraveyardCount(playerA, "Island", 1); + } + + @Test + public void TestDuneChanter() { + addCard(Zone.BATTLEFIELD, playerA, "Desert Warfare"); + addCard(Zone.BATTLEFIELD, playerA, "Dune Chanter"); + + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, "Plains"); + addCard(Zone.LIBRARY, playerA, "Island"); + addCard(Zone.LIBRARY, playerA, "Desert"); + + addCard(Zone.BATTLEFIELD, playerA, "Swamp"); + addCard(Zone.HAND, playerA, "Stitcher's Supplier"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Stitcher's Supplier"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Desert", 0); + assertGraveyardCount(playerA, "Plains", 0); + assertGraveyardCount(playerA, "Island", 0); + assertPermanentCount(playerA, "Desert", 1); + assertPermanentCount(playerA, "Plains", 1); + assertPermanentCount(playerA, "Island", 1); + + } +} +