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 | } |