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
This commit is contained in:
2026-02-13 21:52:03 +00:00
parent 80332971b8
commit 16deb5d237
290 changed files with 90316 additions and 5827 deletions

134
docs/tutorial/01-welcome.md Normal file
View File

@@ -0,0 +1,134 @@
# Welcome to Storybook
> **Bring characters to life with code that reads like stories.**
Welcome! This tutorial will guide you through the Storybook language step by step. By the end, you will be able to create rich characters, define complex behaviors, build relationships, and model entire narrative worlds.
## What You Will Learn
In this tutorial, we follow Martha and her bakery family, using their daily lives to learn each concept:
1. **Creating Characters** - Define Martha with traits and descriptions
2. **Your First Behavior Tree** - Give characters decision-making abilities
3. **Making Characters Act** - Actions, conditions, and decorators
4. **Advanced Behaviors** - Subtrees, parameters, and complex patterns
5. **Character Relationships** - Model how characters interact
6. **Schedules and Time** - Give characters daily routines
7. **Life Arcs** - Track character development over time
## What is Storybook?
Storybook is a domain-specific language (DSL) for narrative simulation. It lets you describe:
- **Who** characters are (traits, backstory, species)
- **What** they do (behavior trees with decision logic)
- **How** they relate to others (relationships with perspectives)
- **When** they act (schedules and time-based routines)
- **How they change** (life arcs and state machines)
All of this in syntax designed to be readable and expressive.
## Your First Storybook File
Create a file called `hello.sb` and add this:
```storybook
character Martha {
age: 34
skill_level: 0.95
---description
A master baker who runs the most popular bakery in town,
known for her sourdough bread and apple pastries.
---
}
```
That is it. You have defined a character with two numeric fields and a prose description block. Let us break it down:
- `character Martha` declares a new character named Martha
- `{ ... }` contains her attributes
- `age: 34` is an integer field
- `skill_level: 0.95` is a floating-point field (0.0 to 1.0)
- `---description ... ---` is a prose block for narrative text
## Key Concepts
### Everything is a Declaration
Storybook files contain **declarations** -- named definitions of things in your world:
```storybook
character Martha { ... } // A person or creature
behavior BakeRoutine { ... } // Decision-making logic
relationship Family { ... } // A connection between entities
schedule DailyRoutine { ... } // Time-based activities
life_arc Career { ... } // How someone changes over time
```
### Fields Hold Data
Fields use a simple `name: value` format:
```storybook
age: 34 // Integer
skill_level: 0.95 // Float
name: "Martha Baker" // String
is_open: true // Boolean
wake_time: 04:30 // Time
bake_duration: 45m // Duration
```
### Prose Blocks Tell Stories
Prose blocks embed narrative text directly in your definitions:
```storybook
---backstory
Martha learned to bake from her grandmother, starting at age
twelve with simple bread recipes. Over the years she mastered
sourdough, pastries, and specialty cakes, eventually opening
her own bakery.
---
```
You can have multiple prose blocks with different tags (`backstory`, `appearance`, `personality`, etc.) in a single declaration.
## Project Structure
A typical Storybook project organizes files into directories:
```
my-world/
schema/
core_enums.sb // Enum definitions (skill levels, moods, etc.)
templates.sb // Reusable trait sets
beings.sb // Species definitions
world/
characters/
martha.sb // Character definitions
jane.sb
behaviors/
baking.sb // Behavior trees
relationships/
family.sb // Relationship definitions
```
Files reference each other using `use` statements:
```storybook
use schema::core_enums::SkillLevel;
use schema::beings::Human;
character Martha: Human {
skill_level: expert
}
```
## Next Steps
Ready to create your first character? Head to [Creating Characters](./02-creating-characters.md) to start building Martha in detail.
---
**Tip**: You do not need to memorize everything now. This tutorial builds concepts gradually, and you can always refer back to the [Reference Guide](../reference/09-overview.md) for precise syntax details.

View File

