# Expression Language - Storybook Language Guide
Comprehensive documentation for the Storybook narrative simulation language

# Expression Language

The Storybook expression language enables conditions, queries, and logic throughout the system. Expressions appear in life arc transitions, behavior tree guards, decorator conditions, and relationship queries. This chapter provides a complete reference for expression syntax and semantics.

## What are Expressions?

Expressions are logical statements that evaluate to `true` or `false`. They combine:

- Literals: Numbers, strings, booleans
- Identifiers: References to fields and entities
- Comparisons: `==`, `!=`, `<`, `<=`, `>`, `>=`
- Logical operators: `and`, `or`, `not`
- Field access: `self.field`, `other.field`
- Quantifiers: `forall`, `exists` (for collections)

## Syntax

    <expression> ::= <literal>
                   | <identifier>
                   | <field-access>
                   | <comparison>
                   | <logical>
                   | <unary>
                   | <quantifier>
                   | "(" <expression> ")"

    <literal> ::= <int> | <float> | <string> | <bool>

    <identifier> ::= <simple-name>
                   | <qualified-path>

    <field-access> ::= <expression> "." <identifier>
                     | "self" "." <identifier>
                     | "other" "." <identifier>

    <comparison> ::= <expression> <comp-op> <expression>

    <comp-op> ::= "==" | "!=" | "<" | "<=" | ">" | ">="

    <logical> ::= <expression> "and" <expression>
                | <expression> "or" <expression>

    <unary> ::= "not" <expression>
              | "-" <expression>

    <quantifier> ::= ("forall" | "exists") <identifier> "in" <expression> ":" <expression>

## Literals

### Integer Literals

    42
    -7
    0
    1000

### Float Literals

    3.14
    -0.5
    0.0
    100.25

### String Literals

    "Martha"
    "Sourdough takes patience."
    "active"

Strings are enclosed in double quotes. Escape sequences: `\n`, `\t`, `\\`, `\"`.

### Boolean Literals

    true
    false

## Identifiers

Identifiers reference fields or entities.

### Simple Identifiers

    health
    enemy_count
    is_ready

### Qualified Paths

    Martha.skill_level
    Character.emotional_state

## Comparison Operators

### Equality: `==`

Tests if two values are equal.

    name == "Martha"
    count == 5
    status == active

Type compatibility:

- Both operands must be the same type
- Works with: int, float, string, bool, enum values

### Inequality: `!=`

Tests if two values are not equal.

    name != "Gregory"
    health != 0
    ready != true

### Less Than: `<`

Tests if left operand is less than right.

    health < 20
    age < 18
    distance < 10.0

Valid types: int, float

### Less Than or Equal: `<=`

    health <= 50
    count <= max_count

### Greater Than: `>`

    strength > 10
    bond > 0.5

### Greater Than or Equal: `>=`

    age >= 21
    score >= 100

## Logical Operators

### AND: `and`

Both operands must be true.

    health < 50 and has_potion
    is_ready and not is_busy
    age >= 18 and age < 65

Evaluation: Short-circuit (if left is false, right is not evaluated)

### OR: `or`

At least one operand must be true.

    is_day or is_lit
    health < 20 or surrounded
    enemy_count == 0 or all_enemies_dead

Evaluation: Short-circuit (if left is true, right is not evaluated)

### Operator Precedence

From highest to lowest:

1. Parentheses: `(...)`
2. Unary: `not`, `-`
3. Comparisons: `==`, `!=`, `<`, `<=`, `>`, `>=`
4. AND: `and`
5. OR: `or`

Examples:

    not is_ready and is_awake
    // Equivalent to: (not is_ready) and is_awake

    health < 50 or is_poisoned and has_antidote
    // Equivalent to: (health < 50) or (is_poisoned and has_antidote)

    // Use parentheses for clarity:
    (health < 50 or is_poisoned) and has_antidote

## Unary Operators

### NOT: `not`

Inverts a boolean value.

    not is_ready
    not (health < 20)
    not enemy_nearby and safe

### Negation: `-`

Negates a numeric value.

    -health
    -10
    -(max_value - current_value)

## Field Access

### Direct Field Access

    health
    bond
    emotional_state

References a field on the current entity.

### Dot Access

    Martha.skill_level
    Character.emotional_state
    enemy.health

