From 2f122d189644820199cbb847d741a6d822bec63d Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Tue, 21 Apr 2026 21:29:20 +0700 Subject: [PATCH] feat(levels): redesign L11 Throne Room on 12x12 grid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Climactic Act 6 level — 9 guards covering ALL six guard types (static, rotating, blinking, patrolling, mirror, chaser). BFS-proven solvable in 22 moves. All playable levels (L1-L11) now verified solvable; only L12 remains unsolvable by design. --- src/lib/levels/levels.js | 71 +++++++++++++++++------ src/lib/levels/levels.solvability.test.js | 3 +- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/lib/levels/levels.js b/src/lib/levels/levels.js index 57050ea..dd7c9b8 100644 --- a/src/lib/levels/levels.js +++ b/src/lib/levels/levels.js @@ -634,55 +634,88 @@ export const LEVELS = [ parMoves: 24, }, { - // The Throne Room — all guard types combined including chaser + // L11 Throne Room — 12x12, 9 guards covering ALL SIX TYPES + // (static, rotating, blinking, patrolling, mirror, chaser). + // The climactic test before the impossible Princess Chamber. id: 11, name: "The Throne Room", storyKey: "level11Story", - grid: { rows: 9, cols: 9 }, + grid: { rows: 12, cols: 12 }, player: { row: 0, col: 0 }, - goal: { row: 8, col: 8 }, + goal: { row: 11, col: 11 }, walls: [ - { row: 2, col: 0 }, { row: 2, col: 1 }, { row: 2, col: 2 }, - { row: 2, col: 3 }, { row: 2, col: 4 }, { row: 2, col: 5 }, { row: 2, col: 6 }, - { row: 4, col: 2 }, { row: 4, col: 3 }, { row: 4, col: 4 }, - { row: 4, col: 5 }, { row: 4, col: 6 }, { row: 4, col: 7 }, { row: 4, col: 8 }, - { row: 6, col: 0 }, { row: 6, col: 1 }, { row: 6, col: 2 }, - { row: 6, col: 3 }, { row: 6, col: 4 }, { row: 6, col: 5 }, { row: 6, col: 6 }, + { row: 1, col: 4 }, { row: 1, col: 8 }, + { row: 2, col: 2 }, { row: 2, col: 6 }, + { row: 3, col: 4 }, { row: 3, col: 9 }, + { row: 4, col: 1 }, { row: 4, col: 6 }, + { row: 5, col: 3 }, { row: 5, col: 10 }, + { row: 6, col: 5 }, { row: 6, col: 8 }, + { row: 7, col: 2 }, { row: 7, col: 6 }, + { row: 8, col: 4 }, { row: 8, col: 9 }, + { row: 9, col: 1 }, { row: 9, col: 6 }, + { row: 10, col: 3 }, { row: 10, col: 8 }, ], guards: [ { type: "static", - position: { row: 1, col: 7 }, + position: { row: 1, col: 2 }, litCells: [ - { row: 0, col: 7 }, { row: 1, col: 6 }, { row: 1, col: 8 }, + { row: 0, col: 2 }, { row: 1, col: 1 }, + { row: 1, col: 3 }, { row: 2, col: 1 }, ], }, { type: "rotating", - position: { row: 3, col: 3 }, + position: { row: 3, col: 5 }, startDirection: 0, }, + { + type: "mirror", + position: { row: 5, col: 5 }, + reflectDirection: "cw", + }, { type: "blinking", - position: { row: 5, col: 7 }, + position: { row: 4, col: 9 }, startState: true, litCells: [ - { row: 5, col: 6 }, { row: 5, col: 8 }, + { row: 3, col: 10 }, { row: 4, col: 8 }, + { row: 4, col: 10 }, { row: 5, col: 9 }, ], }, { type: "patrolling", - startPosition: { row: 7, col: 1 }, + startPosition: { row: 6, col: 2 }, path: [ - { row: 7, col: 1 }, { row: 7, col: 2 }, - { row: 7, col: 3 }, { row: 7, col: 4 }, + { row: 6, col: 2 }, { row: 6, col: 3 }, { row: 7, col: 3 }, { row: 7, col: 2 }, ], }, { - // Chaser guards the final stretch + type: "static", + position: { row: 8, col: 2 }, + litCells: [ + { row: 7, col: 2 }, { row: 8, col: 1 }, + { row: 8, col: 3 }, { row: 9, col: 2 }, + ], + }, + { + type: "rotating", + position: { row: 9, col: 8 }, + startDirection: 2, + }, + { + type: "blinking", + position: { row: 10, col: 10 }, + startState: false, + litCells: [ + { row: 9, col: 10 }, { row: 10, col: 9 }, + { row: 10, col: 11 }, + ], + }, + { type: "chaser", - position: { row: 7, col: 7 }, + position: { row: 8, col: 7 }, detectionRadius: 3, }, ], diff --git a/src/lib/levels/levels.solvability.test.js b/src/lib/levels/levels.solvability.test.js index 08dff7f..f399c91 100644 --- a/src/lib/levels/levels.solvability.test.js +++ b/src/lib/levels/levels.solvability.test.js @@ -17,8 +17,7 @@ const SOLVER_OPTS = { maxStates: 2_000_000 }; // Levels known broken under current design. Each entry names the phase that // redesigns it — flip to expect `solvable: true` after the redesign lands. const KNOWN_UNSOLVABLE_BUGS = new Set([ - // L2, L3, L4, L9 fixed (phases 04-08). - 11, // redesign in phase-09-redesign-l11.md + // All playable levels now fixed (phases 04-09). L12 unsolvable by design. ]); describe('level solvability', () => {