@randsum/roller
v1.3.0
Published
TypeScript-first dice notation engine for tabletop RPGs, game development, and probability simulations
Maintainers
Readme
A Zero Dependency, Typescript-First, Bun-Native Dice Notation and Rolling Engine. Throw Dice, Not Exceptions.
Installation
npm install @randsum/roller
# or
bun add @randsum/rollerUsage
import { roll } from "@randsum/roller"
// Three ways to roll: number, notation string, or options object
roll(20) // Roll 1d20
roll("4d6L") // Roll 4d6, drop lowest
roll({ sides: 6, quantity: 4, modifiers: { drop: { lowest: 1 } } })
// Complex modifiers
roll("2d20L") // Advantage (drop lowest, keep highest)
roll("4d6!R{<3}") // Exploding dice, reroll below 3
roll("1d20+5", "2d6+3") // Multiple rolls combinedCLI
npx @randsum/cli 2d20 # Roll two d20s
npx @randsum/cli 4d6L # Roll 4d6, drop lowest
npx @randsum/cli 3d8+2 # Roll 3d8 and add 2API
roll(...args)
The main function accepts numbers, notation strings, or options objects.
const result = roll("2d6+3")
result.total // Final total after all modifiers
result.values // Array of individual die values
result.rolls // Full roll records with modifier historyroll() throws on invalid input. Wrap calls in try/catch:
import { roll, RandsumError } from "@randsum/roller"
try {
const result = roll(userInput)
console.log(result.total)
} catch (e) {
if (e instanceof RandsumError) {
console.error(e.message)
}
}Notation Reference
| Notation | Description |
| ---------- | --------------------------- |
| 4d6 | Roll 4 six-sided dice |
| 4d6+2 | Add 2 to total |
| 4d6L | Drop lowest |
| 4d6H | Drop highest |
| 2d20L | Drop lowest (advantage) |
| 2d20H | Drop highest (disadvantage) |
| 4d6! | Exploding dice |
| 4d6R{<3} | Reroll values below 3 |
| 4d6U | Unique rolls only |
See RANDSUM_DICE_NOTATION.md for the complete notation guide.
Other Exports
import {
// Validation
validateNotation,
isDiceNotation,
validateRollOptions,
// Conversion utilities
optionsToNotation,
optionsToDescription,
// Error types
RandsumError,
NotationParseError,
ValidationError
} from "@randsum/roller"Subpath Exports
Use these subpaths to import only what you need without pulling in the full roll engine.
@randsum/roller/docs — Static modifier documentation. Zero dependencies, safe for any environment.
import { MODIFIER_DOCS } from "@randsum/roller/docs"
import type { ModifierDoc } from "@randsum/roller/docs"
// Keyed by notation shorthand
const doc = MODIFIER_DOCS["L"] // Drop Lowest
const doc = MODIFIER_DOCS["!"] // Explode
const doc = MODIFIER_DOCS["R{..}"] // Reroll@randsum/roller/trace — Transform a RollRecord into a step-by-step display trace.
import { traceRoll, formatAsMath } from "@randsum/roller/trace"
import type { RollTraceStep } from "@randsum/roller/trace"
const result = roll("4d6L")
const steps = traceRoll(result.rolls[0]!)
// [
// { kind: 'rolls', label: 'Rolled', unchanged: [...], removed: [], added: [] },
// { kind: 'rolls', label: 'Drop Lowest 1', unchanged: [...], removed: [2], added: [] },
// { kind: 'finalRolls', rolls: [...], arithmeticDelta: 0 }
// ]
formatAsMath([3, 4, 5]) // "3 + 4 + 5"
formatAsMath([3, 4, 5], -1) // "3 + 4 + 5 - 1"RollTraceStep is a discriminated union on kind: 'rolls' | 'divider' | 'arithmetic' | 'finalRolls'.
@randsum/roller/tokenize — Notation tokenizer without the roll engine.
import { tokenize } from "@randsum/roller/tokenize"@randsum/roller/validate — Validation utilities only.
import { validateNotation, isDiceNotation } from "@randsum/roller/validate"Related Packages
- @randsum/games/blades - Blades in the Dark
- @randsum/games/daggerheart - Daggerheart
- @randsum/games/fifth - D&D 5th Edition
- @randsum/games/root-rpg - Root RPG
- @randsum/games/salvageunion - Salvage Union
- @randsum/games/pbta - Powered by the Apocalypse