@@ -0,0 +1,313 @@
# Creating Characters
Characters are the heart of every Storybook world. In this chapter, you will learn how to define characters with fields, prose blocks, species, and templates.
## A Simple Character
The simplest character has a name and some fields:
```storybook
character Martha {
age: 34
skill_level: 0.95
is_open: true
}
```
Fields use the `name: value` format. Storybook supports several value types:
| Type | Example | Description |
|------|---------|-------------|
| Integer | `42` | Whole numbers |
| Float | `0.85` | Decimal numbers |
| String | `"hello"` | Text in double quotes |
| Boolean | `true` / `false` | Yes or no values |
| Time | `14:30` | Clock times |
| Duration | `2h30m` | Time intervals |
| List | `[1, 2, 3]` | Ordered collections |
## Adding Descriptions with Prose Blocks
Prose blocks embed narrative text directly alongside data. They start and end with `---` and have a tag name:
```storybook
character Martha {
age: 34
skill_level: 0.95
---backstory
Martha learned to bake from her grandmother, starting at age
twelve with simple bread recipes. She mastered sourdough and
pastries, eventually opening the most popular bakery in town.
---
---appearance
A confident woman in her mid-thirties, usually dusted with
flour. Her hands are calloused from years of kneading dough.
---
}
```
You can use any tag name you like. Common ones include `backstory`, `appearance`, `personality`, `motivation`, and `secrets`.
## Defining Species
Species define what a character fundamentally *is*. Define them separately, then reference them with the `:` syntax:
```storybook
species Human {
lifespan: 70
---description
Bipedal mammals with complex language and tool use.
---
}
species Cat {
lifespan: 15
---description
Domestic cats make loyal companions and effective
pest control for bakeries.
---
}
```
Now use species when creating characters:
```storybook
character Martha: Human {
age: 34
}
character Whiskers: Cat {
friendly: true
catches_mice: true
}
```
The `: Human` part says "Martha is a Human." She inherits the species' fields (like `lifespan: 70`) automatically.
A character can have only one species -- you cannot be both Human and Cat.
### But what about hybrids?
If you want a character that combines traits from different sources, use **composition with templates** instead:
```storybook
species Human {
lifespan: 70
reasoning_ability: 1.0
}
template CulinaryExpert {
palate_sensitivity: 0.5..1.0
recipes_mastered: 0..500
can_identify_ingredients: true
}
template BusinessOwner {
business_acumen: 0.0..1.0
manages_finances: true
leadership: 0.0..1.0
}
// A character combining species with multiple templates
character Martha: Human from CulinaryExpert, BusinessOwner {
age: 34
// From CulinaryExpert
palate_sensitivity: 0.9
recipes_mastered: 150
can_identify_ingredients: true
// From BusinessOwner
business_acumen: 0.8
manages_finances: true
leadership: 0.85
// Unique traits
specialty: "sourdough"
years_experience: 22
---personality
A perfectionist in the kitchen who demands the best from her
ingredients and her team. Warm with customers but exacting
with her apprentices.
---
}
```
By combining a species with templates, you can achieve any combination you need. The species defines *what* the character fundamentally is, while templates add *traits* from other sources.
## Reusing Traits with Templates
Templates define reusable sets of attributes. Characters inherit from them using the `from` keyword:
```storybook
template SkilledWorker {
skill_level: 0.0..1.0
years_experience: 0..50
}
template Baker {
include SkilledWorker
specialty: "general"
recipes_mastered: 0..500
}
```
Notice the `0.0..1.0` syntax -- that is a **range**. When a character uses this template, a specific value within that range is selected. Ranges are only valid in templates.
Characters can inherit from multiple templates:
```storybook
character Martha: Human from Baker, BusinessOwner {
age: 34
skill_level: 0.95
specialty: "sourdough"
recipes_mastered: 150
}
```
The `from Baker, BusinessOwner` part says "Martha has the traits from both templates." You can override any inherited field by specifying it directly.
## Species vs. Templates
Understanding the difference is important:
| | Species (`:`) | Templates (`from`) |
|--|--------------|-------------------|
| **Meaning** | What the character *is* | What the character *has* |
| **Count** | Exactly one | Zero or more |
| **Example** | `: Human` | `from Baker, BusinessOwner` |
Think of it this way: a character **is** a Human, but **has** baking skills and business acumen.
## Field Resolution
When a character inherits from multiple sources, fields are resolved in priority order:
1. **Species fields** (lowest priority)
2. **Template fields** (left to right in the `from` clause)
3. **Character fields** (highest priority -- always wins)
```storybook
species Human {
speed: 1.0
}
template Warrior {
speed: 1.5
strength: 10
}
template Berserker {
speed: 2.0
strength: 15
}
character Conan: Human from Warrior, Berserker {
strength: 20
}
// Resolved: speed = 2.0 (Berserker), strength = 20 (Conan)
```
## Using Enums for Controlled Values
Enums define a fixed set of named values. They prevent typos and ensure consistency:
```storybook
enum SkillLevel {
Novice,
Beginner,
Intermediate,
Advanced,
Expert,
Master
}
enum Specialty {
Sourdough,
Pastries,
Cakes,
Bread,
Confections
}
```
Use enum values as field values:
```storybook
character Martha: Human {
skill_level: Master
specialty: Sourdough
}
```
If you write `skill_level: Professional`, the compiler will catch the mistake because `Professional` is not defined in the `SkillLevel` enum.
## Importing Across Files
Real projects split definitions across multiple files. Use the `use` statement to import:
```storybook
// In world/characters/martha.sb
use schema::core_enums::{SkillLevel, Specialty};
use schema::templates::Baker;
use schema::beings::Human;
character Martha: Human from Baker {
skill_level: Master
specialty: Sourdough
}
```
The `use schema::core_enums::{SkillLevel, Specialty}` line imports two enums from the `schema/core_enums.sb` file. You can also import everything with `use schema::core_enums::*`.
## Putting It All Together
Here is a complete character definition with all the features:
```storybook
use schema::core_enums::{SkillLevel, Specialty};
use schema::templates::{Baker, BusinessOwner};
use schema::beings::Human;
character Martha: Human from Baker, BusinessOwner {
// Core identity
age: 34
skill_level: Master
specialty: Sourdough
// Professional
years_experience: 22
recipes_mastered: 150
can_teach: true
// Business
business_acumen: 0.8
leadership: 0.85
---backstory
Martha learned to bake from her grandmother, starting at age
twelve with simple bread recipes. She mastered sourdough and
pastries, eventually opening the most popular bakery in town.
---
---personality
A perfectionist in the kitchen who demands the best from her
ingredients and her team. Warm with customers but exacting
with her apprentices. Known for arriving at 4 AM to start
the morning batch.
---
}
```
## Next Steps
Now that Martha exists, let us give her something to do. In [Your First Behavior Tree](./03-first-behavior-tree.md), you will learn how characters make decisions.
---
**Reference**: For complete character syntax details, see the [Characters Reference](../reference/10-characters.md).

View File

