public void AiPonderMove() { Thinking = true; ChessBoard.BlackMate = false; ChessBoard.WhiteMate = false; PieceValidMoves.GenerateValidMoves(ChessBoard); NodesSearched = 0; var resultBoards = new ResultBoards { Positions = new List <Board>() }; // First search if human move might have caused a mate if (CheckForMate(WhoseMove, ref ChessBoard)) { Thinking = false; return; } var bestMove = new MoveContent(); //If there is no playbook move search for the best move if (FindPlayBookMove(ref bestMove, ChessBoard, OpeningBook) == false || ChessBoard.HalfMoveClock > 90 || ChessBoard.RepeatedMove >= 2) { if (FindPlayBookMove(ref bestMove, ChessBoard, CurrentGameBook) == false || ChessBoard.HalfMoveClock > 90 || ChessBoard.RepeatedMove >= 2) { bestMove = Search.IterativeSearch( ChessBoard, PlyDepthSearched, ref NodesSearched, ref NodesQuiessence, ref pvLine, ref PlyDepthReached, ref RootMovesSearched, CurrentGameBook); } } //Make the move PreviousChessBoard = new Board(ChessBoard); RootMovesSearched = (byte)resultBoards.Positions.Count; Board.MovePiece(ChessBoard, bestMove.MovingPiecePrimary.SrcPosition, bestMove.MovingPiecePrimary.DstPosition, ChessPieceType.Queen); ChessBoard.LastMove.GeneratePGNString(ChessBoard); FileIO.SaveCurrentGameMove(ChessBoard, PreviousChessBoard, CurrentGameBook, bestMove); for (byte x = 0; x < 64; x++) { var sqr = ChessBoard.Squares[x]; if (sqr.Piece == null) { continue; } sqr.Piece.DefendedValue = 0; sqr.Piece.AttackedValue = 0; } PieceValidMoves.GenerateValidMoves(ChessBoard); Evaluation.EvaluateBoardScore(ChessBoard); PieceTakenAdd(ChessBoard.LastMove); MoveHistory.Push(ChessBoard.LastMove); //Second Call if computer move might have caused a mate if (CheckForMate(WhoseMove, ref ChessBoard)) { Thinking = false; if (ChessBoard.WhiteMate || ChessBoard.BlackMate) { LastMove.PgnMove += "#"; } return; } if (ChessBoard.WhiteCheck || ChessBoard.BlackCheck) { LastMove.PgnMove += "+"; } Thinking = false; }
//Quiescence Search private static int Quiescence(Board examineBoard, int alpha, int beta, ref int nodesSearched) { nodesSearched++; //Evaluate Score Evaluation.EvaluateBoardScore(examineBoard); //Invert Score to support Negamax examineBoard.Score = SideToMoveScore(examineBoard.Score, examineBoard.WhoseMove); if (examineBoard.Score >= beta) { return(beta); } if (examineBoard.Score > alpha) { alpha = examineBoard.Score; } List <Position> positions; if (examineBoard.WhiteCheck || examineBoard.BlackCheck) { positions = EvaluateMoves(examineBoard, 0); } else { positions = EvaluateMovesQ(examineBoard); } if (positions.Count == 0) { return(examineBoard.Score); } positions.Sort(Sort); foreach (var move in positions) { if (StaticExchangeEvaluation(examineBoard.Squares[move.DstPosition]) >= 0) { continue; } //Make a copy var board = examineBoard.FastCopy(); //Move Piece Board.MovePiece(board, move.SrcPosition, move.DstPosition, ChessPieceType.Queen); //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(board); if (board.BlackCheck) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { continue; } } if (board.WhiteCheck) { if (examineBoard.WhoseMove == ChessPieceColor.White) { continue; } } var value = -Quiescence(board, -beta, -alpha, ref nodesSearched); if (value >= beta) { KillerMove[2, 0].SrcPosition = move.SrcPosition; KillerMove[2, 0].DstPosition = move.DstPosition; return(beta); } if (value > alpha) { alpha = value; } } return(alpha); }
// Not used anymore // ReSharper disable once UnusedMember.Local private static int MinMax(Board examineBoard, byte depth) { if (depth == 0) { //Evaluate Score Evaluation.EvaluateBoardScore(examineBoard); //Invert Score to support Negamax return(SideToMoveScore(examineBoard.Score, examineBoard.WhoseMove)); } var positions = EvaluateMoves(examineBoard, depth); if (examineBoard.WhiteCheck || examineBoard.BlackCheck || positions.Count == 0) { if (SearchForMate(examineBoard.WhoseMove, examineBoard, ref examineBoard.BlackMate, ref examineBoard.WhiteMate, ref examineBoard.StaleMate)) { if (examineBoard.BlackMate) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { return(-32767 - depth); } return(32767 + depth); } // ReSharper disable once InvertIf if (examineBoard.WhiteMate) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { return(32767 + depth); } return(-32767 - depth); } //If Not Mate then StaleMate return(0); } } var bestScore = -32767; foreach (var move in positions) { //Make a copy var board = examineBoard.FastCopy(); //Move Piece Board.MovePiece(board, move.SrcPosition, move.DstPosition, ChessPieceType.Queen); //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(board); if (board.BlackCheck) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { continue; } } if (board.WhiteCheck) { if (examineBoard.WhoseMove == ChessPieceColor.White) { continue; } } var value = -MinMax(board, (byte)(depth - 1)); if (value > bestScore) { bestScore = value; } } return(bestScore); }
// Not used anymore // ReSharper disable once UnusedMember.Local private static int AlphaBeta(Board examineBoard, byte depth, int alpha, int beta, ref int nodesSearched) { nodesSearched++; if (examineBoard.HalfMoveClock >= 100 || examineBoard.RepeatedMove >= 3) { return(0); } if (depth == 0) { //Evaluate Score Evaluation.EvaluateBoardScore(examineBoard); //Invert Score to support Negamax return(SideToMoveScore(examineBoard.Score, examineBoard.WhoseMove)); } var positions = EvaluateMoves(examineBoard, depth); if (examineBoard.WhiteCheck || examineBoard.BlackCheck || positions.Count == 0) { if (SearchForMate(examineBoard.WhoseMove, examineBoard, ref examineBoard.BlackMate, ref examineBoard.WhiteMate, ref examineBoard.StaleMate)) { if (examineBoard.BlackMate) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { return(-32767 - depth); } return(32767 + depth); } // ReSharper disable once InvertIf if (examineBoard.WhiteMate) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { return(32767 + depth); } return(-32767 - depth); } //If Not Mate then StaleMate return(0); } } positions.Sort(Sort); foreach (var move in positions) { //Make a copy var board = examineBoard.FastCopy(); //Move Piece Board.MovePiece(board, move.SrcPosition, move.DstPosition, ChessPieceType.Queen); //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(board); if (board.BlackCheck) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { continue; } } if (board.WhiteCheck) { if (examineBoard.WhoseMove == ChessPieceColor.White) { continue; } } var value = -AlphaBeta(board, (byte)(depth - 1), -beta, -alpha, ref nodesSearched); if (value >= beta) { return(beta); } if (value > alpha) { alpha = value; } } return(alpha); }
private static ResultBoards GetSortValidMoves(Board examineBoard) { var sortValidMoves = new ResultBoards { Positions = new List <Board>(30) }; piecesRemaining = 0; for (byte x = 0; x < 64; x++) { var sqr = examineBoard.Squares[x]; //Make sure there is a piece on the square if (sqr.Piece == null) { continue; } piecesRemaining++; //Make sure the color is the same color as the one we are moving. if (sqr.Piece.PieceColor != examineBoard.WhoseMove) { continue; } //For each valid move for this piece foreach (var dst in sqr.Piece.ValidMoves) { //We make copies of the board and move so that we can move it without effecting the parent board var board = examineBoard.FastCopy(); //Make move so we can examine it Board.MovePiece(board, x, dst, ChessPieceType.Queen); //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(board); //Invalid Move if (board.WhiteCheck && examineBoard.WhoseMove == ChessPieceColor.White) { continue; } //Invalid Move if (board.BlackCheck && examineBoard.WhoseMove == ChessPieceColor.Black) { continue; } //We calculate the board score Evaluation.EvaluateBoardScore(board); //Invert Score to support Negamax board.Score = SideToMoveScore(board.Score, board.WhoseMove); sortValidMoves.Positions.Add(board); } } sortValidMoves.Positions.Sort(Sort); return(sortValidMoves); }