@mcptoolshop/roll 1.0.0 → 2.0.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 (69) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +105 -137
  3. package/dist/analyze/distribution.d.ts.map +1 -1
  4. package/dist/analyze/distribution.js +249 -33
  5. package/dist/analyze/distribution.js.map +1 -1
  6. package/dist/bridge/handler.d.ts +14 -0
  7. package/dist/bridge/handler.d.ts.map +1 -0
  8. package/dist/bridge/handler.js +163 -0
  9. package/dist/bridge/handler.js.map +1 -0
  10. package/dist/bridge/protocol.d.ts +53 -0
  11. package/dist/bridge/protocol.d.ts.map +1 -0
  12. package/dist/bridge/protocol.js +8 -0
  13. package/dist/bridge/protocol.js.map +1 -0
  14. package/dist/bridge/server.d.ts +3 -0
  15. package/dist/bridge/server.d.ts.map +1 -0
  16. package/dist/bridge/server.js +71 -0
  17. package/dist/bridge/server.js.map +1 -0
  18. package/dist/display/format.d.ts.map +1 -1
  19. package/dist/display/format.js +28 -3
  20. package/dist/display/format.js.map +1 -1
  21. package/dist/engine/pipeline.d.ts +27 -0
  22. package/dist/engine/pipeline.d.ts.map +1 -0
  23. package/dist/engine/pipeline.js +304 -0
  24. package/dist/engine/pipeline.js.map +1 -0
  25. package/dist/engine/roller.d.ts +3 -0
  26. package/dist/engine/roller.d.ts.map +1 -1
  27. package/dist/engine/roller.js +82 -125
  28. package/dist/engine/roller.js.map +1 -1
  29. package/dist/index.d.ts +9 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +9 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/mcp/server.d.ts +3 -0
  34. package/dist/mcp/server.d.ts.map +1 -0
  35. package/dist/mcp/server.js +182 -0
  36. package/dist/mcp/server.js.map +1 -0
  37. package/dist/mcp/tools.d.ts +12 -0
  38. package/dist/mcp/tools.d.ts.map +1 -0
  39. package/dist/mcp/tools.js +106 -0
  40. package/dist/mcp/tools.js.map +1 -0
  41. package/dist/parser/ast.d.ts +7 -1
  42. package/dist/parser/ast.d.ts.map +1 -1
  43. package/dist/parser/lexer.d.ts.map +1 -1
  44. package/dist/parser/lexer.js +138 -45
  45. package/dist/parser/lexer.js.map +1 -1
  46. package/dist/parser/parser.d.ts.map +1 -1
  47. package/dist/parser/parser.js +107 -15
  48. package/dist/parser/parser.js.map +1 -1
  49. package/dist/parser/tokens.d.ts +14 -0
  50. package/dist/parser/tokens.d.ts.map +1 -1
  51. package/dist/parser/tokens.js +22 -0
  52. package/dist/parser/tokens.js.map +1 -1
  53. package/dist/tables/conditions.d.ts +7 -0
  54. package/dist/tables/conditions.d.ts.map +1 -0
  55. package/dist/tables/conditions.js +65 -0
  56. package/dist/tables/conditions.js.map +1 -0
  57. package/dist/tables/engine.d.ts +10 -0
  58. package/dist/tables/engine.d.ts.map +1 -0
  59. package/dist/tables/engine.js +147 -0
  60. package/dist/tables/engine.js.map +1 -0
  61. package/dist/tables/schema.d.ts +89 -0
  62. package/dist/tables/schema.d.ts.map +1 -0
  63. package/dist/tables/schema.js +3 -0
  64. package/dist/tables/schema.js.map +1 -0
  65. package/dist/tables/validate.d.ts +4 -0
  66. package/dist/tables/validate.d.ts.map +1 -0
  67. package/dist/tables/validate.js +98 -0
  68. package/dist/tables/validate.js.map +1 -0
  69. package/package.json +12 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.0 (2026-04-11)
