GameAction.payCostDuringAbilityResolve now returns a boolean indicating whether the cost was paid,

all the paid/unpaid commands eliminated, since the code may be executed right after payCostDuringAbilityResolve under if's branches
This commit is contained in:
Maxmtg
2013-03-25 19:47:10 +00:00
parent a82abd077c
commit 19a1a7b173
5 changed files with 58 additions and 170 deletions

View File

@@ -10,7 +10,6 @@ import org.apache.commons.lang3.StringUtils;
import forge.Card;
import forge.CardLists;
import forge.CardUtil;
import forge.Command;
import forge.Constant;
import forge.CounterType;
import forge.Singletons;
@@ -1036,6 +1035,19 @@ public class AbilityUtils {
AbilityUtils.resolveApiAbility(abSub, usedStack, game);
}
private static void resolveApiAbility(final SpellAbility sa, boolean usedStack, final GameState game) {
// check conditions
if (sa.getConditions().areMet(sa)) {
if (sa.isWrapper() || StringUtils.isBlank(sa.getParam("UnlessCost"))) {
sa.resolve();
} else {
handleUnlessCost(sa, usedStack, game);
return;
}
}
resolveSubAbilities(sa, usedStack, game);
}
private static void handleUnlessCost(final SpellAbility sa, final boolean usedStack, final GameState game) {
final Card source = sa.getSourceCard();
String unlessCost = sa.getParam("UnlessCost");
@@ -1047,7 +1059,8 @@ public class AbilityUtils {
final String resolveSubs = sa.getParam("UnlessResolveSubs"); // no value means 'Always'
final boolean execSubsWhenPaid = "WhenPaid".equals(resolveSubs) || StringUtils.isBlank(resolveSubs);
final boolean execSubsWhenNotPaid = "WhenNotPaid".equals(resolveSubs) || StringUtils.isBlank(resolveSubs);
final boolean isSwitched = sa.hasParam("UnlessSwitched");
// The cost
if (unlessCost.equals("CardManaCost")) {
unlessCost = source.getManaCost().toString();
@@ -1070,43 +1083,6 @@ public class AbilityUtils {
//instead of just X for cards like Draco.
}
final boolean isSwitched = sa.hasParam("UnlessSwitched");
Command paidCommand = new Command() {
private static final long serialVersionUID = 8094833091127334678L;
@Override
public void execute() {
if (isSwitched && execSubsWhenNotPaid || execSubsWhenPaid) {
resolveSubAbilities(sa, usedStack, game);
} else if (usedStack) {
SpellAbility root = sa.getRootAbility();
game.getStack().finishResolving(root, false);
}
}
};
Command unpaidCommand = new Command() {
private static final long serialVersionUID = 8094833091127334678L;
@Override
public void execute() {
sa.resolve();
if (isSwitched && execSubsWhenPaid || execSubsWhenNotPaid) {
resolveSubAbilities(sa, usedStack, game);
} else if (usedStack) {
SpellAbility root = sa.getRootAbility();
game.getStack().finishResolving(root, false);
}
}
};
if (isSwitched) {
final Command dummy = paidCommand;
paidCommand = unpaidCommand;
unpaidCommand = dummy;
}
final Cost cost = new Cost(source, unlessCost, true);
final Ability ability = new AbilityStatic(source, cost, null) {
@Override
@@ -1117,34 +1093,35 @@ public class AbilityUtils {
boolean paid = false;
for (Player payer : payers) {
ability.setActivatingPlayer(payer);
ability.setTarget(sa.getTarget());
if (payer.isComputer()) {
ability.setActivatingPlayer(payer);
if (AbilityUtils.willAIPayForAbility(sa, payer, ability, paid, payers)) {
ability.setTarget(sa.getTarget());
ComputerUtil.playNoStack((AIPlayer) payer, ability, game); // Unless cost was payed - no resolve
paid = true;
}
}
}
boolean waitForInput = false;
for (Player payer : payers) {
if (payer.isHuman()) {
} else {
// if it's paid by the AI already the human can pay, but it won't change anything
if (paid) {
unpaidCommand = paidCommand;
}
ability.setActivatingPlayer(payer);
ability.setTarget(sa.getTarget());
GameActionUtil.payCostDuringAbilityResolve(payer, ability, cost, paidCommand, unpaidCommand, sa, game);
waitForInput = true; // wait for the human input
break; // multiple human players are not supported
paid = GameActionUtil.payCostDuringAbilityResolve(payer, ability, cost, sa, game);
}
}
if (!waitForInput) {
Command toExecute = paid ? paidCommand : unpaidCommand;
toExecute.execute();
}
if ( paid ^ isSwitched ) {
if (isSwitched && execSubsWhenNotPaid || execSubsWhenPaid) {
resolveSubAbilities(sa, usedStack, game);
} else if (usedStack) {
SpellAbility root = sa.getRootAbility();
game.getStack().finishResolving(root, false);
}
} else {
sa.resolve();
if (isSwitched && execSubsWhenPaid || execSubsWhenNotPaid) {
resolveSubAbilities(sa, usedStack, game);
} else if (usedStack) {
SpellAbility root = sa.getRootAbility();
game.getStack().finishResolving(root, false);
}
}
}
/**
@@ -1221,19 +1198,6 @@ public class AbilityUtils {
return false;
}
private static void resolveApiAbility(final SpellAbility sa, boolean usedStack, final GameState game) {
// check conditions
if (sa.getConditions().areMet(sa)) {
if (sa.isWrapper() || StringUtils.isBlank(sa.getParam("UnlessCost"))) {
sa.resolve();
} else {
handleUnlessCost(sa, usedStack, game);
return;
}
}
resolveSubAbilities(sa, usedStack, game);
}
/**
* <p>
* Parse non-mana X variables.

View File

@@ -486,24 +486,6 @@ public class GameAction {
final String recoverCost = recoverable.getKeyword().get(recoverable.getKeywordPosition("Recover")).split(":")[1];
final Cost cost = new Cost(recoverable, recoverCost, true);
final Command paidCommand = new Command() {
private static final long serialVersionUID = -6357156873861051845L;
@Override
public void execute() {
moveToHand(recoverable);
}
};
final Command unpaidCommand = new Command() {
private static final long serialVersionUID = -7354791599039157375L;
@Override
public void execute() {
exile(recoverable);
}
};
final SpellAbility abRecover = new AbilityActivated(recoverable, cost, null) {
private static final long serialVersionUID = 8858061639236920054L;
@@ -535,8 +517,10 @@ public class GameAction {
Player p = recoverable.getController();
if (p.isHuman()) {
GameActionUtil.payCostDuringAbilityResolve(p, abRecover, abRecover.getPayCosts(),
paidCommand, unpaidCommand, null, game);
if ( GameActionUtil.payCostDuringAbilityResolve(p, abRecover, abRecover.getPayCosts(), null, game) )
moveToHand(recoverable);
else
exile(recoverable);
} else { // computer
if (ComputerUtilCost.canPayCost(abRecover, p)) {
ComputerUtil.playNoStack((AIPlayer)p, abRecover, game);

View File

@@ -382,8 +382,7 @@ public final class GameActionUtil {
* a {@link forge.Command} object.
* @param sourceAbility TODO
*/
public static void payCostDuringAbilityResolve(final Player p, final SpellAbility ability, final Cost cost, final Command paid,
final Command unpaid, SpellAbility sourceAbility, final GameState game) {
public static boolean payCostDuringAbilityResolve(final Player p, final SpellAbility ability, final Cost cost, SpellAbility sourceAbility, final GameState game) {
final Card source = ability.getSourceCard();
final List<CostPart> parts = cost.getCostParts();
ArrayList<CostPart> remainingParts = new ArrayList<CostPart>(cost.getCostParts());
@@ -396,13 +395,9 @@ public final class GameActionUtil {
orString = " (or: " + sourceAbility.getStackDescription() + ")";
}
if (parts.isEmpty() || costPart.getAmount().equals("0")) {
if (GuiDialog.confirm(source, "Do you want to pay 0?" + orString)) {
paid.execute();
} else {
unpaid.execute();
}
return;
return GuiDialog.confirm(source, "Do you want to pay 0?" + orString);
}
boolean hasPaid = true;
//the following costs do not need inputs
for (CostPart part : parts) {
@@ -591,12 +586,10 @@ public final class GameActionUtil {
GuiUtils.clearPanelSelections();
if (!hasPaid) {
unpaid.execute();
return;
return false;
}
if (remainingParts.isEmpty()) {
paid.execute();
return;
return true;
}
if (remainingParts.size() > 1) {
throw new RuntimeException("GameActionUtil::payCostDuringAbilityResolve - Too many payment types - " + source);
@@ -609,11 +602,7 @@ public final class GameActionUtil {
InputPayment toSet = new InputPayManaExecuteCommands(game, source + "\r\n", ability.getManaCost());
FThreads.setInputAndWait(toSet);
if (toSet.isPaid() ) {
paid.execute();
} else {
unpaid.execute();
}
return toSet.isPaid();
}
// not restricted to combat damage, not restricted to dealing damage to

View File

@@ -1150,39 +1150,13 @@ public class CombatUtil {
}
};
final Command unpaidCommand = new Command() {
private static final long serialVersionUID = -6483405139208343935L;
@Override
public void execute() {
game.getCombat().removeFromCombat(crd);
if (bLast) {
PhaseUtil.handleAttackingTriggers();
}
}
};
final Command paidCommand = new Command() {
private static final long serialVersionUID = -8303368287601871955L;
@Override
public void execute() {
// if Propaganda is paid, tap this card
if (!crd.hasKeyword("Vigilance")) {
crd.tap();
}
if (bLast) {
PhaseUtil.handleAttackingTriggers();
}
}
};
ability.setActivatingPlayer(c.getController());
if (c.getController().isHuman()) {
GameActionUtil.payCostDuringAbilityResolve(c.getController(), ability, attackCost, paidCommand, unpaidCommand, null, game);
if ( GameActionUtil.payCostDuringAbilityResolve(c.getController(), ability, attackCost, null, game) ) {
if (!crd.hasKeyword("Vigilance")) { crd.tap(); }
} else {
game.getCombat().removeFromCombat(crd);
}
} else { // computer
if (ComputerUtilCost.canPayCost(ability, c.getController())) {
ComputerUtil.playNoStack((AIPlayer)c.getController(), ability, game);
@@ -1194,10 +1168,9 @@ public class CombatUtil {
// during Declare_Attackers
game.getCombat().removeFromCombat(crd);
}
if (bLast) {
PhaseUtil.handleAttackingTriggers();
}
}
if (bLast)
PhaseUtil.handleAttackingTriggers();
}
}

View File

@@ -175,18 +175,6 @@ public class Upkeep extends Phase {
for (int i = 0; i < list.size(); i++) {
final Card c = list.get(i);
if (c.hasStartOfKeyword("(Echo unpaid)")) {
final Command paidCommand = Command.BLANK;
final Command unpaidCommand = new Command() {
private static final long serialVersionUID = -7354791599039157375L;
@Override
public void execute() {
game.getAction().sacrifice(c, null);
}
};
final Ability blankAbility = Upkeep.BlankAbility(c, c.getEchoCost());
final StringBuilder sb = new StringBuilder();
@@ -199,7 +187,9 @@ public class Upkeep extends Phase {
Player controller = c.getController();
if (controller.isHuman()) {
Cost cost = new Cost(c, c.getEchoCost().trim(), true);
GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, cost, paidCommand, unpaidCommand, null, game);
if ( !GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, cost, null, game) )
game.getAction().sacrifice(c, null);;
} else { // computer
if (ComputerUtilCost.canPayCost(blankAbility, controller)) {
ComputerUtil.playNoStack((AIPlayer)controller, blankAbility, game);
@@ -332,18 +322,6 @@ public class Upkeep extends Phase {
}
final String upkeepCost = cost;
final Command unpaidCommand = new Command() {
private static final long serialVersionUID = 5612348769167529102L;
@Override
public void execute() {
game.getAction().sacrifice(c, null);
}
};
final Command paidCommand = Command.BLANK;
final Ability blankAbility = Upkeep.BlankAbility(c, upkeepCost);
blankAbility.setActivatingPlayer(controller);
@@ -351,11 +329,11 @@ public class Upkeep extends Phase {
@Override
public void resolve() {
if (controller.isHuman()) {
GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, blankAbility.getPayCosts(),
paidCommand, unpaidCommand, this, game);
if ( !GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, blankAbility.getPayCosts(), this, game))
game.getAction().sacrifice(c, null);
} else { // computer
if (ComputerUtilCost.shouldPayCost(controller, c, upkeepCost) && ComputerUtilCost.canPayCost(blankAbility, controller)) {
ComputerUtil.playNoStack((AIPlayer)controller, blankAbility, game);
ComputerUtil.playNoStack((AIPlayer)controller, blankAbility, game); // this makes AI pay
} else {
game.getAction().sacrifice(c, null);
}