narrative-engine 0.1.0

A reusable library for procedural text generation in games
Documentation

Narrative Engine

A Rust library for procedural text generation in games. Generates thematically appropriate, contextually aware narrative text at runtime without neural network inference, using a pipeline of simulation-driven events, stochastic grammars, and Markov-trained phrase generation.

Features

  • Narrative Function abstraction — separates what is happening narratively (revelation, escalation, confrontation) from how it's expressed, making the engine reusable across games
  • Stochastic grammar expansion with tag-based rule matching
  • Markov phrase generation for natural texture on top of structured grammar output
  • Voice system — data-driven voice profiles shape vocabulary, grammar weights, and structure without code changes
  • Genre templates — shipped defaults for social drama, survival thriller, political intrigue, and exploration
  • Fully deterministic — seedable RNG guarantees identical output for the same inputs
  • No runtime dependencies on game engines — pure library crate

Quick Start

Add the dependency to your Cargo.toml:

[dependencies]

narrative-engine = { path = "path/to/narrative-engine" }

Generate a passage:

use narrative_engine::*;
use narrative_engine::core::grammar::GrammarSet;
use narrative_engine::core::pipeline::{NarrativeEngine, WorldState};
use narrative_engine::core::voice::VoiceRegistry;
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let grammars = GrammarSet::load_from_ron(
        Path::new("genre_data/social_drama/grammar.ron"),
    )?;
    let mut voices = VoiceRegistry::new();
    voices.load_from_ron(Path::new("genre_data/social_drama/voices.ron"))?;

    let engine = NarrativeEngine::builder()
        .grammars(grammars)
        .voices(voices)
        .seed(42)
        .build()?;

    let world = WorldState::default();
    let event = Event::new("dinner_conversation")
        .mood(Mood::Tense)
        .stakes(Stakes::Personal);

    let passage = engine.narrate(&world, &event)?;
    println!("{}", passage.text);
    Ok(())
}

See the User Guide for the full API reference, content authoring guide, and end-to-end examples.

The Pipeline

Everything flows through:

Event → Narrative Function Mapping → Voice Selection → Grammar Expansion → Markov Phrase Fill → Variety Pass → Context Check → Output Text

Each stage is a distinct module. Stages can be skipped or replaced.

Tools

The crate ships three utility binaries:

# Validate grammar coverage across all rules

cargo run --bin grammar_linter -- genre_data/


# Train a Markov corpus from a text file

cargo run --bin corpus_trainer -- --input corpus.txt --output trained.bin --ngram 3


# Interactive generation shell for testing

cargo run --bin preview -- --grammars genre_data/social_drama/grammar.ron --voices genre_data/social_drama/voices.ron

Examples

cargo run --example dinner_party

cargo run --example dino_park

Documentation

  • User Guide — full usage guide, API reference, and content authoring
  • Design Document — architecture and design rationale

License

MIT