Files
storybook/docs/book/reference/16-other-declarations.html

1006 lines
39 KiB
HTML
Raw Normal View History

<!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>