ants/CLAUDE.md
Jared Miller 64d7bf6437
Update CLAUDE.md for ant behavior overhaul
Documents the budget pool activation model, priority-stack brain,
ant physics (gravity/collision/surface), unified brush spawning,
new config keys (antsStartCount, antBudget, seedWorld), stats
overlay active/budget format, worldInit test, and screenWorld.frag
color variation.
2026-03-11 22:50:10 -04:00

7.3 KiB

ants-simulation

GPU-accelerated ant colony simulation. ants navigate via pheromone trails, all computed in GLSL fragment shaders rendered to offscreen textures. uses WebGL2 features (MRT, GLSL3). side-view ant farm with sand/powder physics and material-based world. ants use a fixed budget pool with probabilistic activation; behavior is driven by a priority-stack brain (fall → deposit → navigate → forage → dig → wander).

stack

  • three.js (0.173) — WebGL2 renderer, render targets, MRT, shader materials
  • lil-gui — runtime parameter tweaking
  • vite — dev server and build
  • biome — lint + format
  • bun — runtime, test runner, package manager
  • typescript

commands

  • just check — lint, typecheck, test (the gate for all work)
  • bun run dev — start dev server
  • bun run build — production build to build/
  • bun test — run tests

architecture

all simulation logic runs on the GPU via ping-pong render targets. no JS-side simulation loop — Renderer.ts orchestrates render passes and manages all WebGLRenderTargets.

render pipeline (per frame)

  1. SandPhysicsScene — Margolus block CA for sand/powder physics
  2. WorldBlurScene — diffuse + decay pheromones (3 channels: toHome, toFood, repellent, blocked by solid cells)
  3. clear antsPresenceRenderTarget (ant-ant spatial queries, stub)
  4. AntsComputeScene — per-ant state via MRT (writes 2 textures simultaneously); gravity pass runs first (ants fall through air), then priority-stack brain for active ants; handles collision displacement out of solid cells
  5. AntsDiscretizeScene — maps continuous ant positions to discrete world grid cells
  6. WorldComputeScene — merges ant deposits into world pheromone grid
  7. ColonyStats — CPU readback of ant texture, computes aggregate stats (foragerRatio, active/budget counts), feeds back as uniforms
  8. DrawScene — user painting with material palette; brush tool also spawns ants (key: A, BRUSH_ANTS = 999 sentinel, uAntSpawn uniform)
  9. ScreenScene — final composited output with side/top camera views (V to toggle); passes ant spawn position to AntsComputeScene

GPU textures

ant state — 2 RGBA Float32 textures per ping-pong target (MRT, count: 2). texture size is Math.ceil(Math.sqrt(antBudget)) — a fixed pool. only antsStartCount ants activate on init; dormant slots sit at pos=(0,0). new ants can be activated via the brush tool (probabilistic activation per frame when spawn is requested):

  • texture 0: [pos.x, pos.y, angle, packed(storage << 1 | isCarrying)]
  • texture 1: [personality, cargoMaterialId, pathIntDx, pathIntDy]

world state — RGBA Float32 (worldSize x worldSize):

  • R: material ID (0-255), maps to MaterialRegistry entry
  • G: scentToHome
  • B: scentToFood
  • A: repellent pheromone

discrete ants — RGBA UnsignedByte (worldSize x worldSize):

  • R: carrying ant scent deposit, G: non-carrying ant scent deposit, B: cell cleared flag, A: 1

ant presence — RGBA Float32 (worldSize x worldSize), cleared each frame. stub for future ant-ant spatial interaction.

material system

