Skip to content
This repository
Browse code

Add generation of castling checks

When we generate checks one case is missing: generation
of castling moves that give check to the opponent king.

This is a very rare case but anyway it is a case
and we can do this without slowing down the common
case of no castling checks.

So this is the patch.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
  • Loading branch information...
commit 03211296f1b99da5a0117094b3865fa7612791d3 1 parent cc76951
Marco Costalba authored

Showing 1 changed file with 76 additions and 48 deletions. Show diff stats Hide diff stats

  1. +76 48 src/movegen.cpp
124 src/movegen.cpp
@@ -35,8 +35,14 @@
35 35
36 36 namespace {
37 37
38   - // Function
39   - MoveStack* generate_castle_moves(const Position&, MoveStack*);
  38 + enum CastlingSide {
  39 + KING_SIDE = 1,
  40 + QUEEN_SIDE = 2
  41 + };
  42 +
  43 + // Functions
  44 + MoveStack* generate_castle_moves(const Position&, MoveStack*, unsigned = (KING_SIDE | QUEEN_SIDE));
  45 + bool castling_is_check(const Position& pos, CastlingSide side);
40 46
41 47 // Template generate_pawn_captures() with specializations
42 48 template<Color, Color, Bitboard, SquareDelta, SquareDelta, SquareDelta>
@@ -165,8 +171,7 @@ int generate_noncaptures(const Position& pos, MoveStack* mlist) {
165 171
166 172
167 173 /// generate_checks() generates all pseudo-legal non-capturing, non-promoting
168   -/// checks, except castling moves (will add this later). It returns the
169   -/// number of generated moves.
  174 +/// checks. It returns the number of generated moves.
170 175
171 176 int generate_checks(const Position& pos, MoveStack* mlist, Bitboard dc) {
172 177
@@ -207,7 +212,16 @@ int generate_checks(const Position& pos, MoveStack* mlist, Bitboard dc) {
207 212 // Hopefully we always have a king ;-)
208 213 mlist = generate_piece_checks_king(pos, pos.king_square(us), dc, ksq, mlist);
209 214
210   - // TODO: Castling moves!
  215 + // Castling moves that give check. Very rare but nice to have!
  216 + if ( pos.can_castle_queenside(us)
  217 + && (square_rank(ksq) == square_rank(pos.king_square(us)) || square_file(ksq) == FILE_D)
  218 + && castling_is_check(pos, QUEEN_SIDE))
  219 + mlist = generate_castle_moves(pos, mlist, QUEEN_SIDE);
  220 +
  221 + if ( pos.can_castle_kingside(us)
  222 + && (square_rank(ksq) == square_rank(pos.king_square(us)) || square_file(ksq) == FILE_F)
  223 + && castling_is_check(pos, KING_SIDE))
  224 + mlist = generate_castle_moves(pos, mlist, KING_SIDE);
211 225
212 226 return int(mlist - mlist_start);
213 227 }
@@ -879,70 +893,84 @@ namespace {
879 893 return mlist;
880 894 }
881 895
882   -
883   - MoveStack* generate_castle_moves(const Position& pos, MoveStack* mlist) {
  896 + MoveStack* generate_castle_moves(const Position& pos, MoveStack* mlist, unsigned side) {
884 897
885 898 Color us = pos.side_to_move();
886 899
887   - if (pos.can_castle(us))
  900 + if (pos.can_castle_kingside(us) && (side & KING_SIDE))
888 901 {
889 902 Color them = opposite_color(us);
890 903 Square ksq = pos.king_square(us);
891 904
892 905 assert(pos.piece_on(ksq) == king_of_color(us));
893 906
894   - if (pos.can_castle_kingside(us))
895   - {
896   - Square rsq = pos.initial_kr_square(us);
897   - Square g1 = relative_square(us, SQ_G1);
898   - Square f1 = relative_square(us, SQ_F1);
899   - Square s;
900   - bool illegal = false;
  907 + Square rsq = pos.initial_kr_square(us);
  908 + Square g1 = relative_square(us, SQ_G1);
  909 + Square f1 = relative_square(us, SQ_F1);
  910 + Square s;
  911 + bool illegal = false;
901 912
902   - assert(pos.piece_on(rsq) == rook_of_color(us));
  913 + assert(pos.piece_on(rsq) == rook_of_color(us));
903 914
904   - for (s = Min(ksq, g1); s <= Max(ksq, g1); s++)
905   - if ( (s != ksq && s != rsq && pos.square_is_occupied(s))
906   - || pos.square_is_attacked(s, them))
907   - illegal = true;
  915 + for (s = Min(ksq, g1); s <= Max(ksq, g1); s++)
  916 + if ( (s != ksq && s != rsq && pos.square_is_occupied(s))
  917 + || pos.square_is_attacked(s, them))
  918 + illegal = true;
908 919
909   - for (s = Min(rsq, f1); s <= Max(rsq, f1); s++)
910   - if (s != ksq && s != rsq && pos.square_is_occupied(s))
911   - illegal = true;
  920 + for (s = Min(rsq, f1); s <= Max(rsq, f1); s++)
  921 + if (s != ksq && s != rsq && pos.square_is_occupied(s))
  922 + illegal = true;
912 923
913   - if (!illegal)
914   - (*mlist++).move = make_castle_move(ksq, rsq);
915   - }
  924 + if (!illegal)
  925 + (*mlist++).move = make_castle_move(ksq, rsq);
  926 + }
916 927
917   - if (pos.can_castle_queenside(us))
918   - {
919   - Square rsq = pos.initial_qr_square(us);
920   - Square c1 = relative_square(us, SQ_C1);
921   - Square d1 = relative_square(us, SQ_D1);
922   - Square s;
923   - bool illegal = false;
  928 + if (pos.can_castle_queenside(us) && (side & QUEEN_SIDE))
  929 + {
  930 + Color them = opposite_color(us);
  931 + Square ksq = pos.king_square(us);
924 932
925   - assert(pos.piece_on(rsq) == rook_of_color(us));
  933 + assert(pos.piece_on(ksq) == king_of_color(us));
926 934
927   - for (s = Min(ksq, c1); s <= Max(ksq, c1); s++)
928   - if ( (s != ksq && s != rsq && pos.square_is_occupied(s))
929   - || pos.square_is_attacked(s, them))
930   - illegal = true;
  935 + Square rsq = pos.initial_qr_square(us);
  936 + Square c1 = relative_square(us, SQ_C1);
  937 + Square d1 = relative_square(us, SQ_D1);
  938 + Square s;
  939 + bool illegal = false;
931 940
932   - for (s = Min(rsq, d1); s <= Max(rsq, d1); s++)
933   - if (s != ksq && s != rsq && pos.square_is_occupied(s))
934   - illegal = true;
  941 + assert(pos.piece_on(rsq) == rook_of_color(us));
935 942
936   - if ( square_file(rsq) == FILE_B
937   - && ( pos.piece_on(relative_square(us, SQ_A1)) == rook_of_color(them)
938   - || pos.piece_on(relative_square(us, SQ_A1)) == queen_of_color(them)))
939   - illegal = true;
  943 + for (s = Min(ksq, c1); s <= Max(ksq, c1); s++)
  944 + if ( (s != ksq && s != rsq && pos.square_is_occupied(s))
  945 + || pos.square_is_attacked(s, them))
  946 + illegal = true;
940 947
941   - if (!illegal)
942   - (*mlist++).move = make_castle_move(ksq, rsq);
943   - }
  948 + for (s = Min(rsq, d1); s <= Max(rsq, d1); s++)
  949 + if (s != ksq && s != rsq && pos.square_is_occupied(s))
  950 + illegal = true;
  951 +
  952 + if ( square_file(rsq) == FILE_B
  953 + && ( pos.piece_on(relative_square(us, SQ_A1)) == rook_of_color(them)
  954 + || pos.piece_on(relative_square(us, SQ_A1)) == queen_of_color(them)))
  955 + illegal = true;
  956 +
  957 + if (!illegal)
  958 + (*mlist++).move = make_castle_move(ksq, rsq);
944 959 }
945 960 return mlist;
946 961 }
947 962
  963 + bool castling_is_check(const Position& pos, CastlingSide side) {
  964 +
  965 + // After castling opponent king is attacked by the castled rook?
  966 + File rookFile = (side == QUEEN_SIDE ? FILE_D : FILE_F);
  967 + Color us = pos.side_to_move();
  968 + Square ksq = pos.king_square(us);
  969 + Bitboard occ = pos.occupied_squares(), oppKingBB = EmptyBoardBB;
  970 +
  971 + set_bit(&oppKingBB, pos.king_square(opposite_color(us)));
  972 + clear_bit(&occ, ksq); // Remove our king from the board
  973 + Square rsq = make_square(rookFile, square_rank(ksq));
  974 + return (rook_attacks_bb(rsq, occ) & oppKingBB);
  975 + }
948 976 }

0 comments on commit 0321129

Please sign in to comment.
Something went wrong with that request. Please try again.