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 <string.h>
23
#include <assert.h>
24
#include <math.h>
25
#include "position.h"
26
#include "fen.h"
27
#include "io.h"
28
#include "keytable.h"
29
#include "hash.h"
30
#include "evaluation.h"
31
 
32
/* #define TRACE_POSITIONS 1 */
33
 
34
#ifdef TRACE_POSITIONS
35
const int POSITION_TRACE_START = 4711;
36
const int POSITION_TRACE_QUANTITY = 100;
37
#endif
38
 
39
int VALUE_QUEEN_OPENING = DEFAULTVALUE_QUEEN_OPENING;
40
int VALUE_QUEEN_ENDGAME = DEFAULTVALUE_QUEEN_ENDGAME;
41
int VALUE_ROOK_OPENING = DEFAULTVALUE_ROOK_OPENING;
42
int VALUE_ROOK_ENDGAME = DEFAULTVALUE_ROOK_ENDGAME;
43
int VALUE_BISHOP_OPENING = DEFAULTVALUE_BISHOP_OPENING;
44
int VALUE_BISHOP_ENDGAME = DEFAULTVALUE_BISHOP_ENDGAME;
45
int VALUE_KNIGHT_OPENING = DEFAULTVALUE_KNIGHT_OPENING;
46
int VALUE_KNIGHT_ENDGAME = DEFAULTVALUE_KNIGHT_ENDGAME;
47
int VALUE_PAWN_OPENING = DEFAULTVALUE_PAWN_OPENING;
48
int VALUE_PAWN_ENDGAME = DEFAULTVALUE_PAWN_ENDGAME;
49
int VALUE_BISHOP_PAIR_OPENING = DEFAULTVALUE_BISHOP_PAIR_OPENING;
50
int VALUE_BISHOP_PAIR_ENDGAME = DEFAULTVALUE_BISHOP_PAIR_ENDGAME;
51
 
52
int basicValue[16];
53
INT32 pieceSquareBonus[16][_64_];
54
BYTE remainingCastlings[_64_];
55
Square rookOrigin[_64_];
56
int pieceCountShift[16];
57
UINT64 pieceCountWeight[16];
58
UINT64 bishopPieceCountWeight[2][_64_];
59
UINT32 matSigOfPieceCount[0xFFff];
60
int krqIndexWhite[4096], bbpIndexWhite[4096];
61
int krqIndexBlack[4096], bbpIndexBlack[4096];
62
 
63
Square relativeSquare(const Square square, const Color color)
64
{
65
   return (color == WHITE ? square : getFlippedSquare(square));
66
}
67
 
68
INT32 evalBonus(INT32 openingBonus, INT32 endgameBonus)
69
{
70
   return V(openingBonus, endgameBonus);
71
}
72
 
73
int getOpeningValue(INT32 value)
74
{
75
   return (int) ((INT16) (value & 0xFFFF));
76
}
77
 
78
int getEndgameValue(INT32 value)
79
{
80
   return (int) ((value + 0x8000) >> 16);
81
}
82
 
83
void addBonusForColor(const INT32 bonus, Position * position,
84
                      const Color color)
85
{
86
   if (color == WHITE)
87
   {
88
      position->balance += bonus;
89
   }
90
   else
91
   {
92
      position->balance -= bonus;
93
   }
94
}
95
 
96
/**
97
 * Pack the specified move into a 16-bit-uint.
98
 */
99
UINT16 packedMove(const Move move)
100
{
101
   return (UINT16) (move & 0xFFFF);
102
}
103
 
104
/**
105
 * Construct the specified move.
106
 */
107
Move getMove(const Square from, const Square to,
108
             const Piece newPiece, const INT16 value)
109
{
110
   return (value << 16) | (newPiece << 12) | (to << 6) | from;
111
}
112
 
113
/**
114
 * Construct the specified ordinary move.
115
 */
116
Move getOrdinaryMove(const Square from, const Square to)
117
{
118
   return (to << 6) | from;
119
}
120
 
121
/**
122
 * Construct the specified packed move.
123
 */
124
Move getPackedMove(const Square from, const Square to, const Piece newPiece)
125
{
126
   return (newPiece << 12) | (to << 6) | from;
127
}
128
 
129
/**
130
 * Get the from square of the specified move.
131
 */
132
Square getFromSquare(const Move move)
133
{
134
   return (Square) (move & 0x3F);
135
}
136
 
137
/**
138
 * Get the to square of the specified move.
139
 */
140
Square getToSquare(const Move move)
141
{
142
   return (Square) ((move >> 6) & 0x3F);
143
}
144
 
145
/**
146
 * Get the new piece of the specified move.
147
 */
148
Piece getNewPiece(const Move move)
149
{
150
   return (Piece) ((move >> 12) & 0x0F);
151
}
152
 
153
/**
154
 * Get the value of the specified move.
155
 */
156
INT16 getMoveValue(const Move move)
157
{
158
   return (INT16) (move >> 16);
159
}
160
 
161
/**
162
 * Set the value of the specified move.
163
 */
164
void setMoveValue(Move * move, const int value)
165
{
166
   *move = (*move & 0xFFFF) | (value << 16);
167
}
168
 
169
/**
170
 * Get the opponent color of the specified color.
171
 */
172
Color opponent(Color color)
173
{
174
   return (Color) (1 - color);
175
}
176
 
177
/**
178
 * Get the direct attackers of 'attackerColor' on 'square'.
179
 */
180
Bitboard getDirectAttackers(const Position * position,
181
                            const Square square,
182
                            const Color attackerColor,
183
                            const Bitboard obstacles)
184
{
185
   const Bitboard king = getKingMoves(square) &
186
      minValue[position->king[attackerColor]];
187
   Bitboard dia = getMagicBishopMoves(square, obstacles);
188
   Bitboard ortho = getMagicRookMoves(square, obstacles);
189
   Bitboard knights = getKnightMoves(square);
190
   const Bitboard pawns =
191
      getPawnCaptures((Piece) (PAWN | opponent(attackerColor)),
192
                      square, position->piecesOfType[PAWN | attackerColor]);
193
 
194
   ortho &= (position->piecesOfType[QUEEN | attackerColor] |
195
             position->piecesOfType[ROOK | attackerColor]);
196
   dia &= (position->piecesOfType[QUEEN | attackerColor] |
197
           position->piecesOfType[BISHOP | attackerColor]);
198
   knights &= position->piecesOfType[KNIGHT | attackerColor];
199
 
200
   return king | ortho | dia | knights | pawns;
201
}
202
 
203
/**
204
 * Get the squares behind targetSquare, seen from 'viewPoint'.
205
 */
206
Bitboard getDiaSquaresBehind(const Position * position,
207
                             const Square targetSquare,
208
                             const Square viewPoint)
209
{
210
   return squaresBehind[targetSquare][viewPoint] &
211
      getMagicBishopMoves(targetSquare, position->allPieces);
212
}
213
 
214
/**
215
 * Get the squares behind targetSquare, seen from 'viewPoint'.
216
 */
217
Bitboard getOrthoSquaresBehind(const Position * position,
218
                               const Square targetSquare,
219
                               const Square viewPoint)
220
{
221
   return squaresBehind[targetSquare][viewPoint] &
222
      getMagicRookMoves(targetSquare, position->allPieces);
223
}
224
 
225
/**
226
 * Initialize the current plyInfo data structure.
227
 */
228
void initializePlyInfo(Variation * variation)
229
{
230
   const Position *position = &variation->singlePosition;
231
   PlyInfo *plyInfo = &variation->plyInfo[variation->ply];
232
   const Color activeColor = position->activeColor;
233
 
234
   plyInfo->pawnHashKey = position->pawnHashKey;
235
   plyInfo->enPassantSquare = position->enPassantSquare;
236
   plyInfo->kingSquare = position->king[activeColor];
237
   plyInfo->castlingRights = position->castlingRights;
238
   plyInfo->halfMoveClock = position->halfMoveClock;
239
   plyInfo->allPieces = position->allPieces;
240
   plyInfo->whitePieces = position->piecesOfColor[WHITE];
241
   plyInfo->blackPieces = position->piecesOfColor[BLACK];
242
   plyInfo->balance = 0;
243
}
244
 
245
/**
246
 * Initialize the current pv.
247
 */
248
void initializePv(PrincipalVariation * pv)
249
{
250
   int i;
251
 
252
   pv->length = 0;
253
   pv->score = VALUE_MATED;
254
   pv->scoreType = HASHVALUE_LOWER_LIMIT;
255
 
256
   for (i = 0; i < MAX_DEPTH_ARRAY_SIZE; i++)
257
   {
258
      pv->move[i] = (UINT16) NO_MOVE;
259
   }
260
}
261
 
262
/**
263
 * Initialize the pvs of the current variation.
264
 */
265
void initializePvsOfVariation(Variation * variation)
266
{
267
   int i;
268
 
269
   initializePv(&variation->completePv);
270
 
271
   for (i = 0; i < MAX_NUM_PV; i++)
272
   {
273
      initializePv(&variation->pv[i]);
274
   }
275
 
276
   variation->pvId = 0;
277
}
278
 
279
/**
280
 * Initialize the pvs of the current variation.
281
 */
282
void resetPvsOfVariation(Variation * variation)
283
{
284
   int i;
285
 
286
   for (i = 0; i < MAX_NUM_PV; i++)
287
   {
288
      variation->pv[i].score = VALUE_MATED;
289
      variation->pv[i].scoreType = HASHVALUE_LOWER_LIMIT;
290
   }
291
 
292
   variation->pvId = 0;
293
}
294
 
295
int getPvlistMoveCount(Variation * variation, PrincipalVariation * pv)
296
{
297
   int i, count = 0;
298
 
299
   for (i = 0; i < MAX_NUM_PV; i++)
300
   {
301
      if (movesAreEqual(pv->move[0], variation->pv[i].move[0]))
302
      {
303
         count++;
304
      }
305
   }
306
 
307
   return count;
308
}
309
 
310
bool pvListContainsMove(Variation * variation, PrincipalVariation * pv)
311
{
312
   int i;
313
 
314
   for (i = 0; i < MAX_NUM_PV; i++)
315
   {
316
      if (movesAreEqual(pv->move[0], variation->pv[i].move[0]))
317
      {
318
         return TRUE;
319
      }
320
   }
321
 
322
   return FALSE;
323
}
324
 
325
void clearPvList(Variation * variation, PrincipalVariation * pv)
326
{
327
   int i;
328
 
329
   for (i = 0; i < MAX_NUM_PV; i++)
330
   {
331
      if (movesAreEqual(pv->move[0], variation->pv[i].move[0]))
332
      {
333
         int j;
334
 
335
         for (j = i; j < MAX_NUM_PV - 1; j++)
336
         {
337
            variation->pv[j] = variation->pv[j + 1];
338
         }
339
 
340
         initializePv(&variation->pv[MAX_NUM_PV - 1]);
341
      }
342
   }
343
}
344
 
345
void addPvByScore(Variation * variation, PrincipalVariation * pv)
346
{
347
   int i;
348
 
349
   /* Delete previous pv entries for the same root move */
350
   while (pvListContainsMove(variation, pv))
351
   {
352
      clearPvList(variation, pv);
353
   }
354
 
355
   for (i = 0; i < MAX_NUM_PV; i++)
356
   {
357
      if (pv->score > variation->pv[i].score)
358
      {
359
         int j;
360
 
361
         for (j = MAX_NUM_PV - 1; j > i; j--)
362
         {
363
            variation->pv[j] = variation->pv[j - 1];
364
         }
365
 
366
         variation->pv[i] = *pv;
367
         break;
368
      }
369
   }
370
 
371
   /* logDebug("move count on exit = %d\n", getPvlistMoveCount(variation, pv)); */
372
}
373
 
374
void resetPlyInfo(Variation * variation)
375
{
376
   int i;
377
 
378
   for (i = 0; i < MAX_DEPTH_ARRAY_SIZE; i++)
379
   {
380
      variation->plyInfo[i].staticValueAvailable =
381
         variation->plyInfo[i].gainsUpdated = FALSE;
382
      variation->plyInfo[i].pv.length = 0;
383
      variation->plyInfo[i].pv.move[0] = NO_MOVE;
384
   }
385
}
386
 
