diff --git a/example/src/App.tsx b/example/src/App.tsx index 043af5e..78ea0e7 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,4 +1,4 @@ -import { useGame, version, calculateMazeScore } from "../../src"; +import { useGame, version, calculateMazeScore, type ScoreManager } from "../../src"; import { useKeyBindings } from "./useKeyBindings"; import { useIsMobile } from "./useIsMobile"; import { useMemo } from "react"; @@ -9,7 +9,12 @@ function App() { const cols = isMobile ? 12 : 32; const rows = isMobile ? 8 : 24; - const gameManager = useGame({ cols, rows }, useKeyBindings); + const gameOver = (scroreManager: ScoreManager) => { + console.log('gameOver', scroreManager); + return scoreManager.efficiency < 70; + } + + const gameManager = useGame({ cols, rows, gameOver }, useKeyBindings); const { containerRef, gameStatus, scoreManager } = gameManager; const { timeValue, keystrokes, optimalSteps, efficiency } = scoreManager; @@ -30,41 +35,41 @@ function App() {

VIMazing vim-maze v{version} example

- {(gameStatus === "started" || gameStatus === "has-key" || gameStatus === "game-won") && ( -
-
-
Time
-
{formatTime(timeValue)}
-
-
-
Keystrokes
-
{keystrokes}
-
- {optimalSteps > 0 && ( - <> -
-
-
Optimal Steps
-
{optimalSteps}
-
-
-
Efficiency
-
{efficiency}%
-
- - )} - {gameStatus === "game-won" && finalScore && ( - <> -
-
-
Final Score
-
{finalScore}
-
- - )} -
- )} -
+ {(gameStatus === "started" || gameStatus === "has-key" || gameStatus === "game-won") && ( +
+
+
Time
+
{formatTime(timeValue)}
+
+
+
Keystrokes
+
{keystrokes}
+
+ {optimalSteps > 0 && ( + <> +
+
+
Optimal Steps
+
{optimalSteps}
+
+
+
Efficiency
+
{efficiency}%
+
+ + )} + {gameStatus === "game-won" && finalScore && ( + <> +
+
+
Final Score
+
{finalScore}
+
+ + )} +
+ )} +
diff --git a/src/formatGameInfo.ts b/src/formatGameInfo.ts new file mode 100644 index 0000000..5a8fffe --- /dev/null +++ b/src/formatGameInfo.ts @@ -0,0 +1,54 @@ +import type { GameManager } from './types'; +import { gameInfo as baseGameInfo } from './gameInfo'; + +/** + * Format the gameOver condition as a readable string + */ +function formatGameOverCondition(condition: GameManager['gameOverCondition']): string { + if (condition === undefined) { + return 'None - game continues indefinitely'; + } + + if (condition === true) { + return 'Always (immediate game over)'; + } + + if (condition === false) { + return 'Never (game never ends)'; + } + + if (typeof condition === 'function') { + // Try to get the function source + const source = condition.toString(); + // Clean up and format + const cleaned = source + .replace(/\s+/g, ' ') + .replace(/=>/, '→') + .trim(); + return cleaned.length > 200 ? cleaned.substring(0, 197) + '...' : cleaned; + } + + return 'Unknown condition'; +} + +/** + * Enrich gameInfo with runtime gameOver condition + * Returns the base gameInfo plus runtime condition info + */ +export function enrichGameInfo(gameManager: GameManager) { + const runtimeCondition = formatGameOverCondition(gameManager.gameOverCondition); + + return { + ...baseGameInfo, + gameOverRuntime: { + condition: runtimeCondition, + type: gameManager.gameOverCondition === undefined + ? 'none' + : typeof gameManager.gameOverCondition === 'boolean' + ? 'static' + : 'function', + }, + }; +} + +export { formatGameOverCondition }; diff --git a/src/index.ts b/src/index.ts index 5f641b8..0447913 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ export * from './useGame'; export * from './useGameStatus'; export { gameInfo } from './gameInfo'; export { calculateMazeScore } from './useScore'; +export { enrichGameInfo, formatGameOverCondition } from './formatGameInfo'; import { version } from '../package.json'; export type { GameInfo } from './gameInfo'; export { version }; diff --git a/src/types.ts b/src/types.ts index 517d7b7..ae34e9b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -29,4 +29,5 @@ export type GameManager = { hero: HeroManager; renderer: HeroRenderManager; scoreManager: ScoreManager; + gameOverCondition?: boolean | ((scoreManager: ScoreManager) => boolean); } & GameStatusManager & GameKeyManager; diff --git a/src/useGame.ts b/src/useGame.ts index f2f7fb4..f375745 100644 --- a/src/useGame.ts +++ b/src/useGame.ts @@ -25,6 +25,7 @@ export function useGame(options: GameOptions, platformHook?: unknown): GameManag hero, renderer, scoreManager, + gameOverCondition: gameOver, } if (typeof platformHook === 'function') {