roll-parser 3.0.0-beta.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/CHANGELOG.md +142 -9
  2. package/MIGRATION.md +219 -0
  3. package/README.md +1026 -154
  4. package/dist/cli/args.d.ts +1 -0
  5. package/dist/cli/args.d.ts.map +1 -1
  6. package/dist/cli/args.js +81 -0
  7. package/dist/cli/args.js.map +1 -0
  8. package/dist/cli/format.d.ts +15 -3
  9. package/dist/cli/format.d.ts.map +1 -1
  10. package/dist/cli/format.js +18 -0
  11. package/dist/cli/format.js.map +1 -0
  12. package/dist/cli/index.d.ts +3 -0
  13. package/dist/cli/index.d.ts.map +1 -1
  14. package/dist/cli/index.js +14 -0
  15. package/dist/cli/index.js.map +1 -0
  16. package/dist/cli/main.d.ts +36 -0
  17. package/dist/cli/main.d.ts.map +1 -0
  18. package/dist/cli/main.js +83 -0
  19. package/dist/cli/main.js.map +1 -0
  20. package/dist/errors.d.ts +332 -17
  21. package/dist/errors.d.ts.map +1 -1
  22. package/dist/errors.js +141 -0
  23. package/dist/errors.js.map +1 -0
  24. package/dist/evaluator/die.d.ts +27 -0
  25. package/dist/evaluator/die.d.ts.map +1 -0
  26. package/dist/evaluator/die.js +19 -0
  27. package/dist/evaluator/die.js.map +1 -0
  28. package/dist/evaluator/env.d.ts +89 -0
  29. package/dist/evaluator/env.d.ts.map +1 -0
  30. package/dist/evaluator/env.js +11 -0
  31. package/dist/evaluator/env.js.map +1 -0
  32. package/dist/evaluator/evaluator.d.ts +41 -75
  33. package/dist/evaluator/evaluator.d.ts.map +1 -1
  34. package/dist/evaluator/evaluator.js +914 -0
  35. package/dist/evaluator/evaluator.js.map +1 -0
  36. package/dist/evaluator/modifiers/compare.js +15 -0
  37. package/dist/evaluator/modifiers/compare.js.map +1 -0
  38. package/dist/evaluator/modifiers/crit-threshold.d.ts +57 -5
  39. package/dist/evaluator/modifiers/crit-threshold.d.ts.map +1 -1
  40. package/dist/evaluator/modifiers/crit-threshold.js +42 -0
  41. package/dist/evaluator/modifiers/crit-threshold.js.map +1 -0
  42. package/dist/evaluator/modifiers/die-bound.d.ts +29 -0
  43. package/dist/evaluator/modifiers/die-bound.d.ts.map +1 -0
  44. package/dist/evaluator/modifiers/die-bound.js +17 -0
  45. package/dist/evaluator/modifiers/die-bound.js.map +1 -0
  46. package/dist/evaluator/modifiers/explode.d.ts +13 -5
  47. package/dist/evaluator/modifiers/explode.d.ts.map +1 -1
  48. package/dist/evaluator/modifiers/explode.js +105 -0
  49. package/dist/evaluator/modifiers/explode.js.map +1 -0
  50. package/dist/evaluator/modifiers/flags.d.ts +47 -0
  51. package/dist/evaluator/modifiers/flags.d.ts.map +1 -0
  52. package/dist/evaluator/modifiers/flags.js +25 -0
  53. package/dist/evaluator/modifiers/flags.js.map +1 -0
  54. package/dist/evaluator/modifiers/keep-drop.d.ts +15 -29
  55. package/dist/evaluator/modifiers/keep-drop.d.ts.map +1 -1
  56. package/dist/evaluator/modifiers/keep-drop.js +82 -0
  57. package/dist/evaluator/modifiers/keep-drop.js.map +1 -0
  58. package/dist/evaluator/modifiers/reroll.d.ts +12 -4
  59. package/dist/evaluator/modifiers/reroll.d.ts.map +1 -1
  60. package/dist/evaluator/modifiers/reroll.js +68 -0
  61. package/dist/evaluator/modifiers/reroll.js.map +1 -0
  62. package/dist/evaluator/modifiers/sort.d.ts +5 -1
  63. package/dist/evaluator/modifiers/sort.d.ts.map +1 -1
  64. package/dist/evaluator/modifiers/sort.js +13 -0
  65. package/dist/evaluator/modifiers/sort.js.map +1 -0
  66. package/dist/evaluator/modifiers/success-count.d.ts +6 -7
  67. package/dist/evaluator/modifiers/success-count.d.ts.map +1 -1
  68. package/dist/evaluator/modifiers/success-count.js +25 -0
  69. package/dist/evaluator/modifiers/success-count.js.map +1 -0
  70. package/dist/index.d.ts +33 -11
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +12 -2560
  73. package/dist/index.js.map +1 -26
  74. package/dist/lexer/lexer.d.ts +50 -5
  75. package/dist/lexer/lexer.d.ts.map +1 -1
  76. package/dist/lexer/lexer.js +260 -0
  77. package/dist/lexer/lexer.js.map +1 -0
  78. package/dist/lexer/tokens.d.ts +31 -6
  79. package/dist/lexer/tokens.d.ts.map +1 -1
  80. package/dist/lexer/tokens.js +42 -0
  81. package/dist/lexer/tokens.js.map +1 -0
  82. package/dist/parser/ast.d.ts +324 -165
  83. package/dist/parser/ast.d.ts.map +1 -1
  84. package/dist/parser/ast.js +52 -0
  85. package/dist/parser/ast.js.map +1 -0
  86. package/dist/parser/guards.d.ts +106 -0
  87. package/dist/parser/guards.d.ts.map +1 -0
  88. package/dist/parser/guards.js +121 -0
  89. package/dist/parser/guards.js.map +1 -0
  90. package/dist/parser/parser.d.ts +118 -14
  91. package/dist/parser/parser.d.ts.map +1 -1
  92. package/dist/parser/parser.js +751 -0
  93. package/dist/parser/parser.js.map +1 -0
  94. package/dist/render.d.ts +95 -0
  95. package/dist/render.d.ts.map +1 -0
  96. package/dist/render.js +227 -0
  97. package/dist/render.js.map +1 -0
  98. package/dist/rng/mock.d.ts +73 -12
  99. package/dist/rng/mock.d.ts.map +1 -1
  100. package/dist/rng/mock.js +30 -0
  101. package/dist/rng/mock.js.map +1 -0
  102. package/dist/rng/seeded.d.ts +141 -9
  103. package/dist/rng/seeded.d.ts.map +1 -1
  104. package/dist/rng/seeded.js +138 -0
  105. package/dist/rng/seeded.js.map +1 -0
  106. package/dist/rng/types.d.ts +57 -0
  107. package/dist/rng/types.d.ts.map +1 -1
  108. package/dist/rng/types.js +2 -0
  109. package/dist/rng/types.js.map +1 -0
  110. package/dist/roll.d.ts +58 -28
  111. package/dist/roll.d.ts.map +1 -1
  112. package/dist/roll.js +8 -0
  113. package/dist/roll.js.map +1 -0
  114. package/dist/testing.d.ts +5 -4
  115. package/dist/testing.d.ts.map +1 -1
  116. package/dist/testing.js +2 -41
  117. package/dist/testing.js.map +1 -11
  118. package/dist/types.d.ts +349 -47
  119. package/dist/types.d.ts.map +1 -1
  120. package/dist/types.js +8 -0
  121. package/dist/types.js.map +1 -0
  122. package/dist/version.d.ts +2 -0
  123. package/dist/version.d.ts.map +1 -0
  124. package/dist/version.js +2 -0
  125. package/dist/version.js.map +1 -0
  126. package/package.json +93 -34
  127. package/src/cli/args.ts +66 -10
  128. package/src/cli/format.ts +37 -26
  129. package/src/cli/index.ts +27 -84
  130. package/src/cli/main.ts +129 -0
  131. package/src/errors.ts +480 -27
  132. package/src/evaluator/die.ts +51 -0
  133. package/src/evaluator/env.ts +105 -0
  134. package/src/evaluator/evaluator.ts +693 -434
  135. package/src/evaluator/modifiers/crit-threshold.ts +96 -14
  136. package/src/evaluator/modifiers/die-bound.ts +48 -0
  137. package/src/evaluator/modifiers/explode.ts +70 -62
  138. package/src/evaluator/modifiers/flags.ts +78 -0
  139. package/src/evaluator/modifiers/keep-drop.ts +129 -127
  140. package/src/evaluator/modifiers/reroll.ts +44 -56
  141. package/src/evaluator/modifiers/sort.ts +21 -2
  142. package/src/evaluator/modifiers/success-count.ts +24 -12
  143. package/src/index.ts +56 -35
  144. package/src/lexer/lexer.ts +107 -34
  145. package/src/lexer/tokens.ts +31 -6
  146. package/src/parser/ast.ts +333 -346
  147. package/src/parser/guards.ts +248 -0
  148. package/src/parser/parser.ts +419 -242
  149. package/src/render.ts +392 -0
  150. package/src/rng/mock.ts +74 -13
  151. package/src/rng/seeded.ts +299 -64
  152. package/src/rng/types.ts +57 -0
  153. package/src/roll.ts +64 -47
  154. package/src/testing.ts +5 -9
  155. package/src/types.ts +353 -46
  156. package/src/version.ts +2 -0
  157. package/dist/cli.js +0 -2608
  158. package/dist/cli.js.map +0 -28
  159. package/dist/evaluator/index.d.ts +0 -8
  160. package/dist/evaluator/index.d.ts.map +0 -1
  161. package/dist/rng/index.d.ts +0 -8
  162. package/dist/rng/index.d.ts.map +0 -1
  163. package/src/evaluator/index.ts +0 -14
  164. package/src/rng/index.ts +0 -8
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Per-evaluation shared environment.
3
+ *
4
+ * Lives in its own module so the modifier implementations under
5
+ * `./modifiers/*` can type their `env` parameter without importing
6
+ * `./evaluator.js`, which imports them back.
7
+ *
8
+ * @module evaluator/env
9
+ */
10
+
11
+ import { EvaluatorError } from '../errors.js';
12
+ import type { ASTNode } from '../parser/ast.js';
13
+ import type { DieResult, ResolvedCritThreshold } from '../types.js';
14
+
15
+ /**
16
+ * A resolved `cs`/`cf` pair, recorded per die so that dice minted later by
17
+ * explode or reroll can be judged by the rule the user declared instead of
18
+ * the built-in default.
19
+ */
20
+ export type CritRule = {
21
+ readonly success: readonly ResolvedCritThreshold[];
22
+ readonly fail: readonly ResolvedCritThreshold[];
23
+ };
24
+
25
+ /**
26
+ * Per-evaluation shared environment (created once, shared across all branches).
27
+ *
28
+ * Exported for use by modifier implementations under `./modifiers/*`. Not part
29
+ * of the public library API.
30
+ */
31
+ export type EvalEnv = {
32
+ readonly maxDice: number;
33
+ readonly maxExplodeIterations: number;
34
+ readonly maxRerollIterations: number;
35
+ totalDiceRolled: number;
36
+ /**
37
+ * Set to `true` by `evalSuccessCount`. Propagates through the shared env
38
+ * so `evaluate()` can include `successes`/`failures` fields even when no
39
+ * die was tagged (impossible threshold).
40
+ */
41
+ hasSuccessCount: boolean;
42
+ /**
43
+ * `true` while the evaluator is inside a `VersusNode`'s roll or DC
44
+ * sub-evaluation. `evalVersus` rejects nesting via this flag — catches
45
+ * paren-nested versus (`1d20 vs (5 vs 3)`) that slip past the parser's
46
+ * left-chain check.
47
+ */
48
+ insideVersus: boolean;
49
+ /**
50
+ * `true` once a `vs` has tagged its DC dice `'dc'`. Lets every pool
51
+ * operation skip its per-die `isVersusDc` check outright — the tag exists in
52
+ * a small minority of notation, and the call inside the loop cost 11-38% on
53
+ * keep/drop, success, and sort notation that can never carry one (#281).
54
+ *
55
+ * ! Monotonic: set by `evalVersus`, never cleared. `insideVersus` is not a
56
+ * ! model for it — that flag resets in a `finally`, and it is false exactly
57
+ * ! when the tagged DC dice become visible to the enclosing pool.
58
+ */
59
+ hasVersusDc: boolean;
60
+ /**
61
+ * Crit rule per die, keyed on the `DieResult` object itself. Populated by
62
+ * `applyCritThresholds`; read by explode and reroll so a die they mint
63
+ * inherits the rule of the die it descended from.
64
+ *
65
+ * Out of band rather than a `DieResult` field because `DieResult` is public
66
+ * and serialized. `undefined` until the first `cs`/`cf` node — declared here
67
+ * so the shape stays stable for notation that has none.
68
+ */
69
+ critRules: WeakMap<DieResult, CritRule> | undefined;
70
+ /**
71
+ * User-supplied variable map for `@name` / `@{name}` references. Always
72
+ * defined — `evaluate()` defaults to an empty object so lookups can be
73
+ * branch-free on presence.
74
+ */
75
+ readonly context: Readonly<Record<string, number>>;
76
+ /**
77
+ * Behavior when a referenced variable is missing from `context`. Always
78
+ * defined — `evaluate()` defaults to `'throw'`.
79
+ */
80
+ readonly onMissingVariable: 'throw' | 'zero';
81
+ };
82
+
83
+ /**
84
+ * Reserves `count` dice against the global `maxDice` budget, throwing
85
+ * `DICE_LIMIT_EXCEEDED` when the reservation would overshoot.
86
+ *
87
+ * Every path that consumes RNG draws for dice charges through here — initial
88
+ * pools (`evalDice` / `evalFateDice`), explosion continuations, and reroll
89
+ * replacements — so the limit and its message have one definition.
90
+ */
91
+ export function chargeDice(env: EvalEnv, count: number, nodeType: ASTNode['type']): void {
92
+ if (env.totalDiceRolled + count > env.maxDice) {
93
+ throw new EvaluatorError(
94
+ `Total dice count ${env.totalDiceRolled + count} exceeds limit of ${env.maxDice}`,
95
+ 'DICE_LIMIT_EXCEEDED',
96
+ nodeType,
97
+ );
98
+ }
99
+ env.totalDiceRolled += count;
100
+ }
101
+
102
+ /** Single-die shorthand for {@link chargeDice}. */
103
+ export function chargeDie(env: EvalEnv, nodeType: ASTNode['type']): void {
104
+ chargeDice(env, 1, nodeType);
105
+ }