Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
112 pmbaty 1
/*
2
    Protector -- a UCI chess engine
3
 
4
    Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)
5
 
6
    This program is free software: you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation, either version 3 of the License, or
9
    (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 
19
*/
20
 
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <assert.h>
25
#include <math.h>
26
#include "movegeneration.h"
27
#include "evaluation.h"
28
#include "fen.h"
29
#include "io.h"
30
#include "hash.h"
31
#include "evaluation.h"
32
 
33
#define PAWN_FOR_KNIGHT basicValue[BLACK_PAWN] - basicValue[WHITE_KNIGHT]
34
#define PAWN_FOR_BISHOP basicValue[BLACK_PAWN] - basicValue[WHITE_BISHOP]
35
 
36
int pieceOrder[16], promotionPieceValue[16];
37
MovegenerationStage moveGenerationStage[100];
38
int MG_SCHEME_STANDARD, MG_SCHEME_ESCAPE, MG_SCHEME_CHECKS,
39
   MG_SCHEME_QUIESCENCE_WITH_CHECKS, MG_SCHEME_QUIESCENCE, MG_SCHEME_CAPTURES;
40
const Move NO_MOVE = (B4 << 6) | A1;    /* (a1-b4 is always an illegal move) */
41
const Move NULLMOVE = 0;
42
const int VALUEOFFSET_PROMOTION_TO_QUEEN = 4000;
43
const int VALUEOFFSET_HISTORY_MOVE = 24000;
44
const int VALUEOFFSET_BAD_MOVE = 28000;
45
 
46
/**
47
 * Register the specified killermove.
48
 */
49
void registerKillerMove(PlyInfo * plyInfo, Move killerMove)
50
{
51
   if (plyInfo->killerMove1 != killerMove)
52
   {
53
      plyInfo->killerMove2 = plyInfo->killerMove1;
54
      plyInfo->killerMove1 = killerMove;
55
   }
56
}
57
 
58
/**
59
 * Test if the passive king can be captured.
60
 */
61
bool passiveKingIsSafe(Position * position)
62
{
63
   return (bool)
64
      (getDirectAttackers(position,
65
                          position->king[opponent(position->activeColor)],
66
                          position->activeColor,
67
                          position->allPieces) == EMPTY_BITBOARD);
68
}
69
 
70
/**
71
 * Test if the active king is safe (i.e. not in check).
72
 */
73
bool activeKingIsSafe(Position * position)
74
{
75
   return (bool)
76
      (getDirectAttackers(position,
77
                          position->king[position->activeColor],
78
                          opponent(position->activeColor),
79
                          position->allPieces) == EMPTY_BITBOARD);
80
}
81
 
82
int seeMove(Position * position, const Move move)
83
{
84
   const Square to = getToSquare(move);
85
   const Piece targetPiece = position->piece[to];
86
   const Bitboard all = position->allPieces;
87
   const Square enPassantSquare = position->enPassantSquare;
88
   int result;
89
   Bitboard attackers[2];
90
 
91
   attackers[WHITE] =
92
      getDirectAttackers(position, to, WHITE, position->allPieces);
93
   attackers[BLACK] =
94
      getDirectAttackers(position, to, BLACK, position->allPieces);
95
 
96
   result = seeMoveRec(position, move, attackers, VALUE_MATED);
97
   position->enPassantSquare = enPassantSquare;
98
   position->allPieces = all;
99
   position->piece[to] = targetPiece;
100
 
101
   return result;
102
}
103
 
104
/**
105
 * Compare the value of the two specified moves.
106
 */
107
int compareMoves(const void *move1, const void *move2)
108
{
109
   return getMoveValue(*((Move *) move2)) - getMoveValue(*((Move *) move1));
110
}
111
 
112
/**
113
 * Sort the specified movelist.
114
 */
115
void sortMoves(Movelist * movelist)
116
{
117
   qsort(&(movelist->moves[0]), movelist->numberOfMoves,
118
         sizeof(Move), compareMoves);
119
}
120
 
121
/**
122
 * Initialize the specified movelist for quiescence move generation.
123
 */
124
void initQuiescenceMovelist(Movelist * movelist,
125
                            Position * position, PlyInfo * plyInfo,
126
                            UINT16 * historyValue, const Move hashMove,
127
                            const int restDepth, const bool check)
128
{
129
   movelist->position = position;
130
   movelist->plyInfo = plyInfo;
131
   movelist->historyValue = historyValue;
132
   movelist->nextMove = movelist->numberOfPieces = 0;
133
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
134
   movelist->hashMove = hashMove;
135
   movelist->killer1Executed = movelist->killer2Executed = FALSE;
136
   movelist->killer3Executed = movelist->killer4Executed = FALSE;
137
   movelist->killer5Executed = movelist->killer6Executed = FALSE;
138
 
139
   if (check)
140
   {
141
      movelist->currentStage = MG_SCHEME_ESCAPE;
142
   }
143
   else
144
   {
145
      movelist->currentStage =
146
         (restDepth >= 0 ?
147
          MG_SCHEME_QUIESCENCE_WITH_CHECKS : MG_SCHEME_QUIESCENCE);
148
   }
149
 
150
   if (hashMove != NO_MOVE)
151
   {
152
      movelist->moves[movelist->numberOfMoves++] = hashMove;
153
   }
154
}
155
 
156
/**
157
 * Initialize the specified movelist for capture move generation.
158
 */
159
void initCaptureMovelist(Movelist * movelist,
160
                         Position * position, PlyInfo * plyInfo,
161
                         UINT16 * historyValue, const Move hashMove,
162
                         const bool check)
163
{
164
   movelist->position = position;
165
   movelist->plyInfo = plyInfo;
166
   movelist->historyValue = historyValue;
167
   movelist->nextMove = movelist->numberOfPieces = 0;
168
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
169
   movelist->hashMove = hashMove;
170
   movelist->killer1Executed = movelist->killer2Executed = FALSE;
171
   movelist->killer3Executed = movelist->killer4Executed = FALSE;
172
   movelist->killer5Executed = movelist->killer6Executed = FALSE;
173
 
174
   if (check)
175
   {
176
      movelist->currentStage = MG_SCHEME_ESCAPE;
177
   }
178
   else
179
   {
180
      movelist->currentStage = MGS_GOOD_CAPTURES;
181
   }
182
 
183
   if (hashMove != NO_MOVE)
184
   {
185
      movelist->moves[movelist->numberOfMoves++] = hashMove;
186
   }
187
}
188
 
189
/**
190
 * Initialize the specified movelist for standard move generation.
191
 */
192
void initStandardMovelist(Movelist * movelist, Position * position,
193
                          PlyInfo * plyInfo, UINT16 * historyValue,
194
                          const Move hashMove, const bool check)
195
{
196
   movelist->position = position;
197
   movelist->plyInfo = plyInfo;
198
   movelist->historyValue = historyValue;
199
   movelist->nextMove = movelist->numberOfPieces = 0;
200
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
201
   movelist->hashMove = hashMove;
202
 
203
   if (check)
204
   {
205
      movelist->currentStage = MG_SCHEME_ESCAPE;
206
   }
207
   else
208
   {
209
      movelist->currentStage = MG_SCHEME_STANDARD;
210
 
211
      if (hashMove != NO_MOVE)
212
      {
213
         movelist->moves[movelist->numberOfMoves++] = hashMove;
214
      }
215
   }
216
}
217
 
218
/**
219
 * Initialize the specified movelist for check move generation.
220
 */
221
void initCheckMovelist(Movelist * movelist, Position * position,
222
                       UINT16 * historyValue)
223
{
224
   movelist->position = position;
225
   movelist->plyInfo = 0;
226
   movelist->historyValue = historyValue;
227
   movelist->nextMove = movelist->numberOfPieces = 0;
228
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
229
   movelist->hashMove = NO_MOVE;
230
   movelist->currentStage = MG_SCHEME_CHECKS;
231
   movelist->killer1Executed = movelist->killer2Executed = FALSE;
232
   movelist->killer3Executed = movelist->killer4Executed = FALSE;
233
   movelist->killer5Executed = movelist->killer6Executed = FALSE;
234
}
235
 
236
/**
237
 * Initialize the specified movelist for move insertion.
238
 */
239
void initMovelist(Movelist * movelist, Position * position)
240
{
241
   movelist->position = position;
242
   movelist->plyInfo = 0;
243
   movelist->historyValue = 0;
244
   movelist->nextMove = movelist->numberOfPieces = 0;
245
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
246
   movelist->hashMove = NO_MOVE;
247
   movelist->currentStage = MG_SCHEME_CHECKS;
248
   movelist->killer1Executed = movelist->killer2Executed = FALSE;
249
   movelist->killer3Executed = movelist->killer4Executed = FALSE;
250
   movelist->killer5Executed = movelist->killer6Executed = FALSE;
251
}
252
 
253
Move getNextMove(Movelist * movelist)
254
{
255
   do
256
   {
257
      if (movelist->nextMove < movelist->numberOfMoves)
258
      {
259
         switch (moveGenerationStage[movelist->currentStage])
260
         {
261
         case MGS_GOOD_CAPTURES_AND_PROMOTIONS:
262
         case MGS_GOOD_CAPTURES_AND_PROMOTIONS_PURE:
263
         case MGS_GOOD_CAPTURES:
264
            {
265
               const Move move = movelist->moves[movelist->nextMove++];
266
 
267
               if (basicValue[movelist->position->piece[getFromSquare(move)]]
268
                   > basicValue[movelist->position->piece[getToSquare(move)]]
269
                   && seeMove(movelist->position, move) < 0)
270
               {
271
                  movelist->badCaptures[movelist->numberOfBadCaptures++] =
272
                     move;
273
 
274
                  continue;
275
               }
276
 
277
               return move;
278
            }
279
 
280
         case MGS_SAFE_CHECKS:
281
            {
282
               const Move move = movelist->moves[movelist->nextMove++];
283
 
284
               if (seeMove(movelist->position, move) < 0)
285
               {
286
                  continue;
287
               }
288
 
289
               return move;
290
            }
291
 
292
         default:
293
 
294
            return movelist->moves[movelist->nextMove++];
295
         }
296
      }
297
      else
298
      {
299
         Position *position;
300
         Move killer1, killer2, killer3, killer4, killer5, killer6;
301
 
302
         switch (moveGenerationStage[++movelist->currentStage])
303
         {
304
         case MGS_GOOD_CAPTURES_AND_PROMOTIONS:
305
            generateSpecialMoves(movelist);
306
            break;
307
 
308
         case MGS_GOOD_CAPTURES_AND_PROMOTIONS_PURE:
309
            generateSpecialMovesPure(movelist);
310
            break;
311
 
312
         case MGS_GOOD_CAPTURES:
313
            generateCaptures(movelist);
314
            break;
315
 
316
         case MGS_KILLER_MOVES:
317
            movelist->killer1Executed = movelist->killer2Executed = FALSE;
318
            movelist->killer3Executed = movelist->killer4Executed = FALSE;
319
            movelist->numberOfMoves = movelist->nextMove = 0;
320
            position = movelist->position;
321
            killer1 = movelist->plyInfo->killerMove1;
322
            killer2 = movelist->plyInfo->killerMove2;
323
            killer3 = movelist->plyInfo->killerMove3;
324
            killer4 = movelist->plyInfo->killerMove4;
325
            killer5 = movelist->plyInfo->killerMove5;
326
            killer6 = movelist->plyInfo->killerMove6;
327
 
328
            if (moveIsPseudoLegal(position, killer1) &&
329
                position->piece[getToSquare(killer1)] == NO_PIECE &&
330
                position->piece[getFromSquare(killer1)] ==
331
                (Piece) getMoveValue(killer1) &&
332
                (pieceType(position->piece[getFromSquare(killer1)]) != PAWN ||
333
                 getToSquare(killer1) != position->enPassantSquare) &&
334
                movesAreEqual(killer1, movelist->hashMove) == FALSE)
335
            {
336
               setMoveValue(&killer1, 6);
337
               movelist->moves[movelist->numberOfMoves++] = killer1;
338
               movelist->killer1Executed = TRUE;
339
            }
340
 
341
            if (moveIsPseudoLegal(position, killer2) &&
342
                position->piece[getToSquare(killer2)] == NO_PIECE &&
343
                position->piece[getFromSquare(killer2)] ==
344
                (Piece) getMoveValue(killer2) &&
345
                (pieceType(position->piece[getFromSquare(killer2)]) != PAWN ||
346
                 getToSquare(killer2) != position->enPassantSquare) &&
347
                movesAreEqual(killer2, movelist->hashMove) == FALSE)
348
            {
349
               setMoveValue(&killer2, 5);
350
               movelist->moves[movelist->numberOfMoves++] = killer2;
351
               movelist->killer2Executed = TRUE;
352
            }
353
 
354
            if (moveIsPseudoLegal(position, killer3) &&
355
                position->piece[getToSquare(killer3)] == NO_PIECE &&
356
                position->piece[getFromSquare(killer3)] ==
357
                (Piece) getMoveValue(killer3) &&
358
                (pieceType(position->piece[getFromSquare(killer3)]) != PAWN ||
359
                 getToSquare(killer3) != position->enPassantSquare) &&
360
                movesAreEqual(killer3, movelist->hashMove) == FALSE &&
361
                movesAreEqual(killer3, killer1) == FALSE &&
362
                movesAreEqual(killer3, killer2) == FALSE)
363
            {
364
               setMoveValue(&killer3, 4);
365
               movelist->moves[movelist->numberOfMoves++] = killer3;
366
               movelist->killer3Executed = TRUE;
367
            }
368
 
369
            if (moveIsPseudoLegal(position, killer4) &&
370
                position->piece[getToSquare(killer4)] == NO_PIECE &&
371
                position->piece[getFromSquare(killer4)] ==
372
                (Piece) getMoveValue(killer4) &&
373
                (pieceType(position->piece[getFromSquare(killer4)]) != PAWN ||
374
                 getToSquare(killer4) != position->enPassantSquare) &&
375
                movesAreEqual(killer4, movelist->hashMove) == FALSE &&
376
                movesAreEqual(killer4, killer1) == FALSE &&
377
                movesAreEqual(killer4, killer2) == FALSE)
378
            {
379
               setMoveValue(&killer4, 3);
380
               movelist->moves[movelist->numberOfMoves++] = killer4;
381
               movelist->killer4Executed = TRUE;
382
            }
383
 
384
            if (moveIsPseudoLegal(position, killer5) &&
385
                position->piece[getToSquare(killer5)] == NO_PIECE &&
386
                position->piece[getFromSquare(killer5)] ==
387
                (Piece) getMoveValue(killer5) &&
388
                (pieceType(position->piece[getFromSquare(killer5)]) != PAWN ||
389
                 getToSquare(killer5) != position->enPassantSquare) &&
390
                movesAreEqual(killer5, movelist->hashMove) == FALSE &&
391
                movesAreEqual(killer5, killer1) == FALSE &&
392
                movesAreEqual(killer5, killer2) == FALSE &&
393
                movesAreEqual(killer5, killer3) == FALSE &&
394
                movesAreEqual(killer5, killer4) == FALSE)
395
            {
396
               setMoveValue(&killer5, 2);
397
               movelist->moves[movelist->numberOfMoves++] = killer5;
398
               movelist->killer5Executed = TRUE;
399
            }
400
 
401
            if (moveIsPseudoLegal(position, killer6) &&
402
                position->piece[getToSquare(killer6)] == NO_PIECE &&
403
                position->piece[getFromSquare(killer6)] ==
404
                (Piece) getMoveValue(killer6) &&
405
                (pieceType(position->piece[getFromSquare(killer6)]) != PAWN ||
406
                 getToSquare(killer6) != position->enPassantSquare) &&
407
                movesAreEqual(killer6, movelist->hashMove) == FALSE &&
408
                movesAreEqual(killer6, killer1) == FALSE &&
409
                movesAreEqual(killer6, killer2) == FALSE &&
410
                movesAreEqual(killer6, killer3) == FALSE &&
411
                movesAreEqual(killer6, killer4) == FALSE)
412
            {
413
               setMoveValue(&killer6, 1);
414
               movelist->moves[movelist->numberOfMoves++] = killer6;
415
               movelist->killer6Executed = TRUE;
416
            }
417
 
418
            break;
419
 
420
         case MGS_REST:
421
            generateRestMoves(movelist);
422
            break;
423
 
424
         case MGS_BAD_CAPTURES:
425
            movelist->numberOfMoves = movelist->numberOfBadCaptures;
426
            movelist->nextMove = 0;
427
            memmove(&movelist->moves[0],
428
                    &movelist->badCaptures[0],
429
                    movelist->numberOfMoves * sizeof(Move));
430
            break;
431
 
432
         case MGS_ESCAPES:
433
            generateEscapes(movelist);
434
            break;
435
 
436
         case MGS_SAFE_CHECKS:
437
            generateChecks(movelist, FALSE);
438
            break;
439
 
440
         case MGS_CHECKS:
441
            generateChecks(movelist, TRUE);
442
            break;
443
 
444
         case MGS_DANGEROUS_PAWN_ADVANCES:
445
            generateDangerousPawnAdvances(movelist);
446
            break;
447
 
448
         default:
449
            break;
450
         }
451
      }
452
   }
453
   while (moveGenerationStage[movelist->currentStage] != MGS_FINISHED);
454
 
455
   return NO_MOVE;
456
}
457
 
