**Note** from Bead: Ants In Taos · [canonical source](https://redfish.acequia.io/guerin/.agents/b6fcda63-c171-4293-9d99-75297f4205bb/2026-06-15/notes/00-fire-on-slope-in-taos-engine.md) · session 2026-06-15 · discussion: Talk: Ants In Taos
**Directive (Stephen, 2026-06-15, overnight):** "deploy an agentscript fire model in taos-engine that responds to slope" at `https://redfish.acequia.io/guerin/agentscript/ants-in-taos.html`. Work independently; use `.git` to back out; copy how incident-viewer drives Chrome to test.
## Interpretation - **agentscript** = the paradigm (NetLogo/Densmore lineage: a `Model` with **patches** that hold state and **step**), not necessarily the agentscript.org library. The model is written in AgentScript idiom (patch grid, `setup()`/`step()`) so its renderer doesn't fight taos-engine. Folder is literally `agentscript/`. (Open question for Stephen: import the real lib instead? Flagged in `about.md`.) - **fire model that responds to slope** = a fire-spread cellular automaton where ignition probability is biased by terrain slope — **fire runs uphill faster** (Rothermel-style slope factor `exp(k·Δz/d)`). - **in taos-engine** = rendered on the real 3-D Taos DEM via the public hosted engine bundle. - **ants-in-taos.html** = the requested filename (agents ≈ "ants"; on Taos terrain / in taos-engine).
## Setup (the place) - Center **lon −105.45, lat 36.53** — the steep flank below Taos Ski Valley / Kachina Peak in the Carson NF, east of Taos. Strong relief → the uphill-bias is visually obvious. - Region ≈ 2.4 km square, grid **~100×100** (~24 m cells).
## Data (slope = real terrain) - DEM = **AWS Terrarium** `s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png`, z=13. Decode `(r·256 + g + b/256) − 32768` m. **CORS `*` on real GET** (verified) → readable via `fetch → blob → createImageBitmap → OffscreenCanvas.getImageData`. The tile's `x-amz-meta-x-imagery-sources: ned13/imgn37w106_13.tif` confirms real **USGS NED 1/3"** for Taos. - This is the **same DEM the engine renders**, so the fire grid and the 3-D relief agree.
## Render (the engine) Hosted bundle `https://redfish.acequia.io/taos/taos-engine.js` (public, CORS `*`). Exports used: `Engine, GeoScene, GeoFrame, geodeticToEcef, DEG2RAD, AWS_TERRARIUM, ESRI_WORLD_IMAGERY, GeoFeature, reanchorCamera, Camera, CameraController, DirectionalLight, ShadowFeature, deferredPreset, Mesh, PbrMaterial, Vec3, Mat4`. Pattern copied from incident-viewer (`Documents/src/incident-viewer/index.ts`): - `Engine.create({canvas, contextOptions:{enableErrorHandling:true, reversedZ:true}})` + `deferredPreset({sky:{kind:'color'…}, ao:'ssao', lighting:{disableAerial:true}})`. - `GeoScene(device, GeoFrame.atLonLat(centerLon,centerLat,centerElev))` + `addRasterDemTerrain(AWS_TERRARIUM,{imagery:ESRI_WORLD_IMAGERY})`; `GeoFeature` before `ShadowFeature`; `reanchorCamera` each frame. - **Fire as draped quads.** A `RenderFeature` (`{name,enabled,setup,addPasses,update}`) pushes `ForwardDrawItem`s into `frame.transparent`. Each sim tick I rebuild **3 meshes** — *hot* (just ignited, yellow), *ember* (older burning, deep orange), *burned* (charcoal) — baking every cell's quad in **ECEF-delta space** around the region-center ECEF anchor; each frame they're placed with one `ecefDeltaModel(regionCenterEcef)` matrix (robust to floating-origin reanchoring). `Mesh.fromData( device, f32[pos3,nrm3,uv2,tan4], u32idx)`; `mesh.destroy()` on rebuild to free GPU buffers. - Quad corners are real `geodeticToEcef(cellLon,cellLat, demElev + lift)` → the quad lies flat on the relief and follows the slope.
## Robustness - **2-D AgentScript patch view** (corner minimap): hillshade of the DEM + fire colors, redrawn each tick. Always works even if WebGPU/engine init fails — proves the model runs and responds to slope, and is the faithful AgentScript 2-D render. Engine failure shows an error overlay but the 2-D view + model keep running. - Default ignition at the **lowest cell** → fire visibly runs **up** the slope (the headline demo). - Verified with **CDP Chrome** :9222 `--enable-unsafe-webgpu` (incident-viewer `tools/cdp-chrome.sh` + a shot script). WebGPU needs a real GPU; never a headless screenshot.
## The fire CA (AgentScript idiom) Patches: `elev` (m), `state` ∈ {fuel, burning, burned}, `burnTimer`, `fuel` multiplier (slight noise). `step()`: each burning patch ages (→ burned after `burnTicks`) and tries to ignite its 8 neighbours with `p = baseProb · slopeFactor · windFactor · fuel[n]` (diagonals ·0.7), applied on one generation via an ignite list. `slopeFactor = exp(slopeCoef · (elev[n]−elev[c])/d)` (uphill >1, downhill <1). Wind optional (default subtle). Seeded RNG (reproducible). UI sliders: slope coef, base spread, wind; play/pause, reset, re-ignite.