src/materials/ defines a data-driven material registry. adding a new material requires only a registry entry — no shader changes needed.

  • MaterialRegistry — 6 built-in materials (ids 0-5): air, sand, dirt, rock, food, home
  • behavior types: BEHAVIOR_POWDER (0), BEHAVIOR_LIQUID (1), BEHAVIOR_GAS (2), BEHAVIOR_SOLID (3)
  • each material has: id, name, behavior, density, hardness, angleOfRepose, color
  • lookup textures (256x1 Float RGBA) uploaded as uniforms to shaders:
    • properties texture: [behavior, density, hardness, angleOfRepose] per row
    • colors texture: [r, g, b, a] per row
  • material IDs defined in src/constants.ts (MAT_AIR through MAT_HOME)

sand physics

Margolus neighborhood cellular automata runs as the first render pass each frame.

  • world is divided into 2x2 blocks; block offset alternates each frame between (0,0) and (1,1)
  • within each block, cells with BEHAVIOR_POWDER fall downward and slide diagonally, swapping with lighter materials
  • physics pass writes back to world ping-pong target before pheromone diffusion runs
  • src/sand/margolus.ts computes the per-frame block offset (JS side, passed as uniform)

ant physics and brain

ants run a gravity pass before the priority stack each frame:

  • gravity: ants in air cells fall downward. steering logic is skipped while falling (!isFalling guard).
  • collision displacement: if an ant ends up inside a solid cell, it is pushed out.
  • surface constraint: grounded ants follow surface contours.

the priority stack resolves behavior in order, first match wins:

  1. fall — handled before stack; sets isFalling, skips steering
  2. deposit — drop food at home tile, or deposit carried powder on surface
  3. navigate — pheromone-following when carrying food; upward bias when carrying powder
  4. forage — follow food scent when empty
  5. dig — bias toward diggable powder below surface (side-view only)
  6. wander — fallback random movement

key files

  • src/Renderer.ts — render target creation, pass orchestration, MRT setup, colony stats readback
  • src/Config.ts — simulation parameters (per-channel pheromone configs); ant keys: antsStartCount (default 4), antBudget (pool size, default 512), seedWorld (boolean)
  • src/constants.ts — material IDs (single source of truth for TS + GLSL); BRUSH_ANTS = 999 sentinel for ant-spawn brush
  • src/ColonyStats.ts — CPU readback of ant texture for colony-level aggregate stats (reports active/budget)
  • src/StatsOverlay.ts — on-screen stats display (cursor position, TPS, colony info); ant count shown as "active / budget"
  • src/__tests__/worldInit.test.ts — tests for world seeding (home/food placement via mulberry32 PRNG)
  • src/materials/types.ts — Material interface and BehaviorType constants
  • src/materials/registry.ts — MaterialRegistry with 6 built-in materials
  • src/materials/lookupTexture.ts — builds GPU lookup textures from registry
  • src/sand/margolus.ts — Margolus block offset calculation
  • src/scenes/SandPhysicsScene.ts — sand physics render pass
  • src/shaders/antsCompute.frag — ant behavior + MRT output (2 render targets via layout qualifiers); gravity, priority stack, spawn activation
  • src/shaders/worldBlur.frag — per-channel pheromone diffusion/decay (solid cells block diffusion)
  • src/shaders/world.frag — material ID preservation + pheromone merging
  • src/shaders/sandPhysics.frag — Margolus block CA for powder/sand movement
  • src/shaders/screenWorld.frag — final composite; applies per-pixel hash noise (+/-4% brightness) to material colors

planning docs

  • REALISM-IDEAS.md — research-backed features for more realistic ant behavior
  • INFRASTRUCTURE.md — data structure analysis mapping features to GPU infrastructure layers
  • docs/plans/2026-03-11-ant-farm-sand-physics-design.md — sand physics design
  • docs/plans/2026-03-11-ant-farm-implementation.md — ant farm implementation plan

shader files

in src/shaders/. each scene has a matched .vert/.frag pair. loaded as raw strings by the vite glsl plugin in vite.config.ts. all shaders use GLSL3 (#version 300 es via three.js glslVersion: THREE.GLSL3).

textures

in public/textures/ — ant.png and food.png sprites.