# @randsum/roller

Roll dice with a single function call — numbers, notation strings, or options objects. `@randsum/roller` is the core engine that powers the entire RANDSUM ecosystem: full TypeScript types, strict input validation, and zero dependencies — notation parsing is built in.

:::tip[RDN Conformant]
`@randsum/roller` is **RDN v1.0 Level 4 (Full) Conformant**, implementing the complete [RANDSUM Dice Notation Specification](https://notation.randsum.dev).
:::

## Features

- **Three input modes** — pass a number, a notation string, or a typed options object
- **Advanced notation** — drop/keep, reroll, exploding, compounding, penetrating, cap, replace, unique, count successes/failures, wild die, integer division, modulo, annotations, and repeat
- **Special dice** — geometric die (`gN`), draw die (`DDN`), percentile (`d%`), and Fate/Fudge (`dF`)
- **Modifier pipeline** — 19 modifiers execute in a defined priority order, composable and predictable
- **Multiple arguments** — combine rolls into a single total: `roll('1d20+5', '2d6')`
- **Strict validation** — throws on invalid input; validate user strings with `isDiceNotation()` or `validateNotation()`
- **Custom RNG** — pass a `randomFn` for seeded, deterministic, or cryptographic randomness
- **Universal runtime** — works in Node.js, Bun, Deno, browsers, and edge functions

## Argument types

### Number

Pass a number to roll one die with that many sides.

<CodeExample code={`const result = roll(20)
console.log(result.total) // 1-20`} />

### Notation string

Pass a [Randsum Dice Notation](https://randsum.dev/notation/randsum-dice-notation/) string for complex rolls.

<CodeExample code={`// 4d6, drop the lowest
const abilityScore = roll('4d6L')

// 2d20, keep highest (advantage), add 5
const attack = roll('2d20K+5')

// Exploding d6s with rerolls below 3
const wild = roll('4d6!R{<3}')`} />

<NotationRoller defaultNotation="4d6L" client:only="react" />

### Options object

Pass a typed object for full control over the roll without notation parsing.

<CodeExample code={`const result = roll({
  sides: 6,
  quantity: 4,
  modifiers: {
    drop: { lowest: 1 },
    plus: 2
  }
})

console.log(result.total)  // Sum of best 3d6 + 2`} />

All three input types produce the same `RollerRollResult` — you can mix them in a single call:

<CodeExample code={`// Combine multiple arguments into one total
const result = roll('1d20+5', '2d6')
console.log(result.total) // d20 + 5 + 2d6`} />

## Notation quick reference

| Pattern | Description | Example |
|---|---|---|
| `NdS` | Roll N dice with S sides | `4d6` |
| `+X` / `-X` | Add/subtract from total | `1d20+5` |
| `L` / `H` | Drop lowest/highest | `4d6L` |
| `K` / `kl` | Keep highest/lowest | `4d6K3` |
| `!` | Exploding dice | `3d6!` |
| `!!` | Compounding exploding | `3d6!!` |
| `!p` | Penetrating exploding | `3d6!p` |
| `U` | Unique results | `4d20U` |
| `W` | Wild die (D6 System) | `5d6W` |
| `F{N}` | Count failures | `5d10F{3}` |
| `//N` | Integer divide total | `4d6//2` |
| `%N` | Total modulo | `4d6%3` |
| `gN` | Geometric die | `g6` |
| `DDN` | Draw die (no replacement) | `3DD6` |
| `[text]` | Annotation/label | `2d6[fire]` |
| `xN` | Repeat notation | `4d6Lx6` |

See the full [Randsum Dice Notation Spec](https://randsum.dev/notation/randsum-dice-notation/) for reroll conditions, caps, replacements, success counting, and multipliers.

## Learn more

- **[Getting Started](https://randsum.dev/roller/getting-started/)** — install, first roll, result types
- **[Roll Options](https://randsum.dev/roller/roll-options/)** — every option the `roll()` function accepts
- **[Modifiers](https://randsum.dev/roller/modifiers/)** — how the modifier pipeline works, priority order, and examples
- **[Error Handling](https://randsum.dev/roller/error-handling/)** — validation patterns for user-provided input
- **[API Reference](https://randsum.dev/roller/api-reference/)** — all exported functions and types