Screw tubes use all their lanes: grains spread sideways inside a tube
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+62
-1
@@ -37,6 +37,66 @@ rect(run, 100, 60, 103, 79, run('WATER'));
|
||||
ticks(run, 400);
|
||||
check('water runs down through an upward screw, which never pushes it back', count(run, run('WATER'), 0, 0, 319, 79) === 0, count(run, run('WATER'), 0, 0, 319, 79));
|
||||
|
||||
// Intake itself fills the far lanes first, for either tube axis.
|
||||
for (const horizontal of [false, true]) {
|
||||
fresh();
|
||||
run(`placeBlock(BP_TUBE, ${horizontal ? 1 : 0}, 25, 20, true);`);
|
||||
const filled = run(`(() => {
|
||||
const lanes = [];
|
||||
for (let k = 0; k < BS; k++) {
|
||||
tickStamp++;
|
||||
const x = ${horizontal ? 100 : 99}, y = ${horizontal ? 79 : 80};
|
||||
setCell(y*W+x, SAND, AMB[y], 0);
|
||||
tubeIntake(80*W+100, ${horizontal ? 'P_TR, 1, 0' : 'P_TU, 0, -1'});
|
||||
for (let lane = 0; lane < BS; lane++) if (mat[(80+${horizontal ? 'lane' : '0'})*W+100+${horizontal ? '0' : 'lane'}] === SAND && !lanes.includes(lane)) lanes.push(lane);
|
||||
}
|
||||
return lanes;
|
||||
})()`);
|
||||
check(horizontal ? 'a right screw takes grains from above into every row' : 'an up screw takes grains from the side into every column', filled.join() === '3,2,1,0', filled);
|
||||
}
|
||||
|
||||
// A finite heap rides into the side of a six-block lift; remove each mouth flyer once.
|
||||
const sideSeed = run('RS');
|
||||
fresh();
|
||||
run('RS = 7; for (let bx = 16; bx < 32; bx++) placeBlock(BP_BELT, 1, bx, 25, true); for (let by = 19; by <= 24; by++) placeBlock(BP_TUBE, 0, 32, by, true);');
|
||||
rect(run, 64, 40, 119, 99, run('SAND'));
|
||||
const sideLift = run(`(() => {
|
||||
let out = 0; const lanes = [0, 0, 0, 0];
|
||||
const grains = () => mat.reduce((n, m) => n + (m === SAND), 0) + flyers.filter(f => f.m === SAND).length;
|
||||
const before = grains();
|
||||
for (let k = 0; k < 3000; k++) {
|
||||
simTick();
|
||||
for (let x = 128; x < 132; x++) if (mat[88*W+x] === SAND) lanes[x-128]++;
|
||||
for (let f = flyers.length - 1; f >= 0; f--) if (flyers[f].m === SAND && flyers[f].y < 76 && flyers[f].vy < 0) { out++; flyers.splice(f, 1); }
|
||||
}
|
||||
return { out, lanes, before, after: grains() + out };
|
||||
})()`);
|
||||
console.log('Side-fed lift, 3000 ticks: ' + JSON.stringify(sideLift));
|
||||
check('a belt feeding a lift from the side fills all four lanes', sideLift.lanes.every(n => n > 0), sideLift.lanes);
|
||||
check('the side-fed lift conserves its sand, including mouth flyers', sideLift.before === sideLift.after, `${sideLift.before} -> ${sideLift.after}`);
|
||||
// Before side spreading: 1459 grains left this lift in 3000 ticks (one lane, nearly full).
|
||||
// The same belt and heap deliver 2243 into an open drop, the most the lift can be given.
|
||||
check('a side-fed lift carries at least 90% of what its belt brings (it was 65%)', sideLift.out >= Math.floor(0.9 * 2243), sideLift.out);
|
||||
|
||||
// Same belt and finite heap, with a non-blocking sink at the tube side.
|
||||
run(`RS = ${sideSeed}`);
|
||||
fresh();
|
||||
run('RS = 7; for (let bx = 16; bx < 32; bx++) placeBlock(BP_BELT, 1, bx, 25, true);');
|
||||
rect(run, 64, 40, 119, 99, run('SAND'));
|
||||
const beltDelivery = run(`(() => {
|
||||
let out = 0;
|
||||
for (let k = 0; k < 3000; k++) {
|
||||
simTick();
|
||||
for (let y = 0; y < H; y++) for (let x = 128; x < W; x++) {
|
||||
const i = y*W+x;
|
||||
if (mat[i] === SAND) { out++; setCell(i, EMPTY, AMB[y], 0); }
|
||||
}
|
||||
for (let f = flyers.length - 1; f >= 0; f--) if (flyers[f].m === SAND && flyers[f].x >= 128) { out++; flyers.splice(f, 1); }
|
||||
}
|
||||
return out;
|
||||
})()`);
|
||||
console.log('Belt delivery to a non-blocking sink, 3000 ticks: ' + beltDelivery);
|
||||
|
||||
// --- throughput
|
||||
fresh();
|
||||
run('for (let bx = 20; bx < 30; bx++) placeBlock(BP_TUBE, 1, bx, 20, true);');
|
||||
@@ -44,6 +104,7 @@ run('for (let y = 0; y < 80; y++) { setCell(y*W+79, STONE, AMB[y], 0); setCell(y
|
||||
rect(run, 80, 0, 95, 79, run('SAND'));
|
||||
ticks(run, 60);
|
||||
const lanes = run('(() => { const s = new Set(); for (let y = 80; y < 84; y++) for (let x = 100; x < 120; x++) if (mat[y*W+x] === SAND) s.add(y); return s.size; })()');
|
||||
check('a sideways tube fed from above (its side) fills more than one row', lanes > 1, lanes);
|
||||
check('a sideways tube fed from a hopper runs full, all four grains wide', lanes === 4, lanes);
|
||||
fresh();
|
||||
run('for (let bx = 20; bx < 30; bx++) placeBlock(BP_TUBE, 1, bx, 20, true);');
|
||||
@@ -174,7 +235,7 @@ run(`globalThis.__carry = carryColumn;
|
||||
for (const lift of [true, false]) {
|
||||
fresh();
|
||||
run('RS = 7; __shear = 0; for (let bx = 20; bx < 32; bx++) placeBlock(BP_BELT, 1, bx, 25, true);');
|
||||
if (lift) run('for (let by = 15; by <= 25; by++) placeBlock(BP_TUBE, 0, 32, by, true);');
|
||||
if (lift) run('for (let by = 15; by <= 24; by++) placeBlock(BP_TUBE, 0, 32, by, true);');
|
||||
else run('for (let by = 10; by <= 25; by++) placeBlock(BP_WALL, RSTONE, 32, by, true);');
|
||||
rect(run, 88, 94, 119, 99, run('SAND'));
|
||||
rect(run, 88, 70, 119, 93, run('CUORE'));
|
||||
|
||||
Reference in New Issue
Block a user