I can't make a very fast compile of it, it is only 32 bit but that should be enough for a fun engine. The changes are also small so maybe they could be merged in some way if they would turn out not to be bad, but I already said the thing is bad...
I only made it because I wanted to try out some new idea in nullmove and test if it could be built into the new Stockfish. But by itself I don't think the first idea, that was just more or less dreamt up for the occasion, will ever be worth incorporating into other programs. The idea was that if the nullmove follows a threat, the threat can be carried out without resistance because the opponent passed. Then you can not reduce the node, it is too tactical. But maybe if there would be only one threatmove and you then exclude that move from the possible 'free' moves, and when the other moves do not refute the nullmove, it would still be okay to reduce. The drawback is that you need an exclusion search in addition to the normal nullmove search, and you know there is at least one threat in the position. The first implemention I had was wrong, the exclusion search was never triggered and the search was identical to Stockfish 2.3, but much slower because the compile is not as fast as Jim's

As a final change I also copied most of the material imbalance table from Rainbow Serpent, but I think that is more or less pink noise


That's it. Only three changes to Stockfish from the other universe. This is the change in nullmove.
Stockfish's nullmove:
Code: Select all
// Step 8. Null move search with verification search (is omitted in PV nodes)
if ( !PvNode
&& !ss->skipNullMove
&& depth > ONE_PLY
&& !inCheck
&& refinedValue >= beta
&& abs(beta) < VALUE_MATE_IN_MAX_PLY
&& pos.non_pawn_material(pos.side_to_move()))
{
ss->currentMove = MOVE_NULL;
// Null move dynamic reduction based on depth
Depth R = 3 * ONE_PLY + depth / 4;
// Null move dynamic reduction based on value
if (refinedValue - PawnValueMg > beta)
R += ONE_PLY;
pos.do_null_move<true>(st);
(ss+1)->skipNullMove = true;
nullValue = depth-R < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
: - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R);
(ss+1)->skipNullMove = false;
pos.do_null_move<false>(st);
if (nullValue >= beta)
{
// Do not return unproven mate scores
if (nullValue >= VALUE_MATE_IN_MAX_PLY)
nullValue = beta;
if (depth < 6 * ONE_PLY)
return nullValue;
// Do verification search at high depths
ss->skipNullMove = true;
Value v = search<NonPV>(pos, ss, alpha, beta, depth-R);
ss->skipNullMove = false;
if (v >= beta)
return nullValue;
}
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).
threatMove = (ss+1)->currentMove;
if ( depth < ThreatDepth
&& (ss-1)->reduction
&& threatMove != MOVE_NONE
&& connected_moves(pos, (ss-1)->currentMove, threatMove))
return beta - 1;
}
}
Code: Select all
// Step 8. Null move search with verification search (is omitted in PV nodes)
if ( !PvNode
&& !ss->skipNullMove
&& depth > ONE_PLY
&& !inCheck
&& refinedValue >= beta
&& abs(beta) < VALUE_MATE_IN_MAX_PLY
&& pos.non_pawn_material(pos.side_to_move()))
{
ss->currentMove = MOVE_NULL;
// Null move dynamic reduction based on depth
Depth R = 3 * ONE_PLY + depth / 4;
// Null move dynamic reduction based on value
if (refinedValue - PawnValueMg > beta)
R += ONE_PLY;
pos.do_null_move<true>(st);
(ss+1)->skipNullMove = true;
nullValue = depth-R < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
: - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R);
if (nullValue < beta)
{// 'Nullexclusion Search'
threatMove = (ss)->currentMove;
CheckInfo ci(pos);
if ( threatMove != MOVE_NONE
&& pos.pl_move_is_legal(threatMove, ci.pinned)
&& depth-R >= SingularExtensionDepth[false]
&& !excludedMove // Recursive singular search is not allowed
&& connected_moves(pos, (ss-2)->currentMove, threatMove)
&& tte
&& ttMove != MOVE_NONE
&& can_return_tt(tte, depth-R-ONE_PLY, ttValue, beta))
{
nullExclusionsearch = true;
ss->excludedMove = threatMove;
nullValue = -search<NonPV>(pos, ss+1, -beta, -alpha, depth-R);
ss->excludedMove = MOVE_NONE;
}
} // Nullexclusion Search
(ss+1)->skipNullMove = false;
pos.do_null_move<false>(st);
if (nullValue >= beta)
{
// Do not return unproven mate scores
if (nullValue >= VALUE_MATE_IN_MAX_PLY)
nullValue = beta;
if ( depth < 6 * ONE_PLY
&& !nullExclusionsearch)
return nullValue;
// Do verification search at high depths
// [In case of a 'Nullexclusion search'
// we try to extend the hashresult]
CheckInfo ci(pos);
if ( (nullExclusionsearch || (tte && ttMove != MOVE_NONE && can_return_tt(tte, depth-R-ONE_PLY, ttValue, beta)))
&& pos.pl_move_is_legal(ttMove, ci.pinned))
{
pos.do_move(ttMove, st, ci, pos.move_gives_check(ttMove, ci));
verificationValue = - search<PV>(pos, ss+1, -(ttValue), -(ttValue - 1), depth-R);
if (verificationValue < ttValue)
verificationValue = - search<PV>(pos, ss+1, -beta, -alpha, depth-R);
pos.undo_move(ttMove);
if (verificationValue >= beta)
TT.store(posKey, value_to_tt(verificationValue, ss->ply), BOUND_LOWER, depth-R, ttMove, tte->static_value(), tte->static_value_margin());
}
if (verificationValue < beta)
{
ss->skipNullMove = true;
verificationValue = search<NonPV>(pos, ss, alpha, beta, depth-R);
ss->skipNullMove = false;
if (verificationValue >= beta)
TT.store(posKey, value_to_tt(verificationValue, ss->ply), BOUND_LOWER, depth-R, (ss)->currentMove, ss->eval, ss->evalMargin);
}
if (verificationValue >= beta)
return nullValue;
}
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 ( depth < ThreatDepth
&& (ss-1)->reduction
&& threatMove != MOVE_NONE
&& connected_moves(pos, (ss-1)->currentMove, threatMove))
return beta - 1;
}
}
A link to the source will follow shortly, but a post for it has not been created yet.