38 lines
1.9 KiB
JavaScript
38 lines
1.9 KiB
JavaScript
// 可达性求解器:验证每关终点 / 存档点 / 苹果能否到达
|
|
// DJ=0,12,24 收紧二段跳时机;REL=0 禁用短跳 —— 检验是否只有"某一帧"能过
|
|
import { setupGlobals, reach, makeTargets } from './lib-reach.mjs';
|
|
setupGlobals();
|
|
|
|
const { LEVELS } = await import('../js/levels/index.js');
|
|
|
|
const DJSET = (process.env.DJ || '0,6,12,18,24,30').split(',').map(Number);
|
|
const RELSET = (process.env.REL || '0,4,8,14').split(',').map(Number);
|
|
|
|
let fail = 0;
|
|
console.log(`=== 可达性求解 (DJ=${DJSET} REL=${RELSET}) ===`);
|
|
for (const d of LEVELS) {
|
|
if (d.type === 'boss') { console.log(` ${d.id.padEnd(3)} ${d.name.padEnd(17)} (BOSS 关跳过)`); continue; }
|
|
let r;
|
|
try {
|
|
const { Level } = await import('../js/level.js');
|
|
const L = new Level(d);
|
|
const targets = makeTargets(L);
|
|
r = reach(L, { DJSET, RELSET, targets });
|
|
r.targets = targets;
|
|
} catch (e) { console.log(` ✗ ${d.id} 求解异常: ${e.message}`); fail++; continue; }
|
|
if (r.err) { console.log(` ✗ ${d.id.padEnd(3)} ${d.name.padEnd(17)} ${r.err}`); fail++; continue; }
|
|
|
|
const goal = r.targets.find(t => t.type === 'goal');
|
|
const saves = r.targets.filter(t => t.type === 'save');
|
|
const apples = r.targets.filter(t => t.type === 'apple');
|
|
const okSave = saves.filter(s => s.hit).length;
|
|
const okApple = apples.filter(a => a.hit).length;
|
|
const badSave = saves.filter(s => !s.hit).map(s => `#${s.no ?? s.idx}`);
|
|
const flag = goal && goal.hit ? ' ' : '✗';
|
|
if (!goal || !goal.hit) fail++;
|
|
if (badSave.length) fail++;
|
|
console.log(` ${flag} ${d.id.padEnd(3)} ${d.name.padEnd(17)} 终点=${goal ? (goal.hit ? 'OK' : '不可达') : '无'} 存档=${okSave}/${saves.length}${badSave.length ? ' 缺:' + badSave.join(',') : ''}${apples.length ? ` 苹果=${okApple}/${apples.length}` : ''} (状态${r.states})`);
|
|
}
|
|
console.log(fail ? `\n❌ ${fail} 项不可达` : '\n✅ 所有关卡终点与存档点均可达');
|
|
process.exit(fail ? 1 : 0);
|