diff --git a/src/main/java/forge/card/ability/ai/DrawAi.java b/src/main/java/forge/card/ability/ai/DrawAi.java index 896dbc28131..c77833996f0 100644 --- a/src/main/java/forge/card/ability/ai/DrawAi.java +++ b/src/main/java/forge/card/ability/ai/DrawAi.java @@ -19,7 +19,6 @@ package forge.card.ability.ai; import java.util.ArrayList; -import java.util.List; import java.util.Random; import forge.Card; @@ -72,8 +71,7 @@ public class DrawAi extends SpellAbilityAi { if (part instanceof CostDiscard) { CostDiscard cd = (CostDiscard) part; cd.decideAIPayment((AIPlayer) ai, sa, sa.getSourceCard(), null); - List discards = cd.getList(); - for (Card discard : discards) { + for (Card discard : cd.getList()) { if (!ComputerUtil.isWorseThanDraw(ai, discard)) { return false; } diff --git a/src/main/java/forge/card/cost/CostDamage.java b/src/main/java/forge/card/cost/CostDamage.java index 18155737fad..7f290b3705d 100644 --- a/src/main/java/forge/card/cost/CostDamage.java +++ b/src/main/java/forge/card/cost/CostDamage.java @@ -103,10 +103,11 @@ public class CostDamage extends CostPart { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { final String amount = this.getAmount(); final Player activator = ability.getActivatingPlayer(); final int life = activator.getLife(); + final Card source = ability.getSourceCard(); Integer c = this.convertAmount(); if (c == null) { @@ -124,10 +125,10 @@ public class CostDamage extends CostPart { if (GuiDialog.confirm(source, sb.toString()) && activator.canPayLife(c)) { activator.addDamage(c, source); - this.setLastPaidAmount(c); } else { - payment.setCancel(true); + return false; } + return true; } /* diff --git a/src/main/java/forge/card/cost/CostDiscard.java b/src/main/java/forge/card/cost/CostDiscard.java index ad54dbb1253..fae93cd3709 100644 --- a/src/main/java/forge/card/cost/CostDiscard.java +++ b/src/main/java/forge/card/cost/CostDiscard.java @@ -28,6 +28,7 @@ import forge.FThreads; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.player.AIPlayer; import forge.game.player.Player; @@ -56,6 +57,7 @@ public class CostDiscard extends CostPartWithList { private static final long serialVersionUID = -329993322080934435L; private int nDiscard = 0; private boolean sameName; + private String firstName = null; private final SpellAbility sa; @@ -69,8 +71,7 @@ public class CostDiscard extends CostPartWithList { * @param sp * @param discType */ - public InputPayCostDiscard(SpellAbility sa, List handList, CostDiscard part, CostPayment payment, int nNeeded, String discType) { - super(payment); + public InputPayCostDiscard(SpellAbility sa, List handList, CostDiscard part, int nNeeded, String discType) { this.sa = sa; this.handList = handList; this.part = part; @@ -111,18 +112,18 @@ public class CostDiscard extends CostPartWithList { public void selectCard(final Card card) { Zone zone = Singletons.getModel().getGame().getZoneOf(card); if (zone.is(ZoneType.Hand) && handList.contains(card)) { - if (!sameName || part.getList().isEmpty() - || part.getList().get(0).getName().equals(card.getName())) { + if (!sameName || part.getList().isEmpty()|| firstName.equals(card.getName()) ) { + if( part.getList().isEmpty() ) + firstName = card.getName(); // send in List for Typing - card.getController().discard(card, sa); - part.addToList(card); + part.executePayment(sa, card); handList.remove(card); this.nDiscard++; // in case no more cards in hand if (this.nDiscard == nNeeded) { this.done(); - } else if (sa.getActivatingPlayer().getZone(ZoneType.Hand).size() == 0) { + } else if (sa.getActivatingPlayer().getZone(ZoneType.Hand).isEmpty()) { // really // shouldn't // happen @@ -247,7 +248,7 @@ public class CostDiscard extends CostPartWithList { @Override public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { for (final Card c : this.getList()) { - ai.discard(c, ability); + executePayment(ability, c); } } @@ -259,8 +260,9 @@ public class CostDiscard extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { final Player activator = ability.getActivatingPlayer(); + final Card source = ability.getSourceCard(); List handList = new ArrayList(activator.getCardsIn(ZoneType.Hand)); String discardType = this.getType(); final String amount = this.getAmount(); @@ -268,23 +270,22 @@ public class CostDiscard extends CostPartWithList { if (this.payCostFromSource()) { if (!handList.contains(source)) { - payment.setCancel(true); + return false; } - activator.discard(source, ability); - payment.setPaidPart(this); + executePayment(ability, source); + return true; //this.addToList(source); } else if (discardType.equals("Hand")) { this.setList(handList); activator.discardHand(ability); - payment.setPaidPart(this); + return true; } else if (discardType.equals("LastDrawn")) { final Card lastDrawn = activator.getLastDrawnCard(); - this.addToList(lastDrawn); if (!handList.contains(lastDrawn)) { - payment.setCancel(true); + return false; } - activator.discard(lastDrawn, ability); - payment.setPaidPart(this); + executePayment(ability, lastDrawn); + return true; } else { Integer c = this.convertAmount(); @@ -300,7 +301,7 @@ public class CostDiscard extends CostPartWithList { } this.setList(activator.discardRandom(c, ability)); - payment.setPaidPart(this); + return true; } else { String type = new String(discardType); boolean sameName = false; @@ -335,11 +336,11 @@ public class CostDiscard extends CostPartWithList { } } - FThreads.setInputAndWait(new InputPayCostDiscard(ability, handList, this, payment, c, discardType)); + InputPayment inp = new InputPayCostDiscard(ability, handList, this, c, discardType); + FThreads.setInputAndWait(inp); + return inp.isPaid(); } } - if ( !payment.isCanceled()) - this.addListToHash(ability, "Discarded"); } /* @@ -396,6 +397,23 @@ public class CostDiscard extends CostPartWithList { return this.getList() != null; } + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + this.addToList(targetCard); + targetCard.getController().discard(targetCard, ability); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "Discarded"; + } + // Inputs } diff --git a/src/main/java/forge/card/cost/CostExile.java b/src/main/java/forge/card/cost/CostExile.java index 2f1f260ff1f..9f1e1fef2c0 100644 --- a/src/main/java/forge/card/cost/CostExile.java +++ b/src/main/java/forge/card/cost/CostExile.java @@ -23,15 +23,17 @@ import java.util.List; import forge.Card; import forge.CardLists; import forge.CardPredicates; +import forge.FThreads; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityStackInstance; -import forge.control.input.InputSynchronized; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.ai.ComputerUtil; import forge.game.player.AIPlayer; import forge.game.player.Player; +import forge.game.zone.MagicStack; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; import forge.gui.GuiDialog; @@ -65,8 +67,7 @@ public class CostExile extends CostPartWithList { * @param payment * @param part */ - private InputExileFrom(SpellAbility sa, String type, int nNeeded, CostPayment payment, CostExile part) { - super(payment); + private InputExileFrom(SpellAbility sa, String type, int nNeeded, CostExile part) { this.sa = sa; this.type = type; this.nNeeded = nNeeded; @@ -91,8 +92,7 @@ public class CostExile extends CostPartWithList { if (c != null) { this.typeList.remove(c); - part.addToList(c); - Singletons.getModel().getGame().getAction().exile(c); + part.executePayment(sa, c); if (i == (nNeeded - 1)) { this.done(); } @@ -125,8 +125,7 @@ public class CostExile extends CostPartWithList { * @param nNeeded * @param payableZone */ - private InputExileFromSame(List list, CostExile part, CostPayment payment, int nNeeded, List payableZone) { - super(payment); + private InputExileFromSame(List list, CostExile part, int nNeeded, List payableZone) { this.list = list; this.part = part; this.nNeeded = nNeeded; @@ -160,8 +159,7 @@ public class CostExile extends CostPartWithList { if (c != null) { this.typeList.remove(c); - part.addToList(c); - Singletons.getModel().getGame().getAction().exile(c); + part.executePayment(null, c); if (i == (nNeeded - 1)) { this.done(); } @@ -195,8 +193,7 @@ public class CostExile extends CostPartWithList { * @param nNeeded * @param part */ - private InputExileFromStack(CostPayment payment, SpellAbility sa, String type, int nNeeded, CostExile part) { - super(payment); + private InputExileFromStack(SpellAbility sa, String type, int nNeeded, CostExile part) { this.sa = sa; this.type = type; this.nNeeded = nNeeded; @@ -211,10 +208,11 @@ public class CostExile extends CostPartWithList { saList = new ArrayList(); descList = new ArrayList(); + final MagicStack stack = sa.getActivatingPlayer().getGame().getStack(); - for (int i = 0; i < Singletons.getModel().getGame().getStack().size(); i++) { - final Card stC = Singletons.getModel().getGame().getStack().peekAbility(i).getSourceCard(); - final SpellAbility stSA = Singletons.getModel().getGame().getStack().peekAbility(i).getRootAbility(); + for (int i = 0; i < stack.size(); i++) { + final Card stC = stack.peekAbility(i).getSourceCard(); + final SpellAbility stSA = stack.peekAbility(i).getRootAbility(); if (stC.isValid(type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard()) && stSA.isSpell()) { this.saList.add(stSA); if (stC.isCopiedSpell()) { @@ -236,16 +234,19 @@ public class CostExile extends CostPartWithList { if (o != null) { final SpellAbility toExile = this.saList.get(descList.indexOf(o)); final Card c = toExile.getSourceCard(); + + this.saList.remove(toExile); - part.addToList(c); if (!c.isCopiedSpell()) { - Singletons.getModel().getGame().getAction().exile(c); - } + part.executePayment(sa, c); + } else + part.addToList(c); + if (i == (nNeeded - 1)) { this.done(); } - final SpellAbilityStackInstance si = Singletons.getModel().getGame().getStack().getInstanceFromSpellAbility(toExile); - Singletons.getModel().getGame().getStack().remove(si); + final SpellAbilityStackInstance si = stack.getInstanceFromSpellAbility(toExile); + stack.remove(si); } else { this.cancel(); break; @@ -275,8 +276,7 @@ public class CostExile extends CostPartWithList { * @param nNeeded * @param sa */ - private InputExileType(CostExile part, CostPayment payment, String type, int nNeeded, SpellAbility sa) { - super(payment); + private InputExileType(CostExile part, String type, int nNeeded, SpellAbility sa) { this.part = part; this.type = type; this.nNeeded = nNeeded; @@ -312,8 +312,7 @@ public class CostExile extends CostPartWithList { public void selectCard(final Card card) { if (this.typeList.contains(card)) { this.nExiles++; - part.addToList(card); - Singletons.getModel().getGame().getAction().exile(card); + part.executePayment(sa, card); this.typeList.remove(card); // in case nothing else to exile if (this.nExiles == nNeeded) { @@ -343,8 +342,7 @@ public class CostExile extends CostPartWithList { * @param part * @param sa */ - private InputExileThis(CostPayment payment, CostExile part, SpellAbility sa) { - super(payment); + private InputExileThis(CostExile part, SpellAbility sa) { this.part = part; this.sa = sa; } @@ -354,9 +352,7 @@ public class CostExile extends CostPartWithList { if ( sa.getActivatingPlayer().getZone(part.getFrom()).contains(card)) { boolean choice = GuiDialog.confirm(card, card.getName() + " - Exile?"); if (choice) { - Singletons.getModel().getGame().getAction().exile(card); - part.addToList(card); - part.addListToHash(sa, "Exiled"); + part.executePayment(sa, card); done(); return; } @@ -539,8 +535,9 @@ public class CostExile extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { final String amount = this.getAmount(); + final Card source = ability.getSourceCard(); Integer c = this.convertAmount(); final Player activator = ability.getActivatingPlayer(); List list; @@ -552,11 +549,10 @@ public class CostExile extends CostPartWithList { } if (this.getType().equals("All")) { - this.setList(list); for (final Card card : list) { - Singletons.getModel().getGame().getAction().exile(card); + executePayment(ability, card); } - payment.setPaidPart(this); + return true; } list = CardLists.getValidCards(list, this.getType().split(";"), activator, source); if (c == null) { @@ -571,16 +567,16 @@ public class CostExile extends CostPartWithList { } } - InputSynchronized target = null; + InputPayment target = null; if (this.payCostFromSource()) { - target = new InputExileThis(payment, this, ability); + target = new InputExileThis(this, ability); } else if (this.from.equals(ZoneType.Battlefield) || this.from.equals(ZoneType.Hand)) { - target = new InputExileType(this, payment, this.getType(), c, ability); + target = new InputExileType(this, this.getType(), c, ability); } else if (this.from.equals(ZoneType.Stack)) { - target = new InputExileFromStack(payment, ability, this.getType(), c, this); + target = new InputExileFromStack(ability, this.getType(), c, this); } else if (this.from.equals(ZoneType.Library)) { // this does not create input - CostExile.exileFromTop(ability, this, payment, c); + return exileFromTop(ability, c); } else if (this.sameZone) { List players = game.getPlayers(); List payableZone = new ArrayList(); @@ -592,13 +588,13 @@ public class CostExile extends CostPartWithList { payableZone.add(p); } } - target = new InputExileFromSame(list, this, payment, c, payableZone); + target = new InputExileFromSame(list, this, c, payableZone); } else { - target = new InputExileFrom(ability, this.getType(), c, payment, this); + target = new InputExileFrom(ability, this.getType(), c, this); } - target.awaitLatchRelease(); - if(!payment.isCanceled()) - addListToHash(ability, "Exiled"); + FThreads.setInputAndWait(target); + return target.isPaid(); + } /* @@ -661,30 +657,43 @@ public class CostExile extends CostPartWithList { * @param nNeeded * the n needed */ - public static void exileFromTop(final SpellAbility sa, final CostExile part, final CostPayment payment, - final int nNeeded) { + public boolean exileFromTop(final SpellAbility sa, final int nNeeded) { final StringBuilder sb = new StringBuilder(); sb.append("Exile ").append(nNeeded).append(" cards from the top of your library?"); final List list = sa.getActivatingPlayer().getCardsIn(ZoneType.Library, nNeeded); if (list.size() > nNeeded) { // I don't believe this is possible - payment.cancelCost(); - return; + return false; } final boolean doExile = GuiDialog.confirm(sa.getSourceCard(), sb.toString()); if (doExile) { final Iterator itr = list.iterator(); while (itr.hasNext()) { - final Card c = itr.next(); - part.addToList(c); - Singletons.getModel().getGame().getAction().exile(c); + executePayment(sa, itr.next()); } - part.addListToHash(sa, "Exiled"); - payment.setPaidPart(part); + return true; } else { - payment.cancelCost(); + return false; } } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + addToList(targetCard); + ability.getActivatingPlayer().getGame().getAction().exile(targetCard); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + // TODO Auto-generated method stub + return "Exiled"; + } } diff --git a/src/main/java/forge/card/cost/CostGainLife.java b/src/main/java/forge/card/cost/CostGainLife.java index ceea608893f..f48fb1508ab 100644 --- a/src/main/java/forge/card/cost/CostGainLife.java +++ b/src/main/java/forge/card/cost/CostGainLife.java @@ -137,7 +137,8 @@ public class CostGainLife extends CostPart { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { + final Card source = ability.getSourceCard(); final String amount = this.getAmount(); final Player activator = ability.getActivatingPlayer(); final int life = activator.getLife(); @@ -172,13 +173,13 @@ public class CostGainLife extends CostPart { for(int playersLeft = cntPlayers; playersLeft > 0; playersLeft--) { final Player chosenToGain = GuiChoose.oneOrNone(sb.toString(), oppsThatCanGainLife); if (null == chosenToGain) { - payment.setCancel(true); - return; + return false; } else { final Player chosen = chosenToGain; chosen.gainLife(c, null); } } + return true; } /* diff --git a/src/main/java/forge/card/cost/CostMill.java b/src/main/java/forge/card/cost/CostMill.java index bf537d0d6e8..54e1da824bf 100644 --- a/src/main/java/forge/card/cost/CostMill.java +++ b/src/main/java/forge/card/cost/CostMill.java @@ -126,9 +126,10 @@ public class CostMill extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { final String amount = this.getAmount(); Integer c = this.convertAmount(); + final Card source = ability.getSourceCard(); final Player activator = ability.getActivatingPlayer(); if (c == null) { @@ -144,26 +145,22 @@ public class CostMill extends CostPartWithList { if ((list == null) || (list.size() > c)) { // I don't believe this is possible - payment.cancelCost(); - return; + return false; } final StringBuilder sb = new StringBuilder(); sb.append("Mill ").append(c).append(" cards from your library?"); - final boolean doMill = GuiDialog.confirm(source, sb.toString()); - if (doMill) { - this.resetList(); - final Iterator itr = list.iterator(); - while (itr.hasNext()) { - final Card card = itr.next(); - this.addToList(card); - Singletons.getModel().getGame().getAction().moveToGraveyard(card); - } - this.addListToHash(ability, "Milled"); - } else { - payment.cancelCost(); + if ( false == GuiDialog.confirm(source, sb.toString()) ) + return false; + + this.resetList(); + final Iterator itr = list.iterator(); + while (itr.hasNext()) { + final Card card = itr.next(); + executePayment(ability, card); } + return true; } /* @@ -192,4 +189,21 @@ public class CostMill extends CostPartWithList { return sb.toString(); } + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + this.addToList(targetCard); + ability.getActivatingPlayer().getGame().getAction().moveToGraveyard(targetCard); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "Milled"; + } + } diff --git a/src/main/java/forge/card/cost/CostPart.java b/src/main/java/forge/card/cost/CostPart.java index 6861cc7c554..0c9edb55ed6 100644 --- a/src/main/java/forge/card/cost/CostPart.java +++ b/src/main/java/forge/card/cost/CostPart.java @@ -200,8 +200,8 @@ public abstract class CostPart { * @param game * @return true, if successful */ - public abstract void payHuman(SpellAbility ability, Card source, CostPayment payment, GameState game); - + public abstract boolean payHuman(SpellAbility ability, GameState game); + /* * (non-Javadoc) * diff --git a/src/main/java/forge/card/cost/CostPartMana.java b/src/main/java/forge/card/cost/CostPartMana.java index 498561baeec..948c5012f6b 100644 --- a/src/main/java/forge/card/cost/CostPartMana.java +++ b/src/main/java/forge/card/cost/CostPartMana.java @@ -25,6 +25,7 @@ import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; import forge.control.input.InputPayManaOfCostPayment; import forge.control.input.InputPayManaX; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.ai.ComputerUtilMana; import forge.game.player.AIPlayer; @@ -205,7 +206,8 @@ public class CostPartMana extends CostPart { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { + final Card source = ability.getSourceCard(); int manaToAdd = 0; if (!this.hasNoXManaCost()) { // if X cost is a defined value, other than xPaid @@ -217,12 +219,19 @@ public class CostPartMana extends CostPart { if (!"0".equals(this.getManaToPay()) || manaToAdd > 0) { - FThreads.setInputAndWait(new InputPayManaOfCostPayment(game, this, ability, payment, manaToAdd)); + InputPayment inpPayment = new InputPayManaOfCostPayment(game, this, ability, manaToAdd); + FThreads.setInputAndWait(inpPayment); + if(!inpPayment.isPaid()) + return false; } if (this.getXMana() > 0) { source.setXManaCostPaid(0); - FThreads.setInputAndWait(new InputPayManaX(game, ability, payment, this)); + InputPayment inpPayment = new InputPayManaX(game, ability, this); + FThreads.setInputAndWait(inpPayment); + if(!inpPayment.isPaid()) + return false; } + return true; } diff --git a/src/main/java/forge/card/cost/CostPartWithList.java b/src/main/java/forge/card/cost/CostPartWithList.java index 6eca887197f..3a5274dfed4 100644 --- a/src/main/java/forge/card/cost/CostPartWithList.java +++ b/src/main/java/forge/card/cost/CostPartWithList.java @@ -17,8 +17,9 @@ */ package forge.card.cost; -import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import forge.Card; import forge.CardUtil; @@ -30,14 +31,16 @@ import forge.card.spellability.SpellAbility; public abstract class CostPartWithList extends CostPart { /** The list. */ - private List list = null; + private Set list = new HashSet(); + // set is here because executePayment() adds card to list, while ai's decide payment does the same thing. + // set allows to avoid duplication /** * Gets the list. * * @return the list */ - public final List getList() { + public final Set getList() { return this.list; } @@ -48,14 +51,15 @@ public abstract class CostPartWithList extends CostPart { * the new list */ public final void setList(final List setList) { - this.list = setList; + this.list.clear(); + list.addAll(setList); } /** * Reset list. */ public final void resetList() { - this.setList(new ArrayList()); + this.list.clear(); } /** @@ -65,10 +69,7 @@ public abstract class CostPartWithList extends CostPart { * the c */ public final void addToList(final Card c) { - if (this.getList() == null) { - this.resetList(); - } - this.getList().add(c); + this.list.add(c); } /** @@ -91,7 +92,7 @@ public abstract class CostPartWithList extends CostPart { */ public CostPartWithList() { } - + /** * Instantiates a new cost part with list. * @@ -106,4 +107,12 @@ public abstract class CostPartWithList extends CostPart { super(amount, type, description); this.resetList(); } + + public abstract void executePayment(SpellAbility ability, Card targetCard); + + /** + * TODO: Write javadoc for this method. + * @return + */ + public abstract String getHashForList(); } diff --git a/src/main/java/forge/card/cost/CostPayLife.java b/src/main/java/forge/card/cost/CostPayLife.java index 4fc6b6548ad..391f3de9af7 100644 --- a/src/main/java/forge/card/cost/CostPayLife.java +++ b/src/main/java/forge/card/cost/CostPayLife.java @@ -123,7 +123,8 @@ public class CostPayLife extends CostPart { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { + final Card source = ability.getSourceCard(); final String amount = this.getAmount(); final Player activator = ability.getActivatingPlayer(); final int life = activator.getLife(); @@ -149,10 +150,10 @@ public class CostPayLife extends CostPart { if (activator.canPayLife(c) && GuiDialog.confirm(source, sb.toString())) { activator.payLife(c, null); - this.setLastPaidAmount(c); } else { - payment.setCancel(true); + return false; } + return true; } /* diff --git a/src/main/java/forge/card/cost/CostPayment.java b/src/main/java/forge/card/cost/CostPayment.java index 1499b480454..a24d60b970b 100644 --- a/src/main/java/forge/card/cost/CostPayment.java +++ b/src/main/java/forge/card/cost/CostPayment.java @@ -38,7 +38,6 @@ import forge.game.player.Player; public class CostPayment { private Cost cost = null; private SpellAbility ability = null; - private Card card = null; private SpellAbilityRequirements req = null; private boolean bCancel = false; private final ArrayList paidCostParts = new ArrayList(); @@ -74,7 +73,7 @@ public class CostPayment { * @return a {@link forge.Card} object. */ public final Card getCard() { - return this.card; + return this.ability.getSourceCard(); } /** @@ -135,7 +134,6 @@ public class CostPayment { public CostPayment(final Cost cost, final SpellAbility abil, final GameState game) { this.cost = cost; this.ability = abil; - this.card = abil.getSourceCard(); this.game = game; } @@ -212,9 +210,12 @@ public class CostPayment { continue; } - part.payHuman(this.ability, this.card, this, game); - if ( isCanceled() ) return; - + if ( false == part.payHuman(getAbility(), game) ) { + this.setCancel(true); + return; + } + if( part instanceof CostPartWithList ) + ((CostPartWithList) part).addListToHash(ability, ((CostPartWithList) part).getHashForList()); setPaidPart(part); } this.resetUndoList(); @@ -258,7 +259,7 @@ public class CostPayment { public final void cancelPayment() { for (final CostPart part : this.paidCostParts) { if (part.isUndoable()) { - part.refund(this.card); + part.refund(this.getCard()); } } diff --git a/src/main/java/forge/card/cost/CostPutCounter.java b/src/main/java/forge/card/cost/CostPutCounter.java index ed9688e7452..4d2aeb8b6c5 100644 --- a/src/main/java/forge/card/cost/CostPutCounter.java +++ b/src/main/java/forge/card/cost/CostPutCounter.java @@ -21,9 +21,10 @@ import java.util.List; import forge.Card; import forge.CardLists; import forge.CounterType; +import forge.FThreads; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; -import forge.control.input.InputSynchronized; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.ai.ComputerUtilCard; import forge.game.player.AIPlayer; @@ -57,8 +58,7 @@ public class CostPutCounter extends CostPartWithList { * @param payment * @param sa */ - public InputPayCostPutCounter(String type, CostPutCounter costPutCounter, int nNeeded, CostPayment payment, SpellAbility sa) { - super(payment); + public InputPayCostPutCounter(String type, CostPutCounter costPutCounter, int nNeeded, SpellAbility sa) { this.type = type; this.costPutCounter = costPutCounter; this.nNeeded = nNeeded; @@ -90,9 +90,7 @@ public class CostPutCounter extends CostPartWithList { public void selectCard(final Card card) { if (this.typeList.contains(card)) { this.nPut++; - costPutCounter.addToList(card); - card.addCounter(costPutCounter.getCounter(), 1, false); - + costPutCounter.executePayment(sa, card); if (nNeeded == this.nPut) { this.done(); } else { @@ -220,17 +218,14 @@ public class CostPutCounter extends CostPartWithList { */ @Override public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { - Integer c = this.convertAmount(); - if (c == null) { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } + Integer c = getNumberOfCounters(ability); if (this.payCostFromSource()) { - source.addCounter(this.getCounter(), c, false); + executePayment(ability, source, c); } else { // Put counter on chosen card for (final Card card : this.getList()) { - card.addCounter(this.getCounter(), 1, false); + executePayment(ability, card); } } } @@ -243,21 +238,26 @@ public class CostPutCounter extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { - Integer c = this.convertAmount(); - if (c == null) { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } + public final boolean payHuman(final SpellAbility ability, final GameState game) { + final Card source = ability.getSourceCard(); + Integer c = getNumberOfCounters(ability); if (this.payCostFromSource()) { - source.addCounter(this.getCounter(), c, false); - this.addToList(source); + executePayment(ability, source, c); + return true; } else { - InputSynchronized inp = new InputPayCostPutCounter(this.getType(), this, c, payment, ability); - inp.awaitLatchRelease(); + InputPayment inp = new InputPayCostPutCounter(this.getType(), this, c, ability); + FThreads.setInputAndWait(inp); + return inp.isPaid(); } - if ( !payment.isCanceled()) - addListToHash(ability, "CounterPut"); + } + + private Integer getNumberOfCounters(final SpellAbility ability) { + Integer c = this.convertAmount(); + if (c == null) { + c = AbilityUtils.calculateAmount(ability.getSourceCard(), this.getAmount(), ability); + } + return c; } /* @@ -274,13 +274,7 @@ public class CostPutCounter extends CostPartWithList { this.addToList(source); return true; } else { - Integer c = this.convertAmount(); - if (c == null) { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - final List typeList = - CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ai, source); + final List typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ai, source); Card card = null; if (this.getType().equals("Creature.YouCtrl")) { @@ -292,4 +286,23 @@ public class CostPutCounter extends CostPartWithList { } return true; } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard){ + executePayment(ability, targetCard, 1); + } + + public void executePayment(SpellAbility ability, Card targetCard, int c) { + targetCard.addCounter(this.getCounter(), c, false); + this.addToList(targetCard); + } + + + @Override + public String getHashForList() { + return "CounterPut"; + } } diff --git a/src/main/java/forge/card/cost/CostRemoveCounter.java b/src/main/java/forge/card/cost/CostRemoveCounter.java index ffc4f56643c..c802168f551 100644 --- a/src/main/java/forge/card/cost/CostRemoveCounter.java +++ b/src/main/java/forge/card/cost/CostRemoveCounter.java @@ -25,7 +25,7 @@ import forge.CounterType; import forge.FThreads; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; -import forge.control.input.InputSynchronized; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.player.AIPlayer; import forge.game.player.Player; @@ -66,8 +66,7 @@ public class CostRemoveCounter extends CostPartWithList { * @param type * @param costRemoveCounter */ - public InputPayCostRemoveCounterType(CostPayment payment, int nNeeded, SpellAbility sa, String type, CostRemoveCounter costRemoveCounter) { - super(payment); + public InputPayCostRemoveCounterType(int nNeeded, SpellAbility sa, String type, CostRemoveCounter costRemoveCounter) { this.nNeeded = nNeeded; this.sa = sa; this.type = type; @@ -99,8 +98,7 @@ public class CostRemoveCounter extends CostPartWithList { if (this.typeList.contains(card)) { if (card.getCounters(costRemoveCounter.getCounter()) > 0) { this.nRemove++; - costRemoveCounter.addToList(card); - card.subtractCounter(costRemoveCounter.getCounter(), 1); + costRemoveCounter.executePayment(sa, card); if (nNeeded == this.nRemove) { this.done(); @@ -133,9 +131,8 @@ public class CostRemoveCounter extends CostPartWithList { * @param nNeeded * @param payment */ - public InputPayCostRemoveCounterFrom(CostRemoveCounter costRemoveCounter, String type, SpellAbility sa, - int nNeeded, CostPayment payment) { - super(payment); + public InputPayCostRemoveCounterFrom(CostRemoveCounter costRemoveCounter, String type, SpellAbility sa, int nNeeded) { + this.costRemoveCounter = costRemoveCounter; this.type = type; this.sa = sa; @@ -153,20 +150,18 @@ public class CostRemoveCounter extends CostPartWithList { this.typeList = CardLists.getValidCards(this.typeList, type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard()); for (int i = 0; i < nNeeded; i++) { - if (this.typeList.size() == 0) { + if (this.typeList.isEmpty()) { this.cancel(); } - final Card o = GuiChoose - .oneOrNone("Remove counter(s) from a card in " + costRemoveCounter.getZone(), this.typeList); + final Card o = GuiChoose.oneOrNone("Remove counter(s) from a card in " + costRemoveCounter.getZone(), this.typeList); if (o != null) { final Card card = o; if (card.getCounters(costRemoveCounter.getCounter()) > 0) { this.nRemove++; - costRemoveCounter.addToList(card); - card.subtractCounter(costRemoveCounter.getCounter(), 1); + costRemoveCounter.executePayment(sa, card); if (card.getCounters(costRemoveCounter.getCounter()) == 0) { this.typeList.remove(card); @@ -361,8 +356,9 @@ public class CostRemoveCounter extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { final String amount = this.getAmount(); + final Card source = ability.getSourceCard(); Integer c = this.convertAmount(); int maxCounters = 0; @@ -377,16 +373,14 @@ public class CostRemoveCounter extends CostPartWithList { } } - final InputSynchronized inp; + final InputPayment inp; if (this.getZone().equals(ZoneType.Battlefield)) { - inp = new InputPayCostRemoveCounterType(payment, c, ability, this.getType(), this); + inp = new InputPayCostRemoveCounterType(c, ability, this.getType(), this); } else { - inp = new InputPayCostRemoveCounterFrom(this, this.getType(), ability, c, payment); + inp = new InputPayCostRemoveCounterFrom(this, this.getType(), ability, c); } FThreads.setInputAndWait(inp); - if ( !payment.isCanceled() ) - addListToHash(ability, "CounterRemove"); - return; + return inp.isPaid(); } maxCounters = source.getCounters(this.counter); @@ -404,14 +398,13 @@ public class CostRemoveCounter extends CostPartWithList { } } - if (maxCounters >= c) { - this.addToList(source); - source.setSVar("CostCountersRemoved", "Number$" + Integer.toString(c)); - source.subtractCounter(this.counter, c); - this.setLastPaidAmount(c); - } else { - payment.setCancel(true); - } + if (maxCounters < c) return false; + + + this.addToList(source); + source.setSVar("CostCountersRemoved", "Number$" + Integer.toString(c)); + executePayment(ability, source, c); + return true; } /* @@ -457,4 +450,24 @@ public class CostRemoveCounter extends CostPartWithList { } return true; } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + executePayment(ability, targetCard, 1); + } + + public void executePayment(SpellAbility ability, Card targetCard, int n) { + addToList(targetCard); + targetCard.subtractCounter(getCounter(), n); + } + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "CounterRemove"; + } } diff --git a/src/main/java/forge/card/cost/CostReturn.java b/src/main/java/forge/card/cost/CostReturn.java index 03683a80ade..f350104dc04 100644 --- a/src/main/java/forge/card/cost/CostReturn.java +++ b/src/main/java/forge/card/cost/CostReturn.java @@ -22,7 +22,6 @@ import java.util.List; import forge.Card; import forge.CardLists; import forge.FThreads; -import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; import forge.control.input.InputSelectCards; @@ -121,7 +120,7 @@ public class CostReturn extends CostPartWithList { @Override public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { for (final Card c : this.getList()) { - Singletons.getModel().getGame().getAction().moveToHand(c); + executePayment(ability, c); } } @@ -133,8 +132,9 @@ public class CostReturn extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { final String amount = this.getAmount(); + final Card source = ability.getSourceCard(); Integer c = this.convertAmount(); final Player activator = ability.getActivatingPlayer(); final List list = activator.getCardsIn(ZoneType.Battlefield); @@ -152,27 +152,24 @@ public class CostReturn extends CostPartWithList { if (card.getController() == ability.getActivatingPlayer() && card.isInPlay()) { boolean confirm = GuiDialog.confirm(card, card.getName() + " - Return to Hand?"); if (confirm) { - addToList(card); - game.getAction().moveToHand(card); - } else { - payment.cancelCost(); + executePayment(ability, card); } + return confirm; } } else { List validCards = CardLists.getValidCards(ability.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard()); InputSelectCards inp = new InputSelectCardsFromList(c, c, validCards); - inp.setMessage("Return %d " + this.getType() + " card(s) to hand"); + inp.setMessage("Return %d " + this.getType() + " " + this.getType() + " card(s) to hand"); FThreads.setInputAndWait(inp); if (inp.hasCancelled()) - payment.setCancel(true); - else - for(Card crd : inp.getSelected()) - game.getAction().moveToHand(crd); + return false; + + for(Card crd : inp.getSelected()) + executePayment(ability, crd); + return true; } - - if (!payment.isCanceled()) - addListToHash(ability, "Returned"); + return false; } /* @@ -194,13 +191,30 @@ public class CostReturn extends CostPartWithList { } this.setList(ComputerUtil.chooseReturnType(ai, this.getType(), source, ability.getTargetCard(), c)); - if (this.getList() == null) { + if (this.getList().isEmpty()) { return false; } } return true; } + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + addToList(targetCard); + ability.getActivatingPlayer().getGame().getAction().moveToHand(targetCard); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "Returned"; + } + // Inputs diff --git a/src/main/java/forge/card/cost/CostReveal.java b/src/main/java/forge/card/cost/CostReveal.java index 8c266734f74..a4920553bd0 100644 --- a/src/main/java/forge/card/cost/CostReveal.java +++ b/src/main/java/forge/card/cost/CostReveal.java @@ -25,13 +25,13 @@ import forge.FThreads; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.player.AIPlayer; import forge.game.player.Player; import forge.game.zone.Zone; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; -import forge.gui.match.CMatchUI; import forge.view.ButtonUtil; /** @@ -63,9 +63,7 @@ public class CostReveal extends CostPartWithList { * @param payment * @param nNeeded */ - public InputPayReveal(CostReveal part, String discType, List handList, SpellAbility sa, - CostPayment payment, int nNeeded) { - super(payment); + public InputPayReveal(CostReveal part, String discType, List handList, SpellAbility sa, int nNeeded) { this.part = part; this.discType = discType; this.handList = handList; @@ -95,7 +93,7 @@ public class CostReveal extends CostPartWithList { sb.append(nNeeded - this.nReveal); sb.append(" remaining."); } - CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString()); + showMessage(sb.toString()); ButtonUtil.enableOnlyCancel(); } @@ -105,7 +103,7 @@ public class CostReveal extends CostPartWithList { if (zone.is(ZoneType.Hand) && handList.contains(card)) { // send in List for Typing handList.remove(card); - part.addToList(card); + part.executePayment(sa, card); this.nReveal++; // in case no more cards in hand @@ -222,6 +220,8 @@ public class CostReveal extends CostPartWithList { @Override public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { GuiChoose.oneOrNone("Revealed cards:", this.getList()); + for(Card c: getList()) // should not throw concurrent modification here - no items should be added. + executePayment(ability, c); } /* @@ -232,15 +232,19 @@ public class CostReveal extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { final Player activator = ability.getActivatingPlayer(); + final Card source = ability.getSourceCard(); final String amount = this.getAmount(); this.resetList(); if (this.payCostFromSource()) { - this.addToList(source); + executePayment(ability, source); + return true; } else if (this.getType().equals("Hand")) { - this.setList(new ArrayList(activator.getCardsIn(ZoneType.Hand))); + for(Card c : activator.getCardsIn(ZoneType.Hand)) + executePayment(ability, c); + return true; } else { Integer num = this.convertAmount(); @@ -255,12 +259,12 @@ public class CostReveal extends CostPartWithList { num = AbilityUtils.calculateAmount(source, amount, ability); } } - if (num > 0) { - FThreads.setInputAndWait(new InputPayReveal(this, this.getType(), handList, ability, payment, num)); - } + if ( num == 0 ) return true; + + InputPayment inp = new InputPayReveal(this, this.getType(), handList, ability, num); + FThreads.setInputAndWait(inp); + return inp.isPaid(); } - if ( !payment.isCanceled()) - this.addListToHash(ability, "Revealed"); } /* @@ -296,6 +300,23 @@ public class CostReveal extends CostPartWithList { return sb.toString(); } + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + addToList(targetCard); + // write code to actually reveal card + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "Revealed"; + } + // Inputs diff --git a/src/main/java/forge/card/cost/CostSacrifice.java b/src/main/java/forge/card/cost/CostSacrifice.java index 369b09bdd6c..01c3156e397 100644 --- a/src/main/java/forge/card/cost/CostSacrifice.java +++ b/src/main/java/forge/card/cost/CostSacrifice.java @@ -22,9 +22,9 @@ import java.util.List; import forge.Card; import forge.CardLists; import forge.FThreads; -import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.ai.ComputerUtil; import forge.game.player.AIPlayer; @@ -59,9 +59,7 @@ public class CostSacrifice extends CostPartWithList { * @param payment * @param typeList */ - public InputPayCostSacrificeFromList(CostSacrifice part, SpellAbility sa, int nNeeded, CostPayment payment, - List typeList) { - super(payment); + public InputPayCostSacrificeFromList(CostSacrifice part, SpellAbility sa, int nNeeded, List typeList) { this.part = part; this.sa = sa; this.nNeeded = nNeeded; @@ -90,13 +88,12 @@ public class CostSacrifice extends CostPartWithList { public void selectCard(final Card card) { if (typeList.contains(card)) { this.nSacrifices++; - part.addToList(card); - Singletons.getModel().getGame().getAction().sacrifice(card, sa); + part.executePayment(sa, card); typeList.remove(card); // in case nothing else to sacrifice if (this.nSacrifices == nNeeded) { this.done(); - } else if (typeList.size() == 0) { + } else if (typeList.isEmpty()) { // happen this.cancel(); } else { @@ -197,7 +194,7 @@ public class CostSacrifice extends CostPartWithList { public final void payAI(final AIPlayer ai, final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { this.addListToHash(ability, "Sacrificed"); for (final Card c : this.getList()) { - Singletons.getModel().getGame().getAction().sacrifice(c, ability); + executePayment(ability, c); } } @@ -209,8 +206,9 @@ public class CostSacrifice extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { final String amount = this.getAmount(); + final Card source = ability.getSourceCard(); final String type = this.getType(); final Player activator = ability.getActivatingPlayer(); List list = new ArrayList(activator.getCardsIn(ZoneType.Battlefield)); @@ -220,22 +218,19 @@ public class CostSacrifice extends CostPartWithList { } if (this.payCostFromSource()) { - final Card card = ability.getSourceCard(); - if (card.getController() == ability.getActivatingPlayer() && card.isInPlay()) { - if (GuiDialog.confirm(card, card.getName() + " - Sacrifice?")) { - this.addToList(card); - Singletons.getModel().getGame().getAction().sacrifice(card, ability); - } else { - payment.cancelCost(); - } + if (source.getController() == ability.getActivatingPlayer() && source.isInPlay()) { + if (!GuiDialog.confirm(source, source.getName() + " - Sacrifice?")) + return false; + executePayment(ability, source); + return true; } } else if (amount.equals("All")) { this.setList(list); // TODO Ask First for (final Card card : list) { - payment.getAbility().addCostToHashList(card, "Sacrificed"); - Singletons.getModel().getGame().getAction().sacrifice(card, ability); + executePayment(ability, card); } + return true; } else { Integer c = this.convertAmount(); if (c == null) { @@ -247,13 +242,13 @@ public class CostSacrifice extends CostPartWithList { } } if (0 == c.intValue()) { - return; + return true; } - FThreads.setInputAndWait(new InputPayCostSacrificeFromList(this, ability, c, payment, list)); + InputPayment inp = new InputPayCostSacrificeFromList(this, ability, c, list); + FThreads.setInputAndWait(inp); + return inp.isPaid(); } - - if( !payment.isCanceled()) - addListToHash(ability, "Sacrificed"); + return false; } /* @@ -294,6 +289,23 @@ public class CostSacrifice extends CostPartWithList { return true; } + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + this.addToList(targetCard); + ability.getActivatingPlayer().getGame().getAction().sacrifice(targetCard, ability); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "Sacrificed"; + } + // Inputs } diff --git a/src/main/java/forge/card/cost/CostTap.java b/src/main/java/forge/card/cost/CostTap.java index f14da7667e1..0a1e19c2fd4 100644 --- a/src/main/java/forge/card/cost/CostTap.java +++ b/src/main/java/forge/card/cost/CostTap.java @@ -93,12 +93,13 @@ public class CostTap extends CostPart { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { // if (!canPay(ability, source, ability.getActivatingPlayer(), // payment.getCost())) // return false; - source.tap(); + ability.getSourceCard().tap(); + return true; } /* diff --git a/src/main/java/forge/card/cost/CostTapType.java b/src/main/java/forge/card/cost/CostTapType.java index 91d0151b50c..c9ea3369ce0 100644 --- a/src/main/java/forge/card/cost/CostTapType.java +++ b/src/main/java/forge/card/cost/CostTapType.java @@ -26,13 +26,13 @@ import forge.FThreads; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.ai.ComputerUtil; import forge.game.player.AIPlayer; import forge.game.player.Player; import forge.game.zone.Zone; import forge.game.zone.ZoneType; -import forge.gui.match.CMatchUI; import forge.view.ButtonUtil; /** @@ -59,8 +59,7 @@ public class CostTapType extends CostPartWithList { * @param cardList * @param payment */ - public InputPayCostTapType(CostTapType tapType, int nCards, List cardList, CostPayment payment) { - super(payment); + public InputPayCostTapType(CostTapType tapType, int nCards, List cardList) { this.tapType = tapType; this.nCards = nCards; this.cardList = cardList; @@ -70,8 +69,7 @@ public class CostTapType extends CostPartWithList { public void showMessage() { final int left = nCards - this.nTapped; - CMatchUI.SINGLETON_INSTANCE - .showMessage("Select a " + tapType.getDescription() + " to tap (" + left + " left)"); + showMessage("Select a " + tapType.getDescription() + " to tap (" + left + " left)"); ButtonUtil.enableOnlyCancel(); if (nCards == 0) { this.done(); @@ -85,8 +83,7 @@ public class CostTapType extends CostPartWithList { Zone zone = Singletons.getModel().getGame().getZoneOf(card); if (zone.is(ZoneType.Battlefield) && cardList.contains(card) && card.isUntapped()) { // send in List for Typing - card.tap(); - tapType.addToList(card); + tapType.executePayment(null, card); cardList.remove(card); this.nTapped++; @@ -211,11 +208,12 @@ public class CostTapType extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { List typeList = new ArrayList(ability.getActivatingPlayer().getCardsIn(ZoneType.Battlefield)); typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard()); typeList = CardLists.filter(typeList, Presets.UNTAPPED); final String amount = this.getAmount(); + final Card source = ability.getSourceCard(); Integer c = this.convertAmount(); if (c == null) { final String sVar = ability.getSVar(amount); @@ -226,9 +224,9 @@ public class CostTapType extends CostPartWithList { c = AbilityUtils.calculateAmount(source, amount, ability); } } - FThreads.setInputAndWait(new InputPayCostTapType(this, c, typeList, payment)); - if( !payment.isCanceled()) - addListToHash(ability, "Tapped"); + InputPayment inp = new InputPayCostTapType(this, c, typeList); + FThreads.setInputAndWait(inp); + return inp.isPaid(); } /* @@ -266,6 +264,23 @@ public class CostTapType extends CostPartWithList { return true; } + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + addToList(targetCard); + targetCard.tap(); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "Tapped"; + } + // Inputs } diff --git a/src/main/java/forge/card/cost/CostUnattach.java b/src/main/java/forge/card/cost/CostUnattach.java index ef620d61724..df8b5cfd548 100644 --- a/src/main/java/forge/card/cost/CostUnattach.java +++ b/src/main/java/forge/card/cost/CostUnattach.java @@ -114,17 +114,15 @@ public class CostUnattach extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { - this.resetList(); + public final boolean payHuman(final SpellAbility ability, final GameState game) { + final Card source = ability.getSourceCard(); Player activator = ability.getActivatingPlayer(); Card cardToUnattach = findCardToUnattach(source, activator, ability); if (cardToUnattach != null && GuiDialog.confirm(source, String.format("Unattach %s?", cardToUnattach.toString()))) { - Card equippingCard = cardToUnattach.getEquipping().get(0); - cardToUnattach.unEquipCard(equippingCard); - this.addToList(cardToUnattach); - this.addListToHash(ability, "Unattached"); + executePayment(ability, cardToUnattach); + return true; } else { - payment.setCancel(true); + return false; } } @@ -160,4 +158,18 @@ public class CostUnattach extends CostPartWithList { this.resetList(); return true; } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + targetCard.unEquipCard(targetCard.getEquipping().get(0)); + this.addToList(targetCard); + } + + @Override + public String getHashForList() { + return "Unattached"; + } } diff --git a/src/main/java/forge/card/cost/CostUntap.java b/src/main/java/forge/card/cost/CostUntap.java index 6490a4d67ab..d3355e9bc49 100644 --- a/src/main/java/forge/card/cost/CostUntap.java +++ b/src/main/java/forge/card/cost/CostUntap.java @@ -92,12 +92,13 @@ public class CostUntap extends CostPart { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { + public final boolean payHuman(final SpellAbility ability, final GameState game) { // if (!canPay(ability, source, ability.getActivatingPlayer(), // payment.getCost())) // return false; - source.untap(); + ability.getSourceCard().untap(); + return true; } /* diff --git a/src/main/java/forge/card/cost/CostUntapType.java b/src/main/java/forge/card/cost/CostUntapType.java index 1d86147fd0f..d33a89556e3 100644 --- a/src/main/java/forge/card/cost/CostUntapType.java +++ b/src/main/java/forge/card/cost/CostUntapType.java @@ -25,13 +25,13 @@ import forge.FThreads; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.spellability.SpellAbility; +import forge.control.input.InputPayment; import forge.game.GameState; import forge.game.ai.ComputerUtil; import forge.game.player.AIPlayer; import forge.game.player.Player; import forge.game.zone.Zone; import forge.game.zone.ZoneType; -import forge.gui.match.CMatchUI; import forge.view.ButtonUtil; /** @@ -59,8 +59,7 @@ public class CostUntapType extends CostPartWithList { * @param sa * @param payment */ - public InputPayCostUntapY(int nCards, List cardList, CostUntapType untapType, CostPayment payment) { - super(payment); + public InputPayCostUntapY(int nCards, List cardList, CostUntapType untapType) { this.nCards = nCards; this.cardList = cardList; this.untapType = untapType; @@ -77,8 +76,7 @@ public class CostUntapType extends CostPartWithList { } final int left = nCards - this.nUntapped; - CMatchUI.SINGLETON_INSTANCE - .showMessage("Select a " + untapType.getDescription() + " to untap (" + left + " left)"); + showMessage("Select a " + untapType.getDescription() + " to untap (" + left + " left)"); ButtonUtil.enableOnlyCancel(); } @@ -228,12 +226,13 @@ public class CostUntapType extends CostPartWithList { * forge.Card, forge.card.cost.Cost_Payment) */ @Override - public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) { - final boolean untap = payment.getCost().hasUntapCost(); + public final boolean payHuman(final SpellAbility ability, final GameState game) { + final boolean canUntapSource = false; // payment.getCost().hasUntapCost(); - only Crackleburr uses this List typeList = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield); typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard()); typeList = CardLists.filter(typeList, Presets.TAPPED); - if (untap) { + final Card source = ability.getSourceCard(); + if (canUntapSource) { typeList.remove(source); } final String amount = this.getAmount(); @@ -247,10 +246,9 @@ public class CostUntapType extends CostPartWithList { c = AbilityUtils.calculateAmount(source, amount, ability); } } - FThreads.setInputAndWait(new InputPayCostUntapY(c, typeList, this, payment)); - - if ( !payment.isCanceled() ) - addListToHash(ability, "Untapped"); + InputPayment inp = new InputPayCostUntapY(c, typeList, this); + FThreads.setInputAndWait(inp); + return inp.isPaid(); } /* @@ -291,6 +289,23 @@ public class CostUntapType extends CostPartWithList { return true; } + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public void executePayment(SpellAbility ability, Card targetCard) { + addToList(targetCard); + targetCard.untap(); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "Untapped"; + } + // Inputs } diff --git a/src/main/java/forge/card/cost/InputPayCostBase.java b/src/main/java/forge/card/cost/InputPayCostBase.java index b6d01d1a158..00847b3c488 100644 --- a/src/main/java/forge/card/cost/InputPayCostBase.java +++ b/src/main/java/forge/card/cost/InputPayCostBase.java @@ -1,35 +1,29 @@ package forge.card.cost; +import forge.control.input.InputPayment; import forge.control.input.InputSyncronizedBase; /** * TODO: Write javadoc for this type. * */ -abstract class InputPayCostBase extends InputSyncronizedBase { +abstract class InputPayCostBase extends InputSyncronizedBase implements InputPayment { private static final long serialVersionUID = -2967434867139585579L; + boolean bPaid = false; - private final CostPayment payment; - /** - * TODO: Write javadoc for Constructor. - * @param cdl - * @param payment - */ - public InputPayCostBase(CostPayment payment0) { - payment = payment0; - } - @Override final public void selectButtonCancel() { this.cancel(); } final protected void done() { + bPaid = true; this.stop(); } final public void cancel() { - payment.cancelCost(); this.stop(); } + + final public boolean isPaid() { return bPaid; } } \ No newline at end of file diff --git a/src/main/java/forge/control/input/InputPayManaBase.java b/src/main/java/forge/control/input/InputPayManaBase.java index a2b1d430fb9..9fd4e078434 100644 --- a/src/main/java/forge/control/input/InputPayManaBase.java +++ b/src/main/java/forge/control/input/InputPayManaBase.java @@ -28,7 +28,7 @@ import forge.gui.match.views.VMessage; * TODO: Write javadoc for this type. * */ -public abstract class InputPayManaBase extends InputSyncronizedBase { +public abstract class InputPayManaBase extends InputSyncronizedBase implements InputPayment { private static final long serialVersionUID = -9133423708688480255L; @@ -39,9 +39,11 @@ public abstract class InputPayManaBase extends InputSyncronizedBase { protected ManaCostBeingPaid manaCost; protected final SpellAbility saPaidFor; + boolean bPaid = false; + protected InputPayManaBase(final GameState game, SpellAbility saToPayFor) { this.game = game; - this.whoPays = Singletons.getControl().getPlayer(); + this.whoPays = saToPayFor.getActivatingPlayer(); this.saPaidFor = saToPayFor; } @@ -312,6 +314,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase { @Override public void run() { if (manaCost.isPaid()) { + bPaid = true; done(); } else if (Singletons.getModel().getMatch().getInput().getInput() == InputPayManaBase.this) { showMessage(); @@ -333,10 +336,11 @@ public abstract class InputPayManaBase extends InputSyncronizedBase { for (final Card c : saPaidFor.getTappedForConvoke()) { c.setTapped(false); if (!isCancelled) - c.tap(); + c.tap(); // that will tap cards with all the triggers, it's no good to call this from EDT } saPaidFor.clearTappedForConvoke(); - } + } } + public boolean isPaid() { return bPaid; } } diff --git a/src/main/java/forge/control/input/InputPayManaOfCostPayment.java b/src/main/java/forge/control/input/InputPayManaOfCostPayment.java index d43fb71454a..4d32e437216 100644 --- a/src/main/java/forge/control/input/InputPayManaOfCostPayment.java +++ b/src/main/java/forge/control/input/InputPayManaOfCostPayment.java @@ -3,45 +3,23 @@ package forge.control.input; import forge.Card; import forge.Singletons; import forge.card.cost.CostPartMana; -import forge.card.cost.CostPayment; import forge.card.mana.ManaCostBeingPaid; import forge.card.spellability.SpellAbility; import forge.game.GameState; import forge.game.player.Player; -import forge.gui.match.CMatchUI; import forge.view.ButtonUtil; public class InputPayManaOfCostPayment extends InputPayManaBase { - private final CostPartMana costMana; - - // I would kill the one who made 2 classes like above - private final String originalManaCost; - private final int manaToAdd; - private final CostPayment payment; - - public InputPayManaOfCostPayment(final GameState game, CostPartMana costMana, SpellAbility spellAbility, final CostPayment payment, int toAdd) { + public InputPayManaOfCostPayment(final GameState game, CostPartMana costMana, SpellAbility spellAbility, int toAdd) { super(game, spellAbility); manaCost = new ManaCostBeingPaid(costMana.getManaToPay()); manaCost.increaseColorlessMana(toAdd); - - this.costMana = costMana; - originalManaCost = costMana.getMana(); - manaToAdd = toAdd; - this.payment = payment; } private static final long serialVersionUID = 3467312982164195091L; - - - private int phyLifeToLose = 0; - private void resetManaCost() { - this.manaCost = new ManaCostBeingPaid(this.originalManaCost); - this.phyLifeToLose = 0; - } - @Override public void selectPlayer(final Player player) { if (player == whoPays) { @@ -61,11 +39,6 @@ public class InputPayManaOfCostPayment extends InputPayManaBase { } source.setColorsPaid(this.manaCost.getColorsPaid()); source.setSunburstValue(this.manaCost.getSunburst()); - this.resetManaCost(); - - if (costMana.hasNoXManaCost() || (manaToAdd > 0)) { - payment.setPaidPart(costMana); - } // If this is a spell with convoke, re-tap all creatures used for it. // This is done to make sure Taps triggers go off at the right time @@ -79,9 +52,6 @@ public class InputPayManaOfCostPayment extends InputPayManaBase { @Override public void selectButtonCancel() { handleConvokedCards(true); - - this.resetManaCost(); - payment.cancelCost(); stop(); } @@ -89,7 +59,6 @@ public class InputPayManaOfCostPayment extends InputPayManaBase { public void showMessage() { ButtonUtil.enableOnlyCancel(); final String displayMana = manaCost.toString().replace("X", "").trim(); - CMatchUI.SINGLETON_INSTANCE.showMessage("Pay Mana Cost: " + displayMana); final StringBuilder msg = new StringBuilder("Pay Mana Cost: " + displayMana); if (this.phyLifeToLose > 0) { @@ -102,8 +71,9 @@ public class InputPayManaOfCostPayment extends InputPayManaBase { msg.append("\n(Click on your life total to pay life for phyrexian mana.)"); } - CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString()); + showMessage(msg.toString()); if (manaCost.isPaid()) { + bPaid = true; this.done(); } } diff --git a/src/main/java/forge/control/input/InputPayManaX.java b/src/main/java/forge/control/input/InputPayManaX.java index ecc85a589d8..ca7b231b176 100644 --- a/src/main/java/forge/control/input/InputPayManaX.java +++ b/src/main/java/forge/control/input/InputPayManaX.java @@ -2,7 +2,6 @@ package forge.control.input; import forge.Card; import forge.card.cost.CostPartMana; -import forge.card.cost.CostPayment; import forge.card.mana.ManaCostBeingPaid; import forge.card.spellability.SpellAbility; import forge.game.GameState; @@ -16,14 +15,12 @@ public class InputPayManaX extends InputPayManaBase { private final String strX; private String colorsPaid; private final CostPartMana costMana; - private final CostPayment payment; - public InputPayManaX(final GameState game, final SpellAbility sa0, final CostPayment payment0, final CostPartMana costMana0) + public InputPayManaX(final GameState game, final SpellAbility sa0, final CostPartMana costMana0) { super(game, sa0); - payment = payment0; xPaid = 0; colorX = saPaidFor.hasParam("XColor") ? saPaidFor.getParam("XColor") : ""; colorsPaid = saPaidFor.getSourceCard().getColorsPaid(); @@ -32,12 +29,25 @@ public class InputPayManaX extends InputPayManaBase { manaCost = new ManaCostBeingPaid(strX); } + /* (non-Javadoc) + * @see forge.control.input.InputPayManaBase#isPaid() + */ + @Override + public boolean isPaid() { + // only cancel if partially paid an X value + // or X is 0, and x can't be 0 + + + //return !( xPaid == 0 && !costMana.canXbe0() || this.colorX.equals("") && !this.manaCost.toString().equals(strX) ); + // return !( xPaid == 0 && !costMana.canXbe0()) && !(this.colorX.equals("") && !this.manaCost.toString().equals(strX)); + + return ( xPaid > 0 || costMana.canXbe0()) && (!this.colorX.equals("") || this.manaCost.toString().equals(strX)); + } + @Override public void showMessage() { - if (xPaid == 0 && !costMana.canXbe0() || this.colorX.equals("") && !this.manaCost.toString().equals(strX)) { + if (!isPaid()) { ButtonUtil.enableOnlyCancel(); - // only cancel if partially paid an X value - // or X is 0, and x can't be 0 } else { ButtonUtil.enableAllFocusOk(); } @@ -55,6 +65,7 @@ public class InputPayManaX extends InputPayManaBase { // selectCard @Override public void selectCard(final Card card) { + // don't allow here the cards that produce only wrong colors activateManaAbility(card, this.colorX.isEmpty() ? this.manaCost : new ManaCostBeingPaid(this.colorX)); } @@ -72,7 +83,6 @@ public class InputPayManaX extends InputPayManaBase { @Override public void selectButtonCancel() { - payment.cancelCost(); this.stop(); } @@ -89,10 +99,10 @@ public class InputPayManaX extends InputPayManaBase { @Override protected void done() { - payment.getCard().setXManaCostPaid(this.xPaid); - payment.setPaidPart(costMana); - payment.getCard().setColorsPaid(this.colorsPaid); - payment.getCard().setSunburstValue(this.colorsPaid.length()); + final Card card = saPaidFor.getSourceCard(); + card.setXManaCostPaid(this.xPaid); + card.setColorsPaid(this.colorsPaid); + card.setSunburstValue(this.colorsPaid.length()); this.stop(); } }