314 lines
7.7 KiB
Markdown
314 lines
7.7 KiB
Markdown
# 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 |
|
|
|------|---------|-------------|
|
|
| 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:
|
|
|
|
```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).
|