458
bool moveIsPseudoLegal(const Position * position, const Move move)
459
{
460
   const Square from = getFromSquare(move), to = getToSquare(move);
461
   const Piece newPiece = getNewPiece(move);
462
   Piece piece;
463
   Bitboard moves;
464
 
465
   if (squareIsValid(from) == FALSE || squareIsValid(to) == FALSE ||
466
       (piece = position->piece[from]) == NO_PIECE ||
467
       pieceColor(piece) != position->activeColor)
468
   {
469
      return FALSE;
470
   }
471
 
472
   if (pieceType(position->piece[from]) == PAWN &&
473
       colorRank(position->activeColor, from) == RANK_7)
474
   {
475
      if (newPiece != WHITE_QUEEN && newPiece != WHITE_ROOK &&
476
          newPiece != WHITE_BISHOP && newPiece != WHITE_KNIGHT)
477
      {
478
         return FALSE;
479
      }
480
   }
481
   else
482
   {
483
      if (newPiece != NO_PIECE)
484
      {
485
         return FALSE;
486
      }
487
   }
488
 
489
   if (pieceType(position->piece[from]) == PAWN &&
490
       position->enPassantSquare != NO_SQUARE)
491
   {
492
      Bitboard allPieces = position->allPieces |
493
         minValue[position->enPassantSquare];
494
 
495
      moves = getMoves(from, piece, allPieces);
496
   }
497
   else
498
   {
499
      moves = getMoves(from, piece, position->allPieces);
500
   }
501
 
502
   excludeSquares(moves, position->piecesOfColor[position->activeColor]);
503
 
504
   if (pieceType(piece) == KING &&
505
       hasCastlings(position->activeColor, position->castlingRights))
506
   {
507
      moves |= getCastlingMoves(position->activeColor,
508
                                position->castlingRights,
509
                                position->allPieces);
510
   }
511
 
512
   return (bool) testSquare(moves, to);
513
}
514
 
515
bool moveIsLegal(const Position * position, const Move move)
516
{
517
   bool result = FALSE;
518
   Variation variation;
519
 
520
   if (moveIsPseudoLegal(position, move) == FALSE)
521
   {
522
      return FALSE;
523
   }
524
 
525
   setBasePosition(&variation, position);
526
 
527
   if (makeMove(&variation, move) == 0 &&
528
       passiveKingIsSafe(&variation.singlePosition))
529
   {
530
      result = TRUE;
531
   }
532
 
533
   unmakeLastMove(&variation);
534
 
535
   return result;
536
}
537
 
538
static Bitboard getPinnedPieces(const Position * position,
539
                                const Color pinningColor)
540
{
541
   const Square kingSquare = position->king[opponent(pinningColor)];
542
   Bitboard pinnedPieces = EMPTY_BITBOARD, pinningCandidates =
543
      (generalMoves[ROOK][kingSquare] &
544
       (position->piecesOfType[QUEEN | pinningColor] |
545
        position->piecesOfType[ROOK | pinningColor])) |
546
      (generalMoves[BISHOP][kingSquare] &
547
       (position->piecesOfType[QUEEN | pinningColor] |
548
        position->piecesOfType[BISHOP | pinningColor]));
549
   Square pinningCandidate;
550
 
551
   ITERATE_BITBOARD(&pinningCandidates, pinningCandidate)
552
   {
553
      const Bitboard imSquares = squaresBetween[kingSquare][pinningCandidate];
554
 
555
      if ((imSquares & position->piecesOfColor[pinningColor]) ==
556
          EMPTY_BITBOARD)
557
      {
558
         const Bitboard pinnedCandidates = imSquares &
559
            position->piecesOfColor[opponent(pinningColor)];
560
 
561
         if (getNumberOfSetSquares(pinnedCandidates) == 1)
562
         {
563
            pinnedPieces |= pinnedCandidates;
564
         }
565
      }
566
   }
567
 
568
   return pinnedPieces;
569
}
570
 
571
int getNumberOfPieceMoves(const Position * position, const Color color,
572
                          const int sufficientNumberOfMoves)
573
{
574
   const Color oppColor = opponent(color);
575
   const Bitboard unpinnedPieces = ~getPinnedPieces(position, oppColor);
576
   const Bitboard permittedSquares = ~position->piecesOfColor[color];
577
   int numberOfMoves = 0;
578
   Square square;
579
   Bitboard moves, pieces = position->piecesOfColor[color] &
580
      ~(position->piecesOfType[PAWN | color] |
581
        minValue[position->king[color]]) & unpinnedPieces;
582
 
583
   ITERATE_BITBOARD(&pieces, square)
584
   {
585
      switch (pieceType(position->piece[square]))
586
      {
587
      case QUEEN:
588
         moves =
589
            getMagicQueenMoves(square,
590
                               position->allPieces) & permittedSquares;
591
         break;
592
 
593
      case ROOK:
594
         moves =
595
            getMagicRookMoves(square, position->allPieces) & permittedSquares;
596
         break;
597
 
598
      case BISHOP:
599
         moves =
600
            getMagicBishopMoves(square,
601
                                position->allPieces) & permittedSquares;
602
         break;
603
 
604
      case KNIGHT:
605
         moves = getKnightMoves(square) & permittedSquares;
606
         break;
607
 
608
      default:
609
         moves = EMPTY_BITBOARD;
610
      }
611
 
612
      numberOfMoves += getNumberOfSetSquares(moves);
613
 
614
      if (numberOfMoves >= sufficientNumberOfMoves)
615
      {
616
         return numberOfMoves;
617
      }
618
   }
619
 
620
   return numberOfMoves;
621
}
622
 
623
int seeMoveRec(Position * position, const Move move,
624
               Bitboard attackers[2], const int minValue)
625
{
626
   const Square from = getFromSquare(move), to = getToSquare(move);
627
   const Color activeColor = pieceColor(position->piece[from]);
628
   const Color passiveColor = opponent(activeColor);
629
   int valueCaptured = basicValue[position->piece[to]];
630
   Piece leastValuableAttacker, bestNewPiece;
631
   Bitboard leastValuableAttackers;
632
   Move bestCapture;
633
   int recResult;
634
 
635
   if (pieceType(position->piece[to]) == KING)
636
   {
637
      return valueCaptured;
638
   }
639
 
640
   position->piece[to] = position->piece[from];
641
   clearSquare(position->allPieces, from);
642
   clearSquare(attackers[activeColor], from);
643
 
644
   if (horizontalDistance(to, from) == verticalDistance(to, from))
645
   {
646
      attackers[WHITE] |=
647
         getMagicBishopMoves(to, position->allPieces) &
648
         (position->piecesOfType[WHITE_QUEEN] |
649
          position->piecesOfType[WHITE_BISHOP]) & position->allPieces;
650
      attackers[BLACK] |=
651
         getMagicBishopMoves(to, position->allPieces) &
652
         (position->piecesOfType[BLACK_QUEEN] |
653
          position->piecesOfType[BLACK_BISHOP]) & position->allPieces;
654
   }
655
   else
656
   {
657
      attackers[WHITE] |=
658
         getMagicRookMoves(to, position->allPieces) &
659
         (position->piecesOfType[WHITE_QUEEN] |
660
          position->piecesOfType[WHITE_ROOK]) & position->allPieces;
661
      attackers[BLACK] |=
662
         getMagicRookMoves(to, position->allPieces) &
663
         (position->piecesOfType[BLACK_QUEEN] |
664
          position->piecesOfType[BLACK_ROOK]) & position->allPieces;
665
   }
666
 
667
   if (to == position->enPassantSquare &&
668
       pieceType(position->piece[to]) == PAWN)
669
   {
670
      const Square captureSquare = (Square)
671
         (to + (rank(from) - rank(to)) * 8);
672
 
673
      clearSquare(position->allPieces, captureSquare);
674
      attackers[WHITE] |= getMagicBishopMoves(to, position->allPieces) &
675
         (position->piecesOfType[WHITE_QUEEN] |
676
          position->piecesOfType[WHITE_BISHOP]) & position->allPieces;
677
      attackers[WHITE] |= getMagicRookMoves(to, position->allPieces) &
678
         (position->piecesOfType[WHITE_QUEEN] |
679
          position->piecesOfType[WHITE_ROOK]) & position->allPieces;
680
      attackers[BLACK] |= getMagicBishopMoves(to, position->allPieces) &
681
         (position->piecesOfType[BLACK_QUEEN] |
682
          position->piecesOfType[BLACK_BISHOP]) & position->allPieces;
683
      attackers[BLACK] |= getMagicRookMoves(to, position->allPieces) &
684
         (position->piecesOfType[BLACK_QUEEN] |
685
          position->piecesOfType[BLACK_ROOK]) & position->allPieces;
686
 
687
      valueCaptured += basicValue[position->piece[captureSquare]];
688
   }
689
 
690
   if (getNewPiece(move) != NO_PIECE)
691
   {
692
      valueCaptured += basicValue[getNewPiece(move) | activeColor] -
693
         basicValue[PAWN | activeColor];
694
      position->piece[to] = (Piece) (getNewPiece(move) | activeColor);
695
   }
696
 
697
   if (attackers[passiveColor] == EMPTY_BITBOARD)
698
   {
699
      return valueCaptured;
700
   }
701
 
702
   position->enPassantSquare = NO_SQUARE;
703
 
704
   if (attackers[passiveColor] & position->piecesOfType[PAWN | passiveColor])
705
   {
706
      leastValuableAttacker = (Piece) (PAWN | passiveColor);
707
   }
708
   else if (attackers[passiveColor] &
709
            position->piecesOfType[KNIGHT | passiveColor])
710
   {
711
      leastValuableAttacker = (Piece) (KNIGHT | passiveColor);
712
   }
713
   else if (attackers[passiveColor] &
714
            position->piecesOfType[BISHOP | passiveColor])
715
   {
716
      leastValuableAttacker = (Piece) (BISHOP | passiveColor);
717
   }
718
   else if (attackers[passiveColor] &
719
            position->piecesOfType[ROOK | passiveColor])
720
   {
721
      leastValuableAttacker = (Piece) (ROOK | passiveColor);
722
   }
723
   else if (attackers[passiveColor] &
724
            position->piecesOfType[QUEEN | passiveColor])
725
   {
726
      leastValuableAttacker = (Piece) (QUEEN | passiveColor);
727
   }
728
   else
729
   {
730
      leastValuableAttacker = (Piece) (KING | passiveColor);
731
   }
732
 
733
   leastValuableAttackers =
734
      attackers[passiveColor] & position->piecesOfType[leastValuableAttacker];
735
 
736
   if ((leastValuableAttacker == WHITE_PAWN && rank(to) == RANK_8) ||
737
       (leastValuableAttacker == BLACK_PAWN && rank(to) == RANK_1))
738
   {
739
      bestNewPiece = WHITE_QUEEN;
740
   }
741
   else
742
   {
743
      bestNewPiece = NO_PIECE;
744
   }
745
 
746
   bestCapture =
747
      getMove(getLastSquare(&leastValuableAttackers), to, bestNewPiece, 0);
748
 
749
   recResult = seeMoveRec(position, bestCapture, attackers, 0);
750
 
751
   /*
752
      logDebug("valueCaptured = %d\n", valueCaptured);
753
      logDebug("recResult = %d\n", recResult);
754
      logDebug("returnValue = %d\n", max(minValue, valueCaptured - recResult));
755
    */
756
 
757
   return max(minValue, valueCaptured - recResult);
758
}
759
 
