diff --git a/Mage.Sets/src/mage/sets/darkascension/HuntmasterOfTheFells.java b/Mage.Sets/src/mage/sets/darkascension/HuntmasterOfTheFells.java new file mode 100644 index 00000000000..6aae73ad182 --- /dev/null +++ b/Mage.Sets/src/mage/sets/darkascension/HuntmasterOfTheFells.java @@ -0,0 +1,252 @@ +/* + * 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.darkascension; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.common.NoSpellsWereCastLastTurnCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.WolfToken; +import mage.game.stack.StackObject; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetOpponent; + +/** + * + * @author BetaSteward + */ +public class HuntmasterOfTheFells extends CardImpl { + + public HuntmasterOfTheFells(UUID ownerId) { + super(ownerId, 140, "Huntmaster of the Fells", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); + this.expansionSetCode = "DKA"; + this.subtype.add("Human"); + this.subtype.add("Werewolf"); + + this.canTransform = true; + this.secondSideCard = new RavagerOfTheFells(ownerId); + + this.color.setRed(true); + this.color.setGreen(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever this creature enters the battlefield or transforms into Huntmaster of the Fells, put a 2/2 green Wolf creature token onto the battlefield and you gain 2 life. + this.addAbility(new HuntmasterOfTheFellsAbility()); + + // Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls. + this.addAbility(new RavagerOfTheFellsAbility()); + + // At the beginning of each upkeep, if no spells were cast last turn, transform Huntmaster of the Fells. + this.addAbility(new TransformAbility()); + TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(true), Constants.TargetController.ANY, false); + this.addAbility(new ConditionalTriggeredAbility(ability, NoSpellsWereCastLastTurnCondition.getInstance(), TransformAbility.NO_SPELLS_TRANSFORM_RULE)); + } + + public HuntmasterOfTheFells(final HuntmasterOfTheFells card) { + super(card); + } + + @Override + public HuntmasterOfTheFells copy() { + return new HuntmasterOfTheFells(this); + } +} + +class HuntmasterOfTheFellsAbility extends TriggeredAbilityImpl { + + public HuntmasterOfTheFellsAbility() { + super(Constants.Zone.BATTLEFIELD, new CreateTokenEffect(new WolfToken()), true); + this.addEffect(new GainLifeEffect(2)); + } + + public HuntmasterOfTheFellsAbility(final HuntmasterOfTheFellsAbility ability) { + super(ability); + } + + @Override + public HuntmasterOfTheFellsAbility copy() { + return new HuntmasterOfTheFellsAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.TRANSFORMED && event.getTargetId().equals(this.getSourceId())) { + Permanent permanent = game.getPermanent(sourceId); + if (permanent != null && !permanent.isTransformed()) + return true; + } + if (event.getType() == GameEvent.EventType.ZONE_CHANGE && event.getTargetId().equals(this.getSourceId())) { + ZoneChangeEvent zEvent = (ZoneChangeEvent)event; + if (zEvent.getToZone() == Zone.BATTLEFIELD) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever this creature enters the battlefield or transforms into Huntmaster of the Fells, put a 2/2 green Wolf creature token onto the battlefield and you gain 2 life."; + } + +} + +class RavagerOfTheFellsAbility extends TriggeredAbilityImpl { + + public RavagerOfTheFellsAbility() { + super(Constants.Zone.BATTLEFIELD, new RavagerOfTheFellsEffect(), true); + Target target1 = new TargetOpponent(); + target1.setRequired(true); + this.addTarget(target1); + this.addTarget(new RavagerOfTheFellsTarget()); + } + + public RavagerOfTheFellsAbility(final RavagerOfTheFellsAbility ability) { + super(ability); + } + + @Override + public RavagerOfTheFellsAbility copy() { + return new RavagerOfTheFellsAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.TRANSFORMED && event.getTargetId().equals(sourceId)) { + Permanent permanent = game.getPermanent(sourceId); + if (permanent != null && permanent.isTransformed()) + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls."; + } + +} + +class RavagerOfTheFellsEffect extends OneShotEffect { + + public RavagerOfTheFellsEffect() { + super(Constants.Outcome.Damage); + staticText = "{this} deals 2 damage to target opponent and 2 damage to up to one target creature that player controls"; + } + + public RavagerOfTheFellsEffect(final RavagerOfTheFellsEffect effect) { + super(effect); + } + + @Override + public RavagerOfTheFellsEffect copy() { + return new RavagerOfTheFellsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getTargets().get(0).getFirstTarget()); + if (player != null) { + player.damage(2, source.getSourceId(), game, false, true); + } + Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); + if (creature != null) { + creature.damage(2, source.getSourceId(), game, true, false); + } + return true; + } + +} + +class RavagerOfTheFellsTarget extends TargetPermanent { + + public RavagerOfTheFellsTarget() { + super(0, 1, new FilterCreaturePermanent(), false); + } + + public RavagerOfTheFellsTarget(final RavagerOfTheFellsTarget target) { + super(target); + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + UUID firstTarget = source.getFirstTarget(); + Permanent permanent = game.getPermanent(id); + if (firstTarget != null && permanent != null && permanent.getControllerId().equals(firstTarget)) { + return super.canTarget(id, source, game); + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); + Set possibleTargets = new HashSet(); + MageObject object = game.getObject(sourceId); + if (object instanceof StackObject) { + UUID playerId = ((StackObject)object).getStackAbility().getFirstTarget(); + for (UUID targetId : availablePossibleTargets) { + Permanent permanent = game.getPermanent(targetId); + if(permanent != null && permanent.getControllerId().equals(playerId)){ + possibleTargets.add(targetId); + } + } + } + return possibleTargets; + } + + @Override + public RavagerOfTheFellsTarget copy() { + return new RavagerOfTheFellsTarget(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/darkascension/RavagerOfTheFells.java b/Mage.Sets/src/mage/sets/darkascension/RavagerOfTheFells.java new file mode 100644 index 00000000000..05ac541ef86 --- /dev/null +++ b/Mage.Sets/src/mage/sets/darkascension/RavagerOfTheFells.java @@ -0,0 +1,79 @@ +/* + * 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.darkascension; + +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.common.TwoOrMoreSpellsWereCastLastTurnCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; + +/** + * + * @author BetaSteward + */ +public class RavagerOfTheFells extends CardImpl { + + public RavagerOfTheFells(UUID ownerId) { + super(ownerId, 140, "Ravager of the Fells", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, ""); + this.expansionSetCode = "DKA"; + this.subtype.add("Werewolf"); + + // this card is the second face of double-faced card + this.nightCard = true; + this.canTransform = true; + + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + this.addAbility(TrampleAbility.getInstance()); + + // Whenever this creature transforms into Ravager of the Fells, it deals 2 damage to target opponent and 2 damage to up to one target creature that player controls. + + // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ravager of the Fells. + TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), Constants.TargetController.ANY, false); + this.addAbility(new ConditionalTriggeredAbility(ability, TwoOrMoreSpellsWereCastLastTurnCondition.getInstance(), TransformAbility.TWO_OR_MORE_SPELLS_TRANSFORM_RULE)); + } + + public RavagerOfTheFells(final RavagerOfTheFells card) { + super(card); + } + + @Override + public RavagerOfTheFells copy() { + return new RavagerOfTheFells(this); + } +} diff --git a/Mage.Sets/src/mage/sets/darkascension/SorinLordOfInnistrad.java b/Mage.Sets/src/mage/sets/darkascension/SorinLordOfInnistrad.java new file mode 100644 index 00000000000..05aff395e25 --- /dev/null +++ b/Mage.Sets/src/mage/sets/darkascension/SorinLordOfInnistrad.java @@ -0,0 +1,169 @@ +/* + * 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.darkascension; + +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Duration; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.continious.BoostControlledEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.counters.CounterType; +import mage.filter.Filter; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.command.Emblem; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.target.TargetPermanent; + +/** + * + * @author BetaSteward + */ +public class SorinLordOfInnistrad extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("creature or planeswalker"); + + static { + filter.getCardType().add(CardType.CREATURE); + filter.getCardType().add(CardType.PLANESWALKER); + filter.setScopeCardType(Filter.ComparisonScope.Any); + } + + public SorinLordOfInnistrad(UUID ownerId) { + super(ownerId, 142, "Sorin, Lord of Innistrad", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{2}{W}{B}"); + this.expansionSetCode = "DKA"; + this.subtype.add("Sorin"); + + this.color.setBlack(true); + this.color.setWhite(true); + + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(3)), "")); + + // +1: Put a 1/1 black Vampire creature token with lifelink onto the battlefield. + this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new VampireToken()), 1)); + + // -2: You get an emblem with "Creatures you control get +1/+0." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new SorinEmblem()), -2)); + + // -6: Destroy up to three target creatures and/or other planeswalkers. Return each card put into a graveyard this way to the battlefield under your control. + LoyaltyAbility ability = new LoyaltyAbility(new SorinLordOfInnistradEffect(), -6); + ability.addTarget(new TargetPermanent(0, 3, filter, false)); + this.addAbility(ability); + } + + public SorinLordOfInnistrad(final SorinLordOfInnistrad card) { + super(card); + } + + @Override + public SorinLordOfInnistrad copy() { + return new SorinLordOfInnistrad(this); + } +} + +class VampireToken extends Token { + VampireToken() { + super("Vampire", "a 1/1 black Vampire creature token with lifelink"); + cardType.add(Constants.CardType.CREATURE); + color.setBlack(true); + subtype.add("Vampire"); + power = new MageInt(1); + toughness = new MageInt(1); + addAbility(LifelinkAbility.getInstance()); + } +} + +class SorinEmblem extends Emblem { + + public SorinEmblem() { + BoostControlledEffect effect = new BoostControlledEffect(1, 0, Duration.EndOfGame); + Ability ability = new SimpleStaticAbility(Zone.COMMAND, effect); + this.getAbilities().add(ability); + } +} + +class SorinLordOfInnistradEffect extends OneShotEffect { + + public SorinLordOfInnistradEffect() { + super(Constants.Outcome.Sacrifice); + this.staticText = "Destroy up to three target creatures and/or other planeswalkers. Return each card put into a graveyard this way to the battlefield under your control"; + } + + public SorinLordOfInnistradEffect(final SorinLordOfInnistradEffect effect) { + super(effect); + } + + @Override + public SorinLordOfInnistradEffect copy() { + return new SorinLordOfInnistradEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID targetId: source.getTargets().get(0).getTargets()) { + Permanent perm = game.getPermanent(targetId); + if (perm != null) { + perm.destroy(source.getSourceId(), game, false); + } + } + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + for (UUID targetId: source.getTargets().get(0).getTargets()) { + if (game.getState().getZone(targetId) == Zone.GRAVEYARD) { + Card card = game.getCard(targetId); + if (card != null) { + Player owner = game.getPlayer(card.getOwnerId()); + if (owner != null) { + owner.removeFromGraveyard(card, game); + card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getId(), player.getId()); + } + } + } + } + } + + return true; + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/TestHuntmasterOfTheFells.java b/Mage.Tests/src/test/java/org/mage/test/cards/TestHuntmasterOfTheFells.java new file mode 100644 index 00000000000..4ed3d34e1ca --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/TestHuntmasterOfTheFells.java @@ -0,0 +1,32 @@ +package org.mage.test.cards; + +import mage.Constants; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author BetaSteward + */ +public class TestHuntmasterOfTheFells extends CardTestPlayerBase { + + @Test + public void testCard() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Mountain"); + addCard(Constants.Zone.HAND, playerA, "Huntmaster of the Fells"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Ornithopter"); + + castSpell(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "Huntmaster of the Fells"); + setStopAt(3, Constants.PhaseStep.DRAW); + execute(); + + assertLife(playerA, 22); + assertLife(playerB, 18); + assertPermanentCount(playerA, "Wolf", 1); + assertPermanentCount(playerA, "Huntmaster of the Fells", 0); + assertPermanentCount(playerA, "Ravager of the Fells", 1); + assertPermanentCount(playerB, "Ornithopter", 0); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/TestSorinLordOfInnistrad.java b/Mage.Tests/src/test/java/org/mage/test/cards/TestSorinLordOfInnistrad.java new file mode 100644 index 00000000000..c99b258adf7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/TestSorinLordOfInnistrad.java @@ -0,0 +1,71 @@ +package org.mage.test.cards; + +import mage.Constants; +import mage.counters.CounterType; +import mage.filter.Filter; +import org.junit.Ignore; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * also tests emblems + * + * @author BetaSteward + */ +public class TestSorinLordOfInnistrad extends CardTestPlayerBase { + + @Test + public void testCard() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Sorin, Lord of Innistrad"); + + activateAbility(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "+1: put a a 1/1 black Vampire creature token with lifelink onto the battlefield. "); + setStopAt(1, Constants.PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Sorin, Lord of Innistrad", 1); + assertPermanentCount(playerA, "Vampire", 1); + + } + + @Test + public void testCard2() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Sorin, Lord of Innistrad"); + addCard(Constants.Zone.BATTLEFIELD, playerA, "Sejiri Merfolk"); + + addCounters(1, Constants.PhaseStep.UPKEEP, playerA, "Sorin, Lord of Innistrad", CounterType.LOYALTY, 1); + activateAbility(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "-2: You get an emblem with \"[creature you control get +1/+0. ]\". "); + activateAbility(3, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "-2: You get an emblem with \"[creature you control get +1/+0. ]\". "); + setStopAt(3, Constants.PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Sorin, Lord of Innistrad", 0); + assertPermanentCount(playerA, "Sejiri Merfolk", 1); + assertPowerToughness(playerA, "Sejiri Merfolk", 4, 1, Filter.ComparisonScope.Any); + } + + @Test + public void testCard3() { + addCard(Constants.Zone.BATTLEFIELD, playerA, "Sorin, Lord of Innistrad"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Craw Wurm"); + addCard(Constants.Zone.BATTLEFIELD, playerB, "Angel of Mercy"); + + addCounters(1, Constants.PhaseStep.UPKEEP, playerA, "Sorin, Lord of Innistrad", CounterType.LOYALTY, 3); + activateAbility(1, Constants.PhaseStep.PRECOMBAT_MAIN, playerA, "-6: ", "Craw Wurm^Angel of Mercy"); + setStopAt(1, Constants.PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 23); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Sorin, Lord of Innistrad", 0); + assertPermanentCount(playerA, "Craw Wurm", 1); + assertPermanentCount(playerB, "Craw Wurm", 0); + assertPermanentCount(playerA, "Angel of Mercy", 1); + assertPermanentCount(playerB, "Angel of Mercy", 0); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 2371a9c9877..41d1be17806 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -36,6 +36,7 @@ import mage.Constants; import mage.Constants.PhaseStep; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; +import mage.counters.Counter; import mage.filter.FilterPermanent; import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterCreatureForCombat; @@ -80,7 +81,7 @@ public class TestPlayer extends ComputerPlayer { command = command.substring(command.indexOf("activate:") + 9); String[] groups = command.split(";"); for (Ability ability: this.getPlayable(game, true)) { - if (ability.toString().equals(groups[0])) { + if (ability.toString().startsWith(groups[0])) { if (groups.length > 1) { addTargets(ability, groups, game); } @@ -90,6 +91,18 @@ public class TestPlayer extends ComputerPlayer { } } } + if (action.getAction().startsWith("addCounters:")) { + String command = action.getAction(); + command = command.substring(command.indexOf("addCounters:") + 12); + String[] groups = command.split(";"); + for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) { + if (permanent.getName().equals(groups[0])) { + Counter counter = new Counter(groups[1], Integer.parseInt(groups[2])); + permanent.addCounters(counter, game); + break; + } + } + } } } pass(); @@ -158,18 +171,21 @@ public class TestPlayer extends ComputerPlayer { } else if (group.startsWith("target=")) { target = group.substring(group.indexOf("target=") + 7); - for (Permanent permanent: game.getBattlefield().getAllActivePermanents()) { - if (permanent.getName().equals(target)) { - ability.getTargets().get(0).addTarget(permanent.getId(), ability, game); - break; + String[] targets = target.split("\\^"); + for (String t: targets) { + for (Permanent permanent: game.getBattlefield().getAllActivePermanents()) { + if (permanent.getName().equals(t)) { + ability.getTargets().get(0).addTarget(permanent.getId(), ability, game); + break; + } } - } - Iterator it = game.getStack().iterator(); - while (it.hasNext()) { - StackObject object = it.next(); - if (object.getName().equals(target)) { - ability.getTargets().get(0).addTarget(object.getId(), ability, game); - break; + Iterator it = game.getStack().iterator(); + while (it.hasNext()) { + StackObject object = it.next(); + if (object.getName().equals(t)) { + ability.getTargets().get(0).addTarget(object.getId(), ability, game); + break; + } } } } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 69f6314ca79..9bc5ea4d774 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -15,6 +15,7 @@ import org.mage.test.serverside.base.MageTestPlayerBase; import java.util.List; import java.util.UUID; import mage.Constants.PhaseStep; +import mage.counters.Counter; import mage.counters.CounterType; import org.mage.test.player.TestPlayer; @@ -156,7 +157,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement } } } - + /** * Returns card list containter for specified game zone and player. * @@ -490,7 +491,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement player.addAction(turnNum, step, "activate:" + ability + ";target=" + targetName); } - public void useAbility(int turnNum, PhaseStep step, TestPlayer player, String cardName) { + public void addCounters(int turnNum, PhaseStep step, TestPlayer player, String cardName, CounterType type, int count) { + player.addAction(turnNum, step, "addCounters:" + cardName + ";" + type.getName() + ";" + count); } public void attack(int turnNum, TestPlayer player, String attacker) { diff --git a/Mage/src/mage/abilities/effects/common/GetEmblemEffect.java b/Mage/src/mage/abilities/effects/common/GetEmblemEffect.java index 62dcd2b8787..077d86654c7 100644 --- a/Mage/src/mage/abilities/effects/common/GetEmblemEffect.java +++ b/Mage/src/mage/abilities/effects/common/GetEmblemEffect.java @@ -30,12 +30,9 @@ package mage.abilities.effects.common; import mage.Constants.Outcome; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.game.Game; import mage.game.command.Emblem; -import mage.game.permanent.token.Token; /** * @@ -67,6 +64,9 @@ public class GetEmblemEffect extends OneShotEffect { newEmblem.setSourceId(source.getSourceId()); newEmblem.setControllerId(source.getControllerId()); game.getState().getCommand().add(newEmblem); + for (Ability ability: newEmblem.getAbilities()) { + game.getState().addAbility(ability); + } return true; } diff --git a/Mage/src/mage/game/command/Emblem.java b/Mage/src/mage/game/command/Emblem.java index 55986304da9..95f6412ad40 100644 --- a/Mage/src/mage/game/command/Emblem.java +++ b/Mage/src/mage/game/command/Emblem.java @@ -27,22 +27,19 @@ */ package mage.game.command; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import mage.Constants; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Abilities; import mage.abilities.AbilitiesImpl; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; import mage.game.Game; -import mage.game.events.GameEvent; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; /** * @author nantuko @@ -82,25 +79,13 @@ public class Emblem implements CommandObject { public void setControllerId(UUID controllerId) { this.controllerId = controllerId; + this.abilites.setControllerId(controllerId); } public void setSourceId(UUID sourceId) { this.sourceId = sourceId; } -// @Override -// public void checkTriggers(GameEvent event, Game game) { -// // we have to use Zone.BATTLEFIELD to use the same predefined abilities (like SpellCastTriggeredAbility) -// // and not create duplicates -// for (TriggeredAbility ability: getAbilities().getTriggeredAbilities(Constants.Zone.BATTLEFIELD)) { -// ability.setControllerId(getControllerId()); -// ability.setSourceId(getSourceId()); -// if (ability.checkTrigger(event, game)) { -// ability.trigger(game, getControllerId()); -// } -// } -// } - @Override public String getName() { return ""; @@ -162,6 +147,7 @@ public class Emblem implements CommandObject { return this.id; } + @Override public Emblem copy() { return new Emblem(this); }