@@ -63,15 +63,15 @@ namespace {
63
63
64
64
// Futility margin
65
65
Value futility_margin (Depth d, bool improving) {
66
- return Value (158 * (d - improving));
66
+ return Value (154 * (d - improving));
67
67
}
68
68
69
69
// Reductions lookup table, initialized at startup
70
70
int Reductions[MAX_MOVES]; // [depth or moveNumber]
71
71
72
72
Depth reduction (bool i, Depth d, int mn, Value delta, Value rootDelta) {
73
73
int r = Reductions[d] * Reductions[mn];
74
- return (r + 1460 - int (delta) * 1024 / int (rootDelta)) / 1024 + (!i && r > 937 );
74
+ return (r + 1449 - int (delta) * 1032 / int (rootDelta)) / 1024 + (!i && r > 941 );
75
75
}
76
76
77
77
constexpr int futility_move_count (bool improving, Depth depth) {
@@ -81,7 +81,7 @@ namespace {
81
81
82
82
// History and stats update bonus, based on depth
83
83
int stat_bonus (Depth d) {
84
- return std::min (350 * d - 400 , 1650 );
84
+ return std::min (340 * d - 470 , 1855 );
85
85
}
86
86
87
87
// Add a small random component to draw evaluations to avoid 3-fold blindness
@@ -161,7 +161,7 @@ namespace {
161
161
void Search::init () {
162
162
163
163
for (int i = 1 ; i < MAX_MOVES; ++i)
164
- Reductions[i] = int ((20.26 + std::log (Threads.size ()) / 2 ) * std::log (i));
164
+ Reductions[i] = int ((19.47 + std::log (Threads.size ()) / 2 ) * std::log (i));
165
165
}
166
166
167
167
@@ -354,12 +354,12 @@ void Thread::search() {
354
354
if (rootDepth >= 4 )
355
355
{
356
356
Value prev = rootMoves[pvIdx].averageScore ;
357
- delta = Value (10 ) + int (prev) * prev / 15400 ;
357
+ delta = Value (10 ) + int (prev) * prev / 16502 ;
358
358
alpha = std::max (prev - delta,-VALUE_INFINITE);
359
359
beta = std::min (prev + delta, VALUE_INFINITE);
360
360
361
361
// Adjust optimism based on root move's previousScore
362
- int opt = 116 * prev / (std::abs (prev) + 170 );
362
+ int opt = 120 * prev / (std::abs (prev) + 161 );
363
363
optimism[ us] = Value (opt);
364
364
optimism[~us] = -optimism[us];
365
365
}
@@ -462,16 +462,16 @@ void Thread::search() {
462
462
&& !Threads.stop
463
463
&& !mainThread->stopOnPonderhit )
464
464
{
465
- double fallingEval = (71 + 12 * (mainThread->bestPreviousAverageScore - bestValue)
466
- + 6 * (mainThread->iterValue [iterIdx] - bestValue)) / 656.7 ;
465
+ double fallingEval = (69 + 13 * (mainThread->bestPreviousAverageScore - bestValue)
466
+ + 6 * (mainThread->iterValue [iterIdx] - bestValue)) / 619.6 ;
467
467
fallingEval = std::clamp (fallingEval, 0.5 , 1.5 );
468
468
469
469
// If the bestMove is stable over several iterations, reduce time accordingly
470
- timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.37 : 0.65 ;
471
- double reduction = (1.4 + mainThread->previousTimeReduction ) / (2.15 * timeReduction);
472
- double bestMoveInstability = 1 + 1.7 * totBestMoveChanges / Threads.size ();
470
+ timeReduction = lastBestMoveDepth + 8 < completedDepth ? 1.57 : 0.65 ;
471
+ double reduction = (1.4 + mainThread->previousTimeReduction ) / (2.08 * timeReduction);
472
+ double bestMoveInstability = 1 + 1.8 * totBestMoveChanges / Threads.size ();
473
473
int complexity = mainThread->complexityAverage .value ();
474
- double complexPosition = std::min (1.0 + (complexity - 261 ) / 1738.7 , 1.5 );
474
+ double complexPosition = std::min (1.03 + (complexity - 241 ) / 1552.0 , 1.45 );
475
475
476
476
double totalTime = Time.optimum () * fallingEval * reduction * bestMoveInstability * complexPosition;
477
477
@@ -491,7 +491,7 @@ void Thread::search() {
491
491
Threads.stop = true ;
492
492
}
493
493
else if ( !mainThread->ponder
494
- && Time.elapsed () > totalTime * 0.53 )
494
+ && Time.elapsed () > totalTime * 0.50 )
495
495
Threads.increaseDepth = false ;
496
496
else
497
497
Threads.increaseDepth = true ;
@@ -760,7 +760,7 @@ namespace {
760
760
// Use static evaluation difference to improve quiet move ordering (~4 Elo)
761
761
if (is_ok ((ss-1 )->currentMove ) && !(ss-1 )->inCheck && !priorCapture)
762
762
{
763
- int bonus = std::clamp (-19 * int ((ss-1 )->staticEval + ss->staticEval ), -1940 , 1940 );
763
+ int bonus = std::clamp (-19 * int ((ss-1 )->staticEval + ss->staticEval ), -1920 , 1920 );
764
764
thisThread->mainHistory [~us][from_to ((ss-1 )->currentMove )] << bonus;
765
765
}
766
766
@@ -770,13 +770,13 @@ namespace {
770
770
// margin and the improving flag are used in various pruning heuristics.
771
771
improvement = (ss-2 )->staticEval != VALUE_NONE ? ss->staticEval - (ss-2 )->staticEval
772
772
: (ss-4 )->staticEval != VALUE_NONE ? ss->staticEval - (ss-4 )->staticEval
773
- : 172 ;
773
+ : 156 ;
774
774
improving = improvement > 0 ;
775
775
776
776
// Step 7. Razoring (~1 Elo).
777
777
// If eval is really low check with qsearch if it can exceed alpha, if it can't,
778
778
// return a fail low.
779
- if (eval < alpha - 394 - 255 * depth * depth)
779
+ if (eval < alpha - 426 - 252 * depth * depth)
780
780
{
781
781
value = qsearch<NonPV>(pos, ss, alpha - 1 , alpha);
782
782
if (value < alpha)
@@ -786,27 +786,27 @@ namespace {
786
786
// Step 8. Futility pruning: child node (~40 Elo).
787
787
// The depth condition is important for mate finding.
788
788
if ( !ss->ttPv
789
- && depth < 8
790
- && eval - futility_margin (depth, improving) - (ss-1 )->statScore / 304 >= beta
789
+ && depth < 9
790
+ && eval - futility_margin (depth, improving) - (ss-1 )->statScore / 280 >= beta
791
791
&& eval >= beta
792
- && eval < 28580 ) // larger than VALUE_KNOWN_WIN, but smaller than TB wins
792
+ && eval < 25128 ) // larger than VALUE_KNOWN_WIN, but smaller than TB wins
793
793
return eval;
794
794
795
795
// Step 9. Null move search with verification search (~35 Elo)
796
796
if ( !PvNode
797
797
&& (ss-1 )->currentMove != MOVE_NULL
798
- && (ss-1 )->statScore < 18200
798
+ && (ss-1 )->statScore < 18755
799
799
&& eval >= beta
800
800
&& eval >= ss->staticEval
801
- && ss->staticEval >= beta - 20 * depth - improvement / 14 + 235 + complexity / 24
801
+ && ss->staticEval >= beta - 19 * depth - improvement / 13 + 253 + complexity / 25
802
802
&& !excludedMove
803
803
&& pos.non_pawn_material (us)
804
804
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor ))
805
805
{
806
806
assert (eval - beta >= 0 );
807
807
808
808
// Null move dynamic reduction based on depth, eval and complexity of position
809
- Depth R = std::min (int (eval - beta) / 165 , 6 ) + depth / 3 + 4 - (complexity > 800 );
809
+ Depth R = std::min (int (eval - beta) / 168 , 6 ) + depth / 3 + 4 - (complexity > 825 );
810
810
811
811
ss->currentMove = MOVE_NULL;
812
812
ss->continuationHistory = &thisThread->continuationHistory [0 ][0 ][NO_PIECE][0 ];
@@ -842,7 +842,7 @@ namespace {
842
842
}
843
843
}
844
844
845
- probCutBeta = beta + 180 - 54 * improving;
845
+ probCutBeta = beta + 186 - 54 * improving;
846
846
847
847
// Step 10. ProbCut (~10 Elo)
848
848
// If we have a good enough capture and a reduced search returns a value
@@ -904,14 +904,14 @@ namespace {
904
904
return qsearch<PV>(pos, ss, alpha, beta);
905
905
906
906
if ( cutNode
907
- && depth >= 9
907
+ && depth >= 7
908
908
&& !ttMove)
909
909
depth -= 2 ;
910
910
911
911
moves_loop: // When in check, search starts here
912
912
913
913
// Step 12. A small Probcut idea, when we are in check (~4 Elo)
914
- probCutBeta = beta + 402 ;
914
+ probCutBeta = beta + 391 ;
915
915
if ( ss->inCheck
916
916
&& !PvNode
917
917
&& depth >= 2
@@ -1006,14 +1006,14 @@ namespace {
1006
1006
// Futility pruning for captures (~2 Elo)
1007
1007
if ( !givesCheck
1008
1008
&& !PvNode
1009
- && lmrDepth < 7
1009
+ && lmrDepth < 6
1010
1010
&& !ss->inCheck
1011
- && ss->staticEval + 185 + 203 * lmrDepth + PieceValue[EG][pos.piece_on (to_sq (move))]
1012
- + captureHistory[movedPiece][to_sq (move)][type_of (pos.piece_on (to_sq (move)))] / 6 < alpha)
1011
+ && ss->staticEval + 182 + 230 * lmrDepth + PieceValue[EG][pos.piece_on (to_sq (move))]
1012
+ + captureHistory[movedPiece][to_sq (move)][type_of (pos.piece_on (to_sq (move)))] / 7 < alpha)
1013
1013
continue ;
1014
1014
1015
1015
// SEE based pruning (~11 Elo)
1016
- if (!pos.see_ge (move, Value (-220 ) * depth))
1016
+ if (!pos.see_ge (move, Value (-206 ) * depth))
1017
1017
continue ;
1018
1018
}
1019
1019
else
@@ -1024,24 +1024,24 @@ namespace {
1024
1024
1025
1025
// Continuation history based pruning (~2 Elo)
1026
1026
if ( lmrDepth < 5
1027
- && history < -4180 * (depth - 1 ))
1027
+ && history < -4405 * (depth - 1 ))
1028
1028
continue ;
1029
1029
1030
1030
history += 2 * thisThread->mainHistory [us][from_to (move)];
1031
1031
1032
- lmrDepth += history / 7208 ;
1032
+ lmrDepth += history / 7278 ;
1033
1033
lmrDepth = std::max (lmrDepth, -2 );
1034
1034
1035
1035
// Futility pruning: parent node (~13 Elo)
1036
1036
if ( !ss->inCheck
1037
1037
&& lmrDepth < 13
1038
- && ss->staticEval + 103 + 136 * lmrDepth <= alpha)
1038
+ && ss->staticEval + 103 + 138 * lmrDepth <= alpha)
1039
1039
continue ;
1040
1040
1041
1041
lmrDepth = std::max (lmrDepth, 0 );
1042
1042
1043
1043
// Prune moves with negative SEE (~4 Elo)
1044
- if (!pos.see_ge (move, Value (-25 * lmrDepth * lmrDepth - 16 * lmrDepth)))
1044
+ if (!pos.see_ge (move, Value (-24 * lmrDepth * lmrDepth - 15 * lmrDepth)))
1045
1045
continue ;
1046
1046
}
1047
1047
}
@@ -1056,15 +1056,15 @@ namespace {
1056
1056
// a reduced search on all the other moves but the ttMove and if the
1057
1057
// result is lower than ttValue minus a margin, then we will extend the ttMove.
1058
1058
if ( !rootNode
1059
- && depth >= 4 - (thisThread->completedDepth > 22 ) + 2 * (PvNode && tte->is_pv ())
1059
+ && depth >= 4 - (thisThread->completedDepth > 21 ) + 2 * (PvNode && tte->is_pv ())
1060
1060
&& move == ttMove
1061
1061
&& !excludedMove // Avoid recursive singular search
1062
1062
/* && ttValue != VALUE_NONE Already implicit in the next condition */
1063
1063
&& abs (ttValue) < VALUE_KNOWN_WIN
1064
1064
&& (tte->bound () & BOUND_LOWER)
1065
1065
&& tte->depth () >= depth - 3 )
1066
1066
{
1067
- Value singularBeta = ttValue - (3 + (ss->ttPv && !PvNode)) * depth;
1067
+ Value singularBeta = ttValue - (2 + (ss->ttPv && !PvNode)) * depth;
1068
1068
Depth singularDepth = (depth - 1 ) / 2 ;
1069
1069
1070
1070
ss->excludedMove = move;
@@ -1083,7 +1083,7 @@ namespace {
1083
1083
&& ss->doubleExtensions <= 10 )
1084
1084
{
1085
1085
extension = 2 ;
1086
- depth += depth < 12 ;
1086
+ depth += depth < 13 ;
1087
1087
}
1088
1088
}
1089
1089
@@ -1106,15 +1106,15 @@ namespace {
1106
1106
1107
1107
// Check extensions (~1 Elo)
1108
1108
else if ( givesCheck
1109
- && depth > 9
1110
- && abs (ss->staticEval ) > 78 )
1109
+ && depth > 10
1110
+ && abs (ss->staticEval ) > 88 )
1111
1111
extension = 1 ;
1112
1112
1113
1113
// Quiet ttMove extensions (~1 Elo)
1114
1114
else if ( PvNode
1115
1115
&& move == ttMove
1116
1116
&& move == ss->killers [0 ]
1117
- && (*contHist[0 ])[movedPiece][to_sq (move)] >= 5600 )
1117
+ && (*contHist[0 ])[movedPiece][to_sq (move)] >= 5705 )
1118
1118
extension = 1 ;
1119
1119
}
1120
1120
@@ -1155,7 +1155,7 @@ namespace {
1155
1155
1156
1156
// Decrease reduction for PvNodes based on depth
1157
1157
if (PvNode)
1158
- r -= 1 + 11 / (3 + depth);
1158
+ r -= 1 + 12 / (3 + depth);
1159
1159
1160
1160
// Decrease reduction if ttMove has been singularly extended (~1 Elo)
1161
1161
if (singularQuietLMR)
@@ -1172,17 +1172,17 @@ namespace {
1172
1172
1173
1173
// Decrease reduction if move is a killer and we have a good history
1174
1174
if (move == ss->killers [0 ]
1175
- && (*contHist[0 ])[movedPiece][to_sq (move)] >= 3600 )
1175
+ && (*contHist[0 ])[movedPiece][to_sq (move)] >= 3722 )
1176
1176
r--;
1177
1177
1178
1178
ss->statScore = 2 * thisThread->mainHistory [us][from_to (move)]
1179
1179
+ (*contHist[0 ])[movedPiece][to_sq (move)]
1180
1180
+ (*contHist[1 ])[movedPiece][to_sq (move)]
1181
1181
+ (*contHist[3 ])[movedPiece][to_sq (move)]
1182
- - 4467 ;
1182
+ - 4182 ;
1183
1183
1184
1184
// Decrease/increase reduction for moves with a good/bad history (~30 Elo)
1185
- r -= ss->statScore / (12800 + 4410 * (depth > 7 && depth < 19 ));
1185
+ r -= ss->statScore / (11791 + 3992 * (depth > 6 && depth < 19 ));
1186
1186
1187
1187
// Step 17. Late moves reduction / extension (LMR, ~117 Elo)
1188
1188
// We use various heuristics for the sons of a node after the first son has
@@ -1206,8 +1206,8 @@ namespace {
1206
1206
{
1207
1207
// Adjust full depth search based on LMR results - if result
1208
1208
// was good enough search deeper, if it was bad enough search shallower
1209
- const bool doDeeperSearch = value > (alpha + 66 + 11 * (newDepth - d));
1210
- const bool doEvenDeeperSearch = value > alpha + 582 && ss->doubleExtensions <= 5 ;
1209
+ const bool doDeeperSearch = value > (alpha + 58 + 12 * (newDepth - d));
1210
+ const bool doEvenDeeperSearch = value > alpha + 588 && ss->doubleExtensions <= 5 ;
1211
1211
const bool doShallowerSearch = value < bestValue + newDepth;
1212
1212
1213
1213
ss->doubleExtensions = ss->doubleExtensions + doEvenDeeperSearch;
@@ -1318,8 +1318,8 @@ namespace {
1318
1318
// Reduce other moves if we have found at least one score improvement
1319
1319
if ( depth > 1
1320
1320
&& depth < 6
1321
- && beta < VALUE_KNOWN_WIN
1322
- && alpha > -VALUE_KNOWN_WIN )
1321
+ && beta < 10534
1322
+ && alpha > -10534 )
1323
1323
depth -= 1 ;
1324
1324
1325
1325
assert (depth > 0 );
@@ -1374,7 +1374,7 @@ namespace {
1374
1374
else if (!priorCapture)
1375
1375
{
1376
1376
// Extra bonuses for PV/Cut nodes or bad fail lows
1377
- int bonus = (depth > 4 ) + (PvNode || cutNode) + (bestValue < alpha - 88 * depth);
1377
+ int bonus = (depth > 5 ) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth);
1378
1378
update_continuation_histories (ss-1 , pos.piece_on (prevSq), prevSq, stat_bonus (depth) * bonus);
1379
1379
}
1380
1380
@@ -1502,7 +1502,7 @@ namespace {
1502
1502
if (PvNode && bestValue > alpha)
1503
1503
alpha = bestValue;
1504
1504
1505
- futilityBase = bestValue + 158 ;
1505
+ futilityBase = bestValue + 168 ;
1506
1506
}
1507
1507
1508
1508
const PieceToHistory* contHist[] = { (ss-1 )->continuationHistory , (ss-2 )->continuationHistory ,
@@ -1575,7 +1575,7 @@ namespace {
1575
1575
continue ;
1576
1576
1577
1577
// Do not search moves with bad enough SEE values (~5 Elo)
1578
- if (!pos.see_ge (move, Value (-108 )))
1578
+ if (!pos.see_ge (move, Value (-110 )))
1579
1579
continue ;
1580
1580
1581
1581
}
@@ -1708,7 +1708,7 @@ namespace {
1708
1708
1709
1709
if (!pos.capture (bestMove))
1710
1710
{
1711
- int bonus2 = bestValue > beta + 146 ? bonus1 // larger bonus
1711
+ int bonus2 = bestValue > beta + 153 ? bonus1 // larger bonus
1712
1712
: stat_bonus (depth); // smaller bonus
1713
1713
1714
1714
// Increase stats for the best move in case it was a quiet move
0 commit comments