public static int GetLine(int depth, Board board) { Debug.Assert(depth < Variables.MAX_DEPTH); int move = PvTable.Probe(board); int count = 0; while (move != Variables.NO_MOVE && count < depth) { if (MakeMove.MoveExists(board, move)) { MakeMove.Make_Move(board, move); board.PvArray[count++] = move; } else { break; } move = PvTable.Probe(board); } // Take back the performed moves, so board position stay unchanged. while (board.Ply > 0) { MakeMove.TakeMove(board); } return(count); }
public void Perft_Test(int depth, Board board) // Also prints information regarding the moves { Debug.Assert(BoardOperations.CheckBoard(board)); var startTime = Variables.Watch.ElapsedMilliseconds; Console.Write("\nStarting Perft Test to Depth {0}", depth); BoardOperations.PrintBoard(board); LeafNodes = 0; MoveList list = new MoveList(); MoveGen.GenerateAllMoves(board, list, false); for (int i = 0; i < list.Count; ++i) { int move = list.Moves[i].Move; if (!MakeMove.Make_Move(board, list.Moves[i].Move)) { continue; } long cumulativeNodes = LeafNodes; _Perft(depth - 1, board); MakeMove.TakeMove(board); long oldNodes = LeafNodes - cumulativeNodes; Console.Write("\nmove {0} : {1} : {2}", i + 1, Io.MoveToString(move), oldNodes); } Console.Write("\nTest Complete: {0} nodes visited in {1} miliseconds\n", LeafNodes, Variables.Watch.ElapsedMilliseconds - startTime); }
/// <summary> /// Counts the amount of leafNode at the parameter input depth, /// by an inorder recursive tree traversion algorithm. /// It checks all legal moves with the parameter input depth, /// and increments the leafNode counter when the "last" move /// (the leaf) has been located. /// </summary> /// <param name="depth"> The depth to traverse </param> /// <param name="board"> The chess board operate on </param> /// <exception cref="Exception"></exception> public void _Perft(int depth, Board board) // For counting the TOTAL available moves { Debug.Assert(BoardOperations.CheckBoard(board)); // Increment leafNode and return. if (depth == 0) { LeafNodes++; return; } // Generate moves for rootposition MoveList list = new MoveList(); MoveGen.GenerateAllMoves(board, list, false); for (int i = 0; i < list.Count; ++i) { if (!MakeMove.Make_Move(board, list.Moves[i].Move)) { continue; } _Perft(depth - 1, board); MakeMove.TakeMove(board); } }
/// <summary> /// Search all capture positions, to help avoid the Horizon effect. /// </summary> private int Quiescence(int alpha, int beta, ref S_SearchInfo info) { Debug.Assert(BoardOperations.CheckBoard(board)); if ((info.Nodes & 2047) == 0) { CheckUp(ref info); } info.Nodes++; // If position is a draw. if ((IsRepetition() || board.FiftyMoves >= 100) && board.Ply != 0) { return(0); } int score = Evaluate.Position(board); // Stand_pat. if (board.Ply > Variables.MAX_DEPTH - 1) { return(score); } if (score >= beta) { return(beta); } if (score > alpha) { alpha = score; } MoveList list = new MoveList(); MoveGen.GenerateAllMoves(board, list, true); // Only capture moves int oldAlpha = alpha; score = -infinite; int legal = 0; // Will increment when we find a legal move. int bestMove = Variables.NO_MOVE; int PvMove = PvTable.Probe(board); for (int i = 0; i < list.Count; ++i) { PickNextMove(i, list); var move = list.Moves[i].Move; if (!MakeMove.Make_Move(board, move)) { continue; } legal++; score = -Quiescence(-beta, -alpha, ref info); MakeMove.TakeMove(board); // Take back the made move. if (info.Stopped) { return(0); } // We have a new alpha or beta cutoff. if (score > alpha) { bool isCaptureMove = (move & MoveOperations.MoveFlagCapture) != 0; // beta cutoff? if (score >= beta) { if (legal == 1) { info.Fhf++; // We searched the best move first. } info.Fh++; return(beta); } // Alpha cutoff alpha = score; bestMove = move; } } if (alpha != oldAlpha) { PvTable.StoreMove(board, bestMove); } return(alpha); }
public int AlphaBeta(int alpha, int beta, int depth, ref S_SearchInfo info, bool DoNull) { Debug.Assert(BoardOperations.CheckBoard(board)); if (depth == 0) { return(Quiescence(alpha, beta, ref info)); } if ((info.Nodes & 2047) == 0) { CheckUp(ref info); } info.Nodes++; // If position is a draw. if ((IsRepetition() || board.FiftyMoves >= 100) && board.Ply != 0) { return(0); } if (board.Ply > Variables.MAX_DEPTH - 1) { return(Evaluate.Position(board)); } bool kingInCheck = Attack.IsSqAttacked(board.KingSq[board.Side], board.Side ^ 1, board); // If king is in check, search deeper to get out of check. if (kingInCheck) { depth++; // The two following lines are possibly ERROR. long timeInc = (info.StopTime - info.StartTime) * (1 / 2); info.StopTime += timeInc; } MoveList list = new MoveList(); MoveGen.GenerateAllMoves(board, list, false); int oldAlpha = alpha; int score = -infinite; int legal = 0; // Will increment when we find a legal move. int bestMove = Variables.NO_MOVE; int PvMove = PvTable.Probe(board); // Prioritize Principle Variation move if it's found. if (PvMove != Variables.NO_MOVE) { for (int i = 0; i < list.Count; ++i) { var move = list.Moves[i].Move; if (move == PvMove) { list.Moves[i].Score = 2000000; break; } } } for (int i = 0; i < list.Count; ++i) { PickNextMove(i, list); var move = list.Moves[i].Move; if (!MakeMove.Make_Move(board, move)) { continue; } legal++; score = -AlphaBeta(-beta, -alpha, depth - 1, ref info, true); MakeMove.TakeMove(board); // Take back the made move. if (info.Stopped) { return(0); // Back up to the root if times up. } // We have a new alpha or beta cutoff. if (score > alpha) { bool isCaptureMove = (move & MoveOperations.MoveFlagCapture) != 0; // beta cutoff? if (score >= beta) { if (legal == 1) { info.Fhf++; // We searched the best move first. } info.Fh++; // If beta cutoff, but no capture move. if (!isCaptureMove) { board.SearchKillers[1, board.Ply] = board.SearchKillers[0, board.Ply]; board.SearchKillers[0, board.Ply] = move; } return(beta); } // Alpha cutoff alpha = score; bestMove = move; if (!isCaptureMove) { int from = MoveOperations.FromSq(move); int to = MoveOperations.ToSq(move); board.SearchHistory[board[from], to] += depth; // Prioritizes move near the root of the tree. } } } // If we haven't had any legal moves. if (legal == 0) { // If in check with no legal moves checkmate. if (kingInCheck) { return(-mate + board.Ply); // Return the amount of moves it takes to mate. // Returning in this way, allows the method to "prefer" the fastest checkmate combination. } else { return(0); // Stalemate. } } if (alpha != oldAlpha) { PvTable.StoreMove(board, bestMove); } return(alpha); }