4
+
5
+ Universal game infrastructure release.
6
+
7
+ ### Extended Notation
8
+
9
+ - **Reroll** — `r` (unlimited), `ro` (once) with compare points: `2d6r<2`, `2d6ro=1`
10
+ - **Compounding dice** — `!!` sums explosions into same die: `1d6!!`, `1d6!!>4`
11
+ - **Penetrating dice** — `!p` subtracts 1 per explosion: `1d6!p`
12
+ - **Min/max clamping** — `min`/`max` per die: `2d6min3`, `2d6max5`
13
+ - **Success counting** — `cs` with compare point for dice pools: `8d6cs>=5`
14
+ - **Failure counting** — `cf` subtracts from success count: `8d6cs>=5cf<=1`
15
+ - **Critical marking** — `cs`/`cf` without compare point for visual highlights
16
+ - **Sorting** — `sa`/`sd` for display order: `4d6sa`
17
+ - **Full comparison operators** — `>`, `>=`, `<`, `<=`, `=` in all compare points
18
+
19
+ ### Probability Engine
20
+
21
+ - **Analytical reroll** — exact redistribution of probability mass for rerolled faces
22
+ - **Analytical min/max** — exact truncated distributions with piled mass
23
+ - **Analytical success counting** — exact binomial-like convolution for dice pools
24
+ - **Compounding/penetrating distributions** — exact iterative depth expansion variants
25
+ - All V2 modifiers have exact probability analysis, not just Monte Carlo
26
+
27
+ ### Game Table System
28
+
29
+ - **8 table kinds** — loot, encounter, critical, fumble, reward, status, event, custom
30
+ - **4 condition types** — compare (trigger roll), nat (natural die), tag, context variable
31
+ - **Level filtering** — minLevel/maxLevel per entry
32
+ - **Table chaining** — result of one table triggers rolls on others
33
+ - **Dice fields** — roll, quantity, duration expressions per entry
34
+ - **Rarity tiers** — common, uncommon, rare, epic, legendary
35
+ - **Validation** — missing refs, circular detection, invalid dice, level range sanity
36
+ - **V1 bridge** — `convertLootToGameTable()` for migration
37
+
38
+ ### JSON Bridge
39
+
40
+ - **JSON-RPC 2.0** — 11 methods: roll, roll_batch, analyze, at_least, compare, table_roll, table_load, table_list, seed, ping, shutdown
41
+ - **Stdio transport** — newline-delimited JSON for Godot/Unreal child process
42
+ - **HTTP transport** — POST /rpc endpoint for network access
43
+ - **Deterministic seeding** — session-level seed for reproducible gameplay
44
+
45
+ ### MCP Server
46
+
47
+ - **5 tools** — roll_dice, analyze_dice, compare_dice, roll_table, query_table
48
+ - **Stdio MCP transport** — standard MCP protocol for Claude integration
49
+
50
+ ### Engine Architecture
51
+
52
+ - **8-stage modifier pipeline** — roll → reroll → min/max → explode → keep/drop → sort → mark → total
53
+ - **PipelineDie type** — tracks rerolledFrom, critical markers per die
54
+ - **DiceGroupResult.resultMode** — "sum" or "success_count" (backward compatible)
55
+ - **ComparePoint type** — operator + value for all comparison-based modifiers
56
+
57
+ ### Numbers
58
+
59
+ - 226 tests across 9 suites (up from 80)
60
+ - Zero runtime dependencies maintained
61
+ - Full backward compatibility with V1 API
62
+
63
+ ## 1.0.1 (2026-04-10)
64
+
65
+ Patch release.
66
+
3
67
  ## 1.0.0 (2026-04-10)
4
68
 
5
69
  Initial release.
package/README.md CHANGED
@@ -11,43 +11,10 @@
11
11
  <a href="https://www.npmjs.com/package/@mcptoolshop/roll"><img src="https://img.shields.io/npm/v/@mcptoolshop/roll" alt="npm version"></a>
12
12
  </p>
13
13
 
14
- <p align="center">RPG dice engine with probability analysis, loot tables, and beautiful terminal output.</p>
14
+ <p align="center">Universal RPG dice engine full notation, probability analysis, game tables, and engine integration.</p>
15
15
 
16
16
  ```
17
- npx @mcptoolshop/roll 4d6dl1 --analyze
18
- ```
19
-
20
- ```
21
- Distribution
22
-
23
- 3 0.08%
24
- 4 █ 0.31%
25
- 5 ███ 0.77%
26
- 6 ███████ 1.62%
27
- 7 █████████████ 2.93%
28
- 8 ██████████████████████ 4.78%
29
- 9 ████████████████████████████████ 7.02%
30
- 10 ███████████████████████████████████████████ 9.41%
31
- 11 ████████████████████████████████████████████████████ 11.42%
32
- 12 ██████████████████████████████████████████████████████████ 12.89%
33
- 13 ████████████████████████████████████████████████████████████ 13.27%
34
- 14 ████████████████████████████████████████████████████████ 12.35%
35
- 15 ██████████████████████████████████████████████ 10.11%
36
- 16 █████████████████████████████████ 7.25%
37
- 17 ███████████████████ 4.17%
38
- 18 ███████ 1.62%
39
-
40
- ┌─ Statistics ─────────────────────────────────┐
41
- │ Mean: 12.24 │
42
- │ Median: 12 │
43
- │ Mode: 13 │
44
- │ Std Dev: 2.85 │
45
- │ Range: 3–18 │
46
- │ Entropy: 3.53 bits │
47
- │ │
48
- │ Percentiles: │
49
- │ p10:8 p25:10 p50:12 p75:14 p90:16 p95:17│
50
- └───────────────────────────────────────────────┘
17
+ npx @mcptoolshop/roll 8d6cs>=5 --analyze
51
18
  ```
