Fog of war: underground is black until the bot has seen it (t8)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 01:37:34 -04:00
co-authored by Claude Opus 5.5
parent a730a7d73c
commit 152a2af6df
20 changed files with 222 additions and 22 deletions
+35
View File
@@ -0,0 +1,35 @@
// Exploration only: never changes grains or the random stream.
const FOG = 2;
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) {
if (x < 0 || y < 0 || x >= W || y >= H) return;
const i = Math.floor(y / FOG) * FW + Math.floor(x / FOG);
if (v > fog[i]) fog[i] = v;
}
function fogSeen(x, y) {
if (x < 0 || y < 0 || x >= W || y >= H) return 255;
return fog[Math.floor(y / FOG) * FW + Math.floor(x / FOG)];
}
function fogInit() {
for (let x = 0; x < W; x++) for (let y = 0; y < Math.min(H, surfY[x] + 8); y++) fogMark(x, y, y <= surfY[x] ? 255 : (surfY[x] + 8 - y) * 255 / 8);
}
function fogLook(cx, cy) {
for (let a = 0; a < 256; a++) {
const dx = Math.cos(a * Math.PI / 128), dy = Math.sin(a * Math.PI / 128);
let hit = -1;
for (let d = 0; d < 48; d++) {
const x = Math.floor(cx + dx * d), y = Math.floor(cy + dy * d);
if (x < 0 || y < 0 || x >= W || y >= H) break;
const ph = PH[mat[y * W + x]];
if (hit < 0 && (ph === PH_SOLID || ph === PH_POWDER)) hit = d;
const v = Math.min(255, (48 - d) * 255 / 8, hit < 0 ? 255 : (4 - d + hit) * 255 / 4);
if (v <= 0) break;
fogMark(x, y, 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);
}
function fogRevealAll() { fog.fill(255); }
+9 -1
View File
@@ -25,7 +25,7 @@ function serializeWorld() {
pipes: (() => { if (pipesDirty) rebuildPipes(); return pipeNets.filter(pn => pn.n > 0).map(pn => [pn.blocks[0], pn.m, pn.n, Math.round(pn.T)]); })(),
cols: { surfY: Array.from(surfY), dirtY: Array.from(dirtY), graniteY: Array.from(graniteY), basaltY: Array.from(basaltY), magmaY: Array.from(magmaY) },
};
return { meta, buffers: { mat: mat.slice(), temp: t16, life: life.slice(), flags: flags.slice(), part: part.slice(), blockP: blockP.slice(), blockV: blockV.slice(), bgm: bgm.slice() } };
return { meta, buffers: { fog: fog.slice(), mat: mat.slice(), temp: t16, life: life.slice(), flags: flags.slice(), part: part.slice(), blockP: blockP.slice(), blockV: blockV.slice(), bgm: bgm.slice() } };
}
function deserializeWorld(meta, buffers) {
if (meta.v !== SAVE_VERSION) throw new Error('This world was saved by an older version of the game and cannot be loaded.');
@@ -108,5 +108,13 @@ function deserializeWorld(meta, buffers) {
if (!meta.specks) clearHardSpecks(true); // older saves: tidy away tiny specks of too-hard rock once
rebuildPipes();
for (const [b, m, n, T] of meta.pipes || []) { const id = pipeNetAt[b]; if (id >= 0) { const pn = pipeNets[id]; pn.m = m; pn.n = Math.min(n, pn.cap); pn.T = T; } }
if (buffers.fog && buffers.fog.length === fog.length) fog.set(buffers.fog);
else {
fogInit();
for (let b = 0; b < NB; b++) if (blockP[b]) fogRevealAround((b % BW) * BS + BS / 2, ((b / BW) | 0) * BS + BS / 2, 12);
for (const m of machines) if (m) for (let y = m.y; y < m.y + m.h; y += BS) for (let x = m.x; x < m.x + m.w; x += BS) fogRevealAround(x, y, 12);
for (const mo of molds) for (const i of moldCellsAt(mo.kind, mo.x, mo.y).walls) fogRevealAround(i % W, (i / W) | 0, 12);
}
fogLook(bot.x + bot.w / 2, bot.y + bot.h / 2);
EV.length = 0;
}
+1
View File
@@ -22,4 +22,5 @@ function simTick() {
if (tick % 60 === 17) { marketTick(); ordersTick(); }
if (tick % 30 === 11 && saplings.length) saplingTick();
ghostTick();
if (tick % 4 === 0) fogLook(bot.x + bot.w / 2, bot.y + bot.h / 2);
}
+1
View File
@@ -39,6 +39,7 @@ function discover(m, x, y, from, how, T) {
function alloc(w, h) {
W = w; H = h; N = w * h;
fogAlloc();
CW = Math.ceil(w / 32); CH = Math.ceil(h / 32); NCH = CW * CH;
mat = new Uint8Array(N); temp = new Float32Array(N); life = new Uint8Array(N); flags = new Uint8Array(N);
stamp = new Uint8Array(N); part = new Uint8Array(N); mach = new Uint16Array(N); digp = new Uint8Array(N);
+1
View File
@@ -311,5 +311,6 @@ function generateWorld(seedIn, w, h, onProgress) {
seen = new Uint8Array(NMAT); ledger = {};
stats.dug = stats.moved = stats.placed = stats.ignitions = stats.cast = stats.bars = 0;
EV.length = 0;
fogInit(); fogLook(bot.x + bot.w / 2, bot.y + bot.h / 2);
if (onProgress) onProgress(1);
}