diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index b9e0a3afb10..bdd540f494d 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -36,6 +36,7 @@ import forge.game.phase.PhaseType; import forge.game.player.*; import forge.game.replacement.ReplacementEffect; import forge.game.spellability.*; +import forge.game.staticability.StaticAbility; import forge.game.trigger.WrappedAbility; import forge.game.zone.ZoneType; import forge.item.PaperCard; @@ -980,6 +981,12 @@ public class PlayerControllerAi extends PlayerController { return brains.chooseSingleReplacementEffect(possibleReplacers); } + @Override + public StaticAbility chooseSingleStaticAbility(String prompt, List possibleStatics) { + // only matters in corner cases + return Iterables.getFirst(possibleStatics, null); + } + @Override public String chooseProtectionType(String string, SpellAbility sa, List choices) { String choice = choices.get(0); @@ -1436,7 +1443,6 @@ public class PlayerControllerAi extends PlayerController { @Override public int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, int max) { // TODO: improve the logic depending on the keyword and the playability of the cost-modified SA (enough targets present etc.) - if (keyword.getKeyword() == Keyword.CASUALTY && "true".equalsIgnoreCase(sa.getHostCard().getSVar("AINoCasualtyPayment"))) { // TODO: Grisly Sigil - currently will be misplayed if Casualty is paid (the cost is always paid, targeting is wrong). @@ -1460,6 +1466,11 @@ public class PlayerControllerAi extends PlayerController { return chosenAmount; } + @Override + public int chooseNumberForCostReduction(final SpellAbility sa, final int min, final int max) { + return max; + } + @Override public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title, boolean isOptional) { CardCollection choices = new CardCollection(); diff --git a/forge-game/src/main/java/forge/game/cost/CostAdjustment.java b/forge-game/src/main/java/forge/game/cost/CostAdjustment.java index 46e29c01c14..80d0b961c1e 100644 --- a/forge-game/src/main/java/forge/game/cost/CostAdjustment.java +++ b/forge-game/src/main/java/forge/game/cost/CostAdjustment.java @@ -34,6 +34,7 @@ import forge.game.spellability.TargetChoices; import forge.game.staticability.StaticAbility; import forge.game.zone.Zone; import forge.game.zone.ZoneType; +import forge.util.Localizer; public class CostAdjustment { @@ -169,7 +170,7 @@ public class CostAdjustment { // If cardsToDelveOut is null, will immediately exile the delved cards and remember them on the host card. // Otherwise, will return them in cardsToDelveOut and the caller is responsible for doing the above. public static final void adjust(ManaCostBeingPaid cost, final SpellAbility sa, CardCollection cardsToDelveOut, boolean test) { - if (sa.isTrigger()) { + if (sa.isTrigger() || sa.isReplacementAbility()) { return; } @@ -212,8 +213,10 @@ public class CostAdjustment { sumGeneric += AbilityUtils.calculateAmount(originalCard, sa.getParam("ReduceCost"), sa); } - for (final StaticAbility stAb : reduceAbilities) { - sumGeneric += applyReduceCostAbility(stAb, sa, cost, sumGeneric); + while (!reduceAbilities.isEmpty()) { + StaticAbility choice = sa.getActivatingPlayer().getController().chooseSingleStaticAbility(Localizer.getInstance().getMessage("lblChooseCostReduction"), reduceAbilities); + reduceAbilities.remove(choice); + sumGeneric += applyReduceCostAbility(choice, sa, cost, sumGeneric); } // need to reduce generic extra because of 2 hybrid mana cost.decreaseGenericMana(sumGeneric); @@ -402,6 +405,10 @@ public class CostAdjustment { value = AbilityUtils.calculateAmount(hostCard, amount, staticAbility); } + if (staticAbility.hasParam("UpTo")) { + value = sa.getActivatingPlayer().getController().chooseNumberForCostReduction(sa, 0, value); + } + if (!staticAbility.hasParam("Cost") && !staticAbility.hasParam("Color")) { int minMana = 0; if (staticAbility.hasParam("MinMana")) { 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 6652b75d24d..a5895f0bea8 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -39,6 +39,7 @@ import forge.game.spellability.OptionalCostValue; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.TargetChoices; +import forge.game.staticability.StaticAbility; import forge.game.trigger.WrappedAbility; import forge.game.zone.ZoneType; import forge.item.PaperCard; @@ -201,6 +202,7 @@ public abstract class PlayerController { public abstract boolean payManaOptional(Card card, Cost cost, SpellAbility sa, String prompt, ManaPaymentPurpose purpose); + public abstract int chooseNumberForCostReduction(final SpellAbility sa, final int min, final int max); public abstract int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, int max); public boolean addKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt) { return chooseNumberForKeywordCost(sa, cost, keyword, prompt, 1) == 1; @@ -232,6 +234,7 @@ public abstract class PlayerController { public abstract boolean confirmPayment(CostPart costPart, String string, SpellAbility sa); public abstract ReplacementEffect chooseSingleReplacementEffect(String prompt, List possibleReplacers); + public abstract StaticAbility chooseSingleStaticAbility(String prompt, List possibleReplacers); public abstract String chooseProtectionType(String string, SpellAbility sa, List choices); // these 4 need some refining. @@ -269,6 +272,11 @@ public abstract class PlayerController { public abstract List chooseCardsForZoneChange(ZoneType destination, List origin, SpellAbility sa, CardCollection fetchList, int min, int max, DelayedReveal delayedReveal, String selectPrompt, Player decider); + public boolean isFullControl() { + return false; + } + public void setFullControl(boolean full) {} + public abstract void autoPassCancel(); public abstract void awaitNextInput(); 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 0d73b0ba31a..299d578e8af 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 @@ -35,6 +35,7 @@ import forge.game.mana.ManaCostBeingPaid; import forge.game.player.*; import forge.game.replacement.ReplacementEffect; import forge.game.spellability.*; +import forge.game.staticability.StaticAbility; import forge.game.trigger.WrappedAbility; import forge.game.zone.ZoneType; import forge.gamesimulationtests.util.card.CardSpecification; @@ -529,6 +530,12 @@ public class PlayerControllerForTests extends PlayerController { return Iterables.getFirst(possibleReplacers, null); } + @Override + public StaticAbility chooseSingleStaticAbility(String prompt, List possibleStatics) { + // TODO Auto-generated method stub + return Iterables.getFirst(possibleStatics, null); + } + @Override public String chooseProtectionType(String string, SpellAbility sa, List choices) { return choices.get(0); @@ -720,12 +727,16 @@ public class PlayerControllerForTests extends PlayerController { } @Override - public int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, - int max) { + public int chooseNumberForKeywordCost(SpellAbility sa, Cost cost, KeywordInterface keyword, String prompt, int max) { // TODO Auto-generated method stub return 0; } + @Override + public int chooseNumberForCostReduction(final SpellAbility sa, final int min, final int max) { + return max; + } + @Override public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title, boolean isOptional) { // TODO Auto-generated method stub diff --git a/forge-gui/res/cardsfolder/c/catalyst_stone.txt b/forge-gui/res/cardsfolder/c/catalyst_stone.txt index 611b94f3b63..6201c0c2c45 100644 --- a/forge-gui/res/cardsfolder/c/catalyst_stone.txt +++ b/forge-gui/res/cardsfolder/c/catalyst_stone.txt @@ -1,7 +1,7 @@ Name:Catalyst Stone ManaCost:2 Types:Artifact -S:Mode$ ReduceCost | ValidCard$ Card | ValidSpell$ Spell.Flashback | Activator$ You | Amount$ 2 | Description$ Flashback costs you pay cost up to {2} less. +S:Mode$ ReduceCost | ValidCard$ Card | ValidSpell$ Spell.Flashback | Activator$ You | Amount$ 2 | UpTo$ True | Description$ Flashback costs you pay cost up to {2} less. S:Mode$ RaiseCost | ValidCard$ Card | ValidSpell$ Spell.Flashback | Activator$ Opponent | Amount$ 2 | Description$ Flashback costs your opponents pay cost {2} more. AI:RemoveDeck:Random Oracle:Flashback costs you pay cost up to {2} less.\nFlashback costs your opponents pay cost {2} more. diff --git a/forge-gui/res/cardsfolder/f/fluctuator.txt b/forge-gui/res/cardsfolder/f/fluctuator.txt index d8a90bfa855..02349526280 100644 --- a/forge-gui/res/cardsfolder/f/fluctuator.txt +++ b/forge-gui/res/cardsfolder/f/fluctuator.txt @@ -1,6 +1,6 @@ Name:Fluctuator ManaCost:2 Types:Artifact -S:Mode$ ReduceCost | ValidCard$ Card | ValidSpell$ Activated.Cycling | Activator$ You | Amount$ 2 | Description$ Cycling abilities you activate cost you up to {2} less to activate. +S:Mode$ ReduceCost | ValidCard$ Card | ValidSpell$ Activated.Cycling | Activator$ You | Amount$ 2 | UpTo$ True | Description$ Cycling abilities you activate cost you up to {2} less to activate. AI:RemoveDeck:Random Oracle:Cycling abilities you activate cost up to {2} less to activate. diff --git a/forge-gui/res/cardsfolder/m/mana_matrix.txt b/forge-gui/res/cardsfolder/m/mana_matrix.txt index 4fa50df48ca..32bab7a4631 100644 --- a/forge-gui/res/cardsfolder/m/mana_matrix.txt +++ b/forge-gui/res/cardsfolder/m/mana_matrix.txt @@ -1,6 +1,6 @@ Name:Mana Matrix ManaCost:6 Types:Artifact -S:Mode$ ReduceCost | ValidCard$ Instant,Enchantment | Type$ Spell | Activator$ You | Amount$ 2 | Description$ Instant and enchantment spells you cast cost up to {2} less to cast. +S:Mode$ ReduceCost | ValidCard$ Instant,Enchantment | Type$ Spell | Activator$ You | Amount$ 2 | UpTo$ True | Description$ Instant and enchantment spells you cast cost up to {2} less to cast. DeckNeeds:Type$Enchantment|Instant Oracle:Instant and enchantment spells you cast cost up to {2} less to cast. diff --git a/forge-gui/res/cardsfolder/p/planar_gate.txt b/forge-gui/res/cardsfolder/p/planar_gate.txt index 13a2786ff4b..378a78f0a8c 100644 --- a/forge-gui/res/cardsfolder/p/planar_gate.txt +++ b/forge-gui/res/cardsfolder/p/planar_gate.txt @@ -1,5 +1,5 @@ Name:Planar Gate ManaCost:6 Types:Artifact -S:Mode$ ReduceCost | ValidCard$ Creature | Type$ Spell | Activator$ You | Amount$ 2 | Description$ Creature spells you cast cost up to {2} less to cast. +S:Mode$ ReduceCost | ValidCard$ Creature | Type$ Spell | Activator$ You | Amount$ 2 | UpTo$ True | Description$ Creature spells you cast cost up to {2} less to cast. Oracle:Creature spells you cast cost up to {2} less to cast. diff --git a/forge-gui/res/cardsfolder/s/stone_calendar.txt b/forge-gui/res/cardsfolder/s/stone_calendar.txt index 4736c79e690..95056a8e471 100644 --- a/forge-gui/res/cardsfolder/s/stone_calendar.txt +++ b/forge-gui/res/cardsfolder/s/stone_calendar.txt @@ -1,5 +1,5 @@ Name:Stone Calendar ManaCost:5 Types:Artifact -S:Mode$ ReduceCost | Type$ Spell | Activator$ You | Amount$ 1 | Description$ Spells you cast cost up to {1} less to cast. +S:Mode$ ReduceCost | Type$ Spell | Activator$ You | Amount$ 1 | UpTo$ True | Description$ Spells you cast cost up to {1} less to cast. Oracle:Spells you cast cost up to {1} less to cast. diff --git a/forge-gui/res/cardsfolder/u/urzas_filter.txt b/forge-gui/res/cardsfolder/u/urzas_filter.txt index b764de2d4e4..55a8b254e4b 100644 --- a/forge-gui/res/cardsfolder/u/urzas_filter.txt +++ b/forge-gui/res/cardsfolder/u/urzas_filter.txt @@ -1,5 +1,5 @@ Name:Urza's Filter ManaCost:4 Types:Artifact -S:Mode$ ReduceCost | ValidCard$ Card.MultiColor | Type$ Spell | Amount$ 2 | Description$ Multicolored spells cost up to {2} less to cast. +S:Mode$ ReduceCost | ValidCard$ Card.MultiColor | Type$ Spell | Amount$ 2 | UpTo$ True | Description$ Multicolored spells cost up to {2} less to cast. Oracle:Multicolored spells cost up to {2} less to cast. diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index cd77379e798..d2bb57a6861 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -1405,6 +1405,8 @@ lblSacrifice=Opfern lblLookCardInPlayerZone=Schaue nach Karten in {0} {1} lblPlayerZone={0} {1} lblActionFromPlayerDeck={0} von {1} Deck +lblChooseCostReduction=Choose which cost reduction to apply first +lblChooseAmountCostReduction=Choose amount of cost reduction #AbstractGuiGame.java lblConcedeCurrentGame=Das Spiel wird als verloren gewertet.\n\nTrotzdem aufgeben? lblConcedeTitle=Spiel verloren geben? diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index ffa8f4e1200..c51b3d27bb4 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1410,6 +1410,8 @@ lblSacrifice=Sacrifice lblLookCardInPlayerZone=Looking at cards in {0} {1} lblPlayerZone={0} {1} lblActionFromPlayerDeck={0} from {1} Deck +lblChooseCostReduction=Choose which cost reduction to apply first +lblChooseAmountCostReduction=Choose amount of cost reduction #AbstractGuiGame.java lblConcedeCurrentGame=This will concede the current game and you will lose.\n\nConcede anyway? lblConcedeTitle=Concede Game? diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 53a52fd103f..4a4f7c744d2 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -1406,6 +1406,8 @@ lblSacrifice=Sacrificio lblLookCardInPlayerZone=Mirando las cartas en {1} {0} lblPlayerZone={0} {1} lblActionFromPlayerDeck={0} del Mazo {1} +lblChooseCostReduction=Choose which cost reduction to apply first +lblChooseAmountCostReduction=Choose amount of cost reduction #AbstractGuiGame.java lblConcedeCurrentGame=Concederás la partida actual y perderás.\n\n¿Conceder de todos modos? lblConcedeTitle=¿Conceder partida? diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index cfed0b20c91..64d41d85fd0 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -1409,6 +1409,8 @@ lblSacrifice=Sacrifice lblLookCardInPlayerZone=Regarder des cartes dans {0} {1} lblPlayerZone={0} {1} lblActionFromPlayerDeck={0} de la plate-forme {1} +lblChooseCostReduction=Choose which cost reduction to apply first +lblChooseAmountCostReduction=Choose amount of cost reduction #AbstractGuiGame.java lblConcedeCurrentGame=Ceci concédera la partie en cours et vous perdrez.\n\nConcéder quand même ? lblConcedeTitle=Concéder le jeu ? diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 34127d963ec..f868aff557c 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -1406,6 +1406,8 @@ lblSacrifice=Sacrifica lblLookCardInPlayerZone=Stai guardando le carte in {1} di {0} lblPlayerZone={1} di {0} lblActionFromPlayerDeck={0} dal mazzo di {1} +lblChooseCostReduction=Choose which cost reduction to apply first +lblChooseAmountCostReduction=Choose amount of cost reduction #AbstractGuiGame.java lblConcedeCurrentGame=Questo concederà la partita in corso e perderai. \n \nConcedi comunque? lblConcedeTitle=Concedere la partita? diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index 8ed396820c4..2492858fc11 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -1407,6 +1407,8 @@ lblSacrifice=生け贄 lblLookCardInPlayerZone={0} {1}のカードを見る lblPlayerZone={0} {1} lblActionFromPlayerDeck={1}デッキから{0} +lblChooseCostReduction=Choose which cost reduction to apply first +lblChooseAmountCostReduction=Choose amount of cost reduction #AbstractGuiGame.java lblConcedeCurrentGame=これは現在のゲームを投了し、負けます。とにかく投了しますか? lblConcedeTitle=ゲームを投了する? diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index 3237ff24dbf..7059e1663fb 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -1437,6 +1437,8 @@ lblSacrifice=Sacrifice lblLookCardInPlayerZone=Olhando as cartas em {0} {1} lblPlayerZone={0} {1} lblActionFromPlayerDeck={0} do deck {1} +lblChooseCostReduction=Choose which cost reduction to apply first +lblChooseAmountCostReduction=Choose amount of cost reduction #AbstractGuiGame.java lblConcedeCurrentGame=Isto concede o jogo atual e você perderá.\n\ \n\ diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 00b05dfe7b7..dd1ce7c0569 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -1410,6 +1410,8 @@ lblSacrifice=牺牲 lblLookCardInPlayerZone=查看{0}的{1}中的牌 lblPlayerZone={0}的{1} lblActionFromPlayerDeck=从{1}的套牌{0} +lblChooseCostReduction=Choose which cost reduction to apply first +lblChooseAmountCostReduction=Choose amount of cost reduction #AbstractGuiGame.java lblConcedeCurrentGame=这局游戏认输。\n\n确认吗? lblConcedeTitle=这局游戏认输? diff --git a/forge-gui/src/main/java/forge/gamemodes/match/input/InputPassPriority.java b/forge-gui/src/main/java/forge/gamemodes/match/input/InputPassPriority.java index 868b6f5aab9..8e3b854be3c 100644 --- a/forge-gui/src/main/java/forge/gamemodes/match/input/InputPassPriority.java +++ b/forge-gui/src/main/java/forge/gamemodes/match/input/InputPassPriority.java @@ -23,6 +23,7 @@ import java.util.List; import forge.game.Game; import forge.game.card.Card; import forge.game.player.Player; +import forge.game.player.PlayerController; import forge.game.spellability.LandAbility; import forge.game.spellability.SpellAbility; import forge.localinstance.properties.ForgePreferences.FPref; @@ -127,6 +128,14 @@ public class InputPassPriority extends InputSyncronizedBase { public List getChosenSa() { return chosenSa; } + @Override + protected final void onPlayerSelected(Player selected, final ITriggerEvent triggerEvent) { + PlayerController pc = selected.getController(); + if (pc.isGuiPlayer()) { + pc.setFullControl(!pc.isFullControl()); + } + } + @Override protected boolean onCardSelected(final Card card, final List otherCardsToSelect, final ITriggerEvent triggerEvent) { //remove unplayable unless triggerEvent specified, in which case unplayable may be shown as disabled options diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index d83ca8a5e36..a532b6e6635 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -100,6 +100,7 @@ import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.SpellAbilityView; import forge.game.spellability.TargetChoices; +import forge.game.staticability.StaticAbility; import forge.game.trigger.Trigger; import forge.game.trigger.WrappedAbility; import forge.game.zone.MagicStack; @@ -160,6 +161,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont private boolean mayLookAtAllCards = false; private boolean disableAutoYields = false; + private boolean fullControl = false; + private IGuiGame gui; protected final InputQueue inputQueue; @@ -205,7 +208,6 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public boolean getDisableAutoYields() { return disableAutoYields; } - public void setDisableAutoYields(final boolean disableAutoYields0) { disableAutoYields = disableAutoYields0; } @@ -214,6 +216,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public boolean mayLookAtAllCards() { return mayLookAtAllCards; } + /** + * Set this to {@code true} to enable this player to see all cards any other + * player can see. + * + * @param mayLookAtAllCards the mayLookAtAllCards to set + */ + public void setMayLookAtAllCards(final boolean mayLookAtAllCards) { + this.mayLookAtAllCards = mayLookAtAllCards; + } private final ArrayList tempShownCards = new ArrayList<>(); @@ -255,14 +266,13 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont tempShownCards.clear(); } - /** - * Set this to {@code true} to enable this player to see all cards any other - * player can see. - * - * @param mayLookAtAllCards the mayLookAtAllCards to set - */ - public void setMayLookAtAllCards(final boolean mayLookAtAllCards) { - this.mayLookAtAllCards = mayLookAtAllCards; + @Override + public boolean isFullControl() { + return fullControl; + } + @Override + public void setFullControl(boolean full) { + fullControl = full; } /** @@ -1883,6 +1893,23 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return first; } + @Override + public StaticAbility chooseSingleStaticAbility(final String prompt, final List possibleStatics) { + final StaticAbility first = possibleStatics.get(0); + if (possibleStatics.size() == 1 || !fullControl) { + return first; + } + final String firstStr = first.toString(); + for (int i = 1; i < possibleStatics.size(); i++) { + // prompt user if there are multiple different options + if (!possibleStatics.get(i).toString().equals(firstStr)) { + return getGui().one(prompt, possibleStatics); + } + } + // return first option without prompting if all options are the same + return first; + } + @Override public String chooseProtectionType(final String string, final SpellAbility sa, final List choices) { return getGui().one(string, choices); @@ -3343,8 +3370,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont * spellability.SpellAbility, java.util.List) */ @Override - public List chooseOptionalCosts(SpellAbility choosen, - List optionalCost) { + public List chooseOptionalCosts(SpellAbility choosen, List optionalCost) { return getGui().many(localizer.getMessage("lblChooseOptionalCosts"), localizer.getMessage("lblOptionalCosts"), 0, optionalCost.size(), optionalCost, choosen.getHostCard().getView()); } @@ -3367,6 +3393,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return v == null ? 0 : v.intValue(); } + @Override + public int chooseNumberForCostReduction(final SpellAbility sa, final int min, final int max) { + if (fullControl) { + return chooseNumber(sa, localizer.getMessage("lblChooseAmountCostReduction"), min, max); + } + return max; + } + @Override public CardCollection chooseCardsForEffectMultiple(Map validMap, SpellAbility sa, String title, boolean isOptional) { CardCollection result = new CardCollection();