Refactor: merge duplicated rules, split the largest files by topic (t21)
- One helper each for wall and mold refunds, tube edges and lanes, pipe text, piece dimensions, font lookup, reach circles and surface averaging. - previews, smooth, notebook, materials, worldgen and selection split into topic files (preview-drill, preview-selection, smooth-shaders, notebook-market, notebook-blueprints, material-tables, worldgen-helpers, selection-pickers, selection-panels). - Every suite's output identical apart from timings; seeds make the same worlds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-61
@@ -1,64 +1,4 @@
|
||||
// World generation: noise, layers, ores, caves, water, trees, and clearing tiny hard specks.
|
||||
// ---------- Perlin noise ----------
|
||||
function makeNoise(rng) {
|
||||
const perm = new Uint8Array(512), gx = new Float32Array(256), gy = new Float32Array(256);
|
||||
const p = []; for (let i = 0; i < 256; i++) p.push(i);
|
||||
for (let i = 255; i > 0; i--) { const j = Math.floor(rng() * (i + 1)); const t = p[i]; p[i] = p[j]; p[j] = t; }
|
||||
for (let i = 0; i < 512; i++) perm[i] = p[i & 255];
|
||||
for (let i = 0; i < 256; i++) { const a = rng() * Math.PI * 2; gx[i] = Math.cos(a); gy[i] = Math.sin(a); }
|
||||
return function (x, y) {
|
||||
const xi = Math.floor(x), yi = Math.floor(y), xf = x - xi, yf = y - yi;
|
||||
const X = xi & 255, Y = yi & 255;
|
||||
const p0 = perm[Y], p1 = perm[Y + 1];
|
||||
const h00 = perm[X + p0], h10 = perm[X + 1 + p0], h01 = perm[X + p1], h11 = perm[X + 1 + p1];
|
||||
const n00 = gx[h00] * xf + gy[h00] * yf, n10 = gx[h10] * (xf - 1) + gy[h10] * yf;
|
||||
const n01 = gx[h01] * xf + gy[h01] * (yf - 1), n11 = gx[h11] * (xf - 1) + gy[h11] * (yf - 1);
|
||||
const u = xf * xf * xf * (xf * (xf * 6 - 15) + 10), v = yf * yf * yf * (yf * (yf * 6 - 15) + 10);
|
||||
return (n00 + u * (n10 - n00) + v * (n01 - n00) + u * v * (n00 - n10 - n01 + n11)) * 1.41;
|
||||
};
|
||||
}
|
||||
function fbm(n, x, y, oct) { let s = 0, a = 1, f = 1, t = 0; for (let o = 0; o < oct; o++) { s += n(x * f, y * f) * a; t += a; a *= 0.5; f *= 2; } return s / t; }
|
||||
|
||||
// Small specks of rock harder than the rock around them (a few grains of iron ore in stone, a
|
||||
// chip of granite, a sliver of basalt) are not worth having: a bit too weak to break them leaves
|
||||
// them hanging in the way. Any such piece of SPECK_MIN grains or fewer becomes the softer rock
|
||||
// around it. Bigger veins and pockets stay. live: the world is in play (an older save).
|
||||
const SPECK_MIN = 30;
|
||||
function clearHardSpecks(live) {
|
||||
const seen = new Uint8Array(N), st = new Int32Array(N), cells = new Int32Array(SPECK_MIN + 1);
|
||||
let n = 0;
|
||||
for (const h0 of [6, 5, 4]) {
|
||||
seen.fill(0);
|
||||
const mem = (i) => { const m = mat[i]; return (flags[i] & F_NAT) !== 0 && PH[m] === PH_SOLID && HARD[m] >= h0 && HARD[m] <= 6 && YLD[m] !== 0 && !PARTMAT[m]; };
|
||||
const soft = (i) => { const m = mat[i]; return (flags[i] & F_NAT) !== 0 && PH[m] === PH_SOLID && HARD[m] >= 1 && HARD[m] < h0 && YLD[m] !== 0 && !PARTMAT[m]; };
|
||||
for (let i0 = 0; i0 < N; i0++) {
|
||||
if (seen[i0] || !mem(i0)) continue;
|
||||
let sp = 0, sz = 0, x0 = W, y0 = H, x1 = 0, y1 = 0;
|
||||
const hosts = new Map();
|
||||
st[sp++] = i0; seen[i0] = 1;
|
||||
while (sp) {
|
||||
const i = st[--sp], x = i % W, y = (i / W) | 0;
|
||||
if (sz <= SPECK_MIN) cells[sz] = i;
|
||||
sz++;
|
||||
if (x < x0) x0 = x; if (x > x1) x1 = x; if (y < y0) y0 = y; if (y > y1) y1 = y;
|
||||
for (const j of [x > 0 ? i - 1 : -1, x < W - 1 ? i + 1 : -1, i - W, i + W]) {
|
||||
if (j < 0 || j >= N || seen[j]) continue;
|
||||
if (mem(j)) { seen[j] = 1; st[sp++] = j; }
|
||||
else if (soft(j)) hosts.set(mat[j], (hosts.get(mat[j]) || 0) + 1);
|
||||
}
|
||||
}
|
||||
if (sz > SPECK_MIN) continue;
|
||||
// a speck left floating (in a cave, or dug round) takes the rock nearest round it
|
||||
if (!hosts.size) for (let y = Math.max(0, y0 - 5); y <= Math.min(H - 1, y1 + 5); y++) for (let x = Math.max(0, x0 - 5); x <= Math.min(W - 1, x1 + 5); x++) { const j = y * W + x; if (soft(j)) hosts.set(mat[j], (hosts.get(mat[j]) || 0) + 1); }
|
||||
let host = 0, best = 0;
|
||||
for (const [m, c] of hosts) if (c > best) { best = c; host = m; }
|
||||
if (!host) continue;
|
||||
for (let k = 0; k < sz; k++) { const i = cells[k]; if (live) setCell(i, host, temp[i], F_NAT); else mat[i] = host; }
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
// World generation: staged terrain, ore, caves and placement, with synchronous and async entry points.
|
||||
// ---------- World generation ----------
|
||||
function* worldSteps(seedIn, w, h) {
|
||||
yield [0, 'Shaping the land'];
|
||||
|
||||
Reference in New Issue
Block a user