diff --git a/src/main/java/forge/card/cost/Cost.java b/src/main/java/forge/card/cost/Cost.java index a42fd9e9ff5..69ceb73afb5 100644 --- a/src/main/java/forge/card/cost/Cost.java +++ b/src/main/java/forge/card/cost/Cost.java @@ -136,10 +136,13 @@ public class Cost { while (parse.contains(addStr)) { // AddCounter - String[] splitStr = abCostParse(parse, addStr, 2); + String[] splitStr = abCostParse(parse, addStr, 4); parse = abUpdateParse(parse, addStr); - costParts.add(new CostPutCounter(splitStr[0], Counters.valueOf(splitStr[1]))); + String type = splitStr.length > 2 ? splitStr[2] : "CARDNAME"; + String description = splitStr.length > 3 ? splitStr[3] : null; + + costParts.add(new CostPutCounter(splitStr[0], Counters.valueOf(splitStr[1]), type, description)); } // While no card has "PayLife<2> PayLife<3> there might be a card that Changes Cost by adding a Life Payment diff --git a/src/main/java/forge/card/cost/CostPartWithList.java b/src/main/java/forge/card/cost/CostPartWithList.java index a18d314dc59..7d1f9c13379 100644 --- a/src/main/java/forge/card/cost/CostPartWithList.java +++ b/src/main/java/forge/card/cost/CostPartWithList.java @@ -9,7 +9,12 @@ public abstract class CostPartWithList extends CostPart { public CardList getList() { return list; } public void setList(CardList setList) { list = setList; } public void resetList() { list = new CardList(); } - public void addToList(Card c) { list.add(c); } + public void addToList(Card c) { + if (list == null){ + resetList(); + } + list.add(c); + } public void addListToHash(SpellAbility sa, String hash){ for(Card card : list){ diff --git a/src/main/java/forge/card/cost/CostPutCounter.java b/src/main/java/forge/card/cost/CostPutCounter.java index 17b50966e67..ff09e49c07b 100644 --- a/src/main/java/forge/card/cost/CostPutCounter.java +++ b/src/main/java/forge/card/cost/CostPutCounter.java @@ -1,87 +1,230 @@ package forge.card.cost; +import forge.AllZone; +import forge.ButtonUtil; import forge.Card; +import forge.CardList; import forge.Counters; import forge.Player; +import forge.PlayerZone; +import forge.Constant.Zone; import forge.card.abilityFactory.AbilityFactory; +import forge.card.cardFactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; +import forge.gui.input.Input; -public class CostPutCounter extends CostPart { - // Put Counter doesn't really have a "Valid" portion of the cost +public class CostPutCounter extends CostPartWithList { + // Put Counter doesn't really have a "Valid" portion of the cost private Counters counter; private int lastPaidAmount = 0; public Counters getCounter() { return counter; } - - public void setLastPaidAmount(int paidAmount){ + + public void setLastPaidAmount(int paidAmount) { lastPaidAmount = paidAmount; } - - public CostPutCounter(String amount, Counters counter){ - this.type = "CARDNAME"; + + public CostPutCounter(String amount, Counters cntr, String type, String description) { isReusable = true; this.amount = amount; - this.counter = counter; + this.counter = cntr; + + this.type = type; + this.typeDescription = description; } @Override public String toString() { StringBuilder sb = new StringBuilder(); - if (counter.getName().equals("Loyalty")) + if (counter.getName().equals("Loyalty")) { sb.append("+").append(amount); + } else { sb.append("Put "); Integer i = convertAmount(); sb.append(Cost.convertAmountTypeToWords(i, amount, counter.getName())); - sb.append(" on ").append(type); + sb.append(" on "); + if (getThis()){ + sb.append(type); + } + else { + String desc = typeDescription == null ? type : typeDescription; + sb.append(desc); + } } return sb.toString(); } @Override public void refund(Card source) { - source.subtractCounter(counter, lastPaidAmount); + for(Card c : list) { + c.subtractCounter(counter, lastPaidAmount); + } } @Override public boolean canPay(SpellAbility ability, Card source, Player activator, Cost cost) { + if (getThis()) { + if (source.hasKeyword("CARDNAME can't have counters placed on it.")) { + return false; + } + if (source.hasKeyword("CARDNAME can't have -1/-1 counters placed on it.") + && counter.equals(Counters.M1M1)) { + return false; + } + } + else { + // 3 Cards have Put a -1/-1 Counter on a Creature you control. + CardList typeList = activator.getCardsIn(Zone.Battlefield) + .getValidCards(getType().split(";"), activator, source); - if(source.hasKeyword("CARDNAME can't have counters placed on it.")) { - return false; + if (typeList.size() == 0) { + return false; + } } - if (source.hasKeyword("CARDNAME can't have -1/-1 counters placed on it.") && counter.equals(Counters.M1M1)) { - return false; - } - + return true; } @Override public void payAI(SpellAbility ability, Card source, Cost_Payment payment) { Integer c = convertAmount(); - if (c == null){ + if (c == null) { c = AbilityFactory.calculateAmount(source, amount, ability); } - source.addCounterFromNonEffect(getCounter(), c); + + if (getThis()) { + source.addCounterFromNonEffect(getCounter(), c); + } + else { + // Put counter on chosen card + for(Card card : list) { + card.addCounterFromNonEffect(getCounter(), 1); + } + } } @Override public boolean payHuman(SpellAbility ability, Card source, Cost_Payment payment) { Integer c = convertAmount(); - if (c == null){ + if (c == null) { c = AbilityFactory.calculateAmount(source, amount, ability); } - - source.addCounterFromNonEffect(getCounter(), c); - payment.setPaidManaPart(this, true); - return true; + + if (getThis()) { + source.addCounterFromNonEffect(getCounter(), c); + payment.setPaidManaPart(this, true); + addToList(source); + return true; + } + else { + CostUtil.setInput(putCounterType(ability, getType(), payment, this, c)); + return false; + } } @Override public boolean decideAIPayment(SpellAbility ability, Card source, Cost_Payment payment) { + resetList(); + if (getThis()) { + addToList(source); + return true; + } + else { + Player activator = ability.getActivatingPlayer(); + Integer c = convertAmount(); + if (c == null) { + c = AbilityFactory.calculateAmount(source, amount, ability); + } + + CardList typeList = activator.getCardsIn(Zone.Battlefield) + .getValidCards(getType().split(";"), activator, source); + + Card card = null; + if (type.equals("Creature.YouCtrl")) { + card = CardFactoryUtil.AI_getWorstCreature(typeList); + } + else { + card = CardFactoryUtil.AI_getWorstPermanent(typeList, false, false, false, false); + } + addToList(card); + } return true; } + + /** + *

returnType.

+ * + * @param sa a {@link forge.card.spellability.SpellAbility} object. + * @param type a {@link java.lang.String} object. + * @param payment a {@link forge.card.cost.Cost_Payment} object. + * @param costPutCounter TODO + * @return a {@link forge.gui.input.Input} object. + */ + public static Input putCounterType(final SpellAbility sa, final String type, final Cost_Payment payment, final CostPutCounter costPutCounter, final int nNeeded) { + Input target = new Input() { + private static final long serialVersionUID = 2685832214519141903L; + private CardList typeList; + private int nPut = 0; + + @Override + public void showMessage() { + if (nNeeded == 0 || nNeeded == nPut) { + done(); + } + + StringBuilder msg = new StringBuilder("Put "); + int nLeft = nNeeded - nPut; + msg.append(nLeft).append(" "); + msg.append(costPutCounter.getCounter()).append(" on "); + + msg.append(costPutCounter.getDescriptiveType()); + if (nLeft > 1) { + msg.append("s"); + } + + typeList = sa.getActivatingPlayer().getCardsIn(Zone.Battlefield); + typeList = typeList.getValidCards(type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard()); + AllZone.getDisplay().showMessage(msg.toString()); + ButtonUtil.enableOnlyCancel(); + } + + @Override + public void selectButtonCancel() { + cancel(); + } + + @Override + public void selectCard(final Card card, final PlayerZone zone) { + if (typeList.contains(card)) { + nPut++; + costPutCounter.addToList(card); + card.addCounterFromNonEffect(costPutCounter.getCounter(), 1); + + if (nNeeded == nPut) { + done(); + } + else{ + showMessage(); + } + } + } + + public void done() { + stop(); + payment.paidCost(costPutCounter); + } + + public void cancel() { + stop(); + costPutCounter.addListToHash(sa, "CounterPut"); + payment.cancelCost(); + } + }; + + return target; + } } diff --git a/src/main/java/forge/card/cost/CostReturn.java b/src/main/java/forge/card/cost/CostReturn.java index cef2a249fbc..c669fba3a29 100644 --- a/src/main/java/forge/card/cost/CostReturn.java +++ b/src/main/java/forge/card/cost/CostReturn.java @@ -146,7 +146,7 @@ public class CostReturn extends CostPartWithList { msg.append("s"); } - typeList = sa.getSourceCard().getController().getCardsIn(Zone.Battlefield); + typeList = sa.getActivatingPlayer().getCardsIn(Zone.Battlefield); typeList = typeList.getValidCards(type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard()); AllZone.getDisplay().showMessage(msg.toString()); ButtonUtil.enableOnlyCancel();