2 Glaurung, a UCI chess playing engine.
3 Copyright (C) 2004-2008 Tord Romstad
5 Glaurung is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 Glaurung is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 //// Local definitions
35 inline Bitboard forward_white(Bitboard b) { return b << 8; }
36 inline Bitboard forward_right_white(Bitboard b) { return b << 9; }
37 inline Bitboard forward_left_white(Bitboard b) { return b << 7; }
39 inline Bitboard forward_black(Bitboard b) { return b >> 8; }
40 inline Bitboard forward_right_black(Bitboard b) { return b >> 7; }
41 inline Bitboard forward_left_black(Bitboard b) { return b >> 9; }
45 Bitboard Rank3BB, Rank8BB;
47 SquareDelta DELTA_N, DELTA_NE, DELTA_NW;
49 typedef Bitboard (*Shift_fn)(Bitboard b);
50 Shift_fn forward, forward_left, forward_right;
53 const PawnOffsets WhitePawnOffsets = { Rank3BB, Rank8BB, RANK_8, DELTA_N, DELTA_NE, DELTA_NW, WHITE, BLACK,
54 &forward_white, forward_left_white, forward_right_white };
56 const PawnOffsets BlackPawnOffsets = { Rank6BB, Rank1BB, RANK_1, DELTA_S, DELTA_SE, DELTA_SW, BLACK, WHITE,
57 &forward_black, &forward_left_black, &forward_right_black };
59 int generate_pawn_captures(const PawnOffsets&, const Position&, MoveStack*);
60 int generate_pawn_noncaptures(const PawnOffsets&, const Position&, MoveStack*);
61 int generate_pawn_checks(const PawnOffsets&, const Position&, Bitboard, Square, MoveStack*, int);
62 int generate_castle_moves(const Position&, MoveStack*, Color);
63 int generate_pawn_blocking_evasions(const PawnOffsets&, const Position&, Bitboard, Bitboard, MoveStack*, int);
66 int generate_piece_moves(const Position&, MoveStack*, Color, Bitboard);
69 int generate_piece_checks(const Position&, Bitboard, Bitboard, Square, MoveStack*, int);
72 int generate_piece_blocking_evasions(const Position&, Bitboard, Bitboard, MoveStack*, int);
75 /// Templates are defined here to avoid lookup issues with specializations
77 template<PieceType Piece>
78 int generate_piece_moves(const Position &pos, MoveStack *mlist,
79 Color side, Bitboard target) {
81 for (int i = 0; i < pos.piece_count(side, Piece); i++)
83 Square from = pos.piece_list(side, Piece, i);
84 Bitboard b = pos.piece_attacks<Piece>(from) & target;
87 Square to = pop_1st_bit(&b);
88 mlist[n++].move = make_move(from, to);
95 template<PieceType Piece>
96 int generate_piece_checks(const Position& pos, Bitboard target, Bitboard dc,
97 Square ksq, MoveStack* mlist, int n) {
99 Bitboard b = target & dc;
102 Square from = pop_1st_bit(&b);
103 Bitboard bb = pos.piece_attacks<Piece>(from) & pos.empty_squares();
106 Square to = pop_1st_bit(&bb);
107 mlist[n++].move = make_move(from, to);
112 Bitboard checkSqs = pos.piece_attacks<Piece>(ksq) & pos.empty_squares();
115 Square from = pop_1st_bit(&b);
116 Bitboard bb = pos.piece_attacks<Piece>(from) & checkSqs;
119 Square to = pop_1st_bit(&bb);
120 mlist[n++].move = make_move(from, to);
127 template<> // Special case the King
128 int generate_piece_checks<KING>(const Position& pos, Bitboard, Bitboard dc,
129 Square ksq, MoveStack* mlist, int n) {
130 if (bit_is_set(dc, ksq))
132 Bitboard bb = pos.piece_attacks<KING>(ksq)
133 & pos.empty_squares()
134 & ~QueenPseudoAttacks[ksq];
137 Square to = pop_1st_bit(&bb);
138 mlist[n++].move = make_move(ksq, to);
145 template<PieceType Piece>
146 int generate_piece_blocking_evasions(const Position& pos, Bitboard b,
147 Bitboard blockSquares, MoveStack* mlist, int n) {
150 Square from = pop_1st_bit(&b);
151 Bitboard bb = pos.piece_attacks<Piece>(from) & blockSquares;
154 Square to = pop_1st_bit(&bb);
155 mlist[n++].move = make_move(from, to);
168 /// generate_captures generates() all pseudo-legal captures and queen
169 /// promotions. The return value is the number of moves generated.
171 int generate_captures(const Position& pos, MoveStack* mlist) {
174 assert(!pos.is_check());
176 Color us = pos.side_to_move();
177 Bitboard target = pos.pieces_of_color(opposite_color(us));
181 n = generate_pawn_captures(WhitePawnOffsets, pos, mlist);
183 n = generate_pawn_captures(BlackPawnOffsets, pos, mlist);
185 n += generate_piece_moves<KNIGHT>(pos, mlist+n, us, target);
186 n += generate_piece_moves<BISHOP>(pos, mlist+n, us, target);
187 n += generate_piece_moves<ROOK>(pos, mlist+n, us, target);
188 n += generate_piece_moves<QUEEN>(pos, mlist+n, us, target);
189 n += generate_piece_moves<KING>(pos, mlist+n, us, target);
194 /// generate_noncaptures() generates all pseudo-legal non-captures and
195 /// underpromotions. The return value is the number of moves generated.
197 int generate_noncaptures(const Position& pos, MoveStack *mlist) {
200 assert(!pos.is_check());
202 Color us = pos.side_to_move();
203 Bitboard target = pos.empty_squares();
207 n = generate_pawn_noncaptures(WhitePawnOffsets, pos, mlist);
209 n = generate_pawn_noncaptures(BlackPawnOffsets, pos, mlist);
211 n += generate_piece_moves<KNIGHT>(pos, mlist+n, us, target);
212 n += generate_piece_moves<BISHOP>(pos, mlist+n, us, target);
213 n += generate_piece_moves<ROOK>(pos, mlist+n, us, target);
214 n += generate_piece_moves<QUEEN>(pos, mlist+n, us, target);
215 n += generate_piece_moves<KING>(pos, mlist+n, us, target);
217 n += generate_castle_moves(pos, mlist+n, us);
222 /// generate_checks() generates all pseudo-legal non-capturing, non-promoting
223 /// checks, except castling moves (will add this later). It returns the
224 /// number of generated moves.
226 int generate_checks(const Position& pos, MoveStack* mlist, Bitboard dc) {
229 assert(!pos.is_check());
232 Color us = pos.side_to_move();
233 Square ksq = pos.king_square(opposite_color(us));
235 assert(pos.piece_on(ksq) == king_of_color(opposite_color(us)));
237 dc = pos.discovered_check_candidates(us);
241 n = generate_pawn_checks(WhitePawnOffsets, pos, dc, ksq, mlist, 0);
243 n = generate_pawn_checks(BlackPawnOffsets, pos, dc, ksq, mlist, 0);
246 Bitboard b = pos.knights(us);
248 n = generate_piece_checks<KNIGHT>(pos, b, dc, ksq, mlist, n);
252 n = generate_piece_checks<BISHOP>(pos, b, dc, ksq, mlist, n);
256 n = generate_piece_checks<ROOK>(pos, b, dc, ksq, mlist, n);
260 n = generate_piece_checks<QUEEN>(pos, b, dc, ksq, mlist, n);
262 // Hopefully we always have a king ;-)
263 n = generate_piece_checks<KING>(pos, b, dc, pos.king_square(us), mlist, n);
265 // TODO: Castling moves!
271 /// generate_evasions() generates all check evasions when the side to move is
272 /// in check. Unlike the other move generation functions, this one generates
273 /// only legal moves. It returns the number of generated moves. This
274 /// function is very ugly, and needs cleaning up some time later. FIXME
276 int generate_evasions(const Position& pos, MoveStack* mlist) {
279 assert(pos.is_check());
281 Color us = pos.side_to_move();
282 Color them = opposite_color(us);
283 Square ksq = pos.king_square(us);
287 assert(pos.piece_on(ksq) == king_of_color(us));
289 // Generate evasions for king
290 Bitboard b1 = pos.piece_attacks<KING>(ksq) & ~pos.pieces_of_color(us);
291 Bitboard b2 = pos.occupied_squares();
296 Square to = pop_1st_bit(&b1);
298 // Make sure to is not attacked by the other side. This is a bit ugly,
299 // because we can't use Position::square_is_attacked. Instead we use
300 // the low-level bishop_attacks_bb and rook_attacks_bb with the bitboard
301 // b2 (the occupied squares with the king removed) in order to test whether
302 // the king will remain in check on the destination square.
303 if (!( (bishop_attacks_bb(to, b2) & pos.bishops_and_queens(them))
304 || (rook_attacks_bb(to, b2) & pos.rooks_and_queens(them))
305 || (pos.piece_attacks<KNIGHT>(to) & pos.knights(them))
306 || (pos.pawn_attacks(us, to) & pos.pawns(them))
307 || (pos.piece_attacks<KING>(to) & pos.kings(them))))
309 mlist[n++].move = make_move(ksq, to);
312 // Generate evasions for other pieces only if not double check. We use a
313 // simple bit twiddling hack here rather than calling count_1s in order to
314 // save some time (we know that pos.checkers() has at most two nonzero bits).
315 Bitboard checkers = pos.checkers();
317 if (!(checkers & (checkers - 1))) // Only one bit set?
319 Square checksq = first_1(checkers);
321 assert(pos.color_of_piece_on(checksq) == them);
323 // Find pinned pieces
324 Bitboard not_pinned = ~pos.pinned_pieces(us);
326 // Generate captures of the checking piece
329 b1 = pos.pawn_attacks(them, checksq) & pos.pawns(us) & not_pinned;
332 from = pop_1st_bit(&b1);
333 if (relative_rank(us, checksq) == RANK_8)
335 mlist[n++].move = make_promotion_move(from, checksq, QUEEN);
336 mlist[n++].move = make_promotion_move(from, checksq, ROOK);
337 mlist[n++].move = make_promotion_move(from, checksq, BISHOP);
338 mlist[n++].move = make_promotion_move(from, checksq, KNIGHT);
340 mlist[n++].move = make_move(from, checksq);
344 b1 = ( (pos.piece_attacks<KNIGHT>(checksq) & pos.knights(us))
345 | (pos.piece_attacks<BISHOP>(checksq) & pos.bishops_and_queens(us))
346 | (pos.piece_attacks<ROOK>(checksq) & pos.rooks_and_queens(us)) ) & not_pinned;
350 from = pop_1st_bit(&b1);
351 mlist[n++].move = make_move(from, checksq);
354 // Blocking check evasions are possible only if the checking piece is
356 if (checkers & pos.sliders())
358 Bitboard blockSquares = squares_between(checksq, ksq);
360 assert((pos.occupied_squares() & blockSquares) == EmptyBoardBB);
362 // Pawn moves. Because a blocking evasion can never be a capture, we
363 // only generate pawn pushes.
365 n = generate_pawn_blocking_evasions(WhitePawnOffsets, pos, not_pinned, blockSquares, mlist, n);
367 n = generate_pawn_blocking_evasions(BlackPawnOffsets, pos, not_pinned, blockSquares, mlist, n);
370 b1 = pos.knights(us) & not_pinned;
372 n = generate_piece_blocking_evasions<KNIGHT>(pos, b1, blockSquares, mlist, n);
374 b1 = pos.bishops(us) & not_pinned;
376 n = generate_piece_blocking_evasions<BISHOP>(pos, b1, blockSquares, mlist, n);
378 b1 = pos.rooks(us) & not_pinned;
380 n = generate_piece_blocking_evasions<ROOK>(pos, b1, blockSquares, mlist, n);
382 b1 = pos.queens(us) & not_pinned;
384 n = generate_piece_blocking_evasions<QUEEN>(pos, b1, blockSquares, mlist, n);
387 // Finally, the ugly special case of en passant captures. An en passant
388 // capture can only be a check evasion if the check is not a discovered
389 // check. If pos.ep_square() is set, the last move made must have been
390 // a double pawn push. If, furthermore, the checking piece is a pawn,
391 // an en passant check evasion may be possible.
392 if (pos.ep_square() != SQ_NONE && (checkers & pos.pawns(them)))
394 to = pos.ep_square();
395 b1 = pos.pawn_attacks(them, to) & pos.pawns(us);
397 assert(b1 != EmptyBoardBB);
402 from = pop_1st_bit(&b1);
404 // Before generating the move, we have to make sure it is legal.
405 // This is somewhat tricky, because the two disappearing pawns may
406 // cause new "discovered checks". We test this by removing the
407 // two relevant bits from the occupied squares bitboard, and using
408 // the low-level bitboard functions for bishop and rook attacks.
409 b2 = pos.occupied_squares();
410 clear_bit(&b2, from);
411 clear_bit(&b2, checksq);
412 if (!( (bishop_attacks_bb(ksq, b2) & pos.bishops_and_queens(them))
413 ||(rook_attacks_bb(ksq, b2) & pos.rooks_and_queens(them))))
415 mlist[n++].move = make_ep_move(from, to);
423 /// generate_legal_moves() computes a complete list of legal moves in the
424 /// current position. This function is not very fast, and should be used
425 /// only in situations where performance is unimportant. It wouldn't be
426 /// very hard to write an efficient legal move generator, but for the moment
427 /// we don't need it.
429 int generate_legal_moves(const Position& pos, MoveStack* mlist) {
434 return generate_evasions(pos, mlist);
436 // Generate pseudo-legal moves:
437 int n = generate_captures(pos, mlist);
438 n += generate_noncaptures(pos, mlist + n);
440 Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
442 // Remove illegal moves from the list:
443 for (int i = 0; i < n; i++)
444 if (!pos.move_is_legal(mlist[i].move, pinned))
445 mlist[i--].move = mlist[--n].move;
451 /// generate_move_if_legal() takes a position and a (not necessarily
452 /// pseudo-legal) move and a pinned pieces bitboard as input, and tests
453 /// whether the move is legal. If the move is legal, the move itself is
454 /// returned. If not, the function returns MOVE_NONE. This function must
455 /// only be used when the side to move is not in check.
457 Move generate_move_if_legal(const Position &pos, Move m, Bitboard pinned) {
460 assert(!pos.is_check());
461 assert(move_is_ok(m));
463 Color us = pos.side_to_move();
464 Color them = opposite_color(us);
465 Square from = move_from(m);
466 Piece pc = pos.piece_on(from);
468 // If the from square is not occupied by a piece belonging to the side to
469 // move, the move is obviously not legal.
470 if (color_of_piece(pc) != us)
473 Square to = move_to(m);
478 // The piece must be a pawn and destination square must be the
479 // en passant square.
480 if ( type_of_piece(pc) != PAWN
481 || to != pos.ep_square())
484 assert(pos.square_is_empty(to));
485 assert(pos.piece_on(to - pawn_push(us)) == pawn_of_color(them));
487 // The move is pseudo-legal. If it is legal, return it.
488 return (pos.move_is_legal(m) ? m : MOVE_NONE);
492 if (move_is_short_castle(m))
494 // The piece must be a king and side to move must still have
495 // the right to castle kingside.
496 if ( type_of_piece(pc) != KING
497 ||!pos.can_castle_kingside(us))
500 assert(from == pos.king_square(us));
501 assert(to == pos.initial_kr_square(us));
502 assert(pos.piece_on(to) == rook_of_color(us));
504 Square g1 = relative_square(us, SQ_G1);
505 Square f1 = relative_square(us, SQ_F1);
507 bool illegal = false;
509 // Check if any of the squares between king and rook
510 // is occupied or under attack.
511 for (s = Min(from, g1); s <= Max(from, g1); s++)
512 if ( (s != from && s != to && !pos.square_is_empty(s))
513 || pos.square_is_attacked(s, them))
516 // Check if any of the squares between king and rook
518 for (s = Min(to, f1); s <= Max(to, f1); s++)
519 if (s != from && s != to && !pos.square_is_empty(s))
522 return (!illegal ? m : MOVE_NONE);
525 if (move_is_long_castle(m))
527 // The piece must be a king and side to move must still have
528 // the right to castle kingside.
529 if ( type_of_piece(pc) != KING
530 ||!pos.can_castle_queenside(us))
533 assert(from == pos.king_square(us));
534 assert(to == pos.initial_qr_square(us));
535 assert(pos.piece_on(to) == rook_of_color(us));
537 Square c1 = relative_square(us, SQ_C1);
538 Square d1 = relative_square(us, SQ_D1);
540 bool illegal = false;
542 for (s = Min(from, c1); s <= Max(from, c1); s++)
543 if( (s != from && s != to && !pos.square_is_empty(s))
544 || pos.square_is_attacked(s, them))
547 for (s = Min(to, d1); s <= Max(to, d1); s++)
548 if(s != from && s != to && !pos.square_is_empty(s))
551 if ( square_file(to) == FILE_B
552 && ( pos.piece_on(to + DELTA_W) == rook_of_color(them)
553 || pos.piece_on(to + DELTA_W) == queen_of_color(them)))
556 return (!illegal ? m : MOVE_NONE);
561 // The destination square cannot be occupied by a friendly piece
562 if (pos.color_of_piece_on(to) == us)
565 // Proceed according to the type of the moving piece.
566 if (type_of_piece(pc) == PAWN)
568 // If the destination square is on the 8/1th rank, the move must
570 if ( ( (square_rank(to) == RANK_8 && us == WHITE)
571 ||(square_rank(to) == RANK_1 && us != WHITE))
572 && !move_promotion(m))
575 // Proceed according to the square delta between the source and
576 // destionation squares.
583 // Capture. The destination square must be occupied by an enemy
584 // piece (en passant captures was handled earlier).
585 if (pos.color_of_piece_on(to) != them)
591 // Pawn push. The destination square must be empty.
592 if (!pos.square_is_empty(to))
597 // Double white pawn push. The destination square must be on the fourth
598 // rank, and both the destination square and the square between the
599 // source and destination squares must be empty.
600 if ( square_rank(to) != RANK_4
601 || !pos.square_is_empty(to)
602 || !pos.square_is_empty(from + DELTA_N))
607 // Double black pawn push. The destination square must be on the fifth
608 // rank, and both the destination square and the square between the
609 // source and destination squares must be empty.
610 if ( square_rank(to) != RANK_5
611 || !pos.square_is_empty(to)
612 || !pos.square_is_empty(from + DELTA_S))
619 // The move is pseudo-legal. Return it if it is legal.
620 return (pos.move_is_legal(m) ? m : MOVE_NONE);
623 // Luckly we can handle all the other pieces in one go
624 return ( pos.piece_attacks_square(from, to)
625 && pos.move_is_legal(m)
626 && !move_promotion(m) ? m : MOVE_NONE);
632 int generate_pawn_captures(const PawnOffsets& ofs, const Position& pos, MoveStack* mlist) {
634 Bitboard pawns = pos.pawns(ofs.us);
635 Bitboard enemyPieces = pos.pieces_of_color(ofs.them);
639 // Captures in the a1-h8 (a8-h1 for black) direction
640 Bitboard b1 = (ofs.forward_right)(pawns) & ~FileABB & enemyPieces;
642 // Capturing promotions
643 Bitboard b2 = b1 & ofs.Rank8BB;
646 sq = pop_1st_bit(&b2);
647 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_NE, sq, QUEEN);
650 // Capturing non-promotions
651 b2 = b1 & ~ofs.Rank8BB;
654 sq = pop_1st_bit(&b2);
655 mlist[n++].move = make_move(sq - ofs.DELTA_NE, sq);
658 // Captures in the h1-a8 (h8-a1 for black) direction
659 b1 = (ofs.forward_left)(pawns) & ~FileHBB & enemyPieces;
661 // Capturing promotions
662 b2 = b1 & ofs.Rank8BB;
665 sq = pop_1st_bit(&b2);
666 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_NW, sq, QUEEN);
669 // Capturing non-promotions
670 b2 = b1 & ~ofs.Rank8BB;
673 sq = pop_1st_bit(&b2);
674 mlist[n++].move = make_move(sq - ofs.DELTA_NW, sq);
677 // Non-capturing promotions
678 b1 = (ofs.forward)(pawns) & pos.empty_squares() & Rank8BB;
681 sq = pop_1st_bit(&b1);
682 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_N, sq, QUEEN);
685 // En passant captures
686 if (pos.ep_square() != SQ_NONE)
688 assert(ofs.us != WHITE || square_rank(pos.ep_square()) == RANK_6);
689 assert(ofs.us != BLACK || square_rank(pos.ep_square()) == RANK_3);
691 b1 = pawns & pos.pawn_attacks(ofs.them, pos.ep_square());
692 assert(b1 != EmptyBoardBB);
696 sq = pop_1st_bit(&b1);
697 mlist[n++].move = make_ep_move(sq, pos.ep_square());
704 int generate_pawn_noncaptures(const PawnOffsets& ofs, const Position& pos, MoveStack* mlist) {
706 Bitboard pawns = pos.pawns(ofs.us);
707 Bitboard enemyPieces = pos.pieces_of_color(ofs.them);
708 Bitboard emptySquares = pos.empty_squares();
713 // Underpromotion captures in the a1-h8 (a8-h1 for black) direction
714 b1 = ofs.forward_right(pawns) & ~FileABB & enemyPieces & ofs.Rank8BB;
717 sq = pop_1st_bit(&b1);
718 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_NE, sq, ROOK);
719 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_NE, sq, BISHOP);
720 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_NE, sq, KNIGHT);
723 // Underpromotion captures in the h1-a8 (h8-a1 for black) direction
724 b1 = ofs.forward_left(pawns) & ~FileHBB & enemyPieces & ofs.Rank8BB;
727 sq = pop_1st_bit(&b1);
728 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_NW, sq, ROOK);
729 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_NW, sq, BISHOP);
730 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_NW, sq, KNIGHT);
733 // Single pawn pushes
734 b1 = ofs.forward(pawns) & emptySquares;
735 b2 = b1 & ofs.Rank8BB;
738 sq = pop_1st_bit(&b2);
739 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_N, sq, ROOK);
740 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_N, sq, BISHOP);
741 mlist[n++].move = make_promotion_move(sq - ofs.DELTA_N, sq, KNIGHT);
743 b2 = b1 & ~ofs.Rank8BB;
746 sq = pop_1st_bit(&b2);
747 mlist[n++].move = make_move(sq - ofs.DELTA_N, sq);
750 // Double pawn pushes
751 b2 = (ofs.forward(b1 & ofs.Rank3BB)) & emptySquares;
754 sq = pop_1st_bit(&b2);
755 mlist[n++].move = make_move(sq - ofs.DELTA_N - ofs.DELTA_N, sq);
761 int generate_castle_moves(const Position &pos, MoveStack *mlist, Color us) {
765 if (pos.can_castle(us))
767 Color them = opposite_color(us);
768 Square ksq = pos.king_square(us);
770 assert(pos.piece_on(ksq) == king_of_color(us));
772 if (pos.can_castle_kingside(us))
774 Square rsq = pos.initial_kr_square(us);
775 Square g1 = relative_square(us, SQ_G1);
776 Square f1 = relative_square(us, SQ_F1);
778 bool illegal = false;
780 assert(pos.piece_on(rsq) == rook_of_color(us));
782 for (s = Min(ksq, g1); s <= Max(ksq, g1); s++)
783 if ( (s != ksq && s != rsq && pos.square_is_occupied(s))
784 || pos.square_is_attacked(s, them))
787 for (s = Min(rsq, f1); s <= Max(rsq, f1); s++)
788 if (s != ksq && s != rsq && pos.square_is_occupied(s))
792 mlist[n++].move = make_castle_move(ksq, rsq);
795 if (pos.can_castle_queenside(us))
797 Square rsq = pos.initial_qr_square(us);
798 Square c1 = relative_square(us, SQ_C1);
799 Square d1 = relative_square(us, SQ_D1);
801 bool illegal = false;
803 assert(pos.piece_on(rsq) == rook_of_color(us));
805 for (s = Min(ksq, c1); s <= Max(ksq, c1); s++)
806 if ( (s != ksq && s != rsq && pos.square_is_occupied(s))
807 || pos.square_is_attacked(s, them))
810 for (s = Min(rsq, d1); s <= Max(rsq, d1); s++)
811 if (s != ksq && s != rsq && pos.square_is_occupied(s))
814 if ( square_file(rsq) == FILE_B
815 && ( pos.piece_on(relative_square(us, SQ_A1)) == rook_of_color(them)
816 || pos.piece_on(relative_square(us, SQ_A1)) == queen_of_color(them)))
820 mlist[n++].move = make_castle_move(ksq, rsq);
827 int generate_pawn_checks(const PawnOffsets& ofs, const Position& pos, Bitboard dc, Square ksq, MoveStack* mlist, int n)
829 // Pawn moves which give discovered check. This is possible only if the
830 // pawn is not on the same file as the enemy king, because we don't
831 // generate captures.
832 Bitboard empty = pos.empty_squares();
834 // Find all friendly pawns not on the enemy king's file
835 Bitboard b1 = pos.pawns(pos.side_to_move()) & ~file_bb(ksq), b2, b3;
837 // Discovered checks, single pawn pushes
838 b2 = b3 = (ofs.forward)(b1 & dc) & ~ofs.Rank8BB & empty;
841 Square to = pop_1st_bit(&b3);
842 mlist[n++].move = make_move(to - ofs.DELTA_N, to);
845 // Discovered checks, double pawn pushes
846 b3 = (ofs.forward)(b2 & ofs.Rank3BB) & empty;
849 Square to = pop_1st_bit(&b3);
850 mlist[n++].move = make_move(to - ofs.DELTA_N - ofs.DELTA_N, to);
853 // Direct checks. These are possible only for pawns on neighboring files
856 b1 &= (~dc & neighboring_files_bb(ksq)); // FIXME why ~dc ??
858 // Direct checks, single pawn pushes
859 b2 = (ofs.forward)(b1) & empty;
860 b3 = b2 & pos.pawn_attacks(ofs.them, ksq);
863 Square to = pop_1st_bit(&b3);
864 mlist[n++].move = make_move(to - ofs.DELTA_N, to);
867 // Direct checks, double pawn pushes
868 b3 = (ofs.forward)(b2 & ofs.Rank3BB) & empty & pos.pawn_attacks(ofs.them, ksq);
871 Square to = pop_1st_bit(&b3);
872 mlist[n++].move = make_move(to - ofs.DELTA_N - ofs.DELTA_N, to);
878 int generate_pawn_blocking_evasions(const PawnOffsets& ofs, const Position& pos, Bitboard not_pinned,
879 Bitboard blockSquares, MoveStack* mlist, int n) {
880 // Find non-pinned pawns
881 Bitboard b1 = pos.pawns(ofs.us) & not_pinned;
883 // Single pawn pushes. We don't have to AND with empty squares here,
884 // because the blocking squares will always be empty.
885 Bitboard b2 = (ofs.forward)(b1) & blockSquares;
888 Square to = pop_1st_bit(&b2);
890 assert(pos.piece_on(to) == EMPTY);
892 if (square_rank(to) == ofs.RANK_8)
894 mlist[n++].move = make_promotion_move(to - ofs.DELTA_N, to, QUEEN);
895 mlist[n++].move = make_promotion_move(to - ofs.DELTA_N, to, ROOK);
896 mlist[n++].move = make_promotion_move(to - ofs.DELTA_N, to, BISHOP);
897 mlist[n++].move = make_promotion_move(to - ofs.DELTA_N, to, KNIGHT);
899 mlist[n++].move = make_move(to - ofs.DELTA_N, to);
902 // Double pawn pushes
903 b2 = (ofs.forward)((ofs.forward)(b1) & pos.empty_squares() & ofs.Rank3BB) & blockSquares;
906 Square to = pop_1st_bit(&b2);
908 assert(pos.piece_on(to) == EMPTY);
909 assert(ofs.us != WHITE || square_rank(to) == RANK_4);
910 assert(ofs.us != BLACK || square_rank(to) == RANK_5);
912 mlist[n++].move = make_move(to - ofs.DELTA_N - ofs.DELTA_N, to);