Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔍 Implement razoring #429

Merged
merged 10 commits into from
Oct 17, 2023
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ If you're a Linux user and are new to .NET ecosystem, the conversation in [this

- Check extensions [[1](https://www.chessprogramming.org/Check_Extensions)]

- Razoring [[1](https://www.chessprogramming.org/Razoring)]

## Credits

Lynx development wouldn't have been possible without:
Expand Down
5 changes: 4 additions & 1 deletion src/Lynx.Cli/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@
"BenchDepth": 5,
"RFP_MaxDepth": 6,
"RFP_DepthScalingFactor": 75,
"ShowWDL": false
"ShowWDL": false,
"Razoring_MaxDepth": 2,
"Razoring_Depth1Bonus": 125,
"Razoring_NotDepth1Bonus": 175
},

// Logging settings
Expand Down
6 changes: 6 additions & 0 deletions src/Lynx/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,12 @@ public sealed class EngineSettings
public int RFP_DepthScalingFactor { get; set; } = 75;

public bool ShowWDL { get; set; } = false;

public int Razoring_MaxDepth { get; set; } = 2;

public int Razoring_Depth1Bonus { get; set; } = 125;

public int Razoring_NotDepth1Bonus{ get; set; } = 175;
}

[JsonSourceGenerationOptions(
Expand Down
38 changes: 34 additions & 4 deletions src/Lynx/Search/NegaMax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,46 @@ private int NegaMax(int depth, int ply, int alpha, int beta, bool isVerifyingNul

VerifiedNullMovePruning_SearchAgain:

// 🔍 Reverse FutilityPrunning (RFP) - https://www.chessprogramming.org/Reverse_Futility_Pruning
if (!pvNode && !isInCheck
&& depth <= Configuration.EngineSettings.RFP_MaxDepth)
if (!pvNode && !isInCheck && depth <= Configuration.EngineSettings.RFP_MaxDepth)
{
var staticEval = position.StaticEvaluation(Game.HalfMovesWithoutCaptureOrPawnMove);
int staticEval = position.StaticEvaluation(Game.HalfMovesWithoutCaptureOrPawnMove);

// 🔍 Reverse FutilityPrunning (RFP) - https://www.chessprogramming.org/Reverse_Futility_Pruning
if (staticEval - (Configuration.EngineSettings.RFP_DepthScalingFactor * depth) >= beta)
{
return staticEval;
}

// 🔍 Razoring - Strelka impl (CPW) - https://www.chessprogramming.org/Razoring#Strelka
if (depth <= Configuration.EngineSettings.Razoring_MaxDepth)
{
var score = staticEval + Configuration.EngineSettings.Razoring_Depth1Bonus;

if (score < beta) // Static evaluation + bonus indicates fail-low node
{
if (depth == 1)
{
var qSearchScore = QuiescenceSearch(ply, alpha, beta);

return qSearchScore > score
? qSearchScore
: score;
}

score += Configuration.EngineSettings.Razoring_NotDepth1Bonus;

if (score < beta) // Static evaluation indicates fail-low node
{
var qSearchScore = QuiescenceSearch(ply, alpha, beta);
if (qSearchScore < beta) // Quiescence score also indicates fail-low node
{
return qSearchScore > score
? qSearchScore
: score;
}
}
}
}
}

var nodeType = NodeType.Alpha;
Expand Down
29 changes: 29 additions & 0 deletions tests/Lynx.Test/ConfigurationValuesTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Microsoft.Extensions.Configuration;
using NUnit.Framework;

namespace Lynx.Test;

/// <summary>
/// Current logic relies on this
/// </summary>
[Explicit]
[Category(Categories.Configuration)]
[NonParallelizable]
public class ConfigurationValuesTest
{
[Test]
public void RazoringValues()
{
Assert.Greater(Configuration.EngineSettings.RFP_MaxDepth, Configuration.EngineSettings.Razoring_MaxDepth);

var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false)
.Build();

var engineSettingsSection = config.GetRequiredSection(nameof(EngineSettings));
Assert.IsNotNull(engineSettingsSection);
engineSettingsSection.Bind(Configuration.EngineSettings);

Assert.Greater(Configuration.EngineSettings.RFP_MaxDepth, Configuration.EngineSettings.Razoring_MaxDepth);
}
}