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
This commit is contained in:
302
docs/tutorial/04-making-characters-act.md
Normal file
302
docs/tutorial/04-making-characters-act.md
Normal file
@@ -0,0 +1,302 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user