diff --git a/Rudim.Test/UnitTest/Board/TraversalTest.cs b/Rudim.Test/UnitTest/Board/TraversalTest.cs index 02142a9..f74d258 100644 --- a/Rudim.Test/UnitTest/Board/TraversalTest.cs +++ b/Rudim.Test/UnitTest/Board/TraversalTest.cs @@ -13,10 +13,10 @@ public class TraversalTest // This helps keep track if certain optimizations are good enough to make up for the extra time spent // Compare time spent with and without the change before updating the keys [Theory] - [InlineData(Helpers.StartingFEN, 3916083,5, 8)] - [InlineData(Helpers.EndgameFEN, 2327956,45, 9)] - [InlineData(Helpers.AdvancedMoveFEN, 10012236,1520, 8)] - [InlineData(Helpers.KiwiPeteFEN, 11101517,-18, 8)] + [InlineData(Helpers.StartingFEN, 3804303,5, 8)] + [InlineData(Helpers.EndgameFEN, 1130154,45, 9)] + [InlineData(Helpers.AdvancedMoveFEN, 6689081,1520, 8)] + [InlineData(Helpers.KiwiPeteFEN, 10605420,-18, 8)] public void ShouldTraverseDeterministically(string position, int expectedNodes, int expectedScore, int depth) { Global.Reset(); diff --git a/Rudim/Search/Negamax.cs b/Rudim/Search/Negamax.cs index 3086d04..614a8c3 100644 --- a/Rudim/Search/Negamax.cs +++ b/Rudim/Search/Negamax.cs @@ -37,6 +37,7 @@ private static int Search(BoardState boardState, int depth, int alpha, int beta, int originalAlpha = alpha; int ply = _searchDepth - depth; + bool foundPv = false; Move bestEvaluation = Move.NoMove; Nodes++; @@ -55,7 +56,9 @@ private static int Search(BoardState boardState, int depth, int alpha, int beta, boardState.UnmakeMove(move); continue; } - int score = -Search(boardState, depth - 1, -beta, -alpha, cancellationToken); + + int score = SearchDeeper(boardState, depth, alpha, beta, cancellationToken, foundPv); + numberOfLegalMoves++; boardState.UnmakeMove(move); @@ -65,14 +68,14 @@ private static int Search(BoardState boardState, int depth, int alpha, int beta, } if (score > alpha) { - AlphaUpdate(out alpha, score, move, out bestEvaluation); + AlphaUpdate(out alpha, score, move, out bestEvaluation, out foundPv); } } if (numberOfLegalMoves == 0) { if (boardState.IsInCheck(boardState.SideToMove)) - return -Constants.MaxCentipawnEval + (_searchDepth - depth); + return -Constants.MaxCentipawnEval + ply; return 0; } @@ -82,10 +85,28 @@ private static int Search(BoardState boardState, int depth, int alpha, int beta, return alpha; } - private static void AlphaUpdate(out int alpha, int score, Move move, out Move bestEvaluation) + private static int SearchDeeper(BoardState boardState, int depth, int alpha, int beta, + CancellationToken cancellationToken, bool foundPv) + { + int score; + if (foundPv) + { + score = -Search(boardState, depth - 1, -alpha - 1, -alpha, cancellationToken); + if (score > alpha && score < beta) + score = -Search(boardState,depth - 1, -beta, -alpha, cancellationToken); + } + else + { + score = -Search(boardState, depth - 1, -beta, -alpha, cancellationToken); + } + return score; + } + + private static void AlphaUpdate(out int alpha, int score, Move move, out Move bestEvaluation, out bool foundPv) { alpha = score; bestEvaluation = move; + foundPv = true; } private static int BetaCutoff(int beta, Move move, int ply)