62 lines
2.6 KiB
TypeScript
62 lines
2.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { BufferGeometry, Float32BufferAttribute } from "three";
|
|
import { readFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
import { buildPartyNavigationGraph } from "./partyNavigation";
|
|
import { auditOrderedObjectiveRoutes } from "../../scripts/runewaker-pipeline/lib/objective-route-audit.mjs";
|
|
|
|
describe("RuneWaker ordered objective route audit", () => {
|
|
it("does not substitute the last reachable point for an unreachable predecessor", () => {
|
|
const geometry = new BufferGeometry();
|
|
geometry.setAttribute("position", new Float32BufferAttribute([
|
|
0, 0, 0, 4, 0, 0, 0, 0, 4,
|
|
20, 0, 0, 21, 0, 0, 20, 0, 1,
|
|
], 3));
|
|
const graph = buildPartyNavigationGraph(geometry);
|
|
const routes = auditOrderedObjectiveRoutes(graph, [1, 0, 1], [
|
|
{ id: "island-boss", name: "Island Boss", position: [20, 0, 0] },
|
|
{ id: "home-boss", name: "Home Boss", position: [2, 0, 1] },
|
|
]);
|
|
|
|
expect(routes.map(({ from, to, reachable }) => ({ from, to, reachable }))).toEqual([
|
|
{ from: "entrance", to: "Island Boss", reachable: false },
|
|
{ from: "Island Boss", to: "Home Boss", reachable: false },
|
|
]);
|
|
});
|
|
|
|
it("keeps the reviewed navigation blockers deterministic and fail-closed", () => {
|
|
const report = JSON.parse(readFileSync(resolve(
|
|
"scripts/runewaker-pipeline/RUNEWAKER_NAVIGATION_GAP_REPORT.json",
|
|
), "utf8"));
|
|
|
|
expect(report.schemaVersion).toBe(2);
|
|
expect(report).not.toHaveProperty("generatedAt");
|
|
expect(report.unreachableLegs).toBe(19);
|
|
expect(report.dungeons).toHaveLength(8);
|
|
expect(report.resolutionSummary).toEqual({
|
|
sourceAuthoredFixedOrders: 0,
|
|
authoredOffMeshLinksAdded: 0,
|
|
requirementDungeonCounts: {
|
|
"dynamic-navigation-transition": 5,
|
|
"encounter-gate-state": 3,
|
|
"encounter-teleport-state": 2,
|
|
"modular-environment-assembly": 3,
|
|
"navigation-geometry-review": 1,
|
|
"nonlinear-objectives": 1,
|
|
"source-objective-review": 6,
|
|
},
|
|
});
|
|
expect(report.dungeons.every((dungeon: {
|
|
objectiveOrdering: { authoritative: boolean };
|
|
reviewedFinding: { safeAutomaticLink: boolean; requirements: string[] };
|
|
}) => (
|
|
dungeon.objectiveOrdering.authoritative === false
|
|
&& dungeon.reviewedFinding.safeAutomaticLink === false
|
|
&& dungeon.reviewedFinding.requirements.length > 0
|
|
))).toBe(true);
|
|
expect(report.dungeons.find((dungeon: { id: string }) => (
|
|
dungeon.id === "kalins-shrine"
|
|
))?.reviewedFinding.objectiveOrderStatus).toBe("source-randomized-not-linear");
|
|
});
|
|
});
|