From 431d0005f25a737086bf48c139d4d27de408d2ea Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 8 Nov 2015 20:07:02 +0100 Subject: [PATCH] Updated modes to handle selection of modes multiple times (not working yet if targets included). --- .../src/mage/player/human/HumanPlayer.java | 17 +++++-- .../cost/kicker/GatekeeperOfMalakirTest.java | 3 +- Mage/src/mage/abilities/AbilityImpl.java | 20 +++++--- Mage/src/mage/abilities/Modes.java | 47 ++++++++++++------- 4 files changed, 60 insertions(+), 27 deletions(-) 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 96a5dfc7ebe..dd3830375a3 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 @@ -1285,11 +1285,22 @@ public class HumanPlayer extends PlayerImpl { MageObject obj = game.getObject(source.getSourceId()); Map modeMap = new LinkedHashMap<>(); for (Mode mode : modes.getAvailableModes(source, game)) { - if (!modes.getSelectedModes().contains(mode.getId()) // show only modes not already selected - && mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and where targets are available + if ((!modes.getSelectedModes().contains(mode.getId()) || modes.isEachModeMoreThanOnce())// show only modes not already selected if more than once is not allowed + && mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and needed targets have to be available String modeText = mode.getEffects().getText(mode); if (obj != null) { - modeText = modeText.replace("{source}", obj.getName()); + modeText = modeText.replace("{source}", obj.getName()).replace("{this}", obj.getName()); + } + if (modes.isEachModeMoreThanOnce()) { + int timesSelected = 0; + for (UUID selectedModeId : modes.getSelectedModes()) { + if (mode.getId().equals(selectedModeId)) { + timesSelected++; + } + } + if (timesSelected > 0) { + modeText = "(selected " + timesSelected + "x) " + modeText; + } } modeMap.put(mode.getId(), modeText); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/kicker/GatekeeperOfMalakirTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/kicker/GatekeeperOfMalakirTest.java index 322cc8f4201..770f6265f6d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/kicker/GatekeeperOfMalakirTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/kicker/GatekeeperOfMalakirTest.java @@ -17,6 +17,8 @@ public class GatekeeperOfMalakirTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Gatekeeper of Malakir"); addCard(Zone.BATTLEFIELD, playerB, "Llanowar Elves"); + // Kicker {B} (You may pay an additional {B} as you cast this spell.) + // When Gatekeeper of Malakir enters the battlefield, if it was kicked, target player sacrifices a creature. castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gatekeeper of Malakir"); setStopAt(1, PhaseStep.BEGIN_COMBAT); @@ -29,5 +31,4 @@ public class GatekeeperOfMalakirTest extends CardTestPlayerBase { assertGraveyardCount(playerB, 1); } - } diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java index 659d4987fb1..a595b7478f1 100644 --- a/Mage/src/mage/abilities/AbilityImpl.java +++ b/Mage/src/mage/abilities/AbilityImpl.java @@ -902,6 +902,9 @@ public abstract class AbilityImpl implements Ability { for (Mode mode : modes.values()) { if (mode.getTargets().canChoose(sourceId, controllerId, game)) { found++; + if (modes.isEachModeMoreThanOnce()) { + return true; + } if (found >= getModes().getMinModes()) { return true; } @@ -1103,13 +1106,16 @@ public abstract class AbilityImpl implements Ability { } } else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) { Modes spellModes = ((Spell) object).getSpellAbility().getModes(); - int item = 0; - for (Mode mode : spellModes.values()) { - item++; - if (spellModes.getSelectedModes().contains(mode.getId())) { - spellModes.setActiveMode(mode.getId()); - sb.append(" (mode ").append(item).append(")"); - sb.append(getTargetDescriptionForLog(getTargets(), game)); + for (UUID modeId : spellModes.getSelectedModes()) { + int item = 0; + for (Mode mode : spellModes.values()) { + item++; + if (mode.getId().equals(modeId)) { + spellModes.setActiveMode(mode.getId()); + sb.append(" (mode ").append(item).append(")"); + sb.append(getTargetDescriptionForLog(getTargets(), game)); + break; + } } } } else { diff --git a/Mage/src/mage/abilities/Modes.java b/Mage/src/mage/abilities/Modes.java index be01464e4f0..f17c787cb08 100644 --- a/Mage/src/mage/abilities/Modes.java +++ b/Mage/src/mage/abilities/Modes.java @@ -30,7 +30,6 @@ package mage.abilities; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -51,11 +50,12 @@ import mage.util.CardUtil; public class Modes extends LinkedHashMap { private UUID modeId; - private final Set selectedModes = new LinkedHashSet<>(); + private final ArrayList selectedModes = new ArrayList<>(); private int minModes; private int maxModes; private TargetController modeChooser; - private boolean eachModeOnlyOnce; // state if each mode can be chosen only once + private boolean eachModeMoreThanOnce; // each mode can be selected multiple times during one choice + private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists public Modes() { Mode mode = new Mode(); @@ -65,6 +65,8 @@ public class Modes extends LinkedHashMap { this.maxModes = 1; this.selectedModes.add(modeId); this.modeChooser = TargetController.YOU; + this.eachModeOnlyOnce = false; + this.eachModeMoreThanOnce = false; } public Modes(final Modes modes) { @@ -77,6 +79,7 @@ public class Modes extends LinkedHashMap { this.selectedModes.addAll(modes.selectedModes); this.modeChooser = modes.modeChooser; this.eachModeOnlyOnce = modes.eachModeOnlyOnce; + this.eachModeMoreThanOnce = modes.eachModeMoreThanOnce; } public Modes copy() { @@ -87,7 +90,7 @@ public class Modes extends LinkedHashMap { return get(modeId); } - public Set getSelectedModes() { + public ArrayList getSelectedModes() { return selectedModes; } @@ -125,14 +128,6 @@ public class Modes extends LinkedHashMap { if (this.containsKey(mode.getId())) { this.modeId = mode.getId(); this.selectedModes.add(mode.getId()); - Set copySelectedModes = new LinkedHashSet<>(); - copySelectedModes.addAll(selectedModes); - selectedModes.clear(); - for (UUID basicModeId : this.keySet()) { - if (copySelectedModes.contains(basicModeId)) { - selectedModes.add(basicModeId); - } - } } } @@ -153,7 +148,7 @@ public class Modes extends LinkedHashMap { } } // check if all modes can be activated automatically - if (this.size() == this.getMinModes()) { + if (this.size() == this.getMinModes() && !isEachModeMoreThanOnce()) { Set onceSelectedModes = null; if (isEachModeOnlyOnce()) { onceSelectedModes = getAlreadySelectedModes(source, game); @@ -205,6 +200,7 @@ public class Modes extends LinkedHashMap { return true; } this.modeId = this.values().iterator().next().getId(); + this.selectedModes.clear(); this.selectedModes.add(modeId); if (isEachModeOnlyOnce()) { setAlreadySelectedModes(selectedModes, source, game); @@ -212,7 +208,7 @@ public class Modes extends LinkedHashMap { return true; } - private void setAlreadySelectedModes(Set selectedModes, Ability source, Game game) { + private void setAlreadySelectedModes(ArrayList selectedModes, Ability source, Game game) { String key = getKey(source, game); Set onceSelectedModes = (Set) game.getState().getValue(key); if (onceSelectedModes == null) { @@ -232,7 +228,12 @@ public class Modes extends LinkedHashMap { public List getAvailableModes(Ability source, Game game) { List availableModes = new ArrayList<>(); - Set nonAvailableModes = getAlreadySelectedModes(source, game); + Set nonAvailableModes; + if (isEachModeMoreThanOnce()) { + nonAvailableModes = new HashSet<>(); + } else { + nonAvailableModes = getAlreadySelectedModes(source, game); + } for (Mode mode : this.values()) { if (isEachModeOnlyOnce() && nonAvailableModes != null && nonAvailableModes.contains(mode.getId())) { continue; @@ -253,13 +254,19 @@ public class Modes extends LinkedHashMap { sb.append("choose one or both "); } else if (this.getMinModes() == 2 && this.getMaxModes() == 2) { sb.append("choose two "); + } else if (this.getMinModes() == 3 && this.getMaxModes() == 3) { + sb.append("choose three "); } else { sb.append("choose one "); } if (isEachModeOnlyOnce()) { sb.append("that hasn't been chosen "); } - sb.append("—
"); + if (isEachModeMoreThanOnce()) { + sb.append(". You may choose the same mode more than once.
"); + } else { + sb.append("—
"); + } for (Mode mode : this.values()) { sb.append("&bull "); sb.append(mode.getEffects().getTextStartingUpperCase(mode)); @@ -283,4 +290,12 @@ public class Modes extends LinkedHashMap { this.eachModeOnlyOnce = eachModeOnlyOnce; } + public boolean isEachModeMoreThanOnce() { + return eachModeMoreThanOnce; + } + + public void setEachModeMoreThanOnce(boolean eachModeMoreThanOnce) { + this.eachModeMoreThanOnce = eachModeMoreThanOnce; + } + }