From 184cb23739351086dd2e8844bcefa9b27cc52da6 Mon Sep 17 00:00:00 2001 From: dnutiu Date: Wed, 24 Jan 2024 14:10:52 +0200 Subject: [PATCH] fix dice parser allow adding dices --- src/bot/discord/commands/dice.py | 4 ++-- src/dice/dice.py | 2 ++ src/dice/parser.py | 10 ++++++---- src/dice/semantics.py | 5 +++-- tests/bot/discord/commands/test_dice.py | 12 ++++++++---- tests/dice/test_dice.py | 25 ++++++++++++++++++++++++- 6 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/bot/discord/commands/dice.py b/src/bot/discord/commands/dice.py index eb74fa2..4039ac3 100644 --- a/src/bot/discord/commands/dice.py +++ b/src/bot/discord/commands/dice.py @@ -19,7 +19,7 @@ class DiceCog(commands.Cog): for index, die in enumerate(die_result.dies): roll_fields.append( ( - f"- #{index+1} 🎲 ", + f"- #{index+1} 🎲 {die.type}{die.die_number}", f"Res: {die.result}, Mod: {die.modifier}, Rolls: {die.rolls}", ) ) @@ -47,7 +47,7 @@ class DiceCog(commands.Cog): die_result: DieExpressionResult = DiceRoller.roll(dice_expression) embed = disnake.Embed( - title="", + title=f"{die_result.total} !!", description=f"{dice_expression} = {die_result.total}", timestamp=datetime.now(), ) diff --git a/src/dice/dice.py b/src/dice/dice.py index 2b2f778..200364d 100644 --- a/src/dice/dice.py +++ b/src/dice/dice.py @@ -13,6 +13,7 @@ class DieRollResult: result: int modifier: int rolls: typing.List[int] + die_number: int type: str @@ -66,6 +67,7 @@ class DiceRoller: result=die.get("result"), rolls=die.get("rolls"), type=die.get("type"), + die_number=die.get("die_number"), ) ) return DieExpressionResult(total=result.get("total"), dies=dies) diff --git a/src/dice/parser.py b/src/dice/parser.py index ec9570f..9ef491d 100644 --- a/src/dice/parser.py +++ b/src/dice/parser.py @@ -8,12 +8,14 @@ DIE_GRAMMAR = """ @@grammar::Die @@whitespace :: None - start = die:die ~ {op:operator die:die} $; + start = die:die {op:operator die:die} $; die = [number_of_dies:number] die_type:die_type die_number:number [modifier:die_modifier]; - die_modifier = op:operator modifier:number; - - operator = '+' | '-' | 'adv' | 'dis'; + die_modifier = op:modifier_operator modifier:number; + + + modifier_operator = '+' | '-'; + operator = 'add' | 'sub' | 'adv' | 'dis'; die_type = 'd' | 'zd'; diff --git a/src/dice/semantics.py b/src/dice/semantics.py index ec06ff4..4f2f893 100644 --- a/src/dice/semantics.py +++ b/src/dice/semantics.py @@ -27,9 +27,9 @@ class DieSemantics: right = die_results.popleft() operator = operators.popleft() total = 0 - if operator == "+": + if operator == "add": total = left + right - if operator == "-": + if operator == "sub": total = left - right if operator == "adv": total = max(left, right) @@ -64,6 +64,7 @@ class DieSemantics: return { "result": max(sum(rolls) + die_modifier, minimum_value_for_die), + "die_number": die_number, "type": die_type, "rolls": rolls, "modifier": die_modifier, diff --git a/tests/bot/discord/commands/test_dice.py b/tests/bot/discord/commands/test_dice.py index ce70c70..231034e 100644 --- a/tests/bot/discord/commands/test_dice.py +++ b/tests/bot/discord/commands/test_dice.py @@ -7,12 +7,16 @@ def test_format_die_result_to_message(): DieExpressionResult( total=25, dies=[ - DieRollResult(result=10, modifier=5, rolls=[10], type="d"), - DieRollResult(result=15, modifier=0, rolls=[10, 5], type="d"), + DieRollResult( + result=10, modifier=5, rolls=[10], type="d", die_number=20 + ), + DieRollResult( + result=15, modifier=0, rolls=[10, 5], type="d", die_number=20 + ), ], ), ) assert message == [ - ("- #1 🎲 ", "Res: 10, Mod: 5, Rolls: [10]"), - ("- #2 🎲 ", "Res: 15, Mod: 0, Rolls: [10, 5]"), + ("- #1 🎲 d20", "Res: 10, Mod: 5, Rolls: [10]"), + ("- #2 🎲 d20", "Res: 15, Mod: 0, Rolls: [10, 5]"), ] diff --git a/tests/dice/test_dice.py b/tests/dice/test_dice.py index 8b86387..95f21c0 100644 --- a/tests/dice/test_dice.py +++ b/tests/dice/test_dice.py @@ -55,6 +55,29 @@ def test_die_roller_die_roll_simple(expression, range_min, range_max, dice_rolle assert range_min <= result <= range_max +@pytest.mark.parametrize( + "expression, range_min, range_max", + [ + # normal roll + ("d20 add d20", 1, 40), + ("d20+0 add d20", 1, 40), + ("d20+0 adv d20", 1, 20), + ("d20+0 adv 2d20", 1, 40), + ("d20+0 adv 2zd20", 1, 40), + ("d20+0 dis 2d12", 1, 20), + ("d20+0 add 2d20+2", 1, 62), + ("zd20+0 add 2d20+2", 1, 62), + ], +) +def test_die_roller_die_roll_compound_simple( + expression, range_min, range_max, dice_roller +): + # let the dies roll... + for i in range(100): + result = dice_roller.roll_simple(expression) + assert range_min <= result <= range_max + + @pytest.mark.parametrize( "expression, range_min, range_max", [ @@ -124,6 +147,6 @@ def test_die_roller_die_parsing_fail(expression, dice_roller): def test_die_roller_roll(dice_roller): for i in range(100): - result = dice_roller.roll("d20 + d20 adv d20+5 dis d12+3") + result = dice_roller.roll("d20 add d20 adv d20+5 dis d12+3") assert 1 <= result.total <= 15 assert len(result.dies) == 4