@@ -0,0 +1,203 @@
# Your First Behavior Tree
Behavior trees define how characters make decisions. They model the thought process: "Try this first, and if it fails, try that instead." In this chapter, you will create your first behavior tree for Martha.
## What is a Behavior Tree?
A behavior tree is a hierarchy of nodes that executes from top to bottom. Each node either **succeeds** or **fails**, and the tree uses that result to decide what to do next.
There are two fundamental building blocks:
- **`choose`** (Selector): Try children in order until one succeeds. Think "try A, else try B, else try C."
- **`then`** (Sequence): Run children in order, stopping if any fails. Think "do A, then B, then C -- all must succeed."
## Your First Tree
Let us give Martha a simple baking behavior:
```storybook
behavior Martha_BakeRoutine {
choose what_to_do {
then fill_special_orders {
CheckSpecialOrders
PrepareSpecialIngredients
BakeSpecialItem
}
then daily_bread {
MixDough
KneadDough
BakeLoaves
}
CleanWorkstation
}
}
```
Reading this as a story:
> Martha will **choose** what to do. First, she tries to **fill special orders**: she checks for orders, prepares special ingredients, and bakes the item. If that path fails (maybe there are no special orders), she tries **daily bread**: she mixes dough, kneads it, and bakes loaves. If even that fails, she simply cleans her workstation.
## Understanding choose (Selector)
A `choose` node tries its children one at a time. As soon as one succeeds, it stops and returns success. If all children fail, it returns failure.
```storybook
choose response {
HandleUrgentOrder // Try first: handle urgent order
ServeCustomer // If that fails: serve a customer
RestockShelves // If that fails: restock
}
```
This is like a priority list -- the first successful option wins.
## Understanding then (Sequence)
A `then` node runs its children in order. If any child fails, the whole sequence fails and stops. All children must succeed for the sequence to succeed.
```storybook
then make_sourdough {
MixDough // Must succeed
KneadDough // Must succeed
FirstRise // Must succeed
ShapeLoaves // Must succeed
}
```
If `MixDough` fails (no flour available), the whole process stops.
## Naming Your Nodes
Both `choose` and `then` accept optional labels:
```storybook
choose daily_priority {
then morning_baking { ... }
then afternoon_sales { ... }
}
```
Labels are optional but highly recommended. They make your trees readable as narratives and help with debugging. Compare:
```storybook
// Without labels (hard to read)
choose {
then { MixDough, BakeLoaves }
then { ServeCustomer, CollectPayment }
}
// With labels (reads like a story)
choose priority {
then baking { MixDough, BakeLoaves }
then sales { ServeCustomer, CollectPayment }
}
```
## Combining choose and then
Behavior trees become powerful when you nest selectors and sequences:
```storybook
behavior Jane_PastryRoutine {
choose pastry_priorities {
// Highest priority: fill custom cake orders
then custom_orders {
ReviewCakeOrder
DesignDecoration
BakeAndDecorate
PackageForPickup
}
// If no orders: prepare display pastries
then display_pastries {
RollPastryDough
PrepareFillings
AssemblePastries
ArrangeDisplay
}
// Default: experiment with new recipes
ExperimentWithFlavors
}
}
```
Reading this as narrative:
> Jane always prioritizes custom cake orders. She reviews the order, designs the decoration, bakes and decorates, then packages it. If there are no orders, she prepares display pastries. If there is nothing else to do, she experiments with new flavors.
## Actions
The leaf nodes in a behavior tree are **actions** -- concrete things a character does:
```storybook
MixDough // Simple action
KneadDough // Simple action
ServeCustomer // Simple action
```
Actions are identifiers that the runtime interprets. They represent the actual behaviors executed in your simulation.
## A Complete Example
Here is a behavior tree for the morning rush at the bakery:
```storybook
behavior Bakery_MorningRush {
---description
Handles the busy morning rush when customers are
lining up for fresh bread and pastries.
---
choose morning_priority {
then serve_waiting_customer {
GreetCustomer
TakeOrder
PackageItems
CollectPayment
ThankCustomer
}
then restock_display {
CheckDisplayLevels
FetchFromKitchen
ArrangeOnShelves
}
then quick_bake {
CheckInventory
StartQuickBatch
MonitorOven
}
}
}
```
Notice the prose block (`---description ... ---`) at the top of the behavior. You can document what the behavior does right alongside the code.
## Behavior-Character Connection
Characters link to behaviors using the `uses behaviors` clause:
```storybook
character Martha: Human {
age: 34
uses behaviors: [
{ tree: Martha_BakeRoutine },
{ tree: HandleEmergency }
]
}
```
This tells the simulation that Martha uses two behavior trees. We will cover advanced behavior linking (priorities, conditions) in [Making Characters Act](./04-making-characters-act.md).
## Next Steps
Your behavior trees so far make decisions between options and run sequences of actions. In [Making Characters Act](./04-making-characters-act.md), you will learn how to add conditions, decorators, and parameters to create truly dynamic behaviors.
---
**Reference**: For complete behavior tree syntax, see the [Behavior Trees Reference](../reference/11-behavior-trees.md).

View File

@@ -0,0 +1,302 @@
# Making Characters Act
In the previous chapter, you created behavior trees with selectors and sequences. Now you will add conditions, action parameters, and decorators to create dynamic, responsive behaviors.
## Conditions: if and when
Conditions let behavior trees react to the world. Use `if` or `when` to test a condition before proceeding:
```storybook
behavior Martha_React {
choose response {
then bake_path {
if(inventory_sufficient)
StartBaking
}
then restock_path {
if(inventory_low)
OrderSupplies
}
CleanWorkstation
}
}
```
`if(inventory_sufficient)` succeeds when inventory is sufficient, and fails otherwise. If it fails, the entire `bake_path` sequence fails, and the tree moves on to the next option.
`if` and `when` are interchangeable -- use whichever reads more naturally:
```storybook
// "if" for state checks
if(health < 20)
// "when" for event-like conditions
when(alarm_triggered)
```
### Condition Expressions
Conditions support comparisons and logical operators:
```storybook
// Comparisons
if(health < 20)
if(distance > 100)
if(name == "Martha")
if(status is Curious) // 'is' is syntactic sugar for ==
// Logical operators
if(hungry and tired)
if(rich or lucky)
if(not is_dangerous)
// Combined
if(health < 50 and not has_potion)
if((age > 18 and age < 65) or is_veteran)
```
## Action Parameters
Actions can take named parameters using parenthesis syntax:
```storybook
behavior Martha_BakeSpecial {
then baking {
MixDough(recipe: "sourdough", quantity: 10)
KneadDough(duration: 15m)
BakeLoaves(temperature: 230, duration: 35m)
}
}
```
Parameters are fields inside `( )` after the action name. They let you customize behavior without defining separate actions for each variation.
## Decorators
Decorators wrap a single child node and modify its behavior. They are your tools for timing, repetition, and conditional execution.
### repeat -- Looping
```storybook
// Infinite repeat (checks oven forever)
repeat {
CheckOvenTemperature
}
// Repeat exactly 3 times
repeat(3) {
KneadDough
}
// Repeat between 2 and 5 times (random)
repeat(2..5) {
FoldDough
}
```
### invert -- Flip Results
Inverts success/failure. Useful for "if NOT" conditions:
```storybook
behavior SafeBake {
choose options {
then bake_safely {
invert { OvenOverheating } // Succeeds if oven is NOT overheating
ContinueBaking
}
StopAndInspect
}
}
```
### retry -- Try Again on Failure
Retries the child up to N times if it fails:
```storybook
retry(3) {
LightOven // Try up to 3 times before giving up
}
```
### timeout -- Time Limits
Fails the child if it does not complete within the duration:
```storybook
timeout(10s) {
WaitForDoughToRise // Must finish within 10 seconds
}
```
### cooldown -- Rate Limiting
Prevents the child from running again within the cooldown period:
```storybook
cooldown(30s) {
CheckOvenTemperature // Can only check once every 30 seconds
}
```
### if as Decorator (Guard)
The `if` decorator only runs the child when a condition is true:
```storybook
if(has_special_orders) {
PrepareSpecialBatch // Only prepare when there are orders
}
```
This is different from `if` as a condition node. As a decorator, `if` wraps a child and gates its execution. As a condition node, `if` is a simple pass/fail check inline in a sequence.
### succeed_always and fail_always
Force a result regardless of the child:
```storybook
// Try bonus task, but don't fail the routine if it fails
succeed_always {
ExperimentWithNewRecipe
}
// Temporarily disable a feature
fail_always {
UntestedBakingMethod
}
```
## Combining Decorators
Decorators can nest for complex control:
```storybook
behavior ResilientAction {
// Only run if oven is ready, with 20s timeout, retrying up to 3 times
if(oven_ready) {
timeout(20s) {
retry(3) {
BakeDelicateItem
}
}
}
}
```
Execution flows outside-in: first the `if` checks the oven, then the timeout starts, then the retry begins.
## Subtree References
The `include` keyword references another behavior tree, enabling reuse:
```storybook
behavior SourdoughRecipe {
then sourdough {
MixDough(recipe: "sourdough", quantity: 10)
KneadDough(duration: 15m)
FirstRise(duration: 2h)
ShapeLoaves
}
}
behavior Martha_DailyRoutine {
choose daily_priority {
then special_orders {
if(has_special_orders)
include SpecialOrderBehavior
}
include SourdoughRecipe // Reuse sourdough behavior
}
}
```
Subtrees help you avoid duplicating behavior logic. You can also reference behaviors from other modules using qualified paths:
```storybook
include behaviors::baking::sourdough
include behaviors::service::greet_customer
```
## Behavior Linking with Priorities
Characters can link to multiple behaviors with priorities and conditions:
```storybook
character Martha: Human {
uses behaviors: [
{
tree: BakerRoutine
priority: normal
},
{
tree: HandleEmergency
when: emergency_detected
priority: high
},
{
tree: HandleHealthInspection
when: inspector_present
priority: critical
}
]
}
```
The runtime evaluates behaviors by priority (critical > high > normal > low). Higher-priority behaviors preempt lower-priority ones when their conditions are met.
## A Complete Example
Here is a complete behavior tree for handling the morning rush:
```storybook
behavior MorningRush_Routine {
---description
The bakery's morning rush routine: serve customers, restock,
and keep the ovens running.
---
repeat {
then rush_cycle {
// Serve any waiting customers
choose service_mode {
then serve_regular {
if(customer_waiting)
GreetCustomer
TakeOrder
PackageItems
CollectPayment
}
then restock {
if(display_low)
FetchFromKitchen
ArrangeOnShelves
}
}
// Check ovens between customers
timeout(5s) {
CheckAllOvens
}
PrepareNextBatch
}
}
}
```
This tree repeats forever: serve a customer or restock the display, check the ovens, and prepare the next batch.
## Next Steps
You now know the full toolkit for behavior trees. In [Advanced Behaviors](./05-advanced-behaviors.md), you will learn patterns for building complex AI systems with nested trees, state-based switching, and modular design.
---
**Reference**: See [Decorators Reference](../reference/12-decorators.md) for all decorator types and [Expression Language](../reference/17-expressions.md) for complete condition syntax.

