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:
+141
@@ -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;
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './useGame';
|
export * from './useGame';
|
||||||
export * from './useGameStatus';
|
export * from './useGameStatus';
|
||||||
|
export { gameInfo } from './gameInfo';
|
||||||
|
export type { GameInfo } from './gameInfo';
|
||||||
|
|||||||
Reference in New Issue
Block a user