Henk wrote:hgm wrote:Well, qperft does not do fully legal move generation. It doesn't generate illegal moves with pinned pieces (which saves it some time), so the only moves that would have to be tested to see if it puts itself in check are King moves and e.p. capture. So it makes those at the 1-ply level. And it then tests for check using the 0x88 attack test for all non-Pawns in the piece list, and testing the two board squares from which it could be checked by a Pawn.
If the side to move is not in check then the only pieces that can capture it's king are the pieces located on the squares of the x-ray queen moves of the square that is not longer occupied by the move of the side to move if that move is not a king move or an en passant move
Am I right ? Unfortunately that does not work in Skipper. But I don't know why.
A possible reason is that your description above is hard to understand. Rewrite the phrase in way that can easily be transformed into a simple algorithm. Also it seems your definition does not deal with a king being attacked by a knight. The most simple way to detect whether a king has been left in check (i.e., is attacked by an enemy piece) is to test for attacks in all possible directions starting at the king square:
- is it attacked by a pawn,
- by a knight,
- by a king,
- by a rook or queen on a horizonal/vertical ray, or
- by a bishop or queen on a diagonal ray?
You can try to be more clever by using information about the last move, as you mentioned, but you do not get this for free. If you do so, and it does not work, then watch out for the bug, or go the simple way first and postpone the clever way.
A pseudo-legal move can be illegal in one of these four cases:
- it is a check evasion,
- it is a king move,
- it is an ep capture, or
- it is a move of a pinned piece.
All other pseudo-legal moves are legal and do not require a make-unmake for legality testing.
The set of moves given above can even be reduced a bit in some cases but doing so usually does not give you another drastical improvement.
Code: Select all
bool MoveIsLegal(Move move)
{
bool legal = true; // most pseudo-legal moves are legal
Color self = sideToMove;
if (inCheckFlag || IsKingMove(move) || IsEpMove(move) || IsPinned(move.from)) // move could be illegal
{
do(move);
legal = !IsAttackedBy(KingSquare(self), Opponent(self));
undo(move);
}
return legal;
}
MoveList LegalMoves()
{
MoveList pMoves = PseudoLegalMoves();
MoveList moves;
inCheckFlag = IsInCheck();
DetectPins();
foreach (move in pMoves)
{
if (MoveIsLegal(move))
{
moves.add(move);
}
}
return moves;
}
Regarding IsPinned(), even if Skipper is not a bitboard engine you can still use a bitboard for that purpose. DetectPins() finds all pieces pinned to the king of the moving side and stores their locations in a 64-bit number. IsPinned() maps the given square to a bit position and does a simple AND.