Files
storybook/docs/book/reference/09-overview.html
Sienna Meridian Satterwhite 16deb5d237 release: Storybook v0.2.0 - Major syntax and features update
BREAKING CHANGES:
- Relationship syntax now requires blocks for all participants
- Removed self/other perspective blocks from relationships
- Replaced 'guard' keyword with 'if' for behavior tree decorators

Language Features:
- Add tree-sitter grammar with improved if/condition disambiguation
- Add comprehensive tutorial and reference documentation
- Add SBIR v0.2.0 binary format specification
- Add resource linking system for behaviors and schedules
- Add year-long schedule patterns (day, season, recurrence)
- Add behavior tree enhancements (named nodes, decorators)

Documentation:
- Complete tutorial series (9 chapters) with baker family examples
- Complete reference documentation for all language features
- SBIR v0.2.0 specification with binary format details
- Added locations and institutions documentation

Examples:
- Convert all examples to baker family scenario
- Add comprehensive working examples

Tooling:
- Zed extension with LSP integration
- Tree-sitter grammar for syntax highlighting
- Build scripts and development tools

Version Updates:
- Main package: 0.1.0 → 0.2.0
- Tree-sitter grammar: 0.1.0 → 0.2.0
- Zed extension: 0.1.0 → 0.2.0
- Storybook editor: 0.1.0 → 0.2.0
2026-02-13 21:52:03 +00:00

