mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-11 16:26:22 +00:00
Fix AI failing to pay Spree-like charm because it didn't see final cost (#5208)
Co-authored-by: tool4EvEr <tool4EvEr@192.168.0.60>
This commit is contained in:
@@ -791,7 +791,7 @@ public class AiController {
|
||||
}
|
||||
|
||||
int oldCMC = -1;
|
||||
boolean xCost = sa.costHasX() || host.hasKeyword(Keyword.STRIVE);
|
||||
boolean xCost = sa.costHasX() || host.hasKeyword(Keyword.STRIVE) || sa.getApi() == ApiType.Charm;
|
||||
if (!xCost) {
|
||||
if (!ComputerUtilCost.canPayCost(sa, player, sa.isTrigger())) {
|
||||
// for most costs, it's OK to check if they can be paid early in order to avoid running a heavy API check
|
||||
@@ -820,7 +820,7 @@ public class AiController {
|
||||
if (tgt.hasKeyword(Keyword.WARD) && tgt.isInPlay() && tgt.getController().isOpponentOf(host.getController())) {
|
||||
Cost wardCost = ComputerUtilCard.getTotalWardCost(tgt);
|
||||
if (wardCost.hasManaCost()) {
|
||||
xCost = wardCost.getTotalMana().getCMC() > 0;
|
||||
xCost |= wardCost.getTotalMana().getCMC() > 0;
|
||||
}
|
||||
SpellAbilityAi topAI = new SpellAbilityAi() {};
|
||||
if (!topAI.willPayCosts(player, sa, wardCost, host)) {
|
||||
|
||||
@@ -966,8 +966,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
* forge.game.player.PlayerController.BinaryChoiceType, java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice,
|
||||
Map<String, Object> params) {
|
||||
public boolean chooseBinary(SpellAbility sa, String question, BinaryChoiceType kindOfChoice, Map<String, Object> params) {
|
||||
ApiType api = sa.getApi();
|
||||
if (null == api) {
|
||||
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
|
||||
|
||||
@@ -14,7 +14,6 @@ import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.effects.CharmEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
@@ -41,6 +40,7 @@ public class CharmAi extends SpellAbilityAi {
|
||||
|
||||
// Reset the chosen list otherwise it will be locked in forever by earlier calls
|
||||
sa.setChosenList(null);
|
||||
sa.setSubAbility(null);
|
||||
List<AbilitySub> chosenList;
|
||||
|
||||
if (!ai.equals(sa.getActivatingPlayer())) {
|
||||
@@ -51,7 +51,7 @@ public class CharmAi extends SpellAbilityAi {
|
||||
chosenList = chooseTriskaidekaphobia(choices, ai);
|
||||
} else {
|
||||
// only randomize if not all possible together
|
||||
if (num < choices.size() || source.hasKeyword(Keyword.ESCALATE)) {
|
||||
if (num < choices.size()) {
|
||||
Collections.shuffle(choices);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,13 @@ public class CharmAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// store the choices so they'll get reused
|
||||
sa.setChosenList(chosenList);
|
||||
if (sa.isSpell()) {
|
||||
// prebuild chain to improve cost calculation accuracy
|
||||
CharmEffect.chainAbilities(sa, chosenList);
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
return MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
||||
|
||||
@@ -249,7 +249,7 @@ public class CharmEffect extends SpellAbilityEffect {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void chainAbilities(SpellAbility sa, List<AbilitySub> chosen) {
|
||||
public static void chainAbilities(SpellAbility sa, List<AbilitySub> chosen) {
|
||||
if (chosen == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user