- Add removedCells to GameOptions for custom puzzle sizes
- removedCells overrides difficulty default when provided
- Maintain backward compatibility with all defaults
- Complete IMPLEMENTATION.md with Iteration 16 and summary
- Completely rewrite README.md with comprehensive documentation:
- Complete API reference (GameOptions, GameManager, CursorManager, ScoreManager)
- Game states and state machine flow
- Full VIM controls reference (movement, editing, hints, game control)
- Cell state rules and visual feedback
- Detailed scoring formula with examples
- Game-over conditions (time and hint limits)
- Hint system priority and penalties
- Configuration examples for different play styles
- Platform hook integration guide
- Mark implementation as COMPLETE and PRODUCTION READY
- Add getHint() method to BoardManager with two-tier priority:
1. Find incorrect user-entered cells → flash red
2. Find empty cells → show correct digit green temporarily
- Add Shift+H key handler in useCursor (normal mode only)
- Visual feedback:
- Red flash (hint-flash-error): incorrect cells, 1s duration, red bg + border
- Green flash (hint-flash-correct): correct digit shown, 1s duration, green bg + border
- Distinct from invalid-move (no background, 500ms)
- Score penalties based on difficulty:
- Easy: 25 points per hint
- Medium: 50 points per hint
- Hard: 100 points per hint
- Track hints used in scoreboard display
- Correct digit appears temporarily (1s) then disappears (player still does the work)
- Update example app to show hints counter and Shift+H instruction
- Add useTimer hook for elapsed time tracking
- Add useScore hook with comprehensive metrics:
- Total keystrokes (all keys)
- Edit keystrokes (only editing keys)
- Optimal keystrokes (empty cells × 3)
- Efficiency percentage (optimal/edit × 100)
- Final score (70% efficiency + 30% time-based)
- Win condition detects board completion only in normal mode
- Track all keystrokes with timestamps in useGame
- Update example app with full scoreboard display
- Expose boardRef in BoardManager for state checking
- Adjust easy mode to 5 removed cells for testing
- Add x, d, Delete in normal mode to erase user-entered cells
- Add Backspace in edit mode to erase and stay in edit mode
- Add Backspace in normal mode as invalid move (red flash)
- All erase commands respect given cell protection
- Empty cells flash red on erase attempt in normal mode
- Add singleEdit state to track single vs multi-edit mode
- r and c only work on user-entered cells (flash red otherwise)
- i only works on empty cells (flash red on given or user-entered)
- r/c auto-exit to normal mode after one digit entry
- i stays in edit mode until Escape (multi-edit)
- Add position to useEffect dependency array in useCursor
- Fixes issue where old position was captured in handleKeyDown closure
- Edit mode entry now correctly validates current cell position
- Add setCell method to useBoard to update board state
- Handle digit keys 1-9 in edit mode in useCursor
- Move boardRendered counter to useBoard for proper cursor re-rendering
- Fix golden glow disappearing after digit entry
- Digits display with .user-entered class via renderer
Documented complete edit mode state machine:
- Phase 40.3.1: Mode state (normal/edit) with i and Escape
- Phase 40.3.2: Edit rules (given cells block, red flash feedback)
- Visual indicators using existing CSS classes
- Mode behavior and transitions
All edit mode functionality tested and working:
✅ State machine transitions
✅ Given cell validation with red flash
✅ Visual feedback (blue/yellow/red)
✅ Vim motions blocked in edit mode
Phase 40.3 complete. Ready for digit entry (40.3.3).
Documented:
- Issue 3: Red flash on invalid movement (500ms animation)
- Cleanup: Removed all debug console.logs
- Summary: All 3 issues resolved, production-ready
Phase 40.1 complete:
✅ Basic cursor with hjkl movement
✅ Visual cursor highlight (blue outline)
✅ Shows immediately on game start
✅ No border conflicts with grid edges
✅ Red flash feedback on invalid moves
✅ Clean, production-ready code
Ready for next phase or sidequest.
Extract game status logic into dedicated hook following vim-maze pattern:
New Module Structure:
- src/useGameStatus/types.ts: GameStatus and GameStatusManager types
- src/useGameStatus/useGameStatus.ts: Hook implementation
- src/useGameStatus/index.ts: Public exports
Hook Implementation:
- State machine with 5 states (waiting/started/paused/game-over/game-won)
- Methods: startGame, togglePause, quitGame, setGameStatus
- Clean state transitions with useState
- Simpler than vim-maze (no intermediate 'has-key' state)
Updated Core Files:
- src/useGame.ts: Use useGameStatus() instead of inline useState
- Compose gameStatusManager into GameManager
- Cleaner separation of concerns
- src/types.ts: Import and re-export GameStatus types
- GameManager extends GameStatusManager (intersection type)
- Single source of truth for status types
- src/index.ts: Export useGameStatus hook publicly
Benefits:
- Reusable state machine
- Easier to test in isolation
- Follows unified API architecture
- Matches vim-maze patterns
State Transitions:
waiting → startGame() → started ↔ togglePause() ↔ paused
started → (win/lose) → game-won/game-over
* → quitGame() → waiting
Phase 30 complete. Next: Phase 40 (useCursor composition).
Port sudoku generation algorithm and integrate with game flow:
Core Changes:
- src/useBoard/SudokuGenerator.ts: Ported from src_old/lib/Sudoku.ts
- Full puzzle generation algorithm (robatron/sudoku.js)
- Supports all difficulty levels (easy through inhuman)
- Returns 81-character string representation
- src/useBoard/useBoard.ts: Enhanced with puzzle state
- Added boardRef and initialBoardRef for state management
- Added generateBoard(difficulty) method
- Updated renderBoard() to display givens from board string
- Cells show digits for givens, empty for '.' characters
- src/useGame.ts: Integrated game flow
- Reads difficulty from GameOptions (defaults to 'easy')
- Generates puzzle on startGame (gameStatus → 'started')
- Re-renders board on status changes
- quitGame returns to empty grid
Game Flow:
- Waiting: Empty 9x9 grid
- Press Space → startGame() → puzzle generated (~62 givens on easy)
- Press Q → quitGame() → empty grid
Testing platformHook integration:
- startGame trigger working via useKeyBindings
- quitGame trigger working via useKeyBindings
- Board state properly cleared/populated on status changes
Phase 20 complete. Next: Phase 30 (useGameStatus hook).
- Archive previous implementation attempt (src -> src_failed)
- Create comprehensive IMPLEMENTATION_PLAN.md with phased approach
- Create IMPLEMENTATION.md to track implementation progress
- Update example app to match vim-maze patterns:
- Simplify UI to desktop-only (no mobile support)
- Add score metrics display (time, keystrokes, final score)
- Update instructions for sudoku-specific keys (hjkl, i for edit)
- Remove unnecessary mobile hooks
Phase 5 complete. Ready to begin Phase 10 (Setup & Core Types).