Skip to content

Commit

Permalink
Merge branch 'refactor/tm-outside-of-engine' into refactor/tt-outside…
Browse files Browse the repository at this point in the history
…-of-engine-1-static
  • Loading branch information
eduherminio authored Nov 11, 2024
2 parents 6c3e819 + 55e0eee commit c362b08
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 9 deletions.
6 changes: 6 additions & 0 deletions src/Lynx/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ public int TranspositionTableSize
[SPSA<int>(1, 10, 0.5)]
public int NMP_DepthDivisor { get; set; } = 3;

[SPSA<int>(150, 350, 10)]
public int NMP_StaticEvalBetaDivisor { get; set; } = 100;

[SPSA<int>(1, 10, 0.5)]
public int NMP_StaticEvalBetaMaxReduction { get; set; } = 3;

[SPSA<int>(5, 30, 1)]
public int AspirationWindow_Base { get; set; } = 13;

Expand Down
26 changes: 22 additions & 4 deletions src/Lynx/Search/NegaMax.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Lynx.Model;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Security.Authentication;

using static Lynx.Model.TranspositionTable;

Expand Down Expand Up @@ -78,6 +79,9 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM
// - Prune less aggressively when evaluation is low low: uncertainty on how bad the position really is
bool improving = false;

// From Potential
double improvingRate = 0;

bool isInCheck = position.IsInCheck();
int staticEval = int.MaxValue;
int phase = int.MaxValue;
Expand Down Expand Up @@ -115,7 +119,9 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM

if (ply >= 2)
{
improving = staticEval > Game.ReadStaticEvalFromStack(ply - 2);
var evalDiff = staticEval - Game.ReadStaticEvalFromStack(ply - 2);
improving = evalDiff >= 0;
improvingRate = evalDiff / 50.0;
}

// From smol.cs
Expand All @@ -133,7 +139,13 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM
{
// 🔍 Reverse Futility Pruning (RFP) - https://www.chessprogramming.org/Reverse_Futility_Pruning
// Return formula by Ciekce, instead of just returning static eval
if (staticEval - (Configuration.EngineSettings.RFP_DepthScalingFactor * (depth - (improving ? 1 : 0))) >= beta)
// Improving impl. based on Potential's
var rfpMargin = improving ? 80 * (depth - 1) : 100 * depth;
var improvingFactor = improvingRate * (0.75 * depth);

var rfpThreshold = rfpMargin + improvingFactor;

if (staticEval - rfpThreshold >= beta)
{
#pragma warning disable S3949 // Calculations should not overflow - value is being set at the beginning of the else if (!pvNode)
return (staticEval + beta) / 2;
Expand Down Expand Up @@ -172,14 +184,20 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool parentWasNullM
}
}

var staticEvalBetaDiff = staticEval - beta;

// 🔍 Null Move Pruning (NMP) - our position is so good that we can potentially afford giving our opponent a double move and still remain ahead of beta
if (depth >= Configuration.EngineSettings.NMP_MinDepth
&& staticEval >= beta
&& staticEvalBetaDiff >= 0
&& !parentWasNullMove
&& phase > 2 // Zugzwang risk reduction: pieces other than pawn presents
&& (ttElementType != NodeType.Alpha || ttScore >= beta)) // TT suggests NMP will fail: entry must not be a fail-low entry with a score below beta - Stormphrax and Ethereal
{
var nmpReduction = Configuration.EngineSettings.NMP_BaseDepthReduction + ((depth + Configuration.EngineSettings.NMP_DepthIncrement) / Configuration.EngineSettings.NMP_DepthDivisor); // Clarity
var nmpReduction = Configuration.EngineSettings.NMP_BaseDepthReduction
+ ((depth + Configuration.EngineSettings.NMP_DepthIncrement) / Configuration.EngineSettings.NMP_DepthDivisor) // Clarity
+ Math.Min(
Configuration.EngineSettings.NMP_StaticEvalBetaMaxReduction,
staticEvalBetaDiff / Configuration.EngineSettings.NMP_StaticEvalBetaDivisor);

// TODO more advanced adaptative reduction, similar to what Ethereal and Stormphrax are doing
//var nmpReduction = Math.Min(
Expand Down
16 changes: 16 additions & 0 deletions src/Lynx/UCIHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,22 @@ private void HandleSetOption(ReadOnlySpan<char> command)
}
break;
}
case "nmp_staticevalbetadivisor":
{
if (length > 4 && int.TryParse(command[commandItems[4]], out var value))
{
Configuration.EngineSettings.NMP_StaticEvalBetaDivisor = value;
}
break;
}
case "nmp_staticevalbetamaxreduction":
{
if (length > 4 && int.TryParse(command[commandItems[4]], out var value))
{
Configuration.EngineSettings.NMP_StaticEvalBetaMaxReduction = value;
}
break;
}

//case "aspirationwindow_delta":
// {
Expand Down
7 changes: 2 additions & 5 deletions tests/Lynx.Test/BestMove/RegressionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,12 @@ public void KeepNonGoodQuiescenceMoves(int depth)

switch (depth)
{
case 5:
case 5 when bestResult.Moves.Length >= 5:
Assert.AreNotEqual("f6e4", bestResult.Moves[4].UCIString());
break;
case 6:
case 6 when bestResult.Moves.Length >= 6:
Assert.AreNotEqual("f3e5", bestResult.Moves[5].UCIString());
break;
default:
Assert.True(false);
break;
}
}

Expand Down

0 comments on commit c362b08

Please sign in to comment.