diff --git a/src/Lynx.Cli/appsettings.json b/src/Lynx.Cli/appsettings.json index 4220df5db..949bc00df 100644 --- a/src/Lynx.Cli/appsettings.json +++ b/src/Lynx.Cli/appsettings.json @@ -39,7 +39,8 @@ "IIR_MinDepth": 4, "LMP_MaxDepth": 3, - "LMP_BaseMovesToTry": 3, + "LMP_BaseMovesToTry": 0, + "LMP_MovesDepthMultiplier": 5, "History_MaxMoveValue": 8192, diff --git a/src/Lynx/Configuration.cs b/src/Lynx/Configuration.cs index 972d1438a..ed0f46a38 100644 --- a/src/Lynx/Configuration.cs +++ b/src/Lynx/Configuration.cs @@ -151,7 +151,9 @@ public sealed class EngineSettings public int LMP_MaxDepth { get; set; } = 3; - public int LMP_BaseMovesToTry { get; set; } = 3; + public int LMP_BaseMovesToTry { get; set; } = 0; + + public int LMP_MovesDepthMultiplier { get; set; } = 5; public int History_MaxMoveValue { get; set; } = 8_192; diff --git a/src/Lynx/Search/NegaMax.cs b/src/Lynx/Search/NegaMax.cs index f4f8aae0f..8780c2065 100644 --- a/src/Lynx/Search/NegaMax.cs +++ b/src/Lynx/Search/NegaMax.cs @@ -153,8 +153,7 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM } var nodeType = NodeType.Alpha; - int movesSearched = 0; - int quietMovesSearched = 0; + int quietMovesSearchedCount = 0; Move? bestMove = null; bool isAnyMoveValid = false; @@ -183,20 +182,20 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM } } - for (int i = 0; i < pseudoLegalMoves.Length; ++i) + for (int moveIndex = 0; moveIndex < pseudoLegalMoves.Length; ++moveIndex) { // Incremental move sorting, inspired by https://github.com/jw1912/Chess-Challenge and suggested by toanth // There's no need to sort all the moves since most of them don't get checked anyway // So just find the first unsearched one with the best score and try it - for (int j = i + 1; j < pseudoLegalMoves.Length; j++) + for (int j = moveIndex + 1; j < pseudoLegalMoves.Length; j++) { - if (scores[j] > scores[i]) + if (scores[j] > scores[moveIndex]) { - (scores[i], scores[j], pseudoLegalMoves[i], pseudoLegalMoves[j]) = (scores[j], scores[i], pseudoLegalMoves[j], pseudoLegalMoves[i]); + (scores[moveIndex], scores[j], pseudoLegalMoves[moveIndex], pseudoLegalMoves[j]) = (scores[j], scores[moveIndex], pseudoLegalMoves[j], pseudoLegalMoves[moveIndex]); } } - var move = pseudoLegalMoves[i]; + var move = pseudoLegalMoves[moveIndex]; var gameState = position.MakeMove(move); @@ -226,7 +225,7 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM // don't belong to this line and if this move were to beat alpha, they'd incorrectly copied to pv line. Array.Clear(_pVTable, nextPvIndex, _pVTable.Length - nextPvIndex); } - else if (pvNode && movesSearched == 0) + else if (pvNode && moveIndex == 0) { evaluation = -NegaMax(depth - 1, ply + 1, -beta, -alpha); } @@ -237,8 +236,8 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM if (!pvNode && !isInCheck && depth <= Configuration.EngineSettings.LMP_MaxDepth - && scores[i] < EvaluationConstants.PromotionMoveScoreValue // Quiet moves - && quietMovesSearched >= 10 * depth) // Based on SP and Altair + && scores[moveIndex] < EvaluationConstants.PromotionMoveScoreValue // Quiet moves + && quietMovesSearchedCount >= Configuration.EngineSettings.LMP_BaseMovesToTry + (Configuration.EngineSettings.LMP_MovesDepthMultiplier * depth)) // Based on SP and Altair { // After making a move Game.HalfMovesWithoutCaptureOrPawnMove = oldValue; @@ -255,12 +254,12 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM // 🔍 Late Move Reduction (LMR) - search with reduced depth // Impl. based on Ciekce advice (Stormphrax) and Stormphrax & Akimbo implementations - if (movesSearched >= (pvNode ? Configuration.EngineSettings.LMR_MinFullDepthSearchedMoves : Configuration.EngineSettings.LMR_MinFullDepthSearchedMoves - 1) + if (moveIndex >= (pvNode ? Configuration.EngineSettings.LMR_MinFullDepthSearchedMoves : Configuration.EngineSettings.LMR_MinFullDepthSearchedMoves - 1) && depth >= Configuration.EngineSettings.LMR_MinDepth && !isInCheck && !move.IsCapture()) { - reduction = EvaluationConstants.LMRReductions[depth, movesSearched]; + reduction = EvaluationConstants.LMRReductions[depth, moveIndex]; if (pvNode) { @@ -344,10 +343,9 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM nodeType = NodeType.Exact; } - ++movesSearched; - if (scores[i] < EvaluationConstants.PromotionMoveScoreValue) + if (scores[moveIndex] < EvaluationConstants.PromotionMoveScoreValue) { - ++quietMovesSearched; + ++quietMovesSearchedCount; } }