Rev 169 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 169 | Rev 185 | ||
|---|---|---|---|
| Line 4... | Line 4... | ||
| 4 |   Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad | 
            4 |   Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad | 
          
| 5 |   Copyright (C) 2015- | 
            5 |   Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad | 
          
| 6 | 6 | ||
| 7 |   Stockfish is free software: you can redistribute it and/or modify | 
            7 |   Stockfish is free software: you can redistribute it and/or modify | 
          
| 8 |   it under the terms of the GNU General Public License as published by | 
            8 |   it under the terms of the GNU General Public License as published by | 
          
| 9 |   the Free Software Foundation, either version 3 of the License, or | 
            9 |   the Free Software Foundation, either version 3 of the License, or | 
          
| 10 |   (at your option) any later version. | 
            10 |   (at your option) any later version. | 
          
| Line 23... | Line 23... | ||
| 23 | #include "movegen.h" | 
            23 | #include "movegen.h" | 
          
| 24 | #include "position.h" | 
            24 | #include "position.h" | 
          
| 25 | 25 | ||
| 26 | namespace {  | 
            26 | namespace {  | 
          
| 27 | 27 | ||
| 28 | template<  | 
            28 | template<Color Us, CastlingSide Cs, bool Checks, bool Chess960>  | 
          
| 29 | ExtMove* generate_castling(const Position& pos, ExtMove*  | 
            29 | ExtMove* generate_castling(const Position& pos, ExtMove* moveList) {  | 
          
| 30 | 30 | ||
| - | 31 | constexpr CastlingRight Cr = Us | Cs;  | 
          |
| 31 | 
  | 
            32 | constexpr bool KingSide = (Cr == WHITE_OO || Cr == BLACK_OO);  | 
          
| 32 | 33 | ||
| 33 | if (pos.castling_impeded(Cr) || !pos.can_castle(Cr))  | 
            34 | if (pos.castling_impeded(Cr) || !pos.can_castle(Cr))  | 
          
| 34 | return moveList;  | 
            35 | return moveList;  | 
          
| 35 | 36 | ||
| 36 |     // After castling, the rook and king final positions are the same in Chess960 | 
            37 |     // After castling, the rook and king final positions are the same in Chess960 | 
          
| 37 |     // as they would be in standard chess. | 
            38 |     // as they would be in standard chess. | 
          
| 38 | Square kfrom = pos.square<KING>(  | 
            39 | Square kfrom = pos.square<KING>(Us);  | 
          
| 39 | Square rfrom = pos.castling_rook_square(Cr);  | 
            40 | Square rfrom = pos.castling_rook_square(Cr);  | 
          
| 40 | Square kto = relative_square(  | 
            41 | Square kto = relative_square(Us, KingSide ? SQ_G1 : SQ_C1);  | 
          
| 41 | Bitboard enemies = pos.pieces(  | 
            42 | Bitboard enemies = pos.pieces(~Us);  | 
          
| 42 | 43 | ||
| 43 | assert(!pos.checkers());  | 
            44 | assert(!pos.checkers());  | 
          
| 44 | 45 | ||
| 45 | const Direction  | 
            46 | const Direction step = Chess960 ? kto > kfrom ? WEST : EAST  | 
          
| 46 | : KingSide ? WEST : EAST;  | 
            47 | : KingSide ? WEST : EAST;  | 
          
| 47 | 48 | ||
| 48 | for (Square s = kto; s != kfrom; s +=  | 
            49 | for (Square s = kto; s != kfrom; s += step)  | 
          
| 49 | if (pos.attackers_to(s) & enemies)  | 
            50 | if (pos.attackers_to(s) & enemies)  | 
          
| 50 | return moveList;  | 
            51 | return moveList;  | 
          
| 51 | 52 | ||
| 52 |     // Because we generate only legal castling moves we need to verify that | 
            53 |     // Because we generate only legal castling moves we need to verify that | 
          
| 53 |     // when moving the castling rook we do not discover some hidden checker. | 
            54 |     // when moving the castling rook we do not discover some hidden checker. | 
          
| 54 |     // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. | 
            55 |     // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. | 
          
| 55 | if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(  | 
            56 | if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(~Us, ROOK, QUEEN)))  | 
          
| 56 | return moveList;  | 
            57 | return moveList;  | 
          
| 57 | 58 | ||
| 58 | Move m = make<CASTLING>(kfrom, rfrom);  | 
            59 | Move m = make<CASTLING>(kfrom, rfrom);  | 
          
| 59 | 60 | ||
| 60 | if (Checks && !pos.gives_check(m))  | 
            61 | if (Checks && !pos.gives_check(m))  | 
          
| Line 92... | Line 93... | ||
| 92 | template<Color Us, GenType Type>  | 
            93 | template<Color Us, GenType Type>  | 
          
| 93 | ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {  | 
            94 | ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {  | 
          
| 94 | 95 | ||
| 95 |     // Compute our parametrized parameters at compile time, named according to | 
            96 |     // Compute our parametrized parameters at compile time, named according to | 
          
| 96 |     // the point of view of white side. | 
            97 |     // the point of view of white side. | 
          
| 97 | 
  | 
            98 | constexpr Color Them = (Us == WHITE ? BLACK : WHITE);  | 
          
| 98 | 
  | 
            99 | constexpr Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);  | 
          
| 99 | 
  | 
            100 | constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);  | 
          
| 100 | 
  | 
            101 | constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);  | 
          
| 101 | 
  | 
            102 | constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);  | 
          
| 102 | 
  | 
            103 | constexpr Direction UpRight = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);  | 
          
| 103 | 
  | 
            104 | constexpr Direction UpLeft = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);  | 
          
| 104 | 105 | ||
| 105 |     Bitboard emptySquares; | 
            106 |     Bitboard emptySquares; | 
          
| 106 | 107 | ||
| 107 | Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;  | 
            108 | Bitboard pawnsOn7 = pos.pieces(Us, PAWN) & TRank7BB;  | 
          
| 108 | Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;  | 
            109 | Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;  | 
          
| Line 133... | Line 134... | ||
| 133 | 134 | ||
| 134 |             // Add pawn pushes which give discovered check. This is possible only | 
            135 |             // Add pawn pushes which give discovered check. This is possible only | 
          
| 135 |             // if the pawn is not on the same file as the enemy king, because we | 
            136 |             // if the pawn is not on the same file as the enemy king, because we | 
          
| 136 |             // don't generate captures. Note that a possible discovery check | 
            137 |             // don't generate captures. Note that a possible discovery check | 
          
| 137 |             // promotion has been already generated amongst the captures. | 
            138 |             // promotion has been already generated amongst the captures. | 
          
| 138 | Bitboard dcCandidates = pos.  | 
            139 | Bitboard dcCandidates = pos.blockers_for_king(Them);  | 
          
| 139 | if (pawnsNotOn7 & dcCandidates)  | 
            140 | if (pawnsNotOn7 & dcCandidates)  | 
          
| 140 |             { | 
            141 |             { | 
          
| 141 | Bitboard dc1 = shift<Up>(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);  | 
            142 | Bitboard dc1 = shift<Up>(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);  | 
          
| 142 | Bitboard dc2 = shift<Up>(dc1 & TRank3BB) & emptySquares;  | 
            143 | Bitboard dc2 = shift<Up>(dc1 & TRank3BB) & emptySquares;  | 
          
| 143 | 144 | ||
| Line 166... | Line 167... | ||
| 166 | emptySquares = ~pos.pieces();  | 
            167 | emptySquares = ~pos.pieces();  | 
          
| 167 | 168 | ||
| 168 | if (Type == EVASIONS)  | 
            169 | if (Type == EVASIONS)  | 
          
| 169 | emptySquares &= target;  | 
            170 | emptySquares &= target;  | 
          
| 170 | 171 | ||
| 171 | Bitboard b1 = shift<  | 
            172 | Bitboard b1 = shift<UpRight>(pawnsOn7) & enemies;  | 
          
| 172 | Bitboard b2 = shift<  | 
            173 | Bitboard b2 = shift<UpLeft >(pawnsOn7) & enemies;  | 
          
| 173 | Bitboard b3 = shift<Up >(pawnsOn7) & emptySquares;  | 
            174 | Bitboard b3 = shift<Up >(pawnsOn7) & emptySquares;  | 
          
| 174 | 175 | ||
| 175 | Square ksq = pos.square<KING>(Them);  | 
            176 | Square ksq = pos.square<KING>(Them);  | 
          
| 176 | 177 | ||
| 177 | while (b1)  | 
            178 | while (b1)  | 
          
| 178 | moveList = make_promotions<Type,  | 
            179 | moveList = make_promotions<Type, UpRight>(moveList, pop_lsb(&b1), ksq);  | 
          
| 179 | 180 | ||
| 180 | while (b2)  | 
            181 | while (b2)  | 
          
| 181 | moveList = make_promotions<Type,  | 
            182 | moveList = make_promotions<Type, UpLeft >(moveList, pop_lsb(&b2), ksq);  | 
          
| 182 | 183 | ||
| 183 | while (b3)  | 
            184 | while (b3)  | 
          
| 184 | moveList = make_promotions<Type, Up >(moveList, pop_lsb(&b3), ksq);  | 
            185 | moveList = make_promotions<Type, Up >(moveList, pop_lsb(&b3), ksq);  | 
          
| 185 |     } | 
            186 |     } | 
          
| 186 | 187 | ||
| 187 |     // Standard and en-passant captures | 
            188 |     // Standard and en-passant captures | 
          
| 188 | if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)  | 
            189 | if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)  | 
          
| 189 |     { | 
            190 |     { | 
          
| 190 | Bitboard b1 = shift<  | 
            191 | Bitboard b1 = shift<UpRight>(pawnsNotOn7) & enemies;  | 
          
| 191 | Bitboard b2 = shift<  | 
            192 | Bitboard b2 = shift<UpLeft >(pawnsNotOn7) & enemies;  | 
          
| 192 | 193 | ||
| 193 | while (b1)  | 
            194 | while (b1)  | 
          
| 194 |         { | 
            195 |         { | 
          
| 195 | Square to = pop_lsb(&b1);  | 
            196 | Square to = pop_lsb(&b1);  | 
          
| 196 | *moveList++ = make_move(to -  | 
            197 | *moveList++ = make_move(to - UpRight, to);  | 
          
| 197 |         } | 
            198 |         } | 
          
| 198 | 199 | ||
| 199 | while (b2)  | 
            200 | while (b2)  | 
          
| 200 |         { | 
            201 |         { | 
          
| 201 | Square to = pop_lsb(&b2);  | 
            202 | Square to = pop_lsb(&b2);  | 
          
| 202 | *moveList++ = make_move(to -  | 
            203 | *moveList++ = make_move(to - UpLeft, to);  | 
          
| 203 |         } | 
            204 |         } | 
          
| 204 | 205 | ||
| 205 | if (pos.ep_square() != SQ_NONE)  | 
            206 | if (pos.ep_square() != SQ_NONE)  | 
          
| 206 |         { | 
            207 |         { | 
          
| 207 | assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6));  | 
            208 | assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6));  | 
          
| Line 239... | Line 240... | ||
| 239 |         { | 
            240 |         { | 
          
| 240 | if ( (Pt == BISHOP || Pt == ROOK || Pt == QUEEN)  | 
            241 | if ( (Pt == BISHOP || Pt == ROOK || Pt == QUEEN)  | 
          
| 241 | && !(PseudoAttacks[Pt][from] & target & pos.check_squares(Pt)))  | 
            242 | && !(PseudoAttacks[Pt][from] & target & pos.check_squares(Pt)))  | 
          
| 242 | continue;  | 
            243 | continue;  | 
          
| 243 | 244 | ||
| 244 | if (pos.  | 
            245 | if (pos.blockers_for_king(~us) & from)  | 
          
| 245 | continue;  | 
            246 | continue;  | 
          
| 246 |         } | 
            247 |         } | 
          
| 247 | 248 | ||
| 248 | Bitboard b = pos.attacks_from<Pt>(from) & target;  | 
            249 | Bitboard b = pos.attacks_from<Pt>(from) & target;  | 
          
| 249 | 250 | ||
| Line 259... | Line 260... | ||
| 259 | 260 | ||
| 260 | 261 | ||
| 261 | template<Color Us, GenType Type>  | 
            262 | template<Color Us, GenType Type>  | 
          
| 262 | ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target) {  | 
            263 | ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target) {  | 
          
| 263 | 264 | ||
| 264 | 
  | 
            265 | constexpr bool Checks = Type == QUIET_CHECKS;  | 
          
| 265 | 266 | ||
| 266 | moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);  | 
            267 | moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);  | 
          
| 267 | moveList = generate_moves<KNIGHT, Checks>(pos, moveList, Us, target);  | 
            268 | moveList = generate_moves<KNIGHT, Checks>(pos, moveList, Us, target);  | 
          
| 268 | moveList = generate_moves<BISHOP, Checks>(pos, moveList, Us, target);  | 
            269 | moveList = generate_moves<BISHOP, Checks>(pos, moveList, Us, target);  | 
          
| 269 | moveList = generate_moves< ROOK, Checks>(pos, moveList, Us, target);  | 
            270 | moveList = generate_moves< ROOK, Checks>(pos, moveList, Us, target);  | 
          
| Line 279... | Line 280... | ||
| 279 | 280 | ||
| 280 | if (Type != CAPTURES && Type != EVASIONS && pos.can_castle(Us))  | 
            281 | if (Type != CAPTURES && Type != EVASIONS && pos.can_castle(Us))  | 
          
| 281 |     { | 
            282 |     { | 
          
| 282 | if (pos.is_chess960())  | 
            283 | if (pos.is_chess960())  | 
          
| 283 |         { | 
            284 |         { | 
          
| 284 | moveList = generate_castling  | 
            285 | moveList = generate_castling<Us, KING_SIDE, Checks, true>(pos, moveList);  | 
          
| 285 | moveList = generate_castling  | 
            286 | moveList = generate_castling<Us, QUEEN_SIDE, Checks, true>(pos, moveList);  | 
          
| 286 |         } | 
            287 |         } | 
          
| 287 |         else | 
            288 |         else | 
          
| 288 |         { | 
            289 |         { | 
          
| 289 | moveList = generate_castling  | 
            290 | moveList = generate_castling<Us, KING_SIDE, Checks, false>(pos, moveList);  | 
          
| 290 | moveList = generate_castling  | 
            291 | moveList = generate_castling<Us, QUEEN_SIDE, Checks, false>(pos, moveList);  | 
          
| 291 |         } | 
            292 |         } | 
          
| 292 |     } | 
            293 |     } | 
          
| 293 | 294 | ||
| 294 | return moveList;  | 
            295 | return moveList;  | 
          
| 295 |   } | 
            296 |   } | 
          
