Skip to content

Commit 3998d8a

Browse files
committed
fix LMR/PVS bug
1 parent 2d7b591 commit 3998d8a

1 file changed

Lines changed: 68 additions & 29 deletions

File tree

search.cpp

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)