View File

@@ -0,0 +1,222 @@
# Advanced Behaviors
You have learned the fundamentals of behavior trees. This chapter covers advanced patterns: complex decision hierarchies, modular design with subtrees, and state-driven behavior.
## Deep Decision Trees
Real characters need layered decision-making. Nest selectors and sequences to create rich AI:
```storybook
behavior Baker_DailyAI {
choose daily_activity {
// Morning: Prepare the bakery
then morning_prep {
if(time_is_morning)
then prep_sequence {
LightOven
PrepareDough
StartFirstBatch
}
}
// Day: Serve customers
then day_service {
if(time_is_daytime)
choose service_mode {
then serve_customer {
if(customer_waiting)
GreetCustomer
TakeOrder
PackageItems
CollectPayment
}
then restock {
if(display_low)
FetchFromKitchen
}
CleanCounter
}
}
// Evening: Close up
then evening_close {
if(time_is_evening)
then close_sequence {
TurnOffOvens
CleanKitchen
CountRegister
LockUp
}
}
}
}
```
Each level of nesting refines the decision. The outer `choose` selects the time of day; inner nodes handle the specifics.
## Modular Subtrees
Large behavior trees become unwieldy. Break them into focused subtrees and compose with `include`:
```storybook
// Focused subtree: just baking
behavior Baking_Sourdough {
then sourdough_sequence {
MixDough
KneadDough
FirstRise
ShapeLoaves
}
}
// Focused subtree: just customer service
behavior Service_ServeCustomer {
then service_sequence {
GreetCustomer
TakeOrder
PackageItems
CollectPayment
}
}
// Composition: combine subtrees
behavior Martha_FullDay {
choose activity {
then morning_baking {
if(time_is_morning)
include Baking_Sourdough
include Baking_Pastries
}
then afternoon_sales {
if(time_is_afternoon)
include Service_ServeCustomer
}
CleanWorkstation
}
}
```
Benefits of modular subtrees:
- Each subtree is testable in isolation
- Multiple characters can share subtrees
- Changes propagate automatically
## Conditional Behavior Selection
Use conditions to switch between behavioral modes:
```storybook
behavior SmartBaker {
choose strategy {
// Busy mode when there are many customers
then busy_mode {
if(customer_count > 5 and inventory_sufficient)
choose rush_tactics {
ServeFastOrder
QuickRestock
ExpressBake
}
}
// Careful mode when supplies are low
then careful_mode {
if(inventory_low or special_ingredients_missing)
choose conservation_tactics {
ReducePortions
SubstituteIngredients
OrderEmergencySupply
}
}
// Normal mode otherwise
then normal_mode {
if(customer_count <= 5 and inventory_sufficient)
StandardRoutine
}
}
}
```
## Decorator Combinations
Combine decorators to build sophisticated control patterns:
```storybook
behavior Baker_SpecialRecipe {
// Only when inventory is sufficient
if(has_special_ingredients) {
// Limited to once per hour
cooldown(1h) {
// Must complete within 30 minutes
timeout(30m) {
// Try up to 3 times
retry(3) {
then bake_special {
PrepareSpecialDough
BakeAtPreciseTemperature
}
}
}
}
}
}
```
## Prose Documentation
Add narrative context to complex behaviors with prose blocks:
```storybook
behavior Elena_TrainingSession {
---description
Elena practicing a new recipe under Martha's guidance.
Uses retry decorator for persistence and if for
checking readiness.
---
choose training_strategy {
then practice_supervised {
if(martha_available)
retry(3) {
then attempt_recipe {
ReviewRecipeSteps
MeasureIngredients
MixAndKnead
CheckWithMartha
}
}
}
then practice_solo {
if(not martha_available)
then solo_attempt {
ReviewRecipeNotes
AttemptRecipeFromMemory
TasteTestResult
}
}
}
}
```
## Design Tips
**Prefer shallow trees**: Break deep nesting into subtrees with `include`.
**Name every composite node**: Labels make trees self-documenting.
**Use decorators for control flow**: Timing, repetition, and gating belong in decorators, not in action logic.
**Keep actions atomic**: Each action should do one thing. Complex operations are sequences of simple actions.
## Next Steps
Characters do not exist in isolation. In [Character Relationships](./06-relationships.md), you will model how characters connect to each other -- friendships, rivalries, parent-child bonds, and more.
---
**Reference**: See [Behavior Trees Reference](../reference/11-behavior-trees.md) and [Decorators Reference](../reference/12-decorators.md) for complete syntax.