| Line 334... | Line 335... | ||
| 334 | ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {  | 
            335 | ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {  | 
          
| 335 | 336 | ||
| 336 | assert(!pos.checkers());  | 
            337 | assert(!pos.checkers());  | 
          
| 337 | 338 | ||
| 338 | Color us = pos.side_to_move();  | 
            339 | Color us = pos.side_to_move();  | 
          
| 339 | Bitboard dc = pos.  | 
            340 | Bitboard dc = pos.blockers_for_king(~us) & pos.pieces(us);  | 
          
| 340 | 341 | ||
| 341 | while (dc)  | 
            342 | while (dc)  | 
          
| 342 |   { | 
            343 |   { | 
          
| 343 | Square from = pop_lsb(&dc);  | 
            344 | Square from = pop_lsb(&dc);  | 
          
| 344 | PieceType pt = type_of(pos.piece_on(from));  | 
            345 | PieceType pt = type_of(pos.piece_on(from));  | 
          
| Line 401... | Line 402... | ||
| 401 | /// generate<LEGAL> generates all the legal moves in the given position | 
            402 | /// generate<LEGAL> generates all the legal moves in the given position | 
          
| 402 | 403 | ||
| 403 | template<>  | 
            404 | template<>  | 
          
| 404 | ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {  | 
            405 | ExtMove* generate<LEGAL>(const Position& pos, ExtMove* moveList) {  | 
          
| 405 | 406 | ||
| - | 407 | Color us = pos.side_to_move();  | 
          |
| 406 | Bitboard pinned = pos.  | 
            408 | Bitboard pinned = pos.blockers_for_king(us) & pos.pieces(us);  | 
          
| 407 | Square ksq = pos.square<KING>(  | 
            409 | Square ksq = pos.square<KING>(us);  | 
          
| 408 | ExtMove* cur = moveList;  | 
            410 | ExtMove* cur = moveList;  | 
          
| 409 | 411 | ||
| 410 | moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList)  | 
            412 | moveList = pos.checkers() ? generate<EVASIONS >(pos, moveList)  | 
          
| 411 | : generate<NON_EVASIONS>(pos, moveList);  | 
            413 | : generate<NON_EVASIONS>(pos, moveList);  | 
          
| 412 | while (cur != moveList)  | 
            414 | while (cur != moveList)  |