docs: update gameInfo.ts to reflect scoring refactor

- Update gameOver section: removed hardcoded time limit, now uses custom gameOver condition
- Add examples of gameOver usage: time-based, efficiency-based, combined
- Update metrics: add optimalSteps and efficiency to tracked metrics
- Add note: ScoreManager provides metrics for flexible game-over/scoring logic
- Update objective: reflect custom game-over condition requirement
This commit is contained in:
2025-11-02 17:08:54 +00:00
parent 0749aba648
commit 897cb5de13
+80 -61
View File
@@ -57,56 +57,72 @@ export const gameInfo = {
], ],
}, },
scoring: { scoring: {
formula: 'Base Score = 1000 - (time penalty) - (keystroke penalty)', calculation: 'Call calculateMazeScore(scoreManager, mazeSize) to compute final score',
multiplier: 'Final Score = min(1000, Base Score × size multiplier)', note: 'Score calculation moved to consumer - ScoreManager only provides raw metrics',
range: '0 - 1000 points', formula: 'Base Score = 1000 - (time penalty) - (keystroke penalty)',
multiplier: 'Final Score = min(1000, Base Score × size multiplier)',
penalties: [ range: '0 - 1000 points',
{ factor: 'Time', formula: 'seconds / 10', example: '60 seconds = -6 points' },
{ factor: 'Keystrokes', formula: 'total keys / 2', example: '100 keys = -50 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', sizeMultiplier: {
examples: [ formula: 'max(1.0, (rows × cols) / 500)',
{ size: '16×24 (384 cells)', multiplier: '1.0x', description: 'Small maze, no bonus' }, description: 'Larger mazes earn higher potential scores',
{ size: '24×32 (768 cells)', multiplier: '1.54x', description: 'Medium maze' }, examples: [
{ size: '32×48 (1536 cells)', multiplier: '3.07x', description: 'Large maze' }, { 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', examples: [
time: '60 seconds', {
keystrokes: 80, size: '16×24',
calculation: '1000 - 6 - 40 = 954 × 1.0', time: '60 seconds',
score: '954 / 1000', keystrokes: 80,
}, calculation: '1000 - 6 - 40 = 954 × 1.0',
{ score: '954 / 1000',
size: '32×48', },
time: '180 seconds', {
keystrokes: 200, size: '32×48',
calculation: '1000 - 18 - 100 = 882 × 3.07', time: '180 seconds',
score: '1000 / 1000 (capped)', keystrokes: 200,
}, calculation: '1000 - 18 - 100 = 882 × 3.07',
], score: '1000 / 1000 (capped)',
}, },
],
},
gameOver: { gameOver: {
conditions: [ conditions: [
{ {
type: 'Time Limit', type: 'Custom Condition',
trigger: '10 minutes (600 seconds) by default', trigger: 'Defined via gameOver option in GameOptions',
configurable: true, configurable: true,
message: 'Time ran out!', message: 'Game over!',
description: 'Failed to reach exit with key in time', description: 'Can be a boolean or function that receives scoreManager metrics',
}, },
], ],
note: 'No other game-over conditions - take your time and find the optimal path!', examples: [
}, {
description: 'Time-based (10 minutes)',
code: 'gameOver: (sm) => sm.timeValue >= 600000',
},
{
description: 'Efficiency-based (exceed 150%)',
code: 'gameOver: (sm) => sm.efficiency > 150',
},
{
description: 'Combined condition',
code: 'gameOver: (sm) => sm.efficiency > 150 || sm.timeValue >= 600000',
},
],
note: 'Game-over conditions are flexible and controlled by the game consumer. No built-in limits - define your own rules!',
},
mazeGeneration: { mazeGeneration: {
algorithm: 'Depth-first search with backtracking', algorithm: 'Depth-first search with backtracking',
@@ -123,19 +139,22 @@ export const gameInfo = {
], ],
}, },
metrics: { metrics: {
tracked: [ tracked: [
{ metric: 'Time', unit: 'seconds', description: 'Elapsed time since game start' }, { metric: 'Time', unit: 'milliseconds', description: 'Elapsed time since game start' },
{ metric: 'Keystrokes', unit: 'count', description: 'Total keys pressed' }, { metric: 'Keystrokes', unit: 'count', description: 'Total keys pressed' },
{ metric: 'Distance to Key', unit: 'cells', description: 'Current shortest path to key' }, { metric: 'Optimal Steps', unit: 'cells', description: 'Perfect path length (entrance → key → exit)' },
{ metric: 'Distance to Exit', unit: 'cells', description: 'Current shortest path to exit' }, { metric: 'Efficiency', unit: 'percentage', description: 'Keystroke efficiency ratio (100% = perfect)' },
], { metric: 'Distance to Key', unit: 'cells', description: 'Current shortest path to key' },
displayed: 'Live during gameplay to help you track progress', { metric: 'Distance to Exit', unit: 'cells', description: 'Current shortest path to exit' },
}, ],
available: 'All metrics available via scoreManager for use in scoring or game-over conditions',
displayed: 'Live during gameplay to help you track progress and make decisions',
},
objective: 'Navigate from entrance to key, then from key to exit, before time runs out.', objective: 'Navigate from entrance to key, then from key to exit with a custom game-over condition.',
winCondition: 'Reach the exit cell while holding the key (key must be collected first).', winCondition: 'Reach the exit cell while holding the key (key must be collected first).',
} as const; } as const;
export type GameInfo = typeof gameInfo; export type GameInfo = typeof gameInfo;