Files
storybook/docs/book/reference/15-relationships.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

837 lines
32 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>Relationships - 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="relationships"><a class="header" href="#relationships">Relationships</a></h1>
<p>Relationships define connections between characters, institutions, and other entities. They capture social bonds, power dynamics, emotional ties, and interactive patterns. Relationships can be symmetric (friendship) or asymmetric (parent-child), and support bidirectional perspectives where each participant has different fields.</p>
<h2 id="what-is-a-relationship"><a class="header" href="#what-is-a-relationship">What is a Relationship?</a></h2>
<p>A relationship connects two or more participants and describes:</p>
<ul>
<li><strong>Participants</strong>: The entities involved (characters, institutions)</li>
<li><strong>Roles</strong>: Optional labels (parent, employer, spouse)</li>
<li><strong>Shared fields</strong>: Properties of the relationship itself (bond strength, duration)</li>
<li><strong>Perspective fields</strong>: How each participant views the relationship (<code>self</code>/<code>other</code> blocks)</li>
</ul>
<pre><code>Relationship: ParentChild
├─ Participant: Martha (as parent)
│ ├─ self: { responsibility: 1.0, protective: 0.9 }
│ └─ other: { dependent: 0.8 }
├─ Participant: Tommy (as child)
└─ Shared: { bond: 0.9, years_together: 8 }
</code></pre>
<h2 id="syntax"><a class="header" href="#syntax">Syntax</a></h2>
<pre><code class="language-bnf">&lt;relationship-decl&gt; ::= "relationship" &lt;identifier&gt; &lt;body&gt;
&lt;body&gt; ::= "{" &lt;participant&gt;+ &lt;field&gt;* "}"
&lt;participant&gt; ::= &lt;qualified-path&gt; &lt;role-clause&gt;? &lt;perspective-blocks&gt;?
&lt;role-clause&gt; ::= "as" &lt;identifier&gt;
&lt;perspective-blocks&gt; ::= "self" "{" &lt;field&gt;* "}" "other" "{" &lt;field&gt;* "}"
| "self" "{" &lt;field&gt;* "}"
| "other" "{" &lt;field&gt;* "}"
&lt;field&gt; ::= &lt;identifier&gt; ":" &lt;value&gt;
</code></pre>
<h2 id="basic-relationships"><a class="header" href="#basic-relationships">Basic Relationships</a></h2>
<h3 id="simple-two-party-relationship"><a class="header" href="#simple-two-party-relationship">Simple Two-Party Relationship</a></h3>
<pre><code class="language-storybook">relationship Friendship {
Martha
Gregory
bond: 0.8
years_known: 15
}
</code></pre>
<p><strong>Semantics:</strong></p>
<ul>
<li>Two participants: Martha and Gregory</li>
<li>Shared field: <code>bond</code> (strength of friendship)</li>
<li>Shared field: <code>years_known</code> (duration)</li>
</ul>
<h3 id="multi-party-relationship"><a class="header" href="#multi-party-relationship">Multi-Party Relationship</a></h3>
<pre><code class="language-storybook">relationship Family {
Martha
David
Tommy
Elena
household: "Baker Residence"
family_bond: 0.95
}
</code></pre>
<p>Relationships can have any number of participants.</p>
<h2 id="roles"><a class="header" href="#roles">Roles</a></h2>
<p>Roles label a participants function in the relationship.</p>
<h3 id="syntax-1"><a class="header" href="#syntax-1">Syntax</a></h3>
<pre><code class="language-storybook">ParticipantName as role_name
</code></pre>
<h3 id="examples"><a class="header" href="#examples">Examples</a></h3>
<pre><code class="language-storybook">relationship Marriage {
Martha as spouse
David as spouse
bond: 0.9
anniversary: "2015-06-20"
}
</code></pre>
<pre><code class="language-storybook">relationship ParentChild {
Martha as parent
Tommy as child
bond: 0.95
guardianship: true
}
</code></pre>
<pre><code class="language-storybook">relationship EmployerEmployee {
Martha as employer
Elena as employee
workplace: "Martha's Bakery"
salary: 45000
}
</code></pre>
<h3 id="role-semantics"><a class="header" href="#role-semantics">Role Semantics</a></h3>
<ul>
<li><strong>Labels</strong>: Roles are descriptive labels, not types</li>
<li><strong>Multiple roles</strong>: Same person can have different roles in different relationships</li>
<li><strong>Optional</strong>: Roles are optional—participants can be unnamed</li>
<li><strong>Flexibility</strong>: No predefined role vocabulary—use what makes sense</li>
</ul>
<h2 id="perspective-fields-selfother-blocks"><a class="header" href="#perspective-fields-selfother-blocks">Perspective Fields (Self/Other Blocks)</a></h2>
<p>Perspective fields specify how each participant views the relationship. They enable asymmetric, bidirectional relationships.</p>
<h3 id="syntax-2"><a class="header" href="#syntax-2">Syntax</a></h3>
<pre><code class="language-storybook">ParticipantName as role self {
// Fields describing this participant's perspective
} other {
// Fields describing how this participant views others
}
</code></pre>
<h3 id="self-block"><a class="header" href="#self-block">Self Block</a></h3>
<p>The <code>self</code> block contains fields about how the participant experiences the relationship:</p>
<pre><code class="language-storybook">relationship ParentChild {
Martha as parent self {
responsibility: 1.0
protective: 0.9
anxiety_level: 0.6
}
Tommy as child
}
</code></pre>
<p><strong>Marthas perspective:</strong></p>
<ul>
<li><code>responsibility</code>: She feels 100% responsible</li>
<li><code>protective</code>: Shes highly protective (90%)</li>
<li><code>anxiety_level</code>: Moderate anxiety about parenting</li>
</ul>
<h3 id="other-block"><a class="header" href="#other-block">Other Block</a></h3>
<p>The <code>other</code> block contains fields about how the participant views the other participants:</p>
<pre><code class="language-storybook">relationship ParentChild {
Martha as parent self {
responsibility: 1.0
} other {
dependent: 0.8 // She sees Tommy as 80% dependent
mature_for_age: 0.7 // She thinks he's fairly mature
}
Tommy as child
}
</code></pre>
<h3 id="both-blocks"><a class="header" href="#both-blocks">Both Blocks</a></h3>
<pre><code class="language-storybook">relationship EmployerEmployee {
Martha as employer self {
authority: 0.9
stress: 0.6
} other {
respect: 0.8
trust: 0.85
}
Elena as employee
}
</code></pre>
<p><strong>Marthas perspective:</strong></p>
<ul>
<li><strong>Self</strong>: She has high authority (90%), moderate stress (60%)</li>
<li><strong>Other</strong>: She respects Elena (80%), trusts her (85%)</li>
</ul>
<h3 id="asymmetric-relationships"><a class="header" href="#asymmetric-relationships">Asymmetric Relationships</a></h3>
<p>Different participants can have different perspective fields:</p>
<pre><code class="language-storybook">relationship TeacherStudent {
Gandalf as teacher self {
patience: 0.8
wisdom_to_impart: 1.0
} other {
potential: 0.9
ready_to_learn: 0.6
}
Frodo as student self {
eager_to_learn: 0.7
overwhelmed: 0.5
} other {
admiration: 0.95
intimidated: 0.4
}
bond: 0.85
}
</code></pre>
<p><strong>Gandalfs view:</strong></p>
<ul>
<li>Hes patient (80%), has much wisdom to share</li>
<li>Sees Frodo as having high potential but only moderately ready</li>
</ul>
<p><strong>Frodos view:</strong></p>
<ul>
<li>Hes eager but overwhelmed</li>
<li>Deeply admires Gandalf, slightly intimidated</li>
</ul>
<h2 id="shared-fields"><a class="header" href="#shared-fields">Shared Fields</a></h2>
<p>Fields declared at the relationship level (not in <code>self</code>/<code>other</code> blocks) are <strong>shared</strong> among all participants.</p>
<pre><code class="language-storybook">relationship Friendship {
Martha
Gregory
bond: 0.8 // Shared: mutual bond strength
years_known: 15 // Shared: how long they've known each other
shared_routines: 3 // Shared: number of daily routines
}
</code></pre>
<p><strong>Common shared fields:</strong></p>
<ul>
<li><code>bond</code>: Relationship strength (0.0 to 1.0)</li>
<li><code>years_known</code>: Duration of relationship</li>
<li><code>trust</code>: Mutual trust level</li>
<li><code>commitment</code>: Commitment to the relationship</li>
<li><code>compatibility</code>: How well they get along</li>
</ul>
<h2 id="prose-blocks"><a class="header" href="#prose-blocks">Prose Blocks</a></h2>
<p>Relationships can include prose blocks for narrative context.</p>
<pre><code class="language-storybook">relationship MarthaAndGregory {
Martha {
role: shopkeeper
values_loyalty: 0.9
---perspective
Martha appreciates Gregory's unwavering loyalty. He has
been buying her sourdough loaf every morning for fifteen
years. Their brief daily exchanges about the weather and
local gossip are a comforting routine.
---
}
Gregory {
role: regular_customer
always_orders: "sourdough_loaf"
---perspective
Gregory considers Martha's bakery a cornerstone of his
daily routine. The bread is excellent, but it is the brief
human connection that keeps him coming back.
---
}
}
</code></pre>
<p><strong>Common prose tags:</strong></p>
<ul>
<li><code>---perspective</code>: How a participant views the relationship</li>
<li><code>---history</code>: Background of the relationship</li>
<li><code>---dynamics</code>: How the relationship functions</li>
<li><code>---notes</code>: Design or development notes</li>
</ul>
<p>Note: In this syntax, perspective fields are inside participant blocks (not separate <code>self</code>/<code>other</code> blocks).</p>
<h2 id="complete-examples"><a class="header" href="#complete-examples">Complete Examples</a></h2>
<h3 id="simple-friendship"><a class="header" href="#simple-friendship">Simple Friendship</a></h3>
<pre><code class="language-storybook">relationship Friendship {
Martha
NeighborBaker
bond: 0.6
years_known: 10
}
</code></pre>
<h3 id="marriage-with-roles"><a class="header" href="#marriage-with-roles">Marriage with Roles</a></h3>
<pre><code class="language-storybook">relationship Marriage {
Martha as spouse
David as spouse
bond: 0.9
anniversary: "2015-06-20"
children: 2
}
</code></pre>
<h3 id="parent-child-with-perspectives"><a class="header" href="#parent-child-with-perspectives">Parent-Child with Perspectives</a></h3>
<pre><code class="language-storybook">relationship ParentChild {
Martha as parent self {
responsibility: 1.0
protective: 0.9
anxiety_level: 0.6
} other {
dependent: 0.8
mature_for_age: 0.7
}
Tommy as child self {
seeks_independence: 0.7
appreciates_parent: 0.9
} other {
feels_understood: 0.6
wants_more_freedom: 0.8
}
bond: 0.95
years_together: 8
}
</code></pre>
<h3 id="employer-employee"><a class="header" href="#employer-employee">Employer-Employee</a></h3>
<pre><code class="language-storybook">relationship EmployerEmployee {
Martha as employer self {
authority: 0.9
satisfaction_with_employee: 0.85
} other {
respect: 0.8
trust: 0.85
}
Elena as employee self {
job_satisfaction: 0.8
career_growth: 0.7
} other {
respects_boss: 0.9
appreciates_flexibility: 0.95
}
workplace: "Martha's Bakery"
salary: 45000
employment_start: "2023-01-15"
}
</code></pre>
<h3 id="complex-multi-perspective"><a class="header" href="#complex-multi-perspective">Complex Multi-Perspective</a></h3>
<pre><code class="language-storybook">relationship MentorApprentice {
Martha {
role: mentor
teaching_style: "patient"
investment: 0.9
---perspective
Martha sees Elena as the daughter she might have had in
the trade. She recognizes the same passion she felt at
that age and pushes Elena harder because she knows the
talent is there. Every correction comes from love.
---
}
Elena {
role: apprentice
dedication: 0.9
anxiety: 0.4
---perspective
Elena idolizes Martha's skill but fears disappointing
her. Every morning she arrives thirty minutes early to
practice techniques before Martha gets in. She keeps a
notebook of every correction, reviewing them each night.
"I want to be half as good as her someday" -- this quiet
ambition drives everything Elena does.
---
}
bond: 0.85
}
</code></pre>
<h3 id="business-rivalry"><a class="header" href="#business-rivalry">Business Rivalry</a></h3>
<pre><code class="language-storybook">relationship BakeryRivalry {
Martha {
role: established_baker
aware_of_competition: true
respects_rival: 0.6
---perspective
Martha views the new bakery across town as healthy
competition. She respects their pastry work but knows
her sourdough is unmatched. The rivalry pushes her to
keep innovating.
---
}
RivalBaker {
role: newcomer
wants_to_surpass: true
studies_martha: 0.8
---perspective
The rival baker moved to town specifically because of
Martha's reputation. They study her techniques, buy her
bread to analyze it, and dream of the day a customer
chooses their loaf over Martha's sourdough.
---
}
bond: 0.3
}
</code></pre>
<h3 id="multi-party-family"><a class="header" href="#multi-party-family">Multi-Party Family</a></h3>
<pre><code class="language-storybook">relationship BakerFamily {
Martha as parent
David as parent
Tommy as child
Elena as child
household: "Baker Residence"
family_bond: 0.95
dinner_time: 18:00
---dynamics
A loving queer family running a bakery together. Martha and
David met at culinary school, married, and adopted Tommy and
Elena. The whole family works at the bakery on weekends.
---
}
</code></pre>
<h3 id="co-owners-partnership"><a class="header" href="#co-owners-partnership">Co-Owners Partnership</a></h3>
<pre><code class="language-storybook">relationship BakeryPartnership {
Martha {
role: co_owner
specialty: "bread"
handles_finances: true
---perspective
Martha and Jane complement each other perfectly. Martha
handles the bread and business side while Jane creates
the pastries that draw customers in. Together they have
built something neither could alone.
---
}
Jane {
role: co_owner
specialty: "pastries"
handles_creativity: true
---perspective
Jane considers Martha the steady foundation of their
partnership. While Jane experiments and creates, Martha
ensures the bakery runs like clockwork. Their different
strengths make the bakery stronger.
---
}
bond: 0.9
}
</code></pre>
<h2 id="participant-types"><a class="header" href="#participant-types">Participant Types</a></h2>
<p>Participants can be:</p>
<ol>
<li><strong>Characters</strong>: Most common</li>
<li><strong>Institutions</strong>: Organizations in relationships</li>
<li><strong>Locations</strong>: Less common, but valid (e.g., “GuardianOfPlace”)</li>
</ol>
<pre><code class="language-storybook">relationship GuildMembership {
Elena as member
BakersGuild as organization
membership_since: "2023-01-01"
standing: "good"
dues_paid: true
}
</code></pre>
<h2 id="field-resolution"><a class="header" href="#field-resolution">Field Resolution</a></h2>
<p>When a relationship is resolved, fields are merged:</p>
<ol>
<li><strong>Relationship shared fields</strong> apply to all participants</li>
<li><strong>Participant <code>self</code> blocks</strong> apply to that participant</li>
<li><strong>Participant <code>other</code> blocks</strong> describe how that participant views others</li>
</ol>
<p><strong>Example:</strong></p>
<pre><code class="language-storybook">relationship Example {
Martha as friend self {
loyalty: 0.9
} other {
trust: 0.8
}
Gregory as friend
bond: 0.85
}
</code></pre>
<p><strong>Resolution:</strong></p>
<ul>
<li>Martha gets: <code>loyalty: 0.9</code> (from self), <code>trust: 0.8</code> (towards Gregory, from other), <code>bond: 0.85</code> (shared)</li>
<li>Gregory gets: <code>bond: 0.85</code> (shared)</li>
<li>Relationship gets: <code>bond: 0.85</code></li>
</ul>
<h2 id="validation-rules"><a class="header" href="#validation-rules">Validation Rules</a></h2>
<ol>
<li><strong>At least two participants</strong>: Relationships require ≥2 participants</li>
<li><strong>Participants exist</strong>: All participant names must reference defined entities</li>
<li><strong>Unique participant names</strong>: Each participant appears at most once</li>
<li><strong>Field type consistency</strong>: Fields must have valid value types</li>
<li><strong>No circular relationships</strong>: Avoid infinite relationship chains (warning)</li>
<li><strong>Self/other completeness</strong>: If using <code>self</code>/<code>other</code>, both blocks should be present (best practice)</li>
</ol>
<h2 id="use-cases"><a class="header" href="#use-cases">Use Cases</a></h2>
<h3 id="social-networks"><a class="header" href="#social-networks">Social Networks</a></h3>
<pre><code class="language-storybook">relationship BakerFriendship {
Martha
Gregory
bond: 0.8
}
relationship SupplierPartnership {
Martha
Farmer_Jenkins
bond: 0.7
}
relationship BakeryRivalry {
Martha
RivalBaker
bond: 0.2
competitive: true
}
</code></pre>
<h3 id="family-structures"><a class="header" href="#family-structures">Family Structures</a></h3>
<pre><code class="language-storybook">relationship ParentChild {
Martha as parent
Tommy as child
bond: 0.95
}
relationship Siblings {
Tommy as older_sibling
Elena as younger_sibling
bond: 0.85
rivalry: 0.3
}
</code></pre>
<h3 id="power-dynamics"><a class="header" href="#power-dynamics">Power Dynamics</a></h3>
<pre><code class="language-storybook">relationship Vassalage {
King as lord self {
grants: "protection"
expects: "loyalty"
} other {
trusts: 0.6
}
Knight as vassal self {
swears: "fealty"
expects: "land"
} other {
respects: 0.9
}
oath_date: "1205-03-15"
}
</code></pre>
<h3 id="asymmetric-awareness"><a class="header" href="#asymmetric-awareness">Asymmetric Awareness</a></h3>
<pre><code class="language-storybook">relationship StalkingVictim {
Stalker as pursuer self {
obsession: 0.95
distance_maintained: 50 // meters
} other {
believes_unnoticed: true
}
Victim as unaware_target self {
awareness: 0.0
}
danger_level: 0.8
}
</code></pre>
<h2 id="best-practices"><a class="header" href="#best-practices">Best Practices</a></h2>
<h3 id="1-use-descriptive-relationship-names"><a class="header" href="#1-use-descriptive-relationship-names">1. Use Descriptive Relationship Names</a></h3>
<p><strong>Avoid:</strong></p>
<pre><code class="language-storybook">relationship R1 { ... }
relationship MarthaGregory { ... }
</code></pre>
<p><strong>Prefer:</strong></p>
<pre><code class="language-storybook">relationship Friendship { ... }
relationship ParentChild { ... }
relationship MentorApprentice { ... }
</code></pre>
<h3 id="2-use-roles-for-clarity"><a class="header" href="#2-use-roles-for-clarity">2. Use Roles for Clarity</a></h3>
<pre><code class="language-storybook">relationship Marriage {
Martha as spouse
David as spouse
}
</code></pre>
<p>Better than:</p>
<pre><code class="language-storybook">relationship Marriage {
Martha
David
}
</code></pre>
<h3 id="3-shared-fields-for-mutual-properties"><a class="header" href="#3-shared-fields-for-mutual-properties">3. Shared Fields for Mutual Properties</a></h3>
<pre><code class="language-storybook">relationship Partnership {
Martha
Jane
bond: 0.9 // Mutual bond
years_together: 5 // Shared history
}
</code></pre>
<h3 id="4-selfother-for-perspectives"><a class="header" href="#4-selfother-for-perspectives">4. Self/Other for Perspectives</a></h3>
<pre><code class="language-storybook">relationship TeacherStudent {
Teacher as mentor self {
patience: 0.8
} other {
potential: 0.9
}
Student as learner self {
motivation: 0.7
} other {
admiration: 0.95
}
}
</code></pre>
<h3 id="5-prose-blocks-for-rich-context"><a class="header" href="#5-prose-blocks-for-rich-context">5. Prose Blocks for Rich Context</a></h3>
<pre><code class="language-storybook">relationship ComplexDynamic {
Martha { ... }
Jane { ... }
---dynamics
Their relationship is characterized by mutual respect but
divergent goals. Martha focuses on traditional bread while Jane
pushes for experimental pastries, creating creative tension.
---
}
</code></pre>
<h2 id="cross-references"><a class="header" href="#cross-references">Cross-References</a></h2>
<ul>
<li><a href="./10-characters.html">Characters</a> - Participants are typically characters</li>
<li><a href="./16-other-declarations.html#institutions">Institutions</a> - Institutions can participate</li>
<li><a href="./18-value-types.html">Value Types</a> - Field value types</li>
<li><a href="./17-expressions.html">Expression Language</a> - Querying relationships</li>
</ul>
<h2 id="related-concepts"><a class="header" href="#related-concepts">Related Concepts</a></h2>
<ul>
<li><strong>Bidirectional modeling</strong>: <code>self</code>/<code>other</code> blocks enable asymmetric perspectives</li>
<li><strong>Social simulation</strong>: Relationships drive character interactions</li>
<li><strong>Narrative depth</strong>: Prose blocks embed storytelling in relationship data</li>
<li><strong>Power dynamics</strong>: Roles and perspective fields model hierarchies</li>
<li><strong>Emotional bonds</strong>: Bond strength and trust metrics quantify connections</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../reference/14-schedules.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/16a-locations.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/14-schedules.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/16a-locations.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>