7.7 KiB
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:
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 |
|---|---|---|
| Number | 42 |
Whole numbers |
| Decimal | 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:
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:
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:
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:
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:
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:
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:
- Species fields (lowest priority)
- Template fields (left to right in the
fromclause) - Character fields (highest priority -- always wins)
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:
enum SkillLevel {
Novice,
Beginner,
Intermediate,
Advanced,
Expert,
Master
}
enum Specialty {
Sourdough,
Pastries,
Cakes,
Bread,
Confections
}
Use enum values as field values:
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:
// 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:
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, you will learn how characters make decisions.
Reference: For complete character syntax details, see the Characters Reference.