Access fields on other entities.

### Self Access

In relationships and certain contexts, `self` refers to the current participant:

    self.bond
    self.responsibility
    self.trust

Use case: Relationship transitions, symmetric queries

### Other Access

In relationships, `other` refers to other participants:

    other.bond
    other.aware_of_mentor
    other.respect

Use case: Relationship queries with perspective

### Example in Life Arcs

    life_arc RelationshipState {
        state new {
            on self.bond > 0.7 and other.bond > 0.7 -> stable
        }

        state stable {
            on self.bond < 0.3 -> troubled
            on other.bond < 0.3 -> troubled
        }

        state troubled {
            on self.bond < 0.1 or other.bond < 0.1 -> broken
        }

        state broken {}
    }

## Quantifiers

Quantifiers test conditions over collections.

### ForAll: `forall`

Tests if a condition holds for all elements in a collection.

    forall e in enemies: e.defeated
    forall item in inventory: item.weight < 10

Syntax:

    forall <variable> in <collection>: <predicate>

Semantics:

- Returns `true` if predicate is true for every element
- Returns `true` for empty collections (vacuously true)

Examples:

    // All enemies defeated?
    forall enemy in enemies: enemy.health <= 0

    // All party members ready?
    forall member in party: member.is_ready

    // All doors locked?
    forall door in doors: door.is_locked

### Exists: `exists`

Tests if a condition holds for at least one element.

    exists e in enemies: e.is_hostile
    exists item in inventory: item.is_healing_potion

Syntax:

    exists <variable> in <collection>: <predicate>

Semantics:

- Returns `true` if predicate is true for any element
- Returns `false` for empty collections

Examples:

    // Any enemy nearby?
    exists enemy in enemies: enemy.distance < 10

    // Any door unlocked?
    exists door in doors: not door.is_locked

    // Any ally wounded?
    exists ally in allies: ally.health < ally.max_health * 0.5

### Nested Quantifiers

Quantifiers can nest:

    forall team in teams: exists player in team: player.is_leader
    // Every team has at least one leader

    exists room in dungeon: forall enemy in room.enemies: enemy.defeated
    // At least one room has all enemies defeated

## Usage in Context

### Life Arc Transitions

    life_arc CombatState {
        state idle {
            on enemy_count > 0 -> combat
        }

        state combat {
            on health < 20 -> fleeing
            on enemy_count == 0 -> victorious
        }

        state fleeing {
            on distance_from_enemies > 100 -> safe
        }

        state victorious {
            on celebration_complete -> idle
        }

        state safe {
            on health >= 50 -> idle
        }
    }

### Behavior Tree Conditions

    behavior GuardedAction {
        if(health > 50 and has_weapon) {
            AggressiveAttack
        }
    }

    behavior ConditionalChoice {
        choose tactics {
            then melee {
                if(distance < 5 and weapon_type == "sword")
                MeleeAttack
            }

            then ranged {
                if(distance >= 5 and has_arrows)
                RangedAttack
            }
        }
    }

### Behavior Tree Conditions

    behavior SmartAI {
        choose strategy {
            then aggressive {
                if(health > 70 and enemy_count < 3)
                Attack
            }

            then defensive {
                if(health < 30 or enemy_count >= 5)
                Defend
            }

            then balanced {
                if(health >= 30 and health <= 70)
                TacticalManeuver
            }
        }
    }

## Type System

### Type Compatibility

Comparisons require compatible types:

Operator | Left Type | Right Type | Valid?
--- | --- | --- | ---
`==`, `!=` | int | int | ✓
`==`, `!=` | float | float | ✓
`==`, `!=` | string | string | ✓
`==`, `!=` | bool | bool | ✓
`==`, `!=` | enum | same enum | ✓
`==`, `!=` | int | float | ✗
`<`, `<=`, `>`, `>=` | int | int | ✓
`<`, `<=`, `>`, `>=` | float | float | ✓
`<`, `<=`, `>`, `>=` | string | string | ✗

### Implicit Coercion

None. Storybook has no implicit type coercion. All comparisons must be between compatible types.

Error:

    count == "5"  // Error: int vs string
    health < true  // Error: int vs bool

Correct:

    count == 5
    health < 50

## Special Keyword: `is`

