Docs / Developer / Dice entity
Dice entity
A CanonicalDice is CanonicalEntity<"dice", DiceBody>: a name, a description, a type, and the one field that
type rolls. Rolling itself is math and is not a piece: src/core/dice.ts reads dice notation and rolls it, and the{{roll}} macro, the battle tracker and the spellbook use the same module. What each type of piece rolls isrollDicePiece in src/core/dice-piece.ts, on randomness the caller hands in.
Types
- roll carries
dice, notation such as2d6or1d20+3, and totals it: "Stealth, 1d20+3: [14] +3 = 17". - table carries
rows(at least one), each atextand a wholeweightof 1 or more. It rolls one die the size
of all the weights and lands on the row that number falls in, so a row of weight 2 is twice as likely as one of
weight 1: "Wild magic (rolled 2 of 3): Sparks". - pool carries
pool: acountof dice (1 or more) ofsides(2 or more), and atarget. Each die at or over
the target is a success: "Shadow pool, 4d10, 8 or more: [8, 2, 10, 8] = 3 successes".
A roll is never refused or shortened for being big, and costs one draw per die. Only the answer's text is presented
differently: it lists each die up to 20 dice (DICE_LIST_SHOWN, presentation tuning, not a limit), and past that it
gives the count, the lowest, the highest and the total ("Horde, 40d6: 40 dice, lowest 1, highest 6 = 142"); the trace
detail keeps every die.
Where dice are used
A tool links a dice piece by id (its dice action; tool.md), so a model can roll it while it writes, and
the turn's seeded randomness decides the roll.
The rules
A piece carries exactly the field its type rolls and no other. A roll's dice must be readable notation with at least one
die of at least two sides, and a pool's target may not be more than its sides. These are checked when the piece is
saved, so a stored piece always rolls. The only bounds beyond that are the hostile-input ceilings ofsrc/entities/_shared/sanity.ts (10,000 dice, rows or list items, 1,000,000 characters, whole numbers up toNumber.MAX_SAFE_INTEGER): they guard against a hostile file, are about a hundred times past real use, and are not
design limits; a file past one is refused as unusually large.
Editing
A dice piece opens in the Workbench's dice editor (src/ui/apps/workbench/pieces/dice-editor.tsx): one small page with Roll, Table and Pool, each
with its one-line roll card. A roll has its dice; a table has its rows, each with a weight, its result and its chance (its weight over the total),
and "+ Row" and "Paste a list..." (one row per line, weight 1); a pool has its dice, sides and the number it counts at. Roll uses the real piece roll
(rollDicePiece, the call a tool's action makes), shows the result on the card, and lights the table row the roll picked until the piece is edited.
Rolling changes nothing and is off while the draft cannot be saved. A piece keeps exactly the field its type rolls; switching type sets the others
aside and brings them back if the type is switched back before the editor is closed. A save sends a patch of the edits; with nothing edited
nothing is sent. The Library's "New dice" saves a blank roll of 1d20.