mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
moved AI decision making about unless cost to AI-related class.
Simplified the resolution
This commit is contained in:
@@ -1100,7 +1100,7 @@ public class AbilityUtils {
|
|||||||
ManaCostBeingPaid newCost = new ManaCostBeingPaid(unlessCost.toString());
|
ManaCostBeingPaid newCost = new ManaCostBeingPaid(unlessCost.toString());
|
||||||
newCost.decreaseColorlessMana(2);
|
newCost.decreaseColorlessMana(2);
|
||||||
unlessCost = newCost.toString();
|
unlessCost = newCost.toString();
|
||||||
} else {
|
} else if( unlessCost.indexOf('<') < 0 ) { // if cost has '<' or '>' signs - it's definitely not a variable
|
||||||
try {
|
try {
|
||||||
String unlessVar = Integer.toString(calculateAmount(source, sa.getParam("UnlessCost").replace(" ", ""), sa));
|
String unlessVar = Integer.toString(calculateAmount(source, sa.getParam("UnlessCost").replace(" ", ""), sa));
|
||||||
unlessCost = unlessVar;
|
unlessCost = unlessVar;
|
||||||
@@ -1110,19 +1110,16 @@ public class AbilityUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Cost cost = new Cost(source, unlessCost, true);
|
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
|
@Override
|
||||||
public void resolve() {
|
public void resolve() { /* nothing to do here */ }
|
||||||
// nothing to do here
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
boolean paid = false;
|
boolean paid = false;
|
||||||
for (Player payer : payers) {
|
for (Player payer : payers) {
|
||||||
ability.setActivatingPlayer(payer);
|
ability.setActivatingPlayer(payer);
|
||||||
ability.setTarget(sa.getTarget());
|
|
||||||
if (payer.isComputer()) {
|
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
|
ComputerUtil.playNoStack((AIPlayer) payer, ability, game); // Unless cost was payed - no resolve
|
||||||
paid = true;
|
paid = true;
|
||||||
}
|
}
|
||||||
@@ -1132,21 +1129,15 @@ public class AbilityUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( paid ^ isSwitched ) {
|
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();
|
sa.resolve();
|
||||||
if (isSwitched && execSubsWhenPaid || execSubsWhenNotPaid) {
|
}
|
||||||
resolveSubAbilities(sa, usedStack, game);
|
|
||||||
} else if (usedStack) {
|
if ( paid && execSubsWhenPaid || !paid && execSubsWhenNotPaid ) { // switched refers only to main ability!
|
||||||
SpellAbility root = sa.getRootAbility();
|
resolveSubAbilities(sa, usedStack, game);
|
||||||
game.getStack().finishResolving(root, false);
|
} 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>
|
* <p>
|
||||||
* Parse non-mana X variables.
|
* Parse non-mana X variables.
|
||||||
|
|||||||
@@ -382,4 +382,41 @@ public class ComputerUtilCost {
|
|||||||
return CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user