feat: implement game-over logic with time and hint limits

- Add configurable timeLimit to GameOptions (default 600 seconds / 10 minutes)
- Time limit applies to all difficulty levels (harder puzzles = more time pressure)
- Implement game-over triggers:
  1. Time limit exceeded: timeValue >= timeLimit → 'Time's up!'
  2. Hint penalty limit: hintsUsed * penalty >= 500 → 'Too many hints!'
- Hint limits by difficulty:
  - Easy: 20 hints max (20 × 25 = 500 points)
  - Medium: 10 hints max (10 × 50 = 500 points)
  - Hard: 5 hints max (5 × 100 = 500 points)
- Add gameOverReason to ScoreManager to display specific failure reason
- Timer stops on game-over
- Update example app to show game-over reason
- Both conditions checked during gameplay before win condition
This commit is contained in:
2025-10-22 21:48:33 +01:00
parent 97c31ab6cc
commit f68098657b
6 changed files with 194 additions and 6 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ function App() {
const [difficulty, setDifficulty] = useState<Difficulty>('easy');
const gameManager = useGame({ difficulty }, useKeyBindings);
const { containerRef, gameStatus, scoreManager } = gameManager;
const { timeValue, totalKeystrokes, hintsUsed, finalScore } = scoreManager;
const { timeValue, totalKeystrokes, hintsUsed, finalScore, gameOverReason } = scoreManager;
const formatTime = (ms: number) => {
const seconds = Math.floor(ms / 1000);
@@ -99,7 +99,7 @@ function App() {
<div className="text-center text-2xl text-muted-foreground">
{gameStatus === "waiting" && <p>Press <kbd className="px-2 py-1 bg-muted rounded">space</kbd> to start</p>}
{gameStatus === "started" && <p>Use <kbd className="px-2 py-1 bg-muted rounded">hjkl</kbd> to navigate • Press <kbd className="px-2 py-1 bg-muted rounded">i</kbd> to edit • Press <kbd className="px-2 py-1 bg-muted rounded">Shift+H</kbd> for hint • Press <kbd className="px-2 py-1 bg-muted rounded">q</kbd> to quit</p>}
{gameStatus === "game-over" && <p>Game Over! Press <kbd className="px-2 py-1 bg-muted rounded">space</kbd> to restart</p>}
{gameStatus === "game-over" && <p>{gameOverReason || "Game Over!"} Press <kbd className="px-2 py-1 bg-muted rounded">space</kbd> to restart</p>}
{gameStatus === "game-won" && <p>You Won! Press <kbd className="px-2 py-1 bg-muted rounded">space</kbd> to play again</p>}
</div>
</div>