Deep dive into the chess engine, state management, and real-time analysis that powers ChessMaster.
ChessMaster Game Architecture:
├── State Management (Zustand Store)
│ ├── Chess Game State
│ ├── UI State
│ └── Analysis State
├── Chess Logic Layer
│ ├── Move Validation
│ ├── Game Rules
│ └── Position Management
├── AI Analysis Engine
│ ├── Stockfish Integration
│ ├── Real-time Analysis
│ └── Move Suggestions
└── Practice System
├── Session Tracking
├── Progress Saving
└── Opening DatabaseChessMaster uses a centralized Zustand store to manage complex chess game state, UI state, and analysis data in a type-safe manner.
interface ChessGameState {
// Game Engine
chessGame: Chess; // chess.js instance
chessPosition: string; // Current FEN position
movesHistory: string[]; // Move history in SAN
// Move Interaction
moveFrom: string; // Selected square for move
optionSquares: Record<string, any>; // Highlighted possible moves
// Analysis & AI
moveAnalysis: StockfishAnalysis | null;
isAnalyzing: boolean;
isCpuThinking: boolean;
bestMove: string;
bestEnemyMove: string;
// Game State
gameOver: { isOver: boolean; result?: string };
relatedOpenings: Opening[];
// UI State
isFullscreen: boolean;
settings: GameSettings;
}makeMove() - Validate & execute movesresetBoard() - Reset to initial positionloadOpeningPosition() - Load specific FENonPieceDrop() - Handle drag & drop movesonSquareClick() - Handle square selectiongetMoveOptions() - Show possible movessetIsFullscreen() - Toggle fullscreen modeupdateSettings() - Modify user preferencesUser clicks square or drags piece
chess.js validates move against game rules
Update FEN, move history, and game state
Kick off real-time position analysis
// Core move validation and execution
makeMove: (from, to, promotion = 'q') => {
const state = get();
try {
// Validate and execute move using chess.js
state.chessGame.move({ from, to, promotion });
const newFen = state.chessGame.fen();
const newHistory = state.chessGame.history();
// Update all related state
set({
chessPosition: newFen,
movesHistory: newHistory,
moveFrom: '',
optionSquares: {},
});
return true;
} catch {
return false; // Invalid move
}
},
// Handle piece drop from react-chessboard
onPieceDrop: ({sourceSquare, targetSquare}) => {
const state = get();
const { settings, isCpuThinking } = state;
// Prevent moves during CPU thinking
const currentTurn = state.chessGame.turn();
const isCpuTurn = (currentTurn === "w" && settings.cpuSide === "white") ||
(currentTurn === "b" && settings.cpuSide === "black");
if (isCpuTurn || isCpuThinking) return false;
// Execute the move
return state.makeMove(sourceSquare, targetSquare, "q");
}// Real-time position analysis
const analyzePosition = async (fen: string) => {
if (isCpuThinking) return;
setIsAnalyzing(true);
try {
// External Stockfish API call
const response = await fetch(
`https://stockfish.online/api/s/v2.php?fen=${encodeURIComponent(
fen
)}&depth=${settings?.analysisDepth || 11}`
);
const data = await response.json();
if (data.success) {
const bestMoveParts = data.bestmove?.split(" ") || [];
const analysis: StockfishAnalysis = {
bestMove: bestMoveParts[1] || "", // Best move for current player
ponder: bestMoveParts[3] || "", // Expected opponent response
evaluation: data.evaluation || "0", // Position evaluation (cp)
continuation: data.continuation || "", // Suggested line
mate: data.mate, // Mate in X moves if available
};
setMoveAnalysis(analysis);
}
} catch (error) {
console.error("Error analyzing position:", error);
} finally {
setIsAnalyzing(false);
}
};// Practice session data saved to database
interface PracticeSessionData {
moves: string; // "e4 e5 Nf3 Nc6 Bb5" - moves in SAN
finalFen: string; // Final position after moves
movesCount: number; // Total moves in session
openingId?: string; // Optional reference to opening
}
// Database model
model PracticeSession {
id String @id @default(cuid())
user User @relation(fields: [userId])
userId String
opening Opening? @relation(fields: [openingId])
openingId String?
moves String // Moves in SAN notation
finalFen String // Final position
movesCount Int // Number of moves
createdAt DateTime @default(now())
}User clicks "Save Session" button
Check if moves exist and user is authenticated
Send session data to /api/user/practice-sessions
Store session with user relationship
Chess Game Engine Stack: ├── chess.js (v^1.0.0) - Chess rules & move validation ├── react-chessboard (v^5.0.0) - Interactive chess board UI ├── Stockfish API - AI analysis & engine moves ├── Zustand (v^4.0.0) - State management ├── React Hooks - Component lifecycle & effects └── TypeScript - Type safety & developer experience