diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java index 3f245ba9bfc..3e6d0b5628b 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java @@ -166,7 +166,7 @@ public class CardPluginImpl implements CardPlugin { boolean othersOnTheRight = true; if (options != null && options.containsKey("nonLandPermanentsInOnePile")) { if (options.get("nonLandPermanentsInOnePile").equals("true")) { - System.out.println("in one pile"); +// System.out.println("in one pile"); othersOnTheRight = false; allCreatures.addAll(allOthers); allOthers.clear(); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java index 31cc12a6684..c8b2fe3eb6c 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java @@ -49,7 +49,7 @@ public class WizardCardsImageSource implements CardImageSource { Document doc = Jsoup.connect("http://www.wizards.com/magic/tcg/article.aspx?x=mtg/tcg/" + (String) setsAliases.get(cardSet)).get(); Elements cardsImages = doc.select("img[height$=370]"); for (int i = 0; i < cardsImages.size(); i++) { - String cardName = cardsImages.get(i).attr("title").replace("\u00C6", "AE").replace("’", "'"); + String cardName = cardsImages.get(i).attr("title").replace("\u00C6", "AE").replace("\u2019", "'"); if (cardName != null && !cardName.isEmpty()) { if (cardName.equals("Forest") || cardName.equals("Swamp") || cardName.equals("Mountain") || cardName.equals("Island") || cardName.equals("Plains")) { int landNumber = 1; diff --git a/Mage.Client/src/main/resources/avatars/special/4.gif b/Mage.Client/src/main/resources/avatars/special/4.gif index 46df44d8045..257752d549b 100644 Binary files a/Mage.Client/src/main/resources/avatars/special/4.gif and b/Mage.Client/src/main/resources/avatars/special/4.gif differ diff --git a/Mage.Common/src/mage/remote/Session.java b/Mage.Common/src/mage/remote/Session.java index 7f72e9972c9..0b4251a9090 100644 --- a/Mage.Common/src/mage/remote/Session.java +++ b/Mage.Common/src/mage/remote/Session.java @@ -135,8 +135,8 @@ public class Session { callbackClient = new Client(clientLocator, "callback", clientMetadata); Map listenerMetadata = new HashMap(); - listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "5000"); - listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "2000"); + listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_PERIOD, "10000"); + listenerMetadata.put(ConnectionValidator.VALIDATOR_PING_TIMEOUT, "9000"); callbackClient.connect(new ClientConnectionListener(), listenerMetadata); Map callbackMetadata = new HashMap(); @@ -184,6 +184,7 @@ public class Session { if (connection == null) return; try { + callbackClient.disconnect(); TransporterClient.destroyTransporterClient(server); } catch (Throwable ex) { diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java index f15c6e5dc23..9b317d1a399 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java @@ -56,5 +56,7 @@ public class Standard extends Constructed { setCodes.add(set.getCode()); } } + banned.add("Jace, the Mind Sculptor"); + banned.add("Stoneforge Mystic"); } } diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java index 134d4b87708..f19206c4369 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Vintage.java @@ -38,5 +38,64 @@ public class Vintage extends Constructed { public Vintage() { super("Constructed - Vintage"); + + banned.add("Amulet of Quoz"); + banned.add("Bronze Tablet"); + banned.add("Chaos Orb"); + banned.add("Contract from Below"); + banned.add("Darkpact"); + banned.add("Demonic Attorney"); + banned.add("Falling Star"); + banned.add("Jeweled Bird"); + banned.add("Rebirth"); + banned.add("Shahrazad"); + banned.add("Tempest Efreet"); + banned.add("Timmerian Fiends"); + + restricted.add("Ancestral Recall"); + restricted.add("Balance"); + restricted.add("Black Lotus"); + restricted.add("Brainstorm"); + restricted.add("Burning Wish"); + restricted.add("Channel"); + restricted.add("Demonic Consultation"); + restricted.add("Demonic Tutor"); + restricted.add("Fact or Fiction"); + restricted.add("Fastbond"); + restricted.add("Flash"); + restricted.add("Gifts Ungiven"); + restricted.add("Imperial Seal"); + restricted.add("Library of Alexandria"); + restricted.add("Lion's Eye Diamond"); + restricted.add("Lotus Petal"); + restricted.add("Mana Crypt"); + restricted.add("Mana Vault"); + restricted.add("Memory Jar"); + restricted.add("Merchant Scroll"); + restricted.add("Mind's Desire"); + restricted.add("Mox Emerald"); + restricted.add("Mox Jet"); + restricted.add("Mox Pearl"); + restricted.add("Mox Ruby"); + restricted.add("Mox Sapphire"); + restricted.add("Mystical Tutor"); + restricted.add("Necropotence"); + restricted.add("Ponder"); + restricted.add("Regrowth"); + restricted.add("Sol Ring"); + restricted.add("Strip Mine"); + restricted.add("Thirst for Knowledge"); + restricted.add("Time Vault"); + restricted.add("Time Walk"); + restricted.add("Timetwister"); + restricted.add("Tinker"); + restricted.add("Tolarian Academy"); + restricted.add("Trinisphere"); + restricted.add("Vampiric Tutor"); + restricted.add("Wheel of Fortune"); + restricted.add("Windfall"); + restricted.add("Yawgmoth's Bargain"); + restricted.add("Yawgmoth's Will"); + } } diff --git a/Mage.Server/plugins/mage-deck-constructed.jar b/Mage.Server/plugins/mage-deck-constructed.jar index 1223483690f..54befdbed1b 100644 Binary files a/Mage.Server/plugins/mage-deck-constructed.jar and b/Mage.Server/plugins/mage-deck-constructed.jar differ diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index e48219bdf40..4d2bcabc4ff 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -88,7 +88,7 @@ public class ChatManager { } } - void removeUser(UUID userId) { + public void removeUser(UUID userId) { for (ChatSession chat: chatSessions.values()) { chat.kill(userId); } diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 8a782381775..c99199b4726 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -131,10 +131,12 @@ public class Session { } public void disconnect() { + logger.info("session disconnected for user " + userId); UserManager.getInstance().disconnect(userId); } public void kill() { + logger.info("session killed for user " + userId); UserManager.getInstance().removeUser(userId); } diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index d062cdb06c1..5b63a16ab01 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -67,7 +67,7 @@ public class SessionManager { Session session = sessions.get(sessionId); if (session != null) { session.registerUser(userName); - logger.info("User " + userName + " connected from " + session.getHost()); + logger.info("User " + userName + " connected from " + session.getHost() + " sessionId: " + sessionId); return true; } return false; @@ -94,13 +94,16 @@ public class SessionManager { public synchronized void disconnect(String sessionId, boolean voluntary) { Session session = sessions.get(sessionId); + sessions.remove(sessionId); if (session != null) { if (voluntary) session.kill(); else session.disconnect(); - sessions.remove(sessionId); } + else { + logger.info("could not find session with id " + sessionId); + } } public Map getSessions() { diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index fb549c212cb..dfdb9e15ecc 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -470,6 +470,8 @@ public class TableController { } public boolean isOwner(UUID userId) { + if (userId == null) + return false; return userId.equals(this.userId); } diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index c5c593e9cd9..875ddbff9d8 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -41,6 +41,7 @@ import mage.server.game.GameManager; import mage.server.game.GameSession; import mage.server.tournament.TournamentSession; import mage.view.TableClientMessage; +import org.apache.log4j.Logger; /** * @@ -48,7 +49,9 @@ import mage.view.TableClientMessage; */ public class User { - public enum UserState { + private final static Logger logger = Logger.getLogger(User.class); + + public enum UserState { Created, Connected, Disconnected, Reconnected; } @@ -92,13 +95,16 @@ public class User { public void setSessionId(String sessionId) { this.sessionId = sessionId; - if (sessionId.isEmpty()) + if (sessionId.isEmpty()) { userState = UserState.Disconnected; - else if (userState == UserState.Created) + logger.info("User " + userName + " disconnected"); + } else if (userState == UserState.Created) { userState = UserState.Connected; - else { + logger.info("User " + userName + " created"); + } else { userState = UserState.Reconnected; reconnect(); + logger.info("User " + userName + " reconnected"); } } diff --git a/Mage.Server/src/main/java/mage/server/UserManager.java b/Mage.Server/src/main/java/mage/server/UserManager.java index b9f9b2560ce..5776ebbe3ca 100644 --- a/Mage.Server/src/main/java/mage/server/UserManager.java +++ b/Mage.Server/src/main/java/mage/server/UserManager.java @@ -35,8 +35,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import mage.players.net.UserData; import mage.view.ChatMessage.MessageColor; +import org.apache.log4j.Logger; /** * @@ -50,6 +50,7 @@ public class UserManager { protected static ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor(); private final static UserManager INSTANCE = new UserManager(); + private final static Logger logger = Logger.getLogger(UserManager.class); public static UserManager getInstance() { return INSTANCE; @@ -99,7 +100,9 @@ public class UserManager { } public void disconnect(UUID userId) { + ChatManager.getInstance().removeUser(userId); if (users.containsKey(userId)) { + logger.info("user disconnected " + userId); users.get(userId).setSessionId(""); ChatManager.getInstance().broadcast(userId, "has lost connection", MessageColor.BLACK); } @@ -114,6 +117,7 @@ public class UserManager { public void removeUser(UUID userId) { if (users.containsKey(userId)) { + logger.info("user removed" + userId); users.get(userId).setSessionId(""); ChatManager.getInstance().broadcast(userId, "has disconnected", MessageColor.BLACK); users.get(userId).kill(); diff --git a/Mage.Server/src/main/java/mage/server/game/PlayerFactory.java b/Mage.Server/src/main/java/mage/server/game/PlayerFactory.java index 4420d80ba34..90f5a3d552f 100644 --- a/Mage.Server/src/main/java/mage/server/game/PlayerFactory.java +++ b/Mage.Server/src/main/java/mage/server/game/PlayerFactory.java @@ -57,14 +57,20 @@ public class PlayerFactory { Player player; Constructor con; try { - con = playerTypes.get(playerType).getConstructor(new Class[]{String.class, RangeOfInfluence.class, int.class}); - player = (Player)con.newInstance(new Object[] {name, range, skill}); + Class playerTypeClass = playerTypes.get(playerType); + if (playerTypeClass != null) { + con = playerTypeClass.getConstructor(new Class[]{String.class, RangeOfInfluence.class, int.class}); + player = (Player)con.newInstance(new Object[] {name, range, skill}); + logger.info("Player created: " + name + "-" + player.getId().toString()); + return player; + } + else { + logger.fatal("Unknown player type: " + playerType); + } } catch (Exception ex) { logger.fatal("PlayerFactory error ", ex); - return null; } - logger.info("Player created: " + name + "-" + player.getId().toString()); - return player; + return null; } public Set getPlayerTypes() { diff --git a/Mage.Sets/src/mage/sets/innistrad/SkeletalGrimace.java b/Mage.Sets/src/mage/sets/innistrad/SkeletalGrimace.java new file mode 100644 index 00000000000..92782dafbdd --- /dev/null +++ b/Mage.Sets/src/mage/sets/innistrad/SkeletalGrimace.java @@ -0,0 +1,83 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.innistrad; + +import java.util.UUID; +import mage.Constants.AttachmentType; +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.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.effects.common.continious.BoostEnchantedEffect; +import mage.abilities.effects.common.continious.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author North + */ +public class SkeletalGrimace extends CardImpl { + + public SkeletalGrimace(UUID ownerId) { + super(ownerId, 116, "Skeletal Grimace", Rarity.COMMON, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); + this.expansionSetCode = "ISD"; + this.subtype.add("Aura"); + + this.color.setBlack(true); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + // Enchanted creature gets +1/+1 and has "{B}: Regenerate this creature." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield))); + Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{B}")); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA))); + } + + public SkeletalGrimace(final SkeletalGrimace card) { + super(card); + } + + @Override + public SkeletalGrimace copy() { + return new SkeletalGrimace(this); + } +} diff --git a/Mage.Sets/src/mage/sets/newphyrexia/Spellskite.java b/Mage.Sets/src/mage/sets/newphyrexia/Spellskite.java new file mode 100644 index 00000000000..813ff432fda --- /dev/null +++ b/Mage.Sets/src/mage/sets/newphyrexia/Spellskite.java @@ -0,0 +1,127 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.newphyrexia; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Outcome; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetStackObject; +import mage.target.Targets; + +/** + * + * @author BetaSteward + */ +public class Spellskite extends CardImpl { + + public Spellskite(UUID ownerId) { + super(ownerId, 159, "Spellskite", Rarity.RARE, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); + this.expansionSetCode = "NPH"; + this.subtype.add("Horror"); + this.power = new MageInt(0); + this.toughness = new MageInt(4); + + // {UP}: Change a target of target spell or ability to Spellskite. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SpellskiteEffect(), new ManaCostsImpl("{UP}")); + ability.addTarget(new TargetStackObject()); + this.addAbility(ability); + } + + public Spellskite(final Spellskite card) { + super(card); + } + + @Override + public Spellskite copy() { + return new Spellskite(this); + } +} + +class SpellskiteEffect extends OneShotEffect { + + public SpellskiteEffect() { + super(Outcome.Neutral); + staticText = "Change a target of target spell or ability to {this}"; + } + + public SpellskiteEffect(final SpellskiteEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getStack().getSpell(source.getFirstTarget()); + if (spell != null) { + Targets targets = spell.getSpellAbility().getTargets(); + if (targets.size() == 1 && targets.get(0).getTargets().size() == 1) { + targets.get(0).clearChosen(); + targets.get(0).add(source.getSourceId(), game); + } + else { + Player player = game.getPlayer(source.getControllerId()); + for (Target target: targets) { + for (UUID targetId: target.getTargets()) { + MageObject object = game.getObject(targetId); + String name = null; + if (object == null) { + Player targetPlayer = game.getPlayer(targetId); + name = targetPlayer.getName(); + } else { + name = object.getName(); + } + if (name != null && player.chooseUse(Outcome.Neutral, "Change target from " + name + " to {this}?", game)) { + target.remove(targetId); + target.addTarget(source.getSourceId(), source, game); + break; + } + } + } + } + } + return false; + } + + @Override + public SpellskiteEffect copy() { + return new SpellskiteEffect(this); + } + +} \ No newline at end of file diff --git a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java index fd88106e110..07aedce5fea 100644 --- a/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java +++ b/Mage/src/mage/abilities/effects/common/PutOnLibraryTargetEffect.java @@ -74,10 +74,12 @@ public class PutOnLibraryTargetEffect extends OneShotEffect invalid; @@ -47,4 +48,14 @@ public class InvalidDeckException extends MageException { public Map getInvalid() { return invalid; } + + @Override + public String getMessage() { + StringBuilder sb = new StringBuilder(); + sb.append(super.getMessage()).append("\n"); + for (Entry entry: invalid.entrySet()) { + sb.append(entry.getKey()).append(" ").append(entry.getValue()).append("\n"); + } + return sb.toString(); + } } diff --git a/Mage/src/mage/filter/FilterMana.java b/Mage/src/mage/filter/FilterMana.java index a03d18b7258..2836f3f3a91 100644 --- a/Mage/src/mage/filter/FilterMana.java +++ b/Mage/src/mage/filter/FilterMana.java @@ -27,10 +27,12 @@ */ package mage.filter; +import java.io.Serializable; + /** * @author nantuko */ -public class FilterMana { +public class FilterMana implements Serializable { protected boolean black; protected boolean green; diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 4e10b42e289..72629aaa602 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -393,12 +393,18 @@ public abstract class PlayerImpl> implements Player, Ser game.fireInformEvent(name + " discards " + Integer.toString(discardAmount) + " card" + (discardAmount > 1?"s":"")); return; } - for (int i = 0; i < amount; i++) { + int numDiscarded = 0; + while (numDiscarded < amount) { + if (hand.size() == 0) + break; TargetDiscard target = new TargetDiscard(playerId); choose(Outcome.Discard, target, game); - discard(hand.get(target.getFirstTarget(), game), source, game); + Card card = hand.get(target.getFirstTarget(), game); + if (card != null && discard(card, source, game)) { + numDiscarded++; + } } - game.fireInformEvent(name + " discards " + Integer.toString(amount) + " card" + (amount > 1?"s":"")); + game.fireInformEvent(name + " discards " + Integer.toString(numDiscarded) + " card" + (numDiscarded > 1?"s":"")); } @Override @@ -583,7 +589,7 @@ public abstract class PlayerImpl> implements Player, Ser //20091005 - 603.3c, 603.3d int bookmark = game.bookmarkState(); TriggeredAbility ability = (TriggeredAbility) source.copy(); - if (ability.canChooseTarget(game)) { + if (ability != null && ability.canChooseTarget(game)) { game.getStack().push(new StackAbility(ability, playerId)); if (ability.activate(game, false)) { game.removeBookmark(bookmark); diff --git a/Mage/src/mage/target/Target.java b/Mage/src/mage/target/Target.java index 46e351c0b55..182fec71b01 100644 --- a/Mage/src/mage/target/Target.java +++ b/Mage/src/mage/target/Target.java @@ -65,6 +65,7 @@ public interface Target extends Serializable { public Set possibleTargets(UUID sourceControllerId, Game game); public boolean choose(Outcome outcome, UUID playerId, Game game); public void add(UUID id, Game game); + public void remove(UUID targetId); public String getMessage(); public String getTargetName(); diff --git a/Mage/src/mage/target/TargetImpl.java b/Mage/src/mage/target/TargetImpl.java index 2aa054cb7f6..1e8da2c87a8 100644 --- a/Mage/src/mage/target/TargetImpl.java +++ b/Mage/src/mage/target/TargetImpl.java @@ -166,6 +166,12 @@ public abstract class TargetImpl> implements Target { } } } + + @Override + public void remove(UUID id) { + if (targets.containsKey(id)) + targets.remove(id); + } @Override public void addTarget(UUID id, Ability source, Game game) { @@ -213,11 +219,6 @@ public abstract class TargetImpl> implements Target { } chosen = targets.size() >= minNumberOfTargets; } - while (!doneChosing()) { - if (!player.choose(outcome, this, game)) { - break; - } - } return chosen = true; } @@ -231,11 +232,6 @@ public abstract class TargetImpl> implements Target { } chosen = targets.size() >= minNumberOfTargets; } - while (!doneChosing()) { - if (!player.chooseTarget(outcome, this, source, game)) { - break; - } - } return chosen = true; } diff --git a/Utils/ISD.txt b/Utils/ISD.txt new file mode 100644 index 00000000000..5be92835e36 --- /dev/null +++ b/Utils/ISD.txt @@ -0,0 +1,137 @@ +Abbey Griffin|Innistrad|1|C|{3}{W}|Creature - Griffin|2|2|Flying, vigilance| +Angel of Flight Alabaster|Innistrad|2|R|{4}{W}|Creature - Angel|4|4|Flying$At the beginning of your upkeep, return target Spirit card from your graveyard to your hand.| +Angelic Overseer|Innistrad|3|M|{3}{W}{W}|Creature - Angel|5|3|Flying$As long as you control a Human, Angelic Overseer has hexproof and is indestructible.| +Bonds of Faith|Innistrad|5|C|{1}{W}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +2/+2 as long as it's a Human. Otherwise, it can't attack or block.| +Champion of the Parish|Innistrad|6|R|{W}|Creature - Human Soldier|1|1|Whenever another Human enters the battlefield under your control, put a +1/+1 counter on Champion of the Parish.| +Dearly Departed|Innistrad|9|R|{4}{W}{W}|Creature - Spirit|5|5|Flying$As long as Dearly Departed is in your graveyard, each Human creature you control enters the battlefield with an additional +1/+1 counter on it.| +Divine Reckoning|Innistrad|10|R|{2}{W}{W}|Sorcery|||Each player chooses a creature he or she controls. Destroy the rest.$Flashback {5}{W}{W}| +Doomed Traveler|Innistrad|11|C|{W}|Creature - Human Soldier|1|1|When Doomed Traveler dies, put a 1/1 white Spirit creature token with flying onto the battlefield.| +Elite Inquisitor|Innistrad|13|R|{W}{W}|Creature - Human Soldier|2|2|First strike, vigilance$Protection from Vampires, from Werewolves, and from Zombies.| +Fiend Hunter|Innistrad|15|U|{1}{W}{W}|Creature - Human Cleric|1|3|When Fiend Hunter enters the battlefield, you may exile another target creature.$When Fiend Hunter leaves the battlefield, return the exiled card to the battlefield under its owner's control.| +Mentor of the Meek|Innistrad|21|R|{2}{W}|Creature - Human Soldier|2|2|Whenever another creature with power 2 or less enters the battlefield under your control, you may pay {1}. If you do, draw a card.| +Mikaeus, the Lunarch|Innistrad|23|M|{X}{W}|Legendary Creature - Human Cleric|0|0|Mikaeus, the Lunarch enters the battlefield with X +1/+1 counters on it.${T}: Put a +1/+1 counter on Mikaeus.${T}, Remove a +1/+1 counter from Mikaeus: Put a +1/+1 counter on each other creature you control.| +Rally the Peasants|Innistrad|28|U|{2}{W}|Instant|||Creatures you control get +2/+0 until end of turn.$Flashback {2}{R}| +Slayer of the Wicked|Innistrad||U|{3}{W}|Creature - Human Soldier|3|2|When Slayer of the Wicked enters the battlefield, you may destroy target Vampire, Werewolf, or Zombie.| +Spectral Rider|Innistrad||U|{W}{W}|Creature - Spirit Knight|2|2|Intimidate| +Thraben Sentry|Innistrad|38|C|{3}{W}|Creature - Human Soldier|2|2|Vigilance$Whenever another creature you control dies, you may transform Thraben Sentry.| +Thraben Militia|Innistrad|38|C||Creature - Human Soldier|5|4|Trample| +Battleground Geist|Innistrad|45|U|{4}{U}|Creature - Spirit|3|3|Flying$Other Spirit creatures you control get +1/+0.| +Cackling Counterpart|Innistrad|46|R|{1}{U}{U}|Instant|||Put a token onto the battlefield that's a copy of target creature you control.$Flashback {5}{U}{U}| +Civilized Scholar|Innistrad|47|U|{2}{U}|Creature - Human Advisor|0|1|{T}: Draw a card, then discard a card. If a creature card is discarded this way, untap Civilized Scholar, then transform it| +Homicidal Brute|Innistrad|47|U||Human Mutant|5|1|{R}$At the beginning of your end step, if Homicidal Brute didn't attack this turn, tap Homicidal Brute, then transform it.| +Curiosity|Innistrad|49|U|{U}|Enchantment - Aura|||Enchant creature$Whenever enchanted creature deals damage to an opponent, you may draw a card.| +Curse of the Bloody Tome|Innistrad|50|C|{2}{U}|Enchantment - Aura Curse|||Enchant player$At the beginning of enchanted player's upkeep, that player puts the top two cards of his or her library into his or her graveyard.| +Delver of Secrets|Innistrad|51|C|{U}|Creature - Human Wizard|1|1|At the beginning of your upkeep, look at the top card of your library. You may reveal that card. If an instant or sorcery is revealed this way, transform Delver of Secrets.| +Insectile Aberration|Innistrad|51|C||Creature - Human Insect|3|2|Flying| +Deranged Assistant|Innistrad|52|C|{1}{U}|Creature - Human Wizard|1|1|{T}, Put the top card of your library into your graveyard: Add {1} to your mana pool.| +Grasp of Phantoms|Innistrad|58|U|{3}{U}|Sorcery|||Put target creature on top of its owner's library.$Flashback {7}{U}| +Invisible Stalker|Innistrad|60|U|{1}{U}|Creature - Human Rogue|1|1|Hexproof$Invisible Stalker is unblockable.| +Laboratory Maniac|Innistrad|61|R|{2}{U}|Creature - Human Wizard|2|2|If you would draw a card while your library has no cards in it, you win the game instead.| +Ludevic's Test Subject|Innistrad|64|R|{1}{U}|Creature - Lizard|0|3|Defender${1}{U}: Put a hatchling counter on Ludevic's Test Subject. Then if there are five or more hatchling counters on it, remove all of them and transform it.| +Ludevic's Abomination|Innistrad|64|R||Creature - Lizard Horror|13|13|Trample| +Mindshrieker|Innistrad|67|R|{1}{U}|Creature - Spirit Bird|1|1|Flying${2}: Target player puts the top card of his or her library into his or her graveyard. Mindshrieker gets +X/+X until end of turn, where X is that card's converted mana cost.| +Mirror-Mad Phantasm|Innistrad||M|{3}{U}{U}|Creature - Spirit|5|1|Flying${1}{U}: Mirror-Mad Phantasm's owner shuffles it into his or her library. If that player does, he or she reveals cards from the top of that library until a card named Mirror-Mad Phantasm is revealed. That player puts that card onto the battlefield and all other cards revealed this way into his or her graveyard.| +Murder of Crows|Innistrad|70|U|{3}{U}{U}|Creature - Bird|4|4|Flying$Whenever another creature dies, you may draw a card. If you do, discard a card.| +Rooftop Storm|Innistrad|71|R|{5}{U}|Enchantment|||You may pay {0} rather than pay the mana cost for Zombie creature spells you cast.| +Silent Departure|Innistrad|75|C|{U}|Sorcery|||Return target creature to its owner's hand.$Flashback {4}{U}| +Skaab Ruinator|Innistrad|77|M|{1}{U}{U}|Creature - Zombie Horror|5|6|As an additional cost to cast Skaab Ruinator, exile 3 creature cards from your graveyard.$Flying$You may cast Skaab Ruinator from your graveyard.| +Snapcaster Mage|Innistrad||R|{1}{U}|Creature - Human Wizard|2|1|Flash$When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.| +Stitched Drake|Innistrad|80|C|{1}{U}{U}|Creature - Zombie Drake|3|4|As an addition cost to cast Stitched Drake, exile a creature card from your graveyard.$$Flying| +Stitcher's Apprentice|Innistrad|81|C|{1}{U}|Creature - Homunculus|1|2|{1}{U}, {T}: Put a 2/2 blue Homunculus creature token onto the battlefield, then sacrifice a creature.| +Undead Alchemist|Innistrad|84|R|{3}{U}|Creature - Zombie|4|2|If a Zombie you control would deal combat damage to a player, instead that player puts that many cards from the top of his or her library into his or her graveyard.$Whenever a creature card is put into an opponent's graveyard from his or her library, exile that card and put a 2/2 black Zombie creature token onto the battlefield.| +Army of the Damned|Innistrad|87|M|{5}{B}{B}{B}|Sorcery|||Put thirteen 2/2 black Zombie creature tokens onto the battlefield tapped.$Flashback {7}{B}{B}{B}| +Bloodgift Demon|Innistrad|89|R|{3}{B}{B}|Creature - Demon|5|4|Flying$At the beginning of your upkeep, target player draws a card and loses 1 life.| +Bloodline Keeper|Innistrad||R|{2}{B}{B}|Creature - Vampire|3|3|Flying${T}: Put a 2/2 black Vampire creature token with flying onto the battlefield.${B}: Transform Bloodline Keeper.$Activate this ability only if you control five or more vampires.| +Lord of Lineage|Innistrad||R||undefined|5|5|Flying$Other Vampire creatures you control get +2/+2.${T}: Put a 2/2 black Vampire creature token with flying onto the battlefield.| +Bump in the Night|Innistrad|92|C|{B}|Sorcery|||Target opponent loses 3 life.$Flashback {5}{R}| +Curse of Death's Hold|Innistrad|94|R|{3}{B}{B}|Enchantment - Aura Curse|||Enchant Player$Creatures enchanted player controls gets -1/-1.| +Diregraf Ghoul|Innistrad|97|U|{B}|Creature - Zombie|2|2|Diregraf Ghoul enters the battlefield tapped.| +Endless Ranks of the Dead|Innistrad|99|R|{2}{B}{B}|Enchantment|||At the beginning of your upkeep, put X 2/2 black zombie creature tokens onto the battlefield, where X is half the number of the zombies you control, rounded down.| +Liliana of the Veil|Innistrad|105|M|{1}{B}{B}|Planeswalker - Liliana|3|+1: Each player discards a card.$-2: Target player sacrifices a creature.$-6: Separate all permanents target player controls into two piles. That player sacrifices all permanents in the pile of his or her choice.| +Moan of the Unhallowed|Innistrad|109|U|{2}{B}{B}|Sorcery|||Put two 2/2 black Zombie creature tokens onto the battlefield.$Flashback {5}{B}{B}| +Morkrut Banshee|Innistrad|110|U|{3}{B}{B}|Creature - Spirit|4|4|Morbid - When Morkut Banshee enters the battlefield, if a creature died this turn, target creature gets -4/-4 until end of turn.| +Reaper from the Abyss|Innistrad|112|M|{3}{B}{B}{B}|Creature - Demon|6|6|Flying$Morbid - At the beginning of each end step, if a creature died this turn, destroy target non-demon creature.$| +Screeching Bat|Innistrad|114|U|{2}{B}|Creature - Bat|2|2|Flying$$At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform Screeching Bat.| +Stalking Vampire|Innistrad|114|U||Creature - Vampire|5|5|At the beginning of your upkeep, you may pay {2}{B}{B}. If you do, transform Stalking Vampire.| +Skeletal Grimace|Innistrad|116|C|{1}{B}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +1/+1 and has "{B}: Regenerate this creature."| +Skirsdag High Priest|Innistrad|117|R|{1}{B}|Creature - Human Cleric|1|2|Morbid - {T}, tap two untapped creatures you control: Put a 5/5 black Demon creature token with flying onto the battlefield. Activate this ability only if a creature died this turn.| +Vampire Interloper|Innistrad|123|C|{1}{B}|Creature - Vampire Scout|2|1|Flying$Vampire Interloper can't block.| +Village Cannibals|Innistrad||U|{2}{B}|Creature - Human|2|2|Whenever another Human creature dies, put a +1/+1 counter on Village Cannibals.| +Walking Corpse|Innistrad|126|C|{1}{B}|Creature - Zombie|2|2|| +Balefire Dragon|Innistrad||M|{5}{R}{R}|Creature - Dragon|6|6|Flying$Whenever Balefire Dragon deals combat damage to a player, it deals that much damage to each creature that player controls.| +Blasphemous Act|Innistrad||R|{8}{R}|Sorcery|||Blasphemous Act costs {1} less to cast for each creature on the battlefield.$Blasphemous Act deals 13 damage to each creature.| +Bloodcrazed Neonate|Innistrad||C|{1}{R}|Creature - Vampire|2|1|Bloodcrazed Neonate attacks each turn if able. $$Whenever Bloodcrazed Neonate deals combat damage to a player, put a +1/+1 counter on it.| +Brimstone Volley|Innistrad|132|C|{2}{R}|Instant|||Brimstone Volley deals 3 damage to target creature or player.$Morbid - Brimstone Volley deals 5 damage to that creature or player instead if a creature died this turn.| +Curse of Stalked Prey|Innistrad||R|{1}{R}|Enchantment - Aura Curse|||Enchant player$Whenever a creature deals combat damage to enchanted player, put a +1/+1 counter on that creature.| +Devil's Play|Innistrad||R|{X}{R}|Sorcery|||Devil's Play deals X damage to target creature or player.$Flashback {X}{R}{R}{R}| +Falkenrath Marauders|Innistrad||R|{3}{R}{R}|Creature - Vampire Warrior|2|2|Flying, haste$Whenever Falkenrath Marauders deals combat damage to a player, put two +1/+1 counters on it.| +Instigator Gang|Innistrad||R|{3}{R}|Creature - Human Werewolf|2|3|Attacking creatures you control get +1/+0.$At the beginning of each upkeep, if no spells were cast last turn, transform Instigator Gang.| +Wildblood Pack|Innistrad||R||Creature - Werewolf|5|5|Trample$Attacking creatures you control get +3/+0.$At the beginning of each upkeep, if a player cast two or more spells last turn, transform Wildblood Pack.| +Into the Maw of Hell|Innistrad||U|{4}{R}{R}|Sorcery|||Destroy target land. Into the Maw of Hell deals 13 damage to target creature. | +Kruin Outlaw|Innistrad||R|{1}{R}{R}|Creature - Human Rogue Werewolf|2|2|First strike$At the beginning of each upkeep, if no spells were cast last turn, transform Kruin Outlaw.| +Terror of Kruin Pass|Innistrad||R||Creature - Werewolf|3|3|Double strike$Each Werewolf you control can't be blocked except by two or more creatures.$At the beginning of each upkeep, if a player cast two or more spells last turn, transform Terror of Kruin Pass.| +Rakish Heir|Innistrad|158|U|{2}{R}|Creature - Vampire|2|2|Whenever a Vampire you control deals combat damage to a player, put a +1/+1 counter on it.| +Skirsdag Cultist|Innistrad||U|{2}{R}{R}|Creature - Human Shaman|2|2|{R}, {T}, Sacrifice a creature: Skirsdag Cultist deals 2 damage to target creature or player.| +Stromkirk Noble|Innistrad||R|{R}|Creature - Vampire|1|1|Stromkirk Noble can't be blocked by Humans.$When Stromkirk Noble deals combat damage to a player, put a +1/+1 counter on it.| +Tormented Pariah|Innistrad|165|C|{3}{R}|Creature - Human Warrior Werewolf|3|2|At the beginning of each upkeep, if no spells were cast last turn, transform Tormented Pariah.| +Rampaging Werewolf|Innistrad|165|C||Creatue - Werewolf|6|4|At the beginning of each upkeep, if a player cast two or more spells last turn, transform Rampaging Werewolf.| +Village Ironsmith|Innistrad||C|{1}{R}|Creature - Human Werewolf|1|1|First strike$At the beginning of each upkeep, if no spells were cast last turn, transform Village Ironsmith.| +Ironfang|Innistrad||C||Creature - Werewolf|3|1|First strike$At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ironfang.| +Avacyn's Pilgrim|Innistrad|170|C|{G}|Creature - Human Monk|1|1|{T}: Add {W} to your mana pool.| +Boneyard Wurm|Innistrad|171|U|{1}{G}|Creature - Wurm|*|*|Boneyard Wurm's power and toughness are each equal to the number of creature cards in your graveyard.| +Daybreak Ranger|Innistrad|176|R|{2}{G}|Creature - Human Archer Werewolf|2|2|{T}: Daybreak Ranger deals 2 damage to target creature with flying.$At the beginning of each upkeep, if no spells were cast last turn, transform Daybreak Ranger.| +Nightfall Predator|Innistrad|176|R||Creature - Werewolf|4|4|{R}, {T}: Nightfall Predator fights target creature. (Each deals damage equal to its power to the other.)$At the beginning of each upkeep, if a player cast two or more spells last turn, transform Nightfall Predator.| +Essence of the Wild|Innistrad|178|M|{3}{G}{G}{G}|Creature - Avatar|6|6|Creatures you control enter the battlefield as a copy of Essence of the Wild.| +Garruk Relentless|Innistrad|181|M|{3}{G}|Planeswalker - Garruk|3|When Garruk Relentless has two or fewer loyalty counters on him, transform him.$0: Garruk Relentless deals 3 damage to target creature. That creature deals damage equal to its power to him$0: Put a 2/2 green Wolf creature token onto the battlefield.| +Garruk, the Veil-Cursed|Innistrad|181|M||Planeswalker - Garruk|||{bg}$+1 : Put a 1/1 black Wolf creature token with deathtouch onto the battlefield.$-1 : Sacrifice a creature. If you do, search your library for a creature card, reveal it, put it into your hand, then shuffle your library.$-3 : Creatures you control gain trample and get +X/+X until end of turn, where X is the number of creature cards in your graveyard.| +Gatstaf Shepherd|Innistrad|182|U|{1}{G}|Creature - Human Werewolf|2|2|At the beginning of each upkeep, if no spells were cast last turn, transform Gastaf Shepherd.| +Gatstaf Howler|Innistrad|182|U||Creature - Werewolf|3|3|Intimidate$At the beginning of each upkeep, if a player cast two or more spells last turn, transform Gastaf Howler.| +Grizzled Outcasts|Innistrad||C|{4}{G}|Creature - Human Werewolf|4|4|At the beginning of each upkeep, if no spells were cast last turn, transform Grizzled Outcasts.| +Krallenhorde Wantons|Innistrad||C||Creature - Werewolf|7|7|At the beginning of each upkeep, if a player cast two or more spells last turn, transform Krallenhorde Wantons.| +Hollowhenge Scavenger|Innistrad|188|U|{3}{G}{G}|Creature - Elemental|4|5|Morbid - When Hollowhenge Scavenger enters the battlefield, if a creature died this turn, you gain 5 life.| +Kessig Cagebreakers|Innistrad|189|R|{4}{G}|Creature - Human Rogue|3|4|Whenever Kessig Cagebreakers attacks, put a 2/2 green Wolf creature token onto the battlefield tapped and attacking for each creature card in your graveyard.| +Mayor of Avabruck|Innistrad|193|R|{1}{G}|Creature - Human Advisor Werewolf|1|1|Other Human creatures you control get +1/+1.$At the beginning of each upkeep, if no spells were cast last turn, transform Mayor of Avabruck.| +Howlpack Alpha|Innistrad|193|R||Creature - Werewolf|3|3|Other Werewolf and Wolf creatures you control get +1/+1.$$At the beginning of your end step, put a 2/2 green Wolf creature token onto the battlefield.$At the beginning of each upkeep, if a player cast two or more spells last turn, transform Howlpack Alpha.| +Moonmist|Innistrad|195|C|{1}{G}|Instant|||Transform all Humans. Prevent all combat damage that would be dealt this turn by creatures other than Werewolves and Wolves.| +Spider Spawning|Innistrad|203|U|{4}{G}|Sorcery|||Put a 1/2 green Spider creature token with reach onto the battlefield for each creature card in your graveyard.$Flashback {6}{B}| +Spidery Grasp|Innistrad|204|C|{2}{G}|Instant|||Untap target creature. It gets +2/+4 and gains reach until end of turn.| +Prey Upon|Innistrad|208|C|{G}|Sorcery|||Target creature you control fights target creature you don't control.| +Travel Preparations|Innistrad||C|{1}{G}|Sorcery|||Put a +1/+1 counter on each of up to two target creatures.$Flashback {1}{W}| +Ulvenwald Mystics|Innistrad|208|U|{2}{G}{G}|Creature - Human Shaman Werewolf|3|3|At the beginning of each upkeep, if no spells were cast last turn, transform Ulvenwald Mystics.| +Ulvenwald Primordials|Innistrad|208|U||Creature - Werewolf|5|5|{G}: Regenerate Ulvenwald Primordials.$At the beginning of each upkeep, if a player cast two or more spells last turn, transform Ulvenwald Primordials.| +Woodland Sleuth|Innistrad|210|C|{3}{G}|Creature - Human Scout|2|3|Morbid - When woodland sleuth enters the battlefield, if a creature died this turn, return a creature card at random from your graveyard to your hand.| +Wreath of Geists|Innistrad|211|U|{G}|Enchantment - Aura|||Enchant creature$Enchanted creature gets +X/+X, where X is the number of creature cards in your graveyard.| +Evil Twin|Innistrad|212|R|{2}{U}{B}|Creature - Shapeshifter|0|0|You may have Evil Twin enter the battlefield as a copy of any creature on the battlefield except it gains "{U}{B}, {T}: Destroy target creature with the same name as this creature.| +Grimgrin, Corpse-Born|Innistrad|214|M|{3}{U}{B}|Legendary Creaute - Zombie Warrior|5|5|Grimgrin, Corpse-Born enters the battlefield tapped and doesn't untap during your untap step.$Sacrifice another creature: Untap Grimgrin and put a +1/+1 counter on it.$Whenever Grimgrin attacks, destroy target creature defending player controls, then put a +1/+1 counter on Grimgrin.| +Olivia Voldaren|Innistrad|215|M|{2}{B}{R}|Legendary Creature - Vampire|3|3|Flying${1}{R}: Olivia Voldaren deals 1 damage to another target creature. That creature becomes a Vampire in addition to its other types. Put a +1/+1 counter on Olivia Voldaren.${3}{B}{B}: Gain control of target Vampire for as long as you control Olivia Voldaren.| +Blazing Torch|Innistrad|216|C|{1}|Artifact - Equipment|||Equipped creature can't be blocked by Vampires or Zombies.$$Equipped creature has "{T}, Sacrifice Blazing Torch: Blazing Torch deals 2 damage to target creature or player."$$Equip {1}| +Butcher's Cleaver|Innistrad|217|U|{3}|Artifact - Equipment|||Equipped creature gets +3/+0.$As long as equipped creature is a Human, it has lifelink.$Equip {3}| +Cellar Door|Innistrad|218|U|{2}|Artifact|||{3},{T}: Target player puts the bottom card of his or her library into his or her graveyard. If it's a creature card, you put a 2/2 black Zombie creature token onto the battlefield.| +Creepy Doll|Innistrad|220|R|{5}|Artifact Creature - Construct|1|1|Creepy Doll is indestructible.$Whenever Creepy Doll deals combat damage to a creature, flip a coin. If you win the flip, destroy that creature.| +Wooden Stake|Innistrad|237|C|{2}|Artifact - Equipment|||Equipped creature gets +1/+0.$$Whenever equipped creature blocks or becomes blocked by a Vampire, destroy that creature. It can't be regenerated.$$Equip {1}| +Clifftop Retreat|Innistrad|238|R||Land|||Clifftop Retreat enters the battlefield tapped unless you control a Mountain or Plains.${T}: Add {R} or {W} to your mana pool.| +Gavony Township|Innistrad|239|R||Land|||{T}: Add {1} to your mana pool.${2}{G}{W}, {T}: Put a +1/+1 counter on each creature you control.| +Ghost Quarter|Innistrad|240|U||Land|||{T}: Add {1} to your mana pool.${T}, Sacrifice Ghost Quarter: Destroy target land. Its controller may search his or her llibrary for a basic land card, put it onto the battlefield, then shuffle his or her library.| +Hinterland Harbor|Innistrad|241|R||Land|||Hinterland Harbor enters the battlefield tapped unless you control a Forest or Island.${T}: Add {G} or {U} to your mana pool.| +Isolated Chapel|Innistrad|242|R||Land|||Isolated Chapel enters the battlefield tapped unless you control a Plains or Swamp.${T}: Add {W} or {B} to your mana pool.| +Kessig Wolf Run|Innistrad|243|R||Land|||{T}: Add {1} to your mana pool.${X}{R}{G}, {T}: Target creature gets +X/+0 and gains trample until end of turn.| +Moorland Haunt|Innistrad|244|R||Land|||{T}: Add {1} to your mana pool.${W}{U}, {T}, Exile a creature card from your graveyard: Put a 1/1 white Spirit creature token with flying onto the battlefield.| +Nephalia Drownyard|Innistrad|245|R||Land|||{T}: Add 1 to your mana pool.${1}{U}{B}, {T}: Target player puts the top three cards of his or her library into his or her graveyard.| +Shimmering Grotto|Innistrad||C||Land|||{T}: Add {1} to your mana pool.${1}, {T}: Add one mana of any color to your mana pool.| +Sulfur Falls|Innistrad|248|R||Land|||Sulfur Falls enters the battlefield tapped unless you control an Island or Mountain.${T}: Add {U} or {R} to your mana pool.| +Woodland Cemetery|Innistrad|249|R||Land|||Woodland Cemetery enters the battlefield tapped unless you control a Swamp or Forest.${T}: Add {B} or {G} to your mana pool.| +Plains|Innistrad|250|L||Basic Land - Plains|||| +Plains|Innistrad|251|L||Basic Land - Plains|||| +Plains|Innistrad|252|L||Basic Land - Plains|||| +Island|Innistrad|253|L||Basic Land - Island|||| +Island|Innistrad|254|L||Basic Land - Island|||| +Island|Innistrad|255|L||Basic Land - Island|||| +Swamp|Innistrad|256|L||Basic Land - Swamp|||| +Swamp|Innistrad|257|L||Basic Land - Swamp|||| +Swamp|Innistrad|258|L||Basic Land - Swamp|||| +Mountain|Innistrad|259|L||Basic Land - Mountain|||| +Mountain|Innistrad|260|L||Basic Land - Mountain|||| +Mountain|Innistrad|261|L||Basic Land - Mountain|||| +Forest|Innistrad|262|L||Basic Land - Forest|||| +Forest|Innistrad|263|L||Basic Land - Forest|||| +Forest|Innistrad|264|L||Basic Land - Forest|||| \ No newline at end of file