
plotline
Authored sequences, the rules that gate them, and unlock trees, as plain data for any engine. Use it for dialog, quests, cutscenes, tutorials, and technology or ability trees.
A step is a value. The runner walks the steps and hands each action to your code. Your code performs the action and answers, and the runner moves on.
Quick start
[]
= "0.3"
use BTreeSet;
use ;
// Your vocabulary. The crate never interprets it.
let mut library = new;
library.insert;
library.insert;
library.insert;
library.insert;
let held = new; // The player has no ring yet.
let mut runner = default;
runner.start.unwrap;
let mut status = runner.advance;
while let Act = status
assert!;
A wait is the gap between advance and resume, so the crate needs no
clock, callback, or async runtime.
Trees
Unlocks holds nodes that require keys and grant them. Nobody authors the
edges. One node grants a key, another requires it, and that is the arrow,
so a rule and its graph cannot drift apart.
use BTreeSet;
use ;
let mut tree = new;
tree.insert;
tree.insert;
let mut held = new;
let mut taken = new;
tree.take;
taken.insert;
for node in tree.view
view gives each node's status, layout column, and edges in one call.
validate checks the required keys of each node. It reports a key that
nothing grants, and a node that a loop or a missing key blocks.
Why
- Plain data. A script is a list of
Stepvalues. It prints, compares, validates, and loads from JSON, RON, or YAML. - Your loop, your code. The runner reads keys through your
Hasholder and hands every action back to you. Every effect lives in onematchin the host, so a test can check the actions a script produces. - One answer per key. Stored and computed keys go through one
Hastrait, so a dialog gate, a tooltip, and a tech tree always agree. - Rules that explain themselves. An
Evaluationprints as a ✓/✗ tree and lists what is missing. - Small. 19 public items,
no_std, no required dependencies. Runaway content aborts instead of hanging, and a runner saves in the middle of a chain.
Requirements and features
- Rust 1.85 or later, edition 2024.
no_stdwithalloc; no required dependencies.serde(off): derivesSerializeandDeserializefor the data types, includingLibraryandRunner. Loading fails on an unknown field and on a name that appears twice. It works withoutstd.
More examples and documentation
- API documentation — rustdoc is the manual.
examples/dialog.rs— a conversation with a choice, an event, and a quest gate. Run it withcargo run --example dialog.examples/unlocks.rs— requirements that explain themselves and gate a sequence. Run it withcargo run --example unlocks.examples/techtree.rs— a technology tree drawn from derived edges. Run it withcargo run --example techtree.- CHANGELOG
- Issue tracker
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Banner artwork: “Subway” (1934) by Lily Furedi, via Wikimedia Commons. The digital image is credited to the Smithsonian American Art Museum; the file is marked public domain.