Player.moveTo enforces wall/door/one-way validation with direction-of-approach
matching. keysHeld bitmask auto-collects on stepping on key cell. Capture/apply
includes inventory state.
Drop run-wide lives state. Detection routes to level-restart instead of
game-over. Repurpose GameOver scene for run-complete (L11) and bittersweet
(L12) flows. One-shot save migration wipes legacy lives field with welcome
modal.
New cell flags (door, key, one-way, warm). SniperGuard with line-of-sight beam
+ mirror reflection. SuspicionGuard with 3-tier meter. ThrowableSystem with
stone-throw distraction resolved before guard turn. Capture/apply round-trip
preserves all new state.
Static guards now emit a Manhattan aura that shrinks by 1 per turn until
harmless (clamped at -1 to keep solver state finite). Level data schema
change: 'static' guards now take 'initialRadius' instead of 'litCells'.
All 27 static-guard entries migrated in one pass.
L1 and L2 redesigned with real forced-zigzag walls — solver path is now
20 moves (vs Manhattan 14), so players must move AWAY from the goal to
reach it. L2 adds three wilting tomatoes parked on the zigzag path as
a gentle intro to the mechanic.
Tests: +3 new tests on StaticGuard wilting behavior; all 70 tests pass.
L12 widened to 13x13 with 10 guards including 2 chasers and a mirror.
Remains unsolvable by normal play (BFS-verified). window.__nntvDev.teleport
exposed as an intentional escape hatch — console-savvy users who invoke it
win the game. Hidden from README and in-game UI.
Act 5 redesign — chaser guard introduced. L9 has 8 guards with the
chaser ambushing the short route, forcing a perimeter detour. L10 is
the Hall of Mirrors with 9 guards (2 rotating + 3 mirrors + chaser).
Both solvable under 50 ms via BFS.
Act 4 redesign — mirror guard introduced. L7 has 7 guards including
one mirror that deflects a rotating beam. L8 has 8 guards with two
mirrors creating a crossfire pattern.
Act 3 redesign — patrolling guard introduced in L5 (6 guards total).
L6 widens with two patrollers, two blinkers, and a rotating guard
(7 guards). Both solvable via BFS solver.
Act 2 redesign — rotating guard (L3) and blinking guard (L4) introduced.
Both levels widened to 9x9. L4 solution requires a wait action to
synchronize with the blinking cycle, teaching the timing mechanic.
L2 right-side region was disconnected — player could not reach the goal
via any sequence of moves (verified via BFS). New L2 places three static
guards with two viable paths. L1 widens to 8x8 as a gentle Act 1 intro.
Preserves id/name/storyKey/isFinalLevel for progress persistence.
Asserts L1/5-8/10 solvable, L12 unsolvable (easter-egg invariant), and
locks the 12-level count. Known-broken levels (L2/3/4/9/11) tracked
explicitly and auto-unskip when their redesign phases flip them.
Pure BFS over (player, guard snapshots, princess state). Reuses guards.js
and princess-mechanic.js so solver verdicts match runtime behavior. State
budget cap prevents runaway search on impossible levels.
Fix cellSize at 50 and wrap board-container with overflow:auto + smooth
scrollTo effect centered on player. Unlocks grid sizes beyond 9x9 without
shrinking cells below readable size.
Built index.html now references ./assets/... instead of /assets/...
so the dist folder works when opened directly (file://), served from a
subpath (github pages project site, netlify deploy preview, etc.), or
any non-root path. Previously the absolute-root paths produced a blank
page with module load failures in those environments.
Also ignore .claude/ local scratch dir.
- Fix ChaserGuard with BFS pathfinding and proper chase/return states
- Add undo/redo system (Z/Y keys) with full state snapshots
- Add procedural audio via Web Audio API (move, wait, detection, complete)
- Add mobile swipe controls with touch gesture detection
- Add detection feedback (cell flash, player shake animation)
- Add CSS transitions on grid cells for smooth lighting changes
- Add ARIA accessibility labels on game board and cells
- Add controls overlay ("?" button) showing all keyboard/touch shortcuts
- Add mute toggle in HUD
- Update Guide scene with chaser/mirror guard descriptions and tips
- Replace guard switch statement with factory registry pattern
- Extract princess mechanic and touch controls into separate modules
- Localize all UI strings (EN/VI) including new controls and tips
- Update README for Svelte 5 architecture with all current features
- Update project docs (architecture, code standards, codebase summary)
- Wait action (Space/click player): skip turn while guards advance, enables timing puzzles
- Star rating system: 1-3 stars per level based on par moves, persisted in localStorage
- Level complete popup with animated star display and move count vs par
- Stars and best moves shown on level select screen
- ChaserGuard: new guard type that chases player's last known position when nearby
- All 12 levels redesigned with tighter corridors, more guards, and chasers in Act 5
- Guard vision preview (V key/button): ghost overlay shows next-turn danger zones
- Level 12 remains intentionally unbeatable with added chaser
Svelte 5 does not proxy class instances, so self-assignment (grid = grid)
was a no-op. Introduced renderVersion counter to force re-derivation of
all rendering data after game state mutations.
Also redesigned level progression with better mechanic teaching arc,
added Mirror Guard type (reflects rotating beams), and replaced instant
final-level detection with escalating light wave radiating from goal.
@sveltejs/vite-plugin-svelte@7 requires vite@^8.0.0 but we use
vite@6.3.6. Downgrade to v6 which supports vite@^6.3.0.
Fixes npm ci failure in GitHub Actions deploy workflow.
Phaser constructor only runs once; init() runs on every scene.start().
handleLevelComplete() was setting isPaused=true/inputEnabled=false which
persisted into subsequent levels, freezing player input.
- Fix StaticGuard ignoring litCells and RotatingGuard not lighting
facing direction
- Fix guard cleanup leak (direction indicators not destroyed)
- Add centralized theme system with dark stealth aesthetic
- Add scene fade transitions and level completion animation
- Add level progress persistence via localStorage
- Add turn counter, locked/completed level states in LevelSelect
- Redesign 12 levels across 6-act narrative arc with per-level story
- Add LevelIntro scene showing story text before each level
- Add bilingual (EN/VI) level story descriptions
- Remove dead code (counter.js, duplicate game/main.js)
- Initialize project docs (overview, architecture, code standards)