/// <summary> /// AlphaBeta algorithm.Calculates best line in given depth /// </summary> /// <param name="alpha">Lowest value</param> /// <param name="beta">highest value</param> /// <param name="ply"></param> /// <param name="depth"></param> /// <param name="pv">Holds principal variation</param> /// <param name="nullmove"></param> /// <param name="nodeCount">Holds value of calculated moves</param> /// <returns>Returning value is the score of best line</returns> int AlphaBeta(int alpha, int beta, int ply, int depth, List <Move> pv, NullMove nullmove, ref int nodeCount) { //if time out or exit requested after 1st iteration,so leave thinking. if ((!HaveTime() || Exit) && iterationPly > 1) { return(0); } nodeCount++; var moves = Board.GenerateMoves(); if (!moves.Any()) { return(-Board.GetCheckMateOrStaleMateScore(ply)); } if (ply <= 0) { return(QuiescenceSearch(alpha, beta, ref nodeCount)); } var localpv = new List <Move>(); var pvSearch = false; #region Null Move Prunning if (nullmove == NullMove.Enabled && !Board.IsInCheck()) { int R = 2; Board.ToggleSide(); int score = -AlphaBeta(-beta, -beta + 1, ply - 1 - R, depth + 1, localpv, NullMove.Disabled, ref nodeCount); Board.ToggleSide(); if (score >= beta) { return(score); } } #endregion var sortedMoves = SortMoves(moves, depth); foreach (var move in sortedMoves) { Board.MakeMove(move); int score; if (Board.threeFoldRepetetion.IsThreeFoldRepetetion) { score = Board.Draw; } else { #region Late Move Reduction if (!Board.IsInCheck()) { score = -AlphaBeta(-alpha - 1, -alpha, ply - 2, depth + 1, localpv, NullMove.Enabled, ref nodeCount); } else { score = alpha + 1; } #endregion if (score > alpha) { if (pvSearch) { score = -AlphaBeta(-alpha - 1, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount); if (score > alpha && score < beta) { score = -AlphaBeta(-beta, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount); } } else { score = -AlphaBeta(-beta, -alpha, ply - 1, depth + 1, localpv, NullMove.Enabled, ref nodeCount); } } } Board.TakeBackMove(move); if (score >= beta) { killerMoves.Add(move, depth); return(beta);//beta cut-off } if (score > alpha) { historyMoves.AddMove(move); pvSearch = true; alpha = score; pv.Clear(); pv.Add(move); pv.AddRange(localpv); } } return(alpha); }