From be9599d6a1dd4daade40e4aafd4e5d8de63bdbd1 Mon Sep 17 00:00:00 2001 From: Justin Herlehy Date: Mon, 2 Jan 2017 22:07:11 -0500 Subject: [PATCH 1/2] [AER] Implement Pacification Array Added card to data file and implemented. --- .../src/mage/cards/p/PacificationArray.java | 76 +++++++++++++++++++ Mage.Sets/src/mage/sets/AetherRevolt.java | 3 +- Utils/mtg-cards-data.txt | 1 + 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/p/PacificationArray.java diff --git a/Mage.Sets/src/mage/cards/p/PacificationArray.java b/Mage.Sets/src/mage/cards/p/PacificationArray.java new file mode 100644 index 00000000000..69aaf6aace7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PacificationArray.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.p; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.TapTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author JRHerlehy + */ +public class PacificationArray extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("artifact or creature"); + + static { + filter.add(Predicates.or(new CardTypePredicate(CardType.ARTIFACT), + new CardTypePredicate(CardType.CREATURE))); + } + + public PacificationArray(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); + + // {2}, {t}: Tap target artifact or creature. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new ManaCostsImpl("{2}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + public PacificationArray(final PacificationArray card) { + super(card); + } + + @Override + public PacificationArray copy() { + return new PacificationArray(this); + } +} diff --git a/Mage.Sets/src/mage/sets/AetherRevolt.java b/Mage.Sets/src/mage/sets/AetherRevolt.java index 1baacb8df91..ecf808df336 100644 --- a/Mage.Sets/src/mage/sets/AetherRevolt.java +++ b/Mage.Sets/src/mage/sets/AetherRevolt.java @@ -51,8 +51,6 @@ public class AetherRevolt extends ExpansionSet { protected final List savedSpecialLand = new ArrayList<>(); - //TODO: Check Paradox Engine's card number - private AetherRevolt() { super("Aether Revolt", "AER", ExpansionSet.buildDate(2017, 1, 20), SetType.EXPANSION); this.blockName = "Kaladesh"; @@ -79,6 +77,7 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Gonti's Aether Heart", 152, Rarity.MYTHIC, mage.cards.g.GontisAetherHeart.class)); cards.add(new SetCardInfo("Heart of Kiran", 153, Rarity.MYTHIC, mage.cards.h.HeartOfKiran.class)); cards.add(new SetCardInfo("Oath of Ajani", 131, Rarity.RARE, mage.cards.o.OathOfAjani.class)); + cards.add(new SetCardInfo("Pacification Array", 168, Rarity.UNCOMMON, mage.cards.p.PacificationArray.class)); cards.add(new SetCardInfo("Paradox Engine", 169, Rarity.MYTHIC, mage.cards.p.ParadoxEngine.class)); cards.add(new SetCardInfo("Peacekeeper Colossus", 170, Rarity.RARE, mage.cards.p.PeacekeeperColossus.class)); cards.add(new SetCardInfo("Pia's Revolution", 91, Rarity.RARE, mage.cards.p.PiasRevolution.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index af1f00ff952..7c52bdeb680 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -30383,6 +30383,7 @@ Foundry Assembler|Aether Revolt|151|C|{5}|Artifact Creature - Assembly-Worker|3| Gonti's Aether Heart|Aether Revolt|152|M|{6}|Legendary Artifact|||Whenever Gonti's Aether Heart or another artifact enters the battlefield under your control, you get {E}{E} (two energy counters).$Pay {E}{E}{E}{E}{E}{E}{E}{E}, Exile Gonti's Aether Heart: Take an extra turn after this one.| Heart of Kiran|Aether Revolt|153|M|{2}|Legendary Artifact - Vehicle|4|4|Flying, vigilance$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)$You may remove a loyalty counter from a planeswalker you control rather than pay Heart of Kiran's crew cost.| Metallic Mimic|Aether Revolt|164|R|{2}|Artifact Creature - Shapeshifter|2|1|As Metallic Mimic enters the battlefield, choose a creature type.$Metallic Mimic is the chosen type in addition to its other types.$Each other creature you control of the chosen type enters the battlefield with an additional +1/+1 counter on it.| +Pacification Array|Aether Revolt|168|U|{1}|Artifact|||{2}, {t}: Tap target artifact or creature.| Paradox Engine|Aether Revolt|169|M|{5}|Legendary Artifact|||Whenever you cast a spell, untap all nonland permanents you control.| Peacekeeper Colossus|Aether Revolt|170|R|{3}|Artifact - Vehicle|6|6|{1}{W}: Another target Vehicle you control becomes an artifact creature until end of turn.$Crew 4 (Tap any number of creatures you control with total power 4 or more: This Vehicle becomes an artifact creature until end of turn.)| Planar Bridge|Aether Revolt|171|M|{6}|Legendary Artifact|||{8}, {T}: Search your library for a permanent card, put it onto the battlefield, then shuffle your library.| From 99bb976d997d88410800f430f6174415c83bd00d Mon Sep 17 00:00:00 2001 From: Justin Herlehy Date: Tue, 3 Jan 2017 01:20:44 -0500 Subject: [PATCH 2/2] [AER] Implement Greenbelt Rampager and Hungry Flames Added test for Greebel Rampager to verify that it returns to the correct player. Added Spoilers to Data File - Merchant's Porter - Ornithopter - Hungry Flames - Rishkar, Peema Renegade --- .../src/mage/cards/g/GreenbeltRampager.java | 106 +++++++++++++++++ Mage.Sets/src/mage/cards/h/HungryFlames.java | 100 ++++++++++++++++ .../src/mage/cards/s/SiegeModification.java | 1 - Mage.Sets/src/mage/sets/AetherRevolt.java | 3 + .../enters/GreenbeltRampagerTest.java | 112 ++++++++++++++++++ Utils/mtg-cards-data.txt | 4 + 6 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/g/GreenbeltRampager.java create mode 100644 Mage.Sets/src/mage/cards/h/HungryFlames.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/GreenbeltRampagerTest.java diff --git a/Mage.Sets/src/mage/cards/g/GreenbeltRampager.java b/Mage.Sets/src/mage/cards/g/GreenbeltRampager.java new file mode 100644 index 00000000000..4c1ba8468b4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GreenbeltRampager.java @@ -0,0 +1,106 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author JRHerlehy + */ +public class GreenbeltRampager extends CardImpl { + + public GreenbeltRampager(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); + + this.subtype.add("Elephant"); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // When Greenbelt Rampager enters the battlefield, pay {E}{E}. If you can't, return Greenbelt Rampager to its owner's hand and you get {E}. + this.addAbility(new EntersBattlefieldTriggeredAbility(new GreenbeltRampagerEffect(), false)); + } + + public GreenbeltRampager(final GreenbeltRampager card) { + super(card); + } + + @Override + public GreenbeltRampager copy() { + return new GreenbeltRampager(this); + } + + private class GreenbeltRampagerEffect extends OneShotEffect { + + GreenbeltRampagerEffect() { + super(Outcome.Neutral); + this.staticText = "pay {E}{E}. If you can't, return {this} to its owner's hand and you get {E}"; + } + + GreenbeltRampagerEffect(final GreenbeltRampagerEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent card = game.getPermanent(source.getSourceId()); + Player player = game.getPlayer(source.getControllerId()); + + if (card == null || player == null) return false; + + if (player.getCounters().getCount(CounterType.ENERGY) > 1) { + player.getCounters().removeCounter(CounterType.ENERGY, 2); + } else { + card.moveToZone(Zone.HAND, source.getSourceId(), game, true); + player.addCounters(CounterType.ENERGY.createInstance(), game); + } + + return true; + } + + @Override + public GreenbeltRampagerEffect copy() { + return new GreenbeltRampagerEffect(this); + } + } + +} diff --git a/Mage.Sets/src/mage/cards/h/HungryFlames.java b/Mage.Sets/src/mage/cards/h/HungryFlames.java new file mode 100644 index 00000000000..9ad5c4565e9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HungryFlames.java @@ -0,0 +1,100 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.cards.h; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author JRHerlehy + */ +public class HungryFlames extends CardImpl { + + public HungryFlames(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); + + // Hungry Flames deals 3 damage to target creature and 2 damage to target player. + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addTarget(new TargetPlayer()); + this.getSpellAbility().addEffect(new HungryFlamesEffect()); + } + + public HungryFlames(final HungryFlames card) { + super(card); + } + + @Override + public HungryFlames copy() { + return new HungryFlames(this); + } + + private class HungryFlamesEffect extends OneShotEffect { + HungryFlamesEffect() { + super(Outcome.Damage); + this.staticText = "{this} deals 3 damage to target creature and 2 damage to target player"; + } + + HungryFlamesEffect(final HungryFlamesEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getTargets().get(0).getFirstTarget()); + Player player = game.getPlayer(source.getTargets().get(1).getFirstTarget()); + + if (permanent != null) { + permanent.damage(3, source.getSourceId(), game, false, true); + } + + if (player != null) { + player.damage(2, source.getSourceId(), game, false, true); + } + + return true; + } + + @Override + public HungryFlamesEffect copy() { + return new HungryFlamesEffect(this); + } + } + +} diff --git a/Mage.Sets/src/mage/cards/s/SiegeModification.java b/Mage.Sets/src/mage/cards/s/SiegeModification.java index 01f41e7343f..db9bf8cb71b 100644 --- a/Mage.Sets/src/mage/cards/s/SiegeModification.java +++ b/Mage.Sets/src/mage/cards/s/SiegeModification.java @@ -106,7 +106,6 @@ public class SiegeModification extends CardImpl { public BecomesCreatureIfVehicleEffect(final BecomesCreatureIfVehicleEffect effect) { super(effect); - this.staticText = effect.staticText; } @Override diff --git a/Mage.Sets/src/mage/sets/AetherRevolt.java b/Mage.Sets/src/mage/sets/AetherRevolt.java index ecf808df336..42ba3fc16fb 100644 --- a/Mage.Sets/src/mage/sets/AetherRevolt.java +++ b/Mage.Sets/src/mage/sets/AetherRevolt.java @@ -75,8 +75,11 @@ public class AetherRevolt extends ExpansionSet { cards.add(new SetCardInfo("Foundry Assembler", 151, Rarity.COMMON, mage.cards.f.FoundryAssembler.class)); cards.add(new SetCardInfo("Freejam Regent", 81, Rarity.RARE, mage.cards.f.FreejamRegent.class)); cards.add(new SetCardInfo("Gonti's Aether Heart", 152, Rarity.MYTHIC, mage.cards.g.GontisAetherHeart.class)); + cards.add(new SetCardInfo("Greenbelt Rampager", 107, Rarity.RARE, mage.cards.g.GreenbeltRampager.class)); cards.add(new SetCardInfo("Heart of Kiran", 153, Rarity.MYTHIC, mage.cards.h.HeartOfKiran.class)); + cards.add(new SetCardInfo("Hungry Flames", 84, Rarity.UNCOMMON, mage.cards.h.HungryFlames.class)); cards.add(new SetCardInfo("Oath of Ajani", 131, Rarity.RARE, mage.cards.o.OathOfAjani.class)); + cards.add(new SetCardInfo("Ornithopter", 167, Rarity.UNCOMMON, mage.cards.o.Ornithopter.class)); cards.add(new SetCardInfo("Pacification Array", 168, Rarity.UNCOMMON, mage.cards.p.PacificationArray.class)); cards.add(new SetCardInfo("Paradox Engine", 169, Rarity.MYTHIC, mage.cards.p.ParadoxEngine.class)); cards.add(new SetCardInfo("Peacekeeper Colossus", 170, Rarity.RARE, mage.cards.p.PeacekeeperColossus.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/GreenbeltRampagerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/GreenbeltRampagerTest.java new file mode 100644 index 00000000000..e34a5802ee7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/GreenbeltRampagerTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package org.mage.test.cards.abilities.enters; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author JRHerlehy + */ +public class GreenbeltRampagerTest extends CardTestPlayerBase { + + @Test + public void testFirstCast() { + addCard(Zone.HAND, playerA, "Greenbelt Rampager"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Greenbelt Rampager"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, "Greenbelt Rampager", 1); + assertPermanentCount(playerA, "Greenbelt Rampager", 0); + assertCounterCount(playerA, CounterType.ENERGY, 1); + } + + @Test + public void testScondCast() { + addCard(Zone.HAND, playerA, "Greenbelt Rampager"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Greenbelt Rampager"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Greenbelt Rampager"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, "Greenbelt Rampager", 1); + assertPermanentCount(playerA, "Greenbelt Rampager", 0); + assertCounterCount(playerA, CounterType.ENERGY, 2); + } + + @Test + public void testThirdCast() { + addCard(Zone.HAND, playerA, "Greenbelt Rampager"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Greenbelt Rampager"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Greenbelt Rampager"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Greenbelt Rampager"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, "Greenbelt Rampager", 0); + assertPermanentCount(playerA, "Greenbelt Rampager", 1); + assertCounterCount(playerA, CounterType.ENERGY, 0); + } + + @Test + public void testCastNotOwned() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10); + addCard(Zone.HAND, playerA, "Gonti, Lord of Luxury"); + + addCard(Zone.LIBRARY, playerB, "Greenbelt Rampager"); + + skipInitShuffling(); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gonti, Lord of Luxury"); + addTarget(playerA, playerB); + setChoice(playerA, "Greenbelt Rampager"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Greenbelt Rampager"); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertCounterCount(playerA, CounterType.ENERGY, 1); + assertPermanentCount(playerA, "Greenbelt Rampager", 0); + assertHandCount(playerA, "Greenbelt Rampager", 0); + assertHandCount(playerB, "Greenbelt Rampager", 1); + } +} diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 7c52bdeb680..f10eee19114 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -30366,12 +30366,14 @@ Fatal Push|Aether Revolt|57|U|{B}|Instant|||Destroy target creature if it has co Night Market Aeronaut|67|C|{3}{B}|Creature - Aetherborn Warrior|2|2|Flying$Revolt — Night Market Aeronaut enters the battlefield with a +1/+1 counter on it if a permanent you controlled left the battlefield this turn.| Yahenni's Expertise|Aether Revolt|75|R|{2}{B}{B}|Sorcery|||All creatures get -3/-3 until end of turn.$You may cast a card with converted mana cost 3 or less from your hand without paying its mana cost.| Freejam Regent|Aether Revolt|81|R|{4}{R}{R}|Creature - Dragon|4|4|Improvise (Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for 1.)$Flying${1}{R}: Freejam Regent gets +2/+0 until end of turn.| +Hungry Flames|Aether Revolt|84|U|{2}{R}|Instant|||Hungry Flames deals 3 damage to target creature and 2 damage to target player.| Pia's Revolution|Aether Revolt|91|R|{2}{R}|Enchantment|||Whenever a nontoken artifact is put into your graveyard from the battlefield, return that card to your hand unless target opponent has Pia's Revolution deal 3 damage to him or her.| Quicksmith Rebel|Aether Revolt|93|R|{3}{R}|Creature - Human Artificer|3|2|When Quicksmith Rebel enters the battlefield, target artifact you control gains "{T}: This artifact deals 2 damage to target creature or player" for as long as you control Quicksmith Rebel.| Siege Modification|Aether Revolt|99|U|{1}{R}{R}|Enchantment - Aura|||Enchant creature or Vehicle$As long as enchanted permanent is a Vehicle, it's a creature in addition to its other types.$Enchanted creature gets +3/+0 and has first strike.| Sweatworks Brawler|Aether Revolt|100|C|{3}{R}|Creature - Human Artificer|3|3|Improvise (Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for {1}.)$Menace| Greenbelt Rampager|Aether Revolt|107|R|{G}|Creature - Elephant|3|4|When Greenbelt Rampager enters the battlefield, pay {E}{E} (two energy counters). If you can't, return Greenbelt Rampager to its owner's hand and you get {E}.| Greenwheel Liberator|Aether Revolt|108|R|{1}{G}|Creature - Elf Warrior|2|1|Revolt — Greenbelt Liberator enters the battlefield with two +1/+1 counters on it if a permanent you controlled left the battlefield this turn.| +Rishkar, Peema Renegade|Aether Revolt|122|R|{2}{G}|Legendary Creature - Elf Druid|2|2|When Rishkar, Peema Renegade enters the battlefield, put a +1/+1 counter on each of up to two target creatures.$Each creature you control with a counter on it has "T: Add G to your mana pool."| Silkweaver Elite|Aether Revolt|125|C|{2}{G}|Creature - Elf Archer|2|2|Reach (This creature can block creatures with flying.)$Revolt — When Silkweaver Elite enters the battlefield, if a permanent you controlled left the battlefield this turn, draw a card.| Ajani Unyielding|Aether Revolt|127|M|{4}{G}{W}|Planeswalker - Ajani|||+2: Reveal the top three cards of your library. Put all nonland permanent cards revealed this way into your hand and the rest on the bottom of your library in any order.$-2: Exile target creature. Its controller gains life equal to its power.$-9: Put five +1/+1 counters on each creature you control and five loyalty counters on each other planeswalker you control.| Dark Intimations|Aether Revolt|128|R|{2}{U}{B}{R}|Sorcery|||Each opponent sacrifices a creature or planeswalker, then discards a card. You return a creature or planeswalker card from your graveyard to your hand, then draw a card.$When you cast a Bolas planeswalker spell, exile Dark Intimations from your graveyard. That planeswalker enters the battlefield with an additional loyalty counter on it.| @@ -30382,7 +30384,9 @@ Consulate Dreadnought|Aether Revolt|146|U|{1}|Artifact - Vehicle|7|11|Crew 6 Foundry Assembler|Aether Revolt|151|C|{5}|Artifact Creature - Assembly-Worker|3|3|Improvise (Your artifacts can help cast this spell. Each artifact you tap after you're done activating mana abilities pays for {1).)| Gonti's Aether Heart|Aether Revolt|152|M|{6}|Legendary Artifact|||Whenever Gonti's Aether Heart or another artifact enters the battlefield under your control, you get {E}{E} (two energy counters).$Pay {E}{E}{E}{E}{E}{E}{E}{E}, Exile Gonti's Aether Heart: Take an extra turn after this one.| Heart of Kiran|Aether Revolt|153|M|{2}|Legendary Artifact - Vehicle|4|4|Flying, vigilance$Crew 3 (Tap any number of creatures you control with total power 3 or more: This Vehicle becomes an artifact creature until end of turn.)$You may remove a loyalty counter from a planeswalker you control rather than pay Heart of Kiran's crew cost.| +Merchant's Porter|Aether Revolt|163|R|Artifact Creature - Construct|1|2|{3}{U}, {T}, Tap X untapped artifacts you control: Look at the top X cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order.| Metallic Mimic|Aether Revolt|164|R|{2}|Artifact Creature - Shapeshifter|2|1|As Metallic Mimic enters the battlefield, choose a creature type.$Metallic Mimic is the chosen type in addition to its other types.$Each other creature you control of the chosen type enters the battlefield with an additional +1/+1 counter on it.| +Ornithopter|Aether Revolt|167|U|{0}|Artifact Creature - Thopter|0|2|Flying| Pacification Array|Aether Revolt|168|U|{1}|Artifact|||{2}, {t}: Tap target artifact or creature.| Paradox Engine|Aether Revolt|169|M|{5}|Legendary Artifact|||Whenever you cast a spell, untap all nonland permanents you control.| Peacekeeper Colossus|Aether Revolt|170|R|{3}|Artifact - Vehicle|6|6|{1}{W}: Another target Vehicle you control becomes an artifact creature until end of turn.$Crew 4 (Tap any number of creatures you control with total power 4 or more: This Vehicle becomes an artifact creature until end of turn.)|