View File

@@ -0,0 +1,212 @@
# Character Relationships
Characters exist in a web of connections -- friendships, rivalries, parent-child bonds, and complex power dynamics. In Storybook, relationships are first-class declarations that capture these connections with nuance and perspective.
## Basic Relationships
The simplest relationship connects two characters with shared fields:
```storybook
relationship MarthaAndEmma {
Martha as parent {}
Emma as child {}
bond: 0.95
type: "parent_child"
}
```
This says Martha and Emma share a relationship with a bond strength of 0.95 (very close). The `bond` field is shared -- it applies equally to both participants.
## Adding Roles
Roles label each participant's function in the relationship:
```storybook
relationship ParentChild {
Martha as parent
Emma as child
bond: 0.95
guardianship: true
}
```
The `as parent` and `as child` labels clarify who plays which role. Roles are descriptive -- you can use any name that makes sense.
## Perspectives: Self and Other
Real relationships are not symmetric. How one person sees the relationship may differ from how the other sees it. Storybook handles this with `self` and `other` blocks:
```storybook
relationship MentorApprentice {
Martha as mentor self {
patience: 0.8
investment_in_student: 0.9
} other {
sees_potential: 0.85
frustration_level: 0.2
}
Elena as apprentice self {
dedication: 0.9
overwhelmed: 0.4
} other {
admiration: 0.95
desire_to_impress: 0.9
}
bond: 0.85
}
```
Reading this:
- **Martha's self view**: She feels patient (80%), highly invested in her student
- **Martha's view of Elena (other)**: Sees high potential (85%) with low frustration (20%)
- **Elena's self view**: Dedicated (90%) but sometimes overwhelmed (40%)
- **Elena's view of Martha (other)**: Deep admiration (95%), strong desire to impress (90%)
- **Shared**: Their bond strength is 0.85
## Prose in Relationships
Relationships can include narrative descriptions for each participant:
```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. He worries
about what would happen if she ever retired.
---
}
bond: 0.7
}
```
## Multi-Party Relationships
Relationships can involve more than two participants:
```storybook
relationship BakerFamily {
Martha as parent
Jane as parent
Emma as child
household: "Baker Residence"
family_bond: 0.95
dinner_time: 18:00
---dynamics
A loving family running a bakery together. Martha handles
the bread, Jane manages pastries, and Emma helps out on
weekends while learning the craft.
---
}
```
## Asymmetric Awareness
Relationships can model situations where one party does not know the relationship exists:
```storybook
relationship BossAndNewHire {
Martha {
role: boss
aware_of_struggles: false
expects: high_quality_work
---perspective
Martha sees the new hire as competent and expects them
to learn the bakery routines quickly. She has no idea
they are struggling with the early morning schedule.
---
}
NewHire {
role: employee
intimidated: 0.8
hides_struggles: true
---perspective
The new hire is in awe of Martha's skill but terrified
of disappointing her. They arrive thirty minutes early
every day to practice techniques before she gets in.
---
}
bond: 0.4
}
```
## Institutional Relationships
Institutions can participate in relationships too:
```storybook
relationship GuildMembership {
Martha as member
BakersGuild as organization
membership_since: "2015-01-01"
standing: "good"
dues_paid: true
}
```
## Building a Relationship Web
Multiple relationships create a rich social network:
```storybook
relationship Marriage {
Martha as spouse
Jane as spouse
bond: 0.9
}
relationship MentorApprentice {
Martha as mentor
Elena as apprentice
bond: 0.85
}
relationship RegularCustomer {
Martha as shopkeeper
Gregory as customer
bond: 0.7
}
relationship Colleagues {
Martha as peer
NeighborBaker as peer
bond: 0.5
competitive: true
}
```
## Next Steps
Characters have traits, behaviors, and relationships. In [Schedules and Time](./07-schedules.md), you will give them daily routines and time-based activities.
---
**Reference**: For complete relationship syntax, see the [Relationships Reference](../reference/15-relationships.md).

View File

