Updated modes to handle selection of modes multiple times (not working yet if targets included).

This commit is contained in:
LevelX2 2015-11-08 20:07:02 +01:00
parent 9b29cd042f
commit 431d0005f2
4 changed files with 60 additions and 27 deletions

View file

@ -1285,11 +1285,22 @@ public class HumanPlayer extends PlayerImpl {
MageObject obj = game.getObject(source.getSourceId()); MageObject obj = game.getObject(source.getSourceId());
Map<UUID, String> modeMap = new LinkedHashMap<>(); Map<UUID, String> modeMap = new LinkedHashMap<>();
for (Mode mode : modes.getAvailableModes(source, game)) { for (Mode mode : modes.getAvailableModes(source, game)) {
if (!modes.getSelectedModes().contains(mode.getId()) // show only modes not already selected 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 where targets are available && mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) { // and needed targets have to be available
String modeText = mode.getEffects().getText(mode); String modeText = mode.getEffects().getText(mode);
if (obj != null) { 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); modeMap.put(mode.getId(), modeText);
} }

View file

@ -17,6 +17,8 @@ public class GatekeeperOfMalakirTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Gatekeeper of Malakir"); addCard(Zone.HAND, playerA, "Gatekeeper of Malakir");
addCard(Zone.BATTLEFIELD, playerB, "Llanowar Elves"); 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"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gatekeeper of Malakir");
setStopAt(1, PhaseStep.BEGIN_COMBAT); setStopAt(1, PhaseStep.BEGIN_COMBAT);
@ -29,5 +31,4 @@ public class GatekeeperOfMalakirTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, 1); assertGraveyardCount(playerB, 1);
} }
} }

View file

