Sloped belts and filters drawn as one belt turned to 45° (t40)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
// Drawing geometry against real parts, without changing transport.
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { load, suite, flatWorld } = require('./harness');
|
||||
const { run } = load();
|
||||
const { check, done } = suite();
|
||||
run(fs.readFileSync(path.join(__dirname, '../src/render/slope-belts.js'), 'utf8'));
|
||||
flatWorld(run, 160, 120, 112);
|
||||
for (const code of ['BP_BELT_UP', 'BP_BELT_DOWN', 'BP_FILTER_UP', 'BP_FILTER_DOWN']) {
|
||||
run(`
|
||||
mat.fill(EMPTY); part.fill(0); blockP.fill(0); blockV.fill(0);
|
||||
var artCode = ${code}, artGrade = beltGrade(artCode), artB = 12 * BW + 12;
|
||||
for (let k = -2; k <= 2; k++) placeBlock(artCode, 1, 12 + k, 12 + artGrade * k, true);
|
||||
prepareSlopeBelts(0, 0, W, H);
|
||||
`);
|
||||
check(`${code}: diagonal neighbours continue the band`, run('(slopeBeltJoins[artB] & 12) === 12'));
|
||||
check(`${code}: corner seals use the same band`, run(`(() => {
|
||||
const i = slopeSeal(artCode, 12, 12);
|
||||
return i < 0 || slopeBeltAt(i, i % W, (i / W) | 0) >= 0;
|
||||
})()`));
|
||||
check(`${code}: band is as thick as a flat belt`, run(`(() => {
|
||||
const g = artGrade, x = 50 - g * 1.85 * Math.SQRT1_2, y = 50 + 1.85 * Math.SQRT1_2;
|
||||
return slopeBeltShape(x, y, artB) < -1.8 &&
|
||||
slopeBeltShape(x - g * 1.7 * Math.SQRT1_2, y + 1.7 * Math.SQRT1_2, artB) < 0 &&
|
||||
slopeBeltShape(x - g * 2.1 * Math.SQRT1_2, y + 2.1 * Math.SQRT1_2, artB) > 0;
|
||||
})()`));
|
||||
check(`${code}: air below the triangle gets the continuous band`, run(`(() => {
|
||||
for (let y = 48; y < 57; y++) for (let x = 48; x < 56; x++) {
|
||||
const i = y * W + x, own = (y >> 2) * BW + (x >> 2);
|
||||
if (!blockP[own] && mat[i] === EMPTY && slopeBeltAt(i, x, y) >= 0) return true;
|
||||
}
|
||||
return false;
|
||||
})()`));
|
||||
run(`
|
||||
for (let end = 0; end < 2; end++) {
|
||||
const side = end ? 1 : -1;
|
||||
removeBlock(12 + side, 12 + side * artGrade, true);
|
||||
placeBlock(BP_BELT, 1, 12 + side, 12 + (end ? artGrade > 0 : artGrade < 0), true);
|
||||
}
|
||||
prepareSlopeBelts(0, 0, W, H);
|
||||
`);
|
||||
check(`${code}: both flat joints form elbows`, run('(slopeBeltJoins[artB] & 3) === 3'));
|
||||
check(`${code}: adjoining flats do not round off at the joint`, run(`(() => {
|
||||
const l = (12 + (artGrade < 0)) * BW + 11, r = (12 + (artGrade > 0)) * BW + 13;
|
||||
return !(flatBeltCaps(l) & 2) && !(flatBeltCaps(r) & 1);
|
||||
})()`));
|
||||
check(`${code}: overhang never covers terrain, parts, machines or bars`, run(`(() => {
|
||||
for (let y = 48; y < 57; y++) for (let x = 48; x < 56; x++) {
|
||||
const i = y * W + x, own = (y >> 2) * BW + (x >> 2);
|
||||
if (blockP[own] || mat[i] !== EMPTY || slopeBeltAt(i, x, y) < 0) continue;
|
||||
mat[i] = STONE; const ground = slopeBeltAt(i, x, y); mat[i] = EMPTY;
|
||||
part[i] = P_GRATE; const built = slopeBeltAt(i, x, y); part[i] = 0;
|
||||
mach[i] = 1; const machine = slopeBeltAt(i, x, y); mach[i] = 0;
|
||||
occ[i] = 1; const bar = slopeBeltAt(i, x, y); occ[i] = 0;
|
||||
return ground < 0 && built < 0 && machine < 0 && bar < 0;
|
||||
}
|
||||
return false;
|
||||
})()`));
|
||||
}
|
||||
check('free end rounds its corners and stops at the end', run(`(() => {
|
||||
const b = artB, x = 48 - Math.SQRT2, y = 48 + Math.SQRT2;
|
||||
blockP[b] = BP_BELT_DOWN;
|
||||
return slopeBeltShape(x + 0.8, y + 0.8, b, 0) < 0 && slopeBeltShape(x - 1, y - 1, b, 0) > 0;
|
||||
})()`));
|
||||
check('flat belts still meet diagonal tube elbows without an end cap', run(`(() => {
|
||||
blockP[artB - 1] = BP_BELT;
|
||||
blockP[artB] = BP_TUBE; blockV[artB] = 4;
|
||||
const joined = !(flatBeltCaps(artB - 1) & 2);
|
||||
blockP[artB] = BP_BELT_DOWN;
|
||||
return joined;
|
||||
})()`));
|
||||
check('unpowered rollers and studs stand still', run(`(() => {
|
||||
slopeBeltJoins[artB] &= ~16;
|
||||
for (let y = 48; y < 56; y++) for (let x = 48; x < 56; x++)
|
||||
if (slopeBeltColor(artB, x, y, 0, 150, 170, 190) !== slopeBeltColor(artB, x, y, 20, 150, 170, 190)) return false;
|
||||
return true;
|
||||
})()`));
|
||||
check('powered rollers and studs reverse with the belt', run(`(() => {
|
||||
slopeBeltJoins[artB] |= 16;
|
||||
let moves = false;
|
||||
for (let y = 48; y < 56; y++) for (let x = 48; x < 56; x++) {
|
||||
blockV[artB] = 1;
|
||||
const a = slopeBeltColor(artB, x, y, 12, 150, 170, 190), stopped = slopeBeltColor(artB, x, y, 0, 150, 170, 190);
|
||||
blockV[artB] = 0;
|
||||
if (a !== slopeBeltColor(artB, x, y, -12, 150, 170, 190)) return false;
|
||||
if (a !== stopped) moves = true;
|
||||
}
|
||||
return moves;
|
||||
})()`));
|
||||
check('drawing leaves the seed, cells and saved block data unchanged', run(`(() => {
|
||||
const snapshot = () => JSON.stringify([RS, Array.from(mat), Array.from(part), Array.from(blockP), Array.from(blockV)]);
|
||||
const before = snapshot();
|
||||
prepareSlopeBelts(0, 0, W, H);
|
||||
for (let y = 40; y < 64; y++) for (let x = 40; x < 72; x++) {
|
||||
const b = slopeBeltAt(y * W + x, x, y);
|
||||
if (b >= 0) slopeBeltColor(b, x, y, 12, 150, 170, 190);
|
||||
}
|
||||
return snapshot() === before;
|
||||
})()`));
|
||||
done();
|
||||
@@ -138,7 +138,9 @@ fresh();
|
||||
run('placeBlock(BP_BELT_UP,1,20,32,true);for(let l=1;l<=CARRY_DEPTH;l++)setCell((131-l)*W+80,SAND,20,0);tickStamp++;carryColumn(130*W+80,1,null);');
|
||||
check('a slope carries the same full 96-grain column as a flat belt',run('Array.from({length:CARRY_DEPTH},(_,k)=>mat[(129-k)*W+81]===SAND).every(Boolean)'));
|
||||
run(fs.readFileSync('src/render/slope-belts.js','utf8'));
|
||||
check('sloped stripes vary along the face and travel with the motor',run('(()=>{const b=32*BW+20,c=(x,y,t)=>slopeBeltColor(b,x,y,t,0,0,0);return c(80,131,0)!==c(82,129,0) && c(80,131,0)===c(82,129,4);})()'));
|
||||
// The renderer prepares joins and power first; stripe pitch is measured along the rotated band.
|
||||
run('prepareSlopeBelts(0,0,W,H);');
|
||||
check('sloped stripes vary along the face and travel with the motor',run('(()=>{const b=32*BW+20,c=(x,y,t)=>slopeBeltColor(b,x,y,t,0,0,0);return c(81,130,0)!==c(82,129,0) && c(81,130,0)===c(82,129,4);})()'));
|
||||
run(fs.readFileSync('src/ui/selection.js','utf8'));
|
||||
run(fs.readFileSync('src/ui/actions.js','utf8'));
|
||||
run("globalThis.GAME={pieceDir:{belt:1,filter:1},filterCfg:{m:[SAND],inv:0},wallMat:RSTONE};globalThis.hudDirty=false;globalThis.aimBlock=()=>({bx:25,by:15});globalThis.toolId=()=>'build';globalThis.playSfx=()=>{};");
|
||||
|
||||
Reference in New Issue
Block a user