Skip to content

Dice / RNG API 0.1 — De Facto Specification

Status: Descriptive. Documents the dice/roll contract as it ships today (retroactively numbered 0.1; unversioned). Written from production source on branch version/0.40.0. Quirks flagged ⚠︎.

1. The shared contract

packages/shared/src/utils/dice.ts is the platform's canonical dice surface — deterministic, no I/O, usable on client and server:

Function Line Purpose
rollDie(sides) :14 single die
rollD20() :21 d20 shorthand
rollDice(count, sides) :28 array of rolls
rollExpression(expr) :39 evaluate a dice expression → DiceExpressionResult
parseDiceExpression(expr) :85 parse → ParsedDiceExpression | null
rollSkillCheck(name, mod) :113 skill-check helper
rollAttack(input) :148 attack roll
rollDamage(input, isCritical) :194 damage roll

2. Consumers

  • Action API — roll() / rollDetailed() injected globals build on this contract (see action-api-0.1.md §3.4–3.5); ability shorthands (1d20+strength) resolve from property definitions.
  • Server — rollAttack/rollDamage/rollExpression are used server-side (e.g. roll tables routes/rollTables.ts, POST /:id/roll).
  • Module extension — the Module API's DiceRollerExtension can replace the built-in 3D dice; the platform routes rolls through the active roller via diceExtensionAdapter.ts
    • DiceExtensionBridge.tsx.

3. Client rendering layer (in-house deterministic 3D dice)

apps/web renders rolls with an in-house deterministic 3D dice system (built-in since v0.31.0; dice-box removed): the result is pre-simulated off-thread (simulateRollOffThread, InHouseDice/simClient.ts:108) then the animation is symmetry-relabeled to land on the pre-decided value. Rendering + chat integration: Dice3D, DiceRollMessage, diceRoller.ts, rollExpressionToChat.ts / rollDiceToChat.ts. Rolls sync to other clients over the dice:roll socket event (see realtime-api-0.1.md), wired by useDiceSync.ts.

4. Known gaps

  1. ⚠︎ Duplicate parser. DiceRollMessage.tsx defines its own parseDiceExpression (:251) and rollDice (:276), independent of the shared utils/dice.ts implementations — two dice grammars can drift apart.
  2. Unversioned; expression grammar is defined only by the two parser implementations (no formal spec of supported syntax).