387
/**
388
 * Get the number of non-pawn pieces for the specified color.
389
 */
390
int numberOfNonPawnPieces(const Position * position, const Color color)
391
{
392
   return position->numberOfPieces[color] - position->numberOfPawns[color];
393
}
394
 
395
/**
396
 * Check if the specified color has a rook or a queen.
397
 */
398
bool hasOrthoPieces(const Position * position, const Color color)
399
{
400
   return (bool) (position->piecesOfType[ROOK | color] != EMPTY_BITBOARD ||
401
                  position->piecesOfType[QUEEN | color] != EMPTY_BITBOARD);
402
}
403
 
404
/**
405
 * Check if the specified color has a queen.
406
 */
407
bool hasQueen(const Position * position, const Color color)
408
{
409
   return (bool) (position->piecesOfType[QUEEN | color] != EMPTY_BITBOARD);
410
}
411
 
412
/**
413
 * Append the given move to the old pv and copy the new pv to 'new'.
414
 */
415
void appendMoveToPv(const PrincipalVariation * oldPv,
416
                    PrincipalVariation * newPv, const Move move)
417
{
418
   newPv->move[0] = packedMove(move);
419
   newPv->length = oldPv->length + 1;
420
   memmove((void *) &newPv->move[1], (void *) &oldPv->move[0],
421
           oldPv->length * sizeof(UINT16));
422
}
423
 
424
/**
425
 * Calculate the value to be stored in the hashtable.
426
 */
427
INT16 calcHashtableValue(const int value, const int ply)
428
{
429
   if (value >= -VALUE_ALMOST_MATED)
430
   {
431
      return (INT16) (value + ply);
432
   }
433
   else if (value <= VALUE_ALMOST_MATED)
434
   {
435
      return (INT16) (value - ply);
436
   }
437
 
438
   return (INT16) value;
439
}
440
 
441
/**
442
 * Calculate the effective value from the specified hashtable value.
443
 */
444
int calcEffectiveValue(const int value, const int ply)
445
{
446
   if (value >= -VALUE_ALMOST_MATED)
447
   {
448
      return value - ply;
449
   }
450
   else if (value <= VALUE_ALMOST_MATED)
451
   {
452
      return value + ply;
453
   }
454
 
455
   return value;
456
}
457
 
458
/**
459
 * Get all ordinary pieces (queens, rooks, bishops, knights)
460
 * of the specified color.
461
 */
462
Bitboard getOrdinaryPieces(const Position * position, const Color color)
463
{
464
   return position->piecesOfColor[color] &
465
      ~(position->piecesOfType[PAWN | color] |
466
        minValue[position->king[color]]);
467
}
468
 
469
/**
470
 * Get all non pawn pieces of the specified color.
471
 */
472
Bitboard getNonPawnPieces(const Position * position, const Color color)
473
{
474
   return position->piecesOfColor[color] &
475
      ~position->piecesOfType[PAWN | color];
476
}
477
 
478
/**
479
 * Get all ortho pieces (queens, rooks)
480
 * of the specified color.
481
 */
482
Bitboard getOrthoPieces(const Position * position, const Color color)
483
{
484
   return position->piecesOfType[ROOK | color] |
485
      position->piecesOfType[QUEEN | color];
486
}
487
 
488
/**
489
 * Check if the given moves are equal by ignoring their respective values.
490
 */
491
bool movesAreEqual(const Move m1, const Move m2)
492
{
493
   return (bool) ((m1 & 0xFFFF) == (m2 & 0xFFFF));
494
}
495
 
496
/**
497
 * Get the population count for the specified piece in the specified position.
498
 */
499
int getPieceCount(const Position * position, const Piece piece)
500
{
501
   return (int) ((position->pieceCount >> pieceCountShift[piece]) & 0x0F);
502
}
503
 
504
/**
505
 * Check if the specified piece is present in the specified position.
506
 */
507
bool pieceIsPresent(const Position * position, const Piece piece)
508
{
509
   return (bool) (position->piecesOfType[piece] != EMPTY_BITBOARD);
510
}
511
 
512
/**
513
 * Get the history index of the specified move.
514
 */
515
int historyIndex(const Move move, const Position * position)
516
{
517
   return (position->piece[getFromSquare(move)] << 6) + getToSquare(move);
518
}
519
 
520
/**
521
 * Calculate the distance to the next piece of a given type.
522
 *
523
 * @return the distance or 8 if no piece was found
524
 */
525
int getMinimalDistance(const Position * position,
526
                       const Square origin, const Piece piece)
527
{
528
   int distance;
529
 
530
   for (distance = 1; distance <= 7; distance++)
531
   {
532
      if ((squaresInDistance[distance][origin] &
533
           position->piecesOfType[piece]) != EMPTY_BITBOARD)
534
      {
535
         return distance;
536
      }
537
   }
538
 
539
   return 8;
540
}
541
 
542
/**
543
 * Calculate the distance to the next piece of a given type.
544
 *
545
 * @return the taxidistance or 15 if no piece was found
546
 */
547
int getMinimalTaxiDistance(const Position * position,
548
                           const Square origin, const Piece piece)
549
{
550
   int distance;
551
 
552
   for (distance = 1; distance <= 14; distance++)
553
   {
554
      if ((squaresInTaxiDistance[distance][origin] &
555
           position->piecesOfType[piece]) != EMPTY_BITBOARD)
556
      {
557
         return distance;
558
      }
559
   }
560
 
561
   return 15;
562
}
563
 
564
/**
565
 * Calculate the weight of the non-pawn-pieces of the specified color.
566
 *
567
 * @return a value in the range [0-103]
568
 */
569
int getPieceWeight(const Position * position, const Color color)
570
{
571
   const int numNonPawnPieces = numberOfNonPawnPieces(position, color) - 1;
572
   const int numRooks = getPieceCount(position, (Piece) (ROOK | color));
573
   const int numQueens = getPieceCount(position, (Piece) (QUEEN | color));
574
 
575
   return 6 * numQueens + 2 * numRooks + 3 * numNonPawnPieces;  /* q=9, r=5, b,n=3 */
576
}
577
 
578
/**
579
 * Calculate the phase index of the specified position.
580
 *
581
 * @return a value in the range [0(initial position)-256(endgame)]
582
 */
583
int phaseIndex(const Position * position)
584
{
585
   const int weightWhite = getPieceWeight(position, WHITE);
586
   const int weightBlack = getPieceWeight(position, BLACK);
587
   const int basicPhase = (weightWhite + weightBlack <= PIECE_WEIGHT_ENDGAME ?
588
                           PHASE_MAX :
589
                           max(0, PHASE_MAX - weightWhite - weightBlack));
590
 
591
   assert(getPieceWeight(position, WHITE) >= 0);
592
   assert(getPieceWeight(position, WHITE) <= 103);
593
   assert(getPieceWeight(position, BLACK) >= 0);
594
   assert(getPieceWeight(position, BLACK) <= 103);
595
   assert(basicPhase >= 0);
596
   assert(basicPhase <= PHASE_MAX);
597
 
598
   return (basicPhase * 256 + (PHASE_MAX / 2)) / PHASE_MAX;
599
}
600
 
601
/**
602
 * Get the piece counters from a material signature.
603
 */
604
void getPieceCounters(UINT32 materialSignature,
605
                      int *numWhiteQueens, int *numWhiteRooks,
606
                      int *numWhiteLightSquareBishops,
607
                      int *numWhiteDarkSquareBishops,
608
                      int *numWhiteKnights, int *numWhitePawns,
609
                      int *numBlackQueens, int *numBlackRooks,
610
                      int *numBlackLightSquareBishops,
611
                      int *numBlackDarkSquareBishops,
612
                      int *numBlackKnights, int *numBlackPawns)
613
{
614
   *numWhitePawns = materialSignature % 9;
615
   materialSignature /= 9;
616
   *numWhiteLightSquareBishops = materialSignature % 2;
617
   materialSignature /= 2;
618
   *numWhiteDarkSquareBishops = materialSignature % 2;
619
   materialSignature /= 2;
620
   *numWhiteQueens = materialSignature % 2;
621
   materialSignature /= 2;
622
   *numWhiteRooks = materialSignature % 3;
623
   materialSignature /= 3;
624
   *numWhiteKnights = materialSignature % 3;
625
   materialSignature /= 3;
626
 
627
   *numBlackPawns = materialSignature % 9;
628
   materialSignature /= 9;
629
   *numBlackLightSquareBishops = materialSignature % 2;
630
   materialSignature /= 2;
631
   *numBlackDarkSquareBishops = materialSignature % 2;
632
   materialSignature /= 2;
633
   *numBlackQueens = materialSignature % 2;
634
   materialSignature /= 2;
635
   *numBlackRooks = materialSignature % 3;
636
   materialSignature /= 3;
637
   *numBlackKnights = materialSignature % 3;
638
}
639
 
640
/**
641
 * Calculate a material signature from a white and a black signature.
642
 */
643
UINT32 bilateralSignature(const UINT32 signatureWhite,
644
                          const UINT32 signatureBlack)
645
{
646
   return signatureWhite + 648 * signatureBlack;
647
}
648
 
649
/**
650
 * Get the piece counters from a material signature.
651
 */
652
UINT32 getMaterialSignature(const int numWhiteQueens,
653
                            const int numWhiteRooks,
654
                            const int numWhiteLightSquareBishops,
655
                            const int numWhiteDarkSquareBishops,
656
                            const int numWhiteKnights,
657
                            const int numWhitePawns,
658
                            const int numBlackQueens,
659
                            const int numBlackRooks,
660
                            const int numBlackLightSquareBishops,
661
                            const int numBlackDarkSquareBishops,
662
                            const int numBlackKnights,
663
                            const int numBlackPawns)
664
{
665
   const int blackFactor = (3 * 3 * 2 * 2 * 2 * 9);
666
 
667
   return numWhitePawns +
668
      min(1, numWhiteLightSquareBishops) * 9 +
669
      min(1, numWhiteDarkSquareBishops) * (2 * 9) +
670
      min(1, numWhiteQueens) * (2 * 2 * 9) +
671
      min(2, numWhiteRooks) * (2 * 2 * 2 * 9) +
672
      min(2, numWhiteKnights) * (3 * 2 * 2 * 2 * 9) +
673
      numBlackPawns * blackFactor +
674
      min(1, numBlackLightSquareBishops) * 9 * blackFactor +
675
      min(1, numBlackDarkSquareBishops) * (2 * 9) * blackFactor +
676
      min(1, numBlackQueens) * (2 * 2 * 9) * blackFactor +
677
      min(2, numBlackRooks) * (2 * 2 * 2 * 9) * blackFactor +
678
      min(2, numBlackKnights) * (3 * 2 * 2 * 2 * 9) * blackFactor;
679
}
680
 
681
/**
682
 * Get the piece counters from a material signature.
683
 */
684
UINT32 getSingleMaterialSignature(const int numQueens,
685
                                  const int numRooks,
686
                                  const int numLightSquareBishops,
687
                                  const int numDarkSquareBishops,
688
                                  const int numKnights, const int numPawns)
689
{
690
   return getMaterialSignature(numQueens, numRooks,
691
                               numLightSquareBishops, numDarkSquareBishops,
692
                               numKnights, numPawns, 0, 0, 0, 0, 0, 0);
693
}
694
 
695
/**
696
 * Get the material signature for the specific position.
697
 */
