From 787b2e1bfa5a363860f1a4ed52c67910188ec681 Mon Sep 17 00:00:00 2001 From: Jay Honnold Date: Fri, 29 Mar 2024 17:26:21 -0700 Subject: [PATCH 1/6] SPSA Tune for 7016 iterations (#554) Bench: 3040242 Elo | 5.07 +- 4.13 (95%) SPRT | 60.0+0.60s Threads=1 Hash=64MB LLR | 2.36 (-2.25, 2.89) [0.00, 2.50] Games | N: 12480 W: 2965 L: 2783 D: 6732 Penta | [21, 1309, 3394, 1499, 17] http://chess.grantnet.us/test/36083/ --- src/history.c | 2 +- src/history.h | 2 +- src/makefile | 2 +- src/search.c | 50 +++++++++++++++++++++++++------------------------- src/uci.c | 4 ++-- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/history.c b/src/history.c index 291caf61..00f1bb00 100644 --- a/src/history.c +++ b/src/history.c @@ -47,7 +47,7 @@ void UpdateHistories(SearchStack* ss, // Only increase the best move history when it // wasn't trivial. This idea was first thought of // by Alayan in Ethereal - if (nQ > 1 || depth > 3) { + if (nQ > 1 || depth > 4) { AddHistoryHeuristic(&HH(stm, bestMove, board->threatened), inc); UpdateCH(ss, bestMove, inc); } diff --git a/src/history.h b/src/history.h index a874f4b8..8e44cabe 100644 --- a/src/history.h +++ b/src/history.h @@ -58,7 +58,7 @@ INLINE void AddCounterMove(ThreadData* thread, Move move, Move parent) { } INLINE int16_t HistoryBonus(int depth) { - return Min(1896, 4 * depth * depth + 120 * depth - 120); + return Min(1729, 4 * depth * depth + 164 * depth - 113); } INLINE void AddHistoryHeuristic(int16_t* entry, int16_t inc) { diff --git a/src/makefile b/src/makefile index cd53c4c2..cf827e9c 100644 --- a/src/makefile +++ b/src/makefile @@ -3,7 +3,7 @@ EXE = berserk SRC = attacks.c bench.c berserk.c bits.c board.c eval.c history.c move.c movegen.c movepick.c perft.c random.c \ search.c see.c tb.c thread.c transposition.c uci.c util.c zobrist.c nn/accumulator.c nn/evaluate.c pyrrhic/tbprobe.c CC = clang -VERSION = 20240324 +VERSION = 20240329 MAIN_NETWORK = berserk-d43206fe90e4.nn EVALFILE = $(MAIN_NETWORK) DEFS = -DVERSION=\"$(VERSION)\" -DEVALFILE=\"$(EVALFILE)\" -DNDEBUG diff --git a/src/search.c b/src/search.c index f1894531..a9bc36d0 100644 --- a/src/search.c +++ b/src/search.c @@ -49,7 +49,7 @@ int STATIC_PRUNE[2][MAX_SEARCH_PLY]; void InitPruningAndReductionTables() { for (int depth = 1; depth < MAX_SEARCH_PLY; depth++) for (int moves = 1; moves < 64; moves++) - LMR[depth][moves] = log(depth) * log(moves) / 2.1872 + 0.2487; + LMR[depth][moves] = log(depth) * log(moves) / 2.0385 + 0.2429; LMR[0][0] = LMR[0][1] = LMR[1][0] = 0; @@ -57,11 +57,11 @@ void InitPruningAndReductionTables() { // LMP has both a improving (more strict) and non-improving evalution // parameter for lmp. If the evaluation is getting better we want to check // more - LMP[0][depth] = 1.2973 + 0.3772 * depth * depth; - LMP[1][depth] = 2.7002 + 0.9448 * depth * depth; + LMP[0][depth] = 1.3050 + 0.3503 * depth * depth; + LMP[1][depth] = 2.1885 + 0.9911 * depth * depth; - STATIC_PRUNE[0][depth] = -14.9419 * depth * depth; // quiet move cutoff - STATIC_PRUNE[1][depth] = -103.9379 * depth; // capture cutoff + STATIC_PRUNE[0][depth] = -15.2703 * depth * depth; // quiet move cutoff + STATIC_PRUNE[1][depth] = -94.0617 * depth; // capture cutoff } } @@ -299,7 +299,7 @@ void Search(ThreadData* thread) { break; // delta x 1.25 - delta += delta / 4; + delta += 17 * delta / 64; } SortRootMoves(thread, 0); @@ -326,7 +326,7 @@ void Search(ThreadData* thread) { if (Limits.timeset && thread->depth >= 5 && !Threads.stopOnPonderHit) { int sameBestMove = bestMove == previousBestMove; // same move? searchStability = sameBestMove ? Min(10, searchStability + 1) : 0; // increase how stable our best move is - double stabilityFactor = 1.3658 - 0.0482 * searchStability; + double stabilityFactor = 1.3110 - 0.0533 * searchStability; Score searchScoreDiff = scores[thread->depth - 3] - bestScore; Score prevScoreDiff = thread->previousScore - bestScore; @@ -335,14 +335,14 @@ void Search(ThreadData* thread) { if (thread->previousScore == UNKNOWN) searchScoreDiff *= 2, prevScoreDiff = 0; - double scoreChangeFactor = 0.0995 + // - 0.0286 * searchScoreDiff * (searchScoreDiff > 0) + // + double scoreChangeFactor = 0.1127 + // + 0.0262 * searchScoreDiff * (searchScoreDiff > 0) + // 0.0261 * prevScoreDiff * (prevScoreDiff > 0); - scoreChangeFactor = Max(0.4843, Min(1.4498, scoreChangeFactor)); + scoreChangeFactor = Max(0.5028, Min(1.6561, scoreChangeFactor)); uint64_t bestMoveNodes = thread->rootMoves[0].nodes; double pctNodesNotBest = 1.0 - (double) bestMoveNodes / thread->nodes; - double nodeCountFactor = Max(0.5464, pctNodesNotBest * 2.1394 + 0.4393); + double nodeCountFactor = Max(0.5630, pctNodesNotBest * 2.2669 + 0.4499); if (bestScore >= TB_WIN_BOUND) nodeCountFactor = 0.5; @@ -514,13 +514,13 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* // Reverse Futility Pruning // i.e. the static eval is so far above beta we prune - if (depth <= 8 && !ss->skip && eval < TB_WIN_BOUND && eval >= beta && - eval - 67 * depth + 112 * (improving && !opponentHasEasyCapture) >= beta && - (!hashMove || GetHistory(ss, thread, hashMove) > 12525)) + if (depth <= 9 && !ss->skip && eval < TB_WIN_BOUND && eval >= beta && + eval - 70 * depth + 118 * (improving && !opponentHasEasyCapture) >= beta && + (!hashMove || GetHistory(ss, thread, hashMove) > 11800)) return (eval + beta) / 2; // Razoring - if (depth <= 6 && eval + 252 * depth <= alpha) { + if (depth <= 5 && eval + 214 * depth <= alpha) { score = Quiesce(alpha, beta, 0, thread, ss); if (score <= alpha) return score; @@ -532,7 +532,7 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* // threats) if (depth >= 4 && (ss - 1)->move != NULL_MOVE && !ss->skip && !opponentHasEasyCapture && eval >= beta && HasNonPawn(board, board->stm) && (ss->ply >= thread->nmpMinPly || board->stm != thread->npmColor)) { - int R = 4 + 342 * depth / 1024 + Min(10 * (eval - beta) / 1024, 4); + int R = 4 + 385 * depth / 1024 + Min(10 * (eval - beta) / 1024, 4); TTPrefetch(KeyAfter(board, NULL_MOVE)); ss->move = NULL_MOVE; @@ -565,8 +565,8 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* // Prob cut // If a relatively deep search from our TT doesn't say this node is // less than beta + margin, then we run a shallow search to look - int probBeta = beta + 197; - if (depth >= 5 && !ss->skip && abs(beta) < TB_WIN_BOUND && !(ttHit && ttDepth >= depth - 3 && ttScore < probBeta)) { + int probBeta = beta + 172; + if (depth >= 6 && !ss->skip && abs(beta) < TB_WIN_BOUND && !(ttHit && ttDepth >= depth - 3 && ttScore < probBeta)) { InitPCMovePicker(&mp, thread, probBeta > eval); while ((move = NextMove(&mp, board, 1))) { if (!IsLegal(move, board)) @@ -625,12 +625,12 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* if (!IsCap(move) && PromoPT(move) != QUEEN) { int lmrDepth = Max(1, depth - R); - if (!killerOrCounter && lmrDepth < 7 && history < -2658 * (depth - 1)) { + if (!killerOrCounter && lmrDepth < 5 && history < -2788 * (depth - 1)) { skipQuiets = 1; continue; } - if (!inCheck && lmrDepth < 10 && eval + 87 + 46 * lmrDepth <= alpha) + if (!inCheck && lmrDepth < 10 && eval + 81 + 46 * lmrDepth <= alpha) skipQuiets = 1; if (!SEE(board, move, STATIC_PRUNE[0][lmrDepth])) @@ -673,10 +673,10 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* // no score failed above sBeta, so this is singular if (score < sBeta) { - if (!isPV && score < sBeta - 50 && ss->de <= 6 && !IsCap(move)) { + if (!isPV && score < sBeta - 48 && ss->de <= 6 && !IsCap(move)) { extension = 3; ss->de = (ss - 1)->de + 1; - } else if (!isPV && score < sBeta - 17 && ss->de <= 6) { + } else if (!isPV && score < sBeta - 14 && ss->de <= 6) { extension = 2; ss->de = (ss - 1)->de + 1; } else { @@ -738,7 +738,7 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* if (score > alpha && R > 1) { // Credit to Viz (and lonfom) for the following modification of the zws // re-search depth. They can be found in SF as doDeeperSearch + doShallowerSearch - newDepth += (score > bestScore + 76); + newDepth += (score > bestScore + 69); newDepth -= (score < bestScore + newDepth); if (newDepth - 1 > lmrDepth) @@ -798,7 +798,7 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* // we're failing high if (alpha >= beta) { - UpdateHistories(ss, thread, move, depth + (bestScore > beta + 78), quiets, numQuiets, captures, numCaptures); + UpdateHistories(ss, thread, move, depth + (bestScore > beta + 77), quiets, numQuiets, captures, numCaptures); break; } } @@ -898,7 +898,7 @@ int Quiesce(int alpha, int beta, int depth, ThreadData* thread, SearchStack* ss) bestScore = eval; - futility = bestScore + 60; + futility = bestScore + 63; } int numQuiets = 0, numCaptures = 0; diff --git a/src/uci.c b/src/uci.c index 710b359e..0b78d721 100644 --- a/src/uci.c +++ b/src/uci.c @@ -178,8 +178,8 @@ void ParseGo(char* in, Board* board) { if (movesToGo == -1) { int total = Max(1, time + 50 * inc - 50 * MOVE_OVERHEAD); - Limits.alloc = Min(time * 0.3784, total * 0.0570); - Limits.max = Min(time * 0.7776 - MOVE_OVERHEAD, Limits.alloc * 5.8320) - 10; + Limits.alloc = Min(time * 0.4193, total * 0.0575); + Limits.max = Min(time * 0.9221 - MOVE_OVERHEAD, Limits.alloc * 5.9280) - 10; } else { int total = Max(1, time + movesToGo * inc - MOVE_OVERHEAD); From 9439b87063af42a90a05483a2c9b8cc42b41f7e9 Mon Sep 17 00:00:00 2001 From: Jay Honnold Date: Sat, 30 Mar 2024 22:05:31 -0700 Subject: [PATCH 2/6] Update WDL Model for Berserk 13 Bench: 3040242 Non-functional change --- src/makefile | 2 +- src/uci.c | 4 ++-- src/uci.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/makefile b/src/makefile index cf827e9c..5382cc6d 100644 --- a/src/makefile +++ b/src/makefile @@ -3,7 +3,7 @@ EXE = berserk SRC = attacks.c bench.c berserk.c bits.c board.c eval.c history.c move.c movegen.c movepick.c perft.c random.c \ search.c see.c tb.c thread.c transposition.c uci.c util.c zobrist.c nn/accumulator.c nn/evaluate.c pyrrhic/tbprobe.c CC = clang -VERSION = 20240329 +VERSION = 13 MAIN_NETWORK = berserk-d43206fe90e4.nn EVALFILE = $(MAIN_NETWORK) DEFS = -DVERSION=\"$(VERSION)\" -DEVALFILE=\"$(EVALFILE)\" -DNDEBUG diff --git a/src/uci.c b/src/uci.c index 0b78d721..cf765679 100644 --- a/src/uci.c +++ b/src/uci.c @@ -54,8 +54,8 @@ SearchParams Limits; // this repo: https://github.com/vondele/WLD_model // Third order polynomial fit of Berserk data -const double as[4] = {-5.83465749, 46.43599644, -58.49798392, 172.62328616}; -const double bs[4] = {-7.95320845, 48.50833438, -66.34647240, 56.29169197}; +const double as[4] = {-2.02923586, 16.87641200, -27.06230207, 182.53858835}; +const double bs[4] = {-6.15230497, 42.37548361, -80.19006222, 77.75994970}; // win% as permilli given score and ply int WRModel(Score s, int ply) { diff --git a/src/uci.h b/src/uci.h index 937c6be5..60a770c0 100644 --- a/src/uci.h +++ b/src/uci.h @@ -25,7 +25,7 @@ extern int CONTEMPT; extern SearchParams Limits; // Normalization of a score to 50% WR at 100cp -#define Normalize(s) ((s) / 1.54) +#define Normalize(s) ((s) / 1.70) int WRModel(Score s, int ply); From d7b13294ea51838247386ce8cde7ec5b399b695b Mon Sep 17 00:00:00 2001 From: Jay Honnold Date: Tue, 12 Nov 2024 17:30:15 -0700 Subject: [PATCH 3/6] Utilize depth when updating pawn correction history (#567) Bench: 2818506 Elo | 4.13 +- 2.21 (95%) SPRT | 10.0+0.10s Threads=1 Hash=8MB LLR | 2.91 (-2.25, 2.89) [0.00, 2.00] Games | N: 25002 W: 6182 L: 5885 D: 12935 Penta | [75, 2834, 6405, 3093, 94] http://chess.grantnet.us/test/38329/ Elo | 3.17 +- 2.02 (95%) SPRT | 60.0+0.60s Threads=1 Hash=64MB LLR | 2.90 (-2.25, 2.89) [0.00, 2.50] Games | N: 26338 W: 6063 L: 5823 D: 14452 Penta | [23, 2839, 7211, 3067, 29] http://chess.grantnet.us/test/38330/ --- src/history.c | 5 +++-- src/history.h | 2 +- src/makefile | 2 +- src/search.c | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/history.c b/src/history.c index 00f1bb00..394fd9fd 100644 --- a/src/history.c +++ b/src/history.c @@ -87,9 +87,10 @@ void UpdateHistories(SearchStack* ss, } } -void UpdatePawnCorrection(int raw, int real, Board* board, ThreadData* thread) { +void UpdatePawnCorrection(int raw, int real, int depth, Board* board, ThreadData* thread) { const int16_t correction = Min(30000, Max(-30000, (real - raw) * PAWN_CORRECTION_GRAIN)); const int idx = (board->pawnZobrist & PAWN_CORRECTION_MASK); + const int saveDepth = Min(16, depth); - thread->pawnCorrection[idx] = (thread->pawnCorrection[idx] * 255 + correction) / 256; + thread->pawnCorrection[idx] = (thread->pawnCorrection[idx] * (256 - saveDepth) + correction * saveDepth) / 256; } diff --git a/src/history.h b/src/history.h index 8e44cabe..1c2a4bf8 100644 --- a/src/history.h +++ b/src/history.h @@ -89,6 +89,6 @@ void UpdateHistories(SearchStack* ss, Move captures[], int nC); -void UpdatePawnCorrection(int raw, int real, Board* board, ThreadData* thread); +void UpdatePawnCorrection(int raw, int real, int depth, Board* board, ThreadData* thread); #endif \ No newline at end of file diff --git a/src/makefile b/src/makefile index 5382cc6d..72213649 100644 --- a/src/makefile +++ b/src/makefile @@ -3,7 +3,7 @@ EXE = berserk SRC = attacks.c bench.c berserk.c bits.c board.c eval.c history.c move.c movegen.c movepick.c perft.c random.c \ search.c see.c tb.c thread.c transposition.c uci.c util.c zobrist.c nn/accumulator.c nn/evaluate.c pyrrhic/tbprobe.c CC = clang -VERSION = 13 +VERSION = 20241112 MAIN_NETWORK = berserk-d43206fe90e4.nn EVALFILE = $(MAIN_NETWORK) DEFS = -DVERSION=\"$(VERSION)\" -DEVALFILE=\"$(EVALFILE)\" -DNDEBUG diff --git a/src/search.c b/src/search.c index a9bc36d0..d11bfbec 100644 --- a/src/search.c +++ b/src/search.c @@ -817,7 +817,7 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* TTPut(tt, board->zobrist, depth, bestScore, bound, bestMove, ss->ply, rawEval, ttPv); if (!inCheck && !IsCap(bestMove) && (bound & (bestScore >= rawEval ? BOUND_LOWER : BOUND_UPPER))) - UpdatePawnCorrection(rawEval, bestScore, board, thread); + UpdatePawnCorrection(rawEval, bestScore, depth, board, thread); return bestScore; } From 525dab9923415139bd53303834d9f01d040102d8 Mon Sep 17 00:00:00 2001 From: Jay Honnold Date: Wed, 13 Nov 2024 16:08:22 -0700 Subject: [PATCH 4/6] Continuation Correction History (#568) Bench: 2996197 Elo | 2.75 +- 1.76 (95%) SPRT | 10.0+0.10s Threads=1 Hash=8MB LLR | 2.90 (-2.25, 2.89) [0.00, 2.00] Games | N: 41026 W: 9885 L: 9560 D: 21581 Penta | [163, 4762, 10379, 5005, 204] http://chess.grantnet.us/test/38332/ Elo | 5.46 +- 2.82 (95%) SPRT | 60.0+0.60s Threads=1 Hash=64MB LLR | 2.89 (-2.25, 2.89) [0.00, 2.50] Games | N: 14254 W: 3416 L: 3192 D: 7646 Penta | [19, 1548, 3773, 1764, 23] http://chess.grantnet.us/test/38335/ --- src/history.c | 15 ++++++++++++++- src/history.h | 14 +++++++++++++- src/makefile | 2 +- src/search.c | 13 ++++++++----- src/types.h | 4 +++- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/history.c b/src/history.c index 394fd9fd..b9b84563 100644 --- a/src/history.c +++ b/src/history.c @@ -88,9 +88,22 @@ void UpdateHistories(SearchStack* ss, } void UpdatePawnCorrection(int raw, int real, int depth, Board* board, ThreadData* thread) { - const int16_t correction = Min(30000, Max(-30000, (real - raw) * PAWN_CORRECTION_GRAIN)); + const int16_t correction = Min(30000, Max(-30000, (real - raw) * CORRECTION_GRAIN)); const int idx = (board->pawnZobrist & PAWN_CORRECTION_MASK); const int saveDepth = Min(16, depth); thread->pawnCorrection[idx] = (thread->pawnCorrection[idx] * (256 - saveDepth) + correction * saveDepth) / 256; } + +void UpdateContCorrection(int raw, int real, int depth, SearchStack* ss, ThreadData* thread) { + const Move m1 = (ss - 1)->move; + const Move m2 = (ss - 2)->move; + + if (m1 && m2) { + const int16_t correction = Min(30000, Max(-30000, (real - raw) * CORRECTION_GRAIN)); + const int saveDepth = Min(16, depth); + + int16_t* contCorrection = &thread->contCorrection[Moving(m1)][To(m1)][Moving(m2)][To(m2)]; + *contCorrection = (*contCorrection * (256 - saveDepth) + correction * saveDepth) / 256; + } +} diff --git a/src/history.h b/src/history.h index 1c2a4bf8..a27e540f 100644 --- a/src/history.h +++ b/src/history.h @@ -77,7 +77,18 @@ INLINE void UpdateCH(SearchStack* ss, Move move, int16_t bonus) { } INLINE int GetPawnCorrection(Board* board, ThreadData* thread) { - return thread->pawnCorrection[board->pawnZobrist & PAWN_CORRECTION_MASK] / PAWN_CORRECTION_GRAIN; + return thread->pawnCorrection[board->pawnZobrist & PAWN_CORRECTION_MASK] / CORRECTION_GRAIN; +} + +INLINE int GetContCorrection(SearchStack* ss, ThreadData* thread) { + const Move m1 = (ss - 1)->move; + const Move m2 = (ss - 2)->move; + + if (m1 && m2) { + return thread->contCorrection[Moving(m1)][To(m1)][Moving(m2)][To(m2)] / CORRECTION_GRAIN; + } else { + return 0; + } } void UpdateHistories(SearchStack* ss, @@ -90,5 +101,6 @@ void UpdateHistories(SearchStack* ss, int nC); void UpdatePawnCorrection(int raw, int real, int depth, Board* board, ThreadData* thread); +void UpdateContCorrection(int raw, int real, int depth, SearchStack* ss, ThreadData* thread); #endif \ No newline at end of file diff --git a/src/makefile b/src/makefile index 72213649..dc19a0cc 100644 --- a/src/makefile +++ b/src/makefile @@ -3,7 +3,7 @@ EXE = berserk SRC = attacks.c bench.c berserk.c bits.c board.c eval.c history.c move.c movegen.c movepick.c perft.c random.c \ search.c see.c tb.c thread.c transposition.c uci.c util.c zobrist.c nn/accumulator.c nn/evaluate.c pyrrhic/tbprobe.c CC = clang -VERSION = 20241112 +VERSION = 20241113 MAIN_NETWORK = berserk-d43206fe90e4.nn EVALFILE = $(MAIN_NETWORK) DEFS = -DVERSION=\"$(VERSION)\" -DEVALFILE=\"$(EVALFILE)\" -DNDEBUG diff --git a/src/search.c b/src/search.c index d11bfbec..015c465c 100644 --- a/src/search.c +++ b/src/search.c @@ -468,7 +468,7 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* rawEval = ttEval; if (rawEval == EVAL_UNKNOWN) rawEval = Evaluate(board, thread); - eval = ss->staticEval = ClampEval(rawEval + GetPawnCorrection(board, thread) / 2); + eval = ss->staticEval = ClampEval(rawEval + GetPawnCorrection(board, thread) / 2 + GetContCorrection(ss, thread)); // correct eval on fmr eval = AdjustEvalOnFMR(board, eval); @@ -477,7 +477,7 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* eval = ttScore; } else if (!ss->skip) { rawEval = Evaluate(board, thread); - eval = ss->staticEval = ClampEval(rawEval + GetPawnCorrection(board, thread) / 2); + eval = ss->staticEval = ClampEval(rawEval + GetPawnCorrection(board, thread) / 2 + GetContCorrection(ss, thread)); // correct eval on fmr eval = AdjustEvalOnFMR(board, eval); @@ -816,8 +816,10 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* if (!ss->skip && !(isRoot && thread->multiPV > 0)) TTPut(tt, board->zobrist, depth, bestScore, bound, bestMove, ss->ply, rawEval, ttPv); - if (!inCheck && !IsCap(bestMove) && (bound & (bestScore >= rawEval ? BOUND_LOWER : BOUND_UPPER))) + if (!inCheck && !IsCap(bestMove) && (bound & (bestScore >= rawEval ? BOUND_LOWER : BOUND_UPPER))) { UpdatePawnCorrection(rawEval, bestScore, depth, board, thread); + UpdateContCorrection(rawEval, bestScore, depth, ss, thread); + } return bestScore; } @@ -872,7 +874,7 @@ int Quiesce(int alpha, int beta, int depth, ThreadData* thread, SearchStack* ss) rawEval = ttEval; if (rawEval == EVAL_UNKNOWN) rawEval = Evaluate(board, thread); - eval = ss->staticEval = ClampEval(rawEval + GetPawnCorrection(board, thread) / 2); + eval = ss->staticEval = ClampEval(rawEval + GetPawnCorrection(board, thread) / 2 + GetContCorrection(ss, thread)); // correct eval on fmr eval = AdjustEvalOnFMR(board, eval); @@ -881,7 +883,7 @@ int Quiesce(int alpha, int beta, int depth, ThreadData* thread, SearchStack* ss) eval = ttScore; } else { rawEval = Evaluate(board, thread); - eval = ss->staticEval = ClampEval(rawEval + GetPawnCorrection(board, thread) / 2); + eval = ss->staticEval = ClampEval(rawEval + GetPawnCorrection(board, thread) / 2 + GetContCorrection(ss, thread)); // correct eval on fmr eval = AdjustEvalOnFMR(board, eval); @@ -1065,6 +1067,7 @@ void SearchClearThread(ThreadData* thread) { memset(&thread->ch, 0, sizeof(thread->ch)); memset(&thread->caph, 0, sizeof(thread->caph)); memset(&thread->pawnCorrection, 0, sizeof(thread->pawnCorrection)); + memset(&thread->contCorrection, 0, sizeof(thread->contCorrection)); thread->board.accumulators = thread->accumulators; thread->previousScore = UNKNOWN; diff --git a/src/types.h b/src/types.h index c441f839..3f0fc0b7 100644 --- a/src/types.h +++ b/src/types.h @@ -38,7 +38,8 @@ #define ALIGN_ON 64 #define ALIGN __attribute__((aligned(ALIGN_ON))) -#define PAWN_CORRECTION_GRAIN 256 +#define CORRECTION_GRAIN 256 + #define PAWN_CORRECTION_SIZE 131072 #define PAWN_CORRECTION_MASK (PAWN_CORRECTION_SIZE - 1) @@ -198,6 +199,7 @@ struct ThreadData { int16_t caph[12][64][2][7]; // capture history (piece - to - defeneded - captured_type) int16_t pawnCorrection[PAWN_CORRECTION_SIZE]; + int16_t contCorrection[12][64][12][64]; int action, calls; pthread_t nativeThread; From 899c0bee294a1a07cda8379fd5b3fb7551470ce7 Mon Sep 17 00:00:00 2001 From: Jay Honnold Date: Tue, 19 Nov 2024 06:08:14 -0700 Subject: [PATCH 5/6] "Opponent Worsening" in RFP (#569) Bench: 2625158 Idea from Stockfish. If the opponents last move decreases the static evaluation of the position for them, then slightly increase the possibility of RFP. Elo | 1.65 +- 1.24 (95%) SPRT | 10.0+0.10s Threads=1 Hash=8MB LLR | 2.91 (-2.25, 2.89) [0.00, 2.00] Games | N: 79656 W: 19260 L: 18881 D: 41515 Penta | [257, 9340, 20285, 9659, 287] http://chess.grantnet.us/test/38374/ Elo | 1.11 +- 0.90 (95%) SPRT | 60.0+0.60s Threads=1 Hash=64MB LLR | 2.89 (-2.25, 2.89) [0.00, 2.50] Games | N: 132546 W: 30745 L: 30323 D: 71478 Penta | [97, 14681, 36303, 15087, 105] http://chess.grantnet.us/test/38375/ --- src/makefile | 2 +- src/search.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/makefile b/src/makefile index dc19a0cc..8df616f2 100644 --- a/src/makefile +++ b/src/makefile @@ -3,7 +3,7 @@ EXE = berserk SRC = attacks.c bench.c berserk.c bits.c board.c eval.c history.c move.c movegen.c movepick.c perft.c random.c \ search.c see.c tb.c thread.c transposition.c uci.c util.c zobrist.c nn/accumulator.c nn/evaluate.c pyrrhic/tbprobe.c CC = clang -VERSION = 20241113 +VERSION = 20241119 MAIN_NETWORK = berserk-d43206fe90e4.nn EVALFILE = $(MAIN_NETWORK) DEFS = -DVERSION=\"$(VERSION)\" -DEVALFILE=\"$(EVALFILE)\" -DNDEBUG diff --git a/src/search.c b/src/search.c index 015c465c..55926f2d 100644 --- a/src/search.c +++ b/src/search.c @@ -511,11 +511,12 @@ int Negamax(int alpha, int beta, int depth, int cutnode, ThreadData* thread, PV* MovePicker mp; if (!isPV && !inCheck) { const int opponentHasEasyCapture = !!OpponentsEasyCaptures(board); + const int opponentDeclining = ss->staticEval + (ss - 1)->staticEval > 1; // Reverse Futility Pruning // i.e. the static eval is so far above beta we prune if (depth <= 9 && !ss->skip && eval < TB_WIN_BOUND && eval >= beta && - eval - 70 * depth + 118 * (improving && !opponentHasEasyCapture) >= beta && + eval - 70 * depth + 118 * (improving && !opponentHasEasyCapture) + 25 * opponentDeclining >= beta && (!hashMove || GetHistory(ss, thread, hashMove) > 11800)) return (eval + beta) / 2; From 8a6282eee96d30441d262552a89846b90f86f139 Mon Sep 17 00:00:00 2001 From: Jay Honnold Date: Sat, 23 Nov 2024 09:40:38 -0700 Subject: [PATCH 6/6] Update makefile to fail fast if download-network fails Bench: 2625158 --- src/makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/makefile b/src/makefile index 8df616f2..4c007dcc 100644 --- a/src/makefile +++ b/src/makefile @@ -114,18 +114,21 @@ download-network: echo "Downloaded network $(EVALFILE) and verified"; \ else \ echo "Downloaded network $(EVALFILE) failed validation"; \ + exit 1; \ fi; \ elif hash sha256sum 2>/dev/null; then \ if [ "$(EVALFILE)" = "berserk-"`sha256sum $(EVALFILE) | cut -c1-12`".nn" ]; then \ echo "Downloaded network $(EVALFILE) and verified"; \ else \ echo "Downloaded network $(EVALFILE) failed validation"; \ + exit 1; \ fi; \ else \ echo "Downloaded network $(EVALFILE), but unable to verify"; \ fi; \ else \ - echo "Unable to downlaod network: $(EVALFILE)"; \ + echo "Unable to download network: $(EVALFILE)"; \ + exit 1; \ fi; \ elif test -f "$(EVALFILE)"; then \ echo "Using network: $(EVALFILE)"; \