Subversion Repositories Games.Chess Giants

Rev

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-2018 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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<CastlingRight Cr, bool Checks, bool Chess960>
28
  template<Color Us, CastlingSide Cs, bool Checks, bool Chess960>
29
  ExtMove* generate_castling(const Position& pos, ExtMove* moveList, Color us) {
29
  ExtMove* generate_castling(const Position& pos, ExtMove* moveList) {
30
 
30
 
-
 
31
    constexpr CastlingRight Cr = Us | Cs;
31
    static const bool KingSide = (Cr == WHITE_OO || Cr == BLACK_OO);
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>(us);
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(us, KingSide ? SQ_G1 : SQ_C1);
41
    Square kto = relative_square(Us, KingSide ? SQ_G1 : SQ_C1);
41
    Bitboard enemies = pos.pieces(~us);
42
    Bitboard enemies = pos.pieces(~Us);
42
 
43
 
43
    assert(!pos.checkers());
44
    assert(!pos.checkers());
44
 
45
 
45
    const Direction K = Chess960 ? kto > kfrom ? WEST : EAST
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 += K)
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(~us, ROOK, QUEEN)))
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
    const Color     Them     = (Us == WHITE ? BLACK      : WHITE);
98
    constexpr Color     Them     = (Us == WHITE ? BLACK      : WHITE);
98
    const Bitboard  TRank8BB = (Us == WHITE ? Rank8BB    : Rank1BB);
99
    constexpr Bitboard  TRank8BB = (Us == WHITE ? Rank8BB    : Rank1BB);
99
    const Bitboard  TRank7BB = (Us == WHITE ? Rank7BB    : Rank2BB);
100
    constexpr Bitboard  TRank7BB = (Us == WHITE ? Rank7BB    : Rank2BB);
100
    const Bitboard  TRank3BB = (Us == WHITE ? Rank3BB    : Rank6BB);
101
    constexpr Bitboard  TRank3BB = (Us == WHITE ? Rank3BB    : Rank6BB);
101
    const Direction Up       = (Us == WHITE ? NORTH      : SOUTH);
102
    constexpr Direction Up       = (Us == WHITE ? NORTH      : SOUTH);
102
    const Direction Right    = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
103
    constexpr Direction UpRight  = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
103
    const Direction Left     = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
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.discovered_check_candidates();
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<Right>(pawnsOn7) & enemies;
172
        Bitboard b1 = shift<UpRight>(pawnsOn7) & enemies;
172
        Bitboard b2 = shift<Left >(pawnsOn7) & enemies;
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, Right>(moveList, pop_lsb(&b1), ksq);
179
            moveList = make_promotions<Type, UpRight>(moveList, pop_lsb(&b1), ksq);
179
 
180
 
180
        while (b2)
181
        while (b2)
181
            moveList = make_promotions<Type, Left >(moveList, pop_lsb(&b2), ksq);
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<Right>(pawnsNotOn7) & enemies;
191
        Bitboard b1 = shift<UpRight>(pawnsNotOn7) & enemies;
191
        Bitboard b2 = shift<Left >(pawnsNotOn7) & enemies;
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 - Right, 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 - Left, 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.discovered_check_candidates() & from)
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
    const bool Checks = Type == QUIET_CHECKS;
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<MakeCastling<Us,  KING_SIDE>::right, Checks, true>(pos, moveList, Us);
285
            moveList = generate_castling<Us, KING_SIDE, Checks, true>(pos, moveList);
285
            moveList = generate_castling<MakeCastling<Us, QUEEN_SIDE>::right, Checks, true>(pos, moveList, Us);
286
            moveList = generate_castling<Us, QUEEN_SIDE, Checks, true>(pos, moveList);
286
        }
287
        }
287
        else
288
        else
288
        {
289
        {
289
            moveList = generate_castling<MakeCastling<Us,  KING_SIDE>::right, Checks, false>(pos, moveList, Us);
290
            moveList = generate_castling<Us, KING_SIDE, Checks, false>(pos, moveList);
290
            moveList = generate_castling<MakeCastling<Us, QUEEN_SIDE>::right, Checks, false>(pos, moveList, Us);
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.discovered_check_candidates();
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.pinned_pieces(pos.side_to_move());
408
  Bitboard pinned = pos.blockers_for_king(us) & pos.pieces(us);
407
  Square ksq = pos.square<KING>(pos.side_to_move());
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)