698
UINT32 getMaterialSignatureFromPieceCount(const Position * position)
699
{
700
   return getMaterialSignature(getPieceCount(position, WHITE_QUEEN),
701
                               getPieceCount(position, WHITE_ROOK),
702
                               getPieceCount(position,
703
                                             (Piece) (WHITE_BISHOP_LIGHT)),
704
                               getPieceCount(position,
705
                                             (Piece) (WHITE_BISHOP_DARK)),
706
                               getPieceCount(position, WHITE_KNIGHT),
707
                               position->numberOfPawns[WHITE],
708
                               getPieceCount(position, BLACK_QUEEN),
709
                               getPieceCount(position, BLACK_ROOK),
710
                               getPieceCount(position,
711
                                             (Piece) (BLACK_BISHOP_LIGHT)),
712
                               getPieceCount(position,
713
                                             (Piece) (BLACK_BISHOP_DARK)),
714
                               getPieceCount(position, BLACK_KNIGHT),
715
                               position->numberOfPawns[BLACK]);
716
}
717
 
718
UINT32 calculateMaterialSignature(const Position * position)
719
{
720
   const UINT64 bbpWhite = ((position->pieceCount >> 8) & 0x0ff0) +
721
      position->numberOfPawns[WHITE];
722
   const UINT64 indexWhite = krqIndexWhite[position->pieceCount & 0x0Fff] +
723
      bbpIndexWhite[bbpWhite];
724
   const UINT64 bbpBlack = ((position->pieceCount >> 28) & 0x0ff0) +
725
      position->numberOfPawns[BLACK];
726
   const UINT64 indexBlack =
727
      krqIndexBlack[(position->pieceCount >> 20) & 0x0Fff] +
728
      bbpIndexBlack[bbpBlack];
729
 
730
   assert(bbpWhite < 4096);
731
   assert(bbpBlack < 4096);
732
   assert(indexWhite < 648);
733
   assert(indexBlack < 648 * 648);
734
 
735
   return (UINT32) (indexWhite + indexBlack);
736
}
737
 
738
static UINT64 calculateHashKey(const Position * position)
739
{
740
   UINT64 hashKey = ULONG_ZERO;
741
   Square square;
742
   Piece piece;
743
 
744
   ITERATE(square)
745
   {
746
      piece = position->piece[square];
747
 
748
      if (piece != NO_PIECE)
749
      {
750
         hashKey ^= GENERATED_KEYTABLE[piece][square];
751
      }
752
   }
753
 
754
   if (position->activeColor == BLACK)
755
   {
756
      hashKey = ~hashKey;
757
   }
758
 
759
   hashKey ^= GENERATED_KEYTABLE[0][position->castlingRights];
760
 
761
   if (position->enPassantSquare != NO_SQUARE)
762
   {
763
      hashKey ^= GENERATED_KEYTABLE[0][position->enPassantSquare];
764
   }
765
 
766
   return hashKey;
767
}
768
 
769
static UINT64 calculatePawnHashKey(const Position * position)
770
{
771
   UINT64 hashKey = ULONG_ZERO;
772
   Square square;
773
   Piece piece;
774
 
775
   ITERATE(square)
776
   {
777
      piece = position->piece[square];
778
 
779
      if (pieceType(piece) == PAWN)
780
      {
781
         hashKey ^= GENERATED_KEYTABLE[piece][square];
782
      }
783
   }
784
 
785
   return hashKey;
786
}
787
 
788
void clearPosition(Position * position)
789
{
790
   Square square;
791
 
792
   ITERATE(square)
793
   {
794
      position->piece[square] = NO_PIECE;
795
   }
796
 
797
   position->activeColor = WHITE;
798
   position->castlingRights = 0;
799
   position->enPassantSquare = NO_SQUARE;
800
   position->moveNumber = 1;
801
   position->halfMoveClock = 0;
802
}
803
 
804
void initializePosition(Position * position)
805
{
806
   int i;
807
   Square square;
808
 
809
   position->allPieces = EMPTY_BITBOARD;
810
   position->piecesOfColor[WHITE] = EMPTY_BITBOARD;
811
   position->piecesOfColor[BLACK] = EMPTY_BITBOARD;
812
   position->balance = 0;
813
   position->pieceCount = 0;
814
 
815
   for (i = 0x00; i <= 0x0F; i++)
816
   {
817
      position->piecesOfType[i] = EMPTY_BITBOARD;
818
   }
819
 
820
   if ((position->castlingRights & WHITE_00) &&
821
       (position->piece[E1] != WHITE_KING ||
822
        position->piece[H1] != WHITE_ROOK))
823
   {
824
      position->castlingRights -= WHITE_00;
825
   }
826
 
827
   if ((position->castlingRights & WHITE_000) &&
828
       (position->piece[E1] != WHITE_KING ||
829
        position->piece[A1] != WHITE_ROOK))
830
   {
831
      position->castlingRights -= WHITE_000;
832
   }
833
 
834
   if ((position->castlingRights & BLACK_00) &&
835
       (position->piece[E8] != BLACK_KING ||
836
        position->piece[H8] != BLACK_ROOK))
837
   {
838
      position->castlingRights -= BLACK_00;
839
   }
840
 
841
   if ((position->castlingRights & BLACK_000) &&
842
       (position->piece[E8] != BLACK_KING ||
843
        position->piece[A8] != BLACK_ROOK))
844
   {
845
      position->castlingRights -= BLACK_000;
846
   }
847
 
848
   if (position->enPassantSquare != NO_SQUARE)
849
   {
850
      if (position->activeColor == WHITE)
851
      {
852
         if (rank(position->enPassantSquare) != RANK_6 ||
853
             position->piece[position->enPassantSquare - 8] != BLACK_PAWN)
854
         {
855
            position->enPassantSquare = NO_SQUARE;
856
         }
857
      }
858
      else
859
      {
860
         if (rank(position->enPassantSquare) != RANK_3 ||
861
             position->piece[position->enPassantSquare + 8] != WHITE_PAWN)
862
         {
863
            position->enPassantSquare = NO_SQUARE;
864
         }
865
      }
866
   }
867
 
868
   ITERATE(square)
869
   {
870
      Piece piece = position->piece[square];
871
      Color color = pieceColor(piece);
872
 
873
      if (piece != NO_PIECE)
874
      {
875
         setSquare(position->allPieces, square);
876
         setSquare(position->piecesOfColor[color], square);
877
         setSquare(position->piecesOfType[piece], square);
878
 
879
         if (pieceType(piece) == KING)
880
         {
881
            position->king[color] = square;
882
         }
883
 
884
         addBonusForColor(pieceSquareBonus[piece][square], position, color);
885
 
886
         if (pieceType(piece) == BISHOP)
887
         {
888
            position->pieceCount += bishopPieceCountWeight[color][square];
889
         }
890
         else
891
         {
892
            position->pieceCount += pieceCountWeight[piece];
893
         }
894
      }
895
   }
896
 
897
   position->numberOfPieces[WHITE] =
898
      getNumberOfSetSquares(position->piecesOfColor[WHITE]);
899
   position->numberOfPieces[BLACK] =
900
      getNumberOfSetSquares(position->piecesOfColor[BLACK]);
901
   position->numberOfPawns[WHITE] =
902
      getNumberOfSetSquares(position->piecesOfType[WHITE_PAWN]);
903
   position->numberOfPawns[BLACK] =
904
      getNumberOfSetSquares(position->piecesOfType[BLACK_PAWN]);
905
 
906
   position->hashKey = calculateHashKey(position);
907
   position->pawnHashKey = calculatePawnHashKey(position);
908
}
909
 
910
void flipPosition(Position * position)
911
{
912
   Square square;
913
   BYTE castlingRights = 0;
914
 
915
   position->activeColor = opponent(position->activeColor);
916
 
917
   if (position->castlingRights & WHITE_00)
918
   {
919
      castlingRights += BLACK_00;
920
   }
921
 
922
   if (position->castlingRights & WHITE_000)
923
   {
924
      castlingRights += BLACK_000;
925
   }
926
 
927
   if (position->castlingRights & BLACK_00)
928
   {
929
      castlingRights += WHITE_00;
930
   }
931
 
932
   if (position->castlingRights & BLACK_000)
933
   {
934
      castlingRights += WHITE_000;
935
   }
936
 
937
   position->castlingRights = castlingRights;
938
 
939
   if (position->enPassantSquare != NO_SQUARE)
940
   {
941
      position->enPassantSquare = getFlippedSquare(position->enPassantSquare);
942
   }
943
 
944
   for (square = A1; square <= H4; square++)
945
   {
946
      const Square flippedSquare = getFlippedSquare(square);
947
      const Piece piece = position->piece[square];
948
 
949
      position->piece[square] =
950
         (position->piece[flippedSquare] == NO_PIECE ? NO_PIECE :
951
          (Piece) (position->piece[flippedSquare] ^ BLACK));
952
      position->piece[flippedSquare] =
953
         (piece == NO_PIECE ? NO_PIECE : (Piece) (piece ^ BLACK));
954
   }
955
}
956
 
957
void resetHistoryValues(Variation * variation)
958
{
959
   int i;
960
 
961
   for (i = 0; i < HISTORY_SIZE; i++)
962
   {
963
      variation->historyValue[i] = 0;
964
      variation->counterMove1[i] = variation->counterMove2[i] = NO_MOVE;
965
      variation->followupMove1[i] = variation->followupMove2[i] = NO_MOVE;
966
   }
967
}
968
 
969
void resetGainValues(Variation * variation)
970
{
971
   int i;
972
 
973
   for (i = 0; i < HISTORY_SIZE; i++)
974
   {
975
      variation->positionalGain[i] = 0;
976
   }
977
}
978
 
979
void prepareSearch(Variation * variation)
980
{
981
   int i;
982
 
983
   variation->nodes = variation->nodesAtTimeCheck = 0;
984
   variation->nodesBetweenTimecheck = NODES_BETWEEN_TIMECHECK_DEFAULT;
985
   initializePosition(&variation->singlePosition);
986
   variation->drawScore[WHITE] = variation->drawScore[BLACK] = 0;
987
   variation->bestMoveChangeCount = 0;
988
 
989
   for (i = 0; i < MAX_DEPTH_ARRAY_SIZE; i++)
990
   {
991
      PlyInfo *pi = &(variation->plyInfo[i]);
992
 
993
      pi->killerMove1 = pi->killerMove2 =
994
         pi->killerMove3 = pi->killerMove4 =
995
         pi->killerMove5 = pi->killerMove6 = NO_MOVE;
996
   }
997
}
998
 
999
void shrinkHistoryValues(Variation * variation)
1000
{
1001
   int i;
1002
 
1003
   for (i = 0; i < HISTORY_SIZE; i++)
1004
   {
1005
      variation->historyValue[i] = (variation->historyValue[i] + 1) / 2;
1006
   }
1007
}
1008
 
1009
void initializeVariation(Variation * variation, const char *fen)
1010
{
1011
   variation->ply = 0;
1012
   readFen(fen, &variation->singlePosition);
1013
   prepareSearch(variation);
1014
   variation->startPosition = variation->singlePosition;
1015
}
1016
 
1017
void setBasePosition(Variation * variation, const Position * position)
1018
{
1019
   variation->ply = 0;
1020
   variation->singlePosition = *position;
1021
   variation->startPosition = variation->singlePosition;
1022
}
1023
 
1024
void setDrawScore(Variation * variation, int score, Color color)
1025
{
1026
   variation->drawScore[color] = score;
1027
   variation->drawScore[opponent(color)] = -score;
1028
}
1029
 
1030
Bitboard getInterestedPieces(const Position * position, const Square square,
1031
                             const Color attackerColor)
1032
{
1033
   Bitboard king = getKingMoves(square);
1034
   Bitboard dia = getMagicBishopMoves(square, position->allPieces);
1035
   Bitboard ortho = getMagicRookMoves(square, position->allPieces);
1036
   Bitboard knights = getKnightMoves(square);
1037
   Bitboard pawns = getInterestedPawns(attackerColor, square,
1038
                                       position->allPieces);
1039
 
1040
   king &= position->piecesOfType[KING | attackerColor];
1041
   ortho &= (position->piecesOfType[QUEEN | attackerColor] |
1042
             position->piecesOfType[ROOK | attackerColor]);
1043
   dia &= (position->piecesOfType[QUEEN | attackerColor] |
1044
           position->piecesOfType[BISHOP | attackerColor]);
1045
   knights &= position->piecesOfType[KNIGHT | attackerColor];
1046
   pawns &= position->piecesOfType[PAWN | attackerColor];
1047
 
1048
   return king | ortho | dia | knights | pawns;
1049
}
1050
 