52
19
 
53
20
  ## Install
@@ -56,142 +23,143 @@ npx @mcptoolshop/roll 4d6dl1 --analyze
56
23
  npm install @mcptoolshop/roll
57
24
  ```
58
25
 
59
- Requires Node.js >= 22.
60
-
61
- ## CLI Usage
62
-
63
- ### Roll dice
26
+ Requires Node.js >= 22. Zero runtime dependencies.
64
27
 
65
- ```bash
66
- roll 2d6+3
67
- roll d20+5
68
- roll 4d6kh3
69
- roll 1d6!
70
- roll d%
71
- roll 4dF
72
- roll "(2d6+3)*2"
73
- ```
28
+ ## Dice Notation
74
29
 
75
- ### Analyze probability
30
+ Roll supports the full Roll20/VTT notation standard covering D&D, World of Darkness, Shadowrun, Savage Worlds, Fate, and more.
76
31
 
77
- ```bash
78
- roll 2d6 --analyze # Full distribution + statistics
79
- roll d20+5 --at-least 15 # P(result >= 15)
80
- ```
32
+ | Notation | Meaning |
33
+ |----------|---------|
34
+ | `2d6` | Roll 2 six-sided dice |
35
+ | `d20+5` | Roll d20, add modifier |
36
+ | `4d6kh3` | Roll 4d6, keep highest 3 |
37
+ | `4d6dl1` | Roll 4d6, drop lowest 1 |
38
+ | `1d6!` | Exploding (reroll on max, add) |
39
+ | `1d6!>4` | Explode on 4 or higher |
40
+ | `1d6!!` | Compounding (sum explosions into same die) |
41
+ | `1d6!p` | Penetrating (explosions subtract 1) |
42
+ | `2d6r<2` | Reroll values less than 2 (unlimited) |
43
+ | `2d6ro=1` | Reroll 1s once |
44
+ | `2d6min3` | Floor: no die below 3 |
45
+ | `2d6max5` | Ceiling: no die above 5 |
46
+ | `8d6cs>=5` | Count successes (dice >= 5) |
47
+ | `8d6cs>=5cf<=1` | Successes minus failures |
48
+ | `1d20cs>19cf<2` | Critical success/failure marking |
49
+ | `4d6sa` / `4d6sd` | Sort ascending / descending |
50
+ | `d%` | Percentile (1-100) |
51
+ | `4dF` | Fate/Fudge dice |
52
+ | `(2d6+3)*2` | Arithmetic with grouping |
81
53
 
82
- ### Compare distributions
54
+ ## CLI Usage
83
55
 
84
56
  ```bash
85
- roll --compare "4d6dl1" "3d6"
57
+ roll 2d6+3 # Basic roll
58
+ roll 8d6cs>=5 # WoD-style dice pool
59
+ roll 4d6r<2min2kh3 # Complex modifier chain
60
+ roll 2d6 --analyze # Full distribution + statistics
61
+ roll d20+5 --at-least 15 # P(result >= 15)
62
+ roll --compare "4d6dl1" "3d6" # Side-by-side distributions
63
+ roll --loot treasure.json # Loot table
64
+ roll 2d6+3 --times 5 # Multiple rolls
65
+ roll 2d6+3 --json # Machine-readable output
86
66
  ```
87
67
 
88
- Side-by-side stats (mean, median, mode, stddev, range, entropy) with diff column, plus both histograms.
68
+ ## Game Tables
89
69
 
90
- ### Loot tables
70
+ V2 introduces a universal game table system for encounters, criticals, loot, status effects, and more.
91
71
 
92
- ```bash
93
- roll --loot treasure.json
72
+ ```typescript
73
+ import { rollGameTable } from '@mcptoolshop/roll';
74
+ import type { GameTableCollection } from '@mcptoolshop/roll';
75
+
76
+ const collection: GameTableCollection = {
77
+ version: "2.0",
78
+ tables: [{
79
+ table: "critical_hits",
80
+ kind: "critical",
81
+ entries: [
82
+ { name: "Devastating Blow", weight: 1, roll: "2d6", conditions: [{ type: "nat", operator: "=", value: 20 }] },
83
+ { name: "Solid Hit", weight: 3, conditions: [{ type: "compare", operator: ">=", value: 15 }] },
84
+ { name: "Glancing Blow", weight: 5 },
85
+ ],
86
+ }],
87
+ };
88
+
89
+ const results = rollGameTable(collection, "critical_hits", { triggerNat: 20, triggerRoll: 25 });
94
90
  ```
