private static List <ChessBoard> getValidBoards(ChessBoard examineBoard) { List <ChessBoard> validBoards = new List <ChessBoard>(); for (byte x = 0; x < 64; ++x) { ChessPiece piece = examineBoard.pieces[x]; //Make sure there is a piece on the square //Make sure the color is the same color as the one we are moving. if (piece == null || piece.PieceColor != examineBoard.WhoseMove) { continue; } //For each valid move for this piece foreach (byte dst in piece.ValidMoves) { //We make copies of the board and move so that we can move it without effecting the parent board ChessBoard board = new ChessBoard(examineBoard); //Make move so we can examine it ChessEngine.MoveContent(board, x, dst, ChessPieceType.Queen); //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(board); //Invalid Move if (board.whiteInCheck && examineBoard.WhoseMove == ChessPieceColor.White) { continue; } //Invalid Move if (board.blackInCheck && 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); validBoards.Add(board); } } return(validBoards); }
private static int AlphaBeta(ChessBoard examineBoard, byte depth, int alpha, int beta) { if (examineBoard == null || examineBoard.pieces == null) { return(0); } ++nodesSearched; if (examineBoard.FiftyMove >= 50 || examineBoard.RepeatedMove >= 3) { return(0); } if (depth == 0) { //Evaluate Score Evaluation.EvaluateBoardScore(examineBoard); //Invert Score to support Negamax return(SideToMoveScore(examineBoard.Score, examineBoard.WhoseMove)); } List <Position> positions = EvaluateMoves(examineBoard, depth); int length = positions.Count; if (examineBoard.whiteInCheck || examineBoard.blackInCheck || length == 0) { if (SearchForMate(examineBoard.WhoseMove, examineBoard, ref examineBoard.blackInMate, ref examineBoard.whiteInMate, ref examineBoard.staleMate)) { if (examineBoard.blackInMate) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { return(-Constants.GameOverValue - depth); } else { return(Constants.GameOverValue + depth); } } if (examineBoard.whiteInMate) { if (examineBoard.WhoseMove == ChessPieceColor.Black) { return(Constants.GameOverValue + depth); } else { return(-Constants.GameOverValue - depth); } } //If Not Mate then StaleMate return(0); } } // Sort by score, this increases te chance we can prune moves early on positions.Sort(Sort); for (int i = 0; i < length; ++i) { Position move = positions[i]; //Make a copy ChessBoard board = new ChessBoard(examineBoard); //Move Piece ChessEngine.MoveContent(board, move.SrcPosition, move.DstPosition, ChessPieceType.Queen); //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(board); if (board.blackInCheck && examineBoard.WhoseMove == ChessPieceColor.Black) { //Invalid Move continue; } if (board.whiteInCheck && examineBoard.WhoseMove == ChessPieceColor.White) { //Invalid Move continue; } int value = -AlphaBeta(board, (byte)(depth - 1), -beta, -alpha); if (value >= beta) { // Beta cut-off return(beta); } if (value > alpha) { alpha = value; } } return(alpha); }
internal static bool SearchForMate(ChessPieceColor movingSide, ChessBoard examineBoard, ref bool blackMate, ref bool whiteMate, ref bool staleMate) { bool foundNonCheckBlack = false; bool foundNonCheckWhite = false; for (byte x = 0; x < 64; ++x) { ChessPiece piece = examineBoard.pieces[x]; //Make sure there is a piece on the square //Make sure the color is the same color as the one we are moving. if (piece == null || piece.PieceColor != movingSide) { continue; } //For each valid move for this piece foreach (byte dst in piece.ValidMoves) { //We make copies of the board and move so we don't change the original ChessBoard board = new ChessBoard(examineBoard); //Make move so we can examine it ChessEngine.MoveContent(board, x, dst, ChessPieceType.Queen); //We Generate Valid Moves for Board PieceValidMoves.GenerateValidMoves(board); if (!board.blackInCheck) { foundNonCheckBlack = true; } else if (movingSide == ChessPieceColor.Black) { continue; } if (!board.whiteInCheck) { foundNonCheckWhite = true; } else if (movingSide == ChessPieceColor.White) { continue; } } } if (!foundNonCheckBlack) { if (examineBoard.blackInCheck) { blackMate = true; return(true); } if (!examineBoard.whiteInMate && movingSide != ChessPieceColor.White) { staleMate = true; return(true); } } if (!foundNonCheckWhite) { if (examineBoard.whiteInCheck) { whiteMate = true; return(true); } if (!examineBoard.blackInMate && movingSide != ChessPieceColor.Black) { staleMate = true; return(true); } } return(false); }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) { this.Exit(); } if (boardInfo.WhoseMove == ChessPieceColor.Black && blackIsAI) { ++waitASecond; if (waitASecond > 5) { waitASecond = 0; ChessEngine.EngineMove(boardInfo); } /* * if(boardHistory.Count >= 20) * { * boardHistory.RemoveAt(0); * } * boardHistory.Add(new ChessBoard(boardInfo)); */ } else { // Let AI play vs AI /* ++waitASecond; * if (waitASecond > 5) * { * waitASecond = 0; * ChessEngine.EngineMove(boardInfo); * } * */ MouseState state = Mouse.GetState(); if (state.LeftButton == ButtonState.Pressed) { int xPos = (int)(state.X / Constants.SquareSize); int yPos = (int)(state.Y / Constants.SquareSize); if (xPos < Constants.NumberOfFiles && yPos < Constants.NumberOfRanks) { if (selectedIndex > boardInfo.pieces.Length) { byte index = (byte)(yPos * Constants.NumberOfFiles + xPos); if (boardInfo.pieces[index] != null && boardInfo.pieces[index].PieceColor == boardInfo.WhoseMove) { selectedIndex = index; } } else { byte index = (byte)(yPos * Constants.NumberOfFiles + xPos); if (index != selectedIndex) { //SourceIndex has no piece if (boardInfo.pieces[selectedIndex] == null) { return; } //Select new piece if same color if (boardInfo.pieces[index] != null && boardInfo.pieces[index].PieceColor == boardInfo.WhoseMove) { selectedIndex = index; } //Check if this is infact a valid move if (!ChessEngine.IsValidMove(boardInfo, selectedIndex, index)) { return; } ChessEngine.MovePiece(boardInfo, selectedIndex, index); selectedIndex = 99; } } } else if (undoRectangle.Contains(new Point(state.X, state.Y))) { System.Diagnostics.Debug.WriteLine("UNDO PRESSED"); selectedIndex = 99; if (boardHistory.Count > 1) { boardHistory.RemoveAt(boardHistory.Count - 1); } if (boardHistory.Count > 0) { boardInfo = new ChessBoard(boardHistory[boardHistory.Count - 1]); PieceValidMoves.GenerateValidMoves(boardInfo); } } else if (selectedIndex < boardInfo.pieces.Length) { selectedIndex = 99; } } } base.Update(gameTime); }