1051
int checkVariation(Variation * variation)
1052
{
1053
   if (checkConsistency(&variation->singlePosition) != 0)
1054
   {
1055
      logDebug("consistency check failed!\n");
1056
 
1057
      dumpVariation(variation);
1058
   }
1059
 
1060
   return 0;
1061
}
1062
 
1063
int makeMove(Variation * variation, const Move move)
1064
{
1065
   Position *position = &variation->singlePosition;
1066
   PlyInfo *plyInfo = &variation->plyInfo[variation->ply++];
1067
   const Square from = getFromSquare(move);
1068
   const Square to = getToSquare(move);
1069
   const Piece newPiece = getNewPiece(move);
1070
   const Piece movingPiece = position->piece[from];
1071
   const Piece capturedPiece = position->piece[to];
1072
   const Color activeColor = position->activeColor;
1073
   const Color passiveColor = opponent(activeColor);
1074
   const Bitboard minTo = minValue[to];
1075
   const Bitboard maxFrom = maxValue[from];
1076
   int result = 0;
1077
 
1078
   assert(to == from || pieceType(capturedPiece) != KING);
1079
 
1080
   variation->positionHistory[POSITION_HISTORY_OFFSET - 1 + variation->ply] =
1081
      plyInfo->hashKey = position->hashKey;
1082
   plyInfo->currentMove = move;
1083
   plyInfo->balance = position->balance;
1084
   position->hashKey = ~position->hashKey;
1085
 
1086
   if (position->enPassantSquare != NO_SQUARE)
1087
   {
1088
      position->hashKey ^= GENERATED_KEYTABLE[0][position->enPassantSquare];
1089
   }
1090
 
1091
   plyInfo->pawnHashKey = position->pawnHashKey;
1092
   plyInfo->enPassantSquare = position->enPassantSquare;
1093
   position->enPassantSquare = NO_SQUARE;
1094
   position->activeColor = passiveColor;
1095
 
1096
   if (to == from)
1097
   {
1098
      assert(checkVariation(variation) == 0);
1099
 
1100
      return result;            /* Nullmove */
1101
   }
1102
 
1103
   plyInfo->captured = capturedPiece;
1104
   plyInfo->kingSquare = position->king[activeColor];
1105
   plyInfo->castlingRights = position->castlingRights;
1106
   plyInfo->halfMoveClock = position->halfMoveClock;
1107
   plyInfo->allPieces = position->allPieces;
1108
   plyInfo->whitePieces = position->piecesOfColor[WHITE];
1109
   plyInfo->blackPieces = position->piecesOfColor[BLACK];
1110
   plyInfo->pieceCount = position->pieceCount;
1111
   variation->plyInfo[variation->ply].staticValueAvailable = FALSE;
1112
   variation->plyInfo[variation->ply].gainsUpdated = FALSE;
1113
   position->piecesOfColor[activeColor] &= maxFrom;
1114
   position->piecesOfColor[activeColor] |= minTo;
1115
   position->piecesOfType[movingPiece] &= maxFrom;
1116
   position->hashKey ^=
1117
      GENERATED_KEYTABLE[movingPiece][from] ^
1118
      GENERATED_KEYTABLE[movingPiece][to];
1119
   position->castlingRights &=
1120
      remainingCastlings[to] & remainingCastlings[from];
1121
 
1122
   if (position->castlingRights != plyInfo->castlingRights)
1123
   {
1124
      position->hashKey ^=
1125
         GENERATED_KEYTABLE[0][plyInfo->castlingRights] ^
1126
         GENERATED_KEYTABLE[0][position->castlingRights];
1127
   }
1128
 
1129
   position->halfMoveClock++;
1130
   position->piece[to] = movingPiece;
1131
   position->piece[from] = NO_PIECE;
1132
   addBonusForColor(pieceSquareBonus[movingPiece][to] -
1133
                    pieceSquareBonus[movingPiece][from], position,
1134
                    activeColor);
1135
 
1136
   if (capturedPiece != NO_PIECE)
1137
   {
1138
      position->halfMoveClock = 0;
1139
      position->piecesOfColor[passiveColor] &= ~minTo;
1140
      position->piecesOfType[capturedPiece] &= ~minTo;
1141
      position->numberOfPieces[passiveColor]--;
1142
 
1143
      if (pieceType(capturedPiece) == PAWN)
1144
      {
1145
         position->numberOfPawns[passiveColor]--;
1146
         position->pawnHashKey ^= GENERATED_KEYTABLE[capturedPiece][to];
1147
      }
1148
      else
1149
      {
1150
         position->pieceCount -= (capturedPiece == (BISHOP | passiveColor) ?
1151
                                  bishopPieceCountWeight[passiveColor][to] :
1152
                                  pieceCountWeight[capturedPiece]);
1153
      }
1154
 
1155
      position->hashKey ^= GENERATED_KEYTABLE[capturedPiece][to];
1156
      addBonusForColor(pieceSquareBonus[capturedPiece][to], position,
1157
                       activeColor);
1158
   }
1159
 
1160
   if (pieceType(movingPiece) == PAWN)
1161
   {
1162
      position->halfMoveClock = 0;
1163
      position->pawnHashKey ^=
1164
         GENERATED_KEYTABLE[movingPiece][from] ^
1165
         GENERATED_KEYTABLE[movingPiece][to];
1166
 
1167
      if (distance(from, to) == 2)
1168
      {
1169
         position->enPassantSquare = (Square) ((from + to) >> 1);
1170
         position->hashKey ^=
1171
            GENERATED_KEYTABLE[0][position->enPassantSquare];
1172
      }
1173
      else if (to == plyInfo->enPassantSquare)
1174
      {
1175
         const Square captureSquare =
1176
            (Square) (to + (rank(from) - rank(to)) * 8);
1177
         const Piece capturedPawn = position->piece[captureSquare];
1178
 
1179
         clearSquare(position->piecesOfColor[passiveColor], captureSquare);
1180
         clearSquare(position->piecesOfType[capturedPawn], captureSquare);
1181
         position->hashKey ^= GENERATED_KEYTABLE[capturedPawn][captureSquare];
1182
         position->pawnHashKey ^=
1183
            GENERATED_KEYTABLE[capturedPawn][captureSquare];
1184
         addBonusForColor(pieceSquareBonus[capturedPawn][captureSquare],
1185
                          position, activeColor);
1186
 
1187
         plyInfo->restoreSquare1 = captureSquare;
1188
         plyInfo->restorePiece1 = capturedPawn;
1189
         position->piece[captureSquare] = NO_PIECE;
1190
         position->numberOfPieces[passiveColor]--;
1191
         position->numberOfPawns[passiveColor]--;
1192
      }
1193
      else if (newPiece != NO_PIECE)
1194
      {
1195
         const Piece effectiveNewPiece = (Piece) (newPiece | activeColor);
1196
 
1197
         plyInfo->restoreSquare1 = from;
1198
         plyInfo->restorePiece1 = movingPiece;
1199
         position->piece[to] = effectiveNewPiece;
1200
         position->numberOfPawns[activeColor]--;
1201
         position->pieceCount +=
1202
            (newPiece == (Piece) BISHOP ?
1203
             bishopPieceCountWeight[activeColor][to] :
1204
             pieceCountWeight[effectiveNewPiece]);
1205
         position->hashKey ^=
1206
            GENERATED_KEYTABLE[movingPiece][to] ^
1207
            GENERATED_KEYTABLE[effectiveNewPiece][to];
1208
         position->pawnHashKey ^= GENERATED_KEYTABLE[movingPiece][to];
1209
         addBonusForColor(pieceSquareBonus[effectiveNewPiece][to] -
1210
                          pieceSquareBonus[movingPiece][to],
1211
                          position, activeColor);
1212
         setSquare(position->piecesOfType[position->piece[to]], to);
1213
      }
1214
   }
1215
 
1216
   else if (pieceType(movingPiece) == KING)
1217
   {
1218
      position->king[activeColor] = to;
1219
 
1220
      if (distance(from, to) == 2)
1221
      {
1222
         const Square rookFrom = rookOrigin[to];
1223
         const Square rookTo = (Square) ((from + to) >> 1);
1224
         const Piece movingRook = position->piece[rookFrom];
1225
 
1226
         plyInfo->restoreSquare1 = rookFrom;
1227
         plyInfo->restorePiece1 = movingRook;
1228
         plyInfo->restoreSquare2 = rookTo;
1229
         plyInfo->restorePiece2 = position->piece[rookTo];
1230
         position->piece[rookFrom] = NO_PIECE;
1231
         position->piece[rookTo] = movingRook;
1232
         position->halfMoveClock = 0;
1233
 
1234
         setSquare(position->piecesOfColor[activeColor], rookTo);
1235
         clearSquare(position->piecesOfColor[activeColor], rookFrom);
1236
         setSquare(position->piecesOfType[movingRook], rookTo);
1237
         clearSquare(position->piecesOfType[movingRook], rookFrom);
1238
         position->hashKey ^=
1239
            GENERATED_KEYTABLE[movingRook][rookFrom] ^
1240
            GENERATED_KEYTABLE[movingRook][rookTo];
1241
         addBonusForColor(pieceSquareBonus[movingRook][rookTo] -
1242
                          pieceSquareBonus[movingRook][rookFrom],
1243
                          position, activeColor);
1244
 
1245
         if (getDirectAttackers(position, from, passiveColor,
1246
                                position->allPieces) != EMPTY_BITBOARD ||
1247
             getDirectAttackers(position, rookTo, passiveColor,
1248
                                position->allPieces) != EMPTY_BITBOARD)
1249
         {
1250
            result = 1;         /* castling move was not legal */
1251
         }
1252
      }
1253
   }
1254
 
1255
   setSquare(position->piecesOfType[position->piece[to]], to);
1256
   position->allPieces =
1257
      position->piecesOfColor[WHITE] | position->piecesOfColor[BLACK];
1258
 
1259
   assert(checkVariation(variation) == 0);
1260
 
1261
   return result;
1262
}
1263
 
1264
#define PERSPECTIVE_WHITE
1265
#include "positionc.c"
1266
#undef PERSPECTIVE_WHITE
1267
#include "positionc.c"
1268
 
1269
int makeMoveFast(Variation * variation, const Move move)
1270
{
1271
   if (variation->singlePosition.activeColor == WHITE)
1272
   {
1273
      return makeWhiteMove(variation, move);
1274
   }
1275
   else
1276
   {
1277
      return makeBlackMove(variation, move);
1278
   }
1279
}
1280
 
