I'm currently writing a chess engine. The search itself seems to work, but can't figure out how to display a PV line accurately. Typically the first few moves of it look good, and then I get some illegal moves, probably those envisaged in other variations, that have not been cleaned up.
Here's the part in the search where I modify the PV, which is stored in an array like this:
Code: Select all
struct SearchInfo {
move_t best, current, pv;
};
SearchInfo si[MAX_PLY];
Code: Select all
int search(Board &B, SearchInfo* si, bool is_pv, int alpha, int beta, int depth, int ply)
{
(...)
int cnt = 0;
while (alpha < beta && M.next_move(si->current)) {
++cnt;
// extend: check, single reply, recaptures at PV nodes
int new_depth = M.get_count() == 1 || B.in_check()
|| (is_pv && si->current.is_recapture(B) && B.see(si->current) >= 0)
? depth : depth-1;
B.play(si->current);
if (is_pv && cnt == 1)
// full window search
score = new_depth > 0
? -search(B, si+1, true, -beta, -alpha, new_depth, ply+1)
: -qsearch(B, si+1, true, -beta, -alpha, new_depth, ply+1);
else {
// try zero window first (which is the full window for non PV nodes)
score = new_depth > 0
? -search(B, si+1, false, -(alpha+1), -alpha, new_depth, ply+1)
: -qsearch(B, si+1, false, -(alpha+1), -alpha, new_depth, ply+1);
// fail high: re-search full window (for PV nodes only)
if (score > alpha && is_pv)
score = new_depth > 0
? -search(B, si+1, true, -beta, -alpha, new_depth, ply+1)
: -qsearch(B, si+1, true, -beta, -alpha, new_depth, ply+1);
}
B.undo();
if (score > best_score) {
best_score = score;
si->best = si->current;
if (is_pv)
si->pv = si->best;
if (score > alpha)
alpha = score;
}
}
(...)
return best_score;
}