bool posCanMakeMove(const Pos *pos, Move move) { // Sanity checks and special case. assert(moveIsValid(move) || move==MoveNone); if (move==MoveNone) return true; // Use local variables to simulate having made the move. Colour stm=moveGetColour(move); assert(stm==posGetSTM(pos)); Colour xstm=colourSwap(stm); BB occ=posGetBBAll(pos); BB opp=posGetBBColour(pos, xstm); Sq fromSq=moveGetFromSq(move); Sq toSq=moveGetToSq(move); BB fromBB=bbSq(fromSq); BB toBB=bbSq(toSq); Sq kingSq=posGetKingSq(pos, stm); if (fromSq==kingSq) kingSq=toSq; // King move. occ&=~fromBB; // Move piece. occ|=toBB; opp&=~toBB; // Potentially capture opp piece (so it cannot attack us later). if (moveGetToPieceType(move)==PieceTypePawn && sqFile(fromSq)!=sqFile(toSq) && posGetPieceOnSq(pos, toSq)==PieceNone) { // En-passent capture. assert(pos->data->epSq==toSq); occ^=bbSq(toSq^8); opp^=bbSq(toSq^8); } // Make a list of squares we need to ensure are unattacked. BB checkSquares=bbSq(kingSq); if (moveIsCastling(move)) checkSquares|=fromBB|bbSq((toSq+fromSq)/2); // Test for attacks to any of checkSquares. // Pawns are done setwise. BB oppPawns=(posGetBBPiece(pos, pieceMake(PieceTypePawn, xstm)) & opp); if (bbForwardOne(bbWingify(oppPawns), xstm) & checkSquares) return false; // Pieces are checked for each square in checkSquares (which usually only has a single bit set anyway). while(checkSquares) { Sq sq=bbScanReset(&checkSquares); // Knights. if (attacksKnight(sq) & opp & posGetBBPiece(pos, pieceMake(PieceTypeKnight, xstm))) return false; // Bishops and diagonal queen moves. if (attacksBishop(sq, occ) & opp & (posGetBBPiece(pos, pieceMake(PieceTypeBishopL, xstm)) | posGetBBPiece(pos, pieceMake(PieceTypeBishopD, xstm)) | posGetBBPiece(pos, pieceMake(PieceTypeQueen, xstm)))) return false; // Rooks and orthogonal queen moves. if (attacksRook(sq, occ) & opp & (posGetBBPiece(pos, pieceMake(PieceTypeRook, xstm)) | posGetBBPiece(pos, pieceMake(PieceTypeQueen, xstm)))) return false; // King. if (attacksKing(sq) & opp & posGetBBPiece(pos, pieceMake(PieceTypeKing, xstm))) return false; } return true; }
bool moveIsDP(Move move) { assert(moveIsValid(move)); int toRank=sqRank(moveGetToSqRaw(move)); int fromRank=sqRank(moveGetFromSq(move)); return (moveGetToPieceType(move)==PieceTypePawn && abs(toRank-fromRank)==2); }