diff --git a/Mage.Common/src/main/java/mage/utils/testers/ChooseAmountTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/ChooseAmountTestableDialog.java
index b95937a88b9..6a7847ec4fc 100644
--- a/Mage.Common/src/main/java/mage/utils/testers/ChooseAmountTestableDialog.java
+++ b/Mage.Common/src/main/java/mage/utils/testers/ChooseAmountTestableDialog.java
@@ -15,6 +15,8 @@ import java.util.List;
/**
* Part of testable game dialogs
*
+ * It's a complex dialog with 2 steps: choose targets list + distribute amount between targets
+ *
* Supported methods:
* - player.chooseTarget(amount)
*
diff --git a/Mage.Common/src/main/java/mage/utils/testers/GetAmountTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/GetAmountTestableDialog.java
index 22a4659dd78..0a66bac8f9d 100644
--- a/Mage.Common/src/main/java/mage/utils/testers/GetAmountTestableDialog.java
+++ b/Mage.Common/src/main/java/mage/utils/testers/GetAmountTestableDialog.java
@@ -11,6 +11,8 @@ import java.util.List;
/**
* Part of testable game dialogs
*
+ * Its simple dialog to get some amount (example: part of chooseTargetAmount)
+ *
* Supported methods:
* - player.getAmount()
*
diff --git a/Mage.Common/src/main/java/mage/utils/testers/GetMultiAmountTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/GetMultiAmountTestableDialog.java
new file mode 100644
index 00000000000..2c1f9046f3a
--- /dev/null
+++ b/Mage.Common/src/main/java/mage/utils/testers/GetMultiAmountTestableDialog.java
@@ -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
+ *
+ * Its simple dialog to get distributed value between multiple options (example: part of combat damage distributing)
+ *
+ * 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 amountOptions = new ArrayList<>();
+
+ /**
+ * @param options min, max, default
+ */
+ public GetMultiAmountTestableDialog(boolean isYou, String info, int totalMin, int totalMax, List> 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 single : options) {
+ optionNumber++;
+ String mes = "option " + optionNumber + " with html";
+ this.amountOptions.add(new MultiAmountMessage(mes, single.get(0), single.get(1), single.get(2)));
+ }
+ }
+
+ @Override
+ public List showDialog(Player player, Ability source, Game game, Player opponent) {
+ Player choosingPlayer = this.isYou ? player : opponent;
+ //String message = "message with html";
+ List chooseRes;
+ List options = this.amountOptions.stream().map(MultiAmountMessage::copy).collect(Collectors.toList());
+ chooseRes = choosingPlayer.getMultiAmountWithIndividualConstraints(
+ Outcome.Benefit,
+ options,
+ this.totalMin,
+ this.totalMax,
+ MultiAmountType.DAMAGE,
+ game
+ );
+
+ List 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 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> genSameOptions(int amount, int min, int max, int def) {
+ List> res = new ArrayList<>();
+ for (int i = 0; i < amount; i++) {
+ // min, max, default
+ res.add(Arrays.asList(min, max, def));
+ }
+ return res;
+ }
+}
diff --git a/Mage.Common/src/main/java/mage/utils/testers/TestableDialogsRunner.java b/Mage.Common/src/main/java/mage/utils/testers/TestableDialogsRunner.java
index 6217877dbce..3c2cfb3840d 100644
--- a/Mage.Common/src/main/java/mage/utils/testers/TestableDialogsRunner.java
+++ b/Mage.Common/src/main/java/mage/utils/testers/TestableDialogsRunner.java
@@ -31,7 +31,7 @@ import java.util.stream.Collectors;
* [x] choosePile
* [x] announceX
* [x] getAmount
- * [ ] getMultiAmountWithIndividualConstraints // TODO: implement
+ * [x] getMultiAmountWithIndividualConstraints
*
* 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) {
diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java
index 14b9df75af5..1028d914a0c 100644
--- a/Mage/src/main/java/mage/players/Player.java
+++ b/Mage/src/main/java/mage/players/Player.java
@@ -784,12 +784,18 @@ public interface Player extends MageItem, Copyable {
* @return List of integers with size equal to messages.size(). The sum of the integers is equal to max.
*/
default List getMultiAmount(Outcome outcome, List 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 constraints = messages.stream()
.map(s -> new MultiAmountMessage(s, optionMin, totalMax))
.collect(Collectors.toList());
+
return getMultiAmountWithIndividualConstraints(outcome, constraints, totalMin, totalMax, type, game);
}
diff --git a/Mage/src/main/java/mage/util/MultiAmountMessage.java b/Mage/src/main/java/mage/util/MultiAmountMessage.java
index 3749c20c408..ce4f72f98a9 100644
--- a/Mage/src/main/java/mage/util/MultiAmountMessage.java
+++ b/Mage/src/main/java/mage/util/MultiAmountMessage.java
@@ -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 {
+
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);
+ }
}