mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
refactor: combined announceX methods in one, improved X message and selection for AI (part of #10330)
This commit is contained in:
parent
6af198836b
commit
66db821437
37 changed files with 90 additions and 158 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
return numAvailable;
|
||||
// as X actions
|
||||
xValue = RandomUtil.nextInt(realMax + 1);
|
||||
}
|
||||
|
||||
@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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
if (response.getInteger() != null) {
|
||||
xValue = response.getInteger();
|
||||
if (xValue < min || xValue > max) {
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return xValue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ class AzorTheLawbringerAttacksEffect extends OneShotEffect {
|
|||
if (controller != null) {
|
||||
ManaCosts cost = new ManaCostsImpl<>("{X}{W}{U}{U}");
|
||||
if (controller.chooseUse(Outcome.Damage, "Pay " + cost.getText() + "? If you do, you gain X life and draw X cards.", source, game)) {
|
||||
int costX = controller.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = controller.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (gain life and draw cards)", game, source,true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
controller.resetStoredBookmark(game); // otherwise you can undo the payment
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class DepalaPilotExemplarEffect extends OneShotEffect {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
ManaCosts<ManaCost> cost = new ManaCostsImpl<>("{X}");
|
||||
int xValue = controller.announceXMana(0, Integer.MAX_VALUE, "Choose the amount of mana to pay", game, source);
|
||||
int xValue = controller.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to reveal)", game, source, true);
|
||||
cost.add(new GenericManaCost(xValue));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false) && xValue > 0) {
|
||||
new RevealLibraryPutIntoHandEffect(xValue, filter, Zone.LIBRARY, false).apply(game, source);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class ElendaAndAzorEffect extends OneShotEffect {
|
|||
if (controller != null) {
|
||||
ManaCosts cost = new ManaCostsImpl<>("{X}{W}{U}{B}");
|
||||
if (controller.chooseUse(Outcome.Damage, "Pay " + cost.getText() + "? If you do, draw X cards.", source, game)) {
|
||||
int costX = controller.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = controller.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to draw)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
controller.resetStoredBookmark(game); // otherwise you can undo the payment
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class FlameblastDragonEffect extends OneShotEffect {
|
|||
ManaCosts cost = new ManaCostsImpl<>("{X}{R}");
|
||||
if (player != null) {
|
||||
if (player.chooseUse(Outcome.Damage, "Pay " + cost.getText() + "? If you do, Flameblast Dragon deals X damage to any target", source, game)) {
|
||||
int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to damage)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class HaloForagerPayEffect extends OneShotEffect {
|
|||
if (player == null || !player.chooseUse(outcome, "Pay " + cost.getText() + "?", source, game)) {
|
||||
return false;
|
||||
}
|
||||
int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to free cast)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class HeroOfLeinaTowerEffect extends OneShotEffect {
|
|||
Player you = game.getPlayer(source.getControllerId());
|
||||
ManaCosts cost = new ManaCostsImpl<>("{X}");
|
||||
if (you != null && you.chooseUse(Outcome.BoostCreature, "Do you want to to pay {X}?", source, game)) {
|
||||
int costX = you.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = you.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to add +1/+1 counters)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class IncineratorOfTheGuiltyEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
|
||||
int xValue = controller.announceXMana(0, Integer.MAX_VALUE, "Announce the value for X", game, source);
|
||||
int xValue = controller.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (collect evidence)", game, source, false);
|
||||
CollectEvidenceCost cost = new CollectEvidenceCost(xValue);
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class IsarethTheAwakenerCreateReflexiveTriggerEffect extends OneShotEffect {
|
|||
|| !player.chooseUse(Outcome.BoostCreature, "Pay " + cost.getText() + "?", source, game)) {
|
||||
return false;
|
||||
}
|
||||
int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to return due mana value)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -111,10 +111,8 @@ class LeylineTyrantDamageEffect extends OneShotEffect {
|
|||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
int costX = player.announceXMana(
|
||||
0, Integer.MAX_VALUE,
|
||||
"Announce the value for {X}", game, source
|
||||
);
|
||||
// TODO: add some AI hints by min/max values
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source, true);
|
||||
String manaString;
|
||||
if (costX == 0) {
|
||||
manaString = "{0}";
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ class NumaJoragaChieftainEffect extends OneShotEffect {
|
|||
if (!player.chooseUse(Outcome.BoostCreature, "Pay " + cost.getText() + "?", source, game)) {
|
||||
return false;
|
||||
}
|
||||
int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
// TODO: add some AI hints by min/max values
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to distribute counters)", game, source,true);
|
||||
cost.add(new GenericManaCost(2 * costX));
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class PowerLeakEffect extends OneShotEffect {
|
|||
String message = "Pay {X} to prevent X damage from " + permanent.getLogName() + "?";
|
||||
int xValue = 0;
|
||||
if (player.chooseUse(Outcome.Neutral, message, source, game)) {
|
||||
xValue = player.announceXMana(0, Integer.MAX_VALUE, "Choose the amount of mana to pay", game, source);
|
||||
xValue = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to prevent damage)", game, source, true);
|
||||
cost.add(new GenericManaCost(xValue));
|
||||
if (cost.pay(source, game, source, player.getId(), false, null)) {
|
||||
game.informPlayers(player.getLogName() + " paid {" + xValue + "} for " + permanent.getLogName());
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ class RemnantOfTheRisingStarEffect extends OneShotEffect {
|
|||
)) {
|
||||
return false;
|
||||
}
|
||||
int xValue = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int xValue = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to add counters)", game, source, true);
|
||||
cost.add(new GenericManaCost(xValue));
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import mage.constants.CardType;
|
|||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.ColorPredicate;
|
||||
|
|
@ -87,7 +86,7 @@ class RiseOfTheHobgoblinsEffect extends OneShotEffect {
|
|||
Player you = game.getPlayer(source.getControllerId());
|
||||
ManaCosts<ManaCost> cost = new ManaCostsImpl<>("{X}");
|
||||
if (you != null && you.chooseUse(Outcome.Neutral, "Do you want to to pay {X}?", source, game)) {
|
||||
int costX = you.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = you.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to add counters)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
Token token = new GoblinSoldierToken();
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class RoseRoomTreasurerEffect extends OneShotEffect {
|
|||
if (!player.chooseUse(Outcome.BoostCreature, "Pay {X}?", source, game)) {
|
||||
return false;
|
||||
}
|
||||
int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to damage)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class ChooseNumberEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
int numberChoice = controller.announceXMana(0, Integer.MAX_VALUE, "Choose a number.", game, source);
|
||||
int numberChoice = controller.getAmount(0, Integer.MAX_VALUE, "Choose a number (mana cost to restrict)", game);
|
||||
game.getState().setValue(source.getSourceId().toString(), numberChoice);
|
||||
|
||||
Permanent permanent = game.getPermanentEntering(source.getSourceId());
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.constants.ColoredManaSymbol;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
|
|
@ -80,7 +79,7 @@ class SquealingDevilEffect extends OneShotEffect {
|
|||
ManaCosts cost = new ManaCostsImpl<>("{X}");
|
||||
if (player != null) {
|
||||
if (player.chooseUse(Outcome.BoostCreature, "Pay " + cost.getText() + "?", source, game)) {
|
||||
int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to boost)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class SqueesRevengeEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if(player != null) {
|
||||
int number = player.announceXMana(0, Integer.MAX_VALUE, "Choose how many times to flip a coin", game, source);
|
||||
int number = player.getAmount(0, Integer.MAX_VALUE, "Choose how many times to flip a coin", game);
|
||||
game.informPlayers(player.getLogName() + " chooses " + number + '.');
|
||||
for(int i = 0; i < number; i++) {
|
||||
if(!player.flipCoin(source, game, true)) {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class TilonallisSummonerEffect extends OneShotEffect {
|
|||
if (controller != null) {
|
||||
ManaCosts cost = new ManaCostsImpl<>("{X}{R}");
|
||||
if (controller.chooseUse(outcome, "Pay " + cost.getText() + "? If you do, you create X 1/1 red Elemental creature tokens that are tapped and attacking.", source, game)) {
|
||||
int costX = controller.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = controller.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay for tokens)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
controller.resetStoredBookmark(game); // otherwise you can undo the payment
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class VigilForTheLostEffect extends OneShotEffect {
|
|||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
int costX = controller.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = controller.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay to gain life)", game, source, true);
|
||||
if (new GenericManaCost(costX).pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
controller.gainLife(costX, game, source);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class VoidEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
|
||||
int number = controller.announceXMana(0, Integer.MAX_VALUE, this.staticText, game, source);
|
||||
int number = controller.getAmount(0, Integer.MAX_VALUE, "Choose a number (mana cost to destroy)", game);
|
||||
game.informPlayers(controller.getLogName() + " chooses " + number + '.');
|
||||
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class WellOfLostDreamsEffect extends OneShotEffect {
|
|||
if (controller != null) {
|
||||
int amount = SavedGainedLifeValue.MANY.calculate(game, source, this);
|
||||
if (amount > 0) {
|
||||
int xValue = controller.announceXMana(0, amount, "Announce X Value", game, source);
|
||||
int xValue = controller.announceX(0, amount, "Announce the value for {X} (pay for draw cards)", game, source, true);
|
||||
if (xValue > 0) {
|
||||
if (new GenericManaCost(xValue).pay(source, game, source, controller.getId(), false)) {
|
||||
game.informPlayers(controller.getLogName() + " payed {" + xValue + '}');
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class WildbornPreserverCreateReflexiveTriggerEffect extends OneShotEffect {
|
|||
if (!player.chooseUse(outcome, "Pay " + cost.getText() + "?", source, game)) {
|
||||
return false;
|
||||
}
|
||||
int costX = player.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source);
|
||||
int costX = player.announceX(0, Integer.MAX_VALUE, "Announce the value for {X} (pay for counters)", game, source, true);
|
||||
cost.add(new GenericManaCost(costX));
|
||||
if (!cost.pay(source, game, source, source.getControllerId(), false, null)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public class ProteanHydraTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Protean Hydra");
|
||||
|
||||
setStrictChooseMode(false); // test AI use max for X
|
||||
setStrictChooseMode(false); // TODO: good test for AI's announceX - duplicate it as AI test
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ public class SoulBurnTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Soul Burn", "Craw Wurm");
|
||||
|
||||
setStrictChooseMode(false); // TODO: good test for AI's announceX - duplicate it as AI test (few examples)
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertPermanentCount(playerB, "Craw Wurm", 1);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ public class IncreasingCardsTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Increasing Confusion");
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Flashback {X}{U}");
|
||||
|
||||
setStrictChooseMode(false); // TODO: good test for AI's announceX - duplicate it as AI test
|
||||
setStopAt(3, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
} catch (AssertionError e) {
|
||||
Assert.assertTrue(
|
||||
"X=0 is not a valid choice. Error message:\n" + e.getMessage(),
|
||||
e.getMessage().contains("Message: Announce the number of {E} to pay")
|
||||
e.getMessage().contains("Message: Announce the value for {X}")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public class PostMortemLungeTest extends CardTestPlayerBase {
|
|||
|
||||
attack(1, playerA, "Elite Vanguard");
|
||||
|
||||
setStrictChooseMode(false); // TODO: good test for AI's announceX - duplicate it as AI test
|
||||
setStopAt(1, PhaseStep.CLEANUP);
|
||||
execute();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import mage.abilities.common.SimpleStaticAbility;
|
|||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
|
|
@ -2916,39 +2915,20 @@ public class TestPlayer implements Player {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
assertAliasSupportInChoices(false);
|
||||
if (!choices.isEmpty()) {
|
||||
for (String choice : new ArrayList<>(choices)) {
|
||||
if (choice.startsWith("X=")) {
|
||||
int xValue = Integer.parseInt(choice.substring(2));
|
||||
assertXMinMaxValue(game, ability, xValue, min, max);
|
||||
choices.remove(choice);
|
||||
return xValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.chooseStrictModeFailed("choice", game, getInfo(ability, game)
|
||||
+ "\nMessage: " + message + prepareXMaxInfo(min, max));
|
||||
return computerPlayer.announceXMana(min, max, message, game, ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variablCost) {
|
||||
public int announceX(int min, int max, String message, Game game, Ability source, boolean isManaPay) {
|
||||
assertAliasSupportInChoices(false);
|
||||
if (!choices.isEmpty()) {
|
||||
if (choices.get(0).startsWith("X=")) {
|
||||
int xValue = Integer.parseInt(choices.get(0).substring(2));
|
||||
assertXMinMaxValue(game, ability, xValue, min, max);
|
||||
assertXMinMaxValue(game, source, xValue, min, max);
|
||||
choices.remove(0);
|
||||
return xValue;
|
||||
}
|
||||
}
|
||||
|
||||
this.chooseStrictModeFailed("choice", game, getInfo(ability, game)
|
||||
this.chooseStrictModeFailed("choice", game, getInfo(source, game)
|
||||
+ "\nMessage: " + message + prepareXMaxInfo(min, max));
|
||||
return computerPlayer.announceXCost(min, max, message, game, ability, null);
|
||||
return computerPlayer.announceX(min, max, message, game, source, isManaPay);
|
||||
}
|
||||
|
||||
private String prepareXMaxInfo(int min, int max) {
|
||||
|
|
|
|||
|
|
@ -787,8 +787,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
xValue = variableManaCost.getAmount();
|
||||
} else {
|
||||
// announce by player
|
||||
xValue = controller.announceXMana(variableManaCost.getMinX(), variableManaCost.getMaxX(),
|
||||
"Announce the value for " + variableManaCost.getText(), game, this);
|
||||
xValue = controller.announceX(variableManaCost.getMinX(), variableManaCost.getMaxX(),
|
||||
"Announce the value for " + variableManaCost.getText(), game, this, true);
|
||||
}
|
||||
|
||||
int amountMana = xValue * variableManaCost.getXInstancesCount();
|
||||
|
|
|
|||
|
|
@ -158,8 +158,8 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
|||
if (controller != null
|
||||
&& (source instanceof ManaAbility
|
||||
|| stackObject != null)) {
|
||||
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
|
||||
"Announce the number of " + actionText, game, source, this);
|
||||
xValue = controller.announceX(getMinValue(source, game), getMaxValue(source, game),
|
||||
"Announce the value for {X} (" + actionText + ")", game, source, false);
|
||||
}
|
||||
return xValue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,8 +173,8 @@ class AssistEffect extends OneShotEffect {
|
|||
// AI can't assist other players, maybe for teammates only (but tests must work as normal)
|
||||
int amountToPay = 0;
|
||||
if (!targetPlayer.isComputer()) {
|
||||
amountToPay = targetPlayer.announceXMana(0, unpaid.getMana().getGeneric(),
|
||||
"How much mana to pay as assist for " + controller.getName() + "?", game, source);
|
||||
amountToPay = targetPlayer.announceX(0, unpaid.getMana().getGeneric(),
|
||||
"How much mana to pay as assist for " + controller.getName() + "?", game, source, true);
|
||||
}
|
||||
|
||||
if (amountToPay > 0) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import mage.abilities.*;
|
|||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.mana.ManaOptions;
|
||||
|
|
@ -748,14 +747,10 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
boolean shuffleCardsToLibrary(Card card, Game game, Ability source);
|
||||
|
||||
/**
|
||||
* Set the value for X mana spells and abilities
|
||||
* Set the value for X in spells and abilities
|
||||
* @param isManaPay helper param for better AI logic
|
||||
*/
|
||||
int announceXMana(int min, int max, String message, Game game, Ability ability);
|
||||
|
||||
/**
|
||||
* Set the value for non mana X costs
|
||||
*/
|
||||
int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost);
|
||||
int announceX(int min, int max, String message, Game game, Ability source, boolean isManaPay);
|
||||
|
||||
// TODO: rework to use pair's list of effect + ability instead string's map
|
||||
int chooseReplacementEffect(Map<String, String> effectsMap, Map<String, MageObject> objectsMap, Game game);
|
||||
|
|
|
|||
|
|
@ -156,13 +156,8 @@ public class StubPlayer extends PlayerImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int announceXMana(int min, int max, String message, Game game, Ability ability) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variableCost) {
|
||||
return 0;
|
||||
public int announceX(int min, int max, String message, Game game, Ability source, boolean isManaPay) {
|
||||
return min;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -710,7 +710,7 @@ public final class ManaUtil {
|
|||
int bookmark = game.bookmarkState();
|
||||
player.resetStoredBookmark(game);
|
||||
|
||||
wantToPay = player.announceXMana(0, maxValue, "Choose how much mana to pay", game, source);
|
||||
wantToPay = player.announceX(0, maxValue, "Choose how much mana to pay", game, source, true);
|
||||
if (wantToPay > 0) {
|
||||
Cost cost = ManaUtil.createManaCost(wantToPay, payAsX);
|
||||
payed = cost.pay(source, game, source, player.getId(), false, null);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue