Subversion Repositories Games.Chess Giants

Rev

Rev 96 | Rev 169 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 96 Rev 154
Line 24... Line 24...
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<CastlingRight Cr, bool Checks, bool Chess960>
29
  ExtMove* generate_castling(const Position& pos, ExtMove* moveList, Color us, const CheckInfo* ci) {
29
  ExtMove* generate_castling(const Position& pos, ExtMove* moveList, Color us) {
30
 
30
 
31
    static const bool KingSide = (Cr == WHITE_OO || Cr == BLACK_OO);
31
    static const bool KingSide = (Cr == WHITE_OO || Cr == BLACK_OO);
32
 
32
 
33
    if (pos.castling_impeded(Cr) || !pos.can_castle(Cr))
33
    if (pos.castling_impeded(Cr) || !pos.can_castle(Cr))
34
        return moveList;
34
        return moveList;
Line 40... Line 40...
40
    Square kto = relative_square(us, KingSide ? SQ_G1 : SQ_C1);
40
    Square kto = relative_square(us, KingSide ? SQ_G1 : SQ_C1);
41
    Bitboard enemies = pos.pieces(~us);
41
    Bitboard enemies = pos.pieces(~us);
42
 
42
 
43
    assert(!pos.checkers());
43
    assert(!pos.checkers());
44
 
44
 
45
    const Square K = Chess960 ? kto > kfrom ? DELTA_W : DELTA_E
45
    const Square K = Chess960 ? kto > kfrom ? WEST : EAST
46
                              : KingSide    ? DELTA_W : DELTA_E;
46
                              : KingSide    ? WEST : EAST;
47
 
47
 
48
    for (Square s = kto; s != kfrom; s += K)
48
    for (Square s = kto; s != kfrom; s += K)
49
        if (pos.attackers_to(s) & enemies)
49
        if (pos.attackers_to(s) & enemies)
50
            return moveList;
50
            return moveList;
51
 
51
 
Line 55... Line 55...
55
    if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(~us, ROOK, QUEEN)))
55
    if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(~us, ROOK, QUEEN)))
56
        return moveList;
56
        return moveList;
57
 
57
 
58
    Move m = make<CASTLING>(kfrom, rfrom);
58
    Move m = make<CASTLING>(kfrom, rfrom);
59
 
59
 
60
    if (Checks && !pos.gives_check(m, *ci))
60
    if (Checks && !pos.gives_check(m))
61
        return moveList;
61
        return moveList;
62
    else
-
 
63
        (void)ci; // Silence a warning under MSVC
-
 
64
 
62
 
65
    *moveList++ = m;
63
    *moveList++ = m;
66
    return moveList;
64
    return moveList;
67
  }
65
  }
68
 
66
 
69
 
67
 
70
  template<GenType Type, Square Delta>
68
  template<GenType Type, Square D>
71
  ExtMove* make_promotions(ExtMove* moveList, Square to, const CheckInfo* ci) {
69
  ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) {
72
 
70
 
73
    if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
71
    if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
74
        *moveList++ = make<PROMOTION>(to - Delta, to, QUEEN);
72
        *moveList++ = make<PROMOTION>(to - D, to, QUEEN);
75
 
73
 
76
    if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
74
    if (Type == QUIETS || Type == EVASIONS || Type == NON_EVASIONS)
77
    {
75
    {
78
        *moveList++ = make<PROMOTION>(to - Delta, to, ROOK);
76
        *moveList++ = make<PROMOTION>(to - D, to, ROOK);
79
        *moveList++ = make<PROMOTION>(to - Delta, to, BISHOP);
77
        *moveList++ = make<PROMOTION>(to - D, to, BISHOP);
80
        *moveList++ = make<PROMOTION>(to - Delta, to, KNIGHT);
78
        *moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
81
    }
79
    }
82
 
80
 
83
    // Knight promotion is the only promotion that can give a direct check
81
    // Knight promotion is the only promotion that can give a direct check
84
    // that's not already included in the queen promotion.
82
    // that's not already included in the queen promotion.
85
    if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ci->ksq))
83
    if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ksq))
86
        *moveList++ = make<PROMOTION>(to - Delta, to, KNIGHT);
84
        *moveList++ = make<PROMOTION>(to - D, to, KNIGHT);
87
    else
85
    else
88
        (void)ci; // Silence a warning under MSVC
86
        (void)ksq; // Silence a warning under MSVC
89
 
87
 
90
    return moveList;
88
    return moveList;
91
  }
89
  }
92
 
90
 
93
 
91
 
94
  template<Color Us, GenType Type>
92
  template<Color Us, GenType Type>
95
  ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList,
93
  ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
96
                               Bitboard target, const CheckInfo* ci) {
-
 
97
 
94
 
98
    // Compute our parametrized parameters at compile time, named according to
95
    // Compute our parametrized parameters at compile time, named according to
99
    // the point of view of white side.
96
    // the point of view of white side.
100
    const Color    Them     = (Us == WHITE ? BLACK    : WHITE);
97
    const Color    Them     = (Us == WHITE ? BLACK      : WHITE);
101
    const Bitboard TRank8BB = (Us == WHITE ? Rank8BB  : Rank1BB);
98
    const Bitboard TRank8BB = (Us == WHITE ? Rank8BB    : Rank1BB);
102
    const Bitboard TRank7BB = (Us == WHITE ? Rank7BB  : Rank2BB);
99
    const Bitboard TRank7BB = (Us == WHITE ? Rank7BB    : Rank2BB);
103
    const Bitboard TRank3BB = (Us == WHITE ? Rank3BB  : Rank6BB);
100
    const Bitboard TRank3BB = (Us == WHITE ? Rank3BB    : Rank6BB);
104
    const Square   Up       = (Us == WHITE ? DELTA_N  : DELTA_S);
101
    const Square   Up       = (Us == WHITE ? NORTH      : SOUTH);
105
    const Square   Right    = (Us == WHITE ? DELTA_NE : DELTA_SW);
102
    const Square   Right    = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
106
    const Square   Left     = (Us == WHITE ? DELTA_NW : DELTA_SE);
103
    const Square   Left     = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);
107
 
104
 
108
    Bitboard emptySquares;
105
    Bitboard emptySquares;
109
 
106
 
110
    Bitboard pawnsOn7    = pos.pieces(Us, PAWN) &  TRank7BB;
107
    Bitboard pawnsOn7    = pos.pieces(Us, PAWN) &  TRank7BB;
111
    Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;
108
    Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;
Line 115... Line 112...
115
 
112
 
116
    // Single and double pawn pushes, no promotions
113
    // Single and double pawn pushes, no promotions
117
    if (Type != CAPTURES)
114
    if (Type != CAPTURES)
118
    {
115
    {
119
        emptySquares = (Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces());
116
        emptySquares = (Type == QUIETS || Type == QUIET_CHECKS ? target : ~pos.pieces());
120
 
117
 
121
        Bitboard b1 = shift_bb<Up>(pawnsNotOn7)   & emptySquares;
118
        Bitboard b1 = shift<Up>(pawnsNotOn7)   & emptySquares;
122
        Bitboard b2 = shift_bb<Up>(b1 & TRank3BB) & emptySquares;
119
        Bitboard b2 = shift<Up>(b1 & TRank3BB) & emptySquares;
123
 
120
 
124
        if (Type == EVASIONS) // Consider only blocking squares
121
        if (Type == EVASIONS) // Consider only blocking squares
125
        {
122
        {
126
            b1 &= target;
123
            b1 &= target;
127
            b2 &= target;
124
            b2 &= target;
128
        }
125
        }
129
 
126
 
130
        if (Type == QUIET_CHECKS)
127
        if (Type == QUIET_CHECKS)
131
        {
128
        {
-
 
129
            Square ksq = pos.square<KING>(Them);
-
 
130
 
132
            b1 &= pos.attacks_from<PAWN>(ci->ksq, Them);
131
            b1 &= pos.attacks_from<PAWN>(ksq, Them);
133
            b2 &= pos.attacks_from<PAWN>(ci->ksq, Them);
132
            b2 &= pos.attacks_from<PAWN>(ksq, Them);
134
 
133
 
135
            // Add pawn pushes which give discovered check. This is possible only
134
            // Add pawn pushes which give discovered check. This is possible only
136
            // if the pawn is not on the same file as the enemy king, because we
135
            // if the pawn is not on the same file as the enemy king, because we
137
            // don't generate captures. Note that a possible discovery check
136
            // don't generate captures. Note that a possible discovery check
138
            // promotion has been already generated amongst the captures.
137
            // promotion has been already generated amongst the captures.
-
 
138
            Bitboard dcCandidates = pos.discovered_check_candidates();
139
            if (pawnsNotOn7 & ci->dcCandidates)
139
            if (pawnsNotOn7 & dcCandidates)
140
            {
140
            {
141
                Bitboard dc1 = shift_bb<Up>(pawnsNotOn7 & ci->dcCandidates) & emptySquares & ~file_bb(ci->ksq);
141
                Bitboard dc1 = shift<Up>(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq);
142
                Bitboard dc2 = shift_bb<Up>(dc1 & TRank3BB) & emptySquares;
142
                Bitboard dc2 = shift<Up>(dc1 & TRank3BB) & emptySquares;
143
 
143
 
144
                b1 |= dc1;
144
                b1 |= dc1;
145
                b2 |= dc2;
145
                b2 |= dc2;
146
            }
146
            }
147
        }
147
        }
Line 166... Line 166...
166
            emptySquares = ~pos.pieces();
166
            emptySquares = ~pos.pieces();
167
 
167
 
168
        if (Type == EVASIONS)
168
        if (Type == EVASIONS)
169
            emptySquares &= target;
169
            emptySquares &= target;
170
 
170
 
171
        Bitboard b1 = shift_bb<Right>(pawnsOn7) & enemies;
171
        Bitboard b1 = shift<Right>(pawnsOn7) & enemies;
172
        Bitboard b2 = shift_bb<Left >(pawnsOn7) & enemies;
172
        Bitboard b2 = shift<Left >(pawnsOn7) & enemies;
173
        Bitboard b3 = shift_bb<Up   >(pawnsOn7) & emptySquares;
173
        Bitboard b3 = shift<Up   >(pawnsOn7) & emptySquares;
-
 
174
 
-
 
175
        Square ksq = pos.square<KING>(Them);
174
 
176
 
175
        while (b1)
177
        while (b1)
176
            moveList = make_promotions<Type, Right>(moveList, pop_lsb(&b1), ci);
178
            moveList = make_promotions<Type, Right>(moveList, pop_lsb(&b1), ksq);
177
 
179
 
178
        while (b2)
180
        while (b2)
179
            moveList = make_promotions<Type, Left >(moveList, pop_lsb(&b2), ci);
181
            moveList = make_promotions<Type, Left >(moveList, pop_lsb(&b2), ksq);
180
 
182
 
181
        while (b3)
183
        while (b3)
182
            moveList = make_promotions<Type, Up   >(moveList, pop_lsb(&b3), ci);
184
            moveList = make_promotions<Type, Up   >(moveList, pop_lsb(&b3), ksq);
183
    }
185
    }
184
 
186
 
185
    // Standard and en-passant captures
187
    // Standard and en-passant captures
186
    if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
188
    if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
187
    {
189
    {
188
        Bitboard b1 = shift_bb<Right>(pawnsNotOn7) & enemies;
190
        Bitboard b1 = shift<Right>(pawnsNotOn7) & enemies;
189
        Bitboard b2 = shift_bb<Left >(pawnsNotOn7) & enemies;
191
        Bitboard b2 = shift<Left >(pawnsNotOn7) & enemies;
190
 
192
 
191
        while (b1)
193
        while (b1)
192
        {
194
        {
193
            Square to = pop_lsb(&b1);
195
            Square to = pop_lsb(&b1);
194
            *moveList++ = make_move(to - Right, to);
196
            *moveList++ = make_move(to - Right, to);
Line 223... Line 225...
223
  }
225
  }
224
 
226
 
225
 
227
 
226
  template<PieceType Pt, bool Checks>
228
  template<PieceType Pt, bool Checks>
227
  ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us,
229
  ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us,
228
                          Bitboard target, const CheckInfo* ci) {
230
                          Bitboard target) {
229
 
231
 
230
    assert(Pt != KING && Pt != PAWN);
232
    assert(Pt != KING && Pt != PAWN);
231
 
233
 
232
    const Square* pl = pos.squares<Pt>(us);
234
    const Square* pl = pos.squares<Pt>(us);
233
 
235
 
234
    for (Square from = *pl; from != SQ_NONE; from = *++pl)
236
    for (Square from = *pl; from != SQ_NONE; from = *++pl)
235
    {
237
    {
236
        if (Checks)
238
        if (Checks)
237
        {
239
        {
238
            if (    (Pt == BISHOP || Pt == ROOK || Pt == QUEEN)
240
            if (    (Pt == BISHOP || Pt == ROOK || Pt == QUEEN)
239
                && !(PseudoAttacks[Pt][from] & target & ci->checkSquares[Pt]))
241
                && !(PseudoAttacks[Pt][from] & target & pos.check_squares(Pt)))
240
                continue;
242
                continue;
241
 
243
 
242
            if (ci->dcCandidates && (ci->dcCandidates & from))
244
            if (pos.discovered_check_candidates() & from)
243
                continue;
245
                continue;
244
        }
246
        }
245
 
247
 
246
        Bitboard b = pos.attacks_from<Pt>(from) & target;
248
        Bitboard b = pos.attacks_from<Pt>(from) & target;
247
 
249
 
248
        if (Checks)
250
        if (Checks)
249
            b &= ci->checkSquares[Pt];
251
            b &= pos.check_squares(Pt);
250
 
252
 
251
        while (b)
253
        while (b)
252
            *moveList++ = make_move(from, pop_lsb(&b));
254
            *moveList++ = make_move(from, pop_lsb(&b));
253
    }
255
    }
254
 
256
 
255
    return moveList;
257
    return moveList;
256
  }
258
  }
257
 
259
 
258
 
260
 
259
  template<Color Us, GenType Type>
261
  template<Color Us, GenType Type>
260
  ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target,
262
  ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target) {
261
                        const CheckInfo* ci = nullptr) {
-
 
262
 
263
 
263
    const bool Checks = Type == QUIET_CHECKS;
264
    const bool Checks = Type == QUIET_CHECKS;
264
 
265
 
265
    moveList = generate_pawn_moves<Us, Type>(pos, moveList, target, ci);
266
    moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
266
    moveList = generate_moves<KNIGHT, Checks>(pos, moveList, Us, target, ci);
267
    moveList = generate_moves<KNIGHT, Checks>(pos, moveList, Us, target);
267
    moveList = generate_moves<BISHOP, Checks>(pos, moveList, Us, target, ci);
268
    moveList = generate_moves<BISHOP, Checks>(pos, moveList, Us, target);
268
    moveList = generate_moves<  ROOK, Checks>(pos, moveList, Us, target, ci);
269
    moveList = generate_moves<  ROOK, Checks>(pos, moveList, Us, target);
269
    moveList = generate_moves< QUEEN, Checks>(pos, moveList, Us, target, ci);
270
    moveList = generate_moves< QUEEN, Checks>(pos, moveList, Us, target);
270
 
271
 
271
    if (Type != QUIET_CHECKS && Type != EVASIONS)
272
    if (Type != QUIET_CHECKS && Type != EVASIONS)
272
    {
273
    {
273
        Square ksq = pos.square<KING>(Us);
274
        Square ksq = pos.square<KING>(Us);
274
        Bitboard b = pos.attacks_from<KING>(ksq) & target;
275
        Bitboard b = pos.attacks_from<KING>(ksq) & target;
Line 278... Line 279...
278
 
279
 
279
    if (Type != CAPTURES && Type != EVASIONS && pos.can_castle(Us))
280
    if (Type != CAPTURES && Type != EVASIONS && pos.can_castle(Us))
280
    {
281
    {
281
        if (pos.is_chess960())
282
        if (pos.is_chess960())
282
        {
283
        {
283
            moveList = generate_castling<MakeCastling<Us,  KING_SIDE>::right, Checks, true>(pos, moveList, Us, ci);
284
            moveList = generate_castling<MakeCastling<Us,  KING_SIDE>::right, Checks, true>(pos, moveList, Us);
284
            moveList = generate_castling<MakeCastling<Us, QUEEN_SIDE>::right, Checks, true>(pos, moveList, Us, ci);
285
            moveList = generate_castling<MakeCastling<Us, QUEEN_SIDE>::right, Checks, true>(pos, moveList, Us);
285
        }
286
        }
286
        else
287
        else
287
        {
288
        {
288
            moveList = generate_castling<MakeCastling<Us,  KING_SIDE>::right, Checks, false>(pos, moveList, Us, ci);
289
            moveList = generate_castling<MakeCastling<Us,  KING_SIDE>::right, Checks, false>(pos, moveList, Us);
289
            moveList = generate_castling<MakeCastling<Us, QUEEN_SIDE>::right, Checks, false>(pos, moveList, Us, ci);
290
            moveList = generate_castling<MakeCastling<Us, QUEEN_SIDE>::right, Checks, false>(pos, moveList, Us);
290
        }
291
        }
291
    }
292
    }
292
 
293
 
293
    return moveList;
294
    return moveList;
294
  }
295
  }
Line 333... Line 334...
333
ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
334
ExtMove* generate<QUIET_CHECKS>(const Position& pos, ExtMove* moveList) {
334
 
335
 
335
  assert(!pos.checkers());
336
  assert(!pos.checkers());
336
 
337
 
337
  Color us = pos.side_to_move();
338
  Color us = pos.side_to_move();
338
  CheckInfo ci(pos);
-
 
339
  Bitboard dc = ci.dcCandidates;
339
  Bitboard dc = pos.discovered_check_candidates();
340
 
340
 
341
  while (dc)
341
  while (dc)
342
  {
342
  {
343
     Square from = pop_lsb(&dc);
343
     Square from = pop_lsb(&dc);
344
     PieceType pt = type_of(pos.piece_on(from));
344
     PieceType pt = type_of(pos.piece_on(from));
Line 347... Line 347...
347
         continue; // Will be generated together with direct checks
347
         continue; // Will be generated together with direct checks
348
 
348
 
349
     Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces();
349
     Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces();
350
 
350
 
351
     if (pt == KING)
351
     if (pt == KING)
352
         b &= ~PseudoAttacks[QUEEN][ci.ksq];
352
         b &= ~PseudoAttacks[QUEEN][pos.square<KING>(~us)];
353
 
353
 
354
     while (b)
354
     while (b)
355
         *moveList++ = make_move(from, pop_lsb(&b));
355
         *moveList++ = make_move(from, pop_lsb(&b));
356
  }
356
  }
357
 
357
 
358
  return us == WHITE ? generate_all<WHITE, QUIET_CHECKS>(pos, moveList, ~pos.pieces(), &ci)
358
  return us == WHITE ? generate_all<WHITE, QUIET_CHECKS>(pos, moveList, ~pos.pieces())
359
                     : generate_all<BLACK, QUIET_CHECKS>(pos, moveList, ~pos.pieces(), &ci);
359
                     : generate_all<BLACK, QUIET_CHECKS>(pos, moveList, ~pos.pieces());
360
}
360
}
361
 
361
 
362
 
362
 
363
/// generate<EVASIONS> generates all pseudo-legal check evasions when the side
363
/// generate<EVASIONS> generates all pseudo-legal check evasions when the side
364
/// to move is in check. Returns a pointer to the end of the move list.
364
/// to move is in check. Returns a pointer to the end of the move list.
Line 409... Line 409...
409
 
409
 
410
  moveList = pos.checkers() ? generate<EVASIONS    >(pos, moveList)
410
  moveList = pos.checkers() ? generate<EVASIONS    >(pos, moveList)
411
                            : generate<NON_EVASIONS>(pos, moveList);
411
                            : generate<NON_EVASIONS>(pos, moveList);
412
  while (cur != moveList)
412
  while (cur != moveList)
413
      if (   (pinned || from_sq(*cur) == ksq || type_of(*cur) == ENPASSANT)
413
      if (   (pinned || from_sq(*cur) == ksq || type_of(*cur) == ENPASSANT)
414
          && !pos.legal(*cur, pinned))
414
          && !pos.legal(*cur))
415
          *cur = (--moveList)->move;
415
          *cur = (--moveList)->move;
416
      else
416
      else
417
          ++cur;
417
          ++cur;
418
 
418
 
419
  return moveList;
419
  return moveList;