The `is` keyword provides syntactic sugar for equality with enum values:

    // Instead of:
    status == active

    // You can write:
    status is active

More examples:

    name is "Martha"
    skill_level is master
    emotional_state is focused

This is purely syntactic—`is` and `==` are equivalent.

## Complete Examples

### Simple Conditions

    health < 20
    enemy_nearby
    not is_ready
    count > 5

### Complex Conditions

    (health < 20 and not has_potion) or surrounded
    forall e in enemies: e.defeated
    exists item in inventory: item.is_healing_potion and item.quantity > 0

### Life Arc with Complex Conditions

    life_arc CharacterMood {
        state content {
            on health < 30 or hunger > 80 -> distressed
            on social_interaction > 0.8 -> happy
        }

        state distressed {
            on health >= 50 and hunger < 30 -> content
            on (health < 10 or hunger > 95) and help_available -> desperate
        }

        state happy {
            on social_interaction < 0.3 -> content
            on received_bad_news -> distressed
        }

        state desperate {
            on help_received -> distressed
        }
    }

### Behavior with Quantifiers

    behavior SquadLeader {
        choose leadership {
            then regroup {
                if(squad_has_wounded)
                OrderRetreat
            }

            then advance {
                if(squad_all_ready)
                OrderAdvance
            }

            then hold_position {
                if(not squad_all_ready)
                OrderHold
            }
        }
    }

### Relationship Query

    life_arc FriendshipQuality {
        state new_friends {
            on self.bond > 0.7 and other.bond > 0.7 -> strong_bond
            on self.trust < 0.3 or other.trust < 0.3 -> shaky
        }

        state strong_bond {
            on self.bond < 0.5 -> weakening
        }

        state weakening {
            on self.bond < 0.2 or other.bond < 0.2 -> ended
            on self.bond > 0.7 and other.bond > 0.7 -> strong_bond
        }

        state shaky {
            on self.trust > 0.6 and other.trust > 0.6 -> new_friends
            on self.trust < 0.1 or other.trust < 0.1 -> ended
        }

        state ended {}
    }

## Validation Rules

1. Type consistency: Both sides of comparison must be compatible types
2. Boolean context: Logical operators (`and`, `or`, `not`) require boolean operands
3. Field existence: Referenced fields must exist on the entity
4. Collection validity: Quantifiers require collection-typed expressions
5. Variable scope: Quantifier variables only valid within their predicate
6. No division by zero: Arithmetic operations must not divide by zero
7. Enum validity: Enum comparisons must reference defined enum values

## Best Practices

### 1. Use Parentheses for Clarity

Avoid:

    health < 50 or is_poisoned and has_antidote

Prefer:

    (health < 50 or is_poisoned) and has_antidote

### 2. Break Complex Conditions

Avoid:

    on (health < 20 and not has_potion) or (surrounded and not has_escape) or (enemy_count > 10 and weapon_broken) -> desperate

Prefer:

    state combat {
        on health < 20 and not has_potion -> desperate
        on surrounded and not has_escape -> desperate
        on enemy_count > 10 and weapon_broken -> desperate
    }

### 3. Name Complex Conditions

For repeated complex conditions, consider using intermediate fields:

Instead of:

    on health < (max_health * 0.2) and enemy_count > 5 -> flee

Consider:

    // In character definition:
    critically_wounded: health < (max_health * 0.2)
    outnumbered: enemy_count > 5

    // In life arc:
    on critically_wounded and outnumbered -> flee

### 4. Use `is` for Enums

Prefer:

    status is active
    emotional_state is focused

Over:

    status == active
    emotional_state == focused

### 5. Quantifiers for Collections

Avoid:

    // Manual checks for each element
    if enemy1.defeated and enemy2.defeated and enemy3.defeated

Prefer:

    if forall enemy in enemies: enemy.defeated

## Cross-References

- Life Arcs - Transition conditions
- Behavior Trees - Guard and condition nodes
- Decorators - Guard decorator
- Relationships - Self/other field access
- Value Types - Literal value types

## Related Concepts

- Type safety: Strong typing prevents type errors at compile time
- Short-circuit evaluation: AND/OR operators optimize evaluation
- Quantifiers: Enable expressive collection queries
- Field access: Context-sensitive (`self`, `other`) for relationships
- Boolean algebra: Standard logical operators with expected semantics