ants/docs/plans/2026-03-11-ant-behavior-overhaul-design.md
Jared Miller fe537218a3
Add ant behavior overhaul design and nest-building research
Design covers ant gravity/physics, unified brush tool, behavioral
priority stack, sand color variation, and config changes. Research
doc captures real ant nest construction patterns for informing
simulation behavior.
2026-03-11 20:31:06 -04:00

155 lines
6.9 KiB
Markdown

Ant Behavior Overhaul — Design
===============================
goal: fix broken ant physics, add gravity and surface movement, unify the
brush tool so everything (including ants) is droppable, establish a behavioral
priority stack, and lay groundwork for emergent nest architecture.
reference: docs/NEST-BUILDING.md (research on real ant nest construction)
1. Ant Physics — Gravity and Surface Movement
----------------------------------------------
problem: ants float through air with no physics. they walk through sand and
rise upward forever when carrying.
two physical rules added to antsCompute.frag:
GRAVITY: if the cell below an ant is air, the ant falls one cell downward.
falling ants don't steer — they just drop. this makes dropped ants tumble
from wherever you place them.
SURFACE CONSTRAINT: ants can only walk (apply their steering angle) when
they're adjacent to a solid material cell. "adjacent" means any of the 4
cardinal neighbors is non-air. if an ant is on top of sand, next to a tunnel
wall, or on the world boundary — it can walk. if it's in open air with nothing
nearby, it falls.
ANT-SAND COLLISION: sand physics runs first (pass 1), ants compute runs later
(pass 4). if falling sand fills an ant's cell between frames, the ant gets
displaced to the nearest air cell (check up first, then sideways). sand always
wins, ants get squeezed out. this prevents deadlock where an ant and a grain
occupy the same cell.
MOVEMENT THROUGH MATERIALS: ants treat all non-air materials as solid walls
they can't walk into, UNLESS they're actively digging (picking up a powder
cell they're facing). walking into rock, food, or home blocks movement.
2. Unified Brush — Everything is Droppable
-------------------------------------------
problem: ants are created at init time only. materials and ants use separate
systems. want Sandboxels-style "pick element, drop it."
the brush palette becomes a single list of elements: erase, sand, dirt, rock,
food, home, ants. all use the same brush size slider. brush size = number of
cells filled per click/drag frame.
FOR MATERIALS (sand, dirt, rock, food, home, erase): works like today.
draw.frag writes the material ID into world cells within the brush radius.
FOR ANTS: clicking writes to a separate "ant spawn" buffer — a small queue of
(x, y) positions. each frame, the ant compute pass checks this buffer and
activates inactive ants (those still at pos == vec2(0)) at those positions.
brush size N = activate N ants at/near the click position, randomly scattered
within the brush radius.
ANT BUDGET: a config value antBudget (default 512) sets the texture size. the
starting count antsStartCount (default 4) determines how many activate on init.
drawing ants activates more from the pool. if the pool is full, drawing does
nothing.
GUI CHANGES:
- material palette gets an "ants" entry with keybind (A)
- brush radius slider controls all elements
- antsStartCount replaces the 2^N slider — plain number (0-64)
- antBudget is not in the main GUI (advanced/hidden config)
SEED TOGGLE: a checkbox "seed home + food" (default on). when on, world init
places one home and one food at random surface positions. when off, blank sand
and sky. lives in GUI under world section.
3. Ant Brain — Behavioral Drives
----------------------------------
PHASE A (this implementation):
each ant has a priority stack, evaluated top to bottom each frame:
1. FALLING — if no solid neighbor below, fall. skip all other logic.
2. CARRYING, DEPOSIT — if carrying food and at home, drop it. if carrying
sand/dirt and on the surface (air above, solid below), drop it.
3. CARRYING, NAVIGATE — if carrying food, follow toHome pheromone. if carrying
sand/dirt, bias upward toward surface.
4. NOT CARRYING, FORAGE — if food scent detected, follow toFood pheromone.
5. NOT CARRYING, DIG — if adjacent to diggable powder below the surface, pick
it up. prefer digging downward at roughly the angle of repose (~40 degrees).
6. NOT CARRYING, WANDER — random walk along surfaces. the fallback.
SUPPRESSORS (every drive has a reason NOT to fire):
- digging suppresses when on the surface or material is too hard
- foraging suppresses when no food scent in sample range
- deposit suppresses when no solid ground below drop point
- wandering is the fallback — only fires when nothing else triggers
WHAT GIVES ANTS PURPOSE WITHOUT A QUEEN: home marker acts as anchor. ants
forage food back to home. ants dig near home to create shelter. the home
pheromone radiates outward and gives ants a "come back here" signal. without
a home marker, ants just wander and react to whatever they're near.
PHASE B (future — digging pheromone):
ants deposit a "dig here" scent when excavating, attracting other ants to dig
nearby. this creates the density-driven chamber-to-tunnel transition from
the nest-building research. the repellent pheromone channel (A channel) could
be repurposed or a 5th channel added. pheromone decay rate controls tunnel
compactness: short lifetime = tight tunnels, long lifetime = diffuse.
PHASE C (future — colony dynamics):
age parameter on ants (personality field in texture 1 repurposed or extended).
young ants dig more, old ants forage more. colony growth = activating new ants
from the budget when food-delivered count exceeds a threshold. nest expansion
triggered when population/excavated-area ratio exceeds threshold. emergency
"all hands dig" mode when nest area drops below expected-per-population.
4. Sand Color Variation
------------------------
problem: sand looks flat — every cell is the same color.
in screenWorld.frag, when rendering a non-air material, hash the cell's grid
position to produce a small color offset:
vec3 baseColor = materialColorLookup(materialId);
float noise = hash(ivec2(gl_FragCoord.xy)) * 0.08 - 0.04; // +/-4%
baseColor += noise;
spatial and deterministic (same cell always looks the same). no flickering.
works for all materials automatically — dirt gets subtle variation, rock gets
speckle.
5. Config and Persistence
--------------------------
new/changed config defaults:
antsStartCount 4 slider 0-64, plain number. replaces antsCount.
antBudget 512 hidden. texture size = ceil(sqrt(antBudget)).
seedWorld true checkbox. "seed home + food" toggle.
brushElement "sand" palette buttons. replaces brushMaterial.
includes "ants" as an option.
REMOVED: antsCount (the 2^N exponent).
TEXTURE SIZING: antBudget determines the ant texture dimensions.
512 -> sqrt(512) ~ 23 -> 23x23 = 529 slots. ants at index >= antBudget stay
at (0,0) and never activate. starting ants (0 to antsStartCount-1) get
initialized on first frame. drawing ants activates the next available slot.
LOCAL STORAGE: same pattern as today — only non-default values saved.
antsStartCount and seedWorld persist. antBudget probably shouldn't persist
(changing it requires re-creating textures on reload).