From 4881224b0641fa43b4c62936c2ec7df1fce96f8c Mon Sep 17 00:00:00 2001 From: swordshine Date: Sat, 17 Jun 2017 08:19:41 +0000 Subject: [PATCH] - HOU: Added Oasis Ritualist --- .gitattributes | 2 + .../main/java/forge/ai/AiCostDecision.java | 30 +++++ .../src/main/java/forge/game/cost/Cost.java | 6 + .../main/java/forge/game/cost/CostExert.java | 124 ++++++++++++++++++ .../java/forge/game/cost/ICostVisitor.java | 6 + .../cardsfolder/upcoming/oasis_ritualist.txt | 8 ++ .../java/forge/player/HumanCostDecision.java | 43 ++++++ 7 files changed, 219 insertions(+) create mode 100644 forge-game/src/main/java/forge/game/cost/CostExert.java create mode 100644 forge-gui/res/cardsfolder/upcoming/oasis_ritualist.txt diff --git a/.gitattributes b/.gitattributes index a4a8337da55..63d2032dc49 100644 --- a/.gitattributes +++ b/.gitattributes @@ -517,6 +517,7 @@ forge-game/src/main/java/forge/game/cost/CostDamage.java -text forge-game/src/main/java/forge/game/cost/CostDecisionMakerBase.java -text forge-game/src/main/java/forge/game/cost/CostDiscard.java -text forge-game/src/main/java/forge/game/cost/CostDraw.java -text +forge-game/src/main/java/forge/game/cost/CostExert.java -text forge-game/src/main/java/forge/game/cost/CostExile.java -text forge-game/src/main/java/forge/game/cost/CostExileFromStack.java -text forge-game/src/main/java/forge/game/cost/CostExiledMoveToGrave.java -text @@ -16959,6 +16960,7 @@ forge-gui/res/cardsfolder/upcoming/hour_of_revelation.txt -text forge-gui/res/cardsfolder/upcoming/khenra_eternal.txt -text forge-gui/res/cardsfolder/upcoming/nicol_bolas_god_pharaoh.txt -text forge-gui/res/cardsfolder/upcoming/nissa_genesis_mage.txt -text +forge-gui/res/cardsfolder/upcoming/oasis_ritualist.txt -text forge-gui/res/cardsfolder/upcoming/ramunap_excavator.txt -text forge-gui/res/cardsfolder/upcoming/samut_the_tested.txt -text forge-gui/res/cardsfolder/upcoming/steadfast_sentinel.txt -text diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index 945f2dfbebf..b7451254003 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -218,6 +218,36 @@ public class AiCostDecision extends CostDecisionMakerBase { return chosen.isEmpty() ? null : PaymentDecision.card(chosen); } + @Override + public PaymentDecision visit(CostExert cost) { + if (cost.payCostFromSource()) { + return PaymentDecision.card(source); + } + + Integer c = cost.convertAmount(); + if (c == null) { + if (ability.getSVar(cost.getAmount()).equals("XChoice")) { + return null; + } + + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + final CardCollection typeList = CardLists.getValidCards(player.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), player, source, ability); + + if (typeList.size() < c) { + return null; + } + + CardLists.sortByPowerAsc(typeList); + final CardCollection res = new CardCollection(); + + for (int i = 0; i < c; i++) { + res.add(typeList.get(i)); + } + return res.isEmpty() ? null : PaymentDecision.card(res); + } + @Override public PaymentDecision visit(CostFlipCoin cost) { Integer c = cost.convertAmount(); diff --git a/forge-game/src/main/java/forge/game/cost/Cost.java b/forge-game/src/main/java/forge/game/cost/Cost.java index c642bebc684..df78ddc9347 100644 --- a/forge-game/src/main/java/forge/game/cost/Cost.java +++ b/forge-game/src/main/java/forge/game/cost/Cost.java @@ -436,6 +436,12 @@ public class Cost { return new CostPutCardToLib(splitStr[0], splitStr[1], splitStr[2], description, ZoneType.Graveyard, true); } + if (parse.startsWith("Exert<")) { + final String[] splitStr = abCostParse(parse, 3); + final String description = splitStr.length > 2 ? splitStr[2] : null; + return new CostExert(splitStr[0], splitStr[1], description); + } + // These won't show up with multiples if (parse.equals("Untap") || parse.equals("Q")) { return new CostUntap(); diff --git a/forge-game/src/main/java/forge/game/cost/CostExert.java b/forge-game/src/main/java/forge/game/cost/CostExert.java new file mode 100644 index 00000000000..77251717889 --- /dev/null +++ b/forge-game/src/main/java/forge/game/cost/CostExert.java @@ -0,0 +1,124 @@ +/* + * 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.card.Card; +import forge.game.card.CardCollectionView; +import forge.game.card.CardLists; +import forge.game.player.Player; +import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; + +/** + * The Class CostExert. + */ +public class CostExert extends CostPartWithList { + + /** + * Instantiates a new cost Exert. + * + * @param amount + * the amount + * @param type + * the type + * @param description + * the description + */ + public CostExert(final String amount, final String type, final String description) { + super(amount, type, description); + } + + /* + * (non-Javadoc) + * + * @see forge.card.cost.CostPart#toString() + */ + @Override + public final String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Exert "); + + final Integer i = this.convertAmount(); + + if (this.payCostFromSource()) { + sb.append(this.getType()); + } else { + final String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription(); + if (i != null) { + sb.append(Cost.convertIntAndTypeToWords(i, desc)); + } else { + sb.append(Cost.convertAmountTypeToWords(this.getAmount(), desc)); + } + } + return sb.toString(); + } + + /* + * (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) { + final Player activator = ability.getActivatingPlayer(); + final Card source = ability.getHostCard(); + + + if (!this.payCostFromSource()) { + boolean needsAnnoucement = ability.hasParam("Announce") && this.getType().contains(ability.getParam("Announce")); + + CardCollectionView typeList = activator.getCardsIn(ZoneType.Battlefield); + typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source, ability); + final Integer amount = this.convertAmount(); + + + if (!needsAnnoucement && (amount != null) && (typeList.size() < amount)) { + return false; + } + + } + + return true; + } + + @Override + protected Card doPayment(SpellAbility ability, Card targetCard) { + targetCard.exert(); + return targetCard; + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForLKIList() { + return "Exerted"; + } + @Override + public String getHashForCardList() { + return "ExertedCards"; + } + + // Inputs + 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 a50e37e02fa..296ede6b058 100644 --- a/forge-game/src/main/java/forge/game/cost/ICostVisitor.java +++ b/forge-game/src/main/java/forge/game/cost/ICostVisitor.java @@ -10,6 +10,7 @@ public interface ICostVisitor { public T visit(CostExile cost); public T visit(CostExileFromStack cost); public T visit(CostExiledMoveToGrave cost); + public T visit(CostExert cost); public T visit(CostFlipCoin cost); public T visit(CostMill cost); public T visit(CostAddMana cost); @@ -72,6 +73,11 @@ public interface ICostVisitor { return null; } + @Override + public T visit(CostExert cost) { + return null; + } + @Override public T visit(CostFlipCoin cost) { return null; diff --git a/forge-gui/res/cardsfolder/upcoming/oasis_ritualist.txt b/forge-gui/res/cardsfolder/upcoming/oasis_ritualist.txt new file mode 100644 index 00000000000..4f9a8e848f4 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/oasis_ritualist.txt @@ -0,0 +1,8 @@ +Name:Oasis Ritualist +ManaCost:3 G +Types:Creature Naga Druid +PT:2/4 +A:AB$ Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color to your mana pool. +A:AB$ Mana | Cost$ T Exert<1/CARDNAME> | Produced$ Any | Amount$ 2 | SpellDescription$ Add two mana of any one color to your manna pool. (An exerted creature won't untap during your next untap step.) +SVar:Picture:http://www.wizards.com/global/images/magic/general/oasis_ritualist.jpg +Oracle:{T}: Add one mana of any color to your mana pool.\n{T}, Exert Oasis Ritualist: Add two mana of any one color to your manna pool. (An exerted creature won't untap during your next untap step.) diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index 3b180f455aa..e94c8c20b1f 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -441,6 +441,49 @@ public class HumanCostDecision extends CostDecisionMakerBase { return PaymentDecision.card(choice); } + @Override + public PaymentDecision visit(final CostExert cost) { + final String amount = cost.getAmount(); + final String type = cost.getType(); + + CardCollectionView list = CardLists.getValidCards(player.getCardsIn(ZoneType.Battlefield), type.split(";"), player, source, ability); + + if (cost.payCostFromSource()) { + if (source.getController() == ability.getActivatingPlayer() && source.isInPlay()) { + return player.getController().confirmPayment(cost, "Exert " + source.getName() + "?",ability) ? PaymentDecision.card(source) : null; + } + else { + return null; + } + } + + Integer c = cost.convertAmount(); + if (c == null) { + // Generalize this + if (ability.getSVar(amount).equals("XChoice")) { + c = chooseXValue(list.size()); + } else { + c = AbilityUtils.calculateAmount(source, amount, ability); + } + } + if (0 == c.intValue()) { + return PaymentDecision.number(0); + } + if (list.size() < c) { + return null; + } + final InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, list, ability); + inp.setMessage("Select a " + cost.getDescriptiveType() + " to exert (%d left)"); + inp.setCancelAllowed(true); + inp.showAndWait(); + if (inp.hasCancelled()) { + return null; + } + + return PaymentDecision.card(inp.getSelected()); + + } + @Override public PaymentDecision visit(final CostFlipCoin cost) { final String amount = cost.getAmount();