UNPKG

tmemory

Version:

A terminal-based Memory card game built with React Ink. Features multiple grid sizes, AI opponent, and high scores.

127 lines (126 loc) 5.47 kB
import { Box, Text, useInput } from 'ink'; import BigText from 'ink-big-text'; import Gradient from 'ink-gradient'; import React from 'react'; import { GameLayout } from '../../components/layout/GameLayout.js'; import { COLORS } from '../../constants/colors.js'; import { ALL_PRESET_GRIDS, isValidGrid } from '../../constants/gridPresets.js'; import { useGame } from '../../context/GameContext/index.js'; import { useHighScores } from '../../context/HighScoreContext/index.js'; import { Controls } from './components/Controls.js'; import { GameModeSelect } from './components/GameModeSelect.js'; import { GridSizeConfig } from './components/GridSizeConfig.js'; import { HighScoreDisplay } from './components/HighScoreDisplay.js'; export const MainMenu = () => { const { onlineEnabled, setOnlineEnabled } = useHighScores(); const { state, dispatch } = useGame(); useInput((input, key) => { if (input === 'm' || input === 'M') { dispatch({ type: 'SET_GRID_SELECTION_MODE', payload: state.gridSelectionMode === 'preset' ? 'custom' : 'preset', }); return; } if (input.toLowerCase() === 'l') { dispatch({ type: 'SET_GAME_STATE', payload: 'leaderboard' }); return; } if (input.toLowerCase() === 'o') { setOnlineEnabled(!onlineEnabled); return; } if (input === 'g' || input === 'G') { const nextMode = (() => { switch (state.gameMode) { case 'single': return 'vs-player'; case 'vs-player': return 'vs-ai'; case 'vs-ai': return 'single'; } })(); dispatch({ type: 'SET_GAME_MODE', payload: nextMode }); return; } if (state.gridSelectionMode === 'preset') { if (key.upArrow && state.currentPresetIndex < ALL_PRESET_GRIDS.length - 1) { const nextIndex = state.currentPresetIndex + 1; const nextGrid = ALL_PRESET_GRIDS[nextIndex]; if (nextGrid) { dispatch({ type: 'SET_CURRENT_PRESET_INDEX', payload: nextIndex }); dispatch({ type: 'SET_GRID_DIMENSION', payload: nextGrid }); } } else if (key.downArrow && state.currentPresetIndex > 0) { const nextIndex = state.currentPresetIndex - 1; const nextGrid = ALL_PRESET_GRIDS[nextIndex]; if (nextGrid) { dispatch({ type: 'SET_CURRENT_PRESET_INDEX', payload: nextIndex }); dispatch({ type: 'SET_GRID_DIMENSION', payload: nextGrid }); } } } else { // Custom mode if (key.leftArrow) { const next = { ...state.gridDimension, cols: Math.max(state.gridDimension.cols - 1, 1), }; if (isValidGrid(next)) { dispatch({ type: 'SET_GRID_DIMENSION', payload: next }); } } else if (key.rightArrow) { const next = { ...state.gridDimension, cols: Math.min(state.gridDimension.cols + 1, 12), }; if (isValidGrid(next)) { dispatch({ type: 'SET_GRID_DIMENSION', payload: next }); } } else if (key.upArrow) { const next = { ...state.gridDimension, rows: Math.min(state.gridDimension.rows + 1, 12), }; if (isValidGrid(next)) { dispatch({ type: 'SET_GRID_DIMENSION', payload: next }); } } else if (key.downArrow) { const next = { ...state.gridDimension, rows: Math.max(state.gridDimension.rows - 1, 1), }; if (isValidGrid(next)) { dispatch({ type: 'SET_GRID_DIMENSION', payload: next }); } } } if (input === ' ' || key.return) { dispatch({ type: 'START_NEW_GAME' }); } }); const { gameMode, gridDimension, gridSelectionMode } = state; return (React.createElement(GameLayout, null, React.createElement(Box, { height: 6 }, React.createElement(Gradient, { name: "mind" }, React.createElement(BigText, { text: "Memory" }))), React.createElement(GameModeSelect, { currentMode: gameMode }), React.createElement(GridSizeConfig, { gridDimension: gridDimension, selectionMode: gridSelectionMode }), React.createElement(HighScoreDisplay, { gameMode: gameMode, gridDimension: gridDimension }), React.createElement(Controls, { gridSelectionMode: gridSelectionMode, onlineEnabled: onlineEnabled }), React.createElement(Box, { marginTop: 1 }, React.createElement(Text, { color: COLORS.dim }, "Press", ' ', React.createElement(Gradient, { name: "cristal" }, React.createElement(Text, { bold: true }, "Space")), ' ', "to begin!")))); };