diff --git a/.gitattributes b/.gitattributes
index 11dd4d2fdde..1104163c672 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -5889,6 +5889,7 @@ res/cardsfolder/l/liability.txt svneol=native#text/plain
res/cardsfolder/l/liberate.txt svneol=native#text/plain
res/cardsfolder/l/liberated_dwarf.txt svneol=native#text/plain
res/cardsfolder/l/library_of_alexandria.txt svneol=native#text/plain
+res/cardsfolder/l/library_of_leng.txt -text
res/cardsfolder/l/lich.txt svneol=native#text/plain
res/cardsfolder/l/lich_lord_of_unx.txt svneol=native#text/plain
res/cardsfolder/l/lichenthrope.txt svneol=native#text/plain
@@ -13761,6 +13762,7 @@ src/main/java/forge/card/mana/ManaPool.java svneol=native#text/plain
src/main/java/forge/card/mana/package-info.java svneol=native#text/plain
src/main/java/forge/card/package-info.java svneol=native#text/plain
src/main/java/forge/card/replacement/ReplaceDamage.java -text
+src/main/java/forge/card/replacement/ReplaceDiscard.java -text
src/main/java/forge/card/replacement/ReplaceDraw.java -text
src/main/java/forge/card/replacement/ReplaceGainLife.java -text
src/main/java/forge/card/replacement/ReplaceGameLoss.java -text
diff --git a/res/cardsfolder/l/library_of_leng.txt b/res/cardsfolder/l/library_of_leng.txt
new file mode 100644
index 00000000000..abcb4e83897
--- /dev/null
+++ b/res/cardsfolder/l/library_of_leng.txt
@@ -0,0 +1,16 @@
+Name:Library of Leng
+ManaCost:1
+Types:Artifact
+Text:no text
+S:Mode$ Continuous | EffectZone$ Battlefield | Affected$ You | SetMaxHandSize$ Unlimited | Description$ You have no maximum hand size.
+R:Event$ Discard | ActiveZones$ Battlefield | ValidCard$ Card.YouCtrl | ReplaceWith$ DiscardToLibrary | Optional$ True | DiscardFromEffect$ True | Description$ If an effect causes you to discard a card, discard it, but you may put it on top of your library instead of into your graveyard.
+SVar:DiscardToLibrary:DB$ Discard | Defined$ ReplacedPlayer | Mode$ Defined | DefinedCards$ ReplacedCard | DiscardToTopOfLibrary$ True
+SVar:Picture:http://www.wizards.com/global/images/magic/general/library_of_leng.jpg
+SetInfo:LEA|Uncommon|http://magiccards.info/scans/en/al/257.jpg
+SetInfo:LEB|Uncommon|http://magiccards.info/scans/en/be/259.jpg
+SetInfo:5ED|Uncommon|http://magiccards.info/scans/en/5e/387.jpg
+SetInfo:4ED|Uncommon|http://magiccards.info/scans/en/4e/351.jpg
+SetInfo:3ED|Uncommon|http://magiccards.info/scans/en/rv/261.jpg
+SetInfo:2ED|Uncommon|http://magiccards.info/scans/en/un/258.jpg
+Oracle:You have no maximum hand size.\nIf an effect causes you to discard a card, discard it, but you may put it on top of your library instead of into your graveyard.
+End
\ No newline at end of file
diff --git a/src/main/java/forge/card/replacement/ReplaceDiscard.java b/src/main/java/forge/card/replacement/ReplaceDiscard.java
new file mode 100644
index 00000000000..d995b2b2498
--- /dev/null
+++ b/src/main/java/forge/card/replacement/ReplaceDiscard.java
@@ -0,0 +1,89 @@
+/*
+ * Forge: Play Magic: the Gathering.
+ * Copyright (C) 2011 Forge Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package forge.card.replacement;
+
+import java.util.HashMap;
+
+import forge.Card;
+import forge.card.spellability.SpellAbility;
+
+/**
+ * TODO: Write javadoc for this type.
+ *
+ */
+public class ReplaceDiscard extends ReplacementEffect {
+
+ /**
+ * Instantiates a new replace discard.
+ *
+ * @param params the params
+ * @param host the host
+ */
+ public ReplaceDiscard(final HashMap params, final Card host) {
+ super(params, host);
+ }
+
+ /* (non-Javadoc)
+ * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
+ */
+ @Override
+ public boolean canReplace(HashMap runParams) {
+ if (!runParams.get("Event").equals("Discard")) {
+ return false;
+ }
+ if (this.getMapParams().containsKey("ValidPlayer")) {
+ if (!matchesValid(runParams.get("Affected"), this.getMapParams().get("ValidPlayer").split(","), this.getHostCard())) {
+ return false;
+ }
+ }
+ if (this.getMapParams().containsKey("ValidCard")) {
+ if (!matchesValid(runParams.get("Card"), this.getMapParams().get("ValidCard").split(","), this.getHostCard())) {
+ return false;
+ }
+ }
+ if (this.getMapParams().containsKey("DiscardFromEffect")) {
+ if (null == runParams.get("Source")) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.card.replacement.ReplacementEffect#getCopy()
+ */
+ @Override
+ public ReplacementEffect getCopy() {
+ ReplacementEffect res = new ReplaceDiscard(this.getMapParams(), this.getHostCard());
+ res.setOverridingAbility(this.getOverridingAbility());
+ res.setActiveZone(validHostZones);
+ res.setLayer(getLayer());
+ return res;
+ }
+
+ /* (non-Javadoc)
+ * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
+ */
+ @Override
+ public void setReplacingObjects(HashMap runParams, SpellAbility sa) {
+ sa.setReplacingObject("Card", runParams.get("Card"));
+ sa.setReplacingObject("Player", runParams.get("Affected"));
+ }
+
+}
diff --git a/src/main/java/forge/card/replacement/ReplacementHandler.java b/src/main/java/forge/card/replacement/ReplacementHandler.java
index e6338206a54..40537ae46ad 100644
--- a/src/main/java/forge/card/replacement/ReplacementHandler.java
+++ b/src/main/java/forge/card/replacement/ReplacementHandler.java
@@ -223,7 +223,7 @@ public class ReplacementHandler {
}
} else {
// AI-logic
- if (!replacementEffect.aiShouldRun(effectSA, (AIPlayer)optDecider)) {
+ if (!replacementEffect.aiShouldRun(effectSA, (AIPlayer) optDecider)) {
return ReplacementResult.NotReplaced;
}
}
@@ -239,7 +239,7 @@ public class ReplacementHandler {
if (player.isHuman()) {
game.getActionPlay().playSpellAbilityNoStack(player, effectSA, false);
} else {
- ComputerUtil.playNoStack((AIPlayer)player, effectSA, game);
+ ComputerUtil.playNoStack((AIPlayer) player, effectSA, game);
}
return ReplacementResult.Replaced;
@@ -278,6 +278,8 @@ public class ReplacementHandler {
final String eventToReplace = mapParams.get("Event");
if (eventToReplace.equals("Draw")) {
ret = new ReplaceDraw(mapParams, host);
+ } else if (eventToReplace.equals("Discard")) {
+ ret = new ReplaceDiscard(mapParams, host);
} else if (eventToReplace.equals("GainLife")) {
ret = new ReplaceGainLife(mapParams, host);
} else if (eventToReplace.equals("DamageDone")) {
diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java
index d9ee295b5d9..46206b68687 100644
--- a/src/main/java/forge/game/player/Player.java
+++ b/src/main/java/forge/game/player/Player.java
@@ -1618,11 +1618,24 @@ public abstract class Player extends GameEntity implements Comparable {
/*if (sa != null) {
sa.addCostToHashList(c, "Discarded");
}*/
+ final Card source = sa != null ? sa.getSourceCard() : null;
+
+ // Replacement effects
+ final HashMap repRunParams = new HashMap();
+ repRunParams.put("Event", "Discard");
+ repRunParams.put("Card", c);
+ repRunParams.put("Source", source);
+ repRunParams.put("Affected", this);
+
+ if (game.getReplacementHandler().run(repRunParams) != ReplacementResult.NotReplaced) {
+ return;
+ }
game.getAction().discardMadness(c, this);
boolean hasPutIntoPlayInsteadOfDiscard = c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME, put it onto the battlefield instead of putting it into your graveyard.");
boolean hasPutIntoPlayWith2xP1P1InsteadOfDiscard = c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME, put it onto the battlefield with two +1/+1 counters on it instead of putting it into your graveyard.");
+ boolean discardToTopOfLibrary = null != sa && sa.hasParam("DiscardToTopOfLibrary");
if ((hasPutIntoPlayInsteadOfDiscard || hasPutIntoPlayWith2xP1P1InsteadOfDiscard)
&& null != sa && sa.getSourceCard().getController().isOpponentOf(c.getController())) {
@@ -1633,6 +1646,8 @@ public abstract class Player extends GameEntity implements Comparable {
}
// Play the corresponding Put into Play sound
game.getEvents().post(new SpellResolvedEvent(c, sa));
+ } else if (discardToTopOfLibrary) {
+ game.getAction().moveToLibrary(c, 0);
} else {
game.getAction().moveToGraveyard(c);