diff --git a/src/game/chase/generator.ts b/src/game/chase/generator.ts index 430d5fc..4f4abdb 100644 --- a/src/game/chase/generator.ts +++ b/src/game/chase/generator.ts @@ -12,9 +12,17 @@ export interface GenerateChaseRoundInput { } export interface ChaseRound { - graph: GameGraph; - startNodeId: NodeId; - exitNodeId: NodeId; + snapshot: { + seed: number; + difficulty: Difficulty; + graph: GameGraph; + thiefStartNodeId: NodeId; + guardStartNodeId: NodeId; + thiefNodeId: NodeId; + guardNodeId: NodeId; + exitNodeId: NodeId; + status: "playing"; + }; meta: { hasEscapePath: boolean; pathLength: number; @@ -160,15 +168,26 @@ function generateGraphAttempt(seed: number, difficulty: Difficulty): ChaseRound edgeList: buildEdgeList(nodes), }; - const startNodeId = existingNodeIds[randomInt(rng, 0, existingNodeIds.length - 1)]; - const farthest = getFarthestNode(graph, startNodeId); + const thiefStartNodeId = + existingNodeIds[randomInt(rng, 0, existingNodeIds.length - 1)]; + const farthest = getFarthestNode(graph, thiefStartNodeId); const exitNodeId = farthest.id; - const pathLength = shortestPathLength(graph, startNodeId, exitNodeId); + const pathLength = shortestPathLength(graph, thiefStartNodeId, exitNodeId); + const farthestFromExit = getFarthestNode(graph, exitNodeId); + const guardStartNodeId = farthestFromExit.id; return { - graph, - startNodeId, - exitNodeId, + snapshot: { + seed, + difficulty, + graph, + thiefStartNodeId, + guardStartNodeId, + thiefNodeId: thiefStartNodeId, + guardNodeId: guardStartNodeId, + exitNodeId, + status: "playing", + }, meta: { hasEscapePath: Number.isFinite(pathLength) && pathLength > 0, pathLength, @@ -185,7 +204,7 @@ export function generateChaseRound(input: GenerateChaseRoundInput): ChaseRound { const attemptSeed = normalizeSeed(baseSeed + attempt * 0x9e3779b9); const round = generateGraphAttempt(attemptSeed, input.difficulty); const isPlayable = - isConnected(round.graph) && + isConnected(round.snapshot.graph) && round.meta.hasEscapePath && round.meta.pathLength >= minPathLength; diff --git a/tests/chase/chaseGenerator.test.ts b/tests/chase/chaseGenerator.test.ts index 3c795c0..72c7a16 100644 --- a/tests/chase/chaseGenerator.test.ts +++ b/tests/chase/chaseGenerator.test.ts @@ -16,14 +16,21 @@ describe("chase round generator", () => { const round = generateChaseRound({ seed: 424242, difficulty: "easy" }); expect({ - startNodeId: round.startNodeId, - exitNodeId: round.exitNodeId, + seed: round.snapshot.seed, + difficulty: round.snapshot.difficulty, + thiefStartNodeId: round.snapshot.thiefStartNodeId, + guardStartNodeId: round.snapshot.guardStartNodeId, + thiefNodeId: round.snapshot.thiefNodeId, + guardNodeId: round.snapshot.guardNodeId, + exitNodeId: round.snapshot.exitNodeId, + status: round.snapshot.status, hasEscapePath: round.meta.hasEscapePath, - nodeCount: Object.keys(round.graph.nodes).length, - edgeCount: round.graph.edgeList.length, - firstFiveNodeIds: Object.keys(round.graph.nodes).slice(0, 5), + nodeCount: Object.keys(round.snapshot.graph.nodes).length, + edgeCount: round.snapshot.graph.edgeList.length, + firstFiveNodeIds: Object.keys(round.snapshot.graph.nodes).slice(0, 5), }).toMatchInlineSnapshot(` { + "difficulty": "easy", "edgeCount": 19, "exitNodeId": "0,-1", "firstFiveNodeIds": [ @@ -33,16 +40,21 @@ describe("chase round generator", () => { "2,-1", "1,-2", ], + "guardNodeId": "4,-5", + "guardStartNodeId": "4,-5", "hasEscapePath": true, "nodeCount": 20, - "startNodeId": "4,-5", + "seed": 424242, + "status": "playing", + "thiefNodeId": "4,-5", + "thiefStartNodeId": "4,-5", } `); }); it("generates graph node count between 20 and 30", () => { const round = generateChaseRound({ seed: 11, difficulty: "normal" }); - const nodeCount = Object.keys(round.graph.nodes).length; + const nodeCount = Object.keys(round.snapshot.graph.nodes).length; expect(nodeCount).toBeGreaterThanOrEqual(20); expect(nodeCount).toBeLessThanOrEqual(30); }); @@ -50,9 +62,9 @@ describe("chase round generator", () => { it("ensures an escape path exists", () => { const round = generateChaseRound({ seed: 99, difficulty: "hard" }); const pathLength = shortestPathLength( - round.graph, - round.startNodeId, - round.exitNodeId, + round.snapshot.graph, + round.snapshot.thiefNodeId, + round.snapshot.exitNodeId, ); expect(round.meta.hasEscapePath).toBe(true);