760
void getLegalMoves(Variation * variation, Movelist * movelist)
761
{
762
   const int ply = variation->ply;
763
   Position *position = &variation->singlePosition;
764
   PlyInfo *plyInfo = &variation->plyInfo[ply];
765
   Movelist allMoves;
766
   Move hashmove = NO_MOVE;
767
   Move currentMove;
768
 
769
   allMoves.positionalGain = &(variation->positionalGain[0]);
770
   initMovelist(movelist, position);
771
 
772
   plyInfo->killerMove1 = NO_MOVE;
773
   plyInfo->killerMove2 = NO_MOVE;
774
   plyInfo->killerMove3 = NO_MOVE;
775
   plyInfo->killerMove4 = NO_MOVE;
776
   plyInfo->killerMove5 = NO_MOVE;
777
   plyInfo->killerMove6 = NO_MOVE;
778
 
779
   initStandardMovelist(&allMoves, position,
780
                        plyInfo, &variation->historyValue[0],
781
                        hashmove, FALSE);
782
 
783
   while ((currentMove = getNextMove(&allMoves)) != NO_MOVE)
784
   {
785
      if (moveIsLegal(position, currentMove))
786
      {
787
         movelist->moves[movelist->numberOfMoves++] = currentMove;
788
      }
789
   }
790
 
791
   sortMoves(movelist);
792
}
793
 
794
Gameresult getGameresult(Variation * variation)
795
{
796
   Movelist movelist;
797
   Gameresult result;
798
   Position *pos = &variation->singlePosition;
799
   int i, repetitionCount = 0, historyLimit;
800
 
801
   /* Check for a draw by repetition */
802
 
803
   historyLimit = POSITION_HISTORY_OFFSET - pos->halfMoveClock;
804
 
805
   for (i = POSITION_HISTORY_OFFSET - 4; i >= historyLimit; i -= 2)
806
   {
807
      if (pos->hashKey == variation->positionHistory[i])
808
      {
809
         repetitionCount++;
810
      }
811
   }
812
 
813
   if (repetitionCount >= 2)
814
   {
815
      strcpy(result.result, GAMERESULT_DRAW);
816
      strcpy(result.reason, GAMERESULT_REPETITION);
817
 
818
      return result;
819
   }
820
 
821
   if (pos->halfMoveClock >= 100)
822
   {
823
      strcpy(result.result, GAMERESULT_DRAW);
824
      strcpy(result.reason, GAMERESULT_50_MOVE_RULE);
825
 
826
      return result;
827
   }
828
 
829
   if (pos->numberOfPawns[WHITE] == 0 &&
830
       pos->numberOfPawns[BLACK] == 0 &&
831
       hasWinningPotential(pos, WHITE) == FALSE &&
832
       hasWinningPotential(pos, BLACK) == FALSE)
833
   {
834
      strcpy(result.result, GAMERESULT_DRAW);
835
      strcpy(result.reason, GAMERESULT_INSUFFICIENT_MATERIAL);
836
 
837
      return result;
838
   }
839
 
840
   getLegalMoves(variation, &movelist);
841
 
842
   if (movelist.numberOfMoves > 0)
843
   {
844
      strcpy(result.result, GAMERESULT_UNKNOWN);
845
      strcpy(result.reason, "");
846
   }
847
   else
848
   {
849
      if (activeKingIsSafe(pos))
850
      {
851
         strcpy(result.result, GAMERESULT_DRAW);
852
         strcpy(result.reason, GAMERESULT_STALEMATE);
853
      }
854
      else
855
      {
856
         if (pos->activeColor == WHITE)
857
         {
858
            strcpy(result.result, GAMERESULT_BLACK_WINS);
859
            strcpy(result.reason, GAMERESULT_BLACK_MATES);
860
         }
861
         else
862
         {
863
            strcpy(result.result, GAMERESULT_WHITE_WINS);
864
            strcpy(result.reason, GAMERESULT_WHITE_MATES);
865
         }
866
      }
867
   }
868
 
869
   return result;
870
}
871
 
872
bool listContainsMove(const Movelist * movelist, const Move move)
873
{
874
   int i;
875
   const Move shortMove = move & 0xFFFF;
876
 
877
   for (i = 0; i < movelist->numberOfMoves; i++)
878
   {
879
      if ((movelist->moves[i] & 0xFFFF) == shortMove)
880
      {
881
         return TRUE;
882
      }
883
   }
884
 
885
   return FALSE;
886
}
887
 
888
static void deleteMove(Movelist * movelist, const Move move)
889
{
890
   int i;
891
   const Move shortMove = move & 0xFFFF;
892
 
893
   for (i = 0; i < movelist->numberOfMoves; i++)
894
   {
895
      if ((movelist->moves[i] & 0xFFFF) == shortMove)
896
      {
897
         movelist->numberOfMoves--;
898
 
899
         if (i < movelist->numberOfMoves)
900
         {
901
            memmove(&movelist->moves[i],
902
                    &movelist->moves[i + 1],
903
                    (movelist->numberOfMoves - i) * sizeof(Move));
904
         }
905
 
906
         return;
907
      }
908
   }
909
}
910
 
911
static void setMoveValueInList(Movelist * movelist, const Move move)
912
{
913
   int i;
914
   const Move shortMove = move & 0xFFFF;
915
 
916
   for (i = 0; i < movelist->numberOfMoves; i++)
917
   {
918
      if ((movelist->moves[i] & 0xFFFF) == shortMove)
919
      {
920
         movelist->moves[i] = move;
921
 
922
         return;
923
      }
924
   }
925
}
926
 
927
bool listContainsSimpleMove(Movelist * movelist, const Square from,
928
                            const Square to)
929
{
930
   return listContainsMove(movelist, getPackedMove(from, to, NO_PIECE));
931
}
932
 
933
void initializeMoveValues(Movelist * movelist)
934
{
935
   int i;
936
 
937
   for (i = 0; i < movelist->numberOfMoves; i++)
938
   {
939
      setMoveValue(&movelist->moves[i], VALUE_MATED - 1 - i);
940
   }
941
}
942
 
943
static void addMoveByValue(Movelist * movelist, const Move move)
944
{
945
   int low = -1, high = movelist->numberOfMoves, insertPosition;
946
   const int value = getMoveValue(move);
947
 
948
   while (high - low > 1)
949
   {
950
      const int avg = (low + high) >> 1;
951
 
952
      assert(avg >= 0);
953
      assert(avg < movelist->numberOfMoves);
954
 
955
      if (value <= getMoveValue(movelist->moves[avg]))
956
      {
957
         low = avg;
958
      }
959
      else
960
      {
961
         high = avg;
962
      }
963
   }
964
 
965
   insertPosition = low + 1;
966
 
967
   assert(insertPosition >= 0);
968
   assert(insertPosition <= movelist->numberOfMoves);
969
   assert(insertPosition == 0 ||
970
          value <= getMoveValue(movelist->moves[insertPosition - 1]));
971
 
972
   if (insertPosition < movelist->numberOfMoves)
973
   {
974
      assert(value > getMoveValue(movelist->moves[insertPosition]));
975
 
976
      memmove(&movelist->moves[insertPosition + 1],
977
              &movelist->moves[insertPosition],
978
              (movelist->numberOfMoves - insertPosition) * sizeof(Move));
979
   }
980
 
981
   movelist->moves[insertPosition] = move;
982
   movelist->numberOfMoves++;
983
}
984
 
985
void addMoveAtPosition(Movelist * movelist, const Move move,
986
                       const int insertPosition)
987
{
988
   assert(insertPosition >= 0);
989
   assert(insertPosition <= movelist->numberOfMoves);
990
 
991
   if (insertPosition < movelist->numberOfMoves)
992
   {
993
      memmove(&movelist->moves[insertPosition + 1],
994
              &movelist->moves[insertPosition],
995
              (movelist->numberOfMoves - insertPosition) * sizeof(Move));
996
   }
997
 
998
   movelist->moves[insertPosition] = move;
999
   movelist->numberOfMoves++;
1000
}
1001
 
1002
void deleteMoveAtPosition(Movelist * movelist, const int position)
1003
{
1004
   assert(position >= 0);
1005
   assert(position < movelist->numberOfMoves);
1006
 
1007
   movelist->numberOfMoves--;
1008
 
1009
   if (position < movelist->numberOfMoves)
1010
   {
1011
      memmove(&movelist->moves[position],
1012
              &movelist->moves[position + 1],
1013
              (movelist->numberOfMoves - position) * sizeof(Move));
1014
   }
1015
}
1016
 
1017
static INT16 captureMoveSortValue(const Position * position,
1018
                                  const Square from, const Square to)
1019
{
1020
   return (INT16) (6 * pieceOrder[position->piece[to]] -
1021
                   pieceOrder[position->piece[from]]);
1022
}
1023
 
1024
static INT16 promotionMoveSortValue(const Position * position,
1025
                                    const Square to, const Piece newPiece)
1026
{
1027
   return (INT16) (promotionPieceValue[newPiece] +
1028
                   6 * pieceOrder[position->piece[to]]);
1029
}
1030
 
1031
static INT16 historyMoveSortValue(const Position * position,
1032
                                  const Movelist * movelist, const Move move)
1033
{
1034
   return (INT16) (movelist->historyValue[historyIndex(move, position)] -
1035
                   VALUEOFFSET_HISTORY_MOVE);
1036
}
1037
 
1038
static void addCaptures(Movelist * movelist, const Position * position,
1039
                        const Square from, Bitboard captures)
1040
{
1041
   Square to;
1042
 
1043
   ITERATE_BITBOARD(&captures, to)
1044
   {
1045
      const INT16 value = captureMoveSortValue(position, from, to);
1046
      int i = 0;
1047
 
1048
      movelist->moves[movelist->numberOfMoves] = (value - 1) << 16;
1049
 
1050
      while (getMoveValue(movelist->moves[i]) >= value)
1051
      {
1052
         i++;
1053
      }
1054
 
1055
      if (i < movelist->numberOfMoves)
1056
      {
1057
         memmove(&movelist->moves[i + 1], &movelist->moves[i],
1058
                 (movelist->numberOfMoves - i) * sizeof(Move));
1059
      }
1060
 
1061
      movelist->moves[i] = getMove(from, to, NO_PIECE, value);
1062
      movelist->numberOfMoves++;
1063
   }
1064
}
1065
 
1066
static void addPromotions(Movelist * movelist,
1067
                          const Square from, Bitboard moves)
1068
{
1069
   Square to;
1070
 
1071
   ITERATE_BITBOARD(&moves, to)
1072
   {
1073
      INT16 value;
1074
 
1075
      value = promotionMoveSortValue(movelist->position, to, WHITE_QUEEN);
1076
      addMoveByValue(movelist, getMove(from, to, WHITE_QUEEN, value));
1077
 
1078
      value = promotionMoveSortValue(movelist->position, to, WHITE_ROOK);
1079
      movelist->badCaptures[movelist->numberOfBadCaptures++] =
1080
         getMove(from, to, WHITE_ROOK, value);
1081
 
1082
      value = promotionMoveSortValue(movelist->position, to, WHITE_BISHOP);
1083
      movelist->badCaptures[movelist->numberOfBadCaptures++] =
1084
         getMove(from, to, WHITE_BISHOP, value);
1085
 
1086
      value = promotionMoveSortValue(movelist->position, to, WHITE_KNIGHT);
1087
      movelist->badCaptures[movelist->numberOfBadCaptures++] =
1088
         getMove(from, to, WHITE_KNIGHT, value);
1089
   }
1090
}
1091
 