95
91
 
96
- JSON format:
92
+ Features: 8 table kinds, weighted selection, conditions (compare, nat, tag, context), level filtering, nested tables, table chaining, dice expressions for quantity/roll/duration, rarity tiers, validation with circular reference detection.
97
93
 
98
- ```json
99
- {
100
- "tables": [
101
- {
102
- "table": "Treasure",
103
- "items": [
104
- { "name": "Gold", "weight": 40, "roll": "2d6*10" },
105
- { "name": "Potion of Healing", "weight": 30 },
106
- { "name": "Scroll", "weight": 15, "quantity": "1d3" },
107
- { "name": "Rare Item", "weight": 5, "table": "Rare Weapons" }
108
- ]
109
- },
110
- {
111
- "table": "Rare Weapons",
112
- "items": [
113
- { "name": "Vorpal Blade", "weight": 5 },
114
- { "name": "Frost Brand", "weight": 25 }
115
- ]
116
- }
117
- ]
118
- }
94
+ ## Library API
95
+
96
+ ```typescript
97
+ import { roll, analyze } from '@mcptoolshop/roll';
98
+
99
+ // Roll with any V2 notation
100
+ const result = roll('8d6cs>=5');
101
+ console.log(result.total); // 3 (successes)
102
+ console.log(result.groups[0].resultMode); // "success_count"
103
+ console.log(result.groups[0].dice); // per-die breakdown with .critical markers
104
+
105
+ // Probability analysis — exact, not Monte Carlo
106
+ const analysis = analyze('8d6cs>=5');
107
+ console.log(analysis.stats.mean); // 2.67
108
+ console.log(analysis.probabilityAtLeast(4)); // P(4+ successes)
109
+
110
+ // Seeded deterministic rolls
111
+ import { seededRng, parse, evaluate } from '@mcptoolshop/roll';
112
+ const ast = parse('4d6kh3');
113
+ const r = evaluate(ast, seededRng(42)); // reproducible
119
114
  ```
120
115
 
121
- Features: weighted selection, nested table references, dice expressions for quantity and value.
116
+ ## JSON Bridge (Godot / Unreal / Rust)
122
117
 
123
- ### Other flags
118
+ Roll includes a JSON-RPC 2.0 bridge for game engine integration via child process:
124
119
 
125
120
  ```bash
