Files
storybook/docs/book/reference/16-other-declarations.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

1006 lines
39 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>Other Declarations - 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="other-declarations"><a class="header" href="#other-declarations">Other Declarations</a></h1>
<p>This chapter covers six utility declaration types that complete the Storybook language: Templates, Institutions, Locations, Species, Enums, and Use statements. These declarations enable code reuse, organizational modeling, world-building, type safety, and modular file organization.</p>
<hr />
<h2 id="templates"><a class="header" href="#templates">Templates</a></h2>
<p>Templates are reusable field sets that characters inherit using the <code>from</code> keyword. Unlike <a href="./10-characters.html#species-optional">species</a> (which define what an entity <em>is</em>), templates define what an entity <em>has</em>—capabilities, traits, and characteristics.</p>
<h3 id="syntax"><a class="header" href="#syntax">Syntax</a></h3>
<pre><code class="language-bnf">&lt;template-decl&gt; ::= "template" &lt;identifier&gt; &lt;strict-clause&gt;? &lt;resource-links&gt;? &lt;includes-clause&gt;? &lt;body&gt;
&lt;strict-clause&gt; ::= "strict"
&lt;resource-links&gt; ::= "uses" "behaviors" ":" &lt;behavior-list&gt;
| "uses" "schedule" ":" &lt;schedule-ref&gt;
| "uses" "schedules" ":" &lt;schedule-list&gt;
&lt;includes-clause&gt; ::= "include" &lt;identifier&gt; ("," &lt;identifier&gt;)*
&lt;body&gt; ::= "{" &lt;field&gt;* "}"
&lt;field&gt; ::= &lt;identifier&gt; ":" &lt;value&gt;
</code></pre>
<h3 id="basic-template"><a class="header" href="#basic-template">Basic Template</a></h3>
<pre><code class="language-storybook">template Warrior {
strength: 10..20
dexterity: 8..15
weapon_proficiency: 0.7..1.0
}
</code></pre>
<p>Characters inheriting this template get these fields with values selected from the specified ranges.</p>
<h3 id="template-includes"><a class="header" href="#template-includes">Template Includes</a></h3>
<p>Templates can include other templates to compose functionality:</p>
<pre><code class="language-storybook">template SkilledWorker {
skill_level: SkillLevel
confidence: Confidence
years_experience: 0..50
can_work_independently: false
}
template Baker {
include SkilledWorker
specialty: Specialty
recipes_mastered: 0..200
sourdough_starter_health: 0.0..1.0
}
</code></pre>
<p><strong>Semantics:</strong></p>
<ul>
<li><code>include SkilledWorker</code> brings in all fields from that template</li>
<li>Fields are merged left-to-right (later overrides earlier)</li>
<li>Transitive includes supported</li>
<li>Multiple includes allowed: <code>include A, B, C</code></li>
</ul>
<h3 id="range-values"><a class="header" href="#range-values">Range Values</a></h3>
<p>Templates can specify ranges for procedural variation:</p>
<pre><code class="language-storybook">template Villager {
age: 18..65
wealth: 10..100
height: 150.0..190.0
disposition: 0.0..1.0
}
</code></pre>
<p><strong>Range syntax:</strong></p>
<ul>
<li>Integer ranges: <code>min..max</code> (inclusive)</li>
<li>Float ranges: <code>min..max</code> (inclusive)</li>
<li>Both bounds must be same type</li>
<li>min ≤ max required</li>
</ul>
<p>When a character uses this template, the runtime selects specific values within each range.</p>
<h3 id="strict-mode"><a class="header" href="#strict-mode">Strict Mode</a></h3>
<p>Strict templates enforce that characters using them can only have fields defined in the template:</p>
<pre><code class="language-storybook">template RecipeCard strict {
include SkilledWorker
recipe_name: string
difficulty: Difficulty
prep_time_minutes: 10..180
requires_starter: false
}
</code></pre>
<p><strong>Strict semantics:</strong></p>
<ul>
<li>Characters using strict templates cannot add extra fields</li>
<li>All template fields must be present in the character</li>
<li>Enables type safety for well-defined schemas</li>
<li>Use for controlled domains (game cards, rigid categories)</li>
</ul>
<p><strong>Non-strict (default):</strong></p>
<pre><code class="language-storybook">template Flexible {
base_stat: 10
}
character Custom from Flexible {
base_stat: 15 // Override
extra_field: 42 // Allowed in non-strict
}
</code></pre>
<p><strong>Strict:</strong></p>
<pre><code class="language-storybook">template Rigid strict {
required_stat: 10
}
character Constrained from Rigid {
required_stat: 15 // OK: Override
extra_field: 42 // ERROR: Not allowed in strict template
}
</code></pre>
<h3 id="resource-linking-in-templates"><a class="header" href="#resource-linking-in-templates">Resource Linking in Templates</a></h3>
<p>Templates can link to behaviors and schedules (v0.2.0+):</p>
<pre><code class="language-storybook">template BakeryStaffMember
uses behaviors: DailyBakingRoutine, CustomerService
uses schedule: BakerySchedule
{
include SkilledWorker
on_shift: true
orders_completed: 0..1000
current_station: 0..4
}
</code></pre>
<p>Characters inheriting this template automatically get the linked behaviors and schedule.</p>
<h3 id="templates-vs-species"><a class="header" href="#templates-vs-species">Templates vs. Species</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Aspect</th><th>Templates (<code>from</code>)</th><th>Species (<code>:</code>)</th></tr></thead><tbody>
<tr><td>Semantics</td><td>What entity <em>has</em></td><td>What entity <em>is</em></td></tr>
<tr><td>Cardinality</td><td>Multiple inheritance</td><td>Single inheritance</td></tr>
<tr><td>Ranges</td><td>Allowed</td><td>Not allowed</td></tr>
<tr><td>Strict mode</td><td>Supported</td><td>Not supported</td></tr>
<tr><td>Use case</td><td>Compositional traits</td><td>Ontological identity</td></tr>
</tbody></table>
</div>
<p><strong>Example combining both:</strong></p>
<pre><code class="language-storybook">species Dragon {
lifespan: 1000
can_fly: true
}
template Hoarder {
treasure_value: 0..1000000
greed_level: 0.5..1.0
}
character Smaug: Dragon from Hoarder {
age: 850
greed_level: 0.95
}
</code></pre>
<h3 id="validation-rules"><a class="header" href="#validation-rules">Validation Rules</a></h3>
<ol>
<li><strong>Includes exist</strong>: All included templates must be defined</li>
<li><strong>No circular includes</strong>: Cannot form cycles</li>
<li><strong>Range validity</strong>: min ≤ max for all ranges</li>
<li><strong>Strict enforcement</strong>: Strict templates reject extra fields in characters</li>
<li><strong>Resource links valid</strong>: Behavior/schedule references must resolve</li>
</ol>
<hr />
<h2 id="institutions"><a class="header" href="#institutions">Institutions</a></h2>
<p>Institutions define organizations, groups, and systems—entities that function like characters but represent collectives rather than individuals.</p>
<h3 id="syntax-1"><a class="header" href="#syntax-1">Syntax</a></h3>
<pre><code class="language-bnf">&lt;institution-decl&gt; ::= "institution" &lt;identifier&gt; &lt;resource-links&gt;? &lt;body&gt;
&lt;resource-links&gt; ::= "uses" "behaviors" ":" &lt;behavior-list&gt;
| "uses" "schedule" ":" &lt;schedule-ref&gt;
| "uses" "schedules" ":" &lt;schedule-list&gt;
&lt;body&gt; ::= "{" &lt;field&gt;* &lt;prose-block&gt;* "}"
</code></pre>
<h3 id="basic-institution"><a class="header" href="#basic-institution">Basic Institution</a></h3>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
members: 50
founded: "1450-03-15"
reputation: 0.85
}
</code></pre>
<h3 id="institutions-with-fields"><a class="header" href="#institutions-with-fields">Institutions with Fields</a></h3>
<pre><code class="language-storybook">institution BakersGuild {
type: professional_guild
government_style: elected_board
hierarchy: flat
standards_enforcement: true
// Leadership
board_chair: Martha
vice_chair: Henri
board_temperament: collegial
// Membership
master_bakers: 12
journeymen: 25
apprentices: 8
honorary_members: 3
// Standards
certification_process: "practical exam and peer review"
quality_standard: "excellence"
annual_competition: true
scholarships_offered: 2
---description
The local bakers' guild that sets quality standards, organizes
competitions, and mentors apprentices. Martha has been a board
member for three years.
---
}
</code></pre>
<h3 id="resource-linking"><a class="header" href="#resource-linking">Resource Linking</a></h3>
<p>Institutions can use behaviors and schedules:</p>
<pre><code class="language-storybook">institution MarthasBakery
uses behaviors: DailyBakingRoutine, CustomerService
uses schedule: BakerySchedule
{
type: small_business
purpose: bread_and_pastry_production
family_owned: true
established: 2018
permanent_staff: 4
seasonal_helpers: 0..3
---description
A beloved neighborhood bakery run by Martha and Jane,
known for its sourdough bread and artisan pastries.
---
}
</code></pre>
<h3 id="prose-blocks"><a class="header" href="#prose-blocks">Prose Blocks</a></h3>
<p>Institutions support rich narrative documentation:</p>
<pre><code class="language-storybook">institution TownCulinaryScene {
type: cultural_ecosystem
governs: "local food culture"
// Characteristics
farm_to_table: true
artisan_focus: strong
seasonal_menus: true
community_events: monthly
---description
The overarching culinary culture of the town -- a network
of bakeries, farms, and food artisans that sustain each other.
---
---philosophy
The town's food scene operates on relationships: farmers
supply bakers, bakers feed families, families support farms.
Quality and trust are the currency of this ecosystem.
---
}
</code></pre>
<h3 id="use-cases"><a class="header" href="#use-cases">Use Cases</a></h3>
<ul>
<li><strong>Organizations</strong>: Guilds, companies, governments</li>
<li><strong>Systems</strong>: Magical systems, physical laws, economies</li>
<li><strong>Social structures</strong>: Families, tribes, castes</li>
<li><strong>Abstract entities</strong>: Dream logic, fate, chaos</li>
</ul>
<h3 id="validation-rules-1"><a class="header" href="#validation-rules-1">Validation Rules</a></h3>
<ol>
<li><strong>Unique names</strong>: Institution names must be unique</li>
<li><strong>Resource links valid</strong>: Behaviors/schedules must exist</li>
<li><strong>Field types</strong>: All fields must have valid values</li>
</ol>
<hr />
<h2 id="locations"><a class="header" href="#locations">Locations</a></h2>
<p>Locations define places in your world—rooms, buildings, cities, landscapes, or abstract spaces.</p>
<h3 id="syntax-2"><a class="header" href="#syntax-2">Syntax</a></h3>
<pre><code class="language-bnf">&lt;location-decl&gt; ::= "location" &lt;identifier&gt; &lt;body&gt;
&lt;body&gt; ::= "{" &lt;field&gt;* &lt;prose-block&gt;* "}"
</code></pre>
<h3 id="basic-location"><a class="header" href="#basic-location">Basic Location</a></h3>
<pre><code class="language-storybook">location MarthasBakery {
square_feet: 1200
type: commercial
established: "2018"
has_storefront: true
---description
A warm, inviting bakery on Main Street. The aroma of fresh
bread wafts out the door every morning. Exposed brick walls,
a glass display case, and a view into the open kitchen.
---
}
</code></pre>
<h3 id="location-with-structure"><a class="header" href="#location-with-structure">Location with Structure</a></h3>
<pre><code class="language-storybook">location BakeryKitchen {
type: "commercial kitchen"
ovens: 3
prep_stations: 4
walk_in_cooler: true
// Equipment
has_proofing_cabinet: true
mixer_capacity_kg: 20
starter_shelf: true
// Storage
flour_bins: 6
ingredient_shelves: 12
cold_storage: true
---description
The heart of the bakery. Three professional ovens line the
back wall. The sourdough starter sits on a shelf near the
warmest oven, bubbling contentedly in its ceramic crock.
---
}
</code></pre>
<h3 id="geographic-hierarchy"><a class="header" href="#geographic-hierarchy">Geographic Hierarchy</a></h3>
<p>Locations can reference other locations:</p>
<pre><code class="language-storybook">location MainStreet {
type: commercial_district
shops: 15
foot_traffic: high
}
location BakeryStorefront {
part_of: MainStreet
seating_capacity: 12
display_case: true
---description
The customer-facing area with a glass display case full
of fresh bread, pastries, and seasonal specials.
---
}
location FarmersMarket {
part_of: MainStreet
operates_on: saturday
stalls: 30
---description
The weekly Saturday market where Martha sells bread directly
to the community. Her stall is always the first to sell out.
---
}
</code></pre>
<h3 id="location-with-state"><a class="header" href="#location-with-state">Location with State</a></h3>
<pre><code class="language-storybook">location BakeryWarehouse {
temperature: controlled
square_feet: 400
humidity_controlled: true
shelving_units: 8
// Storage state
flour_stock_kg: 200
yeast_supply_days: 14
packaging_materials: true
---description
The storage area behind the kitchen. Climate-controlled to
keep flour dry and ingredients fresh. Martha takes inventory
every Monday morning.
---
---logistics
Deliveries arrive Tuesday and Friday mornings. The walk-in
cooler holds butter, eggs, and cream. Dry goods are rotated
on a first-in-first-out basis.
---
}
</code></pre>
<h3 id="use-cases-1"><a class="header" href="#use-cases-1">Use Cases</a></h3>
<ul>
<li><strong>Physical places</strong>: Cities, buildings, rooms</li>
<li><strong>Geographic features</strong>: Mountains, rivers, forests</li>
<li><strong>Abstract spaces</strong>: Dream realms, pocket dimensions</li>
<li><strong>Game boards</strong>: Arenas, dungeons, maps</li>
</ul>
<h3 id="validation-rules-2"><a class="header" href="#validation-rules-2">Validation Rules</a></h3>
<ol>
<li><strong>Unique names</strong>: Location names must be unique</li>
<li><strong>Field types</strong>: All fields must have valid values</li>
<li><strong>References valid</strong>: Location references (like <code>part_of</code>) should resolve</li>
</ol>
<hr />
<h2 id="species"><a class="header" href="#species">Species</a></h2>
<p>Species define the fundamental ontological categories of beings. A species represents what an entity <em>is</em> at its core—human, dragon, sentient tree, animated playing card.</p>
<h3 id="syntax-3"><a class="header" href="#syntax-3">Syntax</a></h3>
<pre><code class="language-bnf">&lt;species-decl&gt; ::= "species" &lt;identifier&gt; &lt;includes-clause&gt;? &lt;body&gt;
&lt;includes-clause&gt; ::= "includes" &lt;identifier&gt; ("," &lt;identifier&gt;)*
&lt;body&gt; ::= "{" &lt;field&gt;* &lt;prose-block&gt;* "}"
</code></pre>
<h3 id="basic-species"><a class="header" href="#basic-species">Basic Species</a></h3>
<pre><code class="language-storybook">species Human {
lifespan: 70
---description
Bipedal mammals with complex language and tool use.
Highly variable in cultures and capabilities.
---
}
</code></pre>
<h3 id="species-with-includes"><a class="header" href="#species-with-includes">Species with Includes</a></h3>
<p>Species can include other species for composition:</p>
<pre><code class="language-storybook">species Mammal {
warm_blooded: true
has_fur: true
}
species Primate includes Mammal {
opposable_thumbs: true
sapience_potential: 0.5..1.0
}
species Human includes Primate {
sapience_potential: 1.0
language_complexity: "high"
---description
Highly intelligent primates with advanced tool use.
---
}
</code></pre>
<h3 id="field-resolution-with-includes"><a class="header" href="#field-resolution-with-includes">Field Resolution with Includes</a></h3>
<p>When a species includes others, fields are merged in declaration order:</p>
<ol>
<li><strong>Base species</strong> (leftmost in <code>includes</code>)</li>
<li><strong>Middle species</strong></li>
<li><strong>Rightmost species</strong></li>
<li><strong>Current species</strong> (highest priority)</li>
</ol>
<p>Example:</p>
<pre><code class="language-storybook">species Aquatic {
breathes_underwater: true
speed_in_water: 2.0
}
species Reptile {
cold_blooded: true
speed_in_water: 1.0
}
species SeaTurtle includes Aquatic, Reptile {
has_shell: true
speed_in_water: 1.5 // Overrides both
}
// Resolved:
// breathes_underwater: true (from Aquatic)
// cold_blooded: true (from Reptile)
// speed_in_water: 1.5 (SeaTurtle overrides Reptile overrides Aquatic)
// has_shell: true (from SeaTurtle)
</code></pre>
<h3 id="species-vs-templates"><a class="header" href="#species-vs-templates">Species vs. Templates</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Aspect</th><th>Species (<code>:</code>)</th><th>Templates (<code>from</code>)</th></tr></thead><tbody>
<tr><td>Question</td><td>“What <em>is</em> it?”</td><td>“What <em>traits</em> does it have?”</td></tr>
<tr><td>Cardinality</td><td>One per character</td><td>Zero or more</td></tr>
<tr><td>Inheritance</td><td><code>includes</code> (species → species)</td><td>Characters inherit from templates</td></tr>
<tr><td>Variation</td><td>Concrete defaults</td><td>Ranges allowed</td></tr>
<tr><td>Example</td><td><code>species Human</code></td><td><code>template Warrior</code></td></tr>
</tbody></table>
</div>
<p><strong>When to use species:</strong></p>
<pre><code class="language-storybook">species Dragon {
lifespan: 1000
can_fly: true
breathes_fire: true
}
character Smaug: Dragon {
age: 850 // Smaug IS a Dragon
}
</code></pre>
<p><strong>When to use templates:</strong></p>
<pre><code class="language-storybook">template Hoarder {
treasure_value: 0..1000000
greed_level: 0.5..1.0
}
character Smaug: Dragon from Hoarder {
greed_level: 0.95 // Smaug HAS hoarder traits
}
</code></pre>
<h3 id="design-pattern-prefer-composition-over-deep-hierarchies"><a class="header" href="#design-pattern-prefer-composition-over-deep-hierarchies">Design Pattern: Prefer Composition Over Deep Hierarchies</a></h3>
<p><strong>Avoid:</strong></p>
<pre><code class="language-storybook">species Being { ... }
species LivingBeing includes Being { ... }
species Animal includes LivingBeing { ... }
species Vertebrate includes Animal { ... }
species Mammal includes Vertebrate { ... }
species Primate includes Mammal { ... }
species Human includes Primate { ... } // Too deep!
</code></pre>
<p><strong>Prefer:</strong></p>
<pre><code class="language-storybook">species Mammal {
warm_blooded: true
live_birth: true
}
species Human includes Mammal {
sapient: true
}
// Use templates for capabilities
template Climber { ... }
template SocialCreature { ... }
character Jane: Human from Climber, SocialCreature { ... }
</code></pre>
<h3 id="validation-rules-3"><a class="header" href="#validation-rules-3">Validation Rules</a></h3>
<ol>
<li><strong>Unique names</strong>: Species names must be unique</li>
<li><strong>No circular includes</strong>: Cannot form cycles</li>
<li><strong>Includes exist</strong>: All included species must be defined</li>
<li><strong>Field types</strong>: All fields must have valid values</li>
</ol>
<hr />
<h2 id="enums"><a class="header" href="#enums">Enums</a></h2>
<p>Enums define controlled vocabularies—fixed sets of named values. They enable type-safe categorization and validation.</p>
<h3 id="syntax-4"><a class="header" href="#syntax-4">Syntax</a></h3>
<pre><code class="language-bnf">&lt;enum-decl&gt; ::= "enum" &lt;identifier&gt; "{" &lt;variant&gt;+ "}"
&lt;variant&gt; ::= &lt;identifier&gt; ","?
</code></pre>
<h3 id="basic-enum"><a class="header" href="#basic-enum">Basic Enum</a></h3>
<pre><code class="language-storybook">enum Size {
tiny,
small,
normal,
large,
huge
}
</code></pre>
<h3 id="using-enums"><a class="header" href="#using-enums">Using Enums</a></h3>
<p>Enums are used as field values throughout the system:</p>
<pre><code class="language-storybook">character Martha: Human {
skill_level: master // References SkillLevel enum
specialty: sourdough // References Specialty enum
}
</code></pre>
<h3 id="common-enum-patterns"><a class="header" href="#common-enum-patterns">Common Enum Patterns</a></h3>
<p><strong>Emotional States:</strong></p>
<pre><code class="language-storybook">enum EmotionalState {
curious,
frightened,
confused,
brave,
angry,
melancholy,
amused
}
</code></pre>
<p><strong>Card Suits:</strong></p>
<pre><code class="language-storybook">enum CardSuit {
hearts,
diamonds,
clubs,
spades
}
enum CardRank {
two, three, four, five, six, seven, eight, nine, ten,
knave, queen, king
}
</code></pre>
<p><strong>Time States:</strong></p>
<pre><code class="language-storybook">enum TimeState {
normal,
frozen,
reversed,
accelerated
}
</code></pre>
<p><strong>Government Types:</strong></p>
<pre><code class="language-storybook">enum GovernmentType {
monarchy,
democracy,
anarchy,
tyranny,
oligarchy
}
enum GovernmentStyle {
absolute_tyranny,
benevolent_dictatorship,
constitutional_monarchy,
direct_democracy,
representative_democracy
}
</code></pre>
<h3 id="calendar-enums-configurable"><a class="header" href="#calendar-enums-configurable">Calendar Enums (Configurable)</a></h3>
<p>Define custom calendars for your world:</p>
<pre><code class="language-storybook">enum Season {
spring,
summer,
fall,
winter
}
enum DayOfWeek {
monday,
tuesday,
wednesday,
thursday,
friday,
saturday,
sunday
}
enum Month {
january, february, march, april,
may, june, july, august,
september, october, november, december
}
</code></pre>
<p><strong>Custom calendars:</strong></p>
<pre><code class="language-storybook">enum EightSeasons {
deep_winter,
late_winter,
early_spring,
late_spring,
early_summer,
late_summer,
early_fall,
late_fall
}
</code></pre>
<h3 id="validation-integration"><a class="header" href="#validation-integration">Validation Integration</a></h3>
<p>Enums enable compile-time validation:</p>
<pre><code class="language-storybook">enum Size {
tiny, small, normal, large, huge
}
character Martha {
skill_level: medium // ERROR: 'medium' not in SkillLevel enum
}
</code></pre>
<h3 id="use-cases-2"><a class="header" href="#use-cases-2">Use Cases</a></h3>
<ul>
<li><strong>Controlled vocabularies</strong>: Prevent typos and invalid values</li>
<li><strong>Schema constraints</strong>: Temporal systems, card decks, status types</li>
<li><strong>Type safety</strong>: Catch errors at compile time</li>
<li><strong>Documentation</strong>: Enumerate all valid options</li>
</ul>
<h3 id="validation-rules-4"><a class="header" href="#validation-rules-4">Validation Rules</a></h3>
<ol>
<li><strong>Unique enum names</strong>: Enum names must be unique</li>
<li><strong>Unique variants</strong>: Variant names must be unique within the enum</li>
<li><strong>Non-empty</strong>: Enums must have at least one variant</li>
<li><strong>Valid identifiers</strong>: Variants must follow identifier rules</li>
</ol>
<hr />
<h2 id="use-statements"><a class="header" href="#use-statements">Use Statements</a></h2>
<p>Use statements import definitions from other files, enabling modular organization and code reuse.</p>
<h3 id="syntax-5"><a class="header" href="#syntax-5">Syntax</a></h3>
<pre><code class="language-bnf">&lt;use-decl&gt; ::= "use" &lt;use-path&gt; &lt;use-kind&gt;
&lt;use-path&gt; ::= &lt;identifier&gt; ("::" &lt;identifier&gt;)*
&lt;use-kind&gt; ::= ";" // Single import
| "::{" &lt;identifier&gt; ("," &lt;identifier&gt;)* "}" ";" // Grouped import
| "::*" ";" // Wildcard import
</code></pre>
<h3 id="single-import"><a class="header" href="#single-import">Single Import</a></h3>
<pre><code class="language-storybook">use schema::beings::Human;
</code></pre>
<p>Imports the <code>Human</code> species from <code>schema/beings.sb</code>.</p>
<h3 id="grouped-import"><a class="header" href="#grouped-import">Grouped Import</a></h3>
<pre><code class="language-storybook">use schema::core_enums::{Size, EmotionalState};
</code></pre>
<p>Imports multiple items from the same module.</p>
<h3 id="wildcard-import"><a class="header" href="#wildcard-import">Wildcard Import</a></h3>
<pre><code class="language-storybook">use schema::beings::*;
</code></pre>
<p>Imports all public items from <code>schema/beings.sb</code>.</p>
<h3 id="qualified-paths"><a class="header" href="#qualified-paths">Qualified Paths</a></h3>
<p><strong>Module structure:</strong></p>
<pre><code>examples/alice-in-wonderland/
├─ schema/
│ ├─ core_enums.sb
│ ├─ templates.sb
│ └─ beings.sb
└─ world/
├─ characters/
│ └─ alice.sb
└─ locations/
└─ wonderland_places.sb
</code></pre>
<p><strong>In <code>martha.sb</code>:</strong></p>
<pre><code class="language-storybook">use schema::core_enums::{SkillLevel, Specialty};
use schema::templates::Baker;
use schema::beings::Human;
character Martha: Human from Baker {
skill_level: master
specialty: sourdough
}
</code></pre>
<h3 id="path-resolution"><a class="header" href="#path-resolution">Path Resolution</a></h3>
<ol>
<li><strong>Relative to files module path</strong>: Imports are resolved relative to the current files location</li>
<li><strong>Module hierarchy</strong>: <code>schema::beings</code> maps to <code>schema/beings.sb</code></li>
<li><strong>Transitive imports</strong>: Imported modules can themselves import others</li>
</ol>
<h3 id="common-patterns"><a class="header" href="#common-patterns">Common Patterns</a></h3>
<p><strong>Schema organization:</strong></p>
<pre><code class="language-storybook">// In schema/core_enums.sb
enum SkillLevel { novice, beginner, intermediate, advanced, master }
enum Specialty { sourdough, pastries, cakes, general }
// In world/characters/martha.sb
use schema::core_enums::{SkillLevel, Specialty};
</code></pre>
<p><strong>Template composition:</strong></p>
<pre><code class="language-storybook">// In schema/templates.sb
template SkilledWorker { ... }
template Baker {
include SkilledWorker
...
}
// In world/characters/martha.sb
use schema::templates::Baker;
</code></pre>
<p><strong>Cross-file references:</strong></p>
<pre><code class="language-storybook">// In world/characters/martha.sb
character Martha { ... }
// In world/relationships/bakery.sb
use world::characters::Martha;
relationship MarthaAndJane {
Martha
Jane
}
</code></pre>
<h3 id="validation-rules-5"><a class="header" href="#validation-rules-5">Validation Rules</a></h3>
<ol>
<li><strong>Path exists</strong>: Imported paths must reference defined modules/items</li>
<li><strong>No circular imports</strong>: Modules cannot form circular dependency chains</li>
<li><strong>Valid identifiers</strong>: All path segments must be valid identifiers</li>
<li><strong>Grouped import validity</strong>: All items in <code>{}</code> must exist</li>
</ol>
<h3 id="best-practices"><a class="header" href="#best-practices">Best Practices</a></h3>
<p><strong>1. Group related imports:</strong></p>
<pre><code class="language-storybook">use schema::core_enums::{SkillLevel, Specialty, Confidence};
use schema::beings::{Human, Cat};
</code></pre>
<p><strong>2. Explicit over wildcard:</strong></p>
<pre><code class="language-storybook">// Prefer:
use schema::core_enums::{SkillLevel, Specialty};
// Over:
use schema::core_enums::*; // Imports everything
</code></pre>
<p><strong>3. Organize by hierarchy:</strong></p>
<pre><code class="language-storybook">// Schema imports first
use schema::core_enums::SkillLevel;
use schema::templates::Baker;
// Then world imports
use world::characters::Martha;
</code></pre>
<p><strong>4. Use qualified paths for clarity:</strong></p>
<pre><code class="language-storybook">character Elena: Human from Baker, Apprentice {
// Human is species (from schema::beings)
// Baker, Apprentice are templates (from schema::templates)
}
</code></pre>
<hr />
<h2 id="cross-references"><a class="header" href="#cross-references">Cross-References</a></h2>
<ul>
<li><a href="./10-characters.html">Characters</a> - Using templates and species</li>
<li><a href="./15-relationships.html">Relationships</a> - Institutions can participate</li>
<li><a href="./14-schedules.html">Schedules</a> - Resource linking</li>
<li><a href="./11-behavior-trees.html">Behavior Trees</a> - Resource linking</li>
<li><a href="./18-value-types.html">Value Types</a> - Field value types</li>
</ul>
<h2 id="related-concepts"><a class="header" href="#related-concepts">Related Concepts</a></h2>
<ul>
<li><strong>Modularity</strong>: Use statements enable file organization</li>
<li><strong>Composition</strong>: Templates provide trait-based composition</li>
<li><strong>Type safety</strong>: Enums prevent invalid values</li>
<li><strong>World-building</strong>: Locations and institutions model environments</li>
<li><strong>Ontology</strong>: Species define entity essence</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../reference/16b-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/17-expressions.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="../reference/16b-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/17-expressions.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>