+ // Handle the special case of a pawn move
+ if (piece_type(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 (piece_color(piece_on(to)) != them)
+ return false;
+
+ // From and to files must be one file apart, avoids a7h5
+ if (abs(square_file(from) - square_file(to)) != 1)
+ return false;
+ break;
+
+ case DELTA_N:
+ case DELTA_S:
+ // Pawn push. The destination square must be empty.
+ if (!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
+ || !square_is_empty(to)
+ || !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
+ || !square_is_empty(to)
+ || !square_is_empty(from + DELTA_S))
+ return false;
+ break;