- Color them = opposite_color(us);
- Square from = move_from(m);
- Square to = move_to(m);
- Piece pc = pos.piece_on(from);
-
- // Use a slower but simpler function for uncommon cases
- if (move_is_special(m))
- return move_is_legal(pos, m);
-
- // If the from square is not occupied by a piece belonging to the side to
- // move, the move is obviously not legal.
- if (color_of_piece(pc) != us)
- return false;
-
- // The destination square cannot be occupied by a friendly piece
- if (pos.color_of_piece_on(to) == us)
- return false;
-
- // Handle the special case of a pawn move
- if (type_of_piece(pc) == PAWN)
- {
- // Move direction must be compatible with pawn color
- int direction = to - from;
- if ((us == WHITE) != (direction > 0))
- return false;
-
- // We have already handled promotion moves, so destination
- // cannot be on the 8/1th rank.
- if (square_rank(to) == RANK_8 || square_rank(to) == RANK_1)
- return false;
-
- // Proceed according to the square delta between the origin and
- // destination squares.
- switch (direction)
- {
- case DELTA_NW:
- case DELTA_NE:
- case DELTA_SW:
- case DELTA_SE:
- // Capture. The destination square must be occupied by an enemy
- // piece (en passant captures was handled earlier).
- if (pos.color_of_piece_on(to) != them)
- return false;
- break;
-
- case DELTA_N:
- case DELTA_S:
- // Pawn push. The destination square must be empty.
- if (!pos.square_is_empty(to))
- return false;
- break;
-
- case DELTA_NN:
- // Double white pawn push. The destination square must be on the fourth
- // rank, and both the destination square and the square between the
- // source and destination squares must be empty.
- if ( square_rank(to) != RANK_4
- || !pos.square_is_empty(to)
- || !pos.square_is_empty(from + DELTA_N))
- return false;
- break;
-
- case DELTA_SS:
- // Double black pawn push. The destination square must be on the fifth
- // rank, and both the destination square and the square between the
- // source and destination squares must be empty.
- if ( square_rank(to) != RANK_5
- || !pos.square_is_empty(to)
- || !pos.square_is_empty(from + DELTA_S))
- return false;
- break;
-
- default:
- return false;
- }
- }
- else if (!bit_is_set(pos.attacks_from(pc, from), to))
- return false;
-
- // The move is pseudo-legal, check if it is also legal
- return pos.is_check() ? pos.pl_move_is_evasion(m, pinned) : pos.pl_move_is_legal(m, pinned);
-}
-
-
-namespace {
-
- template<Square Delta>
- inline Bitboard move_pawns(Bitboard p) {
-
- return Delta == DELTA_N ? p << 8 : Delta == DELTA_S ? p >> 8 :
- Delta == DELTA_NE ? p << 9 : Delta == DELTA_SE ? p >> 7 :
- Delta == DELTA_NW ? p << 7 : Delta == DELTA_SW ? p >> 9 : p;
- }
-
- template<MoveType Type, Square Delta>
- inline MoveStack* generate_pawn_captures(MoveStack* mlist, Bitboard pawns, Bitboard target) {
-
- const Bitboard TFileABB = (Delta == DELTA_NE || Delta == DELTA_SE ? FileABB : FileHBB);
-
- Bitboard b;
- Square to;
-
- // Captures in the a1-h8 (a8-h1 for black) diagonal or in the h1-a8 (h8-a1 for black)
- b = move_pawns<Delta>(pawns) & target & ~TFileABB;
- SERIALIZE_MOVES_D(b, -Delta);
- return mlist;
- }
-
- template<Color Us, MoveType Type, Square Delta>
- inline MoveStack* generate_promotions(const Position& pos, MoveStack* mlist, Bitboard pawnsOn7, Bitboard target) {
-
- const Bitboard TFileABB = (Delta == DELTA_NE || Delta == DELTA_SE ? FileABB : FileHBB);
-
- Bitboard b;
- Square to;
-
- // Promotions and under-promotions, both captures and non-captures
- b = move_pawns<Delta>(pawnsOn7) & target;