SCUMM-style web adventure engine v0.1
Headless, data-driven core (no DOM, no eval): loader with one-pass validation, verb-coin interaction resolution, polygon walkables with Dijkstra pathfinding, branching dialogue with mid-conversation saves, declarative JSON conditions/effects, versioned JSON saves. Thin integration layer: asset manifest with graceful placeholders, WebAudio music loop points (midi-playlist convention), canvas renderer (hotspot boxes drawn where hitTest clicks), HUD model. Web harness (web/) + skeleton example game exercising every feature. 69 tests (node --test), tools/run_all.sh gate, docs/SPEC.md design spec. Verified end-to-end in a real browser: intro scene, walking, look/take, room exits, dialogue choices.
This commit is contained in:
1 parent
ea0df1d475
commit
a4a2348a54
32 files changed
+2849
-1
No files matched your search
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# run_all.sh — the whole verification pipeline, one command:
|
||||
# 1. validate the example game spec
|
||||
# 2. run the full test suite
|
||||
# Never declare success without a passing run.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
echo "== validating example game spec"
|
||||
node tools/validate_game.js example/game.json
|
||||
|
||||
echo "== tests"
|
||||
node --test tests/*.test.js | tail -n 12
|
||||
|
||||
echo "ALL OK"
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env node
|
||||
// validate_game.js — CLI front door: check a game spec, print every problem
|
||||
// at once. Exit 0 = valid (warnings allowed), 1 = invalid.
|
||||
//
|
||||
// node tools/validate_game.js example/game.json
|
||||
|
||||
import { readFileSync } from "node:fs";
|
||||
import { validate } from "../src/core/loader.js";
|
||||
|
||||
const file = process.argv[2];
|
||||
if (!file) {
|
||||
console.error("usage: node tools/validate_game.js <game.json>");
|
||||
process.exit(2);
|
||||
}
|
||||
let spec;
|
||||
try {
|
||||
spec = JSON.parse(readFileSync(file, "utf8"));
|
||||
} catch (e) {
|
||||
console.error(`ERROR: ${file} is not valid JSON: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { errors, warnings } = validate(spec);
|
||||
for (const w of warnings) console.warn("WARNING:", w);
|
||||
if (errors.length) {
|
||||
console.error(`ERROR: ${file}: spec invalid:`);
|
||||
for (const e of errors) console.error(" - " + e);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`OK: ${file} (${spec.rooms.length} rooms, ${spec.objects?.length ?? 0} objects, ` +
|
||||
`${spec.characters.length} characters, ${spec.interactions?.length ?? 0} interactions, ` +
|
||||
`${Object.keys(spec.dialogues ?? {}).length} dialogues, ${Object.keys(spec.scenes ?? {}).length} scenes)`);
|
||||
Reference in new issue
Block a user