diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
index 06ca962697f..48376cafda8 100644
--- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
+++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java
@@ -1924,7 +1924,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
@Override
public Mode chooseMode(Modes modes, Ability source, Game game) {
log.debug("chooseMode");
- if (modes.getMode() != null && modes.getMaxModes() == modes.getSelectedModes().size()) {
+ if (modes.getMode() != null && modes.getMaxModes(game, source) == modes.getSelectedModes().size()) {
// mode was already set by the AI
return modes.getMode();
}
diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java
index 11d8a595079..a0ca6be9b5a 100644
--- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java
+++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java
@@ -2085,7 +2085,7 @@ public class HumanPlayer extends PlayerImpl {
boolean done = false;
while (!done && canRespond()) {
- String message = "Choose mode (selected " + modes.getSelectedModes().size() + " of " + modes.getMaxModes()
+ String message = "Choose mode (selected " + modes.getSelectedModes().size() + " of " + modes.getMaxModes(game, source)
+ ", min " + modes.getMinModes() + ")";
if (obj != null) {
message = message + "
" + obj.getLogName();
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/AkromasWillTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/AkromasWillTest.java
new file mode 100644
index 00000000000..82d5c186025
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/AkromasWillTest.java
@@ -0,0 +1,81 @@
+package org.mage.test.cards.single.cmr;
+
+import mage.abilities.keyword.FlyingAbility;
+import mage.abilities.keyword.LifelinkAbility;
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestCommanderDuelBase;
+
+/**
+ * @author JayDi85
+ */
+
+public class AkromasWillTest extends CardTestCommanderDuelBase {
+
+ @Test
+ public void test_OneMode() {
+ // https://github.com/magefree/mage/issues/7210
+
+ // Choose one. If you control a commander as you cast this spell, you may choose both.
+ // * Creatures you control gain flying, vigilance, and double strike until end of turn.
+ // * Creatures you control gain lifelink, indestructible, and protection from all colors until end of turn.
+ addCard(Zone.HAND, playerA, "Akroma's Will", 1); // {3}{W}
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
+ //
+ addCard(Zone.BATTLEFIELD, playerA, "Kitesail Corsair", 1);
+
+ checkAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", FlyingAbility.class, false);
+ checkAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", LifelinkAbility.class, false);
+
+ // cast and use ONE mode only
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akroma's Will");
+ setModeChoice(playerA, "1");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", FlyingAbility.class, true);
+ checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", LifelinkAbility.class, false);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+ }
+
+ @Test
+ public void test_MultiModesOnCommander() {
+ // https://github.com/magefree/mage/issues/7210
+
+ // Choose one. If you control a commander as you cast this spell, you may choose both.
+ // * Creatures you control gain flying, vigilance, and double strike until end of turn.
+ // * Creatures you control gain lifelink, indestructible, and protection from all colors until end of turn.
+ addCard(Zone.HAND, playerA, "Akroma's Will", 1); // {3}{W}
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
+ //
+ addCard(Zone.COMMAND, playerA, "Balduvian Bears", 1); // {1}{G}
+ addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
+ //
+ addCard(Zone.BATTLEFIELD, playerA, "Kitesail Corsair", 1);
+
+ checkAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", FlyingAbility.class, false);
+ checkAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", LifelinkAbility.class, false);
+
+ // prepare commander
+ activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 2);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkPermanentCount("commander on battle", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears", 1);
+
+ // cast and use two modes instead one
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akroma's Will");
+ setModeChoice(playerA, "2");
+ setModeChoice(playerA, "1");
+ waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
+ checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", FlyingAbility.class, true);
+ checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", LifelinkAbility.class, true);
+
+ setStrictChooseMode(true);
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
index 9ccf4d56ad7..ffc0b2541b9 100644
--- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
+++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java
@@ -1869,7 +1869,7 @@ public class TestPlayer implements Player {
@Override
public Mode chooseMode(Modes modes, Ability source, Game game) {
- if (!modesSet.isEmpty() && modes.getMaxModes() > modes.getSelectedModes().size()) {
+ if (!modesSet.isEmpty() && modes.getMaxModes(game, source) > modes.getSelectedModes().size()) {
// set mode to null to select less than maximum modes if multiple modes are allowed
if (modesSet.get(0) == null) {
modesSet.remove(0);
diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java
index 10a7a87aa73..d64ca6c132c 100644
--- a/Mage/src/main/java/mage/abilities/Modes.java
+++ b/Mage/src/main/java/mage/abilities/Modes.java
@@ -76,6 +76,7 @@ public class Modes extends LinkedHashMap {
} else {
this.currentMode = get(modes.getMode().getId()); // need fix?
}
+ this.moreCondition = modes.moreCondition;
}
public Modes copy() {
@@ -190,8 +191,41 @@ public class Modes extends LinkedHashMap {
this.maxModesFilter = maxModesFilter;
}
- public int getMaxModes() {
- return this.maxModes;
+ /**
+ * Return real affected max modes in current game. Use null params for default max modes value.
+ *
+ * @param game
+ * @param source
+ * @return
+ */
+ public int getMaxModes(Game game, Ability source) {
+ int realMaxModes = this.maxModes;
+ if (game == null || source == null) {
+ return realMaxModes;
+ }
+
+ // use case: make all modes chooseable
+ if (moreCondition != null && moreCondition.apply(game, source)) {
+ realMaxModes = Integer.MAX_VALUE;
+ }
+
+ // use case: limit max modes by opponents (wtf?!)
+ if (getMaxModesFilter() != null) {
+ if (this.maxModesFilter instanceof FilterPlayer) {
+ realMaxModes = 0;
+ for (UUID targetPlayerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
+ Player targetPlayer = game.getPlayer(targetPlayerId);
+ if (((FilterPlayer) this.maxModesFilter).match(targetPlayer, source.getSourceId(), source.getControllerId(), game)) {
+ realMaxModes++;
+ }
+ }
+ if (realMaxModes > this.maxModes) {
+ realMaxModes = this.maxModes;
+ }
+ }
+ }
+
+ return realMaxModes;
}
public void setModeChooser(TargetController modeChooser) {
@@ -222,9 +256,9 @@ public class Modes extends LinkedHashMap {
public boolean choose(Game game, Ability source) {
if (this.isResetEachTurn()) {
- if (this.getTurnNum(game, source) != game.getTurnNum()) {
+ if (getTurnNum(game, source) != game.getTurnNum()) {
this.clearAlreadySelectedModes(source, game);
- this.setTurnNum(game, source);
+ setTurnNum(game, source);
}
}
if (this.size() > 1) {
@@ -284,24 +318,8 @@ public class Modes extends LinkedHashMap {
// player chooses modes manually
this.currentMode = null;
- int currentMaxModes = this.getMaxModes();
- if (moreCondition != null && moreCondition.apply(game, source)) {
- currentMaxModes = Integer.MAX_VALUE;
- }
- if (getMaxModesFilter() != null) {
- if (maxModesFilter instanceof FilterPlayer) {
- currentMaxModes = 0;
- for (UUID targetPlayerId : game.getState().getPlayersInRange(source.getControllerId(), game)) {
- Player targetPlayer = game.getPlayer(targetPlayerId);
- if (((FilterPlayer) maxModesFilter).match(targetPlayer, source.getSourceId(), source.getControllerId(), game)) {
- currentMaxModes++;
- }
- }
- if (currentMaxModes > this.getMaxModes()) {
- currentMaxModes = this.getMaxModes();
- }
- }
- }
+ int currentMaxModes = this.getMaxModes(game, source);
+
while (this.selectedModes.size() < currentMaxModes) {
Mode choice = player.chooseMode(this, source, game);
if (choice == null) {
@@ -446,19 +464,19 @@ public class Modes extends LinkedHashMap {
sb.append(chooseText);
} else if (this.getMaxModesFilter() != null) {
sb.append("choose one or more. Each mode must target ").append(getMaxModesFilter().getMessage());
- } else if (this.getMinModes() == 0 && this.getMaxModes() == 1) {
+ } else if (this.getMinModes() == 0 && this.getMaxModes(null, null) == 1) {
sb.append("choose up to one");
- } else if (this.getMinModes() == 0 && this.getMaxModes() == 3) {
+ } else if (this.getMinModes() == 0 && this.getMaxModes(null, null) == 3) {
sb.append("choose any number");
- } else if (this.getMinModes() == 1 && this.getMaxModes() > 2) {
+ } else if (this.getMinModes() == 1 && this.getMaxModes(null, null) > 2) {
sb.append("choose one or more");
- } else if (this.getMinModes() == 1 && this.getMaxModes() == 2) {
+ } else if (this.getMinModes() == 1 && this.getMaxModes(null, null) == 2) {
sb.append("choose one or both");
- } else if (this.getMinModes() == 2 && this.getMaxModes() == 2) {
+ } else if (this.getMinModes() == 2 && this.getMaxModes(null, null) == 2) {
sb.append("choose two");
- } else if (this.getMinModes() == 3 && this.getMaxModes() == 3) {
+ } else if (this.getMinModes() == 3 && this.getMaxModes(null, null) == 3) {
sb.append("choose three");
- } else if (this.getMinModes() == 4 && this.getMaxModes() == 4) {
+ } else if (this.getMinModes() == 4 && this.getMaxModes(null, null) == 4) {
sb.append("choose four");
} else {
sb.append("choose one");