diff --git a/Mage.Sets/src/mage/sets/conspiracy/CoercivePortal.java b/Mage.Sets/src/mage/sets/conspiracy/CoercivePortal.java new file mode 100644 index 0000000000..7dcd761408 --- /dev/null +++ b/Mage.Sets/src/mage/sets/conspiracy/CoercivePortal.java @@ -0,0 +1,143 @@ +/* + * 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.conspiracy; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterNonlandPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author fireshoes + */ +public class CoercivePortal extends CardImpl { + + public CoercivePortal(UUID ownerId) { + super(ownerId, 56, "Coercive Portal", Rarity.MYTHIC, new CardType[]{CardType.ARTIFACT}, "{4}"); + this.expansionSetCode = "CNS"; + + // Will of the council - At the beginning of your upkeep, starting with you, each player votes for carnage or homage. If carnage gets more votes, sacrifice Coercive Portal and destroy all nonland permanents. If homage gets more votes or the vote is tied, draw a card. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CoercivePortalEffect(), TargetController.YOU, false)); + } + + public CoercivePortal(final CoercivePortal card) { + super(card); + } + + @Override + public CoercivePortal copy() { + return new CoercivePortal(this); + } +} + +class CoercivePortalEffect extends OneShotEffect { + + CoercivePortalEffect() { + super(Outcome.Benefit); + this.staticText = "Will of the council - At the beginning of your upkeep, starting with you, each player votes for carnage or homage. If carnage gets more votes, sacrifice Coercive Portal and destroy all nonland permanents. If homage gets more votes or the vote is tied, draw a card"; + } + + CoercivePortalEffect(final CoercivePortalEffect effect) { + super(effect); + } + + @Override + public CoercivePortalEffect copy() { + return new CoercivePortalEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int carnageCount = 0; + int homageCount = 0; + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + if (player.chooseUse(Outcome.DestroyPermanent, "Choose carnage?", game)) { + carnageCount++; + game.informPlayers(player.getLogName() + " has chosen: carnage"); + } + else { + homageCount++; + game.informPlayers(player.getLogName() + " has chosen: homage"); + } + } + } + if (carnageCount > homageCount) { + new SacrificeSourceEffect().apply(game, source); + new CoercivePortalDestroyEffect().apply(game, source); + } else { + controller.drawCards(1, game); + } + return true; + } + return false; + } +} + +class CoercivePortalDestroyEffect extends OneShotEffect { + + private static final FilterPermanent filter = new FilterNonlandPermanent(); + + public CoercivePortalDestroyEffect() { + super(Outcome.DestroyPermanent); + staticText = "sacrifice Coercive Portal and destroy all nonland permanents"; + } + + public CoercivePortalDestroyEffect(final CoercivePortalDestroyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + permanent.destroy(source.getSourceId(), game, false); + } + return true; + } + + @Override + public CoercivePortalDestroyEffect copy() { + return new CoercivePortalDestroyEffect(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/conspiracy/DeathreapRitual.java b/Mage.Sets/src/mage/sets/conspiracy/DeathreapRitual.java new file mode 100644 index 0000000000..8e6bba3721 --- /dev/null +++ b/Mage.Sets/src/mage/sets/conspiracy/DeathreapRitual.java @@ -0,0 +1,63 @@ +/* + * 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.conspiracy; + +import java.util.UUID; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.common.MorbidCondition; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author fireshoes + */ +public class DeathreapRitual extends CardImpl { + + public DeathreapRitual(UUID ownerId) { + super(ownerId, 44, "Deathreap Ritual", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{G}"); + this.expansionSetCode = "CNS"; + + // Morbid - At the beginning of each end step, if a creature died this turn, you may draw a card. + this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), + TargetController.ANY, MorbidCondition.getInstance(), true)); + } + + public DeathreapRitual(final DeathreapRitual card) { + super(card); + } + + @Override + public DeathreapRitual copy() { + return new DeathreapRitual(this); + } +} diff --git a/Mage.Sets/src/mage/sets/conspiracy/TyrantsChoice.java b/Mage.Sets/src/mage/sets/conspiracy/TyrantsChoice.java new file mode 100644 index 0000000000..845b4b01c3 --- /dev/null +++ b/Mage.Sets/src/mage/sets/conspiracy/TyrantsChoice.java @@ -0,0 +1,136 @@ +/* + * 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.conspiracy; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeOpponentsEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author fireshoes + */ +public class TyrantsChoice extends CardImpl { + + public TyrantsChoice(UUID ownerId) { + super(ownerId, 30, "Tyrant's Choice", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{1}{B}"); + this.expansionSetCode = "CNS"; + + // Will of the council - Starting with you, each player votes for death or torture. If death gets more votes, each opponent sacrifices a creature. If torture gets more votes or the vote is tied, each opponent loses 4 life. + this.getSpellAbility().addEffect(new TyrantsChoiceEffect()); + } + + public TyrantsChoice(final TyrantsChoice card) { + super(card); + } + + @Override + public TyrantsChoice copy() { + return new TyrantsChoice(this); + } +} + +class TyrantsChoiceEffect extends OneShotEffect { + + TyrantsChoiceEffect() { + super(Outcome.Benefit); + this.staticText = "Will of the council - Starting with you, each player votes for death or torture. If death gets more votes, each opponent sacrifices a creature. If torture gets more votes or the vote is tied, each opponent loses 4 life"; + } + + TyrantsChoiceEffect(final TyrantsChoiceEffect effect) { + super(effect); + } + + @Override + public TyrantsChoiceEffect copy() { + return new TyrantsChoiceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + int deathCount = 0; + int tortureCount = 0; + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + if (player.chooseUse(Outcome.Sacrifice, "Choose death?", game)) { + deathCount++; + game.informPlayers(player.getLogName() + " has chosen: death"); + } + else { + tortureCount++; + game.informPlayers(player.getLogName() + " has chosen: torture"); + } + } + } + if (deathCount > tortureCount) { + new SacrificeOpponentsEffect(new FilterControlledCreaturePermanent("a creature")).apply(game, source); + } else { + new TyrantsChoiceLoseLifeEffect().apply(game, source); + } + return true; + } + return false; + } +} + +class TyrantsChoiceLoseLifeEffect extends OneShotEffect { + + public TyrantsChoiceLoseLifeEffect() { + super(Outcome.Damage); + staticText = "Each opponent loses 2 life"; + } + + public TyrantsChoiceLoseLifeEffect(final TyrantsChoiceLoseLifeEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + game.getPlayer(opponentId).loseLife(4, game); + } + return true; + } + + @Override + public TyrantsChoiceLoseLifeEffect copy() { + return new TyrantsChoiceLoseLifeEffect(this); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/eventide/Doomgape.java b/Mage.Sets/src/mage/sets/eventide/Doomgape.java index 79b97608e4..55198b9822 100644 --- a/Mage.Sets/src/mage/sets/eventide/Doomgape.java +++ b/Mage.Sets/src/mage/sets/eventide/Doomgape.java @@ -96,15 +96,15 @@ class DoomgapeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player you = game.getPlayer(source.getControllerId()); - if (you != null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { Target target = new TargetControlledCreaturePermanent(); target.setNotTarget(true); - if (you.choose(Outcome.Sacrifice, target, source.getSourceId(), game)) { + if (controller.choose(Outcome.Sacrifice, target, source.getSourceId(), game)) { Permanent creature = game.getPermanent(target.getFirstTarget()); if (creature != null) { if (creature.sacrifice(source.getSourceId(), game)) { - you.gainLife(creature.getToughness().getValue(), game); + controller.gainLife(creature.getToughness().getValue(), game); return true; } } @@ -112,4 +112,4 @@ class DoomgapeEffect extends OneShotEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/BattlefieldForge.java b/Mage.Sets/src/mage/sets/magicorigins/BattlefieldForge.java new file mode 100644 index 0000000000..bfeaebc725 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/BattlefieldForge.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.magicorigins; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class BattlefieldForge extends mage.sets.apocalypse.BattlefieldForge { + + public BattlefieldForge(UUID ownerId) { + super(ownerId); + this.cardNumber = 244; + this.expansionSetCode = "ORI"; + } + + public BattlefieldForge(final BattlefieldForge card) { + super(card); + } + + @Override + public BattlefieldForge copy() { + return new BattlefieldForge(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/CavesOfKoilos.java b/Mage.Sets/src/mage/sets/magicorigins/CavesOfKoilos.java new file mode 100644 index 0000000000..d88b5f5448 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/CavesOfKoilos.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.magicorigins; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class CavesOfKoilos extends mage.sets.apocalypse.CavesOfKoilos { + + public CavesOfKoilos(UUID ownerId) { + super(ownerId); + this.cardNumber = 245; + this.expansionSetCode = "ORI"; + } + + public CavesOfKoilos(final CavesOfKoilos card) { + super(card); + } + + @Override + public CavesOfKoilos copy() { + return new CavesOfKoilos(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/CitadelCastellan.java b/Mage.Sets/src/mage/sets/magicorigins/CitadelCastellan.java new file mode 100644 index 0000000000..630306749f --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/CitadelCastellan.java @@ -0,0 +1,66 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.keyword.RenownAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class CitadelCastellan extends CardImpl { + + public CitadelCastellan(UUID ownerId) { + super(ownerId, 213, "Citadel Castellan", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{1}{G}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Knight"); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + // Renown 2 + this.addAbility(new RenownAbility(2)); + } + + public CitadelCastellan(final CitadelCastellan card) { + super(card); + } + + @Override + public CitadelCastellan copy() { + return new CitadelCastellan(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/LlanowarWastes.java b/Mage.Sets/src/mage/sets/magicorigins/LlanowarWastes.java new file mode 100644 index 0000000000..74a997f25b --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/LlanowarWastes.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.magicorigins; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class LlanowarWastes extends mage.sets.apocalypse.LlanowarWastes { + + public LlanowarWastes(UUID ownerId) { + super(ownerId); + this.cardNumber = 248; + this.expansionSetCode = "ORI"; + } + + public LlanowarWastes(final LlanowarWastes card) { + super(card); + } + + @Override + public LlanowarWastes copy() { + return new LlanowarWastes(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ShivanReef.java b/Mage.Sets/src/mage/sets/magicorigins/ShivanReef.java new file mode 100644 index 0000000000..c35dfb1fa5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/ShivanReef.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.magicorigins; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class ShivanReef extends mage.sets.apocalypse.ShivanReef { + + public ShivanReef(UUID ownerId) { + super(ownerId); + this.cardNumber = 251; + this.expansionSetCode = "ORI"; + } + + public ShivanReef(final ShivanReef card) { + super(card); + } + + @Override + public ShivanReef copy() { + return new ShivanReef(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/TopanFreeblade.java b/Mage.Sets/src/mage/sets/magicorigins/TopanFreeblade.java new file mode 100644 index 0000000000..9d3e7d6f92 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/TopanFreeblade.java @@ -0,0 +1,64 @@ +/* + * 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.magicorigins; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.keyword.RenownAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class TopanFreeblade extends CardImpl { + + public TopanFreeblade(UUID ownerId) { + super(ownerId, 36, "Topan Freeblade", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.expansionSetCode = "ORI"; + this.subtype.add("Human"); + this.subtype.add("Soldier"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Vigilance (Attacking doesn't cause this creature to tap.) + // Renown 1 + this.addAbility(new RenownAbility(1)); + } + + public TopanFreeblade(final TopanFreeblade card) { + super(card); + } + + @Override + public TopanFreeblade copy() { + return new TopanFreeblade(this); + } +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/YavimayaCoast.java b/Mage.Sets/src/mage/sets/magicorigins/YavimayaCoast.java new file mode 100644 index 0000000000..2775603052 --- /dev/null +++ b/Mage.Sets/src/mage/sets/magicorigins/YavimayaCoast.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.magicorigins; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class YavimayaCoast extends mage.sets.apocalypse.YavimayaCoast { + + public YavimayaCoast(UUID ownerId) { + super(ownerId); + this.cardNumber = 252; + this.expansionSetCode = "ORI"; + } + + public YavimayaCoast(final YavimayaCoast card) { + super(card); + } + + @Override + public YavimayaCoast copy() { + return new YavimayaCoast(this); + } +} diff --git a/Mage.Sets/src/mage/sets/portalsecondage/PredatoryNightstalker.java b/Mage.Sets/src/mage/sets/portalsecondage/PredatoryNightstalker.java new file mode 100644 index 0000000000..9f04d5566e --- /dev/null +++ b/Mage.Sets/src/mage/sets/portalsecondage/PredatoryNightstalker.java @@ -0,0 +1,54 @@ +/* + * 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.portalsecondage; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class PredatoryNightstalker extends mage.sets.vintagemasters.PredatoryNightstalker { + + public PredatoryNightstalker(UUID ownerId) { + super(ownerId); + this.cardNumber = 22; + this.expansionSetCode = "PO2"; + this.rarity = Rarity.UNCOMMON; + } + + public PredatoryNightstalker(final PredatoryNightstalker card) { + super(card); + } + + @Override + public PredatoryNightstalker copy() { + return new PredatoryNightstalker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/scourge/DeathsHeadBuzzard.java b/Mage.Sets/src/mage/sets/scourge/DeathsHeadBuzzard.java new file mode 100644 index 0000000000..091e5500a5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/scourge/DeathsHeadBuzzard.java @@ -0,0 +1,68 @@ +/* + * 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.scourge; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class DeathsHeadBuzzard extends CardImpl { + + public DeathsHeadBuzzard(UUID ownerId) { + super(ownerId, 63, "Death's-Head Buzzard", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); + this.expansionSetCode = "SCG"; + this.subtype.add("Bird"); + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Death's-Head Buzzard dies, all creatures get -1/-1 until end of turn. + this.addAbility(new DiesTriggeredAbility(new BoostAllEffect(-1, -1, Duration.EndOfTurn))); + } + + public DeathsHeadBuzzard(final DeathsHeadBuzzard card) { + super(card); + } + + @Override + public DeathsHeadBuzzard copy() { + return new DeathsHeadBuzzard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/theros/DaxosOfMeletis.java b/Mage.Sets/src/mage/sets/theros/DaxosOfMeletis.java index f59829ce40..2fa8135603 100644 --- a/Mage.Sets/src/mage/sets/theros/DaxosOfMeletis.java +++ b/Mage.Sets/src/mage/sets/theros/DaxosOfMeletis.java @@ -61,6 +61,7 @@ import mage.util.CardUtil; public class DaxosOfMeletis extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with power 3 or greater"); + static { filter.add(new PowerPredicate(Filter.ComparisonType.GreaterThan, 2)); } @@ -119,7 +120,7 @@ class DaxosOfMeletisEffect extends OneShotEffect { Card card = damagedPlayer.getLibrary().getFromTop(game); if (card != null) { // move card to exile - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); // player gains life int cmc = card.getManaCost().convertedManaCost(); if (cmc > 0) { @@ -172,7 +173,7 @@ class DaxosOfMeletisCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - if (sourceId.equals(cardId)) { + if (sourceId.equals(cardId) && source.getControllerId().equals(affectedControllerId)) { ExileZone exileZone = game.getState().getExile().getExileZone(exileId); return exileZone != null && exileZone.contains(cardId); } @@ -202,7 +203,10 @@ class DaxosOfMeletisSpendAnyManaEffect extends AsThoughEffectImpl { } @Override - public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { - return sourceId.equals(getTargetPointer().getFirst(game, source)); + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + return source.getControllerId().equals(affectedControllerId) + && objectId == ((FixedTarget) getTargetPointer()).getTarget() + && ((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(objectId) + && game.getState().getZone(objectId).equals(Zone.STACK); } } diff --git a/Mage.Sets/src/mage/sets/urzassaga/SkirgeFamiliar.java b/Mage.Sets/src/mage/sets/urzassaga/SkirgeFamiliar.java new file mode 100644 index 0000000000..6b3a028fa0 --- /dev/null +++ b/Mage.Sets/src/mage/sets/urzassaga/SkirgeFamiliar.java @@ -0,0 +1,54 @@ +/* + * 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.urzassaga; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class SkirgeFamiliar extends mage.sets.vintagemasters.SkirgeFamiliar { + + public SkirgeFamiliar(UUID ownerId) { + super(ownerId); + this.cardNumber = 157; + this.expansionSetCode = "USG"; + this.rarity = Rarity.UNCOMMON; + } + + public SkirgeFamiliar(final SkirgeFamiliar card) { + super(card); + } + + @Override + public SkirgeFamiliar copy() { + return new SkirgeFamiliar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/CoercivePortal.java b/Mage.Sets/src/mage/sets/vintagemasters/CoercivePortal.java new file mode 100644 index 0000000000..a89aaa3b05 --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/CoercivePortal.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.vintagemasters; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class CoercivePortal extends mage.sets.conspiracy.CoercivePortal { + + public CoercivePortal(UUID ownerId) { + super(ownerId); + this.cardNumber = 266; + this.expansionSetCode = "VMA"; + } + + public CoercivePortal(final CoercivePortal card) { + super(card); + } + + @Override + public CoercivePortal copy() { + return new CoercivePortal(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/CouncilsJudgment.java b/Mage.Sets/src/mage/sets/vintagemasters/CouncilsJudgment.java index 09ab30df41..a468c20fd6 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/CouncilsJudgment.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/CouncilsJudgment.java @@ -44,7 +44,6 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.players.PlayerList; import mage.target.Target; import mage.target.common.TargetNonlandPermanent; @@ -58,7 +57,6 @@ public class CouncilsJudgment extends CardImpl { super(ownerId, 20, "Council's Judgment", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{1}{W}{W}"); this.expansionSetCode = "VMA"; - // Will of the council - Starting with you, each player votes for a nonland permanent you don't control. Exile each permanent with the most votes or tied for most votes. this.getSpellAbility().addEffect(new CouncilsJudgmentEffect()); } @@ -74,21 +72,21 @@ public class CouncilsJudgment extends CardImpl { } class CouncilsJudgmentEffect extends OneShotEffect { - + CouncilsJudgmentEffect() { super(Outcome.Exile); this.staticText = "Will of the council — Starting with you, each player votes for a nonland permanent you don't control. Exile each permanent with the most votes or tied for most votes"; } - + CouncilsJudgmentEffect(final CouncilsJudgmentEffect effect) { super(effect); } - + @Override public CouncilsJudgmentEffect copy() { return new CouncilsJudgmentEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); @@ -98,13 +96,9 @@ class CouncilsJudgmentEffect extends OneShotEffect { FilterNonlandPermanent filter = new FilterNonlandPermanent("a nonland permanent " + controller.getLogName() + " doesn't control"); filter.add(Predicates.not(new ControllerIdPredicate(controller.getId()))); //Players each choose a legal permanent - PlayerList playerList = game.getState().getPlayerList().copy(); - while (!playerList.get().equals(controller.getId()) && controller.isInGame()) { - playerList.getNext(); - } - do { - Player player = game.getPlayer(playerList.get()); - if (player != null && player.isInGame()) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { Target target = new TargetNonlandPermanent(filter); target.setNotTarget(true); if (player.choose(Outcome.Exile, target, source.getSourceId(), game)) { @@ -116,8 +110,7 @@ class CouncilsJudgmentEffect extends OneShotEffect { maxCount = count; } chosenCards.put(permanent, count); - } - else { + } else { if (maxCount == 0) { maxCount = 1; } @@ -127,7 +120,8 @@ class CouncilsJudgmentEffect extends OneShotEffect { } } } - } while (playerList.getNextInRange(controller, game) != controller && controller.isInGame()); + } + //Exile the card(s) with the most votes. for (Entry entry : chosenCards.entrySet()) { if (entry.getValue() == maxCount) { diff --git a/Mage.Sets/src/mage/sets/vintagemasters/DeathreapRitual.java b/Mage.Sets/src/mage/sets/vintagemasters/DeathreapRitual.java new file mode 100644 index 0000000000..b33db6c25b --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/DeathreapRitual.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.vintagemasters; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class DeathreapRitual extends mage.sets.conspiracy.DeathreapRitual { + + public DeathreapRitual(UUID ownerId) { + super(ownerId); + this.cardNumber = 250; + this.expansionSetCode = "VMA"; + } + + public DeathreapRitual(final DeathreapRitual card) { + super(card); + } + + @Override + public DeathreapRitual copy() { + return new DeathreapRitual(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/DeathsHeadBuzzard.java b/Mage.Sets/src/mage/sets/vintagemasters/DeathsHeadBuzzard.java new file mode 100644 index 0000000000..1563509411 --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/DeathsHeadBuzzard.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.vintagemasters; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class DeathsHeadBuzzard extends mage.sets.scourge.DeathsHeadBuzzard { + + public DeathsHeadBuzzard(UUID ownerId) { + super(ownerId); + this.cardNumber = 115; + this.expansionSetCode = "VMA"; + } + + public DeathsHeadBuzzard(final DeathsHeadBuzzard card) { + super(card); + } + + @Override + public DeathsHeadBuzzard copy() { + return new DeathsHeadBuzzard(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/FallenAskari.java b/Mage.Sets/src/mage/sets/vintagemasters/FallenAskari.java new file mode 100644 index 0000000000..a6e6d87e4d --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/FallenAskari.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.vintagemasters; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class FallenAskari extends mage.sets.visions.FallenAskari { + + public FallenAskari(UUID ownerId) { + super(ownerId); + this.cardNumber = 119; + this.expansionSetCode = "VMA"; + } + + public FallenAskari(final FallenAskari card) { + super(card); + } + + @Override + public FallenAskari copy() { + return new FallenAskari(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/FledglingDjinn.java b/Mage.Sets/src/mage/sets/vintagemasters/FledglingDjinn.java new file mode 100644 index 0000000000..5840c4949e --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/FledglingDjinn.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.vintagemasters; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class FledglingDjinn extends mage.sets.weatherlight.FledglingDjinn { + + public FledglingDjinn(UUID ownerId) { + super(ownerId); + this.cardNumber = 121; + this.expansionSetCode = "VMA"; + } + + public FledglingDjinn(final FledglingDjinn card) { + super(card); + } + + @Override + public FledglingDjinn copy() { + return new FledglingDjinn(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/PleaForPower.java b/Mage.Sets/src/mage/sets/vintagemasters/PleaForPower.java index c52d1898eb..1561a1a2ff 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/PleaForPower.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/PleaForPower.java @@ -63,42 +63,42 @@ public class PleaForPower extends CardImpl { } class PleaForPowerEffect extends OneShotEffect { - + PleaForPowerEffect() { super(Outcome.Benefit); this.staticText = "Will of the council — Starting with you, each player votes for time or knowledge. If time gets more votes, take an extra turn after this one. If knowledge gets more votes or the vote is tied, draw three cards"; } - + PleaForPowerEffect(final PleaForPowerEffect effect) { super(effect); } - + @Override public PleaForPowerEffect copy() { return new PleaForPowerEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { int timeCount = 0; int knowledgeCount = 0; - for (UUID playerId : controller.getInRange()) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); - if (player.chooseUse(Outcome.ExtraTurn, "Choose time?", game)) { - timeCount++; - game.informPlayers(player.getLogName() + " has chosen: time"); - } - else { - knowledgeCount++; - game.informPlayers(player.getLogName() + " has chosen: knowledge"); + if (player != null) { + if (player.chooseUse(Outcome.ExtraTurn, "Choose time?", game)) { + timeCount++; + game.informPlayers(player.getLogName() + " has chosen: time"); + } else { + knowledgeCount++; + game.informPlayers(player.getLogName() + " has chosen: knowledge"); + } } } if (timeCount > knowledgeCount) { new AddExtraTurnControllerEffect().apply(game, source); - } - else { + } else { controller.drawCards(3, game); } return true; diff --git a/Mage.Sets/src/mage/sets/vintagemasters/PredatoryNightstalker.java b/Mage.Sets/src/mage/sets/vintagemasters/PredatoryNightstalker.java new file mode 100644 index 0000000000..a5b83faa3e --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/PredatoryNightstalker.java @@ -0,0 +1,68 @@ +/* + * 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.vintagemasters; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.SacrificeEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.common.FilterCreaturePermanent; +import mage.target.common.TargetOpponent; + +/** + * + * @author fireshoes + */ +public class PredatoryNightstalker extends CardImpl { + + public PredatoryNightstalker(UUID ownerId) { + super(ownerId, 134, "Predatory Nightstalker", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + this.expansionSetCode = "VMA"; + this.subtype.add("Nightstalker"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Predatory Nightstalker enters the battlefield, you may have target opponent sacrifice a creature. + Ability ability = new EntersBattlefieldTriggeredAbility(new SacrificeEffect(new FilterCreaturePermanent("creature"), 1, "target opponent"), true); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public PredatoryNightstalker(final PredatoryNightstalker card) { + super(card); + } + + @Override + public PredatoryNightstalker copy() { + return new PredatoryNightstalker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/SkirgeFamiliar.java b/Mage.Sets/src/mage/sets/vintagemasters/SkirgeFamiliar.java new file mode 100644 index 0000000000..bcd11c0a87 --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/SkirgeFamiliar.java @@ -0,0 +1,69 @@ +/* + * 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.vintagemasters; + +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; + +/** + * + * @author fireshoes + */ +public class SkirgeFamiliar extends CardImpl { + + public SkirgeFamiliar(UUID ownerId) { + super(ownerId, 140, "Skirge Familiar", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{4}{B}"); + this.expansionSetCode = "VMA"; + this.subtype.add("Imp"); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Discard a card: Add {B} to your mana pool. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana, new DiscardCardCost(false))); + } + + public SkirgeFamiliar(final SkirgeFamiliar card) { + super(card); + } + + @Override + public SkirgeFamiliar copy() { + return new SkirgeFamiliar(this); + } +} diff --git a/Mage.Sets/src/mage/sets/vintagemasters/TyrantsChoice.java b/Mage.Sets/src/mage/sets/vintagemasters/TyrantsChoice.java new file mode 100644 index 0000000000..b655df48f6 --- /dev/null +++ b/Mage.Sets/src/mage/sets/vintagemasters/TyrantsChoice.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.vintagemasters; + +import java.util.UUID; + +/** + * + * @author fireshoes + */ +public class TyrantsChoice extends mage.sets.conspiracy.TyrantsChoice { + + public TyrantsChoice(UUID ownerId) { + super(ownerId); + this.cardNumber = 143; + this.expansionSetCode = "VMA"; + } + + public TyrantsChoice(final TyrantsChoice card) { + super(card); + } + + @Override + public TyrantsChoice copy() { + return new TyrantsChoice(this); + } +} diff --git a/Mage.Sets/src/mage/sets/visions/FallenAskari.java b/Mage.Sets/src/mage/sets/visions/FallenAskari.java new file mode 100644 index 0000000000..2da44e4824 --- /dev/null +++ b/Mage.Sets/src/mage/sets/visions/FallenAskari.java @@ -0,0 +1,67 @@ +/* + * 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.visions; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.CantBlockAbility; +import mage.abilities.keyword.FlankingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author fireshoes + */ +public class FallenAskari extends CardImpl { + + public FallenAskari(UUID ownerId) { + super(ownerId, 9, "Fallen Askari", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.expansionSetCode = "VIS"; + this.subtype.add("Human"); + this.subtype.add("Knight"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flanking + this.addAbility(new FlankingAbility()); + + // Fallen Askari can't block. + this.addAbility(new CantBlockAbility()); + } + + public FallenAskari(final FallenAskari card) { + super(card); + } + + @Override + public FallenAskari copy() { + return new FallenAskari(this); + } +} diff --git a/Mage.Sets/src/mage/sets/weatherlight/FledglingDjinn.java b/Mage.Sets/src/mage/sets/weatherlight/FledglingDjinn.java new file mode 100644 index 0000000000..4a2a3ab7f5 --- /dev/null +++ b/Mage.Sets/src/mage/sets/weatherlight/FledglingDjinn.java @@ -0,0 +1,68 @@ +/* + * 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.weatherlight; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.TargetController; + +/** + * + * @author fireshoes + */ +public class FledglingDjinn extends CardImpl { + + public FledglingDjinn(UUID ownerId) { + super(ownerId, 11, "Fledgling Djinn", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.expansionSetCode = "WTH"; + this.subtype.add("Djinn"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of your upkeep, Fledgling Djinn deals 1 damage to you. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DamageControllerEffect(1), TargetController.YOU, false)); + } + + public FledglingDjinn(final FledglingDjinn card) { + super(card); + } + + @Override + public FledglingDjinn copy() { + return new FledglingDjinn(this); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/SpendManaAsThoughItWereManaOfAnyColorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/SpendManaAsThoughItWereManaOfAnyColorTest.java new file mode 100644 index 0000000000..30b888546e --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/SpendManaAsThoughItWereManaOfAnyColorTest.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 org.mage.test.cards.mana; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class SpendManaAsThoughItWereManaOfAnyColorTest extends CardTestPlayerBase { + + @Test + public void testDaxosOfMeletis() { + // Put two 2/2 black Zombie creature tokens onto the battlefield. + // Flashback (You may cast this card from your graveyard for its flashback cost. Then exile it.) + addCard(Zone.LIBRARY, playerA, "Moan of the Unhallowed", 1); + + skipInitShuffling(); + + // Daxos of Meletis can't be blocked by creatures with power 3 or greater. + // Whenever Daxos of Meletis deals combat damage to a player, exile the top card of that player's library. + // You gain life equal to that card's converted mana cost. Until end of turn, you may cast that card and + // you may spend mana as though it were mana of any color to cast it. + addCard(Zone.BATTLEFIELD, playerB, "Daxos of Meletis", 1); + addCard(Zone.BATTLEFIELD, playerB, "Island", 4); + + attack(2, playerB, "Daxos of Meletis"); + + castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Moan of the Unhallowed"); + + setStopAt(2, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 18); + assertLife(playerB, 24); + + assertExileCount(playerA, 0); + assertGraveyardCount(playerA, "Moan of the Unhallowed", 1); + assertPermanentCount(playerB, "Zombie", 2); + + } + +} diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index bfc6bcd22b..ad2bf78df8 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.abilities; import java.util.ArrayList; @@ -141,18 +140,18 @@ public abstract class AbilityImpl implements Ability { this.manaCostsToPay = ability.manaCostsToPay.copy(); this.costs = ability.costs.copy(); this.optionalCosts = ability.optionalCosts.copy(); - for (AlternativeCost cost: ability.alternativeCosts) { - this.alternativeCosts.add((AlternativeCost)cost.copy()); + for (AlternativeCost cost : ability.alternativeCosts) { + this.alternativeCosts.add((AlternativeCost) cost.copy()); } if (ability.watchers != null) { this.watchers = new ArrayList<>(); - for (Watcher watcher: ability.watchers) { + for (Watcher watcher : ability.watchers) { watchers.add(watcher.copy()); } } if (ability.subAbilities != null) { this.subAbilities = new ArrayList<>(); - for (Ability subAbility: ability.subAbilities) { + for (Ability subAbility : ability.subAbilities) { subAbilities.add(subAbility.copy()); } } @@ -197,7 +196,7 @@ public abstract class AbilityImpl implements Ability { boolean result = true; //20100716 - 117.12 if (checkIfClause(game)) { - for (Effect effect: getEffects()) { + for (Effect effect : getEffects()) { if (effect instanceof OneShotEffect) { boolean effectResult = effect.apply(game, this); result &= effectResult; @@ -214,24 +213,28 @@ public abstract class AbilityImpl implements Ability { } } } - } - else { + } else { game.addEffect((ContinuousEffect) effect, this); } /** - * All restrained trigger events are fired now. - * To restrain the events is mainly neccessary because of the movement of multiple object at once. - * If the event is fired directly as one object moved, other objects are not already in the correct zone - * to check for their effects. (e.g. Valakut, the Molten Pinnacle) + * All restrained trigger events are fired now. To restrain the + * events is mainly neccessary because of the movement of + * multiple object at once. If the event is fired directly as + * one object moved, other objects are not already in the + * correct zone to check for their effects. (e.g. Valakut, the + * Molten Pinnacle) */ game.getState().handleSimultaneousEvent(game); - game.resetShortLivingLKI(); - /** - * game.applyEffects() has to be done at least for every effect that moves cards/permanent between zones, - * so Static effects work as intened if dependant from the moved objects zone it is in - * Otherwise for example were static abilities with replacement effects deactivated to late - * Example: {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy} - */ + game.resetShortLivingLKI(); + /** + * game.applyEffects() has to be done at least for every effect + * that moves cards/permanent between zones, or chnages control + * of objects so Static effects work as intened if dependant + * from the moved objects zone it is in Otherwise for example + * were static abilities with replacement effects deactivated to + * late Example: + * {@link org.mage.test.cards.replacement.DryadMilitantTest#testDiesByDestroy testDiesByDestroy} + */ if (effect.applyEffectsAfter()) { game.applyEffects(); } @@ -256,7 +259,7 @@ public abstract class AbilityImpl implements Ability { } getSourceObject(game); - + /* 20130201 - 601.2b * If the player wishes to splice any cards onto the spell (see rule 702.45), he * or she reveals those cards in his or her hand. @@ -264,14 +267,13 @@ public abstract class AbilityImpl implements Ability { if (this.abilityType.equals(AbilityType.SPELL)) { game.getContinuousEffects().applySpliceEffects(this, game); } - - + if (sourceObject != null) { sourceObject.adjustChoices(this, game); } // TODO: Because all (non targeted) choices have to be done during resolution // this has to be removed, if all using effects are changed - for (UUID modeId :this.getModes().getSelectedModes()) { + for (UUID modeId : this.getModes().getSelectedModes()) { this.getModes().setActiveMode(modeId); if (getChoices().size() > 0 && getChoices().choose(game, this) == false) { logger.debug("activate failed - choice"); @@ -297,7 +299,7 @@ public abstract class AbilityImpl implements Ability { // as buyback, kicker, or convoke costs (see rules 117.8 and 117.9), the player announces his // or her intentions to pay any or all of those costs (see rule 601.2e). // A player can't apply two alternative methods of casting or two alternative costs to a single spell. - if (!activateAlternateOrAdditionalCosts(sourceObject, noMana, controller, game)){ + if (!activateAlternateOrAdditionalCosts(sourceObject, noMana, controller, game)) { if (getAbilityType().equals(AbilityType.SPELL) && ((SpellAbility) this).getSpellAbilityType().equals(SpellAbilityType.FACE_DOWN_CREATURE)) { return false; @@ -310,7 +312,7 @@ public abstract class AbilityImpl implements Ability { VariableManaCost variableManaCost = handleManaXCosts(game, noMana, controller); String announceString = handleOtherXCosts(game, controller); - for (UUID modeId :this.getModes().getSelectedModes()) { + for (UUID modeId : this.getModes().getSelectedModes()) { this.getModes().setActiveMode(modeId); //20121001 - 601.2c // 601.2c The player announces his or her choice of an appropriate player, object, or zone for @@ -334,15 +336,15 @@ public abstract class AbilityImpl implements Ability { } if (getTargets().size() > 0 && getTargets().chooseTargets(getEffects().get(0).getOutcome(), this.controllerId, this, game) == false) { if ((variableManaCost != null || announceString != null) && !game.isSimulation()) { - game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName(): "") + ": no valid targets with this value of X"); - } + game.informPlayer(controller, (sourceObject != null ? sourceObject.getIdName() : "") + ": no valid targets with this value of X"); + } return false; // when activation of ability is canceled during target selection } } // end modes // TODO: Handle optionalCosts at the same time as already OptionalAdditionalSourceCosts are handled. for (Cost cost : optionalCosts) { - if (cost instanceof ManaCost) { + if (cost instanceof ManaCost) { cost.clearPaid(); if (controller.chooseUse(Outcome.Benefit, "Pay optional cost " + cost.getText() + "?", game)) { manaCostsToPay.add((ManaCost) cost); @@ -353,17 +355,17 @@ public abstract class AbilityImpl implements Ability { if (sourceObject != null) { sourceObject.adjustCosts(this, game); if (sourceObject instanceof Card) { - for (Ability ability : ((Card)sourceObject).getAbilities(game)) { + for (Ability ability : ((Card) sourceObject).getAbilities(game)) { if (ability instanceof AdjustingSourceCosts) { - ((AdjustingSourceCosts)ability).adjustCosts(this, game); + ((AdjustingSourceCosts) ability).adjustCosts(this, game); } - } + } } else { for (Ability ability : sourceObject.getAbilities()) { if (ability instanceof AdjustingSourceCosts) { - ((AdjustingSourceCosts)ability).adjustCosts(this, game); + ((AdjustingSourceCosts) ability).adjustCosts(this, game); } - } + } } } @@ -381,8 +383,8 @@ public abstract class AbilityImpl implements Ability { } UUID activatorId = controllerId; - if ((this instanceof ActivatedAbilityImpl) && ((ActivatedAbilityImpl)this).getActivatorId()!= null) { - activatorId = ((ActivatedAbilityImpl)this).getActivatorId(); + if ((this instanceof ActivatedAbilityImpl) && ((ActivatedAbilityImpl) this).getActivatorId() != null) { + activatorId = ((ActivatedAbilityImpl) this).getActivatorId(); } if (!useAlternativeCost(game)) { // old way still used? @@ -394,7 +396,6 @@ public abstract class AbilityImpl implements Ability { } //20100716 - 601.2g - if (!costs.pay(this, game, sourceId, activatorId, noMana)) { logger.debug("activate failed - non mana costs"); return false; @@ -412,14 +413,14 @@ public abstract class AbilityImpl implements Ability { activated = true; // fire if tapped for mana (may only fire now because else costs of ability itself can be payed with mana of abilities that trigger for that event if (this.getAbilityType().equals(AbilityType.MANA)) { - for (Cost cost: costs) { + for (Cost cost : costs) { if (cost instanceof TapSourceCost) { Mana mana = null; Effect effect = getEffects().get(0); if (effect instanceof BasicManaEffect) { - mana = ((BasicManaEffect)effect).getMana(game, this); + mana = ((BasicManaEffect) effect).getMana(game, this); } else if (effect instanceof DynamicManaEffect) { - mana = ((DynamicManaEffect)effect).getMana(game, this); + mana = ((DynamicManaEffect) effect).getMana(game, this); } if (mana != null && mana.getAny() == 0) { // if mana == null or Any > 0 the event has to be fired in the mana effect to know which mana was produced ManaEvent event = new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, sourceId, sourceId, controllerId, mana); @@ -456,14 +457,14 @@ public abstract class AbilityImpl implements Ability { } } if (ability instanceof OptionalAdditionalSourceCosts) { - ((OptionalAdditionalSourceCosts)ability).addOptionalAdditionalCosts(this, game); + ((OptionalAdditionalSourceCosts) ability).addOptionalAdditionalCosts(this, game); } } // controller specific alternate spell costs if (!noMana && !alternativeCostisUsed) { if (this.getAbilityType().equals(AbilityType.SPELL)) { - for (AlternativeSourceCosts alternativeSourceCosts: controller.getAlternativeSourceCosts()) { - if (alternativeSourceCosts.isAvailable(this, game)) { + for (AlternativeSourceCosts alternativeSourceCosts : controller.getAlternativeSourceCosts()) { + if (alternativeSourceCosts.isAvailable(this, game)) { if (alternativeSourceCosts.askToActivateAlternativeCosts(this, game)) { // only one alternative costs may be activated alternativeCostisUsed = true; @@ -479,7 +480,9 @@ public abstract class AbilityImpl implements Ability { /** * Handles the setting of non mana X costs - * @param controller * + * + * @param controller + * * @param game * @return announce message * @@ -519,7 +522,7 @@ public abstract class AbilityImpl implements Ability { // its mana cost; see rule 107.3), the player announces the value of that variable. // TODO: Handle announcing other variable costs here like: RemoveVariableCountersSourceCost VariableManaCost variableManaCost = null; - for (ManaCost cost: manaCostsToPay) { + for (ManaCost cost : manaCostsToPay) { if (cost instanceof VariableManaCost) { variableManaCost = (VariableManaCost) cost; break; // only one VariableManCost per spell (or is it possible to have more?) @@ -548,7 +551,7 @@ public abstract class AbilityImpl implements Ability { manaSymbol = "W"; } if (manaSymbol == null) { - throw new UnsupportedOperationException("ManaFilter is not supported: " +this.toString() ); + throw new UnsupportedOperationException("ManaFilter is not supported: " + this.toString()); } for (int i = 0; i < amountMana; i++) { manaString.append("{").append(manaSymbol).append("}"); @@ -566,11 +569,12 @@ public abstract class AbilityImpl implements Ability { // called at end of turn for each Permanent @Override - public void reset(Game game) {} + public void reset(Game game) { + } // Is this still needed? protected boolean useAlternativeCost(Game game) { - for (AlternativeCost cost: alternativeCosts) { + for (AlternativeCost cost : alternativeCosts) { if (cost.isAvailable(game, this)) { if (game.getPlayer(this.controllerId).chooseUse(Outcome.Neutral, "Use alternative cost " + cost.getName(), game)) { return cost.pay(this, game, sourceId, controllerId, false); @@ -594,18 +598,17 @@ public abstract class AbilityImpl implements Ability { public void setControllerId(UUID controllerId) { this.controllerId = controllerId; if (watchers != null) { - for (Watcher watcher: watchers) { + for (Watcher watcher : watchers) { watcher.setControllerId(controllerId); } } if (subAbilities != null) { - for (Ability subAbility: subAbilities) { + for (Ability subAbility : subAbilities) { subAbility.setControllerId(controllerId); } } } - @Override public UUID getSourceId() { return sourceId; @@ -621,12 +624,12 @@ public abstract class AbilityImpl implements Ability { } } if (subAbilities != null) { - for (Ability subAbility: subAbilities) { + for (Ability subAbility : subAbilities) { subAbility.setSourceId(sourceId); } } if (watchers != null) { - for (Watcher watcher: watchers) { + for (Watcher watcher : watchers) { watcher.setSourceId(sourceId); } } @@ -643,13 +646,14 @@ public abstract class AbilityImpl implements Ability { } /** - * Should be used by {@link mage.abilities.effects.CostModificationEffect cost modification effects} + * Should be used by + * {@link mage.abilities.effects.CostModificationEffect cost modification effects} * to manipulate what is actually paid before resolution. * * @return */ @Override - public ManaCosts getManaCostsToPay ( ) { + public ManaCosts getManaCostsToPay() { return manaCostsToPay; } @@ -671,7 +675,7 @@ public abstract class AbilityImpl implements Ability { @Override public Effects getEffects(Game game, EffectType effectType) { Effects typedEffects = new Effects(); - for (Effect effect: getEffects()) { + for (Effect effect : getEffects()) { if (effect.getEffectType() == effectType) { typedEffects.add(effect); } @@ -760,7 +764,7 @@ public abstract class AbilityImpl implements Ability { String text = modes.getText(); if (!text.isEmpty()) { if (sbRule.length() > 1) { - String end = sbRule.substring(sbRule.length()-2).trim(); + String end = sbRule.substring(sbRule.length() - 2).trim(); if (end.isEmpty() || end.equals(":") || end.equals(".")) { sbRule.append(Character.toUpperCase(text.charAt(0))).append(text.substring(1)); } else { @@ -791,9 +795,8 @@ public abstract class AbilityImpl implements Ability { public void addCost(Cost cost) { if (cost != null) { if (cost instanceof ManaCost) { - this.addManaCost((ManaCost)cost); - } - else { + this.addManaCost((ManaCost) cost); + } else { this.costs.add(cost); } } @@ -869,7 +872,7 @@ public abstract class AbilityImpl implements Ability { @Override public boolean canChooseTarget(Game game) { - for (Mode mode: modes.values()) { + for (Mode mode : modes.values()) { if (mode.getTargets().canChoose(sourceId, controllerId, game)) { return true; } @@ -878,10 +881,10 @@ public abstract class AbilityImpl implements Ability { } /** - * + * * @param game * @param source - * @return + * @return */ @Override public boolean isInUseableZone(Game game, MageObject source, GameEvent event) { @@ -915,7 +918,7 @@ public abstract class AbilityImpl implements Ability { Zone test = game.getState().getZone(parameterSourceId); return test != null && zone.match(test); } - + @Override public boolean hasSourceObjectAbility(Game game, MageObject source, GameEvent event) { MageObject object = source; @@ -940,7 +943,7 @@ public abstract class AbilityImpl implements Ability { } return true; } - + @Override public String toString() { return getRule(); @@ -985,7 +988,7 @@ public abstract class AbilityImpl implements Ability { @Override public void setAbilityWord(AbilityWord abilityWord) { - this.abilityWord = abilityWord; + this.abilityWord = abilityWord; } @Override @@ -998,7 +1001,7 @@ public abstract class AbilityImpl implements Ability { logger.warn("Could get no object: " + this.toString()); } return new StringBuilder(" activates: ") - .append(object != null ? this.formatRule(modes.getText(), object.getLogName()) :modes.getText()) + .append(object != null ? this.formatRule(modes.getText(), object.getLogName()) : modes.getText()) .append(" from ") .append(getMessageText(game)).toString(); } @@ -1018,7 +1021,7 @@ public abstract class AbilityImpl implements Ability { if (object instanceof Spell) { Spell spell = (Spell) object; String castText = spell.getSpellCastText(game); - sb.append((castText.startsWith("Cast ") ? castText.substring(5):castText)); + sb.append((castText.startsWith("Cast ") ? castText.substring(5) : castText)); if (spell.getFromZone() == Zone.GRAVEYARD) { sb.append(" from graveyard"); } @@ -1044,7 +1047,7 @@ public abstract class AbilityImpl implements Ability { } if (spellAbility.getTargets().size() > 0) { sb.append(half).append(" half targeting "); - for (Target target: spellAbility.getTargets()) { + for (Target target : spellAbility.getTargets()) { sb.append(target.getTargetedName(game)); } } @@ -1054,7 +1057,7 @@ public abstract class AbilityImpl implements Ability { int i = 0; for (SpellAbility spellAbility : spell.getSpellAbilities()) { i++; - if ( i > 1) { + if (i > 1) { sb.append(" splicing "); if (spellAbility.name.length() > 5 && spellAbility.name.startsWith("Cast ")) { sb.append(spellAbility.name.substring(5)); @@ -1106,7 +1109,7 @@ public abstract class AbilityImpl implements Ability { } } } - for (Choice choice :this.getChoices()) { + for (Choice choice : this.getChoices()) { sb.append(" - ").append(choice.getMessage()).append(": ").append(choice.getChoice()); } return sb.toString(); @@ -1170,12 +1173,12 @@ public abstract class AbilityImpl implements Ability { public void setSourceObject(MageObject sourceObject, Game game) { if (sourceObject == null) { this.sourceObject = game.getObject(sourceId); + // if permanent get card /permanent instead of spell + } else { this.sourceObject = sourceObject; } this.sourceObjectZoneChangeCounter = game.getState().getZoneChangeCounter(sourceId); } - } - diff --git a/Mage/src/mage/abilities/effects/common/continuous/BecomesSubtypeTargetEffect.java b/Mage/src/mage/abilities/effects/common/continuous/BecomesSubtypeTargetEffect.java new file mode 100644 index 0000000000..f056b1ffee --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/continuous/BecomesSubtypeTargetEffect.java @@ -0,0 +1,108 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common.continuous; + +import java.util.ArrayList; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.TypeChangingEffects_4; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class BecomesSubtypeTargetEffect extends ContinuousEffectImpl { + + protected ArrayList subtypes = new ArrayList(); + protected boolean loseOther; // loses other subtypes + + public BecomesSubtypeTargetEffect(Duration duration, String subtype) { + this(duration, createArrayList(subtype)); + } + + public BecomesSubtypeTargetEffect(Duration duration, ArrayList subtypes) { + this(duration, subtypes, true); + } + + public BecomesSubtypeTargetEffect(Duration duration, ArrayList subtypes, boolean loseOther) { + super(duration, Outcome.Detriment); + this.subtypes = subtypes; + this.staticText = setText(); + this.loseOther = loseOther; + } + + private static ArrayList createArrayList(String subtype) { + ArrayList subtypes = new ArrayList<>(); + subtypes.add(subtype); + return subtypes; + } + + public BecomesSubtypeTargetEffect(final BecomesSubtypeTargetEffect effect) { + super(effect); + this.subtypes.addAll(effect.subtypes); + this.loseOther = effect.loseOther; + this.loseOther = effect.loseOther; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public BecomesSubtypeTargetEffect copy() { + return new BecomesSubtypeTargetEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + for (UUID targetPermanent : targetPointer.getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetPermanent); + if (permanent != null) { + switch (layer) { + case TypeChangingEffects_4: + if (loseOther) { + permanent.getSubtype().clear(); + permanent.getSubtype().addAll(subtypes); + } else { + for (String subtype : subtypes) { + if (!permanent.getSubtype().contains(subtype)) { + permanent.getSubtype().add(subtype); + } + } + } + break; + } + } else { + if (duration.equals(Duration.Custom)) { + discard(); + } + } + } + return true; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.TypeChangingEffects_4; + } + + private String setText() { + StringBuilder sb = new StringBuilder(); + sb.append("Target creature becomes that type"); + if (!duration.toString().isEmpty() && !duration.equals(Duration.EndOfGame)) { + sb.append(" ").append(duration.toString()); + } + return sb.toString(); + } +} diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index c48ba70ad0..e3a2a8a978 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -1,35 +1,51 @@ /* -* 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. -*/ - + * 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.game; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; import mage.MageObject; -import mage.abilities.*; +import mage.abilities.Abilities; +import mage.abilities.Ability; +import mage.abilities.ActivatedAbility; +import mage.abilities.DelayedTriggeredAbilities; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.Mode; +import mage.abilities.SpecialActions; +import mage.abilities.StaticAbility; +import mage.abilities.TriggeredAbilities; +import mage.abilities.TriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; import mage.abilities.effects.Effect; @@ -53,26 +69,22 @@ import mage.players.PlayerList; import mage.players.Players; import mage.target.Target; import mage.util.Copyable; +import mage.util.ThreadLocalStringBuilder; import mage.watchers.Watcher; import mage.watchers.Watchers; -import java.io.Serializable; -import java.util.*; -import mage.util.ThreadLocalStringBuilder; - /** -* -* @author BetaSteward_at_googlemail.com -* -* since at any time the game state may be copied and restored you cannot -* rely on any object maintaining it's instance -* it then becomes necessary to only refer to objects by their ids since -* these will always remain constant throughout its lifetime -* + * + * @author BetaSteward_at_googlemail.com + * +* since at any time the game state may be copied and restored you cannot rely + * on any object maintaining it's instance it then becomes necessary to only + * refer to objects by their ids since these will always remain constant + * throughout its lifetime + * */ public class GameState implements Serializable, Copyable { - private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(1024); private final Players players; @@ -83,9 +95,9 @@ public class GameState implements Serializable, Copyable { private final Revealed revealed; private final Map lookedAt = new HashMap<>(); - private DelayedTriggeredAbilities delayed; + private DelayedTriggeredAbilities delayed; private SpecialActions specialActions; - private Watchers watchers; + private Watchers watchers; private Turn turn; private TurnMods turnMods; private UUID activePlayerId; // playerId which turn it is @@ -113,7 +125,7 @@ public class GameState implements Serializable, Copyable { private Map zoneChangeCounter = new HashMap<>(); private Map copiedCards = new HashMap<>(); private int permanentOrderNumber; - + public GameState() { players = new Players(); playerList = new PlayerList(); @@ -140,11 +152,11 @@ public class GameState implements Serializable, Copyable { this.lookedAt.putAll(state.lookedAt); this.gameOver = state.gameOver; this.paused = state.paused; - + this.activePlayerId = state.activePlayerId; this.priorityPlayerId = state.priorityPlayerId; this.turn = state.turn.copy(); - + this.stack = state.stack.copy(); this.command = state.command.copy(); this.exile = state.exile.copy(); @@ -154,7 +166,7 @@ public class GameState implements Serializable, Copyable { this.extraTurn = state.extraTurn; this.legendaryRuleActive = state.legendaryRuleActive; this.effects = state.effects.copy(); - for (TriggeredAbility trigger: state.triggered) { + for (TriggeredAbility trigger : state.triggered) { this.triggered.add(trigger.copy()); } this.triggers = state.triggers.copy(); @@ -163,27 +175,27 @@ public class GameState implements Serializable, Copyable { this.combat = state.combat.copy(); this.turnMods = state.turnMods.copy(); this.watchers = state.watchers.copy(); - for (Map.Entry entry: state.values.entrySet()) { - this.values.put(entry.getKey(), entry.getValue()); + for (Map.Entry entry : state.values.entrySet()) { + this.values.put(entry.getKey(), entry.getValue()); } this.zones.putAll(state.zones); this.simultaneousEvents.addAll(state.simultaneousEvents); - for (Map.Entry entry: state.cardState.entrySet()) { + for (Map.Entry entry : state.cardState.entrySet()) { cardState.put(entry.getKey(), entry.getValue().copy()); } - for (Map.Entry entry: state.cardAttribute.entrySet()) { + for (Map.Entry entry : state.cardAttribute.entrySet()) { cardAttribute.put(entry.getKey(), entry.getValue().copy()); } this.zoneChangeCounter.putAll(state.zoneChangeCounter); this.copiedCards.putAll(state.copiedCards); this.permanentOrderNumber = state.permanentOrderNumber; } - + public void restoreForRollBack(GameState state) { restore(state); - this.turn = state.turn; + this.turn = state.turn; } - + public void restore(GameState state) { this.activePlayerId = state.activePlayerId; this.priorityPlayerId = state.priorityPlayerId; @@ -194,7 +206,7 @@ public class GameState implements Serializable, Copyable { this.turnNum = state.turnNum; this.stepNum = state.stepNum; this.extraTurn = state.extraTurn; - this.legendaryRuleActive = state.legendaryRuleActive; + this.legendaryRuleActive = state.legendaryRuleActive; this.effects = state.effects; this.triggered = state.triggered; this.triggers = state.triggers; @@ -202,9 +214,9 @@ public class GameState implements Serializable, Copyable { this.specialActions = state.specialActions; this.combat = state.combat; this.turnMods = state.turnMods; - this.watchers = state.watchers; + this.watchers = state.watchers; this.values = state.values; - for (Player copyPlayer: state.players.values()) { + for (Player copyPlayer : state.players.values()) { Player origPlayer = players.get(copyPlayer.getId()); origPlayer.restore(copyPlayer); } @@ -233,33 +245,32 @@ public class GameState implements Serializable, Copyable { sb.append(turn.getValue(turnNum)); sb.append(activePlayerId).append(priorityPlayerId); - for (Player player: players.values()) { + for (Player player : players.values()) { sb.append("player").append(player.getLife()).append("hand"); if (useHidden) { sb.append(player.getHand()); - } - else { + } else { sb.append(player.getHand().size()); } sb.append("library").append(player.getLibrary().size()).append("graveyard").append(player.getGraveyard()); } sb.append("permanents"); - for (Permanent permanent: battlefield.getAllPermanents()) { + for (Permanent permanent : battlefield.getAllPermanents()) { sb.append(permanent.getValue()); } sb.append("spells"); - for (StackObject spell: stack) { + for (StackObject spell : stack) { sb.append(spell.getControllerId()).append(spell.getName()); } - for (ExileZone zone: exile.getExileZones()) { + for (ExileZone zone : exile.getExileZones()) { sb.append("exile").append(zone.getName()).append(zone); } sb.append("combat"); - for (CombatGroup group: combat.getGroups()) { + for (CombatGroup group : combat.getGroups()) { sb.append(group.getDefenderId()).append(group.getAttackers()).append(group.getBlockers()); } @@ -272,12 +283,11 @@ public class GameState implements Serializable, Copyable { sb.append(turn.getValue(turnNum)); sb.append(activePlayerId).append(priorityPlayerId); - for (Player player: players.values()) { + for (Player player : players.values()) { sb.append("player").append(player.isPassed()).append(player.getLife()).append("hand"); if (useHidden) { sb.append(player.getHand().getValue(game)); - } - else { + } else { sb.append(player.getHand().size()); } sb.append("library").append(player.getLibrary().size()); @@ -287,38 +297,38 @@ public class GameState implements Serializable, Copyable { sb.append("permanents"); List perms = new ArrayList<>(); - for (Permanent permanent: battlefield.getAllPermanents()) { + for (Permanent permanent : battlefield.getAllPermanents()) { perms.add(permanent.getValue()); } Collections.sort(perms); sb.append(perms); sb.append("spells"); - for (StackObject spell: stack) { + for (StackObject spell : stack) { sb.append(spell.getControllerId()).append(spell.getName()); sb.append(spell.getStackAbility().toString()); - for (Mode mode: spell.getStackAbility().getModes().values()) { + for (Mode mode : spell.getStackAbility().getModes().values()) { if (!mode.getTargets().isEmpty()) { sb.append("targets"); - for (Target target: mode.getTargets()) { + for (Target target : mode.getTargets()) { sb.append(target.getTargets()); } } if (!mode.getChoices().isEmpty()) { sb.append("choices"); - for (Choice choice: mode.getChoices()) { + for (Choice choice : mode.getChoices()) { sb.append(choice.getChoice()); } } } } - for (ExileZone zone: exile.getExileZones()) { + for (ExileZone zone : exile.getExileZones()) { sb.append("exile").append(zone.getName()).append(zone.getValue(game)); } sb.append("combat"); - for (CombatGroup group: combat.getGroups()) { + for (CombatGroup group : combat.getGroups()) { sb.append(group.getDefenderId()).append(group.getAttackers()).append(group.getBlockers()); } @@ -331,12 +341,11 @@ public class GameState implements Serializable, Copyable { sb.append(turn.getValue(turnNum)); sb.append(activePlayerId).append(priorityPlayerId); - for (Player player: players.values()) { + for (Player player : players.values()) { sb.append("player").append(player.isPassed()).append(player.getLife()).append("hand"); if (playerId == player.getId()) { sb.append(player.getHand().getValue(game)); - } - else { + } else { sb.append(player.getHand().size()); } sb.append("library").append(player.getLibrary().size()); @@ -346,38 +355,38 @@ public class GameState implements Serializable, Copyable { sb.append("permanents"); List perms = new ArrayList<>(); - for (Permanent permanent: battlefield.getAllPermanents()) { + for (Permanent permanent : battlefield.getAllPermanents()) { perms.add(permanent.getValue()); } Collections.sort(perms); sb.append(perms); sb.append("spells"); - for (StackObject spell: stack) { + for (StackObject spell : stack) { sb.append(spell.getControllerId()).append(spell.getName()); sb.append(spell.getStackAbility().toString()); - for (Mode mode: spell.getStackAbility().getModes().values()) { + for (Mode mode : spell.getStackAbility().getModes().values()) { if (!mode.getTargets().isEmpty()) { sb.append("targets"); - for (Target target: mode.getTargets()) { + for (Target target : mode.getTargets()) { sb.append(target.getTargets()); } } if (!mode.getChoices().isEmpty()) { sb.append("choices"); - for (Choice choice: mode.getChoices()) { + for (Choice choice : mode.getChoices()) { sb.append(choice.getChoice()); } } } } - for (ExileZone zone: exile.getExileZones()) { + for (ExileZone zone : exile.getExileZones()) { sb.append("exile").append(zone.getName()).append(zone.getValue(game)); } sb.append("combat"); - for (CombatGroup group: combat.getGroups()) { + for (CombatGroup group : combat.getGroups()) { sb.append(group.getDefenderId()).append(group.getAttackers()).append(group.getBlockers()); } @@ -448,7 +457,7 @@ public class GameState implements Serializable, Copyable { public void clearRevealed() { revealed.clear(); } - + public void clearLookedAt() { lookedAt.clear(); } @@ -462,8 +471,9 @@ public class GameState implements Serializable, Copyable { } /** - * Gets the game step counter. This counter isgoing one up for - * every played step during the game. + * Gets the game step counter. This counter isgoing one up for every played + * step during the game. + * * @return */ public int getStepNum() { @@ -520,7 +530,7 @@ public class GameState implements Serializable, Copyable { public void applyEffects(Game game) { game.resetShortLivingLKI(); - for (Player player: players.values()) { + for (Player player : players.values()) { player.reset(); } battlefield.reset(game); @@ -557,11 +567,10 @@ public class GameState implements Serializable, Copyable { // public void addMessage(String message) { // this.messages.add(message); // } - /** - * Returns a list of all players of the game ignoring range or - * if a player has lost or left the game. - * + * Returns a list of all players of the game ignoring range or if a player + * has lost or left the game. + * * @return playerList */ public PlayerList getPlayerList() { @@ -569,36 +578,38 @@ public class GameState implements Serializable, Copyable { } /** - * Returns a list of all active players of the game, setting the - * playerId to the current player of the list. - * + * Returns a list of all active players of the game, setting the playerId to + * the current player of the list. + * * @param playerId * @return playerList */ public PlayerList getPlayerList(UUID playerId) { PlayerList newPlayerList = new PlayerList(); - for (Player player: players.values()) { - if (!player.hasLeft()&& !player.hasLost()) { + for (Player player : players.values()) { + if (!player.hasLeft() && !player.hasLost()) { newPlayerList.add(player.getId()); } } newPlayerList.setCurrent(playerId); return newPlayerList; } + /** - * Returns a list of all active players of the game in range of playerId, - * also setting the playerId to the current player of the list. - * + * Returns a list of all active players of the game in range of playerId, + * also setting the playerId to the first/current player of the list. Also + * returning the other players in turn order. + * * @param playerId * @param game * @return playerList */ public PlayerList getPlayersInRange(UUID playerId, Game game) { - PlayerList newPlayerList = new PlayerList(); + PlayerList newPlayerList = new PlayerList(); Player currentPlayer = game.getPlayer(playerId); if (currentPlayer != null) { - for (Player player: players.values()) { - if (!player.hasLeft()&& !player.hasLost() && currentPlayer.getInRange().contains(player.getId())) { + for (Player player : players.values()) { + if (!player.hasLeft() && !player.hasLost() && currentPlayer.getInRange().contains(player.getId())) { newPlayerList.add(player.getId()); } } @@ -606,7 +617,7 @@ public class GameState implements Serializable, Copyable { } return newPlayerList; } - + public Permanent getPermanent(UUID permanentId) { if (permanentId != null && battlefield.containsPermanent(permanentId)) { Permanent permanent = battlefield.getPermanent(permanentId); @@ -637,11 +648,12 @@ public class GameState implements Serializable, Copyable { List eventsToHandle = new ArrayList<>(); eventsToHandle.addAll(simultaneousEvents); simultaneousEvents.clear(); - for (GameEvent event:eventsToHandle) { + for (GameEvent event : eventsToHandle) { this.handleEvent(event, game); } } } + public boolean hasSimultaneousEvents() { return !simultaneousEvents.isEmpty(); } @@ -661,11 +673,11 @@ public class GameState implements Serializable, Copyable { public void addCard(Card card) { setZone(card.getId(), Zone.OUTSIDE); - for (Ability ability: card.getAbilities()) { + for (Ability ability : card.getAbilities()) { addAbility(ability, card); } } - + public void removeCopiedCard(Card card) { if (copiedCards.containsKey(card.getId())) { copiedCards.remove(card.getId()); @@ -676,14 +688,15 @@ public class GameState implements Serializable, Copyable { // TODO Watchers? // TODO Abilities? if (card.isSplitCard()) { - removeCopiedCard( ((SplitCard)card).getLeftHalfCard()); - removeCopiedCard( ((SplitCard)card).getRightHalfCard()); + removeCopiedCard(((SplitCard) card).getLeftHalfCard()); + removeCopiedCard(((SplitCard) card).getRightHalfCard()); } } /** - * Used for adding abilities that exist permanent on cards/permanents and are not - * only gained for a certain time (e.g. until end of turn). + * Used for adding abilities that exist permanent on cards/permanents and + * are not only gained for a certain time (e.g. until end of turn). + * * @param ability * @param attachedTo */ @@ -693,45 +706,45 @@ public class GameState implements Serializable, Copyable { public void addAbility(Ability ability, MageObject attachedTo) { if (ability instanceof StaticAbility) { - for (Mode mode: ability.getModes().values()) { - for (Effect effect: mode.getEffects()) { + for (Mode mode : ability.getModes().values()) { + for (Effect effect : mode.getEffects()) { if (effect instanceof ContinuousEffect) { - addEffect((ContinuousEffect)effect, ability); + addEffect((ContinuousEffect) effect, ability); } } } - } - else if (ability instanceof TriggeredAbility) { - this.triggers.add((TriggeredAbility)ability, attachedTo); + } else if (ability instanceof TriggeredAbility) { + this.triggers.add((TriggeredAbility) ability, attachedTo); } } /** - * Abilities that are applied to other objects or applie for a certain time span + * Abilities that are applied to other objects or applie for a certain time + * span + * * @param ability * @param sourceId * @param attachedTo */ public void addAbility(Ability ability, UUID sourceId, Card attachedTo) { if (ability instanceof StaticAbility) { - for (Mode mode: ability.getModes().values()) { - for (Effect effect: mode.getEffects()) { + for (Mode mode : ability.getModes().values()) { + for (Effect effect : mode.getEffects()) { if (effect instanceof ContinuousEffect) { - addEffect((ContinuousEffect)effect, sourceId, ability); + addEffect((ContinuousEffect) effect, sourceId, ability); } } } - } - else if (ability instanceof TriggeredAbility) { + } else if (ability instanceof TriggeredAbility) { // TODO: add sources for triggers - the same way as in addEffect: sources - this.triggers.add((TriggeredAbility)ability, sourceId, attachedTo); + this.triggers.add((TriggeredAbility) ability, sourceId, attachedTo); } - for (Watcher watcher: ability.getWatchers()) { + for (Watcher watcher : ability.getWatchers()) { watcher.setControllerId(attachedTo.getOwnerId()); watcher.setSourceId(attachedTo.getId()); watchers.add(watcher); } - for (Ability sub: ability.getSubAbilities()) { + for (Ability sub : ability.getSubAbilities()) { addAbility(sub, sourceId, attachedTo); } } @@ -739,7 +752,7 @@ public class GameState implements Serializable, Copyable { public void addCommandObject(CommandObject commandObject) { getCommand().add(commandObject); setZone(commandObject.getId(), Zone.COMMAND); - for (Ability ability: commandObject.getAbilities()) { + for (Ability ability : commandObject.getAbilities()) { addAbility(ability, commandObject); } } @@ -757,8 +770,8 @@ public class GameState implements Serializable, Copyable { } public void removeDelayedTriggeredAbility(UUID abilityId) { - for (DelayedTriggeredAbility ability: delayed) { - if (ability.getId().equals(abilityId)) { + for (DelayedTriggeredAbility ability : delayed) { + if (ability.getId().equals(abilityId)) { delayed.remove(ability); break; } @@ -767,7 +780,7 @@ public class GameState implements Serializable, Copyable { public List getTriggered(UUID controllerId) { List triggereds = new ArrayList<>(); - for (TriggeredAbility ability: triggered) { + for (TriggeredAbility ability : triggered) { if (ability.getControllerId().equals(controllerId)) { triggereds.add(ability); } @@ -788,23 +801,26 @@ public class GameState implements Serializable, Copyable { } /** - * Best only use immutable objects, otherwise the states/values of the object may be - * changed by AI simulation, because the Value objects are not copied as the state - * class is copied. - * + * Best only use immutable objects, otherwise the states/values of the + * object may be changed by AI simulation, because the Value objects are not + * copied as the state class is copied. + * * @param valueId - * @param value + * @param value */ public void setValue(String valueId, Object value) { values.put(valueId, value); } /** - * Other abilities are used to implement some special kind of continuous effects that give abilities to non permanents. + * Other abilities are used to implement some special kind of continuous + * effects that give abilities to non permanents. * - * Crucible of Worlds - You may play land cards from your graveyard. - * Past in Flames - Each instant and sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. - * Varolz, the Scar-Striped - Each creature card in your graveyard has scavenge. The scavenge cost is equal to its mana cost. + * Crucible of Worlds - You may play land cards from your graveyard. Past in + * Flames - Each instant and sorcery card in your graveyard gains flashback + * until end of turn. The flashback cost is equal to its mana cost. Varolz, + * the Scar-Striped - Each creature card in your graveyard has scavenge. The + * scavenge cost is equal to its mana cost. * * @param objectId * @param zone @@ -816,7 +832,7 @@ public class GameState implements Serializable, Copyable { } return null; } - + public Abilities getAllOtherAbilities(UUID objectId) { if (cardState.containsKey(objectId)) { return cardState.get(objectId).getAbilities(); @@ -826,12 +842,13 @@ public class GameState implements Serializable, Copyable { /** * Adds the ability to continuous or triggered abilities + * * @param attachedTo * @param ability */ public void addOtherAbility(Card attachedTo, Ability ability) { ability.setSourceId(attachedTo.getId()); - ability.setControllerId(attachedTo.getOwnerId()); + ability.setControllerId(attachedTo.getOwnerId()); if (!cardState.containsKey(attachedTo.getId())) { cardState.put(attachedTo.getId(), new CardState()); } @@ -840,8 +857,8 @@ public class GameState implements Serializable, Copyable { } /** - * Removes Triggered abilities that belong to sourceId - * This is used if a token leaves the battlefield + * Removes Triggered abilities that belong to sourceId This is used if a + * token leaves the battlefield * * @param sourceId */ @@ -849,7 +866,6 @@ public class GameState implements Serializable, Copyable { triggers.removeAbilitiesOfSource(sourceId); } - /** * Called before applyEffects */ @@ -858,7 +874,7 @@ public class GameState implements Serializable, Copyable { triggers.removeAllGainedAbilities(); getContinuousEffects().removeAllTemporaryEffects(); this.setLegendaryRuleActive(true); - for (CardState state: cardState.values()) { + for (CardState state : cardState.values()) { state.clearAbilities(); } cardAttribute.clear(); @@ -912,14 +928,15 @@ public class GameState implements Serializable, Copyable { this.legendaryRuleActive = legendaryRuleActive; } - /** + /** * Only used for diagnostic purposes of tests - * @return + * + * @return */ public TriggeredAbilities getTriggers() { return triggers; } - + public CardState getCardState(UUID cardId) { if (!cardState.containsKey(cardId)) { cardState.put(cardId, new CardState()); @@ -943,7 +960,7 @@ public class GameState implements Serializable, Copyable { public void addWatcher(Watcher watcher) { this.watchers.add(watcher); } - + public int getZoneChangeCounter(UUID objectId) { if (this.zoneChangeCounter.containsKey(objectId)) { return this.zoneChangeCounter.get(objectId); @@ -964,11 +981,11 @@ public class GameState implements Serializable, Copyable { public void setZoneChangeCounter(UUID objectId, int value) { this.zoneChangeCounter.put(objectId, value); } - + public Card getCopiedCard(UUID cardId) { return copiedCards.get(cardId); } - + public Collection getCopiedCards() { return copiedCards.values(); } @@ -981,16 +998,16 @@ public class GameState implements Serializable, Copyable { copiedCards.put(copiedCard.getId(), copiedCard); addCard(copiedCard); if (copiedCard.isSplitCard()) { - Card leftCard = ((SplitCard)copiedCard).getLeftHalfCard(); + Card leftCard = ((SplitCard) copiedCard).getLeftHalfCard(); copiedCards.put(leftCard.getId(), leftCard); addCard(leftCard); - Card rightCard = ((SplitCard)copiedCard).getRightHalfCard(); + Card rightCard = ((SplitCard) copiedCard).getRightHalfCard(); copiedCards.put(rightCard.getId(), rightCard); addCard(rightCard); } return copiedCard; } - + public int getNextPermanentOrderNumber() { return permanentOrderNumber++; } diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 29b43da0be..113ad1c0e5 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -26060,6 +26060,7 @@ Sign in Blood|Modern Masters 2015 Edition|97|C|{B}{B}|Sorcery|||Target player dr Spread the Sickness|Modern Masters 2015 Edition|98|U|{4}{B}|Sorcery|||Destroy target creature, then proliferate. (You choose any number of permanents and/or players with counters on them, then give each another counter of a kind already there.)| Surgical Extraction|Modern Masters 2015 Edition|99|R|{BP}|Instant|||({BP} can be paid with either {B} or 2 life.)$Choose target card in a graveyard other than a basic land card. Search its owner's graveyard, hand, and library for any number of cards with the same name as that card and exile them. Then that player shuffles his or her library.| Akroan Jailer|Magic Origins|1|C|{W}|Creature - Human Soldier|1|1|{2}{W}, {T}: Tap target creature.| +Archangel of Tithes|Magic Origins|4|M|{1}{W}{W}{W}|Creature - Angel|3|5|Flying$As long as Archangel of Tithes is untapped, creatures can't attack you or a planeswalker you control unless their controller pays {1} for each of those creatures.$As long as Archangel of Tithes is attacking, creatures can't block unless their controller pays {1} for each of those creatures.| Blessed Spirits|Magic Origins|7|U|{2}{W}|Creature - Spirit|2|2|Flying$Whenever you cast an enchantment spell, put a +1/+1 counter on Blessed Spirits.| Charging Griffin|Magic Origins|9|C|{3}{W}|Creature - Griffin|2|2|Flying$Whenever Charging Griffin attacks, it gets +1/+1 until end of turn.| Cleric of the Forward Order|Magic Origins|10|C|{1}{W}|Creature - Human Cleric|2|2|When Cleric of the Forward Order enters the battlefield, you gain 2 life for each creature you control named Cleric of the Forward Order.| @@ -26076,6 +26077,7 @@ Patron of the Valiant|Magic Origins|28|U|{3}{W}{W}|Creature - Angel|4|4|Flying$W Relic Seeker|Magic Origins|29|R|{1}{W}|Creature - Human|2|2|Renown 1 (When this creature deals combat damage to a player, put a +1/+1 counter on it and it becomes renowned.)$When Relic Seeker becomes renowned, you may search your library for an Equipment card, reveal it, put it in your hand, then shuffle your library.| Sentinel of the Eternal Watch|Magic Origins|30|U|{5}{W}|Creature - Giant Soldier|4|6|Vigilance (Attacking doesn't cause this creature to tap.)$At the beginning of combat on each opponent's turn, tap target creature that player controls.| Starfield of Nyx|Magic Origins|33|M|{4}{W}|Enchantment|||At the beginning of your upkeep, you may return target enchantment card from your graveyard to the battlefield.$As long as you control five or more enchantments, each other non-Aura enchantment you control is a creature in addition to its other types and has base power and base toughness each equal to its converted mana cost.| +Topan Freeblade|Magic Origins|36|C|{1}{W}|Creature - Human Soldier|2|2|Vigilance (Attacking doesn't cause this creature to tap.)$Renown 1 (When this creature deals combat damage to a player, if it isn't renowned, put a +1/+1 counter on it and it becomes renowned.)| Valor in Akros|Magic Origins|39|U|{3}{W}|Enchantment|||Whenever a creature enters the battlefield under your control, creatures you control get +1/+1 until end of turn.| Yoked Ox|Magic Origins|42|C|{W}|Creature - Ox|0|4|| Alhammarrat, High Arbiter|43|R|{5}{U}{U}|Legendary Creature - Sphinx|5|5|Flying$As Alhammarret, High Arbiter enters the battlefield, each opponent reveals his or her hand. You choose the name of a nonland card revealed this way.$Your opponents can't cast spells with the chosen name (as long as this creature is on the battlefield).| @@ -26113,6 +26115,7 @@ Reave Soul|Magic Origins|115|C|{1}{B}|Sorcery|||Destroy target creature with pow Shambling Ghoul|Magic Origins|119|C|{1}{B}|Creature - Zombie|2|3|Shambling Ghoul enters the battlefield tapped.| Tainted Remedy|Magic Origins|120|R|{2}{B}|Enchantment|||If an opponent would gain life, that player loses that much life instead.| Undead Servant|Magic Origins|124|C|{3}{B}|Creature - Zombie|3|2|When Undead Servant enters the battlefield, put a 2/2 black Zombie creature token onto the battlefield for each card named Undead Servant in your graveyard.| +Unholy Hunger|Magic Origins|125|C|{3}{B}{B}|Instant|||Destroy target creature.$Spell mastery - If there are two or more instant and/or sorcery cards in your graveyard, you gain 2 life.| Weight of the Underworld|Magic Origins|126|C|{3}{B}|Enchantment - Aura|||Enchant creature$Enchanted creature gets -3/-2.| Act of Treason|Magic Origins|129|C|{2}{R}{2}{R}|Sorcery|||Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.| Avaricious Dragon|Magic Origins|131|M|{2}{R}{R}|Creature - Dragon|4|4|Flying$At the beginning of your draw step, draw an additional card.$At the beginning of your end step, discard your hand.| @@ -26124,6 +26127,7 @@ Chandra's Fury|Magic Origins|136|C|{4}{R}|Instant|||Chandra's Fury deals 4 damag Chandra's Ignition|Magic Origins|137|R|{3}{R}{R}|Sorcery|||Target creature you control deals damage equal to its power to each other creature and each opponent.| Cobblebrute|Magic Origins|138|C|{3}{R}{3}{R}|Creature - Elemental|5|2|| Enthralling Victor|Magic Origins|142|U|{3}{R}|Creature - Human Warrior|3|2|When Enthralling Victor enters the battlefield, gain control of target creature an opponent controls with power 2 or less until end of turn. Untap that creature. It gains haste until end of turn.| +Exquisite Firecraft|Magic Origins|143|R|{1}{R}{R}|Sorcery|||Exquisite Firecraft deals 4 damage to target creature or player.$Spell mastery - If there are two or more instant and/or sorcery cards in your graveyard, Exquisite Firecraft can't be countered by spells or abilities.| Fiery Conclusion|Magic Origins|144|C|{1}{R}|Instant|||As an additional cost to cast Fiery Conclusion, sacrifice a creature.$Fiery Conclusion deals 5 damage to target creature.| Fiery Impulse|Magic Origins|145|C|{R}|Instant|||Fiery Imulse deals 2 damage to target creature.$Spell mastery - If there are two or more instant and/or sorcery cards in your graveyard, Fiery Impulse deals 3 damage to that creature instead.| Flaeshadow Conjuring|Magic Origins|147|R|{3}{R}|Enchantment|||Whenever a nontoken creature enters the battlefield under your control, you may pay {R}. If you do, put a token onto the battlefield that's a copy of that creature. That token gains haste. Exile it at the beginning of the next end step.| @@ -26150,16 +26154,26 @@ Nissa, Vastwood Seer|Magic Origins|189|M|{2}{G}|Legendary Creature - Elf Scout|2 Rhox Maulers|Magic Origins|196|C|{4}{G}|Creature - Rhino Soldier|4|4|Trample (This creature can deal excess combat damage to defending player or planeswalker while attacking.)$Renown 2 (When this creature deals combat damage to a player, if it isn't renowned, put two +1/+1 counters on it and it becomes renowned.)| Timberpack Wolf|Magic Origins|200|C|{1}{G}|Creature - Wolf|2|2|Timberpack Wolf gets +1/+1 for each other creature you control named Timberpack Wolf.| Titanic Growth|Magic Origins|201|C|{1}{G}|Instant|||Target creature gets +4/+4 until end of turn.| +Valeron Wardens|Magic Origins|203|U|{2}{G}|Creature - Human Monk|1|3|Renown 2 (When this creature deals combat damage to a player, if it isn't renowned, put two +1/+1 counters on it and it becomes renowned.)$Whenever a creature you control becomes renowned, draw a card.| Vastwood Gorger|Magic Origins|204|C|{5}{G}|Creature - Wurm|5|6|| +Woodland Bellower|Magic Origins|207|M|{4}{G}{G}|Creature - Beast|6|5|When Woodland Bellower enters the battlefield, you may search your library for a nonlegendary green creature card with converted mana cost 3 or less, put it onto the battlefield, then shuffle your library.| Yeva's Forcemage|Magic Origins|208|C|{2}{G}|Creature - Elf Shaman|2|2|When Yeva's Forcemage enters the battlefield, target creature gets +2/+2 until end of turn.| Blazing Hellhound|Magic Origins|210|U|{2}{B}{R}|Creature - Elemental Hound|4|3|{1}, Sacrifice another creature: Blazing Hellhound deals 1 damage to target creature or player.| Bounding Krasis|Magic Origins|212|U|{1}{G}{U}|Creature - Fish Lizard|3|3|Flash (You may cast this spell any time you could cast an instant.)$When Bounding Krasis enters the battlefield, you may tap or untap target creature.| +Citadel Castellan|Magic Origins|213|U|{1}{G}{W}|Creature - Human Knight|2|3|Vigilance (Attacking doesn't cause this creature to tap.)$Renown 2 (When this creature deals combat damage to a player, if it isn't renowned, put two +1/+1 counters on it and it becomes renowned.)| Zendikar Incarnate|Magic Origins|219|U|{2}{R}{G}|Creature - Elemental|0|4|Zendikar Incarnate's power is equal to the amount of lands you control.| +Alhammarret's Archive|Magic Origins|221|M|{5}|Legendary Artifact|||If you would gain life, you gain twice that much life instead.$If you draw a card except the first one you draw in each of your draw steps, draw two cards instead.| Gold-Forged Sentinel|Magic Origins|226|U|{6}|Artifact Creature - Chimera|4|4|Flying$Flying| +Helm of the Gods|Magic Origins|230|R|{1}|Artifact - Equipment|||Equipped creature gets +1/+1 for each enchantment you control.$Equip {1} ({1}: Attach to target creature you control. Equip only as a sorcery. This card enters the battlefield unattached and stays on the battlefield if the creature leaves.)| Jayemdae Tome|Magic Origins|231|U|{4}|Artifact|||{4}, {T}: Draw a card.${4}, {T}: Draw a card.| Meteorite|Magic Origins|233|U|{5}|Artifact|||When Meteorite enters the battlefield, it deals 2 damage to target creature or player.${T}: Add one mana of any color to your mana pool.| Runed Servitor|Magic Origins|238|U|{2}|Artifact Creature - Construct|2|2|When Runed Servitor dies, each player draws a card.| Veteran's Sidearm|Magic Origins|242|C|{2}|Artifact - Equipment|||Equipped creature gets +1/+1.$Equip {1}| +Battlefield Forge|Magic Origins|244|R||Land|||{T}: Add {1} to your mana pool.${T}: Add {R} or {W} to your mana pool. Battlefield Forge deals 1 damage to you.| +Caves of Koilos|Magic Origins|245|R||Land|||{T}: Add {1} to your mana pool.${T}: Add {W} or {B} to your mana pool. Caves of Koilos deals 1 damage to you.| +Llanowar Wastes|Magic Origins|248|R||Land|||{T}: Add {1} to your mana pool.${T}: Add {B} or {G} to your mana pool. Llanowar Wastes deals 1 damage to you.| +Shivan Reef|Magic Origins|251|R||Land|||{T}: Add {1} to your mana pool.${T}: Add {U} or {R} to your mana pool. Shivan Reef deals 1 damage to you.| +Yavimaya Coast|Magic Origins|252|R||Land|||{T}: Add {1} to your mana pool.${T}: Add {G} or {U} to your mana pool. Yavimaya Coast deals 1 damage to you.| Aegis Angel|Magic Origins|273|R|{4}{W}{W}|Creature - Angel|5|5|Flying$When Aegis Angel enters the battlefield, another target permanent gains indestructible for as long as you control Aegis Angel.| Divine Verdict|Magic Origins|274|C|{3}{W}|Instant|||Destroy target attacking or blocking creature.| Eagle of the Watch|Magic Origins|275|C|{2}{W}|Creature - Bird|2|1|Flying, vigilance|