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).