@@ -83,7 +83,7 @@ namespace {
8383 Value DrawValue[COLOR_NB];
8484 HistoryStats History;
8585 GainsStats Gains;
86- CountermovesStats Countermoves;
86+ MovesStats Countermoves, Followupmoves ;
8787
8888 template <NodeType NT>
8989 Value search (Position& pos, Stack* ss, Value alpha, Value beta, Depth depth, bool cutNode);
@@ -304,6 +304,7 @@ namespace {
304304 History.clear ();
305305 Gains.clear ();
306306 Countermoves.clear ();
307+ Followupmoves.clear ();
307308
308309 PVSize = Options[" MultiPV" ];
309310 Skill skill (Options[" Skill Level" ]);
@@ -499,7 +500,7 @@ namespace {
499500
500501 moveCount = quietCount = 0 ;
501502 bestValue = -VALUE_INFINITE;
502- ss->currentMove = (ss+1 )->excludedMove = bestMove = MOVE_NONE;
503+ ss->currentMove = ss-> ttMove = (ss+1 )->excludedMove = bestMove = MOVE_NONE;
503504 ss->ply = (ss-1 )->ply + 1 ;
504505 (ss+1 )->skipNullMove = false ; (ss+1 )->reduction = DEPTH_ZERO;
505506 (ss+2 )->killers [0 ] = (ss+2 )->killers [1 ] = MOVE_NONE;
@@ -532,7 +533,7 @@ namespace {
532533 excludedMove = ss->excludedMove ;
533534 posKey = excludedMove ? pos.exclusion_key () : pos.key ();
534535 tte = TT.probe (posKey);
535- ttMove = RootNode ? RootMoves[PVIdx].pv [0 ] : tte ? tte->move () : MOVE_NONE;
536+ ss-> ttMove = ttMove = RootNode ? RootMoves[PVIdx].pv [0 ] : tte ? tte->move () : MOVE_NONE;
536537 ttValue = tte ? value_from_tt (tte->value (), ss->ply ) : VALUE_NONE;
537538
538539 // At PV nodes we check for exact scores, whilst at non-PV nodes we check for
@@ -550,7 +551,7 @@ namespace {
550551 TT.refresh (tte);
551552 ss->currentMove = ttMove; // Can be MOVE_NONE
552553
553- // If ttMove is quiet, update killers, history, and counter move on TT hit
554+ // If ttMove is quiet, update killers, history, counter move and followup move on TT hit
554555 if (ttValue >= beta && ttMove && !pos.capture_or_promotion (ttMove) && !inCheck)
555556 update_stats (pos, ss, ttMove, depth, NULL , 0 );
556557
@@ -712,7 +713,11 @@ namespace {
712713 Move countermoves[] = { Countermoves[pos.piece_on (prevMoveSq)][prevMoveSq].first ,
713714 Countermoves[pos.piece_on (prevMoveSq)][prevMoveSq].second };
714715
715- MovePicker mp (pos, ttMove, depth, History, countermoves, ss);
716+ Square prevOwnMoveSq = to_sq ((ss-2 )->currentMove );
717+ Move followupmoves[] = { Followupmoves[pos.piece_on (prevOwnMoveSq)][prevOwnMoveSq].first ,
718+ Followupmoves[pos.piece_on (prevOwnMoveSq)][prevOwnMoveSq].second };
719+
720+ MovePicker mp (pos, ttMove, depth, History, countermoves, followupmoves, ss);
716721 CheckInfo ci (pos);
717722 value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
718723 improving = ss->staticEval >= (ss-2 )->staticEval
@@ -1029,7 +1034,7 @@ namespace {
10291034 PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
10301035 depth, bestMove, ss->staticEval );
10311036
1032- // Quiet best move: update killers, history and countermoves
1037+ // Quiet best move: update killers, history, countermoves and followupmoves
10331038 if (bestValue >= beta && !pos.capture_or_promotion (bestMove) && !inCheck)
10341039 update_stats (pos, ss, bestMove, depth, quietsSearched, quietCount - 1 );
10351040
@@ -1264,7 +1269,7 @@ namespace {
12641269 }
12651270
12661271
1267- // update_stats() updates killers, history and countermoves stats after a fail-high
1272+ // update_stats() updates killers, history, countermoves and followupmoves stats after a fail-high
12681273 // of a quiet move.
12691274
12701275 void update_stats (Position& pos, Stack* ss, Move move, Depth depth, Move* quiets, int quietsCnt) {
@@ -1290,6 +1295,12 @@ namespace {
12901295 Square prevMoveSq = to_sq ((ss-1 )->currentMove );
12911296 Countermoves.update (pos.piece_on (prevMoveSq), prevMoveSq, move);
12921297 }
1298+
1299+ if (is_ok ((ss-2 )->currentMove ) && (ss-1 )->currentMove == (ss-1 )->ttMove )
1300+ {
1301+ Square prevOwnMoveSq = to_sq ((ss-2 )->currentMove );
1302+ Followupmoves.update (pos.piece_on (prevOwnMoveSq), prevOwnMoveSq, move);
1303+ }
12931304 }
12941305
12951306
0 commit comments