Compare commits
3 Commits
fix/192-re
...
sprint/iss
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d961aca53 | ||
| d5645fea58 | |||
|
|
db08f9a478 |
16
GENOME.md
16
GENOME.md
@@ -8,24 +8,32 @@ The Beacon is a browser-based idle/incremental game inspired by Universal Paperc
|
||||
|
||||
Static HTML/JS — no build step, no dependencies, no framework. Open `index.html` in any browser.
|
||||
|
||||
**5,128 lines of JavaScript** across 10 files. **1 HTML file** with embedded CSS (~300 lines). **1 Python test file** for reckoning projects.
|
||||
**6,033 lines of JavaScript** across 11 files. **1 HTML file** with embedded CSS (~300 lines). **3 test files** (2 Node.js, 1 Python).
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
index.html (UI + embedded CSS)
|
||||
index.html (UI + embedded CSS + inline JS ~5000L)
|
||||
|
|
||||
+-- js/engine.js (1590L) Core game loop, tick, resources, buildings, projects, events
|
||||
+-- js/data.js (944L) Building definitions, project trees, event tables, phase data
|
||||
+-- js/render.js (390L) DOM rendering, UI updates, resource displays
|
||||
+-- js/combat.js (359L) Boss encounters, combat mechanics
|
||||
+-- js/combat.js (359L) Canvas boid-flocking combat visualization
|
||||
+-- js/sound.js (401L) Web Audio API ambient drone, phase-aware sound
|
||||
+-- js/dismantle.js (570L) The Dismantle sequence (late-game narrative)
|
||||
+-- js/main.js (223L) Initialization, game loop start, auto-save, help overlay
|
||||
+-- js/utils.js (314L) Formatting, save/load, export/import, DOM helpers
|
||||
+-- js/tutorial.js (251L) New player tutorial, step-by-step guidance
|
||||
+-- js/strategy.js (68L) NPC strategy logic for combat
|
||||
+-- game/npc-logic.js (18L) NPC behavior stub
|
||||
+-- js/emergent-mechanics.js Emergent game mechanics from player behavior
|
||||
|
||||
CI scripts (not browser runtime):
|
||||
+-- scripts/guardrails.sh Static analysis guardrails for game logic
|
||||
+-- scripts/smoke.mjs Playwright smoke tests
|
||||
|
||||
Reference prototypes (NOT loaded by runtime):
|
||||
+-- docs/reference/npc-logic-prototype.js NPC state machine prototype
|
||||
+-- docs/reference/guardrails-prototype.js Stat validation prototype
|
||||
```
|
||||
|
||||
## Entry Points
|
||||
|
||||
15
README.md
15
README.md
@@ -104,13 +104,22 @@ This game is a **decision simulator** for our actual work.
|
||||
|
||||
## Files
|
||||
|
||||
- `index.html` — Game UI
|
||||
- `game.js` — Core engine (tick loop, buildings, projects, events)
|
||||
- `index.html` — Game UI (entry point)
|
||||
- `js/main.js` — Bootstrap: binds UI, starts the tick loop
|
||||
- `js/engine.js` — Core engine (tick loop, buildings, projects, events)
|
||||
- `js/data.js` — Game data, constants, and configuration
|
||||
- `js/utils.js` — Shared helper functions
|
||||
- `js/combat.js` — Combat and threat mechanics
|
||||
- `js/strategy.js` — AI strategy decisions
|
||||
- `js/sound.js` — Audio and music
|
||||
- `js/render.js` — DOM rendering and UI updates
|
||||
- `js/tutorial.js` — New-player tutorial flow
|
||||
- `js/dismantle.js` — Dismantle / teardown mechanics
|
||||
- `js/emergent-mechanics.js` — Emergent gameplay systems
|
||||
- `DESIGN.md` — Full design document with narrative arc and mechanics
|
||||
- `README.md` — This file
|
||||
|
||||
## No Build Required
|
||||
|
||||
This is a static HTML/JS game. Just open `index.html` in a browser.
|
||||
|
||||
---
|
||||
|
||||
@@ -3,20 +3,15 @@ _2026-04-12, Perplexity QA_
|
||||
|
||||
## Findings
|
||||
|
||||
### Potentially Unimported Files
|
||||
### Dead Code — Resolved (2026-04-15, Issue #192)
|
||||
|
||||
The following files were added by recent PRs but may not be imported
|
||||
by the main game runtime (`js/main.js` → `js/engine.js`):
|
||||
The following files were confirmed dead code — never imported by any runtime module.
|
||||
They have been moved to `docs/reference/` as prototype reference code.
|
||||
|
||||
| File | Added By | Lines | Status |
|
||||
|------|----------|-------|--------|
|
||||
| `game/npc-logic.js` | PR #79 (GOFAI NPC State Machine) | ~150 | **Verify import** |
|
||||
| `scripts/guardrails.js` | PR #80 (GOFAI Symbolic Guardrails) | ~120 | **Verify import** |
|
||||
|
||||
**Action:** Check if `js/main.js` or `js/engine.js` imports from `game/` or `scripts/`.
|
||||
If not, these files are dead code and should either be:
|
||||
1. Imported and wired into the game loop, or
|
||||
2. Moved to `docs/` as reference implementations
|
||||
| File | Original | Resolution |
|
||||
|------|----------|------------|
|
||||
| `game/npc-logic.js` | PR #79 (GOFAI NPC State Machine) | **Moved to `docs/reference/npc-logic-prototype.js`** — ES module using `export default`, incompatible with the global-script loading pattern. Concept (NPC state machine) is sound but not wired into any game system. |
|
||||
| `scripts/guardrails.js` | PR #80 (GOFAI Symbolic Guardrails) | **Moved to `docs/reference/guardrails-prototype.js`** — validates HP/MP/stats concepts that don't exist in The Beacon's resource system. The `scripts/guardrails.sh` (bash CI script) remains active. |
|
||||
|
||||
### game.js Bloat (PR #76)
|
||||
|
||||
|
||||
70
tests/test_readme_runtime_map.py
Normal file
70
tests/test_readme_runtime_map.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
Regression test: README file map must stay in sync with scripts loaded by index.html.
|
||||
|
||||
Catches stale references (e.g. the old game.js) and missing documentation for
|
||||
any new modules added to the runtime.
|
||||
"""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
INDEX_HTML = REPO_ROOT / "index.html"
|
||||
README_MD = REPO_ROOT / "README.md"
|
||||
|
||||
|
||||
def _scripts_from_index_html() -> set[str]:
|
||||
"""Return the set of .js paths referenced in <script src="..."> tags."""
|
||||
html = INDEX_HTML.read_text(encoding="utf-8")
|
||||
return set(re.findall(r'<script\s+src="([^"]+\.js)"', html))
|
||||
|
||||
|
||||
def _scripts_from_readme() -> set[str]:
|
||||
"""Return the set of js/ paths mentioned in the README Files section."""
|
||||
text = README_MD.read_text(encoding="utf-8")
|
||||
# Grab everything between "## Files" and the next "## " heading
|
||||
m = re.search(r"## Files\n(.*?)(?=\n## |\Z)", text, re.DOTALL)
|
||||
assert m, "README is missing a '## Files' section"
|
||||
files_section = m.group(1)
|
||||
return set(re.findall(r"`(js/[^`]+\.js)`", files_section))
|
||||
|
||||
|
||||
def test_no_stale_game_js_reference():
|
||||
"""README must not reference the old monolithic game.js."""
|
||||
text = README_MD.read_text(encoding="utf-8")
|
||||
# Only flag if game.js appears *inside* the Files section (not elsewhere in prose)
|
||||
m = re.search(r"## Files\n(.*?)(?=\n## |\Z)", text, re.DOTALL)
|
||||
assert m, "README is missing a '## Files' section"
|
||||
files_section = m.group(1)
|
||||
assert "game.js" not in files_section, (
|
||||
"Stale reference to game.js found in README Files section"
|
||||
)
|
||||
|
||||
|
||||
def test_readme_covers_all_runtime_scripts():
|
||||
"""Every <script> in index.html must be documented in the README."""
|
||||
loaded = _scripts_from_index_html()
|
||||
documented = _scripts_from_readme()
|
||||
undocumented = loaded - documented
|
||||
assert not undocumented, (
|
||||
f"Scripts loaded by index.html but missing from README: {undocumented}"
|
||||
)
|
||||
|
||||
|
||||
def test_readme_has_no_extra_scripts():
|
||||
"""README should not document scripts that index.html does not load."""
|
||||
loaded = _scripts_from_index_html()
|
||||
documented = _scripts_from_readme()
|
||||
extra = documented - loaded
|
||||
assert not extra, (
|
||||
f"Scripts documented in README but not loaded by index.html: {extra}"
|
||||
)
|
||||
|
||||
|
||||
def test_main_js_is_entry_point():
|
||||
"""README should identify js/main.js as the entry / bootstrap point."""
|
||||
text = README_MD.read_text(encoding="utf-8")
|
||||
m = re.search(r"## Files\n(.*?)(?=\n## |\Z)", text, re.DOTALL)
|
||||
assert m, "README is missing a '## Files' section"
|
||||
files_section = m.group(1)
|
||||
assert "main.js" in files_section, "README Files section should mention js/main.js"
|
||||
Reference in New Issue
Block a user