feat: add gameInfo export with structured game instructions
- Export gameInfo object with complete game documentation - Includes controls (navigation, editing, deletion, hints, game) - Includes rules (cell types, modes, visual feedback) - Includes scoring (formula, penalties, multipliers, examples) - Includes game-over conditions - Includes hints system explanation - Structured for easy platform rendering - Fully typed with GameInfo type
This commit is contained in:
+158
@@ -0,0 +1,158 @@
|
|||||||
|
export const gameInfo = {
|
||||||
|
name: 'VIM Sudoku',
|
||||||
|
description: 'Classic Sudoku puzzle with VIM-style modal editing',
|
||||||
|
|
||||||
|
controls: {
|
||||||
|
navigation: [
|
||||||
|
{ keys: 'hjkl', description: 'Move cursor left/down/up/right' },
|
||||||
|
{ keys: '5j, 10l', description: 'Move with count (5 down, 10 right)' },
|
||||||
|
{ keys: '0 or ^', description: 'Jump to start of row' },
|
||||||
|
{ keys: '$', description: 'Jump to end of row' },
|
||||||
|
{ keys: 'gg', description: 'Jump to top of board' },
|
||||||
|
{ keys: 'G', description: 'Jump to bottom of board' },
|
||||||
|
{ keys: '.', description: 'Repeat last motion' },
|
||||||
|
],
|
||||||
|
|
||||||
|
editing: [
|
||||||
|
{ keys: 'i', description: 'Insert digit (works on empty cells only)' },
|
||||||
|
{ keys: 'r', description: 'Replace digit (works on user-entered cells only)' },
|
||||||
|
{ keys: 'c', description: 'Change digit (works on user-entered cells only)' },
|
||||||
|
{ keys: '1-9', description: 'Enter digit (while in edit mode)' },
|
||||||
|
{ keys: 'Escape', description: 'Exit edit mode to normal mode' },
|
||||||
|
],
|
||||||
|
|
||||||
|
deletion: [
|
||||||
|
{ keys: 'x', description: 'Delete digit from user-entered cell' },
|
||||||
|
{ keys: 'd', description: 'Delete digit from user-entered cell' },
|
||||||
|
{ keys: 'Delete', description: 'Delete digit from user-entered cell' },
|
||||||
|
{ keys: 'Backspace', description: 'Delete digit (only in edit mode)' },
|
||||||
|
],
|
||||||
|
|
||||||
|
hints: [
|
||||||
|
{ keys: 'Shift+H', description: 'Request hint (costs 25/50/100 points by difficulty)' },
|
||||||
|
],
|
||||||
|
|
||||||
|
game: [
|
||||||
|
{ keys: 'Space', description: 'Start new game (when waiting)' },
|
||||||
|
{ keys: 'q', description: 'Quit game' },
|
||||||
|
{ keys: 'p', description: 'Pause/unpause game' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
cellTypes: [
|
||||||
|
{ type: 'Empty', canEdit: 'i only', canReplace: 'no', canDelete: 'no', description: 'Empty cell ready for input' },
|
||||||
|
{ type: 'User-entered', canEdit: 'r or c only', canReplace: 'yes', canDelete: 'yes', description: 'Digit you entered' },
|
||||||
|
{ type: 'Given', canEdit: 'no', canReplace: 'no', canDelete: 'no', description: 'Original puzzle digit (locked)' },
|
||||||
|
],
|
||||||
|
|
||||||
|
modes: [
|
||||||
|
{
|
||||||
|
name: 'Normal Mode',
|
||||||
|
indicator: 'Blue outline on cursor',
|
||||||
|
description: 'Navigate with hjkl, access all commands',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Edit Mode (i)',
|
||||||
|
indicator: 'Yellow pulsing glow on cursor',
|
||||||
|
description: 'Type multiple digits, press Escape to exit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Edit Mode (r/c)',
|
||||||
|
indicator: 'Yellow pulsing glow on cursor',
|
||||||
|
description: 'Type one digit, auto-exits to normal mode',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
visualFeedback: [
|
||||||
|
{ indicator: 'Blue outline', meaning: 'Current cell in normal mode' },
|
||||||
|
{ indicator: 'Yellow pulsing glow', meaning: 'Current cell in edit mode' },
|
||||||
|
{ indicator: 'Red flash (500ms)', meaning: 'Invalid move or action' },
|
||||||
|
{ indicator: 'Red flash + background (1s)', meaning: 'Hint: this cell is incorrect' },
|
||||||
|
{ indicator: 'Green flash + background (1s)', meaning: 'Hint: showing correct digit' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
scoring: {
|
||||||
|
formula: 'Base Score = 1000 - (time penalty) - (keystroke penalty) - (hint penalty)',
|
||||||
|
multiplier: 'Final Score = min(1000, Base Score × difficulty 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' },
|
||||||
|
{ factor: 'Hints (Easy)', formula: 'hints × 25', example: '3 hints = -75 points' },
|
||||||
|
{ factor: 'Hints (Medium)', formula: 'hints × 50', example: '3 hints = -150 points' },
|
||||||
|
{ factor: 'Hints (Hard)', formula: 'hints × 100', example: '3 hints = -300 points' },
|
||||||
|
],
|
||||||
|
|
||||||
|
multipliers: [
|
||||||
|
{ difficulty: 'Easy', multiplier: '1.0x', description: 'No bonus' },
|
||||||
|
{ difficulty: 'Medium', multiplier: '1.5x', description: 'Can exceed base 1000, capped at 1000' },
|
||||||
|
{ difficulty: 'Hard', multiplier: '2.0x', description: 'Can exceed base 1000, capped at 1000' },
|
||||||
|
],
|
||||||
|
|
||||||
|
examples: [
|
||||||
|
{
|
||||||
|
difficulty: 'Easy',
|
||||||
|
time: '30 seconds',
|
||||||
|
keystrokes: 50,
|
||||||
|
hints: 0,
|
||||||
|
calculation: '1000 - 3 - 25 - 0 = 972 × 1.0',
|
||||||
|
score: '972 / 1000',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
difficulty: 'Hard',
|
||||||
|
time: '120 seconds',
|
||||||
|
keystrokes: 150,
|
||||||
|
hints: 2,
|
||||||
|
calculation: '1000 - 12 - 75 - 200 = 713 × 2.0',
|
||||||
|
score: '1000 / 1000 (capped)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
gameOver: {
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
type: 'Time Limit',
|
||||||
|
trigger: '10 minutes (600 seconds) by default',
|
||||||
|
configurable: true,
|
||||||
|
message: "Time's up!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'Hint Limit',
|
||||||
|
trigger: '500 points total hint penalty',
|
||||||
|
breakdown: 'Easy: 20 hints | Medium: 10 hints | Hard: 5 hints',
|
||||||
|
configurable: false,
|
||||||
|
message: 'Too many hints!',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
hints: {
|
||||||
|
description: 'Press Shift+H to get help when stuck',
|
||||||
|
priority: [
|
||||||
|
{
|
||||||
|
level: 1,
|
||||||
|
behavior: 'Show Incorrect Cell',
|
||||||
|
description: 'Randomly select a user-entered cell with wrong value and flash it red for 1 second',
|
||||||
|
reveals: 'Location of error (not the correct digit)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
level: 2,
|
||||||
|
behavior: 'Show Correct Digit',
|
||||||
|
description: 'If no errors exist, show correct digit for a random empty cell with green flash for 1 second',
|
||||||
|
reveals: 'Correct digit temporarily (you must remember it)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
cost: 'Deducted from final score based on difficulty',
|
||||||
|
limit: 'Game-over after 500 points of penalties',
|
||||||
|
},
|
||||||
|
|
||||||
|
objective: 'Fill all empty cells with digits 1-9 such that each row, column, and 3×3 box contains each digit exactly once.',
|
||||||
|
|
||||||
|
winCondition: 'All cells filled correctly (no validation enforced - trust yourself!)',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type GameInfo = typeof gameInfo;
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
export { useGame } from './useGame';
|
export { useGame } from './useGame';
|
||||||
export { useGameStatus } from './useGameStatus';
|
export { useGameStatus } from './useGameStatus';
|
||||||
export type { GameManager, GameOptions, GameStatus, GameStatusManager, Difficulty } from './types';
|
export type { GameManager, GameOptions, GameStatus, GameStatusManager, Difficulty } from './types';
|
||||||
|
export { gameInfo } from './gameInfo';
|
||||||
|
export type { GameInfo } from './gameInfo';
|
||||||
|
|||||||
Reference in New Issue
Block a user