wyrd-for-games
wyrd-for-games provides engine-neutral signal-graph game logic: author and
validate a Weave, bind it to dense runtime ids, settle it once per frame, and
apply its output in your game host.
The library target is named wyrd:
Start with the complete, compile-checked
A01: Hello, invert
lesson, then follow the tier links in Rustdoc.
Use wyrd::core, wyrd::graph, and wyrd::runtime when you want an explicit
layer namespace. The crate supports no_std plus alloc, signal-f32
(default) or signal-i32, optional serde codecs, and an opt-in schema
feature for std + serde JSON Schema tooling.
Choose an authoring surface
weave! is the declarative choice for fixed topology. pattern! is the same
validated lowering for a reusable fragment with named inputs and outputs.
Both create the immutable graph values used by bind; they do not introduce a
parallel runtime representation.
Implement Recipe when a graph is a reusable host contract. Its associated
Ports type resolves dense runtime handles once after bind, and
RecipeInstance keeps those typed ports with the owning runtime. Use
Scenario::<MyRecipe>::run for deterministic, closure-scoped frames and
assertions in tests or executable examples.
For topology generated by code, call Weave::compose. Its Composer exposes
Bool, Level, and Count wires for common operations. Composer::knot, input,
output, and thread remain available for every WeaveBuilder operation, so
generation never loses access to the catalog or its diagnostics.
Recipe::manifest returns a deterministic summary of host signal and command
endpoints. Enable schema when tools need schemars::JsonSchema for graph and
recipe manifest types; default and no_std builds do not pull in schema
dependencies.
Host loop
let mut runtime = Runtime::bind(weave, BindOpts::default())?;
// Once: resolve SenseId / HostPathId for the hot path.
// Each frame:
runtime.begin_frame(HostTime { tick });
{
let mut ports = runtime.port_writer();
ports.set_sense(plate_id, value)?; // SenseId — never a string on the hot path.
}
runtime.loom();
for signal in runtime.outbox().signals() {
// signal.path: HostPathId → runtime.path_name(signal.path) when needed.
}
for command in runtime.outbox().emits() {
// command.cmd: CmdId
}
Steady-state loom does not allocate topology: inbound edges and slots are precomputed during bind. Keep active Weaves scoped to a room or puzzle island and bind them on load, not once per frame.
Stability and continuation snapshots
Wyrd 0.4 is pre-1.0. Minor 0.x releases may make breaking public-API changes; patch releases preserve the public Rust API unless the changelog calls out a required correction.
Runtime::snapshot captures the mutable state needed to continue one bound
runtime deterministically. Runtime::restore validates the snapshot format,
numeric path, executable fingerprint, and buffer shape before changing
the runtime. Use Runtime::snapshot_into when repeated captures should reuse
owned buffers.
RuntimeState is opaque in Rust but serializable through the optional serde
feature as Wyrd's versioned checkpoint contract. Capture it after loom and
after the host has applied that frame's outbox, before the next begin_frame;
outbox effects are intentionally not saved or replayed. Games own their wider
save schema and host effects. Use Runtime::bind_restored to load into a fresh
runtime and RuntimePreset / bind_with_preset for authored named Flag,
Counter, and SignalIn starting values. Persist game progress in a host-owned format. Use a runtime snapshot only
with the same bound executable contract; do not assume compatibility across
minor releases or different Weaves.
Tiered examples
The wyrd::examples module provides Tier A
foundations, Tier B first Weaves, Tier C game-logic patterns, and Tier D chamber composition. Each
named lesson is human-readable Rustdoc backed by a complete, compile-checked doctest. Tier D
combines host-owned observations into a latched gate, continuous mover target, and edge-triggered
room-transition request.