diff --git a/.gitattributes b/.gitattributes
index fa278d05bfa..b5d385d295c 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2195,6 +2195,7 @@ res/cardsfolder/d/deep_sea_kraken.txt svneol=native#text/plain
res/cardsfolder/d/deep_sea_serpent.txt svneol=native#text/plain
res/cardsfolder/d/deep_slumber_titan.txt svneol=native#text/plain
res/cardsfolder/d/deep_wood.txt -text
+res/cardsfolder/d/deepcavern_imp.txt -text
res/cardsfolder/d/deepchannel_mentor.txt svneol=native#text/plain
res/cardsfolder/d/deepfire_elemental.txt -text
res/cardsfolder/d/deeptread_merrow.txt svneol=native#text/plain
@@ -12074,6 +12075,7 @@ src/main/java/forge/control/input/InputControl.java svneol=native#text/plain
src/main/java/forge/control/input/InputMana.java -text
src/main/java/forge/control/input/InputMulligan.java svneol=native#text/plain
src/main/java/forge/control/input/InputPassPriority.java svneol=native#text/plain
+src/main/java/forge/control/input/InputPayDiscardCost.java -text
src/main/java/forge/control/input/InputPayManaCost.java svneol=native#text/plain
src/main/java/forge/control/input/InputPayManaCostAbility.java svneol=native#text/plain
src/main/java/forge/control/input/InputPayManaCostUtil.java svneol=native#text/plain
diff --git a/res/cardsfolder/d/deepcavern_imp.txt b/res/cardsfolder/d/deepcavern_imp.txt
new file mode 100644
index 00000000000..89a91154b10
--- /dev/null
+++ b/res/cardsfolder/d/deepcavern_imp.txt
@@ -0,0 +1,13 @@
+Name:Deepcavern Imp
+ManaCost:2 B
+Types:Creature Imp Rebel
+Text:no text
+PT:2/2
+K:Flying
+K:Haste
+K:Echo:Discard<1/Card>:Discard a card.
+SVar:Rarity:Uncommon
+SVar:Picture:http://www.wizards.com/global/images/magic/general/deepcavern_imp.jpg
+SetInfo:FUT|Common|http://magiccards.info/scans/en/fut/83.jpg
+Oracle:Flying, haste\nEcho-Discard a card. (At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep, sacrifice it unless you pay its echo cost.)
+End
\ No newline at end of file
diff --git a/src/main/java/forge/GameActionUtil.java b/src/main/java/forge/GameActionUtil.java
index 996f373724a..ac5ec315766 100644
--- a/src/main/java/forge/GameActionUtil.java
+++ b/src/main/java/forge/GameActionUtil.java
@@ -25,6 +25,7 @@ import javax.swing.JOptionPane;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
+import forge.card.cost.CostDiscard;
import forge.card.cost.CostPart;
import forge.card.cost.CostPayLife;
import forge.card.cost.CostMana;
@@ -35,6 +36,7 @@ import forge.card.spellability.AbilityMana;
import forge.card.spellability.Spell;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityRestriction;
+import forge.control.input.InputPayDiscardCost;
import forge.control.input.InputPayManaCostAbility;
import forge.control.input.InputPayManaCostUtil;
import forge.control.input.InputPaySacCost;
@@ -487,6 +489,12 @@ public final class GameActionUtil {
AllZone.getInputControl().setInput(new InputPaySacCost((CostSacrifice) costPart, ability, paid, unpaid));
AllZone.getStack().setResolving(bResolving);
}
+ else if (costPart instanceof CostDiscard) {
+ final boolean bResolving = AllZone.getStack().getResolving();
+ AllZone.getStack().setResolving(false);
+ AllZone.getInputControl().setInput(new InputPayDiscardCost((CostDiscard) costPart, ability, paid, unpaid));
+ AllZone.getStack().setResolving(bResolving);
+ }
else if (costPart instanceof CostMana) {
if (costPart.getAmount().equals("0")) {
if (showYesNoDialog(source, "Do you want to pay 0?")) {
diff --git a/src/main/java/forge/control/input/InputPayDiscardCost.java b/src/main/java/forge/control/input/InputPayDiscardCost.java
new file mode 100644
index 00000000000..67da19bb461
--- /dev/null
+++ b/src/main/java/forge/control/input/InputPayDiscardCost.java
@@ -0,0 +1,188 @@
+/*
+ * 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
+ * Input_PayManaCost_Ability class. + *
+ * + * @author Forge + * @version $Id: InputPayManaCostAbility.java 15673 2012-05-23 14:01:35Z ArsenalNut $ + */ +public class InputPayDiscardCost extends Input { + /** + * ConstantserialVersionUID=2685832214529141991L.
+ */
+ private static final long serialVersionUID = 5634078561074764401L;
+
+ private int numChosen = 0;
+ private int numRequired = 0;
+ private CardList choiceList;
+ private CostDiscard discardCost;
+ private SpellAbility ability;
+ private Command paid;
+ private Command unpaid;
+
+ /**
+ * + * Constructor for Input_PayManaCost_Ability. + *
+ * + * @param cost + * a {@link forge.card.cost.CostSacrifice} object. + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + * @param paidCommand + * a {@link forge.Command} object. + * @param unpaidCommand + * a {@link forge.Command} object. + */ + public InputPayDiscardCost(final CostDiscard cost, final SpellAbility sa, final Command paidCommand, + final Command unpaidCommand) { + final Card source = sa.getSourceCard(); + + this.ability = sa; + this.discardCost = cost; + this.choiceList = AllZone.getHumanPlayer().getCardsIn(ZoneType.Hand).getValidCards(cost.getType().split(";") + , AllZone.getHumanPlayer(), source); + String amountString = cost.getAmount(); + this.numRequired = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString) + : CardFactoryUtil.xCount(source, source.getSVar(amountString)); + this.paid = paidCommand; + this.unpaid = unpaidCommand; + } + + /** {@inheritDoc} */ + @Override + public void showMessage() { + final StringBuilder msg = new StringBuilder("Discard "); + final int nLeft = this.numRequired - this.numChosen; + msg.append(nLeft).append(" "); + msg.append(this.discardCost.getDescriptiveType()); + if (nLeft > 1) { + msg.append("s"); + } + if (!this.discardCost.getList().isEmpty()) { + msg.append("\r\nSelected:\r\n"); + for (Card selected : this.discardCost.getList()) { + msg.append(selected + "\r\n"); + } + } + + CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString()); + if (nLeft > 0) { + ButtonUtil.enableOnlyCancel(); + } + else { + ButtonUtil.enableAll(); + } + } + + /** {@inheritDoc} */ + @Override + public void selectButtonCancel() { + this.cancel(); + } + + /** {@inheritDoc} */ + @Override + public void selectButtonOK() { + this.done(); + } + + /** {@inheritDoc} */ + @Override + public void selectCard(final Card card, final PlayerZone zone) { + if (this.choiceList.contains(card) && this.numChosen < numRequired) { + this.numChosen++; + this.discardCost.addToList(card); + card.setUsedToPay(true); + this.choiceList.remove(card); + this.showMessage(); + } + } + + /** + *+ * unselectCard. + *
+ * + * @param card + * a {@link forge.Card} object. + * @param zone + * a {@link forge.game.zone.PlayerZone} object. + */ + public void unselectCard(final Card card, final PlayerZone zone) { + if (this.discardCost.getList().contains(card)) { + this.numChosen--; + card.setUsedToPay(false); + this.discardCost.getList().remove(card); + this.choiceList.add(card); + this.showMessage(); + } + } + + /** + *+ * executes paid commmand. + *
+ * + */ + public void done() { + this.stop(); + // actually sacrifice the cards + for (Card selected : this.discardCost.getList()) { + selected.setUsedToPay(false); + AllZone.getHumanPlayer().discard(selected, this.ability); + } + this.discardCost.addListToHash(ability, "Discarded"); + this.paid.execute(); + } + + /** + *+ * executes unpaid commmand. + *
+ * + */ + public void cancel() { + this.stop(); + for (Card selected : this.discardCost.getList()) { + selected.setUsedToPay(false); + } + this.unpaid.execute(); + } + + +}