From 14697f587725fde822c183085c4b41e3dc69d28b Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 05:53:55 +0000 Subject: [PATCH] - Added SubCounter to Ability_Cost and appropriately pay for it in correct locations. - Minor checks for Cost_Payment requirements Note: SubCounter is not in any cards.txt yet, but has been tested with cards locally. Ex. Triskelion's ability would be: abDamageTgtCP SubCounter:1 --- src/forge/Ability_Cost.java | 47 ++++++++++++++++++++++ src/forge/CardFactory.java | 24 +++++------- src/forge/ComputerUtil.java | 53 +++++++++++++++---------- src/forge/Cost_Payment.java | 78 +++++++++++++++++++++++++++++++++---- 4 files changed, 159 insertions(+), 43 deletions(-) diff --git a/src/forge/Ability_Cost.java b/src/forge/Ability_Cost.java index 8b7bc341a17..dd2cd79b278 100644 --- a/src/forge/Ability_Cost.java +++ b/src/forge/Ability_Cost.java @@ -33,6 +33,16 @@ public class Ability_Cost { // future expansion of Ability_Cost class: untap, and lifeCost // private boolean untapCost = false; + private boolean subtractCounterCost = false; + public boolean getSubCounter() { return subtractCounterCost; } + private boolean addCounterCost = false; + public boolean getAddCounter() { return addCounterCost; } + + private int counterAmount = 0; + public int getCounterNum() { return counterAmount; } + private Counters counterType; + public Counters getCounterType() { return counterType; } + private boolean lifeCost = false; private int lifeAmount = 0; @@ -73,6 +83,22 @@ public class Ability_Cost { } } + if(parse.contains("SubCounter<")) { + // SubCounter//counters removed + subtractCounterCost = true; + int counterPos = parse.indexOf("SubCounter<"); + int endPos = parse.indexOf(">", counterPos); + String str = parse.substring(counterPos, endPos+1); + parse = parse.replace(str, "").trim(); + + str = str.replace("SubCounter<", ""); + str = str.replace(">", ""); + String[] strSplit = str.split("/"); + // convert strSplit[0] to Counter.something + counterType = Counters.valueOf(strSplit[0]); + counterAmount = Integer.parseInt(strSplit[1]); + } + if(parse.contains("Sac-")) { sacCost = true; int sacPos = parse.indexOf("Sac-"); @@ -105,6 +131,25 @@ public class Ability_Cost { cost.append("Tap"); else cost.append(", tap"); + caps = false; + } + + if (subtractCounterCost){ + if (caps) + cost.append("Remove "); + else + cost.append(", remove "); + if (counterAmount != 1) + cost.append(counterAmount); + else + cost.append("a"); + cost.append(" " + counterType.getName()); + cost.append(" counter"); + if (counterAmount != 1) + cost.append("s"); + cost.append(" from CARDNAME"); + + caps = false; } if (lifeCost){ @@ -113,6 +158,8 @@ public class Ability_Cost { else cost.append(", Pay"); cost.append(lifeAmount); + + caps = false; } cost.append(sacString(caps)); diff --git a/src/forge/CardFactory.java b/src/forge/CardFactory.java index a25e3ead2ab..c767b492e3a 100644 --- a/src/forge/CardFactory.java +++ b/src/forge/CardFactory.java @@ -1692,9 +1692,7 @@ public class CardFactory implements NewConstants { public boolean canPlayAI() { // temporarily disabled until AI is improved if (abCost.getSacCost()) return false; - - if (abCost.getTap() && (card.isTapped() || card.isSick())) - return false; + if (abCost.getSubCounter()) return false; if (!ComputerUtil.canPayCost(this)) return false; @@ -1745,10 +1743,8 @@ public class CardFactory implements NewConstants { @Override public boolean canPlay() { - if (abCost.getTap() && (card.isTapped() || card.isSick())) - return false; - - return (CardFactoryUtil.canUseAbility(card) && super.canPlay()); + Cost_Payment pay = new Cost_Payment(abCost, this); + return (pay.canPayAdditionalCosts() && CardFactoryUtil.canUseAbility(card) && super.canPlay()); } private CardList getCreatures() { @@ -2212,21 +2208,19 @@ public class CardFactory implements NewConstants { @Override public boolean canPlay(){ - if (abCost.getTap() && (card.isTapped() || card.isSick())) - return false; - - return (CardFactoryUtil.canUseAbility(card) && super.canPlay()); + Cost_Payment pay = new Cost_Payment(abCost, this); + return (pay.canPayAdditionalCosts() && CardFactoryUtil.canUseAbility(card) && super.canPlay()); } @Override public boolean canPlayAI() { - // temporarily disable sac canPlay until better AI - //if (abCost.getSacCost()) return false; - if (abCost.getTap() && (card.isTapped() || card.isSick())) - return false; + // temporarily disabled until better AI + if (abCost.getSacCost()) return false; + if (abCost.getSubCounter()) return false; if (!ComputerUtil.canPayCost(this)) return false; + damage = getNumDamage(); Random r = new Random(); // prevent run-away activations diff --git a/src/forge/ComputerUtil.java b/src/forge/ComputerUtil.java index 9e5991ab314..478513eecbf 100644 --- a/src/forge/ComputerUtil.java +++ b/src/forge/ComputerUtil.java @@ -216,28 +216,39 @@ public class ComputerUtil static public boolean canPayAdditionalCosts(SpellAbility sa) { - Ability_Cost cost = sa.getPayCosts(); - if (cost == null) - return true; + // Add additional cost checks here before attempting to activate abilities + Ability_Cost cost = sa.getPayCosts(); + if (cost == null) + return true; + Card card = sa.getSourceCard(); + + if (cost.getTap() && (card.isTapped() || card.isSick())) + return false; + + if (cost.getSubCounter()){ + Counters c = cost.getCounterType(); + if (card.getCounters(c) - cost.getCounterNum() < 0 || !AllZone.GameAction.isCardInPlay(card)){ + return false; + } + } - // check additional costs. - if (cost.getSacCost()){ - // if there's a sacrifice in the cost, just because we can Pay it doesn't mean we want to. - if (!cost.getSacThis()){ - String type = cost.getSacType(); - PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); - CardList typeList = new CardList(play.getCards()); - typeList = typeList.getType(type); - Card target = sa.getTargetCard(); - if (target != null && target.getController().equals(Constant.Player.Computer)) // don't sacrifice the card we're pumping - typeList.remove(target); - return typeList.size() > 0; - } - else if (cost.getSacThis() && AllZone.GameAction.isCardInPlay(sa.getSourceCard())) - return false; - } - - return true; + // check additional costs. + if (cost.getSacCost()){ + // if there's a sacrifice in the cost, just because we can Pay it doesn't mean we want to. + if (!cost.getSacThis()){ + String type = cost.getSacType(); + PlayerZone play = AllZone.getZone(Constant.Zone.Play, Constant.Player.Computer); + CardList typeList = new CardList(play.getCards()); + typeList = typeList.getType(type); + Card target = sa.getTargetCard(); + if (target != null && target.getController().equals(Constant.Player.Computer)) // don't sacrifice the card we're pumping + typeList.remove(target); + return typeList.size() > 0; + } + else if (cost.getSacThis() && !AllZone.GameAction.isCardInPlay(card)) + return false; + } + return true; } static public boolean canPayCost(String cost) diff --git a/src/forge/Cost_Payment.java b/src/forge/Cost_Payment.java index 71b3af17231..3b168d956f4 100644 --- a/src/forge/Cost_Payment.java +++ b/src/forge/Cost_Payment.java @@ -12,6 +12,7 @@ public class Cost_Payment { private boolean payTap = false; private boolean payMana = false; + private boolean paySubCounter = false; private boolean paySac = false; private boolean bCancel = false; private boolean bCasting = false; @@ -30,9 +31,38 @@ public class Cost_Payment { card = this.ability.getSourceCard(); payTap = !cost.getTap(); payMana = cost.hasNoManaCost(); + paySubCounter = !cost.getSubCounter(); paySac = !cost.getSacCost(); } + public boolean canPayAdditionalCosts(){ + if (cost.getTap() && (card.isTapped() || card.isSick())) + return false; + + int countersLeft = 0; + if (cost.getSubCounter()){ + Counters c = cost.getCounterType(); + countersLeft = card.getCounters(c) - cost.getCounterNum(); + if (countersLeft < 0){ + return false; + } + } + + if (cost.getSacCost()){ + if (!cost.getSacThis()){ + PlayerZone play = AllZone.getZone(Constant.Zone.Play, card.getController()); + CardList typeList = new CardList(play.getCards()); + typeList = typeList.getType(cost.getSacType()); + if (typeList.size() == 0) + return false; + } + else if (cost.getSacThis() && !AllZone.GameAction.isCardInPlay(card)) + return false; + } + + return true; + } + public boolean payCost(){ if (bCancel || bDoneTarget && cost.getNumTargeted() < cost.getMinTargets()){ cancelPayment(); @@ -71,8 +101,22 @@ public class Cost_Payment { if (!payMana && !cost.hasNoManaCost()){ // pay mana here changeInput.stopSetNext(new Input_PayCostMana(this)); + return false; } - else if (!paySac && cost.getSacCost()) + if (!paySubCounter && cost.getSubCounter()){ + // subtract counters here. + Counters c = cost.getCounterType(); + int countersLeft = card.getCounters(c) - cost.getCounterNum(); + if (countersLeft >= 0){ + card.setCounter(c, countersLeft); + paySubCounter = true; + } + else{ + cancelPayment(); + return false; + } + } + if (!paySac && cost.getSacCost()) { // sacrifice stuff here if (cost.getSacThis()) @@ -82,10 +126,14 @@ public class Cost_Payment { return false; } - if (payTap && payMana && paySac) + if (isAllPaid()) allPaid(); return true; } + + public boolean isAllPaid(){ + return (payTap && payMana && paySubCounter && paySac); + } public void allPaid(){ AllZone.ManaPool.clearPay(false); @@ -106,6 +154,14 @@ public class Cost_Payment { } // refund mana AllZone.ManaPool.unpaid(); + + // refund counters + if (cost.getSubCounter() && paySubCounter){ + Counters c = cost.getCounterType(); + int countersLeft = card.getCounters(c) + cost.getCounterNum(); + card.setCounter(c, countersLeft); + } + // can't really unsacrifice things } @@ -303,7 +359,7 @@ public class Cost_Payment { if (cost.doesTarget()) ability.chooseTargetAI(); - // make sure something is there to be sacrificed before going through payments + // double check if something can be sacrificed here. Real check is in ComputerUtil.canPayAdditionalCosts() if (cost.getSacCost()){ if (cost.getSacThis()) sacCard = card; @@ -315,18 +371,26 @@ public class Cost_Payment { return; } } + // double check if counters available? Real check is in ComputerUtil.canPayAdditionalCosts() + int countersLeft = 0; + if (cost.getSubCounter()){ + Counters c = cost.getCounterType(); + countersLeft = card.getCounters(c) - cost.getCounterNum(); + if (countersLeft < 0){ + System.out.println("Not enough " + c.getName() + " on "+card.getName()); + return; + } + } if (cost.getTap()) card.tap(); if (!cost.hasNoManaCost()) ComputerUtil.payManaCost(ability); + if (cost.getSubCounter()) + card.setCounter(cost.getCounterType(), countersLeft); if (cost.getSacCost()) AllZone.GameAction.sacrifice(sacCard); AllZone.Stack.add(ability); } - - - - }