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
57 lines
2.3 KiB
Python
57 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Build Deepgrain Foundry into one self-contained HTML file.
|
|
|
|
The source files listed in src/manifest.json are joined in order (sim first, then the browser
|
|
code) into one classic script, so they share one global scope and 'use strict' at the top of
|
|
src/sim/base.js applies to all of it. No bundler, no dependencies.
|
|
|
|
Writes:
|
|
dist/index.html the full page: open it, or serve dist/ with python -m http.server
|
|
dist/deepgrain-foundry.html the same without <!doctype>/<head>/<body>, for hosts (like a
|
|
claude.ai artifact) that wrap the page themselves
|
|
dist/bundle-lines.json where each source file starts in dist/index.html, so a line number
|
|
from a browser error can be traced back: python3 tools/where.py LINE
|
|
"""
|
|
import json, pathlib
|
|
|
|
root = pathlib.Path(__file__).resolve().parent
|
|
src = root / 'src'
|
|
dist = root / 'dist'
|
|
man = json.loads((src / 'manifest.json').read_text())
|
|
|
|
|
|
def join(files):
|
|
"""Join files with one newline between them; return the text and [first line, file] pairs."""
|
|
parts, starts, line = [], [], 1
|
|
for f in files:
|
|
text = (src / f).read_text().rstrip('\n')
|
|
starts.append([line, f])
|
|
parts.append(text)
|
|
line += text.count('\n') + 1
|
|
return '\n'.join(parts), starts
|
|
|
|
|
|
def main():
|
|
shell = (src / man['shell']).read_text()
|
|
css, _ = join(man['css'])
|
|
js, starts = join(man['sim'] + man['client'])
|
|
head, tail = shell.split('//__JS__')
|
|
body = head.replace('/*__CSS__*/', css)
|
|
page = body + js + tail
|
|
pre = ('<!doctype html><html><head><meta charset="utf-8">'
|
|
'<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">'
|
|
'</head><body>')
|
|
full = pre + page + '</body></html>\n'
|
|
dist.mkdir(exist_ok=True)
|
|
(dist / 'deepgrain-foundry.html').write_text(page)
|
|
(dist / 'index.html').write_text(full)
|
|
# the script starts on this line of index.html (the doctype prefix has no newlines)
|
|
js_line = body.count('\n') + 1
|
|
(dist / 'bundle-lines.json').write_text(json.dumps(
|
|
{'page': 'dist/index.html', 'files': [[js_line + s - 1, f] for s, f in starts]}, indent=1) + '\n')
|
|
print(f'built dist/index.html ({len(full):,} bytes, {len(starts)} source files)')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|