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

1
.gitattributes vendored
View File

@@ -13812,6 +13812,7 @@ src/main/java/forge/control/input/InputPayManaSimple.java svneol=native#text/pla
src/main/java/forge/control/input/InputPayManaX.java -text src/main/java/forge/control/input/InputPayManaX.java -text
src/main/java/forge/control/input/InputPayReturnCost.java -text src/main/java/forge/control/input/InputPayReturnCost.java -text
src/main/java/forge/control/input/InputPaySacCost.java -text src/main/java/forge/control/input/InputPaySacCost.java -text
src/main/java/forge/control/input/InputPayment.java -text
src/main/java/forge/control/input/InputSelectMany.java -text src/main/java/forge/control/input/InputSelectMany.java -text
src/main/java/forge/control/input/InputSelectManyCards.java -text src/main/java/forge/control/input/InputSelectManyCards.java -text
src/main/java/forge/control/input/InputSelectManyPlayers.java -text src/main/java/forge/control/input/InputSelectManyPlayers.java -text

View File

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

View File

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

View File

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

View File

@@ -18,10 +18,10 @@
package forge.control.input; package forge.control.input;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.Command;
import forge.Singletons; import forge.Singletons;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.CostReturn; import forge.card.cost.CostReturn;
@@ -41,7 +41,7 @@ import forge.view.ButtonUtil;
* @author Forge * @author Forge
* @version $Id: InputPayManaCostAbility.java 15673 2012-05-23 14:01:35Z ArsenalNut $ * @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>. * Constant <code>serialVersionUID=2685832214529141991L</code>.
*/ */
@@ -52,8 +52,11 @@ public class InputPayReturnCost extends Input {
private List<Card> choiceList; private List<Card> choiceList;
private CostReturn returnCost; private CostReturn returnCost;
private SpellAbility ability; private SpellAbility ability;
private Command paid;
private Command unpaid; private boolean bPaid;
public boolean isPaid() { return bPaid; }
private final CountDownLatch cdlDone;
/** /**
* <p> * <p>
@@ -69,18 +72,16 @@ public class InputPayReturnCost extends Input {
* @param unpaidCommand * @param unpaidCommand
* a {@link forge.Command} object. * a {@link forge.Command} object.
*/ */
public InputPayReturnCost(final CostReturn cost, final SpellAbility sa, final Command paidCommand, public InputPayReturnCost(final CostReturn cost, final SpellAbility sa, final CountDownLatch cdl) {
final Command unpaidCommand) {
final Card source = sa.getSourceCard(); final Card source = sa.getSourceCard();
this.cdlDone = cdl;
this.ability = sa; this.ability = sa;
this.returnCost = cost; this.returnCost = cost;
this.choiceList = CardLists.getValidCards(Singletons.getControl().getPlayer().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), Singletons.getControl().getPlayer(), source); this.choiceList = CardLists.getValidCards(Singletons.getControl().getPlayer().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), Singletons.getControl().getPlayer(), source);
String amountString = cost.getAmount(); String amountString = cost.getAmount();
this.numRequired = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString) this.numRequired = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString)
: CardFactoryUtil.xCount(source, source.getSVar(amountString)); : CardFactoryUtil.xCount(source, source.getSVar(amountString));
this.paid = paidCommand;
this.unpaid = unpaidCommand;
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@@ -168,7 +169,8 @@ public class InputPayReturnCost extends Input {
Singletons.getModel().getGame().getAction().moveTo(ZoneType.Hand, selected); Singletons.getModel().getGame().getAction().moveTo(ZoneType.Hand, selected);
} }
this.returnCost.addListToHash(ability, "Returned"); 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()) { for (Card selected : this.returnCost.getList()) {
selected.setUsedToPay(false); selected.setUsedToPay(false);
} }
this.unpaid.execute(); bPaid = false;
cdlDone.countDown();
} }
@Override public void isClassUpdated() { @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.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -34,6 +35,7 @@ import forge.CardUtil;
import forge.Command; import forge.Command;
import forge.Constant; import forge.Constant;
import forge.CounterType; import forge.CounterType;
import forge.FThreads;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityFactory; import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
@@ -61,6 +63,7 @@ import forge.control.input.Input;
import forge.control.input.InputPayDiscardCostWithCommands; import forge.control.input.InputPayDiscardCostWithCommands;
import forge.control.input.InputPayManaExecuteCommands; import forge.control.input.InputPayManaExecuteCommands;
import forge.control.input.InputPayReturnCost; import forge.control.input.InputPayReturnCost;
import forge.control.input.InputPayment;
import forge.game.event.CardDamagedEvent; import forge.game.event.CardDamagedEvent;
import forge.game.event.LifeLossEvent; import forge.game.event.LifeLossEvent;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
@@ -367,31 +370,6 @@ public final class GameActionUtil {
ripple.execute(); 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> * <p>
* payCostDuringAbilityResolve. * payCostDuringAbilityResolve.
@@ -597,25 +575,28 @@ public final class GameActionUtil {
// interface for sacrifice costs (instead of the menu-based one above). // interface for sacrifice costs (instead of the menu-based one above).
//the following costs need inputs and can't be combined at the moment //the following costs need inputs and can't be combined at the moment
Input toSet = null; Input toSet = null;
CountDownLatch cdl = new CountDownLatch(1);
if (costPart instanceof CostReturn) { if (costPart instanceof CostReturn) {
toSet = new InputPayReturnCost((CostReturn) costPart, ability, paid, unpaid); toSet = new InputPayReturnCost((CostReturn) costPart, ability, cdl);
} }
else if (costPart instanceof CostDiscard) { 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) { 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) { if (toSet != null) {
// temporarily disable the Resolve flag, so the user can payMana for the
// resolving Ability FThreads.setInputAndWait(toSet, cdl);
final boolean bResolving = Singletons.getModel().getGame().getStack().isResolving(); if (((InputPayment)toSet).isPaid() ) {
Singletons.getModel().getGame().getStack().setResolving(false); paid.execute();
Singletons.getModel().getMatch().getInput().setInput(toSet); } else {
Singletons.getModel().getGame().getStack().setResolving(bResolving); unpaid.execute();
}
} }
} }

View File

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

View File

@@ -22,12 +22,14 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Stack; import java.util.Stack;
import java.util.concurrent.CountDownLatch;
import com.esotericsoftware.minlog.Log; import com.esotericsoftware.minlog.Log;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardPredicates; import forge.CardPredicates;
import forge.FThreads;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.Command; import forge.Command;
import forge.Singletons; import forge.Singletons;
@@ -36,7 +38,6 @@ import forge.card.cardfactory.CardFactory;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostBeingPaid;
import forge.card.mana.ManaCostParser;
import forge.card.spellability.Ability; import forge.card.spellability.Ability;
import forge.card.spellability.AbilityStatic; import forge.card.spellability.AbilityStatic;
import forge.card.spellability.AbilityTriggered; import forge.card.spellability.AbilityTriggered;
@@ -478,49 +479,38 @@ public class MagicStack extends MyObservable {
} else if (sp.isXCost()) { } else if (sp.isXCost()) {
// TODO: convert any X costs to use abCost so it happens earlier // TODO: convert any X costs to use abCost so it happens earlier
final SpellAbility sa = sp; final SpellAbility sa = sp;
final ManaCost mc = new ManaCost( new ManaCostParser(Integer.toString(sa.getXManaCost()))); final int xCost = 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();
Player player = sp.getSourceCard().getController(); Player player = sp.getSourceCard().getController();
if (player.isHuman()) { if (player.isHuman()) {
Singletons.getModel().getMatch().getInput().setInput( final Runnable payNextX = new Runnable() {
new InputPayManaExecuteCommands(game, "Pay X cost for " + sp.getSourceCard().getName() + " (X=" @Override
+ crd.getXManaCostPaid() + ")\r\n", ability.getManaCost().toString(), paidCommand, public void run() {
unpaidCommand, true));
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 { } else {
// computer // computer
final int neededDamage = CardFactoryUtil.getNeededXDamage(sa); 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())) { while (ComputerUtilCost.canPayCost(ability, player) && (neededDamage != sa.getSourceCard().getXManaCostPaid())) {
ComputerUtil.playNoStack((AIPlayer)player, ability, game); 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(); Player activating = sp.getActivatingPlayer();
if (activating.isHuman()) { if (activating.isHuman()) {
sa.getSourceCard().addMultiKickerMagnitude(-1); 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(); paidCommand.execute();
} else { } else {
// computer // 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(); Player controller = sp.getSourceCard().getController();
if (controller.isHuman()) { if (controller.isHuman()) {
sa.getSourceCard().addReplicateMagnitude(-1); 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 { } else {
// computer // computer
while (ComputerUtilCost.canPayCost(ability, controller)) { while (ComputerUtilCost.canPayCost(ability, controller)) {