public bool MovePieceAN(string move) { byte sourceColumn = 0, sourceRow = 0, destinationColumn = 0, destinationRow = 0; MoveContent.ParseAN(move, ref sourceColumn, ref sourceRow, ref destinationColumn, ref destinationRow); return(MovePiece(sourceColumn, sourceRow, destinationColumn, destinationRow)); }
private void PieceTakenRemove(MoveContent lastMove) { if (lastMove.TakenPiece.PieceType == ChessPieceType.None) { return; } if (lastMove.TakenPiece.PieceColor == ChessPieceColor.White) { if (lastMove.TakenPiece.PieceType == ChessPieceType.Queen) { --this.PiecesTakenCount.WhiteQueen; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Rook) { --this.PiecesTakenCount.WhiteRook; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Bishop) { --this.PiecesTakenCount.WhiteBishop; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Knight) { --this.PiecesTakenCount.WhiteKnight; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Pawn) { --this.PiecesTakenCount.WhitePawn; } } if (lastMove.TakenPiece.PieceColor != ChessPieceColor.Black) { return; } if (lastMove.TakenPiece.PieceType == ChessPieceType.Queen) { --this.PiecesTakenCount.BlackQueen; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Rook) { --this.PiecesTakenCount.BlackRook; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Bishop) { --this.PiecesTakenCount.BlackBishop; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Knight) { --this.PiecesTakenCount.BlackKnight; } else { if (lastMove.TakenPiece.PieceType != ChessPieceType.Pawn) { return; } --this.PiecesTakenCount.BlackPawn; } }
internal Board() { Squares = new Square[64]; for (byte i = 0; i < 64; i++) { Squares[i] = new Square(); } LastMove = new MoveContent(); }
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; } } }
private void PieceTakenRemove(MoveContent lastMove) { if (lastMove.TakenPiece.PieceType != ChessPieceType.None) { if (lastMove.TakenPiece.PieceColor == ChessPieceColor.White) { if (lastMove.TakenPiece.PieceType == ChessPieceType.Queen) { PiecesTakenCount.WhiteQueen--; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Rook) { PiecesTakenCount.WhiteRook--; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Bishop) { PiecesTakenCount.WhiteBishop--; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Knight) { PiecesTakenCount.WhiteKnight--; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Pawn) { PiecesTakenCount.WhitePawn--; } } if (lastMove.TakenPiece.PieceColor == ChessPieceColor.Black) { if (lastMove.TakenPiece.PieceType == ChessPieceType.Queen) { PiecesTakenCount.BlackQueen--; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Rook) { PiecesTakenCount.BlackRook--; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Bishop) { PiecesTakenCount.BlackBishop--; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Knight) { PiecesTakenCount.BlackKnight--; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Pawn) { PiecesTakenCount.BlackPawn--; } } } }
private void PieceTakenAdd(MoveContent lastMove) { if (lastMove.TakenPiece.PieceType != ChessPieceType.None) { if (lastMove.TakenPiece.PieceColor == ChessPieceColor.White) { if (lastMove.TakenPiece.PieceType == ChessPieceType.Queen) { PiecesTakenCount.WhiteQueen++; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Rook) { PiecesTakenCount.WhiteRook++; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Bishop) { PiecesTakenCount.WhiteBishop++; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Knight) { PiecesTakenCount.WhiteKnight++; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Pawn) { PiecesTakenCount.WhitePawn++; } } if (ChessBoard.LastMove.TakenPiece.PieceColor == ChessPieceColor.Black) { if (lastMove.TakenPiece.PieceType == ChessPieceType.Queen) { PiecesTakenCount.BlackQueen++; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Rook) { PiecesTakenCount.BlackRook++; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Bishop) { PiecesTakenCount.BlackBishop++; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Knight) { PiecesTakenCount.BlackKnight++; } else if (lastMove.TakenPiece.PieceType == ChessPieceType.Pawn) { PiecesTakenCount.BlackPawn++; } } } }
//Copy Constructor internal Board(Board board) { Squares = new Square[64]; for (byte x = 0; x < 64; x++) { if (board.Squares[x].Piece != null) { Squares[x] = new Square(board.Squares[x].Piece); } } WhiteAttackBoard = new bool[64]; BlackAttackBoard = new bool[64]; for (byte x = 0; x < 64; x++) { WhiteAttackBoard[x] = board.WhiteAttackBoard[x]; BlackAttackBoard[x] = board.BlackAttackBoard[x]; } EndGamePhase = board.EndGamePhase; HalfMoveClock = board.HalfMoveClock; RepeatedMove = board.RepeatedMove; WhiteCastled = board.WhiteCastled; BlackCastled = board.BlackCastled; WhiteCanCastle = board.WhiteCanCastle; BlackCanCastle = board.BlackCanCastle; WhiteKingPosition = board.WhiteKingPosition; BlackKingPosition = board.BlackKingPosition; BlackCheck = board.BlackCheck; WhiteCheck = board.WhiteCheck; StaleMate = board.StaleMate; WhiteMate = board.WhiteMate; BlackMate = board.BlackMate; WhoseMove = board.WhoseMove; EnPassantPosition = board.EnPassantPosition; EnPassantColor = board.EnPassantColor; ZobristHash = board.ZobristHash; Score = board.Score; LastMove = new MoveContent(board.LastMove); MoveCount = board.MoveCount; }
public MoveContent(MoveContent moveContent) { MovingPiecePrimary = new PieceMoving(moveContent.MovingPiecePrimary); MovingPieceSecondary = new PieceMoving(moveContent.MovingPieceSecondary); TakenPiece = new PieceTaken(moveContent.TakenPiece.PieceColor, moveContent.TakenPiece.PieceType, moveContent.TakenPiece.Moved, moveContent.TakenPiece.Position); EnPassantOccured = moveContent.EnPassantOccured; PawnPromoted = moveContent.PawnPromoted; }
public void TestAI() { // set up a simple scenario with an obvious checkmate in 1 move var engine = new Engine("k7/7R/6R1/8/8/8/8/K7 w - - 0 1"); engine.GameDifficulty = Engine.Difficulty.Easy; engine.AiPonderMove(); MoveContent lastMove = engine.GetMoveHistory().ToArray()[0]; string move = lastMove.GetPureCoordinateNotation(); // did the AI find the checkmate? Assert.AreEqual("g6g8", move); }
internal Board() { Squares = new Square[64]; for (byte i = 0; i < 64; i++) { Squares[i] = new Square(); } LastMove = new MoveContent(); BlackCanCastle = true; WhiteCanCastle = true; WhiteAttackBoard = new bool[64]; BlackAttackBoard = new bool[64]; }
private static bool FindPlayBookMove(ref MoveContent bestMove, Board chessBoard, IEnumerable <OpeningMove> openingBook) { string str = Board.Fen(true, chessBoard); foreach (OpeningMove openingMove in openingBook) { if (openingMove.StartingFEN.Contains(str)) { int index = 0; if (openingMove.Moves.Count > 1) { index = new Random(DateTime.Now.Second).Next(openingMove.Moves.Count - 1); } bestMove = openingMove.Moves[index]; return(true); } } return(false); }
private static bool FindPlayBookMove(ref MoveContent bestMove, Board chessBoard, IEnumerable <OpeningMove> openingBook) { //Get the Hash for the current Board; string boardFen = Board.Fen(true, chessBoard); //Check the Opening Move Book foreach (OpeningMove move in openingBook) { if (move.StartingFEN.Contains(boardFen)) { int index = 0; bestMove = move.Moves[index]; return(true); } } return(false); }
public void TestNotation() { byte sourceColumn = 0, sourceRow = 0, destinationColumn = 0, destinationRow = 0; Assert.IsFalse(MoveContent.ParseAN("toolong", ref sourceColumn, ref sourceRow, ref destinationColumn, ref destinationRow)); Assert.IsFalse(MoveContent.ParseAN("abc", ref sourceColumn, ref sourceRow, ref destinationColumn, ref destinationRow)); Assert.IsTrue(MoveContent.ParseAN("a8h1", ref sourceColumn, ref sourceRow, ref destinationColumn, ref destinationRow)); Assert.AreEqual(sourceColumn, 0); Assert.AreEqual(sourceRow, 0); Assert.AreEqual(destinationColumn, 7); Assert.AreEqual(destinationRow, 7); Assert.IsTrue(MoveContent.ParseAN("b3e4", ref sourceColumn, ref sourceRow, ref destinationColumn, ref destinationRow)); Assert.AreEqual(sourceColumn, 1); Assert.AreEqual(sourceRow, 5); Assert.AreEqual(destinationColumn, 4); Assert.AreEqual(destinationRow, 4); }
internal static void SaveCurrentGameMove(Board currentBoard, Board previousBoard, ICollection <OpeningMove> gameBook, MoveContent bestMove) { try { var move = new OpeningMove(); move.StartingFEN = Board.Fen(true, previousBoard); move.EndingFEN = Board.Fen(true, currentBoard); move.Moves.Add(bestMove); gameBook.Add(move); foreach (var move1 in gameBook) { byte repeatedMoves = 0; foreach (var move2 in gameBook) { if (move1.EndingFEN == move2.EndingFEN) { repeatedMoves++; } } if (previousBoard.RepeatedMove < repeatedMoves) { previousBoard.RepeatedMove = repeatedMoves; currentBoard.RepeatedMove = repeatedMoves; } } if (currentBoard.RepeatedMove >= 3) { currentBoard.StaleMate = true; } } catch (Exception) { } }
//Copy Constructor internal Board(Board board) { Squares = new Square[64]; for (byte x = 0; x < 64; x++) { if (board.Squares[x].Piece != null) { Squares[x] = new Square(board.Squares[x].Piece); } } EndGamePhase = board.EndGamePhase; FiftyMove = board.FiftyMove; RepeatedMove = board.RepeatedMove; WhiteCastled = board.WhiteCastled; BlackCastled = board.BlackCastled; BlackCheck = board.BlackCheck; WhiteCheck = board.WhiteCheck; StaleMate = board.StaleMate; WhiteMate = board.WhiteMate; BlackMate = board.BlackMate; WhoseMove = board.WhoseMove; EnPassantPosition = board.EnPassantPosition; EnPassantColor = board.EnPassantColor; ZobristHash = board.ZobristHash; Score = board.Score; LastMove = new MoveContent(board.LastMove); MoveCount = board.MoveCount; }
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 MoveContent MovePiece(byte srcPosition, byte dstPosition, ChessPieceType promoteToPiece) { Piece piece = Squares[srcPosition].Piece; //Record my last move LastMove = new MoveContent(); if (piece.PieceColor == ChessPieceColor.Black) { MoveCount++; //Add One to FiftyMoveCount to check for tie. FiftyMove++; } //En Passant if (EnPassantPosition > 0) { LastMove.EnPassantOccured = SetEnpassantMove(srcPosition, dstPosition, piece.PieceColor); } if (!LastMove.EnPassantOccured) { Square sqr = Squares[dstPosition]; if (sqr.Piece != null) { LastMove.TakenPiece = new PieceTaken(sqr.Piece.PieceColor, sqr.Piece.PieceType, sqr.Piece.Moved, dstPosition); FiftyMove = 0; } else { LastMove.TakenPiece = new PieceTaken(ChessPieceColor.White, ChessPieceType.None, false, dstPosition); } } LastMove.MovingPiecePrimary = new PieceMoving(piece.PieceColor, piece.PieceType, piece.Moved, srcPosition, dstPosition); //Delete the piece in its source position Squares[srcPosition].Piece = null; //Add the piece to its new position piece.Moved = true; piece.Selected = false; Squares[dstPosition].Piece = piece; //Reset EnPassantPosition EnPassantPosition = 0; //Record En Passant if Pawn Moving if (piece.PieceType == ChessPieceType.Pawn) { FiftyMove = 0; RecordEnPassant(piece.PieceColor, piece.PieceType, srcPosition, dstPosition); } WhoseMove = WhoseMove == ChessPieceColor.White ? ChessPieceColor.Black : ChessPieceColor.White; KingCastle(piece, srcPosition, dstPosition); //Promote Pawns if (PromotePawns(piece, dstPosition, promoteToPiece)) { LastMove.PawnPromotedTo = promoteToPiece; } else { LastMove.PawnPromotedTo = ChessPieceType.None; } if (FiftyMove >= 50) { StaleMate = true; } return(LastMove); }
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 (OpeningBook.TryGetMove(ChessBoard, ref bestMove) == false || ChessBoard.FiftyMove > 45 || ChessBoard.RepeatedMove >= 2) { if (CurrentGameBook.TryGetMove(ChessBoard, ref bestMove) == false || ChessBoard.FiftyMove > 45 || ChessBoard.RepeatedMove >= 2) { bestMove = ChessBoard.IterativeSearch(PlyDepthSearched, ref NodesSearched, ref NodesQuiescence, ref pvLine, ref PlyDepthReached, ref RootMovesSearched, CurrentGameBook.MoveList); } } //Make the move PreviousChessBoard = new Board(ChessBoard); RootMovesSearched = (byte)resultBoards.Positions.Count; ChessBoard.MovePiece(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; } ChessBoard.GenerateValidMoves(); ChessBoard.EvaluateBoardScore(); 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 MoveContent IterativeSearch(Board examineBoard, byte depth, ref int nodesSearched, ref int nodesQuiessence, ref string pvLine, ref byte plyDepthReached, ref byte rootMovesSearched, List <OpeningMove> currentGameBook) { List <Position> pvChild = new List <Position>(); int alpha = -400000000; const int beta = 400000000; MoveContent bestMove = new MoveContent(); //We are going to store our result boards here ResultBoards succ = GetSortValidMoves(examineBoard); rootMovesSearched = (byte)succ.Positions.Count; if (rootMovesSearched == 1) { //I only have one move return(succ.Positions[0].LastMove); } //Can I make an instant mate? foreach (Board pos in succ.Positions) { int value = -AlphaBeta(pos, 1, -beta, -alpha, ref nodesSearched, ref nodesQuiessence, ref pvChild, true); if (value >= 32767) { return(pos.LastMove); } } int currentBoard = 0; alpha = -400000000; succ.Positions.Sort(Sort); depth--; plyDepthReached = ModifyDepth(depth, succ.Positions.Count); foreach (Board pos in succ.Positions) { currentBoard++; progress = (int)((currentBoard / (decimal)succ.Positions.Count) * 100); pvChild = new List <Position>(); int value = -AlphaBeta(pos, depth, -beta, -alpha, ref nodesSearched, ref nodesQuiessence, ref pvChild, false); if (value >= 32767) { return(pos.LastMove); } if (examineBoard.RepeatedMove == 2) { string fen = Board.Fen(true, pos); foreach (OpeningMove move in currentGameBook) { if (move.EndingFEN == fen) { value = 0; break; } } } pos.Score = value; //If value is greater then alpha this is the best board if (value > alpha || alpha == -400000000) { pvLine = pos.LastMove.ToString(); foreach (Position pvPos in pvChild) { pvLine += " " + pvPos.ToString(); } alpha = value; bestMove = pos.LastMove; } } plyDepthReached++; progress = 100; return(bestMove); }
internal static MoveContent IterativeSearchOld(Board examineBoard, ChessEngine.Engine.Engine.TimeSettings gameTimeSettings, ref int nodesSearched, ref int nodesQuiessence, ref string pvLine, BackgroundWorker worker, ref byte plyDepthReached, ref byte rootMovesSearched, List <OpeningMove> currentGameBook) { Zobrist.MarkAncient(); MoveContent moveContent1 = new MoveContent(); MoveContent moveContent2 = new MoveContent(); string str1 = ""; List <Search.Position> positionList1 = new List <Search.Position>(); ResultBoards sortValidMoves = Search.GetSortValidMoves(examineBoard); rootMovesSearched = (byte)sortValidMoves.Positions.Count; int num1 = 30; int num2 = 40; byte depth = 1; if (gameTimeSettings == ChessEngine.Engine.Engine.TimeSettings.Moves40In10Minutes) { num1 = 15; } else if (gameTimeSettings == ChessEngine.Engine.Engine.TimeSettings.Moves40In20Minutes) { num1 = 30; } else if (gameTimeSettings == ChessEngine.Engine.Engine.TimeSettings.Moves40In30Minutes) { num1 = 45; } else if (gameTimeSettings == ChessEngine.Engine.Engine.TimeSettings.Moves40In40Minutes) { num1 = 60; } else if (gameTimeSettings == ChessEngine.Engine.Engine.TimeSettings.Moves40In60Minutes) { num1 = 90; } else if (gameTimeSettings == ChessEngine.Engine.Engine.TimeSettings.Moves40In90Minutes) { num1 = 135; } DateTime now = DateTime.Now; do { pvLine = ""; int num3 = -400000000; sortValidMoves.Positions.Sort(new Comparison <Board>(Search.Sort)); foreach (Board position1 in sortValidMoves.Positions) { if (DateTime.Now - now > TimeSpan.FromSeconds((double)num1)) { pvLine = str1; return(moveContent2); } if (worker != null) { worker.ReportProgress((int)((DateTime.Now - now).TotalSeconds / (double)num1 * 100.0)); } List <Search.Position> pvLine1 = new List <Search.Position>(); int num4 = -Search.AlphaBeta(position1, depth, -400000000, -num3, ref nodesSearched, ref nodesQuiessence, ref pvLine1, true); if (num4 >= (int)short.MaxValue) { pvLine = str1; return(position1.LastMove); } if ((int)examineBoard.RepeatedMove == 2) { string str2 = Board.Fen(true, position1); foreach (OpeningMove openingMove in currentGameBook) { if (openingMove.EndingFEN == str2) { num4 = 0; break; } } } position1.Score = num4; if (num4 > num3) { List <Search.Position> positionList2 = new List <Search.Position>(); pvLine = position1.LastMove.ToString(); foreach (Search.Position position2 in pvLine1) { pvLine = pvLine + " " + position2.ToString(); positionList2.Add(position2); } positionList2.Reverse(); num3 = num4; moveContent1 = position1.LastMove; } } moveContent2 = moveContent1; str1 = pvLine; plyDepthReached = depth; ++depth; }while (DateTime.Now - now < TimeSpan.FromSeconds((double)num1) && (int)plyDepthReached < 19); plyDepthReached = (byte)((uint)plyDepthReached + 1U); int num5 = num2 != 1 ? num2 - 1 : 40; return(moveContent2); }
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; }
internal static MoveContent Execute(Board examineBoard, List <Board> positions, int depth, List <OpeningMove> currentGameBook) { List <Position> pvChild = new List <Position>(); int alpha = -400000000; const int beta = 400000000; MoveContent bestMove = new MoveContent(); int nodesSearched = 0; int nodesQuiessence = 0; //Can I make an instant mate? foreach (Board pos in positions) { //TODO: Send each (or in packs of few i.e.) board to different process, and finish if any returned bigger value int value = -AlphaBeta(pos, 1, -beta, -alpha, ref nodesSearched, ref nodesQuiessence, ref pvChild, true); if (value >= 32767) { pos.LastMove.Score = value; return(pos.LastMove); } } int currentBoard = 0; alpha = -400000000; positions.Sort(Sort); depth--; int plyDepthReached = ModifyDepth((byte)depth, positions.Count()); foreach (Board pos in positions) { currentBoard++; progress = (int)((currentBoard / (decimal)positions.Count) * 100); pvChild = new List <Position>(); int value = -AlphaBeta(pos, (byte)depth, -beta, -alpha, ref nodesSearched, ref nodesQuiessence, ref pvChild, false); if (value >= 32767) { pos.LastMove.Score = value; return(pos.LastMove); } if (examineBoard.RepeatedMove == 2) { string fen = Board.Fen(true, pos); foreach (OpeningMove move in currentGameBook) { if (move.EndingFEN == fen) { value = 0; break; } } } pos.Score = value; //If value is greater then alpha this is the best board if (value > alpha || alpha == -400000000) { alpha = value; bestMove = pos.LastMove; bestMove.Score = value; } } plyDepthReached++; progress = 100; return(bestMove); }
internal static MoveContent IterativeSearch(Board examineBoard, byte depth, List <OpeningMove> currentGameBook) { Intracommunicator comm = Communicator.world; int numOfTasks = comm.Size; MoveContent bestMove = new MoveContent(); //We are going to store our result boards here ResultBoards succ = GetSortValidMoves(examineBoard); if ((byte)succ.Positions.Count == 1) { //I only have one move return(succ.Positions[0].LastMove); } int numOfPositions = succ.Positions.Count; int positionsChunkSizeWhole = numOfPositions / numOfTasks; int positionsChunkSizeRest = numOfPositions - numOfTasks * positionsChunkSizeWhole; int[] tasksPosChunkSize = new int[numOfTasks]; for (int i = 0; i < numOfTasks; i++) { tasksPosChunkSize[i] = positionsChunkSizeWhole; if (positionsChunkSizeRest > 0) { tasksPosChunkSize[i] += 1; positionsChunkSizeRest--; } } List <List <Board> > tasksPos = new List <List <Board> >(); int idx = 0; for (int i = 0; i < numOfTasks; i++) { tasksPos.Add(succ.Positions.GetRange(idx, tasksPosChunkSize[i])); idx += tasksPosChunkSize[i]; } List <InterProcessData> dataToSend = new List <InterProcessData>(); for (int i = 0; i < numOfTasks; i++) { dataToSend.Add(new InterProcessData { pos = tasksPos[i], depth = depth, GameBook = currentGameBook, ExamineBoard = examineBoard }); } for (int i = 1; i < numOfTasks; i++) { comm.Send <InterProcessData>(dataToSend[i], i, 0); } DateTime startDate = DateTime.Now; MoveContent thisThreadBestMove = Execute(examineBoard, dataToSend[0].pos, dataToSend[0].depth, currentGameBook); List <MoveContent> bestMoves = new List <MoveContent>(); bestMoves.Add(thisThreadBestMove); for (int i = 1; i < numOfTasks; i++) { bestMoves.Add(comm.Receive <MoveContent>(i, 0)); } DateTime endDate = DateTime.Now; long msElapsed = (endDate.Ticks - startDate.Ticks) / 10000; Console.WriteLine("Elapsed AI search time: " + msElapsed.ToString() + " ms"); return(bestMoves.OrderByDescending(m => m.Score).First()); }
internal static MoveContent IterativeSearch(Board examineBoard, byte depth, ref int nodesSearched, ref int nodesQuiessence, ref string pvLine, BackgroundWorker worker, ref byte plyDepthReached, ref byte rootMovesSearched, List <OpeningMove> currentGameBook) { List <Search.Position> pvLine1 = new List <Search.Position>(); int num1 = -400000000; Zobrist.MarkAncient(); MoveContent moveContent = new MoveContent(); ResultBoards sortValidMoves = Search.GetSortValidMoves(examineBoard); rootMovesSearched = (byte)sortValidMoves.Positions.Count; if ((int)rootMovesSearched == 1) { return(sortValidMoves.Positions[0].LastMove); } foreach (Board position in sortValidMoves.Positions) { if (-Search.AlphaBeta(position, (byte)1, -400000000, -num1, ref nodesSearched, ref nodesQuiessence, ref pvLine1, true) >= (int)short.MaxValue) { return(position.LastMove); } } int num2 = 0; int num3 = -400000000; sortValidMoves.Positions.Sort(new Comparison <Board>(Search.Sort)); --depth; plyDepthReached = Search.ModifyDepth(depth, sortValidMoves.Positions.Count); foreach (Board position1 in sortValidMoves.Positions) { ++num2; if (worker != null) { worker.ReportProgress((int)((Decimal)num2 / (Decimal)sortValidMoves.Positions.Count * new Decimal(100))); } List <Search.Position> pvLine2 = new List <Search.Position>(); int num4 = -Search.AlphaBeta(position1, depth, -400000000, -num3, ref nodesSearched, ref nodesQuiessence, ref pvLine2, false); if (num4 >= (int)short.MaxValue) { return(position1.LastMove); } if ((int)examineBoard.RepeatedMove == 2) { string str = Board.Fen(true, position1); foreach (OpeningMove openingMove in currentGameBook) { if (openingMove.EndingFEN == str) { num4 = 0; break; } } } position1.Score = num4; if (num4 > num3 || num3 == -400000000) { pvLine = position1.LastMove.ToString(); foreach (Search.Position position2 in pvLine2) { pvLine = pvLine + " " + position2.ToString(); } num3 = num4; moveContent = position1.LastMove; } } plyDepthReached = (byte)((uint)plyDepthReached + 1U); return(moveContent); }