- finalScore equals current game score when gameStatus is 'game-over' or 'game-won'
- finalScore is null during active gameplay ('waiting' and 'started')
- Passed currentScore from gameManager to useScore hook
- Expose keyLog.length as totalKeystrokes in ScoreManager
- Pass keyLog from useKeyBindings to useScore hook
- All game inputs (hjkl and platform keys) automatically counted
- Keystroke counter resets when keyLog is cleared (game restart)
- Reset initial snake size from 6 back to 3 segments
- Keep INITIAL_FPS at 5 (good starting speed)
- FOODS_PER_LEVEL = 2 (correct production value)
- Game now starts at normal difficulty
- Clean production-ready state
- Build and example app work correctly
- Remove all console.log debug statements
- Score calculation now working correctly:
* Each food worth current level points
* Level up happens AFTER food is eaten and scored
* Example: food1(+1)=1pt, food2(+1, lvlup)=2pts, food3(+2)=4pts
- FOODS_PER_LEVEL = 2 (final production setting)
- Code is clean and production-ready
- Change from 1 back to 2 for normal gameplay
- Now need 2 foods to level up instead of every food
- Score sequence should be: +1, +1, lvlup, +2, +2, lvlup, +3, +3, etc.
- Testing that score calculation works correctly with threshold of 2
- Call setLevel() BEFORE setScore(), not inside the callback
- This prevents setScore from being called multiple times per food
- Level up happens once, then score is updated with correct points
- Fixes: 1st food +1pt (lvl1), 2nd food +2pts (lvl2), 3rd food +3pts (lvl3)
- No more duplicate level ups on same food
- Save pointsToAdd = levelRef.current at start of setScore
- Use saved value for scoring, not levelRef.current which gets changed
- This ensures 1st food adds 1 point at level 1, then level up to 2
- 2nd food adds 2 points at level 2, then level up to 3, etc.
- Correct sequence: +1, +2, +3, +4... with level ups after each
- Reset INITIAL_FPS from 12 back to 5 for easier debugging
- Change FOODS_PER_LEVEL to 1 for easier threshold testing
- Add console.log to track foods eaten, level ups, and score changes
- Logs show: foods eaten, will level up flag, current level, score additions
- This will help debug the score calculation logic
- Calculate willLevelUp BEFORE foodsEatenRef.current += 1
- This way the 2nd food that triggers level up is still worth 1 point
- Only AFTER eating it do we level up to 2
- Correct: eat food1(+1)=1pt, eat food2(+1, then lvlup)=2pts, eat food3(+2)=4pts
- Issue was checking >= threshold AFTER incrementing, causing wrong level calculation
- Add points at CURRENT level FIRST
- THEN check if we should level up for NEXT food
- Food that triggers level up is worth old level points, not new
- Example: eat food 1 (+1), eat food 2 (+1, now level up), eat food 3 (+2)
- Correct scoring: 1 + 1 = 2 points at level 1, then 2 + 2 = 4 at level 2
- Level up BEFORE adding points, not after
- When foodsEatenRef reaches threshold:
1. Increment level first
2. Reset food counter
3. THEN add points at new level
- Correct flow: eat 2 foods at level 1 (+1,+1=2pts), level up, next food worth +2pts
- Was: eat at level 1, level up happens, get 2pts (wrong level)
- Now: eat at level 1, eat at level 1, level up, next food gets 2pts (correct)
- Remove the buggy 'newScore--' line that was penalizing level ups
- Score now correctly accumulates: each food = (+1 * current_level) points
- Level 1: 1 food = +1 point
- Level 2: 1 food = +2 points
- Level 3: 1 food = +3 points, etc.
- No penalty on leveling up, just speed increase
- Score calculation now makes intuitive sense
- Delete src/useGame/useSnake.ts (replaced by src/useCursor/useCursor.ts)
- Delete src/useGame/useRenderer.ts (replaced by src/useBoard/useBoard.ts)
- Delete src/useGame/useGameStatus.ts (replaced by src/useGameStatus/useGameStatus.ts)
- Update useFood.ts to import from useBoard instead of useRenderer
- Fix TypeScript type annotations in useFood.ts
- Cleaner codebase with no duplicate implementations
- Build and example app still work correctly
- Change initial snake length from 3 to 6 segments
- Makes it easier to test turning mechanics and buffering
- Better visibility of snake movement patterns
- Can be reverted once testing is complete
- Change INITIAL_FPS from 5 to 12 for faster gameplay
- Makes it easier to test key buffering at higher speeds
- Can be reverted once testing is complete
- Move applyBufferedDirection() to execute before moveSnake()
- This ensures buffered input is used for the current frame's movement
- Allows multi-frame 180° turns (down then left, for example)
- Snake can turn in any valid direction across frames
- Fixes the 180° reversal restriction issue
- Change buffer validation from lastMovedDirection to currentDirection
- This allows 180° reversals across frames (they're safe if you have space)
- Only blocks immediate 180° within same frame (would cause self-collision)
- Removes overly restrictive direction blocking
- Player can now freely turn in any direction between moves
- Should fix the 'impossible to turn' and 'immediate death' issues
- Add nextDirectionRef to buffer player input
- Update changeDirection() to queue input instead of immediate execution
- Add applyBufferedDirection() to safely apply buffered input
- Buffer prevents 180° reversals for safe turns
- Call applyBufferedDirection() after each successful move in game loop
- Remove collision grace period - no longer needed with key buffering
- Remove collisionGracePeriodRef and related logic
- Clean up all console.log statements from useGameStatus
- Game now feels responsive at high speeds
- Allows pre-emptive turning on board edges (Nokia Snake style)
- Build and example app work correctly
- Import GameManager type directly from main package
- Use new Unified API methods: renderBoard, quitGame, clearKeyLog
- Remove pause functionality for now (simplified like vim-maze)
- Match vim-maze's key binding pattern
- Game now starts and plays correctly
- Create comprehensive types.ts with all required manager interfaces
- Define GameManager with proper Unified API compliance
- Implement CursorManager interface in useCursor with VIM motions
- Add SnakeCursorManager type with snake-specific extensions
- Update useGame to return proper GameManager interface
- Support both old (cols, rows) and new (options) signatures
- Add quitGame alias for stopGame in useGameStatus
- Wrap renderBoard to match Unified API signature (no parameters)
- Add placeholder for totalKeystrokes and finalScore in ScoreManager
- All TypeScript builds successfully
- Example app builds without errors
- Create new hook modules: useBoard, useCursor, useGameStatus
- Move/copy hook implementations to their own directories
- Create index.ts files for clean module exports
- Update all imports to use new module locations
- Rename useSnake -> useCursor for Unified API alignment
- Rename useRenderer -> useBoard for clarity
- Update main src/index.ts to export from all hook modules
- All TypeScript builds successfully
- Example app remains functional