From 654ce85d2ca040901fdcf9c80f38e0337b0689a0 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Sun, 26 Apr 2026 23:24:03 +0800 Subject: [PATCH] test(chase): cover retry limit failure path in round generation Made-with: Cursor --- src/game/chase/generator.ts | 12 ++++++++++-- tests/chase/chaseGenerator.test.ts | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/game/chase/generator.ts b/src/game/chase/generator.ts index 3321983..6a3f470 100644 --- a/src/game/chase/generator.ts +++ b/src/game/chase/generator.ts @@ -30,6 +30,10 @@ export interface ChaseRound { }; } +export interface GenerateChaseRoundOptions { + generateAttempt?: (seed: number, difficulty: Difficulty) => ChaseRound; +} + function coordKey(q: number, r: number): CoordKey { return `${q},${r}`; } @@ -202,13 +206,17 @@ function generateGraphAttempt(seed: number, difficulty: Difficulty): ChaseRound }; } -export function generateChaseRound(input: GenerateChaseRoundInput): ChaseRound { +export function generateChaseRound( + input: GenerateChaseRoundInput, + options: GenerateChaseRoundOptions = {}, +): ChaseRound { const baseSeed = normalizeSeed(input.seed); const minPathLength = minimumPathByDifficulty(input.difficulty); + const generateAttempt = options.generateAttempt ?? generateGraphAttempt; for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) { const attemptSeed = normalizeSeed(baseSeed + attempt * 0x9e3779b9); - const round = generateGraphAttempt(attemptSeed, input.difficulty); + const round = generateAttempt(attemptSeed, input.difficulty); const isPlayable = isConnected(round.snapshot.graph) && round.meta.hasEscapePath && diff --git a/tests/chase/chaseGenerator.test.ts b/tests/chase/chaseGenerator.test.ts index b261c78..8c0003b 100644 --- a/tests/chase/chaseGenerator.test.ts +++ b/tests/chase/chaseGenerator.test.ts @@ -90,4 +90,37 @@ describe("chase round generator", () => { ); } }); + + it("throws after retry limit when all attempts are unplayable", () => { + let attemptCount = 0; + const unplayableStrategy = (seed: number, difficulty: Difficulty) => { + attemptCount += 1; + return { + snapshot: { + seed, + difficulty, + graph: { nodes: {}, edgeList: [] }, + thiefStartNodeId: "A", + guardStartNodeId: "A", + thiefNodeId: "A", + guardNodeId: "A", + exitNodeId: "A", + status: "playing" as const, + }, + meta: { + hasEscapePath: false, + pathLength: 0, + attemptsUsed: 1, + }, + }; + }; + + expect(() => + generateChaseRound( + { seed: 7, difficulty: "normal" }, + { generateAttempt: unplayableStrategy }, + ), + ).toThrow("Unable to generate playable chase round within retry limit"); + expect(attemptCount).toBe(40); + }); });