private static void GenerateValidMovesKing(Piece piece, Board board, byte srcPosition) { if (piece == null) { return; } for (byte index = 0; (int)index < (int)MoveArrays.KingTotalMoves[(int)srcPosition]; ++index) { byte move = MoveArrays.KingMoves[(int)srcPosition].Moves[(int)index]; if (piece.PieceColor == ChessPieceColor.White) { if (board.BlackAttackBoard[(int)move]) { board.WhiteAttackBoard[(int)move] = true; continue; } } else if (board.WhiteAttackBoard[(int)move]) { board.BlackAttackBoard[(int)move] = true; continue; } PieceValidMoves.AnalyzeMove(board, move, piece); } }
private static void CheckValidMovesPawn(List <byte> moves, Piece pcMoving, byte srcPosition, Board board, byte count) { for (byte index = 0; (int)index < (int)count; ++index) { byte move = moves[(int)index]; if ((int)move % 8 != (int)srcPosition % 8) { PieceValidMoves.AnalyzeMovePawn(board, move, pcMoving); if (pcMoving.PieceColor == ChessPieceColor.White) { board.WhiteAttackBoard[(int)move] = true; } else { board.BlackAttackBoard[(int)move] = true; } } else { if (board.Squares[(int)move].Piece != null) { break; } pcMoving.ValidMoves.Push(move); } } }
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 InitiateBoard(string fen) { this.ChessBoard = new Board(fen); if (string.IsNullOrEmpty(fen)) { return; } PieceValidMoves.GenerateValidMoves(this.ChessBoard); Evaluation.EvaluateBoardScore(this.ChessBoard); }
public void InitiateBoard(string fen) { ChessBoard = new Board(fen); if (!String.IsNullOrEmpty(fen)) { PieceValidMoves.GenerateValidMoves(ChessBoard); Evaluation.EvaluateBoardScore(ChessBoard); } }
public bool MovePiece(byte srcPosition, byte dstPosition) { Piece piece = ChessBoard.Squares[srcPosition].Piece; PreviousChessBoard = new Board(ChessBoard); UndoChessBoard = new Board(ChessBoard); UndoGameBook = new List <OpeningMove>(CurrentGameBook); Board.MovePiece(ChessBoard, srcPosition, dstPosition, PromoteToPieceType); ChessBoard.LastMove.GeneratePGNString(ChessBoard); PieceValidMoves.GenerateValidMoves(ChessBoard); Evaluation.EvaluateBoardScore(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); } } 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); }
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 void Undo() { if (this.UndoChessBoard == null) { return; } this.PieceTakenRemove(this.ChessBoard.LastMove); this.PieceTakenRemove(this.PreviousChessBoard.LastMove); this.ChessBoard = new Board(this.UndoChessBoard); this.CurrentGameBook = new List <OpeningMove>((IEnumerable <OpeningMove>) this.UndoGameBook); PieceValidMoves.GenerateValidMoves(this.ChessBoard); Evaluation.EvaluateBoardScore(this.ChessBoard); }
public void Undo() { if (UndoChessBoard != null) { PieceTakenRemove(ChessBoard.LastMove); PieceTakenRemove(PreviousChessBoard.LastMove); ChessBoard = new Board(UndoChessBoard); CurrentGameBook = new List <OpeningMove>(UndoGameBook); PieceValidMoves.GenerateValidMoves(ChessBoard); Evaluation.EvaluateBoardScore(ChessBoard); } }
public bool IsCheckMate() { bool checkMate = false; if ((IsBlackChecked() && WhoseMove == ChessPieceColor.Black) || (IsWhiteChecked() && WhoseMove == ChessPieceColor.White)) { checkMate = true; DynamicArray pieceList = new DynamicArray(); Square[] squares = ChessBoard.Squares; Board oldBoard = new Board(ChessBoard); byte[] sourcePos; byte[] destinationPos; //Find all pieces that can be moved on this turn for (byte i = 0; i < squares.Length; i++) { if (squares[i].Piece != null && squares[i].Piece.PieceColor == WhoseMove && squares[i].Piece.ValidMoves.Count > 0) { pieceList.Add(i); } } //If piecelist is empty, no moves can be made if (pieceList.Count == 0) { return(false); } foreach (byte piece in pieceList) { sourcePos = CalculateColumnAndRow(piece); foreach (byte move in squares[piece].Piece.ValidMoves) { destinationPos = CalculateColumnAndRow(move); if (MovePiece(sourcePos[0], sourcePos[1], destinationPos[0], destinationPos[1])) { ChessBoard = new Board(oldBoard); PieceValidMoves.GenerateValidMoves(ChessBoard); return(false); } } } } return(checkMate); }
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 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); }
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); }
internal static void GenerateValidMoves(Board board) { board.BlackCheck = false; board.WhiteCheck = false; byte num1 = 0; byte num2 = 0; int num3 = 0; for (byte srcPosition = 0; (int)srcPosition < 64; ++srcPosition) { Square square = board.Squares[(int)srcPosition]; if (square.Piece != null) { square.Piece.ValidMoves = new Stack <byte>(square.Piece.LastValidMoveCount); ++num3; switch (square.Piece.PieceType) { case ChessPieceType.King: if (square.Piece.PieceColor == ChessPieceColor.White) { if (square.Piece.Moved) { board.WhiteCanCastle = false; } board.WhiteKingPosition = srcPosition; continue; } if (square.Piece.Moved) { board.BlackCanCastle = false; } board.BlackKingPosition = srcPosition; continue; case ChessPieceType.Queen: byte num4 = 0; while ((int)num4 < (int)MoveArrays.QueenTotalMoves1[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.QueenMoves1[(int)srcPosition].Moves[(int)num4], square.Piece)) { ++num4; } byte num5 = 0; while ((int)num5 < (int)MoveArrays.QueenTotalMoves2[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.QueenMoves2[(int)srcPosition].Moves[(int)num5], square.Piece)) { ++num5; } byte num6 = 0; while ((int)num6 < (int)MoveArrays.QueenTotalMoves3[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.QueenMoves3[(int)srcPosition].Moves[(int)num6], square.Piece)) { ++num6; } byte num7 = 0; while ((int)num7 < (int)MoveArrays.QueenTotalMoves4[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.QueenMoves4[(int)srcPosition].Moves[(int)num7], square.Piece)) { ++num7; } byte num8 = 0; while ((int)num8 < (int)MoveArrays.QueenTotalMoves5[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.QueenMoves5[(int)srcPosition].Moves[(int)num8], square.Piece)) { ++num8; } byte num9 = 0; while ((int)num9 < (int)MoveArrays.QueenTotalMoves6[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.QueenMoves6[(int)srcPosition].Moves[(int)num9], square.Piece)) { ++num9; } byte num10 = 0; while ((int)num10 < (int)MoveArrays.QueenTotalMoves7[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.QueenMoves7[(int)srcPosition].Moves[(int)num10], square.Piece)) { ++num10; } byte num11 = 0; while ((int)num11 < (int)MoveArrays.QueenTotalMoves8[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.QueenMoves8[(int)srcPosition].Moves[(int)num11], square.Piece)) { ++num11; } continue; case ChessPieceType.Rook: if (square.Piece.Moved) { if (square.Piece.PieceColor == ChessPieceColor.Black) { ++num1; } else { ++num2; } } byte num12 = 0; while ((int)num12 < (int)MoveArrays.RookTotalMoves1[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.RookMoves1[(int)srcPosition].Moves[(int)num12], square.Piece)) { ++num12; } byte num13 = 0; while ((int)num13 < (int)MoveArrays.RookTotalMoves2[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.RookMoves2[(int)srcPosition].Moves[(int)num13], square.Piece)) { ++num13; } byte num14 = 0; while ((int)num14 < (int)MoveArrays.RookTotalMoves3[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.RookMoves3[(int)srcPosition].Moves[(int)num14], square.Piece)) { ++num14; } byte num15 = 0; while ((int)num15 < (int)MoveArrays.RookTotalMoves4[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.RookMoves4[(int)srcPosition].Moves[(int)num15], square.Piece)) { ++num15; } continue; case ChessPieceType.Bishop: byte num16 = 0; while ((int)num16 < (int)MoveArrays.BishopTotalMoves1[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.BishopMoves1[(int)srcPosition].Moves[(int)num16], square.Piece)) { ++num16; } byte num17 = 0; while ((int)num17 < (int)MoveArrays.BishopTotalMoves2[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.BishopMoves2[(int)srcPosition].Moves[(int)num17], square.Piece)) { ++num17; } byte num18 = 0; while ((int)num18 < (int)MoveArrays.BishopTotalMoves3[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.BishopMoves3[(int)srcPosition].Moves[(int)num18], square.Piece)) { ++num18; } byte num19 = 0; while ((int)num19 < (int)MoveArrays.BishopTotalMoves4[(int)srcPosition] && PieceValidMoves.AnalyzeMove(board, MoveArrays.BishopMoves4[(int)srcPosition].Moves[(int)num19], square.Piece)) { ++num19; } continue; case ChessPieceType.Knight: for (byte index = 0; (int)index < (int)MoveArrays.KnightTotalMoves[(int)srcPosition]; ++index) { PieceValidMoves.AnalyzeMove(board, MoveArrays.KnightMoves[(int)srcPosition].Moves[(int)index], square.Piece); } continue; case ChessPieceType.Pawn: if (square.Piece.PieceColor == ChessPieceColor.White) { PieceValidMoves.CheckValidMovesPawn(MoveArrays.WhitePawnMoves[(int)srcPosition].Moves, square.Piece, srcPosition, board, MoveArrays.WhitePawnTotalMoves[(int)srcPosition]); continue; } if (square.Piece.PieceColor == ChessPieceColor.Black) { PieceValidMoves.CheckValidMovesPawn(MoveArrays.BlackPawnMoves[(int)srcPosition].Moves, square.Piece, srcPosition, board, MoveArrays.BlackPawnTotalMoves[(int)srcPosition]); continue; } continue; default: continue; } } } if ((int)num1 > 1) { board.BlackCanCastle = false; } if ((int)num2 > 1) { board.WhiteCanCastle = false; } if (num3 < 10) { board.EndGamePhase = true; } if (board.WhoseMove == ChessPieceColor.White) { PieceValidMoves.GenerateValidMovesKing(board.Squares[(int)board.BlackKingPosition].Piece, board, board.BlackKingPosition); PieceValidMoves.GenerateValidMovesKing(board.Squares[(int)board.WhiteKingPosition].Piece, board, board.WhiteKingPosition); } else { PieceValidMoves.GenerateValidMovesKing(board.Squares[(int)board.WhiteKingPosition].Piece, board, board.WhiteKingPosition); PieceValidMoves.GenerateValidMovesKing(board.Squares[(int)board.BlackKingPosition].Piece, board, board.BlackKingPosition); } if (!board.WhiteCastled && board.WhiteCanCastle && !board.WhiteCheck) { PieceValidMoves.GenerateValidMovesKingCastle(board, board.Squares[(int)board.WhiteKingPosition].Piece); } if (board.BlackCastled || !board.BlackCanCastle || board.BlackCheck) { return; } PieceValidMoves.GenerateValidMovesKingCastle(board, board.Squares[(int)board.BlackKingPosition].Piece); }
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 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); }
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; }
public void GenerateValidMoves() { PieceValidMoves.GenerateValidMoves(ChessBoard); }
private void GenerateValidMoves() { PieceValidMoves.GenerateValidMoves(ChessBoard); }
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; }
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); }