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); + } }