Subversion Repositories Games.Chess Giants

Rev

Rev 33 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
33 pmbaty 1
#include "chess.h"
2
#include "data.h"
108 pmbaty 3
/* modified 12/31/15 */
33 pmbaty 4
/*
5
 *******************************************************************************
6
 *                                                                             *
7
 *   GenerateCaptures() is used to generate capture and pawn promotion moves   *
8
 *   from the current position.                                                *
9
 *                                                                             *
10
 *   The destination square set is the set of squares occupied by opponent     *
11
 *   pieces, plus the set of squares on the 8th rank that pawns can advance to *
12
 *   and promote.                                                              *
13
 *                                                                             *
14
 *******************************************************************************
15
 */
108 pmbaty 16
unsigned *GenerateCaptures(TREE * RESTRICT tree, int ply, int side,
17
    unsigned *move) {
18
  uint64_t target, piecebd, moves, promotions, pcapturesl, pcapturesr;
33 pmbaty 19
  int from, to, temp, common, enemy = Flip(side);
20
 
21
/*
22
 ************************************************************
23
 *                                                          *
24
 *  We produce knight moves by locating the most advanced   *
25
 *  knight and then using that <from> square as an index    *
26
 *  into the precomputed knight_attacks data.  We repeat    *
27
 *  for each knight.                                        *
28
 *                                                          *
29
 ************************************************************
30
 */
31
  for (piecebd = Knights(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 32
    from = MostAdvanced(side, piecebd);
33 pmbaty 33
    moves = knight_attacks[from] & Occupied(enemy);
34
    temp = from + (knight << 12);
35
    Extract(side, move, moves, temp);
36
  }
37
/*
38
 ************************************************************
39
 *                                                          *
108 pmbaty 40
 *  We produce sliding piece moves by locating each piece   *
41
 *  type in turn.  We then start with the most advanced     *
42
 *  piece and generate moves from that square.  This uses   *
43
 *  "magic move generation" to produce the destination      *
44
 *  squares.                                                *
33 pmbaty 45
 *                                                          *
46
 ************************************************************
47
 */
48
  for (piecebd = Bishops(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 49
    from = MostAdvanced(side, piecebd);
33 pmbaty 50
    moves = BishopAttacks(from, OccupiedSquares) & Occupied(enemy);
51
    temp = from + (bishop << 12);
52
    Extract(side, move, moves, temp);
53
  }
54
  for (piecebd = Rooks(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 55
    from = MostAdvanced(side, piecebd);
33 pmbaty 56
    moves = RookAttacks(from, OccupiedSquares) & Occupied(enemy);
57
    temp = from + (rook << 12);
58
    Extract(side, move, moves, temp);
59
  }
60
  for (piecebd = Queens(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 61
    from = MostAdvanced(side, piecebd);
33 pmbaty 62
    moves = QueenAttacks(from, OccupiedSquares) & Occupied(enemy);
63
    temp = from + (queen << 12);
64
    Extract(side, move, moves, temp);
65
  }
66
/*
67
 ************************************************************
68
 *                                                          *
69
 *  We produce king moves by locating the only king and     *
70
 *  then using that <from> square as an index into the      *
71
 *  precomputed king_attacks data.                          *
72
 *                                                          *
73
 ************************************************************
74
 */
75
  from = KingSQ(side);
76
  moves = king_attacks[from] & Occupied(enemy);
77
  temp = from + (king << 12);
78
  Extract(side, move, moves, temp);
79
/*
80
 ************************************************************
81
 *                                                          *
82
 *  Now, produce pawn moves.  This is done differently due  *
83
 *  to inconsistencies in the way a pawn moves when it      *
84
 *  captures as opposed to normal non-capturing moves.      *
85
 *  Another exception is capturing enpassant.  The first    *
86
 *  step is to generate all possible pawn promotions.  We   *
87
 *  do this by removing all pawns but those on the 7th rank *
88
 *  and then advancing them if the square in front is empty.*
89
 *                                                          *
90
 ************************************************************
91
 */
108 pmbaty 92
  promotions = Pawns(side) & rank_mask[rank7[side]];
33 pmbaty 93
  promotions =
108 pmbaty 94
      ((side) ? promotions << 8 : promotions >> 8) & ~OccupiedSquares;
33 pmbaty 95
  for (; promotions; Clear(to, promotions)) {
96
    to = LSB(promotions);
97
    *move++ =
98
        (to + pawnadv1[side]) | (to << 6) | (pawn << 12) | (queen << 18);
99
  }
100
  target = Occupied(enemy) | EnPassantTarget(ply);
101
  pcapturesl =
102
      ((side) ? (Pawns(white) & mask_left_edge) << 7 : (Pawns(black) &
103
          mask_left_edge) >> 9) & target;
104
  for (; pcapturesl; Clear(to, pcapturesl)) {
108 pmbaty 105
    to = MostAdvanced(side, pcapturesl);
33 pmbaty 106
    common = (to + capleft[side]) | (to << 6) | (pawn << 12);
107
    if ((side) ? to < 56 : to > 7)
108
      *move++ = common | (((PcOnSq(to)) ? Abs(PcOnSq(to)) : pawn) << 15);
109
    else
110
      *move++ = common | Abs(PcOnSq(to)) << 15 | queen << 18;
111
  }
112
  pcapturesr =
113
      ((side) ? (Pawns(white) & mask_right_edge) << 9 : (Pawns(black) &
114
          mask_right_edge) >> 7) & target;
115
  for (; pcapturesr; Clear(to, pcapturesr)) {
108 pmbaty 116
    to = MostAdvanced(side, pcapturesr);
33 pmbaty 117
    common = (to + capright[side]) | (to << 6) | (pawn << 12);
118
    if ((side) ? to < 56 : to > 7)
119
      *move++ = common | (((PcOnSq(to)) ? Abs(PcOnSq(to)) : pawn) << 15);
120
    else
121
      *move++ = common | Abs(PcOnSq(to)) << 15 | queen << 18;
122
  }
123
  return move;
124
}
125
 
108 pmbaty 126
/* modified 12/31/15 */
33 pmbaty 127
/*
128
 *******************************************************************************
129
 *                                                                             *
130
 *   GenerateChecks() is used to generate non-capture moves from the current   *
131
 *   position.                                                                 *
132
 *                                                                             *
133
 *   The first pass produces a bitmap that contains the squares a particular   *
134
 *   piece type would attack if sitting on the square the enemy king sits on.  *
135
 *   We then use each of these squares as a source and check to see if the     *
136
 *   same piece type attacks one of these common targets.  If so, we can move  *
137
 *   that piece to that square and it will directly attack the king.  We do    *
138
 *   this for pawns, knights, bishops, rooks and queens to produce the set of  *
139
 *   "direct checking moves."                                                  *
140
 *                                                                             *
141
 *   Then we generate discovered checks in two passes, once for diagonal       *
142
 *   attacks and once for rank/file attacks (we do it in two passes since a    *
143
 *   rook can't produce a discovered check along a rank or file since it moves *
144
 *   in that direction as well.  For diagonals, we first generate the bishop   *
145
 *   attacks from the enemy king square and mask them with the friendly piece  *
146
 *   occupied squares bitmap.  This gives us a set of up to 4 "blocking        *
147
 *   pieces" that could be preventing a check.  We then remove them via the    *
148
 *   "magic move generation" tricks, and see if we now reach friendly bishops  *
149
 *   or queens on those diagonals.  If we have a friendly blocker, and a       *
150
 *   friendly diagonal mover behind that blocker, then moving the blocker is   *
151
 *   a discovered check (and there could be double-checks included but we do   *
152
 *   not check for that since a single check is good enough).  We repeat this  *
153
 *   for the ranks/files and we are done.                                      *
154
 *                                                                             *
155
 *   For the present, this code does not produce discovered checks by the      *
156
 *   king since all king moves are not discovered checks because the king can  *
157
 *   move in the same direction as the piece it blocks and not uncover the     *
158
 *   attack.  This might be fixed at some point, but it is rare enough to not  *
159
 *   be an issue except in far endgames.                                       *
160
 *                                                                             *
161
 *******************************************************************************
162
 */
108 pmbaty 163
unsigned *GenerateChecks(TREE * RESTRICT tree, int side, unsigned *move) {
33 pmbaty 164
  uint64_t temp_target, target, piecebd, moves;
165
  uint64_t padvances1, blockers, checkers;
166
  int from, to, promote, temp, enemy = Flip(side);
167
 
168
/*
108 pmbaty 169
 ************************************************************
170
 *                                                          *
171
 *  First pass:  produce direct checks.  For each piece     *
172
 *  type, we pretend that a piece of that type stands on    *
173
 *  the square of the king and we generate attacks from     *
174
 *  that square for that piece.  Now, if we can find any    *
175
 *  piece of that type that attacks one of those squares,   *
176
 *  then that piece move would deliver a direct check to    *
177
 *  the enemy king.  Easy, wasn't it?                       *
178
 *                                                          *
179
 ************************************************************
33 pmbaty 180
 */
181
  target = ~OccupiedSquares;
182
/*
183
 ************************************************************
184
 *                                                          *
185
 *  Knight direct checks.                                   *
186
 *                                                          *
187
 ************************************************************
188
 */
189
  temp_target = target & knight_attacks[KingSQ(enemy)];
190
  for (piecebd = Knights(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 191
    from = MostAdvanced(side, piecebd);
33 pmbaty 192
    moves = knight_attacks[from] & temp_target;
193
    temp = from + (knight << 12);
194
    Extract(side, move, moves, temp);
195
  }
196
/*
197
 ************************************************************
198
 *                                                          *
108 pmbaty 199
 *  Sliding piece direct checks.                            *
33 pmbaty 200
 *                                                          *
201
 ************************************************************
202
 */
203
  temp_target = target & BishopAttacks(KingSQ(enemy), OccupiedSquares);
204
  for (piecebd = Bishops(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 205
    from = MostAdvanced(side, piecebd);
33 pmbaty 206
    moves = BishopAttacks(from, OccupiedSquares) & temp_target;
207
    temp = from + (bishop << 12);
208
    Extract(side, move, moves, temp);
209
  }
210
  temp_target = target & RookAttacks(KingSQ(enemy), OccupiedSquares);
211
  for (piecebd = Rooks(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 212
    from = MostAdvanced(side, piecebd);
33 pmbaty 213
    moves = RookAttacks(from, OccupiedSquares) & temp_target;
214
    temp = from + (rook << 12);
215
    Extract(side, move, moves, temp);
216
  }
217
  temp_target = target & QueenAttacks(KingSQ(enemy), OccupiedSquares);
218
  for (piecebd = Queens(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 219
    from = MostAdvanced(side, piecebd);
33 pmbaty 220
    moves = QueenAttacks(from, OccupiedSquares) & temp_target;
221
    temp = from + (queen << 12);
222
    Extract(side, move, moves, temp);
223
  }
224
/*
225
 ************************************************************
226
 *                                                          *
227
 *   Pawn direct checks.                                    *
228
 *                                                          *
229
 ************************************************************
230
 */
231
  temp_target = target & pawn_attacks[enemy][KingSQ(enemy)];
232
  padvances1 = ((side) ? Pawns(white) << 8 : Pawns(black) >> 8) & temp_target;
233
  for (; padvances1; Clear(to, padvances1)) {
108 pmbaty 234
    to = MostAdvanced(side, padvances1);
33 pmbaty 235
    *move++ = (to + pawnadv1[side]) | (to << 6) | (pawn << 12);
236
  }
237
/*
238
 ************************************************************
239
 *                                                          *
108 pmbaty 240
 *  Second pass:  produce discovered checks.  Here we do    *
241
 *  things a bit differently.  We first take diagonal       *
242
 *  movers.  From the enemy king's position, we generate    *
243
 *  diagonal moves to see if any of them end at one of our  *
244
 *  pieces that does not slide diagonally, such as a rook,  *
245
 *  knight or pawn.  If we find one, we look further down   *
246
 *  that diagonal to see if we now find a diagonal moves    *
247
 *  (queen or bishop).  If so, any legal move by the        *
248
 *  blocking piece (except captures which have already been *
249
 *  generated) will be a discovered check that needs to be  *
250
 *  searched.  We do the same for vertical / horizontal     *
251
 *  rays that are blocked by bishops, knights or pawns that *
252
 *  would hide a discovered check by a rook or queen.       *
253
 *                                                          *
33 pmbaty 254
 *  First we look for diagonal discovered attacks.  Once we *
255
 *  know which squares hold pieces that create a discovered *
256
 *  check when they move, we generate those piece moves     *
257
 *  piece type by piece type.                               *
258
 *                                                          *
259
 ************************************************************
260
 */
261
  blockers =
262
      BishopAttacks(KingSQ(enemy),
263
      OccupiedSquares) & (Rooks(side) | Knights(side) | Pawns(side));
264
  if (blockers) {
265
    checkers =
266
        BishopAttacks(KingSQ(enemy),
267
        OccupiedSquares & ~blockers) & (Bishops(side) | Queens(side));
268
    if (checkers) {
269
      if (plus7dir[KingSQ(enemy)] & blockers &&
270
          !(plus7dir[KingSQ(enemy)] & checkers))
271
        blockers &= ~plus7dir[KingSQ(enemy)];
272
      if (plus9dir[KingSQ(enemy)] & blockers &&
273
          !(plus9dir[KingSQ(enemy)] & checkers))
274
        blockers &= ~plus9dir[KingSQ(enemy)];
275
      if (minus7dir[KingSQ(enemy)] & blockers &&
276
          !(minus7dir[KingSQ(enemy)] & checkers))
277
        blockers &= ~minus7dir[KingSQ(enemy)];
278
      if (minus9dir[KingSQ(enemy)] & blockers &&
279
          !(minus9dir[KingSQ(enemy)] & checkers))
280
        blockers &= ~minus9dir[KingSQ(enemy)];
281
      target = ~OccupiedSquares;
282
/*
283
 ************************************************************
284
 *                                                          *
285
 *  Knight discovered checks.                               *
286
 *                                                          *
287
 ************************************************************
288
 */
289
      temp_target = target & ~knight_attacks[KingSQ(enemy)];
290
      for (piecebd = Knights(side) & blockers; piecebd; Clear(from, piecebd)) {
108 pmbaty 291
        from = MostAdvanced(side, piecebd);
33 pmbaty 292
        moves = knight_attacks[from] & temp_target;
293
        temp = from + (knight << 12);
294
        Extract(side, move, moves, temp);
295
      }
296
/*
297
 ************************************************************
298
 *                                                          *
299
 *  Rook discovered checks.                                 *
300
 *                                                          *
301
 ************************************************************
302
 */
303
      target = ~OccupiedSquares;
304
      temp_target = target & ~RookAttacks(KingSQ(enemy), OccupiedSquares);
305
      for (piecebd = Rooks(side) & blockers; piecebd; Clear(from, piecebd)) {
108 pmbaty 306
        from = MostAdvanced(side, piecebd);
33 pmbaty 307
        moves = RookAttacks(from, OccupiedSquares) & temp_target;
308
        temp = from + (rook << 12);
309
        Extract(side, move, moves, temp);
310
      }
311
/*
312
 ************************************************************
313
 *                                                          *
314
 *  Pawn discovered checks.                                 *
315
 *                                                          *
316
 ************************************************************
317
 */
318
      piecebd =
319
          Pawns(side) & blockers & ((side) ? ~OccupiedSquares >> 8 :
320
          ~OccupiedSquares << 8);
321
      for (; piecebd; Clear(from, piecebd)) {
108 pmbaty 322
        from = MostAdvanced(side, piecebd);
33 pmbaty 323
        to = from + pawnadv1[enemy];
324
        if ((side) ? to > 55 : to < 8)
325
          promote = queen;
326
        else
327
          promote = 0;
328
        *move++ = from | (to << 6) | (pawn << 12) | (promote << 18);
329
      }
330
    }
331
  }
332
/*
333
 ************************************************************
334
 *                                                          *
335
 *  Next, we look for rank/file discovered attacks.  Once   *
336
 *  we know which squares hold pieces that create a         *
337
 *  discovered check when they move, we generate them       *
338
 *  piece type by piece type.                               *
339
 *                                                          *
340
 ************************************************************
341
 */
342
  blockers =
343
      RookAttacks(KingSQ(enemy),
344
      OccupiedSquares) & (Bishops(side) | Knights(side) | (Pawns(side) &
345
          rank_mask[Rank(KingSQ(enemy))]));
346
  if (blockers) {
347
    checkers =
348
        RookAttacks(KingSQ(enemy),
349
        OccupiedSquares & ~blockers) & (Rooks(side) | Queens(side));
350
    if (checkers) {
351
      if (plus1dir[KingSQ(enemy)] & blockers &&
352
          !(plus1dir[KingSQ(enemy)] & checkers))
353
        blockers &= ~plus1dir[KingSQ(enemy)];
354
      if (plus8dir[KingSQ(enemy)] & blockers &&
355
          !(plus8dir[KingSQ(enemy)] & checkers))
356
        blockers &= ~plus8dir[KingSQ(enemy)];
357
      if (minus1dir[KingSQ(enemy)] & blockers &&
358
          !(minus1dir[KingSQ(enemy)] & checkers))
359
        blockers &= ~minus1dir[KingSQ(enemy)];
360
      if (minus8dir[KingSQ(enemy)] & blockers &&
361
          !(minus8dir[KingSQ(enemy)] & checkers))
362
        blockers &= ~minus8dir[KingSQ(enemy)];
363
      target = ~OccupiedSquares;
364
/*
365
 ************************************************************
366
 *                                                          *
367
 *  Knight discovered checks.                               *
368
 *                                                          *
369
 ************************************************************
370
 */
371
      temp_target = target & ~knight_attacks[KingSQ(enemy)];
372
      for (piecebd = Knights(side) & blockers; piecebd; Clear(from, piecebd)) {
108 pmbaty 373
        from = MostAdvanced(side, piecebd);
33 pmbaty 374
        moves = knight_attacks[from] & temp_target;
375
        temp = from + (knight << 12);
376
        Extract(side, move, moves, temp);
377
      }
378
/*
379
 ************************************************************
380
 *                                                          *
381
 *  Bishop discovered checks.                               *
382
 *                                                          *
383
 ************************************************************
384
 */
385
      target = ~OccupiedSquares;
386
      temp_target = target & ~BishopAttacks(KingSQ(enemy), OccupiedSquares);
387
      for (piecebd = Bishops(side) & blockers; piecebd; Clear(from, piecebd)) {
108 pmbaty 388
        from = MostAdvanced(side, piecebd);
33 pmbaty 389
        moves = BishopAttacks(from, OccupiedSquares) & temp_target;
390
        temp = from + (bishop << 12);
391
        Extract(side, move, moves, temp);
392
      }
393
/*
394
 ************************************************************
395
 *                                                          *
396
 *  Pawn discovered checks.                                 *
397
 *                                                          *
398
 ************************************************************
399
 */
400
      piecebd =
401
          Pawns(side) & blockers & ((side) ? ~OccupiedSquares >> 8 :
402
          ~OccupiedSquares << 8);
403
      for (; piecebd; Clear(from, piecebd)) {
108 pmbaty 404
        from = MostAdvanced(side, piecebd);
33 pmbaty 405
        to = from + pawnadv1[enemy];
406
        if ((side) ? to > 55 : to < 8)
407
          promote = queen;
408
        else
409
          promote = 0;
410
        *move++ = from | (to << 6) | (pawn << 12) | (promote << 18);
411
      }
412
    }
413
  }
414
  return move;
415
}
416
 
108 pmbaty 417
/* modified 12/31/15 */
33 pmbaty 418
/*
419
 *******************************************************************************
420
 *                                                                             *
421
 *   GenerateCheckEvasions() is used to generate moves when the king is in     *
422
 *   check.                                                                    *
423
 *                                                                             *
424
 *   Three types of check-evasion moves are generated:                         *
425
 *                                                                             *
426
 *   (1) Generate king moves to squares that are not attacked by the           *
427
 *   opponent's pieces.  This includes capture and non-capture moves.          *
428
 *                                                                             *
429
 *   (2) Generate interpositions along the rank/file that the checking attack  *
430
 *   is coming along (assuming (a) only one piece is checking the king, and    *
431
 *   (b) the checking piece is a sliding piece [bishop, rook, queen]).         *
432
 *                                                                             *
433
 *   (3) Generate capture moves, but only to the square(s) that are giving     *
434
 *   check.  Captures are a special case.  If there is one checking piece,     *
435
 *   then capturing it by any piece is tried.  If there are two pieces         *
436
 *   checking the king, then the only legal capture to try is for the king to  *
437
 *   capture one of the checking pieces that is on an unattacked square.       *
438
 *                                                                             *
439
 *******************************************************************************
440
 */
108 pmbaty 441
unsigned *GenerateCheckEvasions(TREE * RESTRICT tree, int ply, int side,
442
    unsigned *move) {
443
  uint64_t target, targetc, targetp, piecebd, moves, empty, checksqs;
444
  uint64_t padvances1, padvances2, pcapturesl, pcapturesr, padvances1_all;
445
  int from, to, temp, common, enemy = Flip(side), king_square, checkers;
446
  int checking_square, check_direction1 = 0, check_direction2 = 0;
33 pmbaty 447
 
448
/*
449
 ************************************************************
450
 *                                                          *
451
 *  First, determine how many pieces are attacking the king *
452
 *  and where they are, so we can figure out how to legally *
453
 *  get out of check.                                       *
454
 *                                                          *
455
 ************************************************************
456
 */
457
  king_square = KingSQ(side);
458
  checksqs = AttacksTo(tree, king_square) & Occupied(enemy);
459
  checkers = PopCnt(checksqs);
460
  if (checkers == 1) {
461
    checking_square = LSB(checksqs);
462
    if (PcOnSq(checking_square) != pieces[enemy][pawn])
463
      check_direction1 = directions[checking_square][king_square];
464
    target = InterposeSquares(king_square, checking_square);
465
    target |= checksqs;
466
    target |= Kings(enemy);
467
  } else {
468
    target = Kings(enemy);
469
    checking_square = LSB(checksqs);
470
    if (PcOnSq(checking_square) != pieces[enemy][pawn])
471
      check_direction1 = directions[checking_square][king_square];
472
    checking_square = MSB(checksqs);
473
    if (PcOnSq(checking_square) != pieces[enemy][pawn])
474
      check_direction2 = directions[checking_square][king_square];
475
  }
476
/*
477
 ************************************************************
478
 *                                                          *
479
 *  The next step is to produce the set of valid            *
480
 *  destination squares.  For king moves, this is simply    *
481
 *  the set of squares that are not attacked by enemy       *
482
 *  pieces (if there are any such squares.)                 *
483
 *                                                          *
484
 *  Then, if the checking piece is not a knight, we need    *
485
 *  to know the checking direction so that we can either    *
486
 *  move the king off of that ray, or else block that ray.  *
487
 *                                                          *
488
 *  We produce king moves by locating the only king and     *
489
 *  then using that <from> square as an index into the      *
490
 *  precomputed king_attacks data.                          *
491
 *                                                          *
492
 ************************************************************
493
 */
494
  from = king_square;
495
  temp = from + (king << 12);
496
  for (moves = king_attacks[from] & ~Occupied(side); moves; Clear(to, moves)) {
108 pmbaty 497
    to = MostAdvanced(side, moves);
33 pmbaty 498
    if (!Attacks(tree, enemy, to)
499
        && directions[from][to] != check_direction1 &&
500
        directions[from][to] != check_direction2)
501
      *move++ = temp | (to << 6) | (Abs(PcOnSq(to)) << 15);
502
  }
503
/*
504
 ************************************************************
505
 *                                                          *
506
 *  We produce knight moves by locating the most advanced   *
507
 *  knight and then using that <from> square as an index    *
508
 *  into the precomputed knight_attacks data.  We repeat    *
509
 *  for each knight.                                        *
510
 *                                                          *
511
 ************************************************************
512
 */
513
  if (checkers == 1) {
514
    for (piecebd = Knights(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 515
      from = MostAdvanced(side, piecebd);
33 pmbaty 516
      if (!PinnedOnKing(tree, side, from)) {
517
        moves = knight_attacks[from] & target;
518
        temp = from + (knight << 12);
519
        Extract(side, move, moves, temp);
520
      }
521
    }
522
/*
523
 ************************************************************
524
 *                                                          *
108 pmbaty 525
 *  We produce sliding piece moves by locating each piece   *
526
 *  type in turn.  We then start with the most advanced     *
527
 *  piece and generate moves from that square.  This uses   *
528
 *  "magic move generation" to produce the destination      *
529
 *  squares.                                                *
33 pmbaty 530
 *                                                          *
531
 ************************************************************
532
 */
533
    for (piecebd = Bishops(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 534
      from = MostAdvanced(side, piecebd);
33 pmbaty 535
      if (!PinnedOnKing(tree, side, from)) {
536
        moves = BishopAttacks(from, OccupiedSquares) & target;
537
        temp = from + (bishop << 12);
538
        Extract(side, move, moves, temp);
539
      }
540
    }
541
    for (piecebd = Rooks(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 542
      from = MostAdvanced(side, piecebd);
33 pmbaty 543
      if (!PinnedOnKing(tree, side, from)) {
544
        moves = RookAttacks(from, OccupiedSquares) & target;
545
        temp = from + (rook << 12);
546
        Extract(side, move, moves, temp);
547
      }
548
    }
549
    for (piecebd = Queens(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 550
      from = MostAdvanced(side, piecebd);
33 pmbaty 551
      if (!PinnedOnKing(tree, side, from)) {
552
        moves = QueenAttacks(from, OccupiedSquares) & target;
553
        temp = from + (queen << 12);
554
        Extract(side, move, moves, temp);
555
      }
556
    }
557
/*
558
 ************************************************************
559
 *                                                          *
560
 *  Now, produce pawn moves.  This is done differently due  *
561
 *  to inconsistencies in the way a pawn moves when it      *
562
 *  captures as opposed to normal non-capturing moves.      *
563
 *  Another exception is capturing enpassant.  The first    *
564
 *  step is to generate all possible pawn moves.  We do     *
565
 *  this in 2 operations:  (1) shift the pawns forward one  *
566
 *  rank then AND with empty squares;  (2) shift the pawns  *
567
 *  forward two ranks and then AND with empty squares.      *
568
 *                                                          *
569
 ************************************************************
570
 */
571
    empty = ~OccupiedSquares;
572
    targetp = target & empty;
573
    if (side) {
574
      padvances1 = Pawns(white) << 8 & targetp;
575
      padvances1_all = Pawns(white) << 8 & empty;
576
      padvances2 = ((padvances1_all & ((uint64_t) 255 << 16)) << 8) & targetp;
577
    } else {
578
      padvances1 = Pawns(black) >> 8 & targetp;
579
      padvances1_all = Pawns(black) >> 8 & empty;
580
      padvances2 = ((padvances1_all & ((uint64_t) 255 << 40)) >> 8) & targetp;
581
    }
582
/*
583
 ************************************************************
584
 *                                                          *
585
 *  Now that we got 'em, we simply enumerate the to squares *
586
 *  as before, but in four steps since we have four sets of *
587
 *  potential moves.                                        *
588
 *                                                          *
589
 ************************************************************
590
 */
591
    for (; padvances2; Clear(to, padvances2)) {
108 pmbaty 592
      to = MostAdvanced(side, padvances2);
33 pmbaty 593
      if (!PinnedOnKing(tree, side, to + pawnadv2[side]))
594
        *move++ = (to + pawnadv2[side]) | (to << 6) | (pawn << 12);
595
    }
596
    for (; padvances1; Clear(to, padvances1)) {
108 pmbaty 597
      to = MostAdvanced(side, padvances1);
33 pmbaty 598
      if (!PinnedOnKing(tree, side, to + pawnadv1[side])) {
599
        common = (to + pawnadv1[side]) | (to << 6) | (pawn << 12);
600
        if ((side) ? to < 56 : to > 7)
601
          *move++ = common;
602
        else {
603
          *move++ = common | (queen << 18);
604
          *move++ = common | (knight << 18);
605
        }
606
      }
607
    }
108 pmbaty 608
/*
609
 ************************************************************
610
 *                                                          *
611
 *  And then we try to see if the checking piece can be     *
612
 *  captured by a friendly pawn.                            *
613
 *                                                          *
614
 ************************************************************
615
 */
33 pmbaty 616
    targetc = Occupied(enemy) | EnPassantTarget(ply);
617
    targetc = targetc & target;
618
    if (Pawns(enemy) & target & ((side) ? EnPassantTarget(ply) >> 8 :
619
            EnPassantTarget(ply) << 8))
620
      targetc = targetc | EnPassantTarget(ply);
621
    if (side) {
622
      pcapturesl = (Pawns(white) & mask_left_edge) << 7 & targetc;
623
      pcapturesr = (Pawns(white) & mask_right_edge) << 9 & targetc;
624
    } else {
625
      pcapturesl = (Pawns(black) & mask_left_edge) >> 9 & targetc;
626
      pcapturesr = (Pawns(black) & mask_right_edge) >> 7 & targetc;
627
    }
628
    for (; pcapturesl; Clear(to, pcapturesl)) {
108 pmbaty 629
      to = MostAdvanced(side, pcapturesl);
33 pmbaty 630
      if (!PinnedOnKing(tree, side, to + capleft[side])) {
631
        common = (to + capleft[side]) | (to << 6) | (pawn << 12);
632
        if ((side) ? to < 56 : to > 7)
633
          *move++ = common | (((PcOnSq(to)) ? Abs(PcOnSq(to)) : pawn) << 15);
634
        else {
635
          *move++ = common | Abs(PcOnSq(to)) << 15 | queen << 18;
636
          *move++ = common | Abs(PcOnSq(to)) << 15 | knight << 18;
637
        }
638
      }
639
    }
640
    for (; pcapturesr; Clear(to, pcapturesr)) {
108 pmbaty 641
      to = MostAdvanced(side, pcapturesr);
33 pmbaty 642
      if (!PinnedOnKing(tree, side, to + capright[side])) {
643
        common = (to + capright[side]) | (to << 6) | (pawn << 12);
644
        if ((side) ? to < 56 : to > 7)
645
          *move++ = common | (((PcOnSq(to)) ? Abs(PcOnSq(to)) : pawn) << 15);
646
        else {
647
          *move++ = common | Abs(PcOnSq(to)) << 15 | queen << 18;
648
          *move++ = common | Abs(PcOnSq(to)) << 15 | knight << 18;
649
        }
650
      }
651
    }
652
  }
653
  return move;
654
}
655
 
108 pmbaty 656
/* modified 12/31/15 */
33 pmbaty 657
/*
658
 *******************************************************************************
659
 *                                                                             *
660
 *   GenerateNoncaptures() is used to generate non-capture moves from the      *
661
 *   current position.                                                         *
662
 *                                                                             *
663
 *   Once the valid destination squares are known, we have to locate a         *
108 pmbaty 664
 *   friendly piece to compute the squares it attacks.                         *
33 pmbaty 665
 *                                                                             *
666
 *   Pawns are handled differently.  Regular pawn moves are produced by        *
667
 *   shifting the pawn bitmap 8 bits "forward" and anding this with the        *
108 pmbaty 668
 *   complement of the occupied squares bitmap double advances are then        *
33 pmbaty 669
 *   produced by anding the pawn bitmap with a mask containing 1's on the      *
670
 *   second rank, shifting this 16 bits "forward" and then anding this with    *
671
 *   the complement of the occupied squares bitmap as before.  If [to] reaches *
108 pmbaty 672
 *   the 8th rank, we produce a set of three moves, promoting the pawn to      *
673
 *   knight, bishop and rook (queen promotions were generated earlier by       *
674
 *   GenerateCaptures()).                                                      *
33 pmbaty 675
 *                                                                             *
676
 *******************************************************************************
677
 */
108 pmbaty 678
unsigned *GenerateNoncaptures(TREE * RESTRICT tree, int ply, int side,
679
    unsigned *move) {
33 pmbaty 680
  uint64_t target, piecebd, moves;
681
  uint64_t padvances1, padvances2, pcapturesl, pcapturesr;
682
  int from, to, temp, common, enemy = Flip(side);
683
 
684
/*
685
 ************************************************************
686
 *                                                          *
108 pmbaty 687
 *  First, produce castling moves when they are legal.      *
33 pmbaty 688
 *                                                          *
689
 ************************************************************
690
 */
691
  if (Castle(ply, side) > 0) {
692
    if (Castle(ply, side) & 1 && !(OccupiedSquares & OO[side])
693
        && !Attacks(tree, enemy, OOsqs[side][0])
694
        && !Attacks(tree, enemy, OOsqs[side][1])
695
        && !Attacks(tree, enemy, OOsqs[side][2])) {
696
      *move++ = (king << 12) + (OOto[side] << 6) + OOfrom[side];
697
    }
698
    if (Castle(ply, side) & 2 && !(OccupiedSquares & OOO[side])
699
        && !Attacks(tree, enemy, OOOsqs[side][0])
700
        && !Attacks(tree, enemy, OOOsqs[side][1])
701
        && !Attacks(tree, enemy, OOOsqs[side][2])) {
702
      *move++ = (king << 12) + (OOOto[side] << 6) + OOfrom[side];
703
    }
704
  }
705
  target = ~OccupiedSquares;
706
/*
707
 ************************************************************
708
 *                                                          *
709
 *  We produce knight moves by locating the most advanced   *
710
 *  knight and then using that <from> square as an index    *
711
 *  into the precomputed knight_attacks data.  We repeat    *
712
 *  for each knight.                                        *
713
 *                                                          *
714
 ************************************************************
715
 */
716
  for (piecebd = Knights(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 717
    from = MostAdvanced(side, piecebd);
33 pmbaty 718
    moves = knight_attacks[from] & target;
719
    temp = from + (knight << 12);
720
    Extract(side, move, moves, temp);
721
  }
722
/*
723
 ************************************************************
724
 *                                                          *
108 pmbaty 725
 *  We produce sliding piece moves by locating each piece   *
726
 *  type in turn.  We then start with the most advanced     *
727
 *  piece and generate moves from that square.  This uses   *
728
 *  "magic move generation" to produce the destination      *
729
 *  squares.                                                *
33 pmbaty 730
 *                                                          *
731
 ************************************************************
732
 */
733
  for (piecebd = Bishops(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 734
    from = MostAdvanced(side, piecebd);
33 pmbaty 735
    moves = BishopAttacks(from, OccupiedSquares) & target;
736
    temp = from + (bishop << 12);
737
    Extract(side, move, moves, temp);
738
  }
739
  for (piecebd = Rooks(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 740
    from = MostAdvanced(side, piecebd);
33 pmbaty 741
    moves = RookAttacks(from, OccupiedSquares) & target;
742
    temp = from + (rook << 12);
743
    Extract(side, move, moves, temp);
744
  }
745
  for (piecebd = Queens(side); piecebd; Clear(from, piecebd)) {
108 pmbaty 746
    from = MostAdvanced(side, piecebd);
33 pmbaty 747
    moves = QueenAttacks(from, OccupiedSquares) & target;
748
    temp = from + (queen << 12);
749
    Extract(side, move, moves, temp);
750
  }
751
/*
752
 ************************************************************
753
 *                                                          *
754
 *  We produce king moves by locating the only king and     *
755
 *  then using that <from> square as an index into the      *
756
 *  precomputed king_attacks data.                          *
757
 *                                                          *
758
 ************************************************************
759
 */
760
  from = KingSQ(side);
761
  moves = king_attacks[from] & target;
762
  temp = from + (king << 12);
763
  Extract(side, move, moves, temp);
764
/*
765
 ************************************************************
766
 *                                                          *
767
 *  Now, produce pawn moves.  This is done differently due  *
768
 *  to inconsistencies in the way a pawn moves when it      *
769
 *  captures as opposed to normal non-capturing moves.      *
770
 *  First we generate all possible pawn moves.  We do this  *
771
 *  in 4 operations:  (1) shift the pawns forward one rank  *
772
 *  then and with empty squares;  (2) shift the pawns       *
773
 *  forward two ranks and then and with empty squares;      *
774
 *  (3) remove the a-pawn(s) then shift the pawns           *
775
 *  diagonally left then and with enemy occupied squares;   *
776
 *  (4) remove the h-pawn(s) then shift the pawns           *
777
 *  diagonally right then and with enemy occupied squares.  *
778
 *  note that the only captures produced are under-         *
779
 *  promotions, because the rest were done in GenCap.       *
780
 *                                                          *
781
 ************************************************************
782
 */
783
  padvances1 = ((side) ? Pawns(side) << 8 : Pawns(side) >> 8) & target;
784
  padvances2 =
785
      ((side) ? (padvances1 & mask_advance_2_w) << 8 : (padvances1 &
786
          mask_advance_2_b) >> 8) & target;
787
/*
788
 ************************************************************
789
 *                                                          *
790
 *  Now that we got 'em, we simply enumerate the to         *
791
 *  squares as before, but in four steps since we have      *
792
 *  four sets of potential moves.                           *
793
 *                                                          *
794
 ************************************************************
795
 */
796
  for (; padvances2; Clear(to, padvances2)) {
108 pmbaty 797
    to = MostAdvanced(side, padvances2);
33 pmbaty 798
    *move++ = (to + pawnadv2[side]) | (to << 6) | (pawn << 12);
799
  }
800
  for (; padvances1; Clear(to, padvances1)) {
108 pmbaty 801
    to = MostAdvanced(side, padvances1);
33 pmbaty 802
    common = (to + pawnadv1[side]) | (to << 6) | (pawn << 12);
803
    if ((side) ? to < 56 : to > 7)
804
      *move++ = common;
805
    else {
806
      *move++ = common | (rook << 18);
807
      *move++ = common | (bishop << 18);
808
      *move++ = common | (knight << 18);
809
    }
810
  }
811
/*
812
 ************************************************************
813
 *                                                          *
108 pmbaty 814
 *  Generate the rest of the promotions here since          *
815
 *  GenerateCaptures() only generated captures or           *
33 pmbaty 816
 *  promotions to a queen.                                  *
817
 *                                                          *
818
 ************************************************************
819
 */
108 pmbaty 820
  target = Occupied(enemy) & rank_mask[rank8[side]];
33 pmbaty 821
  pcapturesl =
822
      ((side) ? (Pawns(white) & mask_left_edge) << 7 : (Pawns(black) &
823
          mask_left_edge) >> 9) & target;
824
  for (; pcapturesl; Clear(to, pcapturesl)) {
108 pmbaty 825
    to = MostAdvanced(side, pcapturesl);
33 pmbaty 826
    common = (to + capleft[side]) | (to << 6) | (pawn << 12);
827
    *move++ = common | (Abs(PcOnSq(to)) << 15) | (rook << 18);
828
    *move++ = common | (Abs(PcOnSq(to)) << 15) | (bishop << 18);
829
    *move++ = common | (Abs(PcOnSq(to)) << 15) | (knight << 18);
830
  }
831
  pcapturesr =
832
      ((side) ? (Pawns(white) & mask_right_edge) << 9 : (Pawns(black) &
833
          mask_right_edge) >> 7) & target;
834
  for (; pcapturesr; Clear(to, pcapturesr)) {
108 pmbaty 835
    to = MostAdvanced(side, pcapturesr);
33 pmbaty 836
    common = (to + capright[side]) | (to << 6) | (pawn << 12);
837
    *move++ = common | (Abs(PcOnSq(to)) << 15) | (rook << 18);
838
    *move++ = common | (Abs(PcOnSq(to)) << 15) | (bishop << 18);
839
    *move++ = common | (Abs(PcOnSq(to)) << 15) | (knight << 18);
840
  }
841
  return move;
842
}
843
 
108 pmbaty 844
/* modified 12/31/15 */
33 pmbaty 845
/*
846
 *******************************************************************************
847
 *                                                                             *
848
 *   PinnedOnKing() is used to determine if the piece on <square> is pinned    *
849
 *   against the king, so that it's illegal to move it.  This is used to cull  *
850
 *   potential moves by GenerateCheckEvasions() so that illegal moves are not  *
851
 *   produced.                                                                 *
852
 *                                                                             *
853
 *******************************************************************************
854
 */
855
int PinnedOnKing(TREE * RESTRICT tree, int side, int square) {
108 pmbaty 856
  int ray, enemy = Flip(side);
33 pmbaty 857
 
858
/*
859
 ************************************************************
860
 *                                                          *
861
 *  First, determine if the piece being moved is on the     *
862
 *  same diagonal, rank or file as the king.  If not, then  *
863
 *  it can't be pinned and we return (0).                   *
864
 *                                                          *
865
 ************************************************************
866
 */
867
  ray = directions[square][KingSQ(side)];
868
  if (!ray)
869
    return 0;
870
/*
871
 ************************************************************
872
 *                                                          *
873
 *  If they are on the same ray, then determine if the king *
874
 *  blocks a bishop attack in one direction from this       *
875
 *  square and a bishop or queen blocks a bishop attack on  *
876
 *  the same diagonal in the opposite direction (or the     *
877
 *  same rank/file for rook/queen.)                         *
878
 *                                                          *
879
 ************************************************************
880
 */
881
  switch (Abs(ray)) {
882
    case 1:
883
      if (RankAttacks(square) & Kings(side))
884
        return (RankAttacks(square) & (Rooks(enemy) | Queens(enemy))) != 0;
885
      else
886
        return 0;
887
    case 7:
888
      if (Diagh1Attacks(square) & Kings(side))
889
        return (Diagh1Attacks(square) & (Bishops(enemy) | Queens(enemy))) !=
890
            0;
891
      else
892
        return 0;
893
    case 8:
894
      if (FileAttacks(square) & Kings(side))
895
        return (FileAttacks(square) & (Rooks(enemy) | Queens(enemy))) != 0;
896
      else
897
        return 0;
898
    case 9:
899
      if (Diaga1Attacks(square) & Kings(side))
900
        return (Diaga1Attacks(square) & (Bishops(enemy) | Queens(enemy))) !=
901
            0;
902
      else
903
        return 0;
904
  }
905
  return 0;
906
}