feat: add gameInfo export with structured game instructions

- Export gameInfo object with complete game documentation
- Includes controls (navigation, game)
- Includes rules (movement, game flow, maze elements)
- Includes scoring (formula, penalties, size multiplier, examples)
- Includes game-over conditions
- Includes maze generation details
- Includes tracked metrics
- Structured for easy platform rendering
- Fully typed with GameInfo type
This commit is contained in:
2025-10-22 22:52:07 +01:00
parent 40555d17b8
commit 6d71189e03
2 changed files with 143 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
export const gameInfo = {
name: 'VIM Maze',
description: 'Navigate procedurally generated mazes with VIM-style controls',
controls: {
navigation: [
{ keys: 'hjkl', description: 'Move left/down/up/right' },
{ keys: '5j, 10l', description: 'Move with count (5 down, 10 right)' },
{ keys: '0 or ^', description: 'Jump to leftmost walkable cell in row' },
{ keys: '$', description: 'Jump to rightmost walkable cell in row' },
{ keys: 'gg', description: 'Jump to topmost walkable row' },
{ keys: 'G', description: 'Jump to bottommost walkable row' },
{ keys: '.', description: 'Repeat last motion' },
],
game: [
{ keys: 'Space', description: 'Start new game (when waiting)' },
{ keys: 'q', description: 'Quit game' },
{ keys: 'p', description: 'Pause/unpause game' },
],
},
rules: {
movement: [
{ rule: 'Wall Collision', description: 'Movement stops at walls, no wrapping' },
{ rule: 'Counted Moves', description: 'Multi-step movements (e.g., 5j) stop at first wall encountered' },
{ rule: 'Path Required', description: 'Can only move through open passages' },
],
gameFlow: [
{
phase: 'Start',
location: 'Entrance (top-left area)',
objective: 'Navigate to find the key',
status: 'started',
},
{
phase: 'Key Found',
location: 'Somewhere in maze',
objective: 'Navigate to exit',
status: 'has-key',
},
{
phase: 'Victory',
location: 'Exit (bottom-right area)',
objective: 'Reached with key!',
status: 'game-won',
},
],
mazeElements: [
{ element: 'Entrance', appearance: 'Special cell in top-left area', description: 'Starting position' },
{ element: 'Key', appearance: 'Special cell in maze', description: 'Must collect before exit' },
{ element: 'Exit', appearance: 'Special cell in bottom-right area', description: 'Win condition (with key)' },
{ element: 'Walls', appearance: 'Solid barriers', description: 'Cannot pass through' },
{ element: 'Passages', appearance: 'Open paths', description: 'Walkable areas' },
],
},
scoring: {
formula: 'Base Score = 1000 - (time penalty) - (keystroke penalty)',
multiplier: 'Final Score = min(1000, Base Score × size multiplier)',
range: '0 - 1000 points',
penalties: [
{ factor: 'Time', formula: 'seconds / 10', example: '60 seconds = -6 points' },
{ factor: 'Keystrokes', formula: 'total keys / 2', example: '100 keys = -50 points' },
],
sizeMultiplier: {
formula: 'max(1.0, (rows × cols) / 500)',
description: 'Larger mazes earn higher potential scores',
examples: [
{ size: '16×24 (384 cells)', multiplier: '1.0x', description: 'Small maze, no bonus' },
{ size: '24×32 (768 cells)', multiplier: '1.54x', description: 'Medium maze' },
{ size: '32×48 (1536 cells)', multiplier: '3.07x', description: 'Large maze' },
],
},
examples: [
{
size: '16×24',
time: '60 seconds',
keystrokes: 80,
calculation: '1000 - 6 - 40 = 954 × 1.0',
score: '954 / 1000',
},
{
size: '32×48',
time: '180 seconds',
keystrokes: 200,
calculation: '1000 - 18 - 100 = 882 × 3.07',
score: '1000 / 1000 (capped)',
},
],
},
gameOver: {
conditions: [
{
type: 'Time Limit',
trigger: '10 minutes (600 seconds) by default',
configurable: true,
message: 'Time ran out!',
description: 'Failed to reach exit with key in time',
},
],
note: 'No other game-over conditions - take your time and find the optimal path!',
},
mazeGeneration: {
algorithm: 'Depth-first search with backtracking',
guarantees: [
'Path exists from entrance to key',
'Path exists from key to exit',
'No isolated areas',
'Fully connected passages',
],
placement: [
{ element: 'Entrance', location: 'Top-left area of maze' },
{ element: 'Key', location: 'Random location requiring navigation' },
{ element: 'Exit', location: 'Bottom-right area of maze' },
],
},
metrics: {
tracked: [
{ metric: 'Time', unit: 'seconds', description: 'Elapsed time since game start' },
{ metric: 'Keystrokes', unit: 'count', description: 'Total keys pressed' },
{ metric: 'Distance to Key', unit: 'cells', description: 'Current shortest path to key' },
{ metric: 'Distance to Exit', unit: 'cells', description: 'Current shortest path to exit' },
],
displayed: 'Live during gameplay to help you track progress',
},
objective: 'Navigate from entrance to key, then from key to exit, before time runs out.',
winCondition: 'Reach the exit cell while holding the key (key must be collected first).',
} as const;
export type GameInfo = typeof gameInfo;
+2
View File
@@ -1,3 +1,5 @@
export * from './types';
export * from './useGame';
export * from './useGameStatus';
export { gameInfo } from './gameInfo';
export type { GameInfo } from './gameInfo';