Syncronous mana payment that used to execute commands

This commit is contained in:
Maxmtg
2013-03-23 13:57:56 +00:00
parent c3f7facedf
commit c30bb25547
10 changed files with 232 additions and 259 deletions

View File

@@ -23,6 +23,8 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.CountDownLatch;
import javax.swing.JOptionPane;
import com.google.common.collect.Iterables;
@@ -30,8 +32,8 @@ import com.google.common.collect.Iterables;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.FThreads;
import forge.CardPredicates.Presets;
import forge.Command;
import forge.Constant;
import forge.Singletons;
import forge.card.CardType;
@@ -461,21 +463,13 @@ public class CardFactorySorceries {
game.getAction().moveToPlay(newArtifact[0]);
} else {
final String diffCost = String.valueOf(newCMC - baseCMC);
Singletons.getModel().getMatch().getInput().setInput(new InputPayManaExecuteCommands(game, "Pay difference in artifacts CMC", diffCost, new Command() {
private static final long serialVersionUID = -8729850321341068049L;
@Override
public void execute() {
Singletons.getModel().getGame().getAction().moveToPlay(newArtifact[0]);
}
}, new Command() {
private static final long serialVersionUID = -246036834856971935L;
@Override
public void execute() {
Singletons.getModel().getGame().getAction().moveToGraveyard(newArtifact[0]);
}
}));
final CountDownLatch cdl = new CountDownLatch(1);
InputPayManaExecuteCommands inp = new InputPayManaExecuteCommands(game, "Pay difference in artifacts CMC", diffCost, cdl);
FThreads.setInputAndWait(inp, cdl);
if ( inp.isPaid() )
Singletons.getModel().getGame().getAction().moveToPlay(newArtifact[0]);
else
Singletons.getModel().getGame().getAction().moveToGraveyard(newArtifact[0]);
}
// finally, shuffle library

View File

