From 23434548bdc953f0e2f9d02101401cac59dfde6b Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 23 Sep 2013 17:24:57 -0500 Subject: [PATCH] - Added Gather Specimens, Sludge Strider, and Swerve. Fixed Abattoir Ghoul. Added some tests. --- .../src/mage/sets/conflux/SludgeStrider.java | 159 +++++++++++++++++ .../mage/sets/innistrad/AbattoirGhoul.java | 61 +++---- .../mage/sets/planechase/SludgeStrider.java | 52 ++++++ .../sets/shardsofalara/GatherSpecimens.java | 166 ++++++++++++++++++ .../src/mage/sets/shardsofalara/Swerve.java | 72 ++++++++ .../abilities/enters/GatherSpecimensTest.java | 97 ++++++++++ .../cards/triggers/AbattoirGhoulTest.java | 37 ++++ 7 files changed, 603 insertions(+), 41 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/conflux/SludgeStrider.java create mode 100644 Mage.Sets/src/mage/sets/planechase/SludgeStrider.java create mode 100644 Mage.Sets/src/mage/sets/shardsofalara/GatherSpecimens.java create mode 100644 Mage.Sets/src/mage/sets/shardsofalara/Swerve.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/GatherSpecimensTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/triggers/AbattoirGhoulTest.java diff --git a/Mage.Sets/src/mage/sets/conflux/SludgeStrider.java b/Mage.Sets/src/mage/sets/conflux/SludgeStrider.java new file mode 100644 index 00000000000..4f6f0e31d25 --- /dev/null +++ b/Mage.Sets/src/mage/sets/conflux/SludgeStrider.java @@ -0,0 +1,159 @@ +/* + * 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.sets.conflux; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterArtifactPermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPlayer; + +/** + * + * @author jeffwadsworth + */ +public class SludgeStrider extends CardImpl { + + public SludgeStrider(UUID ownerId) { + super(ownerId, 126, "Sludge Strider", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{W}{U}{B}"); + this.expansionSetCode = "CON"; + this.subtype.add("Insect"); + + this.color.setBlue(true); + this.color.setBlack(true); + this.color.setWhite(true); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever another artifact enters the battlefield under your control or another artifact you control leaves the battlefield, you may pay {1}. If you do, target player loses 1 life and you gain 1 life. + Ability ability = new SludgeStriderTriggeredAbility(); + ability.addTarget(new TargetPlayer(true)); + this.addAbility(ability); + + } + + public SludgeStrider(final SludgeStrider card) { + super(card); + } + + @Override + public SludgeStrider copy() { + return new SludgeStrider(this); + } +} + +class SludgeStriderTriggeredAbility extends TriggeredAbilityImpl { + + public SludgeStriderTriggeredAbility() { + super(Zone.BATTLEFIELD, new DoIfCostPaid(new SludgeStriderEffect(), new GenericManaCost(1)), true); + } + + public SludgeStriderTriggeredAbility(final SludgeStriderTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() == Zone.BATTLEFIELD + || zEvent.getToZone() == Zone.BATTLEFIELD) { + UUID targetId = event.getTargetId(); + Permanent permanent = game.getPermanent(targetId); + if (permanent == null) { + permanent = (Permanent) game.getLastKnownInformation(targetId, Zone.BATTLEFIELD); + } + if (permanent == null) { + return false; + } + FilterArtifactPermanent filter = new FilterArtifactPermanent(); + filter.add(new ControllerIdPredicate(super.getControllerId())); + filter.add(new AnotherPredicate()); + if (filter.match(permanent, getSourceId(), getControllerId(), game)) { + return true; + } + } + } + return false; + } + + @Override + public SludgeStriderTriggeredAbility copy() { + return new SludgeStriderTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever another artifact enters the battlefield under your control or another artifact you control leaves the battlefield, you may pay {1}. If you do, target player loses 1 life and you gain 1 life."; + } +} + +class SludgeStriderEffect extends OneShotEffect { + + SludgeStriderEffect() { + super(Outcome.Detriment); + } + + SludgeStriderEffect(final SludgeStriderEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(source.getFirstTarget()); + Player you = game.getPlayer(source.getControllerId()); + if (targetPlayer != null) { + targetPlayer.loseLife(1, game); + } + if (you != null) { + you.gainLife(1, game); + } + return true; + } + + @Override + public SludgeStriderEffect copy() { + return new SludgeStriderEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/innistrad/AbattoirGhoul.java b/Mage.Sets/src/mage/sets/innistrad/AbattoirGhoul.java index 9fdc64b4164..183c4bf0050 100644 --- a/Mage.Sets/src/mage/sets/innistrad/AbattoirGhoul.java +++ b/Mage.Sets/src/mage/sets/innistrad/AbattoirGhoul.java @@ -29,20 +29,16 @@ package mage.sets.innistrad; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.constants.*; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.events.ZoneChangeEvent; +import java.util.UUID; +import mage.abilities.common.DiesAndDealtDamageThisTurnTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.watchers.common.DamagedByWatcher; - -import java.util.UUID; /** * @@ -60,11 +56,9 @@ public class AbattoirGhoul extends CardImpl { this.toughness = new MageInt(2); this.addAbility(FirstStrikeAbility.getInstance()); - // Whenever a creature dealt damage by Abattoir Ghoul this turn dies, you gain life equal to that creature's toughness. - AbattoirGhoulEffect effect = new AbattoirGhoulEffect(); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); - this.addWatcher(new DamagedByWatcher()); + // Whenever a creature dealt damage by Abattoir Ghoul this turn dies, you gain life equal to that creature's toughness. + this.addAbility(new DiesAndDealtDamageThisTurnTriggeredAbility(new AbattoirGhoulEffect(), false)); } public AbattoirGhoul(final AbattoirGhoul card) { @@ -77,11 +71,11 @@ public class AbattoirGhoul extends CardImpl { } } -class AbattoirGhoulEffect extends ReplacementEffectImpl { +class AbattoirGhoulEffect extends OneShotEffect { public AbattoirGhoulEffect() { - super(Duration.WhileOnBattlefield, Outcome.GainLife); - staticText = "Whenever a creature dealt damage by Abattoir Ghoul this turn dies, you gain life equal to that creature's toughness"; + super(Outcome.GainLife); + staticText = "you gain life equal to that creature's toughness"; } public AbattoirGhoulEffect(final AbattoirGhoulEffect effect) { @@ -95,33 +89,18 @@ class AbattoirGhoulEffect extends ReplacementEffectImpl { @Override public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Permanent permanent = ((ZoneChangeEvent)event).getTarget(); - if (permanent != null) { - MageInt toughness = permanent.getToughness(); - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - player.gainLife(toughness.getValue(), game); + Player you = game.getPlayer(source.getControllerId()); + Card card = game.getCard(targetPointer.getFirst(game, source)); + if (card != null) { + Permanent creature = (Permanent) game.getLastKnownInformation(card.getId(), Zone.BATTLEFIELD); + if (creature != null) { + int toughness = creature.getToughness().getValue(); + if (you != null) { + you.gainLife(toughness, game); + return true; + } } } return false; } - - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) { - Permanent p = game.getPermanent(source.getSourceId()); - if (p != null) { - DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId()); - if (watcher != null) - return watcher.damagedCreatures.contains(event.getTargetId()); - } - } - return false; - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/planechase/SludgeStrider.java b/Mage.Sets/src/mage/sets/planechase/SludgeStrider.java new file mode 100644 index 00000000000..bc34b169b45 --- /dev/null +++ b/Mage.Sets/src/mage/sets/planechase/SludgeStrider.java @@ -0,0 +1,52 @@ +/* + * 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.sets.planechase; + +import java.util.UUID; + +/** + * + * @author jeffwadsworth + */ +public class SludgeStrider extends mage.sets.conflux.SludgeStrider { + + public SludgeStrider(UUID ownerId) { + super(ownerId); + this.cardNumber = 95; + this.expansionSetCode = "HOP"; + } + + public SludgeStrider(final SludgeStrider card) { + super(card); + } + + @Override + public SludgeStrider copy() { + return new SludgeStrider(this); + } +} diff --git a/Mage.Sets/src/mage/sets/shardsofalara/GatherSpecimens.java b/Mage.Sets/src/mage/sets/shardsofalara/GatherSpecimens.java new file mode 100644 index 00000000000..a8c306ac849 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shardsofalara/GatherSpecimens.java @@ -0,0 +1,166 @@ +/* + * 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.sets.shardsofalara; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import static mage.constants.Zone.EXILED; +import static mage.constants.Zone.GRAVEYARD; +import static mage.constants.Zone.HAND; +import static mage.constants.Zone.LIBRARY; +import static mage.constants.Zone.PICK; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.PermanentCard; + +/** + * + * @author jeffwadsworth + */ +public class GatherSpecimens extends CardImpl { + + public GatherSpecimens(UUID ownerId) { + super(ownerId, 45, "Gather Specimens", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{3}{U}{U}{U}"); + this.expansionSetCode = "ALA"; + + this.color.setBlue(true); + + // If a creature would enter the battlefield under an opponent's control this turn, it enters the battlefield under your control instead. + this.getSpellAbility().addEffect(new GatherSpecimensReplacementEffect()); + + } + + public GatherSpecimens(final GatherSpecimens card) { + super(card); + } + + @Override + public GatherSpecimens copy() { + return new GatherSpecimens(this); + } +} + +class GatherSpecimensReplacementEffect extends ReplacementEffectImpl { + + public GatherSpecimensReplacementEffect() { + super(Duration.EndOfTurn, Outcome.GainControl); + staticText = "If a creature would enter the battlefield under an opponent's control this turn, it enters the battlefield under your control instead"; + } + + public GatherSpecimensReplacementEffect(final GatherSpecimensReplacementEffect effect) { + super(effect); + } + + @Override + public GatherSpecimensReplacementEffect copy() { + return new GatherSpecimensReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + if (((ZoneChangeEvent) event).getFromZone() == Zone.HAND + || ((ZoneChangeEvent) event).getFromZone() == Zone.EXILED + || ((ZoneChangeEvent) event).getFromZone() == Zone.LIBRARY + || ((ZoneChangeEvent) event).getFromZone() == Zone.GRAVEYARD + || ((ZoneChangeEvent) event).getFromZone() == Zone.PICK) { + Card card = game.getCard(((ZoneChangeEvent) event).getTargetId()); + game.replaceEvent(event); + if (card != null) { + Zone currentZone = game.getState().getZone(card.getId()); + ZoneChangeEvent event2 = new ZoneChangeEvent(card.getId(), source.getSourceId(), source.getControllerId(), currentZone, Zone.BATTLEFIELD); + if (currentZone != null) { + boolean removed = false; + switch (currentZone) { + case GRAVEYARD: + removed = game.getPlayer(card.getOwnerId()).removeFromGraveyard(card, game); + break; + case HAND: + removed = game.getPlayer(card.getOwnerId()).removeFromHand(card, game); + break; + case LIBRARY: + removed = game.getPlayer(card.getOwnerId()).removeFromLibrary(card, game); + break; + case EXILED: + game.getExile().removeCard(card, game); + removed = true; + break; + case PICK: + removed = true; + break; + default: + System.out.println("putOntoBattlefield, not fully implemented: fromZone=" + currentZone); + } + game.rememberLKI(card.getId(), event2.getFromZone(), card); + if (!removed) { + System.out.println("Couldn't find card in fromZone, card=" + card.getName() + ", fromZone=" + currentZone); + } + } + PermanentCard permanent = new PermanentCard(card, source.getControllerId()); + game.resetForSourceId(permanent.getId()); + game.addPermanent(permanent); + game.setZone(card.getId(), Zone.BATTLEFIELD); + game.setScopeRelevant(true); + game.applyEffects(); + permanent.entersBattlefield(source.getSourceId(), game, currentZone, true); + game.setScopeRelevant(false); + game.applyEffects(); + game.fireEvent(new ZoneChangeEvent(permanent, source.getControllerId(), currentZone, Zone.BATTLEFIELD)); + return true; + } + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE + && ((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) { + Card card = game.getCard(((ZoneChangeEvent) event).getTargetId()); + if (card != null + && card.getCardType().contains(CardType.CREATURE) + && card.getOwnerId() != source.getControllerId()) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/shardsofalara/Swerve.java b/Mage.Sets/src/mage/sets/shardsofalara/Swerve.java new file mode 100644 index 00000000000..c3b4f2f5c44 --- /dev/null +++ b/Mage.Sets/src/mage/sets/shardsofalara/Swerve.java @@ -0,0 +1,72 @@ +/* + * 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.sets.shardsofalara; + +import java.util.UUID; +import mage.abilities.effects.common.ChooseNewTargetsTargetEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.NumberOfTargetsPredicate; +import mage.target.TargetSpell; + +/** + * + * @author jeffwadsworth + */ +public class Swerve extends CardImpl { + + private static final FilterSpell filter = new FilterSpell(); + + static { + filter.add(new NumberOfTargetsPredicate(1)); + } + + public Swerve(UUID ownerId) { + super(ownerId, 200, "Swerve", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{U}{R}"); + this.expansionSetCode = "ALA"; + + this.color.setRed(true); + this.color.setBlue(true); + + // Change the target of target spell with a single target. + this.getSpellAbility().addEffect(new ChooseNewTargetsTargetEffect()); + this.getSpellAbility().addTarget(new TargetSpell(filter)); + + } + + public Swerve(final Swerve card) { + super(card); + } + + @Override + public Swerve copy() { + return new Swerve(this); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/GatherSpecimensTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/GatherSpecimensTest.java new file mode 100644 index 00000000000..82eca043f2c --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/GatherSpecimensTest.java @@ -0,0 +1,97 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.test.cards.abilities.enters; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author jeffwadsworth + */ +public class GatherSpecimensTest extends CardTestPlayerBase { + + /* Gather Specimens {3}{U}{U}{U} + * + * If a creature would enter the battlefield under an opponent's control this turn, it enters the battlefield under your control instead. + */ + + @Test + public void testFromHandEffect() { + + addCard(Zone.BATTLEFIELD, playerA, "Island", 6); + addCard(Zone.HAND, playerA, "Gather Specimens", 1); + + addCard(Zone.LIBRARY, playerB, "Mountain", 1); + addCard(Zone.HAND, playerB, "Memnite", 1); + + castSpell(2, PhaseStep.UPKEEP, playerA, "Gather Specimens"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Memnite"); + + setStopAt(2, PhaseStep.END_TURN); + + execute(); + + assertPermanentCount(playerA, "Memnite", 1); + assertPermanentCount(playerB, "Memnite", 0); + + } + + @Test + public void testFromGraveyardEffect() { + + addCard(Zone.BATTLEFIELD, playerA, "Island", 6); + addCard(Zone.HAND, playerA, "Gather Specimens", 1); + addCard(Zone.LIBRARY, playerA, "Memnite", 10); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 5); + addCard(Zone.HAND, playerB, "Dread Return", 1); + addCard(Zone.GRAVEYARD, playerB, "Memnite", 1); + addCard(Zone.LIBRARY, playerB, "Swamp", 10); + + castSpell(2, PhaseStep.UPKEEP, playerA, "Gather Specimens"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Dread Return", "Memnite"); + + setStopAt(2, PhaseStep.END_TURN); + + execute(); + + assertPermanentCount(playerA, "Memnite", 1); + assertPermanentCount(playerB, "Memnite", 0); + + } + + @Test + public void testFromExileEffect() { + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 10); + addCard(Zone.BATTLEFIELD, playerA, "Island", 10); + addCard(Zone.HAND, playerA, "Disenchant", 1); + addCard(Zone.HAND, playerA, "Oblivion Ring", 1); + addCard(Zone.HAND, playerA, "Gather Specimens", 1); + addCard(Zone.LIBRARY, playerA, "Plains", 10); + + addCard(Zone.BATTLEFIELD, playerB, "Memnite", 1); + addCard(Zone.LIBRARY, playerB, "Plains", 10); + + castSpell(1, PhaseStep.UPKEEP, playerA, "Gather Specimens"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oblivion Ring"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disenchant", "Oblivion Ring"); + + setStopAt(1, PhaseStep.END_TURN); + + execute(); + + assertPermanentCount(playerA, "Memnite", 1); + assertPermanentCount(playerB, "Memnite", 0); + + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/AbattoirGhoulTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/AbattoirGhoulTest.java new file mode 100644 index 00000000000..fc9b33bc592 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/AbattoirGhoulTest.java @@ -0,0 +1,37 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.test.cards.triggers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author jeffwadsworth + */ +public class AbattoirGhoulTest extends CardTestPlayerBase{ + + @Test + public void testAbattoirGhoulEffect() { + + addCard(Zone.BATTLEFIELD, playerA, "Abattoir Ghoul", 1); + addCard(Zone.BATTLEFIELD, playerB, "Memnite", 1); + addCard(Zone.BATTLEFIELD, playerB, "Shivan Dragon", 1); + + attack(1, playerA, "Abattoir Ghoul"); + block(1, playerB, "Memnite", "Abattoir Ghoul"); + block(1, playerB, "Shivan Dragon", "Abattoir Ghoul"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 21); + assertLife(playerB, 20); + + } + +}