1092
void deferMove(Movelist * movelist, Move move)
1093
{
1094
   const int targetSpot = min(movelist->numberOfMoves - 1,
1095
                              movelist->nextMove + 1);
1096
 
1097
   if (targetSpot > movelist->nextMove &&
1098
       movelist->numberOfMoves < MAX_MOVES_PER_POSITION - 1)
1099
   {
1100
      int i;
1101
 
1102
      for (i = movelist->numberOfMoves; i > targetSpot; i--)
1103
      {
1104
         movelist->moves[i] = movelist->moves[i - 1];
1105
      }
1106
 
1107
      movelist->moves[targetSpot] = move;
1108
      movelist->numberOfMoves++;
1109
   }
1110
}
1111
 
1112
void generateSpecialMoves(Movelist * movelist)
1113
{
1114
   const Position *position = movelist->position;
1115
   const Color activeColor = position->activeColor;
1116
   const Color passiveColor = opponent(activeColor);
1117
   const Bitboard captureTargets = position->piecesOfColor[passiveColor];
1118
   Bitboard moves =
1119
      EMPTY_BITBOARD, pieces, pawnCaptureTargets, promotionPawns;
1120
   const Square hashFrom = getFromSquare(movelist->hashMove);
1121
   Square from;
1122
 
1123
   movelist->nextMove = 0;
1124
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
1125
   pawnCaptureTargets = captureTargets;
1126
 
1127
   if (position->enPassantSquare != NO_SQUARE)
1128
   {
1129
      setSquare(pawnCaptureTargets, position->enPassantSquare);
1130
   }
1131
 
1132
   pieces = position->piecesOfType[PAWN | activeColor];
1133
   promotionPawns = pieces & promotionCandidates[activeColor];
1134
   pieces &= ~promotionPawns;
1135
 
1136
   ITERATE_BITBOARD(&promotionPawns, from)
1137
   {
1138
      moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
1139
                              pawnCaptureTargets) |
1140
         getPawnAdvances(activeColor, from, position->allPieces);
1141
 
1142
      if (moves != EMPTY_BITBOARD)
1143
      {
1144
         addPromotions(movelist, from, moves);
1145
 
1146
         if (hashFrom == from)
1147
         {
1148
            deleteMove(movelist, movelist->hashMove);
1149
         }
1150
      }
1151
   }
1152
 
1153
   if (position->activeColor == WHITE)
1154
   {
1155
      const Bitboard capturingPawns =
1156
         ((pawnCaptureTargets & nonA) >> 9) |
1157
         ((pawnCaptureTargets & nonH) >> 7);
1158
 
1159
      pieces &= capturingPawns;
1160
   }
1161
   else
1162
   {
1163
      const Bitboard capturingPawns =
1164
         ((pawnCaptureTargets & nonA) << 7) |
1165
         ((pawnCaptureTargets & nonH) << 9);
1166
 
1167
      pieces &= capturingPawns;
1168
   }
1169
 
1170
   ITERATE_BITBOARD(&pieces, from)
1171
   {
1172
      moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
1173
                              pawnCaptureTargets);
1174
 
1175
      if (moves != EMPTY_BITBOARD)
1176
      {
1177
         if (hashFrom == from)
1178
         {
1179
            clearSquare(moves, getToSquare(movelist->hashMove));
1180
         }
1181
 
1182
         addCaptures(movelist, position, from, moves);
1183
      }
1184
   }
1185
 
1186
   pieces = getOrdinaryPieces(position, activeColor);
1187
 
1188
   ITERATE_BITBOARD(&pieces, from)
1189
   {
1190
      switch (pieceType(position->piece[from]))
1191
      {
1192
      case QUEEN:
1193
         moves = getMagicQueenMoves(from, position->allPieces);
1194
         break;
1195
 
1196
      case ROOK:
1197
         moves = getMagicRookMoves(from, position->allPieces);
1198
         break;
1199
 
1200
      case BISHOP:
1201
         moves = getMagicBishopMoves(from, position->allPieces);
1202
         break;
1203
 
1204
      case KNIGHT:
1205
         moves = getKnightMoves(from);
1206
         break;
1207
 
1208
      default:
1209
         break;
1210
      }
1211
 
1212
      if (hashFrom == from)
1213
      {
1214
         clearSquare(moves, getToSquare(movelist->hashMove));
1215
      }
1216
 
1217
      movelist->movesOfPiece[movelist->numberOfPieces].square = from;
1218
      movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
1219
      moves &= captureTargets;
1220
 
1221
      if (moves != EMPTY_BITBOARD)
1222
      {
1223
         addCaptures(movelist, position, from, moves);
1224
      }
1225
   }
1226
 
1227
   moves = getKingMoves(position->king[activeColor]);
1228
 
1229
   if (hasCastlings(position->activeColor, position->castlingRights))
1230
   {
1231
      moves |= getCastlingMoves(position->activeColor,
1232
                                position->castlingRights,
1233
                                position->allPieces);
1234
   }
1235
 
1236
   if (hashFrom == position->king[activeColor])
1237
   {
1238
      clearSquare(moves, getToSquare(movelist->hashMove));
1239
   }
1240
 
1241
   movelist->movesOfPiece[movelist->numberOfPieces].square =
1242
      position->king[activeColor];
1243
   movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
1244
   moves &= captureTargets;
1245
 
1246
   if (moves != EMPTY_BITBOARD)
1247
   {
1248
      addCaptures(movelist, position, position->king[activeColor], moves);
1249
   }
1250
}
1251
 
1252
void generateSpecialMovesPure(Movelist * movelist)
1253
{
1254
   const Position *position = movelist->position;
1255
   const Color activeColor = position->activeColor;
1256
   const Color passiveColor = opponent(activeColor);
1257
   const Bitboard captureTargets = position->piecesOfColor[passiveColor];
1258
   Bitboard moves =
1259
      EMPTY_BITBOARD, pieces, pawnCaptureTargets, promotionPawns;
1260
   const Square hashFrom = getFromSquare(movelist->hashMove);
1261
   Square from;
1262
 
1263
   movelist->nextMove = 0;
1264
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
1265
   pawnCaptureTargets = captureTargets;
1266
 
1267
   if (position->enPassantSquare != NO_SQUARE)
1268
   {
1269
      setSquare(pawnCaptureTargets, position->enPassantSquare);
1270
   }
1271
 
1272
   pieces = position->piecesOfType[(Piece) (PAWN | activeColor)];
1273
   promotionPawns = pieces & promotionCandidates[activeColor];
1274
   pieces &= ~promotionPawns;
1275
 
1276
   ITERATE_BITBOARD(&promotionPawns, from)
1277
   {
1278
      moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
1279
                              pawnCaptureTargets) |
1280
         getPawnAdvances(activeColor, from, position->allPieces);
1281
 
1282
      if (moves != EMPTY_BITBOARD)
1283
      {
1284
         addPromotions(movelist, from, moves);
1285
 
1286
         if (hashFrom == from)
1287
         {
1288
            deleteMove(movelist, movelist->hashMove);
1289
         }
1290
      }
1291
   }
1292
 
1293
   if (position->activeColor == WHITE)
1294
   {
1295
      const Bitboard capturingPawns =
1296
         ((pawnCaptureTargets & nonA) >> 9) |
1297
         ((pawnCaptureTargets & nonH) >> 7);
1298
 
1299
      pieces &= capturingPawns;
1300
   }
1301
   else
1302
   {
1303
      const Bitboard capturingPawns =
1304
         ((pawnCaptureTargets & nonA) << 7) |
1305
         ((pawnCaptureTargets & nonH) << 9);
1306
 
1307
      pieces &= capturingPawns;
1308
   }
1309
 
1310
   ITERATE_BITBOARD(&pieces, from)
1311
   {
1312
      moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
1313
                              pawnCaptureTargets);
1314
 
1315
      if (moves != EMPTY_BITBOARD)
1316
      {
1317
         if (hashFrom == from)
1318
         {
1319
            clearSquare(moves, getToSquare(movelist->hashMove));
1320
         }
1321
 
1322
         addCaptures(movelist, position, from, moves);
1323
      }
1324
   }
1325
 
1326
   pieces = getOrdinaryPieces(position, activeColor);
1327
 
1328
   ITERATE_BITBOARD(&pieces, from)
1329
   {
1330
      switch (pieceType(position->piece[from]))
1331
      {
1332
      case QUEEN:
1333
         moves = getMagicQueenMoves(from, position->allPieces);
1334
         break;
1335
 
1336
      case ROOK:
1337
         moves = getMagicRookMoves(from, position->allPieces);
1338
         break;
1339
 
1340
      case BISHOP:
1341
         moves = getMagicBishopMoves(from, position->allPieces);
1342
         break;
1343
 
1344
      case KNIGHT:
1345
         moves = getKnightMoves(from);
1346
         break;
1347
 
1348
      case KING:
1349
         moves = getKingMoves(position->king[activeColor]);
1350
         break;
1351
 
1352
      default:
1353
         break;
1354
      }
1355
 
1356
      moves &= captureTargets;
1357
 
1358
      if (moves != EMPTY_BITBOARD)
1359
      {
1360
         if (hashFrom == from)
1361
         {
1362
            clearSquare(moves, getToSquare(movelist->hashMove));
1363
         }
1364
 
1365
         if (moves != EMPTY_BITBOARD)
1366
         {
1367
            addCaptures(movelist, position, from, moves);
1368
         }
1369
      }
1370
   }
1371
 
1372
   moves = getKingMoves(position->king[activeColor]) & captureTargets;
1373
 
1374
   if (moves != EMPTY_BITBOARD)
1375
   {
1376
      if (hashFrom == position->king[activeColor])
1377
      {
1378
         clearSquare(moves, getToSquare(movelist->hashMove));
1379
      }
1380
 
1381
      if (moves != EMPTY_BITBOARD)
1382
      {
1383
         addCaptures(movelist, position, position->king[activeColor], moves);
1384
      }
1385
   }
1386
}
1387
 
1388
void generateCaptures(Movelist * movelist)
1389
{
1390
   const Position *position = movelist->position;
1391
   const Color activeColor = position->activeColor;
1392
   const Color passiveColor = opponent(activeColor);
1393
   const Bitboard captureTargets = position->piecesOfColor[passiveColor];
1394
   Bitboard moves =
1395
      EMPTY_BITBOARD, pieces, pawnCaptureTargets, promotionPawns;
1396
   const Square hashFrom = getFromSquare(movelist->hashMove);
1397
   Square from;
1398
 
1399
   movelist->nextMove = 0;
1400
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
1401
   pawnCaptureTargets = captureTargets;
1402
 
1403
   pieces = position->piecesOfType[PAWN | activeColor];
1404
   promotionPawns = pieces & promotionCandidates[activeColor];
1405
   pieces &= ~promotionPawns;
1406
 
1407
   ITERATE_BITBOARD(&promotionPawns, from)
1408
   {
1409
      moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
1410
                              pawnCaptureTargets);
1411
 
1412
      if (moves != EMPTY_BITBOARD)
1413
      {
1414
         addPromotions(movelist, from, moves);
1415
 
1416
         if (hashFrom == from)
1417
         {
1418
            deleteMove(movelist, movelist->hashMove);
1419
         }
1420
      }
1421
   }
1422
 
1423
   if (position->activeColor == WHITE)
1424
   {
1425
      const Bitboard capturingPawns =
1426
         ((pawnCaptureTargets & nonA) >> 9) |
1427
         ((pawnCaptureTargets & nonH) >> 7);
1428
 
1429
      pieces &= capturingPawns;
1430
   }
1431
   else
1432
   {
1433
      const Bitboard capturingPawns =
1434
         ((pawnCaptureTargets & nonA) << 7) |
1435
         ((pawnCaptureTargets & nonH) << 9);
1436
 
1437
      pieces &= capturingPawns;
1438
   }
1439
 
1440
   ITERATE_BITBOARD(&pieces, from)
1441
   {
1442
      moves = getPawnCaptures((Piece) (PAWN | activeColor), from,
1443
                              pawnCaptureTargets);
1444
 
1445
      if (moves != EMPTY_BITBOARD)
1446
      {
1447
         if (hashFrom == from)
1448
         {
1449
            clearSquare(moves, getToSquare(movelist->hashMove));
1450
         }
1451
 
1452
         addCaptures(movelist, position, from, moves);
1453
      }
1454
   }
1455
 
1456
   pieces = getOrdinaryPieces(position, activeColor);
1457
 
1458
   ITERATE_BITBOARD(&pieces, from)
