From 33d0fea61070db8aad2b025b52ddc4d7931992c6 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Sun, 3 Dec 2023 09:25:59 -0500 Subject: [PATCH] WHO: the_toymakers_trap.txt + support --- .../src/main/java/forge/ai/AiController.java | 2 + .../forge/game/ability/AbilityFactory.java | 2 +- .../ability/effects/ChooseNumberEffect.java | 63 ++++++++++++++++++- .../src/main/java/forge/game/card/Card.java | 5 ++ .../main/java/forge/game/card/CardView.java | 3 + .../upcoming/the_toymakers_trap.txt | 12 ++++ forge-gui/res/languages/de-DE.properties | 1 + forge-gui/res/languages/en-US.properties | 1 + forge-gui/res/languages/es-ES.properties | 1 + forge-gui/res/languages/fr-FR.properties | 5 +- forge-gui/res/languages/it-IT.properties | 1 + forge-gui/res/languages/ja-JP.properties | 1 + forge-gui/res/languages/pt-BR.properties | 1 + forge-gui/res/languages/zh-CN.properties | 1 + 14 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 forge-gui/res/cardsfolder/upcoming/the_toymakers_trap.txt diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index c1a9cce568b..d4a568fb7d3 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -1877,6 +1877,8 @@ public int chooseNumber(SpellAbility sa, String title, List options, Pl } else { return options.get(0); } + case ChooseNumber: + return Aggregates.random(options); default: return options.get(0); } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java index 4e637aeb11c..db93f11e025 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -53,7 +53,7 @@ public final class AbilityFactory { public static final List additionalAbilityKeys = Lists.newArrayList( "WinSubAbility", "OtherwiseSubAbility", // Clash "BidSubAbility", // BidLifeEffect - "ChooseNumberSubAbility", "Lowest", "Highest", "NotLowest", // ChooseNumber + "ChooseNumberSubAbility", "Lowest", "Highest", "NotLowest", "GuessCorrect", "GuessWrong", // ChooseNumber "HeadsSubAbility", "TailsSubAbility", "LoseSubAbility", // FlipCoin "TrueSubAbility", "FalseSubAbility", // Branch "ChosenPile", "UnchosenPile", // MultiplePiles & TwoPiles diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java index 416d2c6642e..aca7c591281 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java @@ -1,5 +1,6 @@ package forge.game.ability.effects; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -15,6 +16,9 @@ import forge.util.Lang; import forge.util.Localizer; import forge.util.MyRandom; +import forge.util.collect.FCollectionView; + +import org.apache.commons.lang3.tuple.Pair; public class ChooseNumberEffect extends SpellAbilityEffect { @@ -47,11 +51,17 @@ public void resolve(SpellAbility sa) { final Map chooseMap = Maps.newHashMap(); + // defined guesser must try to guess the chosen - currently only on "The Toymaker's Trap" + boolean guessedCorrect = false; + Pair guessPair = null; + // may need future work to ensure chooser and guesser get same choices even in absence of RemoveChoices param + List choices = new ArrayList<>(); + for (final Player p : getTargetPlayers(sa)) { if (!p.isInGame()) { continue; } - int chosen; + Integer chosen; if (random) { chosen = MyRandom.getRandom().nextInt((max - min) + 1) + min; //TODO more useful notify for RepeatEach -> ChooseNumber with random @@ -61,6 +71,16 @@ public void resolve(SpellAbility sa) { if (anyNumber) { Integer value = p.getController().announceRequirements(sa, title); chosen = value == null ? 0 : value; + } else if (sa.hasParam("RemoveChoices")) { + // currently we always remove remembered numbers, so the value is not really used yet + for (int i = min; i <= max; i++) { + choices.add(i); + } + for (Object o : card.getRemembered()) { + if (o instanceof Integer) choices.remove((Integer) o); + } + if (choices.isEmpty()) continue; + chosen = p.getController().chooseNumber(sa, title, choices, null); } else { chosen = p.getController().chooseNumber(sa, title, min, max); } @@ -72,15 +92,35 @@ public void resolve(SpellAbility sa) { card.setChosenNumber(chosen); } if (sa.hasParam("Notify")) { - p.getGame().getAction().notifyOfValue(sa, card, Localizer.getInstance().getMessage("lblPlayerPickedChosen", p.getName(), chosen), p); + p.getGame().getAction().notifyOfValue(sa, card, Localizer.getInstance(). + getMessage("lblPlayerPickedChosen", p.getName(), chosen), p); + } + if (sa.hasParam("Guesser") && chosen != null) { // if nothing was chosen, there is nothing to guess + final FCollectionView gChoices = + AbilityUtils.getDefinedPlayers(card, sa.getParam("Guesser"), sa); + final Player guesser = choices.isEmpty() ? null : p.getController(). + chooseSingleEntityForEffect(gChoices, sa, Localizer.getInstance().getMessage("lblChoosePlayer"), + false, null); + if (guesser != null) { + guessPair = Pair.of(guesser, guesser.getController().chooseNumber(sa, + Localizer.getInstance().getMessage("lblChooseNumber"), choices, null)); + // if more complicated effects require this in the future it may be worth a unique message + if (chooseMap.containsValue(guessPair.getValue())) guessedCorrect = true; + } } } - if (secretlyChoose) { + + if (secretlyChoose && !chooseMap.isEmpty()) { StringBuilder sb = new StringBuilder(); List highestNum = Lists.newArrayList(); List lowestNum = Lists.newArrayList(); int highest = 0; int lowest = Integer.MAX_VALUE; + if (guessPair != null) { + sb.append(Localizer.getInstance().getMessage("lblPlayerGuessedNum", guessPair.getKey().getName(), + String.valueOf(guessPair.getValue()))); + sb.append("\r\n"); + } for (Entry ev : chooseMap.entrySet()) { int num = ev.getValue(); Player player = ev.getKey(); @@ -153,7 +193,24 @@ public void resolve(SpellAbility sa) { card.addRemembered(highestNum); } } + + if (sa.hasParam("GuessCorrect") && guessedCorrect) { // correct guess doesn't use any chosen num yet + SpellAbility sub = sa.getAdditionalAbility("GuessCorrect"); + AbilityUtils.resolve(sub); + } + + if (sa.hasParam("GuessWrong") && guessPair != null && !guessedCorrect) { + SpellAbility sub = sa.getAdditionalAbility("GuessWrong"); + // wrong currently uses the guess, not the chosen + card.setChosenNumber(guessPair.getValue()); + card.addRemembered(guessPair.getKey()); + AbilityUtils.resolve(sub); + card.clearChosenNumber(); + card.removeRemembered(guessPair.getKey()); + } } + + if (sa.hasParam("RememberChosen")) card.addRemembered(chooseMap.values()); } } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index d83af601428..1b54090357e 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1819,6 +1819,11 @@ public final void setChosenNumber(final int i) { view.updateChosenNumber(this); } + public final void clearChosenNumber() { + chosenNumber = null; + view.clearChosenNumber(); + } + public final Card getExiledWith() { return exiledWith; } diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index 9aa8fb65c57..dda2778bdd1 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -387,6 +387,9 @@ public String getChosenNumber() { void updateChosenNumber(Card c) { set(TrackableProperty.ChosenNumber, c.getChosenNumber().toString()); } + void clearChosenNumber() { + set(TrackableProperty.ChosenNumber, ""); + } public List getStoredRolls() { return get(TrackableProperty.StoredRolls); diff --git a/forge-gui/res/cardsfolder/upcoming/the_toymakers_trap.txt b/forge-gui/res/cardsfolder/upcoming/the_toymakers_trap.txt new file mode 100644 index 00000000000..98fbdc1e973 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/the_toymakers_trap.txt @@ -0,0 +1,12 @@ +Name:The Toymaker's Trap +ManaCost:2 B +Types:Enchantment +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigChooseNumber | TriggerDescription$ At the beginning of your upkeep, secretly choose a number between 1 and 5 that hasn't been chosen. If you do, an opponent guesses which number you chose, then you reveal the number you chose. If they guessed wrong, they lose life equal to the number they guessed and you draw a card. If they guessed right, sacrifice The Toymaker's Trap. +SVar:TrigChooseNumber:DB$ ChooseNumber | SecretlyChoose$ True | Min$ 1 | Max$ 5 | RemoveChoices$ Remembered | Guesser$ Opponent | GuessWrong$ DBLoseLife | GuessCorrect$ DBSac | RememberChosen$ True | SubAbility$ DBCleanup +SVar:DBLoseLife:DB$ LoseLife | Defined$ RememberedPlayer | LifeAmount$ Count$ChosenNumber | SubAbility$ DBDraw +SVar:DBDraw:DB$ Draw +SVar:DBSac:DB$ Sacrifice +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | Static$ True | ValidCard$ Card.Self | Execute$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +DeckHas:Ability$Sacrifice +Oracle:At the beginning of your upkeep, secretly choose a number between 1 and 5 that hasn't been chosen. If you do, an opponent guesses which number you chose, then you reveal the number you chose. If they guessed wrong, they lose life equal to the number they guessed and you draw a card. If they guessed right, sacrifice The Toymaker's Trap. diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 8c226a83fe8..197e0b947fc 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -1905,6 +1905,7 @@ lblChooseOne=Wähle eines #ChooseNumberEffect.java lblChooseNumber=Wähle eine Zahl lblPlayerChoseNum={0} wähle {1} +lblPlayerGuessedNum={0} hat {1} erraten #ChoosePlayerEffect.java lblChoosePlayer=Wähle einen Spieler #ChooseSourceEffect.java diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index b936a1959a3..346ee898fc8 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1910,6 +1910,7 @@ lblChooseOne=Choose one #ChooseNumberEffect.java lblChooseNumber=Choose a number lblPlayerChoseNum={0} chose {1} +lblPlayerGuessedNum={0} guessed {1} #ChoosePlayerEffect.java lblChoosePlayer=Choose a player #ChooseSourceEffect.java diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 94234bdb8c9..280639e83d7 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -1906,6 +1906,7 @@ lblChooseOne=Elige uno #ChooseNumberEffect.java lblChooseNumber=Elige un número lblPlayerChoseNum={0} eligió {1} +lblPlayerGuessedNum={0} adivinó {1} #ChoosePlayerEffect.java lblChoosePlayer=Elige un jugador #ChooseSourceEffect.java diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index b1aa1dadba5..6fb97b3d4fe 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -1342,7 +1342,7 @@ lblChooseOrderCards=Choisir l''ordre des cartes lblDelveHowManyCards=Creusez combien de cartes ? lblExileWhichCard=Exiler quelle carte({0}/{1}) ? lblDestroy=détruire -lblSelectUpToNumTargetToAction=S\u00e9lectionnez jusqu''\u00e0 %d {0}(s) \u00e0 {1}. +lblSelectUpToNumTargetToAction=Sélectionnez jusqu''à %d {0}(s) à {1}. lblSelectNumTargetToAction=Sélectionnez %d {0}(s) à {1}. lblHighestBidder=Enchérisseur le plus élevé lblUseTriggeredAbilityOf=Utiliser la capacité déclenchée de @@ -1876,7 +1876,7 @@ lblLookingCardIn=Regarder les cartes dans lblDoYouWantPlayCard=Voulez-vous jouer à {0} ? lblDoYouWantPlayCardTransformed=Voulez-vous jouer à {0} transformée? lblSelectCardFromPlayerZone=Sélectionnez une carte de {0} {1} -lblSelectUpToNumCardFromPlayerZone=S\u00e9lectionnez jusqu''\u00e0 {0} cartes de {1} {2} +lblSelectUpToNumCardFromPlayerZone=Sélectionnez jusqu''à {0} cartes de {1} {2} lblSelectCardsFromPlayerZone=Sélectionner les cartes de {0} {1} lblCancelSearchUpToSelectNumCards=Annuler la recherche ? Jusqu''à {0} carte(s) supplémentaire(s) peuvent être sélectionnées. #ChangeZoneAllEffect.java @@ -1909,6 +1909,7 @@ lblChooseOne=Choisissez-en un #ChooseNumberEffect.java lblChooseNumber=Choisissez un nombre lblPlayerChoseNum={0} a choisi {1} +lblPlayerGuessedNum={0} deviné {1} #ChoosePlayerEffect.java lblChoosePlayer=Choisir un joueur #ChooseSourceEffect.java diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 7176c4751d2..767ecc09758 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -1906,6 +1906,7 @@ lblChooseOne=Scegli uno #ChooseNumberEffect.java lblChooseNumber=Scegli un numero lblPlayerChoseNum={0} ha scelto {1} +lblPlayerGuessedNum={0} ha indovinato {1} #ChoosePlayerEffect.java lblChoosePlayer=Scegli un giocatore #ChooseSourceEffect.java diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index 86e1c6eecc4..e366f375e2e 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -1905,6 +1905,7 @@ lblChooseOne=以下から 1つを選ぶ #ChooseNumberEffect.java lblChooseNumber=数字を 1つ選ぶ lblPlayerChoseNum={0}が {1}を選んだ +lblPlayerGuessedNum={0}は {1}を推測しました #ChoosePlayerEffect.java lblChoosePlayer=プレイヤーを選ぶ #ChooseSourceEffect.java diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index 4a67fc2e812..aae2e6575b0 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -1967,6 +1967,7 @@ lblChooseOne=Escolha um #ChooseNumberEffect.java lblChooseNumber=Escolha um número lblPlayerChoseNum={0} escolheu {1} +lblPlayerGuessedNum={0} adivinhou {1} #ChoosePlayerEffect.java lblChoosePlayer=Escolha um jogador #ChooseSourceEffect.java diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 007c6b99f2d..10fd0cf6bcd 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -1910,6 +1910,7 @@ lblChooseOne=选择一个 #ChooseNumberEffect.java lblChooseNumber=选择一个数 lblPlayerChoseNum={0}已选择{1} +lblPlayerGuessedNum={0}猜了{1} #ChoosePlayerEffect.java lblChoosePlayer=选择一个牌手 #ChooseSourceEffect.java