Skip to content

Commit 5e03734

Browse files
committed
Fix an off-by-one bug in extract_pv_from_tt
At root we start counting plies from 1, instead pv[] array starts from 0. So the variable 'ply' we use in extract_pv_from_tt to index pv[] is misnamed, indeed it is not the real ply, but ply-1. The fix is to leave ply name in extract_pv_from_tt but assign it the correct start value and consequentely change all the references to pv[]. Instead in insert_pv_in_tt it's simpler to rename the misnamed 'ply' in 'idx'. The off-by-one bug was unhidden when trying to use 'ply' for what it should have been, for instance in this position: position fen 8/6R1/8/3k4/8/8/8/2K5 w - - 0 1 at depth 24 mate line is erroneusly truncated due to value_from_tt() using the wrong ply. Spotted by Ronald de Man. bench: 8732553
1 parent e46a72d commit 5e03734

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

src/search.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,18 +1399,18 @@ void RootMove::extract_pv_from_tt(Position& pos) {
13991399

14001400
StateInfo state[MAX_PLY_PLUS_6], *st = state;
14011401
const TTEntry* tte;
1402-
int ply = 0;
1403-
Move m = pv[0];
1402+
int ply = 1; // At root ply is 1...
1403+
Move m = pv[0]; // ...instead pv[] array starts from 0
14041404
Value expectedScore = score;
14051405

14061406
pv.clear();
14071407

14081408
do {
14091409
pv.push_back(m);
14101410

1411-
assert(MoveList<LEGAL>(pos).contains(pv[ply]));
1411+
assert(MoveList<LEGAL>(pos).contains(pv[ply - 1]));
14121412

1413-
pos.do_move(pv[ply++], *st++);
1413+
pos.do_move(pv[ply++ - 1], *st++);
14141414
tte = TT.probe(pos.key());
14151415
expectedScore = -expectedScore;
14161416

@@ -1419,11 +1419,11 @@ void RootMove::extract_pv_from_tt(Position& pos) {
14191419
&& pos.pseudo_legal(m = tte->move()) // Local copy, TT could change
14201420
&& pos.legal(m, pos.pinned_pieces(pos.side_to_move()))
14211421
&& ply < MAX_PLY
1422-
&& (!pos.is_draw() || ply < 2));
1422+
&& (!pos.is_draw() || ply <= 2));
14231423

14241424
pv.push_back(MOVE_NONE); // Must be zero-terminating
14251425

1426-
while (ply) pos.undo_move(pv[--ply]);
1426+
while (--ply) pos.undo_move(pv[ply - 1]);
14271427
}
14281428

14291429

@@ -1435,21 +1435,21 @@ void RootMove::insert_pv_in_tt(Position& pos) {
14351435

14361436
StateInfo state[MAX_PLY_PLUS_6], *st = state;
14371437
const TTEntry* tte;
1438-
int ply = 0;
1438+
int idx = 0; // Ply starts from 1, we need to start from 0
14391439

14401440
do {
14411441
tte = TT.probe(pos.key());
14421442

1443-
if (!tte || tte->move() != pv[ply]) // Don't overwrite correct entries
1444-
TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[ply], VALUE_NONE);
1443+
if (!tte || tte->move() != pv[idx]) // Don't overwrite correct entries
1444+
TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[idx], VALUE_NONE);
14451445

1446-
assert(MoveList<LEGAL>(pos).contains(pv[ply]));
1446+
assert(MoveList<LEGAL>(pos).contains(pv[idx]));
14471447

1448-
pos.do_move(pv[ply++], *st++);
1448+
pos.do_move(pv[idx++], *st++);
14491449

1450-
} while (pv[ply] != MOVE_NONE);
1450+
} while (pv[idx] != MOVE_NONE);
14511451

1452-
while (ply) pos.undo_move(pv[--ply]);
1452+
while (idx) pos.undo_move(pv[--idx]);
14531453
}
14541454

14551455

0 commit comments

Comments
 (0)