@@ -129,49 +129,88 @@ Value doSearch(Board board, int depth, Value alpha, Value beta,
129129 }
130130 for (size_t i = 0 ; i < moves.size (); ++i) {
131131 Move move = moves[i];
132- int reduction = (i >= 3 && depth >= 3 && !board.isCapture (move)) ? 1 : 0 ;
132+
133+ bool isCapture = board.isCapture (move);
134+ bool givesCheck = board.givesCheck (move)!=CheckType::NO_CHECK;
135+
136+ // --- LMR reduction ---
137+ int reduction = 0 ;
138+ if (i >= 3 && depth >= 3 && !isCapture && !givesCheck) {
139+ reduction = 1 + (int )(i / 6 ) + (depth / 8 );
140+
141+ // history heuristic: good moves get reduced less
142+ if (movepick::historyHeuristic[(int )move.from ()][(int )move.to ()] > 0 )
143+ reduction--;
144+
145+ reduction = std::max (0 , reduction);
146+ reduction = std::min (reduction, depth - 2 );
147+ }
148+
133149 board.doMove (move);
134- Value childScore = doSearch (board, depth - 1 - reduction, -alpha - 1 ,
135- -alpha, session, ply + 1 );
136- if (childScore == VALUE_NONE) {
137- board.undoMove ();
138- return VALUE_NONE;
150+
151+ Value score;
152+
153+ if (i == 0 ) {
154+ // --- First move: full window (PVS root move) ---
155+ score = -doSearch (board, depth - 1 , -beta, -alpha, session, ply + 1 );
156+
157+ if (score == VALUE_NONE){
158+ board.undoMove ();
159+ return VALUE_NONE;
160+ }
161+ } else {
162+ // --- Null-window search (PVS + LMR) ---
163+ score = doSearch (board,
164+ depth - 1 - reduction,
165+ -alpha - 1 , -alpha,
166+ session, ply + 1 );
167+ if (score == VALUE_NONE) {
168+ board.undoMove ();
169+ return VALUE_NONE;
170+ }
171+ score=-score;
172+ // --- Re-search if it improves alpha ---
173+ if (score > alpha) {
174+ score = doSearch (board,
175+ depth - 1 ,
176+ -beta, -alpha,
177+ session, ply + 1 );
178+ if (score == VALUE_NONE) {
179+ board.undoMove ();
180+ return VALUE_NONE;
181+ }
182+ score = -score;
183+ }
139184 }
140- Value score = -childScore;
141- if (reduction > 0 && score > alpha) {
142- childScore = doSearch (board, depth - 1 , -beta, -alpha, session, ply + 1 );
143- board.undoMove ();
144- if (childScore == VALUE_NONE)
145- return VALUE_NONE;
146- score = -childScore;
147- } else
148- board.undoMove ();
185+
186+ board.undoMove ();
149187
150188 if (score > maxScore) {
151- maxScore = score;
152- update_pv (session.pv [ply], move, session.pv [ply + 1 ]);
189+ maxScore = score;
190+ update_pv (session.pv [ply], move, session.pv [ply + 1 ]);
153191 }
154192
155193 if (score > alpha) {
156- alpha = score;
157- if (!board. isCapture (move))
158- movepick::historyHeuristic[( int )move. from ()][( int )move. to ()] +=
159- depth * depth;
194+ alpha = score;
195+
196+ if (!isCapture)
197+ movepick::historyHeuristic[( int )move. from ()][( int )move. to ()] += depth * depth;
160198 }
199+
161200 if (alpha >= beta) {
162- if (!board.isCapture (move)) {
163- if (movepick::killerMoves[ply][0 ] != move) {
164- movepick::killerMoves[ply][1 ] = movepick::killerMoves[ply][0 ];
165- movepick::killerMoves[ply][0 ] = move;
201+ // killer moves
202+ if (!isCapture) {
203+ if (movepick::killerMoves[ply][0 ] != move) {
204+ movepick::killerMoves[ply][1 ] = movepick::killerMoves[ply][0 ];
205+ movepick::killerMoves[ply][0 ] = move;
206+ }
166207 }
167- }
168-
169- break ;
208+ break ;
170209 }
171210
172211 if (session.tm .elapsed () >= session.tm .optimum () ||
173212 stopSearch.load (std::memory_order_relaxed))
174- return VALUE_NONE;
213+ return VALUE_NONE;
175214 }
176215
177216 if (maxScore != -VALUE_INFINITE) {
0 commit comments