1281
void unmakeLastMove(Variation * variation)
1282
{
1283
   Position *position = &variation->singlePosition;
1284
   const PlyInfo *plyInfo = &variation->plyInfo[--variation->ply];
1285
   const Move move = plyInfo->currentMove;
1286
   const Square from = getFromSquare(move);
1287
   const Square to = getToSquare(move);
1288
   const Piece newPiece = getNewPiece(move);
1289
   const Color activeColor = position->activeColor =
1290
      opponent(position->activeColor);
1291
 
1292
   position->enPassantSquare = plyInfo->enPassantSquare;
1293
   position->hashKey = plyInfo->hashKey;
1294
 
1295
   if (from == to)
1296
   {
1297
      assert(checkVariation(variation) == 0);
1298
 
1299
      return;                   /* Nullmove */
1300
   }
1301
 
1302
   position->pawnHashKey = plyInfo->pawnHashKey;
1303
   clearSquare(position->piecesOfType[position->piece[to]], to);
1304
   position->king[activeColor] = plyInfo->kingSquare;
1305
   position->piece[from] = position->piece[to];
1306
   position->piece[to] = plyInfo->captured;
1307
   position->pieceCount = plyInfo->pieceCount;
1308
 
1309
   if (newPiece != NO_PIECE)
1310
   {
1311
      position->numberOfPawns[activeColor]++;
1312
      position->piece[plyInfo->restoreSquare1] = plyInfo->restorePiece1;
1313
   }
1314
 
1315
   setSquare(position->piecesOfType[position->piece[from]], from);
1316
   position->halfMoveClock = plyInfo->halfMoveClock;
1317
   position->castlingRights = plyInfo->castlingRights;
1318
   position->piecesOfColor[WHITE] = plyInfo->whitePieces;
1319
   position->piecesOfColor[BLACK] = plyInfo->blackPieces;
1320
   position->allPieces = plyInfo->allPieces;
1321
   position->balance = plyInfo->balance;
1322
 
1323
   if (plyInfo->captured != NO_PIECE)
1324
   {
1325
      const Color passiveColor = opponent(activeColor);
1326
 
1327
      setSquare(position->piecesOfType[plyInfo->captured], to);
1328
      position->numberOfPieces[passiveColor]++;
1329
 
1330
      if (pieceType(plyInfo->captured) == PAWN)
1331
      {
1332
         position->numberOfPawns[passiveColor]++;
1333
      }
1334
   }
1335
   else if (to == plyInfo->enPassantSquare &&
1336
            pieceType(position->piece[from]) == PAWN)
1337
   {
1338
      const Color passiveColor = opponent(activeColor);
1339
 
1340
      position->piece[plyInfo->restoreSquare1] = plyInfo->restorePiece1;
1341
      setSquare(position->piecesOfType[plyInfo->restorePiece1],
1342
                plyInfo->restoreSquare1);
1343
      position->numberOfPieces[passiveColor]++;
1344
      position->numberOfPawns[passiveColor]++;
1345
   }
1346
   else if (distance(from, to) == 2 &&
1347
            pieceType(position->piece[from]) == KING)
1348
   {
1349
      position->piece[plyInfo->restoreSquare1] = plyInfo->restorePiece1;
1350
      position->piece[plyInfo->restoreSquare2] = plyInfo->restorePiece2;
1351
      setSquare(position->piecesOfType[plyInfo->restorePiece1],
1352
                plyInfo->restoreSquare1);
1353
      clearSquare(position->piecesOfType[plyInfo->restorePiece1],
1354
                  plyInfo->restoreSquare2);
1355
   }
1356
 
1357
   assert(checkVariation(variation) == 0);
1358
}
1359
 
1360
bool moveIsCheck(const Move move, const Position * position)
1361
{
1362
   const Square kingSquare = position->king[opponent(position->activeColor)];
1363
   const Square from = getFromSquare(move);
1364
   const Square to = getToSquare(move);
1365
   const Piece piece = position->piece[from];
1366
 
1367
   if (testSquare(generalMoves[QUEEN][kingSquare], from) &&
1368
       (position->allPieces & squaresBetween[kingSquare][from]) ==
1369
       EMPTY_BITBOARD &&
1370
       testSquare(squaresBetween[kingSquare][from], to) == FALSE &&
1371
       testSquare(squaresBehind[from][kingSquare], to) == FALSE)
1372
   {
1373
      /* Detect undiscovered check: */
1374
 
1375
      const Color color = position->activeColor;
1376
      Bitboard batteryPieces;
1377
      Square square;
1378
 
1379
      if (rank(from) == rank(kingSquare) || file(from) == file(kingSquare))
1380
      {
1381
         batteryPieces = squaresBehind[from][kingSquare] &
1382
            (position->piecesOfType[ROOK | color] |
1383
             position->piecesOfType[QUEEN | color]);
1384
      }
1385
      else
1386
      {
1387
         batteryPieces = squaresBehind[from][kingSquare] &
1388
            (position->piecesOfType[BISHOP | color] |
1389
             position->piecesOfType[QUEEN | color]);
1390
      }
1391
 
1392
      ITERATE_BITBOARD(&batteryPieces, square)
1393
      {
1394
         if ((squaresBetween[square][kingSquare] & position->allPieces) ==
1395
             minValue[from])
1396
         {
1397
            return TRUE;
1398
         }
1399
      }
1400
   }
1401
 
1402
   /* No undiscovered check: */
1403
 
1404
   if (piece & PP_SLIDING_PIECE)
1405
   {
1406
      return (bool)
1407
         (testSquare(generalMoves[pieceType(piece)][to], kingSquare) &&
1408
          (position->allPieces & squaresBetween[kingSquare][to]) ==
1409
          EMPTY_BITBOARD);
1410
   }
1411
   else if (pieceType(piece) == KNIGHT)
1412
   {
1413
      return (testSquare(generalMoves[KNIGHT][kingSquare], to) !=
1414
              EMPTY_BITBOARD);
1415
   }
1416
   else if (pieceType(piece) == PAWN)
1417
   {
1418
      const Piece newPiece = getNewPiece(move);
1419
 
1420
      if (newPiece == NO_PIECE)
1421
      {
1422
         if (testSquare(generalMoves[piece][to], kingSquare) != FALSE)
1423
         {
1424
            return TRUE;
1425
         }
1426
 
1427
         if (to == position->enPassantSquare)
1428
         {
1429
            const Square captureSquare =
1430
               (Square) (to + (rank(from) - rank(to)) * 8);
1431
 
1432
            if (testSquare(generalMoves[QUEEN][kingSquare], captureSquare) &&
1433
                (squaresBetween[captureSquare][kingSquare] &
1434
                 position->allPieces) == EMPTY_BITBOARD)
1435
            {
1436
               const Color color = position->activeColor;
1437
               Bitboard batteryPieces;
1438
               const Bitboard blockers = minValue[to] |
1439
                  (position->allPieces & maxValue[captureSquare] &
1440
                   maxValue[from]);
1441
               Square square;
1442
 
1443
               if (rank(captureSquare) == rank(kingSquare) ||
1444
                   file(captureSquare) == file(kingSquare))
1445
               {
1446
                  batteryPieces = squaresBehind[captureSquare][kingSquare] &
1447
                     (position->piecesOfType[ROOK | color] |
1448
                      position->piecesOfType[QUEEN | color]);
1449
               }
1450
               else
1451
               {
1452
                  batteryPieces = squaresBehind[captureSquare][kingSquare] &
1453
                     (position->piecesOfType[BISHOP | color] |
1454
                      position->piecesOfType[QUEEN | color]);
1455
               }
1456
 
1457
               ITERATE_BITBOARD(&batteryPieces, square)
1458
               {
1459
                  if ((squaresBetween[kingSquare][square] & blockers) ==
1460
                      EMPTY_BITBOARD)
1461
                  {
1462
                     return TRUE;
1463
                  }
1464
               }
1465
            }
1466
         }
1467
      }
1468
      else
1469
      {
1470
         if (newPiece & PP_SLIDING_PIECE)
1471
         {
1472
            const Bitboard blockers = position->allPieces & maxValue[from];
1473
 
1474
            return (bool)
1475
               (testSquare(generalMoves[newPiece][to], kingSquare) &&
1476
                (blockers & squaresBetween[kingSquare][to]) ==
1477
                EMPTY_BITBOARD);
1478
         }
1479
         else
1480
         {
1481
            return (testSquare(generalMoves[KNIGHT][kingSquare], to) !=
1482
                    EMPTY_BITBOARD);
1483
         }
1484
      }
1485
   }
1486
   else if (pieceType(piece) == KING && abs(to - from) == 2)
1487
   {
1488
      const Bitboard blockers = position->allPieces & maxValue[from];
1489
      const int rookSquare = (to + from) / 2;
1490
 
1491
      return (bool)
1492
         (testSquare(generalMoves[ROOK][rookSquare], kingSquare) &&
1493
          (blockers & squaresBetween[kingSquare][rookSquare]) ==
1494
          EMPTY_BITBOARD);
1495
   }
1496
 
1497
   return FALSE;
1498
}
1499
 
