Sloped belts hold their load with moving cleats (t42); sloped filters are downhill shaking screens (t43)
The magic grip is gone: cleats every 8 face cells, 6 grains tall, carry pockets uphill (about 71 grains/s against 90 flat) and overflow rolls back. Sloped filters always run downhill; grains travel by gravity and a shake, and sorting stays exact. Drawing needs another pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
// Many loaded slopes, with a fresh deterministic world for each timing sample.
|
||||
const { performance } = require('perf_hooks');
|
||||
const { load, flatWorld } = require(process.env.DG_HARNESS || '../../test/harness');
|
||||
const { run } = load();
|
||||
const assert = require('node:assert/strict');
|
||||
const samples=[];
|
||||
for(let sample=0;sample<6;sample++) {
|
||||
flatWorld(run,1024,512,496);
|
||||
run(`RS=7;money=1e9;AMB.fill(20);temp.fill(20);hot.fill(0);
|
||||
for(let row=0;row<6;row++)for(let col=0;col<8;col++)for(let k=0;k<12;k++){
|
||||
const bx=col*30+4+k,by=row*18+35-k;
|
||||
placeBlock(BP_BELT_UP,1,bx,by,true);
|
||||
for(let x=bx*4;x<bx*4+4;x++){const y=beltFaceY(BP_BELT_UP,bx,by,x);for(let h=1;h<=4;h++)setCell((y-h)*W+x,SAND,20,0);}
|
||||
}
|
||||
for(let k=0;k<60;k++)simTick();`);
|
||||
const start=performance.now();run('for(let k=0;k<240;k++)simTick();');
|
||||
if(sample) samples.push((performance.now()-start)/240);
|
||||
}
|
||||
assert(samples.length===5 && samples.every(n=>Number.isFinite(n) && n>0));
|
||||
samples.sort((a,b)=>a-b);
|
||||
console.log(`576 loaded slope blocks, median ${samples[2].toFixed(3)} ms/tick; samples ${samples.map(v=>v.toFixed(3)).join(', ')}`);
|
||||
|
||||
// No slopes: isolate the extra guards in the shared powder hot loop.
|
||||
flatWorld(run,512,384,376);
|
||||
run('RS=7;for(let y=32;y<350;y+=2)for(let x=32;x<480;x++){mat[y*W+x]=SAND;mat[(y+1)*W+x]=STONE;}');
|
||||
const powderSamples=[];
|
||||
for(let sample=0;sample<6;sample++) {
|
||||
const start=performance.now();
|
||||
run('for(let k=0;k<30;k++)for(let y=32;y<350;y+=2)for(let x=32;x<480;x++)powder(y*W+x,x,y,SAND);');
|
||||
if(sample)powderSamples.push(performance.now()-start);
|
||||
}
|
||||
assert(powderSamples.length===5 && powderSamples.every(n=>Number.isFinite(n) && n>0));
|
||||
powderSamples.sort((a,b)=>a-b);
|
||||
console.log(`2.14M powder calls without cleats, median ${powderSamples[2].toFixed(2)} ms`);
|
||||
@@ -0,0 +1,29 @@
|
||||
// Reproducible generous-feed throughput and settled pile angles for t42.
|
||||
const { load, flatWorld } = require(process.env.DG_HARNESS || '../../test/harness');
|
||||
const { run } = load();
|
||||
const assert = require('node:assert/strict');
|
||||
for (const material of ['SAND','GRAVEL','CUORE','COAL']) {
|
||||
const rates=[];
|
||||
for (const grade of [0,-1]) {
|
||||
flatWorld(run,256,224,208);
|
||||
run(`RS=7;money=1e6;AMB.fill(20);temp.fill(20);hot.fill(0);
|
||||
for(let k=0;k<10;k++)placeBlock(${grade?'BP_BELT_UP':'BP_BELT'},1,16+k,${grade?32:24}+k*${grade},true);
|
||||
for(let x=10;x<16;x++)placeBlock(BP_BELT,1,x,${grade?33:24},true);
|
||||
for(let x=26;x<32;x++)placeBlock(BP_BELT,1,x,${grade?23:24},true);`);
|
||||
const result=run(`(()=>{let out=0;for(let k=0;k<1420;k++){
|
||||
for(let l=1;l<=4;l++){const i=(${grade?132:96}-l)*W+44;if(mat[i]===EMPTY)setCell(i,${material},20,0);}
|
||||
simTick();
|
||||
for(let i=0;i<N;i++)if(mat[i]===${material} && i%W>=128){if(k>=220)out++;setCell(i,EMPTY,20,0);}
|
||||
for(let j=flyers.length-1;j>=0;j--)if(flyers[j].m===${material} && flyers[j].x>=128){if(k>=220)out++;flyers.splice(j,1);}
|
||||
}return out/20;})()`);
|
||||
rates.push(result);
|
||||
}
|
||||
flatWorld(run,256,224,208);
|
||||
run(`RS=7;AMB.fill(20);temp.fill(20);hot.fill(0);
|
||||
for(let y=120;y<160;y++)for(let x=118;x<138;x++)setCell(y*W+x,${material},20,0);
|
||||
for(let k=0;k<1200;k++)simTick();`);
|
||||
// Apparent settled angle: heap height divided by half its footprint width.
|
||||
const angle=run(`(()=>{let top=H,left=W,right=0;for(let i=0;i<N;i++)if(mat[i]===${material}){top=Math.min(top,(i/W)|0);left=Math.min(left,i%W);right=Math.max(right,i%W);}return Math.atan2(208-top,(right-left+1)/2)*180/Math.PI;})()`);
|
||||
assert(rates[1]>=60 && rates[1]<=rates[0]*1.1, `${material} slope rate outside the target`);
|
||||
console.log(`${material}: flat ${rates[0].toFixed(1)}, uphill ${rates[1].toFixed(1)} grains/s; pile angle ${angle.toFixed(1)} degrees`);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Loaded sidewall conveyor and screen. Use --js 'slopeScene(false)' (belt) or 'slopeScene(true)' (screen).
|
||||
globalThis.slopeScene = function(screen = false) {
|
||||
const bx = Math.floor((SX - 100) / BS), by = Math.floor((SY + 12) / BS);
|
||||
const left = (bx - 12) * BS, right = (bx + 24) * BS;
|
||||
for(let y=by*BS-64;y<by*BS+64;y++)for(let x=left;x<right;x++) {
|
||||
const i=y*W+x;bgm[i]=0;setCell(i,y>=by*BS+56?STONE:EMPTY,20,0);
|
||||
}
|
||||
for(let x=left;x<right;x++){surfY[x]=by*BS+56;dirtY[x]=by*BS+64;}
|
||||
money=1e6;weather.next=1e15;
|
||||
const startY=screen?by-8:by, grade=screen?1:-1;
|
||||
for(let k=0;k<8;k++)placeBlock(screen?BP_FILTER_DOWN:BP_BELT_UP,screen?128:1,bx+k,startY+grade*k,true,{m:[SAND],inv:0});
|
||||
const inlet=startY+(screen?0:1),outlet=startY+grade*7+(screen?1:0);
|
||||
for(let k=1;k<=5;k++)placeBlock(BP_BELT,1,bx-k,inlet,true);
|
||||
for(let k=8;k<13;k++)placeBlock(BP_BELT,1,bx+k,outlet,true);
|
||||
for(let t=0;t<300;t++) {
|
||||
for(let h=1;h<=4;h++){const i=(inlet*BS-h)*W+(bx-4)*BS;if(mat[i]===EMPTY)setCell(i,screen && (t&2)?GRAVEL:SAND,20,0);}
|
||||
simTick();
|
||||
}
|
||||
// Keep loose rejects and passing grains visible underneath the screen.
|
||||
CAM=[(bx+3)*BS,(startY+grade*4)*BS+4];updateRoof();
|
||||
}
|
||||
Reference in New Issue
Block a user