@ -902,6 +902,9 @@ public abstract class AbilityImpl implements Ability {
for (Mode mode : modes.values()) { for (Mode mode : modes.values()) {
if (mode.getTargets().canChoose(sourceId, controllerId, game)) { if (mode.getTargets().canChoose(sourceId, controllerId, game)) {
found++; found++;
if (modes.isEachModeMoreThanOnce()) {
return true;
}
if (found >= getModes().getMinModes()) { if (found >= getModes().getMinModes()) {
return true; return true;
} }
@ -1103,13 +1106,16 @@ public abstract class AbilityImpl implements Ability {
} }
} else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) { } else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) {
Modes spellModes = ((Spell) object).getSpellAbility().getModes(); Modes spellModes = ((Spell) object).getSpellAbility().getModes();
int item = 0; for (UUID modeId : spellModes.getSelectedModes()) {
for (Mode mode : spellModes.values()) { int item = 0;
item++; for (Mode mode : spellModes.values()) {
if (spellModes.getSelectedModes().contains(mode.getId())) { item++;
spellModes.setActiveMode(mode.getId()); if (mode.getId().equals(modeId)) {
sb.append(" (mode ").append(item).append(")"); spellModes.setActiveMode(mode.getId());
sb.append(getTargetDescriptionForLog(getTargets(), game)); sb.append(" (mode ").append(item).append(")");
sb.append(getTargetDescriptionForLog(getTargets(), game));
break;
}
} }
} }
} else { } else {

View file

@ -30,7 +30,6 @@ package mage.abilities;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -51,11 +50,12 @@ import mage.util.CardUtil;
public class Modes extends LinkedHashMap<UUID, Mode> { public class Modes extends LinkedHashMap<UUID, Mode> {
private UUID modeId; private UUID modeId;
private final Set<UUID> selectedModes = new LinkedHashSet<>(); private final ArrayList<UUID> selectedModes = new ArrayList<>();
private int minModes; private int minModes;
private int maxModes; private int maxModes;
private TargetController modeChooser; 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() { public Modes() {
Mode mode = new Mode(); Mode mode = new Mode();
@ -65,6 +65,8 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
this.maxModes = 1; this.maxModes = 1;
this.selectedModes.add(modeId); this.selectedModes.add(modeId);
this.modeChooser = TargetController.YOU; this.modeChooser = TargetController.YOU;
this.eachModeOnlyOnce = false;
this.eachModeMoreThanOnce = false;
} }
public Modes(final Modes modes) { public Modes(final Modes modes) {
@ -77,6 +79,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
this.selectedModes.addAll(modes.selectedModes); this.selectedModes.addAll(modes.selectedModes);
this.modeChooser = modes.modeChooser; this.modeChooser = modes.modeChooser;
this.eachModeOnlyOnce = modes.eachModeOnlyOnce; this.eachModeOnlyOnce = modes.eachModeOnlyOnce;
this.eachModeMoreThanOnce = modes.eachModeMoreThanOnce;
} }
public Modes copy() { public Modes copy() {
@ -87,7 +90,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
return get(modeId); return get(modeId);
} }
public Set<UUID> getSelectedModes() { public ArrayList<UUID> getSelectedModes() {
return selectedModes; return selectedModes;
} }
@ -125,14 +128,6 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
if (this.containsKey(mode.getId())) { if (this.containsKey(mode.getId())) {
this.modeId = mode.getId(); this.modeId = mode.getId();
this.selectedModes.add(mode.getId()); this.selectedModes.add(mode.getId());
Set<UUID> 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<UUID, Mode> {
} }
} }
// check if all modes can be activated automatically // check if all modes can be activated automatically
if (this.size() == this.getMinModes()) { if (this.size() == this.getMinModes() && !isEachModeMoreThanOnce()) {
Set<UUID> onceSelectedModes = null; Set<UUID> onceSelectedModes = null;
if (isEachModeOnlyOnce()) { if (isEachModeOnlyOnce()) {
onceSelectedModes = getAlreadySelectedModes(source, game); onceSelectedModes = getAlreadySelectedModes(source, game);
@ -205,6 +200,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
return true; return true;
} }
this.modeId = this.values().iterator().next().getId(); this.modeId = this.values().iterator().next().getId();
this.selectedModes.clear();
this.selectedModes.add(modeId); this.selectedModes.add(modeId);
if (isEachModeOnlyOnce()) { if (isEachModeOnlyOnce()) {
setAlreadySelectedModes(selectedModes, source, game); setAlreadySelectedModes(selectedModes, source, game);
@ -212,7 +208,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
return true; return true;
} }
private void setAlreadySelectedModes(Set<UUID> selectedModes, Ability source, Game game) { private void setAlreadySelectedModes(ArrayList<UUID> selectedModes, Ability source, Game game) {
String key = getKey(source, game); String key = getKey(source, game);
Set<UUID> onceSelectedModes = (Set<UUID>) game.getState().getValue(key); Set<UUID> onceSelectedModes = (Set<UUID>) game.getState().getValue(key);
if (onceSelectedModes == null) { if (onceSelectedModes == null) {
@ -232,7 +228,12 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
public List<Mode> getAvailableModes(Ability source, Game game) { public List<Mode> getAvailableModes(Ability source, Game game) {
List<Mode> availableModes = new ArrayList<>(); List<Mode> availableModes = new ArrayList<>();
Set<UUID> nonAvailableModes = getAlreadySelectedModes(source, game); Set<UUID> nonAvailableModes;
if (isEachModeMoreThanOnce()) {
nonAvailableModes = new HashSet<>();
} else {
nonAvailableModes = getAlreadySelectedModes(source, game);
}
for (Mode mode : this.values()) { for (Mode mode : this.values()) {
if (isEachModeOnlyOnce() && nonAvailableModes != null && nonAvailableModes.contains(mode.getId())) { if (isEachModeOnlyOnce() && nonAvailableModes != null && nonAvailableModes.contains(mode.getId())) {
continue; continue;
@ -253,13 +254,19 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
sb.append("choose one or both "); sb.append("choose one or both ");
} else if (this.getMinModes() == 2 && this.getMaxModes() == 2) { } else if (this.getMinModes() == 2 && this.getMaxModes() == 2) {
sb.append("choose two "); sb.append("choose two ");
} else if (this.getMinModes() == 3 && this.getMaxModes() == 3) {
sb.append("choose three ");
} else { } else {
sb.append("choose one "); sb.append("choose one ");
} }
if (isEachModeOnlyOnce()) { if (isEachModeOnlyOnce()) {
sb.append("that hasn't been chosen "); sb.append("that hasn't been chosen ");
} }
sb.append("&mdash;<br>"); if (isEachModeMoreThanOnce()) {
sb.append(". You may choose the same mode more than once.<br>");
} else {
sb.append("&mdash;<br>");
}
for (Mode mode : this.values()) { for (Mode mode : this.values()) {
sb.append("&bull "); sb.append("&bull ");
sb.append(mode.getEffects().getTextStartingUpperCase(mode)); sb.append(mode.getEffects().getTextStartingUpperCase(mode));
@ -283,4 +290,12 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
this.eachModeOnlyOnce = eachModeOnlyOnce; this.eachModeOnlyOnce = eachModeOnlyOnce;
} }
public boolean isEachModeMoreThanOnce() {
return eachModeMoreThanOnce;
}
public void setEachModeMoreThanOnce(boolean eachModeMoreThanOnce) {
this.eachModeMoreThanOnce = eachModeMoreThanOnce;
}
} }