From 9b491912cc5e741d21cf3435ca434d3c0d8d06b0 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Sat, 21 Oct 2023 18:26:02 -0400 Subject: [PATCH 01/10] bamboozling_beeble.txt and Support --- .../java/forge/game/ability/AbilityKey.java | 1 + .../game/ability/effects/ReplaceEffect.java | 8 +++ .../game/ability/effects/RollDiceEffect.java | 63 ++++++++++++++----- .../forge/game/player/PlayerController.java | 1 + .../game/replacement/ReplaceRollDice.java | 41 ++++++++++++ .../game/replacement/ReplacementType.java | 1 + .../util/PlayerControllerForTests.java | 5 ++ .../res/cardsfolder/b/bamboozling_beeble.txt | 11 ++++ .../res/cardsfolder/b/barbarian_class.txt | 4 +- forge-gui/res/cardsfolder/p/pixie_guide.txt | 4 +- .../cardsfolder/w/wyll_blade_of_frontiers.txt | 4 +- forge-gui/res/languages/de-DE.properties | 1 + forge-gui/res/languages/en-US.properties | 1 + forge-gui/res/languages/es-ES.properties | 3 +- forge-gui/res/languages/fr-FR.properties | 1 + 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 + .../forge/player/PlayerControllerHuman.java | 5 ++ 20 files changed, 139 insertions(+), 19 deletions(-) create mode 100644 forge-game/src/main/java/forge/game/replacement/ReplaceRollDice.java create mode 100644 forge-gui/res/cardsfolder/b/bamboozling_beeble.txt diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java index 0db9ccaa4bc..96f598e30a1 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java @@ -73,6 +73,7 @@ public enum AbilityKey { Fizzle("Fizzle"), FoundSearchingLibrary("FoundSearchingLibrary"), Ignore("Ignore"), + IgnoreChosen("IgnoreChosen"), IsCombat("IsCombat"), // TODO confirm that this and IsCombatDamage can be merged IsCombatDamage("IsCombatDamage"), IsDamage("IsDamage"), diff --git a/forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java index 2eca5cf041d..0fcd15e4d15 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java @@ -3,6 +3,7 @@ package forge.game.ability.effects; import java.util.List; import java.util.Map; +import com.google.common.collect.Maps; import forge.game.GameObject; import forge.game.PlanarDice; import forge.game.ability.AbilityKey; @@ -12,6 +13,7 @@ import forge.game.card.Card; import forge.game.player.Player; import forge.game.replacement.ReplacementResult; import forge.game.spellability.SpellAbility; +import org.checkerframework.checker.units.qual.K; public class ReplaceEffect extends SpellAbilityEffect { @@ -44,6 +46,12 @@ public class ReplaceEffect extends SpellAbilityEffect { } } else if ("PlanarDice".equals(type)) { params.put(varName, PlanarDice.smartValueOf(varValue)); + } else if ("Map".equals(type)) { + Map m = Maps.newHashMap(); + for (Player key : AbilityUtils.getDefinedPlayers(card, sa.getParam("VarKey"), sa)) { + m.put(key, AbilityUtils.calculateAmount(card, varValue, sa)); + } + params.put(varName, m); } else { params.put(varName, AbilityUtils.calculateAmount(card, varValue, sa)); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java index 428c1f1e620..4986bd690d7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java @@ -2,7 +2,12 @@ package forge.game.ability.effects; import java.util.*; +import com.google.common.base.Optional; +import com.google.common.collect.Maps; +import forge.game.ability.AbilityFactory; +import forge.game.card.CounterType; import forge.game.event.GameEventRollDie; +import forge.game.replacement.ReplacementType; import org.apache.commons.lang3.StringUtils; import com.google.common.collect.Lists; @@ -37,11 +42,6 @@ public class RollDiceEffect extends SpellAbilityEffect { return sb.toString(); } - private static int getRollAdvange(final Player player) { - String str = "If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll."; - return player.getKeywords().getAmount(str); - } - /* (non-Javadoc) * @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility) */ @@ -68,11 +68,27 @@ public class RollDiceEffect extends SpellAbilityEffect { return rollDiceForPlayer(sa, player, amount, sides, 0, 0, null); } private static int rollDiceForPlayer(SpellAbility sa, Player player, int amount, int sides, int ignore, int modifier, List rollsResult) { + Map ignoreChosenMap = Maps.newHashMap(); + + final Map repParams = AbilityKey.mapFromAffected(player); + repParams.put(AbilityKey.Number, amount); + repParams.put(AbilityKey.Ignore, ignore); + repParams.put(AbilityKey.IgnoreChosen, ignoreChosenMap); + + switch (player.getGame().getReplacementHandler().run(ReplacementType.RollDice, repParams)) { + case NotReplaced: + break; + case Updated: { + amount = (int) repParams.get(AbilityKey.Number); + ignore = (int) repParams.get(AbilityKey.Ignore); + ignoreChosenMap = (Map) repParams.get(AbilityKey.IgnoreChosen); + break; + } + } + if (amount == 0) { return 0; } - int advantage = getRollAdvange(player); - amount += advantage; int total = 0; List naturalRolls = (rollsResult == null ? new ArrayList<>() : rollsResult); @@ -85,21 +101,38 @@ public class RollDiceEffect extends SpellAbilityEffect { total += roll; } - if (amount > 0) { - String message = Localizer.getInstance().getMessage("lblPlayerRolledResult", player, StringUtils.join(naturalRolls, ", ")); - player.getGame().getAction().notifyOfValue(sa, player, message, null); - } - naturalRolls.sort(null); + List ignored = new ArrayList<>(); // Ignore lowest rolls - advantage += ignore; - if (advantage > 0) { - for (int i = advantage - 1; i >= 0; --i) { + if (ignore > 0) { + for (int i = ignore - 1; i >= 0; --i) { total -= naturalRolls.get(i); + ignored.add(naturalRolls.get(i)); naturalRolls.remove(i); } } + // Player chooses to ignore rolls + for (Player chooser : ignoreChosenMap.keySet()) { + for (int ig = 0; ig < ignoreChosenMap.get(chooser); ig++) { + Integer ign = chooser.getController().chooseRollToIgnore(naturalRolls); + total -= ign; + ignored.add(ign); + naturalRolls.remove(ign); + } + } + + //Notify of results + if (amount > 0) { + StringBuilder sb = new StringBuilder(); + sb.append(Localizer.getInstance().getMessage("lblPlayerRolledResult", player, + StringUtils.join(naturalRolls, ", "))); + if (!ignored.isEmpty()) { + sb.append("\r\n").append(Localizer.getInstance().getMessage("lblIgnoredRolls", + StringUtils.join(ignored, ", "))); + } + player.getGame().getAction().notifyOfValue(sa, player, sb.toString(), null); + } List rolls = Lists.newArrayList(); int oddResults = 0; 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..cb04526f753 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerController.java +++ b/forge-game/src/main/java/forge/game/player/PlayerController.java @@ -188,6 +188,7 @@ public abstract class PlayerController { } public abstract PlanarDice choosePDRollToIgnore(List rolls); + public abstract Integer chooseRollToIgnore(List rolls); public abstract Object vote(SpellAbility sa, String prompt, List options, ListMultimap votes, Player forPlayer); diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceRollDice.java b/forge-game/src/main/java/forge/game/replacement/ReplaceRollDice.java new file mode 100644 index 00000000000..4897ca15fb8 --- /dev/null +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceRollDice.java @@ -0,0 +1,41 @@ +package forge.game.replacement; + +import forge.game.ability.AbilityKey; +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; + +import java.util.Map; + +public class ReplaceRollDice extends ReplacementEffect { + + /** + * Instantiates a new replace roll planar dice. + * + * @param params the params + * @param host the host + */ + public ReplaceRollDice(final Map params, final Card host, final boolean intrinsic) { + super(params, host, intrinsic); + } + + /* (non-Javadoc) + * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) + */ + @Override + public boolean canReplace(Map runParams) { + if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Affected))) { + return false; + } + return true; + } + + /* (non-Javadoc) + * @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.Map, forge.card.spellability.SpellAbility) + */ + @Override + public void setReplacingObjects(Map runParams, SpellAbility sa) { + sa.setReplacingObject(AbilityKey.Number, runParams.get(AbilityKey.Number)); + sa.setReplacingObject(AbilityKey.Ignore, runParams.get(AbilityKey.Ignore)); + sa.setReplacingObject(AbilityKey.IgnoreChosen, runParams.get(AbilityKey.IgnoreChosen)); + } +} diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java index 2461d522b80..0c1b1e410b5 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java @@ -38,6 +38,7 @@ public enum ReplacementType { ProduceMana(ReplaceProduceMana.class), Proliferate(ReplaceProliferate.class), RemoveCounter(ReplaceRemoveCounter.class), + RollDice(ReplaceRollDice.class), RollPlanarDice(ReplaceRollPlanarDice.class), Scry(ReplaceScry.class), SetInMotion(ReplaceSetInMotion.class), 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..7d59c7f79b8 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 @@ -495,6 +495,11 @@ public class PlayerControllerForTests extends PlayerController { return Aggregates.random(rolls); } + @Override + public Integer chooseRollToIgnore(List rolls) { + return Aggregates.random(rolls); + } + @Override public Object vote(SpellAbility sa, String prompt, List options, ListMultimap votes, Player forPlayer) { return chooseItem(options); diff --git a/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt b/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt new file mode 100644 index 00000000000..88518121b45 --- /dev/null +++ b/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt @@ -0,0 +1,11 @@ +Name:Bamboozling Beeble +ManaCost:U +Types:Creature Beeble +PT:1/1 +K:Protection from Robots +A:AB$ Effect | Cost$ 1 T | ValidTgts$ Player | ReplacementEffects$ RigRoll | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SpellDescription$ The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. +SVar:RigRoll:Event$ RollDice | ValidPlayer$ Player.IsRemembered | ReplaceWith$ PlusRoll | Description$ The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. +SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreRoll +SVar:IgnoreRoll:DB$ ReplaceEffect | VarName$ IgnoreChosen | VarType$ Map | VarKey$ You | VarValue$ 1 | SubAbility$ DBExileEffect +SVar:DBExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +Oracle:Protection from Robots\n{1}, {T}: The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. diff --git a/forge-gui/res/cardsfolder/b/barbarian_class.txt b/forge-gui/res/cardsfolder/b/barbarian_class.txt index e31c394d41b..e7f8b0954eb 100644 --- a/forge-gui/res/cardsfolder/b/barbarian_class.txt +++ b/forge-gui/res/cardsfolder/b/barbarian_class.txt @@ -1,7 +1,9 @@ Name:Barbarian Class ManaCost:R Types:Enchantment Class -S:Mode$ Continuous | Affected$ You | AddKeyword$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. | Description$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +R:Event$ RollDice | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreLowest +SVar:IgnoreLowest:DB$ ReplaceEffect | VarName$ Ignore | VarValue$ ReplaceCount$Ignore/Plus.1 K:Class:2:1 R:AddTrigger$ TriggerRoll SVar:TriggerRoll:Mode$ RolledDieOnce | TriggerZones$ Battlefield | ValidPlayer$ You | Execute$ TrigPump | Secondary$ True | TriggerDescription$ Whenever you roll one or more dice, target creature you control gets +2/+0 and gains menace until end of turn. SVar:TrigPump:DB$ Pump | ValidTgts$ Creature.YouCtrl | NumAtt$ 2 | KW$ Menace diff --git a/forge-gui/res/cardsfolder/p/pixie_guide.txt b/forge-gui/res/cardsfolder/p/pixie_guide.txt index ff3345eb4a4..ce09901ce1e 100644 --- a/forge-gui/res/cardsfolder/p/pixie_guide.txt +++ b/forge-gui/res/cardsfolder/p/pixie_guide.txt @@ -3,5 +3,7 @@ ManaCost:1 U Types:Creature Faerie PT:1/3 K:Flying -S:Mode$ Continuous | Affected$ You | AddKeyword$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. | Description$ Grant an Advantage — If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +R:Event$ RollDice | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ Grant an Advantage — If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreLowest +SVar:IgnoreLowest:DB$ ReplaceEffect | VarName$ Ignore | VarValue$ ReplaceCount$Ignore/Plus.1 Oracle:Flying\nGrant an Advantage — If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. diff --git a/forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt b/forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt index 09d82a0d8ec..c136d2b6c33 100644 --- a/forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt +++ b/forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt @@ -2,7 +2,9 @@ Name:Wyll, Blade of Frontiers ManaCost:1 R Types:Legendary Creature Human Warlock PT:1/1 -S:Mode$ Continuous | Affected$ You | AddKeyword$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. | Description$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +R:Event$ RollDice | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreLowest +SVar:IgnoreLowest:DB$ ReplaceEffect | VarName$ Ignore | VarValue$ ReplaceCount$Ignore/Plus.1 T:Mode$ RolledDieOnce | TriggerZones$ Battlefield | ValidPlayer$ You | Execute$ TrigPut | TriggerDescription$ Whenever you roll one or more dice, put a +1/+1 counter on CARDNAME. SVar:TrigPut:DB$ PutCounter | CounterType$ P1P1 K:Choose a Background diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index cd77379e798..46d1732d59f 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -2054,6 +2054,7 @@ lblDoYouWantRepeatProcessAgain=Möchtest du den Vorgang wiederholen? lblDoYouWantRevealYourHand=Möchtest du deine Handkarten offen vorzeigen? #RollDiceEffect.java lblPlayerRolledResult={0} würfelt {1} +lblIgnoredRolls=Ignorierte Würfelwürfe: {0} #RollPlanarDiceEffect.java lblPlanarDiceResult=Ergebnis Weltenwürfel: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index ffa8f4e1200..53788329c94 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -2059,6 +2059,7 @@ lblDoYouWantRepeatProcessAgain=Do you want to repeat this process again? lblDoYouWantRevealYourHand=Do you want to reveal your hand? #RollDiceEffect.java lblPlayerRolledResult={0} rolled {1} +lblIgnoredRolls=Ignored rolls: {0} #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 53a52fd103f..85244d13e21 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -2055,8 +2055,9 @@ lblDoYouWantRepeatProcessAgain=¿Quiere repetir este proceso de nuevo? lblDoYouWantRevealYourHand=¿Quieres descubrir tu mano? #RollDiceEffect.java lblPlayerRolledResult={0} lanzó {1} +lblIgnoredRolls=Dados ignorados: {0} #RollPlanarDiceEffect.java -lblPlanarDiceResult=Planar dice result: {0} +lblPlanarDiceResult=Resultado de los dados planares: {0} #SacrificeEffect.java lblDoYouWantPayEcho=¿Quieres pagar Eco lblPayEcho=Pagar Eco diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index cfed0b20c91..4a0341bcca7 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -2059,6 +2059,7 @@ lblDoYouWantRepeatProcessAgain=Voulez-vous répéter ce processus à nouveau ? lblDoYouWantRevealYourHand=Voulez-vous révéler votre main ? #RollDiceEffect.java lblPlayerRolledResult={0} a lancé {1} +lblIgnoredRolls=Rouleaux ignorés: {0} #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 34127d963ec..56cec6179b1 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -2055,6 +2055,7 @@ lblDoYouWantRepeatProcessAgain=Vuoi ripetere nuovamente questo procedimento? lblDoYouWantRevealYourHand=Vuoi rivelare la tua mano? #RollDiceEffect.java lblPlayerRolledResult={0} ha ottenuto {1} col dado +lblIgnoredRolls=Tiri ignorati: {0} #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index 8ed396820c4..7ae43f563d3 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -2054,6 +2054,7 @@ lblDoYouWantRepeatProcessAgain=この手順をもう一度しますか? lblDoYouWantRevealYourHand=手札を公開しますか? #RollDiceEffect.java lblPlayerRolledResult={0}が {1}をロールしました +lblIgnoredRolls=無視されたサイコロロール: {0} #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index 3237ff24dbf..bbc87b8cf2e 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -2116,6 +2116,7 @@ lblDoYouWantRepeatProcessAgain=Quer repetir este processo novamente? lblDoYouWantRevealYourHand=Você quer revelar sua mão? #RollDiceEffect.java lblPlayerRolledResult={0} tirou {1} +lblIgnoredRolls=Rolos ignorados: {0} #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 00b05dfe7b7..cbf2c6ebb25 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -2059,6 +2059,7 @@ lblDoYouWantRepeatProcessAgain=你是否想再次重复这个过程? lblDoYouWantRevealYourHand=你想展示你的手牌吗? #RollDiceEffect.java lblPlayerRolledResult={0}掷骰结果为{1} +lblIgnoredRolls=忽略的卷: {0} #RollPlanarDiceEffect.java lblPlanarDiceResult=时空骰子点数: {0} #SacrificeEffect.java diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index df9d7c2baae..162cb748e7a 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -1413,6 +1413,11 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont return getGui().one(Localizer.getInstance().getMessage("lblChooseRollIgnore"), rolls); } + @Override + public Integer chooseRollToIgnore(List rolls) { + return getGui().one(Localizer.getInstance().getMessage("lblChooseRollIgnore"), rolls); + } + @Override public Object vote(final SpellAbility sa, final String prompt, final List options, final ListMultimap votes, Player forPlayer) { From 28ff7020e879a1913e6fe3dd324711eae4a84736 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Sat, 21 Oct 2023 18:37:47 -0400 Subject: [PATCH 02/10] PlayerControllerAi.chooseRollToIgnore --- forge-ai/src/main/java/forge/ai/PlayerControllerAi.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index b9e0a3afb10..eb258ee1a5f 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -588,6 +588,12 @@ public class PlayerControllerAi extends PlayerController { return Aggregates.random(rolls); } + @Override + public Integer chooseRollToIgnore(List rolls) { + //TODO create AI logic for this + return Aggregates.random(rolls); + } + @Override public boolean mulliganKeepHand(Player firstPlayer, int cardsToReturn) { return !ComputerUtil.wantMulligan(player, cardsToReturn); From 0e36de674e3b6467305e44048c67137041beeec0 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Sat, 21 Oct 2023 18:51:47 -0400 Subject: [PATCH 03/10] RemoveDeck:All for now --- forge-gui/res/cardsfolder/b/bamboozling_beeble.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt b/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt index 88518121b45..3901b6d6993 100644 --- a/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt +++ b/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt @@ -8,4 +8,5 @@ SVar:RigRoll:Event$ RollDice | ValidPlayer$ Player.IsRemembered | ReplaceWith$ P SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreRoll SVar:IgnoreRoll:DB$ ReplaceEffect | VarName$ IgnoreChosen | VarType$ Map | VarKey$ You | VarValue$ 1 | SubAbility$ DBExileEffect SVar:DBExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile +AI:RemoveDeck:All Oracle:Protection from Robots\n{1}, {T}: The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. From d983f0d833f39cff067f7ed0de6e649824df0315 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Sat, 21 Oct 2023 18:53:07 -0400 Subject: [PATCH 04/10] cleanup imports --- .../game/ability/effects/ReplaceEffect.java | 2 -- .../game/ability/effects/RollDiceEffect.java | 17 ++++++----------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java index 0fcd15e4d15..26802697ab7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ReplaceEffect.java @@ -13,8 +13,6 @@ import forge.game.card.Card; import forge.game.player.Player; import forge.game.replacement.ReplacementResult; import forge.game.spellability.SpellAbility; -import org.checkerframework.checker.units.qual.K; - public class ReplaceEffect extends SpellAbilityEffect { diff --git a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java index 4986bd690d7..35208145014 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java @@ -1,27 +1,22 @@ package forge.game.ability.effects; -import java.util.*; - -import com.google.common.base.Optional; -import com.google.common.collect.Maps; -import forge.game.ability.AbilityFactory; -import forge.game.card.CounterType; -import forge.game.event.GameEventRollDie; -import forge.game.replacement.ReplacementType; -import org.apache.commons.lang3.StringUtils; - import com.google.common.collect.Lists; - +import com.google.common.collect.Maps; import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; +import forge.game.event.GameEventRollDie; import forge.game.player.Player; import forge.game.player.PlayerCollection; +import forge.game.replacement.ReplacementType; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; import forge.util.Localizer; import forge.util.MyRandom; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; public class RollDiceEffect extends SpellAbilityEffect { From 50d41552eae6f5c2cfcdf818ef464f7cfea8fbe4 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Sat, 21 Oct 2023 22:30:52 -0400 Subject: [PATCH 05/10] centaur_of_attention.txt and support --- .../java/forge/game/ability/AbilityUtils.java | 21 ++++++++++++++ .../game/ability/effects/RollDiceEffect.java | 28 +++++++++++++++++-- .../src/main/java/forge/game/card/Card.java | 26 +++++++++++++++++ .../main/java/forge/game/card/CardView.java | 7 +++++ .../forge/trackable/TrackableProperty.java | 1 + .../cardsfolder/c/centaur_of_attention.txt | 11 ++++++++ .../java/forge/gui/card/CardDetailUtil.java | 8 ++++++ 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 forge-gui/res/cardsfolder/c/centaur_of_attention.txt diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index ed79ced4e5b..e4c7312dd92 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -2625,6 +2625,27 @@ public class AbilityUtils { return doXMath(game.getStack().getMaxDistinctSources(), expr, c, ctb); } + if (sq[0].equals("MaxSameStoredRolls")) { + int max = 0; + List rolls = c.getStoredRolls(); + if (rolls != null) { + rolls.sort(null); + for (int i = 0; i < rolls.size(); i++) { + Integer num = rolls.get(i); + int counter = 0; + for (Integer roll : rolls) { + if (num.equals(roll)) { + counter++; + } + } + if (counter > max) { + max = counter; + } + } + } + return doXMath(max, expr, c, ctb); + } + //Count$Random.. if (sq[0].equals("Random")) { int min = calculateAmount(c, sq[1], ctb); diff --git a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java index 35208145014..cbcc2fbe37d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java @@ -12,6 +12,7 @@ import forge.game.player.PlayerCollection; import forge.game.replacement.ReplacementType; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; +import forge.util.CardTranslation; import forge.util.Localizer; import forge.util.MyRandom; import org.apache.commons.lang3.StringUtils; @@ -205,6 +206,9 @@ public class RollDiceEffect extends SpellAbilityEffect { List rolls = new ArrayList<>(); int total = rollDiceForPlayer(sa, player, amount, sides, ignore, modifier, rolls); + if (sa.hasParam("StoreResults")) { + host.setStoredRolls(rolls); + } if (sa.hasParam("ResultSVar")) { sa.setSVar(sa.getParam("ResultSVar"), Integer.toString(total)); } @@ -263,8 +267,19 @@ public class RollDiceEffect extends SpellAbilityEffect { List results = new ArrayList<>(playersToRoll.size()); for (Player player : playersToRoll) { - int result = rollDice(sa, player, amount, sides); - results.add(result); + List toReroll = Lists.newArrayList(); + if (sa.hasParam("RerollResults")) { + for (Integer storedResult : host.getStoredRolls()) { + if (player.getController().confirmAction(sa, null, + Localizer.getInstance().getMessage("lblRerollResult", storedResult), null)) { + toReroll.add(storedResult); + } + } + rerollDice(sa, host, player, sides, toReroll); + } else { + int result = rollDice(sa, player, amount, sides); + results.add(result); + } } if (rememberHighest) { int highest = 0; @@ -280,4 +295,13 @@ public class RollDiceEffect extends SpellAbilityEffect { } } } + + private void rerollDice(SpellAbility sa, Card host, Player roller, int sides, List toReroll) { + Map replaceMap = Maps.newHashMap(); + for (Integer old : toReroll) { + int newRoll = rollDice(sa, roller, 1, sides); + replaceMap.put(old, newRoll); + } + host.replaceStoredRoll(replaceMap); + } } 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 c8da2f8b259..106bdca8524 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -189,6 +189,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { private final Set rememberedObjects = Sets.newLinkedHashSet(); private Map flipResult; + private List storedRolls; private final Map assignedDamageMap = Maps.newTreeMap(); @@ -1279,6 +1280,31 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } } + public final List getStoredRolls() { + return storedRolls; + } + public final List getStoredRollsForView() { + List forView = new ArrayList<>(); + for (Integer i : storedRolls) { + forView.add(String.valueOf(i)); + } + return forView; + } + public final void setStoredRolls(final List results) { + if (storedRolls == null) { + storedRolls = Lists.newArrayList(); + } + storedRolls = results; + view.updateStoredRolls(this); + } + public final void replaceStoredRoll(final Map replaceMap) { + for (Integer oldValue : replaceMap.keySet()) { + storedRolls.remove(oldValue); + storedRolls.add(replaceMap.get(oldValue)); + } + view.updateStoredRolls(this); + } + public final String getFlipResult(final Player flipper) { if (flipResult == null) { return null; 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 34c01c66426..29153501c6c 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -388,6 +388,13 @@ public class CardView extends GameEntityView { set(TrackableProperty.ChosenNumber, c.getChosenNumber().toString()); } + public List getStoredRolls() { + return get(TrackableProperty.StoredRolls); + } + void updateStoredRolls(Card c) { + set(TrackableProperty.StoredRolls, c.getStoredRollsForView()); + } + public List getChosenColors() { return get(TrackableProperty.ChosenColors); } diff --git a/forge-game/src/main/java/forge/trackable/TrackableProperty.java b/forge-game/src/main/java/forge/trackable/TrackableProperty.java index ef7ff1a198d..8502a64c8e5 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableProperty.java +++ b/forge-game/src/main/java/forge/trackable/TrackableProperty.java @@ -66,6 +66,7 @@ public enum TrackableProperty { ChosenColors(TrackableTypes.StringListType), ChosenCards(TrackableTypes.CardViewCollectionType), ChosenNumber(TrackableTypes.StringType), + StoredRolls(TrackableTypes.StringListType), ChosenPlayer(TrackableTypes.PlayerViewType), ProtectingPlayer(TrackableTypes.PlayerViewType), ChosenDirection(TrackableTypes.EnumType(Direction.class)), diff --git a/forge-gui/res/cardsfolder/c/centaur_of_attention.txt b/forge-gui/res/cardsfolder/c/centaur_of_attention.txt new file mode 100644 index 00000000000..d3b024fecd1 --- /dev/null +++ b/forge-gui/res/cardsfolder/c/centaur_of_attention.txt @@ -0,0 +1,11 @@ +Name:Centaur of Attention +ManaCost:3 G G +Types:Creature Centaur Performer +PT:3/3 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRollDice | TriggerDescription$ When CARDNAME enters the battlefield, roll five six-sided dice and store those results on it. +SVar:TrigRollDice:DB$ RollDice | Amount$ 5 | StoreResults$ True +T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | Execute$ TrigReroll | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of combat on your turn, you may reroll any number of CARDNAME's stored results. +SVar:TrigReroll:DB$ RollDice | RerollResults$ True +S:Mode$ Continuous | Affected$ Card.Self | AddPower$ X | AddToughness$ X | Description$ Centaur of Attention gets +X/+X, where X is the greatest number of stored results on it of the same value. +SVar:X:Count$MaxSameStoredRolls +Oracle:When Centaur of Attention enters the battlefield, roll five six-sided dice and store those results on it.\nAt the beginning of combat on your turn, you may reroll any number of Centaur of Attention's stored results.\nCentaur of Attention gets +X/+X, where X is the greatest number of stored results on it of the same value. diff --git a/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java b/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java index d59afb7868c..b7229c45bd1 100644 --- a/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java +++ b/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java @@ -484,6 +484,14 @@ public class CardDetailUtil { area.append("(chosen number: ").append(card.getChosenNumber()).append(")"); } + // stored dice results + if (card.getStoredRolls() != null) { + if (area.length() != 0) { + area.append("\n"); + } + area.append("(stored dice results: ").append(StringUtils.join(card.getStoredRolls(), ", ")); + } + // chosen player if (card.getChosenPlayer() != null) { if (area.length() != 0) { From 037c8cc3c6ef86160c9a81cc7f19db1895a1f750 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Sun, 22 Oct 2023 09:23:33 -0400 Subject: [PATCH 06/10] centaur_of_attention.txt cleanup --- .../java/forge/game/ability/AbilityUtils.java | 38 ++++++++++++++----- .../game/ability/effects/RollDiceEffect.java | 21 +++++----- .../src/main/java/forge/game/card/Card.java | 1 + 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 | 1 + forge-gui/res/languages/it-IT.properties | 1 + forge-gui/res/languages/ja-JP.properties | 3 +- forge-gui/res/languages/pt-BR.properties | 1 + forge-gui/res/languages/zh-CN.properties | 1 + .../java/forge/gui/card/CardDetailUtil.java | 1 + 12 files changed, 51 insertions(+), 20 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index e4c7312dd92..24292793666 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -2629,19 +2629,39 @@ public class AbilityUtils { int max = 0; List rolls = c.getStoredRolls(); if (rolls != null) { - rolls.sort(null); + int lastNum = 1; + int tally = 0; for (int i = 0; i < rolls.size(); i++) { - Integer num = rolls.get(i); - int counter = 0; - for (Integer roll : rolls) { - if (num.equals(roll)) { - counter++; + Integer roll = rolls.get(i); + if (roll.equals(lastNum)) { + tally++; + } else { + if (tally > max) { + max = tally; } - } - if (counter > max) { - max = counter; + lastNum = roll; + tally = 1; } } + /** + for (int i = 0; i < rolls.size(); i++) { + Integer num = rolls.get(i); + if (!num.equals(lastNum)) { + lastNum = num; + int counter = 0; + for (int n = i; n < rolls.size(); n++) { + Integer roll = rolls.get(n); + if (num.equals(roll)) { + counter++; + } else if (num < roll) { + break; + } + } + if (counter > max) { + max = counter; + } + } + }**/ } return doXMath(max, expr, c, ctb); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java index cbcc2fbe37d..8dd6210b749 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java @@ -12,7 +12,6 @@ import forge.game.player.PlayerCollection; import forge.game.replacement.ReplacementType; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; -import forge.util.CardTranslation; import forge.util.Localizer; import forge.util.MyRandom; import org.apache.commons.lang3.StringUtils; @@ -267,15 +266,8 @@ public class RollDiceEffect extends SpellAbilityEffect { List results = new ArrayList<>(playersToRoll.size()); for (Player player : playersToRoll) { - List toReroll = Lists.newArrayList(); if (sa.hasParam("RerollResults")) { - for (Integer storedResult : host.getStoredRolls()) { - if (player.getController().confirmAction(sa, null, - Localizer.getInstance().getMessage("lblRerollResult", storedResult), null)) { - toReroll.add(storedResult); - } - } - rerollDice(sa, host, player, sides, toReroll); + rerollDice(sa, host, player, sides); } else { int result = rollDice(sa, player, amount, sides); results.add(result); @@ -296,7 +288,16 @@ public class RollDiceEffect extends SpellAbilityEffect { } } - private void rerollDice(SpellAbility sa, Card host, Player roller, int sides, List toReroll) { + private void rerollDice(SpellAbility sa, Card host, Player roller, int sides) { + List toReroll = Lists.newArrayList(); + + for (Integer storedResult : host.getStoredRolls()) { + if (roller.getController().confirmAction(sa, null, + Localizer.getInstance().getMessage("lblRerollResult", storedResult), null)) { + toReroll.add(storedResult); + } + } + Map replaceMap = Maps.newHashMap(); for (Integer old : toReroll) { int newRoll = rollDice(sa, roller, 1, sides); 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 106bdca8524..5d779d38763 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1302,6 +1302,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { storedRolls.remove(oldValue); storedRolls.add(replaceMap.get(oldValue)); } + storedRolls.sort(null); view.updateStoredRolls(this); } diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 46d1732d59f..10ffc3e333c 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -2055,6 +2055,7 @@ lblDoYouWantRevealYourHand=Möchtest du deine Handkarten offen vorzeigen? #RollDiceEffect.java lblPlayerRolledResult={0} würfelt {1} lblIgnoredRolls=Ignorierte Würfelwürfe: {0} +lblRerollResult={0} neu auswürfeln? #RollPlanarDiceEffect.java lblPlanarDiceResult=Ergebnis Weltenwürfel: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 53788329c94..94b2d20ed6f 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -2060,6 +2060,7 @@ lblDoYouWantRevealYourHand=Do you want to reveal your hand? #RollDiceEffect.java lblPlayerRolledResult={0} rolled {1} lblIgnoredRolls=Ignored rolls: {0} +lblRerollResult=Reroll {0}? #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 85244d13e21..c8ca80f9a10 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -2056,6 +2056,7 @@ lblDoYouWantRevealYourHand=¿Quieres descubrir tu mano? #RollDiceEffect.java lblPlayerRolledResult={0} lanzó {1} lblIgnoredRolls=Dados ignorados: {0} +lblRerollResult=¿Volver a tirar {0}? #RollPlanarDiceEffect.java lblPlanarDiceResult=Resultado de los dados planares: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index 4a0341bcca7..e187f531698 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -2060,6 +2060,7 @@ lblDoYouWantRevealYourHand=Voulez-vous révéler votre main ? #RollDiceEffect.java lblPlayerRolledResult={0} a lancé {1} lblIgnoredRolls=Rouleaux ignorés: {0} +lblRerollResult=Relancez {0} ? #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 56cec6179b1..3aa5c4ee96b 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -2056,6 +2056,7 @@ lblDoYouWantRevealYourHand=Vuoi rivelare la tua mano? #RollDiceEffect.java lblPlayerRolledResult={0} ha ottenuto {1} col dado lblIgnoredRolls=Tiri ignorati: {0} +lblRerollResult=Rilanciare {0}? #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index 7ae43f563d3..2747a09d639 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -2055,8 +2055,9 @@ lblDoYouWantRevealYourHand=手札を公開しますか? #RollDiceEffect.java lblPlayerRolledResult={0}が {1}をロールしました lblIgnoredRolls=無視されたサイコロロール: {0} +lblRerollResult={0}リロール? #RollPlanarDiceEffect.java -lblPlanarDiceResult=Planar dice result: {0} +lblPlanarDiceResult=平面サイコロの結果:{0} #SacrificeEffect.java lblDoYouWantPayEcho=エコーコストを支払いますか: lblPayEcho=エコーコストを支払います diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index bbc87b8cf2e..0e4fea5cf06 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -2117,6 +2117,7 @@ lblDoYouWantRevealYourHand=Você quer revelar sua mão? #RollDiceEffect.java lblPlayerRolledResult={0} tirou {1} lblIgnoredRolls=Rolos ignorados: {0} +lblRerollResult=Rolar {0}? #RollPlanarDiceEffect.java lblPlanarDiceResult=Planar dice result: {0} #SacrificeEffect.java diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index cbf2c6ebb25..e6b62d2134c 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -2060,6 +2060,7 @@ lblDoYouWantRevealYourHand=你想展示你的手牌吗? #RollDiceEffect.java lblPlayerRolledResult={0}掷骰结果为{1} lblIgnoredRolls=忽略的卷: {0} +lblRerollResult=重滚{0}? #RollPlanarDiceEffect.java lblPlanarDiceResult=时空骰子点数: {0} #SacrificeEffect.java diff --git a/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java b/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java index b7229c45bd1..9d83549487b 100644 --- a/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java +++ b/forge-gui/src/main/java/forge/gui/card/CardDetailUtil.java @@ -490,6 +490,7 @@ public class CardDetailUtil { area.append("\n"); } area.append("(stored dice results: ").append(StringUtils.join(card.getStoredRolls(), ", ")); + area.append(")"); } // chosen player From f10ac58bb658c8f191f0fda8c3b965e458ea75ff Mon Sep 17 00:00:00 2001 From: Northmoc Date: Tue, 24 Oct 2023 01:07:46 -0400 Subject: [PATCH 07/10] remove unneeded --- .../java/forge/game/ability/AbilityUtils.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 24292793666..b5bd5ca9647 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -2643,25 +2643,6 @@ public class AbilityUtils { tally = 1; } } - /** - for (int i = 0; i < rolls.size(); i++) { - Integer num = rolls.get(i); - if (!num.equals(lastNum)) { - lastNum = num; - int counter = 0; - for (int n = i; n < rolls.size(); n++) { - Integer roll = rolls.get(n); - if (num.equals(roll)) { - counter++; - } else if (num < roll) { - break; - } - } - if (counter > max) { - max = counter; - } - } - }**/ } return doXMath(max, expr, c, ctb); } From 0ac40475609948c0cfc017a725583f1434113120 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Wed, 25 Oct 2023 08:31:19 -0400 Subject: [PATCH 08/10] add ActiveZones to replacements --- forge-gui/res/cardsfolder/b/bamboozling_beeble.txt | 2 +- forge-gui/res/cardsfolder/b/barbarian_class.txt | 2 +- forge-gui/res/cardsfolder/p/pixie_guide.txt | 2 +- forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt b/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt index 3901b6d6993..9a373683779 100644 --- a/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt +++ b/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt @@ -4,7 +4,7 @@ Types:Creature Beeble PT:1/1 K:Protection from Robots A:AB$ Effect | Cost$ 1 T | ValidTgts$ Player | ReplacementEffects$ RigRoll | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SpellDescription$ The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. -SVar:RigRoll:Event$ RollDice | ValidPlayer$ Player.IsRemembered | ReplaceWith$ PlusRoll | Description$ The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. +SVar:RigRoll:Event$ RollDice | ActiveZones$ Command | ValidPlayer$ Player.IsRemembered | ReplaceWith$ PlusRoll | Description$ The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreRoll SVar:IgnoreRoll:DB$ ReplaceEffect | VarName$ IgnoreChosen | VarType$ Map | VarKey$ You | VarValue$ 1 | SubAbility$ DBExileEffect SVar:DBExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile diff --git a/forge-gui/res/cardsfolder/b/barbarian_class.txt b/forge-gui/res/cardsfolder/b/barbarian_class.txt index e7f8b0954eb..01a088c8a61 100644 --- a/forge-gui/res/cardsfolder/b/barbarian_class.txt +++ b/forge-gui/res/cardsfolder/b/barbarian_class.txt @@ -1,7 +1,7 @@ Name:Barbarian Class ManaCost:R Types:Enchantment Class -R:Event$ RollDice | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +R:Event$ RollDice | ActiveZones$ Battlefield | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreLowest SVar:IgnoreLowest:DB$ ReplaceEffect | VarName$ Ignore | VarValue$ ReplaceCount$Ignore/Plus.1 K:Class:2:1 R:AddTrigger$ TriggerRoll diff --git a/forge-gui/res/cardsfolder/p/pixie_guide.txt b/forge-gui/res/cardsfolder/p/pixie_guide.txt index ce09901ce1e..3e47190f97e 100644 --- a/forge-gui/res/cardsfolder/p/pixie_guide.txt +++ b/forge-gui/res/cardsfolder/p/pixie_guide.txt @@ -3,7 +3,7 @@ ManaCost:1 U Types:Creature Faerie PT:1/3 K:Flying -R:Event$ RollDice | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ Grant an Advantage — If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +R:Event$ RollDice | ActiveZones$ Battlefield | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ Grant an Advantage — If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreLowest SVar:IgnoreLowest:DB$ ReplaceEffect | VarName$ Ignore | VarValue$ ReplaceCount$Ignore/Plus.1 Oracle:Flying\nGrant an Advantage — If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. diff --git a/forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt b/forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt index c136d2b6c33..61925ad4b8b 100644 --- a/forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt +++ b/forge-gui/res/cardsfolder/w/wyll_blade_of_frontiers.txt @@ -2,7 +2,7 @@ Name:Wyll, Blade of Frontiers ManaCost:1 R Types:Legendary Creature Human Warlock PT:1/1 -R:Event$ RollDice | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. +R:Event$ RollDice | ActiveZones$ Battlefield | ValidPlayer$ You | ReplaceWith$ PlusRoll | Description$ If you would roll one or more dice, instead roll that many dice plus one and ignore the lowest roll. SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreLowest SVar:IgnoreLowest:DB$ ReplaceEffect | VarName$ Ignore | VarValue$ ReplaceCount$Ignore/Plus.1 T:Mode$ RolledDieOnce | TriggerZones$ Battlefield | ValidPlayer$ You | Execute$ TrigPut | TriggerDescription$ Whenever you roll one or more dice, put a +1/+1 counter on CARDNAME. From ffe39bb40f55c734e6bb10937178925a3d0465f8 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Wed, 25 Oct 2023 16:01:52 -0400 Subject: [PATCH 09/10] improvements --- .../java/forge/game/ability/AbilityUtils.java | 16 +++++++--------- .../game/ability/effects/RollDiceEffect.java | 2 +- .../src/main/java/forge/game/card/Card.java | 5 +++-- .../res/cardsfolder/b/bamboozling_beeble.txt | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index b5bd5ca9647..420db29504b 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -2629,19 +2629,17 @@ public class AbilityUtils { int max = 0; List rolls = c.getStoredRolls(); if (rolls != null) { - int lastNum = 1; - int tally = 0; + int lastNum = 0; for (int i = 0; i < rolls.size(); i++) { Integer roll = rolls.get(i); if (roll.equals(lastNum)) { - tally++; - } else { - if (tally > max) { - max = tally; - } - lastNum = roll; - tally = 1; + continue; // no need to count instances of the same roll multiple times } + int tally = Collections.frequency(rolls, roll); + if (tally > max) { + max = tally; + } + lastNum = roll; } } return doXMath(max, expr, c, ctb); diff --git a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java index 8dd6210b749..a12c6629308 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java @@ -206,7 +206,7 @@ public class RollDiceEffect extends SpellAbilityEffect { int total = rollDiceForPlayer(sa, player, amount, sides, ignore, modifier, rolls); if (sa.hasParam("StoreResults")) { - host.setStoredRolls(rolls); + host.addStoredRolls(rolls); } if (sa.hasParam("ResultSVar")) { sa.setSVar(sa.getParam("ResultSVar"), Integer.toString(total)); 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 5d779d38763..b28e682aa48 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -1290,11 +1290,12 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } return forView; } - public final void setStoredRolls(final List results) { + public final void addStoredRolls(final List results) { if (storedRolls == null) { storedRolls = Lists.newArrayList(); } - storedRolls = results; + storedRolls.addAll(results); + storedRolls.sort(null); view.updateStoredRolls(this); } public final void replaceStoredRoll(final Map replaceMap) { diff --git a/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt b/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt index 9a373683779..3901b6d6993 100644 --- a/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt +++ b/forge-gui/res/cardsfolder/b/bamboozling_beeble.txt @@ -4,7 +4,7 @@ Types:Creature Beeble PT:1/1 K:Protection from Robots A:AB$ Effect | Cost$ 1 T | ValidTgts$ Player | ReplacementEffects$ RigRoll | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SpellDescription$ The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. -SVar:RigRoll:Event$ RollDice | ActiveZones$ Command | ValidPlayer$ Player.IsRemembered | ReplaceWith$ PlusRoll | Description$ The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. +SVar:RigRoll:Event$ RollDice | ValidPlayer$ Player.IsRemembered | ReplaceWith$ PlusRoll | Description$ The next time target player would roll one or more dice this turn, instead they roll that many dice plus one and you choose one of those rolls to ignore. SVar:PlusRoll:DB$ ReplaceEffect | VarName$ Number | VarValue$ ReplaceCount$Number/Plus.1 | SubAbility$ IgnoreRoll SVar:IgnoreRoll:DB$ ReplaceEffect | VarName$ IgnoreChosen | VarType$ Map | VarKey$ You | VarValue$ 1 | SubAbility$ DBExileEffect SVar:DBExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile From 2a298f7aa61ea935e731818445e17a3e23878c78 Mon Sep 17 00:00:00 2001 From: Northmoc Date: Wed, 25 Oct 2023 18:34:02 -0400 Subject: [PATCH 10/10] tidy up MaxSameStoredRolls --- forge-game/src/main/java/forge/game/ability/AbilityUtils.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 420db29504b..4c312e9e919 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -2630,8 +2630,7 @@ public class AbilityUtils { List rolls = c.getStoredRolls(); if (rolls != null) { int lastNum = 0; - for (int i = 0; i < rolls.size(); i++) { - Integer roll = rolls.get(i); + for (Integer roll : rolls) { if (roll.equals(lastNum)) { continue; // no need to count instances of the same roll multiple times }