@@ -324,6 +324,8 @@ void Thread::search() {
324324 MainThread* mainThread = (this == Threads.main () ? Threads.main () : nullptr );
325325
326326 std::memset (ss-4 , 0 , 7 * sizeof (Stack));
327+ for (int i = -4 ; i < 0 ; i++)
328+ (ss+i)->counterMoves = &this ->counterMoveHistory [NO_PIECE][0 ]; // use as sentinel.
327329
328330 bestValue = delta = alpha = -VALUE_INFINITE;
329331 beta = VALUE_INFINITE;
@@ -593,7 +595,7 @@ namespace {
593595 assert (0 <= ss->ply && ss->ply < MAX_PLY);
594596
595597 ss->currentMove = (ss+1 )->excludedMove = bestMove = MOVE_NONE;
596- ss->counterMoves = nullptr ;
598+ ss->counterMoves = &thisThread-> counterMoveHistory [NO_PIECE][ 0 ] ;
597599 (ss+2 )->killers [0 ] = (ss+2 )->killers [1 ] = MOVE_NONE;
598600 Square prevSq = to_sq ((ss-1 )->currentMove );
599601
@@ -729,14 +731,15 @@ namespace {
729731 && (ss->staticEval >= beta - 35 * (depth / ONE_PLY - 6 ) || depth >= 13 * ONE_PLY)
730732 && pos.non_pawn_material (pos.side_to_move ()))
731733 {
732- ss->currentMove = MOVE_NULL;
733- ss->counterMoves = nullptr ;
734734
735735 assert (eval - beta >= 0 );
736736
737737 // Null move dynamic reduction based on depth and value
738738 Depth R = ((823 + 67 * depth / ONE_PLY) / 256 + std::min ((eval - beta) / PawnValueMg, 3 )) * ONE_PLY;
739739
740+ ss->currentMove = MOVE_NULL;
741+ ss->counterMoves = &thisThread->counterMoveHistory [NO_PIECE][0 ];
742+
740743 pos.do_null_move (st);
741744 Value nullValue = depth-R < ONE_PLY ? -qsearch<NonPV, false >(pos, ss+1 , -beta, -beta+1 )
742745 : - search<NonPV>(pos, ss+1 , -beta, -beta+1 , depth-R, !cutNode, true );
@@ -771,8 +774,7 @@ namespace {
771774 Depth rdepth = depth - 4 * ONE_PLY;
772775
773776 assert (rdepth >= ONE_PLY);
774- assert ((ss-1 )->currentMove != MOVE_NONE);
775- assert ((ss-1 )->currentMove != MOVE_NULL);
777+ assert (is_ok ((ss-1 )->currentMove ));
776778
777779 MovePicker mp (pos, ttMove, rbeta - ss->staticEval );
778780
@@ -781,6 +783,7 @@ namespace {
781783 {
782784 ss->currentMove = move;
783785 ss->counterMoves = &thisThread->counterMoveHistory [pos.moved_piece (move)][to_sq (move)];
786+
784787 pos.do_move (move, st);
785788 value = -search<NonPV>(pos, ss+1 , -rbeta, -rbeta+1 , rdepth, !cutNode, false );
786789 pos.undo_move (move);
@@ -806,6 +809,9 @@ namespace {
806809 const CounterMoveStats* cmh = (ss-1 )->counterMoves ;
807810 const CounterMoveStats* fmh = (ss-2 )->counterMoves ;
808811 const CounterMoveStats* fmh2 = (ss-4 )->counterMoves ;
812+ const bool cm_ok = is_ok ((ss-1 )->currentMove );
813+ const bool fm_ok = is_ok ((ss-2 )->currentMove );
814+ const bool fm2_ok = is_ok ((ss-4 )->currentMove );
809815
810816 MovePicker mp (pos, ttMove, depth, ss);
811817 value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
@@ -905,9 +911,9 @@ namespace {
905911
906912 // Countermoves based pruning
907913 if ( lmrDepth < 3
908- && (!cmh || ( *cmh )[moved_piece][to_sq (move)] < VALUE_ZERO)
909- && (!fmh || ( *fmh )[moved_piece][to_sq (move)] < VALUE_ZERO)
910- && (!fmh2 || ( *fmh2)[moved_piece][to_sq (move)] < VALUE_ZERO || (cmh && fmh )))
914+ && ((( *cmh )[moved_piece][to_sq (move)] < VALUE_ZERO) || !cm_ok )
915+ && ((( *fmh )[moved_piece][to_sq (move)] < VALUE_ZERO) || !fm_ok )
916+ && ((( *fmh2)[moved_piece][to_sq (move)] < VALUE_ZERO) || !fm2_ok || (cm_ok && fm_ok )))
911917 continue ;
912918
913919 // Futility pruning: parent node
@@ -967,9 +973,9 @@ namespace {
967973 && !pos.see_ge (make_move (to_sq (move), from_sq (move)), VALUE_ZERO))
968974 r -= 2 * ONE_PLY;
969975
970- ss->history = (cmh ? ( *cmh )[moved_piece][to_sq (move)] : VALUE_ZERO)
971- + (fmh ? ( *fmh )[moved_piece][to_sq (move)] : VALUE_ZERO)
972- + (fmh2 ? ( *fmh2)[moved_piece][to_sq (move)] : VALUE_ZERO)
976+ ss->history = (*cmh )[moved_piece][to_sq (move)]
977+ + (*fmh )[moved_piece][to_sq (move)]
978+ + (*fmh2)[moved_piece][to_sq (move)]
973979 + thisThread->history .get (~pos.side_to_move (), move)
974980 - 4000 ; // Correction factor
975981
@@ -1112,7 +1118,7 @@ namespace {
11121118 // Bonus for prior countermove that caused the fail low
11131119 else if ( depth >= 3 * ONE_PLY
11141120 && !pos.captured_piece ()
1115- && is_ok ((ss- 1 )-> currentMove ) )
1121+ && cm_ok )
11161122 update_cm_stats (ss-1 , pos.piece_on (prevSq), prevSq, stat_bonus (depth));
11171123
11181124 tte->save (posKey, value_to_tt (bestValue, ss->ply ),
@@ -1372,18 +1378,9 @@ namespace {
13721378
13731379 void update_cm_stats (Stack* ss, Piece pc, Square s, Value bonus) {
13741380
1375- CounterMoveStats* cmh = (ss-1 )->counterMoves ;
1376- CounterMoveStats* fmh1 = (ss-2 )->counterMoves ;
1377- CounterMoveStats* fmh2 = (ss-4 )->counterMoves ;
1378-
1379- if (cmh)
1380- cmh->update (pc, s, bonus);
1381-
1382- if (fmh1)
1383- fmh1->update (pc, s, bonus);
1384-
1385- if (fmh2)
1386- fmh2->update (pc, s, bonus);
1381+ for (int i : {1 , 2 , 4 })
1382+ if (is_ok ((ss-i)->currentMove ))
1383+ (ss-i)->counterMoves ->update (pc, s, bonus);
13871384 }
13881385
13891386
@@ -1403,7 +1400,7 @@ namespace {
14031400 thisThread->history .update (c, move, bonus);
14041401 update_cm_stats (ss, pos.moved_piece (move), to_sq (move), bonus);
14051402
1406- if (( ss-1 )->counterMoves )
1403+ if (is_ok (( ss-1 )->currentMove ) )
14071404 {
14081405 Square prevSq = to_sq ((ss-1 )->currentMove );
14091406 thisThread->counterMoves .update (pos.piece_on (prevSq), prevSq, move);
0 commit comments