1500
int checkConsistency(const Position * position)
1501
{
1502
   Square square;
1503
   int numPieces[2], numPawns[2], value[2], i;
1504
   int openingValue[2], endgameValue[2];
1505
   INT32 balance = 0;
1506
   Bitboard temp;
1507
   BYTE obstacles[NUM_LANES];
1508
   UINT32 materialSignature = calculateMaterialSignature(position);
1509
 
1510
   numPieces[WHITE] = numPieces[BLACK] = 0;
1511
   numPawns[WHITE] = numPawns[BLACK] = 0;
1512
   memset(obstacles, 0x00, NUM_LANES);
1513
   value[WHITE] = value[BLACK] = 0;
1514
   openingValue[WHITE] = openingValue[BLACK] = 0;
1515
   endgameValue[WHITE] = endgameValue[BLACK] = 0;
1516
 
1517
   assert(position->activeColor == WHITE || position->activeColor == BLACK);
1518
   assert(getMaterialSignatureFromPieceCount(position) == materialSignature);
1519
 
1520
   {
1521
      int calculatedNumWhiteQueens;
1522
      int calculatedNumWhiteRooks;
1523
      int calculatedNumWhiteLightSquareBishops;
1524
      int calculatedNumWhiteDarkSquareBishops;
1525
      int calculatedNumWhiteKnights;
1526
      int calculatedNumWhitePawns;
1527
      int calculatedNumBlackQueens;
1528
      int calculatedNumBlackRooks;
1529
      int calculatedNumBlackLightSquareBishops;
1530
      int calculatedNumBlackDarkSquareBishops;
1531
      int calculatedNumBlackKnights;
1532
      int calculatedNumBlackPawns;
1533
 
1534
      getPieceCounters(materialSignature,
1535
                       &calculatedNumWhiteQueens, &calculatedNumWhiteRooks,
1536
                       &calculatedNumWhiteLightSquareBishops,
1537
                       &calculatedNumWhiteDarkSquareBishops,
1538
                       &calculatedNumWhiteKnights,
1539
                       &calculatedNumWhitePawns, &calculatedNumBlackQueens,
1540
                       &calculatedNumBlackRooks,
1541
                       &calculatedNumBlackLightSquareBishops,
1542
                       &calculatedNumBlackDarkSquareBishops,
1543
                       &calculatedNumBlackKnights, &calculatedNumBlackPawns);
1544
 
1545
      assert(getPieceCount(position, WHITE_QUEEN) > 1 ||
1546
             getPieceCount(position, WHITE_QUEEN) ==
1547
             calculatedNumWhiteQueens);
1548
      assert(getPieceCount(position, WHITE_ROOK) > 2 ||
1549
             getPieceCount(position, WHITE_ROOK) == calculatedNumWhiteRooks);
1550
      assert(getPieceCount(position, WHITE_BISHOP_LIGHT) > 1 ||
1551
             getPieceCount(position, WHITE_BISHOP_LIGHT) ==
1552
             calculatedNumWhiteLightSquareBishops);
1553
      assert(getPieceCount(position, WHITE_BISHOP_DARK) > 1 ||
1554
             getPieceCount(position, WHITE_BISHOP_DARK) ==
1555
             calculatedNumWhiteDarkSquareBishops);
1556
      assert(getPieceCount(position, WHITE_KNIGHT) > 2 ||
1557
             getPieceCount(position, WHITE_KNIGHT) ==
1558
             calculatedNumWhiteKnights);
1559
      assert(position->numberOfPawns[WHITE] == calculatedNumWhitePawns);
1560
      assert(getPieceCount(position, BLACK_QUEEN) > 1 ||
1561
             getPieceCount(position, BLACK_QUEEN) ==
1562
             calculatedNumBlackQueens);
1563
      assert(getPieceCount(position, BLACK_ROOK) > 2 ||
1564
             getPieceCount(position, BLACK_ROOK) == calculatedNumBlackRooks);
1565
      assert(getPieceCount(position, BLACK_BISHOP_LIGHT) > 1 ||
1566
             getPieceCount(position, BLACK_BISHOP_LIGHT) ==
1567
             calculatedNumBlackLightSquareBishops);
1568
      assert(getPieceCount(position, BLACK_BISHOP_DARK) > 1 ||
1569
             getPieceCount(position, BLACK_BISHOP_DARK) ==
1570
             calculatedNumBlackDarkSquareBishops);
1571
      assert(getPieceCount(position, BLACK_KNIGHT) > 2 ||
1572
             getPieceCount(position, BLACK_KNIGHT) ==
1573
             calculatedNumBlackKnights);
1574
      assert(position->numberOfPawns[BLACK] == calculatedNumBlackPawns);
1575
 
1576
      if (getPieceCount(position, WHITE_QUEEN) <= 1 &&
1577
          getPieceCount(position, WHITE_ROOK) <= 2 &&
1578
          getPieceCount(position, WHITE_BISHOP_LIGHT) <= 1 &&
1579
          getPieceCount(position, WHITE_BISHOP_DARK) <= 1 &&
1580
          getPieceCount(position, WHITE_KNIGHT) <= 2 &&
1581
          getPieceCount(position, BLACK_QUEEN) <= 1 &&
1582
          getPieceCount(position, BLACK_ROOK) <= 2 &&
1583
          getPieceCount(position, BLACK_BISHOP_LIGHT) <= 1 &&
1584
          getPieceCount(position, BLACK_BISHOP_DARK) <= 1 &&
1585
          getPieceCount(position, BLACK_KNIGHT) <= 2)
1586
      {
1587
         const MaterialInfo *mi = &materialInfo[materialSignature];
1588
 
1589
         if (mi->materialBalance != materialBalance(position))
1590
         {
1591
            logDebug("mimb=%d cmb=%d\n", mi->materialBalance,
1592
                     materialBalance(position));
1593
            dumpPosition(position);
1594
         }
1595
 
1596
         assert(mi->materialBalance == materialBalance(position));
1597
         assert(mi->phaseIndex == phaseIndex(position));
1598
      }
1599
   }
1600
 
1601
   if (position->castlingRights & WHITE_00)
1602
   {
1603
      assert(position->piece[E1] == WHITE_KING);
1604
      assert(position->piece[H1] == WHITE_ROOK);
1605
   }
1606
 
1607
   if (position->castlingRights & WHITE_000)
1608
   {
1609
      assert(position->piece[E1] == WHITE_KING);
1610
      assert(position->piece[A1] == WHITE_ROOK);
1611
   }
1612
 
1613
   if (position->castlingRights & BLACK_00)
1614
   {
1615
      assert(position->piece[E8] == BLACK_KING);
1616
      assert(position->piece[H8] == BLACK_ROOK);
1617
   }
1618
 
1619
   if (position->castlingRights & BLACK_000)
1620
   {
1621
      assert(position->piece[E8] == BLACK_KING);
1622
      assert(position->piece[A8] == BLACK_ROOK);
1623
   }
1624
 
1625
   assert(position->enPassantSquare == NO_SQUARE ||
1626
          squareIsValid(position->enPassantSquare));
1627
 
1628
   if (position->enPassantSquare != NO_SQUARE)
1629
   {
1630
      if (position->activeColor == WHITE)
1631
      {
1632
         assert(rank(position->enPassantSquare) == RANK_6);
1633
         assert(position->piece[position->enPassantSquare - 8] == BLACK_PAWN);
1634
      }
1635
      else
1636
      {
1637
         assert(rank(position->enPassantSquare) == RANK_3);
1638
         assert(position->piece[position->enPassantSquare + 8] == WHITE_PAWN);
1639
      }
1640
   }
1641
 
1642
   assert((position->piecesOfColor[WHITE] ^ position->piecesOfColor[BLACK]) ==
1643
          position->allPieces);
1644
 
1645
   temp = EMPTY_BITBOARD;
1646
 
1647
   for (i = 1; i <= 0x0F; i++)
1648
   {
1649
      temp ^= position->piecesOfType[i];
1650
   }
1651
 
1652
   assert(temp == position->allPieces);
1653
 
1654
   assert(squareIsValid(position->king[WHITE]));
1655
   assert(position->piece[position->king[WHITE]] == WHITE_KING);
1656
   assert(squareIsValid(position->king[BLACK]));
1657
   assert(position->piece[position->king[BLACK]] == BLACK_KING);
1658
   assert(testSquare
1659
          (position->piecesOfType[WHITE_KING], position->king[WHITE]));
1660
   assert(getNumberOfSetSquares(position->piecesOfType[WHITE_KING]) == 1);
1661
   assert(testSquare
1662
          (position->piecesOfType[BLACK_KING], position->king[BLACK]));
1663
   assert(getNumberOfSetSquares(position->piecesOfType[BLACK_KING]) == 1);
1664
 
1665
   assert(getNumberOfSetSquares(position->piecesOfType[WHITE_QUEEN]) ==
1666
          getPieceCount(position, WHITE_QUEEN));
1667
   assert(getNumberOfSetSquares(position->piecesOfType[WHITE_ROOK]) ==
1668
          getPieceCount(position, WHITE_ROOK));
1669
   assert(getNumberOfSetSquares
1670
          (position->piecesOfType[WHITE_BISHOP] & lightSquares) ==
1671
          getPieceCount(position, WHITE_BISHOP_LIGHT));
1672
   assert(getNumberOfSetSquares
1673
          (position->piecesOfType[WHITE_BISHOP] & darkSquares) ==
1674
          getPieceCount(position, WHITE_BISHOP_DARK));
1675
   assert(getNumberOfSetSquares(position->piecesOfType[WHITE_KNIGHT]) ==
1676
          getPieceCount(position, WHITE_KNIGHT));
1677
   assert(getNumberOfSetSquares(position->piecesOfType[BLACK_QUEEN]) ==
1678
          getPieceCount(position, BLACK_QUEEN));
1679
   assert(getNumberOfSetSquares(position->piecesOfType[BLACK_ROOK]) ==
1680
          getPieceCount(position, BLACK_ROOK));
1681
   assert(getNumberOfSetSquares
1682
          (position->piecesOfType[BLACK_BISHOP] & lightSquares) ==
1683
          getPieceCount(position, BLACK_BISHOP_LIGHT));
1684
   assert(getNumberOfSetSquares
1685
          (position->piecesOfType[BLACK_BISHOP] & darkSquares) ==
1686
          getPieceCount(position, BLACK_BISHOP_DARK));
1687
   assert(getNumberOfSetSquares(position->piecesOfType[BLACK_KNIGHT]) ==
1688
          getPieceCount(position, BLACK_KNIGHT));
1689
 
1690
   ITERATE(square)
1691
   {
1692
      Piece piece = position->piece[square];
1693
      PieceType pieceType = pieceType(piece);
1694
      Color color = pieceColor(piece);
1695
 
1696
      assert(piece >= 0 && piece <= 15);
1697
 
1698
      if (piece != NO_PIECE)
1699
      {
1700
         numPieces[color]++;
1701
         setObstacleSquare(square, obstacles);
1702
 
1703
         assert(testSquare(position->allPieces, square));
1704
         assert(testSquare(position->piecesOfColor[color], square));
1705
         assert(testSquare(position->piecesOfType[piece], square));
1706
 
1707
         if (pieceType == PAWN)
1708
         {
1709
            numPawns[color]++;
1710
         }
1711
 
1712
         if (pieceType != KING)
1713
         {
1714
            value[color] += basicValue[piece];
1715
         }
1716
 
1717
         openingValue[color] +=
1718
            getOpeningValue(pieceSquareBonus[piece][square]);
1719
         endgameValue[color] +=
1720
            getEndgameValue(pieceSquareBonus[piece][square]);
1721
 
1722
         if (color == WHITE)
1723
         {
1724
            balance += pieceSquareBonus[piece][square];
1725
         }
1726
         else
1727
         {
1728
            balance -= pieceSquareBonus[piece][square];
1729
         }
1730
      }
1731
      else
1732
      {
1733
         assert(testSquare(position->allPieces, square) == FALSE);
1734
         assert(testSquare(position->piecesOfColor[WHITE], square) == FALSE);
1735
         assert(testSquare(position->piecesOfColor[BLACK], square) == FALSE);
1736
      }
1737
   }
1738
 
1739
   assert(numPieces[WHITE] == position->numberOfPieces[WHITE]);
1740
   assert(numPieces[WHITE] >= 1);
1741
   assert(numPieces[WHITE] <= 16);
1742
   assert(numPieces[WHITE] ==
1743
          getNumberOfSetSquares(position->piecesOfColor[WHITE]));
1744
   assert(numPieces[BLACK] == position->numberOfPieces[BLACK]);
1745
   assert(numPieces[BLACK] >= 1);
1746
   assert(numPieces[BLACK] <= 16);
1747
   assert(numPieces[BLACK] ==
1748
          getNumberOfSetSquares(position->piecesOfColor[BLACK]));
1749
 
1750
   assert(numPawns[WHITE] == position->numberOfPawns[WHITE]);
1751
   assert(numPawns[WHITE] >= 0);
1752
   assert(numPawns[WHITE] <= 8);
1753
   assert(numPawns[WHITE] ==
1754
          getNumberOfSetSquares(position->piecesOfType[WHITE_PAWN]));
1755
   assert(numPawns[BLACK] == position->numberOfPawns[BLACK]);
1756
   assert(numPawns[BLACK] >= 0);
1757
   assert(numPawns[BLACK] <= 8);
1758
   assert(numPawns[BLACK] ==
1759
          getNumberOfSetSquares(position->piecesOfType[BLACK_PAWN]));
1760
   assert(balance == position->balance);
1761
 
1762
   assert(calculateHashKey(position) == position->hashKey);
1763
   assert(calculatePawnHashKey(position) == position->pawnHashKey);
1764
 
1765
   return 0;
1766
}
1767
 
