// Tall loose faces release together; supported heaps stop moving, including when revisited. const {load, suite, flatWorld} = require('./harness'); const {createHash} = require('node:crypto'); const {run} = load(); const {check, done} = suite(); function wall(material, offset = 0) { flatWorld(run, 192, 600, 96); run(`RS=123; worldSeed=7; bot.x=500; bot.y=40; for(let y=56;y<96;y++)for(let x=${80+offset};x<${100+offset};x++)setCell(y*W+x,${material},20,0);`); } function motion(n, revisit = false) { run(`for(let k=0;k<${n};k++) { tick++;tickStamp=tickStamp%255+1; if (${revisit}) awake.fill(3); simMove(); for(let c=0;c{const h=[];let n=0,top=96; for(let x=0;x createHash('sha256').update(run('mat')).digest('hex'); const rubble = '[RSTONE,CUORE,FEORE,LDIRT][(x+y)%4]'; let sandHeight; for(const [name, material] of [['sand','SAND'],['mixed rubble',rubble],['rubble with clay',`(x+y)%5===0?LCLAY:${rubble}`],['clay','LCLAY']]) { for(const offset of [0,17]) { wall(material,offset); const maxCliff = name==='clay' ? 3 : 2; let slopedAt=0; for(let k=1;k<=180;k++) {motion(1);if(profile().cliff<=maxCliff&&!slopedAt)slopedAt=k;} const p=profile(); check(`${name} face slumps within 180 ticks (offset ${offset})`,slopedAt>0&&p.cliff<=maxCliff&&p.n===800,JSON.stringify({slopedAt,...p})); motion(1200,true); if(name==='sand'&&offset===0)sandHeight=profile().height; if(name==='clay'&&offset===0)check('sticky clay holds a steeper settled heap than sand',profile().height>sandHeight,`sand ${sandHeight}, clay ${profile().height}`); const settled=hash(); // Force visits so sleeping cannot hide continued creeping. motion(600,true);motion(3); check(`${name} settled heap stays put and sleeps (offset ${offset})`,hash()===settled&&run('awake.every(v=>v===0)')&&profile().n===800); } } done();