@patterkit/runtime 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +91 -0
- package/dist/index.cjs +1281 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +626 -0
- package/dist/index.d.ts +626 -0
- package/dist/index.js +1249 -0
- package/dist/index.js.map +1 -0
- package/dist/patterplay.min.js +3 -0
- package/dist/patterplay.min.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/engine.ts","../src/tags.ts","../src/gamedata.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @patterkit/runtime - public surface.\n//\n// The reference runtime. Construct an `Engine` from a compiled Bundle (the world\n// + flow manager: shared scope state, foreign scopes, whole-game save/load), then\n// `engine.openFlow(id, { scene })` to get a `Flow` and play it (advance / choices\n// / properties). Many flows run concurrently, sharing the shared `@patter`/`@scene`\n// state, each with its own per-flow half + cursor + PRNG.\n// ---------------------------------------------------------------------------\n\nexport { Engine, Flow } from \"./engine.js\";\n// The compiled-bundle type the Engine constructor consumes (from the shared model), so hosts can\n// type a parsed .patterc without depending on @patterkit/model directly.\nexport type { Bundle } from \"@patterkit/model\";\nexport type {\n StepResult, AdvanceToStopResult, ChoiceOption, EngineOptions, OpenFlowOptions, WorldResolver, PropertyRow,\n EngineSave, SaveGame, FlowSnapshot, SelectorSnapshot, SavedChoice, StackFrame,\n BeatInfo, OutlineNode, OutlineBlock, OutlineScene, FlatBeat,\n} from \"./engine.js\";\n\n// gameData read helpers (sparse overrides + field-default merge).\nexport { gameDataFields, gameDataValue, effectiveGameData } from \"./gamedata.js\";\n\n// Author tags (#215): accumulated node-tag index (also surfaced via Engine.tagsFor* + step.tags).\nexport { buildTagIndex } from \"./tags.js\";\n","// ---------------------------------------------------------------------------\n// @patterkit/runtime - the reference runtime.\n//\n// An `Engine` is the world + flow manager: it owns the compiled Bundle, the\n// shared state (shared `@patter` globals + shared `@scene` props + host foreign\n// scopes), and a set of named **flows**. All *play* happens on a `Flow` handle\n// (`engine.openFlow(id, ...)`): a flow has its own execution cursor, its own PRNG,\n// and its own copy of the NOT-shared state (per-flow `@patter` globals + per-flow\n// `@scene` props). Multiple flows run concurrently and independently - a flow is\n// addressed explicitly (`alice.advance()`), so there is no ambient \"current flow\".\n//\n// Scopes are just two tokens - `@patter` (global; bare `@name`) and `@scene`\n// (scene-local) - with an orthogonal per-property `shared` flag (default: shared\n// for `@patter`, per-flow for `@scene`). So each token spans two storage areas:\n// the shared half lives on the engine, the per-flow half on the flow; a read/write\n// routes by the property's `shared` flag. (Mirrors Storylet Studio's @world/@site.)\n//\n// A flow plays the select-one-child model (spec §4): a block branches one\n// eligible child; a group runs its selector (branch / sequence / choice -\n// `sequence` covers order x exhaust); a `choice` group stops for the host; a snippet runs onEnter, delivers\n// beats, runs onExit, follows its jump. Falling off the end ends the flow.\n// Cross-flow jumps are not a thing - the host switches flows.\n//\n// `engine.saveGame()` / `loadGame()` snapshot + restore the WHOLE game: `@patter`\n// plus every live flow's scopes + PRNG + cursor.\n// ---------------------------------------------------------------------------\n\nimport { evaluate, deserialiseAst } from \"@wildwinter/expr\";\nimport type { ScalarValue, EvalContext, ExprNode } from \"@wildwinter/expr\";\nimport { ScopeRegistry } from \"@wildwinter/scoperegistry\";\nimport type { ScopeDeclaration, ScopeResolver } from \"@wildwinter/scoperegistry\";\nimport { patterDialect, interpolate, splitRef, stripCaptions } from \"@patterkit/dialect\";\nimport { walkNodes, effectiveGameId, castStringKey, DEFAULT_CAPTION_DELIMITERS, DEFAULT_CAPTION_CHARACTER } from \"@patterkit/model\";\nimport { buildTagIndex } from \"./tags.js\";\nimport type {\n Bundle, CompiledScene, CompiledBlock, CompiledGroup, CompiledSnippet,\n CompiledEffect, Beat, LineBeat, TextBeat, GameData, Expression, PropertyDecl, PropertyType, Jump, HostScopeDecl,\n} from \"@patterkit/model\";\n\ntype SelectableNode = CompiledGroup | CompiledSnippet;\n\n// Compiled expressions are immutable, so each one's AST is deserialised once -\n// per evaluation was the engine's hottest path (every condition / effect / slot).\nconst astCache = new WeakMap<Expression, ExprNode>();\n\n/** A property-state snapshot: owned scope -> property name -> value. */\nexport type EngineSave = Record<string, Record<string, ScalarValue>>;\n\n/** Serialised `sequence` selector visit state for one group (spec §4 / §7). */\nexport interface SelectorSnapshot {\n seq?: number; // sequential cursor (visits taken)\n bag?: string[]; // shuffle: child ids still undrawn this pass\n last?: string; // last child id picked (no-immediate-repeat)\n}\n\n/** One entry on a flow's continuation stack: a position within a container's children. */\nexport interface StackFrame {\n sceneId: string;\n /** A block id or a run-group id (both are sequential containers). */\n containerId: string;\n index: number;\n /** SNAPSHOT-ONLY (never set on a live frame): the id of the child at `index` when the save was\n * taken. On restore the child is re-found by this id, so a save survives siblings being inserted,\n * removed, or reordered before the cursor (live bundle refresh / patched-game saves). Absent (an\n * older save, or a frame saved at its container's end) falls back to the raw `index`. */\n nextId?: string;\n}\n\n/** The serialised cursor + scopes + PRNG of a single flow. */\nexport interface FlowSnapshot {\n /** This flow's owned-scope values = the NOT-shared `@patter` globals (under token \"patter\"). */\n scopes: EngineSave;\n /** Per-scene NOT-shared `@scene` bags (scene id -> name -> value); persist across re-entries (spec §7). */\n sceneBags: Record<string, Record<string, ScalarValue>>;\n /** This flow's built-in PRNG position (mulberry32 state). */\n rngState: number;\n /** This flow's per-node entry counts (node id -> times entered by this flow). */\n visits: Record<string, number>;\n cursor: {\n flowEnded: boolean;\n currentSceneId: string | null;\n /** The continuation stack (call frames + the active block run). */\n stack: StackFrame[];\n activeSnippetId: string | null;\n beatIndex: number;\n /** The pending choice's exact option set, REPLAYED on load (schema 9.3). */\n pendingChoice: SavedChoice | null;\n /** The chosen option owning a prompt still to be replayed (save taken between choose + advance).\n * Optional / absent in older saves -> no pending prompt. */\n pendingPromptOwnerId?: string | null;\n /** This flow's `sequence` selector cursors. */\n selectors: Record<string, SelectorSnapshot>;\n };\n}\n\n/**\n * A pending choice as saved: the option set the player was shown, restored\n * verbatim - re-deriving on load would re-evaluate conditions (consuming PRNG\n * draws a second time) and could mutate the choice under the player.\n */\nexport interface SavedChoice {\n groupId: string;\n options: ChoiceOption[];\n}\n\n/** A full resumable save-game: shared `@patter` state + every live flow. */\nexport interface SaveGame {\n version: number;\n /** Shared `@patter` globals (owned scope \"patter\"). */\n shared: EngineSave;\n /** World-wide per-node entry counts (node id -> times entered by any flow). */\n sharedVisits: Record<string, number>;\n /** Shared selector cursors (node id -> snapshot) for `shared` memoried selectors. */\n sharedSelectors: Record<string, SelectorSnapshot>;\n /** Shared, scene-namespaced `@scene` bags (scene id -> name -> value) - the shared scene props. */\n stageBags: Record<string, Record<string, ScalarValue>>;\n /** Each live flow's snapshot, keyed by flow id. */\n flows: Record<string, FlowSnapshot>;\n}\n\n/** What `Flow.advance()` surfaces to the host at each stop. */\nexport type StepResult =\n | { type: \"line\"; id: string; text: string; character?: string; characterName?: string; direction?: string; gameData?: GameData; tags?: string[] }\n | { type: \"text\"; id: string; text: string; gameData?: GameData; tags?: string[] }\n | { type: \"gameEvent\"; id: string; gameData?: GameData; tags?: string[] }\n | { type: \"choice\"; groupId: string; options: ChoiceOption[] }\n | { type: \"end\" };\n\n// --- Static structure introspection (editor / dev tooling) -------------------\n// A read-only view of the AUTHORED tree (scenes -> blocks -> groups/snippets -> beats), for dev\n// tools that build against the writer's structure (e.g. an Unreal Sequencer of subsequences per\n// beat). Static: no flow, no play state. Per-beat data mirrors what a StepResult would carry\n// (source text, author gameData, accumulated tags), read at the default locale.\n\n/** One beat's static data - the same shape a delivered step carries, resolved at the source locale. */\nexport interface BeatInfo {\n id: string;\n kind: \"line\" | \"text\" | \"gameEvent\";\n /** Speaker token (line only). */\n character?: string;\n /** Resolved display name for `character` (source locale), if the cast declares one. */\n characterName?: string;\n /** Performance direction (line only). */\n direction?: string;\n /** Source text, un-interpolated (line / text). Omitted for gameEvent and IDs-only bundles. */\n text?: string;\n /** Author gameData overrides on this beat (raw, as the step carries them). Omitted when empty. */\n gameData?: GameData;\n /** Accumulated author tags (scene -> block -> group(s) -> snippet -> beat). Omitted when empty. */\n tags?: string[];\n}\n\n/** A node in the outline tree: a group (with its selector + children) or a snippet (with its beats). */\nexport interface OutlineNode {\n type: \"group\" | \"snippet\";\n id: string;\n tags?: string[];\n // group only\n selector?: string;\n /** A choice/option group's prompt beat, if any. */\n prompt?: BeatInfo;\n children?: OutlineNode[];\n // snippet only\n beats?: BeatInfo[];\n jumpTo?: string;\n jumpMode?: \"jump\" | \"call\";\n}\n\n/** A block in the outline tree. */\nexport interface OutlineBlock {\n id: string;\n gameId?: string;\n name: string;\n tags?: string[];\n children: OutlineNode[];\n}\n\n/** A scene in the outline tree. */\nexport interface OutlineScene {\n id: string;\n gameId?: string;\n name: string;\n tags?: string[];\n blocks: OutlineBlock[];\n}\n\n/** One beat in document order, with the scene/block/snippet it lives in (the flat view). */\nexport interface FlatBeat {\n sceneId: string;\n blockId: string;\n snippetId: string;\n beat: BeatInfo;\n}\n\n/** What {@link Flow.advanceToStop} returns: the beats walked, and the choice / end that stopped it. */\nexport interface AdvanceToStopResult {\n /** The line / text / game-event beats played on the way to the stop (never a choice / end). */\n played: Array<Extract<StepResult, { type: \"line\" | \"text\" | \"gameEvent\" }>>;\n stop: Extract<StepResult, { type: \"choice\" | \"end\" }>;\n}\n\n/** The choice text of an option (spec §5): its `prompt` beat, resolved + interpolated. */\nexport interface ChoicePrompt {\n kind: \"line\" | \"text\";\n /** Display text (interpolated; may be empty - the host can render from gameData / an icon). */\n text: string;\n /** Speaker / direction - present only for a `line` prompt (the PC's spoken choice). */\n character?: string;\n /** The speaker's resolved player-facing name (locale-aware; absent when the character has none). */\n characterName?: string;\n direction?: string;\n}\n\n/** A single option of a pending `choice` group. */\nexport interface ChoiceOption {\n /** The option's id (an Option group, or a degenerate option snippet) - pass to `choose()`. */\n id: string;\n /**\n * The option's `prompt` (spec §5) - the choice text as a structured line/text beat. For the\n * degenerate bare-snippet tolerance, derived from the snippet's first content line. Undefined\n * only when even that is absent; internal ids are never leaked as display text.\n */\n prompt?: ChoicePrompt;\n /** False when the option's condition fails; still returned (greyed) unless hidden. */\n eligible: boolean;\n gameData?: GameData;\n}\n\n/**\n * The host's **World Properties** resolver: a `{ get, set? }` the game provides so the story can read\n * (and, if you allow it, write) its `@world.*` values at runtime. Property metadata (types, read-only)\n * comes from the compiled bundle's declared world properties; the values themselves live in the host and\n * are never stored or saved by this engine.\n */\nexport type WorldResolver = ScopeResolver;\n\nexport interface EngineOptions {\n /**\n * Custom float-in-[0,1) source for `random()` / shuffle, shared by all flows.\n * Overrides the built-in seeded PRNG - but its position is NOT captured by\n * `saveGame()`. For resumable runs, use the built-in per-flow seed instead.\n */\n rng?: () => number;\n /** Default seed for each flow's built-in (serialisable) PRNG; override per flow in `openFlow`. */\n seed?: number;\n /** Active locale for string lookups (embedded localisation). Defaults to the bundle's default locale.\n * Ignored by an \"ids\" bundle, which emits beat IDs for the game to localise itself. */\n locale?: string;\n /** The host's resolver for **World Properties** (`@world.*`): the values the game owns and the story\n * reads. Omit it and the runtime self-backs `@world` from the declared defaults. Shared by all flows. */\n world?: WorldResolver;\n /**\n * Replay a chosen option's `prompt` as its first played beat (spec §5). Default `false`:\n * the prompt is a label only and `choose()` plays just the option's content. `true`: the\n * prompt beat is delivered first (the choice \"spoken back\"). A host decision, not authored.\n */\n replayPromptOnChoose?: boolean;\n /** Closed captions (#214): show non-spoken caption cues inside dialogue lines (the `[sigh]` in\n * `Oh dear. [sigh] What now?`). Default `true` (full text). `false` strips every cue + its delimiters\n * and collapses the whitespace - for a player who hears the audio and doesn't want the captions.\n * Toggle live with `engine.setClosedCaptions(...)`. */\n closedCaptions?: boolean;\n /** Diagnostics hook (opt-in, dev tooling only): fired with the choice's group id whenever a choice runs\n * DRY - no takeable option and no eligible fallback - so it falls through silently. The behaviour is\n * unchanged; this only makes the fall-through observable. The coverage harness uses it to flag choices\n * that ran dry. Leave it unset in shipped games (zero cost). */\n onDryChoice?: (groupId: string) => void;\n}\n\n/** One shared `@patter` property, for a live state inspector: its ref, declared type, current value,\n * declared default (for reset), and enum options. Mirrors the Unity / Godot ports' ListProperties. */\nexport interface PropertyRow {\n ref: string;\n type: PropertyType;\n value: ScalarValue | undefined;\n default: ScalarValue;\n values?: string[];\n}\n\n/** Options for opening a flow. */\nexport interface OpenFlowOptions {\n /** Scene to start at - its host-facing gameId (address) OR its internal id; defaults to the\n * bundle's first scene. */\n scene?: string;\n /** Block within the scene to start at - its gameId (scene-scoped address) OR its internal id. */\n block?: string;\n /** Seed for this flow's PRNG (defaults to the engine's `seed`). */\n seed?: number;\n}\n\ninterface ChoiceState {\n /** The choice group's id (saved alongside the verbatim option set - SavedChoice). */\n groupId: string;\n options: ChoiceOption[];\n byId: Map<string, SelectableNode>;\n}\n\ninterface SelectorState {\n seq?: number; // sequential cursor (visits taken)\n bag?: string[]; // shuffle: child ids still undrawn this pass (undefined = not started)\n last?: string; // last child id picked (no-immediate-repeat across reshuffles)\n}\n\n/** Shared, read-mostly context the engine hands to every flow it owns. */\ninterface FlowHost {\n bundle: Bundle;\n /** IDs-only build (`localisation.mode === \"ids\"`, no source-debug): the engine emits each beat's ID as\n * its text and omits character display names, leaving localisation to the game (use `flow.interpolate`\n * to apply `{@ref}` property replacement to a string the game looked up itself). */\n emitIds: boolean;\n strings: Record<string, string>;\n /** The DEFAULT locale's string table - fallback for a key the active locale is missing (notably the\n * cast display-name keys, seeded there from `displayName`). */\n defaultStrings: Record<string, string>;\n /** Cast canonical name -> authoring `displayName` (the unlocalised fallback when no loc string exists). */\n castDisplay: Map<string, string>;\n nodeIndex: Map<string, SelectableNode>;\n blockIndex: Map<string, { sceneId: string }>;\n blockById: Map<string, CompiledBlock>;\n /** Author tags (#215): node id -> accumulated tags (own + every ancestor's, deduped). Built once. */\n tagIndex: Map<string, string[]>;\n /** The SHARED `@patter` globals (owned scope \"patter\") + world properties (`@world`). */\n shared: ScopeRegistry;\n /** Decls for the shared `@patter` globals - (re)seed on `engine.reset()`. */\n patterSharedDecls: ScopeDeclaration[];\n /** Decls for the per-flow `@patter` globals - seed each flow's local registry. */\n patterLocalDecls: ScopeDeclaration[];\n /** Lowercase names of the SHARED globals (route a `@patter` ref to engine vs flow). */\n patterSharedNames: Set<string>;\n /** Per-scene set of SHARED `@scene` prop names (route a `@scene` ref to stage vs flow). */\n sceneSharedNames: Map<string, Set<string>>;\n /** World-wide per-node entry counts (node id -> times entered by any flow). */\n sharedVisits: Map<string, number>;\n /** Shared selector cursors (node id -> SelectorState) for `shared` memoried selectors. */\n sharedSelectors: Map<string, SelectorState>;\n /** Shared, scene-namespaced `@scene` bags (scene id -> name -> value) for shared scene props. */\n stageBags: Map<string, Record<string, ScalarValue>>;\n customRng?: () => number;\n /** Play a chosen option's prompt as its first beat (spec §5); default false. */\n replayPromptOnChoose?: boolean;\n /** Closed captions (#214). `captionsOn`: show caption cues in dialogue lines (default true); when\n * false the engine strips `captionOpen`…`captionClose` spans from line text. Mutable via\n * `setClosedCaptions` (one toggle, all flows - like setLocale). */\n captionsOn: boolean;\n captionOpen: string;\n captionClose: string;\n /** A cast member whose lines are pure captions: when captions are off ALL of its dialogue + speaker is\n * omitted (a silent line), delimiters or not. Default `SFX`. Empty = no caption character. */\n captionCharacter: string;\n /** Diagnostics hook (opt-in, dev only): fired when a choice runs DRY - nothing takeable and no eligible\n * fallback - so it falls through and the flow continues past it. Zero cost when unset; the coverage\n * harness passes it to surface silent fall-throughs. Not a gameplay signal (the behaviour is unchanged). */\n onDryChoice?: (groupId: string) => void;\n /** Memoised `splitRef` results (ref string -> {scope,name}). The split depends only on `shared`'s scope\n * set, which is fixed for the engine's life, so every effect target / `{@ref}` slot parses once. */\n refSplitCache: Map<string, { scope: string; name: string }>;\n}\n\n// ---------------------------------------------------------------------------\n// Engine - the world + flow manager\n// ---------------------------------------------------------------------------\n\nexport class Engine {\n private readonly host: FlowHost;\n private readonly defaultSeed: number;\n private readonly flowsById = new Map<string, Flow>();\n /** Every locale's string table (the inline `bundle.strings`), kept so the active locale can be swapped\n * live (setLocale) without rebuilding the engine. Reassigned wholesale by `replaceStrings`\n * (live bundle refresh, tier 1), hence not readonly. */\n private allStrings: Record<string, Record<string, string>>;\n /** The currently active locale (string lookups + character names resolve in it). */\n private currentLocale: string;\n /** True for a source-only DEBUG build (`localisation: { mode: \"ids\", sourceDebug: true }`) - the strings\n * are the source language, embedded only so the build can be played; not a shippable localised build. */\n private readonly sourceDebug: boolean;\n /** Host-facing addresses (spec §6): scene gameId -> internal id (project-wide), and per-scene\n * block gameId -> internal id. The effective gameId falls back to the name slug when unpinned. */\n private readonly sceneGameIdToId = new Map<string, string>();\n private readonly blockGameIdToId = new Map<string, Map<string, string>>();\n\n /** The options this engine was built with - reused verbatim by `hotSwap` so the replacement\n * engine keeps the same world resolver, custom RNG, and diagnostic hooks. */\n private readonly creationOptions: EngineOptions;\n\n constructor(bundle: Bundle, options: EngineOptions = {}) {\n this.creationOptions = options;\n const locale = options.locale ?? bundle.locales.default;\n const allStrings = bundle.strings;\n this.allStrings = allStrings;\n this.currentLocale = locale;\n const strings = allStrings[locale] ?? {};\n const defaultStrings = allStrings[bundle.locales.default] ?? {};\n // Localisation mode (spec §11). \"ids\" + no source-debug = the engine emits beat IDs (the game localises\n // itself). A source-debug build still resolves its embedded source strings, but is flagged for a warning.\n const loc = bundle.localisation;\n const emitIds = loc?.mode === \"ids\" && !loc.sourceDebug;\n this.sourceDebug = loc?.mode === \"ids\" && !!loc.sourceDebug;\n if (this.sourceDebug && typeof console !== \"undefined\") {\n console.warn(\"[Patterplay] source-only DEBUG build: strings are the source language for debugging, not a shippable localised build.\");\n }\n // Cast name -> displayName: the unlocalised fallback for a character's shown name when neither the\n // active nor the default locale carries a `cast:<name>` string.\n const castDisplay = new Map<string, string>();\n for (const c of bundle.cast ?? []) if (c.displayName) castDisplay.set(c.name, c.displayName);\n this.defaultSeed = (options.seed ?? 0x9e3779b9) >>> 0;\n\n const nodeIndex = new Map<string, SelectableNode>();\n const blockIndex = new Map<string, { sceneId: string }>();\n const blockById = new Map<string, CompiledBlock>();\n for (const [sceneId, scene] of Object.entries(bundle.scenes)) {\n this.sceneGameIdToId.set(effectiveGameId(scene), sceneId);\n const blockAddrs = new Map<string, string>();\n for (const block of scene.blocks) {\n blockIndex.set(block.id, { sceneId });\n blockById.set(block.id, block);\n blockAddrs.set(effectiveGameId(block), block.id);\n walkNodes<SelectableNode>(block.children, (n) => nodeIndex.set(n.id, n));\n }\n this.blockGameIdToId.set(sceneId, blockAddrs);\n }\n\n // Globals (`@patter`) split by the `shared` flag (default shared): shared ones\n // live in the engine's owned scope, per-flow ones seed each flow's registry.\n const props = bundle.properties ?? [];\n const patterSharedDecls = props.filter((p) => p.shared ?? true).map(toDecl);\n const patterLocalDecls = props.filter((p) => !(p.shared ?? true)).map(toDecl);\n const patterSharedNames = new Set(patterSharedDecls.map((d) => d.name.toLowerCase()));\n\n const shared = new ScopeRegistry().defineOwned(\"patter\", patterSharedDecls);\n const hostBound = new Set<string>();\n // The host's World Properties resolver binds `@world`; its declarations (types, read-only) come from\n // the compiled bundle's declared world properties. An explicit binding always wins over the self-backed\n // fallback below.\n if (options.world) {\n const worldSpec = bundle.scopeRegistry?.scopes.find((s) => s.token === \"world\");\n const decls = (worldSpec?.declarations ?? []).map(toForeignDecl);\n shared.defineForeign(\"world\", options.world, decls, worldSpec?.writable ?? true);\n hostBound.add(\"world\");\n }\n // A project that DECLARES `@world` but whose embedder binds no resolver (the standalone case) gets a\n // self-backed one: a live in-memory bag seeded from the declarations' defaults. The story reads/writes\n // it like any scope; it stays *foreign* (not in Patter's save: the host owns it conceptually).\n for (const spec of bundle.scopeRegistry?.scopes ?? []) {\n if (hostBound.has(spec.token)) continue;\n const decls = (spec.declarations ?? []).map(toForeignDecl);\n shared.defineForeign(spec.token, selfBackedResolver(spec.declarations ?? []), decls, spec.writable ?? true);\n }\n\n // Scene props (`@scene`) split by `shared` (default per-flow): record, per\n // scene, which names are shared so a `@scene` ref routes to stage vs flow.\n const sceneSharedNames = new Map<string, Set<string>>();\n for (const [sceneId, scene] of Object.entries(bundle.scenes)) {\n const names = new Set((scene.sceneProps ?? []).filter((p) => p.shared ?? false).map((p) => p.name.toLowerCase()));\n sceneSharedNames.set(sceneId, names);\n }\n\n this.host = {\n bundle, emitIds, strings, defaultStrings, castDisplay, nodeIndex, blockIndex, blockById,\n tagIndex: buildTagIndex(bundle), shared,\n patterSharedDecls, patterLocalDecls, patterSharedNames, sceneSharedNames,\n sharedVisits: new Map(),\n sharedSelectors: new Map(),\n stageBags: new Map(),\n customRng: options.rng,\n onDryChoice: options.onDryChoice,\n replayPromptOnChoose: options.replayPromptOnChoose ?? false,\n captionsOn: options.closedCaptions ?? true, // captions shown by default (full text)\n captionOpen: (bundle.closedCaptions ?? DEFAULT_CAPTION_DELIMITERS).open,\n captionClose: (bundle.closedCaptions ?? DEFAULT_CAPTION_DELIMITERS).close,\n captionCharacter: bundle.closedCaptions?.character || DEFAULT_CAPTION_CHARACTER, // absent/empty -> SFX\n refSplitCache: new Map(),\n };\n }\n\n /** The active locale (string + character-name lookups resolve in it). */\n get locale(): string { return this.currentLocale; }\n\n /** True for a source-only DEBUG build: the embedded strings are the source language (for debugging),\n * not a shippable localised build. An IDs-only ship build is `false`. */\n get isSourceDebug(): boolean { return this.sourceDebug; }\n\n /**\n * Switch the active locale LIVE - a real game's \"language\" setting can change mid-session. Subsequent\n * string lookups (new beats, re-resolved character names, `{@ref}` interpolation) render in the new\n * locale; everything else - flow position, `@patter`/`@scene` state, visit counts, the PRNG - is\n * untouched (already-emitted text isn't retro-translated; that's the host's call). A locale with no\n * table resolves every string via the `<Untranslated: {id}>` source fallback. All open flows share the\n * engine's string table, so the swap reaches every flow at once.\n */\n setLocale(locale: string): void {\n this.currentLocale = locale;\n this.host.strings = this.allStrings[locale] ?? {};\n }\n\n /**\n * Live bundle refresh, tier 1 (strings only): swap every locale's string table in place from a\n * freshly compiled bundle whose STRUCTURE is unchanged (same `content.structureHash`). Like\n * setLocale, nothing restarts and no flow is touched: the next delivered beat reads the new text,\n * `{@ref}` slots re-interpolate, and beats the host already received keep the words it saw. The\n * swap reaches every open flow at once and is not part of save state. Structural edits need the\n * full save/load hot swap instead (a structure change here simply won't show).\n */\n replaceStrings(bundle: Bundle): void {\n this.allStrings = bundle.strings;\n this.host.strings = this.allStrings[this.currentLocale] ?? {};\n this.host.defaultStrings = this.allStrings[this.host.bundle.locales.default] ?? {};\n }\n\n /**\n * Live bundle refresh, tier 2 (full swap): rebuild on an edited bundle with the whole run carried\n * over. Snapshot (`saveGame`), construct a fresh engine on `bundle` with THIS engine's original\n * options (same world resolver, RNG, hooks), restore (`loadGame`), and carry over the presentation\n * state that deliberately isn't save state (active locale, closed-captions toggle). The\n * content-drift policy (§9.8) resolves edits under the cursor: stack frames re-find their next\n * child by id, drifted options drop, a vanished snippet is skipped.\n *\n * Returns the REPLACEMENT engine; this one is left untouched and should be discarded. Hosts\n * re-bind their flow handles via `next.getFlow(id)`. If the restore throws (defensive - §9.8\n * makes this unreachable for ordinary edits), the swap falls back to a cold engine with each\n * saved flow restarted from the top of the scene it was in.\n */\n hotSwap(bundle: Bundle): Engine {\n const snapshot = this.saveGame();\n const carryOver = (next: Engine): Engine => {\n next.setLocale(this.currentLocale);\n next.setClosedCaptions(this.host.captionsOn);\n return next;\n };\n const next = new Engine(bundle, this.creationOptions);\n try {\n next.loadGame(snapshot);\n return carryOver(next);\n } catch {\n // A partial load may have mutated `next`: fall back on a THIRD, cold engine and restart each\n // flow at the top of the scene it was in (dropped when that scene is gone too).\n const fresh = new Engine(bundle, this.creationOptions);\n for (const [id, f] of Object.entries(snapshot.flows)) {\n const sceneId = f.cursor.currentSceneId;\n try { fresh.openFlow(id, sceneId !== null ? { scene: sceneId } : {}); } catch { /* scene deleted: drop the flow */ }\n }\n return carryOver(fresh);\n }\n }\n\n /** Whether closed captions are currently shown (full dialogue text). */\n get closedCaptions(): boolean { return this.host.captionsOn; }\n\n /**\n * Turn closed captions on/off LIVE (#214). When OFF, subsequent dialogue lines have their caption\n * cues (`[sigh]` etc., between the project's delimiters) and the surrounding whitespace stripped;\n * narration, choice prompts, and everything else are untouched. Like setLocale this is a presentation\n * toggle - it reaches every open flow at once and isn't part of save state; already-emitted text is\n * not retro-edited. An IDs-only game applies the same rule itself via `flow.stripCaptions`.\n */\n setClosedCaptions(on: boolean): void {\n this.host.captionsOn = on;\n }\n\n /**\n * Open (and start) a named flow. Each flow has its own cursor, PRNG, and per-flow\n * half of the scopes (not-shared `@patter`/`@scene`); all flows share the shared\n * half. Re-opening an existing id replaces it with a fresh flow.\n */\n openFlow(id: string, opts: OpenFlowOptions = {}): Flow {\n const sceneId = this.resolveSceneRef(opts.scene);\n const blockId = this.resolveBlockRef(sceneId, opts.block);\n const flow = new Flow(id, this.host, opts.seed ?? this.defaultSeed);\n this.flowsById.set(id, flow);\n flow.start(sceneId, blockId);\n return flow;\n }\n\n /** Resolve a scene reference (a gameId address OR an internal id) to its internal id. */\n private resolveSceneRef(ref?: string): string | undefined {\n if (ref == null) return undefined;\n if (this.host.bundle.scenes[ref]) return ref; // already an internal id\n return this.sceneGameIdToId.get(ref) ?? ref; // a gameId, else pass through (start reports)\n }\n\n /** Resolve a block reference (a scene-scoped gameId OR an internal id) to its internal id. */\n private resolveBlockRef(sceneId: string | undefined, ref?: string): string | undefined {\n if (ref == null) return undefined;\n if (this.host.blockById.has(ref)) return ref; // already an internal id\n if (sceneId != null) { const id = this.blockGameIdToId.get(sceneId)?.get(ref); if (id) return id; }\n return ref; // pass through (start reports an unknown block)\n }\n\n /** The host-facing address (gameId) of a scene / block by internal id, or undefined if unknown.\n * The inverse of the resolve helpers - for a host that wants to display / log the address. */\n sceneAddress(sceneId: string): string | undefined {\n const scene = this.host.bundle.scenes[sceneId];\n return scene ? effectiveGameId(scene) : undefined;\n }\n blockAddress(blockId: string): string | undefined {\n const block = this.host.blockById.get(blockId);\n return block ? effectiveGameId(block) : undefined;\n }\n\n /**\n * Author tags (#215) accumulated for a beat by id: its own tags unioned with every ancestor's\n * (scene → block → group(s) → snippet → beat), deduped, outermost-first. The same value the beat's\n * delivered step carries. Empty array for an unknown id or a beat with no tags anywhere up the chain.\n */\n tagsForBeat(beatId: string): string[] {\n return this.host.tagIndex.get(beatId) ?? [];\n }\n /** A scene's own tags (by internal id or gameId address). Empty when none / unknown. */\n tagsForScene(sceneRef: string): string[] {\n const id = this.resolveSceneRef(sceneRef);\n return (id != null ? this.host.tagIndex.get(id) : undefined) ?? [];\n }\n /** A block's accumulated tags (scene + block), by scene + block ref (id or gameId). Empty when none / unknown. */\n tagsForBlock(sceneRef: string, blockRef: string): string[] {\n const sceneId = this.resolveSceneRef(sceneRef);\n const id = this.resolveBlockRef(sceneId, blockRef);\n return (id != null ? this.host.tagIndex.get(id) : undefined) ?? [];\n }\n\n /**\n * The authored structure as a nested tree: scenes -> blocks -> children (groups + snippets, groups\n * preserved) -> a snippet's beats. Static (no flow / play state); per-beat data is read at the source\n * locale. For dev tooling that builds against the writer's structure (see also {@link getBeatSequence}).\n */\n getOutline(): OutlineScene[] {\n return Object.values(this.host.bundle.scenes).map((scene) => ({\n id: scene.id,\n ...(effectiveGameId(scene) ? { gameId: effectiveGameId(scene) } : {}),\n name: scene.name,\n ...this.tagsField(scene.id),\n blocks: scene.blocks.map((block) => ({\n id: block.id,\n ...(effectiveGameId(block) ? { gameId: effectiveGameId(block) } : {}),\n name: block.name,\n ...this.tagsField(block.id),\n children: block.children.map((n) => this.outlineNode(n)),\n })),\n }));\n }\n\n /**\n * Every beat in document order, flattened (through groups), each with the scene / block / snippet it\n * belongs to and its static data. The linear view of {@link getOutline} - hand it to a tool that lays\n * one item per beat (e.g. an Unreal Sequencer of subsequences).\n */\n getBeatSequence(): FlatBeat[] {\n const out: FlatBeat[] = [];\n for (const scene of Object.values(this.host.bundle.scenes)) {\n for (const block of scene.blocks) {\n walkNodes<SelectableNode>(block.children, (n) => {\n if (n.type !== \"snippet\") return;\n for (const beat of n.beats ?? []) {\n out.push({ sceneId: scene.id, blockId: block.id, snippetId: n.id, beat: this.beatInfo(beat) });\n }\n });\n }\n }\n return out;\n }\n\n /** A node's outline entry: a group (selector + prompt + children) or a snippet (beats + jump). */\n private outlineNode(n: SelectableNode): OutlineNode {\n if (n.type === \"group\") {\n return {\n type: \"group\",\n id: n.id,\n ...this.tagsField(n.id),\n ...(n.selector ? { selector: n.selector } : {}),\n ...(n.prompt ? { prompt: this.beatInfo(n.prompt) } : {}),\n children: n.children.map((c) => this.outlineNode(c)),\n };\n }\n return {\n type: \"snippet\",\n id: n.id,\n ...this.tagsField(n.id),\n beats: (n.beats ?? []).map((b) => this.beatInfo(b)),\n ...(n.jump ? { jumpTo: n.jump.to, ...(n.jump.mode ? { jumpMode: n.jump.mode } : {}) } : {}),\n };\n }\n\n /** One beat's static data (source locale), the same shape a delivered step carries. */\n private beatInfo(beat: Beat): BeatInfo {\n const tags = this.host.tagIndex.get(beat.id);\n const info: BeatInfo = { id: beat.id, kind: beat.kind };\n if (beat.kind === \"line\") {\n if (beat.character !== undefined) {\n info.character = beat.character;\n const name = this.host.defaultStrings[castStringKey(beat.character)] ?? this.host.castDisplay.get(beat.character);\n if (name !== undefined) info.characterName = name;\n }\n if (beat.direction !== undefined) info.direction = beat.direction;\n }\n if (beat.kind === \"line\" || beat.kind === \"text\") {\n const source = this.host.defaultStrings[beat.id]; // source-locale text, un-interpolated\n if (source !== undefined) info.text = source;\n }\n if (beat.gameData && Object.keys(beat.gameData).length) info.gameData = beat.gameData;\n if (tags && tags.length) info.tags = tags;\n return info;\n }\n\n /** A `{ tags }` fragment for an id, present only when the id has accumulated tags (keeps output tidy). */\n private tagsField(id: string): { tags?: string[] } {\n const tags = this.host.tagIndex.get(id);\n return tags && tags.length ? { tags } : {};\n }\n\n /** Retrieve an open flow by id (undefined if none / closed). */\n getFlow(id: string): Flow | undefined {\n return this.flowsById.get(id);\n }\n\n /** All currently-open flows. */\n flows(): Flow[] {\n return [...this.flowsById.values()];\n }\n\n /** Close (remove) a flow. */\n closeFlow(id: string): void {\n this.flowsById.delete(id);\n }\n\n /**\n * Reset the whole game to its initial state: drop every flow, re-seed the shared\n * `@patter` globals to their declared defaults, and clear all shared state (shared\n * `@scene` bags, world visit counts). World properties are host-owned and untouched.\n * After reset, open fresh flows with `openFlow`.\n */\n reset(): void {\n this.flowsById.clear();\n this.host.shared.reseedOwned(\"patter\", this.host.patterSharedDecls);\n this.host.sharedVisits.clear();\n this.host.sharedSelectors.clear();\n this.host.stageBags.clear();\n }\n\n /** Read a shared (`@patter` / foreign) property by ref. `@scene` refs are rejected (flow-level). */\n getProperty(ref: string): ScalarValue | undefined {\n const { scope, name } = this.splitShared(ref);\n return this.host.shared.get(scope, name);\n }\n\n /** Write a shared (`@patter` / foreign) property by ref. `@scene` refs are rejected (flow-level). */\n setProperty(ref: string, value: ScalarValue): void {\n const { scope, name } = this.splitShared(ref);\n this.host.shared.set(scope, name, value);\n }\n\n /** The shared `@patter` properties, for a live state inspector: each with its ref, type, current\n * value, declared default (for reset), and enum options. Mirrors the Unity / Godot ports. */\n listProperties(): PropertyRow[] {\n return this.host.patterSharedDecls.map((d) => ({\n ref: `@${d.name}`,\n type: d.type as PropertyType,\n values: d.values,\n value: this.getProperty(`@${d.name}`),\n default: declDefault(d),\n }));\n }\n\n // @scene is scene-namespaced and needs a flow's current scene - silently\n // routing it into the shared bag (as a junk \"scene.x\" key) was a trap.\n private splitShared(ref: string): { scope: string; name: string } {\n let split = this.host.refSplitCache.get(ref);\n if (!split) { split = splitRef(ref, (t) => t === \"scene\" || this.host.shared.has(t)); this.host.refSplitCache.set(ref, split); }\n if (split.scope === \"scene\") {\n throw new Error(`'${ref}': @scene properties are scene-scoped - read/write them on a Flow, not the Engine`);\n }\n return split;\n }\n\n /** Snapshot shared `@patter` state only (for a unified cross-engine save blob, Phase D). */\n save(): EngineSave {\n return this.host.shared.save();\n }\n\n /** Restore shared `@patter` values (world properties untouched). */\n load(blob: EngineSave): void {\n this.host.shared.load(blob);\n }\n\n /** Snapshot the whole game: shared `@patter` + visit counts + every live flow. */\n saveGame(): SaveGame {\n const flows: Record<string, FlowSnapshot> = {};\n for (const [id, flow] of this.flowsById) flows[id] = flow.snapshot();\n return {\n version: 2,\n shared: this.host.shared.save(),\n sharedVisits: Object.fromEntries(this.host.sharedVisits),\n sharedSelectors: serialiseSelectors(this.host.sharedSelectors),\n stageBags: Object.fromEntries([...this.host.stageBags].map(([s, bag]) => [s, { ...bag }])),\n flows,\n };\n }\n\n /** Restore a `saveGame()`: shared globals + visit counts + shared scene bags + reconstruct every flow. */\n loadGame(save: SaveGame): void {\n if (save.version !== 2) throw new Error(`unsupported save version: ${save.version}`);\n this.host.shared.load(save.shared);\n this.host.sharedVisits.clear();\n for (const [id, n] of Object.entries(save.sharedVisits ?? {})) this.host.sharedVisits.set(id, n);\n this.host.sharedSelectors.clear();\n for (const [id, st] of deserialiseSelectors(save.sharedSelectors)) this.host.sharedSelectors.set(id, st);\n this.host.stageBags.clear();\n for (const [s, bag] of Object.entries(save.stageBags ?? {})) this.host.stageBags.set(s, { ...bag });\n this.flowsById.clear();\n for (const [id, snap] of Object.entries(save.flows)) {\n const flow = new Flow(id, this.host, this.defaultSeed);\n flow.restore(snap);\n this.flowsById.set(id, flow);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Flow - one playable flow (cursor + the per-flow half of @patter/@scene + PRNG)\n// ---------------------------------------------------------------------------\n\nexport class Flow {\n readonly id: string;\n private readonly host: FlowHost;\n private local: ScopeRegistry; // owns \"patter\" = the NOT-shared globals (this flow's copy)\n private rngState: number;\n\n // Execution cursor. The `stack` is the continuation stack: each frame is a\n // position within a block's children (the top frame is the active block run;\n // lower frames are pending call-returns). A snippet's beats deliver from\n // `activeSnippet`/`beatIndex`.\n private started = false;\n private flowEnded = false;\n private currentSceneId: string | null = null;\n private stack: StackFrame[] = [];\n private activeSnippet: CompiledSnippet | null = null;\n private beatIndex = 0;\n private pendingChoice: ChoiceState | null = null;\n /** When `replayPromptOnChoose`, the chosen option's prompt beat to deliver before its content. */\n private pendingPromptBeat: LineBeat | TextBeat | null = null;\n /** The chosen option that owns `pendingPromptBeat`, so a save taken between choose() and the next\n * advance() can re-derive the prompt on load (the beat isn't otherwise reachable by id). */\n private pendingPromptOwnerId: string | null = null;\n private selectors = new Map<string, SelectorState>();\n /** Per-node entry counts for this flow (node id -> times entered). */\n private visitCounts = new Map<string, number>();\n\n // Per-flow halves of the two scopes. The NOT-shared `@patter` globals live in\n // `local` (owned scope \"patter\"); the NOT-shared `@scene` props live in\n // `sceneBags` (namespaced per scene; they PERSIST across re-entries, spec §7).\n // The SHARED halves live on the host (`host.shared` / `host.stageBags`). Each\n // resolver presents one merged scope, routing each property to its half by the\n // declared `shared` flag.\n private sceneBags = new Map<string, Record<string, ScalarValue>>();\n\n private readonly patterResolver: ScopeResolver = {\n get: (n) => (this.host.patterSharedNames.has(n) ? this.host.shared.get(\"patter\", n) : this.local.get(\"patter\", n)),\n set: (n, v) => {\n if (this.host.patterSharedNames.has(n)) this.host.shared.set(\"patter\", n, v);\n else this.local.set(\"patter\", n, v);\n },\n };\n\n private readonly sceneResolver: ScopeResolver = {\n get: (n) => {\n const s = this.currentSceneId;\n if (s === null) return undefined;\n const bag = this.host.sceneSharedNames.get(s)?.has(n) ? this.host.stageBags.get(s) : this.sceneBags.get(s);\n return bag?.[n];\n },\n set: (n, v) => {\n const s = this.currentSceneId;\n if (s === null) return;\n const bag = this.host.sceneSharedNames.get(s)?.has(n) ? this.host.stageBags.get(s) : this.sceneBags.get(s);\n if (bag) bag[n] = v;\n },\n };\n\n // The eval context is built ONCE: every constituent resolves live state at\n // call time (shared bags mutate in place per scoperegistry's contract;\n // patter/scene route through this flow's resolvers, which read the current\n // `local`/`sceneBags`/`currentSceneId`; the host callbacks read current flow\n // fields). Rebuilding it per evaluation was the engine's hottest allocation.\n private readonly evalCtx: EvalContext;\n\n constructor(id: string, host: FlowHost, seed: number) {\n this.id = id;\n this.host = host;\n this.rngState = seed >>> 0;\n this.local = this.freshLocal();\n\n const scopes = { ...host.shared.toEvalContext().scopes }; // shared @patter bag + foreign resolvers\n scopes[\"patter\"] = this.patterResolver; // override with the merged shared+per-flow view\n scopes[\"scene\"] = this.sceneResolver;\n this.evalCtx = {\n scopes,\n host: {\n nextRandom: this.rng,\n visits: (id: string) => this.visitCounts.get(id) ?? 0,\n patterVisits: (id: string) => this.host.sharedVisits.get(id) ?? 0,\n },\n };\n }\n\n // -- Host API -------------------------------------------------------------\n\n /** Begin this flow at a scene (and optionally a specific block within it). */\n start(sceneId?: string, blockId?: string): void {\n this.sceneBags.clear();\n this.local = this.freshLocal();\n this.selectors.clear();\n this.visitCounts.clear();\n this.stack = [];\n this.currentSceneId = null;\n this.flowEnded = false;\n this.activeSnippet = null;\n this.beatIndex = 0;\n this.pendingChoice = null;\n this.started = true;\n\n if (blockId) {\n const loc = this.host.blockIndex.get(blockId);\n if (!loc) throw new Error(`unknown block: ${blockId}`);\n this.enterSceneSetup(loc.sceneId);\n this.stack = [{ sceneId: loc.sceneId, containerId: blockId, index: 0 }];\n this.enter(blockId);\n } else {\n const id = sceneId ?? Object.keys(this.host.bundle.scenes)[0];\n const scene = id ? this.host.bundle.scenes[id] : undefined;\n if (!scene) throw new Error(id ? `unknown scene: ${id}` : \"no scenes in bundle\");\n this.enterSceneSetup(id!);\n const first = scene.blocks[0];\n if (first) { this.stack = [{ sceneId: id!, containerId: first.id, index: 0 }]; this.enter(first.id); }\n }\n this.settle();\n }\n\n /**\n * Forget everything in this flow and begin again - its per-flow state (not-shared\n * `@patter` globals + `@scene` props), cursor, callstack, selector cursors, and\n * visit counts. Shared state (shared `@patter` / `@scene`, world visit counts) is\n * untouched. A clearer-named alias of `start()`.\n */\n reset(sceneId?: string, blockId?: string): void {\n this.start(sceneId, blockId);\n }\n\n /** The scene the cursor is currently in - set on entry and whenever a jump crosses scenes. Read\n * right after `advance()` to know which scene the just-played beat lives in (tooling that mirrors\n * the playhead, e.g. an editor following a cross-scene jump). `null` before the flow has started. */\n get currentScene(): string | null { return this.currentSceneId; }\n\n /** Run until the next line, game event, choice, or the end of the flow. */\n advance(): StepResult {\n if (!this.started) throw new Error(\"flow has not been started\");\n // A replayed prompt (replayPromptOnChoose) is delivered first, before the option's content.\n if (this.pendingPromptBeat) { const b = this.pendingPromptBeat; this.pendingPromptBeat = null; this.pendingPromptOwnerId = null; return this.beatResult(b); }\n this.settle();\n if (this.flowEnded) return { type: \"end\" };\n if (this.pendingChoice) return { type: \"choice\", groupId: this.pendingChoice.groupId, options: this.pendingChoice.options };\n if (!this.activeSnippet) { this.flowEnded = true; return { type: \"end\" }; }\n return this.beatResult(this.activeSnippet.beats![this.beatIndex++]!);\n }\n\n /**\n * Advance repeatedly, collecting every played beat, until a choice or the end - the \"play to the\n * next stop\" a host's play UI / tooling wants. The terminal `choice` / `end` is returned as `stop`;\n * `played` holds the line / text / game-event results walked on the way to it. Termination is guaranteed\n * (each `advance()` makes progress or `settle()` throws on a contentless jump cycle).\n */\n advanceToStop(): AdvanceToStopResult {\n const played: AdvanceToStopResult[\"played\"] = [];\n for (;;) {\n const r = this.advance();\n if (r.type === \"choice\" || r.type === \"end\") return { played, stop: r };\n played.push(r); // narrowed to line / text / game-event by the guard above\n }\n }\n\n /**\n * Drive the cursor to the next *deliverable* stop: a beat ready on the active\n * snippet, a pending choice, or the end. Runs onExit/jump seams and walks the\n * block run (sequentially, skipping ineligible children); a finished block pops\n * to its caller (call-return) or ends the flow.\n */\n private settle(): void {\n let transitions = 0;\n for (;;) {\n // Static validation cannot rule out jump cycles (conditions gate them),\n // so a content bug like two pure jumps jumping at each other must be an\n // error, not a hang.\n if (++transitions > 10_000) {\n throw new Error(\"flow did not settle after 10000 transitions - likely a jump cycle with no deliverable content\");\n }\n if (this.flowEnded || this.pendingChoice) return;\n\n if (this.activeSnippet) {\n if (this.beatIndex < (this.activeSnippet.beats?.length ?? 0)) return; // a beat is ready\n this.runEffects(this.activeSnippet.onExit);\n const jump = this.activeSnippet.jump;\n this.activeSnippet = null;\n this.beatIndex = 0;\n this.resolveJump(jump);\n continue;\n }\n\n const frame = this.stack[this.stack.length - 1];\n if (!frame) { this.flowEnded = true; return; }\n if (frame.sceneId !== this.currentSceneId) this.currentSceneId = frame.sceneId; // resumed scene (no reseed)\n const children = this.childrenOf(frame.containerId);\n if (!children) { this.stack.pop(); continue; } // drifted container -> skip the frame\n while (frame.index < children.length && !this.eligible(children[frame.index]!)) frame.index++;\n if (frame.index >= children.length) { this.stack.pop(); continue; } // run exhausted -> resume caller\n this.enterChild(children[frame.index++]!); // advance past it: that's the gather/return point\n }\n }\n\n /** The options of a pending choice (empty when not at a choice point). */\n getChoices(): ChoiceOption[] {\n return this.pendingChoice?.options ?? [];\n }\n\n /** Pick an eligible option by id; the next `advance()` runs it. */\n choose(id: string): void {\n const choice = this.pendingChoice;\n if (!choice) throw new Error(\"no choice is pending\");\n const option = choice.options.find((o) => o.id === id);\n if (!option) throw new Error(`unknown choice option: ${id}`);\n if (!option.eligible) throw new Error(`choice option is not eligible: ${id}`);\n const node = choice.byId.get(id)!;\n this.pendingChoice = null;\n // Optionally speak the chosen option's prompt back as its first beat (spec §5).\n this.pendingPromptBeat = this.host.replayPromptOnChoose ? this.promptBeatOf(node) ?? null : null;\n this.pendingPromptOwnerId = this.pendingPromptBeat ? node.id : null;\n // The block frame is already advanced past the choice group (the gather point),\n // so when the chosen option finishes without a jump, the flow continues there.\n this.enterChild(node);\n }\n\n isEnded(): boolean {\n return this.flowEnded;\n }\n\n /** Read a property by ref - `@patter` / `@scene` (each routed by its `shared` flag) or foreign. */\n getProperty(ref: string): ScalarValue | undefined {\n const { scope, name } = this.splitRef(ref);\n if (scope === \"patter\") return this.patterResolver.get(name);\n if (scope === \"scene\") return this.sceneResolver.get(name);\n return this.host.shared.get(scope, name); // foreign\n }\n\n /** Write a property by ref (routed by scope, then by the property's `shared` flag). */\n setProperty(ref: string, value: ScalarValue): void {\n const { scope, name } = this.splitRef(ref);\n if (scope === \"patter\") {\n this.patterResolver.set!(name, value);\n } else if (scope === \"scene\") {\n // The resolver stays graceful for expression evaluation, but a host write\n // with nowhere to land must error, not silently vanish.\n if (this.currentSceneId === null) throw new Error(`'${ref}': the flow has not entered a scene yet`);\n this.sceneResolver.set!(name, value);\n } else {\n this.host.shared.set(scope, name, value); // foreign\n }\n }\n\n // -- Save / restore (engine-driven) --------------------------------------\n\n /** @internal Snapshot this flow's cursor + per-flow scopes (not-shared `@patter`/`@scene`) + PRNG. */\n snapshot(): FlowSnapshot {\n return {\n scopes: this.local.save(), // owned scope \"patter\" = the NOT-shared globals (@scene saved separately)\n sceneBags: Object.fromEntries([...this.sceneBags].map(([s, bag]) => [s, { ...bag }])),\n rngState: this.rngState,\n visits: Object.fromEntries(this.visitCounts),\n cursor: {\n flowEnded: this.flowEnded,\n currentSceneId: this.currentSceneId,\n // Stamp each frame with the id of the child it would run next (nextId), so a restore against\n // an EDITED bundle re-finds the position by id instead of trusting the raw index (§9.8 /\n // live bundle refresh). A frame saved at its container's end has no next child - no stamp.\n stack: this.stack.map((f) => {\n const next = this.childrenOf(f.containerId)?.[f.index];\n return next ? { ...f, nextId: next.id } : { ...f };\n }),\n activeSnippetId: this.activeSnippet?.id ?? null,\n beatIndex: this.beatIndex,\n pendingChoice: this.pendingChoice\n ? { groupId: this.pendingChoice.groupId, options: this.pendingChoice.options.map((o) => ({ ...o })) }\n : null,\n pendingPromptOwnerId: this.pendingPromptOwnerId,\n selectors: serialiseSelectors(this.selectors),\n },\n };\n }\n\n /** @internal Restore this flow from a snapshot. */\n restore(snap: FlowSnapshot): void {\n this.rngState = snap.rngState >>> 0;\n this.visitCounts = new Map(Object.entries(snap.visits ?? {}));\n const c = snap.cursor;\n this.started = true;\n this.flowEnded = c.flowEnded;\n this.beatIndex = c.beatIndex;\n this.currentSceneId = c.currentSceneId;\n // Re-bind each frame to the CURRENT bundle: prefer the saved next-child id (survives siblings\n // inserted / removed / reordered before the cursor); fall back to the raw index when the id is\n // absent (an older save) or its node drifted out of the bundle (§9.8 best-effort).\n this.stack = c.stack.map((f) => {\n const { nextId, ...frame } = f;\n if (nextId !== undefined) {\n const at = this.childrenOf(frame.containerId)?.findIndex((ch) => ch.id === nextId) ?? -1;\n if (at >= 0) return { ...frame, index: at };\n }\n return { ...frame };\n });\n\n // Restore the per-flow @scene bags, then the per-flow @patter globals. @scene\n // resolves through `sceneResolver` over these bags, so nothing else to reseed.\n this.sceneBags = new Map(Object.entries(snap.sceneBags ?? {}).map(([s, bag]) => [s, { ...bag }]));\n this.local = this.freshLocal();\n this.local.load(snap.scopes); // loads the owned not-shared globals; shared halves live on the host\n\n // Content-drift policy (§9.8): if a saved position points at content deleted\n // since the save, resume best-effort rather than throwing - the missing\n // snippet / choice is dropped and play continues from the surviving stack.\n this.activeSnippet = null;\n if (c.activeSnippetId !== null) {\n const node = this.host.nodeIndex.get(c.activeSnippetId);\n if (node && node.type === \"snippet\") this.activeSnippet = node;\n }\n\n this.selectors = deserialiseSelectors(c.selectors); // this flow's (non-shared) selector cursors\n\n // Replay the saved option set VERBATIM (schema 9.3) - re-deriving would\n // re-evaluate conditions (double-consuming PRNG draws) and could change the\n // choice under the player. Options whose nodes drifted out of the bundle\n // are dropped; a choice with no surviving options dissolves (9.8).\n this.pendingChoice = null;\n if (c.pendingChoice !== null) {\n const byId = new Map<string, SelectableNode>();\n const options: ChoiceOption[] = [];\n for (const o of c.pendingChoice.options) {\n const node = this.host.nodeIndex.get(o.id);\n if (!node) continue;\n byId.set(o.id, node);\n options.push({ ...o });\n }\n if (options.length > 0) this.pendingChoice = { groupId: c.pendingChoice.groupId, options, byId };\n }\n\n // A save taken between choose() and the next advance() left a prompt still to be replayed\n // (replayPromptOnChoose). Re-derive it from the chosen option - dropped if that option drifted out\n // of the bundle (§9.8), exactly as the live choose() would have produced nothing.\n this.pendingPromptBeat = null;\n this.pendingPromptOwnerId = c.pendingPromptOwnerId ?? null;\n if (this.pendingPromptOwnerId) {\n const owner = this.host.nodeIndex.get(this.pendingPromptOwnerId);\n this.pendingPromptBeat = owner ? this.promptBeatOf(owner) ?? null : null;\n if (!this.pendingPromptBeat) this.pendingPromptOwnerId = null;\n }\n }\n\n // -- Scene / block / node entry ------------------------------------------\n\n /** Set the current scene, reset its scene-local props, run onEntry. */\n private enterSceneSetup(sceneId: string): void {\n const scene = this.host.bundle.scenes[sceneId];\n if (!scene) throw new Error(`unknown scene: ${sceneId}`);\n this.currentSceneId = sceneId;\n this.enter(sceneId);\n this.seedScene(scene); // seeds @scene defaults (per-flow on first entry; shared once globally)\n this.runEffects(scene.onEntry); // on-entry effects still fire every entry (spec §4)\n }\n\n /**\n * Play one child of the active run. A snippet begins delivering. A group is\n * walked by its selector: the default `run` pushes a nested run (its children\n * play in order, gathering back); `choice` stops for the host; a select-one\n * selector (branch, or a `sequence` in any order x exhaust mode) picks ONE child (recursing\n * to a leaf) - selecting nothing contributes no content and the run continues.\n */\n private enterChild(node: SelectableNode): void {\n this.enter(node.id);\n if (node.type === \"snippet\") { this.beginSnippet(node); return; }\n const selector = node.selector ?? \"run\";\n if (selector === \"run\") {\n this.stack.push({ sceneId: this.currentSceneId!, containerId: node.id, index: 0 });\n return;\n }\n if (selector === \"choice\") { this.setupChoice(node); return; }\n const pick = this.selectChild(node);\n if (pick) this.enterChild(pick);\n }\n\n /** A container's children, whether it's a block or a run-group; undefined if the id is gone. */\n private childrenOf(containerId: string): SelectableNode[] | undefined {\n const block = this.host.blockById.get(containerId);\n if (block) return block.children;\n const node = this.host.nodeIndex.get(containerId);\n if (node && node.type === \"group\") return node.children;\n return undefined; // content drift: the container was deleted since the save\n }\n\n private beginSnippet(snippet: CompiledSnippet): void {\n this.runEffects(snippet.onEnter);\n this.activeSnippet = snippet;\n this.beatIndex = 0;\n }\n\n private setupChoice(group: CompiledGroup): void {\n const options: ChoiceOption[] = [];\n const byId = new Map<string, SelectableNode>();\n const fallbacks: SelectableNode[] = [];\n for (const child of group.children) {\n // An option is an Option group (its content runs + gathers back) or - the\n // degenerate shape - a single snippet. prompt / sticky / fallback / secretUntilEligible\n // live on whichever (spec §5).\n if (child.fallback === true) { fallbacks.push(child); continue; } // never a normal option; auto-followed when last\n // Once-only (default): once the player has followed it, it is GONE from the choice entirely -\n // not delivered, not flagged unavailable, simply absent. A `sticky` option is never consumed,\n // so it stays available as long as its condition passes. Consumption is the existing per-flow\n // visit count, so it persists through save/restore for free.\n if (child.sticky !== true && (this.visitCounts.get(child.id) ?? 0) >= 1) continue;\n const eligible = this.eligible(child);\n const hidden = child.secretUntilEligible === true;\n if (!eligible && hidden) continue; // secret while ineligible; otherwise an ineligible option shows greyed\n options.push({ id: child.id, prompt: this.promptFor(child), eligible, gameData: child.gameData });\n byId.set(child.id, child);\n }\n if (options.length > 0) { this.pendingChoice = { groupId: group.id, options, byId }; return; }\n // No normal option survives. Auto-follow the fallback if it is eligible (its own condition still\n // applies); otherwise the choice GATHERS - it contributes nothing and the run continues past it\n // (a dry choice falls through rather than deadlocking; the validator warns about choices that can\n // run dry with no fallback).\n const fallback = fallbacks.find((f) => this.eligible(f));\n if (fallback) { this.enterChild(fallback); return; }\n // Nothing takeable and no eligible fallback: the choice runs dry and the flow walks past it. The\n // behaviour is unchanged; the opt-in diagnostics hook makes this silent fall-through observable.\n this.host.onDryChoice?.(group.id);\n }\n\n // -- Jumps (jump / call-return) ----------------------------------------\n\n private resolveJump(jump: Jump | undefined): void {\n // No jump: gather - the snippet falls through and the block run continues\n // (settle's frame walk picks the next child, or pops to a caller).\n if (!jump) return;\n this.enterTarget(jump.to, jump.mode === \"call\" ? \"call\" : \"jump\");\n }\n\n /**\n * Route to a target (scene / block / `END`). `call` PUSHES a return frame (the\n * caller's block run, already advanced to its next child, stays below); `jump`\n * is absolute - it REPLACES the whole stack, discarding pending returns. `END`\n * hard-ends the flow regardless of the callstack.\n */\n private enterTarget(to: string, mode: \"call\" | \"jump\"): void {\n if (to === \"END\") { this.flowEnded = true; this.stack = []; return; }\n\n let sceneId: string;\n let containerId: string;\n const scene = this.host.bundle.scenes[to];\n if (scene) {\n this.enterSceneSetup(to);\n const first = scene.blocks[0];\n if (!first) { if (mode === \"jump\") this.stack = []; return; } // empty scene\n sceneId = to; containerId = first.id;\n } else {\n const loc = this.host.blockIndex.get(to);\n if (!loc) throw new Error(`jump target not found: ${to}`);\n if (loc.sceneId !== this.currentSceneId) this.enterSceneSetup(loc.sceneId);\n sceneId = loc.sceneId; containerId = to;\n }\n\n this.enter(containerId); // count the entered block\n const frame: StackFrame = { sceneId, containerId, index: 0 };\n if (mode === \"call\") this.stack.push(frame);\n else this.stack = [frame];\n }\n\n // -- Selectors ------------------------------------------------------------\n\n private selectChild(group: CompiledGroup): SelectableNode | null {\n const eligible = group.children.filter((c) => this.eligible(c));\n if (eligible.length === 0) return null;\n const st = this.selectorState(group);\n\n switch (group.selector) {\n case \"branch\":\n return eligible[0]!;\n\n case \"sequence\": {\n const order = group.options?.order ?? \"sequential\";\n const exhaust = group.options?.exhaust ?? \"once\";\n return order === \"shuffle\"\n ? this.pickShuffle(eligible, exhaust, st)\n : this.pickSequential(eligible, exhaust, st);\n }\n\n case \"run\":\n case \"choice\":\n default:\n return null; // run / choice / default are handled in enterChild, not here\n }\n }\n\n /** `sequence` with `order: \"sequential\"` - walk children in authored order. */\n private pickSequential(eligible: SelectableNode[], exhaust: string, st: SelectorState): SelectableNode | null {\n const len = eligible.length;\n const n = st.seq ?? 0;\n st.seq = n + 1;\n if (exhaust === \"repeat\") return eligible[n % len]!; // cycle\n if (n < len) return eligible[n]!; // still in the first pass\n if (exhaust === \"stick\") return eligible[len - 1]!; // hold the last forever (stopping)\n return null; // once: nothing after the pass\n }\n\n /**\n * `sequence` with `order: \"shuffle\"` - draw WITHOUT replacement (a bag), never\n * repeating the immediately-previous pick across a reshuffle (no line twice in a\n * row when >=2 are eligible). `stick` holds out the last authored child as the\n * permanent terminal; `once` stops after one pass; `repeat` reshuffles.\n */\n private pickShuffle(eligible: SelectableNode[], exhaust: string, st: SelectorState): SelectableNode | null {\n const len = eligible.length;\n const stick = exhaust === \"stick\";\n const fill = (): string[] => (stick ? eligible.slice(0, len - 1) : eligible).map((c) => c.id);\n\n if (st.bag === undefined) st.bag = fill();\n if (st.bag.length === 0) { // a full pass just completed\n if (exhaust === \"once\") return null;\n if (stick) { const last = eligible[len - 1]!; st.last = last.id; return last; }\n st.bag = fill(); // repeat: reshuffle\n }\n\n // Draw without replacement, never repeating the immediately-previous pick. Done allocation-free:\n // rather than materialise a filtered pool, find last's slot `p` and draw into the reduced span,\n // skipping that slot - identical distribution to filtering it out, then erase the pick in place.\n const pool = st.bag;\n const p = st.last !== undefined && pool.length > 1 ? pool.indexOf(st.last) : -1;\n let i = Math.floor(this.rng() * (p >= 0 ? pool.length - 1 : pool.length));\n if (p >= 0 && i >= p) i++;\n const id = pool[i]!;\n pool.splice(i, 1);\n st.last = id;\n return eligible.find((c) => c.id === id)!;\n }\n\n /** A selector's cursor state - shared across flows (`group.shared`) or this flow's own. */\n private selectorState(group: CompiledGroup): SelectorState {\n const map = group.shared ? this.host.sharedSelectors : this.selectors;\n let st = map.get(group.id);\n if (!st) { st = {}; map.set(group.id, st); }\n return st;\n }\n\n // -- Effects + expressions ------------------------------------------------\n\n private runEffects(effects: CompiledEffect[] | undefined): void {\n // SET-ONLY (spec §15): an effect mutates a property. Host events ride on gameData, not effects.\n for (const e of effects ?? []) {\n this.setProperty(e.target, this.evalExpr(e.value));\n }\n }\n\n private eligible(node: SelectableNode): boolean {\n if (!node.condition) return true;\n return truthy(this.evalExpr(node.condition));\n }\n\n private evalExpr(expr: Expression): ScalarValue {\n let ast = astCache.get(expr);\n if (!ast) { ast = deserialiseAst(expr.ast); astCache.set(expr, ast); }\n return evaluate(ast, this.evalCtx, patterDialect);\n }\n\n /** Record an entry of a node (entered-only; spec §7): bumps the flow + world counts. */\n private enter(id: string): void {\n this.visitCounts.set(id, (this.visitCounts.get(id) ?? 0) + 1);\n this.host.sharedVisits.set(id, (this.host.sharedVisits.get(id) ?? 0) + 1);\n }\n\n /** Next float in [0, 1): the shared custom PRNG, or this flow's serialisable mulberry32. */\n private readonly rng = (): number => {\n if (this.host.customRng) return this.host.customRng();\n const a = (this.rngState + 0x6d2b79f5) | 0;\n this.rngState = a;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n\n // -- Strings / beats ------------------------------------------------------\n\n private beatResult(beat: Beat): StepResult {\n // Accumulated author tags (#215): the beat's own tags unioned with every\n // ancestor's. Omitted from the step when empty (parity with `gameData`).\n const tags = this.host.tagIndex.get(beat.id);\n const withTags = tags && tags.length ? { tags } : {};\n // Inline `{@ref}` interpolation (spec §16): text beats always interpolate;\n // line beats interpolate only in a non-voiced project (voiced lines are\n // static). Game-event beats carry no localised content.\n switch (beat.kind) {\n case \"gameEvent\":\n return { type: \"gameEvent\", id: beat.id, gameData: beat.gameData, ...withTags };\n case \"text\":\n return { type: \"text\", id: beat.id, text: this.interpolate(this.resolveString(beat.id)), gameData: beat.gameData, ...withTags };\n case \"line\": {\n const raw = this.resolveString(beat.id);\n // Closed captions (#214) apply to DIALOGUE lines only: strip cues when captions are off. Two ways a\n // line goes SILENT (off only): the caption CHARACTER speaks it (whole line is a caption - omit all\n // dialogue, delimiters or not), or stripping cues leaves it empty. A silent line still FIRES (audio\n // plays + visits count) but carries no text + no speaker, so no caption shows.\n const off = !this.host.captionsOn;\n const captionChar = off && beat.character === this.host.captionCharacter; // captionCharacter is always set (defaults SFX)\n const text = captionChar ? \"\" : this.captionLine(this.host.bundle.voiced ? raw : this.interpolate(raw));\n const silent = off && text.length === 0;\n return {\n type: \"line\",\n id: beat.id,\n text,\n character: silent ? undefined : beat.character,\n characterName: silent ? undefined : this.resolveCharacterName(beat.character),\n direction: silent ? undefined : beat.direction,\n gameData: beat.gameData,\n ...withTags,\n };\n }\n }\n }\n\n /**\n * Expand inline `{@ref}` slots (spec §16) against this flow's CURRENT property state. Public so an\n * IDs-only game can apply the same property replacement to a string it looked up in its own loc system:\n * the engine handed it the beat ID, the game fetched its translation, then calls `flow.interpolate(...)`.\n */\n interpolate(raw: string): string {\n return interpolate(raw, (ref) => this.getProperty(ref));\n }\n\n /**\n * Apply the project's caption rule to a string UNCONDITIONALLY (#214): remove every cue span between\n * the project's delimiters and collapse the whitespace. Public so an IDs-only game - which looks up\n * its own strings - can match the embedded runtime: `flow.stripCaptions(flow.interpolate(text))` when\n * its own captions setting is off. (Embedded play does this automatically for dialogue lines.)\n */\n stripCaptions(raw: string): string {\n return stripCaptions(raw, this.host.captionOpen, this.host.captionClose);\n }\n\n /** Caption-strip a dialogue line ONLY when captions are off; otherwise pass the text through. The\n * internal gate the engine applies to every `line` beat / line-kind prompt. */\n private captionLine(text: string): string {\n return this.host.captionsOn ? text : this.stripCaptions(text);\n }\n\n /**\n * An option's prompt (spec §5): the Option group's `prompt` beat, resolved + interpolated\n * (choice labels are on-screen text, so they interpolate, spec §16). For the degenerate\n * bare-snippet tolerance - or an Option group authored without a prompt - it falls back to the\n * option's first content line. NO look-ahead. Undefined only when even that is absent.\n */\n private promptFor(node: SelectableNode): ChoicePrompt | undefined {\n const beat = this.promptBeatOf(node);\n if (!beat) return undefined;\n const text = this.interpolate(this.resolveString(beat.id));\n // A line-kind prompt is dialogue, so captions apply to it; a text-kind prompt is left as-is.\n return beat.kind === \"line\"\n ? { kind: \"line\", text: this.captionLine(text), character: beat.character, characterName: this.resolveCharacterName(beat.character), direction: beat.direction }\n : { kind: \"text\", text };\n }\n\n /** The prompt BEAT of an option: the Option group's `prompt`, else (tolerance) its first content line. */\n private promptBeatOf(node: SelectableNode): LineBeat | TextBeat | undefined {\n if (node.type === \"group\" && node.prompt) return node.prompt;\n const snippet = node.type === \"snippet\" ? node : this.firstTextSnippetIn(node.children);\n return (snippet?.beats ?? []).find((b): b is LineBeat | TextBeat => b.kind === \"line\" || b.kind === \"text\");\n }\n\n /** The first snippet with a line/text beat within a child list, depth-first in authored order. */\n private firstTextSnippetIn(children: SelectableNode[]): CompiledSnippet | undefined {\n let found: CompiledSnippet | undefined;\n walkNodes<SelectableNode>(children, (n) => {\n if (!found && n.type === \"snippet\" && (n.beats ?? []).some((b) => b.kind === \"line\" || b.kind === \"text\")) {\n found = n;\n }\n });\n return found;\n }\n\n private resolveString(id: string): string {\n if (this.host.emitIds) return id; // IDs-only build: the game resolves text from this id itself\n const active = this.host.strings[id];\n if (active !== undefined) return active;\n // A key the active locale is missing falls back to the default-locale (source) text, but is flagged\n // LOUDLY: an untranslated string is a hard fail authors must notice, not silently paper over. Only a\n // key absent from the default locale too (never extracted) degrades to its bare id.\n const source = this.host.defaultStrings[id];\n return source !== undefined ? `<Untranslated: ${id}> ${source}` : id;\n }\n\n /** A character's player-facing name: the `cast:<name>` string in the active locale, else the default\n * locale, else the authoring `displayName`. Undefined when the character has no display name at all\n * (the host falls back to the `character` token itself). */\n private resolveCharacterName(character: string | undefined): string | undefined {\n if (character === undefined) return undefined;\n if (this.host.emitIds) return undefined; // IDs-only: omit the display name; the game maps the `character` token\n const key = castStringKey(character);\n return this.host.strings[key] ?? this.host.defaultStrings[key] ?? this.host.castDisplay.get(character);\n }\n\n /** Split a ref into scope + name. Tokens: `@scene`, foreign tokens, else `@patter` (incl. bare `@name`). */\n private splitRef(ref: string): { scope: string; name: string } {\n // host.shared.has(\"patter\") is true, so it covers @patter + every foreign token; @scene is explicit.\n let hit = this.host.refSplitCache.get(ref);\n if (!hit) { hit = splitRef(ref, (t) => t === \"scene\" || this.host.shared.has(t)); this.host.refSplitCache.set(ref, hit); }\n return hit;\n }\n\n /** The per-flow registry: the NOT-shared `@patter` globals (the shared ones live on the host). */\n private freshLocal(): ScopeRegistry {\n return new ScopeRegistry().defineOwned(\"patter\", this.host.patterLocalDecls);\n }\n\n /**\n * Seed a scene's `@scene` props (spec §7). The not-shared props seed THIS flow's\n * bag the first time it enters (persist across re-entries thereafter); the shared\n * props seed the host's stage bag the first time ANY flow enters the scene (shared\n * and persistent thereafter - a later flow finds it present and leaves it).\n * `temporary` props are the exception: reseeded to their default on every entry.\n */\n private seedScene(scene: CompiledScene): void {\n const shared = this.host.sceneSharedNames.get(scene.id) ?? new Set<string>();\n if (!this.sceneBags.has(scene.id)) {\n const bag: Record<string, ScalarValue> = {};\n for (const decl of scene.sceneProps ?? []) {\n const name = decl.name.toLowerCase();\n if (!shared.has(name)) bag[name] = sceneDefault(decl);\n }\n this.sceneBags.set(scene.id, bag);\n }\n if (!this.host.stageBags.has(scene.id)) {\n const bag: Record<string, ScalarValue> = {};\n for (const decl of scene.sceneProps ?? []) {\n const name = decl.name.toLowerCase();\n if (shared.has(name)) bag[name] = sceneDefault(decl);\n }\n this.host.stageBags.set(scene.id, bag);\n }\n\n // `temporary` props are reseeded to their default on EVERY entry (\"fresh each\n // playthrough\"), rather than persisting across re-entries like the rest.\n for (const decl of scene.sceneProps ?? []) {\n if (!decl.temporary) continue;\n const name = decl.name.toLowerCase();\n const bag = shared.has(name) ? this.host.stageBags.get(scene.id) : this.sceneBags.get(scene.id);\n if (bag) bag[name] = sceneDefault(decl);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers.\n// ---------------------------------------------------------------------------\n\n/** Serialise a `sequence` selector-cursor map to plain snapshots. */\nfunction serialiseSelectors(map: Map<string, SelectorState>): Record<string, SelectorSnapshot> {\n const out: Record<string, SelectorSnapshot> = {};\n for (const [id, st] of map) {\n const v: SelectorSnapshot = {};\n if (st.seq !== undefined) v.seq = st.seq;\n if (st.bag) v.bag = [...st.bag];\n if (st.last !== undefined) v.last = st.last;\n out[id] = v;\n }\n return out;\n}\n\n/** Rebuild a `sequence` selector-cursor map from snapshots. */\nfunction deserialiseSelectors(rec: Record<string, SelectorSnapshot> | undefined): Map<string, SelectorState> {\n const map = new Map<string, SelectorState>();\n for (const [id, v] of Object.entries(rec ?? {})) {\n const st: SelectorState = {};\n if (v.seq !== undefined) st.seq = v.seq;\n if (v.bag) st.bag = [...v.bag];\n if (v.last !== undefined) st.last = v.last;\n map.set(id, st);\n }\n return map;\n}\n\n/** Adapt a Patter `PropertyDecl` to a registry `ScopeDeclaration` (same type vocabulary). */\nfunction toDecl(decl: PropertyDecl): ScopeDeclaration {\n return { name: decl.name, type: decl.type, values: decl.values, default: decl.default };\n}\n\n/** A shared-decl's value for reset-to-default: its declared default, else the type default. */\nfunction declDefault(d: ScopeDeclaration): ScalarValue {\n if (d.default !== undefined) return d.default;\n switch (d.type) {\n case \"number\": return 0;\n case \"string\": return \"\";\n case \"flags\": return [];\n case \"enum\": return d.values?.[0] ?? \"\";\n default: return false; // boolean (and any unknown) → false\n }\n}\n\n/** A host-scope declaration (`@world.x`) → registry declaration. */\nfunction toForeignDecl(decl: HostScopeDecl): ScopeDeclaration {\n return { name: decl.name, type: decl.type, values: decl.values, default: decl.default, writable: decl.writable };\n}\n\n/** The seed value for a host-scope property: its declared default, else the type default. */\nfunction hostScopeDefault(decl: HostScopeDecl): ScalarValue {\n if (decl.default !== undefined) return decl.default;\n switch (decl.type) {\n case \"boolean\": return false;\n case \"number\": return 0;\n case \"string\": return \"\";\n case \"flags\": return [];\n case \"enum\": return decl.values?.[0] ?? \"\";\n }\n}\n\n/** Build a live in-memory `{ get, set }` resolver for a self-backed host scope (the standalone `@world`):\n * a plain bag seeded from declaration defaults. Declared-but-unseeded names still read `undefined`; an\n * opaque scope (no declarations) starts empty and accepts any name. Per-property read-only is enforced at\n * validation, not here (the registry is per-scope), so `set` accepts any name. */\nfunction selfBackedResolver(decls: HostScopeDecl[]): ScopeResolver {\n const bag = new Map<string, ScalarValue>();\n for (const d of decls) bag.set(d.name, hostScopeDefault(d));\n return {\n get: (name) => bag.get(name),\n set: (name, value) => { bag.set(name, value); },\n };\n}\n\n/** The seed value for a scene-local property (its `default`, else the type default). */\nfunction sceneDefault(decl: PropertyDecl): ScalarValue {\n if (decl.default !== undefined) return decl.default;\n switch (decl.type) {\n case \"boolean\": return false;\n case \"number\": return 0;\n case \"string\": return \"\";\n case \"flags\": return [];\n case \"enum\": return decl.values?.[0] ?? \"\";\n }\n}\n\nfunction truthy(v: ScalarValue): boolean {\n if (typeof v === \"boolean\") return v;\n if (typeof v === \"number\") return v !== 0;\n if (typeof v === \"string\") return v !== \"\";\n return v.length > 0; // string[]\n}\n","// ---------------------------------------------------------------------------\n// Author tags (#215): a cross-cutting label layer baked into the bundle.\n//\n// A node's *accumulated* tags are the union of its own and every ancestor's,\n// ordered outermost-first (scene → block → group(s) → snippet → beat) and\n// deduped. That accumulation is purely structural, it depends only on where a\n// node sits in the tree, not on play state, so it's precomputed ONCE at engine\n// load into a flat `id -> string[]` index and read back as O(1) lookups for both\n// the delivered step `tags` and the `tagsFor*` accessors.\n// ---------------------------------------------------------------------------\n\nimport type { Bundle, CompiledGroup, CompiledSnippet } from \"@patterkit/model\";\n\nfunction dedupe(tags: string[]): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const t of tags) if (!seen.has(t)) { seen.add(t); out.push(t); }\n return out;\n}\n\n/**\n * Map every node id (scene / block / group / snippet / beat) to its accumulated\n * tags. Node ids are globally unique within a project (the validator enforces\n * it), so one flat map suffices. Nodes with no tags anywhere up the chain map to\n * an empty array.\n */\nexport function buildTagIndex(bundle: Bundle): Map<string, string[]> {\n const index = new Map<string, string[]>();\n\n const visit = (node: CompiledGroup | CompiledSnippet, inherited: string[]): void => {\n const acc = dedupe([...inherited, ...(node.tags ?? [])]);\n index.set(node.id, acc);\n if (node.type === \"group\") {\n for (const child of node.children) visit(child, acc);\n } else {\n for (const beat of node.beats ?? []) index.set(beat.id, dedupe([...acc, ...(beat.tags ?? [])]));\n }\n };\n\n for (const scene of Object.values(bundle.scenes)) {\n const sceneAcc = dedupe(scene.tags ?? []);\n index.set(scene.id, sceneAcc);\n for (const block of scene.blocks) {\n const blockAcc = dedupe([...sceneAcc, ...(block.tags ?? [])]);\n index.set(block.id, blockAcc);\n for (const child of block.children) visit(child, blockAcc);\n }\n }\n\n return index;\n}\n","// gameData read helpers (spec: author-defined custom fields per node type). The published bundle\n// carries the field SCHEMA per node type (`bundle.gameDataFields`, each field with its default) plus\n// each node's SPARSE overrides (`node.gameData`). Storage is sparse + merge-at-read: a node holds only\n// the values it overrides, and a reader falls back to the field's default. These pure helpers do that\n// resolution so a host doesn't re-implement it.\n\nimport type { Bundle, GameData, GameDataField, GameDataNodeKind } from \"@patterkit/model\";\n\n/** The author-defined gameData fields declared for a node TYPE in a bundle (empty when none). */\nexport function gameDataFields(bundle: Bundle, kind: GameDataNodeKind): GameDataField[] {\n return bundle.gameDataFields?.[kind] ?? [];\n}\n\n/** One node's effective value for a field: its sparse OVERRIDE if present, else the field's declared\n * default (undefined if neither is set). `fields` is the schema for the node's type. */\nexport function gameDataValue(fields: GameDataField[], node: GameData | undefined, name: string): unknown {\n if (node && Object.prototype.hasOwnProperty.call(node, name)) return node[name];\n return fields.find((f) => f.name === name)?.default;\n}\n\n/** A node's FULL effective gameData: every declared field resolved (override or default), plus any\n * override keys with no matching field (orphans, kept verbatim). Fields left with no value are omitted. */\nexport function effectiveGameData(fields: GameDataField[], node: GameData | undefined): GameData {\n const out: GameData = {};\n for (const f of fields) {\n const v = gameDataValue(fields, node, f.name);\n if (v !== undefined) out[f.name] = v;\n }\n for (const [k, v] of Object.entries(node ?? {})) if (!(k in out)) out[k] = v;\n return out;\n}\n"],"mappings":"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","names":["next","id"]}
|