Skip to content

Commit 3920441

Browse files
Fix RPS game complete bug, and add number of rounds support
1 parent 41b8c01 commit 3920441

File tree

5 files changed

+36
-14
lines changed

5 files changed

+36
-14
lines changed

mcp-server/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515
"allowSyntheticDefaultImports": true
1616
},
1717
"include": ["src/**/*"],
18-
"exclude": ["dist", "node_modules"]
18+
"exclude": ["dist", "node_modules", "**/*.test.ts", "**/*.test.tsx"]
1919
}

shared/src/games/rock-paper-scissors.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,18 +211,19 @@ export class RockPaperScissorsGame implements Game<RPSGameState, RPSMove> {
211211
* Creates the initial game state for a new rock-paper-scissors game
212212
*
213213
* @param players - Array of exactly 2 players
214-
* @returns Initial RPSGameState set up for a best-of-3 match
214+
* @param options - Optional configuration including maxRounds
215+
* @returns Initial RPSGameState set up for a configurable number of rounds
215216
*
216217
* @description
217218
* Sets up a new game with:
218-
* - 3 empty rounds (best-of-3 format)
219+
* - Configurable number of rounds (default: 3 for best-of-3 format)
219220
* - All scores initialized to 0
220221
* - First player goes first
221222
* - Game status set to 'playing'
222223
* - Current round set to 0
223224
*/
224-
getInitialState(players: Player[], options?: any): RPSGameState {
225-
const maxRounds = 3; // Best of 3
225+
getInitialState(players: Player[], options?: { maxRounds?: number }): RPSGameState {
226+
const maxRounds = options?.maxRounds || 3; // Default to best of 3
226227
const rounds = Array.from({ length: maxRounds }, () => ({}));
227228

228229
const scores: Record<string, number> = {};

web/src/app/api/games/rock-paper-scissors/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ const rpsGame = new RockPaperScissorsGame()
88

99
export async function POST(request: NextRequest) {
1010
try {
11-
const { playerName, gameId, aiDifficulty } = await request.json()
11+
const { playerName, gameId, aiDifficulty, maxRounds } = await request.json()
1212

1313
const players: Player[] = [
1414
{ id: 'player1', name: playerName || 'Player', isAI: false },
1515
{ id: 'ai', name: 'AI', isAI: true }
1616
]
1717

18-
const gameState = rpsGame.getInitialState(players)
18+
const gameState = rpsGame.getInitialState(players, { maxRounds })
1919

2020
// Use custom gameId if provided
2121
if (gameId) {

web/src/app/games/rock-paper-scissors/page.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { GameInfoPanel } from '../../../components/games/GameInfoPanel'
66
import { GameContainer, GameControls, ConfirmationModal } from '../../../components/ui'
77
import { MCPAssistantPanel } from '../../../components/shared'
88
import type { RPSGameState, RPSMove } from '@turn-based-mcp/shared'
9-
import type { GameSession } from '@turn-based-mcp/shared'
9+
import type { GameSession, Difficulty } from '@turn-based-mcp/shared'
1010

1111
export default function RockPaperScissorsPage() {
1212
const [gameSession, setGameSession] = useState<GameSession<RPSGameState> | null>(null)
@@ -16,7 +16,8 @@ export default function RockPaperScissorsPage() {
1616
const [availableGames, setAvailableGames] = useState<GameSession<RPSGameState>[]>([])
1717
const [showCreateForm, setShowCreateForm] = useState(false)
1818
const [showJoinForm, setShowJoinForm] = useState(false)
19-
const [aiDifficulty, setAiDifficulty] = useState<'easy' | 'medium' | 'hard'>('medium')
19+
const [aiDifficulty, setAiDifficulty] = useState<Difficulty>('medium')
20+
const [maxRounds, setMaxRounds] = useState<number>(3)
2021
const [gamesToShow, setGamesToShow] = useState(5)
2122
const [showDeleteModal, setShowDeleteModal] = useState(false)
2223
const [gameToDelete, setGameToDelete] = useState<string | null>(null)
@@ -79,9 +80,10 @@ export default function RockPaperScissorsPage() {
7980
setError(null)
8081

8182
try {
82-
const body: { playerName: string; gameId?: string; aiDifficulty: string } = {
83+
const body: { playerName: string; gameId?: string; aiDifficulty: string; maxRounds: number } = {
8384
playerName: 'Player',
84-
aiDifficulty
85+
aiDifficulty,
86+
maxRounds
8587
}
8688
if (customGameId) {
8789
body.gameId = customGameId
@@ -280,7 +282,7 @@ export default function RockPaperScissorsPage() {
280282
<>
281283
<GameContainer
282284
title="Rock Paper Scissors"
283-
description="Best of 3 rounds! Rock beats Scissors, Scissors beats Paper, Paper beats Rock."
285+
description={`Play ${gameSession.gameState.maxRounds} round${gameSession.gameState.maxRounds !== 1 ? 's' : ''}! Rock beats Scissors, Scissors beats Paper, Paper beats Rock.`}
284286
gameBoard={gameBoard}
285287
sidebar={sidebar}
286288
error={error}
@@ -439,6 +441,22 @@ export default function RockPaperScissorsPage() {
439441
<option value="hard">🔴 Hard - Advanced pattern recognition</option>
440442
</select>
441443
</div>
444+
<div>
445+
<label className="block text-sm font-semibold text-slate-700 dark:text-slate-300 mb-2">
446+
Number of Rounds
447+
</label>
448+
<select
449+
value={maxRounds}
450+
onChange={(e) => setMaxRounds(parseInt(e.target.value))}
451+
className="w-full px-4 py-3 bg-white/60 dark:bg-slate-700/60 border border-slate-200 dark:border-slate-600 rounded-xl focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent transition-all duration-200"
452+
>
453+
<option value={1}>1 Round</option>
454+
<option value={3}>3 Rounds (Best of 3)</option>
455+
<option value={5}>5 Rounds (Best of 5)</option>
456+
<option value={7}>7 Rounds (Best of 7)</option>
457+
<option value={10}>10 Rounds</option>
458+
</select>
459+
</div>
442460
<div>
443461
<label className="block text-sm font-semibold text-slate-700 dark:text-slate-300 mb-2">
444462
Custom Game ID (optional)
@@ -534,7 +552,7 @@ export default function RockPaperScissorsPage() {
534552
<>
535553
<GameContainer
536554
title="Rock Paper Scissors"
537-
description="Best of 3 rounds! Rock beats Scissors, Scissors beats Paper, Paper beats Rock."
555+
description={`Play ${maxRounds} round${maxRounds !== 1 ? 's' : ''}! Rock beats Scissors, Scissors beats Paper, Paper beats Rock.`}
538556
gameBoard={gameSetupContent}
539557
sidebar={<div></div>} // Empty sidebar for setup
540558
error={error}

web/src/components/games/RPSGameBoard.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ export function RPSGameBoard({ gameState, onMove, disabled }: RPSGameBoardProps)
108108

109109
<div className="text-center mb-6">
110110
<h2 className="text-xl font-semibold text-gray-800 dark:text-gray-200 mb-2">
111-
Round {gameState.currentRound + 1} of {gameState.maxRounds}
111+
{gameState.status === 'finished' ?
112+
`Game Complete (${gameState.currentRound} of ${gameState.maxRounds} rounds played)` :
113+
`Round ${gameState.currentRound + 1} of ${gameState.maxRounds}`
114+
}
112115
</h2>
113116

114117
{gameState.status === 'playing' && (

0 commit comments

Comments
 (0)