Faces cut into loose piles collapse outward instead of draining column by column (t93)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-28 22:06:48 -04:00
co-authored by Claude Opus 5.5
parent 6ac5f463aa
commit 84dd8b8d0a
11 changed files with 271 additions and 9 deletions
+34
View File
@@ -0,0 +1,34 @@
// Shared Node/browser reproduction: vacuum the foot of settled 60-grain heaps, one stroke per tick.
function pileCutWorld() {
alloc(768, 600); worldSeed = 7; RS = 123;
for (let x = 0; x < W; x++) { surfY[x] = 224; dirtY[x] = 234; graniteY[x] = basaltY[x] = magmaY[x] = H; }
computeAmbient(); fillNoise();
for (let y = 0; y < H; y++) for (let x = 0; x < W; x++) {
const i = y * W + x; mat[i] = y >= 224 ? STONE : EMPTY;
flags[i] = y >= 224 ? F_NAT : 0; temp[i] = AMB[y];
}
bag.fill(0); bagTotal = 0; player.tankTier = 3;
resetWeather(); weather.next = 1e15; updateRoof();
}
function pileCutSetup(peak, mixed) {
const rubble = [RSTONE, CUORE, FEORE, LDIRT];
for (let y = 164; y < 224; y++) for (let x = peak - (y - 164); x <= peak + (y - 164); x++)
setCell(y * W + x, mixed ? rubble[(x + y) % rubble.length] : RSTONE, AMB[y], 0);
}
function pileCutStroke(peak) {
bot.x = peak - 50; bot.y = 170; bot.vx = bot.vy = 0;
for (let y = 223; y >= 164; y--) for (let x = peak - 100; x < peak; x++) {
if (PH[mat[y * W + x]] !== PH_POWDER) continue;
return toolVacuum(Math.min(peak - 7, x), y - 3, 6, () => true).got;
}
return 0;
}
function pileCutProfile(peak) {
let cliff = 0, previous = 0, grains = 0;
for (let x = peak - 110; x <= peak + 110; x++) {
let y = 0; while (y < 224 && PH[mat[y * W + x]] !== PH_POWDER) y++;
const height = 224 - y; cliff = Math.max(cliff, Math.abs(height - previous)); previous = height;
for (; y < 224; y++) if (PH[mat[y * W + x]] === PH_POWDER) grains++;
}
return {cliff, grains};
}