Skip to content

Experiment Design

This guide covers the principles and practical techniques for designing Quale experiments that produce interesting evolved behavior. It assumes familiarity with the Language Reference and Evolution Reference.

Designing an experiment is not just filling in the syntax - it is a craft. The decisions you make about what sensors to give the agent, what consequences to attach to actions, and how to structure the world determine whether evolution discovers something genuinely interesting or collapses onto a trivial strategy. This guide is about making those decisions well.


The most important idea in Quale experiment design:

Do not reward the behavior you want - create conditions where the behavior is necessary for survival.

If you want agents that avoid dangerous items, do not reward “noticed a dangerous item.” Instead, make consuming that item cause health damage or death. The agent must discover avoidance on its own to survive long enough to reproduce.

This principle applies everywhere:

  • Food discrimination: Do not penalize “ate bad food.” Make bad food cause nausea that damages health. The agent learns to discriminate because indiscriminate eating kills it.
  • Hazard avoidance: Do not reward “avoided the hazard.” Make hazard contact cause damage. The agent learns to detect and avoid hazards because ignoring them has consequences.
  • Resource management: Do not reward “conserved energy.” Make energy depletion cause health damage. The agent learns efficiency because waste leads to death.

When you directly reward the target behavior, evolution finds the cheapest way to trigger the reward - which is rarely the behavior you intended. When you create consequences, the target behavior emerges because it is the only viable strategy.


Sensors define what the agent can perceive. They are the only information the brain receives about the world.

sensor energy: internal(0..1)
sensor fatigue: internal(0..1)

Internal sensors expose the agent’s own state. Use them for:

  • Physiological state that should influence behavior (hunger drives food-seeking)
  • Cognitive state the agent should be aware of (fatigue affects response time)
  • Environmental readings the domain provides as scalar values (speed, distance)

Each internal sensor creates one input node in the brain.

sensor food_nearby: directional(range: 20, directions: 4)

Directional sensors provide distance-scaled detection per compass direction. The signal is 1.0 - (distance / range), so nearby items produce strong signals and distant items produce weak ones.

Use directions: 4 (N/S/E/W) for simpler experiments and directions: 8 (adds diagonals) for richer navigation. Be aware that 8-directional sensors create 8 input nodes per sensor - this increases the search space for evolution.

sensor item_color: item_property(color)

Item property sensors report properties of the nearest item (the one producing the strongest directional signal). These enable discrimination - the agent can sense what something is before consuming it.

Property names must match keys in item properties blocks.

sensor peer_health: social(health)

Social sensors expose another agent’s internal state. Only active when agents: 2 in the evolve block. Use these for experiments where agents should respond to each other’s condition.

  1. Give the agent enough information to succeed. If you want food discrimination, the agent needs item_property sensors for distinguishing features. Without them, every item looks the same.

  2. Do not give the agent information it should not have. The agent should discover correlations through evolution, not receive pre-processed labels.

  3. Keep the sensor count manageable. Each sensor adds input nodes. More nodes means a larger search space. Start minimal and add sensors only when the agent cannot solve the task without them.

  4. Name sensors for what they sense, not what you want the agent to do with them. item_smell (what it senses) is better than should_eat (what you want).


Actuators define what the agent can do. They are the brain’s output channels.

actuator move: directional(threshold: 0.5, directions: 4)

Winner-take-all among the direction outputs. The direction with the highest activation above threshold fires. If none exceed threshold, no action occurs.

actuator eat: trigger(threshold: 0.5)
actuator brake: trigger(threshold: 0.3)

Fires when activation exceeds threshold. For continuous control (like throttle or brake force), the domain can use the actual output value, not just the binary trigger.

Lower thresholds (0.3) make it easier for the agent to activate the actuator. Higher thresholds (0.8) make it harder - the agent needs strong conviction.

Use lower thresholds for actions that should be easy to perform (movement, basic actions) and higher thresholds for actions that should require deliberate intent (emergency brake, special abilities).


Items are the things agents interact with in the world. Each item has observable properties and hidden effects.

// Example: two food items with similar but distinguishable properties.
// The agent must learn which is safe and which is harmful.
item SafeFood {
category: food
properties { color: 0.9 smell: 0.6 texture: 0.2 }
on_consume { hunger: -0.2 energy: +0.15 health: +0.05 }
}
item DangerousFood {
category: food
properties { color: 0.85 smell: 0.5 texture: 0.3 }
on_consume { hunger: -0.1 nausea: +0.8 health: -0.4 }
}

Notice that SafeFood and DangerousFood have similar but not identical properties. This creates a discrimination challenge: the agent must learn subtle property differences to distinguish safe from dangerous items.

If properties are too different (color: 1.0 vs 0.0), discrimination is trivial. If properties are too similar, discrimination may be impossible given the sensor resolution. Aim for a middle ground where evolution can find the pattern but it requires real neural computation.

Effect keys in on_consume must match internal() sensor names in the body. This is validated at compile time. Use positive values (+0.3) for increases and negative values (-0.2) for decreases.

Categories group items for spawn rules and domain handling. Category names are arbitrary strings in the .quale file - the domain layer determines which categories it supports. If the domain does not recognize a category, it produces an error at Domain.Configure() time (not during parsing). See Domain Adapters for the categories each domain supports.


world SmallGrid {
size: 10 x 10
walls: border
item_respawn: 30 ticks
spawn food: 6
spawn water: 4
}
  • Minimum 3x3 (need at least 1 interior cell)
  • Smaller grids (5x5 to 10x10) produce dense environments where agents encounter items frequently - good for fast evolution of basic behaviors
  • Larger grids (20x20+) produce sparse environments that require navigation - better for testing pathfinding and exploration

item_respawn controls how quickly consumed items reappear. Short respawn times (10-20 ticks) keep the world resource-rich. Long respawn times (50+ ticks) create scarcity that forces efficiency.

Items of each category are distributed round-robin across all item definitions with that category. For example, spawn food: 6 with 3 food-category items places 2 of each.

Capacity constraint: Total spawns + agents must be less than the interior cell count (width-2) * (height-2). The compiler rejects configurations that exceed capacity.