From: Vizvezdenec Date: Mon, 15 Mar 2021 18:05:01 +0000 (+0100) Subject: Add a specific FRC correction from classical to NNUE X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=ace9632c6713e346ccca73b3e2edc046c1f5527c Add a specific FRC correction from classical to NNUE our net currently is not trained on FRC games, and so doesn't know about the important pattern of a bishop that is cornered in FRC. This patch introduces a term we have in the classical evaluation for this case, and adds it to the NNUE eval. Since fishtest doesn't support FRC right now, the patch was tested locally at STC conditions, starting from the book of FRC starting positions. Score of master vs patch: 993 - 2226 - 6781 [0.438] 10000 Which corresponds to approximately 40 Elo The patch passes non-regression testing for traditional chess (where it adds one branch). passed STC: https://tests.stockfishchess.org/tests/view/604fa2532433018de7a38b67 LLR: 2.95 (-2.94,2.94) {-1.25,0.25} Total: 30560 W: 2701 L: 2636 D: 25223 Ptnml(0-2): 88, 2056, 10921, 2133, 82 passed STC also in an earlier version: https://tests.stockfishchess.org/tests/view/604f61282433018de7a38b4d closes https://github.com/official-stockfish/Stockfish/pull/3398 No functional change --- diff --git a/src/evaluate.cpp b/src/evaluate.cpp index d43b8fa7..bb4f9ef7 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -1038,6 +1038,45 @@ make_v: return v; } + // specifically correct for cornered bishops to fix FRC with NNUE. + Value fix_FRC(const Position& pos) { + + Value bAdjust = Value(0); + + constexpr Value p1=Value(209), p2=Value(136), p3=Value(148); + + Color Us = pos.side_to_move(); + if ( (pos.pieces(Us, BISHOP) & relative_square(Us, SQ_A1)) + && (pos.pieces(Us, PAWN) & relative_square(Us, SQ_B2))) + { + bAdjust -= !pos.empty(relative_square(Us,SQ_B3)) ? p1 + : pos.piece_on(relative_square(Us,SQ_C3)) == make_piece(Us, PAWN) ? p2 + : p3; + } + if ( (pos.pieces(Us, BISHOP) & relative_square(Us, SQ_H1)) + && (pos.pieces(Us, PAWN) & relative_square(Us, SQ_G2))) + { + bAdjust -= !pos.empty(relative_square(Us,SQ_G3)) ? p1 + : pos.piece_on(relative_square(Us,SQ_F3)) == make_piece(Us, PAWN) ? p2 + : p3; + } + if ( (pos.pieces(~Us, BISHOP) & relative_square(Us, SQ_A8)) + && (pos.pieces(~Us, PAWN) & relative_square(Us, SQ_B7))) + { + bAdjust += !pos.empty(relative_square(Us,SQ_B6)) ? p1 + : pos.piece_on(relative_square(Us,SQ_C6)) == make_piece(~Us, PAWN) ? p2 + : p3; + } + if ( (pos.pieces(~Us, BISHOP) & relative_square(Us, SQ_H8)) + && (pos.pieces(~Us, PAWN) & relative_square(Us, SQ_G7))) + { + bAdjust += !pos.empty(relative_square(Us,SQ_G6)) ? p1 + : pos.piece_on(relative_square(Us,SQ_F6)) == make_piece(~Us, PAWN) ? p2 + : p3; + } + return bAdjust; + } + } // namespace @@ -1055,7 +1094,12 @@ Value Eval::evaluate(const Position& pos) { // Scale and shift NNUE for compatibility with search and classical evaluation auto adjusted_NNUE = [&](){ int mat = pos.non_pawn_material() + 2 * PawnValueMg * pos.count(); - return NNUE::evaluate(pos) * (641 + mat / 32 - 4 * pos.rule50_count()) / 1024 + Tempo; + Value nnueValue = NNUE::evaluate(pos) * (641 + mat / 32 - 4 * pos.rule50_count()) / 1024 + Tempo; + + if (pos.is_chess960()) + nnueValue += fix_FRC(pos); + + return nnueValue; }; // If there is PSQ imbalance use classical eval, with small probability if it is small