Taos Engine · Agent Tutorials

Agent Tutorials · Step 4

Neighbors & Flocking

▶ Live demo: run this tutorial — built from src/04_neighbors_flocking.ts. Distilled from samples/agent_flock.ts.

Agent-to-agent interaction needs neighbor queries — "the other turtles within radius r", AgentScript's inRadius / inCone. Taos Engine answers them on the GPU with a spatial hash, exposed in the step as in-radius reductions. With those you can hand-write Reynolds flocking as a turtle program — no built-in "boids" black box.

Turning on the spatial hash#

Add a neighbors block. It builds a uniform grid over the world each frame and buckets agents into cells, so a neighbor query only scans a 3×3-cell window:

TypeScript
neighbors: {
  resolution: Math.max(4, Math.floor(WORLD / perception)),  // cell ≈ perception
  worldMin: [-HALF, -HALF], worldSize: [WORLD, WORLD],
  capacity: 96,                                              // max agents counted per cell
},

Size the cell to your query radius (perception) so the 3×3 window covers it.

The neighbor verbs#

All operate over the other agents within a radius, and are only valid in the step (they need the hash):

VerbReturnsAgentScript
agent.neighborCount(r)count (f32)inRadius … length
agent.neighborCenter(r)center of mass (vec3) — cohesionmean of inRadius
agent.neighborVelocity(r)mean velocity (vec3) — alignment—
agent.neighborSeparation(r)summed away-vector (vec3) — separation—
agent.nearest(r)offset to the closest (vec3)minOneOf
agent.neighborsAhead(r, halfAngle)count in the forward coneinCone

Flocking from two of them#

Reynolds flocking is cohesion + separation (alignment optional). Build a steering target and face it:

TypeScript
const target = expr.add(
  agent.neighborCenter(perception),                          // cohesion: head to the local center
  expr.mul(agent.neighborSeparation(sepRadius), sepWeight),  // separation: push off close neighbors
);
step: [
  agent.face(target),
  agent.turn(agent.randomTurn(wander)),
  agent.moveForward(speed),
],

40,000 agents flock at interactive rates. That's the AgentScript-parity payoff: the same primitives, authored as a per-agent program, at GPU scale.

Built-in behaviors. For the common cases there are packaged behaviors (boids, predator_prey, schelling, link_springs, lotka_volterra) you add to the model instead of hand-writing the step — tutorials 6 and 7 use them. The neighbor verbs are for when you want to write your own.

Constraint: the hash cell has a fixed capacity; in a very dense cell, agents beyond it are not counted. Raise capacity or coarsen resolution if you see flocking break down in dense clumps.

Next#