@@ -0,0 +1,249 @@
# Schedules and Time
Characters live in time. A baker wakes before dawn to prepare dough; a guard patrols during the day shift; an innkeeper serves customers until late. Schedules define these time-based routines.
## Basic Schedules
A schedule contains time blocks, each with a time range and an action:
```storybook
schedule SimpleBaker {
block morning_prep {
05:00 - 08:00
action: baking::prepare_dough
}
block sales {
08:00 - 14:00
action: baking::serve_customers
}
block cleanup {
14:00 - 15:00
action: baking::close_shop
}
}
```
Time ranges use 24-hour clock format (`HH:MM`). The `action` field links to a behavior tree that drives the character's activity during that block.
## Named Blocks
Blocks can have names (like `morning_prep` above). Named blocks are important for schedule composition -- they allow child schedules to override specific blocks by name.
## Linking Schedules to Characters
Characters use the `uses schedule` clause:
```storybook
character Baker: Human {
uses schedule: SimpleBaker
}
```
For multiple schedules:
```storybook
character Innkeeper: Human {
uses schedules: [WeekdaySchedule, WeekendSchedule]
}
```
## Temporal Constraints
Blocks can be restricted to specific times using temporal constraints:
### Season Constraints
```storybook
schedule SeasonalBaker {
block summer_hours {
06:00 - 20:00
action: baking::long_shift
on season summer
}
block winter_hours {
07:00 - 18:00
action: baking::short_shift
on season winter
}
}
```
### Day of Week Constraints
```storybook
schedule WeeklyPattern {
block weekday_work {
09:00 - 17:00
action: work::standard
on day monday
}
block weekend_rest {
10:00 - 16:00
action: leisure::relax
on day saturday
}
}
```
Temporal constraint values (like `summer` or `monday`) reference enums defined in your storybook:
```storybook
enum Season { spring, summer, fall, winter }
enum DayOfWeek { monday, tuesday, wednesday, thursday, friday, saturday, sunday }
```
## Recurring Events
Use `recurs` to define events that repeat on a schedule:
```storybook
schedule MarketSchedule {
// Regular daily hours
block work {
08:00 - 17:00
action: shop::regular_sales
}
// Market day every Saturday
recurs MarketDay on day saturday {
block setup {
06:00 - 08:00
action: market::setup_stall
}
block busy_market {
08:00 - 18:00
action: market::busy_sales
}
block teardown {
18:00 - 20:00
action: market::pack_up
}
}
}
```
Recurrences take priority over regular blocks. On Saturdays, the `MarketDay` blocks replace the regular `work` block.
## Schedule Composition with extends
Schedules can extend other schedules, inheriting and overriding blocks:
```storybook
schedule BaseShopkeeper {
block open {
09:00 - 17:00
action: shop::standard_hours
}
}
schedule EarlyBaker extends BaseShopkeeper {
block open {
05:00 - 13:00
action: baking::early_shift
}
}
```
The `EarlyBaker` schedule overrides the `open` block by name -- same block name, different hours. Any blocks not overridden are inherited unchanged.
You can chain extensions:
```storybook
schedule MasterBaker extends EarlyBaker {
block open {
03:00 - 11:00
action: baking::master_work
}
block teaching {
14:00 - 16:00
action: baking::teach_apprentice
}
}
```
`MasterBaker` overrides `open` again and adds a new `teaching` block.
## Overnight Blocks
Time ranges can span midnight:
```storybook
schedule NightGuard {
block night_patrol {
22:00 - 06:00
action: security::patrol
}
}
```
The system interprets this as 22:00 to midnight on day one, then midnight to 06:00 on day two.
## A Complete Schedule Example
```storybook
schedule MasterBaker_FullYear {
// Daily base
block prep {
04:00 - 06:00
action: baking::prepare
}
block baking {
06:00 - 10:00
action: baking::bake
}
block sales {
10:00 - 16:00
action: baking::serve
}
block cleanup {
16:00 - 17:00
action: baking::clean
}
// Summer extended hours
block summer_sales {
10:00 - 20:00
action: baking::busy_summer
on season summer
}
// Weekly market
recurs MarketDay on day saturday {
block market_prep {
02:00 - 04:00
action: baking::market_prep
}
block market_sales {
08:00 - 18:00
action: baking::market_rush
}
}
// Annual harvest festival
recurs HarvestFestival on dates "Sep 20" .. "Sep 25" {
block festival {
06:00 - 23:00
action: baking::festival_mode
}
}
}
```
## Next Steps
Characters now have traits, behaviors, relationships, and schedules. In [Life Arcs](./08-life-arcs.md), you will learn how to model character development over time -- how they grow, change, and evolve through different phases of life.
---
**Reference**: For complete schedule syntax, see the [Schedules Reference](../reference/14-schedules.md).

View File

@@ -0,0 +1,271 @@
# Life Arcs
Characters grow and change. A timid apprentice becomes a confident master baker. A new employee finds their place in the team. Life arcs model these transformations as state machines -- discrete phases with conditions that trigger transitions between them.
## What is a Life Arc?
A life arc defines:
- **States**: Distinct phases (e.g., "apprentice", "journeyman", "master")
- **Transitions**: Conditions that move between states (e.g., "when skill > 80, become master")
- **On-enter actions**: Changes that happen when entering a state (e.g., set confidence to 0.9)
## Your First Life Arc
```storybook
life_arc BakerCareer {
state apprentice {
on enter {
Baker.skill_level: 0.2
Baker.confidence: 0.3
}
on skill_level > 0.5 -> journeyman
}
state journeyman {
on enter {
Baker.confidence: 0.6
}
on skill_level > 0.8 -> master
}
state master {
on enter {
Baker.confidence: 0.95
Baker.can_teach: true
}
}
}
```
Reading this as a story:
> The baker starts as an **apprentice** with low skill and confidence. When skill exceeds 0.5, they become a **journeyman** with improved confidence. When skill exceeds 0.8, they become a **master** who is confident and can teach others.
## States
Each state represents a distinct phase. States contain:
- **on enter block**: Field updates that happen when entering the state
- **Transitions**: Conditions that trigger moving to another state
- **Prose blocks**: Narrative descriptions
```storybook
state early_apprentice {
on enter {
Elena.skill_level: novice
Elena.confidence: timid
}
on recipes_mastered > 5 -> growing_apprentice
on quit_apprenticeship -> former_apprentice
---narrative
Elena's hands shake as she measures flour. She checks the
recipe three times before adding each ingredient. Martha
patiently corrects her technique.
---
}
```
## Transitions
Transitions use expressions to decide when to change state:
```storybook
// Simple conditions
on health < 20 -> fleeing
on quest_complete -> celebrating
// Boolean fields
on is_hostile -> combat
on not ready -> waiting
// Equality checks
on status is active -> active_state
on name is "Martha" -> found_martha
// Complex conditions
on health < 50 and enemy_count > 3 -> retreat
on (tired and hungry) or exhausted -> resting
```
### Transition Priority
When multiple transitions could fire, the **first one in declaration order** wins:
```storybook
state combat {
on health < 10 -> desperate // Checked first
on health < 50 -> defensive // Checked second
on surrounded -> retreat // Checked third
}
```
If health is 5, only `desperate` triggers, even though `defensive` is also true.
## On-Enter Actions
The `on enter` block sets field values when entering a state. It runs exactly once per transition:
```storybook
state master_baker {
on enter {
Elena.skill_level: master
Elena.confidence: commanding
Elena.can_teach: true
}
}
```
The syntax is `EntityName.field: value`. This updates the referenced character's field.
## Elena's Complete Journey
Here is a complete life arc tracking Elena's growth from apprentice to master:
```storybook
life_arc ElenaCareer {
---description
Tracks Elena's professional and personal growth as she
progresses from nervous apprentice to confident master baker.
---
state early_apprentice {
on enter {
Elena.skill_level: novice
Elena.confidence: timid
}
on recipes_mastered > 5 -> growing_apprentice
---narrative
Elena's hands shake as she measures flour. She checks the
recipe three times before adding each ingredient. Martha
patiently corrects her technique.
---
}
state growing_apprentice {
on enter {
Elena.skill_level: beginner
Elena.confidence: uncertain
}
on recipes_mastered > 15 -> journeyman
---narrative
The shaking stops. Elena can make basic breads without
looking at the recipe. She still doubts herself but
Martha's encouragement is taking root.
---
}
state journeyman {
on enter {
Elena.skill_level: intermediate
Elena.confidence: growing
Elena.can_work_independently: true
}
on recipes_mastered > 50 -> master
---narrative
Elena runs the morning shift alone while Martha handles
special orders. Customers start asking for "Elena's rolls."
---
}
state master {
on enter {
Elena.skill_level: master
Elena.confidence: commanding
Elena.can_teach: true
}
---narrative
Master Baker Elena. She has earned it. The guild acknowledges
her mastery, and Martha beams with pride. Elena begins
mentoring her own apprentice.
---
}
}
```
## Common Patterns
### Hub-and-Spoke
A central idle state with branches to specialized states:
```storybook
life_arc BakerBehavior {
state idle {
on customer_arrived -> serving
on order_placed -> baking
on delivery_arrived -> receiving
}
state serving { on customer_served -> idle }
state baking { on batch_complete -> idle }
state receiving { on delivery_processed -> idle }
}
```
### Linear Progression
States form a one-way sequence (quests, tutorials):
```storybook
life_arc Tutorial {
state intro { on clicked_start -> movement }
state movement { on moved_forward -> combat }
state combat { on defeated_enemy -> inventory }
state inventory { on opened_inventory -> complete }
state complete {}
}
```
### Cyclic States
States form a loop (day/night, seasons, mood swings):
```storybook
life_arc DayNightCycle {
state dawn { on hour >= 8 -> day }
state day { on hour >= 18 -> dusk }
state dusk { on hour >= 20 -> night }
state night { on hour >= 6 -> dawn }
}
```
## Tips
**Order transitions by urgency**: Put the most critical conditions first, since the first true transition wins.
**Use descriptive state names**: `waiting_for_customer` is clearer than `state1`.
**Add narrative prose blocks**: They make life arcs readable as stories and serve as documentation.
**Avoid orphan states**: Every state should be reachable from some other state (the compiler will warn you about unreachable states).
## What You Have Learned
Congratulations! You have completed the tutorial. You now know how to:
- Create characters with species, templates, and enums
- Build behavior trees with selectors, sequences, and decorators
- Add conditions and action parameters
- Model relationships with perspectives
- Define time-based schedules
- Track character development with life arcs
## Where to Go Next
- **[Reference Guide](../reference/09-overview.md)**: Complete syntax specifications
- **[Design Patterns](../advanced/20-patterns.md)**: Common patterns and best practices
- **[Examples Gallery](../examples/24-baker-family-complete.md)**: Full working examples to learn from
---
**Reference**: For complete life arc syntax, see the [Life Arcs Reference](../reference/13-life-arcs.md).

