diff --git a/.gitattributes b/.gitattributes
index 13e57f56bf1..e87b7f9ec7a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -509,6 +509,7 @@ forge-game/src/main/java/forge/game/cost/CostMill.java -text
forge-game/src/main/java/forge/game/cost/CostPart.java -text
forge-game/src/main/java/forge/game/cost/CostPartMana.java -text
forge-game/src/main/java/forge/game/cost/CostPartWithList.java -text
+forge-game/src/main/java/forge/game/cost/CostPayEnergy.java -text
forge-game/src/main/java/forge/game/cost/CostPayLife.java -text
forge-game/src/main/java/forge/game/cost/CostPayment.java svneol=native#text/plain
forge-game/src/main/java/forge/game/cost/CostPutCardToLib.java -text
diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java
index 9506c7d5422..e4997848f63 100644
--- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java
+++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java
@@ -316,6 +316,24 @@ public class AiCostDecision extends CostDecisionMakerBase {
return PaymentDecision.number(c);
}
+ @Override
+ public PaymentDecision visit(CostPayEnergy cost) {
+ Integer c = cost.convertAmount();
+ if (c == null) {
+ final String sVar = ability.getSVar(cost.getAmount());
+ // Generalize cost
+ if (sVar.equals("XChoice")) {
+ return null;
+ } else {
+ c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability);
+ }
+ }
+ if (!player.canPayEnergy(c)) {
+ return null;
+ }
+ return PaymentDecision.number(c);
+ }
+
@Override
public PaymentDecision visit(CostPutCardToLib cost) {
diff --git a/forge-game/src/main/java/forge/game/cost/CostPayEnergy.java b/forge-game/src/main/java/forge/game/cost/CostPayEnergy.java
new file mode 100644
index 00000000000..99a3a3c2383
--- /dev/null
+++ b/forge-game/src/main/java/forge/game/cost/CostPayEnergy.java
@@ -0,0 +1,99 @@
+/*
+ * 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.game.cost;
+
+import forge.game.ability.AbilityUtils;
+import forge.game.card.Card;
+import forge.game.player.Player;
+import forge.game.spellability.SpellAbility;
+
+
+public class CostPayEnergy extends CostPart {
+ int paidAmount = 0;
+
+ /**
+ * Instantiates a new cost pay energy.
+ *
+ * @param amount
+ * the amount
+ */
+ public CostPayEnergy(final String amount) {
+ this.setAmount(amount);
+ }
+
+ @Override
+ public int paymentOrder() { return 7; }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see forge.card.cost.CostPart#toString()
+ */
+ @Override
+ public final String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Pay ").append(this.getAmount()).append(" Energy");
+ return sb.toString();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see forge.card.cost.CostPart#refund(forge.Card)
+ */
+ @Override
+ public final void refund(final Card source) {
+ // Really should be activating player
+ source.getController().loseEnergy(this.paidAmount * -1);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility,
+ * forge.Card, forge.Player, forge.card.cost.Cost)
+ */
+ @Override
+ public final boolean canPay(final SpellAbility ability) {
+ Integer amount = this.convertAmount();
+ Player activator = ability.getActivatingPlayer();
+ if (amount == null) { // try to calculate when it's defined.
+ String sAmount = getAmount();
+ String sVar = ability.getSVar(sAmount);
+ if (!sVar.startsWith("XChoice")) {
+ amount = AbilityUtils.calculateAmount(ability.getHostCard(), getAmount(), ability);
+ }
+ } else {
+ return activator.getEnergy() >= amount;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean payAsDecided(Player ai, PaymentDecision decision, SpellAbility ability) {
+ paidAmount = decision.c;
+ return ai.payEnergy(paidAmount, null);
+ }
+
+ public T accept(ICostVisitor visitor) {
+ return visitor.visit(this);
+ }
+
+}
diff --git a/forge-game/src/main/java/forge/game/cost/ICostVisitor.java b/forge-game/src/main/java/forge/game/cost/ICostVisitor.java
index 51dd15bc450..a50e37e02fa 100644
--- a/forge-game/src/main/java/forge/game/cost/ICostVisitor.java
+++ b/forge-game/src/main/java/forge/game/cost/ICostVisitor.java
@@ -14,6 +14,7 @@ public interface ICostVisitor {
public T visit(CostMill cost);
public T visit(CostAddMana cost);
public T visit(CostPayLife cost);
+ public T visit(CostPayEnergy cost);
public T visit(CostGainLife cost);
public T visit(CostPartMana cost);
public T visit(CostPutCardToLib cost);
@@ -91,6 +92,11 @@ public interface ICostVisitor {
return null;
}
+ @Override
+ public T visit(CostPayEnergy cost) {
+ return null;
+ }
+
@Override
public T visit(CostGainLife cost) {
return null;
diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java
index 3d120e03a07..130db02f2af 100644
--- a/forge-game/src/main/java/forge/game/player/Player.java
+++ b/forge-game/src/main/java/forge/game/player/Player.java
@@ -86,6 +86,7 @@ public class Player extends GameEntity implements Comparable {
private int life = 20;
private int startingLife = 20;
+ private int energy = 0;
private final Map assignedDamage = new HashMap();
private int spellsCastThisTurn = 0;
private int landsPlayedThisTurn = 0;
@@ -492,6 +493,34 @@ public class Player extends GameEntity implements Comparable {
return false;
}
+ public final int getEnergy() {
+ return energy;
+ }
+ public final void setEnergy(int newEnergy) { energy = newEnergy; }
+
+ public final boolean canPayEnergy(final int energyPayment) {
+ return energy >= energyPayment;
+ }
+
+ public final int loseEnergy(int lostEnergy) {
+ if (lostEnergy > energy) {
+ return 0;
+ }
+ energy -= lostEnergy;
+ return lostEnergy;
+ }
+
+ public final boolean payEnergy(final int energyPayment, final Card source) {
+ if (energyPayment <= 0)
+ return true;
+
+ // rule 118.8
+ if (energy >= energyPayment) {
+ return (loseEnergy(energyPayment) > 0);
+ }
+ return false;
+ }
+
// This function handles damage after replacement and prevention effects are applied
@Override
public final boolean addDamageAfterPrevention(final int amount, final Card source, final boolean isCombat) {
diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java
index 768d7488f19..5179e24188b 100644
--- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java
+++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java
@@ -24,34 +24,7 @@ import forge.game.card.CardPredicates;
import forge.game.card.CardPredicates.Presets;
import forge.game.card.CardView;
import forge.game.card.CounterType;
-import forge.game.cost.CostAddMana;
-import forge.game.cost.CostChooseCreatureType;
-import forge.game.cost.CostDamage;
-import forge.game.cost.CostDecisionMakerBase;
-import forge.game.cost.CostDiscard;
-import forge.game.cost.CostDraw;
-import forge.game.cost.CostExile;
-import forge.game.cost.CostExileFromStack;
-import forge.game.cost.CostExiledMoveToGrave;
-import forge.game.cost.CostFlipCoin;
-import forge.game.cost.CostGainControl;
-import forge.game.cost.CostGainLife;
-import forge.game.cost.CostMill;
-import forge.game.cost.CostPartMana;
-import forge.game.cost.CostPayLife;
-import forge.game.cost.CostPutCardToLib;
-import forge.game.cost.CostPutCounter;
-import forge.game.cost.CostRemoveAnyCounter;
-import forge.game.cost.CostRemoveCounter;
-import forge.game.cost.CostReturn;
-import forge.game.cost.CostReveal;
-import forge.game.cost.CostSacrifice;
-import forge.game.cost.CostTap;
-import forge.game.cost.CostTapType;
-import forge.game.cost.CostUnattach;
-import forge.game.cost.CostUntap;
-import forge.game.cost.CostUntapType;
-import forge.game.cost.PaymentDecision;
+import forge.game.cost.*;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbility;
@@ -590,6 +563,30 @@ public class HumanCostDecision extends CostDecisionMakerBase {
return null;
}
+ @Override
+ public PaymentDecision visit(final CostPayEnergy cost) {
+ final String amount = cost.getAmount();
+ final int life = player.getLife();
+
+ Integer c = cost.convertAmount();
+ if (c == null) {
+ final String sVar = ability.getSVar(amount);
+ // Generalize this
+ if (sVar.startsWith("XChoice")) {
+ int limit = life;
+ final int maxLifePayment = limit < life ? limit : life;
+ c = chooseXValue(maxLifePayment);
+ } else {
+ c = AbilityUtils.calculateAmount(source, amount, ability);
+ }
+ }
+
+ if (player.canPayEnergy(c) && player.getController().confirmPayment(cost, "Pay " + c + " Energy?")) {
+ return PaymentDecision.number(c);
+ }
+ return null;
+ }
+
@Override
public PaymentDecision visit(final CostPartMana cost) {
// only interactive payment possible for now =(