410 lines
20 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Language Overview - Storybook Language Guide</title>
<!-- Custom HTML head -->
<meta name="description" content="Comprehensive documentation for the Storybook narrative simulation language">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../css/variables.css">
<link rel="stylesheet" href="../css/general.css">
<link rel="stylesheet" href="../css/chrome.css">
<link rel="stylesheet" href="../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="../highlight.css">
<link rel="stylesheet" href="../tomorrow-night.css">
<link rel="stylesheet" href="../ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- Provide site root to javascript -->
<script>
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Start loading toc.js asap -->
<script src="../toc.js"></script>
</head>
<body>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var sidebar = null;
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Storybook Language Guide</h1>
<div class="right-buttons">
<a href="../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
<a href="https://github.com/r3t-studios/storybook" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="language-overview"><a class="header" href="#language-overview">Language Overview</a></h1>
<blockquote>
<p><strong>The Storybook language enables narrative simulation through structured declarations of characters, behaviors, relationships, and events.</strong></p>
</blockquote>
<h2 id="philosophy"><a class="header" href="#philosophy">Philosophy</a></h2>
<p>Storybook is a domain-specific language for narrative simulation, influenced by:</p>
<ul>
<li><strong>Rust</strong>: Strong typing, explicit declarations, and clear ownership semantics</li>
<li><strong>C#</strong>: Object-oriented patterns with declarative syntax</li>
<li><strong>Python</strong>: Readable, accessible syntax that prioritizes clarity</li>
</ul>
<p>The language balances <strong>technical precision</strong> with <strong>narrative expressiveness</strong>, making it accessible to storytellers while maintaining the rigor developers need.</p>
<h2 id="design-principles"><a class="header" href="#design-principles">Design Principles</a></h2>
<h3 id="1-code-as-narrative"><a class="header" href="#1-code-as-narrative">1. Code as Narrative</a></h3>
<p>Named nodes and prose blocks let code read like stories:</p>
<pre><code class="language-storybook">behavior Baker_MorningRoutine {
choose daily_priority {
then prepare_sourdough { ... }
then serve_customers { ... }
then restock_display { ... }
}
}
</code></pre>
<h3 id="2-explicit-is-better-than-implicit"><a class="header" href="#2-explicit-is-better-than-implicit">2. Explicit is Better Than Implicit</a></h3>
<p>Every declaration is self-documenting:</p>
<ul>
<li>Character fields show what defines them</li>
<li>Behavior trees show decision structures</li>
<li>Relationships name their participants</li>
</ul>
<h3 id="3-progressive-disclosure"><a class="header" href="#3-progressive-disclosure">3. Progressive Disclosure</a></h3>
<p>Simple cases are simple, complex cases are possible:</p>
<ul>
<li>Basic characters need just a name and fields</li>
<li>Templates enable inheritance and reuse</li>
<li>Advanced features (state machines, decorators) available when needed</li>
</ul>
<h3 id="4-semantic-validation"><a class="header" href="#4-semantic-validation">4. Semantic Validation</a></h3>
<p>The compiler catches narrative errors:</p>
<ul>
<li>Bond values must be 0.0..1.0</li>
<li>Schedule blocks cant overlap</li>
<li>Life arc transitions must reference valid states</li>
</ul>
<h2 id="language-structure"><a class="header" href="#language-structure">Language Structure</a></h2>
<h3 id="declaration-types"><a class="header" href="#declaration-types">Declaration Types</a></h3>
<p>Storybook has 10 top-level declaration types:</p>
<div class="table-wrapper"><table><thead><tr><th>Declaration</th><th>Purpose</th><th>Example</th></tr></thead><tbody>
<tr><td><code>character</code></td><td>Define entities with traits and behaviors</td><td>A baker with skills and schedule</td></tr>
<tr><td><code>template</code></td><td>Reusable patterns with ranges</td><td>A generic NPC template</td></tr>
<tr><td><code>behavior</code></td><td>Decision trees for actions</td><td>How a character responds to events</td></tr>
<tr><td><code>life_arc</code></td><td>State machines for life stages</td><td>Apprentice → Baker → Master</td></tr>
<tr><td><code>schedule</code></td><td>Time-based activities</td><td>Daily routine from 6am to 10pm</td></tr>
<tr><td><code>relationship</code></td><td>Connections between entities</td><td>Parent-child with bond values</td></tr>
<tr><td><code>institution</code></td><td>Organizations and groups</td><td>A bakery with employees</td></tr>
<tr><td><code>location</code></td><td>Places with properties</td><td>The town square</td></tr>
<tr><td><code>species</code></td><td>Type definitions with traits</td><td>Human vs Cat vs Rabbit</td></tr>
<tr><td><code>enum</code></td><td>Named value sets</td><td>EmotionalState options</td></tr>
</tbody></table>
</div>
<h3 id="value-types"><a class="header" href="#value-types">Value Types</a></h3>
<p>Fields can contain:</p>
<ul>
<li><strong>Primitives</strong>: <code>42</code>, <code>3.14</code>, <code>"text"</code>, <code>true</code></li>
<li><strong>Time</strong>: <code>08:30:00</code>, <code>14:15</code></li>
<li><strong>Duration</strong>: <code>2h30m</code>, <code>45s</code></li>
<li><strong>Ranges</strong>: <code>20..40</code> (for templates)</li>
<li><strong>Identifiers</strong>: <code>OtherCharacter</code>, <code>path::to::Thing</code></li>
<li><strong>Lists</strong>: <code>[1, 2, 3]</code></li>
<li><strong>Objects</strong>: <code>{ field: value }</code></li>
<li><strong>Prose blocks</strong>: <code> ---tag\nMulti-line\ntext\n---</code></li>
</ul>
<h3 id="expression-language"><a class="header" href="#expression-language">Expression Language</a></h3>
<p>Conditions and queries use:</p>
<ul>
<li><strong>Comparisons</strong>: <code>age &gt; 18</code>, <code>energy &lt;= 0.5</code></li>
<li><strong>Equality</strong>: <code>status is active</code>, <code>ready is true</code></li>
<li><strong>Logic</strong>: <code>tired and hungry</code>, <code>rich or lucky</code>, <code>not ready</code></li>
<li><strong>Field access</strong>: <code>self.health</code>, <code>other.bond</code></li>
<li><strong>Quantifiers</strong>: <code>forall x in children: x.happy</code></li>
</ul>
<h2 id="compilation-model"><a class="header" href="#compilation-model">Compilation Model</a></h2>
<h3 id="source--ast--sbir--runtime"><a class="header" href="#source--ast--sbir--runtime">Source → AST → SBIR → Runtime</a></h3>
<pre><code>.sb files → Parser → Abstract Syntax Tree → Resolver → SBIR Binary
</code></pre>
<p><strong>SBIR</strong> (Storybook Intermediate Representation) is a compact binary format that:</p>
<ul>
<li>Resolves all cross-file references</li>
<li>Validates semantic constraints</li>
<li>Optimizes for simulation runtime</li>
</ul>
<h3 id="validation-layers"><a class="header" href="#validation-layers">Validation Layers</a></h3>
<ol>
<li><strong>Lexical</strong>: Valid tokens and syntax</li>
<li><strong>Syntactic</strong>: Correct grammar structure</li>
<li><strong>Semantic</strong>: Type checking, reference resolution</li>
<li><strong>Domain</strong>: Narrative constraints (bond ranges, schedule overlaps)</li>
</ol>
<h2 id="file-organization"><a class="header" href="#file-organization">File Organization</a></h2>
<h3 id="project-structure"><a class="header" href="#project-structure">Project Structure</a></h3>
<pre><code>my-storybook/
├── characters/
│ ├── baker.sb
│ └── family.sb
├── behaviors/
│ └── daily_routine.sb
├── world/
│ ├── locations.sb
│ └── institutions.sb
└── schema/
├── species.sb
└── templates.sb
</code></pre>
<h3 id="import-system"><a class="header" href="#import-system">Import System</a></h3>
<p>Use <code>use</code> statements to reference definitions from other files:</p>
<pre><code class="language-storybook">use schema::species::Human;
use schema::templates::Adult;
character Baker: Human from Adult {
// ...
}
</code></pre>
<p><strong>Resolution order:</strong></p>
<ol>
<li>Same file</li>
<li>Explicitly imported</li>
<li>Error if not found</li>
</ol>
<h2 id="quick-reference"><a class="header" href="#quick-reference">Quick Reference</a></h2>
<h3 id="character-declaration"><a class="header" href="#character-declaration">Character Declaration</a></h3>
<pre><code class="language-storybook">character Name: Species from Template {
field: value
field: value
---prose_tag
Text content
---
}
</code></pre>
<h3 id="behavior-tree"><a class="header" href="#behavior-tree">Behavior Tree</a></h3>
<pre><code class="language-storybook">behavior Name {
choose label { // Selector
then label { ... } // Sequence
if (condition) // Condition
ActionName // Action
include path // Subtree
}
}
</code></pre>
<h3 id="life-arc"><a class="header" href="#life-arc">Life Arc</a></h3>
<pre><code class="language-storybook">life_arc Name {
state StateName {
on condition -&gt; NextState
}
}
</code></pre>
<h3 id="schedule"><a class="header" href="#schedule">Schedule</a></h3>
<pre><code class="language-storybook">schedule Name {
08:00 -&gt; 12:00: activity { }
12:00 -&gt; 13:00: lunch { }
}
</code></pre>
<h3 id="relationship"><a class="header" href="#relationship">Relationship</a></h3>
<pre><code class="language-storybook">relationship Name {
Person1 as role
Person2 as role
bond: 0.85
}
</code></pre>
<h2 id="next-steps"><a class="header" href="#next-steps">Next Steps</a></h2>
<p>Dive deeper into each declaration type:</p>
<ul>
<li><a href="10-characters.html">Characters</a> - Detailed character syntax</li>
<li><a href="11-behavior-trees.html">Behavior Trees</a> - Complete behavior node reference</li>
<li><a href="12-decorators.html">Decorators</a> - All decorator types</li>
<li><a href="13-life-arcs.html">Life Arcs</a> - State machine semantics</li>
<li><a href="14-schedules.html">Schedules</a> - Time-based planning</li>
<li><a href="15-relationships.html">Relationships</a> - Connection modeling</li>
<li><a href="16-other-declarations.html">Other Declarations</a> - Templates, institutions, etc.</li>
<li><a href="17-expressions.html">Expressions</a> - Full expression language</li>
<li><a href="18-value-types.html">Value Types</a> - All field value types</li>
<li><a href="19-validation.html">Validation</a> - Error checking rules</li>
</ul>
<hr />
<p><strong>Philosophy Note</strong>: Storybook treats narrative as data. Characters arent objects with methods - theyre <strong>declarations</strong> of traits, connected by <strong>behaviors</strong> and <strong>relationships</strong>. This separation enables rich analysis, modification, and simulation of narrative worlds.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../tutorial/09-locations-institutions.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../reference/10-characters.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../tutorial/09-locations-institutions.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../reference/10-characters.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<!-- Livereload script (if served using the cli tool) -->
<script>
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
<script>
window.playground_copyable = true;
</script>
<script src="../elasticlunr.min.js"></script>
<script src="../mark.min.js"></script>
<script src="../searcher.js"></script>
<script src="../clipboard.min.js"></script>
<script src="../highlight.js"></script>
<script src="../book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>