From 4143c472ff2ee4a7232cf8047776810dac64f5c0 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Mon, 15 Apr 2013 08:31:37 +0000 Subject: [PATCH] removed manaCost from SpellAbility, use payCost instead. removed Card arguement from Cost ctor --- src/main/java/forge/Card.java | 20 ++--- .../forge/card/ability/AbilityFactory.java | 2 +- .../java/forge/card/ability/AbilityUtils.java | 2 +- .../forge/card/cardfactory/CardFactory.java | 2 +- .../cardfactory/CardFactoryCreatures.java | 4 +- .../cardfactory/CardFactorySorceries.java | 3 +- .../card/cardfactory/CardFactoryUtil.java | 27 +++---- src/main/java/forge/card/cost/Cost.java | 51 ++++++------ .../java/forge/card/spellability/Ability.java | 10 ++- .../card/spellability/AbilityActivated.java | 6 +- .../card/spellability/AbilityStatic.java | 4 +- .../java/forge/card/spellability/Spell.java | 4 +- .../forge/card/spellability/SpellAbility.java | 45 ++--------- .../card/spellability/SpellPermanent.java | 4 +- .../StaticAbilityCantAttackBlock.java | 4 +- src/main/java/forge/game/GameAction.java | 10 ++- src/main/java/forge/game/GameActionUtil.java | 77 ++++--------------- src/main/java/forge/game/ai/AiController.java | 4 +- .../java/forge/game/ai/ComputerUtilCost.java | 2 +- .../java/forge/game/ai/ComputerUtilMana.java | 2 +- .../java/forge/game/phase/CombatUtil.java | 5 +- src/main/java/forge/game/phase/PhaseUtil.java | 8 +- src/main/java/forge/game/phase/Upkeep.java | 22 +++--- .../java/forge/game/player/HumanPlayer.java | 8 +- src/main/java/forge/game/player/Player.java | 2 +- 25 files changed, 127 insertions(+), 201 deletions(-) diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index 16d8c4e0e31..a27069fbcf2 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -2110,7 +2110,7 @@ public class Card extends GameEntity implements Comparable { } else if (keyword.startsWith("Morph")) { sbLong.append("Morph"); if (keyword.contains(":")) { - final Cost mCost = new Cost(this, keywords.get(i).substring(6), true); + final Cost mCost = new Cost(keywords.get(i).substring(6), true); if (!mCost.isOnlyManaCost()) { sbLong.append(" -"); } @@ -2147,12 +2147,12 @@ public class Card extends GameEntity implements Comparable { } else if (keyword.startsWith("AlternateAdditionalCost")) { final String costString1 = keyword.split(":")[1]; final String costString2 = keyword.split(":")[2]; - final Cost cost1 = new Cost(this, costString1, false); - final Cost cost2 = new Cost(this, costString2, false); + final Cost cost1 = new Cost(costString1, false); + final Cost cost2 = new Cost(costString2, false); sbLong.append("As an additional cost to cast " + this.getName() + ", " + cost1.toSimpleString() + " or pay " + cost2.toSimpleString() + ".\r\n"); } else if (keyword.startsWith("Kicker")) { - final Cost cost = new Cost(this, keywords.get(i).substring(7), false); + final Cost cost = new Cost(keywords.get(i).substring(7), false); sbLong.append("Kicker " + cost.toSimpleString() + "\r\n"); } else if (keyword.endsWith(".") && !keywords.get(i).startsWith("Haunt")) { sbLong.append(keywords.get(i).toString()).append("\r\n"); @@ -2404,7 +2404,7 @@ public class Card extends GameEntity implements Comparable { if (keyword.startsWith("Flashback")) { sb.append("Flashback"); if (keyword.contains(" ")) { - final Cost fbCost = new Cost(this, keyword.substring(10), true); + final Cost fbCost = new Cost(keyword.substring(10), true); if (!fbCost.isOnlyManaCost()) { sb.append(" -"); } @@ -2415,19 +2415,19 @@ public class Card extends GameEntity implements Comparable { } sb.append("\r\n"); } else if (keyword.startsWith("Splice")) { - final Cost cost = new Cost(this, keyword.substring(19), false); + final Cost cost = new Cost(keyword.substring(19), false); sb.append("Splice onto Arcane " + cost.toSimpleString() + "\r\n"); } else if (keyword.startsWith("Buyback")) { - final Cost cost = new Cost(this, keyword.substring(8), false); + final Cost cost = new Cost(keyword.substring(8), false); sb.append("Buyback " + cost.toSimpleString() + "\r\n"); } else if (keyword.startsWith("Kicker")) { - final Cost cost = new Cost(this, keyword.substring(7), false); + final Cost cost = new Cost(keyword.substring(7), false); sb.append("Kicker " + cost.toSimpleString() + "\r\n"); } else if (keyword.startsWith("AlternateAdditionalCost")) { final String costString1 = keyword.split(":")[1]; final String costString2 = keyword.split(":")[2]; - final Cost cost1 = new Cost(this, costString1, false); - final Cost cost2 = new Cost(this, costString2, false); + final Cost cost1 = new Cost(costString1, false); + final Cost cost2 = new Cost(costString2, false); sb.append("As an additional cost to cast " + this.getName() + ", " + cost1.toSimpleString() + " or pay " + cost2.toSimpleString() + ".\r\n"); } else if (keyword.startsWith("Storm")) { diff --git a/src/main/java/forge/card/ability/AbilityFactory.java b/src/main/java/forge/card/ability/AbilityFactory.java index e6caf1fa411..ad45565fe80 100644 --- a/src/main/java/forge/card/ability/AbilityFactory.java +++ b/src/main/java/forge/card/ability/AbilityFactory.java @@ -116,7 +116,7 @@ public final class AbilityFactory { if (!mapParams.containsKey("Cost")) { throw new RuntimeException("AbilityFactory : getAbility -- no Cost in " + hostCard.getName()); } - abCost = new Cost(hostCard, mapParams.get("Cost"), type == AbilityRecordType.Ability); + abCost = new Cost(mapParams.get("Cost"), type == AbilityRecordType.Ability); } return abCost; } diff --git a/src/main/java/forge/card/ability/AbilityUtils.java b/src/main/java/forge/card/ability/AbilityUtils.java index 99fba682361..fdfbfc6ba6c 100644 --- a/src/main/java/forge/card/ability/AbilityUtils.java +++ b/src/main/java/forge/card/ability/AbilityUtils.java @@ -1107,7 +1107,7 @@ public class AbilityUtils { unlessCost = Integer.toString(calculateAmount(source, sa.getParam("UnlessCost").replace(" ", ""), sa)); } - final Cost cost = new Cost(source, unlessCost, true); + final Cost cost = new Cost(unlessCost, true); final Ability ability = new AbilityStatic(source, cost, sa.getTarget()) { @Override public void resolve() { /* nothing to do here */ } diff --git a/src/main/java/forge/card/cardfactory/CardFactory.java b/src/main/java/forge/card/cardfactory/CardFactory.java index 181e2349fa9..08a5264685b 100644 --- a/src/main/java/forge/card/cardfactory/CardFactory.java +++ b/src/main/java/forge/card/cardfactory/CardFactory.java @@ -181,7 +181,7 @@ public class CardFactory { } copySA.setCopied(true); //remove all costs - copySA.setPayCosts(new Cost(c, "", sa.isAbility())); + copySA.setPayCosts(new Cost("", sa.isAbility())); if (sa.getTarget() != null) { Target target = new Target(sa.getTarget()); target.setSourceCard(c); diff --git a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java index 5a33e1bdaa3..0d489a6fadb 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java @@ -152,7 +152,7 @@ public class CardFactoryCreatures { } private static void getCard_MasterOfTheWildHunt(final Card card) { - final Cost abCost = new Cost(card, "T", true); + final Cost abCost = new Cost("T", true); final Target abTgt = new Target(card, "Target a creature to Hunt", "Creature".split(",")); class MasterOfTheWildHuntAbility extends AbilityActivated { public MasterOfTheWildHuntAbility(final Card ca, final Cost co, final Target t) { @@ -568,7 +568,7 @@ public class CardFactoryCreatures { class LevelUpAbility extends AbilityActivated { public LevelUpAbility(final Card ca, final String s) { - super(ca, new Cost(ca, manacost, true), null); + super(ca, new Cost(manacost, true), null); } @Override diff --git a/src/main/java/forge/card/cardfactory/CardFactorySorceries.java b/src/main/java/forge/card/cardfactory/CardFactorySorceries.java index 8ac58de6405..3ebb4b84c67 100644 --- a/src/main/java/forge/card/cardfactory/CardFactorySorceries.java +++ b/src/main/java/forge/card/cardfactory/CardFactorySorceries.java @@ -255,8 +255,7 @@ public class CardFactorySorceries { * library. */ - final Cost abCost = new Cost(card, "U U", false); - return new Spell(card, abCost, null) { + return new Spell(card, new Cost("U U", false), null) { private static final long serialVersionUID = -8497142072380944393L; @Override diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index 0862709438c..f1123c49da2 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -100,7 +100,7 @@ public class CardFactoryUtil { */ public static AbilityActivated abilityUnearth(final Card sourceCard, final String manaCost) { - final Cost cost = new Cost(sourceCard, manaCost, true); + final Cost cost = new Cost(manaCost, true); class AbilityUnearth extends AbilityActivated { public AbilityUnearth(final Card ca, final Cost co, final Target t) { super(ca, co, t); @@ -162,7 +162,7 @@ public class CardFactoryUtil { * @return a {@link forge.card.spellability.SpellAbility} object. */ public static SpellAbility abilityMorphDown(final Card sourceCard) { - final Spell morphDown = new Spell(sourceCard) { + final Spell morphDown = new Spell(sourceCard, new Cost(ManaCost.THREE, false), null) { private static final long serialVersionUID = -1438810964807867610L; @Override @@ -184,7 +184,6 @@ public class CardFactoryUtil { } }; - morphDown.setManaCost(ManaCost.THREE); morphDown.setDescription("(You may cast this face down as a 2/2 creature for 3.)"); morphDown.setStackDescription("Morph - Creature 2/2"); morphDown.setCastFaceDown(true); @@ -313,7 +312,7 @@ public class CardFactoryUtil { */ public static SpellAbility abilityTransmute(final Card sourceCard, String transmuteCost) { transmuteCost += " Discard<1/CARDNAME>"; - final Cost abCost = new Cost(sourceCard, transmuteCost, true); + final Cost abCost = new Cost(transmuteCost, true); class AbilityTransmute extends AbilityActivated { public AbilityTransmute(final Card ca, final Cost co, final Target t) { super(ca, co, t); @@ -406,7 +405,7 @@ public class CardFactoryUtil { */ public static SpellAbility abilitySuspend(final Card sourceCard, final String suspendCost, final String timeCounters) { // be careful with Suspend ability, it will not hit the stack - Cost cost = new Cost(sourceCard, suspendCost, true); + Cost cost = new Cost(suspendCost, true); final SpellAbility suspend = new AbilityStatic(sourceCard, cost, null) { @Override public boolean canPlay() { @@ -2598,7 +2597,7 @@ public class CardFactoryUtil { final SpellAbility sa1 = card.getFirstSpellAbility(); if (sa1 != null && sa1.isSpell()) { final String altCost = card.getSVar("FullCost"); - final Cost abCost = new Cost(card, altCost, sa1.isAbility()); + final Cost abCost = new Cost(altCost, sa1.isAbility()); sa1.setPayCosts(abCost); } } @@ -3104,7 +3103,7 @@ public class CardFactoryUtil { final SpellAbility altCostSA = sa.copy(); - final Cost abCost = new Cost(card, altCost, altCostSA.isAbility()); + final Cost abCost = new Cost(altCost, altCostSA.isAbility()); altCostSA.setPayCosts(abCost); final StringBuilder sb = new StringBuilder(); @@ -3136,7 +3135,11 @@ public class CardFactoryUtil { * @return */ private static SpellAbility makeEvokeSpell(final Card card, final String evokeKeyword) { - final SpellAbility evokedSpell = new Spell(card) { + final String[] k = evokeKeyword.split(":"); + final String evokedCost = k[1]; + ManaCost manaCost = new ManaCost(new ManaCostParser(evokedCost)); + + final SpellAbility evokedSpell = new Spell(card, new Cost(manaCost, false), null) { private static final long serialVersionUID = -1598664196463358630L; @Override @@ -3154,12 +3157,6 @@ public class CardFactoryUtil { } }; card.removeIntrinsicKeyword(evokeKeyword); - - final String[] k = evokeKeyword.split(":"); - final String evokedCost = k[1]; - - evokedSpell.setManaCost(new ManaCost(new ManaCostParser(evokedCost))); - final StringBuilder desc = new StringBuilder(); desc.append("Evoke ").append(evokedCost); desc.append(" (You may cast this spell for its evoke cost. "); @@ -3349,7 +3346,7 @@ public class CardFactoryUtil { Map sVars = card.getSVars(); final String[] k = parse.split(":"); - final Cost cost = new Cost(card, k[1], true); + final Cost cost = new Cost(k[1], true); card.addSpellAbility(CardFactoryUtil.abilityMorphDown(card)); diff --git a/src/main/java/forge/card/cost/Cost.java b/src/main/java/forge/card/cost/Cost.java index 07bacf24860..32d5087c157 100644 --- a/src/main/java/forge/card/cost/Cost.java +++ b/src/main/java/forge/card/cost/Cost.java @@ -43,6 +43,16 @@ public class Cost { private boolean isAbility = true; private final ArrayList costParts = new ArrayList(); + private boolean tapCost = false; + + public final boolean hasTapCost() { + return this.tapCost; + } + + public final boolean hasNoManaCost() { + return this.getTotalMana().isZero(); + } + /** * Gets the cost parts. * @@ -52,23 +62,6 @@ public class Cost { return this.costParts; } - private boolean tapCost = false; - - public final boolean hasTapCost() { - return this.tapCost; - } - - /** - *

- * hasNoManaCost. - *

- * - * @return a boolean. - */ - public final boolean hasNoManaCost() { - return this.getTotalMana().isZero(); - } - /** *

* isOnlyManaCost. @@ -104,12 +97,12 @@ public class Cost { return ManaCost.ZERO; } - private final String name; - + private Cost() {} + // Parsing Strings - public Cost(final Card card, ManaCost cost, final boolean bAbility) { - this(card, cost.toString(), bAbility); + public Cost(ManaCost cost, final boolean bAbility) { + this(cost.toString(), bAbility); } /** @@ -123,10 +116,9 @@ public class Cost { * @param bAbility * a boolean. */ - public Cost(final Card card, String parse, final boolean bAbility) { + public Cost(String parse, final boolean bAbility) { this.isAbility = bAbility; // when adding new costs for cost string, place them here - this.name = card != null ? card.getName() : ""; boolean xCantBe0 = false; boolean untapCost = false; @@ -379,6 +371,17 @@ public class Cost { this.costParts.add(new CostPartMana(changedCost.toManaCost(), null, false)); } } + + public final Cost copyWithNoMana() { + Cost toRet = new Cost(); + for(CostPart cp : this.costParts) { + if ( cp instanceof CostPartMana ) + toRet.costParts.add(new CostPartMana(ManaCost.ZERO, null, false)); + else + toRet.costParts.add(cp); + } + return toRet; + } public final CostPartMana getCostMana() { for (final CostPart part : this.costParts) { @@ -502,7 +505,7 @@ public class Cost { boolean first = true; if (bFlag) { - cost.append("As an additional cost to cast ").append(this.name).append(", "); + cost.append("As an additional cost to cast selected card, "); } else { // usually no additional mana cost for spells // only three Alliances cards have additional mana costs, but they diff --git a/src/main/java/forge/card/spellability/Ability.java b/src/main/java/forge/card/spellability/Ability.java index 36103c4c5d9..b0928b3b95a 100644 --- a/src/main/java/forge/card/spellability/Ability.java +++ b/src/main/java/forge/card/spellability/Ability.java @@ -21,6 +21,7 @@ import com.esotericsoftware.minlog.Log; import forge.Card; import forge.Singletons; +import forge.card.cost.Cost; import forge.card.mana.ManaCost; /** @@ -44,10 +45,11 @@ public abstract class Ability extends SpellAbility { * a {@link java.lang.String} object. */ public Ability(final Card sourceCard, final ManaCost manaCost) { - super(sourceCard); - this.setManaCost(manaCost); + this(sourceCard, new Cost(manaCost, true)); + } + public Ability(final Card sourceCard, final Cost cost) { + super(sourceCard, cost); } - /** *

* Constructor for Ability. @@ -76,7 +78,7 @@ public abstract class Ability extends SpellAbility { return this.getSourceCard().isInPlay() && !this.getSourceCard().isFaceDown(); } - public static final Ability PLAY_LAND_SURROGATE = new Ability(null, null){ + public static final Ability PLAY_LAND_SURROGATE = new Ability(null, (Cost)null){ @Override public void resolve() { // TODO Auto-generated method stub diff --git a/src/main/java/forge/card/spellability/AbilityActivated.java b/src/main/java/forge/card/spellability/AbilityActivated.java index b196661574d..82d5fb67c12 100644 --- a/src/main/java/forge/card/spellability/AbilityActivated.java +++ b/src/main/java/forge/card/spellability/AbilityActivated.java @@ -50,7 +50,7 @@ public abstract class AbilityActivated extends SpellAbility implements java.io.S * a {@link java.lang.String} object. */ public AbilityActivated(final Card card, final String manacost) { - this(card, new Cost(card, manacost, true), null); + this(card, new Cost(manacost, true), null); } /** @@ -66,9 +66,7 @@ public abstract class AbilityActivated extends SpellAbility implements java.io.S * a {@link forge.card.spellability.Target} object. */ public AbilityActivated(final Card sourceCard, final Cost abCost, final Target tgt) { - super(sourceCard); - this.setManaCost(abCost.getTotalMana()); - this.setPayCosts(abCost); + super(sourceCard, abCost); if ((tgt != null) && tgt.doesTarget()) { this.setTarget(tgt); } diff --git a/src/main/java/forge/card/spellability/AbilityStatic.java b/src/main/java/forge/card/spellability/AbilityStatic.java index 58776670fdf..a8b87f27ad9 100644 --- a/src/main/java/forge/card/spellability/AbilityStatic.java +++ b/src/main/java/forge/card/spellability/AbilityStatic.java @@ -45,9 +45,7 @@ public abstract class AbilityStatic extends Ability { } public AbilityStatic(final Card sourceCard, final Cost abCost, final Target tgt) { - super(sourceCard, abCost.getTotalMana()); - this.setManaCost(abCost.getTotalMana()); - this.setPayCosts(abCost); + super(sourceCard, abCost); if ((tgt != null) && tgt.doesTarget()) { this.setTarget(tgt); } diff --git a/src/main/java/forge/card/spellability/Spell.java b/src/main/java/forge/card/spellability/Spell.java index f11a88ac418..9d1e521a2d2 100644 --- a/src/main/java/forge/card/spellability/Spell.java +++ b/src/main/java/forge/card/spellability/Spell.java @@ -59,7 +59,7 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable public Spell(final Card sourceCard) { super(sourceCard); - this.setManaCost(sourceCard.getManaCost()); + this.setPayCosts(new Cost(sourceCard.getManaCost(), false)); this.setStackDescription(sourceCard.getSpellText()); this.getRestrictions().setZone(ZoneType.Hand); } @@ -109,7 +109,7 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable return false; } // for uncastables like lotus bloom, check if manaCost is blank - if (isBasicSpell() && getManaCost().isNoCost()) { + if (isBasicSpell() && (getPayCosts() == null || getPayCosts().getTotalMana().isNoCost())) { return false; } diff --git a/src/main/java/forge/card/spellability/SpellAbility.java b/src/main/java/forge/card/spellability/SpellAbility.java index f2108b500d7..4bc94cdef72 100644 --- a/src/main/java/forge/card/spellability/SpellAbility.java +++ b/src/main/java/forge/card/spellability/SpellAbility.java @@ -31,7 +31,6 @@ import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; import forge.card.cost.Cost; -import forge.card.cost.CostPart; import forge.card.cost.CostPartMana; import forge.card.mana.Mana; import forge.card.mana.ManaCost; @@ -54,7 +53,6 @@ public abstract class SpellAbility implements ISpellAbility { // choices for constructor isPermanent argument private String description = ""; private String stackDescription = ""; - private ManaCost manaCost = null; private ManaCost multiKickerManaCost = null; private ManaCost replicateManaCost = null; private Player activatingPlayer = null; @@ -173,8 +171,13 @@ public abstract class SpellAbility implements ISpellAbility { * @param iSourceCard * a {@link forge.Card} object. */ - public SpellAbility(final Card iSourceCard) { + public SpellAbility(final Card iSourceCard, Cost toPay) { this.sourceCard = iSourceCard; + this.payCosts = toPay; + } + + public SpellAbility(final Card iSourceCard ) { + this(iSourceCard, null); } // Spell, and Ability, and other Ability objects override this method @@ -221,29 +224,6 @@ public abstract class SpellAbility implements ISpellAbility { return false; } - /** - *

- * Getter for the field manaCost. - *

- * - * @return a {@link java.lang.String} object. - */ - public ManaCost getManaCost() { - return this.manaCost; - } - - /** - *

- * Setter for the field manaCost. - *

- * - * @param cost - * a {@link java.lang.String} object. - */ - public void setManaCost(final ManaCost cost) { - this.manaCost = cost; - } - /** *

* Getter for the field multiKickerManaCost. @@ -1136,17 +1116,8 @@ public abstract class SpellAbility implements ISpellAbility { } public SpellAbility copyWithNoManaCost() { - final SpellAbility newSA = this; - final Cost cost = new Cost(this.getSourceCard(), "", false); - if (newSA.getPayCosts() != null) { - for (final CostPart part : newSA.getPayCosts().getCostParts()) { - if (!(part instanceof CostPartMana)) { - cost.getCostParts().add(part); - } - } - } - newSA.setPayCosts(cost); - newSA.setManaCost(ManaCost.NO_COST); + final SpellAbility newSA = this.copy(); + newSA.setPayCosts(newSA.getPayCosts().copyWithNoMana()); newSA.setDescription(newSA.getDescription() + " (without paying its mana cost)"); return newSA; } diff --git a/src/main/java/forge/card/spellability/SpellPermanent.java b/src/main/java/forge/card/spellability/SpellPermanent.java index d09d96b9aa3..8fe530ef722 100644 --- a/src/main/java/forge/card/spellability/SpellPermanent.java +++ b/src/main/java/forge/card/spellability/SpellPermanent.java @@ -67,7 +67,7 @@ public class SpellPermanent extends Spell { */ public SpellPermanent(final Card sourceCard) { // Add Costs for all SpellPermanents - this(sourceCard, new Cost(sourceCard, sourceCard.getManaCost(), false), null); + this(sourceCard, new Cost(sourceCard.getManaCost(), false), null); } // Spell_Permanent() /** @@ -97,7 +97,7 @@ public class SpellPermanent extends Spell { this.setDescription(this.getStackDescription()); - if (this.getManaCost().countX() > 0) { + if (this.getPayCosts().getTotalMana().countX() > 0) { if (!this.getSourceCard().getSVar("X").equals("")) { this.setSVar("X", this.getSourceCard().getSVar("X")); } diff --git a/src/main/java/forge/card/staticability/StaticAbilityCantAttackBlock.java b/src/main/java/forge/card/staticability/StaticAbilityCantAttackBlock.java index 410f5f87d90..13608b0a353 100644 --- a/src/main/java/forge/card/staticability/StaticAbilityCantAttackBlock.java +++ b/src/main/java/forge/card/staticability/StaticAbilityCantAttackBlock.java @@ -84,7 +84,7 @@ public class StaticAbilityCantAttackBlock { costString = Integer.toString(CardFactoryUtil.xCount(hostCard, hostCard.getSVar("Y"))); } - final Cost cost = new Cost(hostCard, costString, true); + final Cost cost = new Cost(costString, true); return cost; } @@ -118,7 +118,7 @@ public class StaticAbilityCantAttackBlock { costString = Integer.toString(CardFactoryUtil.xCount(hostCard, hostCard.getSVar("Y"))); } - final Cost cost = new Cost(hostCard, costString, true); + final Cost cost = new Cost(costString, true); return cost; } diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index 424b299f112..533ae67842e 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -35,6 +35,7 @@ import forge.CardPredicates; import forge.CardUtil; import forge.Command; import forge.CounterType; +import forge.FThreads; import forge.GameEntity; import forge.card.CardType; import forge.card.TriggerReplacementBase; @@ -335,8 +336,11 @@ public class GameAction { * @return a {@link forge.Card} object. */ public final Card moveTo(final Zone zoneTo, Card c) { + // FThreads.assertExecutedByEdt(false); // This code must never be executed from EDT, + // use FThreads.invokeInNewThread to run code in a pooled thread + // if a split card is moved, convert it back to its full form before moving (unless moving to stack) - if (c.isSplitCard() && zoneTo != game.getStackZone()) { + if (c.isSplitCard() && !zoneTo.is(ZoneType.Stack)) { c.setState(CardCharacteristicName.Original); } @@ -481,7 +485,7 @@ public class GameAction { private void handleRecoverAbility(final Card recoverable) { final String recoverCost = recoverable.getKeyword().get(recoverable.getKeywordPosition("Recover")).split(":")[1]; - final Cost cost = new Cost(recoverable, recoverCost, true); + final Cost cost = new Cost(recoverCost, true); final SpellAbility abRecover = new AbilityActivated(recoverable, cost, null) { private static final long serialVersionUID = 8858061639236920054L; @@ -758,7 +762,7 @@ public class GameAction { } final SpellAbility madness = card.getFirstSpellAbility().copy(); - madness.setPayCosts(new Cost(card, card.getMadnessCost(), false)); + madness.setPayCosts(new Cost(card.getMadnessCost(), false)); final StringBuilder sb = new StringBuilder(); sb.append(card.getName()).append(" - Cast via Madness"); diff --git a/src/main/java/forge/game/GameActionUtil.java b/src/main/java/forge/game/GameActionUtil.java index 9c7f6c18c5e..275a2f7f2ec 100644 --- a/src/main/java/forge/game/GameActionUtil.java +++ b/src/main/java/forge/game/GameActionUtil.java @@ -564,8 +564,8 @@ public final class GameActionUtil { throw new RuntimeException("GameActionUtil.payCostDuringAbilityResolve - The remaining payment type is not Mana."); InputPayment toSet = current == null - ? new InputPayManaExecuteCommands(p, source + "\r\n", ability.getManaCost()) - : new InputPayManaExecuteCommands(p, source + "\r\n" + "Current Card: " + current + "\r\n" , ability.getManaCost()); + ? new InputPayManaExecuteCommands(p, source + "\r\n", cost.getCostMana().getManaToPay()) + : new InputPayManaExecuteCommands(p, source + "\r\n" + "Current Card: " + current + "\r\n" , cost.getCostMana().getManaToPay()); FThreads.setInputAndWait(toSet); return toSet.isPaid(); } @@ -1159,7 +1159,7 @@ public final class GameActionUtil { // there is a flashback cost (and not the cards cost) if (!keyword.equals("Flashback")) { - final Cost fbCost = new Cost(source, keyword.substring(10), false); + final Cost fbCost = new Cost(keyword.substring(10), false); flashback.setPayCosts(fbCost); } alternatives.add(flashback); @@ -1170,17 +1170,8 @@ public final class GameActionUtil { sar.setVariables(sa.getRestrictions()); sar.setZone(null); newSA.setRestrictions(sar); - final Cost cost = new Cost(source, "", false); - if (newSA.getPayCosts() != null) { - for (final CostPart part : newSA.getPayCosts().getCostParts()) { - if (!(part instanceof CostPartMana)) { - cost.getCostParts().add(part); - } - } - } newSA.setBasicSpell(false); - newSA.setPayCosts(cost); - newSA.setManaCost(ManaCost.NO_COST); + newSA.setPayCosts(newSA.getPayCosts().copyWithNoMana()); newSA.setDescription(sa.getDescription() + " (without paying its mana cost)"); alternatives.add(newSA); } @@ -1191,17 +1182,8 @@ public final class GameActionUtil { sar.setZone(null); sar.setOpponentOnly(true); newSA.setRestrictions(sar); - final Cost cost = new Cost(source, "", false); - if (newSA.getPayCosts() != null) { - for (final CostPart part : newSA.getPayCosts().getCostParts()) { - if (!(part instanceof CostPartMana)) { - cost.getCostParts().add(part); - } - } - } newSA.setBasicSpell(false); - newSA.setPayCosts(cost); - newSA.setManaCost(ManaCost.NO_COST); + newSA.setPayCosts(newSA.getPayCosts().copyWithNoMana()); newSA.setDescription(sa.getDescription() + " (without paying its mana cost)"); alternatives.add(newSA); } @@ -1211,38 +1193,17 @@ public final class GameActionUtil { sar.setVariables(sa.getRestrictions()); sar.setInstantSpeed(true); newSA.setRestrictions(sar); - final Cost cost = new Cost(source, "", false); - if (newSA.getPayCosts() != null) { - for (final CostPart part : newSA.getPayCosts().getCostParts()) { - if (!(part instanceof CostPartMana)) { - cost.getCostParts().add(part); - } - } - } newSA.setBasicSpell(false); - newSA.setPayCosts(cost); - newSA.setManaCost(ManaCost.NO_COST); + newSA.setPayCosts(newSA.getPayCosts().copyWithNoMana()); newSA.setDescription(sa.getDescription() + " (without paying its mana cost and as though it has flash)"); alternatives.add(newSA); } if (sa.isSpell() && keyword.startsWith("Alternative Cost")) { final SpellAbility newSA = sa.copy(); - final Cost cost = new Cost(source, keyword.substring(17), false); - if (newSA.getPayCosts() != null) { - for (final CostPart part : newSA.getPayCosts().getCostParts()) { - if (!(part instanceof CostPartMana)) { - cost.getCostParts().add(part); - } - } - } newSA.setBasicSpell(false); + final Cost cost = new Cost(keyword.substring(17), false).add(newSA.getPayCosts().copyWithNoMana()); newSA.setPayCosts(cost); - newSA.setManaCost(ManaCost.NO_COST); - String costString = cost.toSimpleString(); - if (costString.equals("")) { - costString = "0"; - } - newSA.setDescription(sa.getDescription() + " (by paying " + costString + " instead of its mana cost)"); + newSA.setDescription(sa.getDescription() + " (by paying " + cost.toSimpleString() + " instead of its mana cost)"); alternatives.add(newSA); } } @@ -1286,8 +1247,7 @@ public final class GameActionUtil { //create a new spell copy final SpellAbility newSA = s.copy(); newSA.setBasicSpell(false); - newSA.setPayCosts(new Cost(c, keyword.substring(19), false).add(newSA.getPayCosts())); - newSA.setManaCost(ManaCost.NO_COST); + newSA.setPayCosts(new Cost(keyword.substring(19), false).add(newSA.getPayCosts())); newSA.setDescription(s.getDescription() + " (Splicing " + c + " onto it)"); newSA.addSplicedCards(c); @@ -1343,8 +1303,7 @@ public final class GameActionUtil { for (SpellAbility sa : abilities) { final SpellAbility newSA = sa.copy(); newSA.setBasicSpell(false); - newSA.setPayCosts(new Cost(source, keyword.substring(8), false).add(newSA.getPayCosts())); - newSA.setManaCost(ManaCost.NO_COST); + newSA.setPayCosts(new Cost(keyword.substring(8), false).add(newSA.getPayCosts())); newSA.setDescription(sa.getDescription() + " (with Buyback)"); ArrayList newoacs = new ArrayList(); newoacs.addAll(sa.getOptionalAdditionalCosts()); @@ -1360,10 +1319,9 @@ public final class GameActionUtil { for (SpellAbility sa : abilities) { final SpellAbility newSA = sa.copy(); newSA.setBasicSpell(false); - final Cost cost = new Cost(source, keyword.substring(7), false); + final Cost cost = new Cost(keyword.substring(7), false); newSA.setDescription(sa.getDescription() + " (Kicker " + cost.toSimpleString() + ")"); newSA.setPayCosts(cost.add(newSA.getPayCosts())); - newSA.setManaCost(ManaCost.NO_COST); ArrayList newoacs = new ArrayList(); newoacs.addAll(sa.getOptionalAdditionalCosts()); newSA.setOptionalAdditionalCosts(newoacs); @@ -1380,9 +1338,8 @@ public final class GameActionUtil { for (SpellAbility sa : abilities) { final SpellAbility newSA = sa.copy(); newSA.setBasicSpell(false); - newSA.setPayCosts(new Cost(source, costString1, false).add(newSA.getPayCosts())); - newSA.setManaCost(ManaCost.NO_COST); - final Cost cost1 = new Cost(source, costString1, false); + newSA.setPayCosts(new Cost(costString1, false).add(newSA.getPayCosts())); + final Cost cost1 = new Cost(costString1, false); newSA.setDescription(sa.getDescription() + " (Additional cost " + cost1.toSimpleString() + ")"); ArrayList newoacs = new ArrayList(); newoacs.addAll(sa.getOptionalAdditionalCosts()); @@ -1393,9 +1350,8 @@ public final class GameActionUtil { //second option final SpellAbility newSA2 = sa.copy(); newSA2.setBasicSpell(false); - newSA.setPayCosts(new Cost(source, costString2, false).add(newSA.getPayCosts())); - newSA2.setManaCost(ManaCost.NO_COST); - final Cost cost2 = new Cost(source, costString2, false); + newSA.setPayCosts(new Cost(costString2, false).add(newSA.getPayCosts())); + final Cost cost2 = new Cost(costString2, false); newSA2.setDescription(sa.getDescription() + " (Additional cost " + cost2.toSimpleString() + ")"); ArrayList newoacs2 = new ArrayList(); newoacs.addAll(sa.getOptionalAdditionalCosts()); @@ -1413,8 +1369,7 @@ public final class GameActionUtil { newSA.setBasicSpell(false); final String conspireCost = "tapXType<2/Creature.SharesColorWith/untapped creature you control" + " that shares a color with " + source.getName() + ">"; - newSA.setPayCosts(new Cost(source, conspireCost, false).add(newSA.getPayCosts())); - newSA.setManaCost(ManaCost.NO_COST); + newSA.setPayCosts(new Cost(conspireCost, false).add(newSA.getPayCosts())); newSA.setDescription(sa.getDescription() + " (Conspire)"); ArrayList newoacs = new ArrayList(); newoacs.addAll(sa.getOptionalAdditionalCosts()); diff --git a/src/main/java/forge/game/ai/AiController.java b/src/main/java/forge/game/ai/AiController.java index 56f043c3d28..76a2d5d77c5 100644 --- a/src/main/java/forge/game/ai/AiController.java +++ b/src/main/java/forge/game/ai/AiController.java @@ -484,8 +484,8 @@ public class AiController { public int compare(final SpellAbility a, final SpellAbility b) { // sort from highest cost to lowest // we want the highest costs first - int a1 = a.getManaCost().getCMC(); - int b1 = b.getManaCost().getCMC(); + int a1 = a.getPayCosts() == null ? 0 : a.getPayCosts().getTotalMana().getCMC(); + int b1 = b.getPayCosts() == null ? 0 : b.getPayCosts().getTotalMana().getCMC(); // cast 0 mana cost spells first (might be a Mox) if (a1 == 0) { diff --git a/src/main/java/forge/game/ai/ComputerUtilCost.java b/src/main/java/forge/game/ai/ComputerUtilCost.java index 719d55da4cd..6fcaf3dcbfc 100644 --- a/src/main/java/forge/game/ai/ComputerUtilCost.java +++ b/src/main/java/forge/game/ai/ComputerUtilCost.java @@ -312,7 +312,7 @@ public class ComputerUtilCost { * @return a boolean. */ public static boolean shouldPayCost(final Player ai, final Card hostCard, final String costString) { - final Cost cost = new Cost(hostCard, costString, false); + final Cost cost = new Cost(costString, false); for (final CostPart part : cost.getCostParts()) { if (part instanceof CostPayLife) { diff --git a/src/main/java/forge/game/ai/ComputerUtilMana.java b/src/main/java/forge/game/ai/ComputerUtilMana.java index b813e34f46d..7d5c72839c5 100644 --- a/src/main/java/forge/game/ai/ComputerUtilMana.java +++ b/src/main/java/forge/game/ai/ComputerUtilMana.java @@ -412,7 +412,7 @@ public class ComputerUtilMana { * @return ManaCost */ private static ManaCostBeingPaid calculateManaCost(final SpellAbility sa, final boolean test, final int extraMana) { - final ManaCost mana = sa.getPayCosts() != null ? sa.getPayCosts().getTotalMana() : sa.getManaCost(); + final ManaCost mana = sa.getPayCosts() != null ? sa.getPayCosts().getTotalMana() : ManaCost.NO_COST; ManaCostBeingPaid cost = new ManaCostBeingPaid(mana); cost.applySpellCostChange(sa); diff --git a/src/main/java/forge/game/phase/CombatUtil.java b/src/main/java/forge/game/phase/CombatUtil.java index a9bc82bc7b0..82d7e4518c5 100644 --- a/src/main/java/forge/game/phase/CombatUtil.java +++ b/src/main/java/forge/game/phase/CombatUtil.java @@ -1123,13 +1123,14 @@ public class CombatUtil { * a boolean. */ public static void checkPropagandaEffects(final GameState game, final Card c) { - Cost attackCost = new Cost(c, "0", true); + Cost attackCost = new Cost(ManaCost.ZERO, true); // Sort abilities to apply them in proper order for (Card card : game.getCardsIn(ZoneType.Battlefield)) { final ArrayList staticAbilities = card.getStaticAbilities(); for (final StaticAbility stAb : staticAbilities) { Cost additionalCost = stAb.getCostAbility("CantAttackUnless", c, game.getCombat().getDefenderByAttacker(c)); - attackCost.add(additionalCost); + if ( null != additionalCost ) + attackCost.add(additionalCost); } } diff --git a/src/main/java/forge/game/phase/PhaseUtil.java b/src/main/java/forge/game/phase/PhaseUtil.java index 9a957d1ac3c..cca08a8747c 100644 --- a/src/main/java/forge/game/phase/PhaseUtil.java +++ b/src/main/java/forge/game/phase/PhaseUtil.java @@ -28,6 +28,7 @@ import forge.CardLists; import forge.CardPredicates.Presets; import forge.Singletons; import forge.card.cost.Cost; +import forge.card.mana.ManaCost; import forge.card.spellability.Ability; import forge.card.spellability.AbilityStatic; import forge.card.staticability.StaticAbility; @@ -212,13 +213,14 @@ public class PhaseUtil { for (Card blocker : filterList) { final List attackers = new ArrayList(combat.getAttackersBlockedBy(blocker)); for (Card attacker : attackers) { - Cost blockCost = new Cost(blocker, "0", true); + Cost blockCost = new Cost(ManaCost.ZERO, true); // Sort abilities to apply them in proper order for (Card card : game.getCardsIn(ZoneType.Battlefield)) { final ArrayList staticAbilities = card.getStaticAbilities(); for (final StaticAbility stAb : staticAbilities) { - Cost additionalCost = stAb.getCostAbility("CantBlockUnless", blocker, attacker); - blockCost = Cost.combine(blockCost, additionalCost); + Cost c1 = stAb.getCostAbility("CantBlockUnless", blocker, attacker); + if ( c1 != null ) + blockCost.add(c1); } } diff --git a/src/main/java/forge/game/phase/Upkeep.java b/src/main/java/forge/game/phase/Upkeep.java index d3d92dad5f9..949499d66fe 100644 --- a/src/main/java/forge/game/phase/Upkeep.java +++ b/src/main/java/forge/game/phase/Upkeep.java @@ -38,6 +38,7 @@ import forge.card.spellability.AbilityManaPart; import forge.card.spellability.AbilityStatic; import forge.card.spellability.SpellAbility; import forge.control.input.InputPayManaExecuteCommands; +import forge.control.input.InputPayment; import forge.control.input.InputSelectCards; import forge.control.input.InputSelectCardsFromList; import forge.game.GameActionUtil; @@ -169,7 +170,7 @@ public class Upkeep extends Phase { for (int i = 0; i < list.size(); i++) { final Card c = list.get(i); if (c.hasStartOfKeyword("(Echo unpaid)")) { - final Ability blankAbility = Upkeep.BlankAbility(c, c.getEchoCost()); + final Ability blankAbility = Upkeep.getBlankAbility(c, c.getEchoCost()); blankAbility.setActivatingPlayer(c.getController()); final StringBuilder sb = new StringBuilder(); @@ -181,7 +182,7 @@ public class Upkeep extends Phase { Player controller = c.getController(); if (controller.isHuman()) { - Cost cost = new Cost(c, c.getEchoCost().trim(), true); + Cost cost = new Cost(c.getEchoCost().trim(), true); if ( !GameActionUtil.payCostDuringAbilityResolve(blankAbility, cost, null, game) ) game.getAction().sacrifice(c, null);; @@ -275,7 +276,7 @@ public class Upkeep extends Phase { FThreads.setInputAndWait(inp); isUpkeepPaid = inp.isPaid(); } else { // computer - Ability aiPaid = Upkeep.BlankAbility(c, upkeepCost.toString()); + Ability aiPaid = Upkeep.getBlankAbility(c, upkeepCost.toString()); isUpkeepPaid = ComputerUtilCost.canPayCost(aiPaid, controller) && !c.hasKeyword("Indestructible"); if (isUpkeepPaid) { ComputerUtil.playNoStack((AIPlayer)controller, aiPaid, game); @@ -317,7 +318,7 @@ public class Upkeep extends Phase { } final String upkeepCost = cost; - final Ability blankAbility = Upkeep.BlankAbility(c, upkeepCost); + final Ability blankAbility = Upkeep.getBlankAbility(c, upkeepCost); blankAbility.setActivatingPlayer(controller); final Ability upkeepAbility = new Ability(c, ManaCost.ZERO) { @@ -360,7 +361,7 @@ public class Upkeep extends Phase { FThreads.setInputAndWait(inp); isUpkeepPaid = inp.isPaid(); } else { // computers - final Ability aiPaid = Upkeep.BlankAbility(c, upkeepCost.toString()); + final Ability aiPaid = Upkeep.getBlankAbility(c, upkeepCost.toString()); if (ComputerUtilCost.canPayCost(aiPaid, controller) && ComputerUtilCombat.predictDamageTo(controller, upkeepDamage, c, false) > 0) { ComputerUtil.playNoStack((AIPlayer)controller, aiPaid, game); isUpkeepPaid = true; @@ -395,13 +396,10 @@ public class Upkeep extends Phase { * a {@link java.lang.String} object. * @return a {@link forge.card.spellability.Ability} object. */ - private static Ability BlankAbility(final Card c, final String costString) { - Cost cost = new Cost(c, costString, true); - return new AbilityStatic(c, cost, null) { + public static Ability getBlankAbility(final Card c, final String costString) { + return new AbilityStatic(c, new Cost(costString, true), null) { @Override - public void resolve() { - - } + public void resolve() {} }; } @@ -601,7 +599,7 @@ public class Upkeep extends Phase { @Override public void resolve() { if (game.getZoneOf(c).is(ZoneType.Battlefield)) { - InputPayManaExecuteCommands inp = new InputPayManaExecuteCommands(cp, "Pay Demonic Hordes upkeep cost", cost.getManaCost() /*, true */); + InputPayment inp = new InputPayManaExecuteCommands(cp, "Pay Demonic Hordes upkeep cost", cost.getPayCosts().getTotalMana() /*, true */); FThreads.setInputAndWait(inp); if ( !inp.isPaid() ) unpaidHordesAb.resolve(); diff --git a/src/main/java/forge/game/player/HumanPlayer.java b/src/main/java/forge/game/player/HumanPlayer.java index 2f7444bdcf4..dfa4fc0f1bb 100644 --- a/src/main/java/forge/game/player/HumanPlayer.java +++ b/src/main/java/forge/game/player/HumanPlayer.java @@ -133,7 +133,7 @@ public class HumanPlayer extends Player { if (newAbility) { CostPayment payment = null; if (sa.getPayCosts() == null) { - payment = new CostPayment(new Cost(sa.getSourceCard(), "0", sa.isAbility()), sa); + payment = new CostPayment(new Cost("0", sa.isAbility()), sa); } else { payment = new CostPayment(sa.getPayCosts(), sa); } @@ -141,11 +141,10 @@ public class HumanPlayer extends Player { final HumanPlaySpellAbility req = new HumanPlaySpellAbility(sa, payment); req.fillRequirements(false, false, false); } else { - ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost()); + ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getPayCosts().getCostMana().getManaToPay()); if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { manaCost = new ManaCostBeingPaid("0"); } else { - manaCost = new ManaCostBeingPaid(sa.getManaCost()); manaCost.applySpellCostChange(sa); } @@ -191,11 +190,10 @@ public class HumanPlayer extends Player { req.fillRequirements(useOldTargets, false, true); } else { - ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost()); + ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getPayCosts().getTotalMana()); if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { manaCost = new ManaCostBeingPaid("0"); } else { - manaCost = new ManaCostBeingPaid(sa.getManaCost()); manaCost.applySpellCostChange(sa); } diff --git a/src/main/java/forge/game/player/Player.java b/src/main/java/forge/game/player/Player.java index a112d88a7bf..b7a5b7687d6 100644 --- a/src/main/java/forge/game/player/Player.java +++ b/src/main/java/forge/game/player/Player.java @@ -3036,7 +3036,7 @@ public abstract class Player extends GameEntity implements Comparable { } final SpellAbility playForMiracleCost = card.getFirstSpellAbility().copy(); - playForMiracleCost.setPayCosts(new Cost(card, card.getMiracleCost(), false)); + playForMiracleCost.setPayCosts(new Cost(card.getMiracleCost(), false)); playForMiracleCost.setStackDescription(card.getName() + " - Cast via Miracle"); // TODO Convert this to a Trigger