Files
storybook/docs/book/reference/16b-institutions.html

570 lines
25 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>Institutions - 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="institutions"><a class="header" href="#institutions">Institutions</a></h1>
<p>Institutions define organizations, groups, and systems entities that function like characters but represent collectives rather than individuals. Unlike locations (which model <em>where</em>), institutions model <em>what structures and organizations</em> operate in your world.</p>
<hr />
<h2 id="syntax"><a class="header" href="#syntax">Syntax</a></h2>
<pre><code class="language-bnf">&lt;institution-decl&gt; ::= "institution" &lt;identifier&gt; "{" &lt;institution-body&gt; "}"
&lt;institution-body&gt; ::= (&lt;field&gt; | &lt;uses-behaviors&gt; | &lt;uses-schedule&gt; | &lt;prose-block&gt;)*
&lt;uses-behaviors&gt; ::= "uses" "behaviors" ":" "[" &lt;behavior-link&gt; ("," &lt;behavior-link&gt;)* "]"
&lt;behavior-link&gt; ::= "{" "tree" ":" &lt;path&gt; ","?
("when" ":" &lt;expression&gt; ","?)?
("priority" ":" &lt;priority-level&gt; ","?)? "}"
&lt;priority-level&gt; ::= "low" | "normal" | "high" | "critical"
&lt;uses-schedule&gt; ::= "uses" "schedule" ":" &lt;identifier&gt;
| "uses" "schedules" ":" "[" &lt;identifier&gt; ("," &lt;identifier&gt;)* "]"
</code></pre>
<p>An institution declaration consists of:</p>
<ul>
<li>The <code>institution</code> keyword</li>
<li>A unique name (identifier)</li>
<li>A body block containing fields, resource links, and optional prose blocks</li>
</ul>
<hr />
<h2 id="basic-institution"><a class="header" href="#basic-institution">Basic Institution</a></h2>
<p>The simplest institution has a name and descriptive fields:</p>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
members: 50
founded: "1892"
reputation: 0.85
}
</code></pre>
<hr />
<h2 id="fields"><a class="header" href="#fields">Fields</a></h2>
<p>Institution fields describe properties of the organization:</p>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
members: 50
founded: "1892"
reputation: 0.85
dues_annual: 120
meeting_frequency: "monthly"
accepts_apprentices: true
max_apprentices: 10
location: BakersGuildHall
}
</code></pre>
<h3 id="common-field-patterns"><a class="header" href="#common-field-patterns">Common Field Patterns</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody>
<tr><td><code>type</code></td><td>enum/identifier</td><td>Category of organization</td></tr>
<tr><td><code>members</code></td><td>integer</td><td>Membership count</td></tr>
<tr><td><code>founded</code></td><td>string</td><td>Establishment date</td></tr>
<tr><td><code>reputation</code></td><td>float</td><td>Public standing (0.0-1.0)</td></tr>
<tr><td><code>location</code></td><td>identifier</td><td>Where the institution operates</td></tr>
<tr><td><code>leader</code></td><td>identifier</td><td>Who runs the institution</td></tr>
</tbody></table>
</div>
<p>These are conventions you define whatever fields make sense for your world.</p>
<hr />
<h2 id="prose-blocks"><a class="header" href="#prose-blocks">Prose Blocks</a></h2>
<p>Institutions support prose blocks for rich narrative documentation:</p>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
members: 50
---description
The Bakers Guild has been the backbone of the town's bread trade
since 1892. Members share recipes, arrange apprenticeships, and
collectively negotiate flour prices with suppliers.
---
---charter
Article I: All members shall maintain the highest standards of
baking quality. Article II: Apprentices must complete a three-year
training program. Article III: Monthly meetings are mandatory.
---
---traditions
Every autumn, the Guild hosts the Great Bake-Off, a competition
open to all members. The winner earns the title of Master Baker
for the following year.
---
}
</code></pre>
<p><strong>Prose block rules:</strong></p>
<ul>
<li>Start with <code>---tag_name</code> on its own line</li>
<li>Content is free-form text (Markdown supported)</li>
<li>End with <code>---</code> on its own line</li>
<li>Multiple prose blocks per institution are allowed</li>
<li>Each tag must be unique within the institution</li>
</ul>
<hr />
<h2 id="resource-linking-behaviors"><a class="header" href="#resource-linking-behaviors">Resource Linking: Behaviors</a></h2>
<p>Institutions can link to <a href="./11-behavior-trees.html">behavior trees</a> using the <code>uses behaviors</code> clause. This defines what actions the institution takes as a collective entity.</p>
<h3 id="simple-behavior-linking"><a class="header" href="#simple-behavior-linking">Simple Behavior Linking</a></h3>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
members: 50
uses behaviors: [
{ tree: ManageApprentices },
{ tree: NegotiateSuppliers },
{ tree: HostEvents }
]
}
</code></pre>
<p>Each behavior link is an object with a <code>tree</code> field referencing a behavior tree by name or path.</p>
<h3 id="behavior-links-with-priority"><a class="header" href="#behavior-links-with-priority">Behavior Links with Priority</a></h3>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
uses behaviors: [
{ tree: ManageApprentices, priority: normal },
{ tree: NegotiateSuppliers, priority: high },
{ tree: HostEvents, priority: low }
]
}
</code></pre>
<p>Priority levels: <code>low</code>, <code>normal</code> (default), <code>high</code>, <code>critical</code>.</p>
<h3 id="conditional-behavior-links"><a class="header" href="#conditional-behavior-links">Conditional Behavior Links</a></h3>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
uses behaviors: [
{ tree: ManageApprentices },
{ tree: NegotiateSuppliers, priority: high },
{ tree: EmergencyMeeting, when: reputation &lt; 0.3, priority: critical }
]
}
</code></pre>
<p>The <code>when</code> clause takes an <a href="./17-expressions.html">expression</a> that determines when the behavior activates.</p>
<h3 id="behavior-link-fields"><a class="header" href="#behavior-link-fields">Behavior Link Fields</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Field</th><th>Required</th><th>Type</th><th>Description</th></tr></thead><tbody>
<tr><td><code>tree</code></td><td>Yes</td><td>path</td><td>Reference to a behavior tree</td></tr>
<tr><td><code>priority</code></td><td>No</td><td>priority level</td><td>Execution priority (default: <code>normal</code>)</td></tr>
<tr><td><code>when</code></td><td>No</td><td>expression</td><td>Activation condition</td></tr>
</tbody></table>
</div>
<hr />
<h2 id="resource-linking-schedules"><a class="header" href="#resource-linking-schedules">Resource Linking: Schedules</a></h2>
<p>Institutions can link to <a href="./14-schedules.html">schedules</a> using the <code>uses schedule</code> or <code>uses schedules</code> clause.</p>
<h3 id="single-schedule"><a class="header" href="#single-schedule">Single Schedule</a></h3>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
uses schedule: GuildOperatingHours
}
</code></pre>
<h3 id="multiple-schedules"><a class="header" href="#multiple-schedules">Multiple Schedules</a></h3>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
uses schedules: [WeekdaySchedule, WeekendSchedule, HolidaySchedule]
}
</code></pre>
<hr />
<h2 id="complete-syntax-example"><a class="header" href="#complete-syntax-example">Complete Syntax Example</a></h2>
<p>An institution using all available features:</p>
<pre><code class="language-storybook">institution BakersGuild {
type: trade_guild
members: 50
founded: "1892"
reputation: 0.85
dues_annual: 120
location: BakersGuildHall
leader: Martha
accepts_apprentices: true
uses behaviors: [
{ tree: ManageApprentices, priority: normal },
{ tree: NegotiateSuppliers, priority: high },
{ tree: HostAnnualBakeOff, when: month is october, priority: high },
{ tree: EmergencyMeeting, when: reputation &lt; 0.3, priority: critical }
]
uses schedule: GuildOperatingHours
---description
The Bakers Guild has been the backbone of the town's bread trade
since 1892. Martha Baker currently serves as Guild Master.
---
---membership_rules
New members must be nominated by an existing member and pass
a baking trial. Apprentices are accepted from age 16.
---
}
</code></pre>
<hr />
<h2 id="membership-modeling"><a class="header" href="#membership-modeling">Membership Modeling</a></h2>
<p>Institutions themselves dont have a built-in membership list. Instead, model membership through character fields or relationships:</p>
<h3 id="via-character-fields"><a class="header" href="#via-character-fields">Via Character Fields</a></h3>
<pre><code class="language-storybook">character Martha {
age: 45
guild_member: true
guild_role: guild_master
guild: BakersGuild
}
character Jane {
age: 19
guild_member: true
guild_role: apprentice
guild: BakersGuild
}
</code></pre>
<h3 id="via-relationships"><a class="header" href="#via-relationships">Via Relationships</a></h3>
<pre><code class="language-storybook">relationship GuildMembership {
Martha as guild_master { }
BakersGuild as organization { }
bond: 0.95
years_active: 20
}
relationship Apprenticeship {
Jane as apprentice { }
BakersGuild as guild { }
Martha as mentor { }
years_completed: 1
years_remaining: 2
}
</code></pre>
<hr />
<h2 id="institutions-vs-characters"><a class="header" href="#institutions-vs-characters">Institutions vs. Characters</a></h2>
<p>Both institutions and characters can use behaviors and schedules, but they serve different purposes:</p>
<div class="table-wrapper"><table><thead><tr><th>Aspect</th><th>Institutions</th><th>Characters</th></tr></thead><tbody>
<tr><td>Represents</td><td>Organizations, collectives</td><td>Individuals</td></tr>
<tr><td>Species</td><td>No</td><td>Yes (optional)</td></tr>
<tr><td>Templates</td><td>No</td><td>Yes (optional)</td></tr>
<tr><td><code>uses behaviors</code></td><td>Yes</td><td>Yes</td></tr>
<tr><td><code>uses schedule</code></td><td>Yes</td><td>Yes</td></tr>
<tr><td>Prose blocks</td><td>Yes</td><td>Yes</td></tr>
<tr><td>Participation in relationships</td><td>Yes (via name)</td><td>Yes (via name)</td></tr>
</tbody></table>
</div>
<p>Use institutions when you need an entity that acts collectively: a guild votes, a government issues decrees, a school enrolls students.</p>
<hr />
<h2 id="use-cases"><a class="header" href="#use-cases">Use Cases</a></h2>
<ul>
<li><strong>Organizations</strong>: Guilds, companies, governments, religions</li>
<li><strong>Social structures</strong>: Families, tribes, castes, classes</li>
<li><strong>Systems</strong>: Economic systems, magical systems, legal frameworks</li>
<li><strong>Abstract entities</strong>: Dream logic, fate, cultural norms</li>
<li><strong>Collectives</strong>: Military units, sports teams, musical ensembles</li>
</ul>
<hr />
<h2 id="complete-example-baker-family-world"><a class="header" href="#complete-example-baker-family-world">Complete Example: Baker Family World</a></h2>
<pre><code class="language-storybook">use schema::enums::{GuildRole, InstitutionType};
institution BakersGuild {
type: trade_guild
members: 50
founded: "1892"
reputation: 0.85
location: BakersGuildHall
leader: Martha
annual_dues: 120
accepts_apprentices: true
max_apprentices_per_mentor: 2
uses behaviors: [
{ tree: ManageApprentices, priority: normal },
{ tree: NegotiateSuppliers, priority: high },
{ tree: HostAnnualBakeOff, when: month is october, priority: high }
]
uses schedule: GuildOperatingHours
---description
The Bakers Guild has served the town since 1892, ensuring quality
standards and fair pricing across all bakeries. Monthly meetings
are held at the Guild Hall, and the annual Bake-Off is the
highlight of the autumn calendar.
---
}
institution TownCouncil {
type: government
members: 12
meets: "first Monday of each month"
location: TownHall
jurisdiction: "town limits"
uses behaviors: [
{ tree: ReviewPetitions },
{ tree: AllocateBudget, priority: high }
]
---description
The elected body governing the town. Martha Baker has been
lobbying them for years about flour import tariffs.
---
}
institution BakersBakeryBusiness {
type: business
owner: Martha
employees: 4
location: BakersBakery
annual_revenue: 180000
established: "2011"
uses behaviors: [
{ tree: DailyBakingOps, priority: high },
{ tree: InventoryManagement },
{ tree: CustomerService }
]
uses schedule: BakeryOperatingHours
---description
The business entity behind Baker's Bakery. Martha runs the
operation with help from her daughter Jane (apprentice baker),
two full-time bakers, and a part-time cashier.
---
}
</code></pre>
<hr />
<h2 id="validation-rules"><a class="header" href="#validation-rules">Validation Rules</a></h2>
<ol>
<li><strong>Unique names</strong>: Institution names must be unique within their scope</li>
<li><strong>Valid field values</strong>: All fields must have values conforming to <a href="./18-value-types.html">value types</a></li>
<li><strong>Unique field names</strong>: No duplicate field names within an institution</li>
<li><strong>Unique prose tags</strong>: No duplicate prose block tags within an institution</li>
<li><strong>Valid behavior links</strong>: Each behavior link must have a <code>tree</code> field</li>
<li><strong>Valid priority levels</strong>: Priority must be <code>low</code>, <code>normal</code>, <code>high</code>, or <code>critical</code></li>
<li><strong>Valid schedule references</strong>: Schedule names in <code>uses schedule</code>/<code>uses schedules</code> must be valid identifiers</li>
<li><strong>Valid identifiers</strong>: Institution names must follow identifier rules (<code>[a-zA-Z_][a-zA-Z0-9_]*</code>)</li>
</ol>
<hr />
<h2 id="cross-references"><a class="header" href="#cross-references">Cross-References</a></h2>
<ul>
<li><a href="./10-characters.html">Characters</a> Characters can be members of institutions</li>
<li><a href="./16a-locations.html">Locations</a> Institutions can be associated with locations</li>
<li><a href="./11-behavior-trees.html">Behavior Trees</a> Institutions can use behaviors</li>
<li><a href="./14-schedules.html">Schedules</a> Institutions can use schedules</li>
<li><a href="./15-relationships.html">Relationships</a> Model membership via relationships</li>
<li><a href="./17-expressions.html">Expressions</a> Conditional behavior activation</li>
<li><a href="./18-value-types.html">Value Types</a> All field value types</li>
<li><a href="./16-other-declarations.html">Other Declarations</a> Overview of all utility declarations</li>
<li><a href="./19-validation.html">Validation Rules</a> Complete validation reference</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../reference/16a-locations.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/16-other-declarations.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/16a-locations.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/16-other-declarations.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>