public bool MovePiece(byte srcPosition, byte dstPosition) { Piece piece = ChessBoard.Squares[srcPosition].Piece; PreviousChessBoard = new Board(ChessBoard); UndoChessBoard = new Board(ChessBoard); UndoGameBook = new Book(CurrentGameBook); ChessBoard.MovePiece(srcPosition, dstPosition, PromoteToPieceType); ChessBoard.LastMove.GeneratePGNString(ChessBoard); GenerateValidMoves(); ChessBoard.EvaluateBoardScore(); //If there is a check in place, check if this is still true; if (piece.PieceColor == ChessPieceColor.White) { if (ChessBoard.WhiteCheck) { //Invalid Move ChessBoard = new Board(PreviousChessBoard); ChessBoard.GenerateValidMoves(); return(false); } } else if (piece.PieceColor == ChessPieceColor.Black) { if (ChessBoard.BlackCheck) { //Invalid Move ChessBoard = new Board(PreviousChessBoard); ChessBoard.GenerateValidMoves(); return(false); } } MoveHistory.Push(ChessBoard.LastMove); FileIO.SaveCurrentGameMove(ChessBoard, PreviousChessBoard, CurrentGameBook, ChessBoard.LastMove); CheckForMate(WhoseMove, ref ChessBoard); PieceTakenAdd(ChessBoard.LastMove); if (ChessBoard.WhiteMate || ChessBoard.BlackMate) { LastMove.PgnMove += "#"; } else if (ChessBoard.WhiteCheck || ChessBoard.BlackCheck) { LastMove.PgnMove += "+"; } return(true); }
private static ResultBoards GetSortValidMoves(Board examineBoard) { ResultBoards resultBoards = new ResultBoards() { Positions = new List <Board>(30) }; Search.piecesRemaining = 0; for (byte srcPosition = 0; (int)srcPosition < 64; ++srcPosition) { Square square = examineBoard.Squares[(int)srcPosition]; if (square.Piece != null) { ++Search.piecesRemaining; if (square.Piece.PieceColor == examineBoard.WhoseMove) { foreach (byte validMove in square.Piece.ValidMoves) { Board board = examineBoard.FastCopy(); Board.MovePiece(board, srcPosition, validMove, ChessPieceType.Queen); PieceValidMoves.GenerateValidMoves(board); if ((!board.WhiteCheck || examineBoard.WhoseMove != ChessPieceColor.White) && (!board.BlackCheck || examineBoard.WhoseMove != ChessPieceColor.Black)) { Evaluation.EvaluateBoardScore(board); board.Score = Search.SideToMoveScore(board.Score, board.WhoseMove); resultBoards.Positions.Add(board); } } } } } resultBoards.Positions.Sort(new Comparison <Board>(Search.Sort)); return(resultBoards); }
private static ResultBoards GetPossibleBoards(ChessPieceColor movingSide, Board examineBoard) { //We are going to store our result boards here resultBoards = new ResultBoards { Positions = new List <Board>() }; for (byte x = 0; x < 64; x++) { Square sqr = examineBoard.Squares[x]; //Make sure there is a piece on the square if (sqr.Piece == null) { continue; } //Make sure the color is the same color as the one we are moving. if (sqr.Piece.PieceColor != movingSide) { continue; } //For each valid move for this piece foreach (byte dst in sqr.Piece.ValidMoves) { //We make copies of the board and move so that we can move it without effecting the parent board Board 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); if (board.BlackCheck && movingSide == ChessPieceColor.Black) { continue; } if (board.WhiteCheck && movingSide == ChessPieceColor.White) { continue; } //We calculate the board score Evaluation.EvaluateBoardScore(board); //Invert Score to support Negamax board.Score = SideToMoveScore(board.Score, GetOppositeColor(movingSide)); resultBoards.Positions.Add(board); } } return(resultBoards); }
internal static bool SearchForMate(ChessPieceColor movingSide, Board examineBoard, ref bool blackMate, ref bool whiteMate, ref bool staleMate) { bool flag1 = false; bool flag2 = false; for (byte srcPosition = 0; (int)srcPosition < 64; ++srcPosition) { Square square = examineBoard.Squares[(int)srcPosition]; if (square.Piece != null && square.Piece.PieceColor == movingSide) { foreach (byte validMove in square.Piece.ValidMoves) { Board board = examineBoard.FastCopy(); Board.MovePiece(board, srcPosition, validMove, ChessPieceType.Queen); PieceValidMoves.GenerateValidMoves(board); if (!board.BlackCheck) { flag1 = true; } else if (movingSide == ChessPieceColor.Black) { continue; } if (!board.WhiteCheck) { flag2 = true; } } } } if (!flag1) { if (examineBoard.BlackCheck) { blackMate = true; return(true); } if (!examineBoard.WhiteMate && movingSide != ChessPieceColor.White) { staleMate = true; return(true); } } if (!flag2) { if (examineBoard.WhiteCheck) { whiteMate = true; return(true); } if (!examineBoard.BlackMate && movingSide != ChessPieceColor.Black) { staleMate = true; return(true); } } return(false); }
public void AiPonderMove(BackgroundWorker worker) { this.Thinking = true; this.NodesSearched = 0; ResultBoards resultBoards = new ResultBoards(); resultBoards.Positions = new List <Board>(); if (ChessEngine.Engine.Engine.CheckForMate(this.WhoseMove, ref this.ChessBoard)) { this.Thinking = false; } else { MoveContent bestMove = new MoveContent(); if ((!ChessEngine.Engine.Engine.FindPlayBookMove(ref bestMove, this.ChessBoard, (IEnumerable <OpeningMove>) this.OpeningBook) || (int)this.ChessBoard.FiftyMove > 45 || (int)this.ChessBoard.RepeatedMove >= 2) && (!ChessEngine.Engine.Engine.FindPlayBookMove(ref bestMove, this.ChessBoard, (IEnumerable <OpeningMove>) this.CurrentGameBook) || (int)this.ChessBoard.FiftyMove > 45 || (int)this.ChessBoard.RepeatedMove >= 2)) { bestMove = Search.IterativeSearch(this.ChessBoard, this.PlyDepthSearched, ref this.NodesSearched, ref this.NodesQuiessence, ref this.pvLine, worker, ref this.PlyDepthReached, ref this.RootMovesSearched, this.CurrentGameBook); } this.PreviousChessBoard = new Board(this.ChessBoard); this.RootMovesSearched = (byte)resultBoards.Positions.Count; Board.MovePiece(this.ChessBoard, bestMove.MovingPiecePrimary.SrcPosition, bestMove.MovingPiecePrimary.DstPosition, ChessPieceType.Queen); this.ChessBoard.LastMove.GeneratePGNString(this.ChessBoard); for (byte index = 0; (int)index < 64; ++index) { Square square = this.ChessBoard.Squares[(int)index]; if (square.Piece != null) { square.Piece.DefendedValue = (short)0; square.Piece.AttackedValue = (short)0; } } PieceValidMoves.GenerateValidMoves(this.ChessBoard); Evaluation.EvaluateBoardScore(this.ChessBoard); this.PieceTakenAdd(this.ChessBoard.LastMove); this.MoveHistory.Push(this.ChessBoard.LastMove); if (ChessEngine.Engine.Engine.CheckForMate(this.WhoseMove, ref this.ChessBoard)) { this.Thinking = false; if (!this.ChessBoard.WhiteMate && !this.ChessBoard.BlackMate) { return; } this.LastMove.PgnMove += "#"; } else { if (this.ChessBoard.WhiteCheck || this.ChessBoard.BlackCheck) { this.LastMove.PgnMove += "+"; } this.Thinking = false; } } }
public bool MovePiece(byte sourceColumn, byte sourceRow, byte destinationColumn, byte destinationRow) { byte srcPosition = (byte)(sourceColumn + (sourceRow * 8)); byte dstPosition = (byte)(destinationColumn + (destinationRow * 8)); Piece piece = ChessBoard.Squares[srcPosition].Piece; _previousChessBoard = new Board(ChessBoard); Board.MovePiece(ChessBoard, srcPosition, dstPosition, ChessPieceType.Queen); PieceMoveVaidation.GenerateValidMoves(ChessBoard); switch (piece.PieceColor) { //If there is a check in place, check if this is still true; case ChessPieceColor.White: { if (ChessBoard.WhiteCheck) { //Invalid Move ChessBoard = new Board(_previousChessBoard); PieceMoveVaidation.GenerateValidMoves(ChessBoard); return(false); } break; } case ChessPieceColor.Black: { if (ChessBoard.BlackCheck) { //Invalid Move ChessBoard = new Board(_previousChessBoard); PieceMoveVaidation.GenerateValidMoves(ChessBoard); return(false); } break; } default: throw new ArgumentOutOfRangeException("ChessPieceColor ", " is not valid"); } return(true); }
private static int Quiescence(Board examineBoard, int alpha, int beta, ref int nodesSearched) { nodesSearched = nodesSearched + 1; Evaluation.EvaluateBoardScore(examineBoard); examineBoard.Score = Search.SideToMoveScore(examineBoard.Score, examineBoard.WhoseMove); if (examineBoard.Score >= beta) { return(beta); } if (examineBoard.Score > alpha) { alpha = examineBoard.Score; } List <Search.Position> positionList = examineBoard.WhiteCheck || examineBoard.BlackCheck ? Search.EvaluateMoves(examineBoard, (byte)0) : Search.EvaluateMovesQ(examineBoard); if (positionList.Count == 0) { return(examineBoard.Score); } positionList.Sort(new Comparison <Search.Position>(Search.Sort)); foreach (Search.Position position in positionList) { if (Search.StaticExchangeEvaluation(examineBoard.Squares[(int)position.DstPosition]) < 0) { Board board = examineBoard.FastCopy(); Board.MovePiece(board, position.SrcPosition, position.DstPosition, ChessPieceType.Queen); PieceValidMoves.GenerateValidMoves(board); if ((!board.BlackCheck || examineBoard.WhoseMove != ChessPieceColor.Black) && (!board.WhiteCheck || examineBoard.WhoseMove != ChessPieceColor.White)) { int num = -Search.Quiescence(board, -beta, -alpha, ref nodesSearched); if (num >= beta) { Search.KillerMove[2, 0].SrcPosition = position.SrcPosition; Search.KillerMove[2, 0].DstPosition = position.DstPosition; return(beta); } if (num > alpha) { alpha = num; } } } } return(alpha); }
public bool MovePiece(byte srcPosition, byte dstPosition) { Piece piece = this.ChessBoard.Squares[(int)srcPosition].Piece; this.PreviousChessBoard = new Board(this.ChessBoard); this.UndoChessBoard = new Board(this.ChessBoard); this.UndoGameBook = new List <OpeningMove>((IEnumerable <OpeningMove>) this.CurrentGameBook); Board.MovePiece(this.ChessBoard, srcPosition, dstPosition, this.PromoteToPieceType); this.ChessBoard.LastMove.GeneratePGNString(this.ChessBoard); PieceValidMoves.GenerateValidMoves(this.ChessBoard); Evaluation.EvaluateBoardScore(this.ChessBoard); if (piece.PieceColor == ChessPieceColor.White) { if (this.ChessBoard.WhiteCheck) { this.ChessBoard = new Board(this.PreviousChessBoard); PieceValidMoves.GenerateValidMoves(this.ChessBoard); return(false); } } else if (piece.PieceColor == ChessPieceColor.Black && this.ChessBoard.BlackCheck) { this.ChessBoard = new Board(this.PreviousChessBoard); PieceValidMoves.GenerateValidMoves(this.ChessBoard); return(false); } this.MoveHistory.Push(this.ChessBoard.LastMove); ChessEngine.Engine.Engine.CheckForMate(this.WhoseMove, ref this.ChessBoard); this.PieceTakenAdd(this.ChessBoard.LastMove); if (this.ChessBoard.WhiteMate || this.ChessBoard.BlackMate) { this.LastMove.PgnMove += "#"; } else if (this.ChessBoard.WhiteCheck || this.ChessBoard.BlackCheck) { this.LastMove.PgnMove += "+"; } return(true); }
public bool MovePiece(byte sourceColumn, byte sourceRow, byte destinationColumn, byte destinationRow) { byte srcPosition = (byte)(sourceColumn + (sourceRow * 8)); byte dstPosition = (byte)(destinationColumn + (destinationRow * 8)); Piece piece = ChessBoard.Squares[srcPosition].Piece; PreviousChessBoard = new Board(ChessBoard); Board.MovePiece(ChessBoard, srcPosition, dstPosition, ChessPieceType.Queen); PieceValidMoves.GenerateValidMoves(ChessBoard); //If there is a check in place, check if this is still true; if (piece.PieceColor == ChessPieceColor.White) { if (ChessBoard.WhiteCheck) { //Invalid Move ChessBoard = new Board(PreviousChessBoard); PieceValidMoves.GenerateValidMoves(ChessBoard); return(false); } } else if (piece.PieceColor == ChessPieceColor.Black) { if (ChessBoard.BlackCheck) { //Invalid Move ChessBoard = new Board(PreviousChessBoard); PieceValidMoves.GenerateValidMoves(ChessBoard); return(false); } } return(true); }
private ResultBoards GetSortValidMoves() { ResultBoards succ = new ResultBoards { Positions = new List<Board>(30) }; piecesRemaining = 0; #if (USETPL) Parallel.For(0,64, (ii) => #else for (byte ii = 0; ii < 64; ii++) #endif { byte x = (byte)ii; Square sqr = Squares[x]; //Make sure there is a piece on the square if (sqr.Piece == null) #if (USETPL) return; #else continue; #endif piecesRemaining++; //Make sure the color is the same color as the one we are moving. if (sqr.Piece.PieceColor != WhoseMove) #if (USETPL) return; #else continue; #endif //For each valid move for this piece foreach (byte dst in sqr.Piece.ValidMoves) { //We make copies of the board and move so that we can move it without effecting the parent board Board board = FastBoardCopy(); //Make move so we can examine it board.MovePiece(x, dst, ChessPieceType.Queen); //We Generate Valid Moves for Board board.GenerateValidMoves(); //Invalid Move if (board.WhiteCheck && WhoseMove == ChessPieceColor.White) { continue; } //Invalid Move if (board.BlackCheck && WhoseMove == ChessPieceColor.Black) { continue; } //We calculate the board score board.EvaluateBoardScore(); //Invert Score to support Negamax board.Score = SideToMoveScore(board.Score, board.WhoseMove); succ.Positions.Add(board); } }
public void AiPonderMove() { Thinking = true; /* Fix added to prevent premature declaration of checkmate against computer's king. * * The original version only looked at squares that were available for the black king to move to PRIOR to white's latest move. * So... suppose you had a situation like this: * r4r2/pppb1p1k/8/3p2Q1/q4P2/2np4/6PP/5RK1/ w - 0 27 * ... and moved the white queen from G5 to H5. * At the start of white's move, the black king has 5 possible moves... 4 of which are attackable by white, and noted by * GenerateValidMoves in WhiteAttackBoard[]. When AiPonderMove executes, it immediately eliminates those 4 squares as options * for the black king, even though 2 of them are now safe because no white piece can attack them. However, square 7 is now * directly in the queen's attack path, so it's eliminated as an option as well. Boom, premature checkmate... game over. */ ChessBoard.BlackMate = false; ChessBoard.WhiteMate = false; PieceValidMoves.GenerateValidMoves(ChessBoard); NodesSearched = 0; var resultBoards = new ResultBoards(); resultBoards.Positions = new List <Board>(); if (CheckForMate(WhoseMove, ref ChessBoard)) { Thinking = false; return; } MoveContent 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++) { Square 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); if (CheckForMate(WhoseMove, ref ChessBoard)) { Thinking = false; if (ChessBoard.WhiteMate || ChessBoard.BlackMate) { LastMove.PgnMove += "#"; } return; } if (ChessBoard.WhiteCheck || ChessBoard.BlackCheck) { LastMove.PgnMove += "+"; } Thinking = false; }
public void AiPonderMove() { Thinking = true; NodesSearched = 0; var resultBoards = new ResultBoards(); resultBoards.Positions = new List <Board>(); if (CheckForMate(WhoseMove, ref ChessBoard)) { Thinking = false; return; } MoveContent bestMove = new MoveContent(); //If there is no playbook move search for the best move if (FindPlayBookMove(ref bestMove, ChessBoard, OpeningBook) == false || ChessBoard.FiftyMove > 45 || ChessBoard.RepeatedMove >= 2) { if (FindPlayBookMove(ref bestMove, ChessBoard, CurrentGameBook) == false || ChessBoard.FiftyMove > 45 || 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++) { Square 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); if (CheckForMate(WhoseMove, ref ChessBoard)) { Thinking = false; if (ChessBoard.WhiteMate || ChessBoard.BlackMate) { LastMove.PgnMove += "#"; } return; } if (ChessBoard.WhiteCheck || ChessBoard.BlackCheck) { LastMove.PgnMove += "+"; } Thinking = false; }
public void AiPonderMove() { Thinking = true; /* Fix added to prevent premature declaration of checkmate against computer's king. * * The original version only looked at squares that were available for the black king to move to PRIOR to white's latest move. * So... suppose you had a situation like this: * r4r2/pppb1p1k/8/3p2Q1/q4P2/2np4/6PP/5RK1/ w - 0 27 * ... and moved the white queen from G5 to H5. * At the start of white's move, the black king has 5 possible moves... 4 of which are attackable by white, and noted by * GenerateValidMoves in WhiteAttackBoard[]. When AiPonderMove executes, it immediately eliminates those 4 squares as options * for the black king, even though 2 of them are now safe because no white piece can attack them. However, square 7 is now * directly in the queen's attack path, so it's eliminated as an option as well. Boom, premature checkmate... game over. * * The time it takes to regenerate the valid moves is nontrivial under Android. To improve performance, * my fix regenerates the valid moves ONLY when it might prevent a game-ending premature declaration * of checkmate, unless the difficulty is set to Hard or VeryHard (in which case it runs every time). * Even a novice player is likely to get confused if the engine declares checkmate for no apparent reason, * but the bug's more insidious manifestations at the two easiest difficulty levels help to make the computer a tiny bit easier * to beat by giving it a blind spot that a player can exploit, the same way HUMAN opponents have blind spots and weaknesses of their own. */ if (ChessBoard.BlackMate || ChessBoard.WhiteMate || (GameDifficulty == Difficulty.VeryHard) || (GameDifficulty == Difficulty.Hard)) { ChessBoard.BlackMate = false; ChessBoard.WhiteMate = false; PieceValidMoves.GenerateValidMoves(ChessBoard); } NodesSearched = 0; var resultBoards = new ResultBoards(); resultBoards.Positions = new List <Board>(); if (CheckForMate(WhoseMove, ref ChessBoard)) { Thinking = false; return; } MoveContent bestMove = new MoveContent(); //If there is no playbook move search for the best move if (FindPlayBookMove(ref bestMove, ChessBoard, OpeningBook) == false || ChessBoard.FiftyMove > 45 || ChessBoard.RepeatedMove >= 2) { if (FindPlayBookMove(ref bestMove, ChessBoard, CurrentGameBook) == false || ChessBoard.FiftyMove > 45 || 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++) { Square 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); if (CheckForMate(WhoseMove, ref ChessBoard)) { Thinking = false; if (ChessBoard.WhiteMate || ChessBoard.BlackMate) { LastMove.PgnMove += "#"; } return; } if (ChessBoard.WhiteCheck || ChessBoard.BlackCheck) { LastMove.PgnMove += "+"; } Thinking = false; }
internal static bool SearchForMate(ChessPieceColor movingSide, Board examineBoard, ref bool blackMate, ref bool whiteMate, ref bool staleMate) { bool foundNonCheckBlack = false; bool foundNonCheckWhite = false; for (byte x = 0; x < 64; x++) { Square sqr = examineBoard.Squares[x]; //Make sure there is a piece on the square if (sqr.Piece == null) { continue; } //Make sure the color is the same color as the one we are moving. if (sqr.Piece.PieceColor != movingSide) { continue; } //For each valid move for this piece foreach (byte dst in sqr.Piece.ValidMoves) { //We make copies of the board and move so that we can move it without effecting the parent board Board 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); if (board.BlackCheck == false) { foundNonCheckBlack = true; } else if (movingSide == ChessPieceColor.Black) { continue; } if (board.WhiteCheck == false) { foundNonCheckWhite = true; } else if (movingSide == ChessPieceColor.White) { continue; } } } if (foundNonCheckBlack == false) { if (examineBoard.BlackCheck) { blackMate = true; return(true); } if (!examineBoard.WhiteMate && movingSide != ChessPieceColor.White) { staleMate = true; return(true); } } if (foundNonCheckWhite == false) { if (examineBoard.WhiteCheck) { whiteMate = true; return(true); } if (!examineBoard.BlackMate && movingSide != ChessPieceColor.Black) { staleMate = true; return(true); } } return(false); }
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 (Position move in positions) { if (StaticExchangeEvaluation(examineBoard.Squares[move.DstPosition]) >= 0) { continue; } //Make a copy Board 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) { //Invalid Move continue; } } if (board.WhiteCheck) { if (examineBoard.WhoseMove == ChessPieceColor.White) { //Invalid Move continue; } } int 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); }
private static int AlphaBeta(Board examineBoard, byte depth, int alpha, int beta, ref int nodesSearched, ref int nodesQuiessence, ref List <Position> pvLine, bool extended) { nodesSearched++; if (examineBoard.FiftyMove >= 50 || examineBoard.RepeatedMove >= 3) { return(0); } //End Main Search with Quiescence if (depth == 0) { if (!extended && examineBoard.BlackCheck || examineBoard.WhiteCheck) { depth++; extended = true; } else { //Perform a Quiessence Search return(Quiescence(examineBoard, alpha, beta, ref nodesQuiessence)); } } List <Position> 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); } 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 (Position move in positions) { List <Position> pvChild = new List <Position>(); //Make a copy Board 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) { //Invalid Move continue; } } if (board.WhiteCheck) { if (examineBoard.WhoseMove == ChessPieceColor.White) { //Invalid Move continue; } } int value = -AlphaBeta(board, (byte)(depth - 1), -beta, -alpha, ref nodesSearched, ref nodesQuiessence, ref pvChild, extended); if (value >= beta) { KillerMove[kIndex, depth].SrcPosition = move.SrcPosition; KillerMove[kIndex, depth].DstPosition = move.DstPosition; kIndex = ((kIndex + 1) % 2); return(beta); } if (value > alpha) { Position pvPos = new Position(); pvPos.SrcPosition = board.LastMove.MovingPiecePrimary.SrcPosition; pvPos.DstPosition = board.LastMove.MovingPiecePrimary.DstPosition; pvPos.Move = board.LastMove.ToString(); pvChild.Insert(0, pvPos); pvLine = pvChild; alpha = (int)value; } } return(alpha); }
private static ResultBoards GetSortValidMoves(Board examineBoard) { ResultBoards succ = new ResultBoards { Positions = new List <Board>(30) }; piecesRemaining = 0; for (byte x = 0; x < 64; x++) { Square 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 (byte dst in sqr.Piece.ValidMoves) { //We make copies of the board and move so that we can move it without effecting the parent board Board 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); succ.Positions.Add(board); } } succ.Positions.Sort(Sort); return(succ); }
private static int AlphaBeta(Board examineBoard, byte depth, int alpha, int beta, ref int nodesSearched, ref int nodesQuiessence, ref List <Search.Position> pvLine, bool extended) { nodesSearched = nodesSearched + 1; if ((int)examineBoard.FiftyMove >= 50 || (int)examineBoard.RepeatedMove >= 3) { return(0); } int?nullable1 = Zobrist.Search(examineBoard.ZobristHash, depth, alpha, beta); if (nullable1.HasValue) { return(nullable1.Value); } if ((int)depth == 0) { if (!extended && examineBoard.BlackCheck || examineBoard.WhiteCheck) { ++depth; extended = true; } else { int score = Search.Quiescence(examineBoard, alpha, beta, ref nodesQuiessence); if (score >= beta) { Zobrist.AddEntry(examineBoard.ZobristHash, depth, score, Zobrist.NodeType.Beta); } else if (score <= alpha) { Zobrist.AddEntry(examineBoard.ZobristHash, depth, score, Zobrist.NodeType.Alpha); } else { Zobrist.AddEntry(examineBoard.ZobristHash, depth, score, Zobrist.NodeType.Exact); } return(score); } } Zobrist.NodeType nodeType = Zobrist.NodeType.Alpha; List <Search.Position> moves = Search.EvaluateMoves(examineBoard, depth); if ((examineBoard.WhiteCheck || examineBoard.BlackCheck || moves.Count == 0) && Search.SearchForMate(examineBoard.WhoseMove, examineBoard, ref examineBoard.BlackMate, ref examineBoard.WhiteMate, ref examineBoard.StaleMate)) { if (examineBoard.BlackMate) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { return(-32767 - (int)depth); } return((int)short.MaxValue + (int)depth); } if (!examineBoard.WhiteMate) { return(0); } if (examineBoard.WhoseMove == ChessPieceColor.Black) { return((int)short.MaxValue + (int)depth); } return(-32767 - (int)depth); } moves.Sort(new Comparison <Search.Position>(Search.Sort)); foreach (Search.Position position in moves) { List <Search.Position> pvLine1 = new List <Search.Position>(); Board board = examineBoard.FastCopy(); Board.MovePiece(board, position.SrcPosition, position.DstPosition, ChessPieceType.Queen); PieceValidMoves.GenerateValidMoves(board); if ((!board.BlackCheck || examineBoard.WhoseMove != ChessPieceColor.Black) && (!board.WhiteCheck || examineBoard.WhoseMove != ChessPieceColor.White)) { int?nullable2 = new int?(-Search.AlphaBeta(board, (byte)((uint)depth - 1U), -beta, -alpha, ref nodesSearched, ref nodesQuiessence, ref pvLine1, extended)); int?nullable3 = nullable2; int num1 = beta; if ((nullable3.GetValueOrDefault() >= num1 ? (nullable3.HasValue ? 1 : 0) : 0) != 0) { Search.KillerMove[Search.kIndex, (int)depth].SrcPosition = position.SrcPosition; Search.KillerMove[Search.kIndex, (int)depth].DstPosition = position.DstPosition; Search.kIndex = (Search.kIndex + 1) % 2; Zobrist.AddEntry(examineBoard.ZobristHash, depth, nullable2.Value, Zobrist.NodeType.Beta); return(beta); } nullable3 = nullable2; int num2 = alpha; if ((nullable3.GetValueOrDefault() > num2 ? (nullable3.HasValue ? 1 : 0) : 0) != 0) { pvLine1.Insert(0, new Search.Position() { SrcPosition = board.LastMove.MovingPiecePrimary.SrcPosition, DstPosition = board.LastMove.MovingPiecePrimary.DstPosition, Move = board.LastMove.ToString() }); pvLine = pvLine1; alpha = nullable2.Value; nodeType = Zobrist.NodeType.Exact; } } } Zobrist.AddEntry(examineBoard.ZobristHash, depth, alpha, nodeType); return(alpha); }