1459
   {
1460
      switch (pieceType(position->piece[from]))
1461
      {
1462
      case QUEEN:
1463
         moves = getMagicQueenMoves(from, position->allPieces);
1464
         break;
1465
 
1466
      case ROOK:
1467
         moves = getMagicRookMoves(from, position->allPieces);
1468
         break;
1469
 
1470
      case BISHOP:
1471
         moves = getMagicBishopMoves(from, position->allPieces);
1472
         break;
1473
 
1474
      case KNIGHT:
1475
         moves = getKnightMoves(from);
1476
         break;
1477
 
1478
      default:
1479
         break;
1480
      }
1481
 
1482
      if (hashFrom == from)
1483
      {
1484
         clearSquare(moves, getToSquare(movelist->hashMove));
1485
      }
1486
 
1487
      movelist->movesOfPiece[movelist->numberOfPieces].square = from;
1488
      movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
1489
      moves &= captureTargets;
1490
 
1491
      if (moves != EMPTY_BITBOARD)
1492
      {
1493
         addCaptures(movelist, position, from, moves);
1494
      }
1495
   }
1496
 
1497
   moves = getKingMoves(position->king[activeColor]);
1498
 
1499
   if (hashFrom == position->king[activeColor])
1500
   {
1501
      clearSquare(moves, getToSquare(movelist->hashMove));
1502
   }
1503
 
1504
   movelist->movesOfPiece[movelist->numberOfPieces].square =
1505
      position->king[activeColor];
1506
   movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
1507
   moves &= captureTargets;
1508
 
1509
   if (moves != EMPTY_BITBOARD)
1510
   {
1511
      addCaptures(movelist, position, position->king[activeColor], moves);
1512
   }
1513
}
1514
 
1515
void generateRestMoves(Movelist * movelist)
1516
{
1517
   const Position *position = movelist->position;
1518
   const Bitboard permittedSquares = ~position->allPieces;
1519
   const Color activeColor = position->activeColor;
1520
   Bitboard pieces = (activeColor == WHITE ?
1521
                      position->piecesOfType[WHITE_PAWN] &
1522
                      ~((position->allPieces >> 8) | squaresOfRank[RANK_7]) :
1523
                      position->piecesOfType[BLACK_PAWN] &
1524
                      ~((position->allPieces << 8) | squaresOfRank[RANK_2]));
1525
   Square from;
1526
   const Square k1from =
1527
      (movelist->killer1Executed ?
1528
       getFromSquare(movelist->plyInfo->killerMove1) : NO_SQUARE);
1529
   const Square k2from =
1530
      (movelist->killer2Executed ?
1531
       getFromSquare(movelist->plyInfo->killerMove2) : NO_SQUARE);
1532
   const Square k3from =
1533
      (movelist->killer3Executed ?
1534
       getFromSquare(movelist->plyInfo->killerMove3) : NO_SQUARE);
1535
   const Square k4from =
1536
      (movelist->killer4Executed ?
1537
       getFromSquare(movelist->plyInfo->killerMove4) : NO_SQUARE);
1538
   const Square k5from =
1539
      (movelist->killer5Executed ?
1540
       getFromSquare(movelist->plyInfo->killerMove5) : NO_SQUARE);
1541
   const Square k6from =
1542
      (movelist->killer6Executed ?
1543
       getFromSquare(movelist->plyInfo->killerMove6) : NO_SQUARE);
1544
   int i;
1545
 
1546
   ITERATE_BITBOARD(&pieces, from)
1547
   {
1548
      Bitboard moves =
1549
         getPawnAdvances(activeColor, from, position->allPieces);
1550
 
1551
      assert(moves != EMPTY_BITBOARD);
1552
 
1553
      if (getFromSquare(movelist->hashMove) == from)
1554
      {
1555
         clearSquare(moves, getToSquare(movelist->hashMove));
1556
      }
1557
 
1558
      movelist->movesOfPiece[movelist->numberOfPieces].square = from;
1559
      movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
1560
   }
1561
 
1562
   movelist->nextMove = 0;
1563
   movelist->numberOfMoves = 0;
1564
 
1565
   for (i = 0; i < movelist->numberOfPieces; i++)
1566
   {
1567
      Bitboard moves = movelist->movesOfPiece[i].moves & permittedSquares;
1568
      UINT8 moveSquares[_64_];
1569
      int numMoves, moveIndex;
1570
 
1571
      from = movelist->movesOfPiece[i].square;
1572
 
1573
      if (from == k1from)
1574
      {
1575
         clearSquare(moves, getToSquare(movelist->plyInfo->killerMove1));
1576
      }
1577
 
1578
      if (from == k2from)
1579
      {
1580
         clearSquare(moves, getToSquare(movelist->plyInfo->killerMove2));
1581
      }
1582
 
1583
      if (from == k3from)
1584
      {
1585
         clearSquare(moves, getToSquare(movelist->plyInfo->killerMove3));
1586
      }
1587
 
1588
      if (from == k4from)
1589
      {
1590
         clearSquare(moves, getToSquare(movelist->plyInfo->killerMove4));
1591
      }
1592
 
1593
      if (from == k5from)
1594
      {
1595
         clearSquare(moves, getToSquare(movelist->plyInfo->killerMove5));
1596
      }
1597
 
1598
      if (from == k6from)
1599
      {
1600
         clearSquare(moves, getToSquare(movelist->plyInfo->killerMove6));
1601
      }
1602
 
1603
      numMoves = getSetSquares(moves, moveSquares);
1604
 
1605
      for (moveIndex = 0; moveIndex < numMoves; moveIndex++)
1606
      {
1607
         Move move = getOrdinaryMove(from, (Square) moveSquares[moveIndex]);
1608
 
1609
         setMoveValue(&move, historyMoveSortValue(position, movelist, move));
1610
         addMoveByValue(movelist, move);
1611
 
1612
         assert(movesAreEqual(move, movelist->hashMove) == FALSE);
1613
      }
1614
   }
1615
}
1616
 
1617
void generateDangerousPawnAdvances(Movelist * movelist)
1618
{
1619
   const Position *position = movelist->position;
1620
   const Color activeColor = position->activeColor;
1621
   const Rank sixthRank = (activeColor == WHITE ? RANK_6 : RANK_3);
1622
   Bitboard moves, pieces = position->piecesOfType[PAWN | activeColor] &
1623
      squaresOfRank[sixthRank];
1624
   Square from;
1625
 
1626
   ITERATE_BITBOARD(&pieces, from)
1627
   {
1628
      if ((moves = getPawnAdvances(activeColor, from, position->allPieces)) !=
1629
          EMPTY_BITBOARD)
1630
      {
1631
         const Square to = getLastSquare(&moves);
1632
         Move move = getPackedMove(from, to, NO_PIECE);
1633
 
1634
         if (move == movelist->hashMove)
1635
         {
1636
            continue;
1637
         }
1638
 
1639
         setMoveValue(&move, historyMoveSortValue(position, movelist, move));
1640
         addMoveByValue(movelist, move);
1641
      }
1642
   }
1643
}
1644
 
1645
void generateChecks(Movelist * movelist, bool allChecks)
1646
{
1647
   Position *position = movelist->position;
1648
   const Color activeColor = position->activeColor;
1649
   const Color passiveColor = opponent(activeColor);
1650
   Bitboard permittedSquares;
1651
   Bitboard moves, orthoChecks, diaChecks, pawnChecks;
1652
   Bitboard pieces = position->piecesOfType[PAWN | activeColor] &
1653
      ~promotionCandidates[activeColor];
1654
   const Square opponentKing = position->king[passiveColor];
1655
   Square from;
1656
   int i;
1657
 
1658
   ITERATE_BITBOARD(&pieces, from)
1659
   {
1660
      if ((moves = getPawnAdvances(activeColor, from, position->allPieces)) !=
1661
          EMPTY_BITBOARD)
1662
      {
1663
         if (getFromSquare(movelist->hashMove) == from)
1664
         {
1665
            clearSquare(moves, getToSquare(movelist->hashMove));
1666
         }
1667
 
1668
         movelist->movesOfPiece[movelist->numberOfPieces].square = from;
1669
         movelist->movesOfPiece[movelist->numberOfPieces++].moves = moves;
1670
      }
1671
   }
1672
 
1673
   movelist->nextMove = 0;
1674
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
1675
   orthoChecks = getMagicRookMoves(opponentKing, position->allPieces);
1676
   diaChecks = getMagicBishopMoves(opponentKing, position->allPieces);
1677
   pawnChecks = generalMoves[PAWN | passiveColor][opponentKing];
1678
   permittedSquares = (allChecks ? ~position->piecesOfColor[activeColor] :
1679
                       ~position->allPieces);
1680
 
1681
   for (i = 0; i < movelist->numberOfPieces; i++)
1682
   {
1683
      Bitboard checks = EMPTY_BITBOARD;
1684
      const Square from = movelist->movesOfPiece[i].square;
1685
      const PieceType piece = pieceType(position->piece[from]);
1686
      Square batteryPieceSquare = NO_SQUARE, to;
1687
 
1688
      moves = movelist->movesOfPiece[i].moves & permittedSquares;
1689
 
1690
      if (testSquare(orthoChecks, from))
1691
      {
1692
         static const int pieceProperties = PP_SLIDING_PIECE | PP_ORTHOPIECE;
1693
         Bitboard batteryPiece = position->piecesOfColor[activeColor] &
1694
            squaresBehind[from][opponentKing] &
1695
            getMagicRookMoves(from, position->allPieces);
1696
         batteryPieceSquare = getLastSquare(&batteryPiece);
1697
 
1698
         if (batteryPieceSquare != NO_SQUARE &&
1699
             (int) (position->piece[batteryPieceSquare] & pieceProperties) !=
1700
             pieceProperties)
1701
         {
1702
            batteryPieceSquare = NO_SQUARE;
1703
         }
1704
      }
1705
      else if (testSquare(diaChecks, from))
1706
      {
1707
         static const int pieceProperties = PP_SLIDING_PIECE | PP_DIAPIECE;
1708
         Bitboard batteryPiece = position->piecesOfColor[activeColor] &
1709
            squaresBehind[from][opponentKing] &
1710
            getMagicBishopMoves(from, position->allPieces);
1711
         batteryPieceSquare = getLastSquare(&batteryPiece);
1712
 
1713
         if (batteryPieceSquare != NO_SQUARE &&
1714
             (int) (position->piece[batteryPieceSquare] & pieceProperties) !=
1715
             pieceProperties)
1716
         {
1717
            batteryPieceSquare = NO_SQUARE;
1718
         }
1719
      }
1720
 
1721
      if (batteryPieceSquare != NO_SQUARE)
1722
      {
1723
         checks = moves & ~squaresBetween[opponentKing][batteryPieceSquare];
1724
      }
1725
      else
1726
      {
1727
         switch (piece)
1728
         {
1729
         case QUEEN:
1730
            checks = moves & (orthoChecks | diaChecks);
1731
            break;
1732
 
1733
         case ROOK:
1734
            checks = moves & orthoChecks;
1735
            break;
1736
 
1737
         case BISHOP:
1738
            checks = moves & diaChecks;
1739
            break;
1740
 
1741
         case KNIGHT:
1742
            checks = moves & getKnightMoves(opponentKing);
1743
            break;
1744
 
1745
         case PAWN:
1746
            checks = moves & pawnChecks;
1747
            break;
1748
 
1749
         default:
1750
            break;
1751
         }
1752
      }
1753
 
1754
      if (piece == KING)
1755
      {
1756
         Bitboard castlingMoves = moves &
1757
            ~getKingMoves(position->king[activeColor]);
1758
         Square kingSquare;
1759
 
1760
         ITERATE_BITBOARD(&castlingMoves, kingSquare)
1761
         {
1762
            const Bitboard obstacles = position->allPieces &
1763
               maxValue[position->king[activeColor]];
1764
            Bitboard rookMoves;
1765
            const Square rookSquare = (Square)
1766
               ((kingSquare + position->king[activeColor]) / 2);
1767
 
1768
            rookMoves = getMagicRookMoves(rookSquare, obstacles);
1769
 
1770
            if (testSquare(rookMoves, opponentKing))
1771
            {
1772
               setSquare(checks, kingSquare);
1773
            }
1774
         }
1775
      }
1776
 
1777
      if (checks != EMPTY_BITBOARD)
1778
      {
1779
         if (from == getFromSquare(movelist->hashMove))
1780
         {
1781
            clearSquare(checks, getToSquare(movelist->hashMove));
1782
         }
1783
 
1784
         if (movelist->killer1Executed &&
1785
             from == getFromSquare(movelist->plyInfo->killerMove1))
1786
         {
1787
            clearSquare(checks, getToSquare(movelist->plyInfo->killerMove1));
1788
         }
1789
 
1790
         if (movelist->killer2Executed &&
1791
             from == getFromSquare(movelist->plyInfo->killerMove2))
1792
         {
1793
            clearSquare(checks, getToSquare(movelist->plyInfo->killerMove2));
1794
         }
1795
 
1796
         if (movelist->killer3Executed &&
1797
             from == getFromSquare(movelist->plyInfo->killerMove3))
1798
         {
1799
            clearSquare(checks, getToSquare(movelist->plyInfo->killerMove3));
1800
         }
1801
 
1802
         if (movelist->killer4Executed &&
1803
             from == getFromSquare(movelist->plyInfo->killerMove4))
1804
         {
1805
            clearSquare(checks, getToSquare(movelist->plyInfo->killerMove4));
1806
         }
1807
 
1808
         if (movelist->killer5Executed &&
1809
             from == getFromSquare(movelist->plyInfo->killerMove5))
1810
         {
1811
            clearSquare(checks, getToSquare(movelist->plyInfo->killerMove5));
1812
         }
1813
 
1814
         if (movelist->killer6Executed &&
1815
             from == getFromSquare(movelist->plyInfo->killerMove6))
1816
         {
1817
            clearSquare(checks, getToSquare(movelist->plyInfo->killerMove6));
1818
         }
1819
 
1820
         movelist->movesOfPiece[i].moves &= ~checks;
1821
 
1822
         ITERATE_BITBOARD(&checks, to)
1823
         {
1824
            Move move = getPackedMove(from, to, NO_PIECE);
1825
 
1826
            setMoveValue(&move,
1827
                         historyMoveSortValue(position, movelist, move));
1828
            addMoveByValue(movelist, move);
1829
         }
1830
      }
1831
   }
1832
}
1833
 
