Files
storybook/docs/reference/10-characters.md
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

12 KiB

Characters

Characters are the primary entities in Storybook—the people, creatures, and beings that inhabit your world. Each character has a set of attributes that define who they are, what they can do, and how they relate to the world around them.

Syntax

<character-decl> ::= "character" <identifier> <species-clause>? <template-clause>? <body>

<species-clause> ::= ":" <qualified-path>

<template-clause> ::= "from" <qualified-path> ("," <qualified-path>)*

<body> ::= "{" <body-item>* "}"

<body-item> ::= <field>
              | <uses-behaviors>
              | <uses-schedule>

<uses-behaviors> ::= "uses" "behaviors" ":" <behavior-link-list>

<uses-schedule> ::= "uses" ("schedule" | "schedules") ":" (<qualified-path> | <schedule-list>)

<behavior-link-list> ::= "[" <behavior-link> ("," <behavior-link>)* "]"

<behavior-link> ::= "{" <behavior-link-field>* "}"

<behavior-link-field> ::= "tree" ":" <qualified-path>
                        | "when" ":" <expression>
                        | "priority" ":" ("low" | "normal" | "high" | "critical")

<schedule-list> ::= "[" <qualified-path> ("," <qualified-path>)* "]"

<field> ::= <identifier> ":" <value>

<value> ::= <literal>
          | <qualified-path>
          | <list>
          | <object>
          | <prose-block>
          | <override>

<prose-block> ::= "---" <identifier> <content> "---"

Components

Name

The character's identifier. Must be unique within its scope and follow standard identifier rules (alphanumeric + underscore, cannot start with digit).

Species (Optional)

The species clause (: SpeciesName) defines what the character fundamentally is. This is distinct from templates, which define what attributes they have.

  • Purpose: Ontological typing—what kind of being this is
  • Validation: Must reference a defined species declaration
  • Single inheritance: A character can only have one species
  • Default behavior: Species fields are inherited automatically

Example:

character Martha: Human {
    age: 34
}

Template Inheritance (Optional)

The template clause (from Template1, Template2) specifies templates from which the character inherits fields. Templates provide reusable attribute sets.

  • Purpose: Compositional inheritance—mix-and-match capabilities and traits
  • Multiple inheritance: Characters can inherit from multiple templates
  • Merge semantics: Fields from later templates override earlier ones
  • Override allowed: Character fields override all inherited fields

Example:

character Martha: Human from Baker, BusinessOwner {
    specialty: "sourdough"
}

Fields

Fields define the character's attributes using the standard field syntax. All value types are supported.

Common field categories:

  • Physical traits: height, weight, age, eye_color
  • Personality: confidence, patience, dedication
  • Professional: skill_level, specialty, recipes_mastered
  • State tracking: energy, mood, orders_today
  • Capabilities: can_teach, can_work_independently

Prose Blocks

Characters can contain multiple prose blocks for narrative content. Common tags:

  • ---backstory: Character history and origin
  • ---appearance: Physical description
  • ---personality: Behavioral traits and quirks
  • ---motivation: Goals and desires
  • ---secrets: Hidden information

Prose blocks are narrative-only and do not affect simulation logic.

Behavior Integration

Characters can link to behavior trees using the uses behaviors clause.

character Guard {
    uses behaviors: [
        {
            tree: combat::patrol_route
            priority: normal
        },
        {
            tree: combat::engage_intruder
            when: threat_detected
            priority: high
        }
    ]
}

Each behavior link includes:

  • tree: Qualified path to the behavior tree (required)
  • when: Condition expression for activation (optional)
  • priority: Execution priority (optional, default: normal)

See Behavior Trees for details on behavior tree syntax and semantics.

Schedule Integration

Characters can follow schedules using the uses schedule or uses schedules clause.

character Baker {
    uses schedule: BakerySchedule
}

character Innkeeper {
    uses schedules: [WeekdaySchedule, WeekendSchedule]
}
  • Single schedule: uses schedule: ScheduleName
  • Multiple schedules: uses schedules: [Schedule1, Schedule2]

The runtime selects the appropriate schedule based on temporal constraints. See Schedules for composition and selection semantics.

Species vs. Templates

The distinction between species (:) and templates (from) reflects ontological vs. compositional typing:

Feature Species (:) Templates (from)
Semantics What the character is What the character has
Cardinality Exactly one Zero or more
Example : Human, : Dragon from Warrior, Mage
Purpose Fundamental nature Reusable trait sets
Override Can override species fields Can override template fields

Example showing both:

species Dragon {
    max_lifespan: 1000
    can_fly: true
}

template Hoarder {
    treasure_value: 0..1000000
    greed_level: 0.0..1.0
}

template Ancient {
    age: 500..1000
    wisdom: 0.8..1.0
}

character Smaug: Dragon from Hoarder, Ancient {
    age: 850
    treasure_value: 500000
    greed_level: 0.95
}

Field Resolution Order

