diff --git a/src/main/java/forge/CounterType.java b/src/main/java/forge/CounterType.java
index 61d99928089..492d67a7fb0 100644
--- a/src/main/java/forge/CounterType.java
+++ b/src/main/java/forge/CounterType.java
@@ -383,6 +383,12 @@ public enum CounterType {
public String getName() {
return this.name;
}
+
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
/**
*
diff --git a/src/main/java/forge/card/ability/effects/CountersProliferateEffect.java b/src/main/java/forge/card/ability/effects/CountersProliferateEffect.java
index 9979716d4da..197dcaa2c53 100644
--- a/src/main/java/forge/card/ability/effects/CountersProliferateEffect.java
+++ b/src/main/java/forge/card/ability/effects/CountersProliferateEffect.java
@@ -1,27 +1,100 @@
package forge.card.ability.effects;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
import com.google.common.base.Predicate;
-import com.google.common.collect.Lists;
-
import forge.Card;
import forge.CardLists;
import forge.CounterType;
+import forge.FThreads;
+import forge.GameEntity;
import forge.Singletons;
import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
-import forge.control.input.InputBase;
+import forge.control.input.InputSelectManyBase;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
-import forge.gui.match.CMatchUI;
-import forge.view.ButtonUtil;
public class CountersProliferateEffect extends SpellAbilityEffect {
+ /**
+ * TODO: Write javadoc for this type.
+ *
+ */
+ public static final class InputProliferate extends InputSelectManyBase {
+ private static final long serialVersionUID = -1779224307654698954L;
+ private Map chosenCounters = new HashMap();
+
+ public InputProliferate() {
+ super(1, Integer.MAX_VALUE);
+ }
+
+ @Override
+ protected String getMessage() {
+ StringBuilder sb = new StringBuilder("Choose permanents and/or players with counters on them to add one more counter of that type.");
+ sb.append("\n\nYou've selected so far:\n");
+ if( selected.isEmpty())
+ sb.append("(none)");
+ else
+ for(GameEntity ge : selected ) {
+ if( ge instanceof Player )
+ sb.append("* A poison counter to player ").append(ge).append("\n");
+ else
+ sb.append("* ").append(ge).append(" -> ").append(chosenCounters.get(ge)).append("counter\n");
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ public void selectCard(final Card card) {
+ if( !selectEntity(card) )
+ return;
+
+ if( selected.contains(card) ) {
+ final List choices = new ArrayList();
+ for (final CounterType ct : CounterType.values()) {
+ if (card.getCounters(ct) > 0) {
+ choices.add(ct);
+ }
+ }
+
+ CounterType toAdd = choices.size() == 1 ? choices.get(0) : GuiChoose.one("Select counter type", choices);
+ chosenCounters.put(card, toAdd);
+ }
+
+ refresh();
+ }
+
+ @Override
+ public void selectPlayer(final Player player) {
+ if( !selectEntity(player) )
+ return;
+ refresh();
+ }
+
+ @Override
+ protected boolean isValidChoice(GameEntity choice) {
+ if (choice instanceof Player)
+ return ((Player) choice).getPoisonCounters() > 0 && !choice.hasKeyword("You can't get poison counters");
+
+ if (choice instanceof Card)
+ return ((Card) choice).hasCounters();
+
+ return false;
+ }
+
+ public CounterType getCounterFor(GameEntity ge) {
+ return chosenCounters.get(ge);
+ }
+ }
+
+
@Override
protected String getStackDescription(SpellAbility sa) {
final StringBuilder sb = new StringBuilder();
@@ -36,66 +109,23 @@ public class CountersProliferateEffect extends SpellAbilityEffect {
public void resolve(SpellAbility sa) {
Player controller = sa.getSourceCard().getController();
if (controller.isHuman()) {
- resolveHuman(sa);
+ InputProliferate inp = new InputProliferate();
+ inp.setCancelAllowed(true);
+ FThreads.setInputAndWait(inp);
+ if ( inp.hasCancelled() )
+ return;
+
+ for(GameEntity ge: inp.getSelected()) {
+ if( ge instanceof Player )
+ ((Player) ge).addPoisonCounters(1, sa.getSourceCard());
+ else if( ge instanceof Card)
+ ((Card) ge).addCounter(inp.getCounterFor(ge), 1, true);
+ }
} else {
resolveAI(controller, sa);
}
}
- private static void resolveHuman(final SpellAbility sa) {
- final List unchosen = Lists.newArrayList(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield));
- final List players = new ArrayList(Singletons.getModel().getGame().getPlayers());
- Singletons.getModel().getMatch().getInput().setInput(new InputBase() {
- private static final long serialVersionUID = -1779224307654698954L;
-
- @Override
- public void showMessage() {
- ButtonUtil.enableOnlyOk();
- CMatchUI.SINGLETON_INSTANCE.showMessage("Proliferate: Choose permanents and/or players");
- }
-
- @Override
- public void selectButtonOK() {
- // Hacky intermittent solution to triggers that look for
- // counters being put on. They used
- // to wait for another priority passing after proliferate
- // finished.
- Singletons.getModel().getGame().getStack().chooseOrderOfSimultaneousStackEntryAll();
- this.stop();
- }
-
- @Override
- public void selectCard(final Card card) {
- if (!unchosen.contains(card)) {
- return;
- }
- unchosen.remove(card);
- final ArrayList choices = new ArrayList();
- for (final CounterType c1 : CounterType.values()) {
- if (card.getCounters(c1) != 0) {
- choices.add(c1.getName());
- }
- }
- if (choices.size() > 0) {
- card.addCounter(CounterType.getType((choices.size() == 1 ? choices.get(0) : GuiChoose.one(
- "Select counter type", choices).toString())), 1, true);
- }
- }
-
- @Override
- public void selectPlayer(final Player player) {
- if (players.indexOf(player) >= 0) {
-
- players.remove(player); // no second selection
- if (player.getPoisonCounters() > 0) {
- player.addPoisonCounters(1, sa.getSourceCard());
- }
- }
- }
- });
- }
-
-
private static void resolveAI(final Player ai, final SpellAbility sa) {
final List allies = ai.getAllies();
allies.add(ai);
diff --git a/src/main/java/forge/control/input/InputSelectCards.java b/src/main/java/forge/control/input/InputSelectCards.java
index 1ab25e83afb..474aa4544e3 100644
--- a/src/main/java/forge/control/input/InputSelectCards.java
+++ b/src/main/java/forge/control/input/InputSelectCards.java
@@ -12,26 +12,9 @@ public abstract class InputSelectCards extends InputSelectManyBase {
@Override
public final void selectCard(final Card c) {
- selectEntity(c);
+ if ( !selectEntity(c) )
+ return;
+
+ refresh();
}
-
- /* (non-Javadoc)
- * @see forge.control.input.InputSelectListBase#onSelectStateChanged(forge.GameEntity, boolean)
- */
- @Override
- protected void onSelectStateChanged(Card c, boolean newState) {
- c.setUsedToPay(newState); // UI supports card highlighting though this abstraction-breaking mechanism
- }
-
- /* (non-Javadoc)
- * @see forge.control.input.InputSyncronizedBase#afterStop()
- */
- @Override
- protected void afterStop() {
- for(Card c : selected)
- c.setUsedToPay(false);
- super.afterStop(); // It's ultimatelly important to keep call to super class!
-
- }
-
}
diff --git a/src/main/java/forge/control/input/InputSelectManyBase.java b/src/main/java/forge/control/input/InputSelectManyBase.java
index 42983399272..84c58f000c7 100644
--- a/src/main/java/forge/control/input/InputSelectManyBase.java
+++ b/src/main/java/forge/control/input/InputSelectManyBase.java
@@ -3,8 +3,8 @@ package forge.control.input;
import java.util.ArrayList;
import java.util.List;
+import forge.Card;
import forge.GameEntity;
-import forge.gui.match.CMatchUI;
import forge.view.ButtonUtil;
public abstract class InputSelectManyBase extends InputSyncronizedBase implements InputSelectMany {
@@ -31,10 +31,17 @@ public abstract class InputSelectManyBase extends InputSyn
this.max = max;
}
+ protected void refresh() {
+ if (hasAllTargets()) {
+ selectButtonOK();
+ } else {
+ this.showMessage();
+ }
+ }
+
@Override
public final void showMessage() {
- String msgToShow = getMessage();
- CMatchUI.SINGLETON_INSTANCE.showMessage(msgToShow);
+ showMessage(getMessage());
boolean canCancel = (min == 0 && selected.isEmpty()) || allowCancel;
boolean canOk = hasEnoughTargets();
@@ -95,31 +102,41 @@ public abstract class InputSelectManyBase extends InputSyn
// might re-define later
protected boolean hasEnoughTargets() { return selected.size() >= min; }
protected boolean hasAllTargets() { return selected.size() >= max; }
- protected void onSelectStateChanged(T c, boolean newState) {} // Select card inputs may highlight selected cards with this method
- protected void selectEntity(T c) {
+ protected boolean selectEntity(T c) {
if (!isValidChoice(c)) {
- return;
+ return false;
}
if ( selected.contains(c) ) {
if ( allowUnselect ) {
this.selected.remove(c);
onSelectStateChanged(c, false);
- }
+ } else
+ return false;
} else {
this.selected.add(c);
onSelectStateChanged(c, true);
}
-
- if (hasAllTargets()) {
- selectButtonOK();
- } else {
- this.showMessage();
- }
+ return true;
}
+ protected void onSelectStateChanged(T c, boolean newState) {
+ if( c instanceof Card )
+ ((Card)c).setUsedToPay(newState); // UI supports card highlighting though this abstraction-breaking mechanism
+ }
+
+
+ protected void afterStop() {
+ for(T c : selected)
+ if( c instanceof Card)
+ ((Card)c).setUsedToPay(false);
+
+ super.afterStop(); // It's ultimatelly important to keep call to super class!
+
+ }
+
public final boolean isUnselectAllowed() { return allowUnselect; }