Sloped belts and filters, laid by a 45° drag (t40)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+38
-6
@@ -59,9 +59,10 @@ function entTubeFree(x, y, tubeOnly = false) {
|
||||
function entTubeMove(e, x, y, tubeOnly = false, mouth = false) {
|
||||
if (!entTubeFree(x, y, tubeOnly)) return false;
|
||||
if (mouth) {
|
||||
// Lift clear of the receiving belt before sliding over it; check both legs before moving.
|
||||
for (let yy = Math.min(e.iy, y); yy <= Math.max(e.iy, y); yy++) if (!entTubeFree(e.ix, yy)) return false;
|
||||
for (let xx = Math.min(e.ix, x); xx <= Math.max(e.ix, x); xx++) if (!entTubeFree(xx, y)) return false;
|
||||
// Go around the receiving corner, checking both legs before moving.
|
||||
const acrossY = y > e.iy ? e.iy : y, downX = y > e.iy ? x : e.ix;
|
||||
for (let yy = Math.min(e.iy, y); yy <= Math.max(e.iy, y); yy++) if (!entTubeFree(downX, yy)) return false;
|
||||
for (let xx = Math.min(e.ix, x); xx <= Math.max(e.ix, x); xx++) if (!entTubeFree(xx, acrossY)) return false;
|
||||
} else for (let yy = Math.min(e.iy, y); yy <= Math.max(e.iy, y); yy++)
|
||||
for (let xx = Math.min(e.ix, x); xx <= Math.max(e.ix, x); xx++) if (!entTubeFree(xx, yy)) return false;
|
||||
e.x = e.ix = x; e.y = e.iy = y; e.vx = e.vy = 0; return true;
|
||||
@@ -71,7 +72,7 @@ function entTubeEdge(e, dx, dy, k) {
|
||||
const x = e.ix + (dx > 0 ? BAR_W : dx < 0 ? -1 : k), y = e.iy + (dy > 0 ? BAR_H : dy < 0 ? -1 : k);
|
||||
return x < 0 || y < 0 || x >= W || y >= H ? -1 : y * W + x;
|
||||
}
|
||||
function entTubeEnter(e, dx, dy) {
|
||||
function entTubeEnter(e, dx, dy, mouth = false) {
|
||||
for (let k = 0; k < (dx ? BAR_H : BAR_W); k++) {
|
||||
const i = entTubeEdge(e, dx, dy, k);
|
||||
if (i < 0) continue;
|
||||
@@ -79,7 +80,7 @@ function entTubeEnter(e, dx, dy) {
|
||||
const p = part[i]; if (!IS_TUBE[p] || (!dx && TDX[p]) || dx * TDX[p] + dy * TDY[p] < 0) continue;
|
||||
// Vertical screws require the full width; horizontal screws use the nearest two-row lane.
|
||||
const x = (xx & ~3), y = entTubeLane(yy, e.iy);
|
||||
if (entTubeMove(e, x, TDX[p] || dy ? y : e.iy, true)) return true;
|
||||
if (entTubeMove(e, x, TDX[p] || dy ? y : e.iy, true, mouth)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -129,6 +130,37 @@ function entDiagonalTubeTick(e, p) {
|
||||
for (let yy = y; yy < y + BAR_H; yy++) for (let xx = x; xx < x + BAR_W; xx++) if (part[yy * W + xx]) return;
|
||||
if (entTubeMove(e, x, y, false, dy < 0)) { e.vx = dx * 0.5; e.vy = dy * 0.6; stats.moved++; }
|
||||
}
|
||||
// Bars stay level; their highest contact follows the face one grain per belt beat.
|
||||
function entSlopeBeltTick(e) {
|
||||
const bottom = e.iy + BAR_H;
|
||||
if (bottom >= H) return false;
|
||||
let d = 0, slope = false;
|
||||
for (let x = e.ix; x < e.ix + BAR_W; x++) {
|
||||
const i = bottom * W + x, b = (bottom >> 2) * BW + (x >> 2), c = blockP[b];
|
||||
if ((isBelt(c) || isFilter(c)) && entSolidCell(i)) {
|
||||
d = isFilter(c) ? (blockV[b] & 128 ? 1 : -1) : (blockV[b] ? 1 : -1);
|
||||
if (isSlopeBelt(c)) slope = true;
|
||||
}
|
||||
}
|
||||
if (!d) return false;
|
||||
let face = H;
|
||||
for (let x = e.ix + d; x < e.ix + d + BAR_W; x++) for (let dy = -1; dy <= 1; dy++) {
|
||||
const y = bottom + dy;
|
||||
if (x < 0 || x >= W || y < 0 || y >= H) continue;
|
||||
const b = (y >> 2) * BW + (x >> 2), c = blockP[b];
|
||||
if (!(isBelt(c) || isFilter(c)) || (isFilter(c) && filterPassAt(e.m, y * W + x))) continue;
|
||||
if (beltFaceY(c, x >> 2, y >> 2, x) !== y) continue;
|
||||
if (isSlopeBelt(c)) slope = true;
|
||||
face = Math.min(face, y);
|
||||
}
|
||||
if (!slope) return false;
|
||||
e.x = e.ix; e.y = e.iy; e.vx = e.vy = 0;
|
||||
if (tick & 1) return true;
|
||||
const y = face === H ? e.iy : face - BAR_H, x = e.ix + d;
|
||||
if (entFreeAt(x, y)) { e.vx = d * 0.5; e.vy = (y - e.iy) * 0.5; e.x = e.ix = x; e.y = e.iy = y; stats.moved++; }
|
||||
else if (!entTubeEnter(e, d, 0)) entTubeEnter(e, d, Math.sign(y - e.iy), true);
|
||||
return true;
|
||||
}
|
||||
function entTick() {
|
||||
for (let k = ents.length - 1; k >= 0; k--) {
|
||||
const e = ents[k];
|
||||
@@ -137,7 +169,7 @@ function entTick() {
|
||||
let ix = e.ix; const iy = e.iy;
|
||||
const tube = entTubeAt(ix, iy);
|
||||
if (tube) entTubeTick(e, tube);
|
||||
else {
|
||||
else if (!entSlopeBeltTick(e)) {
|
||||
// what is underneath?
|
||||
let belt = 0, bsat = 0, transport = false, support = iy + BAR_H >= H;
|
||||
if (!support) {
|
||||
|
||||
Reference in New Issue
Block a user