From 4e36fdc2b327f0c53ac001e942166641f47ad6ee Mon Sep 17 00:00:00 2001 From: Sol Date: Sat, 3 Sep 2016 01:15:05 +0000 Subject: [PATCH] - Adding Energy and PayEnergy for Players (still needs UI updates) --- .gitattributes | 1 + .../main/java/forge/ai/AiCostDecision.java | 18 ++++ .../java/forge/game/cost/CostPayEnergy.java | 99 +++++++++++++++++++ .../java/forge/game/cost/ICostVisitor.java | 6 ++ .../main/java/forge/game/player/Player.java | 29 ++++++ .../java/forge/player/HumanCostDecision.java | 53 +++++----- 6 files changed, 178 insertions(+), 28 deletions(-) create mode 100644 forge-game/src/main/java/forge/game/cost/CostPayEnergy.java 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 =(