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
This commit is contained in:
2026-10-23 16:05:31 -04:00
co-authored by Claude Opus 5.5
commit b270c4e818
97 changed files with 11710 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
// Milestone checks (the ledger) and the sky roof line used for cooling.
// ---------- Ledger ----------
function checkLedger() {
const done = id => ledger[id];
const mark = id => { if (!ledger[id]) { ledger[id] = tick || 1; emit({ t: 'milestone', id }); } };
if (stats.dug >= 15) mark('dig');
if (seen[FIRE]) { mark('fire'); if (!player.lens) { player.lens = true; } }
if (seen[BRICK] || seen[RBRICK]) mark('brick');
if (seen[CHARCOAL]) mark('charcoal');
if (stats.grown > 0) mark('grow');
if (seen[MCU]) mark('copper');
if (stats.bars > 0) mark('bars');
if (player.bitTier >= 1) mark('bit1');
let anyPower = false, steamOn = false;
for (const mm of machines) if (mm) { if ((mm.type === 'wheel' || mm.type === 'engine') && mm.out > 0.5) anyPower = true; if (mm.type === 'engine' && mm.out > 1) steamOn = true; }
if (anyPower && !POWER_FREE) mark('power');
if (stats.moved >= 300) mark('auto');
if (seen[MGL] || seen[GLASS] || seen[CULLET]) { mark('glass'); player.flask = true; }
if (steamOn && !POWER_FREE) mark('steam');
if (seen[MFE]) mark('iron');
if (player.bitTier >= 2) mark('bit2');
if (seen[MST]) mark('steel');
if (player.bitTier >= 3) mark('bit3');
if (player.tankTier >= 1) mark('tank');
if (depthU(bot.y) > 0.85) mark('deep');
if (stats.sold > 0) mark('sale');
if (ordersDone > 0) mark('order');
if (seen[MBZ] || seen[MBS]) mark('alloy');
if (seen[AGORE] || seen[AUORE] || seen[SILVER] || seen[GOLD]) mark('precious');
if (debt <= 0) mark('claim');
if (earned >= 50000) mark('rich1');
if (earned >= 200000) mark('rich2');
void done;
}
// Topmost non-air cell of each column: air above it can shed heat to the sky.
function updateRoof() {
for (let x = 0; x < W; x++) {
let y = 0;
for (; y < H; y++) { const ph = PH[mat[y * W + x]]; if (ph === PH_SOLID || ph === PH_POWDER || ph === PH_LIQUID) break; }
roofY[x] = y;
}
}