- 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).
8.8 KiB
vim-sudoku Unified API Implementation Plan
Overview
Port vim-sudoku to the unified API architecture established by vim-maze, following the composable hook pattern with useGame() as the single entry point.
Goals
- Follow unified API architecture from UNIFIED_API.md
- Maintain vim-maze patterns and conventions
- Preserve all working functionality from src_old
- Support platform integration via optional platformHook parameter
- Enable code reuse across games (vim-maze, vim-sudoku, vim-snake)
Architecture
Core Composition
// Inside useGame:
const board = useBoard();
const gameStatusManager = useGameStatus();
const { cursor, keyManager } = useCursor(board, gameStatusManager);
const scoreManager = useScore({ board, gameStatusManager, keyManager });
// Returns unified GameManager interface
File Structure
src/
├── index.ts # Main package exports
├── types.ts # Re-exports all types from modules
├── useGame.ts # Main orchestrator hook
├── useGameStatus/
│ ├── index.ts # Public exports
│ ├── types.ts # GameStatus, GameStatusManager
│ └── useGameStatus.ts # Game state management
├── useBoard/
│ ├── index.ts # Public exports
│ ├── types.ts # SudokuBoard, SudokuCell, Difficulty, BoardManager
│ ├── useBoard.ts # Board management hook
│ ├── SudokuGenerator.ts # Puzzle generation (from src_old/lib/Sudoku.ts)
│ └── SudokuRenderer.ts # DOM rendering for sudoku grid
├── useCursor/
│ ├── index.ts # Public exports
│ ├── types.ts # CursorManager, CursorMode, VimMotionSystem, CellEditor
│ ├── useCursor.ts # Main cursor/input hook
│ ├── useCellEditor.ts # Cell editing logic (analog to useHero)
│ ├── useCursorRender.ts # Cursor rendering on DOM (analog to useHeroRender)
│ ├── useVimMotions.ts # Vim keybinding system
│ └── useGameKeys.ts # Game-specific key handling
└── useScore/
├── index.ts # Public exports
├── types.ts # TimerManager, ScoreManager
├── useScore.ts # Main scoring hook
└── useTimer.ts # Timer state management
Implementation Steps
Phase 5: Prepare Example App
- Update example/src/App.tsx to match vim-maze structure
- Update App to display score metrics (time, keystrokes, final score)
- Update App to show game status messages
- Update App instructions for sudoku-specific keys (i for edit)
- Keep it simple - no mobile support for now
Phase 10: Setup & Core Types
- Create clean src/ directory structure
- Define all types in module-specific types.ts files
- Create index.ts exports for each module
- Set up main types.ts re-export file
Phase 20: useBoard Hook
- Port SudokuGenerator from src_old/lib/Sudoku.ts
- Port SudokuRenderer from src_old rendering logic
- Implement useBoard hook with refs pattern
- containerRef for DOM
- boardRef for SudokuBoard (2D array of cells)
- initialBoardRef for puzzle state
- solutionRef for solved state
- Methods: renderBoard, generateBoard, getCell, setCell, canEditCell, isComplete, isFullyValid
Phase 30: useGameStatus Hook
- Implement GameStatus state machine
- 'waiting' → 'started' → 'game-won' / 'game-over'
- 'paused' state support
- Methods: startGame, togglePause, quitGame, setGameStatus
Phase 40: useCursor Hook Composition
40.1 useCellEditor (analog to useHero)
- Manage cursor position (row, col)
- Handle cell editing operations
- Validate edits against isGiven cells
- Trigger validation on cell changes
- Handle win condition detection
40.2 useVimMotions
- Port vim motion system from vim-maze
- Support: h/j/k/l, ^/$, g/G, . (repeat)
- Support: i (insert), r (replace), x (delete)
- Count prefix handling (e.g., 5j)
- Mode transitions (normal ↔ edit)
40.3 useGameKeys
- Keyboard event listener
- Route keys through vim motion processor
- Execute cursor movements
- Execute cell editing commands
- Track keystroke history
- Handle game-specific keys (q, p, space)
40.4 useCursorRender (analog to useHeroRender)
- Render cursor highlight on current cell
- Show edit mode indicator
- Flash animations (valid/invalid/locked)
- Highlight conflict cells
40.5 useCursor Main Hook
- Compose cellEditor, vimMotions, gameKeys, cursorRender
- Return unified CursorManager interface
- Split keyManager for useGame composition
Phase 50: useScore Hook
- Port timer from src_old/useScore/hooks/useTimer.ts
- Track keystrokes from keyManager.keyLog
- Calculate efficiency metrics
- Detect win/loss conditions based on completion
- Compute final score on game-won
Phase 60: useGame Orchestrator
- Compose all hooks (board, cursor, gameStatus, score)
- Handle initial board generation
- Coordinate rendering updates
- Expose unified GameManager interface
- Support optional platformHook parameter
Phase 70: Testing & Refinement
- Test with example app
- Verify all vim motions work
- Verify edit mode (i/r/x) works
- Verify validation and conflicts work
- Verify win condition triggers
- Test platform hook integration
- Update UNIFIED_API.md with sudoku specifics
Key Design Decisions
1. Board Representation
Choice: Use 2D array of SudokuCell objects
type SudokuCell = {
value: string; // '1'-'9' or ''
isGiven: boolean; // true for puzzle clues
hasConflict: boolean; // validation state
};
type SudokuBoard = SudokuCell[][];
Rationale: Easier to work with than 81-char string, matches vim-maze pattern of using structured data.
2. Cell Editing (analog to Hero Movement)
Choice: useCellEditor hook manages cell editing state
- Similar to useHero managing hero position in maze
- Handles validation before setting values
- Triggers game status changes on completion
Rationale: Keeps editing logic separate from cursor movement, following vim-maze separation of concerns.
3. Edit Mode vs Insert Mode
Choice: Two modes - 'normal' and 'edit'
- Normal mode: vim navigation + commands (i/r/x/d)
- Edit mode: digit entry (1-9) + erase (x/Backspace)
- i = insert (enter edit mode on empty cell)
- r = replace (enter edit mode on filled cell)
- Escape/Enter = exit edit mode
Rationale: Matches vim philosophy and src_old behavior.
4. Rendering Strategy
Choice: Keep rendering separate from state
- SudokuRenderer handles DOM generation
- useCursorRender handles cursor highlighting
- useBoard calls renderer with board data
Rationale: Matches vim-maze pattern (MazeRenderer + useHeroRender).
5. Validation Approach
Choice: Validate on setCell, show conflicts visually
- Real-time validation when setting digits
- Flash animations for feedback
- Highlight conflicting cells temporarily
- Don't prevent invalid moves (optional strictMode)
Rationale: Provides immediate feedback without blocking player exploration.
Type Mappings (vim-maze → vim-sudoku)
| vim-maze | vim-sudoku | Notes |
|---|---|---|
| MazeCell[][] | SudokuBoard | Board structure |
| Coord | Coord | Same (row, col) |
| useHero | useCellEditor | Cell editing vs movement |
| useHeroRender | useCursorRender | Visual feedback |
| MazeGenerator | SudokuGenerator | Puzzle generation |
| MazeRenderer | SudokuRenderer | Grid rendering |
| hero.moveTo | cellEditor.setValue | Action semantics |
| 'entrance'/'exit'/'key' | 'isGiven'/'value' | Cell metadata |
Differences from vim-maze
- No pathfinding: Simple grid bounds checking
- Edit mode: Need mode toggle for digit entry
- Validation: Real-time conflict detection
- Win condition: Complete + valid vs reach exit
- No animation: Cursor moves instantly (no multi-step)
- Board generation: On-demand vs one-time initialization
Success Criteria
- All functionality from src_old preserved
- Follows unified API architecture
- Types match vim-maze patterns
- Hook composition mirrors vim-maze
- Example app works identically to src_old version
- Platform hook integration works
- Code is clean, documented, and maintainable
- UNIFIED_API.md updated with vim-sudoku section
Notes
- Keep game.css from src_old for styling
- Port sudoku generation algorithm directly (working code)
- Maintain existing vim keybindings (h/j/k/l, ^/$, g/G, ., i/r/x)
- Preserve flash animations for visual feedback
- Follow AGENTS.md conventions throughout