Fog of war reveals the ground around the bot through rock (t17)

Also: board rule to write tasks from chat in our own words, task
descriptions rewritten that way, and a note on lost web-board descriptions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 12:29:08 -04:00
co-authored by Claude Opus 5.5
parent ec687b8c6c
commit 1f56d27ded
6 changed files with 37 additions and 2 deletions
+4
View File
@@ -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 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. 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 ## Ideas not built yet
- **Concrete**, as a stronger wall material from rubble. - **Concrete**, as a stronger wall material from rubble.
+2 -2
View File
@@ -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 - 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 - 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. Exploration only: never changes grains or the random stream.
- functions: fogAlloc, fogMark, fogSeen, fogInit, fogLook, fogRevealAround, fogRevealAll - 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) ### src/sim/cells.js (176 lines)
Cell helpers (setCell, move, enter) and the falling-sand movement of powders, liquids and gases (simMove). Cell helpers (setCell, move, enter) and the falling-sand movement of powders, liquids and gases (simMove).
+13
View File
@@ -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 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. 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) ## 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 - The owner's description was lost in kandown; chosen in chat: bag rows light up and the card
+4
View File
@@ -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; 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. 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 ## Saving
The fog buffer is saved and exported with the other typed arrays, without a save version The fog buffer is saved and exported with the other typed arrays, without a save version
+11
View File
@@ -1,5 +1,6 @@
// Exploration only: never changes grains or the random stream. // Exploration only: never changes grains or the random stream.
const FOG = 2; const FOG = 2;
const FOG_SENSE = 20; // Reveal nearby ground through rock, in grains.
let fog, FW, FH; let fog, FW, FH;
function fogAlloc() { FW = Math.ceil(W / FOG); FH = Math.ceil(H / FOG); fog = new Uint8Array(FW * FH); } function fogAlloc() { FW = Math.ceil(W / FOG); FH = Math.ceil(H / FOG); fog = new Uint8Array(FW * FH); }
function fogMark(x, y, v) { function fogMark(x, y, v) {
@@ -28,6 +29,16 @@ function fogLook(cx, cy) {
fogMark(x, y, v); 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) { 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); 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);
+3
View File
@@ -9,6 +9,9 @@ rect(run, 40, 100, 140, 110, run('EMPTY'));
rect(run, 40, 125, 140, 135, run('EMPTY')); rect(run, 40, 125, 140, 135, run('EMPTY'));
run('bot.x = 60; bot.y = 102; fogLook(62.5, 104.5)'); run('bot.x = 60; bot.y = 102; fogLook(62.5, 104.5)');
check('open pocket is visible', run('fogSeen(82, 104) >= 200')); 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('rock hides separate pocket', run('fogSeen(62, 130) === 0'));
check('one look has limited range', run('fogSeen(124, 104) === 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)})()')); check('fog only increases', run('(()=>{const f = fog.slice(); fogLook(90,104); return f.every((v,i)=>fog[i]>=v)})()'));