// Plays a starter design the way a player would: paste the blueprint, let the // bot build it from the bag, blow an even ore/coal mix inside, light it, wait, // knock out the castings. Usage: node tools/experiments/starter.js [design id] [ore] [coal] const { load, flatWorld, ticks } = require('../../test/harness'); const { run } = load(); const id = process.argv[2] || 'smelter1', ore = +(process.argv[3] || 40), coal = +(process.argv[4] || 40); flatWorld(run, 240, 160, 100); for (let k = 0; k < +(process.argv[5] || 0); k++) run('rnd()'); // shake the dice: how robust is the design? run(`bag[RSTONE] = 900; bag[LCLAY] = 200; bag[COAL] = ${coal}; bag[CUORE] = ${ore}; bagTotal = 0; for (let k = 0; k < NMAT; k++) bagTotal += bag[k];`); const d = run(`JSON.stringify(STARTER_DESIGNS.find(d => d.id === '${id}').bp())`); const bp = JSON.parse(d); // sit it on the ground: bottom row at block 24 (ground starts at block 25) const ox = 24, oy = 25 - bp.bh; run(`bot.x = ${ox * 4 + bp.bw * 2 - 2}; bot.y = ${oy * 4 - 14}; pasteGhost(${d}, ${ox}, ${oy});`); for (let k = 0; k < 40 && run('ghostBlocks.size + ghostMolds.length') > 0; k++) ticks(run, 30); console.log(id, `${bp.bw}x${bp.bh} blocks;`, 'ghosts left', run('ghostBlocks.size + ghostMolds.length'), 'molds', run('molds.length'), 'stone used', 900 - run('bag[RSTONE]'), 'clay used', 200 - run('bag[LCLAY]')); // fly inside (the bot passes through walls) and blow the mix across the chamber floor const cx0 = (ox + 1) * 4, cx1 = (ox + bp.bw - 1) * 4 - 1, floorY = (oy + 4) * 4 - 1; run(`bot.x = ${(cx0 + cx1) / 2 - 2}; bot.y = ${oy * 4};`); run(`GCOL = [CUORE, COAL];`); for (let k = 0; k < 400 && run('bag[CUORE] + bag[COAL]') > 0; k++) { const tx = cx0 + 1 + (k * 5) % (cx1 - cx0 - 2); run(`toolBlow(${tx}, ${floorY - 1}, 0, CUORE, GCOL); simTick();`); } ticks(run, 60); const inside = run(`(()=>{let o=0,c=0;for(let y=${oy * 4};y<=${floorY};y++)for(let x=${cx0};x<=${cx1};x++){const m=mat[y*W+x];if(m===CUORE)o++;else if(m===COAL)c++;}return [o,c]})()`); console.log('charge inside', inside, 'left in bag', run('[bag[CUORE], bag[COAL]]')); // light the top of the pile from inside, then leave // like a player: hold the igniter on a few coal grains that touch air const spots = run(`(()=>{const out=[];for(let y=${oy * 4 + 4};y<=${floorY};y++)for(let x=${cx0};x<=${cx1};x++){const i=y*W+x;if(mat[i]===COAL&&mat[i-W]===EMPTY)out.push([x,y]);}return out})()`); const pick = [spots[0], spots[Math.floor(spots.length / 2)], spots[spots.length - 1]].filter(Boolean); run(`for (let k=0;k<50;k++){ ${pick.map(([x, y]) => `toolIgnite(${x}, ${y});`).join('')} simTick(); }`); run(`bot.x = ${ox * 4 - 30}; bot.y = ${oy * 4 - 20};`); let t = 0; for (const dt of [900, 900, 1800, 1800]) { ticks(run, dt); t += dt; console.log(`${t / 60}s`, run(`JSON.stringify(molds.map(m => m.state + (m.ready.length ? ':' + m.ready.length : '') + (m.flaw ? ':' + m.flaw : '')))`), 'ore left', run(`(()=>{let n=0;for(let i=0;i{let n=0;const cav=new Set(molds.flatMap(m=>m.cavs.flat()));for(let i=0;i{let n=0;for(const i of molds.flatMap(m=>m.cavs.flat()))if(mat[i]===COPPER||mat[i]===MCU)n++;return n})()`), 'slag', run(`(()=>{let n=0;for(let i=0;i{let n=0;for(let i=0;i{const out=[];for (let y = ${oy * 4 - 2}; y < ${(oy + bp.bh) * 4 + 2}; y++) { const r = []; for (let x = ${ox * 4 - 2}; x < ${(ox + bp.bw) * 4 + 2}; x++) { const i = y * W + x; r.push([mat[i], part[i], Math.round(temp[i])]); } out.push(r); } return out; })()`); for (const r of rows) console.log(r.map(([m, p]) => p === 5 && m === 0 ? '+' : p === 5 ? (ch[m] || '?').toUpperCase() : (ch[m] || '?')).join('')); } if (process.env.DUMP) dump('before knocking out'); const msgs = run(`JSON.stringify(molds.map(m => collectMold(m)))`); console.log('knock out:', msgs, '| bars on the ground', run('ents.length'), '| bit tier', run('player.bitTier'));