1768
bool positionIsLegal(const Position * position)
1769
{
1770
   Square square;
1771
   int numPieces[2], numPawns[2], value[2], i;
1772
   Bitboard temp;
1773
   BYTE obstacles[NUM_LANES];
1774
 
1775
   numPieces[WHITE] = numPieces[BLACK] = 0;
1776
   numPawns[WHITE] = numPawns[BLACK] = 0;
1777
   memset(obstacles, 0x00, NUM_LANES);
1778
   value[WHITE] = value[BLACK] = 0;
1779
 
1780
   if (position->activeColor != WHITE && position->activeColor != BLACK)
1781
   {
1782
      return FALSE;
1783
   }
1784
 
1785
   if (position->castlingRights & WHITE_00)
1786
   {
1787
      if (position->piece[E1] != WHITE_KING)
1788
      {
1789
         return FALSE;
1790
      }
1791
 
1792
      if (position->piece[H1] != WHITE_ROOK)
1793
      {
1794
         return FALSE;
1795
      }
1796
   }
1797
 
1798
   if (position->castlingRights & WHITE_000)
1799
   {
1800
      if (position->piece[E1] != WHITE_KING)
1801
      {
1802
         return FALSE;
1803
      }
1804
 
1805
      if (position->piece[A1] != WHITE_ROOK)
1806
      {
1807
         return FALSE;
1808
      }
1809
   }
1810
 
1811
   if (position->castlingRights & BLACK_00)
1812
   {
1813
      if (position->piece[E8] != BLACK_KING)
1814
      {
1815
         return FALSE;
1816
      }
1817
 
1818
      if (position->piece[H8] != BLACK_ROOK)
1819
      {
1820
         return FALSE;
1821
      }
1822
   }
1823
 
1824
   if (position->castlingRights & BLACK_000)
1825
   {
1826
      if (position->piece[E8] != BLACK_KING)
1827
      {
1828
         return FALSE;
1829
      }
1830
 
1831
      if (position->piece[A8] != BLACK_ROOK)
1832
      {
1833
         return FALSE;
1834
      }
1835
   }
1836
 
1837
   if (position->enPassantSquare != NO_SQUARE)
1838
   {
1839
      if (squareIsValid(position->enPassantSquare) == FALSE)
1840
      {
1841
         return FALSE;
1842
      }
1843
 
1844
      if (position->activeColor == WHITE)
1845
      {
1846
         if (rank(position->enPassantSquare) != RANK_6)
1847
         {
1848
            return FALSE;
1849
         }
1850
 
1851
         if (position->piece[position->enPassantSquare - 8] != BLACK_PAWN)
1852
         {
1853
            return FALSE;
1854
         }
1855
      }
1856
      else
1857
      {
1858
         if (rank(position->enPassantSquare) != RANK_3)
1859
         {
1860
            return FALSE;
1861
         }
1862
 
1863
         if (position->piece[position->enPassantSquare + 8] != WHITE_PAWN)
1864
         {
1865
            return FALSE;
1866
         }
1867
      }
1868
   }
1869
 
1870
   if ((position->piecesOfColor[WHITE] ^ position->piecesOfColor[BLACK]) !=
1871
       position->allPieces)
1872
   {
1873
      return FALSE;
1874
   }
1875
 
1876
   temp = EMPTY_BITBOARD;
1877
 
1878
   for (i = 1; i <= 0x0F; i++)
1879
   {
1880
      temp ^= position->piecesOfType[i];
1881
   }
1882
 
1883
   /*
1884
      dumpBitboard(temp, "temp");
1885
      dumpBitboard(position->allPieces, "allPieces");
1886
    */
1887
 
1888
   if (temp != position->allPieces)
1889
   {
1890
      return FALSE;
1891
   }
1892
 
1893
   if (squareIsValid(position->king[WHITE]) == FALSE)
1894
   {
1895
      return FALSE;
1896
   }
1897
 
1898
   if (position->piece[position->king[WHITE]] != WHITE_KING)
1899
   {
1900
      return FALSE;
1901
   }
1902
 
1903
   if (squareIsValid(position->king[BLACK]) == FALSE)
1904
   {
1905
      return FALSE;
1906
   }
1907
 
1908
   if (position->piece[position->king[BLACK]] != BLACK_KING)
1909
   {
1910
      return FALSE;
1911
   }
1912
 
1913
   if (distance(position->king[WHITE], position->king[BLACK]) < 2)
1914
   {
1915
      return FALSE;
1916
   }
1917
 
1918
   if (testSquare(position->piecesOfType[WHITE_KING],
1919
                  position->king[WHITE]) == FALSE)
1920
   {
1921
      return FALSE;
1922
   }
1923
 
1924
   if (getNumberOfSetSquares(position->piecesOfType[WHITE_KING]) != 1)
1925
   {
1926
      return FALSE;
1927
   }
1928
 
1929
   if (testSquare(position->piecesOfType[BLACK_KING],
1930
                  position->king[BLACK]) == FALSE)
1931
   {
1932
      return FALSE;
1933
   }
1934
 
1935
   if (getNumberOfSetSquares(position->piecesOfType[BLACK_KING]) != 1)
1936
   {
1937
      return FALSE;
1938
   }
1939
 
1940
   ITERATE(square)
1941
   {
1942
      Piece piece = position->piece[square];
1943
      PieceType pieceType = pieceType(piece);
1944
      Color color = pieceColor(piece);
1945
 
1946
      if (piece < 0 || piece > 15)
1947
      {
1948
         return FALSE;
1949
      }
1950
 
1951
      if (piece != NO_PIECE)
1952
      {
1953
         numPieces[color]++;
1954
         setObstacleSquare(square, obstacles);
1955
 
1956
         if (testSquare(position->allPieces, square) == FALSE)
1957
         {
1958
            return FALSE;
1959
         }
1960
 
1961
         if (testSquare(position->piecesOfColor[color], square) == FALSE)
1962
         {
1963
            return FALSE;
1964
         }
1965
 
1966
         if (testSquare(position->piecesOfType[piece], square) == FALSE)
1967
         {
1968
            return FALSE;
1969
         }
1970
 
1971
         if (pieceType == PAWN)
1972
         {
1973
            numPawns[color]++;
1974
         }
1975
 
1976
         if (pieceType != KING)
1977
         {
1978
            value[color] += basicValue[piece];
1979
         }
1980
      }
1981
      else
1982
      {
1983
         if (testSquare(position->allPieces, square))
1984
         {
1985
            return FALSE;
1986
         }
1987
 
1988
         if (testSquare(position->piecesOfColor[WHITE], square))
1989
         {
1990
            return FALSE;
1991
         }
1992
 
1993
         if (testSquare(position->piecesOfColor[BLACK], square))
1994
         {
1995
            return FALSE;
1996
         }
1997
      }
1998
   }
1999
 
2000
   if (numPieces[WHITE] < 1)
2001
   {
2002
      return FALSE;
2003
   }
2004
 
2005
   if (numPieces[WHITE] > 16)
2006
   {
2007
      return FALSE;
2008
   }
2009
 
2010
   if (numPieces[BLACK] < 1)
2011
   {
2012
      return FALSE;
2013
   }
2014
 
2015
   if (numPieces[BLACK] > 16)
2016
   {
2017
      return FALSE;
2018
   }
2019
 
2020
   if (numPawns[WHITE] < 0)
2021
   {
2022
      return FALSE;
2023
   }
2024
 
2025
   if (numPawns[WHITE] > 8)
2026
   {
2027
      return FALSE;
2028
   }
2029
 
2030
   if (numPawns[BLACK] < 0)
2031
   {
2032
      return FALSE;
2033
   }
2034
 
2035
   if (numPawns[BLACK] > 8)
2036
   {
2037
      return FALSE;
2038
   }
2039
 
2040
   return TRUE;
2041
}
2042
 
2043
bool positionsAreIdentical(const Position * position1,
2044
                           const Position * position2)
2045
{
2046
   Square square;
2047
 
2048
   if (position1->activeColor != position2->activeColor ||
2049
       position1->castlingRights != position2->castlingRights ||
2050
       position1->enPassantSquare != position2->enPassantSquare)
2051
   {
2052
      logDebug("activeColor1=%d activeColor2=%d\n",
2053
               position1->activeColor, position2->activeColor);
2054
      logDebug("castlingRights1=%d castlingRights2=%d\n",
2055
               position1->castlingRights, position2->castlingRights);
2056
      logDebug("enPassantSquare1=%d enPassantSquare2=%d\n",
2057
               position1->enPassantSquare, position2->enPassantSquare);
2058
 
2059
      return FALSE;
2060
   }
2061
 
2062
   if (position1->halfMoveClock != position2->halfMoveClock ||
2063
       position1->moveNumber != position2->moveNumber)
2064
   {
2065
      logDebug("halfMoveClock1=%d halfMoveClock2=%d\n",
2066
               position1->halfMoveClock, position2->halfMoveClock);
2067
      logDebug("moveNumber1=%d moveNumber2=%d\n",
2068
               position1->moveNumber, position2->moveNumber);
2069
 
2070
      return FALSE;
2071
   }
2072
 
2073
   ITERATE(square)
2074
   {
2075
      if (position1->piece[square] != position2->piece[square])
2076
      {
2077
         logDebug("piece diff!\n");
2078
         dumpSquare(square);
2079
 
2080
         return FALSE;
2081
      }
2082
   }
2083
 
2084
   return (bool) (checkConsistency(position1) == 0);
2085
}
2086
 
2087
static void initializeKrqSignatureTable()
2088
{
2089
   UINT32 qc, rc, kc;
2090
 
2091
   for (qc = 0; qc <= 9; qc++)
2092
   {
2093
      for (rc = 0; rc <= 10; rc++)
2094
      {
2095
         for (kc = 0; kc <= 10; kc++)
2096
         {
2097
            const int index = (qc << pieceCountShift[WHITE_QUEEN]) +
2098
               (rc << pieceCountShift[WHITE_ROOK]) +
2099
               (kc << pieceCountShift[WHITE_KNIGHT]);
2100
 
2101
            assert(index >= 0 && index < 4096);
2102
 
2103
            krqIndexWhite[index] =
2104
               getMaterialSignature(qc, rc, 0, 0, kc, 0, 0, 0, 0, 0, 0, 0);
2105
            krqIndexBlack[index] =
2106
               getMaterialSignature(0, 0, 0, 0, 0, 0, qc, rc, 0, 0, kc, 0);
2107
         }
2108
      }
2109
   }
2110
}
2111
 
2112
static void initializeBbpSignatureTable()
2113
{
2114
   UINT32 pc, dc, lc;
2115
 
2116
   for (pc = 0; pc <= 8; pc++)
2117
   {
2118
      for (dc = 0; dc <= 9; dc++)
2119
      {
2120
         for (lc = 0; lc <= 9; lc++)
2121
         {
2122
            const int index =
2123
               (lc << (pieceCountShift[WHITE_BISHOP_LIGHT] - 8)) +
2124
               (dc << (pieceCountShift[WHITE_BISHOP_DARK] - 8)) + pc;
2125
 
2126
            assert(index >= 0 && index < 4096);
2127
 
2128
            bbpIndexWhite[index] =
2129
               getMaterialSignature(0, 0, lc, dc, 0, pc, 0, 0, 0, 0, 0, 0);
2130
            bbpIndexBlack[index] =
2131
               getMaterialSignature(0, 0, 0, 0, 0, 0, 0, 0, lc, dc, 0, pc);
2132
         }
2133
      }
2134
   }
2135
}
2136
 
2137
int initializeModulePosition()
2138
{
2139
   Square square;
2140
   int i;
2141
 
2142
   ITERATE(square)
2143
   {
2144
      remainingCastlings[square] = (WHITE_00 | WHITE_000 |
2145
                                    BLACK_00 | BLACK_000);
2146
 
2147
      switch (square)
2148
      {
2149
      case A1:
2150
         remainingCastlings[square] -= WHITE_000;
2151
         break;
2152
 
2153
      case E1:
2154
         remainingCastlings[square] -= WHITE_000;
2155
         remainingCastlings[square] -= WHITE_00;
2156
         break;
2157
 
2158
      case H1:
2159
         remainingCastlings[square] -= WHITE_00;
2160
         break;
2161
 
2162
      case A8:
2163
         remainingCastlings[square] -= BLACK_000;
2164
         break;
2165
 
2166
      case E8:
2167
         remainingCastlings[square] -= BLACK_000;
2168
         remainingCastlings[square] -= BLACK_00;
2169
         break;
2170
 
2171
      case H8:
2172
         remainingCastlings[square] -= BLACK_00;
2173
         break;
2174
 
2175
      default:
2176
         break;
2177
      }
2178
   }
2179
 
2180
   rookOrigin[C1] = A1;
2181
   rookOrigin[G1] = H1;
2182
   rookOrigin[C8] = A8;
2183
   rookOrigin[G8] = H8;
2184
 
2185
   basicValue[NO_PIECE] = 0;
2186
   basicValue[WHITE_KING] = basicValue[BLACK_KING] = -VALUE_MATED;
2187
   basicValue[WHITE_QUEEN] = basicValue[BLACK_QUEEN] =
2188
      max(VALUE_QUEEN_OPENING, VALUE_QUEEN_ENDGAME);
2189
   basicValue[WHITE_ROOK] = basicValue[BLACK_ROOK] =
2190
      max(VALUE_ROOK_OPENING, VALUE_ROOK_ENDGAME);
2191
   basicValue[WHITE_BISHOP] = basicValue[BLACK_BISHOP] =
2192
      max(VALUE_BISHOP_OPENING, VALUE_BISHOP_ENDGAME);
2193
   basicValue[WHITE_KNIGHT] = basicValue[BLACK_KNIGHT] =
2194
      max(VALUE_KNIGHT_OPENING, VALUE_KNIGHT_ENDGAME);
2195
   basicValue[WHITE_PAWN] = basicValue[BLACK_PAWN] =
2196
      max(VALUE_PAWN_OPENING, VALUE_PAWN_ENDGAME);
2197
 
2198
   /*logDebug("size of Variation: %d bytes\n", sizeof(Variation)); */
2199
 
2200
   pieceCountShift[WHITE_KING] = 40;
2201
   pieceCountShift[WHITE_QUEEN] = 0;
2202
   pieceCountShift[WHITE_ROOK] = 4;
2203
   pieceCountShift[WHITE_KNIGHT] = 8;
2204
   pieceCountShift[WHITE_BISHOP_LIGHT] = 12;
2205
   pieceCountShift[WHITE_BISHOP_DARK] = 16;
2206
   pieceCountShift[WHITE_PAWN] = 40;
2207
   pieceCountShift[BLACK_KING] = 40;
2208
   pieceCountShift[BLACK_QUEEN] = 20;
2209
   pieceCountShift[BLACK_ROOK] = 24;
2210
   pieceCountShift[BLACK_KNIGHT] = 28;
2211
   pieceCountShift[BLACK_BISHOP_LIGHT] = 32;
2212
   pieceCountShift[BLACK_BISHOP_DARK] = 36;
2213
   pieceCountShift[BLACK_PAWN] = 40;
2214
 
2215
   for (i = 0; i < 16; i++)
2216
   {
2217
      pieceCountWeight[i] =
2218
         (pieceCountShift[i] < 40 ? ((UINT64) (1)) << pieceCountShift[i] : 0);
2219
 
2220
      /* logDebug("pcw(%d) = %lu (%d)\n", i, pieceCountWeight[i], pieceCountShift[i]); */
2221
   }
2222
 
2223
   ITERATE(square)
2224
   {
2225
      if (testSquare(darkSquares, square))
2226
      {
2227
         bishopPieceCountWeight[WHITE][square] =
2228
            pieceCountWeight[WHITE_BISHOP_DARK];
2229
         bishopPieceCountWeight[BLACK][square] =
2230
            pieceCountWeight[BLACK_BISHOP_DARK];
2231
      }
2232
      else
2233
      {
2234
         bishopPieceCountWeight[WHITE][square] =
2235
            pieceCountWeight[WHITE_BISHOP_LIGHT];
2236
         bishopPieceCountWeight[BLACK][square] =
2237
            pieceCountWeight[BLACK_BISHOP_LIGHT];
2238
      }
2239
   }
2240
 
2241
   initializeKrqSignatureTable();
2242
   initializeBbpSignatureTable();
2243
 
2244
   return 0;
2245
}
2246
 