1834
void generateEscapes(Movelist * movelist)
1835
{
1836
   Move move;
1837
   Square from, to;
1838
   Piece newPiece;
1839
   INT16 value;
1840
   PieceType attackerType;
1841
   Position *position = movelist->position;
1842
   const Color activeColor = position->activeColor;
1843
   const Color passiveColor = opponent(activeColor);
1844
   Square kingsquare = position->king[activeColor], attackerSquare;
1845
   Bitboard attackers = getDirectAttackers(position, kingsquare, passiveColor,
1846
                                           position->allPieces), defenders;
1847
   Bitboard kingmoves =
1848
      getKingMoves(kingsquare) & ~position->piecesOfColor[activeColor];
1849
   Bitboard corridor;
1850
   const Bitboard obstacles = position->allPieces & maxValue[kingsquare];
1851
 
1852
   movelist->nextMove = 0;
1853
   movelist->numberOfMoves = movelist->numberOfBadCaptures = 0;
1854
   from = kingsquare;
1855
   newPiece = NO_PIECE;
1856
 
1857
   ITERATE_BITBOARD(&kingmoves, to)
1858
   {
1859
      if (getDirectAttackers(position, to, passiveColor, obstacles) ==
1860
          EMPTY_BITBOARD)
1861
      {
1862
         move = getPackedMove(from, to, newPiece);
1863
 
1864
         if (position->piece[to] == NO_PIECE)
1865
         {
1866
            value = historyMoveSortValue(position, movelist, move);
1867
         }
1868
         else
1869
         {
1870
            value = captureMoveSortValue(position, from, to);
1871
         }
1872
 
1873
         setMoveValue(&move, value);
1874
         movelist->moves[movelist->numberOfMoves++] = move;
1875
      }
1876
   }
1877
 
1878
   if (getNumberOfSetSquares(attackers) > 1)
1879
   {
1880
      goto sortMoves;
1881
   }
1882
 
1883
   attackerSquare = getLastSquare(&attackers);
1884
   attackerType = pieceType(position->piece[attackerSquare]);
1885
   defenders = getDirectAttackers(position, attackerSquare, activeColor,
1886
                                  position->allPieces);
1887
   clearSquare(defenders, kingsquare);
1888
   to = attackerSquare;
1889
 
1890
   ITERATE_BITBOARD(&defenders, from)
1891
   {
1892
      if (pieceType(position->piece[from]) == PAWN &&
1893
          testSquare(promotionCandidates[activeColor], from))
1894
      {
1895
         INT16 value;
1896
 
1897
         value = promotionMoveSortValue(movelist->position, to, WHITE_QUEEN);
1898
         movelist->moves[movelist->numberOfMoves++] =
1899
            getMove(from, to, WHITE_QUEEN, value);
1900
 
1901
         value = promotionMoveSortValue(movelist->position, to, WHITE_ROOK);
1902
         movelist->moves[movelist->numberOfMoves++] =
1903
            getMove(from, to, WHITE_ROOK, value);
1904
 
1905
         value = promotionMoveSortValue(movelist->position, to, WHITE_BISHOP);
1906
         movelist->moves[movelist->numberOfMoves++] =
1907
            getMove(from, to, WHITE_BISHOP, value);
1908
 
1909
         value = promotionMoveSortValue(movelist->position, to, WHITE_KNIGHT);
1910
         movelist->moves[movelist->numberOfMoves++] =
1911
            getMove(from, to, WHITE_KNIGHT, value);
1912
      }
1913
      else
1914
      {
1915
         value = captureMoveSortValue(position, from, to);
1916
         move = getMove(from, to, NO_PIECE, value);
1917
 
1918
         if (basicValue[position->piece[from]] >
1919
             basicValue[position->piece[to]] && seeMove(position, move) < 0)
1920
         {
1921
            setMoveValue(&move, value - VALUEOFFSET_BAD_MOVE);
1922
         }
1923
 
1924
         movelist->moves[movelist->numberOfMoves++] = move;
1925
      }
1926
   }
1927
 
1928
   if (position->enPassantSquare != NO_SQUARE && attackerType == PAWN)
1929
   {
1930
      defenders = getPawnCaptures((Piece) (PAWN | opponent(activeColor)),
1931
                                  position->enPassantSquare,
1932
                                  position->piecesOfType[PAWN | activeColor]);
1933
 
1934
      to = position->enPassantSquare;
1935
      newPiece = NO_PIECE;
1936
      value = (INT16) basicValue[PAWN | opponent(activeColor)];
1937
 
1938
      ITERATE_BITBOARD(&defenders, from)
1939
      {
1940
         movelist->moves[movelist->numberOfMoves++] =
1941
            getMove(from, to, newPiece, value);
1942
      }
1943
 
1944
      goto sortMoves;
1945
   }
1946
 
1947
   if ((attackerType & PP_SLIDING_PIECE) == 0)
1948
   {
1949
      goto sortMoves;
1950
   }
1951
 
1952
   corridor = squaresBetween[attackerSquare][kingsquare];
1953
 
1954
   ITERATE_BITBOARD(&corridor, to)
1955
   {
1956
      defenders = getInterestedPieces(position, to, activeColor);
1957
      clearSquare(defenders, kingsquare);
1958
 
1959
      ITERATE_BITBOARD(&defenders, from)
1960
      {
1961
         if (pieceType(position->piece[from]) == PAWN &&
1962
             testSquare(promotionCandidates[activeColor], from))
1963
         {
1964
            INT16 value;
1965
 
1966
            value = promotionMoveSortValue(movelist->position,
1967
                                           to, WHITE_QUEEN);
1968
 
1969
            if (seeMove(position, getPackedMove(from, to, WHITE_QUEEN)) < 0)
1970
            {
1971
               value = (INT16) (value - (VALUEOFFSET_BAD_MOVE +
1972
                                         VALUEOFFSET_PROMOTION_TO_QUEEN));
1973
            }
1974
 
1975
            movelist->moves[movelist->numberOfMoves++] =
1976
               getMove(from, to, WHITE_QUEEN, value);
1977
 
1978
            value = promotionMoveSortValue(movelist->position,
1979
                                           to, WHITE_ROOK);
1980
            movelist->moves[movelist->numberOfMoves++] =
1981
               getMove(from, to, WHITE_ROOK, value);
1982
 
1983
            value = promotionMoveSortValue(movelist->position,
1984
                                           to, WHITE_BISHOP);
1985
            movelist->moves[movelist->numberOfMoves++] =
1986
               getMove(from, to, WHITE_BISHOP, value);
1987
 
1988
            value = promotionMoveSortValue(movelist->position,
1989
                                           to, WHITE_KNIGHT);
1990
            movelist->moves[movelist->numberOfMoves++] =
1991
               getMove(from, to, WHITE_KNIGHT, value);
1992
         }
1993
         else
1994
         {
1995
            move = getPackedMove(from, to, NO_PIECE);
1996
 
1997
            if (seeMove(position, move) >= 0)
1998
            {
1999
               value = historyMoveSortValue(position, movelist, move);
2000
            }
2001
            else
2002
            {
2003
               value = (INT16) (captureMoveSortValue(position, from, to) -
2004
                                VALUEOFFSET_BAD_MOVE);
2005
            }
2006
 
2007
            setMoveValue(&move, value);
2008
            movelist->moves[movelist->numberOfMoves++] = move;
2009
         }
2010
      }
2011
   }
2012
 
2013
 sortMoves:
2014
 
2015
   if (movelist->hashMove != NO_MOVE && movelist->numberOfMoves > 1)
2016
   {
2017
      move = movelist->hashMove;
2018
      setMoveValue(&move, 32000);
2019
      setMoveValueInList(movelist, move);
2020
   }
2021
 
2022
   sortMoves(movelist);
2023
 
2024
   assert(movelist->hashMove == NO_MOVE ||
2025
          movesAreEqual(movelist->moves[0], movelist->hashMove));
2026
}
2027
 
2028
bool simpleMoveIsCheck(const Position * position, const Move move)
2029
{
2030
   const Color attackingColor = position->activeColor;
2031
   const Color defendingColor = opponent(attackingColor);
2032
   const Square from = getFromSquare(move);
2033
   const Square to = getToSquare(move);
2034
   const Piece movingPiece = position->piece[from];
2035
   const PieceType movingPieceType = pieceType(movingPiece);
2036
   const Square target = position->king[defendingColor];
2037
   const Bitboard moves =
2038
      getMoves(to, position->piece[from], position->allPieces);
2039
 
2040
   if (testSquare(moves, target) && movingPieceType != KING)
2041
   {
2042
      return TRUE;
2043
   }
2044
 
2045
   if (testSquare(getMagicRookMoves(target, position->allPieces), from))
2046
   {
2047
      Bitboard batteryPieces =
2048
         (position->piecesOfType[ROOK | attackingColor] |
2049
          position->piecesOfType[QUEEN | attackingColor]) &
2050
         squaresBehind[from][target];
2051
      Square square;
2052
 
2053
      ITERATE_BITBOARD(&batteryPieces, square)
2054
      {
2055
         Bitboard blockingPieces = (position->allPieces | minValue[to]) &
2056
            squaresBetween[target][square] & maxValue[from];
2057
 
2058
         if (blockingPieces == EMPTY_BITBOARD)
2059
         {
2060
            return TRUE;
2061
         }
2062
      }
2063
   }
2064
 
2065
   if (testSquare(getMagicBishopMoves(target, position->allPieces), from))
2066
   {
2067
      Bitboard batteryPieces =
2068
         (position->piecesOfType[BISHOP | attackingColor] |
2069
          position->piecesOfType[QUEEN | attackingColor]) &
2070
         squaresBehind[from][target];
2071
      Square square;
2072
 
2073
      ITERATE_BITBOARD(&batteryPieces, square)
2074
      {
2075
         Bitboard blockingPieces = (position->allPieces | minValue[to]) &
2076
            squaresBetween[target][square] & maxValue[from];
2077
 
2078
         if (blockingPieces == EMPTY_BITBOARD)
2079
         {
2080
            return TRUE;
2081
         }
2082
      }
2083
   }
2084
 
2085
   return FALSE;
2086
}
2087
 
2088
bool kingCanEscape(Position * position)
2089
{
2090
   Square square;
2091
   PieceType attackerType;
2092
   const Color activeColor = position->activeColor;
2093
   const Color passiveColor = opponent(activeColor);
2094
   Square kingsquare = position->king[activeColor], attackerSquare;
2095
   Bitboard attackers = getDirectAttackers(position, kingsquare, passiveColor,
2096
                                           position->allPieces), defenders;
2097
   Bitboard kingmoves =
2098
      getKingMoves(kingsquare) & ~position->piecesOfColor[activeColor];
2099
   Bitboard corridor;
2100
   const Bitboard unpinnedPieces = ~getPinnedPieces(position, passiveColor);
2101
   const Bitboard obstacles = position->allPieces & maxValue[kingsquare];
2102
 
2103
   ITERATE_BITBOARD(&kingmoves, square)
2104
   {
2105
      if (getDirectAttackers(position, square, passiveColor, obstacles) ==
2106
          EMPTY_BITBOARD)
2107
      {
2108
         return TRUE;
2109
      }
2110
   }
2111
 
2112
   if (getNumberOfSetSquares(attackers) > 1)
2113
   {
2114
      return FALSE;
2115
   }
2116
 
2117
   attackerSquare = getLastSquare(&attackers);
2118
   attackerType = pieceType(position->piece[attackerSquare]);
2119
   defenders = getDirectAttackers(position, attackerSquare, activeColor,
2120
                                  position->allPieces);
2121
   clearSquare(defenders, kingsquare);
2122
 
2123
   if ((defenders & unpinnedPieces) != EMPTY_BITBOARD)
2124
   {
2125
      return TRUE;
2126
   }
2127
 
2128
   if (position->enPassantSquare != NO_SQUARE && attackerType == PAWN)
2129
   {
2130
      defenders = getPawnCaptures((Piece) (PAWN | opponent(activeColor)),
2131
                                  position->enPassantSquare,
2132
                                  position->piecesOfType[PAWN | activeColor]);
2133
 
2134
      if ((defenders & unpinnedPieces) != EMPTY_BITBOARD)
2135
      {
2136
         return TRUE;
2137
      }
2138
   }
2139
 
2140
   if ((attackerType & PP_SLIDING_PIECE) == 0)
2141
   {
2142
      return FALSE;
2143
   }
2144
 
2145
   corridor = squaresBetween[attackerSquare][kingsquare];
2146
 
2147
   ITERATE_BITBOARD(&corridor, square)
2148
   {
2149
      defenders = getInterestedPieces(position, square, activeColor);
2150
      clearSquare(defenders, kingsquare);
2151
 
2152
      if ((defenders & unpinnedPieces) != EMPTY_BITBOARD)
2153
      {
2154
         return TRUE;
2155
      }
2156
   }
2157
 
2158
   return FALSE;
2159
}
2160
 
