Browse Source

fix(chase): enforce distinct start positions in round generation

Made-with: Cursor
master
npmrun 2 weeks ago
parent
commit
3692b59ccc
  1. 9
      src/game/chase/generator.ts
  2. 23
      tests/chase/chaseGenerator.test.ts

9
src/game/chase/generator.ts

@ -174,7 +174,13 @@ function generateGraphAttempt(seed: number, difficulty: Difficulty): ChaseRound
const exitNodeId = farthest.id;
const pathLength = shortestPathLength(graph, thiefStartNodeId, exitNodeId);
const farthestFromExit = getFarthestNode(graph, exitNodeId);
const guardStartNodeId = farthestFromExit.id;
let guardStartNodeId = farthestFromExit.id;
if (guardStartNodeId === thiefStartNodeId) {
const fallbackCandidates = existingNodeIds.filter(
(nodeId) => nodeId !== thiefStartNodeId,
);
guardStartNodeId = fallbackCandidates[0] ?? thiefStartNodeId;
}
return {
snapshot: {
@ -206,6 +212,7 @@ export function generateChaseRound(input: GenerateChaseRoundInput): ChaseRound {
const isPlayable =
isConnected(round.snapshot.graph) &&
round.meta.hasEscapePath &&
round.snapshot.guardStartNodeId !== round.snapshot.thiefStartNodeId &&
round.meta.pathLength >= minPathLength;
if (isPlayable) {

23
tests/chase/chaseGenerator.test.ts

@ -40,8 +40,8 @@ describe("chase round generator", () => {
"2,-1",
"1,-2",
],
"guardNodeId": "4,-5",
"guardStartNodeId": "4,-5",
"guardNodeId": "0,0",
"guardStartNodeId": "0,0",
"hasEscapePath": true,
"nodeCount": 20,
"seed": 424242,
@ -71,4 +71,23 @@ describe("chase round generator", () => {
expect(pathLength).toBeGreaterThan(0);
expect(pathLength).toBeLessThan(Infinity);
});
it("ensures thief and guard do not start on the same node", () => {
const round = generateChaseRound({ seed: 123456, difficulty: "normal" });
expect(round.snapshot.thiefStartNodeId).not.toBe(round.snapshot.guardStartNodeId);
});
it("stays playable and stable across many seeds", () => {
for (let seed = 1; seed <= 60; seed += 1) {
const round = generateChaseRound({ seed, difficulty: "normal" });
const nodeCount = Object.keys(round.snapshot.graph.nodes).length;
expect(nodeCount).toBeGreaterThanOrEqual(20);
expect(nodeCount).toBeLessThanOrEqual(30);
expect(round.meta.hasEscapePath).toBe(true);
expect(round.snapshot.thiefStartNodeId).not.toBe(
round.snapshot.guardStartNodeId,
);
}
});
});

Loading…
Cancel
Save