From 0be4ad70da3a6fb95e4cbbde42ba728052f9ebc8 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Fri, 5 Apr 2013 22:01:32 +0000 Subject: [PATCH] Infrastructure for Myr Superion (part 1) - added alt syntax for mana cost: Mana<3 U W\Creature> - backslash is intentional --- src/main/java/forge/card/cost/Cost.java | 43 ++++++++++--------- .../java/forge/card/cost/CostPartMana.java | 15 ++++++- .../java/forge/card/cost/CostPayment.java | 2 +- src/main/java/forge/card/cost/CostUtil.java | 6 ++- .../card/spellability/SpellPermanent.java | 23 ++-------- src/main/java/forge/util/TextUtil.java | 21 +++++---- 6 files changed, 56 insertions(+), 54 deletions(-) diff --git a/src/main/java/forge/card/cost/Cost.java b/src/main/java/forge/card/cost/Cost.java index 66ce7a4caa9..d3d0cb34bf0 100644 --- a/src/main/java/forge/card/cost/Cost.java +++ b/src/main/java/forge/card/cost/Cost.java @@ -51,24 +51,12 @@ public class Cost { return this.costParts; } - private boolean sacCost = false; private boolean tapCost = false; - private boolean untapCost = false; - - - public final boolean getSacCost() { - return this.sacCost; - } - public final boolean hasTapCost() { return this.tapCost; } - public final boolean hasUntapCost() { - return this.untapCost; - } - /** *

* hasNoManaCost. @@ -140,6 +128,7 @@ public class Cost { this.name = card != null ? card.getName() : ""; boolean xCantBe0 = false; + boolean untapCost = false; StringBuilder manaParts = new StringBuilder(); String[] parts = TextUtil.splitWithParenthesis(parse, ' ', '<', '>'); @@ -149,30 +138,38 @@ public class Cost { if ( part.equals("T") || part.equals("Tap") ) this.tapCost = true; if ( part.equals("Q") || part.equals("Untap") ) - this.untapCost = true; + untapCost = true; } + CostPartMana parsedMana = null; for(String part : parts) { if( "XCantBe0".equals(part) ) xCantBe0 = true; else { CostPart cp = parseCostPart(part, tapCost, untapCost); if ( null != cp ) - this.costParts.add(cp); + if ( cp instanceof CostPartMana ) { + parsedMana = (CostPartMana) cp; + } else { + this.costParts.add(cp); + } else manaParts.append(part).append(" "); } } - if (manaParts.length() > 0) { - this.costParts.add(0, new CostPartMana(new ManaCost(new ManaCostParser(manaParts.toString())), xCantBe0)); + if ( parsedMana == null && manaParts.length() > 0) { + parsedMana = new CostPartMana(new ManaCost(new ManaCostParser(manaParts.toString())), null, xCantBe0); + } + if ( parsedMana != null ) { + this.costParts.add(0, parsedMana); } + // inspect parts to set Sac, {T} and {Q} flags for (int iCp = 0; iCp < costParts.size(); iCp++) { CostPart cp = costParts.get(iCp); - if( cp instanceof CostSacrifice ) sacCost = true; // my guess why Q/T are to be first and are followed by mana parts // is because Q/T are undoable and mana is interactive, so it well be easy to rollback if player refuses to pay @@ -189,6 +186,13 @@ public class Cost { private static CostPart parseCostPart(String parse, boolean tapCost, boolean untapCost) { + if(parse.startsWith("Mana<")) { + final String[] splitStr = TextUtil.split(abCostParse(parse, 1)[0], '\\'); + final String restriction = splitStr.length > 1 ? splitStr[1] : null; + final boolean xCantBe0 = splitStr.length > 1 && splitStr[1].equals("XCantBe0"); + return new CostPartMana(new ManaCost(new ManaCostParser(splitStr[0])), xCantBe0 ? null : restriction, xCantBe0); + } + if(parse.startsWith("tapXType<")) { final String[] splitStr = abCostParse(parse, 3); final String description = splitStr.length > 2 ? splitStr[2] : null; @@ -342,8 +346,7 @@ public class Cost { final int startPos = 1 + parse.indexOf("<"); final int endPos = parse.indexOf(">", startPos); String str = parse.substring(startPos, endPos); - - final String[] splitStr = str.split("/", numParse); + final String[] splitStr = TextUtil.split(str, '/', numParse); return splitStr; } @@ -372,7 +375,7 @@ public class Cost { // Spells with a cost of 0 should be affected too final ManaCostBeingPaid changedCost = new ManaCostBeingPaid("0"); changedCost.applySpellCostChange(sa); - this.costParts.add(new CostPartMana(changedCost.toManaCost(), false)); + this.costParts.add(new CostPartMana(changedCost.toManaCost(), null, false)); } } diff --git a/src/main/java/forge/card/cost/CostPartMana.java b/src/main/java/forge/card/cost/CostPartMana.java index 14c74e1b5b0..e175a97c58e 100644 --- a/src/main/java/forge/card/cost/CostPartMana.java +++ b/src/main/java/forge/card/cost/CostPartMana.java @@ -40,6 +40,7 @@ public class CostPartMana extends CostPart { private final ManaCost cost; private ManaCost adjustedCost; private boolean xCantBe0 = false; + private final String restriction; /** * Instantiates a new cost mana. @@ -50,9 +51,10 @@ public class CostPartMana extends CostPart { * the amount * @param xCantBe0 TODO */ - public CostPartMana(final ManaCost cost, boolean xCantBe0) { + public CostPartMana(final ManaCost cost, String restriction, boolean xCantBe0) { this.cost = cost; - this.xCantBe0 = xCantBe0; // TODO: Add 0 to parameter's name. + this.xCantBe0 = xCantBe0; + this.restriction = restriction; } /** @@ -172,4 +174,13 @@ public class CostPartMana extends CostPart { public PaymentDecision decideAIPayment(AIPlayer ai, SpellAbility ability, Card source) { return new PaymentDecision(0); } + + /** + * TODO: Write javadoc for this method. + * @return + */ + public String getRestiction() { + // TODO Auto-generated method stub + return restriction; + } } diff --git a/src/main/java/forge/card/cost/CostPayment.java b/src/main/java/forge/card/cost/CostPayment.java index 706440f03e4..7a593662451 100644 --- a/src/main/java/forge/card/cost/CostPayment.java +++ b/src/main/java/forge/card/cost/CostPayment.java @@ -180,7 +180,7 @@ public class CostPayment { final List parts = this.cost.getCostParts(); if (this.getCost().getCostMana() == null) { - parts.add(new CostPartMana(ManaCost.ZERO, false)); + parts.add(new CostPartMana(ManaCost.ZERO, null, false)); } Map, PaymentDecision> decisions = new HashMap, PaymentDecision>(); diff --git a/src/main/java/forge/card/cost/CostUtil.java b/src/main/java/forge/card/cost/CostUtil.java index c261d0def7a..935796ca951 100644 --- a/src/main/java/forge/card/cost/CostUtil.java +++ b/src/main/java/forge/card/cost/CostUtil.java @@ -135,9 +135,11 @@ public class CostUtil { ManaCostBeingPaid oldManaCost = new ManaCostBeingPaid(((CostPartMana) part).getMana()); boolean xCanBe0 = ((CostPartMana) part).canXbe0() && costPart2.canXbe0(); oldManaCost.combineManaCost(costPart2.getMana()); - + String r2 = costPart2.getRestiction(); + String r1 = ((CostPartMana) part).getRestiction(); + String r = r1 == null ? r2 : ( r2 == null ? r1 : r1+"."+r2); cost2.getCostParts().remove(costPart2); - cost2.getCostParts().add(0, new CostPartMana(oldManaCost.toManaCost(), !xCanBe0)); + cost2.getCostParts().add(0, new CostPartMana(oldManaCost.toManaCost(), r, !xCanBe0)); } else { cost2.getCostParts().add(part); } diff --git a/src/main/java/forge/card/spellability/SpellPermanent.java b/src/main/java/forge/card/spellability/SpellPermanent.java index a4539088000..d09d96b9aa3 100644 --- a/src/main/java/forge/card/spellability/SpellPermanent.java +++ b/src/main/java/forge/card/spellability/SpellPermanent.java @@ -70,22 +70,6 @@ public class SpellPermanent extends Spell { this(sourceCard, new Cost(sourceCard, sourceCard.getManaCost(), false), null); } // Spell_Permanent() - /** - *

- * Constructor for Spell_Permanent. - *

- * - * @param sourceCard - * a {@link forge.Card} object. - * @param cost - * a {@link forge.card.cost.Cost} object. - * @param tgt - * a {@link forge.card.spellability.Target} object. - */ - public SpellPermanent(final Card sourceCard, final Cost cost, final Target tgt) { - this(sourceCard, cost, tgt, true); - } // Spell_Permanent() - /** * Instantiates a new spell_ permanent. * @@ -98,7 +82,7 @@ public class SpellPermanent extends Spell { * @param setDesc * the set desc */ - public SpellPermanent(final Card sourceCard, final Cost cost, final Target tgt, final boolean setDesc) { + public SpellPermanent(final Card sourceCard, final Cost cost, final Target tgt) { super(sourceCard, cost, tgt); if (sourceCard.isCreature()) { @@ -110,9 +94,8 @@ public class SpellPermanent extends Spell { this.setStackDescription(sourceCard.getName()); } - if (setDesc) { - this.setDescription(this.getStackDescription()); - } + + this.setDescription(this.getStackDescription()); if (this.getManaCost().countX() > 0) { if (!this.getSourceCard().getSVar("X").equals("")) { diff --git a/src/main/java/forge/util/TextUtil.java b/src/main/java/forge/util/TextUtil.java index 99795041f94..df55cd34510 100644 --- a/src/main/java/forge/util/TextUtil.java +++ b/src/main/java/forge/util/TextUtil.java @@ -41,34 +41,37 @@ public class TextUtil { } public static String[] split(CharSequence input, char delimiter) { - return splitWithParenthesis(input, delimiter, '\0', '\0', true); + return splitWithParenthesis(input, delimiter, Integer.MAX_VALUE, '\0', '\0', true); } - - public static String[] split(CharSequence input, char delimiter, boolean skipEmpty) { - return splitWithParenthesis(input, delimiter, '\0', '\0', skipEmpty); + + public static String[] split(CharSequence input, char delimiter, int limit) { + return splitWithParenthesis(input, delimiter, limit, '\0', '\0', true); } - + public static String[] splitWithParenthesis(CharSequence input, char delimiter, char openPar, char closePar) { - return splitWithParenthesis(input, delimiter, openPar, closePar, true); + return splitWithParenthesis(input, delimiter, Integer.MAX_VALUE, openPar, closePar, true); } /** * Split string separated by a single char delimiter, can take parenthesis in account * It's faster than String.split, and allows parenthesis */ - public static String[] splitWithParenthesis(CharSequence input, char delimiter, char openPar, char closePar, boolean skipEmpty) { + public static String[] splitWithParenthesis(CharSequence input, char delimiter, int maxEntries, char openPar, char closePar, boolean skipEmpty) { List result = new ArrayList(); int nPar = 0; int len = input.length(); int start = 0; + int idx = 1; for (int iC = 0; iC < len; iC++ ) { char c = input.charAt(iC); if( openPar > 0 && c == openPar ) nPar++; if( closePar > 0 && c == closePar ) { nPar = nPar > 0 ? nPar - 1 : 0; } - if( c == delimiter && nPar == 0) { - if( iC > start || !skipEmpty ) + if( c == delimiter && nPar == 0 && idx < maxEntries) { + if( iC > start || !skipEmpty ) { result.add(input.subSequence(start, iC).toString()); + idx++; + } start = iC + 1; } }