Add ant docs

This commit is contained in:
Jared Miller 2026-03-09 10:22:03 -04:00
parent d90a6784c5
commit a3bbc258be
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
2 changed files with 522 additions and 0 deletions

308
docs/INFRASTRUCTURE.md Normal file
View file

@ -0,0 +1,308 @@
# Infrastructure Requirements
Foundational data structures and capabilities needed to support all features
described in REALISM-IDEAS.md. These are the structural primitives — every
realism feature reduces to needing one or more of these five layers.
## A. Expanded ant state
Currently all 4 RGBA Float32 channels are used:
R = pos.x, G = pos.y, B = angle, A = packed(storage | isCarrying)
Most realism features need more per-ant data. This means a second ant
texture (RGBA Float32, same dimensions, same ping-pong pattern).
What needs to live in ant state:
personality/threshold float #3 individuality, #4 adaptive noise
steps since pickup int #1 distance-modulated deposition
cargo quality float #5 food quality encoding
path integration dx float #9 path integration
path integration dy float #9 path integration
role/caste float #11 caste switching
colony ID int #12 CHC recognition
That's 7 values. Two RGBA textures give 8 floats total, so with some
packing of ints into float bits (steps, colony ID, carrying flag are all
small integers) it fits in 2 textures. If the packing gets uncomfortable
a third texture is an option — WebGL supports up to 16 texture units per
shader, current shaders use 2-3, so headroom is fine.
Layout sketch for texture 2:
R = personality (0.0 = pure follower, 1.0 = pure explorer)
G = cargo quality (0.0 when not carrying, otherwise food quality value)
B = path integration dx (accumulated displacement since last reset)
A = packed(path_integration_dy | role | colony_id | steps_since_pickup)
The A channel packing is tight. Alternative: move steps_since_pickup into
texture 1's storage bits (current storage uses ~20 of 31 available bits)
and give path_integration_dy its own float in texture 2.A. Then role and
colony_id pack together (role quantized to 8 bits, colony_id in 8 bits =
16 bits, fits in the fractional part of another channel).
Pipeline impact:
- AntsComputeScene needs to read/write 2 textures per ant instead of 1
- Ping-pong doubles from 2 textures to 4
- antsCompute.frag gets a second sampler input and second render target
(requires MRT — multiple render targets — or a second pass)
- MRT is available in WebGL2 via gl.drawBuffers(), clean solution
Features unlocked: #1, #3, #4, #5, #9, #11, #12
## B. Generalized pheromone system
Currently 2 pheromone channels in the world texture:
G = scentToHome, B = scentToFood
A = unused (free slot for one more)
Minimum viable expansion: put repellent pheromone in world.A. That gives
3 channels with zero new textures.
But alarm pheromone (#6) and multicomponent blends (#8) need more. Options:
Option 1: Second world texture (RGBA Float32, same worldSize)
R = alarm pheromone
G = blend component A
B = blend component B
A = reserved
Option 2: Multiplex channels temporally or semantically
Less clean, harder to reason about, not recommended
Going with option 1, total pheromone channels = 6:
world1.G scentToHome
world1.B scentToFood
world1.A repellent
world2.R alarm
world2.G blend component A
world2.B blend component B
The blur/diffusion shader must generalize:
- Currently applies one blur radius and one fade-out factor uniformly
- Needs per-channel parameters:
channel decay rate diffusion radius notes
toHome medium medium standard trail
toFood medium medium standard trail
repellent slow (2x) narrow persists longer per biology
alarm fast wide spreads fast, fades fast
blend A configurable configurable depends on compound
blend B configurable configurable depends on compound
- Pass these as a uniform array or pack into a small config texture
- The blur pass runs once but processes all channels with their own params
Pipeline impact:
- worldBlur.frag becomes per-channel parameterized
- world.frag merges deposits into more channels
- antsCompute.frag reads more pheromone channels for decision-making
- antsDiscretize.frag may need more output channels (MRT again, or
expand discrete texture to RGBA Float32 to carry more deposit types)
Features unlocked: #2, #6, #8
## C. World cell metadata
Currently world.R uses 3 bits for cell flags:
bit 0 = hasFood, bit 1 = isHome, bit 2 = isObstacle
bits 3-31 = unused (29 bits free in float representation)
Several features need more per-cell information:
terrain type 3-4 bits #7 substrate-dependent decay
colony ownership 4-8 bits #12 multi-colony territories
food quality ~8 bits #5 quality encoding (quantized)
Terrain type (3 bits = 8 terrain types) and colony ownership (4 bits = 16
colonies) fit cleanly into world.R's unused bits:
bits 0-2: cell type flags (food, home, obstacle) — existing
bits 3-5: terrain type (0=default, 1-7 = surface variants)
bits 6-9: colony ID that owns this cell (0=neutral, 1-15 = colonies)
bits 10-17: food quality (0-255 quantized, only meaningful when hasFood)
bits 18-31: reserved
This keeps everything in a single channel with bit operations the shader
already uses (the existing code does bitwise AND/OR on world.R).
Terrain type feeds into the blur shader — the decay rate per cell becomes:
effective_decay = base_decay * terrain_decay_multiplier[terrain_type]
This means the blur shader needs to read the world texture (not just the
blurred copy) to know each cell's terrain type. Small perf cost but
the texture is already bound.
Food quality feeds into ant pickup behavior — when an ant grabs food, it
reads the quality bits and stores them in its cargo quality channel
(ant texture 2.G from section A).
Features unlocked: #5, #7, #12
## D. Ant-ant spatial interaction
Currently zero. Ants only interact through stigmergy (pheromone trails in
the world texture). No ant knows about any other ant's position or state.
The discrete ants texture maps ant deposits to grid cells but doesn't
preserve ant identity — it just accumulates pheromone values.
To enable ant-ant awareness, options:
Option 1: Identity-preserving discrete texture
Instead of (or in addition to) accumulating pheromone deposits,
store the ant index of whoever occupies each cell. Multiple ants
per cell requires either:
a) Last-write-wins (lossy but simple, GPU-friendly)
b) Linked list in a buffer (complex, needs WebGL2 atomic ops or
compute shaders)
c) Spatial hash with fixed bucket size (e.g. 4 ants per cell,
pack 4 ant indices into RGBA)
Option (a) is probably fine — tandem running only needs to know
"is there an ant near me" and check one neighbor, not enumerate
all neighbors.
Option 2: Proximity via world texture overlay
A separate texture where each cell stores the ID (or packed state)
of an ant occupying it. Ants sample neighboring cells to find nearby
ants. Radius-1 gives 8 neighbors, radius-2 gives 24.
For tandem running: leader deposits its ID in the cell. Follower
checks adjacent cells for the leader's ID, moves toward it.
For CHC recognition: ant reads neighbor cell, extracts colony ID
from neighbor's state, compares to own colony ID.
Implementation:
- New texture: antsPresenceTexture (RGBA Float32, worldSize x worldSize)
- R = ant index (or packed ant state subset)
- G = colony ID of occupant
- B = role/caste of occupant
- A = reserved
- Written during discretize pass, read during ant compute pass
- Cleared each frame before discretize
Tandem running specifics:
- Leader state: "has follower" flag, movement gated on follower proximity
- Follower state: "leader index" reference, moves toward leader cell
- Pairing logic: when a returning forager passes a naive ant, the naive
ant checks if the forager is available as a leader (not already paired)
- Race condition on pairing: last-write-wins means two ants might both
claim the same leader. Acceptable — worst case is a broken tandem that
reforms next frame.
Pipeline impact:
- New texture in discretize pass
- antsCompute.frag gets a new sampler for neighbor awareness
- Possibly a CPU readback for complex pairing logic that's too hard on GPU
Features unlocked: #10, #12
## E. Colony-level feedback
Currently no aggregate state. Individual ants have no information about the
colony as a whole — they only react to local pheromone concentrations.
Caste switching (#11) and alarm response scaling (#6) need colony-wide stats:
forager count how many ants are currently foraging
scout count how many ants are currently exploring
total food collected cumulative food delivered to nest
threat level number of alarm pheromone cells above threshold
colony size total ants (static, but relevant for ratios)
Two approaches:
Option 1: GPU reduction
Run a reduction shader that sums values across the ant texture:
- Count ants with isCarrying = 1 (foragers returning)
- Count ants with role > threshold (scouts)
- Sum food deposits at home cells
Requires multiple passes halving texture dimensions each time
(standard parallel reduction). Result lands in a 1x1 texture.
Read the 1x1 texture as a uniform for the next frame.
Pros: stays on GPU, no sync stall
Cons: multiple passes, more textures, latency (stats are 1 frame old)
Option 2: CPU readback
Use gl.readPixels on the ant texture (or a downsampled version).
Compute stats on CPU. Upload as uniforms next frame.
Pros: simpler to implement, flexible computation
Cons: GPU-CPU sync stall (readPixels is blocking in WebGL1, async in
WebGL2 via pixel buffer objects / fences). Could downsample first to
reduce transfer size.
Option 3: Hybrid
Reduce on GPU to a small texture (e.g. 4x4), read back 16 pixels
instead of thousands, compute final stats on CPU.
This is probably the pragmatic choice.
Colony stats feed back as uniforms into antsCompute.frag:
uniform float u_foragerRatio; // foragers / total ants
uniform float u_scoutRatio; // scouts / total ants
uniform float u_foodCollected; // cumulative food at nest
uniform float u_threatLevel; // alarm pheromone intensity
Individual ants use these to adjust their role variable:
- If foragerRatio is high and scoutRatio is low, some foragers transition
toward scouting (role variable drifts)
- If threatLevel is high, nearby ants shift toward defensive behavior
- Transitions are gradual (continuous role variable, not discrete switch)
Features unlocked: #6, #11
## Dependency graph
Which infrastructure layers does each feature need?
feature A B C D E
ant pher cell a2a agg
#1 distance-modulated deposition x
#2 negative pheromone x
#3 individual thresholds x
#4 adaptive noise x
#5 food quality encoding x x
#6 alarm pheromone x x
#7 substrate-dependent decay x x
#8 multicomponent blends x
#9 path integration x
#10 tandem running x x
#11 caste switching x x
#12 CHC recognition x x x
Layer A (expanded ant state) unlocks: 9 of 12 features
Layer B (generalized pheromones) : 4 of 12 features
Layer C (cell metadata) : 3 of 12 features
Layer D (ant-ant interaction) : 2 of 12 features
Layer E (colony feedback) : 2 of 12 features
Suggested build order based on feature unlock count and dependency:
1. Layer A — second ant texture + MRT (unlocks most features)
2. Layer B — pheromone channel expansion + per-channel blur params
3. Layer C — bit-packed cell metadata (small change, high leverage)
4. Layer E — colony aggregate readback (needed before caste switching)
5. Layer D — spatial neighbor queries (hardest, fewest features, do last)
## WebGL2 requirements
Several infrastructure pieces depend on WebGL2 features:
MRT (multiple render targets) layers A, D
gl.drawBuffers() writing 2+ textures per pass
pixel buffer objects layer E async readback
integer textures (optional) cleaner bit packing in layers A, C
The simulation already uses three.js WebGLRenderer. Confirm it's running
in WebGL2 mode (three.js defaults to WebGL2 when available). If targeting
WebGL1 fallback, MRT requires WEBGL_draw_buffers extension and some
features may not be feasible.

214
docs/REALISM-IDEAS.md Normal file
View file

@ -0,0 +1,214 @@
# Realism Improvements for Ant Simulation
Research notes on real ant biology that could improve the simulation.
Based on current literature through early 2026.
## Current simulation model
- 2 pheromone channels (toHome, toFood) with uniform deposition rate
- 3-way sampling (ahead/left/right) for trail following
- Random noise for exploration
- Binary carrying state (has food or doesn't)
- Uniform ant behavior (no individuality beyond ±20% scent storage)
- Exponential decay + blur for pheromone diffusion
## High impact, probably feasible on GPU
### 1. Concentration-dependent pheromone deposition
Real ants deposit up to 22x more pheromone near the food source vs near the
nest (Lasius niger study, Springer 2024). They also modulate based on food
quality — Pharaoh's ants deposit significantly more trail pheromone for 1.0M
sucrose vs 0.01M sucrose.
Currently `scentPerMarker` is constant (200). Making it decay with distance
traveled since pickup (or scale with a food quality value) would produce more
realistic trail dynamics. The concentration gradient effectively encodes
distance information for other ants.
Shader change: track steps-since-pickup in ant state, use it to scale
deposition.
### 2. Negative/repellent pheromone ("no entry")
Pharaoh's ants deposit a repellent pheromone at trail junctions leading to
unrewarding branches. Key details:
- Lasts ~2x longer than attractive pheromone (~78 min vs ~33 min half-life)
- Ants encountering it U-turn or exhibit zigzagging
- Deposited specifically at bifurcation points, not along entire failed paths
Source: Nature 438, 442 (2005)
This would prevent the colony from getting stuck on depleted food sources.
The alpha channel in the world texture is available for a 3rd pheromone type.
Shader change: add repellent channel, deposit on failed searches or at
depleted food, make ants U-turn on contact.
### 3. Individual response thresholds (ant "personality")
Real ants show consistent individual differences:
- Bolder/more exploratory individuals become scouts, discover new food
- Less exploratory individuals become recruits, exploit known trails
- Scouts show lower responsiveness to trail pheromone
- Recruits are highly attracted to trail pheromone and nestmates
- These differences affect learning strategies (personal vs social info)
Source: Frontiers in Ecology and Evolution (2021)
The dominant model for task allocation is the "response threshold model" —
each ant has a threshold for each stimulus. When pheromone concentration
exceeds the ant's threshold, it follows; below threshold, it explores.
Thresholds are determined by genetics, age, body size, experience, and
spatial location.
Shader change: pack a per-ant exploration/exploitation bias into the ant
texture. Use it to modulate the balance between pheromone following and
random walk.
### 4. Adaptive stochastic noise
In real colonies, noise prevents deadlocking onto suboptimal food sources.
When a better source appears, noise is what allows some ants to discover it
instead of all ants reinforcing the first trail found.
Source: arXiv 1508.06816
Could make noise level inversely proportional to pheromone strength — ants
on weak trails explore more, ants on strong trails follow more tightly.
This is a small change to the existing random walk logic.
## Medium impact, moderate complexity
### 5. Food quality encoding
Real ants encode food quality in trail strength — the number of ants
recruited scales directly with pheromone quantity released by returning
foragers.
Adding multiple food sources with different quality values would let ants
deposit proportionally more pheromone for better food. The colony would
naturally converge on the best source first, then shift when it depletes.
Requires: food quality attribute per food cell, ants read it on pickup,
store it, use it as a deposition multiplier.
### 6. Alarm pheromone
A separate fast-spreading, fast-decaying signal that causes nearby ants to
either flee or swarm depending on context. Transgenic ant research mapped
alarm pheromone processing to just 6 glomeruli — a sparse "panic button"
with simple encoding.
Could interact with obstacle placement or painted "danger zones." Would
need a 4th pheromone channel or multiplexing with existing channels.
Real compounds: formic acid + n-undecane in carpenter ants, pyrazines in
Tetramorium. The blend ratio determines whether ants flee vs attack.
### 7. Substrate-dependent pheromone decay
Real pheromone half-life varies ~3x depending on surface type:
- ~9 min on plastic
- ~3 min on paper (Pharaoh's ant trail pheromone)
- Temperature also accelerates degradation
If the world had terrain types (encoded in unused bits of the world
texture), pheromone could persist longer on some surfaces. This would
create emergent preferred highway corridors on "good" terrain.
### 8. Multicomponent pheromone blends
Real pheromone signals are multicomponent blends, not single compounds.
A single gland secretion can contain 32+ hydrocarbons, acids, aldehydes,
etc. Different ratios trigger different responses — in Tetramorium,
workers respond maximally to a specific 3:7 ratio of two pyrazine
components.
Could model as ratio between two co-deposited channels rather than
single-channel signals.
## Lower priority but fascinating
### 9. Path integration
Desert ants (Cataglyphis) maintain a running home vector — a cumulative
sum of direction + distance traveled. This gives them a "home vector"
pointing back to the nest at all times, even without pheromone trails.
Key details:
- The integrator resets at known locations (nest entrance, landmarks)
- No cognitive map — it's a procedural "when you see this, go that way"
- Ants can store multiple reference vectors to different food sites
- Works even in featureless environments
Source: Springer, Journal of Comparative Physiology A (2024)
Shader change: accumulate displacement vector per ant, use it as fallback
navigation when no pheromone detected.
### 10. Tandem running
One-to-one recruitment where a knowledgeable leader guides a naive
follower:
- Follower maintains antennal contact with leader's legs/abdomen
- Leader only advances after being tapped (feedback loop)
- Leader moves slowly so follower can learn landmarks
- Follower can become leader after learning the route
Source: Journal of Experimental Biology 223(9), 2020
Hard to implement on GPU due to ant-ant interaction requirements, but
would produce striking emergent behavior. Might need a CPU-side pass for
pairing logic.
### 11. Caste role switching via neuropeptides
2025 Cell paper (Rockefeller): two neuropeptides — CCAP and NPA — control
division of labor in leafcutter ants. Manipulating them turns defenders
into nurses or gardeners into harvesters. Same molecular mechanism found
in naked mole-rats (convergent evolution, 600M+ years).
Could model as a continuous "role" variable per ant that shifts based on
colony-level signals (ratio of foragers to scouts, food availability,
threat level).
### 12. Cuticular hydrocarbon (CHC) recognition
Ants recognize nestmates via complex blends of dozens of cuticular
hydrocarbons. Non-nestmates are attacked. This is relevant if the
simulation ever has multiple colonies competing for resources.
## Ant brain / connectome status (for reference)
- No ant connectome exists yet
- Drosophila adult connectome completed Oct 2024: 139K neurons, 50M
synapses, 8,400+ cell types (FlyWire Consortium, Nature)
- Clonal raider ant (Ooceraea biroi) reference brain published 2025
(Rockefeller). TEM imaging for full connectome is underway
- Ant antennal lobes have ~460 olfactory glomeruli vs ~50 in Drosophila,
reflecting the centrality of chemical communication
- Alarm pheromone processing maps to just 6 glomeruli — validates using
simple threshold rules in simulation
- 2025 PNAS paper describes ant colonies as "liquid brains" where
heterogeneity in individual movement patterns (not uniformity) drives
collective efficiency
## Key sources
- Pharaoh's ant pheromone modulation: ScienceDirect S0003347207002278
- Spatial pheromone deposition in Lasius niger: Springer s00040-024-00995-y
- Negative pheromone: Nature 438, 442 (2005)
- Individual personality: Frontiers in Ecology and Evolution (2021)
- Stochastic noise in foraging: arXiv 1508.06816
- Drosophila connectome: Nature s41586-024-07968-y
- Ant reference brain: Current Biology S0960-9822(25)01520-9
- Neuropeptide caste control: Cell S0092867425005732
- Path integration: Springer s00359-024-01725-2
- Tandem running: JEB 223(9) jeb221408
- Liquid brains: PNAS 2506930122