272 lines
7.2 KiB
Markdown
272 lines
7.2 KiB
Markdown
|
|
# 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).
|