RNG streams
Every random draw in osrlib comes from a named stream, and every stream is forked from the session's master seed. Given the same master seed and the same stream key, a stream always produces the identical sequence of draws — and it produces that sequence no matter what any other stream does. Drawing a hundred rolls from the treasure stream never changes what the combat stream yields next. That per-key independence is what makes deterministic replays and saved games reliable: two sessions built from the same seed replay identically, and adding new draws to one subsystem never shifts another subsystem's rolls.
Each stream is identified by a plain string key, such as "combat" or "treasure".
Code that uses the kernel functions directly — à la carte, outside of a running game —
passes an explicit stream into each function call. A GameSession
does this wiring for you: it owns an RngStreams container built from the session's
master seed and hands out the correctly named stream wherever a kernel function needs
one, so ordinary gameplay never requires touching a stream directly.
There are 13 named streams in total. The table below lists each one; the sections that follow give more detail on what each stream governs.
| Stream key | Constant | Governs |
|---|---|---|
"character_creation" |
CHARACTER_CREATION_STREAM |
Character creation: ability scores, first-level hit points, starting gold. |
"advancement" |
ADVANCEMENT_STREAM |
In-play advancement: level-up hit point rolls. |
"combat" |
COMBAT_STREAM |
Battle resolution: attack rolls, damage rolls, saving throws, morale checks, initiative, reaction rolls. |
"effects" |
EFFECTS_STREAM |
Effect-internal draws: onset and duration dice, revival delays. |
"monster_spawn" |
MONSTER_SPAWN_STREAM |
Monster spawning: hit point rolls when a monster instance is created. |
"npc_party" |
NPC_PARTY_STREAM |
NPC adventuring-party generation: composition, class and level, ability scores, hit points, spell picks. |
"magic" |
MAGIC_STREAM |
Spell resolution: targeting, damage, cast-time forced saves, dispel survival rolls, turning undead. |
"treasure" |
TREASURE_STREAM |
Treasure generation: presence rolls, quantity dice, per-item resolution, magic item rolls. |
"wandering" |
WANDERING_STREAM |
Wandering monsters: the wandering check, group counts, variant picks. |
"encounter" |
ENCOUNTER_STREAM |
Encounter setup: surprise, distance, reaction rolls, distraction, and group counts for monsters or NPC parties spawned by command. |
"exploration" |
EXPLORATION_STREAM |
Exploration: forcing doors, listening, searching, traps, tinder, and thief skill checks. |
"monster_action" |
MONSTER_ACTION_STREAM |
Monster action policy during battle: which action a monster group takes each round and which target it picks. |
"adjudication" |
ADJUDICATION_STREAM |
The referee's ad-hoc adjudication rolls: freeform dice commanded through the seeded session. |
Character streams
Character creation and in-play advancement are split into two separate streams so that changing one never disturbs the other's draws.
The CHARACTER_CREATION_STREAM
(key "character_creation") covers one-time creation draws: rolling ability scores,
first-level hit points, and starting gold.
The ADVANCEMENT_STREAM (key
"advancement") covers hit point rolls when a character levels up during play.
Combat and effects streams
The COMBAT_STREAM (key "combat") covers the
battle-resolution kernel: attack rolls, damage rolls, saving throws, morale checks,
initiative, and reaction rolls made in combat.
The EFFECTS_STREAM (key "effects") is
separate from combat and covers draws internal to the effects engine: rolled onset
and duration dice for conditions such as poison or paralysis, and revival delays.
Keeping this on its own stream means a change to how battle resolves never shifts
which round an effect ticks or expires.
Monster and NPC streams
The MONSTER_SPAWN_STREAM (key
"monster_spawn") covers hit point rolls at the moment a monster instance is spawned
from its template.
The NPC_PARTY_STREAM (key "npc_party") covers
generating an NPC adventuring party through the same character-creation kernel player
characters use: party composition, each member's class and level, ability scores,
hit points, and spell picks. An NPC party's treasure and any Expert-class magic items
are generated on the treasure stream instead, since they are treasure procedures.
Magic stream
The MAGIC_STREAM (key "magic") covers every
draw made while resolving a spell: targeting, damage dice, touch-attack rolls,
cast-time forced saving throws, dispel-survival rolls, and both rolls involved in
turning undead. Durations rolled when an effect attaches, and saves rolled later when
that effect ticks (such as a charm spell's periodic re-save), draw from the effects
stream instead, following the same convention as the rest of the effects engine.
Treasure stream
The TREASURE_STREAM (key "treasure")
covers treasure generation end to end, in the order a treasure entry is printed:
whether a treasure type is present at all, how much of it there is, and the
resolution of each individual coin hoard, gem, piece of jewellery, or magic item.
Crawl-session streams
Five streams belong to the dungeon-crawl loop and are keyed on
GameSession rather than a kernel module, since
they only make sense in the context of a running session.
The WANDERING_STREAM (key "wandering")
covers the wandering-monster check itself, how many monsters appear, and which
variant appears when a wandering table entry has more than one.
The ENCOUNTER_STREAM (key "encounter")
covers everything that happens once an encounter starts: surprise rolls, the
distance at which the two sides meet, reaction rolls, and mid-encounter distraction
checks. It also covers the group-size roll when a monster group or NPC party is
spawned directly by command with dice rather than a fixed count.
The EXPLORATION_STREAM (key
"exploration") covers the rest of dungeon exploration: forcing doors, listening at
doors, searching for secret doors or traps, disarming or triggering traps, lighting
tinder, and thief skill checks such as picking locks.
The MONSTER_ACTION_STREAM (key
"monster_action") covers the action policy that drives monster groups during
battle: which action a group takes on its turn and which target it selects. Keeping
this on its own stream means swapping in a different monster action policy never
shifts the combat stream's attack and damage rolls.
The ADJUDICATION_STREAM (key
"adjudication") covers the referee's ad-hoc rolls for freeform adjudication —
dice commanded through the seeded session to resolve a chance outcome the content
model can't express, such as whether a frayed rope holds. Keeping these on their own
stream means an ad-hoc referee roll never perturbs the draw sequence of a keyed
mechanic, so the outcomes of encounters, combat, and exploration stay fixed under
replay no matter how many adjudication rolls the referee interleaves.
Stream independence in practice
The following example creates two independent RngStreams containers from the same
master seed and shows that the "combat" stream produces the same sequence in both,
even after one of the containers draws from an unrelated "treasure" stream:
from osrlib.core.rng import RngStreams
streams_a = RngStreams(master_seed=42)
streams_b = RngStreams(master_seed=42)
combat_a = streams_a.get("combat")
combat_b = streams_b.get("combat")
# Same master seed and same stream key always yield the same draw sequence.
assert combat_a.next_uint64() == combat_b.next_uint64()
# Drawing from an unrelated stream doesn't perturb the combat stream's sequence.
streams_a.get("treasure").next_uint64()
assert combat_a.next_uint64() == combat_b.next_uint64()