A Foundry-free dice primitive for structured NdM+K rolls.

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 parent Logic (the modifier/result/logic it belongs to) and serializes through the shared entity toJSON/clone machinery.

To convert a SimpleRoll to a Foundry Roll for chat display, use the toFoundryRoll() shim in FoundryHelpers.ts.

Hierarchy (View Summary)

Constructors

Properties

dieFaces: number

Number of faces per die (the M in NdM+K).

modifier: number

Flat modifier added to the dice total (the K in NdM+K).

numDice: number

Number of dice to roll (the N in NdM+K).

rolls: number[]

The individual die results; empty until roll or setRolls is called.

Accessors

  • get kind(): string
  • 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.

    Returns string

  • get median(): number
  • 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.

    Returns number

    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. 1d63.5, 1d2010.5); round at the call site if you want an integer. With no dice, it is just the modifier.

  • get parent(): SohlLogic<any>
  • The Logic that owns this entity. Always present (the constructor rejects a missing parent) and transient — it is not serialized and is re-supplied when the entity is revived or cloned.

    Returns SohlLogic<any>

  • get result(): string
  • A human-readable string showing the evaluated expression, e.g. "[3, 5] + 2" for 2d6+2 with rolls of 3 and 5.

    Returns string

Methods

  • Roll the dice — consuming forced values when queued, otherwise drawing from a seedable sohl.entity.random.Rng.

    Parameters

    • rng: Rng = ...

      The random source; defaults to the sohl.random singleton.

    Returns number

    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.

    Parameters

    • values: number[]

      The array of die results to use.

    Returns void

    If values.length does not equal numDice.

  • Seed 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).

    Parameters

    • ...values: number[]

      Die values the next rolls should use, in order.

    Returns void