-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add percentile dice (d%) #35
Copy link
Copy link
Open
Labels
featureNew functionalityNew functionality
Description
Add d% as an alias for d100. The notation d% and 2d% should produce DiceNode with sides = Literal(100).
Currently d% throws a parse error because % after d is scanned as DICE + MODULO. With the Stage 2 foundation (#34), the lexer already emits DICE_PERCENT for d%. This issue covers the parser and test work.
Parser Changes
- NUD (prefix
d%): createDiceNode(Literal(1), Literal(100)) - LED (infix
2d%): createDiceNode(left, Literal(100)) getLeftBp:DICE_PERCENT→BP.DICE_LEFT(40)- No
getRightBpneeded — sides are always 100, no right-hand expression to parse
No new AST node type. Reuses DiceNode with synthetic sides = Literal(100).
Evaluator Changes
None. DiceNode with sides = 100 is already handled correctly by evalDice. Critical detection (result === 100 && 100 > 1) and fumble detection (result === 1) work naturally.
Expression/Rendered Output
expression: shows1d100(canonical form)notation: preservesd%(original input)rendered:1d100[42] = 42
Edge Cases
| Expression | Expected |
|---|---|
d% |
1d100 |
2d% |
2d100 |
D% |
1d100 (case-insensitive) |
d%+5 |
1d100 + 5 |
2d%kh1 |
Roll 2d100, keep highest |
(2)d% |
2d100 (computed count) |
d % 3 |
Error — whitespace breaks the d% token, producing DICE + MODULO |
d%% |
Error — d% consumed as DICE_PERCENT, then bare % is MODULO with no NUD |
10%3 |
Modulo (unchanged) — % after digit is still MODULO in the operator switch |
Test Plan
- Parser tests for AST structure:
d%,2d%,d%+5,2d%kh1,(2)d% - Evaluator tests with MockRNG: verify
sides = 100, total in[1, 100] - Integration tests via
roll():d%,2d%,d%+5 - Property test:
Nd% total is in [N, N*100] - Error tests:
d%%, standaloned%followed by invalid token
Drafted with AI assistance
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
featureNew functionalityNew functionality