@@ -103,6 +103,11 @@ Value qsearch(Position& pos, int depth, int ply, Value alpha, Value beta) {
103103 break ;
104104 }
105105
106+ // Delta Pruning
107+ if (!pos.inCheck () && standPat + Value (1000 ) < alpha) {
108+ continue ;
109+ }
110+
106111 pos.makeMove (m);
107112 Value score = -qsearch (pos, depth - 1 , ply + 1 , -beta, -alpha);
108113 pos.unmakeMove (m);
@@ -166,6 +171,9 @@ Value negamax(Position& pos, int depth, int ply, Value alpha, Value beta, bool c
166171
167172 searchHistory.killerTable [ply + 1 ].clear ();
168173 searchStats.nodes ++;
174+ if (ply == 0 ) {
175+ searchHistory.qHistoryTable .clear ();
176+ }
169177
170178 // Transposition table lookup
171179 // See if this node has been visited before. If so, we can reuse the data
@@ -271,9 +279,10 @@ Value negamax(Position& pos, int depth, int ply, Value alpha, Value beta, bool c
271279 currSS->bestMove = m;
272280 if (score >= beta) {
273281 ttFlag = EntryType::LOWER_BOUND;
274- // Record quiet killer moves
282+ // Update quiet history
275283 if (!pos.isCapture (bestMove)) {
276284 searchHistory.killerTable [ply].add (bestMove);
285+ searchHistory.qHistoryTable .update (pos.sideToMove (), bestMove, depth * depth);
277286 }
278287 break ;
279288 }
@@ -303,15 +312,36 @@ void searchWorker(SearchParams params, Position pos) {
303312 Move rootBestMove;
304313 Value rootBestScore = MATED_VALUE;
305314
315+ Value windowUpper = 20 ;
316+ Value windowLower = 20 ;
317+
306318 for (int depth = 1 ; depth <= maxDepth; ++depth) {
307319 if (g_stopRequested.load ())
308320 break ;
309321 if (g_timeControl.hitSoftLimit (depth, (int ) searchStats.nodes , 0 ))
310322 break ;
311323
312- Value score = negamax<true >(pos, depth, 0 , MATED_VALUE, MATE_VALUE, false );
313- if (g_stopRequested.load ())
314- break ;
324+ // Aspiration window
325+ Value score;
326+ if (depth <= 3 ) {
327+ score = negamax<true >(pos, depth, 0 , MATED_VALUE, MATE_VALUE, false );
328+ } else {
329+ Value alpha = rootBestScore - windowLower;
330+ Value beta = rootBestScore + windowUpper;
331+ score = negamax<true >(pos, depth, 0 , alpha, beta, false );
332+ // Adjust window on fail-highs or fail-lows
333+ if (score >= beta) {
334+ windowUpper = std::min (MATE_VALUE, windowUpper * 2 );
335+ continue ;
336+ } else if (score <= alpha) {
337+ windowLower = std::min (MATE_VALUE, windowLower * 2 );
338+ continue ;
339+ } else {
340+ // Score within window, accept the score
341+ windowUpper = 25 ;
342+ windowLower = 25 ;
343+ }
344+ }
315345
316346 auto pv = extractPv (pos, depth);
317347 if (!pv.empty ())
@@ -326,6 +356,8 @@ void searchWorker(SearchParams params, Position pos) {
326356
327357 if (g_timeControl.hitSoftLimit (depth, (int ) searchStats.nodes , 0 ))
328358 break ;
359+ if (g_stopRequested.load ())
360+ break ;
329361 }
330362
331363 if (rootBestMove.move () != 0 )
0 commit comments