2161
int initializeModuleMovegeneration()
2162
{
2163
   int i = 0;
2164
 
2165
   MG_SCHEME_STANDARD = i;
2166
   moveGenerationStage[i++] = MGS_INITIALIZE;
2167
   moveGenerationStage[i++] = MGS_GOOD_CAPTURES_AND_PROMOTIONS;
2168
   moveGenerationStage[i++] = MGS_KILLER_MOVES;
2169
   moveGenerationStage[i++] = MGS_REST;
2170
   moveGenerationStage[i++] = MGS_BAD_CAPTURES;
2171
   moveGenerationStage[i++] = MGS_FINISHED;
2172
 
2173
   MG_SCHEME_ESCAPE = i;
2174
   moveGenerationStage[i++] = MGS_INITIALIZE;
2175
   moveGenerationStage[i++] = MGS_ESCAPES;
2176
   moveGenerationStage[i++] = MGS_FINISHED;
2177
 
2178
   MG_SCHEME_QUIESCENCE_WITH_CHECKS = i;
2179
   moveGenerationStage[i++] = MGS_INITIALIZE;
2180
   moveGenerationStage[i++] = MGS_GOOD_CAPTURES_AND_PROMOTIONS;
2181
   moveGenerationStage[i++] = MGS_SAFE_CHECKS;
2182
   moveGenerationStage[i++] = MGS_FINISHED;
2183
 
2184
   MG_SCHEME_QUIESCENCE = i;
2185
   moveGenerationStage[i++] = MGS_INITIALIZE;
2186
   moveGenerationStage[i++] = MGS_GOOD_CAPTURES_AND_PROMOTIONS_PURE;
2187
   moveGenerationStage[i++] = MGS_FINISHED;
2188
 
2189
   MG_SCHEME_CAPTURES = i;
2190
   moveGenerationStage[i++] = MGS_INITIALIZE;
2191
   moveGenerationStage[i++] = MGS_GOOD_CAPTURES;
2192
   moveGenerationStage[i++] = MGS_FINISHED;
2193
 
2194
   MG_SCHEME_CHECKS = i;
2195
   moveGenerationStage[i++] = MGS_INITIALIZE;
2196
   moveGenerationStage[i++] = MGS_GOOD_CAPTURES_AND_PROMOTIONS;
2197
   moveGenerationStage[i++] = MGS_CHECKS;
2198
   moveGenerationStage[i++] = MGS_FINISHED;
2199
 
2200
   pieceOrder[NO_PIECE] = 0;
2201
   pieceOrder[WHITE_PAWN] = pieceOrder[BLACK_PAWN] = 1;
2202
   pieceOrder[WHITE_KNIGHT] = pieceOrder[BLACK_KNIGHT] = 2;
2203
   pieceOrder[WHITE_BISHOP] = pieceOrder[BLACK_BISHOP] = 3;
2204
   pieceOrder[WHITE_ROOK] = pieceOrder[BLACK_ROOK] = 4;
2205
   pieceOrder[WHITE_QUEEN] = pieceOrder[BLACK_QUEEN] = 5;
2206
   pieceOrder[WHITE_KING] = pieceOrder[BLACK_KING] = 6;
2207
 
2208
   promotionPieceValue[WHITE_KNIGHT] = promotionPieceValue[BLACK_KNIGHT] =
2209
      2 - VALUEOFFSET_BAD_MOVE;
2210
   promotionPieceValue[WHITE_BISHOP] = promotionPieceValue[BLACK_BISHOP] =
2211
      3 - VALUEOFFSET_BAD_MOVE;
2212
   promotionPieceValue[WHITE_ROOK] = promotionPieceValue[BLACK_ROOK] =
2213
      4 - VALUEOFFSET_BAD_MOVE;
2214
   promotionPieceValue[WHITE_QUEEN] = promotionPieceValue[BLACK_QUEEN] =
2215
      VALUEOFFSET_PROMOTION_TO_QUEEN;
2216
 
2217
   return 0;
2218
}
2219
 
2220
#ifndef NDEBUG
2221
 
2222
static int testPseudoLegalMoves()
2223
{
2224
   Variation variation;
2225
   Bitboard attackers, interested;
2226
 
2227
   initializeVariation(&variation, FEN_GAMESTART);
2228
   assert(moveIsPseudoLegal
2229
          (&variation.singlePosition, getPackedMove(E2, E4, NO_PIECE)));
2230
   assert(moveIsPseudoLegal
2231
          (&variation.singlePosition, getPackedMove(G1, F3, NO_PIECE)));
2232
   assert(moveIsPseudoLegal
2233
          (&variation.singlePosition,
2234
           getPackedMove(G1, E2, NO_PIECE)) == FALSE);
2235
   assert(moveIsPseudoLegal
2236
          (&variation.singlePosition,
2237
           getPackedMove(G8, F6, NO_PIECE)) == FALSE);
2238
   assert(moveIsPseudoLegal
2239
          (&variation.singlePosition,
2240
           getPackedMove(E4, E5, NO_PIECE)) == FALSE);
2241
 
2242
   attackers =
2243
      getDirectAttackers(&variation.singlePosition, F3, WHITE,
2244
                         variation.singlePosition.allPieces);
2245
   assert(testSquare(attackers, G1));
2246
   assert(testSquare(attackers, E2));
2247
   assert(testSquare(attackers, G2));
2248
   assert(getNumberOfSetSquares(attackers) == 3);
2249
 
2250
   interested = getInterestedPieces(&variation.singlePosition, F3, WHITE);
2251
   assert(testSquare(interested, G1));
2252
   assert(testSquare(interested, F2));
2253
   assert(getNumberOfSetSquares(interested) == 2);
2254
 
2255
   interested = getInterestedPieces(&variation.singlePosition, F4, WHITE);
2256
   assert(testSquare(interested, F2));
2257
   assert(getNumberOfSetSquares(interested) == 1);
2258
 
2259
   attackers =
2260
      getDirectAttackers(&variation.singlePosition, C6, BLACK,
2261
                         variation.singlePosition.allPieces);
2262
   assert(testSquare(attackers, B8));
2263
   assert(testSquare(attackers, B7));
2264
   assert(testSquare(attackers, D7));
2265
   assert(getNumberOfSetSquares(attackers) == 3);
2266
 
2267
   makeMove(&variation, getPackedMove(E2, E4, NO_PIECE));
2268
 
2269
   assert(moveIsPseudoLegal
2270
          (&variation.singlePosition,
2271
           getPackedMove(E2, E4, NO_PIECE)) == FALSE);
2272
   assert(moveIsPseudoLegal
2273
          (&variation.singlePosition,
2274
           getPackedMove(G1, F3, NO_PIECE)) == FALSE);
2275
   assert(moveIsPseudoLegal
2276
          (&variation.singlePosition,
2277
           getPackedMove(G1, E2, NO_PIECE)) == FALSE);
2278
   assert(moveIsPseudoLegal
2279
          (&variation.singlePosition, getPackedMove(G8, F6, NO_PIECE)));
2280
   assert(moveIsPseudoLegal
2281
          (&variation.singlePosition,
2282
           getPackedMove(E4, E5, NO_PIECE)) == FALSE);
2283
 
2284
   attackers =
2285
      getDirectAttackers(&variation.singlePosition, F3, WHITE,
2286
                         variation.singlePosition.allPieces);
2287
   assert(testSquare(attackers, G1));
2288
   assert(testSquare(attackers, D1));
2289
   assert(testSquare(attackers, G2));
2290
   assert(getNumberOfSetSquares(attackers) == 3);
2291
 
2292
   attackers =
2293
      getDirectAttackers(&variation.singlePosition, D2, WHITE,
2294
                         variation.singlePosition.allPieces);
2295
   assert(testSquare(attackers, B1));
2296
   assert(testSquare(attackers, C1));
2297
   assert(testSquare(attackers, D1));
2298
   assert(testSquare(attackers, E1));
2299
   assert(getNumberOfSetSquares(attackers) == 4);
2300
 
2301
   makeMove(&variation, getPackedMove(G8, F6, NO_PIECE));
2302
 
2303
   assert(moveIsPseudoLegal
2304
          (&variation.singlePosition, getPackedMove(E4, E5, NO_PIECE)));
2305
 
2306
   makeMove(&variation, getPackedMove(E4, E5, NO_PIECE));
2307
 
2308
   assert(moveIsPseudoLegal
2309
          (&variation.singlePosition, getPackedMove(D7, D5, NO_PIECE)));
2310
 
2311
   makeMove(&variation, getPackedMove(D7, D5, NO_PIECE));
2312
 
2313
   assert(moveIsPseudoLegal
2314
          (&variation.singlePosition, getPackedMove(E5, D6, NO_PIECE)));
2315
   assert(moveIsPseudoLegal
2316
          (&variation.singlePosition, getPackedMove(G1, F3, NO_PIECE)));
2317
 
2318
   makeMove(&variation, getPackedMove(G1, F3, NO_PIECE));
2319
 
2320
   assert(moveIsPseudoLegal
2321
          (&variation.singlePosition, getPackedMove(E7, E6, NO_PIECE)));
2322
 
2323
   makeMove(&variation, getPackedMove(E7, E6, NO_PIECE));
2324
 
2325
   assert(moveIsPseudoLegal
2326
          (&variation.singlePosition, getPackedMove(F1, C4, NO_PIECE)));
2327
   assert(moveIsPseudoLegal
2328
          (&variation.singlePosition,
2329
           getPackedMove(E1, G1, NO_PIECE)) == FALSE);
2330
 
2331
   makeMove(&variation, getPackedMove(F1, C4, NO_PIECE));
2332
 
2333
   assert(moveIsPseudoLegal
2334
          (&variation.singlePosition, getPackedMove(F8, C5, NO_PIECE)));
2335
   assert(moveIsPseudoLegal
2336
          (&variation.singlePosition,
2337
           getPackedMove(E8, G8, NO_PIECE)) == FALSE);
2338
 
2339
   makeMove(&variation, getPackedMove(F8, C5, NO_PIECE));
2340
 
2341
   assert(moveIsPseudoLegal
2342
          (&variation.singlePosition, getPackedMove(E1, G1, NO_PIECE)));
2343
 
2344
   makeMove(&variation, getPackedMove(E1, G1, NO_PIECE));
2345
 
2346
   assert(moveIsPseudoLegal
2347
          (&variation.singlePosition, getPackedMove(E8, G8, NO_PIECE)));
2348
 
2349
   return 0;
2350
}
2351
 
2352
static int testLegalMoves()
2353
{
2354
   Variation variation;
2355
 
2356
   initializeVariation(&variation, FEN_GAMESTART);
2357
   assert(moveIsLegal
2358
          (&variation.singlePosition, getPackedMove(E2, E4, NO_PIECE)));
2359
   assert(moveIsLegal
2360
          (&variation.singlePosition, getPackedMove(G1, F3, NO_PIECE)));
2361
 
2362
   makeMove(&variation, getPackedMove(E2, E4, NO_PIECE));
2363
 
2364
   assert(moveIsLegal
2365
          (&variation.singlePosition, getPackedMove(G8, F6, NO_PIECE)));
2366
 
2367
   makeMove(&variation, getPackedMove(D7, D5, NO_PIECE));
2368
   makeMove(&variation, getPackedMove(F1, B5, NO_PIECE));
2369
 
2370
   assert(moveIsLegal
2371
          (&variation.singlePosition, getPackedMove(B8, C6, NO_PIECE)));
2372
   assert(moveIsLegal
2373
          (&variation.singlePosition, getPackedMove(B8, D7, NO_PIECE)));
2374
   assert(moveIsLegal
2375
          (&variation.singlePosition,
2376
           getPackedMove(B8, A6, NO_PIECE)) == FALSE);
2377
   assert(moveIsLegal
2378
          (&variation.singlePosition,
2379
           getPackedMove(G8, F6, NO_PIECE)) == FALSE);
2380
 
2381
   return 0;
2382
}
2383
 
