diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 64f9172574a..dcc7401be2c 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,8 @@ namespace Eval { bool useNNUE; string eval_file_loaded = "None"; + int NNUE::RandomEvalPerturb = 0; + /// NNUE::init() tries to load a NNUE network at startup time, or when the engine /// receives a UCI command "setoption name EvalFile value nn-[a-z0-9]{12}.nnue" /// The name of the NNUE network is always retrieved from the EvalFile option. @@ -1081,6 +1084,10 @@ namespace { Value Eval::evaluate(const Position& pos) { + static thread_local std::mt19937_64 tls_rng = [](){ + return std::mt19937_64(std::time(0)); + }(); + Value v; if (!Eval::useNNUE) @@ -1107,6 +1114,7 @@ Value Eval::evaluate(const Position& pos) { int r50 = pos.rule50_count(); Value psq = Value(abs(eg_value(pos.psq_score()))); bool classical = psq * 5 > (850 + pos.non_pawn_material() / 64) * (5 + r50); + classical = false; v = classical ? Evaluation(pos).value() // classical : adjusted_NNUE(); // NNUE @@ -1115,6 +1123,12 @@ Value Eval::evaluate(const Position& pos) { // Damp down the evaluation linearly when shuffling v = v * (100 - pos.rule50_count()) / 100; + std::normal_distribution d(0.0, RookValueEg); + float r = d(tls_rng); + r = std::clamp(r, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); + + v = (NNUE::RandomEvalPerturb * Value(r) + (100 - NNUE::RandomEvalPerturb) * v) / 100; + // Guarantee evaluation does not hit the tablebase range v = std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); diff --git a/src/evaluate.h b/src/evaluate.h index 4430a28c807..1b087f1bce9 100644 --- a/src/evaluate.h +++ b/src/evaluate.h @@ -43,6 +43,8 @@ namespace Eval { namespace NNUE { + extern int RandomEvalPerturb; + std::string trace(Position& pos); Value evaluate(const Position& pos, bool adjusted = false); diff --git a/src/ucioption.cpp b/src/ucioption.cpp index 07b3027da70..886e583af8e 100644 --- a/src/ucioption.cpp +++ b/src/ucioption.cpp @@ -42,6 +42,7 @@ void on_clear_hash(const Option&) { Search::clear(); } void on_hash_size(const Option& o) { TT.resize(size_t(o)); } void on_logger(const Option& o) { start_logger(o); } void on_threads(const Option& o) { Threads.set(size_t(o)); } +void on_eval_perturb(const Option& o) { Eval::NNUE::RandomEvalPerturb = o; } void on_tb_path(const Option& o) { Tablebases::init(o); } void on_use_NNUE(const Option& ) { Eval::NNUE::init(); } void on_eval_file(const Option& ) { Eval::NNUE::init(); } @@ -62,6 +63,7 @@ void init(OptionsMap& o) { o["Debug Log File"] << Option("", on_logger); o["Threads"] << Option(1, 1, 512, on_threads); + o["RandomEvalPerturb"] << Option(0, 0, 100, on_eval_perturb); o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size); o["Clear Hash"] << Option(on_clear_hash); o["Ponder"] << Option(false);