One plus two, times three
Oscar has one main move generation routine which produces all legal-only moves for a position. It calls one of two other routines each time; one for check evasion moves and the other for non-evasion moves:
Code: Select all
static void PositionGenerate(Position * const positionptr, MoveSeg * const movesegptr)
{
// This routine generates the moves for the given position.
if (positionptr->apd.incheck)
PositionGenerateEvasion(positionptr, movesegptr);
else
PositionGenerateNotInCheck(positionptr, movesegptr);
}
There is a second related routine which counts the moves in a position, and it has a similar structure:
Code: Select all
static ui PositionCountMoves(Position * const positionptr)
{
// This routine counts the number of available moves for the given position.
ui count;
if (positionptr->apd.incheck)
count = PositionCountMovesEvasion(positionptr);
else
count = PositionCountMovesNotInCheck(positionptr);
return count;
}
And there is a third routine with the same structure as the first two; it determines if the given position is a mate (checkmate/stalemate):
Code: Select all
static bool PositionHasNoMoves(Position * const positionptr)
{
// This routine is the checkmate/stalemate detector for the given position.
bool hasnomoves;
if (positionptr->apd.incheck)
hasnomoves = PositionHasNoMovesEvasion(positionptr);
else
hasnomoves = PositionHasNoMovesNotInCheck(positionptr);
return hasnomoves;
}
The three
PositionGenerate() routines were written first and then carefully debugged and optimized. After this, the three
PositionCountMoves() routines were written using the
PositionGenerate() routines as a guide. Finally, the three
PositionHasNoMoves() routines were written using the
PositionCountMoves() routines as a guide.
This way, when there are bugs, at least the bugs are consistent!