diff --git a/.kandown/kandown_work.md b/.kandown/kandown_work.md index 1969d82..22cd3ab 100644 --- a/.kandown/kandown_work.md +++ b/.kandown/kandown_work.md @@ -10,9 +10,12 @@ The board is the owner's to-do list. `docs/kandown.md` explains how kandown work chat, and write nothing in code until the owner decides. Then record the decision. - **Backlog, tagged `idea`**: ideas for later. Leave them alone unless asked. - Questions get answers. -- **Keep the owner's words.** Never rewrite or tidy the owner's text in `## Context`, and don't +- **Keep the owner's words.** Never rewrite or tidy text the owner wrote in a task file, and don't rename tasks the owner made. Add what you learn as `## Subtasks` with `report:` lines, or in the `report` field. +- **Writing tasks from chat.** When you write a description, task or subtask from what the owner + said in chat, write it fully in your own words as a clear description of what they want. Don't + label it as the owner's, add dates, or quote them. - **When a task is finished**, move it to **Review** (that is "done, please check") and set the `report` field: what changed, and how to check it in the game. Never move a task to Done: the owner does that after checking it. If the owner moves it back with feedback, keep the @@ -24,4 +27,4 @@ The board is the owner's to-do list. `docs/kandown.md` explains how kandown work - **Commit task files with the work** they describe. The owner may be editing tasks too: stage only the task files you changed. - **New tasks the owner asks for**: `kandown create "title" --to Todo` (add `-t discussion` or - `-t idea` for Backlog), then put the owner's words under `## Context`. + `-t idea` for Backlog), then describe the task under `## Context`. 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/kandown.md b/docs/kandown.md index 5b901bb..944f7c4 100644 --- a/docs/kandown.md +++ b/docs/kandown.md @@ -49,6 +49,10 @@ kandown daemon stop # stop that daemon Find it with `tasks/_*.md`; don't rename it. - `kandown create` has no body option: write the body into the file after creating it. - `depends_on` blocks a move to Done until the listed tasks are done. +- **Descriptions typed on the web board can be lost.** On 2026-10-24 the owner created t16–t19 + on the web board with descriptions; the files were saved with a title and no body. The owner + believes it is a bug in the web daemon (not investigated). A task with only a title may have + had a description: ask the owner, then write their words under `## Context` yourself. ## A task file 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/tasks/t16.md b/tasks/t16.md index b25731b..7e23e05 100644 --- a/tasks/t16.md +++ b/tasks/t16.md @@ -20,7 +20,7 @@ report: | ## Context -- (owner's answers, 2026-10-24) What bothers you about the vacuum now? "Too many modes". Direction: "F opens a vacuum menu (Recommended)": F with the vacuum opens a dialog like the wall menu: one tile per material with Pick up and Blow toggles. The ⬇/⬆ buttons leave the bag rows. Pick-up modes shrink to two: Everything, or Only marked. +- The vacuum still has too many modes. Replace them with a menu on F, like the wall menu, where each material has a Pick up and a Blow toggle. Take the ⬇/⬆ buttons off the bag rows. Pick-up has only two states: everything when nothing is marked, or only the marked materials. ## Subtasks @@ -29,7 +29,7 @@ report: | - [x] Text, tests and screenshots up - [x] shift to blow all report: Shift + right click (while not flying) blows an even mix of everything loose in the bag; bars are left out. What you've chosen to blow doesn't change. -- [x] Ctrl+click bag items to select several for vac and blow (owner, in chat) +- [x] Ctrl+click bag items to select several for pick-up and blow report: Ctrl+click a bag name adds it to (or takes it out of) what you blow; Ctrl+right-click does the same for pick-up. Plain click still blows only that one. -- [x] Compact the F menu: one line per item (owner, in chat) +- [x] Compact the F menu: one line per item report: One row per material: swatch, name, count, a ⬇ and a ⬆ button under Pick up / Blow headings. diff --git a/tasks/t17.md b/tasks/t17.md new file mode 100644 index 0000000..d3e9759 --- /dev/null +++ b/tasks/t17.md @@ -0,0 +1,24 @@ +--- +id: t17 +status: Review +order: 0 +priority: P3 +created: 2026-10-24 +updated: 2026-10-24T16:29:07Z +title: fog of war changes +report: | + (agent) The bot now sees into the ground around it, through rock: about 20 grains in every + direction, fully clear, with a soft edge over the last few grains. It moves with the bot and + stays revealed afterwards, like the rest of the fog. Line of sight down tunnels and into caves + works as before (out to 48 grains). + To check: start or load a world, dig down, and look at the ore and caves showing in the rock + around the bot as you go. +--- + +## Context + +- Fog of war only reveals open areas the bot can see into, so you can't tell what's in the ground around you or where to dig. Also reveal the ground around the bot, through rock, out to about 20 grains with a soft edge. Ground revealed this way looks fully clear, the same as ground seen in the open. + +## Subtasks + +- [x] Reveal ground within about 20 grains of the bot, through rock, with a soft edge diff --git a/tasks/t19.md b/tasks/t19.md index ce5916d..46803c7 100644 --- a/tasks/t19.md +++ b/tasks/t19.md @@ -17,7 +17,7 @@ report: | ## Context -- (owner's answers, 2026-10-24) The description typed in kandown was lost. Chosen: "Bag rows light up" (while Shift is held, or while blowing everything, every row that will be blown lights up in the bag) and "Card shows it while Shift is held" (the Blow out line reads "Everything · mix of N" and the swatches by the cursor show the whole mix, before you click). +- Show what Shift + right click will blow before you click. While Shift is held with the Vacuum, or while blowing everything, every bag row that will be blown lights up, the card's Blow out line reads "Everything · mix of N", and the swatches by the cursor show the whole mix. ## Subtasks 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)})()'));