diff --git a/.gitattributes b/.gitattributes index 3bd1d5f07fd..0b2263bc5f2 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12851,6 +12851,7 @@ src/main/java/forge/control/input/InputPayManaCostUtil.java svneol=native#text/p src/main/java/forge/control/input/InputPayManaX.java -text src/main/java/forge/control/input/InputPayReturnCost.java -text src/main/java/forge/control/input/InputPaySacCost.java -text +src/main/java/forge/control/input/InputSelectManyCards.java -text src/main/java/forge/control/input/package-info.java svneol=native#text/plain src/main/java/forge/control/package-info.java -text src/main/java/forge/deck/CardCollections.java -text diff --git a/src/main/java/forge/Action.java b/src/main/java/forge/Action.java index 6b41aec3974..6e3120f1e67 100644 --- a/src/main/java/forge/Action.java +++ b/src/main/java/forge/Action.java @@ -2,13 +2,13 @@ package forge; /** *

- * Command interface. + * Command interface, just like Guava Function but return type is void. *

* * @author Forge * @version $Id: Command.java 12297 2011-11-28 19:56:47Z jendave $ */ -public interface Action extends java.io.Serializable { +public interface Action { /** *

* execute. diff --git a/src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java b/src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java index f3c03b68734..30c8cb94f80 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java @@ -5,6 +5,9 @@ import java.util.List; import javax.swing.JOptionPane; +import com.google.common.base.Function; +import com.google.common.base.Predicate; + import forge.Card; import forge.Command; @@ -16,6 +19,7 @@ import forge.card.spellability.AbilityActivated; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.control.input.Input; +import forge.control.input.InputSelectManyCards; import forge.game.player.ComputerUtil; import forge.game.player.Player; import forge.game.zone.PlayerZone; @@ -24,8 +28,6 @@ import forge.game.zone.ZoneType; import forge.gui.GuiChoose; import forge.gui.match.CMatchUI; -import forge.view.ButtonUtil; - /** * TODO: Write javadoc for this type. * @@ -369,36 +371,19 @@ class CardFactoryArtifacts { public void resolve() { // not implemented for compy if (card.getController().isHuman()) { - Singletons.getModel().getMatch().getInput().setInput(new Input() { - private static final long serialVersionUID = -2305549394512889450L; - private final List exiled = new ArrayList(); - + + Predicate validForPick = new Predicate() { @Override - public void showMessage() { - final StringBuilder sb = new StringBuilder(); - sb.append(card.getName()).append(" - Exile cards from hand. Currently, "); - sb.append(this.exiled.size()).append(" selected. (Press OK when done.)"); - CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString()); - ButtonUtil.enableOnlyOK(); - } - - @Override - public void selectButtonOK() { - this.done(); - } - - @Override - public void selectCard(final Card c) { + public boolean apply(Card c) { Zone zone = Singletons.getModel().getGame().getZoneOf(c); - if (zone.is(ZoneType.Hand) && c.getController() == card.getController() && !this.exiled.contains(c)) { - this.exiled.add(c); - this.showMessage(); - } + return zone.is(ZoneType.Hand) && c.getController() == card.getController(); } - - public void done() { - // exile those cards - for (final Card c : this.exiled) { + }; + + Function, Input> onSelected = new Function, Input>() { + @Override + public Input apply(List exiled) { + for (final Card c : exiled) { Singletons.getModel().getGame().getAction().exile(c); } @@ -407,7 +392,7 @@ class CardFactoryArtifacts { // Ruling: This is not a draw... final PlayerZone lib = card.getController().getZone(ZoneType.Library); int numCards = 0; - while ((lib.size() > 0) && (numCards < this.exiled.size())) { + while ((lib.size() > 0) && (numCards < exiled.size())) { Singletons.getModel().getGame().getAction().moveToHand(lib.get(0)); numCards++; } @@ -418,15 +403,20 @@ class CardFactoryArtifacts { // Then look at the exiled cards and put them on // top of your library in any order. - while (this.exiled.size() > 0) { - final Card c1 = GuiChoose.one("Put a card on top of your library.", this.exiled); + while (exiled.size() > 0) { + final Card c1 = GuiChoose.one("Put a card on top of your library.", exiled); Singletons.getModel().getGame().getAction().moveToLibrary(c1); - this.exiled.remove(c1); + exiled.remove(c1); } + return null; + }; + }; + + InputSelectManyCards inp = new InputSelectManyCards(validForPick, 0, Integer.MAX_VALUE, onSelected); + inp.setMessage(card.getName() + " - Exile cards from hand. Currently, %d selected. (Press OK when done.)"); + + Singletons.getModel().getMatch().getInput().setInput(inp); - this.stop(); - } - }); } } diff --git a/src/main/java/forge/card/cardfactory/CardFactoryAuras.java b/src/main/java/forge/card/cardfactory/CardFactoryAuras.java index a1d12a38756..25406e36b0b 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryAuras.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryAuras.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.List; import com.esotericsoftware.minlog.Log; +import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; @@ -31,6 +32,7 @@ import forge.CardLists; import forge.CardPredicates.Presets; import forge.CardUtil; import forge.Command; +import forge.Constant; import forge.Singletons; import forge.card.cost.Cost; import forge.card.spellability.Ability; @@ -39,11 +41,14 @@ import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellPermanent; import forge.card.spellability.Target; import forge.control.input.Input; +import forge.control.input.InputPayManaCost; +import forge.control.input.InputSelectManyCards; import forge.game.player.Player; import forge.game.zone.PlayerZone; import forge.game.zone.Zone; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; +import forge.gui.match.CMatchUI; /** @@ -129,7 +134,7 @@ class CardFactoryAuras { public void resolve() { // Only query player, AI will have decided already. if (card.getController().isHuman()) { - newType[0] = GuiChoose.one("Select land type.", CardUtil.getLandTypes()); + newType[0] = GuiChoose.one("Select land type.", Constant.CardTypes.BASIC_TYPES); } Singletons.getModel().getGame().getAction().moveToPlay(card); @@ -243,17 +248,36 @@ class CardFactoryAuras { card.addUnEnchantCommand(onUnEnchant); card.addLeavesPlayCommand(onLeavesPlay); - final Input runtime = new Input() { - - private static final long serialVersionUID = -62372711146079880L; - + Function, Input> onSelected = new Function, Input>() { @Override - public void showMessage() { - final List land = Singletons.getModel().getGame().getLandsInPlay(); - this.stopSetNext(CardFactoryUtil - .inputTargetSpecific(spell, land, "Select target land", true, false)); + public final Input apply(List selected) { + spell.setTargetCard(selected.get(0)); + if (spell.getManaCost().equals("0")) { + Singletons.getModel().getGame().getStack().add(spell); + return null; + } else { + return new InputPayManaCost(spell); + } } }; + + Predicate canTarget = new Predicate() { + @Override + public boolean apply(Card c) { + if (!c.isLand() || !c.isInZone(ZoneType.Battlefield)) + return false; + + if (!c.canBeTargetedBy(spell)) { + CMatchUI.SINGLETON_INSTANCE.showMessage("Cannot target this card (Shroud? Protection?)."); + return false; + } + + return true; + } + }; + + InputSelectManyCards runtime = new InputSelectManyCards(canTarget, 1, 1, onSelected); + runtime.setMessage("Select target land"); spell.setBeforePayMana(runtime); } // *************** END ************ END ************************** diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index 2b69c4cd6b2..410aff79de7 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -67,7 +67,6 @@ import forge.card.trigger.Trigger; import forge.card.trigger.TriggerHandler; import forge.card.trigger.TriggerType; import forge.control.input.Input; -import forge.control.input.InputPayManaCost; import forge.control.input.InputPayManaCostUtil; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; @@ -1203,85 +1202,6 @@ public class CardFactoryUtil { return entersBattleFieldWithCounters(sourceCard, Counters.TIME, power); } // vanishing - // List choices are the only cards the user can successful select - /** - *

- * inputTargetSpecific. - *

- * - * @param spell - * a {@link forge.card.spellability.SpellAbility} object. - * @param choices - * a {@link forge.CardList} object. - * @param message - * a {@link java.lang.String} object. - * @param targeted - * a boolean. - * @param free - * a boolean. - * @return a {@link forge.control.input.Input} object. - */ - public static Input inputTargetSpecific(final SpellAbility spell, final List choices, final String message, - final boolean targeted, final boolean free) { - return CardFactoryUtil.inputTargetSpecific(spell, choices, message, Command.BLANK, targeted, free); - } - - // List choices are the only cards the user can successful select - /** - *

- * inputTargetSpecific. - *

- * - * @param spell - * a {@link forge.card.spellability.SpellAbility} object. - * @param choices - * a {@link forge.CardList} object. - * @param message - * a {@link java.lang.String} object. - * @param paid - * a {@link forge.Command} object. - * @param targeted - * a boolean. - * @param free - * a boolean. - * @return a {@link forge.control.input.Input} object. - */ - public static Input inputTargetSpecific(final SpellAbility spell, final List choices, final String message, - final Command paid, final boolean targeted, final boolean free) { - final Input target = new Input() { - private static final long serialVersionUID = -1779224307654698954L; - - @Override - public void showMessage() { - CMatchUI.SINGLETON_INSTANCE.showMessage(message); - ButtonUtil.enableOnlyCancel(); - } - - @Override - public void selectButtonCancel() { - this.stop(); - } - - @Override - public void selectCard(final Card card) { - if (targeted && !card.canBeTargetedBy(spell)) { - CMatchUI.SINGLETON_INSTANCE.showMessage("Cannot target this card (Shroud? Protection?)."); - } else if (choices.contains(card)) { - spell.setTargetCard(card); - if (spell.getManaCost().equals("0") || free) { - Singletons.getModel().getGame().getStack().add(spell); - this.stop(); - } else { - this.stopSetNext(new InputPayManaCost(spell)); - } - - paid.execute(); - } - } // selectCard() - }; - return target; - } // inputTargetSpecific() - // List choices are the only cards the user can successful select /** *

diff --git a/src/main/java/forge/control/input/Input.java b/src/main/java/forge/control/input/Input.java index 38554898947..9d840a0116d 100644 --- a/src/main/java/forge/control/input/Input.java +++ b/src/main/java/forge/control/input/Input.java @@ -122,6 +122,6 @@ public abstract class Input implements java.io.Serializable { * This method is used to mark old descendants of Input * TODO: Write javadoc for this method. */ - public /* abstract */void isClassUpdated(){} //; + public /* abstract */ void isClassUpdated() {}//; } diff --git a/src/main/java/forge/control/input/InputSelectManyCards.java b/src/main/java/forge/control/input/InputSelectManyCards.java new file mode 100644 index 00000000000..6babbbc3ee1 --- /dev/null +++ b/src/main/java/forge/control/input/InputSelectManyCards.java @@ -0,0 +1,110 @@ +package forge.control.input; + +import java.util.ArrayList; +import java.util.List; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; + +import forge.Card; +import forge.gui.match.CMatchUI; +import forge.view.ButtonUtil; + +/** + * TODO: Write javadoc for this type. + * + */ +public class InputSelectManyCards extends Input { + + private static final long serialVersionUID = -2305549394512889450L; + + private List allowedCards = null; + private Predicate allowedFilter = null; + private final List selected = new ArrayList(); + private final Function, Input> onComplete; + private final int min; + private final int max; + + private String message = "Source-Card-Name - Select %d more card(s)"; + + private InputSelectManyCards(int min, int max, final Function, Input> onDone) + { + onComplete = onDone; + if( min > max ) throw new IllegalArgumentException("Min must not be greater than Max"); + this.min = min; + this.max = max; + } + + public InputSelectManyCards(final List allowedList, int min, int max, final Function, Input> onDone) + { + this(min, max, onDone); + allowedCards = allowedList; + } + + public InputSelectManyCards(final Predicate allowedRule, int min, int max, final Function, Input> onDone) + { + this(min, max, onDone); + allowedFilter = allowedRule; + } + + + @Override + public void showMessage() { + String msgToShow = max == Integer.MAX_VALUE ? String.format(message, selected.size()) : String.format(message, max - selected.size()); + CMatchUI.SINGLETON_INSTANCE.showMessage(msgToShow); + + boolean canCancel = min == 0 && selected.isEmpty(); + boolean canOk = min <= selected.size(); + + if (canOk && canCancel) ButtonUtil.enableAll(); + if (!canOk && canCancel) ButtonUtil.enableOnlyCancel(); + if (canOk && !canCancel) ButtonUtil.enableOnlyOK(); + if (!canOk && !canCancel) ButtonUtil.disableAll(); + } + + @Override + public void selectButtonOK() { + this.done(); + } + + @Override + public void selectButtonCancel() { + this.stop(); + } + + @Override + public void selectCard(final Card c) { + if ( selected.contains(c) ) return; + if ( allowedCards != null && !allowedCards.contains(c)) return; + if ( allowedFilter != null && !allowedFilter.apply(c)) return; + + this.selected.add(c); + this.showMessage(); + + if ( selected.size() == max ) + done(); + } + + public void done() { + Input next = onComplete.apply(selected); + if ( null == next ) + this.stop(); + else + this.stopSetNext(next); + } + + @Override + public void isClassUpdated() {} + + + + public String getMessage() { + return message; + } + + + public void setMessage(String message0) { + this.message = message0; // TODO: Add 0 to parameter's name. + } + +}