Skip to content

Commit 0f3f5d8

Browse files
snicoletvondele
authored andcommitted
Introduce DistanceFromPV
We introduce a metric for each internal node in search, called DistanceFromPV. This distance indicated how far the current node is from the principal variation. We then use this distance to search the nodes which are close to the PV a little deeper (up to 4 plies deeper than the PV): this improves the quality of the search at these nodes and bring better updates for the PV during search. STC: LLR: 2.96 (-2.94,2.94) {-0.25,1.25} Total: 54936 W: 5047 L: 4850 D: 45039 Ptnml(0-2): 183, 3907, 19075, 4136, 167 https://tests.stockfishchess.org/tests/view/6037b88e7f517a561bc4a392 LTC: LLR: 2.95 (-2.94,2.94) {0.25,1.25} Total: 49608 W: 1880 L: 1703 D: 46025 Ptnml(0-2): 22, 1514, 21555, 1691, 22 https://tests.stockfishchess.org/tests/view/6038271b7f517a561bc4a3cb Closes #3369 Bench: 5037279
1 parent 7c30091 commit 0f3f5d8

File tree

2 files changed

+16
-8
lines changed

2 files changed

+16
-8
lines changed

src/search.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ namespace {
616616
moveCount = captureCount = quietCount = ss->moveCount = 0;
617617
bestValue = -VALUE_INFINITE;
618618
maxValue = VALUE_INFINITE;
619+
ss->distanceFromPv = (PvNode ? 0 : ss->distanceFromPv);
619620

620621
// Check for the available remaining time
621622
if (thisThread == Threads.main())
@@ -1175,8 +1176,12 @@ namespace {
11751176
// Step 15. Make the move
11761177
pos.do_move(move, st, givesCheck);
11771178

1178-
// Step 16. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
1179-
// re-searched at full depth.
1179+
(ss+1)->distanceFromPv = ss->distanceFromPv + moveCount - 1;
1180+
1181+
// Step 16. Late moves reduction / extension (LMR, ~200 Elo)
1182+
// We use various heuristics for the sons of a node after the first son has
1183+
// been searched. In general we would like to reduce them, but there are many
1184+
// cases where we extend a son if it has good chances to be "interesting".
11801185
if ( depth >= 3
11811186
&& moveCount > 1 + 2 * rootNode
11821187
&& ( !captureOrPromotion
@@ -1258,27 +1263,29 @@ namespace {
12581263
r++;
12591264

12601265
// Decrease/increase reduction for moves with a good/bad history (~30 Elo)
1261-
// If we are not in check use statScore, if we are in check
1262-
// use sum of main history and first continuation history with an offset
1266+
// If we are not in check use statScore, but if we are in check we use
1267+
// the sum of main history and first continuation history with an offset.
12631268
if (ss->inCheck)
12641269
r -= (thisThread->mainHistory[us][from_to(move)]
12651270
+ (*contHist[0])[movedPiece][to_sq(move)] - 3833) / 16384;
12661271
else
12671272
r -= ss->statScore / 14790;
12681273
}
12691274

1270-
Depth d = std::clamp(newDepth - r, 1, newDepth);
1275+
// In general we want to cap the LMR depth search at newDepth. But for nodes
1276+
// close to the principal variation the cap is at (newDepth + 1), which will
1277+
// allow these nodes to be searched deeper than the pv (up to 4 plies deeper).
1278+
Depth d = std::clamp(newDepth - r, 1, newDepth + ((ss+1)->distanceFromPv <= 4));
12711279

12721280
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, d, true);
12731281

1274-
doFullDepthSearch = value > alpha && d != newDepth;
1275-
1282+
// If the son is reduced and fails high it will be re-searched at full depth
1283+
doFullDepthSearch = value > alpha && d < newDepth;
12761284
didLMR = true;
12771285
}
12781286
else
12791287
{
12801288
doFullDepthSearch = !PvNode || moveCount > 1;
1281-
12821289
didLMR = false;
12831290
}
12841291

src/search.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct Stack {
4747
Value staticEval;
4848
int statScore;
4949
int moveCount;
50+
int distanceFromPv;
5051
bool inCheck;
5152
bool ttPv;
5253
bool ttHit;

0 commit comments

Comments
 (0)