moved AI decision making about unless cost to AI-related class.

Simplified the resolution
This commit is contained in:
Maxmtg
2013-04-05 14:42:56 +00:00
parent f951ad4d36
commit b39ba46d45
2 changed files with 49 additions and 58 deletions

View File

@@ -1100,7 +1100,7 @@ public class AbilityUtils {
ManaCostBeingPaid newCost = new ManaCostBeingPaid(unlessCost.toString());
newCost.decreaseColorlessMana(2);
unlessCost = newCost.toString();
} else {
} else if( unlessCost.indexOf('<') < 0 ) { // if cost has '<' or '>' signs - it's definitely not a variable
try {
String unlessVar = Integer.toString(calculateAmount(source, sa.getParam("UnlessCost").replace(" ", ""), sa));
unlessCost = unlessVar;
@@ -1110,19 +1110,16 @@ public class AbilityUtils {
}
final Cost cost = new Cost(source, unlessCost, true);
final Ability ability = new AbilityStatic(source, cost, null) {
final Ability ability = new AbilityStatic(source, cost, sa.getTarget()) {
@Override
public void resolve() {
// nothing to do here
}
public void resolve() { /* nothing to do here */ }
};
boolean paid = false;
for (Player payer : payers) {
ability.setActivatingPlayer(payer);
ability.setTarget(sa.getTarget());
if (payer.isComputer()) {
if (AbilityUtils.willAIPayForAbility(sa, payer, ability, paid, payers)) {
if (ComputerUtilCost.willPayUnlessCost(sa, payer, ability, paid, payers)) {
ComputerUtil.playNoStack((AIPlayer) payer, ability, game); // Unless cost was payed - no resolve
paid = true;
}
@@ -1132,21 +1129,15 @@ public class AbilityUtils {
}
}
if ( paid ^ isSwitched ) {
if (isSwitched && execSubsWhenNotPaid || execSubsWhenPaid) {
resolveSubAbilities(sa, usedStack, game);
} else if (usedStack) {
SpellAbility root = sa.getRootAbility();
game.getStack().finishResolving(root, false);
}
} else {
if( paid == isSwitched ) {
sa.resolve();
if (isSwitched && execSubsWhenPaid || execSubsWhenNotPaid) {
resolveSubAbilities(sa, usedStack, game);
} else if (usedStack) {
SpellAbility root = sa.getRootAbility();
game.getStack().finishResolving(root, false);
}
}
if ( paid && execSubsWhenPaid || !paid && execSubsWhenNotPaid ) { // switched refers only to main ability!
resolveSubAbilities(sa, usedStack, game);
} else if (usedStack) {
SpellAbility root = sa.getRootAbility();
game.getStack().finishResolving(root, false);
}
}
@@ -1195,43 +1186,6 @@ public class AbilityUtils {
}
}
private static boolean willAIPayForAbility(SpellAbility sa, Player payer, SpellAbility ability, boolean paid, List<Player> payers) {
Card source = sa.getSourceCard();
boolean payForOwnOnly = "OnlyOwn".equals(sa.getParam("UnlessAI"));
boolean payOwner = sa.hasParam("UnlessAI") ? sa.getParam("UnlessAI").startsWith("Defined") : false;
boolean payNever = "Never".equals(sa.getParam("UnlessAI"));
boolean isMine = sa.getActivatingPlayer().equals(payer);
if (payNever) { return false; }
if (payForOwnOnly && !isMine) { return false; }
if (payOwner) {
final String defined = sa.getParam("UnlessAI").substring(7);
final Player player = AbilityUtils.getDefinedPlayers(source, defined, sa).get(0);
if (!payer.equals(player)) {
return false;
}
}
// AI will only pay when it's not already payed and only opponents abilities
if (paid || (payers.size() > 1 && (isMine && !payForOwnOnly))) {
return false;
}
if (ComputerUtilCost.canPayCost(ability, payer)
&& ComputerUtilCost.checkLifeCost(payer, ability.getPayCosts(), source, 4, sa)
&& ComputerUtilCost.checkDamageCost(payer, ability.getPayCosts(), source, 4)
&& ComputerUtilCost.checkDiscardCost(payer, ability.getPayCosts(), source)
&& (!source.getName().equals("Tyrannize") || payer.getCardsIn(ZoneType.Hand).size() > 2)
&& (!source.getName().equals("Perplex") || payer.getCardsIn(ZoneType.Hand).size() < 2)
&& (!source.getName().equals("Breaking Point") || payer.getCreaturesInPlay().size() > 1)
&& (!source.getName().equals("Chain of Vapor")
|| (payer.getOpponent().getCreaturesInPlay().size() > 0 && payer.getLandsInPlay().size() > 3))) {
// AI was crashing because the blank ability used to pay costs
// Didn't have any of the data on the original SA to pay dependant costs
return true;
}
return false;
}
/**
* <p>
* Parse non-mana X variables.

View File

@@ -382,4 +382,41 @@ public class ComputerUtilCost {
return CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa);
}
public static boolean willPayUnlessCost(SpellAbility sa, Player payer, SpellAbility ability, boolean alreadyPaid, List<Player> payers) {
Card source = sa.getSourceCard();
boolean payForOwnOnly = "OnlyOwn".equals(sa.getParam("UnlessAI"));
boolean payOwner = sa.hasParam("UnlessAI") ? sa.getParam("UnlessAI").startsWith("Defined") : false;
boolean payNever = "Never".equals(sa.getParam("UnlessAI"));
boolean isMine = sa.getActivatingPlayer().equals(payer);
if (payNever) { return false; }
if (payForOwnOnly && !isMine) { return false; }
if (payOwner) {
final String defined = sa.getParam("UnlessAI").substring(7);
final Player player = AbilityUtils.getDefinedPlayers(source, defined, sa).get(0);
if (!payer.equals(player)) {
return false;
}
}
// AI will only pay when it's not already payed and only opponents abilities
if (alreadyPaid || (payers.size() > 1 && (isMine && !payForOwnOnly))) {
return false;
}
if (canPayCost(ability, payer)
&& checkLifeCost(payer, ability.getPayCosts(), source, 4, sa)
&& checkDamageCost(payer, ability.getPayCosts(), source, 4)
&& checkDiscardCost(payer, ability.getPayCosts(), source)
&& (!source.getName().equals("Tyrannize") || payer.getCardsIn(ZoneType.Hand).size() > 2)
&& (!source.getName().equals("Perplex") || payer.getCardsIn(ZoneType.Hand).size() < 2)
&& (!source.getName().equals("Breaking Point") || payer.getCreaturesInPlay().size() > 1)
&& (!source.getName().equals("Chain of Vapor")
|| (payer.getOpponent().getCreaturesInPlay().size() > 0 && payer.getLandsInPlay().size() > 3))) {
// AI was crashing because the blank ability used to pay costs
// Didn't have any of the data on the original SA to pay dependant costs
return true;
}
return false;
}
}