83 lines
2.2 KiB
JavaScript
83 lines
2.2 KiB
JavaScript
#!/usr/bin/env node
|
|
// Hand-authors the sample Wolfenstein levels as compact ASCII maps and writes
|
|
// them to assets/gamedata/wolfenstein/ — the tools/genBloxorz.js role. Every
|
|
// level is run through auditLevel() (validateLevel + BFS reachability) before
|
|
// being written; an unsolvable or malformed map fails the build rather than
|
|
// shipping silently broken.
|
|
//
|
|
// node tools/genWolfenstein.js
|
|
|
|
import { writeFileSync, mkdirSync } from 'fs';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname, join } from 'path';
|
|
import { parseMap, auditLevel } from './wolfensteinMap.js';
|
|
|
|
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
const OUT_DIR = join(ROOT, 'assets/gamedata/wolfenstein');
|
|
mkdirSync(OUT_DIR, { recursive: true });
|
|
|
|
const LEVELS = [];
|
|
const lvl = (id, name, art, opts) => { LEVELS.push(parseMap(id, name, art, opts)); };
|
|
|
|
lvl('e1m1', 'First Blood', `
|
|
############
|
|
#S..#...E.X#
|
|
#...#......#
|
|
#...D......#
|
|
#..........#
|
|
#....##....#
|
|
#....##....#
|
|
#..A.....H.#
|
|
#..........#
|
|
############
|
|
`, {
|
|
campaignId: 'episode1', missionIndex: 0,
|
|
briefing: ['Clear the outpost.', 'Find the exit.'],
|
|
});
|
|
|
|
lvl('e1m2', 'The Armory', `
|
|
##############
|
|
#S...#....E..#
|
|
#....#.......#
|
|
#....D.......#
|
|
#....#.......#
|
|
#....#..##...#
|
|
#..A.#..##...#
|
|
#....#.......#
|
|
#....#...E...#
|
|
#....#.....HX#
|
|
##############
|
|
`, {
|
|
campaignId: 'episode1', missionIndex: 1,
|
|
briefing: ['Tougher resistance ahead.', 'The armory door only opens from this side.'],
|
|
// The second guard (E index 1, at 9,8 — reading order top-to-bottom,
|
|
// left-to-right) walks the open floor along its own row; the first guard
|
|
// stays put. See wolfensteinMap.js's legend comment for the opts.patrols
|
|
// convention.
|
|
patrols: { 1: [[7, 8], [12, 8]] },
|
|
});
|
|
|
|
lvl('e2m1', 'Descent', `
|
|
##########
|
|
#S..#...X#
|
|
#...#....#
|
|
#...D....#
|
|
#........#
|
|
#..E..A..#
|
|
#........#
|
|
#....H...#
|
|
#........#
|
|
##########
|
|
`, {
|
|
campaignId: 'episode2', missionIndex: 0,
|
|
briefing: ['Underground now.', 'Watch corners.'],
|
|
});
|
|
|
|
for (const level of LEVELS) {
|
|
const result = auditLevel(level);
|
|
writeFileSync(join(OUT_DIR, `level-${level.id}.json`), `${JSON.stringify(level, null, 2)}\n`);
|
|
console.log(`wrote level-${level.id}.json — reachable=${result.reachable}`);
|
|
}
|
|
|
|
console.log(`\n${LEVELS.length} level(s) generated into ${OUT_DIR}`);
|