Construct an empty roll owned by parent — shorthand for
new SimpleRoll({}, { parent }) (all fields default to 0/[]).
The owning sohl.core.logic.SohlLogic.
Construct a roll from partial data; any omitted field defaults to 0
(or [] for rolls).
Partial roll definition (numDice, dieFaces, modifier,
rolls).
Must provide options.parent, the owning Logic (base
SohlEntity).
Number of faces per die (the M in NdM+K).
Flat modifier added to the dice total (the K in NdM+K).
Number of dice to roll (the N in NdM+K).
The dice formula string, e.g. "2d6+3" or "1d100".
Whether the dice have actually been cast — roll() has run, or values
were supplied at construction.
The distinction matters wherever a result object may exist before it has
been resolved: an unrolled die reads total as just its modifier,
which is indistinguishable from a genuine result. The opposed test relies
on this to tell a pending target side (the placeholder
sohl.entity.result.OpposedTestResult builds from the target token)
from one the defender has already rolled — see
sohl.entity.modifier.MasteryLevelModifier.opposedTestResume.
The serialization discriminator for this instance — the concrete class's static Kind. Written into the JSON by toJSON under the kind key and read back by sohl.utils.defaultFromJSON to select the constructor. Derived from the class, never stored per-instance.
The average (expected value) of this roll — the mean outcome of
numDice dice of dieFaces faces, plus the flat modifier. It is the
roll's fixed statistical center, with no randomness.
The average/expected result of the roll, possibly fractional.
Each die averages (dieFaces + 1) / 2 (a fair die's mean), so the dice
sum's expected value is numDice * (dieFaces + 1) / 2, to which the
modifier is added. Because the sum of uniform dice is a symmetric
distribution, its mean and median coincide — so this single value is both
the average and the median (the getter is named for the latter).
The result is not rounded: an odd count of even-faced dice yields a
half-integer (e.g. 1d6 → 3.5, 1d20 → 10.5); round at the call
site if you want an integer. With no dice, it is just the modifier.
A human-readable string showing the evaluated expression,
e.g. "[3, 5] + 2" for 2d6+2 with rolls of 3 and 5.
Compute the total result.
StaticforcedHow many forced die values remain queued (for assertions / hygiene).
Deep-copy this entity, re-parenting the copy under parent with no other
changes. Shorthand for clone({}, { parent }).
The Logic to own the cloned entity.
The cloned entity.
Deep-copy this entity, optionally overriding fields and clone options.
Field overrides applied to the clone.
Clone options (e.g. a new parent).
The cloned entity.
Roll the dice — consuming forced values when queued, otherwise drawing from a seedable sohl.entity.random.Rng.
The random source; defaults to the sohl.random singleton.
The total of the rolls plus the modifier.
If roll has already been made, this method will return the total without rolling again.
Each die takes the next forced value when the queue is non-empty, else a
fresh draw from rng; a partly-drained queue mixes the two.
rng defaults to the shared sohl.random singleton — pass an
injected instance (sohl.entity.random.createRng) for an isolated,
reproducible stream (unit tests) rather than perturbing the shared one.
Set specific results for the dice instead of rolling randomly.
The array of die results to use.
If values.length does not equal numDice.
Serialize the roll to a plain object satisfying SimpleRoll.Data.
A plain-object snapshot of this roll's fields.
StaticclearStaticforceSeed the deterministic-testing queue with predetermined die values,
appended in order. Subsequent roll calls consume them one per die
(FIFO) instead of rolling randomly. Accepts a spread or a spread array
(forceValues(...[5, 3])). Left-over values leak into the next roll, so a
test seeding these must clearForced afterward (e.g. an afterEach).
Die values the next rolls should use, in order.
StaticfromParse a dice formula string into an unrolled SimpleRoll.
Accepts forms like "2d6+3", "1d100", "d20" (implicit one die),
"-2" (modifier only), with optional whitespace around the modifier
sign.
The dice formula to parse.
The Logic that owns the resulting roll.
A new SimpleRoll with no dice rolled yet.
A Foundry-free dice primitive for structured
NdM+Krolls.Unlike Foundry's Roll class, SimpleRoll requires no runtime environment, supports deterministic testing via setRolls, and provides a median calculation for statistical analysis.
As a SohlEntity, a SimpleRoll is owned by a
parentLogic (the modifier/result/logic it belongs to) and serializes through the shared entitytoJSON/clonemachinery.To convert a SimpleRoll to a Foundry Roll for chat display, use the
toFoundryRoll()shim inFoundryHelpers.ts.