pub struct Story<'p, R: StoryRng = FastRng> { /* private fields */ }Expand description
Per-instance mutable state for executing stories.
Created from a Program via Story::new. Holds all mutable state
(stacks, globals, output buffer) while the immutable program data lives
in Program.
Generic over R: StoryRng — defaults to FastRng. Use
DotNetRng for .NET-compatible deterministic output.
Implementations§
Source§impl<R: StoryRng> Story<'_, R>
impl<R: StoryRng> Story<'_, R>
Sourcepub fn save_state(&self) -> SaveState
pub fn save_state(&self) -> SaveState
Capture the default flow’s game state as a durable, name-keyed
SaveState. Does not capture execution position.
Sourcepub fn load_state(&mut self, save: &SaveState) -> LoadReport
pub fn load_state(&mut self, save: &SaveState) -> LoadReport
Reconcile a SaveState into the default flow’s context, returning a
LoadReport of anything that couldn’t be applied. Globals are matched
by name; visit/turn counts by id. Tolerant of story patches: unknown
globals are reported, scopes the program no longer has retain their
saved counts harmlessly.
Source§impl<'p, R: StoryRng> Story<'p, R>
impl<'p, R: StoryRng> Story<'p, R>
Sourcepub fn new(program: &'p Program, line_tables: Vec<Vec<LineEntry>>) -> Self
pub fn new(program: &'p Program, line_tables: Vec<Vec<LineEntry>>) -> Self
Create a new story instance from a linked program and its line tables.
Sourcepub fn set_plural_resolver(&mut self, resolver: Box<dyn PluralResolver>)
pub fn set_plural_resolver(&mut self, resolver: Box<dyn PluralResolver>)
Set the plural resolver for Select resolution in localized lines.
Sourcepub fn set_line_tables(&mut self, tables: Vec<Vec<LineEntry>>)
pub fn set_line_tables(&mut self, tables: Vec<Vec<LineEntry>>)
Replace the active line tables (e.g. for locale swapping).
Sourcepub fn line_tables(&self) -> &[Vec<LineEntry>]
pub fn line_tables(&self) -> &[Vec<LineEntry>]
Read-only access to the current line tables.
Sourcepub fn transcript(&self) -> &[OutputPart]
pub fn transcript(&self) -> &[OutputPart]
The full append-only transcript of all output parts produced so far.
Sourcepub fn transcript_len(&self) -> usize
pub fn transcript_len(&self) -> usize
Number of parts in the transcript.
Sourcepub fn reset_cursor(&mut self)
pub fn reset_cursor(&mut self)
Reset the transcript read cursor to the beginning (for re-rendering).
Sourcepub fn resolve_transcript_slice(
&self,
range: Range<usize>,
) -> Vec<(String, Vec<String>)>
pub fn resolve_transcript_slice( &self, range: Range<usize>, ) -> Vec<(String, Vec<String>)>
Resolve a slice of the transcript against the current line tables.
Returns (text, tags) tuples — one per line in the resolved output.
Sourcepub fn pending_choices(&self) -> Vec<Choice>
pub fn pending_choices(&self) -> Vec<Choice>
Re-resolve all pending choices against the current line tables.
Returns the same choices that would appear in Line::Choices,
but freshly resolved (useful after locale switch).
Sourcepub fn resolve_fragment(&self, idx: u32) -> String
pub fn resolve_fragment(&self, idx: u32) -> String
Resolve a fragment against the current line tables.
Sourcepub fn choice_fragment_idx(&self, choice_index: usize) -> Option<u32>
pub fn choice_fragment_idx(&self, choice_index: usize) -> Option<u32>
Get the fragment index for a pending choice’s display text, if any.
Sourcepub fn fragments(&self) -> &[Fragment]
pub fn fragments(&self) -> &[Fragment]
Read-only access to the fragment store (for transcript serialization).
Sourcepub fn variable(&self, name: &str) -> Option<&Value>
pub fn variable(&self, name: &str) -> Option<&Value>
Read a global variable’s current value by name. None if no global
with that name is declared. Reads the default flow’s context.
Sourcepub fn set_variable(&mut self, name: &str, value: Value) -> bool
pub fn set_variable(&mut self, name: &str, value: Value) -> bool
Set a global variable by name, returning false (no-op) if no global
with that name is declared. Ink globals are dynamically typed, so the
host is responsible for passing a sensibly-typed value.
Sourcepub fn set_rng_seed(&mut self, seed: i32)
pub fn set_rng_seed(&mut self, seed: i32)
Set the RNG seed for the default flow’s context. Seeding makes
RANDOM/shuffle output reproducible — set it before running (or after
a reset) so two runs of the same story on different machines match.
Sourcepub fn advance_with(
&mut self,
handler: &dyn ExternalFnHandler,
) -> Result<StepOutcome, RuntimeError>
pub fn advance_with( &mut self, handler: &dyn ExternalFnHandler, ) -> Result<StepOutcome, RuntimeError>
Advance the default flow by one step with a custom handler, surfacing a
deferred external as StepOutcome::AwaitingExternal rather than
erroring (unlike continue_single_with).
On AwaitingExternal, resolve the pending call
(resolve_external, or
invoke_fallback) and call advance_with again
to resume. Inspect the pending call via
pending_external_name /
pending_external_args.
Sourcepub fn pending_external_name(&self) -> Option<&str>
pub fn pending_external_name(&self) -> Option<&str>
Name of the external the default flow is paused on, if any.
Sourcepub fn pending_external_args(&self) -> &[Value]
pub fn pending_external_args(&self) -> &[Value]
Arguments of the external the default flow is paused on.
Sourcepub fn call_function(
&mut self,
name: &str,
args: &[Value],
handler: &dyn ExternalFnHandler,
) -> Result<Value, RuntimeError>
pub fn call_function( &mut self, name: &str, args: &[Value], handler: &dyn ExternalFnHandler, ) -> Result<Value, RuntimeError>
Evaluate an ink function by name from engine code, returning its value.
Runs out-of-band on the default flow: output is isolated (the visible
story is untouched), and the call completes synchronously. Externals the
function calls are resolved inline by handler; an external the handler
defers (ExternalResult::Pending) can’t be resolved in a synchronous
call and yields RuntimeError::AsyncExternalInCall (the paused eval is
cleaned up first).
§Errors
RuntimeError::FunctionNotFound for an unknown name;
RuntimeError::AsyncExternalInCall if a called external defers; plus
any runtime error raised during evaluation.
Sourcepub fn into_snapshot(self) -> (StorySnapshot<R>, Vec<Vec<LineEntry>>)
pub fn into_snapshot(self) -> (StorySnapshot<R>, Vec<Vec<LineEntry>>)
Detach story state from the program, consuming the story.
Sourcepub fn from_snapshot(
program: &'p Program,
snapshot: StorySnapshot<R>,
line_tables: Vec<Vec<LineEntry>>,
) -> Self
pub fn from_snapshot( program: &'p Program, snapshot: StorySnapshot<R>, line_tables: Vec<Vec<LineEntry>>, ) -> Self
Reattach a snapshot to a program with line tables.
Sourcepub fn continue_single(&mut self) -> Result<Line, RuntimeError>
pub fn continue_single(&mut self) -> Result<Line, RuntimeError>
Execute until one line of content (up to newline), or until a yield point (choices/end) if no newline occurs first.
The returned Line variant tells you what to do next:
Line::Text— more output may follow, keep calling.Line::Choices— callchoosethen resume.Line::End— the story has permanently ended.
Sourcepub fn continue_single_observed(
&mut self,
observer: &mut dyn WriteObserver,
) -> Result<Line, RuntimeError>
pub fn continue_single_observed( &mut self, observer: &mut dyn WriteObserver, ) -> Result<Line, RuntimeError>
Like continue_single but with a
WriteObserver that receives notifications for every state mutation.
Sourcepub fn continue_single_with(
&mut self,
handler: &dyn ExternalFnHandler,
) -> Result<Line, RuntimeError>
pub fn continue_single_with( &mut self, handler: &dyn ExternalFnHandler, ) -> Result<Line, RuntimeError>
Like continue_single but with a custom
external function handler.
Sourcepub fn continue_maximally(&mut self) -> Result<Vec<Line>, RuntimeError>
pub fn continue_maximally(&mut self) -> Result<Vec<Line>, RuntimeError>
Execute until the next yield point, collecting all lines.
Returns a Vec<Line> where the last element is always
Line::Choices or Line::End, and all preceding elements
are Line::Text.
Sourcepub fn continue_maximally_with(
&mut self,
handler: &dyn ExternalFnHandler,
) -> Result<Vec<Line>, RuntimeError>
pub fn continue_maximally_with( &mut self, handler: &dyn ExternalFnHandler, ) -> Result<Vec<Line>, RuntimeError>
Like continue_maximally but with a
custom external function handler.
Sourcepub fn continue_maximally_observed(
&mut self,
observer: &mut dyn WriteObserver,
) -> Result<Vec<Line>, RuntimeError>
pub fn continue_maximally_observed( &mut self, observer: &mut dyn WriteObserver, ) -> Result<Vec<Line>, RuntimeError>
Execute until the next yield point with a WriteObserver that
receives notifications for every state mutation.
Sourcepub fn choose(&mut self, index: usize) -> Result<(), RuntimeError>
pub fn choose(&mut self, index: usize) -> Result<(), RuntimeError>
Select a choice by index, then resume with
continue_single or
continue_maximally.
Sourcepub fn choose_path_string(&mut self, path: &str) -> Result<(), RuntimeError>
pub fn choose_path_string(&mut self, path: &str) -> Result<(), RuntimeError>
Move the default flow’s play head to a named knot/stitch path — ink’s
ChoosePathString equivalent. The current flow is force-completed
(callstack reset, pending choices cleared), the jump counts as a visit
to the target exactly like a -> path divert, and subsequent
continue_single /
continue_maximally calls run from there.
See FlowInstance::choose_path_string for full semantics.
§Errors
UnknownPath for an unknown path;
JumpWhileAwaitingExternal
if the flow is parked on an unresolved external call;
AlreadyEvaluatingFunction
if an engine→ink function evaluation is in progress.
Sourcepub fn choose_path_string_with_args(
&mut self,
path: &str,
args: &[Value],
) -> Result<(), RuntimeError>
pub fn choose_path_string_with_args( &mut self, path: &str, args: &[Value], ) -> Result<(), RuntimeError>
Move the default flow’s play head to a parameterized knot/stitch,
binding its declared parameters from args — ink’s
ChoosePathString with arguments. Otherwise identical to
choose_path_string. See
FlowInstance::choose_path_string_with_args for full semantics.
§Errors
As choose_path_string, plus
ArgCountMismatch when args.len()
doesn’t match the target’s declared parameter count.
Sourcepub fn has_pending_external(&self) -> bool
pub fn has_pending_external(&self) -> bool
Returns true if the default flow has a pending external call
(an External frame on top of the call stack).
Sourcepub fn resolve_external(&mut self, value: Value)
pub fn resolve_external(&mut self, value: Value)
Resolve a pending external call on the default flow by providing
the return value. For fire-and-forget calls, pass Value::Null.
After resolving, call continue_maximally
to continue execution.
Sourcepub fn invoke_fallback(&mut self) -> Result<(), RuntimeError>
pub fn invoke_fallback(&mut self) -> Result<(), RuntimeError>
Resolve a pending external call on the default flow by invoking the ink-defined fallback body. The fallback is a function call whose output becomes the return value.
After invoking, call continue_maximally
to continue execution.
Sourcepub fn spawn_flow(
&mut self,
name: &str,
entry_point: DefinitionId,
) -> Result<(), RuntimeError>
pub fn spawn_flow( &mut self, name: &str, entry_point: DefinitionId, ) -> Result<(), RuntimeError>
Spawn a new flow instance starting at the given entry point.
entry_point is the DefinitionId of the target container
(e.g., a knot). Each flow instance gets its own globals, visit
counts, and execution state.
Sourcepub fn continue_flow_maximally(
&mut self,
name: &str,
) -> Result<Vec<Line>, RuntimeError>
pub fn continue_flow_maximally( &mut self, name: &str, ) -> Result<Vec<Line>, RuntimeError>
Run a named flow instance until the next yield point.
Sourcepub fn continue_flow_maximally_with(
&mut self,
name: &str,
handler: &dyn ExternalFnHandler,
) -> Result<Vec<Line>, RuntimeError>
pub fn continue_flow_maximally_with( &mut self, name: &str, handler: &dyn ExternalFnHandler, ) -> Result<Vec<Line>, RuntimeError>
Run a named flow instance with an external function handler.
Sourcepub fn choose_flow(
&mut self,
name: &str,
index: usize,
) -> Result<(), RuntimeError>
pub fn choose_flow( &mut self, name: &str, index: usize, ) -> Result<(), RuntimeError>
Select a choice in a named flow.
Sourcepub fn destroy_flow(&mut self, name: &str) -> Result<(), RuntimeError>
pub fn destroy_flow(&mut self, name: &str) -> Result<(), RuntimeError>
Destroy a named flow instance — isolated or shared (#200).
Sourcepub fn flow_names(&self) -> Vec<&str>
pub fn flow_names(&self) -> Vec<&str>
List active flow names (isolated + shared), sorted for determinism.
Spawn a shared-context flow at container_idx (or the root if None).
Sourcepub fn continue_flow_single(&mut self, name: &str) -> Result<Line, RuntimeError>
pub fn continue_flow_single(&mut self, name: &str) -> Result<Line, RuntimeError>
Advance a shared flow one line (against the shared context).
Sourcepub fn continue_flow_single_with(
&mut self,
name: &str,
handler: &dyn ExternalFnHandler,
) -> Result<Line, RuntimeError>
pub fn continue_flow_single_with( &mut self, name: &str, handler: &dyn ExternalFnHandler, ) -> Result<Line, RuntimeError>
Advance a shared flow one line with an external-function handler.
Select a choice in a shared flow (against the shared context).
Sourcepub fn debug_snapshot(&self) -> DebugSnapshot
pub fn debug_snapshot(&self) -> DebugSnapshot
A structured, name-resolved snapshot of the current runtime state for
the studio State View: status, current location, globals, call stack,
visit counts, pending choices, and rng. Read-only; built on demand and
not on any hot path. See DebugSnapshot.
Sourcepub fn debug_snapshot_flow(
&self,
name: &str,
) -> Result<DebugSnapshot, RuntimeError>
pub fn debug_snapshot_flow( &self, name: &str, ) -> Result<DebugSnapshot, RuntimeError>
A debug snapshot of a named shared flow (#200), built against the shared
default_context — so its globals / visit counts match the default
flow’s, while its call stack + temps are the flow’s own. Falls back to a
named isolated flow’s own context if name is one of those instead.
Sourcepub fn debug_state(&self) -> String
pub fn debug_state(&self) -> String
Dump the current execution state for debugging.
Returns a human-readable summary of the call stack, current position, value stack, output buffer, globals, and pending choices.
Sourcepub fn did_safe_exit(&self) -> bool
pub fn did_safe_exit(&self) -> bool
Returns whether the last execution cycle ended with a safe exit
(explicit -> DONE opcode). If false after a Done line, the
story ran out of content.
Sourcepub fn did_unsafe_yield(&self) -> bool
pub fn did_unsafe_yield(&self) -> bool
Returns whether the last execution cycle passed through an empty
choice set (a Yield opcode with no pending choices).
Sourcepub fn step_once(
&mut self,
) -> Result<Option<(String, u32, usize)>, RuntimeError>
pub fn step_once( &mut self, ) -> Result<Option<(String, u32, usize)>, RuntimeError>
Execute a single VM step and return a debug trace of what happened.
Returns (opcode_description, container_idx, offset_before) or None
if the step didn’t decode an opcode (frame exhaustion, thread completion, etc).