The main difference between razoring and delta pruning being that razoring occurs in the primary search routine when remaining search depth is low and delta pruning occurs in quiescence search. I'm leaving out other details of course, but hopefully that sums it up more or less accurately.
As I've tinkered with chess engine development of the years I have never seen much in the way of good results from these two techniques no matter how much I've tweaked deltas or pre-requisites. So either I'm doing something wrong or there are certain caveats involved in using these techniques that I'm unaware of.
I was wondering if anyone familiar with these techniques that has actually measured real success in using them would care to scrutinize the following code to help me figure out where I'm going awry.
This is the delta pruning code inside the move loop of quiescence search:
Note: 'depth' in this routine will be <= 0 and the 'child' variable is the destination position of the move being executed.
Code: Select all
Exec<color>(*move, *child);
if (!(checks | child->checks | (move->Promo() == (color|Queen)) | (abs(alpha) >= WinningScore)) &
((standPat + ValueOf(move->Cap()) + _qsearchDelta[-depth]) < alpha))
{
_stats.deltaCount++;
Undo<color>(*move);
continue;
}
move->Score() = -child->QSearch<!color>(-beta, -alpha, (depth - 1));
Undo<color>(*move);
Note: 'parent' is the position prior to this one.
Code: Select all
// forward pruning prerequisites
if (pvNode || !(pruneOK & !checks & (depthChange <= 0))) {
goto search_main; // yeah that's a goto, horrible I know
}
// razoring (fail low pruning)
if ((depth < 4) & (abs(alpha) < WinningScore) &
!parent->checks & ((eval + _razorDelta[depth]) <= alpha))
{
_stats.rzrCount++;
if ((depth <= 1) && ((eval + _razorDelta[3 * depth]) <= alpha)) {
_stats.rzrEarlyOut++;
return QSearch<color>(alpha, beta, 0);
}
const int ralpha = (alpha - _razorDelta[depth]);
const int val = QSearch<color>(ralpha, (ralpha + 1), 0);
if (_stop) {
return beta;
}
if (val <= ralpha) {
_stats.rzrCutoffs++;
return val;
}
}
Code: Select all
_qsearchDelta[] = { 1550, 500, 305, 237, 206, 188, 178, 171, 167, 164, 161, 159, 158, 157, 156, 155, 154, 154, 153, 153, ...}
_razorDelta[] = { NOT_USED, 544, 640, 800, 1024 }
I'm running a larger round-robin now. This one will take days to complete, but so far the engines with these techniques enabled are solidly in last place - even below the instance of my engine with "NO" forward pruning of any kind.