BrettVsop wrote:if i remove the function that checks for illegal moves then I will run into a problem with stalemate. I will try it though and see how well it affects the speed.
Hi,
I remember that your speed problems have already been thoroughly discussed in another thread. There were a couple of advices which are of course also valid for perft calculation.
IIRC you make/unmake all moves at the end of move generation only for legality check, before presenting the resulting move list to the search (or perft). This is far too expensive.
Decide whether you want to have legal or pseudolegal move generation. Depending on this, there are a couple of tricks to ensure correct play, and they have all been mentioned in that other thread.
But in both cases, the move generator should not make/unmake all moves, this should only be done as part of the search (or here: the perft calculation), because you get "(N+1) * (cost of make+unmake)" per node instead of 1 * ..., where N is the average number of pseudolegal moves at a node.
For perft, it would be possible to check whether the enemy king is in check right after makeMove(), and to unmake and decrement the counter if it is, so that you do not count nodes below an illegal move.
Find below my current perft code, just for illustration. The legality check is done at the beginning of the recursive function, which is right after makeMove().
I know that it can be done even a lot easier, but that's another issue.
- Code: Select all
uint64 Searcher::getPerftValue(
uint argMaxDepth)
{
Position & currentPos = m_game.getCurrentPosition();
if (currentPos.isIllegal()) {
return 0;
}
if (argMaxDepth == 0) {
return 1;
}
if (currentPos.isTechnicalDrawn()) {
// leaves above maximum depth do not count
return 0;
}
uint numberOfChecks = 0; // ignored here
SquareId checkSqrId = NoSqrId; // will be used by move generator
// using side effects ...
(void) currentPos.isOwnKingInCheck(numberOfChecks, checkSqrId);
bool mustExpand = false;
m_moveGenerator.generate(
currentPos, currentPos.m_moveList, true, checkSqrId, mustExpand);
// no move ordering here
if (!mustExpand) {
// leaves above maximum depth do not count
return 0;
}
uint64 nLeafNodesInSubtree = 0;
uint nLegalMoves = 0;
MoveList & moveList = currentPos.m_moveList;
MoveListEntry * move = moveList.m_first;
for (uint n = 0; n < moveList.m_size; n++, move++) {
makeMove(*move, 0);
uint64 nLeafNodes = getPerftValue(argMaxDepth - 1);
if (nLeafNodes > 0) {
++nLegalMoves;
nLeafNodesInSubtree += nLeafNodes;
}
unmakeLastMove();
}
if (nLegalMoves == 0) {
// leaves above maximum depth do not count
return 0;
} else {
return nLeafNodesInSubtree;
}
}
Regards,
Sven