diff --git a/Mage.Common/src/mage/view/CardsView.java b/Mage.Common/src/mage/view/CardsView.java index a39a9d6e00..a4400c5faa 100644 --- a/Mage.Common/src/mage/view/CardsView.java +++ b/Mage.Common/src/mage/view/CardsView.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.view; import java.util.ArrayList; @@ -37,6 +36,7 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.cards.Card; +import mage.constants.CardType; import mage.constants.Zone; import static mage.constants.Zone.ALL; import static mage.constants.Zone.BATTLEFIELD; @@ -56,27 +56,28 @@ import mage.target.targetpointer.TargetPointer; */ public class CardsView extends LinkedHashMap { - public CardsView() {} + public CardsView() { + } public CardsView(Collection cards) { - for (Card card: cards) { + for (Card card : cards) { this.put(card.getId(), new CardView(card)); } } public CardsView(Game game, Collection cards) { - for (Card card: cards) { + for (Card card : cards) { this.put(card.getId(), new CardView(card, game, false)); } } - public CardsView ( Collection abilities, Game game ) { - for ( Ability ability : abilities ) { + public CardsView(Collection abilities, Game game) { + for (Ability ability : abilities) { MageObject sourceObject = null; AbilityView abilityView = null; boolean isCard = false; boolean isPermanent = false; - switch ( ability.getZone() ) { + switch (ability.getZone()) { case ALL: case EXILED: case GRAVEYARD: @@ -86,7 +87,7 @@ public class CardsView extends LinkedHashMap { case BATTLEFIELD: sourceObject = game.getPermanent(ability.getSourceId()); if (sourceObject == null) { - sourceObject = (Permanent)game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD); + sourceObject = (Permanent) game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD); } isPermanent = true; break; @@ -99,14 +100,19 @@ public class CardsView extends LinkedHashMap { case COMMAND: sourceObject = game.getObject(ability.getSourceId()); if (sourceObject instanceof Emblem) { - Card planeswalkerCard = game.getCard(((Emblem)sourceObject).getSourceId()); + Card planeswalkerCard = game.getCard(((Emblem) sourceObject).getSourceId()); if (planeswalkerCard != null) { - abilityView = new AbilityView(ability, "Emblem " + planeswalkerCard.getName(), new CardView(new EmblemView((Emblem)sourceObject, planeswalkerCard))); + if (!planeswalkerCard.getCardType().contains(CardType.PLANESWALKER)) { + if (planeswalkerCard.getSecondCardFace() != null) { + planeswalkerCard = planeswalkerCard.getSecondCardFace(); + } + } + abilityView = new AbilityView(ability, "Emblem " + planeswalkerCard.getName(), new CardView(new EmblemView((Emblem) sourceObject, planeswalkerCard))); abilityView.setName("Emblem " + planeswalkerCard.getName()); abilityView.setExpansionSetCode(planeswalkerCard.getExpansionSetCode()); } else { throw new IllegalArgumentException("Source card for emblem not found."); - } + } } break; } @@ -114,9 +120,9 @@ public class CardsView extends LinkedHashMap { if (abilityView == null) { CardView sourceCardView; if (isPermanent) { - sourceCardView = new CardView((Permanent)sourceObject); + sourceCardView = new CardView((Permanent) sourceObject); } else if (isCard) { - sourceCardView = new CardView((Card)sourceObject); + sourceCardView = new CardView((Card) sourceObject); } else { sourceCardView = new CardView(sourceObject); } @@ -153,7 +159,7 @@ public class CardsView extends LinkedHashMap { } public CardsView(Collection abilities, GameState state) { - for (Ability ability: abilities) { + for (Ability ability : abilities) { Card sourceCard = state.getPermanent(ability.getSourceId()); if (sourceCard != null) { this.put(ability.getId(), new AbilityView(ability, sourceCard.getName(), new CardView(sourceCard))); diff --git a/Mage.Common/src/mage/view/GameView.java b/Mage.Common/src/mage/view/GameView.java index b75d804513..9f078a75b9 100644 --- a/Mage.Common/src/mage/view/GameView.java +++ b/Mage.Common/src/mage/view/GameView.java @@ -1,36 +1,42 @@ /* -* 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.view; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import mage.MageObject; import mage.abilities.costs.Cost; import mage.cards.Card; +import mage.constants.CardType; import mage.constants.PhaseStep; import mage.constants.TurnPhase; import mage.constants.Zone; @@ -45,18 +51,15 @@ import mage.game.stack.Spell; import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.players.Player; -import org.apache.log4j.Logger; - -import java.io.Serializable; -import java.util.*; import mage.watchers.common.CastSpellLastTurnWatcher; - +import org.apache.log4j.Logger; /** * * @author BetaSteward_at_googlemail.com */ public class GameView implements Serializable { + private static final long serialVersionUID = 1L; private static final transient Logger logger = Logger.getLogger(GameView.class); @@ -83,70 +86,73 @@ public class GameView implements Serializable { private final int spellsCastCurrentTurn; private final boolean rollbackTurnsAllowed; - public GameView(GameState state, Game game, UUID createdForPlayerId, UUID watcherUserId) { Player createdForPlayer = null; this.isPlayer = createdForPlayerId != null; this.priorityTime = game.getPriorityTime(); - for (Player player: state.getPlayers().values()) { + for (Player player : state.getPlayers().values()) { players.add(new PlayerView(player, state, game, createdForPlayerId, watcherUserId)); if (player.getId().equals(createdForPlayerId)) { createdForPlayer = player; } } - for (StackObject stackObject: state.getStack()) { + for (StackObject stackObject : state.getStack()) { if (stackObject instanceof StackAbility) { - // Stack Ability + // Stack Ability MageObject object = game.getObject(stackObject.getSourceId()); Card card = game.getCard(stackObject.getSourceId()); if (card != null) { if (object != null) { - stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility)stackObject, card.getName(), new CardView(card))); + stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, card.getName(), new CardView(card))); } else { - stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility)stackObject, "", new CardView(card))); + stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, "", new CardView(card))); } if (card.canTransform()) { updateLatestCardView(game, card, stackObject.getId()); } - checkPaid(stackObject.getId(), (StackAbility)stackObject); + checkPaid(stackObject.getId(), (StackAbility) stackObject); } else if (object != null) { if (object instanceof PermanentToken) { - PermanentToken token = (PermanentToken)object; - stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility)stackObject, token.getName(), new CardView(token))); - checkPaid(stackObject.getId(), (StackAbility)stackObject); + PermanentToken token = (PermanentToken) object; + stack.put(stackObject.getId(), new StackAbilityView(game, (StackAbility) stackObject, token.getName(), new CardView(token))); + checkPaid(stackObject.getId(), (StackAbility) stackObject); } else if (object instanceof Emblem) { - Card sourceCard = game.getCard(((Emblem)object).getSourceId()); + Card sourceCard = game.getCard(((Emblem) object).getSourceId()); if (sourceCard != null) { - ((StackAbility)stackObject).setName("Emblem " + sourceCard.getName()); - ((StackAbility)stackObject).setExpansionSetCode(sourceCard.getExpansionSetCode()); + if (!sourceCard.getCardType().contains(CardType.PLANESWALKER)) { + if (sourceCard.getSecondCardFace() != null) { + sourceCard = sourceCard.getSecondCardFace(); + } + } + ((StackAbility) stackObject).setName("Emblem " + sourceCard.getName()); + ((StackAbility) stackObject).setExpansionSetCode(sourceCard.getExpansionSetCode()); } else { throw new IllegalArgumentException("Source card for emblem not found."); } - stack.put(stackObject.getId(), - new StackAbilityView(game, (StackAbility)stackObject, object.getName(), new CardView(new EmblemView(((Emblem)object),sourceCard)))); - checkPaid(stackObject.getId(), ((StackAbility)stackObject)); + stack.put(stackObject.getId(), + new StackAbilityView(game, (StackAbility) stackObject, object.getName(), new CardView(new EmblemView(((Emblem) object), sourceCard)))); + checkPaid(stackObject.getId(), ((StackAbility) stackObject)); } else { - StackAbility stackAbility = ((StackAbility)object); + StackAbility stackAbility = ((StackAbility) object); stackAbility.newId(); - stack.put(stackObject.getId(), new CardView(((StackAbility)stackObject))); - checkPaid(stackObject.getId(), ((StackAbility)stackObject)); + stack.put(stackObject.getId(), new CardView(((StackAbility) stackObject))); + checkPaid(stackObject.getId(), ((StackAbility) stackObject)); } } else { logger.error("Stack Object for stack ability not found: " + stackObject.getStackAbility().getRule()); } - } - else { + } else { // Spell - stack.put(stackObject.getId(), new CardView((Spell)stackObject, game, stackObject.getControllerId().equals(createdForPlayerId))); - checkPaid(stackObject.getId(), (Spell)stackObject); + stack.put(stackObject.getId(), new CardView((Spell) stackObject, game, stackObject.getControllerId().equals(createdForPlayerId))); + checkPaid(stackObject.getId(), (Spell) stackObject); } //stackOrder.add(stackObject.getId()); } //Collections.reverse(stackOrder); - for (ExileZone exileZone: state.getExile().getExileZones()) { + for (ExileZone exileZone : state.getExile().getExileZones()) { exiles.add(new ExileView(exileZone, game)); } - for (String name: state.getRevealed().keySet()) { + for (String name : state.getRevealed().keySet()) { revealed.add(new RevealedView(name, state.getRevealed().get(name), game)); } this.phase = state.getTurn().getPhaseType(); @@ -163,7 +169,7 @@ public class GameView implements Serializable { } else { this.priorityPlayerName = ""; } - for (CombatGroup combatGroup: state.getCombat().getGroups()) { + for (CombatGroup combatGroup : state.getCombat().getGroups()) { combat.add(new CombatGroupView(combatGroup, game)); } if (isPlayer) { @@ -174,13 +180,13 @@ public class GameView implements Serializable { } else { this.special = false; } - + CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher"); if (watcher != null) { spellsCastCurrentTurn = watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn(); } else { spellsCastCurrentTurn = 0; - } + } rollbackTurnsAllowed = game.getOptions().rollbackTurnsAllowed; } @@ -215,7 +221,7 @@ public class GameView implements Serializable { } Permanent permanent = game.getPermanent(card.getId()); if (permanent == null) { - permanent = (Permanent)game.getLastKnownInformation(card.getId(), Zone.BATTLEFIELD); + permanent = (Permanent) game.getLastKnownInformation(card.getId(), Zone.BATTLEFIELD); } if (permanent != null) { if (permanent.isTransformed()) { @@ -328,5 +334,5 @@ public class GameView implements Serializable { public boolean isRollbackTurnsAllowed() { return rollbackTurnsAllowed; } - + } diff --git a/Mage.Common/src/mage/view/PlayerView.java b/Mage.Common/src/mage/view/PlayerView.java index 14c3990eb3..ce66a5ffbe 100644 --- a/Mage.Common/src/mage/view/PlayerView.java +++ b/Mage.Common/src/mage/view/PlayerView.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; import mage.cards.Card; +import mage.constants.CardType; import mage.counters.CounterType; import mage.game.ExileZone; import mage.game.Game; @@ -125,6 +126,11 @@ public class PlayerView implements Serializable { if (emblem.getControllerId().equals(this.playerId)) { Card sourceCard = game.getCard(((CommandObject) emblem).getSourceId()); if (sourceCard != null) { + if (!sourceCard.getCardType().contains(CardType.PLANESWALKER)) { + if (sourceCard.getSecondCardFace() != null) { + sourceCard = sourceCard.getSecondCardFace(); + } + } commandList.add(new EmblemView(emblem, sourceCard)); } } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 952fe020cf..89d7ab3763 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -161,7 +161,7 @@ public class ComputerPlayer extends PlayerImpl implements Player { private transient final static Logger log = Logger.getLogger(ComputerPlayer.class); protected int PASSIVITY_PENALTY = 5; // Penalty value for doing nothing if some actions are availble - protected boolean ALLOW_INTERRUPT = false; // change this for test / debugging purposes to false to switch off interrupts while debugging + protected boolean ALLOW_INTERRUPT = true; // change this for test / debugging purposes to false to switch off interrupts while debugging private transient Map unplayable = new TreeMap<>(); private transient List playableNonInstant = new ArrayList<>(); diff --git a/Mage.Sets/src/mage/sets/alarareborn/NecromancersCovenant.java b/Mage.Sets/src/mage/sets/alarareborn/NecromancersCovenant.java index df2dbbeadf..9e5dcf9df7 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/NecromancersCovenant.java +++ b/Mage.Sets/src/mage/sets/alarareborn/NecromancersCovenant.java @@ -28,11 +28,6 @@ package mage.sets.alarareborn; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -41,6 +36,11 @@ import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.keyword.LifelinkAbility; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.SubtypePredicate; @@ -54,9 +54,9 @@ import mage.target.TargetPlayer; * @author jeffwadsworth */ public class NecromancersCovenant extends CardImpl { - + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Zombies you control"); - + static { filter.add(new SubtypePredicate("Zombie")); } @@ -65,9 +65,6 @@ public class NecromancersCovenant extends CardImpl { super(ownerId, 82, "Necromancer's Covenant", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{B}{B}"); this.expansionSetCode = "ARB"; - - - // When Necromancer's Covenant enters the battlefield, exile all creature cards from target player's graveyard, then put a 2/2 black Zombie creature token onto the battlefield for each card exiled this way. Ability ability = new EntersBattlefieldTriggeredAbility(new NecromancersConvenantEffect(), false); ability.addTarget(new TargetPlayer()); @@ -110,7 +107,7 @@ class NecromancersConvenantEffect extends OneShotEffect { count += 1; } } - ZombieToken zombieToken = new ZombieToken("ALA"); + ZombieToken zombieToken = new ZombieToken(); if (zombieToken.putOntoBattlefield(count, game, source.getSourceId(), source.getControllerId())) { return true; } diff --git a/Mage.Sets/src/mage/sets/alarareborn/UnscytheKillerOfKings.java b/Mage.Sets/src/mage/sets/alarareborn/UnscytheKillerOfKings.java index b89373ee45..3400918c53 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/UnscytheKillerOfKings.java +++ b/Mage.Sets/src/mage/sets/alarareborn/UnscytheKillerOfKings.java @@ -163,7 +163,7 @@ class UnscytheEffect extends OneShotEffect { if (controller != null) { Card card = game.getCard(targetPointer.getFirst(game, source)); if (card != null && game.getState().getZone(card.getId()).equals(Zone.GRAVEYARD) && controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.GRAVEYARD, true)) { - ZombieToken zombie = new ZombieToken("ALA"); + ZombieToken zombie = new ZombieToken(); return zombie.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); } return true; diff --git a/Mage.Sets/src/mage/sets/avacynrestored/MaalfeldTwins.java b/Mage.Sets/src/mage/sets/avacynrestored/MaalfeldTwins.java index 72bcf6c1af..503fc720b6 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/MaalfeldTwins.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/MaalfeldTwins.java @@ -28,12 +28,12 @@ package mage.sets.avacynrestored; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.game.permanent.token.ZombieToken; /** @@ -51,7 +51,7 @@ public class MaalfeldTwins extends CardImpl { this.toughness = new MageInt(4); // When Maalfeld Twins dies, put two 2/2 black Zombie creature tokens onto the battlefield. - this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ZombieToken("ALA"), 2))); + this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ZombieToken(), 2))); } public MaalfeldTwins(final MaalfeldTwins card) { diff --git a/Mage.Sets/src/mage/sets/commander2014/GhoulcallerGisa.java b/Mage.Sets/src/mage/sets/commander2014/GhoulcallerGisa.java index 24e6fb4e5d..00c32af9c7 100644 --- a/Mage.Sets/src/mage/sets/commander2014/GhoulcallerGisa.java +++ b/Mage.Sets/src/mage/sets/commander2014/GhoulcallerGisa.java @@ -72,11 +72,11 @@ public class GhoulcallerGisa extends CardImpl { // {B}, {tap}, Sacrifice another creature: Put X 2/2 black Zombie creature tokens onto the battlefield, where X is the sacrificed creature's power. DynamicValue xValue = new SacrificeCostCreaturesPower(); - Token zombie = new ZombieToken("C14"); + Token zombie = new ZombieToken(); zombie.setTokenType(2); Effect effect = new CreateTokenEffect(zombie, xValue); effect.setText("Put X 2/2 black Zombie creature tokens onto the battlefield, where X is the sacrificed creature's power"); - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{B}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{B}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/commander2014/OverseerOfTheDamned.java b/Mage.Sets/src/mage/sets/commander2014/OverseerOfTheDamned.java index d31d1267b9..b4f79d1268 100644 --- a/Mage.Sets/src/mage/sets/commander2014/OverseerOfTheDamned.java +++ b/Mage.Sets/src/mage/sets/commander2014/OverseerOfTheDamned.java @@ -75,7 +75,7 @@ public class OverseerOfTheDamned extends CardImpl { ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); // Whenever a nontoken creature an opponent controls dies, put a 2/2 black Zombie creature token onto the battlefield tapped. - Token zombie = new ZombieToken("C14"); + Token zombie = new ZombieToken(); zombie.setTokenType(2); this.addAbility(new DiesCreatureTriggeredAbility(new CreateTokenEffect(zombie, 1, true, false), false, filter)); diff --git a/Mage.Sets/src/mage/sets/conflux/GrixisSlavedriver.java b/Mage.Sets/src/mage/sets/conflux/GrixisSlavedriver.java index 3710c6ace3..9897aad58c 100644 --- a/Mage.Sets/src/mage/sets/conflux/GrixisSlavedriver.java +++ b/Mage.Sets/src/mage/sets/conflux/GrixisSlavedriver.java @@ -25,21 +25,19 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.conflux; -import mage.constants.CardType; -import mage.constants.Rarity; +import java.util.UUID; import mage.MageInt; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.UnearthAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.game.permanent.token.ZombieToken; -import java.util.UUID; - /** * @author Loki */ @@ -53,7 +51,7 @@ public class GrixisSlavedriver extends CardImpl { this.subtype.add("Giant"); this.power = new MageInt(4); this.toughness = new MageInt(4); - this.addAbility(new LeavesBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken("ALA")), false)); + this.addAbility(new LeavesBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken()), false)); this.addAbility(new UnearthAbility(new ManaCostsImpl("{3}{B}"))); } diff --git a/Mage.Sets/src/mage/sets/darkascension/HavengulRunebinder.java b/Mage.Sets/src/mage/sets/darkascension/HavengulRunebinder.java index 4426178976..b4f746332c 100644 --- a/Mage.Sets/src/mage/sets/darkascension/HavengulRunebinder.java +++ b/Mage.Sets/src/mage/sets/darkascension/HavengulRunebinder.java @@ -28,9 +28,6 @@ package mage.sets.darkascension; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.ExileFromGraveCost; @@ -39,6 +36,9 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreatureCard; @@ -71,7 +71,7 @@ public class HavengulRunebinder extends CardImpl { // {2}{U}, {tap}, Exile a creature card from your graveyard: Put a 2/2 black Zombie creature token onto the battlefield, // then put a +1/+1 counter on each Zombie creature you control. SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new CreateTokenEffect(new ZombieToken("ISD")), + new CreateTokenEffect(new ZombieToken()), new ManaCostsImpl("{2}{U}")); ability.addCost(new TapSourceCost()); ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(filter))); diff --git a/Mage.Sets/src/mage/sets/darkascension/ReapTheSeagraf.java b/Mage.Sets/src/mage/sets/darkascension/ReapTheSeagraf.java index cd1d8070e6..7623e13224 100644 --- a/Mage.Sets/src/mage/sets/darkascension/ReapTheSeagraf.java +++ b/Mage.Sets/src/mage/sets/darkascension/ReapTheSeagraf.java @@ -19,8 +19,7 @@ public class ReapTheSeagraf extends CardImpl { super(ownerId, 72, "Reap the Seagraf", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{2}{B}"); this.expansionSetCode = "DKA"; - - this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken("ISD"))); + this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken())); this.addAbility(new FlashbackAbility(new ManaCostsImpl("{4}{U}"), TimingRule.SORCERY)); } diff --git a/Mage.Sets/src/mage/sets/darkascension/Wakedancer.java b/Mage.Sets/src/mage/sets/darkascension/Wakedancer.java index 2055a9ae02..1324ea54bd 100644 --- a/Mage.Sets/src/mage/sets/darkascension/Wakedancer.java +++ b/Mage.Sets/src/mage/sets/darkascension/Wakedancer.java @@ -44,6 +44,7 @@ import mage.game.permanent.token.ZombieToken; * @author Loki */ public class Wakedancer extends CardImpl { + private static final String staticText = "Morbid - When {this} enters the battlefield, if a creature died this turn, put a 2/2 black Zombie creature token onto the battlefield."; public Wakedancer(UUID ownerId) { @@ -57,7 +58,7 @@ public class Wakedancer extends CardImpl { this.toughness = new MageInt(2); // Morbid - When Wakedancer enters the battlefield, if a creature died this turn, put a 2/2 black Zombie creature token onto the battlefield. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken("ISD"))); + TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken())); this.addAbility(new ConditionalTriggeredAbility(ability, MorbidCondition.getInstance(), staticText)); } diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/RakshasaGravecaller.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/RakshasaGravecaller.java index f30c57e476..ca087c2729 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/RakshasaGravecaller.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/RakshasaGravecaller.java @@ -53,9 +53,9 @@ public class RakshasaGravecaller extends CardImpl { // Exploit this.addAbility(new ExploitAbility()); - + // When Rakshasa Gravecaller exploits a creature, put two 2/2 black Zombie creature tokens onto the battlefield. - this.addAbility(new ExploitCreatureTriggeredAbility(new CreateTokenEffect(new ZombieToken("DTK"), 2), false)); + this.addAbility(new ExploitCreatureTriggeredAbility(new CreateTokenEffect(new ZombieToken(), 2), false)); } public RakshasaGravecaller(final RakshasaGravecaller card) { diff --git a/Mage.Sets/src/mage/sets/elvesvsgoblins/IbHalfheartGoblinTactician.java b/Mage.Sets/src/mage/sets/elvesvsgoblins/IbHalfheartGoblinTactician.java index 095e9dc2bb..44cfadd869 100644 --- a/Mage.Sets/src/mage/sets/elvesvsgoblins/IbHalfheartGoblinTactician.java +++ b/Mage.Sets/src/mage/sets/elvesvsgoblins/IbHalfheartGoblinTactician.java @@ -86,7 +86,7 @@ public class IbHalfheartGoblinTactician extends CardImpl { // Sacrifice two Mountains: Put two 1/1 red Goblin creature tokens onto the battlefield. this.addAbility(new SimpleActivatedAbility( Zone.BATTLEFIELD, - new CreateTokenEffect(new GoblinToken(expansionSetCode), 2), + new CreateTokenEffect(new GoblinToken(), 2), new SacrificeTargetCost(new TargetControlledPermanent(2, 2, filter, true)))); } diff --git a/Mage.Sets/src/mage/sets/innistrad/ArmyOfTheDamned.java b/Mage.Sets/src/mage/sets/innistrad/ArmyOfTheDamned.java index 1ab4ba853f..a80ff5eac5 100644 --- a/Mage.Sets/src/mage/sets/innistrad/ArmyOfTheDamned.java +++ b/Mage.Sets/src/mage/sets/innistrad/ArmyOfTheDamned.java @@ -37,7 +37,6 @@ import mage.constants.Rarity; import mage.constants.TimingRule; import mage.game.permanent.token.ZombieToken; - /** * @author nantuko */ @@ -47,9 +46,8 @@ public class ArmyOfTheDamned extends CardImpl { super(ownerId, 87, "Army of the Damned", Rarity.MYTHIC, new CardType[]{CardType.SORCERY}, "{5}{B}{B}{B}"); this.expansionSetCode = "ISD"; - // Put thirteen 2/2 black Zombie creature tokens onto the battlefield tapped. - this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken("ISD"), 13, true, false)); + this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken(), 13, true, false)); // Flashback {7}{B}{B}{B} this.addAbility(new FlashbackAbility(new ManaCostsImpl("{7}{B}{B}{B}"), TimingRule.SORCERY)); diff --git a/Mage.Sets/src/mage/sets/innistrad/CellarDoor.java b/Mage.Sets/src/mage/sets/innistrad/CellarDoor.java index e209ee7f2d..869b49fbeb 100644 --- a/Mage.Sets/src/mage/sets/innistrad/CellarDoor.java +++ b/Mage.Sets/src/mage/sets/innistrad/CellarDoor.java @@ -28,10 +28,6 @@ package mage.sets.innistrad; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; @@ -39,6 +35,10 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.token.ZombieToken; import mage.players.Player; @@ -95,7 +95,7 @@ class CellarDoorEffect extends OneShotEffect { if (card != null) { player.moveCards(card, Zone.LIBRARY, Zone.GRAVEYARD, source, game); if (card.getCardType().contains(CardType.CREATURE)) { - ZombieToken token = new ZombieToken("ISD"); + ZombieToken token = new ZombieToken(); token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/sets/innistrad/EndlessRanksOfTheDead.java b/Mage.Sets/src/mage/sets/innistrad/EndlessRanksOfTheDead.java index 28d7a191a3..dfc6815538 100644 --- a/Mage.Sets/src/mage/sets/innistrad/EndlessRanksOfTheDead.java +++ b/Mage.Sets/src/mage/sets/innistrad/EndlessRanksOfTheDead.java @@ -27,6 +27,7 @@ */ package mage.sets.innistrad; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; @@ -41,8 +42,6 @@ import mage.game.Game; import mage.game.events.GameEvent.EventType; import mage.game.permanent.token.ZombieToken; -import java.util.UUID; - /** * * @author BetaSteward @@ -53,11 +52,10 @@ public class EndlessRanksOfTheDead extends CardImpl { super(ownerId, 99, "Endless Ranks of the Dead", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); this.expansionSetCode = "ISD"; - // At the beginning of your upkeep, put X 2/2 black Zombie creature tokens onto the battlefield, // where X is half the number of Zombies you control, rounded down. this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", - new CreateTokenEffect(new ZombieToken("ISD"), new HalfZombiesCount()))); + new CreateTokenEffect(new ZombieToken(), new HalfZombiesCount()))); } diff --git a/Mage.Sets/src/mage/sets/innistrad/MoanOfTheUnhallowed.java b/Mage.Sets/src/mage/sets/innistrad/MoanOfTheUnhallowed.java index a981392e93..82b16d77bc 100644 --- a/Mage.Sets/src/mage/sets/innistrad/MoanOfTheUnhallowed.java +++ b/Mage.Sets/src/mage/sets/innistrad/MoanOfTheUnhallowed.java @@ -47,9 +47,8 @@ public class MoanOfTheUnhallowed extends CardImpl { super(ownerId, 109, "Moan of the Unhallowed", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{2}{B}{B}"); this.expansionSetCode = "ISD"; - // Put two 2/2 black Zombie creature tokens onto the battlefield. - this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken("ISD"), 2)); + this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken(), 2)); // Flashback {5}{B}{B} this.addAbility(new FlashbackAbility(new ManaCostsImpl("{5}{B}{B}"), TimingRule.SORCERY)); diff --git a/Mage.Sets/src/mage/sets/innistrad/UndeadAlchemist.java b/Mage.Sets/src/mage/sets/innistrad/UndeadAlchemist.java index 884fc9e016..4e39289c8d 100644 --- a/Mage.Sets/src/mage/sets/innistrad/UndeadAlchemist.java +++ b/Mage.Sets/src/mage/sets/innistrad/UndeadAlchemist.java @@ -86,7 +86,7 @@ class UndeadAlchemistTriggeredAbility extends TriggeredAbilityImpl { public UndeadAlchemistTriggeredAbility() { super(Zone.BATTLEFIELD, new ExileTargetEffect(), true); - this.addEffect(new CreateTokenEffect(new ZombieToken("ISD"))); + this.addEffect(new CreateTokenEffect(new ZombieToken())); } public UndeadAlchemistTriggeredAbility(final UndeadAlchemistTriggeredAbility ability) { @@ -105,7 +105,7 @@ class UndeadAlchemistTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - ZoneChangeEvent zEvent = (ZoneChangeEvent)event; + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; if (zEvent.getFromZone() == Zone.LIBRARY && zEvent.getToZone() == Zone.GRAVEYARD && game.getOpponents(this.getControllerId()).contains(zEvent.getPlayerId())) { Card card = game.getCard(event.getTargetId()); if (card != null && card.getCardType().contains(CardType.CREATURE)) { diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/HordelingOutburst.java b/Mage.Sets/src/mage/sets/khansoftarkir/HordelingOutburst.java index 663895c792..d812a84e0d 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/HordelingOutburst.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/HordelingOutburst.java @@ -44,9 +44,8 @@ public class HordelingOutburst extends CardImpl { super(ownerId, 111, "Hordeling Outburst", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{1}{R}{R}"); this.expansionSetCode = "KTK"; - // Put 3 1/1 red Goblin creature tokens onto the battlefield. - this.getSpellAbility().addEffect(new CreateTokenEffect(new GoblinToken(expansionSetCode), 3)); + this.getSpellAbility().addEffect(new CreateTokenEffect(new GoblinToken(), 3)); } public HordelingOutburst(final HordelingOutburst card) { diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/MarduAscendancy.java b/Mage.Sets/src/mage/sets/khansoftarkir/MarduAscendancy.java index 86f5efc4b4..13e222bca1 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/MarduAscendancy.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/MarduAscendancy.java @@ -64,9 +64,8 @@ public class MarduAscendancy extends CardImpl { super(ownerId, 185, "Mardu Ascendancy", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{R}{W}{B}"); this.expansionSetCode = "KTK"; - // Whenever a nontoken creature you control attacks, put a 1/1 red Goblin creature token onto the battlefield tapped and attacking. - this.addAbility(new AttacksCreatureYouControlTriggeredAbility(new CreateTokenEffect(new GoblinToken(expansionSetCode), 1, true, true), false, attackFilter)); + this.addAbility(new AttacksCreatureYouControlTriggeredAbility(new CreateTokenEffect(new GoblinToken(), 1, true, true), false, attackFilter)); // Sacrifice Mardu Ascendancy: Creatures you control get +0/+3 until end of turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostAllEffect(0, 3, Duration.EndOfTurn, filter, false), diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/PonybackBrigade.java b/Mage.Sets/src/mage/sets/khansoftarkir/PonybackBrigade.java index f6f03ca9d0..fde44d673e 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/PonybackBrigade.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/PonybackBrigade.java @@ -60,7 +60,7 @@ public class PonybackBrigade extends CardImpl { this.toughness = new MageInt(2); // When Ponyback Brigade enters the battlefield or is turned face up, put three 1/1 red Goblin creature tokens onto the battlefield. - this.addAbility(new PonybackBrigadeAbility(new GoblinToken(expansionSetCode))); + this.addAbility(new PonybackBrigadeAbility(new GoblinToken())); // Morph {2}{R}{W}{B} this.addAbility(new MorphAbility(this, new ManaCostsImpl("{2}{R}{W}{B}"))); @@ -102,7 +102,7 @@ class PonybackBrigadeAbility extends TriggeredAbilityImpl { if (event.getType() == EventType.TURNEDFACEUP && event.getTargetId().equals(this.getSourceId())) { return true; } - if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId()) ) { + if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId())) { Permanent sourcePermanent = game.getPermanent(getSourceId()); if (sourcePermanent != null && !sourcePermanent.isFaceDown(game)) { return true; diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/SidisiBroodTyrant.java b/Mage.Sets/src/mage/sets/khansoftarkir/SidisiBroodTyrant.java index 6eda6b2e4e..be677f414d 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/SidisiBroodTyrant.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/SidisiBroodTyrant.java @@ -112,7 +112,7 @@ class SidisiBroodTyrantAbility extends TriggeredAbilityImpl { class SidisiBroodTyrantTriggeredAbility extends TriggeredAbilityImpl { public SidisiBroodTyrantTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken("KTK")), false); + super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken()), false); } public SidisiBroodTyrantTriggeredAbility(final SidisiBroodTyrantTriggeredAbility ability) { @@ -126,12 +126,12 @@ class SidisiBroodTyrantTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent)event; + ZoneChangeGroupEvent zEvent = (ZoneChangeGroupEvent) event; if (Zone.LIBRARY == zEvent.getFromZone() && Zone.GRAVEYARD == zEvent.getToZone()) { - for (Card card: zEvent.getCards()) { + for (Card card : zEvent.getCards()) { if (card.getOwnerId().equals(getControllerId()) && card.getCardType().contains(CardType.CREATURE)) { return true; - } + } } } return false; @@ -142,7 +142,6 @@ class SidisiBroodTyrantTriggeredAbility extends TriggeredAbilityImpl { return new SidisiBroodTyrantTriggeredAbility(this); } - @Override public String getRule() { return "Whenever one or more creature cards are put into your graveyard from your library, put a 2/2 black Zombie creature token onto the battlefield."; diff --git a/Mage.Sets/src/mage/sets/magic2011/GraveTitan.java b/Mage.Sets/src/mage/sets/magic2011/GraveTitan.java index b478145b76..22f1f6bfa4 100644 --- a/Mage.Sets/src/mage/sets/magic2011/GraveTitan.java +++ b/Mage.Sets/src/mage/sets/magic2011/GraveTitan.java @@ -1,16 +1,16 @@ /* * 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 @@ -20,12 +20,11 @@ * 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.magic2011; import java.util.UUID; @@ -74,7 +73,7 @@ public class GraveTitan extends CardImpl { class GraveTitanAbility extends TriggeredAbilityImpl { public GraveTitanAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken("M11"), 2), false); + super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken(), 2), false); } public GraveTitanAbility(final GraveTitanAbility ability) { @@ -96,7 +95,7 @@ class GraveTitanAbility extends TriggeredAbilityImpl { if (event.getType() == EventType.ATTACKER_DECLARED && event.getSourceId().equals(this.getSourceId())) { return true; } - if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId()) ) { + if (event.getType() == EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId())) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/magic2012/CemeteryReaper.java b/Mage.Sets/src/mage/sets/magic2012/CemeteryReaper.java index 91a639adbb..54bc7b115d 100644 --- a/Mage.Sets/src/mage/sets/magic2012/CemeteryReaper.java +++ b/Mage.Sets/src/mage/sets/magic2012/CemeteryReaper.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.magic2012; import java.util.UUID; @@ -55,7 +54,7 @@ import mage.target.common.TargetCardInGraveyard; public class CemeteryReaper extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Zombie creatures"); - + static { filter.add(new SubtypePredicate("Zombie")); } @@ -66,14 +65,14 @@ public class CemeteryReaper extends CardImpl { this.subtype.add("Zombie"); this.power = new MageInt(2); this.toughness = new MageInt(2); - + // Other Zombie creatures you control get +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filter, true))); - - // {2}{B}, {T} : Exile target creature card from a graveyard. Put a 2/2 black Zombie creature token onto the battlefield. + + // {2}{B}, {T} : Exile target creature card from a graveyard. Put a 2/2 black Zombie creature token onto the battlefield. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new ManaCostsImpl("{2}{B}")); ability.addCost(new TapSourceCost()); - ability.addEffect(new CreateTokenEffect(new ZombieToken("M12"))); + ability.addEffect(new CreateTokenEffect(new ZombieToken())); ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard"))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/magic2012/ZombieInfestation.java b/Mage.Sets/src/mage/sets/magic2012/ZombieInfestation.java index 09c3d72857..e557f40100 100644 --- a/Mage.Sets/src/mage/sets/magic2012/ZombieInfestation.java +++ b/Mage.Sets/src/mage/sets/magic2012/ZombieInfestation.java @@ -28,13 +28,13 @@ package mage.sets.magic2012; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.DiscardTargetCost; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.permanent.token.ZombieToken; import mage.target.common.TargetCardInHand; @@ -49,10 +49,9 @@ public class ZombieInfestation extends CardImpl { super(ownerId, 120, "Zombie Infestation", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); this.expansionSetCode = "M12"; - // Discard two cards: Put a 2/2 black Zombie creature token onto the battlefield. SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, - new CreateTokenEffect(new ZombieToken("M12")), + new CreateTokenEffect(new ZombieToken()), new DiscardTargetCost(new TargetCardInHand(2, new FilterCard("two cards")))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/magic2013/VileRebirth.java b/Mage.Sets/src/mage/sets/magic2013/VileRebirth.java index 2daa3aca0f..f62b22cdea 100644 --- a/Mage.Sets/src/mage/sets/magic2013/VileRebirth.java +++ b/Mage.Sets/src/mage/sets/magic2013/VileRebirth.java @@ -37,8 +37,6 @@ import mage.filter.common.FilterCreatureCard; import mage.game.permanent.token.ZombieToken; import mage.target.common.TargetCardInGraveyard; - - /** * * @author North @@ -49,13 +47,12 @@ public class VileRebirth extends CardImpl { super(ownerId, 115, "Vile Rebirth", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{B}"); this.expansionSetCode = "M13"; - // Exile target creature card from a graveyard. this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard"))); // Put a 2/2 black Zombie creature token onto the battlefield. - this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken("M13"))); + this.getSpellAbility().addEffect(new CreateTokenEffect(new ZombieToken())); } public VileRebirth(final VileRebirth card) { diff --git a/Mage.Sets/src/mage/sets/magic2014/LilianasReaver.java b/Mage.Sets/src/mage/sets/magic2014/LilianasReaver.java index 8e1cc16edf..d2094078eb 100644 --- a/Mage.Sets/src/mage/sets/magic2014/LilianasReaver.java +++ b/Mage.Sets/src/mage/sets/magic2014/LilianasReaver.java @@ -57,8 +57,8 @@ public class LilianasReaver extends CardImpl { this.addAbility(DeathtouchAbility.getInstance()); // Whenever Liliana's Reaver deals combat damage to a player, that player discards a card and you put a 2/2 black Zombie creature token onto the battlefield tapped. - Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1),false, true); - ability.addEffect(new CreateTokenEffect(new ZombieToken("M14"), 1, true, false)); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(1), false, true); + ability.addEffect(new CreateTokenEffect(new ZombieToken(), 1, true, false)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/magic2014/XathridNecromancer.java b/Mage.Sets/src/mage/sets/magic2014/XathridNecromancer.java index 32b7487ad9..cb5fd96188 100644 --- a/Mage.Sets/src/mage/sets/magic2014/XathridNecromancer.java +++ b/Mage.Sets/src/mage/sets/magic2014/XathridNecromancer.java @@ -49,6 +49,7 @@ import mage.game.permanent.token.ZombieToken; public class XathridNecromancer extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Human creature you control"); + static { filter.add(new ControllerPredicate(TargetController.YOU)); filter.add(new SubtypePredicate("Human")); @@ -64,7 +65,7 @@ public class XathridNecromancer extends CardImpl { this.toughness = new MageInt(2); // Whenever Xathrid Necromancer or another Human creature you control dies, put a 2/2 black Zombie creature token onto the battlefield tapped. - Effect effect = new CreateTokenEffect(new ZombieToken("M14"), 1, true, false); + Effect effect = new CreateTokenEffect(new ZombieToken(), 1, true, false); Ability ability = new DiesThisOrAnotherCreatureTriggeredAbility(effect, false, filter); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/magic2015/FeralIncarnation.java b/Mage.Sets/src/mage/sets/magic2015/FeralIncarnation.java index 0123ea48b2..2f4d8900e7 100644 --- a/Mage.Sets/src/mage/sets/magic2015/FeralIncarnation.java +++ b/Mage.Sets/src/mage/sets/magic2015/FeralIncarnation.java @@ -45,11 +45,10 @@ public class FeralIncarnation extends CardImpl { super(ownerId, 174, "Feral Incarnation", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{8}{G}"); this.expansionSetCode = "M15"; - // Convoke this.addAbility(new ConvokeAbility()); // Put three 3/3 green Beast creature tokens onto the battlefield. - this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken("M15", 1), 3)); + this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken(), 3)); } public FeralIncarnation(final FeralIncarnation card) { diff --git a/Mage.Sets/src/mage/sets/magic2015/NecromancersStockpile.java b/Mage.Sets/src/mage/sets/magic2015/NecromancersStockpile.java index c3f5a323e4..51af6f7ded 100644 --- a/Mage.Sets/src/mage/sets/magic2015/NecromancersStockpile.java +++ b/Mage.Sets/src/mage/sets/magic2015/NecromancersStockpile.java @@ -27,6 +27,7 @@ */ package mage.sets.magic2015; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.CostImpl; @@ -47,8 +48,6 @@ import mage.game.permanent.token.ZombieToken; import mage.players.Player; import mage.target.common.TargetCardInHand; -import java.util.UUID; - /** * @author noxx */ @@ -60,7 +59,6 @@ public class NecromancersStockpile extends CardImpl { super(ownerId, 108, "Necromancer's Stockpile", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); this.expansionSetCode = "M15"; - // {1}{B}, Discard a creature card: Draw a card. // If the discarded card was a Zombie card, put a 2/2 black Zombie creature token onto the battlefield tapped. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new ManaCostsImpl("{1}{B}")); @@ -97,7 +95,7 @@ class NecromancersStockpileDiscardTargetCost extends CostImpl { public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) { if (targets.choose(Outcome.Discard, controllerId, sourceId, game)) { Player player = game.getPlayer(controllerId); - for (UUID targetId: targets.get(0).getTargets()) { + for (UUID targetId : targets.get(0).getTargets()) { Card card = player.getHand().get(targetId, game); if (card == null) { return false; @@ -127,6 +125,7 @@ class NecromancersStockpileDiscardTargetCost extends CostImpl { } class NecromancersStockpilePutTokenEffect extends OneShotEffect { + NecromancersStockpilePutTokenEffect() { super(Outcome.Neutral); staticText = "If the discarded card was a Zombie card, put a 2/2 black Zombie creature token onto the battlefield tapped"; @@ -140,7 +139,7 @@ class NecromancersStockpilePutTokenEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { NecromancersStockpileDiscardTargetCost cost = (NecromancersStockpileDiscardTargetCost) source.getCosts().get(0); if (cost != null && cost.isZombieCard()) { - new CreateTokenEffect(new ZombieToken("M15"), 1, true, false).apply(game, source); + new CreateTokenEffect(new ZombieToken(), 1, true, false).apply(game, source); } return true; } @@ -150,4 +149,3 @@ class NecromancersStockpilePutTokenEffect extends OneShotEffect { return new NecromancersStockpilePutTokenEffect(this); } } - diff --git a/Mage.Sets/src/mage/sets/magic2015/SoulOfZendikar.java b/Mage.Sets/src/mage/sets/magic2015/SoulOfZendikar.java index 7c09f0eb7c..09593c1622 100644 --- a/Mage.Sets/src/mage/sets/magic2015/SoulOfZendikar.java +++ b/Mage.Sets/src/mage/sets/magic2015/SoulOfZendikar.java @@ -58,9 +58,9 @@ public class SoulOfZendikar extends CardImpl { // Reach this.addAbility(ReachAbility.getInstance()); // {3}{G}{G}: Put a 3/3 green Beast creature token onto the battlefield. - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new BeastToken("M15")), new ManaCostsImpl("{3}{G}{G}"))); + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new BeastToken()), new ManaCostsImpl("{3}{G}{G}"))); // {3}{G}{G}, Exile Soul of Zendikar from your graveyard: Put a 3/3 green Beast creature token onto the battlefield. - Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new CreateTokenEffect(new BeastToken("M15")), new ManaCostsImpl("{3}{G}{G}")); + Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new CreateTokenEffect(new BeastToken()), new ManaCostsImpl("{3}{G}{G}")); ability.addCost(new ExileSourceFromGraveCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/magic2015/WasteNot.java b/Mage.Sets/src/mage/sets/magic2015/WasteNot.java index 4fba77c7a4..ed5690362e 100644 --- a/Mage.Sets/src/mage/sets/magic2015/WasteNot.java +++ b/Mage.Sets/src/mage/sets/magic2015/WasteNot.java @@ -53,13 +53,12 @@ public class WasteNot extends CardImpl { super(ownerId, 122, "Waste Not", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); this.expansionSetCode = "M15"; - // Whenever an opponent discards a creature card, put a 2/2 black Zombie creature token onto the battlefield. this.addAbility(new WasteNotCreatureTriggeredAbility()); - + // Whenever an opponent discards a land card, add {B}{B} to your mana pool. this.addAbility(new WasteNotLandTriggeredAbility()); - + // Whenever an opponent discards a noncreature, nonland card, draw a card. this.addAbility(new WasteNotOtherTriggeredAbility()); } @@ -75,15 +74,15 @@ public class WasteNot extends CardImpl { } class WasteNotCreatureTriggeredAbility extends TriggeredAbilityImpl { - + WasteNotCreatureTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken("M15")), false); + super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken()), false); } - + WasteNotCreatureTriggeredAbility(final WasteNotCreatureTriggeredAbility ability) { super(ability); } - + @Override public WasteNotCreatureTriggeredAbility copy() { return new WasteNotCreatureTriggeredAbility(this); @@ -93,7 +92,7 @@ class WasteNotCreatureTriggeredAbility extends TriggeredAbilityImpl { public boolean checkEventType(GameEvent event, Game game) { return event.getType() == EventType.DISCARDED_CARD; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(this.getControllerId()).contains(event.getPlayerId())) { @@ -104,7 +103,7 @@ class WasteNotCreatureTriggeredAbility extends TriggeredAbilityImpl { } return false; } - + @Override public String getRule() { return "Whenever an opponent discards a creature card, put a 2/2 black Zombie creature token onto the battlefield."; @@ -112,15 +111,15 @@ class WasteNotCreatureTriggeredAbility extends TriggeredAbilityImpl { } class WasteNotLandTriggeredAbility extends TriggeredAbilityImpl { - + WasteNotLandTriggeredAbility() { super(Zone.BATTLEFIELD, new BasicManaEffect(new Mana(0, 0, 0, 0, 2, 0, 0)), false); } - + WasteNotLandTriggeredAbility(final WasteNotLandTriggeredAbility ability) { super(ability); } - + @Override public WasteNotLandTriggeredAbility copy() { return new WasteNotLandTriggeredAbility(this); @@ -130,7 +129,7 @@ class WasteNotLandTriggeredAbility extends TriggeredAbilityImpl { public boolean checkEventType(GameEvent event, Game game) { return event.getType() == EventType.DISCARDED_CARD; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(this.getControllerId()).contains(event.getPlayerId())) { @@ -141,7 +140,7 @@ class WasteNotLandTriggeredAbility extends TriggeredAbilityImpl { } return false; } - + @Override public String getRule() { return "Whenever an opponent discards a land card, add {B}{B} to your mana pool."; @@ -149,15 +148,15 @@ class WasteNotLandTriggeredAbility extends TriggeredAbilityImpl { } class WasteNotOtherTriggeredAbility extends TriggeredAbilityImpl { - + WasteNotOtherTriggeredAbility() { super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false); } - + WasteNotOtherTriggeredAbility(final WasteNotOtherTriggeredAbility ability) { super(ability); } - + @Override public WasteNotOtherTriggeredAbility copy() { return new WasteNotOtherTriggeredAbility(this); @@ -167,7 +166,7 @@ class WasteNotOtherTriggeredAbility extends TriggeredAbilityImpl { public boolean checkEventType(GameEvent event, Game game) { return event.getType() == EventType.DISCARDED_CARD; } - + @Override public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(this.getControllerId()).contains(event.getPlayerId())) { @@ -178,9 +177,9 @@ class WasteNotOtherTriggeredAbility extends TriggeredAbilityImpl { } return false; } - + @Override public String getRule() { return "Whenever an opponent discards a noncreature, nonland card, draw a card."; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/AspiringAeronaut.java b/Mage.Sets/src/mage/sets/magicorigins/AspiringAeronaut.java index 4af2005c38..c05f943cc9 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/AspiringAeronaut.java +++ b/Mage.Sets/src/mage/sets/magicorigins/AspiringAeronaut.java @@ -53,9 +53,9 @@ public class AspiringAeronaut extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - + // When Aspiring Aeronaut enters the battlefield, put a 1/1 colorless Thopter artifact creature token with flying onto the battlefield. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken("ORI")))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken()))); } public AspiringAeronaut(final AspiringAeronaut card) { diff --git a/Mage.Sets/src/mage/sets/magicorigins/FoundryOfTheConsuls.java b/Mage.Sets/src/mage/sets/magicorigins/FoundryOfTheConsuls.java index 954e9edf44..d6b8561812 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/FoundryOfTheConsuls.java +++ b/Mage.Sets/src/mage/sets/magicorigins/FoundryOfTheConsuls.java @@ -44,7 +44,7 @@ import mage.game.permanent.token.ThopterColorlessToken; /** * * @author LoneFox - + * */ public class FoundryOfTheConsuls extends CardImpl { @@ -55,8 +55,8 @@ public class FoundryOfTheConsuls extends CardImpl { // {T}: Add {1} to your mana pool. this.addAbility(new ColorlessManaAbility()); // {5}, {T}, Sacrifice Foundry of the Consuls: Put two 1/1 colorless Thopter artifact creature tokens with flying onto the battlefield. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken("ORI"), 2), - new ManaCostsImpl("{5}")); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken(), 2), + new ManaCostsImpl("{5}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/sets/magicorigins/GideonsPhalanx.java b/Mage.Sets/src/mage/sets/magicorigins/GideonsPhalanx.java index fe0af645a1..58afd8bc82 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/GideonsPhalanx.java +++ b/Mage.Sets/src/mage/sets/magicorigins/GideonsPhalanx.java @@ -79,7 +79,7 @@ public class GideonsPhalanx extends CardImpl { class GideonsPhalanxKnightToken extends Token { public GideonsPhalanxKnightToken() { - super("Soldier", "2/2 white Knight creature tokens with vigilance"); + super("Knight", "2/2 white Knight creature tokens with vigilance"); this.setOriginalExpansionSetCode("ORI"); cardType.add(CardType.CREATURE); color.setColor(ObjectColor.WHITE); diff --git a/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java b/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java index 025ce20611..6a1aa70c7c 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java +++ b/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java @@ -66,10 +66,10 @@ public class HangarbackWalker extends CardImpl { // Hangarback Walker enters the battlefield with X +1/+1 counters on it. this.addAbility(new EntersBattlefieldAbility(new HangarbackWalkerEffect(), "with X +1/+1 counters on it")); - + // When Hangarback Walker dies, put a 1/1 colorless Thopter artifact creature token with flying onto the battlefield for each +1/+1 counter on Hangarback Walker. - this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken("ORI"), new CountersCount(CounterType.P1P1)), false)); - + this.addAbility(new DiesTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken(), new CountersCount(CounterType.P1P1)), false)); + // {1}, {t}: Put a +1/+1 counter on Hangarback Walker. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); @@ -88,33 +88,33 @@ public class HangarbackWalker extends CardImpl { class HangarbackWalkerEffect extends OneShotEffect { - public HangarbackWalkerEffect() { - super(Outcome.BoostCreature); - staticText = "{this} enters the battlefield with X +1/+1 counters on it"; - } + public HangarbackWalkerEffect() { + super(Outcome.BoostCreature); + staticText = "{this} enters the battlefield with X +1/+1 counters on it"; + } - public HangarbackWalkerEffect(final HangarbackWalkerEffect effect) { - super(effect); - } + public HangarbackWalkerEffect(final HangarbackWalkerEffect effect) { + super(effect); + } - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - Object obj = getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility) { - int amount = ((SpellAbility)obj).getManaCostsToPay().getX(); - if (amount > 0) { - permanent.addCounters(CounterType.P1P1.createInstance(amount), game); - } + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + Object obj = getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (obj != null && obj instanceof SpellAbility) { + int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + if (amount > 0) { + permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } } - return true; } + return true; + } - @Override - public HangarbackWalkerEffect copy() { - return new HangarbackWalkerEffect(this); - } + @Override + public HangarbackWalkerEffect copy() { + return new HangarbackWalkerEffect(this); + } - } \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/JaceTelepathUnbound.java b/Mage.Sets/src/mage/sets/magicorigins/JaceTelepathUnbound.java index a90cad9b16..32b4489ce8 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/JaceTelepathUnbound.java +++ b/Mage.Sets/src/mage/sets/magicorigins/JaceTelepathUnbound.java @@ -50,6 +50,7 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.counters.CounterType; +import mage.filter.FilterSpell; import mage.filter.common.FilterInstantOrSorceryCard; import mage.game.Game; import mage.game.command.Emblem; @@ -212,7 +213,7 @@ class JaceTelepathUnboundEmblem extends Emblem { this.setName("Emblem - Jace"); Effect effect = new PutTopCardOfLibraryIntoGraveTargetEffect(5); effect.setText("target opponent puts the top five cards of his or her library into his or her graveyard"); - Ability ability = new SpellCastControllerTriggeredAbility(effect, false); + Ability ability = new SpellCastControllerTriggeredAbility(Zone.COMMAND, effect, new FilterSpell("a spell"), false, false); ability.addTarget(new TargetOpponent()); getAbilities().add(ability); } diff --git a/Mage.Sets/src/mage/sets/magicorigins/LilianaHereticalHealer.java b/Mage.Sets/src/mage/sets/magicorigins/LilianaHereticalHealer.java index a3a6bc156b..265fa04b4e 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/LilianaHereticalHealer.java +++ b/Mage.Sets/src/mage/sets/magicorigins/LilianaHereticalHealer.java @@ -77,7 +77,7 @@ public class LilianaHereticalHealer extends CardImpl { // Whenever another nontoken creature you control dies, exile Liliana Heretical Healer, then return her to the battlefield transformed under her owner's control. If you do, put a 2/2 black Zombie creature token onto the battlefield. this.addAbility(new DiesCreatureTriggeredAbility(new ExileAndReturnTransformedSourceEffect(ExileAndReturnTransformedSourceEffect.Gender.FEMAL, - new CreateTokenEffect(new ZombieToken(expansionSetCode))), false, filter)); + new CreateTokenEffect(new ZombieToken())), false, filter)); } public LilianaHereticalHealer(final LilianaHereticalHealer card) { diff --git a/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java b/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java index ff93fac461..6f256623cd 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java +++ b/Mage.Sets/src/mage/sets/magicorigins/NissaSageAnimist.java @@ -65,10 +65,10 @@ public class NissaSageAnimist extends CardImpl { this.expansionSetCode = "ORI"; this.subtype.add("Nissa"); this.color.setGreen(true); - + this.nightCard = true; this.canTransform = true; - + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(3)), false)); // +1: Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand. @@ -95,21 +95,21 @@ public class NissaSageAnimist extends CardImpl { } class NissaSageAnimistPlusOneEffect extends OneShotEffect { - + NissaSageAnimistPlusOneEffect() { super(Outcome.Benefit); this.staticText = "Reveal the top card of your library. If it's a land card, put it onto the battlefield. Otherwise, put it into your hand."; } - + NissaSageAnimistPlusOneEffect(final NissaSageAnimistPlusOneEffect effect) { super(effect); } - + @Override public NissaSageAnimistPlusOneEffect copy() { return new NissaSageAnimistPlusOneEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); @@ -195,4 +195,4 @@ class NissaSageAnimistMinusSevenEffect extends ContinuousEffectImpl { public boolean hasLayer(Layer layer) { return layer == Layer.TypeChangingEffects_4 || layer == Layer.PTChangingEffects_7; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/PiaAndKiranNalaar.java b/Mage.Sets/src/mage/sets/magicorigins/PiaAndKiranNalaar.java index f6e8eff77f..a0d055231c 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/PiaAndKiranNalaar.java +++ b/Mage.Sets/src/mage/sets/magicorigins/PiaAndKiranNalaar.java @@ -61,11 +61,11 @@ public class PiaAndKiranNalaar extends CardImpl { this.toughness = new MageInt(2); // When Pia and Kiran Nalaar enters the battlefield put 2 1/1 colorless Thopter artifact creature tokens with flying onto the battlefield. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken("ORI"), 2))); - + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ThopterColorlessToken(), 2))); + // {2}{R}, Sacrifice an artifact: Pia and Kiran Nalaar deals 2 damage to target creature or player. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new ManaCostsImpl("{2}{R}")); - ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(1,1, new FilterControlledArtifactPermanent("an artifact"),true))); + ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(1, 1, new FilterControlledArtifactPermanent("an artifact"), true))); ability.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability); } @@ -78,4 +78,4 @@ public class PiaAndKiranNalaar extends CardImpl { public PiaAndKiranNalaar copy() { return new PiaAndKiranNalaar(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/ThopterSpyNetwork.java b/Mage.Sets/src/mage/sets/magicorigins/ThopterSpyNetwork.java index d5df94f6bc..b56f9b7c0d 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/ThopterSpyNetwork.java +++ b/Mage.Sets/src/mage/sets/magicorigins/ThopterSpyNetwork.java @@ -56,7 +56,7 @@ public class ThopterSpyNetwork extends CardImpl { // At the beginning of your upkeep, if you control an artifact, put a 1/1 colorless Thopter artifact creature token with flying onto the battlefield. this.addAbility(new ThopterSpyNetworkUpkeepTriggeredAbility()); - + // Whenever one or more artifact creatures you control deals combat damage to a player, draw a card. this.addAbility(new ThopterSpyNetworkDamageTriggeredAbility()); } @@ -74,7 +74,7 @@ public class ThopterSpyNetwork extends CardImpl { class ThopterSpyNetworkUpkeepTriggeredAbility extends TriggeredAbilityImpl { public ThopterSpyNetworkUpkeepTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken("ORI"), 1), false); + super(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken(), 1), false); } public ThopterSpyNetworkUpkeepTriggeredAbility(final ThopterSpyNetworkUpkeepTriggeredAbility ability) { @@ -98,7 +98,7 @@ class ThopterSpyNetworkUpkeepTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkInterveningIfClause(Game game) { - return game.getBattlefield().countAll(new FilterArtifactPermanent(), this.controllerId, game) >= 1; + return game.getBattlefield().countAll(new FilterArtifactPermanent(), this.controllerId, game) >= 1; } @Override @@ -108,7 +108,7 @@ class ThopterSpyNetworkUpkeepTriggeredAbility extends TriggeredAbilityImpl { } class ThopterSpyNetworkDamageTriggeredAbility extends TriggeredAbilityImpl { - + List damagedPlayerIds = new ArrayList<>(); public ThopterSpyNetworkDamageTriggeredAbility() { @@ -127,7 +127,7 @@ class ThopterSpyNetworkDamageTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.DAMAGED_PLAYER - || event.getType() == GameEvent.EventType.END_COMBAT_STEP_POST; + || event.getType() == GameEvent.EventType.END_COMBAT_STEP_POST; } @Override @@ -135,14 +135,14 @@ class ThopterSpyNetworkDamageTriggeredAbility extends TriggeredAbilityImpl { if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { if (((DamagedPlayerEvent) event).isCombatDamage()) { Permanent creature = game.getPermanent(event.getSourceId()); - if (creature != null && creature.getControllerId().equals(controllerId) - && creature.getCardType().contains(CardType.ARTIFACT) && !damagedPlayerIds.contains(event.getTargetId())) { - damagedPlayerIds.add(event.getTargetId()); - return true; + if (creature != null && creature.getControllerId().equals(controllerId) + && creature.getCardType().contains(CardType.ARTIFACT) && !damagedPlayerIds.contains(event.getTargetId())) { + damagedPlayerIds.add(event.getTargetId()); + return true; } } } - if (event.getType().equals(GameEvent.EventType.END_COMBAT_STEP_POST)){ + if (event.getType().equals(GameEvent.EventType.END_COMBAT_STEP_POST)) { damagedPlayerIds.clear(); } return false; @@ -152,4 +152,4 @@ class ThopterSpyNetworkDamageTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { return "Whenever one or more artifact creatures you control deals combat damage to a player, draw a card"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java b/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java index de8bbce496..559d024821 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java +++ b/Mage.Sets/src/mage/sets/magicorigins/UndeadServant.java @@ -59,7 +59,7 @@ public class UndeadServant extends CardImpl { this.toughness = new MageInt(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. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken(expansionSetCode), new CardsInControllerGraveyardCount(filter)))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken(), new CardsInControllerGraveyardCount(filter)))); } public UndeadServant(final UndeadServant card) { diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/NestedGhoul.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/NestedGhoul.java index 6751f451c2..c28f1a4610 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/NestedGhoul.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/NestedGhoul.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.mirrodinbesieged; import java.util.UUID; @@ -47,7 +46,7 @@ import mage.game.permanent.token.ZombieToken; */ public class NestedGhoul extends CardImpl { - public NestedGhoul (UUID ownerId) { + public NestedGhoul(UUID ownerId) { super(ownerId, 48, "Nested Ghoul", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.expansionSetCode = "MBS"; this.subtype.add("Zombie"); @@ -58,7 +57,7 @@ public class NestedGhoul extends CardImpl { this.addAbility(new NestedGhoulTriggeredAbility()); } - public NestedGhoul (final NestedGhoul card) { + public NestedGhoul(final NestedGhoul card) { super(card); } @@ -70,8 +69,9 @@ public class NestedGhoul extends CardImpl { } class NestedGhoulTriggeredAbility extends TriggeredAbilityImpl { + NestedGhoulTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken("MBS"))); + super(Zone.BATTLEFIELD, new CreateTokenEffect(new ZombieToken())); } NestedGhoulTriggeredAbility(final NestedGhoulTriggeredAbility ability) { @@ -97,4 +97,4 @@ class NestedGhoulTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { return "Whenever a source deals damage to {this}, put a 2/2 black Zombie creature token onto the battlefield."; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/planechase2012/BeetlebackChief.java b/Mage.Sets/src/mage/sets/planechase2012/BeetlebackChief.java index f1b2cb90f9..a4c631a622 100644 --- a/Mage.Sets/src/mage/sets/planechase2012/BeetlebackChief.java +++ b/Mage.Sets/src/mage/sets/planechase2012/BeetlebackChief.java @@ -28,12 +28,12 @@ package mage.sets.planechase2012; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.game.permanent.token.GoblinToken; /** @@ -52,7 +52,7 @@ public class BeetlebackChief extends CardImpl { this.toughness = new MageInt(2); // When Beetleback Chief enters the battlefield, put two 1/1 red Goblin creature tokens onto the battlefield. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new GoblinToken(expansionSetCode), 2))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new GoblinToken(), 2))); } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/KuldothaRebirth.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/KuldothaRebirth.java index 0def5d46f3..f5e1c2d714 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/KuldothaRebirth.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/KuldothaRebirth.java @@ -25,33 +25,32 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.scarsofmirrodin; -import mage.constants.CardType; -import mage.constants.Rarity; +import java.util.UUID; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.permanent.token.GoblinToken; import mage.target.common.TargetControlledPermanent; -import java.util.UUID; - /** * * @author Loki */ public class KuldothaRebirth extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledPermanent("an artifact"); static { filter.add(new CardTypePredicate(CardType.ARTIFACT)); } - public KuldothaRebirth (UUID ownerId) { + public KuldothaRebirth(UUID ownerId) { super(ownerId, 96, "Kuldotha Rebirth", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{R}"); this.expansionSetCode = "SOM"; @@ -59,7 +58,7 @@ public class KuldothaRebirth extends CardImpl { this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledPermanent(filter))); } - public KuldothaRebirth (final KuldothaRebirth card) { + public KuldothaRebirth(final KuldothaRebirth card) { super(card); } @@ -68,4 +67,4 @@ public class KuldothaRebirth extends CardImpl { return new KuldothaRebirth(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/shardsofalara/ArchdemonOfUnx.java b/Mage.Sets/src/mage/sets/shardsofalara/ArchdemonOfUnx.java index 9d490cb6f3..4ab86cd587 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/ArchdemonOfUnx.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/ArchdemonOfUnx.java @@ -51,10 +51,11 @@ import mage.game.permanent.token.ZombieToken; public class ArchdemonOfUnx extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Zombie creature"); + static { filter.add(Predicates.not(new SubtypePredicate("Zombie"))); } - + public ArchdemonOfUnx(UUID ownerId) { super(ownerId, 64, "Archdemon of Unx", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{B}{B}"); this.expansionSetCode = "ALA"; @@ -69,7 +70,7 @@ public class ArchdemonOfUnx extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of your upkeep, sacrifice a non-Zombie creature, then put a 2/2 black Zombie creature token onto the battlefield. Ability ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeControllerEffect(filter, 1, ""), TargetController.YOU, false); - ability.addEffect(new CreateTokenEffect(new ZombieToken("ALA"))); + ability.addEffect(new CreateTokenEffect(new ZombieToken())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/shardsofalara/DragonFodder.java b/Mage.Sets/src/mage/sets/shardsofalara/DragonFodder.java index c1b33de673..3e6a4f5989 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/DragonFodder.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/DragonFodder.java @@ -28,10 +28,10 @@ package mage.sets.shardsofalara; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.game.permanent.token.GoblinToken; /** diff --git a/Mage.Sets/src/mage/sets/stronghold/MoggInfestation.java b/Mage.Sets/src/mage/sets/stronghold/MoggInfestation.java index b408d3a3d5..3082cf3210 100644 --- a/Mage.Sets/src/mage/sets/stronghold/MoggInfestation.java +++ b/Mage.Sets/src/mage/sets/stronghold/MoggInfestation.java @@ -31,7 +31,6 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenTargetEffect; import mage.cards.CardImpl; import mage.constants.CardType; @@ -83,14 +82,14 @@ class MoggInfestationEffect extends OneShotEffect { @Override public MoggInfestationEffect copy() { - return new MoggInfestationEffect(this); + return new MoggInfestationEffect(this); } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null && getTargetPointer().getFirst(game, source) != null) { - for (Permanent permanent: game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), getTargetPointer().getFirst(game, source), game)) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), getTargetPointer().getFirst(game, source), game)) { if (permanent.destroy(source.getSourceId(), game, false)) { Effect effect = new CreateTokenTargetEffect(new GoblinToken(), 2); effect.setTargetPointer(getTargetPointer()); diff --git a/Mage.Sets/src/mage/sets/timespiral/EmptyTheWarrens.java b/Mage.Sets/src/mage/sets/timespiral/EmptyTheWarrens.java index 5397da90d2..54433fa976 100644 --- a/Mage.Sets/src/mage/sets/timespiral/EmptyTheWarrens.java +++ b/Mage.Sets/src/mage/sets/timespiral/EmptyTheWarrens.java @@ -28,11 +28,11 @@ package mage.sets.timespiral; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.StormAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; import mage.game.permanent.token.GoblinToken; /** @@ -45,7 +45,6 @@ public class EmptyTheWarrens extends CardImpl { super(ownerId, 152, "Empty the Warrens", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{R}"); this.expansionSetCode = "TSP"; - // Put two 1/1 red Goblin creature tokens onto the battlefield. this.getSpellAbility().addEffect(new CreateTokenEffect(new GoblinToken(), 2)); // Storm diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/BattlefieldThaumaturgeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/BattlefieldThaumaturgeTest.java new file mode 100644 index 0000000000..a779b7e5ee --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/BattlefieldThaumaturgeTest.java @@ -0,0 +1,299 @@ +package org.mage.test.cards.cost.modification; + +import mage.abilities.keyword.HexproofAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.game.permanent.Permanent; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * Battlefield Thaumaturge: + * Creature - Human Wizard + * Each instant and sorcery spell you cast costs {1} less to cast for each creature it targets. + * Heroic - Whenever you cast a spell that targets Battlefield Thaumaturge, Battlefield Thaumaturge gains hexproof until end of turn. + * + * @author Simown + */ +public class BattlefieldThaumaturgeTest extends CardTestPlayerBase { + + @Test + public void testSingleTargetReduction() { + + addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + addCard(Zone.BATTLEFIELD, playerA, "Island"); + addCard(Zone.HAND, playerA, "Lightning Strike"); + + addCard(Zone.BATTLEFIELD, playerB, "Akroan Skyguard"); + + // Lightning Strike - {1}{R} - Lightning Strike deals 3 damage to target creature or player. + // Because Battlefield Thaumaturge is on the battlefield, and the creature is targeted by the + // Lightning Strike it will be payable with {R}. + castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Strike", "Akroan Skyguard"); + setStopAt(2, PhaseStep.END_TURN); + execute(); + + // PlayerA still has the Battlefield Thaumaturge + assertPermanentCount(playerA, "Battlefield Thaumaturge", 1); + // The Akroan Skyguard has been killed by the Lightning Strike + assertPermanentCount(playerB, "Akroan Skyguard", 0); + assertGraveyardCount(playerB, "Akroan Skyguard", 1); + + // Check {R} has been used to pay, and the other land remains untapped + assertTappedCount("Mountain", true, 1); + assertTappedCount("Island", false, 1); + } + + @Test + public void testStriveTargetingReduction1() { + + addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + addCard(Zone.BATTLEFIELD, playerA, "Pharika's Chosen"); + addCard(Zone.HAND, playerA, "Silence the Believers"); + + addCard(Zone.BATTLEFIELD, playerB, "Battlewise Hoplite"); + /** + * Silence the Believers - {2}{B}{B} + * Exile any number of target creatures and all Auras attached to them + * Strive - Silence the Believers costs {2}{B} more to cast for each target beyond the first. + * Targetting a creature on both sides of the battlefield. + */ + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Silence the Believers", "Pharika's Chosen^Battlewise Hoplite"); + setStopAt(2, PhaseStep.END_TURN); + execute(); + + // Both creatures were exiled + assertExileCount("Pharika's Chosen", 1); + assertExileCount("Battlewise Hoplite", 1); + // Not still on the battlefield or in the graveyard + assertPermanentCount(playerA, "Pharika's Chosen", 0); + assertPermanentCount(playerB, "Battlewise Hoplite", 0); + assertGraveyardCount(playerA, "Pharika's Chosen", 0); + assertGraveyardCount(playerB, "Battlewise Hoplite", 0); + + /* Cost to exile 2 permanents will be: + * + {2}{B}{B} for the base spell + * + {2}{B} for an additional target + * - {2} for Battlefield Thaumaturge cost reducing effect + * = {2}{B}{B}{B} to pay. + */ + // Check 3 Swamps have been tapped to pay the reduced cost + assertTappedCount("Swamp", true, 3); + // And 2 Forests for the colorless mana + assertTappedCount("Forest", true, 2); + // And the rest of the Forests remain untapped + assertTappedCount("Forest", false, 2); + } + + @Test + public void testStriveTargetingReduction2() { + + String [] creatures = {"Battlefield Thaumaturge", "Agent of Horizons", "Blood-Toll Harpy", "Anvilwrought Raptor", "Fleshmad Steed" }; + for(String creature : creatures) { + addCard(Zone.BATTLEFIELD, playerA, creature); + } + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + addCard(Zone.HAND, playerA, "Launch the Fleet"); + + // Launch the Fleet - {W} + // Strive - Launch the Fleet costs {1} more to cast for each target beyond the first. + // Until end of turn, any number of target creatures each gain "Whenever this creature attacks, put a 1/1 white Soldier token onto the battlefield tapped and attacking." + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Launch the Fleet", createTargetingString(creatures)); + for(String creature : creatures) { + attack(3, playerA, creature); + } + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + // 5 initial creatures + 5 soldier tokens + 6 lands + assertPermanentCount(playerA, 16); + // The initial creatures exist + for(String creature : creatures) { + assertPermanentCount(playerA, creature, 1); + } + // Each has a solider token generated while attacking + assertPermanentCount(playerA, "Soldier", 5); + // Battlefield Thaumaturge will have hexproof from heroic trigger + Permanent battlefieldThaumaturge = getPermanent("Battlefield Thaumaturge", playerA.getId()); + Assert.assertTrue("Battlefield Thaumaturge must have hexproof", battlefieldThaumaturge.getAbilities().contains(HexproofAbility.getInstance())); + + assertLife(playerA, 20); + // 5 initial creatures + 5 soldier tokens => 16 damage + assertLife(playerB, 4); + /* Cost to have 5 attackers generate soldier tokens + * + {W} for the base spell + * + {4} for an additional targets + * - {4} for Battlefield Thaumaturge cost reducing effect (reduce {1} per target) + * = {W} to pay. + */ + assertTappedCount("Plains", true, 1); + // No other mana has been tapped to pay costs + assertTappedCount("Island", false, 5); + } + + @Test + public void testVariableCostReduction() { + addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); + addCard(Zone.HAND, playerA, "Curse of the Swine"); + + String [] opponentsCreatures = {"Fleecemane Lion", "Sedge Scorpion", "Boon Satyr", "Bronze Sable"}; + for(String creature: opponentsCreatures) { + addCard(Zone.BATTLEFIELD, playerB, creature); + } + + /* Curse of the Swine - {X}{U}{U} + * Exile X target creatures. For each creature exiled this way, + * its controller puts a 2/2 green Boar creature token onto the battlefield + */ + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curse of the Swine"); + setChoice(playerA, "X=4"); + addTarget(playerA, createTargetingString(opponentsCreatures)); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + // All the opponents creatures have been exiled from the battlefield + for(String creature: opponentsCreatures) { + assertPermanentCount(playerB, creature, 0); + assertGraveyardCount(playerB, creature, 0); + assertExileCount(creature, 1); + } + + // All 4 creatures have been replaced by boars + assertPermanentCount(playerB, "Boar", 4); + + /* Cost to target 4 permanents will be: + * + {4}{U}{U} for the base spell with X = 4 + * - {4} for Battlefield Thaumaturge cost reducing effect as 4 creatures are targetted + * = {U}{U} to pay. + */ + // Check 2 islands have been tapped to pay the reduced cost + assertTappedCount("Island", true, 2); + // And the rest of the lands remain untapped + assertTappedCount("Plains", false, 4); + } + + @Test + public void testMutipleTargetReduction() { + + String [] playerACreatures = {"Battlefield Thaumaturge", "Sedge Scorpion", "Boon Satyr"}; + String [] playerBCreatures = {"Agent of Horizons", "Blood-Toll Harpy", "Anvilwrought Raptor"}; + + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4); + // Creatures for player A + for(String creature: playerACreatures) { + addCard(Zone.BATTLEFIELD, playerA, creature); + } + addCard(Zone.HAND, playerA, "Descent of the Dragons"); + // Creatures for player B + for(String creature: playerBCreatures) { + addCard(Zone.BATTLEFIELD, playerB, creature); + } + /* Descent of the Dragons - {4}{R}{R} + * Destroy any number of target creatures. + * For each creature destroyed this way, its controller puts a 4/4 red Dragon creature token with flying onto the battlefield. + * Battlefield Thaumaturge should reduce the cost of the spell when cast, before he is destroyed and replaced with a dragon. + */ + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Descent of the Dragons", createTargetingString(playerACreatures) + "^" + createTargetingString(playerBCreatures)); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + // All creatures have been put in the graveyard + for(String creature: playerACreatures) { + assertPermanentCount(playerA, creature, 0); + assertGraveyardCount(playerA, creature, 1); + } + for(String creature: playerBCreatures) { + assertPermanentCount(playerB, creature, 0); + assertGraveyardCount(playerB, creature, 1); + } + + // And each player has 3 dragons + assertPermanentCount(playerA, "Dragon", 3); + assertPermanentCount(playerB, "Dragon", 3); + + /* Cost to target 6 creatures will be + * + {4}{R}{R} for the fixed cost base spell + * - {4} for Battlefield Thaumaturge cost reducing effect + * each creature targeted will reduce the cost by {1} so the cost + * can only be reduced by {4} maximum using Battlefield Thaumaturge + * even though 6 creatures are targeted. + * = {R}{R} to pay. + */ + // Check 2 mountains have been tapped to pay the reduced cost + assertTappedCount("Mountain", true, 2); + // And the rest of the lands remain untapped + assertTappedCount("Swamp", false, 4); + } + + @Test + public void testTargetNonCreature() { + + addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Zone.HAND, playerA, "Fade into Antiquity"); + + addCard(Zone.BATTLEFIELD, playerB, "Heliod, God of the Sun"); + + // Fade into Antiquity - Sorcery - {2}{G} - Exile target artifact or enchantment. + // Battlefield Thaumaturge only reduces the cost instants and sorceries where the target is a creature + // No cost reduction for targeting an enchantment (devotion is too low for Heliod to be a creature) + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fade into Antiquity", "Heliod, God of the Sun"); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + // PlayerA still has the Battlefield Thaumaturge + assertPermanentCount(playerA, "Battlefield Thaumaturge", 1); + // Heliod has been exiled + assertPermanentCount(playerB, "Heliod, God of the Sun", 0); + assertGraveyardCount(playerB, "Heliod, God of the Sun", 0); + assertExileCount("Heliod, God of the Sun", 1); + + // Expect full amount paid, i.e. all lands are tapped. Cost was not reduced by Battlefield Thaumaturge, no creature was targeted. + assertTappedCount("Forest", true, 3); + } + + @Test + public void testTargetWithAura() { + + addCard(Zone.BATTLEFIELD, playerA, "Battlefield Thaumaturge"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); + addCard(Zone.HAND, playerA, "Spectra Ward"); + + // Spectra Ward - {3}{W}{W} - Aura + // Enchanted creature gets +2/+2 and has protection from all colors. This effect doesn't remove auras. + // Battlefield Thaumaturge only reduces the cost instants and sorceries targeting creatures. + // No cost reduction for targeting a creature with an Aura. + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Spectra Ward", "Battlefield Thaumaturge"); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Battlefield Thaumaturge", 1); + assertPermanentCount(playerA, "Spectra Ward", 1); + // Battlefield Thaumaturge will have hexproof from heroic trigger + Permanent battlefieldThaumaturge = getPermanent("Battlefield Thaumaturge", playerA.getId()); + Assert.assertTrue("Battlefield Thaumaturge must have hexproof", battlefieldThaumaturge.getAbilities().contains(HexproofAbility.getInstance())); + + // No cost reduction from Battlefield Thaumaturge, full amount paid + assertTappedCount("Plains", true, 5); + } + + private String createTargetingString(String [] targets) { + StringBuilder targetBuilder = new StringBuilder(); + for (String target : targets) { + if (targetBuilder.length() > 0) { + targetBuilder.append('^'); + } + targetBuilder.append(target); + } + return targetBuilder.toString(); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 331f42e4fe..25b40da186 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -711,6 +711,28 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement Assert.assertEquals("(Battlefield) Tapped state is not equal (" + cardName + ")", tapped, found.isTapped()); } + /** + * Assert whether X permanents of the same name are tapped or not. + * + * @param cardName Name of the permanent that should be checked. + * @param tapped Whether the permanent is tapped or not + * @param count The amount of this permanents that should be tapped + */ + public void assertTappedCount(String cardName, boolean tapped, int count) throws AssertionError { + int tappedAmount = 0; + Permanent found = null; + for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) { + if (permanent.getName().equals(cardName)) { + if(permanent.isTapped() == tapped) { + tappedAmount++; + } + found = permanent; + } + } + Assert.assertNotNull("There is no such permanent on the battlefield, cardName=" + cardName, found); + Assert.assertEquals("(Battlefield) " + count + " permanents (" + cardName + ") are not " + ((tapped) ? "" : "un") + "tapped.", count, tappedAmount); + } + /** * Assert whether a permanent is attacking or not * diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ManaUtilTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/ManaUtilTest.java index 07bc006edf..49ee45f089 100644 --- a/Mage.Tests/src/test/java/org/mage/test/utils/ManaUtilTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/utils/ManaUtilTest.java @@ -66,6 +66,22 @@ public class ManaUtilTest extends CardTestPlayerBase { testManaToPayVsLand("{W/R}{R/G}", "Sacred Foundry", 2, 2); // can't auto choose to pay } + @Test + public void testManaCondensing() { + Assert.assertEquals("{5}{W}", ManaUtil.condenseManaCostString(("{1}{1}{1}{2}{W}"))); + Assert.assertEquals("{4}{B}{B}", ManaUtil.condenseManaCostString("{2}{B}{2}{B}")); + Assert.assertEquals("{6}{R}{R}{R}{U}", ManaUtil.condenseManaCostString("{R}{1}{R}{2}{R}{3}{U}")); + Assert.assertEquals("{5}{B}{U}{W}", ManaUtil.condenseManaCostString("{1}{B}{W}{4}{U}")); + Assert.assertEquals("{8}{B}{G}{G}{U}", ManaUtil.condenseManaCostString("{1}{G}{1}{2}{3}{G}{B}{U}{1}")); + Assert.assertEquals("{3}{R}{U}", ManaUtil.condenseManaCostString("{3}{R}{U}")); + Assert.assertEquals("{10}", ManaUtil.condenseManaCostString("{1}{2}{3}{4}")); + Assert.assertEquals("{B}{G}{R}{U}{W}", ManaUtil.condenseManaCostString("{B}{G}{R}{U}{W}")); + Assert.assertEquals("{R}{R}", ManaUtil.condenseManaCostString("{R}{R}")); + Assert.assertEquals("{U}", ManaUtil.condenseManaCostString("{U}")); + Assert.assertEquals("{2}", ManaUtil.condenseManaCostString("{2}")); + Assert.assertEquals("", ManaUtil.condenseManaCostString("")); + } + /** * Common way to test ManaUtil.tryToAutoPay * @@ -133,4 +149,5 @@ public class ManaUtilTest extends CardTestPlayerBase { } return useableAbilities; } + } diff --git a/Mage/src/mage/abilities/abilityword/StriveAbility.java b/Mage/src/mage/abilities/abilityword/StriveAbility.java index 404933fde2..cc7c57bd04 100644 --- a/Mage/src/mage/abilities/abilityword/StriveAbility.java +++ b/Mage/src/mage/abilities/abilityword/StriveAbility.java @@ -39,6 +39,7 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.target.Target; +import mage.util.ManaUtil; /** * @@ -50,7 +51,7 @@ public class StriveAbility extends SimpleStaticAbility { private final String striveCost; public StriveAbility(String manaString) { - super(Zone.STACK, new StriveCostIncreasementEffect(new ManaCostsImpl(manaString))); + super(Zone.STACK, new StriveCostIncreasingEffect(new ManaCostsImpl(manaString))); setRuleAtTheTop(true); this.striveCost = manaString; } @@ -71,29 +72,32 @@ public class StriveAbility extends SimpleStaticAbility { } } -class StriveCostIncreasementEffect extends CostModificationEffectImpl { +class StriveCostIncreasingEffect extends CostModificationEffectImpl { private ManaCostsImpl striveCosts = null; - public StriveCostIncreasementEffect(ManaCostsImpl striveCosts) { + public StriveCostIncreasingEffect(ManaCostsImpl striveCosts) { super(Duration.WhileOnStack, Outcome.Benefit, CostModificationType.INCREASE_COST); this.striveCosts = striveCosts; } - protected StriveCostIncreasementEffect(StriveCostIncreasementEffect effect) { + protected StriveCostIncreasingEffect(StriveCostIncreasingEffect effect) { super(effect); this.striveCosts = effect.striveCosts; } @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - // Target target = abilityToModify.getTargets().get(0); for (Target target : abilityToModify.getTargets()) { if (target.getMaxNumberOfTargets() == Integer.MAX_VALUE) { int additionalTargets = target.getTargets().size() - 1; + StringBuilder sb = new StringBuilder(); for (int i = 0; i < additionalTargets; i++) { - abilityToModify.getManaCostsToPay().add(striveCosts.copy()); + // Build up a string of strive costs for each target + sb.append(striveCosts.getText()); } + String finalCost = ManaUtil.condenseManaCostString(sb.toString()); + abilityToModify.getManaCostsToPay().add(new ManaCostsImpl(finalCost)); return true; } } @@ -106,7 +110,7 @@ class StriveCostIncreasementEffect extends CostModificationEffectImpl { } @Override - public StriveCostIncreasementEffect copy() { - return new StriveCostIncreasementEffect(this); + public StriveCostIncreasingEffect copy() { + return new StriveCostIncreasingEffect(this); } } diff --git a/Mage/src/mage/abilities/effects/common/CreateTokenEffect.java b/Mage/src/mage/abilities/effects/common/CreateTokenEffect.java index ee32ab0e86..00c9dbd3a3 100644 --- a/Mage/src/mage/abilities/effects/common/CreateTokenEffect.java +++ b/Mage/src/mage/abilities/effects/common/CreateTokenEffect.java @@ -1,39 +1,40 @@ /* -* 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.effects.common; import java.util.ArrayList; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.token.Token; @@ -51,6 +52,7 @@ public class CreateTokenEffect extends OneShotEffect { private boolean attacking; private UUID lastAddedTokenId; private ArrayList lastAddedTokenIds = new ArrayList<>(); + private boolean expansionSetCodeChecked; public CreateTokenEffect(Token token) { this(token, new StaticValue(1)); @@ -63,7 +65,7 @@ public class CreateTokenEffect extends OneShotEffect { public CreateTokenEffect(Token token, DynamicValue amount) { this(token, amount, false, false); } - + public CreateTokenEffect(Token token, int amount, boolean tapped, boolean attacking) { this(token, new StaticValue(amount), tapped, attacking); } @@ -74,6 +76,7 @@ public class CreateTokenEffect extends OneShotEffect { this.amount = amount.copy(); this.tapped = tapped; this.attacking = attacking; + this.expansionSetCodeChecked = false; setText(); } @@ -85,6 +88,7 @@ public class CreateTokenEffect extends OneShotEffect { this.attacking = effect.attacking; this.lastAddedTokenId = effect.lastAddedTokenId; this.lastAddedTokenIds.addAll(effect.lastAddedTokenIds); + this.expansionSetCodeChecked = effect.expansionSetCodeChecked; } @Override @@ -94,6 +98,9 @@ public class CreateTokenEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + if (!expansionSetCodeChecked) { + updateExpansionSetCode(game, source); + } int value = amount.calculate(game, source, this); token.putOntoBattlefield(value, game, source.getSourceId(), source.getControllerId(), tapped, attacking); this.lastAddedTokenId = token.getLastAddedToken(); @@ -101,10 +108,18 @@ public class CreateTokenEffect extends OneShotEffect { return true; } + private void updateExpansionSetCode(Game game, Ability source) { + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject instanceof Card) { + token.setExpansionSetCodeForImage(((Card) sourceObject).getExpansionSetCode()); + } + expansionSetCodeChecked = true; + } + public UUID getLastAddedTokenId() { return lastAddedTokenId; } - + public ArrayList getLastAddedTokenIds() { return lastAddedTokenIds; } diff --git a/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java b/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java index 6fe7a0a697..6e99909a49 100644 --- a/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java +++ b/Mage/src/mage/abilities/effects/common/ExileAndReturnTransformedSourceEffect.java @@ -60,7 +60,7 @@ public class ExileAndReturnTransformedSourceEffect extends OneShotEffect { // Creature has to be on the battlefield to get exiled and be able to return transformed Permanent sourceObject = game.getPermanent(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); - if (sourceObject != null && controller != null) { + if (sourceObject != null && controller != null && sourceObject.getZoneChangeCounter(game) == source.getSourceObjectZoneChangeCounter()) { Card card = (Card) sourceObject; if (controller.moveCards(card, Zone.BATTLEFIELD, Zone.EXILED, source, game)) { Player owner = game.getPlayer(card.getOwnerId()); diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index 1706ac1fea..db25e8f955 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.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.cards; import java.lang.reflect.Constructor; @@ -74,13 +73,14 @@ import mage.watchers.Watcher; import org.apache.log4j.Logger; public abstract class CardImpl extends MageObjectImpl implements Card { + private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(CardImpl.class); protected UUID ownerId; protected int cardNumber; - protected String expansionSetCode; + public String expansionSetCode; protected String tokenSetCode; protected Rarity rarity; protected boolean canTransform; @@ -108,16 +108,15 @@ public abstract class CardImpl extends MageObjectImpl implements Card { Ability ability = new PlayLandAbility(name); ability.setSourceId(this.getId()); abilities.add(ability); - } - else { + } else { SpellAbility ability = new SpellAbility(manaCost, name, Zone.HAND, spellAbilityType); if (!cardType.contains(CardType.INSTANT)) { ability.setTiming(TimingRule.SORCERY); } ability.setSourceId(this.getId()); - abilities.add(ability); + abilities.add(ability); } - this.usesVariousArt = Character.isDigit(this.getClass().getName().charAt(this.getClass().getName().length()-1)); + this.usesVariousArt = Character.isDigit(this.getClass().getName().charAt(this.getClass().getName().length() - 1)); this.morphCard = false; } @@ -206,8 +205,12 @@ public abstract class CardImpl extends MageObjectImpl implements Card { game.getState().getCardState(objectId).addInfo(key, value); } - protected static final ArrayList rulesError = new ArrayList() {{add("Exception occured in rules generation");}}; - + protected static final ArrayList rulesError = new ArrayList() { + { + add("Exception occured in rules generation"); + } + }; + @Override public List getRules() { try { @@ -217,7 +220,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } return rulesError; } - + @Override public List getRules(Game game) { try { @@ -228,7 +231,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { for (String data : cardState.getInfo().values()) { rules.add(data); } - for (Ability ability: cardState.getAbilities()) { + for (Ability ability : cardState.getAbilities()) { rules.add(ability.getRule()); } } @@ -243,6 +246,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { /** * Gets all base abilities - does not include additional abilities added by * other cards or effects + * * @return A list of {@link Ability} - this collection is modifiable */ @Override @@ -251,9 +255,10 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } /** - * Gets all current abilities - includes additional abilities added by - * other cards or effects - * @param game + * Gets all current abilities - includes additional abilities added by other + * cards or effects + * + * @param game * @return A list of {@link Ability} - this collection is not modifiable */ @Override @@ -265,28 +270,28 @@ public abstract class CardImpl extends MageObjectImpl implements Card { Abilities all = new AbilitiesImpl<>(); all.addAll(abilities); all.addAll(otherAbilities); - return all; + return all; } protected void addAbility(Ability ability) { ability.setSourceId(this.getId()); abilities.add(ability); - for (Ability subAbility: ability.getSubAbilities()) { + for (Ability subAbility : ability.getSubAbilities()) { abilities.add(subAbility); } } protected void addAbilities(List abilities) { - for (Ability ability: abilities) { + for (Ability ability : abilities) { addAbility(ability); } } - + protected void addAbility(Ability ability, Watcher watcher) { addAbility(ability); ability.addWatcher(watcher); } - + @Override public SpellAbility getSpellAbility() { if (spellAbility == null) { @@ -322,9 +327,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card { public List getMana() { List mana = new ArrayList<>(); for (ManaAbility ability : this.abilities.getManaAbilities(Zone.BATTLEFIELD)) { - for (Mana netMana: ability.getNetMana(null)) { + for (Mana netMana : ability.getNetMana(null)) { mana.add(netMana); - } + } } return mana; } @@ -357,14 +362,14 @@ public abstract class CardImpl extends MageObjectImpl implements Card { game.getPlayer(ownerId).getSideboard().remove(this); break; case COMMAND: - game.getState().getCommand().remove((Commander)game.getObject(objectId)); + game.getState().getCommand().remove((Commander) game.getObject(objectId)); break; case STACK: StackObject stackObject = game.getStack().getSpell(getId()); if (stackObject == null && (this instanceof SplitCard)) { // handle if half od Split cast is on the stack - stackObject = game.getStack().getSpell(((SplitCard)this).getLeftHalfCard().getId()); + stackObject = game.getStack().getSpell(((SplitCard) this).getLeftHalfCard().getId()); if (stackObject == null) { - stackObject = game.getStack().getSpell(((SplitCard)this).getRightHalfCard().getId()); + stackObject = game.getStack().getSpell(((SplitCard) this).getRightHalfCard().getId()); } } if (stackObject != null) { @@ -379,12 +384,12 @@ public abstract class CardImpl extends MageObjectImpl implements Card { logger.fatal(new StringBuilder("Invalid from zone [").append(fromZone) .append("] for card [").append(this.getName()) .append("] to zone [").append(toZone) - .append("] source [").append(sourceCard != null ? sourceCard.getName():"null").append("]").toString()); + .append("] source [").append(sourceCard != null ? sourceCard.getName() : "null").append("]").toString()); break; } game.rememberLKI(objectId, event.getFromZone(), this); } - + setFaceDown(false, game); updateZoneChangeCounter(game); switch (event.getToZone()) { @@ -406,8 +411,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { case LIBRARY: if (flag) { game.getPlayer(ownerId).getLibrary().putOnTop(this, game); - } - else { + } else { game.getPlayer(ownerId).getLibrary().putOnBottom(this, game); } break; @@ -428,9 +432,9 @@ public abstract class CardImpl extends MageObjectImpl implements Card { default: Card sourceCard = game.getCard(sourceId); logger.fatal(new StringBuilder("Invalid to zone [").append(toZone) - .append("] for card [").append(this.getName()) - .append("] to zone [").append(toZone) - .append("] source [").append(sourceCard != null ? sourceCard.getName():"null").append("]").toString()); + .append("] for card [").append(this.getName()) + .append("] to zone [").append(toZone) + .append("] source [").append(sourceCard != null ? sourceCard.getName() : "null").append("]").toString()); return false; } game.setZone(objectId, event.getToZone()); @@ -462,12 +466,12 @@ public abstract class CardImpl extends MageObjectImpl implements Card { case OUTSIDE: game.getPlayer(ownerId).getSideboard().remove(mainCard); break; - + case COMMAND: - game.getState().getCommand().remove((Commander)game.getObject(mainCard.getId())); + game.getState().getCommand().remove((Commander) game.getObject(mainCard.getId())); break; default: - //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone()); + //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone()); } game.rememberLKI(mainCard.getId(), event.getFromZone(), this); } @@ -479,6 +483,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } return false; } + @Override public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { return moveToExile(exileId, name, sourceId, game, null); @@ -514,7 +519,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { break; default: MageObject object = game.getObject(sourceId); - logger.warn(new StringBuilder("moveToExile, not fully implemented: from = ").append(fromZone).append(" - ").append(object != null ? object.getName():"null")); + logger.warn(new StringBuilder("moveToExile, not fully implemented: from = ").append(fromZone).append(" - ").append(object != null ? object.getName() : "null")); } game.rememberLKI(objectId, event.getFromZone(), this); } @@ -537,19 +542,19 @@ public abstract class CardImpl extends MageObjectImpl implements Card { public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId) { return this.putOntoBattlefield(game, fromZone, sourceId, controllerId, false, false, null); } - + @Override - public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped){ + public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped) { return this.putOntoBattlefield(game, fromZone, sourceId, controllerId, tapped, false, null); } @Override - public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown){ + public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown) { return this.putOntoBattlefield(game, fromZone, sourceId, controllerId, tapped, facedown, null); } - - @Override - public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, ArrayList appliedEffects){ + + @Override + public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, ArrayList appliedEffects) { ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, controllerId, fromZone, Zone.BATTLEFIELD, appliedEffects, tapped); if (facedown) { this.setFaceDown(true, game); @@ -582,7 +587,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { removed = true; break; default: - logger.warn("putOntoBattlefield, not fully implemented: fromZone="+fromZone); + logger.warn("putOntoBattlefield, not fully implemented: fromZone=" + fromZone); } game.rememberLKI(objectId, event.getFromZone(), this); if (!removed) { @@ -601,7 +606,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { permanent.entersBattlefield(sourceId, game, event.getFromZone(), true); game.setScopeRelevant(false); game.applyEffects(); - game.addSimultaneousEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD)); + game.addSimultaneousEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD)); return true; } if (facedown) { @@ -625,7 +630,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { GameEvent event = GameEvent.getEvent(GameEvent.EventType.TURNFACEUP, getId(), playerId); if (!game.replaceEvent(event)) { setFaceDown(false, game); - for (Ability ability :abilities) { // abilities that were set to not visible face down must be set to visible again + for (Ability ability : abilities) { // abilities that were set to not visible face down must be set to visible again if (ability.getWorksFaceDown() && !ability.getRuleVisible()) { ability.setRuleVisible(true); } @@ -678,7 +683,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card { } @Override - public void build() {} + public void build() { + } @Override public boolean getUsesVariousArt() { diff --git a/Mage/src/mage/game/command/Emblem.java b/Mage/src/mage/game/command/Emblem.java index 3321f3ead7..35b35b1a4c 100644 --- a/Mage/src/mage/game/command/Emblem.java +++ b/Mage/src/mage/game/command/Emblem.java @@ -1,30 +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.game.command; import java.util.ArrayList; @@ -86,7 +86,7 @@ public class Emblem implements CommandObject { } public void setControllerId(UUID controllerId) { - this.controllerId = controllerId; + this.controllerId = controllerId; this.abilites.setControllerId(controllerId); } @@ -101,9 +101,9 @@ public class Emblem implements CommandObject { @Override public String getIdName() { - return getName() + " ["+getId().toString().substring(0,3) +"]"; + return getName() + " [" + getId().toString().substring(0, 3) + "]"; } - + @Override public String getLogName() { return GameLog.getColoredObjectIdName(this); @@ -170,13 +170,16 @@ public class Emblem implements CommandObject { } @Override - public void adjustChoices(Ability ability, Game game) {} + public void adjustChoices(Ability ability, Game game) { + } @Override - public void adjustCosts(Ability ability, Game game) {} + public void adjustCosts(Ability ability, Game game) { + } @Override - public void adjustTargets(Ability ability, Game game) {} + public void adjustTargets(Ability ability, Game game) { + } @Override public UUID getId() { @@ -207,7 +210,7 @@ public class Emblem implements CommandObject { @Override public int getZoneChangeCounter(Game game) { - throw new UnsupportedOperationException("Unsupported operation"); + return 1; // Emblems can't move zones until now so return always 1 } @Override @@ -219,5 +222,5 @@ public class Emblem implements CommandObject { public void setZoneChangeCounter(int value, Game game) { throw new UnsupportedOperationException("Unsupported operation"); } - + } diff --git a/Mage/src/mage/game/permanent/token/BeastToken.java b/Mage/src/mage/game/permanent/token/BeastToken.java index f5d9b98a54..761f5e03c7 100644 --- a/Mage/src/mage/game/permanent/token/BeastToken.java +++ b/Mage/src/mage/game/permanent/token/BeastToken.java @@ -1,35 +1,35 @@ /* -* 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.permanent.token; +import java.util.Arrays; +import java.util.Random; import mage.MageInt; -import mage.ObjectColor; import mage.constants.CardType; /** @@ -39,24 +39,24 @@ import mage.constants.CardType; public class BeastToken extends Token { public BeastToken() { - this("LRW"); - } - public BeastToken(String setCode) { - this(setCode, Integer.MIN_VALUE); - } - - public BeastToken(String setCode, int tokenType) { super("Beast", "3/3 green Beast creature token"); - setOriginalExpansionSetCode(setCode); - if (tokenType != Integer.MIN_VALUE) { - setTokenType(tokenType); - } + availableImageSetCodes.addAll(Arrays.asList("C14", "LRW", "M15", "M14", "DDL", "M13", "M12")); cardType.add(CardType.CREATURE); color.setGreen(true); subtype.add("Beast"); power = new MageInt(3); toughness = new MageInt(3); - + } + @Override + public void setExpansionSetCodeForImage(String code) { + super.setExpansionSetCodeForImage(code); + if (getOriginalExpansionSetCode().equals("C14")) { + this.setTokenType(new Random().nextInt(2) + 1); + } + if (getOriginalExpansionSetCode().equals("M15")) { + this.setTokenType(2); + } + } } diff --git a/Mage/src/mage/game/permanent/token/ElfToken.java b/Mage/src/mage/game/permanent/token/ElfToken.java index 11807debd7..256c67e8cc 100644 --- a/Mage/src/mage/game/permanent/token/ElfToken.java +++ b/Mage/src/mage/game/permanent/token/ElfToken.java @@ -1,33 +1,33 @@ /* -* 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.permanent.token; +import java.util.Arrays; import mage.MageInt; import mage.constants.CardType; @@ -39,6 +39,7 @@ public class ElfToken extends Token { public ElfToken() { super("Elf Warrior", "1/1 green Elf Warrior creature token"); + availableImageSetCodes.addAll(Arrays.asList("C14", "SHM", "EVG", "LRW", "ORI")); cardType.add(CardType.CREATURE); color.setGreen(true); subtype.add("Elf"); @@ -47,4 +48,11 @@ public class ElfToken extends Token { toughness = new MageInt(1); } + @Override + public void setExpansionSetCodeForImage(String code) { + super.setExpansionSetCodeForImage(code); + if (getOriginalExpansionSetCode().equals("SHM")) { + this.setTokenType(1); + } + } } diff --git a/Mage/src/mage/game/permanent/token/GoblinToken.java b/Mage/src/mage/game/permanent/token/GoblinToken.java index 6b37933e5d..ffbbac6b0a 100644 --- a/Mage/src/mage/game/permanent/token/GoblinToken.java +++ b/Mage/src/mage/game/permanent/token/GoblinToken.java @@ -28,8 +28,6 @@ package mage.game.permanent.token; import java.util.Arrays; -import java.util.List; -import java.util.Random; import mage.MageInt; import mage.constants.CardType; @@ -39,22 +37,10 @@ import mage.constants.CardType; */ public class GoblinToken extends Token { - static List imageSetCodes = Arrays.asList( - "M10", "C14", "KTK", "EVG", "DTK" - ); - public GoblinToken() { - this(imageSetCodes.get(new Random().nextInt(imageSetCodes.size()))); - } - - public GoblinToken(String originalExpansionSetCode) { super("Goblin", "1/1 red Goblin creature token"); - if (!imageSetCodes.contains(originalExpansionSetCode)) { - this.setOriginalExpansionSetCode(imageSetCodes.get(new Random().nextInt(imageSetCodes.size()))); - } else { - this.setOriginalExpansionSetCode(originalExpansionSetCode); - } - + availableImageSetCodes.addAll(Arrays.asList("SOM", "M10", "C14", "KTK", "EVG", "DTK", "ORI")); + cardType.add(CardType.CREATURE); subtype.add("Goblin"); diff --git a/Mage/src/mage/game/permanent/token/ThopterColorlessToken.java b/Mage/src/mage/game/permanent/token/ThopterColorlessToken.java index a75c83ff0c..81135864b5 100644 --- a/Mage/src/mage/game/permanent/token/ThopterColorlessToken.java +++ b/Mage/src/mage/game/permanent/token/ThopterColorlessToken.java @@ -27,6 +27,8 @@ */ package mage.game.permanent.token; +import java.util.Arrays; +import java.util.Random; import mage.MageInt; import mage.abilities.keyword.FlyingAbility; import mage.constants.CardType; @@ -38,12 +40,8 @@ import mage.constants.CardType; public class ThopterColorlessToken extends Token { public ThopterColorlessToken() { - this("EXO"); - } - - public ThopterColorlessToken(String expansionSetCode) { super("Thopter", "1/1 colorless Thopter artifact creature token with flying"); - this.setOriginalExpansionSetCode(expansionSetCode); + availableImageSetCodes.addAll(Arrays.asList("EXO", "ORI")); cardType.add(CardType.ARTIFACT); cardType.add(CardType.CREATURE); subtype.add("Thopter"); @@ -53,4 +51,11 @@ public class ThopterColorlessToken extends Token { addAbility(FlyingAbility.getInstance()); } + @Override + public void setExpansionSetCodeForImage(String code) { + super.setExpansionSetCodeForImage(code); + if (getOriginalExpansionSetCode().equals("ORI")) { + this.setTokenType(new Random().nextInt(2) + 1); + } + } } diff --git a/Mage/src/mage/game/permanent/token/Token.java b/Mage/src/mage/game/permanent/token/Token.java index 48d99e43df..9e4906947a 100644 --- a/Mage/src/mage/game/permanent/token/Token.java +++ b/Mage/src/mage/game/permanent/token/Token.java @@ -1,35 +1,35 @@ /* -* 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.permanent.token; import java.util.ArrayList; import java.util.List; +import java.util.Random; import java.util.UUID; import mage.MageObjectImpl; import mage.ObjectColor; @@ -44,8 +44,6 @@ import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.PermanentToken; import mage.players.Player; -import mage.util.CardUtil; - public class Token extends MageObjectImpl { @@ -56,22 +54,26 @@ public class Token extends MageObjectImpl { private int originalCardNumber; private String originalExpansionSetCode; private Card copySourceCard; // the card the Token is a copy from - + + // list of set codes tokene images are available for + protected List availableImageSetCodes = new ArrayList<>(); + public enum Type { + FIRST(1), SECOND(2); - + int code; - + Type(int code) { - this.code = code; + this.code = code; } - + int getCode() { return this.code; } } - + public Token(String name, String description) { this.name = name; this.description = description; @@ -95,7 +97,7 @@ public class Token extends MageObjectImpl { this.tokenType = token.tokenType; this.lastAddedTokenId = token.lastAddedTokenId; this.lastAddedTokenIds.addAll(token.lastAddedTokenIds); - this.originalCardNumber = token.originalCardNumber; + this.originalCardNumber = token.originalCardNumber; this.originalExpansionSetCode = token.originalExpansionSetCode; this.copySourceCard = token.copySourceCard; // will never be changed } @@ -165,7 +167,7 @@ public class Token extends MageObjectImpl { } if (!game.isSimulation()) { game.informPlayers(controller.getLogName() + " puts a " + newToken.getLogName() + " token onto the battlefield"); - } + } } return true; @@ -207,5 +209,13 @@ public class Token extends MageObjectImpl { } } - + public void setExpansionSetCodeForImage(String code) { + if (availableImageSetCodes.size() > 0) { + if (availableImageSetCodes.contains(code)) { + setOriginalExpansionSetCode(code); + } else { + setOriginalExpansionSetCode(availableImageSetCodes.get(new Random().nextInt(availableImageSetCodes.size()))); + } + } + } } diff --git a/Mage/src/mage/game/permanent/token/ZombieToken.java b/Mage/src/mage/game/permanent/token/ZombieToken.java index e64c978b46..5e716ade6a 100644 --- a/Mage/src/mage/game/permanent/token/ZombieToken.java +++ b/Mage/src/mage/game/permanent/token/ZombieToken.java @@ -1,16 +1,16 @@ /* * 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 @@ -20,14 +20,14 @@ * 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.permanent.token; +import java.util.Arrays; import java.util.Random; import mage.MageInt; import mage.constants.CardType; @@ -39,15 +39,8 @@ import mage.constants.CardType; public class ZombieToken extends Token { public ZombieToken() { - this("10E"); - } - - public ZombieToken(String expansionSetCode) { super("Zombie", "2/2 black Zombie creature token"); - this.setOriginalExpansionSetCode(expansionSetCode); - if (expansionSetCode.equals("ISD")) { - this.setTokenType(new Random().nextInt(3) + 1); - } + availableImageSetCodes.addAll(Arrays.asList("10E", "M10", "M11", "M12", "M13", "M14", "M15", "MBS", "ALA", "ISD", "C14", "CNS", "MMA", "BNG", "KTK", "DTK", "ORI")); cardType.add(CardType.CREATURE); color.setBlack(true); subtype.add("Zombie"); @@ -55,4 +48,12 @@ public class ZombieToken extends Token { toughness = new MageInt(2); } -} \ No newline at end of file + @Override + public void setExpansionSetCodeForImage(String code) { + super.setExpansionSetCodeForImage(code); + if (getOriginalExpansionSetCode().equals("ISD")) { + this.setTokenType(new Random().nextInt(3) + 1); + } + } + +} diff --git a/Mage/src/mage/util/ManaUtil.java b/Mage/src/mage/util/ManaUtil.java index 6b8e006292..d094f807d3 100644 --- a/Mage/src/mage/util/ManaUtil.java +++ b/Mage/src/mage/util/ManaUtil.java @@ -1,9 +1,7 @@ package mage.util; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Set; -import java.util.UUID; +import java.util.*; + import mage.MageObject; import mage.Mana; import mage.ManaSymbol; @@ -379,4 +377,46 @@ public class ManaUtil { return unpaid.getText(); } } + + /** Converts a collection of mana symbols into a single condensed string + * e.g. + * {1}{1}{1}{1}{1}{W} = {5}{W} + * {2}{B}{2}{B}{2}{B} = {6}{B}{B}{B} + * {1}{2}{R}{U}{1}{1} = {5}{R}{U} + * {B}{G}{R} = {B}{G}{R} + * */ + public static String condenseManaCostString(String rawCost) { + int total = 0; + int index = 0; + // Split the string in to an array of numbers and colored mana symbols + String[] splitCost = rawCost.replace("{", "").replace("}", " ").split(" "); + // Sort alphabetically which will push1 the numbers to the front before the colored mana symbols + Arrays.sort(splitCost); + for (String c : splitCost) { + // If the string is a representation of a number + if(c.matches("\\d+")) { + total += Integer.parseInt(c); + } else { + // First non-number we see we can finish as they are sorted + break; + } + index++; + } + int splitCostLength = splitCost.length; + // No need to add {total} to the mana cost if total == 0 + int shift = (total > 0) ? 1 : 0; + String [] finalCost = new String[shift + splitCostLength - index]; + // Account for no colourless mana symbols seen + if(total > 0) { + finalCost[0] = String.valueOf(total); + } + System.arraycopy(splitCost, index, finalCost, shift, splitCostLength - index); + // Combine the cost back as a mana string + StringBuilder sb = new StringBuilder(); + for(String s: finalCost) { + sb.append("{" + s + "}"); + } + // Return the condensed string + return sb.toString(); + } }