126
- roll 2d6+3 --times 5 # Roll 5 times
127
- roll 2d6+3 --json # Machine-readable output
128
- roll --help # Full usage
129
- roll --version # Version
121
+ # Stdio mode (pipe JSON in, get JSON out)
122
+ echo '{"jsonrpc":"2.0","id":1,"method":"roll","params":{"expression":"4d6kh3","seed":42}}' | roll-bridge
123
+
124
+ # HTTP mode
125
+ roll-bridge --http --port 3947
126
+ curl -X POST http://localhost:3947/rpc -d '{"jsonrpc":"2.0","id":1,"method":"roll","params":{"expression":"2d6+3"}}'
130
127
  ```
131
128
 
132
- ## Dice Notation
129
+ Methods: `roll`, `roll_batch`, `analyze`, `at_least`, `compare`, `table_roll`, `table_load`, `table_list`, `seed`, `ping`, `shutdown`.
133
130
 
134
- | Notation | Meaning |
135
- |----------|---------|
136
- | `2d6` | Roll 2 six-sided dice |
137
- | `d20` | Roll 1 twenty-sided die |
138
- | `4d6kh3` | Roll 4d6, keep highest 3 |
139
- | `4d6dl1` | Roll 4d6, drop lowest 1 |
140
- | `1d6!` | Exploding d6 (reroll on max, add) |
141
- | `1d6!>4` | Explode on 4 or higher |
142
- | `d%` | Percentile die (1-100) |
143
- | `4dF` | Fate/Fudge dice (-1, 0, +1 each) |
144
- | `(2d6+3)*2` | Arithmetic with grouping |
145
- | `2d6+1d4+3` | Chained expressions |
131
+ ## MCP Server
146
132
 
147
- ## Library API
133
+ Roll ships as an MCP server for Claude integration during game design:
148
134
 
149
- ```typescript
150
- import { roll, analyze, parse, evaluate, computeDistribution } from '@mcptoolshop/roll';
151
-
152
- // Quick roll
153
- const result = roll('4d6kh3');
154
- console.log(result.total); // 14
155
- console.log(result.groups[0].dice); // per-die breakdown
156
-
157
- // Full analysis
158
- const analysis = analyze('2d6+3');
159
- console.log(analysis.stats.mean); // 10
160
- console.log(analysis.stats.percentiles[95]); // 14
161
- console.log(analysis.probabilityAtLeast(12)); // 0.2778
162
-
163
- // Low-level: parse → AST → evaluate
164
- import { seededRng } from '@mcptoolshop/roll';
165
- const ast = parse('4d6dl1');
166
- const r = evaluate(ast, seededRng(42)); // deterministic
167
-
168
- // Loot tables
169
- import { rollLootTable } from '@mcptoolshop/roll';
170
- const tables = [{ table: "Loot", items: [{ name: "Gold", weight: 50, roll: "2d6*10" }] }];
171
- const drops = rollLootTable(tables);
135
+ ```json
136
+ {
137
+ "mcpServers": {
138
+ "roll": {
139
+ "command": "node",
140
+ "args": ["node_modules/@mcptoolshop/roll/dist/mcp/server.js"]
141
+ }
142
+ }
143
+ }
172
144
  ```
173
145
 
146
+ 5 tools: `roll_dice`, `analyze_dice`, `compare_dice`, `roll_table`, `query_table`.
147
+
174
148
  ## Probability Engine
175
149
 
176
150
  - **Exact distributions** via polynomial convolution for basic NdM
177
151
  - **Full enumeration** for keep/drop mechanics (4d6 = 1,296 states)
178
- - **Truncated recursion** for exploding dice (capped at 10 explosions)
152
+ - **Analytical reroll** redistributes probability mass over non-matching faces
153
+ - **Analytical min/max** — truncates distribution and piles mass at clamp
154
+ - **Analytical success counting** — maps faces to +1/0/-1, convolves N times
155
+ - **Truncated recursion** for exploding/compounding/penetrating dice
179
156
  - **Monte Carlo fallback** (100k samples) when exact computation exceeds 10M states
180
157
 
181
- ## Zero Dependencies
182
-
183
- Built entirely on Node.js 22+ builtins:
184
- - `util.styleText` for terminal colors
185
- - `util.parseArgs` for CLI argument parsing
186
- - `crypto.randomInt` for cryptographically secure dice rolls
158
+ Every modifier has exact probability analysis — not just simulation.
187
159
 
188
160
  ## Security & Trust
189
161
 
190
- `@mcptoolshop/roll` processes dice expressions and nothing else. It makes no network requests, writes no files, and collects no data. The only filesystem access is the `--loot` flag, which reads a single user-specified JSON file.
191
-
192
- There is no telemetry, no analytics, and no tracking of any kind. No secrets, tokens, or credentials are involved in any operation.
193
-
194
- All dice rolls use `crypto.randomInt` from the Node.js `crypto` module, providing cryptographically secure randomness suitable for fair outcomes.
162
+ Processes dice expressions and nothing else. No network requests, no file writes (except `--loot` reads one JSON), no telemetry, no secrets. All dice rolls use `crypto.randomInt` for cryptographic randomness.
195
163
 
196
164
  See [SECURITY.md](./SECURITY.md) for the vulnerability reporting policy.
197
165
 
@@ -1 +1 @@
1
- {"version":3,"file":"distribution.d.ts","sourceRoot":"","sources":["../../src/analyze/distribution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAuB,MAAM,kBAAkB,CAAC;AAGrE,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AA+L/C,yGAAyG;AACzG,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAI9D"}
1
+ {"version":3,"file":"distribution.d.ts","sourceRoot":"","sources":["../../src/analyze/distribution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAqC,MAAM,kBAAkB,CAAC;AAInF,6DAA6D;AAC7D,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAka/C,yGAAyG;AACzG,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAI9D"}