Dynamics
Defines per-tick state cascade rules - how internal states change over time independent of agent actions. Dynamics is optional; omitting it means no per-tick state changes.
Dynamics are the physics of your simulation - the rules that govern what happens every tick regardless of what the agent does. This is where you model things like fatigue slowly increasing, stress accumulating, or physiological decay over time. Without dynamics, state only changes when agent actions or entity interactions modify it. With dynamics, the world exerts constant pressure that the agent must respond to.
Dynamics runs at step 6 of the tick loop, after all other blocks have finished. This means all state mutations from the action block, entity interactions, and agent machines are visible to the dynamics cascade.
The Network Security demo does not use a dynamics block - the IDS agent has no physiological state that changes over time independent of actions. Not every domain requires dynamics.
dynamics OperatorPhysiology { hidden dt: 0..1 = 0.05
per_tick { fatigue += 0.001 * dt stress -= 0.005 * dt boredom += 0.003 * dt cognitive_load -= 0.01 * dt }
rules { if cognitive_load > 0.2: fatigue += 0.002 * dt if fatigue > 0.8: stress += 0.001 * dt }
clamp 0..1}dynamics ForagerMetabolism { hidden dt: 0..1 = 0.05
per_tick { hunger += 0.005 * dt thirst += 0.004 * dt energy -= 0.003 * dt nausea -= 0.01 * dt }
rules { if hunger > 0.8: energy -= 0.005 * dt if nausea > 0.3: health -= 0.01 * dt if hunger > 0.9: health -= 0.01 * dt if thirst > 0.9: health -= 0.01 * dt }
death { if health <= 0 if energy <= 0 }
clamp 0..1}Hidden State
Section titled “Hidden State”Hidden states are invisible to the brain - the agent cannot sense them. They participate in rules but never appear as sensor inputs.
hidden name: min..max = initialBoth demo dynamics blocks use a hidden dt variable to scale state changes:
-- Human Factorshidden dt: 0..1 = 0.05
-- Survivalhidden dt: 0..1 = 0.05Per-Tick Rules
Section titled “Per-Tick Rules”The per_tick block contains rules that run unconditionally every tick.
Models fatigue growth, stress recovery, boredom growth, and cognitive load decay:
per_tick { fatigue += 0.001 * dt stress -= 0.005 * dt boredom += 0.003 * dt cognitive_load -= 0.01 * dt}Models hunger and thirst growth, energy drain, and nausea recovery:
per_tick { hunger += 0.005 * dt thirst += 0.004 * dt energy -= 0.003 * dt nausea -= 0.01 * dt}Conditional Rules
Section titled “Conditional Rules”The rules block contains conditional rules evaluated in order. Earlier rules’ effects are visible to later rules within the same tick.
Cascading effects: high cognitive load accelerates fatigue, and high fatigue increases stress.
rules { if cognitive_load > 0.2: fatigue += 0.002 * dt if fatigue > 0.8: stress += 0.001 * dt}Multiple cascading effects: hunger drains energy, nausea damages health, and extreme hunger or thirst damages health.
rules { if hunger > 0.8: energy -= 0.005 * dt if nausea > 0.3: health -= 0.01 * dt if hunger > 0.9: health -= 0.01 * dt if thirst > 0.9: health -= 0.01 * dt}Death Conditions
Section titled “Death Conditions”The death block defines conditions that kill the agent. Death conditions are checked after all rules apply.
-- Survival: agent dies when health or energy reaches zerodeath { if health <= 0 if energy <= 0}The Human Factors demo does not have a death block in dynamics - the agent dies when it reaches the end of the route (agent.alive = false in the action block).
Setting agent.alive = false in any block also kills the agent, independent of the dynamics death block.
The clamp directive constrains all dynamics-managed states to a range after each tick.
-- Both demos use the same clamp rangeclamp 0..1This ensures no state drifts below 0 or above 1 due to accumulated rule effects.
Operators
Section titled “Operators”| Operator | Meaning | Example |
|---|---|---|
+= | Add to current value | hunger += 0.005 * dt |
-= | Subtract from current value | energy -= 0.003 * dt |
*= | Multiply current value | nausea *= 0.95 |
= | Set to value | health = 0.0 |
Conditions
Section titled “Conditions”| Operator | Meaning |
|---|---|
> | Greater than |
< | Less than |
>= | Greater than or equal |
<= | Less than or equal |
Expressions
Section titled “Expressions”Right-hand side of an assignment can be:
| Form | Example |
|---|---|
| Literal value | hunger += 0.003 |
| Unary minus | energy += -0.1 |
| State reference | energy = health |
number * state_ref | fatigue += 0.002 * dt |
number * (expr) | stress += 0.001 * (1.0 + fatigue * 2.0) |
state * value | nausea *= 0.95 |
state + value | recovery = health + 0.1 |
state - value | penalty = energy - 0.2 |
| Parenthesized sub-expression | energy -= (hunger + thirst) |
Operator precedence: * binds tighter than + and -. Use parentheses to override precedence when needed.
Rules Summary
Section titled “Rules Summary”- Rule ordering matters - earlier rules’ effects are visible to later rules within the same tick
per_tickrules run unconditionally every tickrulesblock contains conditional rules evaluated in orderdeathconditions are checked after all rules apply; if any is true the agent diesclampapplies to all states after each tick
Dynamics Block Keyword Reference
Section titled “Dynamics Block Keyword Reference”The dynamics block uses a simpler syntax than perception/action blocks. The let, when, match, and ternary features are NOT available in dynamics. Dynamics uses if for conditionals, not when.
Top-Level Structure
Section titled “Top-Level Structure”dynamics <Name> { hidden <name>: <range> = <initial> per_tick { <rules> } rules { <conditional_rules> } death { <death_conditions> } clamp <range>}| Sub-block | Required | Description |
|---|---|---|
hidden | No | Hidden state variables (invisible to the brain) |
per_tick | No | Unconditional per-tick rules |
rules | No | Conditional rules (if guards) |
death | No | Death conditions checked after all rules |
clamp | No | Range constraint applied to all dynamics-managed states |
Hidden State Syntax
Section titled “Hidden State Syntax”hidden dt: 0..1 = 0.05Hidden states are invisible to the brain and do not appear as sensor inputs. They participate in dynamics rules only.
Assignment Operators (Dynamics)
Section titled “Assignment Operators (Dynamics)”| Operator | Meaning | Example |
|---|---|---|
+= | Add to current value | hunger += 0.005 * dt |
-= | Subtract from current value | energy -= 0.003 * dt |
*= | Multiply current value | nausea *= 0.95 |
= | Set to value | health = 0.0 |
Condition Syntax (Dynamics)
Section titled “Condition Syntax (Dynamics)”Dynamics uses if, not when:
rules { if hunger > 0.8: energy -= 0.005 * dt if nausea > 0.3: health -= 0.01 * dt}| Operator | Meaning |
|---|---|
> | Greater than |
< | Less than |
>= | Greater than or equal |
<= | Less than or equal |
Expression Forms (Dynamics)
Section titled “Expression Forms (Dynamics)”The dynamics expression syntax is simpler than the full expression language.
| Form | Example |
|---|---|
| Literal value | hunger += 0.003 |
| Unary minus | energy += -0.1 |
| State reference | energy = health |
number * state_ref | fatigue += 0.002 * dt |
state * value | nausea *= 0.95 |
state + value | recovery = health + 0.1 |
state - value | penalty = energy - 0.2 |
| Parenthesized sub-expression | energy -= (hunger + thirst) |
Death Conditions
Section titled “Death Conditions”death { if health <= 0 if energy <= 0}Each condition is checked independently. If any condition is true, agent.alive is set to false.
Clamp Directive
Section titled “Clamp Directive”clamp 0..1Applied after all rules and death checks. Constrains every dynamics-managed state to the specified range.