diff --git a/docs/DESIGN.md b/docs/DESIGN.md index f65b817..4fd79ed 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -234,6 +234,10 @@ above, including: the bag; Ctrl+click a bag name adds it to the blow mix and Ctrl+right-click to pick-up; the menu is one line per material because the first version was too large. +- **Fog of war also reveals the ground around the bot (t17, 2026-10-24).** About 20 grains in every + direction, through rock, fully clear with a soft edge. Line of sight alone hid everything inside + the ground, so the owner couldn't see what was around them or where to dig. + ## Ideas not built yet - **Concrete**, as a stronger wall material from rubble. diff --git a/docs/PROJECT_MAP.md b/docs/PROJECT_MAP.md index ac70253..e504ce7 100644 --- a/docs/PROJECT_MAP.md +++ b/docs/PROJECT_MAP.md @@ -221,10 +221,10 @@ World state: the per-cell typed arrays, alloc(), ambient temperature by depth, w - functions: emit, bagCap, discover, alloc, depthU, depthY, computeAmbient, fillNoise, wakeXY, wakeHeatXY, wakeIdx, wakeHeatIdx - variables: W, H, N, CW, CH, NCH, mat, temp, life, flags, stamp, part, mach, digp, noiseB, airS, netId, isPow, occ, surfY, dirtY, graniteY, basaltY, magmaY, roofY, AMB, worldSeed, surfBase, underD, shallowD, lapse, BW, BH, NB, blockP, blockV, ents, bgm, flyers, ghostBlocks, ghostMolds, awake, hot, hotLvl, tick, tickStamp, machines, molds, nets, pcells, powerDirty, beltL, beltR, tubeLists, brokenMachines, ghostMachines, ghostBlocked, EV, bot, bag, bagTotal, player, seen, ledger, stats -### src/sim/fog.js (35 lines) +### src/sim/fog.js (46 lines) Exploration only: never changes grains or the random stream. - functions: fogAlloc, fogMark, fogSeen, fogInit, fogLook, fogRevealAround, fogRevealAll -- variables: FOG, fog, FW, FH +- variables: FOG, FOG_SENSE, fog, FW, FH ### src/sim/cells.js (176 lines) Cell helpers (setCell, move, enter) and the falling-sand movement of powders, liquids and gases (simMove). diff --git a/docs/agent-log.md b/docs/agent-log.md index 1bdecc3..cd5feb7 100644 --- a/docs/agent-log.md +++ b/docs/agent-log.md @@ -4,6 +4,19 @@ What agents have done, newest first. Add an entry for every piece of work: the d note or request it was for, what changed, the files touched, the tests run, and anything left open or not verified. Keep each entry short; the git history has the details. +## 2026-10-24: t17 Fog of war reveals the ground around the bot (Claude Code, Codex) + +- `src/sim/fog.js`: `FOG_SENSE = 20`; `fogLook` also reveals every fog cell within 20 grains, + through rock (full to 16, fading to 20). Claude rewrote Codex's per-grain `Math.hypot` loop to + work per fog cell. `fogLook` cost: 0.042 → 0.043 ms (every 4 ticks). +- `test/t_fog.js`: rock 12 grains away is seen, near the edge partly, 25 away still hidden. +- `docs/systems/fog.md`, DESIGN.md decision. Also: `.kandown/kandown_work.md` rule to write + tasks from chat in our own words (no owner labels, dates or quotes); t16/t19 descriptions + rewritten that way; `docs/kandown.md` notes that web-board descriptions were lost. +- Tests: `run_all.py --browser` all pass (220 `play.py` checks). `t_smooth` half-resolution failed + on two runs while the machine was loaded (load 6–10) and passed on the final run; timing + `fogLook` showed the change is not the cause. Screenshot `shots/fog-sense.png` checked. + ## 2026-10-24: t19 Vacuum blow all visual (Claude Code, Codex) - The owner's description was lost in kandown; chosen in chat: bag rows light up and the card diff --git a/docs/systems/fog.md b/docs/systems/fog.md index edff906..bb90261 100644 --- a/docs/systems/fog.md +++ b/docs/systems/fog.md @@ -13,6 +13,10 @@ Every four ticks, 256 rays from the bot's centre reveal up to 48 grains. The las grains fade out. Solid and powder stop sight after a four-grain fade into their face; air, gas and liquid pass sight. Bars and machine voids do not block it. +Each look also senses the ground around the bot through rock: every fog cell within +`FOG_SENSE` (20 grains) of the bot is revealed, fully clear out to 16 grains and fading to +nothing at 20, so the player can see ore and caves next to their tunnel and choose where to dig. + ## Saving The fog buffer is saved and exported with the other typed arrays, without a save version diff --git a/src/sim/fog.js b/src/sim/fog.js index 638c4a8..a250b35 100644 --- a/src/sim/fog.js +++ b/src/sim/fog.js @@ -1,5 +1,6 @@ // Exploration only: never changes grains or the random stream. const FOG = 2; +const FOG_SENSE = 20; // Reveal nearby ground through rock, in grains. let fog, FW, FH; function fogAlloc() { FW = Math.ceil(W / FOG); FH = Math.ceil(H / FOG); fog = new Uint8Array(FW * FH); } function fogMark(x, y, v) { @@ -28,6 +29,16 @@ function fogLook(cx, cy) { fogMark(x, y, v); } } + // one fog cell at a time, measured from its centre; full inside FOG_SENSE - 4, fading to the edge + const R2 = FOG_SENSE * FOG_SENSE, in2 = (FOG_SENSE - 4) ** 2; + const fy0 = Math.max(0, Math.floor((cy - FOG_SENSE) / FOG)), fy1 = Math.min(FH - 1, Math.floor((cy + FOG_SENSE) / FOG)); + const fx0 = Math.max(0, Math.floor((cx - FOG_SENSE) / FOG)), fx1 = Math.min(FW - 1, Math.floor((cx + FOG_SENSE) / FOG)); + for (let fy = fy0; fy <= fy1; fy++) for (let fx = fx0; fx <= fx1; fx++) { + const dx = (fx + 0.5) * FOG - cx, dy = (fy + 0.5) * FOG - cy, d2 = dx * dx + dy * dy, i = fy * FW + fx; + if (d2 >= R2) continue; + const v = d2 <= in2 ? 255 : (FOG_SENSE - Math.sqrt(d2)) * 255 / 4; + if (v > fog[i]) fog[i] = v; + } } function fogRevealAround(x, y, r) { for (let yy = Math.max(0, Math.floor(y - r)); yy <= Math.min(H - 1, y + r); yy++) for (let xx = Math.max(0, Math.floor(x - r)); xx <= Math.min(W - 1, x + r); xx++) if ((xx - x) ** 2 + (yy - y) ** 2 <= r * r) fogMark(xx, yy, 255); diff --git a/test/t_fog.js b/test/t_fog.js index 10de206..bfe60a0 100644 --- a/test/t_fog.js +++ b/test/t_fog.js @@ -9,6 +9,9 @@ rect(run, 40, 100, 140, 110, run('EMPTY')); rect(run, 40, 125, 140, 135, run('EMPTY')); run('bot.x = 60; bot.y = 102; fogLook(62.5, 104.5)'); check('open pocket is visible', run('fogSeen(82, 104) >= 200')); +check('sense test points are rock', run('mat[117 * W + 62] === STONE && mat[122 * W + 62] === STONE')); +check('nearby rock is clearly seen through the floor', run('fogSeen(62, 117) >= 200')); +check('rock near the sense edge is seen', run('fogSeen(62, 122) > 0')); check('rock hides separate pocket', run('fogSeen(62, 130) === 0')); check('one look has limited range', run('fogSeen(124, 104) === 0')); check('fog only increases', run('(()=>{const f = fog.slice(); fogLook(90,104); return f.every((v,i)=>fog[i]>=v)})()'));