@@ -44,7 +44,22 @@ public final class ManaCost implements Comparable<ManaCost> {
public static final ManaCost NO_COST = new ManaCost(-1);
public static final ManaCost ZERO = new ManaCost(0);
public static final ManaCost ONE = new ManaCost(1);
public static final ManaCost TWO = new ManaCost(2);
public static final ManaCost THREE = new ManaCost(3);
public static final ManaCost FOUR = new ManaCost(4);
public static ManaCost get(int cntColorless) {
if(cntColorless >= 5 || cntColorless < 0) throw new IllegalArgumentException("Supports only 0-4");
switch (cntColorless) {
case 0: return ZERO;
case 1: return ONE;
case 2: return TWO;
case 3: return THREE;
case 4: return FOUR;
default: return NO_COST;
}
}
// pass mana cost parser here
private ManaCost(int cmc) {
this.hasNoCost = cmc < 0;

View File

@@ -18,10 +18,10 @@
package forge.control.input;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import forge.Card;
import forge.CardLists;
import forge.Command;
import forge.Singletons;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.CostDiscard;
@@ -42,7 +42,7 @@ import forge.view.ButtonUtil;
* @author Forge
* @version $Id: InputPayManaCostAbility.java 15673 2012-05-23 14:01:35Z ArsenalNut $
*/
public class InputPayDiscardCostWithCommands extends Input {
public class InputPayDiscardCostWithCommands extends Input implements InputPayment {
/**
* Constant <code>serialVersionUID=2685832214529141991L</code>.
*/
@@ -53,8 +53,10 @@ public class InputPayDiscardCostWithCommands extends Input {
private List<Card> choiceList;
private CostDiscard discardCost;
private SpellAbility ability;
private Command paid;
private Command unpaid;
private boolean bPaid;
private final CountDownLatch cdlDone;
public final boolean isPaid() { return bPaid; }
/**
* <p>
@@ -70,19 +72,16 @@ public class InputPayDiscardCostWithCommands extends Input {
* @param unpaidCommand
* a {@link forge.Command} object.
*/
public InputPayDiscardCostWithCommands(final CostDiscard cost, final SpellAbility sa, final Command paidCommand,
final Command unpaidCommand) {
public InputPayDiscardCostWithCommands(final CostDiscard cost, final SpellAbility sa, final CountDownLatch cdl) {
final Card source = sa.getSourceCard();
final Player human = Singletons.getControl().getPlayer();
this.cdlDone = cdl;
this.ability = sa;
this.discardCost = cost;
this.choiceList = CardLists.getValidCards(human.getCardsIn(ZoneType.Hand), cost.getType().split(";"), human, source);
String amountString = cost.getAmount();
this.numRequired = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString)
: CardFactoryUtil.xCount(source, source.getSVar(amountString));
this.paid = paidCommand;
this.unpaid = unpaidCommand;
}
/** {@inheritDoc} */
@@ -168,7 +167,10 @@ public class InputPayDiscardCostWithCommands extends Input {
Singletons.getControl().getPlayer().discard(selected, this.ability);
}
this.discardCost.addListToHash(ability, "Discarded");
this.paid.execute();
bPaid = true;
cdlDone.countDown();
}
/**
@@ -182,7 +184,8 @@ public class InputPayDiscardCostWithCommands extends Input {
for (Card selected : this.discardCost.getList()) {
selected.setUsedToPay(false);
}
this.unpaid.execute();
bPaid = false;
cdlDone.countDown();
}
@Override public void isClassUpdated() {

View File

@@ -17,7 +17,8 @@
*/
package forge.control.input;
import forge.Command;
import java.util.concurrent.CountDownLatch;
import forge.Singletons;
import forge.card.mana.ManaCostBeingPaid;
import forge.card.spellability.SpellAbility;
@@ -36,18 +37,19 @@ import forge.view.ButtonUtil;
* @author Forge
* @version $Id$
*/
public class InputPayManaExecuteCommands extends InputPayManaBase {
public class InputPayManaExecuteCommands extends InputPayManaBase implements InputPayment {
/**
* Constant <code>serialVersionUID=3836655722696348713L</code>.
*/
private static final long serialVersionUID = 3836655722696348713L;
final private CountDownLatch cdlDone;
private String originalManaCost;
private String message = "";
private Command paidCommand;
private Command unpaidCommand;
private boolean bPaid = false;
public boolean isPaid() { return bPaid; }
// only used for X costs:
private boolean showOnlyOKButton = false;
@@ -67,8 +69,8 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
* @param unpaidCommand2
* a {@link forge.Command} object.
*/
public InputPayManaExecuteCommands(final GameState game, final String prompt, final String manaCost2, final Command paidCommand2, final Command unpaidCommand2) {
this(game, prompt, manaCost2, paidCommand2, unpaidCommand2, false);
public InputPayManaExecuteCommands(final GameState game, final String prompt, final String manaCost2, final CountDownLatch cdl) {
this(game, prompt, manaCost2, cdl, false);
}
/**
@@ -87,7 +89,7 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
* @param showOKButton
* a boolean.
*/
public InputPayManaExecuteCommands(final GameState game, final String prompt, final String manaCost2, final Command paid, final Command unpaid, final boolean showOKButton) {
public InputPayManaExecuteCommands(final GameState game, final String prompt, final String manaCost2, final CountDownLatch cdl, final boolean showOKButton) {
super(game, new SpellAbility(null) {
@Override
public void resolve() {}
@@ -98,10 +100,9 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
this.originalManaCost = manaCost2;
this.phyLifeToLose = 0;
this.message = prompt;
this.cdlDone = cdl;
this.manaCost = new ManaCostBeingPaid(this.originalManaCost);
this.paidCommand = paid;
this.unpaidCommand = unpaid;
this.showOnlyOKButton = showOKButton;
}
@@ -134,19 +135,22 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
if (this.phyLifeToLose > 0) {
Singletons.getControl().getPlayer().payLife(this.phyLifeToLose, null);
}
this.paidCommand.execute();
this.resetManaCost();
Singletons.getControl().getPlayer().getManaPool().clearManaPaid(this.saPaidFor, false);
bPaid = true;
this.stop();
cdlDone.countDown();
}
/** {@inheritDoc} */
@Override
public final void selectButtonCancel() {
this.unpaidCommand.execute();
this.resetManaCost();
Singletons.getControl().getPlayer().getManaPool().refundManaPaid(this.saPaidFor, true);
bPaid = false;
this.stop();
cdlDone.countDown();
}
/** {@inheritDoc} */
@@ -154,7 +158,9 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
public final void selectButtonOK() {
if (this.showOnlyOKButton) {
this.stop();
this.unpaidCommand.execute();
bPaid = false;
cdlDone.countDown();
}
}

View File

@@ -18,10 +18,10 @@
package forge.control.input;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import forge.Card;
import forge.CardLists;
import forge.Command;
import forge.Singletons;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.CostReturn;
@@ -41,7 +41,7 @@ import forge.view.ButtonUtil;
* @author Forge
* @version $Id: InputPayManaCostAbility.java 15673 2012-05-23 14:01:35Z ArsenalNut $
*/
public class InputPayReturnCost extends Input {
public class InputPayReturnCost extends Input implements InputPayment {
/**
* Constant <code>serialVersionUID=2685832214529141991L</code>.
*/
@@ -52,8 +52,11 @@ public class InputPayReturnCost extends Input {
private List<Card> choiceList;
private CostReturn returnCost;
private SpellAbility ability;
private Command paid;
private Command unpaid;
private boolean bPaid;
public boolean isPaid() { return bPaid; }
private final CountDownLatch cdlDone;
/**
* <p>
@@ -69,18 +72,16 @@ public class InputPayReturnCost extends Input {
* @param unpaidCommand
* a {@link forge.Command} object.
*/
public InputPayReturnCost(final CostReturn cost, final SpellAbility sa, final Command paidCommand,
final Command unpaidCommand) {
public InputPayReturnCost(final CostReturn cost, final SpellAbility sa, final CountDownLatch cdl) {
final Card source = sa.getSourceCard();
this.cdlDone = cdl;
this.ability = sa;
this.returnCost = cost;
this.choiceList = CardLists.getValidCards(Singletons.getControl().getPlayer().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), Singletons.getControl().getPlayer(), source);
String amountString = cost.getAmount();
this.numRequired = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString)
: CardFactoryUtil.xCount(source, source.getSVar(amountString));
this.paid = paidCommand;
this.unpaid = unpaidCommand;
}
/** {@inheritDoc} */
@@ -168,7 +169,8 @@ public class InputPayReturnCost extends Input {
Singletons.getModel().getGame().getAction().moveTo(ZoneType.Hand, selected);
}
this.returnCost.addListToHash(ability, "Returned");
this.paid.execute();
bPaid = true;
cdlDone.countDown();
}
/**
@@ -182,7 +184,8 @@ public class InputPayReturnCost extends Input {
for (Card selected : this.returnCost.getList()) {
selected.setUsedToPay(false);
}
this.unpaid.execute();
bPaid = false;
cdlDone.countDown();
}
@Override public void isClassUpdated() {

View File

@@ -0,0 +1,5 @@
package forge.control.input;
public interface InputPayment {
boolean isPaid();
}

View File

@@ -20,6 +20,7 @@ package forge.game;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.lang3.StringUtils;
@@ -34,6 +35,7 @@ import forge.CardUtil;
import forge.Command;
import forge.Constant;
import forge.CounterType;
import forge.FThreads;
import forge.Singletons;
import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityUtils;
@@ -61,6 +63,7 @@ import forge.control.input.Input;
import forge.control.input.InputPayDiscardCostWithCommands;
import forge.control.input.InputPayManaExecuteCommands;
import forge.control.input.InputPayReturnCost;
import forge.control.input.InputPayment;
import forge.game.event.CardDamagedEvent;
import forge.game.event.LifeLossEvent;
import forge.game.player.AIPlayer;
@@ -367,31 +370,6 @@ public final class GameActionUtil {
ripple.execute();
}
/**
* <p>
* payManaDuringAbilityResolve.
* </p>
*
* @param message
* a {@link java.lang.String} object.
* @param spellManaCost
* a {@link java.lang.String} object.
* @param paid
* a {@link forge.Command} object.
* @param unpaid
* a {@link forge.Command} object.
*/
public static void payManaDuringAbilityResolve(final String message, final ManaCost spellManaCost, final Command paid,
final Command unpaid) {
// temporarily disable the Resolve flag, so the user can payMana for the
// resolving Ability
GameState game = Singletons.getModel().getGame();
final boolean bResolving = game.getStack().isResolving();
game.getStack().setResolving(false);
Singletons.getModel().getMatch().getInput().setInput(new InputPayManaExecuteCommands(game, message, spellManaCost.toString(), paid, unpaid));
game.getStack().setResolving(bResolving);
}
/**
* <p>
* payCostDuringAbilityResolve.
@@ -597,25 +575,28 @@ public final class GameActionUtil {
// interface for sacrifice costs (instead of the menu-based one above).
//the following costs need inputs and can't be combined at the moment
Input toSet = null;
CountDownLatch cdl = new CountDownLatch(1);
if (costPart instanceof CostReturn) {
toSet = new InputPayReturnCost((CostReturn) costPart, ability, paid, unpaid);
toSet = new InputPayReturnCost((CostReturn) costPart, ability, cdl);
}
else if (costPart instanceof CostDiscard) {
toSet = new InputPayDiscardCostWithCommands((CostDiscard) costPart, ability, paid, unpaid);
toSet = new InputPayDiscardCostWithCommands((CostDiscard) costPart, ability, cdl);
}
else if (costPart instanceof CostPartMana) {
toSet = new InputPayManaExecuteCommands(game, source + "\r\n", ability.getManaCost().toString(), paid, unpaid);
toSet = new InputPayManaExecuteCommands(game, source + "\r\n", ability.getManaCost().toString(), cdl);
}
if (toSet != null) {
// temporarily disable the Resolve flag, so the user can payMana for the
// resolving Ability
final boolean bResolving = Singletons.getModel().getGame().getStack().isResolving();
Singletons.getModel().getGame().getStack().setResolving(false);
Singletons.getModel().getMatch().getInput().setInput(toSet);
Singletons.getModel().getGame().getStack().setResolving(bResolving);
FThreads.setInputAndWait(toSet, cdl);
if (((InputPayment)toSet).isPaid() ) {
paid.execute();
} else {
unpaid.execute();
}
}
}

View File

@@ -21,12 +21,14 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import com.google.common.base.Predicate;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.FThreads;
import forge.CardPredicates.Presets;
import forge.Command;
import forge.CounterType;
@@ -40,6 +42,7 @@ import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.AbilityStatic;
import forge.card.spellability.SpellAbility;
import forge.control.input.Input;
import forge.control.input.InputPayManaExecuteCommands;
import forge.control.input.InputSelectManyCards;
import forge.game.GameActionUtil;
import forge.game.GameState;
@@ -279,44 +282,35 @@ public class Upkeep extends Phase {
final String[] k = ability.split(" pay ");
final ManaCost upkeepCost = new ManaCost(new ManaCostParser(k[1]));
final Command unpaidCommand = new Command() {
private static final long serialVersionUID = 8942537892273123542L;
@Override
public void execute() {
if (c.getName().equals("Cosmic Horror")) {
controller.addDamage(7, c);
}
game.getAction().destroy(c);
}
};
final Command paidCommand = Command.BLANK;
final Ability aiPaid = Upkeep.BlankAbility(c, upkeepCost.toString());
final StringBuilder sb = new StringBuilder();
sb.append("Upkeep for ").append(c).append("\n");
final String sb = "Upkeep for " + c;
final Ability upkeepAbility = new Ability(c, ManaCost.ZERO) {
@Override
public void resolve() {
final boolean isUpkeepPaid;
if (controller.isHuman()) {
GameActionUtil.payManaDuringAbilityResolve(sb.toString(), upkeepCost, paidCommand, unpaidCommand);
CountDownLatch cdl = new CountDownLatch(1);
InputPayManaExecuteCommands inp = new InputPayManaExecuteCommands(game, sb, upkeepCost.toString(), cdl);
FThreads.setInputAndWait(inp, cdl);
isUpkeepPaid = inp.isPaid();
} else { // computer
if (ComputerUtilCost.canPayCost(aiPaid, controller) && !c.hasKeyword("Indestructible")) {
Ability aiPaid = Upkeep.BlankAbility(c, upkeepCost.toString());
isUpkeepPaid = ComputerUtilCost.canPayCost(aiPaid, controller) && !c.hasKeyword("Indestructible");
if (isUpkeepPaid) {
ComputerUtil.playNoStack((AIPlayer)controller, aiPaid, game);
} else {
if (c.getName().equals("Cosmic Horror")) {
controller.addDamage(7, c);
}
game.getAction().destroy(c);
}
}
if( !isUpkeepPaid ) {
if (c.getName().equals("Cosmic Horror")) {
controller.addDamage(7, c);
}
game.getAction().destroy(c);
}
}
};
upkeepAbility.setActivatingPlayer(controller);
upkeepAbility.setStackDescription(sb.toString());
upkeepAbility.setDescription(sb.toString());
upkeepAbility.setStackDescription(sb);
upkeepAbility.setDescription(sb);
game.getStack().addSimultaneousStackEntry(upkeepAbility);
} // destroy
@@ -386,34 +380,26 @@ public class Upkeep extends Phase {
final String[] l = k[1].split(" pay ");
final ManaCost upkeepCost = new ManaCost(new ManaCostParser(l[1]));
final Command unpaidCommand = new Command() {
private static final long serialVersionUID = 1238166187561501928L;
@Override
public void execute() {
controller.addDamage(upkeepDamage, c);
}
};
final Command paidCommand = Command.BLANK;
final Ability aiPaid = Upkeep.BlankAbility(c, upkeepCost.toString());
final StringBuilder sb = new StringBuilder();
sb.append("Damage upkeep for ").append(c).append("\n");
final String sb = "Damage upkeep for " + c;
final Ability upkeepAbility = new Ability(c, ManaCost.ZERO) {
@Override
public void resolve() {
boolean isUpkeepPaid = false;
if (controller.isHuman()) {
GameActionUtil.payManaDuringAbilityResolve(sb.toString(), upkeepCost, paidCommand, unpaidCommand);
CountDownLatch cdl = new CountDownLatch(1);
InputPayManaExecuteCommands inp = new InputPayManaExecuteCommands(game, sb, upkeepCost.toString(), cdl);
FThreads.setInputAndWait(inp, cdl);
isUpkeepPaid = inp.isPaid();
} else { // computers
if (ComputerUtilCost.canPayCost(aiPaid, controller)
&& (ComputerUtilCombat.predictDamageTo(controller, upkeepDamage, c, false) > 0)) {
final Ability aiPaid = Upkeep.BlankAbility(c, upkeepCost.toString());
if (ComputerUtilCost.canPayCost(aiPaid, controller) && ComputerUtilCombat.predictDamageTo(controller, upkeepDamage, c, false) > 0) {
ComputerUtil.playNoStack((AIPlayer)controller, aiPaid, game);
} else {
controller.addDamage(upkeepDamage, c);
isUpkeepPaid = true;
}
}
if (!isUpkeepPaid) {
controller.addDamage(upkeepDamage, c);
}
}
};
upkeepAbility.setActivatingPlayer(controller);
@@ -617,9 +603,7 @@ public class Upkeep extends Phase {
final Player player = game.getPhaseHandler().getPlayerTurn();
final List<Card> cards = player.getCardsIn(ZoneType.Battlefield, "Demonic Hordes");
for (int i = 0; i < cards.size(); i++) {
final Card c = cards.get(i);
for (final Card c : cards) {
final Ability cost = new Ability(c, new ManaCost(new ManaCostParser("B B B"))) {
@Override
@@ -627,7 +611,7 @@ public class Upkeep extends Phase {
}
}; // end cost ability
final Ability noPay = new Ability(c, ManaCost.ZERO) {
final Ability unpaidHordesAb = new Ability(c, ManaCost.ZERO) {
@Override
public void resolve() {
final List<Card> playerLand = player.getLandsInPlay();
@@ -648,36 +632,25 @@ public class Upkeep extends Phase {
final Player cp = c.getController();
if (cp.isHuman()) {
final String question = "Pay Demonic Hordes upkeep cost?";
if (GuiDialog.confirm(c, question)) {
final Ability pay = new Ability(c, ManaCost.ZERO) {
@Override
public void resolve() {
if (game.getZoneOf(c).is(ZoneType.Battlefield)) {
final StringBuilder coststring = new StringBuilder();
coststring.append("Pay cost for ").append(c).append("\r\n");
GameActionUtil.payManaDuringAbilityResolve(coststring.toString(), cost.getManaCost(),
Command.BLANK, Command.BLANK);
}
} // end resolve()
}; // end pay ability
pay.setStackDescription("Demonic Hordes - Upkeep Cost");
pay.setDescription("Demonic Hordes - Upkeep Cost");
final Ability pay = new Ability(c, ManaCost.ZERO) {
@Override
public void resolve() {
if (game.getZoneOf(c).is(ZoneType.Battlefield)) {
CountDownLatch cdl = new CountDownLatch(1);
InputPayManaExecuteCommands inp = new InputPayManaExecuteCommands(game, "Pay Demonic Hordes upkeep cost", cost.getManaCost().toString(), cdl/*, true */);
FThreads.setInputAndWait(inp, cdl);
if ( !inp.isPaid() )
unpaidHordesAb.resolve();
}
} // end resolve()
}; // end pay ability
pay.setStackDescription("Demonic Hordes - Upkeep Cost");
pay.setDescription("Demonic Hordes - Upkeep Cost");
game.getStack().addSimultaneousStackEntry(pay);
} // end choice
else {
final StringBuilder sb = new StringBuilder();
sb.append(c.getName()).append(" - is tapped and you must sacrifice a land of opponent's choice");
noPay.setStackDescription(sb.toString());
game.getStack().addSimultaneousStackEntry(noPay);
}
game.getStack().addSimultaneousStackEntry(pay);
} // end human
else { // computer
noPay.setActivatingPlayer(cp);
unpaidHordesAb.setActivatingPlayer(cp);
if (ComputerUtilCost.canPayCost(cost, (AIPlayer) cp)) {
final Ability computerPay = new Ability(c, ManaCost.ZERO) {
@Override
@@ -689,8 +662,8 @@ public class Upkeep extends Phase {
game.getStack().addSimultaneousStackEntry(computerPay);
} else {
noPay.setStackDescription("Demonic Hordes - Upkeep Cost");
game.getStack().addSimultaneousStackEntry(noPay);
unpaidHordesAb.setStackDescription("Demonic Hordes - Upkeep Cost");
game.getStack().addSimultaneousStackEntry(unpaidHordesAb);
}
} // end computer

View File

@@ -22,12 +22,14 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.CountDownLatch;
import com.esotericsoftware.minlog.Log;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.FThreads;
import forge.CardPredicates.Presets;
import forge.Command;
import forge.Singletons;
@@ -36,7 +38,6 @@ import forge.card.cardfactory.CardFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostBeingPaid;
import forge.card.mana.ManaCostParser;
import forge.card.spellability.Ability;
import forge.card.spellability.AbilityStatic;
import forge.card.spellability.AbilityTriggered;
@@ -478,49 +479,38 @@ public class MagicStack extends MyObservable {
} else if (sp.isXCost()) {
// TODO: convert any X costs to use abCost so it happens earlier
final SpellAbility sa = sp;
final ManaCost mc = new ManaCost( new ManaCostParser(Integer.toString(sa.getXManaCost())));
final Ability ability = new Ability(sp.getSourceCard(), mc) {
@Override
public void resolve() {
final Card crd = this.getSourceCard();
crd.addXManaCostPaid(1);
}
};
final Command unpaidCommand = new Command() {
private static final long serialVersionUID = -3342222770086269767L;
@Override
public void execute() {
MagicStack.this.push(sa);
}
};
final Command paidCommand = new Command() {
private static final long serialVersionUID = -2224875229611007788L;
@Override
public void execute() {
ability.resolve();
final Card crd = sa.getSourceCard();
Singletons.getModel().getMatch().getInput().setInput(
new InputPayManaExecuteCommands(game, "Pay X cost for " + crd.getName() + " (X="
+ crd.getXManaCostPaid() + ")\r\n", ability.getManaCost().toString(), this, unpaidCommand,
true));
}
};
final Card crd = sa.getSourceCard();
final int xCost = sa.getXManaCost();
Player player = sp.getSourceCard().getController();
if (player.isHuman()) {
Singletons.getModel().getMatch().getInput().setInput(
new InputPayManaExecuteCommands(game, "Pay X cost for " + sp.getSourceCard().getName() + " (X="
+ crd.getXManaCostPaid() + ")\r\n", ability.getManaCost().toString(), paidCommand,
unpaidCommand, true));
final Runnable payNextX = new Runnable() {
@Override
public void run() {
final Card crd = sa.getSourceCard();
String message = "Pay X cost for " + crd.getName() + " (X=" + crd.getXManaCostPaid() + ")\r\n";
CountDownLatch cdl = new CountDownLatch(1);
InputPayManaExecuteCommands inp = new InputPayManaExecuteCommands(game, message, String.valueOf(xCost), cdl, true);
FThreads.setInputAndWait(inp, cdl);
if ( inp.isPaid() ) {
crd.addXManaCostPaid(1);
this.run();
} else
MagicStack.this.push(sa);
}
};
payNextX.run();
} else {
// computer
final int neededDamage = CardFactoryUtil.getNeededXDamage(sa);
final Ability ability = new Ability(sp.getSourceCard(), ManaCost.get(xCost)) {
@Override
public void resolve() {
final Card crd = this.getSourceCard();
crd.addXManaCostPaid(1);
}
};
while (ComputerUtilCost.canPayCost(ability, player) && (neededDamage != sa.getSourceCard().getXManaCostPaid())) {
ComputerUtil.playNoStack((AIPlayer)player, ability, game);
}
@@ -548,37 +538,44 @@ public class MagicStack extends MyObservable {
}
};
final Command paidCommand = new Command() {
private static final long serialVersionUID = -6037161763374971106L;
@Override
public void execute() {
ability.resolve();
final ManaCostBeingPaid manaCost = MagicStack.this.getMultiKickerSpellCostChange(ability);
if (manaCost.isPaid()) {
this.execute();
} else {
String prompt;
int mkCostPaid = game.getActionPlay().getCostCuttingGetMultiKickerManaCostPaid();
String mkCostPaidColored = game.getActionPlay().getCostCuttingGetMultiKickerManaCostPaidColored();
int mkMagnitude = sa.getSourceCard().getMultiKickerMagnitude();
if ((mkCostPaid == 0) && mkCostPaidColored.equals("")) {
prompt = String.format("Multikicker for %s\r\nTimes Kicked: %d\r\n", sa.getSourceCard(), mkMagnitude );
} else {
prompt = String.format("Multikicker for %s\r\nMana in Reserve: %s %s\r\nTimes Kicked: %d", sa.getSourceCard(),
(mkCostPaid != 0) ? Integer.toString(mkCostPaid) : "", mkCostPaidColored, mkMagnitude);
}
Input toSet = new InputPayManaExecuteCommands(game, prompt, manaCost.toString(), this, unpaidCommand);
Singletons.getModel().getMatch().getInput().setInput(toSet);
}
}
};
Player activating = sp.getActivatingPlayer();
if (activating.isHuman()) {
sa.getSourceCard().addMultiKickerMagnitude(-1);
final Command paidCommand = new Command() {
private static final long serialVersionUID = -6037161763374971106L;
@Override
public void execute() {
ability.resolve();
final ManaCostBeingPaid manaCost = MagicStack.this.getMultiKickerSpellCostChange(ability);
if (manaCost.isPaid()) {
this.execute();
} else {
String prompt;
int mkCostPaid = game.getActionPlay().getCostCuttingGetMultiKickerManaCostPaid();
String mkCostPaidColored = game.getActionPlay().getCostCuttingGetMultiKickerManaCostPaidColored();
int mkMagnitude = sa.getSourceCard().getMultiKickerMagnitude();
if ((mkCostPaid == 0) && mkCostPaidColored.equals("")) {
prompt = String.format("Multikicker for %s\r\nTimes Kicked: %d\r\n", sa.getSourceCard(), mkMagnitude );
} else {
prompt = String.format("Multikicker for %s\r\nMana in Reserve: %s %s\r\nTimes Kicked: %d", sa.getSourceCard(),
(mkCostPaid != 0) ? Integer.toString(mkCostPaid) : "", mkCostPaidColored, mkMagnitude);
}
CountDownLatch cdl = new CountDownLatch(1);
InputPayManaExecuteCommands toSet = new InputPayManaExecuteCommands(game, prompt, manaCost.toString(), cdl);
FThreads.setInputAndWait(toSet, cdl);
if ( toSet.isPaid() ) {
this.execute();
} else
unpaidCommand.execute();
Singletons.getModel().getMatch().getInput().setInput(toSet);
}
}
};
paidCommand.execute();
} else {
// computer
@@ -603,38 +600,33 @@ public class MagicStack extends MyObservable {
}
};
final Command unpaidCommand = new Command() {
private static final long serialVersionUID = -3180458633098297855L;
@Override
public void execute() {
for (int i = 0; i < sp.getSourceCard().getReplicateMagnitude(); i++) {
CardFactory.copySpellontoStack(sp.getSourceCard(), sp.getSourceCard(), sp, false);
}
}
};
final Command paidCommand = new Command() {
private static final long serialVersionUID = 132624005072267304L;
@Override
public void execute() {
ability.resolve();
final ManaCostBeingPaid manaCost = MagicStack.this.getReplicateSpellCostChange(ability);
if (manaCost.isPaid()) {
this.execute();
} else {
String prompt = String.format("Replicate for %s\r\nTimes Replicated: %d\r\n", sa.getSourceCard(), sa.getSourceCard().getReplicateMagnitude());
Input toSet = new InputPayManaExecuteCommands(game, prompt, manaCost.toString(), this, unpaidCommand);
Singletons.getModel().getMatch().getInput().setInput(toSet);
}
}
};
Player controller = sp.getSourceCard().getController();
if (controller.isHuman()) {
sa.getSourceCard().addReplicateMagnitude(-1);
paidCommand.execute();
final Runnable addMagnitude = new Runnable() {
@Override
public void run() {
ability.resolve();
final ManaCostBeingPaid manaCost = MagicStack.this.getReplicateSpellCostChange(ability);
if (manaCost.isPaid()) {
this.run();
} else {
String prompt = String.format("Replicate for %s\r\nTimes Replicated: %d\r\n", sa.getSourceCard(), sa.getSourceCard().getReplicateMagnitude());
CountDownLatch cdl = new CountDownLatch(1);
InputPayManaExecuteCommands toSet = new InputPayManaExecuteCommands(game, prompt, manaCost.toString(), cdl);
FThreads.setInputAndWait(toSet, cdl);
if ( toSet.isPaid() ) {
this.run();
} else {
for (int i = 0; i < sp.getSourceCard().getReplicateMagnitude(); i++) {
CardFactory.copySpellontoStack(sp.getSourceCard(), sp.getSourceCard(), sp, false);
}
}
}
}
};
addMagnitude.run();
} else {
// computer
while (ComputerUtilCost.canPayCost(ability, controller)) {