other: added getMultiAmount testable dialogs in cheat menu (part of #13638)

This commit is contained in:
Oleg Agafonov 2025-06-07 08:48:47 +04:00
parent ee1dc74b90
commit 1112c9516d
6 changed files with 145 additions and 3 deletions

View file

@ -15,6 +15,8 @@ import java.util.List;
/**
* Part of testable game dialogs
* <p>
* It's a complex dialog with 2 steps: choose targets list + distribute amount between targets
* <p>
* Supported methods:
* - player.chooseTarget(amount)
*

View file

@ -11,6 +11,8 @@ import java.util.List;
/**
* Part of testable game dialogs
* <p>
* Its simple dialog to get some amount (example: part of chooseTargetAmount)
* <p>
* Supported methods:
* - player.getAmount()
*

View file

@ -0,0 +1,118 @@
package mage.utils.testers;
import mage.abilities.Ability;
import mage.constants.MultiAmountType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
import mage.util.MultiAmountMessage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Part of testable game dialogs
* <p>
* Its simple dialog to get distributed value between multiple options (example: part of combat damage distributing)
* <p>
* Supported methods:
* - player.getMultiAmountWithIndividualConstraints()
* - player.getMultiAmount() - simple version of constraints
*
* @author JayDi85
*/
class GetMultiAmountTestableDialog extends BaseTestableDialog {
boolean isYou; // who choose - you or opponent
int totalMin;
int totalMax;
List<MultiAmountMessage> amountOptions = new ArrayList<>();
/**
* @param options min, max, default
*/
public GetMultiAmountTestableDialog(boolean isYou, String info, int totalMin, int totalMax, List<List<Integer>> options) {
super(String.format("player.getMultiAmount(%s)", isYou ? "you" : "AI"),
String.format("%s, %d options from [%d-%d]", info, options.size(), totalMin, totalMax),
"");
this.isYou = isYou;
this.totalMin = totalMin;
this.totalMax = totalMax;
int optionNumber = 0;
for (List<Integer> single : options) {
optionNumber++;
String mes = "<font color=green>option</font> " + optionNumber + " with html";
this.amountOptions.add(new MultiAmountMessage(mes, single.get(0), single.get(1), single.get(2)));
}
}
@Override
public List<String> showDialog(Player player, Ability source, Game game, Player opponent) {
Player choosingPlayer = this.isYou ? player : opponent;
//String message = "<font color=green>message</font> with html";
List<Integer> chooseRes;
List<MultiAmountMessage> options = this.amountOptions.stream().map(MultiAmountMessage::copy).collect(Collectors.toList());
chooseRes = choosingPlayer.getMultiAmountWithIndividualConstraints(
Outcome.Benefit,
options,
this.totalMin,
this.totalMax,
MultiAmountType.DAMAGE,
game
);
List<String> result = new ArrayList<>();
result.add(getGroup() + " - " + this.getName());
int selectedIndex = -1;
int selectedTotal = 0;
for (Integer selectedValue : chooseRes) {
selectedIndex++;
selectedTotal += selectedValue;
MultiAmountMessage option = this.amountOptions.get(selectedIndex);
result.add(String.format("%d from [%d-%d, def %d]",
selectedValue,
option.min,
option.max,
option.defaultValue
));
}
result.add("total selected: " + selectedTotal);
return result;
}
static public void register(TestableDialogsRunner runner) {
List<Boolean> isYous = Arrays.asList(false, true);
for (boolean isYou : isYous) {
// make sure default values are valid due min/max settings
// single target
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 0 def", 0, 1, genSameOptions(1, 0, 1, 0)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 0 def", 0, 3, genSameOptions(1, 0, 3, 0)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 1 def", 1, 1, genSameOptions(1, 1, 1, 1)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 1 def", 1, 3, genSameOptions(1, 1, 3, 1)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 5 def", 0, 10, genSameOptions(1, 0, 10, 5)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 10 def", 10, 10, genSameOptions(1, 0, 10, 10)));
// multiple targets
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 0 def", 0, 5, genSameOptions(3, 0, 3, 0)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 0 def", 0, 5, genSameOptions(3, 0, 3, 0)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 1 def", 1, 5, genSameOptions(3, 1, 3, 1)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 1 def", 1, 5, genSameOptions(3, 1, 3, 1)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 20 def", 0, 60, genSameOptions(3, 0, 60, 20)));
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 20 def", 60, 60, genSameOptions(3, 0, 60, 20)));
// big lists
runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "big list", 0, 100, genSameOptions(20, 0, 100, 0)));
}
}
private static List<List<Integer>> genSameOptions(int amount, int min, int max, int def) {
List<List<Integer>> res = new ArrayList<>();
for (int i = 0; i < amount; i++) {
// min, max, default
res.add(Arrays.asList(min, max, def));
}
return res;
}
}

View file

@ -31,7 +31,7 @@ import java.util.stream.Collectors;
* [x] choosePile
* [x] announceX
* [x] getAmount
* [ ] getMultiAmountWithIndividualConstraints // TODO: implement
* [x] getMultiAmountWithIndividualConstraints
* <p>
* Support of priority dialogs (can be called by game engine, some can be implemented in theory):
* --- priority
@ -75,6 +75,7 @@ public class TestableDialogsRunner {
ChooseAmountTestableDialog.register(this);
AnnounceXTestableDialog.register(this);
GetAmountTestableDialog.register(this);
GetMultiAmountTestableDialog.register(this);
}
void registerDialog(TestableDialog dialog) {

View file

@ -784,12 +784,18 @@ public interface Player extends MageItem, Copyable<Player> {
* @return List of integers with size equal to messages.size(). The sum of the integers is equal to max.
*/
default List<Integer> getMultiAmount(Outcome outcome, List<String> messages, int optionMin, int totalMin, int totalMax, MultiAmountType type, Game game) {
// do not override it
// runtime check: make sure all default values are valid
// TODO: add default check inside getMultiAmountWithIndividualConstraints
if (optionMin > totalMax || optionMin * messages.size() > totalMin) {
throw new IllegalArgumentException(String.format("Wrong code usage: getMultiAmount found bad option min/max values: %d/%d", optionMin, totalMax));
}
List<MultiAmountMessage> constraints = messages.stream()
.map(s -> new MultiAmountMessage(s, optionMin, totalMax))
.collect(Collectors.toList());
return getMultiAmountWithIndividualConstraints(outcome, constraints, totalMin, totalMax, type, game);
}

View file

@ -5,9 +5,10 @@ import java.io.Serializable;
/**
* A helper class for facilitating the multi-choose dialog
*
* @author alexander-novo
* @author alexander-novo, JayDi85
*/
public class MultiAmountMessage implements Serializable {
public class MultiAmountMessage implements Serializable, Copyable<MultiAmountMessage> {
public String message;
public int min;
public int max;
@ -24,8 +25,20 @@ public class MultiAmountMessage implements Serializable {
this.defaultValue = defaultValue;
}
private MultiAmountMessage(final MultiAmountMessage mes) {
this.message = mes.message;
this.min = mes.min;
this.max = mes.max;
this.defaultValue = mes.defaultValue;
}
@Override
public String toString() {
return String.format("%s - from %d to %d - default %d", message, min, max, defaultValue);
}
@Override
public MultiAmountMessage copy() {
return new MultiAmountMessage(this);
}
}