diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index f4f4c7d93c9..905843b62a8 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -501,8 +501,8 @@ public class PlayerControllerAi extends PlayerController { * @see forge.game.player.PlayerController#chooseModeForAbility(forge.card.spellability.SpellAbility, java.util.List, int, int) */ @Override - public List chooseModeForAbility(SpellAbility sa, int min, int num) { - return CharmAi.chooseOptionsAi(sa, player, sa.isTrigger(), num, min, !player.equals(sa.getActivatingPlayer())); + public List chooseModeForAbility(SpellAbility sa, int min, int num, boolean allowRepeat) { + return CharmAi.chooseOptionsAi(sa, player, sa.isTrigger(), num, min, allowRepeat, !player.equals(sa.getActivatingPlayer())); } @Override diff --git a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java index f05168f35de..7711575e888 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java @@ -26,7 +26,7 @@ public class CharmAi extends SpellAbilityAi { // reset the chosen list. Otherwise it will be locked in forever sa.setChosenList(null); - List chosenList = min > 1 ? chooseMultipleOptionsAi(sa, ai, min) : chooseOptionsAi(sa, ai, timingRight, num, min, false); + List chosenList = min > 1 ? chooseMultipleOptionsAi(sa, ai, min) : chooseOptionsAi(sa, ai, timingRight, num, min, sa.hasParam("CanRepeatModes"), false); if (chosenList.isEmpty()) { return false; @@ -38,7 +38,7 @@ public class CharmAi extends SpellAbilityAi { return r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); } - public static List chooseOptionsAi(SpellAbility sa, final Player ai, boolean playNow, int num, int min, boolean opponentChoser) { + public static List chooseOptionsAi(SpellAbility sa, final Player ai, boolean playNow, int num, int min, boolean allowRepeat, boolean opponentChoser) { if (sa.getChosenList() != null) { return sa.getChosenList(); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java index a0a5cd7ed63..279566902f0 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java @@ -52,9 +52,9 @@ public class CharmEffect extends SpellAbilityEffect { // so nothing to do in this resolve } - @Override protected String getStackDescription(SpellAbility sa) { + // TODO Build StackDescription based on Chosen SubAbilities return ""; } @@ -79,7 +79,7 @@ public class CharmEffect extends SpellAbilityEffect { source.setChosenPlayer(chooser); } - List chosen = chooser.getController().chooseModeForAbility(sa, min, num); + List chosen = chooser.getController().chooseModeForAbility(sa, min, num, sa.hasParam(("CanRepeatModes"))); chainAbilities(sa, chosen); } @@ -98,12 +98,15 @@ public class CharmEffect extends SpellAbilityEffect { }); for (AbilitySub sub : chosen) { - saDeepest.setSubAbility(sub); - sub.setActivatingPlayer(saDeepest.getActivatingPlayer()); - sub.setParent(saDeepest); + // Clone the chosen, just in case the some subAb gets chosen multiple times + AbilitySub clone = (AbilitySub)sub.getCopy(); + + saDeepest.setSubAbility(clone); + clone.setActivatingPlayer(saDeepest.getActivatingPlayer()); + clone.setParent(saDeepest); // to chain the next one (but make sure it goes all the way at the end of the SA chain) - saDeepest = sub; + saDeepest = clone; while (saDeepest.getSubAbility() != null) { saDeepest = saDeepest.getSubAbility(); } diff --git a/forge-game/src/main/java/forge/game/player/PlayerController.java b/forge-game/src/main/java/forge/game/player/PlayerController.java index 7314253467a..d69e818d84e 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -184,7 +184,7 @@ public abstract class PlayerController { public abstract boolean chooseFlipResult(SpellAbility sa, Player flipper, boolean[] results, boolean call); public abstract Card chooseProtectionShield(GameEntity entityBeingDamaged, List options, Map choiceMap); - public abstract List chooseModeForAbility(SpellAbility sa, int min, int num); + public abstract List chooseModeForAbility(SpellAbility sa, int min, int num, boolean allowRepeat); public abstract byte chooseColor(String message, SpellAbility sa, ColorSet colors); public abstract byte chooseColorAllowColorless(String message, Card c, ColorSet colors); diff --git a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java index f05d1283963..d3b17faeada 100644 --- a/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java +++ b/forge-gui-desktop/src/test/java/forge/gamesimulationtests/util/PlayerControllerForTests.java @@ -444,7 +444,7 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public List chooseModeForAbility(SpellAbility sa, int min, int num) { + public List chooseModeForAbility(SpellAbility sa, int min, int num, boolean allowRepeat) { throw new IllegalStateException("Erring on the side of caution here..."); } diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 60e5e6fea0c..0797596a199 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1082,7 +1082,7 @@ public class PlayerControllerHuman * @see forge.game.player.PlayerController#chooseModeForAbility(forge.card.spellability.SpellAbility, java.util.List, int, int) */ @Override - public List chooseModeForAbility(final SpellAbility sa, final int min, final int num) { + public List chooseModeForAbility(final SpellAbility sa, final int min, final int num, boolean allowRepeat) { final List choices = CharmEffect.makePossibleOptions(sa); final String modeTitle = String.format("%s activated %s - Choose a mode", sa.getActivatingPlayer(), sa.getHostCard()); final List chosen = Lists.newArrayListWithCapacity(num); @@ -1098,7 +1098,9 @@ public class PlayerControllerHuman break; } - choices.remove(a); + if (!allowRepeat) { + choices.remove(a); + } chosen.add(a); } return chosen;