2247
static int checkMove(Square from, Square to, Piece newPiece,
2248
                     Variation * variation)
2249
{
2250
   Move move = getPackedMove(from, to, newPiece);
2251
 
2252
   makeMove(variation, move);
2253
   assert(checkConsistency(&variation->singlePosition) == 0);
2254
 
2255
   return 0;
2256
}
2257
 
2258
static int testPawnMoves()
2259
{
2260
   Variation variation;
2261
 
2262
   initializeVariation(&variation, FEN_GAMESTART);
2263
   assert(checkConsistency(&variation.singlePosition) == 0);
2264
 
2265
   checkMove(E2, E4, NO_PIECE, &variation);
2266
   assert(variation.singlePosition.enPassantSquare == E3);
2267
   checkMove(D7, D5, NO_PIECE, &variation);
2268
   assert(variation.singlePosition.enPassantSquare == D6);
2269
 
2270
   checkMove(E4, D5, NO_PIECE, &variation);
2271
   assert(variation.singlePosition.enPassantSquare == NO_SQUARE);
2272
   checkMove(D8, D5, NO_PIECE, &variation);
2273
 
2274
   checkMove(D2, D4, NO_PIECE, &variation);
2275
   checkMove(D5, D8, NO_PIECE, &variation);
2276
 
2277
   checkMove(D4, D5, NO_PIECE, &variation);
2278
   checkMove(C7, C5, NO_PIECE, &variation);
2279
   assert(variation.singlePosition.enPassantSquare == C6);
2280
 
2281
   checkMove(D5, C6, NO_PIECE, &variation);
2282
   checkMove(E7, E5, NO_PIECE, &variation);
2283
 
2284
   checkMove(C6, B7, NO_PIECE, &variation);
2285
   checkMove(E5, E4, NO_PIECE, &variation);
2286
 
2287
   checkMove(F2, F4, NO_PIECE, &variation);
2288
   assert(variation.singlePosition.enPassantSquare == F3);
2289
   checkMove(E4, F3, NO_PIECE, &variation);
2290
 
2291
   checkMove(B7, C8, WHITE_ROOK, &variation);
2292
   checkMove(F3, G2, NO_PIECE, &variation);
2293
 
2294
   checkMove(C8, B8, NO_PIECE, &variation);
2295
   checkMove(G2, H1, WHITE_QUEEN, &variation);
2296
 
2297
   checkMove(D1, D8, WHITE_QUEEN, &variation);  /* checkmate; what a game! */
2298
 
2299
   return 0;
2300
}
2301
 
2302
static int testShortCastlings()
2303
{
2304
   Variation variation;
2305
 
2306
   initializeVariation(&variation, FEN_GAMESTART);
2307
   assert(checkConsistency(&variation.singlePosition) == 0);
2308
 
2309
   checkMove(E2, E4, NO_PIECE, &variation);
2310
   checkMove(E7, E5, NO_PIECE, &variation);
2311
 
2312
   checkMove(G1, F3, NO_PIECE, &variation);
2313
   checkMove(G8, F6, NO_PIECE, &variation);
2314
 
2315
   checkMove(F1, C4, NO_PIECE, &variation);
2316
   checkMove(F8, C5, NO_PIECE, &variation);
2317
 
2318
   checkMove(E1, G1, NO_PIECE, &variation);
2319
   assert(variation.singlePosition.piece[F1] == WHITE_ROOK);
2320
   checkMove(E8, G8, NO_PIECE, &variation);
2321
   assert(variation.singlePosition.piece[F8] == BLACK_ROOK);
2322
 
2323
   return 0;
2324
}
2325
 
2326
static int testLongCastlings()
2327
{
2328
   Variation variation;
2329
 
2330
   initializeVariation(&variation, FEN_GAMESTART);
2331
   assert(checkConsistency(&variation.singlePosition) == 0);
2332
 
2333
   checkMove(D2, D4, NO_PIECE, &variation);
2334
   checkMove(D7, D5, NO_PIECE, &variation);
2335
 
2336
   checkMove(B1, C3, NO_PIECE, &variation);
2337
   checkMove(B8, C6, NO_PIECE, &variation);
2338
 
2339
   checkMove(C1, F4, NO_PIECE, &variation);
2340
   checkMove(C8, F5, NO_PIECE, &variation);
2341
 
2342
   checkMove(D1, D2, NO_PIECE, &variation);
2343
   checkMove(D8, D7, NO_PIECE, &variation);
2344
 
2345
   checkMove(E1, C1, NO_PIECE, &variation);
2346
   assert(variation.singlePosition.piece[D1] == WHITE_ROOK);
2347
   checkMove(E8, C8, NO_PIECE, &variation);
2348
   assert(variation.singlePosition.piece[D8] == BLACK_ROOK);
2349
 
2350
   return 0;
2351
}
2352
 
2353
static int testCastlingLegality()
2354
{
2355
   Variation variation, *p_variation = &variation;
2356
 
2357
   initializeVariation(&variation, FEN_GAMESTART);
2358
   assert(checkConsistency(&variation.singlePosition) == 0);
2359
 
2360
   checkMove(E2, E4, NO_PIECE, &variation);
2361
   checkMove(E7, E5, NO_PIECE, &variation);
2362
 
2363
   checkMove(G1, F3, NO_PIECE, &variation);
2364
   checkMove(G8, F6, NO_PIECE, &variation);
2365
 
2366
   checkMove(F3, E5, NO_PIECE, &variation);
2367
   checkMove(F6, E4, NO_PIECE, &variation);
2368
 
2369
   checkMove(E5, G6, NO_PIECE, &variation);
2370
   checkMove(E4, G3, NO_PIECE, &variation);
2371
 
2372
   checkMove(F1, C4, NO_PIECE, &variation);
2373
   checkMove(F8, C5, NO_PIECE, &variation);
2374
 
2375
   assert(makeMove(&variation, getPackedMove(E1, G1, NO_PIECE)) == 1);
2376
   unmakeLastMove(p_variation);
2377
 
2378
   checkMove(H2, G3, NO_PIECE, &variation);
2379
 
2380
   assert(makeMove(&variation, getPackedMove(E8, G8, NO_PIECE)) == 1);
2381
   unmakeLastMove(p_variation);
2382
 
2383
   checkMove(H7, G6, NO_PIECE, &variation);
2384
 
2385
   assert(makeMove(&variation, getPackedMove(E1, G1, NO_PIECE)) == 0);
2386
 
2387
   assert(makeMove(&variation, getPackedMove(E8, G8, NO_PIECE)) == 0);
2388
 
2389
   initializeVariation(&variation, FEN_GAMESTART);
2390
   assert(checkConsistency(&variation.singlePosition) == 0);
2391
 
2392
   checkMove(E2, E4, NO_PIECE, &variation);
2393
   checkMove(E7, E5, NO_PIECE, &variation);
2394
 
2395
   checkMove(G1, F3, NO_PIECE, &variation);
2396
   checkMove(G8, F6, NO_PIECE, &variation);
2397
 
2398
   checkMove(F3, E5, NO_PIECE, &variation);
2399
   checkMove(F6, E4, NO_PIECE, &variation);
2400
 
2401
   checkMove(E5, F3, NO_PIECE, &variation);
2402
   checkMove(E4, F6, NO_PIECE, &variation);
2403
 
2404
   checkMove(F1, C4, NO_PIECE, &variation);
2405
   checkMove(F8, C5, NO_PIECE, &variation);
2406
 
2407
   checkMove(D1, E2, NO_PIECE, &variation);
2408
 
2409
   assert(makeMove(&variation, getPackedMove(E8, G8, NO_PIECE)) == 1);
2410
   unmakeLastMove(p_variation); /* 0-0 */
2411
   unmakeLastMove(p_variation); /* Qe2+ */
2412
 
2413
   assert(makeMove(&variation, getPackedMove(E1, G1, NO_PIECE)) == 0);
2414
   unmakeLastMove(p_variation); /* 0-0 */
2415
 
2416
   checkMove(D2, D3, NO_PIECE, &variation);
2417
 
2418
   assert(makeMove(&variation, getPackedMove(E8, G8, NO_PIECE)) == 0);
2419
   unmakeLastMove(p_variation); /* 0-0 */
2420
 
2421
   checkMove(D8, E7, NO_PIECE, &variation);
2422
 
2423
   assert(makeMove(&variation, getPackedMove(E1, G1, NO_PIECE)) == 1);
2424
   unmakeLastMove(p_variation); /* 0-0 */
2425
   unmakeLastMove(p_variation); /* Qe7+ */
2426
 
2427
   checkMove(D7, D6, NO_PIECE, &variation);
2428
 
2429
   assert(makeMove(&variation, getPackedMove(E1, G1, NO_PIECE)) == 0);
2430
 
2431
   return 0;
2432
}
2433
 
2434
static int testMove()
2435
{
2436
#ifndef NDEBUG
2437
   Move move;
2438
 
2439
   move = getMove(A1, C3, NO_PIECE, -17);
2440
 
2441
   assert(getFromSquare(move) == A1);
2442
   assert(getToSquare(move) == C3);
2443
   assert(getNewPiece(move) == NO_PIECE);
2444
   assert(getMoveValue(move) == -17);
2445
#endif
2446
 
2447
   return 0;
2448
}
2449
 
2450
int testModulePosition()
2451
{
2452
   int result;
2453
 
2454
   if ((result = testPawnMoves()) != 0)
2455
   {
2456
      return result;
2457
   }
2458
 
2459
   if ((result = testShortCastlings()) != 0)
2460
   {
2461
      return result;
2462
   }
2463
 
2464
   if ((result = testLongCastlings()) != 0)
2465
   {
2466
      return result;
2467
   }
2468
 
2469
   if ((result = testCastlingLegality()) != 0)
2470
   {
2471
      return result;
2472
   }
2473
 
2474
   if ((result = testMove()) != 0)
2475
   {
2476
      return result;
2477
   }
2478
 
2479
   return 0;
2480
}