High-performance dice notation parser for tabletop RPGs.
TypeScript-first, Bun-optimized, Pratt parser architecture.
v3 in Development - Complete architectural rewrite in progress.
For production use, install v2.3.2.
- Basic dice notation:
2d6,d20,4d6+4 - Full arithmetic:
+,-,*,/,%,** - Parentheses:
(1d4+1)*2 - Keep/Drop modifiers:
4d6kh3,2d20kl1,4d6dl1 - Computed dice:
(1+1)d(3*2) - Seedable RNG for reproducible rolls
- Exploding dice:
1d6!,1d6!!,1d6!p - Reroll mechanics:
2d6r<2,2d6ro<3 - Success counting:
10d10>=6,10d10>=6f1 - Math functions:
floor(),ceil(),max(),min()
- Variables:
1d20+@str,1d20+@{modifier} - Grouped rolls:
{1d8, 1d10}kh1 - Rich JSON output with roll breakdown
# When v3 is released
bun add roll-parser
npm install roll-parserimport { roll, parse } from 'roll-parser';
// Simple roll
const result = roll('4d6kh3');
console.log(result.total); // e.g., 14
console.log(result.rolls); // Individual die results
console.log(result.rendered); // "4d6kh3[6,5,3,2] = 14"
// With seeded RNG for reproducibility
const seeded = roll('2d20', { seed: 'my-seed' });
// Parse without rolling (for inspection)
const ast = parse('2d6+5');# Roll dice from command line
roll-parser 2d6+3
roll-parser 4d6kh3
roll-parser --helpbun install # Install dependencies
bun check:fix # Type check + lint + format
bun test # Run tests
bun run build # Build library
bun release:dry # Validate releaseBuilt with a Pratt parser for:
- Clean precedence handling - Operator binding power, not grammar rules
- Easy extensibility - Add new modifiers without restructuring
- Optimal performance - Target <1ms for complex expressions
- Type safety - Strict TypeScript, no
any
src/
├── lexer/ # Tokenization (d, kh, kl, dh, dl, numbers, operators)
├── parser/ # Pratt parser with AST generation
├── evaluator/ # AST evaluation with modifier handling
├── rng/ # Seedable random number generation
├── cli/ # Command-line interface
└── index.ts # Public API exports
| System | Notation Examples | Stage |
|---|---|---|
| D&D 5e | 2d6, 1d20+5, 4d6kh3 |
1 |
| Pathfinder 2e | 1d20+10 vs 25 |
2 |
| World of Darkness | 10d10>=6f1 |
2 |
| Savage Worlds | 1d6! |
2 |
See CONTRIBUTING.md for development guidelines.