Files
storybook/docs/tutorial/04-making-characters-act.md

303 lines
7.0 KiB
Markdown
Raw Normal View History

# 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.