View File

@@ -0,0 +1,500 @@
# Locations and Institutions
So far you have created characters, given them behaviors, connected them with relationships, scheduled their days, and guided them through life arcs. But characters need places to *be* and organizations to *belong to*. That is what locations and institutions provide.
---
## What Are Locations?
A **location** is a place in your world. It can be a building, a room, a park, a city -- any space where things happen. Locations hold fields that describe the place and optional prose blocks for narrative detail.
### Your First Location
Let's create the bakery where Martha works:
```storybook
location BakersBakery {
type: bakery
address: "14 Main Street"
capacity: 30
}
```
That is all it takes. The `location` keyword, a name, and a block of fields. Every field is a key-value pair, and you choose whatever fields make sense for your world.
### Adding Detail
A real location needs more than three fields. Let's flesh out the bakery:
```storybook
location BakersBakery {
type: bakery
address: "14 Main Street"
capacity: 30
employees: 4
specialty: "artisan sourdough"
daily_output_loaves: 80..120
open: true
established: "2011"
}
```
Notice `daily_output_loaves: 80..120` -- that is a range. Each simulation run can pick a different number of loaves, adding natural variation.
### Prose Blocks
Bare fields are good for data, but locations also need narrative flavor. Use prose blocks:
```storybook
location BakersBakery {
type: bakery
address: "14 Main Street"
capacity: 30
---description
A warm, inviting bakery on Main Street. The smell of fresh bread
wafts out the door every morning at dawn. Martha has run the shop
for fifteen years, and the locals consider it the heart of the
neighborhood.
---
}
```
Prose blocks start with `---tag_name` and end with `---`. The tag name (`description` here) becomes the key. You can have as many prose blocks as you want:
```storybook
location BakersBakery {
type: bakery
---description
The bakery on Main Street...
---
---history
Originally a hardware store, Martha converted the space in 2011...
---
---atmosphere
Flour dust catches the light from tall windows...
---
}
```
---
## Building a World with Locations
Locations work best when they form a coherent world. Here is the Baker family's neighborhood:
```storybook
location BakersBakery {
type: bakery
address: "14 Main Street"
capacity: 30
owner: Martha
---description
Martha's artisan bakery. The stone oven was imported from France.
---
}
location BakerHome {
type: residence
address: "22 Elm Lane"
bedrooms: 4
has_garden: true
---description
The Baker family home. Martha insisted on an oversized kitchen.
---
}
location BakersGuildHall {
type: guild_hall
address: "7 Guild Row"
capacity: 100
established: "1892"
---description
The historic headquarters of the Bakers Guild.
---
}
location TownSquare {
type: public_square
capacity: 500
has_fountain: true
has_market_stalls: true
---description
The central gathering place. On weekends, the farmers market
fills the square with produce stalls.
---
}
```
### Modeling Hierarchy
Storybook does not enforce a built-in parent-child relationship for locations. Instead, you use fields to express hierarchy:
```storybook
location MainStreet {
type: street
district: TownCenter
shops: 12
}
location BakersBakery {
type: bakery
street: MainStreet
district: TownCenter
}
```
This convention-based approach keeps the language simple while letting you model whatever spatial relationships your world needs.
---
## What Are Institutions?
An **institution** is an organization, group, or system. Think of it as a character that represents a collective: a guild, a government, a school, a business. Institutions have a key capability that locations lack -- they can **use behaviors and schedules**, just like characters.
### Your First Institution
```storybook
institution BakersGuild {
type: trade_guild
members: 50
founded: "1892"
reputation: 0.85
}
```
This looks just like a location so far. The difference comes when you add behaviors.
### Institutions with Behaviors
Institutions can act. The `uses behaviors` clause links behavior trees to the institution:
```storybook
institution BakersGuild {
type: trade_guild
members: 50
reputation: 0.85
uses behaviors: [
{ tree: ManageApprentices },
{ tree: NegotiateSuppliers },
{ tree: HostEvents }
]
}
```
Each entry in the list is a behavior link object with a `tree` field. This tells the simulation engine that the Bakers Guild can manage apprentices, negotiate with suppliers, and host events.
### Behavior Priorities
Not all behaviors are equally important. Use the `priority` field:
```storybook
institution BakersGuild {
type: trade_guild
uses behaviors: [
{ tree: ManageApprentices, priority: normal },
{ tree: NegotiateSuppliers, priority: high },
{ tree: HostEvents, priority: low }
]
}
```
Priority levels are `low`, `normal`, `high`, and `critical`. Higher-priority behaviors take precedence when the institution must choose between actions.
### Conditional Behaviors
Some behaviors only activate under certain conditions:
```storybook
institution BakersGuild {
type: trade_guild
reputation: 0.85
uses behaviors: [
{ tree: ManageApprentices },
{ tree: NegotiateSuppliers, priority: high },
{ tree: EmergencyMeeting, when: reputation < 0.3, priority: critical }
]
}
```
The `when` clause uses an [expression](../reference/17-expressions.md). Here, the emergency meeting behavior only activates when reputation drops below 0.3.
### Institutions with Schedules
Institutions can also follow schedules:
```storybook
institution BakersGuild {
type: trade_guild
uses schedule: GuildOperatingHours
}
```
For multiple schedules:
```storybook
institution BakersGuild {
type: trade_guild
uses schedules: [WeekdaySchedule, WeekendSchedule]
}
```
### Prose Blocks
Just like locations, institutions support prose blocks:
```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.
---
---charter
Article I: All members shall maintain the highest standards.
Article II: Apprentices must complete a three-year program.
---
}
```
---
## Connecting Characters to Institutions
Institutions do not have a built-in membership list. You model membership through character fields or relationships.
### Through Character Fields
The simplest approach -- add fields to your characters:
```storybook
character Martha {
age: 45
occupation: baker
guild: BakersGuild
guild_role: guild_master
guild_member_since: "2005"
}
character Jane {
age: 19
occupation: apprentice_baker
guild: BakersGuild
guild_role: apprentice
guild_member_since: "2024"
}
```
### Through Relationships
For richer modeling, use relationships:
```storybook
relationship GuildMembership {
Martha as guild_master { years_active: 20 }
BakersGuild as organization { }
bond: 0.95
}
relationship Apprenticeship {
Jane as apprentice { skills_learned: 12 }
Martha as mentor { patience_remaining: 0.7 }
BakersGuild as guild { }
years_completed: 1
}
```
This approach captures richer information: roles, duration, and multi-party connections.
---
## Locations vs. Institutions
When should you use each?
| Question | Use... |
|----------|--------|
| Where does something happen? | Location |
| Who or what organizes things? | Institution |
| Does it need behaviors? | Institution |
| Does it need a schedule? | Institution |
| Is it purely a place? | Location |
| Is it a group or organization? | Institution |
Sometimes the same concept needs both:
```storybook
// The physical building
location BakersGuildHall {
type: guild_hall
address: "7 Guild Row"
capacity: 100
}
// The organization that meets there
institution BakersGuild {
type: trade_guild
members: 50
location: BakersGuildHall
uses behaviors: [
{ tree: ManageApprentices },
{ tree: NegotiateSuppliers }
]
uses schedule: GuildOperatingHours
}
```
The guild hall is a *place*. The guild is an *organization*. Keeping them separate lets you say "the guild meets at the guild hall" without conflating the building with the institution.
---
## Putting It All Together
Here is a complete example showing how locations, institutions, and characters work together in the Baker family world:
```storybook
// Enums for type safety
enum PlaceType {
bakery, residence, guild_hall, public_square
}
enum GuildRole {
guild_master, journeyman, apprentice
}
// Locations: where things happen
location BakersBakery {
type: bakery
address: "14 Main Street"
capacity: 30
owner: Martha
---description
Martha's artisan bakery on Main Street.
---
}
location BakerHome {
type: residence
address: "22 Elm Lane"
bedrooms: 4
residents: ["Martha", "David", "Jane", "Tom"]
}
location BakersGuildHall {
type: guild_hall
address: "7 Guild Row"
capacity: 100
---description
The historic Bakers Guild headquarters, established 1892.
---
}
// Institution: the organization
institution BakersGuild {
type: trade_guild
members: 50
founded: "1892"
reputation: 0.85
location: BakersGuildHall
leader: Martha
uses behaviors: [
{ tree: ManageApprentices, priority: normal },
{ tree: NegotiateSuppliers, priority: high },
{ tree: HostAnnualBakeOff, when: month is october }
]
uses schedule: GuildOperatingHours
---description
The Bakers Guild oversees apprenticeships, quality standards,
and the annual Great Bake-Off competition.
---
}
// Institution: the business
institution BakersBakeryBusiness {
type: business
owner: Martha
employees: 4
location: BakersBakery
uses behaviors: [
{ tree: DailyBakingOps, priority: high },
{ tree: InventoryManagement }
]
uses schedule: BakeryOperatingHours
}
// Characters connected to all of the above
character Martha {
age: 45
occupation: baker
workplace: BakersBakery
home: BakerHome
guild: BakersGuild
guild_role: guild_master
}
character Jane {
age: 19
occupation: apprentice_baker
workplace: BakersBakery
home: BakerHome
guild: BakersGuild
guild_role: apprentice
}
// Relationships tying it all together
relationship GuildLeadership {
Martha as guild_master { }
BakersGuild as guild { }
years_in_role: 8
}
relationship BakeryApprenticeship {
Jane as apprentice { }
Martha as mentor { }
BakersGuild as certifying_body { }
year: 1
total_years: 3
}
```
---
## Key Takeaways
1. **Locations** are simple: name, fields, prose blocks. They model *places*.
2. **Institutions** are richer: they add `uses behaviors` and `uses schedule` on top of fields and prose. They model *organizations*.
3. **Membership** is modeled through character fields or relationships, not built into institution syntax.
4. **Separate place from organization**: A guild hall (location) and the guild (institution) are different things.
5. **Use enums** for type-safe categorization of locations and institutions.
---
## Next Steps
- Learn about [expressions](../reference/17-expressions.md) used in conditional behavior links
- Explore [behavior trees](./03-first-behavior-tree.md) to create the behaviors your institutions use
- See [schedules](./07-schedules.md) to define operating hours for institutions
- Read the full [Locations Reference](../reference/16a-locations.md) and [Institutions Reference](../reference/16b-institutions.md)