public ChessMoveResult AsyncCalculateAiSimpleMove(ChessAiAsyncTurnKey key, ref ChessPieceCoord from, ref ChessPieceCoord to) { var color = Turn; var bestBoardScore = 0.0f; ChessMove bestMove = null; var storage = new List <ChessMove>(); GenerateMoves(color, storage); var nonCheckMoves = new List <ChessMove>(); foreach (var generatedMove in storage) { // no need to evaluate the board if the ai has checkmated the other player var result = FinalizeMove(generatedMove); if (result.HasFlag(ChessMoveResult.OKMoveCheckmate)) { from = generatedMove.From; to = generatedMove.To; return(result); } if (!InCheck(color)) { var boardScore = EvaluateBoard(); if (boardScore > bestBoardScore) { bestMove = generatedMove; bestBoardScore = boardScore; } nonCheckMoves.Add(generatedMove); } UndoMove(1); } // every generated move had the same board score, pick one at random // this shouldn't happen, just here to prevent crash if (bestMove == null && nonCheckMoves.Count > 0) { var rng = ThreadSafeRandom.Next(0, nonCheckMoves.Count - 1); rng = 0; // easier debugging bestMove = nonCheckMoves[rng]; } // checkmate / stalemate if (bestMove == null) { return(ChessMoveResult.NoMoveResult); } from = bestMove.From; to = bestMove.To; return(FinalizeMove(bestMove)); }
public void StartAiMove() { Debug.Assert(AiState == ChessAiState.WaitingToStart); AiState = ChessAiState.WaitingForWorker; // todo: execute ai work on a separate thread var key = new ChessAiAsyncTurnKey(); AiFuture = new ChessAiMoveResult(); AsyncMoveAiSimple(key, AiFuture); }
public void AsyncMoveAiSimple(ChessAiAsyncTurnKey key, ChessAiMoveResult result) { Debug.Assert(AiState == ChessAiState.WaitingForWorker); AiState = ChessAiState.InProgress; ChessPieceCoord from = null, to = null; var moveResult = Logic.AsyncCalculateAiSimpleMove(key, ref from, ref to); result.SetResult(moveResult, from, to); AiState = ChessAiState.WaitingForFinish; }
public void AsyncMoveAiComplex(ChessAiAsyncTurnKey key, ChessAiMoveResult result) { Debug.Assert(AiState == ChessAiState.WaitingForWorker); AiState = ChessAiState.InProgress; ChessPieceCoord from = null, to = null; uint counter = 0; var moveResult = Logic.AsyncCalculateAiComplexMove(key, ref from, ref to, ref counter); result.SetResult(moveResult, from, to); result.ProfilingCounter = counter; AiState = ChessAiState.WaitingForFinish; }
public ChessMoveResult AsyncCalculateAiComplexMove(ChessAiAsyncTurnKey key, ref ChessPieceCoord from, ref ChessPieceCoord to, ref uint counter) { uint depth = 3; var isMaximizingPower = true; var storage = new List <ChessMove>(); GenerateMoves(Turn, storage); var bestBoardScore = -9999.0f; ChessMove bestMove = null; foreach (var generatedMove in storage) { // no need to evaluate the board if the ai has checkmated the other player var result = FinalizeMove(generatedMove); if (result.HasFlag(ChessMoveResult.OKMoveCheckmate)) { from = generatedMove.From; to = generatedMove.To; return(result); } var boardScore = MinimaxAlphaBeta(depth - 1, -10000, 10000, !isMaximizingPower, ref counter); UndoMove(1); if (boardScore >= bestBoardScore) { bestMove = generatedMove; bestBoardScore = boardScore; } } // ever generated move had the same board score, pick one at random // this shouldn't happen, just here to prevent crash if (bestMove == null && storage.Count > 0) { var rng = ThreadSafeRandom.Next(0, storage.Count - 1); bestMove = storage[rng]; } Debug.Assert(bestMove != null); from = bestMove.From; to = bestMove.To; return(FinalizeMove(bestMove)); }