A stylistically remark regarding the search stack variables ss->bestMove and ss->currentMove. You somehow mix up these variables semantically in search() and qsearch(). There is no bug, but at first look the usage of those variables seems unclear or even wrong.
The current move is actual the move you search deeper in the tree. The best move is the best move found at a ply.
The move you store in the TT is the best move. Therefore, when you have a TT hit, you should store the TT move back in ss->bestMove, not in ss->currentMove.
search(), TT hit (same in qsearch())
Code: Select all
if (!PvNode && tte && ok_to_use_TT(tte, depth, beta, ply))
{
// Refresh tte entry to avoid aging
TT.store(posKey, tte->value(), tte->type(), tte->depth(), ttMove, tte->static_value(), tte->king_danger());
ss->bestMove = ttMove; // Can be MOVE_NONE
return value_from_tt(tte->value(), ply);
}
search(), threat move storage from null move search fail low
Code: Select all
else
{
// The null move failed low, which means that we may be faced with
// some kind of threat. If the previous move was reduced, check if
// the move that refuted the null move was somehow connected to the
// move which was reduced. If a connection is found, return a fail
// low score (which will cause the reduced move to fail high in the
// parent node, which will trigger a re-search with full depth).
if (nullValue == value_mated_in(ply + 2))
mateThreat = true;
ss->threatMove = (ss+1)->bestMove;
if ( depth < ThreatDepth
&& (ss-1)->reduction
&& connected_moves(pos, (ss-1)->currentMove, ss->threatMove))
return beta - 1;
}
search(), IID, ttMove storage
Code: Select all
// Step 9. Internal iterative deepening
if ( depth >= IIDDepth[PvNode]
&& ttMove == MOVE_NONE
&& (PvNode || (!isCheck && ss->eval >= beta - IIDMargin)))
{
Depth d = (PvNode ? depth - 2 * OnePly : depth / 2);
ss->skipNullMove = true;
search<PvNode>(pos, ss, alpha, beta, d, ply);
ss->skipNullMove = false;
ttMove = ss->bestMove;
tte = TT.retrieve(posKey);
}