A common scheme is to generate moves at a node then try only those which can pass some threshold test based in part on possible gain for that move.
Now it may be the case that none of the moves can pass the threshold test. It would be nice if this case were detected early, prior to move ordering and even before move generation.
To help with this, a program needs a routine which will quickly determine the maximum possible gain in a position. Here's Symbolic's version:
Code: Select all
SV Position::CalcMaxGain(void) const
{
// For the given position, determine the maximum possible material gain
SV maxgain = 0;
Bitboard bb;
Sq sq;
// If there's a valid en passant target, then a pawn can be gained
if (IsSqNotNil(fss.epsq))
maxgain = SvPawn;
// Update the maximum gain by scanning all attacked evil men for simple captures
bb = bbdb.GetLocbc(fss.evil) & bbdb.GetAtkbc(fss.good);
while (IsSqNotNil(sq = bb.NextSq()))
{
const SV gain = ManSvVec[board.GetMan(sq)];
if (maxgain < gain)
maxgain = gain;
};
// Update the maximum gain with any pawn promotion moves
bb = bbdb.GetLocbm(SynthPawn[fss.good]) & Bitboard::RankBBVec[CvColorToOrd7Rank[fss.good]];
while (IsSqNotNil(sq = bb.NextSq()))
{
SqPtr tosqptr;
Sq tosq;
// Check non-capture promotions
tosq = NextSquare[sq][CvColorToAdvanceDir[fss.good]];
if (IsManVacant(board.GetMan(tosq)))
{
const SV gain = SvQueen - SvPawn;
if (maxgain < gain)
maxgain = gain;
};
// Check capture promotions
tosqptr = PawnRunPtrs[fss.good][sq];
while (IsSqNotNil(tosq = *tosqptr++))
{
const Man toman = board.GetMan(tosq);
if (CvManToColor[toman] == fss.evil)
{
const SV gain = SvQueen - SvPawn + ManSvVec[toman];
if (maxgain < gain)
maxgain = gain;
};
};
};
return maxgain;
}