2384
static int testStaticExchangeEvaluation()
2385
{
2386
   Variation variation;
2387
   Move move;
2388
 
2389
   initializeVariation(&variation, FEN_GAMESTART);
2390
 
2391
   makeMove(&variation, getPackedMove(E2, E4, NO_PIECE));
2392
   makeMove(&variation, getPackedMove(E7, E5, NO_PIECE));
2393
   makeMove(&variation, getPackedMove(G1, F3, NO_PIECE));
2394
   makeMove(&variation, getPackedMove(B8, C6, NO_PIECE));
2395
 
2396
   move = getPackedMove(F3, E5, NO_PIECE);
2397
   assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
2398
 
2399
   makeMove(&variation, getPackedMove(B1, A3, NO_PIECE));
2400
   makeMove(&variation, getPackedMove(G8, H6, NO_PIECE));
2401
   makeMove(&variation, getPackedMove(A3, C4, NO_PIECE));
2402
 
2403
   move = getPackedMove(F3, E5, NO_PIECE);
2404
   assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
2405
   move = getPackedMove(C4, E5, NO_PIECE);
2406
   assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
2407
 
2408
   makeMove(&variation, getPackedMove(H6, G4, NO_PIECE));
2409
 
2410
   move = getPackedMove(F3, E5, NO_PIECE);
2411
   assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
2412
 
2413
   makeMove(&variation, getPackedMove(B2, B3, NO_PIECE));
2414
   makeMove(&variation, getPackedMove(G7, G6, NO_PIECE));
2415
   makeMove(&variation, getPackedMove(C1, B2, NO_PIECE));
2416
 
2417
   move = getPackedMove(F3, E5, NO_PIECE);
2418
   assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
2419
   move = getPackedMove(C4, E5, NO_PIECE);
2420
   assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
2421
   move = getPackedMove(B2, E5, NO_PIECE);
2422
   assert(seeMove(&variation.singlePosition, move) ==
2423
          basicValue[BLACK_PAWN] - basicValue[WHITE_BISHOP] +
2424
          basicValue[BLACK_KNIGHT]);
2425
 
2426
   makeMove(&variation, getPackedMove(F8, G7, NO_PIECE));
2427
 
2428
   move = getPackedMove(F3, E5, NO_PIECE);
2429
   assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
2430
   move = getPackedMove(C4, E5, NO_PIECE);
2431
   assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
2432
   move = getPackedMove(B2, E5, NO_PIECE);
2433
   assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_BISHOP);
2434
 
2435
   makeMove(&variation, getPackedMove(A2, A4, NO_PIECE));
2436
   makeMove(&variation, getPackedMove(H7, H5, NO_PIECE));
2437
   makeMove(&variation, getPackedMove(A4, A5, NO_PIECE));
2438
   makeMove(&variation, getPackedMove(H5, H4, NO_PIECE));
2439
   makeMove(&variation, getPackedMove(A5, A6, NO_PIECE));
2440
   makeMove(&variation, getPackedMove(H4, H3, NO_PIECE));
2441
   makeMove(&variation, getPackedMove(A1, A5, NO_PIECE));
2442
 
2443
   move = getPackedMove(F3, E5, NO_PIECE);
2444
   assert(seeMove(&variation.singlePosition, move) > 0);
2445
   move = getPackedMove(C4, E5, NO_PIECE);
2446
   assert(seeMove(&variation.singlePosition, move) > 0);
2447
   move = getPackedMove(B2, E5, NO_PIECE);
2448
   assert(seeMove(&variation.singlePosition, move) > 0);
2449
   move = getPackedMove(A5, E5, NO_PIECE);
2450
   assert(seeMove(&variation.singlePosition, move) ==
2451
          basicValue[BLACK_PAWN] + basicValue[BLACK_KNIGHT] -
2452
          basicValue[WHITE_ROOK]);
2453
 
2454
   makeMove(&variation, getPackedMove(H8, H5, NO_PIECE));
2455
 
2456
   move = getPackedMove(F3, E5, NO_PIECE);
2457
   assert(seeMove(&variation.singlePosition, move) < 0);
2458
   move = getPackedMove(C4, E5, NO_PIECE);
2459
   assert(seeMove(&variation.singlePosition, move) < 0);
2460
   move = getPackedMove(B2, E5, NO_PIECE);
2461
   assert(seeMove(&variation.singlePosition, move) < 0);
2462
   move = getPackedMove(A5, E5, NO_PIECE);
2463
   assert(seeMove(&variation.singlePosition, move) ==
2464
          basicValue[BLACK_PAWN] - basicValue[WHITE_ROOK]);
2465
 
2466
   makeMove(&variation, getPackedMove(D1, A1, NO_PIECE));
2467
 
2468
   move = getPackedMove(F3, E5, NO_PIECE);
2469
   assert(seeMove(&variation.singlePosition, move) > 0);
2470
   move = getPackedMove(C4, E5, NO_PIECE);
2471
   assert(seeMove(&variation.singlePosition, move) > 0);
2472
   move = getPackedMove(B2, E5, NO_PIECE);
2473
   assert(seeMove(&variation.singlePosition, move) > 0);
2474
   move = getPackedMove(A5, E5, NO_PIECE);
2475
   assert(seeMove(&variation.singlePosition, move) ==
2476
          basicValue[BLACK_PAWN] + basicValue[BLACK_KNIGHT] -
2477
          basicValue[WHITE_ROOK]);
2478
 
2479
   makeMove(&variation, getPackedMove(D8, F6, NO_PIECE));
2480
 
2481
   move = getPackedMove(F3, E5, NO_PIECE);
2482
   assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
2483
   move = getPackedMove(C4, E5, NO_PIECE);
2484
   assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_KNIGHT);
2485
   move = getPackedMove(B2, E5, NO_PIECE);
2486
   assert(seeMove(&variation.singlePosition, move) == PAWN_FOR_BISHOP);
2487
   move = getPackedMove(A5, E5, NO_PIECE);
2488
   assert(seeMove(&variation.singlePosition, move) ==
2489
          basicValue[BLACK_PAWN] - basicValue[WHITE_KNIGHT] ||
2490
          seeMove(&variation.singlePosition, move) ==
2491
          basicValue[BLACK_PAWN] - basicValue[WHITE_BISHOP]);
2492
   move = getPackedMove(F6, F3, NO_PIECE);
2493
   assert(seeMove(&variation.singlePosition, move) ==
2494
          basicValue[WHITE_KNIGHT] - basicValue[BLACK_QUEEN]);
2495
   move = getPackedMove(A6, B7, NO_PIECE);
2496
   assert(seeMove(&variation.singlePosition, move) == 0);
2497
 
2498
   makeMove(&variation, getPackedMove(A6, B7, NO_PIECE));
2499
   makeMove(&variation, getPackedMove(C8, B7, NO_PIECE));
2500
 
2501
   move = getPackedMove(A5, A7, NO_PIECE);
2502
   assert(seeMove(&variation.singlePosition, move) ==
2503
          basicValue[BLACK_PAWN] - basicValue[WHITE_ROOK]);
2504
   move = getPackedMove(C6, A5, NO_PIECE);
2505
   assert(seeMove(&variation.singlePosition, move) ==
2506
          basicValue[WHITE_ROOK] - basicValue[BLACK_KNIGHT]);
2507
 
2508
   return 0;
2509
}
2510
 
2511
static int testStaticExchangeEvaluationWithKing()
2512
{
2513
   Variation variation;
2514
   Move move;
2515
 
2516
   initializeVariation(&variation, FEN_GAMESTART);
2517
 
2518
   makeMove(&variation, getPackedMove(E2, E4, NO_PIECE));
2519
   makeMove(&variation, getPackedMove(E7, E5, NO_PIECE));
2520
   makeMove(&variation, getPackedMove(D1, H5, NO_PIECE));
2521
   makeMove(&variation, getPackedMove(D7, D6, NO_PIECE));
2522
 
2523
   move = getPackedMove(H5, F7, NO_PIECE);
2524
   assert(seeMove(&variation.singlePosition, move) ==
2525
          basicValue[BLACK_PAWN] - basicValue[WHITE_QUEEN]);
2526
 
2527
   makeMove(&variation, getPackedMove(F1, C4, NO_PIECE));
2528
 
2529
   move = getPackedMove(H5, F7, NO_PIECE);
2530
   assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
2531
 
2532
   makeMove(&variation, getPackedMove(G8, H6, NO_PIECE));
2533
 
2534
   move = getPackedMove(C4, F7, NO_PIECE);
2535
   assert(seeMove(&variation.singlePosition, move) ==
2536
          basicValue[BLACK_PAWN] - basicValue[WHITE_BISHOP]);
2537
 
2538
   return 0;
2539
}
2540
 
2541
static int testStaticExchangeEvaluationWithEnPassantCapture()
2542
{
2543
   Variation variation;
2544
   Move move;
2545
 
2546
   initializeVariation(&variation, "6k1/8/7r/pP6/8/8/8/R5K1 w - a6 0 1");
2547
 
2548
   move = getPackedMove(B5, A6, NO_PIECE);
2549
   assert(seeMove(&variation.singlePosition, move) == basicValue[BLACK_PAWN]);
2550
 
2551
   makeMove(&variation, getPackedMove(B5, A6, NO_PIECE));
2552
   makeMove(&variation, getPackedMove(G8, G7, NO_PIECE));
2553
   makeMove(&variation, getPackedMove(A6, A7, NO_PIECE));
2554
   makeMove(&variation, getPackedMove(H6, H8, NO_PIECE));
2555
 
2556
   move = getPackedMove(A7, A8, WHITE_QUEEN);
2557
   assert(seeMove(&variation.singlePosition, move) ==
2558
          basicValue[BLACK_ROOK] - basicValue[WHITE_PAWN]);
2559
 
2560
   return 0;
2561
}
2562
 
2563
#define P1 "2b3k1/1p1n1pP1/5P2/2r2q2/4Q3/3N1p2/5Pp1/1R1B2K1 w - - 0 1"
2564
 
2565
static int testAttackCalculations()
2566
{
2567
   Variation variation;
2568
 
2569
   initializeVariation(&variation, FEN_GAMESTART);
2570
   assert(passiveKingIsSafe(&variation.singlePosition));
2571
 
2572
   initializeVariation(&variation, "R5k1/8/6K1/8/8/8/1r6/8 w - - 0 1");
2573
   assert(passiveKingIsSafe(&variation.singlePosition) == FALSE);
2574
 
2575
   initializeVariation(&variation, "6k1/R7/6K1/8/8/8/6r1/8 b - - 0 1");
2576
   assert(passiveKingIsSafe(&variation.singlePosition) == FALSE);
2577
 
2578
   initializeVariation(&variation, "6k1/R7/6K1/6P1/8/8/6r1/8 b - - 0 1");
2579
   assert(passiveKingIsSafe(&variation.singlePosition));
2580
 
2581
   initializeVariation(&variation, "R5k1/8/6K1/8/8/8/1r6/8 b - - 0 1");
2582
   assert(activeKingIsSafe(&variation.singlePosition) == FALSE);
2583
 
2584
   initializeVariation(&variation, "6k1/R7/6K1/8/8/8/6r1/8 w - - 0 1");
2585
   assert(activeKingIsSafe(&variation.singlePosition) == FALSE);
2586
 
2587
   initializeVariation(&variation, "6k1/R7/6K1/6P1/8/8/6r1/8 w - - 0 1");
2588
   assert(activeKingIsSafe(&variation.singlePosition));
2589
 
2590
   return 0;
2591
}
2592
 
2593
static int testLegalMoveGeneration()
2594
{
2595
   Variation variation;
2596
   Movelist movelist;
2597
 
2598
   initializeVariation(&variation, "R5k1/8/5K2/8/8/8/1r6/8 b - - 0 1");
2599
   getLegalMoves(&variation, &movelist);
2600
 
2601
   assert(movelist.numberOfMoves == 2);
2602
   assert(listContainsSimpleMove(&movelist, G8, H7));
2603
   assert(listContainsSimpleMove(&movelist, B2, B8));
2604
 
2605
   return 0;
2606
}
2607
 
2608
static int testPinCheck()
2609
{
2610
   static const char *fen1 =
2611
      "r1b1k2r/ppp2ppp/2n2n2/1B6/1b2qp2/2NP1N2/PPP1QPPP/R3K2R w KQkq - 0 9";
2612
   Variation variation;
2613
   Bitboard pinnedPieces;
2614
 
2615
   initializeVariation(&variation, fen1);
2616
   pinnedPieces = getPinnedPieces(&variation.singlePosition, WHITE);
2617
   assert(testSquare(pinnedPieces, E4));
2618
   assert(testSquare(pinnedPieces, C6));
2619
   assert(getNumberOfSetSquares(pinnedPieces) == 2);
2620
   pinnedPieces = getPinnedPieces(&variation.singlePosition, BLACK);
2621
   assert(testSquare(pinnedPieces, E2));
2622
   assert(testSquare(pinnedPieces, C3));
2623
   assert(getNumberOfSetSquares(pinnedPieces) == 2);
2624
 
2625
   return 0;
2626
}
2627
 
2628
#endif
2629
 
2630
int testModuleMovegeneration()
2631
{
2632
 
2633
#ifndef NDEBUG
2634
 
2635
   int result;
2636
 
2637
   if ((result = testPseudoLegalMoves()) != 0)
2638
   {
2639
      return result;
2640
   }
2641
 
2642
   if ((result = testLegalMoves()) != 0)
2643
   {
2644
      return result;
2645
   }
2646
 
2647
   if ((result = testStaticExchangeEvaluation()) != 0)
2648
   {
2649
      return result;
2650
   }
2651
 
2652
   if ((result = testStaticExchangeEvaluationWithKing()) != 0)
2653
   {
2654
      return result;
2655
   }
2656
 
2657
   if ((result = testStaticExchangeEvaluationWithEnPassantCapture()) != 0)
2658
   {
2659
      return result;
2660
   }
2661
 
2662
   if ((result = testAttackCalculations()) != 0)
2663
   {
2664
      return result;
2665
   }
2666
 
2667
   if ((result = testLegalMoveGeneration()) != 0)
2668
   {
2669
      return result;
2670
   }
2671
 
2672
   if ((result = testPinCheck()) != 0)
2673
   {
2674
      return result;
2675
   }
2676
 
2677
#endif
2678
 
2679
   return 0;
2680
}