refactor: combined announceX methods in one, improved X message and selection for AI (part of #10330)

This commit is contained in:
Oleg Agafonov 2025-05-16 19:34:57 +04:00
parent 6af198836b
commit 66db821437
37 changed files with 90 additions and 158 deletions

View file

@ -2,7 +2,6 @@ package mage.player.ai;
import mage.MageObject;
import mage.abilities.*;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.mana.ManaCost;
import mage.cards.Card;
import mage.cards.Cards;
@ -250,20 +249,11 @@ public class ComputerPlayerControllableProxy extends ComputerPlayer7 {
}
@Override
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
public int announceX(int min, int max, String message, Game game, Ability source, boolean isManaPay) {
if (isUnderMe(game)) {
return super.announceXMana(min, max, message, game, ability);
return super.announceX(min, max, message, game, source, isManaPay);
} else {
return getControllingPlayer(game).announceXMana(min, max, message, game, ability);
}
}
@Override
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost) {
if (isUnderMe(game)) {
return super.announceXCost(min, max, message, game, ability, variableCost);
} else {
return getControllingPlayer(game).announceXCost(min, max, message, game, ability, variableCost);
return getControllingPlayer(game).announceX(min, max, message, game, source, isManaPay);
}
}

View file

@ -5,7 +5,6 @@ import mage.ConditionalMana;
import mage.MageObject;
import mage.Mana;
import mage.abilities.*;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.mana.*;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
@ -2039,42 +2038,40 @@ public class ComputerPlayer extends PlayerImpl {
}
@Override
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
// current logic - use max possible mana
public int announceX(int min, int max, String message, Game game, Ability source, boolean isManaPay) {
// fast calc on nothing to choose
if (min >= max) {
return min;
}
// TODO: add good/bad effects support
// TODO: add simple game simulations like declare blocker?
// TODO: add simple game simulations like declare blocker (need to find only workable payment)?
// TODO: remove random logic or make it more stable (e.g. use same value in same game cycle)
int numAvailable = getAvailableManaProducers(game).size() - ability.getManaCosts().manaValue();
if (numAvailable < 0) {
numAvailable = 0;
// protection from too big values
int realMin = min;
int realMax = max;
if (max == Integer.MAX_VALUE) {
realMax = Math.max(realMin, 10); // AI don't need huge values for X, cause can't use infinite combos
}
int xValue;
if (isManaPay) {
// as X mana payment - due available mana
xValue = Math.max(0, getAvailableManaProducers(game).size() - source.getManaCostsToPay().getUnpaid().manaValue());
} else {
if (numAvailable < min) {
numAvailable = min;
}
if (numAvailable > max) {
numAvailable = max;
}
// as X actions
xValue = RandomUtil.nextInt(realMax + 1);
}
return numAvailable;
}
@Override
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variablCost) {
// current logic - use random non-zero value
// TODO: add good/bad effects support
// TODO: remove random logic
int value = RandomUtil.nextInt(CardUtil.overflowInc(max, 1));
if (value < min) {
value = min;
if (xValue > realMax) {
xValue = realMax;
}
if (value < max) {
// do not use zero values
value++;
if (xValue < realMin) {
xValue = realMin;
}
return value;
return xValue;
}
@Override

View file

@ -1687,64 +1687,39 @@ public class HumanPlayer extends PlayerImpl {
}
/**
* Gets the amount of mana the player want to spent for a x spell
*
* @param min
* @param max
* @param message
* @param ability
* @param game
* @return
* Gets the amount of mana the player want to spend for an x spell
*/
@Override
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
public int announceX(int min, int max, String message, Game game, Ability source, boolean isManaPay) {
if (!canCallFeedback(game)) {
return min;
}
int xValue = 0;
while (canRespond()) {
prepareForResponse(game);
if (!isExecutingMacro()) {
game.fireGetAmountEvent(playerId, message + CardUtil.getSourceLogName(game, ability), min, max);
}
waitForResponse(game);
if (response.getInteger() != null) {
break;
}
// TODO: add response verify here
}
if (response.getInteger() != null) {
xValue = response.getInteger();
}
return xValue;
}
@Override
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost) {
if (!canCallFeedback(game)) {
// fast calc on nothing to choose
if (min >= max) {
return min;
}
int xValue = 0;
int xValue = min;
while (canRespond()) {
prepareForResponse(game);
if (!isExecutingMacro()) {
game.fireGetAmountEvent(playerId, message, min, max);
game.fireGetAmountEvent(playerId, message + CardUtil.getSourceLogName(game, source), min, max);
}
waitForResponse(game);
if (response.getInteger() != null) {
break;
if (response.getInteger() == null) {
continue;
}
xValue = response.getInteger();
if (xValue < min || xValue > max) {
continue;
}
break;
}
if (response.getInteger() != null) {
xValue = response.getInteger();
}
return xValue;
}