When a character inherits from species and templates, fields are resolved in this order (later overrides earlier):

  1. Species fields (base ontology)
  2. Template fields (left to right in from clause)
  3. Character fields (highest priority)

Example:

species Human {
    lifespan: 80
    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 fields:
// lifespan: 80     (from Human)
// speed: 2.0       (Berserker overrides Warrior overrides Human)
// strength: 20     (character overrides Berserker)

Validation Rules

The Storybook compiler enforces these validation rules:

  1. Unique names: Character names must be unique within their module
  2. Species exists: If specified, the species must reference a defined species declaration
  3. Templates exist: All templates in the from clause must reference defined template declarations
  4. No circular inheritance: Templates cannot form circular dependency chains
  5. Field type consistency: Field values must match expected types from species/templates
  6. Reserved fields: Cannot use reserved keywords as field names
  7. Behavior trees exist: All behavior tree references must resolve to defined behavior declarations
  8. Schedules exist: All schedule references must resolve to defined schedule declarations
  9. Prose tag uniqueness: Each prose tag can appear at most once per character

Examples

Basic Character

character SimpleMerchant {
    name: "Gregor"
    occupation: "Fish Merchant"
    wealth: 50

    ---personality
    A straightforward fish seller at the market. Honest, hardworking,
    and always smells faintly of mackerel.
    ---
}

Character with Species

character Martha: Human {
    age: 34
    skill_level: 0.95
    specialty: "sourdough"

    ---backstory
    Martha learned to bake from her grandmother, starting at age
    twelve. She now runs the most popular bakery in town.
    ---
}

Character with Template Inheritance

character Jane: Human from Baker, PastrySpecialist {
    age: 36
    specialty: "pastries"
    recipes_mastered: 120

    years_experience: 18
    can_teach: true

    ---appearance
    A focused woman with flour-dusted apron and steady hands.
    Known for her intricate pastry decorations and precise
    temperature control.
    ---
}

Character with All Features

character CityGuard: Human from CombatTraining, LawEnforcement {
    age: 30
    rank: "Sergeant"

    // Physical traits
    height: 175
    strength: 12

    // Equipment
    has_weapon: true
    armor_level: 2

    // Behavior integration
    uses behaviors: [
        {
            tree: guards::patrol_route
            priority: normal
        },
        {
            tree: guards::engage_hostile
            when: threat_detected
            priority: high
        },
        {
            tree: guards::sound_alarm
            when: emergency
            priority: critical
        }
    ]

    // Schedule integration
    uses schedules: [guards::day_shift, guards::night_shift]

    ---backstory
    A veteran of the city watch, now responsible for training new recruits
    while maintaining order in the merchant district.
    ---

    ---personality
    Gruff exterior with a hidden soft spot for street children. Follows
    the rules but knows when to look the other way.
    ---
}

Character with Overrides

template WeaponUser {
    damage: 5..15
    accuracy: 0.7
}

character MasterSwordsman: Human from WeaponUser {
    // Override template range with specific value
    damage: 15
    accuracy: 0.95

    // Add character-specific fields
    signature_move: "Whirlwind Strike"
}

Use Cases

Protagonist Definition

Define rich, dynamic protagonists with complex attributes:

character Elena: Human from Scholar, Diplomat {
    age: 28
    intelligence: 18
    charisma: 16

    languages_known: ["Common", "Elvish", "Draconic"]
    books_read: 347

    current_quest: "Broker peace between warring kingdoms"

    ---backstory
    Raised in the Grand Library, Elena discovered ancient texts that
    hinted at a forgotten alliance between humans and dragons. She now
    seeks to revive that alliance to end the current war.
    ---
}

NPC Templates

Create diverse NPCs from templates:

template Villager {
    occupation: "Farmer"
    wealth: 10..50
    disposition: 0.0..1.0  // 0=hostile, 1=friendly
}

character Oswald: Human from Villager {
    occupation: "Blacksmith"
    wealth: 45
    disposition: 0.8
}

character Mildred: Human from Villager {
    occupation: "Baker"
    wealth: 35
    disposition: 0.95
}

Ensemble Casts

Define multiple related characters:

template BakeryStaff {
    punctuality: 0.5..1.0
    teamwork: 0.5..1.0
}

template Apprentice {
    skill_level: 0.0..0.5
    dedication: 0.5..1.0
}

character Elena: Human from BakeryStaff, Apprentice {
    age: 16
    natural_talent: 0.8
    dedication: 0.9

    ---backstory
    Elena comes from a family of farmers who could never afford to
    buy bread from the bakery. When Martha offered her an apprenticeship,
    she jumped at the chance to learn a trade.
    ---
}

Cross-References

  • Instantiation: Characters are concrete instances; they cannot be instantiated further
  • Composition: Prefer template composition over deep species hierarchies
  • Modularity: Characters can reference behaviors and schedules from other modules
  • Narrative-driven: Use prose blocks to embed storytelling directly with data