You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
53 lines
1.7 KiB
53 lines
1.7 KiB
import { describe, expect, it } from "vitest";
|
|
import { optimalGuardStep, thiefHasWinningStrategy } from "../../src/stages/games/chase/logic/solvability";
|
|
import type { GameGraph } from "../../src/stages/games/chase/logic/types";
|
|
|
|
function lineGraph(ids: string[]): GameGraph {
|
|
const nodes: GameGraph["nodes"] = {};
|
|
const edgeList: Array<[string, string]> = [];
|
|
for (let i = 0; i < ids.length; i += 1) {
|
|
const id = ids[i];
|
|
const prev = ids[i - 1];
|
|
const next = ids[i + 1];
|
|
const neighbors: string[] = [];
|
|
if (prev) {
|
|
neighbors.push(prev);
|
|
}
|
|
if (next) {
|
|
neighbors.push(next);
|
|
}
|
|
nodes[id] = { id, q: i, r: 0, neighbors };
|
|
}
|
|
for (let i = 0; i < ids.length - 1; i += 1) {
|
|
edgeList.push([ids[i], ids[i + 1]]);
|
|
}
|
|
return { nodes, edgeList };
|
|
}
|
|
|
|
describe("solvability (optimal guard)", () => {
|
|
it("returns false when guard blocks the only exit from a leaf", () => {
|
|
const graph = lineGraph(["L", "N", "E"]);
|
|
expect(thiefHasWinningStrategy(graph, "L", "N", "E")).toBe(false);
|
|
});
|
|
|
|
it("returns true when thief reaches exit in one step before guard reacts", () => {
|
|
const graph: GameGraph = {
|
|
nodes: {
|
|
T: { id: "T", q: 0, r: 0, neighbors: ["E", "G"] },
|
|
E: { id: "E", q: 1, r: 0, neighbors: ["T"] },
|
|
G: { id: "G", q: 0, r: 1, neighbors: ["T"] },
|
|
},
|
|
edgeList: [
|
|
["T", "E"],
|
|
["T", "G"],
|
|
],
|
|
};
|
|
expect(thiefHasWinningStrategy(graph, "T", "G", "E")).toBe(true);
|
|
});
|
|
|
|
it("optimalGuardStep matches shortest-path tie-break toward thief", () => {
|
|
const graph = lineGraph(["A", "B", "C"]);
|
|
expect(optimalGuardStep(graph, "A", "C")).toBe("B");
|
|
expect(optimalGuardStep(graph, "C", "A")).toBe("B");
|
|
});
|
|
});
|
|
|