Files
44r0n7andClaude Opus 5.5 b270c4e818 Deepgrain Foundry: move from a claude.ai artifact to a local repository
The game as of artifact version 24, ready for local development with
coding agents.

- Source split from three large files into 52 small ones under src/sim,
  src/render and src/ui, joined in the order in src/manifest.json by
  build.py. The joined code is unchanged apart from comments; every
  headless suite gives the same output, and screenshots in both looks
  are pixel-identical to before.
- Light tidying with no change in behaviour: one movement scan loop,
  shared hazard-stripe and belt shader helpers, unused code removed, a
  shared check helper for the test suites.
- World files can be exported as an ordinary download outside claude.ai.
- Tests: broken old scripts removed, experiments moved to tools/,
  test/run_all.py added. Tools: shot.py (repeatable screenshots),
  where.py, map.py.
- Docs: AGENTS.md, CLAUDE.md, NOTES.md (the owner's to-do inbox),
  docs/PROJECT_MAP.md, DESIGN.md, TESTING.md, systems notes, the
  owner's requests and an agent log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K9kLmYADKSEjuwUN3rFxDA
2026-10-23 16:05:31 -04:00

49 lines
3.3 KiB
JavaScript

// Furnace scenarios on a flat test world: builds a chamber, charges it with ore and coal, lights it
// and prints temperatures, burning cells and what has melted or set at intervals.
const { load, flatWorld, rect, count, maxTemp, ticks } = require('../../test/harness');
const { run } = load();
const C = n => run(n);
function report(t, region) {
const [x0, y0, x1, y1] = region;
const burning = run(`(()=>{let n=0;for(let y=${y0};y<=${y1};y++)for(let x=${x0};x<=${x1};x++)if(flags[y*W+x]&F_BURN)n++;return n})()`);
const oreT = run(`(()=>{let s=0,n=0;for(let y=${y0};y<=${y1};y++)for(let x=${x0};x<=${x1};x++)if(mat[y*W+x]===CUORE||mat[y*W+x]===FEORE){s+=temp[y*W+x];n++;}return n?Math.round(s/n):0})()`);
const airT = run(`(()=>{let s=0,n=0;for(let y=${y0};y<=${y1};y++)for(let x=${x0};x<=${x1};x++)if(mat[y*W+x]===EMPTY){s+=temp[y*W+x];n++;}return n?Math.round(s/n):0})()`);
console.log(`t=${String(t).padStart(5)} maxT=${String(maxTemp(run, x0, y0, x1, y1)).padStart(5)} oreT=${String(oreT).padStart(5)} airT=${String(airT).padStart(4)} burn=${String(burning).padStart(3)} coal=${count(run, C('COAL'), x0, y0, x1, y1)} cuOre=${count(run, C('CUORE'), x0, y0, x1, y1)} feOre=${count(run, C('FEORE'), x0, y0, x1, y1)} mCu=${count(run, C('MCU'), x0, y0, x1, y1)} Cu=${count(run, C('COPPER'), x0, y0, x1, y1)} mFe=${count(run, C('MFE'), x0, y0, x1, y1)} Fe=${count(run, C('IRON'), x0, y0, x1, y1)} slag=${count(run, C('SLAG'), x0, y0, x1, y1)} ash=${count(run, C('ASH'), x0, y0, x1, y1)} magma=${count(run, C('MAGMA'), x0, y0, x1, y1)} brick=${count(run, C('BRICK'), x0, y0, x1, y1)} smoke=${count(run, C('SMOKE'), x0, 0, x1, y1)}`);
}
function scenario(name, build, total, every, region) {
flatWorld(run, 200, 140, 90);
build();
console.log(`\n=== ${name} ===`);
for (let t = 0; t <= total; t += every) { if (t) ticks(run, every); report(t, region); }
}
function ignite(x, y, n = 40) { run(`for (let k=0;k<${n};k++){ toolIgnite(${x},${y}); simTick(); }`); }
// mixed charge: coal with ore grains sprinkled through it
function charge(x0, y0, x1, y1, ore, frac) {
run(`{ let r=mulberry32(5); for (let y=${y0};y<=${y1};y++) for (let x=${x0};x<=${x1};x++) setCell(y*W+x, r()<${frac} ? ${ore} : COAL, AMB[y], 0); }`);
}
function furnace(x0, y0, x1, y1, wall, thick, vent) {
rect(run, x0, y0, x0 + thick - 1, y1, wall); rect(run, x1 - thick + 1, y0, x1, y1, wall);
rect(run, x0, y0, x1, y0 + thick - 1, wall);
const cx = (x0 + x1) >> 1;
run(`for (let y=${y0};y<${y0 + thick};y++) for (let x=${cx - (vent >> 1)};x<${cx - (vent >> 1) + vent};x++) setCell(y*W+x, EMPTY, AMB[y], 0)`);
}
const which = process.argv[2] || 'all';
if (which === 'all' || which === 'open') scenario('Open mixed pile (coal + 30% copper ore)', () => {
charge(80, 80, 103, 89, C('CUORE'), 0.3);
ignite(85, 79); ignite(98, 79);
}, 3600, 600, [70, 60, 113, 89]);
if (which === 'all' || which === 'stone') scenario('Stone furnace, mixed charge, 2-wide vent', () => {
furnace(77, 66, 106, 89, C('STONE'), 2, 2);
charge(79, 76, 104, 89, C('CUORE'), 0.3);
ignite(84, 75); ignite(99, 75);
}, 4800, 600, [77, 64, 106, 89]);
if (which === 'all' || which === 'clay') scenario('Clay furnace, mixed charge (walls fire to brick)', () => {
furnace(77, 66, 106, 89, C('CLAY'), 2, 2);
charge(79, 76, 104, 89, C('CUORE'), 0.3);
ignite(84, 75); ignite(99, 75);
}, 4800, 600, [77, 64, 106, 89]);