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 | /* |
||
22 | This module contains a bitboard-based chess move generator. |
||
23 | */ |
||
24 | #include <assert.h> |
||
25 | #include <string.h> |
||
26 | #include <stdlib.h> |
||
27 | #include <stdio.h> |
||
28 | #include "bitboard.h" |
||
29 | #include "io.h" |
||
30 | |||
31 | #ifndef __builtin_popcountll // Pierre-Marie Baty -- __builtin_popcountll support for MSVC 32-bit |
||
32 | int __builtin_popcountll (unsigned long long x) { |
||
33 | static const unsigned long long m1 = 0x5555555555555555; //binary: 0101... |
||
34 | static const unsigned long long m2 = 0x3333333333333333; //binary: 00110011.. |
||
35 | static const unsigned long long m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones ... |
||
36 | static const unsigned long long h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3... |
||
37 | x -= (x >> 1) & m1; //put count of each 2 bits into those 2 bits |
||
38 | x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits |
||
39 | x = (x + (x >> 4)) & m4; //put count of each 8 bits into those 8 bits |
||
40 | return (int)((x * h01) >> 56); //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... |
||
41 | } |
||
42 | #endif // Pierre-Marie Baty -- __builtin_popcountll support for MSVC 32-bit |
||
43 | |||
44 | #ifndef __builtin_ctzll // Pierre-Marie Baty -- __builtin_ctzll support for MSVC 32-bit |
||
45 | int __builtin_ctzll (unsigned long long x) |
||
46 | { |
||
47 | // Returns the number of trailing 0-bits in x, starting at the least significant bit position. |
||
48 | // If x is zero, the result is undefined. |
||
49 | // This uses a binary search algorithm from Hacker's Delight. |
||
50 | int n = 1; |
||
51 | if ((x & 0x00000000FFFFFFFF) == 0) { n = n + 32; x = x >> 32; } |
||
52 | if ((x & 0x000000000000FFFF) == 0) { n = n + 16; x = x >> 16; } |
||
53 | if ((x & 0x00000000000000FF) == 0) { n = n + 8; x = x >> 8; } |
||
54 | if ((x & 0x000000000000000F) == 0) { n = n + 4; x = x >> 4; } |
||
55 | if ((x & 0x0000000000000003) == 0) { n = n + 2; x = x >> 2; } |
||
56 | return (n - (x & 1)); |
||
57 | } |
||
58 | #endif // Pierre-Marie Baty -- __builtin_ctzll support for MSVC 32-bit |
||
59 | |||
60 | #ifndef __builtin_clzll // Pierre-Marie Baty -- __builtin_clzll support for MSVC 32-bit |
||
61 | int __builtin_clzll (unsigned long long x) |
||
62 | { |
||
63 | // Returns the number of leading 0-bits in x, starting at the most significant bit position. |
||
64 | // If x is zero, the result is undefined. |
||
65 | // This uses a binary search (counting down) algorithm from Hacker's Delight. |
||
66 | unsigned long long y; |
||
67 | int n = 64; |
||
68 | y = x >> 32; if (y != 0) { n = n - 32; x = y; } |
||
69 | y = x >> 16; if (y != 0) { n = n - 16; x = y; } |
||
70 | y = x >> 8; if (y != 0) { n = n - 8; x = y; } |
||
71 | y = x >> 4; if (y != 0) { n = n - 4; x = y; } |
||
72 | y = x >> 2; if (y != 0) { n = n - 2; x = y; } |
||
73 | y = x >> 1; if (y != 0) return (n - 2); |
||
74 | return (n - (int) x); |
||
75 | } |
||
76 | #endif // Pierre-Marie Baty -- __builtin_clzll support for MSVC 32-bit |
||
77 | |||
78 | #define offset(sq1,sq2) ( ( (sq2)-(sq1) ) / distance(sq1,sq2) ) |
||
79 | |||
80 | /** |
||
81 | * Macros for internal use. |
||
82 | */ |
||
83 | #define HLANE(sq) ( rank(sq) ) |
||
84 | #define HLANEBIT(sq) ( FILE_H - file(sq) ) |
||
85 | #define VLANE(sq) ( file(sq) ) |
||
86 | #define VLANEBIT(sq) ( RANK_8 - rank(sq) ) |
||
87 | #define ULANE(sq) ( file(sq) - rank(sq) + 7 ) |
||
88 | #define ULANEBIT(sq) ( RANK_8 - rank(sq) ) |
||
89 | #define DLANE(sq) ( file(sq) + rank(sq) ) |
||
90 | #define DLANEBIT(sq) ( rank(sq) ) |
||
91 | #define HLANE_SQUARE(lane,bit) ( getSquare ( 7-(bit), (lane) ) ) |
||
92 | #define VLANE_SQUARE(lane,bit) ( getSquare ( (lane), 7-(bit) ) ) |
||
93 | #define ULANE_SQUARE(lane,bit) ( getSquare ( (lane)-(bit), 7-(bit) ) ) |
||
94 | #define DLANE_SQUARE(lane,bit) ( getSquare ( (lane)-(bit), (bit) ) ) |
||
95 | |||
96 | static bool isInitialized = FALSE; |
||
97 | |||
98 | UINT64 minValue[_64_]; |
||
99 | UINT64 maxValue[_64_]; |
||
100 | INT8 highestBit[0x10000]; |
||
101 | INT8 lowestBit[0x10000]; |
||
102 | INT8 numSetBits[0x10000]; |
||
103 | UINT8 rankOverlay[0x10000]; |
||
104 | UINT8 bitshiftGap[8][256]; |
||
105 | int hLaneNumber[_64_], vLaneNumber[_64_]; |
||
106 | int uLaneNumber[_64_], dLaneNumber[_64_]; |
||
107 | |||
108 | Bitboard generalMoves[0x0f][_64_]; |
||
109 | |||
110 | /* *INDENT-OFF* */ |
||
111 | const Bitboard squaresOfFile[8] = { |
||
112 | 0x0101010101010101llu, |
||
113 | 0x0202020202020202llu, |
||
114 | 0x0404040404040404llu, |
||
115 | 0x0808080808080808llu, |
||
116 | 0x1010101010101010llu, |
||
117 | 0x2020202020202020llu, |
||
118 | 0x4040404040404040llu, |
||
119 | 0x8080808080808080llu |
||
120 | }; |
||
121 | const Bitboard squaresOfRank[8] = { |
||
122 | 0x00000000000000ffllu, |
||
123 | 0x000000000000ff00llu, |
||
124 | 0x0000000000ff0000llu, |
||
125 | 0x00000000ff000000llu, |
||
126 | 0x000000ff00000000llu, |
||
127 | 0x0000ff0000000000llu, |
||
128 | 0x00ff000000000000llu, |
||
129 | 0xff00000000000000llu |
||
130 | }; |
||
131 | const Bitboard squaresOfLateralFiles[8] = { |
||
132 | 0x0202020202020202llu, |
||
133 | 0x0505050505050505llu, |
||
134 | 0x0a0a0a0a0a0a0a0allu, |
||
135 | 0x1414141414141414llu, |
||
136 | 0x2828282828282828llu, |
||
137 | 0x5050505050505050llu, |
||
138 | 0xa0a0a0a0a0a0a0a0llu, |
||
139 | 0x4040404040404040llu |
||
140 | }; |
||
141 | /* *INDENT-ON* */ |
||
142 | |||
143 | Bitboard squaresOfFileRange[8][8]; |
||
144 | Bitboard squaresOfRankRange[8][8]; |
||
145 | Bitboard nonA, nonH, border, center, lightSquares, darkSquares, queenSide, |
||
146 | kingSide, centerFiles, extendedCenter; |
||
147 | Bitboard squaresBehind[_64_][_64_]; |
||
148 | Bitboard squaresBetween[_64_][_64_]; |
||
149 | Bitboard squaresInDistance[8][_64_]; |
||
150 | Bitboard squaresInTaxiDistance[15][_64_]; |
||
151 | Bitboard squaresAbove[2][_64_]; |
||
152 | Bitboard squaresBelow[2][_64_]; |
||
153 | Bitboard squaresLeftOf[_64_]; |
||
154 | Bitboard squaresRightOf[_64_]; |
||
155 | Bitboard orthoKingAttackers[_64_]; |
||
156 | Bitboard diaKingAttackers[_64_]; |
||
157 | Bitboard knightKingAttackers[_64_]; |
||
158 | Bitboard pawnKingAttackers[2][_64_]; |
||
159 | |||
160 | SquareLaneInfo squareLaneInfo[_64_]; |
||
161 | Bitboard hlane[_64_][256]; |
||
162 | Bitboard vlane[_64_][256]; |
||
163 | Bitboard ulane[_64_][256]; |
||
164 | Bitboard dlane[_64_][256]; |
||
165 | ObstacleSquareInfo obsi[_64_]; |
||
166 | Bitboard pawnMoves[2][_64_][256]; |
||
167 | Bitboard interestedPawns[2][_64_][256]; |
||
168 | Bitboard castlings[2][16][256]; |
||
169 | int castlingLane[] = { HLANE(E1), HLANE(E8) }; |
||
170 | Bitboard promotionCandidates[2]; |
||
171 | SetSquaresInfo setSquares[4][0x10000]; |
||
172 | Bitboard preMaskRook[64], preMaskBishop[64]; |
||
173 | Bitboard magicRookMoves[64][IMAX_ROOK]; |
||
174 | Bitboard magicBishopMoves[64][IMAX_BISHOP]; |
||
175 | MagicSquareInfoRook magicSquareInfoRook[64]; |
||
176 | MagicSquareInfoBishop magicSquareInfoBishop[64]; |
||
177 | |||
178 | /* *INDENT-OFF* */ |
||
179 | const Bitboard magicRookNumber[64] = { |
||
180 | 2341871876025885824llu, 5908793080399659264llu, |
||
181 | 2814784401577026llu, 4755810071654563842llu, |
||
182 | 4683749110191751172llu, 648520571176420352llu, |
||
183 | 288793875996213508llu, 36039242390061312llu, |
||
184 | 2233855853176307712llu, 360296835543278592llu, |
||
185 | 37470368710784llu, 2261832991510528llu, |
||
186 | 74595267411776576llu, 4612831726723531008llu, |
||
187 | 17491104022660138llu, 9015996489662496llu, |
||
188 | 164381455144716288llu, 4785426803991552llu, |
||
189 | 2603080765009821794llu, 4504870937840771llu, |
||
190 | 73202185810346241llu, 2594073935322554944llu, |
||
191 | 577059170398781952llu, 687199551504llu, |
||
192 | 36029072970620928llu, 4755818807417635204llu, |
||
193 | 2305854279342097445llu, 4654506018003485187llu, |
||
194 | 1369095394823243808llu, 1650609881216llu, |
||
195 | 35189740863840llu, 17609634498592llu, |
||
196 | 17867407885440llu, 1307170084179935305llu, |
||
197 | 5224509820511455237llu, 30399366238175240llu, |
||
198 | 685674177139050632llu, 4504708001565696llu, |
||
199 | 576777574861506688llu, 2305843147759948801llu, |
||
200 | 36046664624070657llu, 2305862800624326656llu, |
||
201 | 35201686183936llu, 76563943050448912llu, |
||
202 | 4828140284174931982llu, 93630429790212llu, |
||
203 | 2305862800758624268llu, 4918212371161546978llu, |
||
204 | 1197987317416064llu, 4629700452154347536llu, |
||
205 | 144220742299427329llu, 1152928385211832832llu, |
||
206 | 40132191457288llu, 9354573578272llu, |
||
207 | 650209674406199320llu, 36029355649925192llu, |
||
208 | 3470081245843620386llu, 9208682512641llu, |
||
209 | 586664357648667141llu, 113161891886927874llu, |
||
210 | 19144700892151826llu, 594756909391937601llu, |
||
211 | 562958551810122llu, 1152922124158043138llu, |
||
212 | }; |
||
213 | |||
214 | const Bitboard magicBishopNumber[64] = { |
||
215 | 2287018567549508llu, 20833559275112450llu, |
||
216 | 1157535125460746242llu, 2343279465658384466llu, |
||
217 | 182423557274534246llu, 91204498130747394llu, |
||
218 | 79165240377360llu, 18024053647361153llu, |
||
219 | 4756927389883318784llu, 2377974339296303121llu, |
||
220 | 1529092243969llu, 18016872700051744llu, |
||
221 | 1153204084472553600llu, 873698516757668385llu, |
||
222 | 1125942867148800llu, 26423192526848llu, |
||
223 | 289939073072784384llu, 10714208241454656llu, |
||
224 | 2306405960274414104llu, 54114131212519426llu, |
||
225 | 109212291534684230llu, 2306971108957557248llu, |
||
226 | 288239189760215296llu, 166643228131737628llu, |
||
227 | 3459894829004630016llu, 35193180131968llu, |
||
228 | 576478344523031040llu, 1134696069202368llu, |
||
229 | 298367873364066368llu, 2882596248975577091llu, |
||
230 | 432437927499531776llu, 72621163549300482llu, |
||
231 | 468396630660612192llu, 576812875222894592llu, |
||
232 | 3463272528741531664llu, 2612123106223325312llu, |
||
233 | 3242874314789487108llu, 3461016494560002066llu, |
||
234 | 4539883779662384llu, 5909074606504807464llu, |
||
235 | 4684333518172472324llu, 306280543752814656llu, |
||
236 | 2345387698176llu, 293016142258114592llu, |
||
237 | 5073215437209668llu, 79251277611040llu, |
||
238 | 602532708688384llu, 20310252071682068llu, |
||
239 | 4467607076866llu, 648573875995549696llu, |
||
240 | 288232580007339520llu, 1188986585695191042llu, |
||
241 | 9306611390751752llu, 5498105049088llu, |
||
242 | 4625205909830770716llu, 1152994261659095304llu, |
||
243 | 126118725618245632llu, 2305851875981395204llu, |
||
244 | 351843796394505llu, 40532672078233696llu, |
||
245 | 9009398294791225llu, 4611688257515749392llu, |
||
246 | 1152930369572702464llu, 2306989456245202960llu, |
||
247 | }; |
||
248 | /* *INDENT-ON* */ |
||
249 | |||
250 | bool testSquare(const Bitboard bitboard, const Square square) |
||
251 | { |
||
252 | return (bool) (((bitboard) & minValue[(square)]) != EMPTY_BITBOARD); |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * Get the king moves for the specified square. |
||
257 | */ |
||
258 | Bitboard getKingMoves(const Square square) |
||
259 | { |
||
260 | return generalMoves[KING][square]; |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * Get castling moves depending from the castling rights and |
||
265 | * the current position. |
||
266 | */ |
||
267 | Bitboard getCastlingMoves(const Color color, const BYTE castlingRights, |
||
268 | const Bitboard obstacles) |
||
269 | { |
||
270 | if (color == WHITE) |
||
271 | { |
||
272 | return castlings[WHITE][castlingRights][obstacles & 0xFF]; |
||
273 | } |
||
274 | else |
||
275 | { |
||
276 | return castlings[BLACK][castlingRights][obstacles >> 56]; |
||
277 | } |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Get the queen moves for the specified square. |
||
282 | */ |
||
283 | /* |
||
284 | Bitboard getQueenMoves(const Square square, const BYTE * obstacles) |
||
285 | { |
||
286 | const ObstacleSquareInfo *_obsi = &obsi[square]; |
||
287 | |||
288 | return _obsi->hLane[obstacles[_obsi->hLaneNumber]] | |
||
289 | _obsi->vLane[obstacles[_obsi->vLaneNumber]] | |
||
290 | _obsi->uLane[obstacles[_obsi->uLaneNumber]] | |
||
291 | _obsi->dLane[obstacles[_obsi->dLaneNumber]]; |
||
292 | } |
||
293 | */ |
||
294 | |||
295 | int getWidth(const Bitboard set) |
||
296 | { |
||
297 | if (set == EMPTY_BITBOARD) |
||
298 | { |
||
299 | return 0; |
||
300 | } |
||
301 | else |
||
302 | { |
||
303 | File leftMost = FILE_A, rightMost = FILE_H; |
||
304 | |||
305 | while ((set & squaresOfFile[leftMost]) == EMPTY_BITBOARD) |
||
306 | { |
||
307 | leftMost++; |
||
308 | } |
||
309 | |||
310 | while ((set & squaresOfFile[rightMost]) == EMPTY_BITBOARD) |
||
311 | { |
||
312 | rightMost--; |
||
313 | } |
||
314 | |||
315 | return rightMost - leftMost; |
||
316 | } |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * Get the queen moves for the specified square. |
||
321 | */ |
||
322 | Bitboard getMagicQueenMoves(const Square square, const Bitboard obstacles) |
||
323 | { |
||
324 | MagicSquareInfoRook *msir = &magicSquareInfoRook[square]; |
||
325 | MagicSquareInfoBishop *msib = &magicSquareInfoBishop[square]; |
||
326 | |||
327 | return |
||
328 | msir->moves[((obstacles & msir->preMask) * msir->magicNumber) >> 52] | |
||
329 | msib->moves[((obstacles & msib->preMask) * msib->magicNumber) >> 55]; |
||
330 | } |
||
331 | |||
332 | /** |
||
333 | * Get the rook moves for the specified square. |
||
334 | */ |
||
335 | Bitboard getRookMoves(const Square square, const BYTE * obstacles) |
||
336 | { |
||
337 | const ObstacleSquareInfo *_obsi = &obsi[square]; |
||
338 | |||
339 | return _obsi->hLane[obstacles[_obsi->hLaneNumber]] | |
||
340 | _obsi->vLane[obstacles[_obsi->vLaneNumber]]; |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * Get the rook moves for the specified square. |
||
345 | */ |
||
346 | Bitboard getMagicRookMoves(const Square square, const Bitboard obstacles) |
||
347 | { |
||
348 | MagicSquareInfoRook *msir = &magicSquareInfoRook[square]; |
||
349 | |||
350 | return |
||
351 | msir->moves[((obstacles & msir->preMask) * msir->magicNumber) >> 52]; |
||
352 | } |
||
353 | |||
354 | /** |
||
355 | * Get the bishop moves for the specified square. |
||
356 | */ |
||
357 | Bitboard getBishopMoves(const Square square, const BYTE * obstacles) |
||
358 | { |
||
359 | const ObstacleSquareInfo *_obsi = &obsi[square]; |
||
360 | |||
361 | return _obsi->uLane[obstacles[_obsi->uLaneNumber]] | |
||
362 | _obsi->dLane[obstacles[_obsi->dLaneNumber]]; |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Get the bishop moves for the specified square. |
||
367 | */ |
||
368 | Bitboard getMagicBishopMoves(const Square square, const Bitboard obstacles) |
||
369 | { |
||
370 | MagicSquareInfoBishop *msib = &magicSquareInfoBishop[square]; |
||
371 | |||
372 | return |
||
373 | msib->moves[((obstacles & msib->preMask) * msib->magicNumber) >> 55]; |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * Get the knight moves for the specified square. |
||
378 | */ |
||
379 | Bitboard getKnightMoves(const Square square) |
||
380 | { |
||
381 | return generalMoves[KNIGHT][square]; |
||
382 | } |
||
383 | |||
384 | /** |
||
385 | * Get the pawn captures for the specified square. |
||
386 | */ |
||
387 | Bitboard getPawnCaptures(const Piece piece, const Square square, |
||
388 | const Bitboard allPieces) |
||
389 | { |
||
390 | return generalMoves[piece][square] & allPieces; |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * Get the pawn advances for the specified square. |
||
395 | */ |
||
396 | Bitboard getPawnAdvances(const Color color, const Square square, |
||
397 | const Bitboard obstacles) |
||
398 | { |
||
399 | Bitboard advances; |
||
400 | |||
401 | if (color == WHITE) |
||
402 | { |
||
403 | advances = (minValue[square] << 8) & ~obstacles; |
||
404 | |||
405 | if (rank(square) == RANK_2) |
||
406 | { |
||
407 | advances |= (advances << 8) & ~obstacles; |
||
408 | } |
||
409 | } |
||
410 | else |
||
411 | { |
||
412 | advances = (minValue[square] >> 8) & ~obstacles; |
||
413 | |||
414 | if (rank(square) == RANK_7) |
||
415 | { |
||
416 | advances |= (advances >> 8) & ~obstacles; |
||
417 | } |
||
418 | } |
||
419 | |||
420 | return advances; |
||
421 | } |
||
422 | |||
423 | /** |
||
424 | * Get the pawns interested in advancing to the specified square. |
||
425 | */ |
||
426 | Bitboard getInterestedPawns(const Color color, const Square square, |
||
427 | const Bitboard obstacles) |
||
428 | { |
||
429 | Bitboard interestedPawns; |
||
430 | |||
431 | if (color == WHITE) |
||
432 | { |
||
433 | interestedPawns = minValue[square] >> 8; |
||
434 | |||
435 | if (rank(square) == RANK_4 && |
||
436 | (interestedPawns & obstacles) == EMPTY_BITBOARD) |
||
437 | { |
||
438 | interestedPawns |= minValue[square] >> 16; |
||
439 | } |
||
440 | } |
||
441 | else |
||
442 | { |
||
443 | interestedPawns = minValue[square] << 8; |
||
444 | |||
445 | if (rank(square) == RANK_5 && |
||
446 | (interestedPawns & obstacles) == EMPTY_BITBOARD) |
||
447 | { |
||
448 | interestedPawns |= minValue[square] << 16; |
||
449 | } |
||
450 | } |
||
451 | |||
452 | return interestedPawns; |
||
453 | } |
||
454 | |||
455 | /** |
||
456 | * Get the squares between the two specified squares. |
||
457 | */ |
||
458 | Bitboard getSquaresBetween(const Square square1, const Square square2) |
||
459 | { |
||
460 | return squaresBetween[square1][square2]; |
||
461 | } |
||
462 | |||
463 | /** |
||
464 | * Get the squares behind 'target', as seen from 'viewpoint'. |
||
465 | */ |
||
466 | Bitboard getSquaresBehind(const Square target, const Square viewpoint) |
||
467 | { |
||
468 | return squaresBehind[target][viewpoint]; |
||
469 | } |
||
470 | |||
471 | /** |
||
472 | * Shift all set squares one file to the left. |
||
473 | */ |
||
474 | Bitboard shiftLeft(const Bitboard bitboard) |
||
475 | { |
||
476 | return (bitboard & nonA) >> 1; |
||
477 | } |
||
478 | |||
479 | /** |
||
480 | * Shift all set squares one file to the right. |
||
481 | */ |
||
482 | Bitboard shiftRight(const Bitboard bitboard) |
||
483 | { |
||
484 | return (bitboard & nonH) << 1; |
||
485 | } |
||
486 | |||
487 | /** |
||
488 | * Get all squares lateral to the specified squares. |
||
489 | */ |
||
490 | Bitboard getLateralSquares(const Bitboard squares) |
||
491 | { |
||
492 | return ((squares & nonA) >> 1) | ((squares & nonH) << 1); |
||
493 | } |
||
494 | |||
495 | /** |
||
496 | * Get the squares of the specified file. |
||
497 | */ |
||
498 | Bitboard getSquaresOfFile(const File file) |
||
499 | { |
||
500 | return squaresOfFile[file]; |
||
501 | } |
||
502 | |||
503 | /** |
||
504 | * Get the squares of the specified rank. |
||
505 | */ |
||
506 | Bitboard getSquaresOfRank(const Rank rank) |
||
507 | { |
||
508 | return squaresOfRank[rank]; |
||
509 | } |
||
510 | |||
511 | /** |
||
512 | * Get the number of set squares in the specified bitboard. |
||
513 | */ |
||
514 | int getNumberOfSetSquares(const Bitboard bitboard) |
||
515 | { |
||
516 | return __builtin_popcountll(bitboard); |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * Get the rank overlay of the specified bitboard. |
||
521 | */ |
||
522 | int getRankOverlay(const Bitboard bitboard) |
||
523 | { |
||
524 | return rankOverlay[(bitboard) & UHEX_FFFF] | |
||
525 | rankOverlay[(bitboard >> 16) & UHEX_FFFF] | |
||
526 | rankOverlay[(bitboard >> 32) & UHEX_FFFF] | |
||
527 | rankOverlay[(bitboard >> 48) & UHEX_FFFF]; |
||
528 | } |
||
529 | |||
530 | /** |
||
531 | * Get the moves of the the specified piece. |
||
532 | */ |
||
533 | Bitboard getMoves(Square square, Piece piece, Bitboard allPieces) |
||
534 | { |
||
535 | switch (pieceType(piece)) |
||
536 | { |
||
537 | case PAWN: |
||
538 | return getPawnCaptures(piece, square, allPieces) | |
||
539 | getPawnAdvances(pieceColor(piece), square, allPieces); |
||
540 | case KING: |
||
541 | return getKingMoves(square); |
||
542 | case KNIGHT: |
||
543 | return getKnightMoves(square); |
||
544 | case ROOK: |
||
545 | return getMagicRookMoves(square, allPieces); |
||
546 | case BISHOP: |
||
547 | return getMagicBishopMoves(square, allPieces); |
||
548 | default: |
||
549 | return getMagicQueenMoves(square, allPieces); |
||
550 | } |
||
551 | } |
||
552 | |||
553 | /** |
||
554 | * Get the capture moves of the the specified piece. |
||
555 | */ |
||
556 | Bitboard getCaptureMoves(Square square, Piece piece, Bitboard allPieces) |
||
557 | { |
||
558 | switch (pieceType(piece)) |
||
559 | { |
||
560 | case PAWN: |
||
561 | return getPawnCaptures(piece, square, allPieces); |
||
562 | case KING: |
||
563 | return getKingMoves(square); |
||
564 | case KNIGHT: |
||
565 | return getKnightMoves(square); |
||
566 | case ROOK: |
||
567 | return getMagicRookMoves(square, allPieces); |
||
568 | case BISHOP: |
||
569 | return getMagicBishopMoves(square, allPieces); |
||
570 | default: |
||
571 | return getMagicQueenMoves(square, allPieces); |
||
572 | } |
||
573 | } |
||
574 | |||
575 | /** |
||
576 | * Set a square in the specified vector of obstacles. |
||
577 | */ |
||
578 | void setObstacleSquare(Square square, BYTE obstacles[NUM_LANES]) |
||
579 | { |
||
580 | SquareLaneInfo *sqi = &squareLaneInfo[square]; |
||
581 | |||
582 | obstacles[sqi->hLane] |= sqi->hLaneSetMask; |
||
583 | obstacles[sqi->vLane] |= sqi->vLaneSetMask; |
||
584 | obstacles[sqi->uLane] |= sqi->uLaneSetMask; |
||
585 | obstacles[sqi->dLane] |= sqi->dLaneSetMask; |
||
586 | } |
||
587 | |||
588 | /** |
||
589 | * Clear a square in the specified vector of obstacles. |
||
590 | */ |
||
591 | void clearObstacleSquare(Square square, BYTE obstacles[NUM_LANES]) |
||
592 | { |
||
593 | SquareLaneInfo *sqi = &squareLaneInfo[square]; |
||
594 | |||
595 | obstacles[sqi->hLane] &= sqi->hLaneClearMask; |
||
596 | obstacles[sqi->vLane] &= sqi->vLaneClearMask; |
||
597 | obstacles[sqi->uLane] &= sqi->uLaneClearMask; |
||
598 | obstacles[sqi->dLane] &= sqi->dLaneClearMask; |
||
599 | } |
||
600 | |||
601 | /** |
||
602 | * Calculate all obstacles according to the specified bitboard. |
||
603 | */ |
||
604 | void calculateObstacles(Bitboard board, BYTE obstacles[NUM_LANES]) |
||
605 | { |
||
606 | Square square; |
||
607 | |||
608 | memset(obstacles, 0x00, NUM_LANES); |
||
609 | |||
610 | ITERATE(square) |
||
611 | { |
||
612 | if (board & minValue[square]) |
||
613 | { |
||
614 | setObstacleSquare(square, obstacles); |
||
615 | } |
||
616 | } |
||
617 | } |
||
618 | |||
619 | /** |
||
620 | * Get the number of a set square and clear the corresponding bit. |
||
621 | * |
||
622 | * @return NO_SQUARE if no square was set. |
||
623 | */ |
||
624 | Square getLastSquare(Bitboard * vector); |
||
625 | |||
626 | /** |
||
627 | * Extend all set bits by one square into all directions. |
||
628 | */ |
||
629 | void floodBoard(Bitboard * board); |
||
630 | |||
631 | /** |
||
632 | * Get the targets of all pawns specified by 'whitePawns'. |
||
633 | */ |
||
634 | Bitboard getWhitePawnTargets(const Bitboard whitePawns) |
||
635 | { |
||
636 | return ((whitePawns & nonA) << 7) | ((whitePawns & nonH) << 9); |
||
637 | } |
||
638 | |||
639 | /** |
||
640 | * Get the targets of all pawns specified by 'blackPawns'. |
||
641 | */ |
||
642 | Bitboard getBlackPawnTargets(const Bitboard blackPawns) |
||
643 | { |
||
644 | return ((blackPawns & nonA) >> 9) | ((blackPawns & nonH) >> 7); |
||
645 | } |
||
646 | |||
647 | /** |
||
648 | * Iteration shortcuts |
||
649 | */ |
||
650 | #define ITERATE_BITBOARD(b,sq) while ( ( sq = getLastSquare(b) ) >= 0 ) |
||
651 | |||
652 | void floodBoard(Bitboard * board) |
||
653 | { |
||
654 | const Bitboard toLeft = *board & nonA, toRight = *board & nonH; |
||
655 | |||
656 | *board = (toLeft >> 1) | (toLeft << 7) | (*board >> 8) | (toLeft >> 9) | |
||
657 | (toRight << 1) | (toRight >> 7) | (*board << 8) | (toRight << 9); |
||
658 | } |
||
659 | |||
660 | Square getLastSquare(Bitboard * vector) |
||
661 | { |
||
662 | if (*vector == EMPTY_BITBOARD) |
||
663 | { |
||
664 | return NO_SQUARE; |
||
665 | } |
||
666 | else |
||
667 | { |
||
668 | const int index = 63 - __builtin_clzll(*vector); |
||
669 | |||
670 | *vector &= maxValue[index]; |
||
671 | |||
672 | return index; |
||
673 | } |
||
674 | } |
||
675 | |||
676 | Square getFirstSquare(Bitboard * vector) |
||
677 | { |
||
678 | if (*vector == EMPTY_BITBOARD) |
||
679 | { |
||
680 | return NO_SQUARE; |
||
681 | } |
||
682 | else |
||
683 | { |
||
684 | const int index = __builtin_ctzll(*vector); |
||
685 | |||
686 | *vector &= maxValue[index]; |
||
687 | |||
688 | return index; |
||
689 | } |
||
690 | } |
||
691 | |||
692 | int getSetSquares(const Bitboard board, UINT8 squares[_64_]) |
||
693 | { |
||
694 | int index; |
||
695 | UINT8 *currentSquare = &squares[0]; |
||
696 | |||
697 | if ((index = (int) (0xFFFF & board)) != 0) |
||
698 | { |
||
699 | const SetSquaresInfo *info = &setSquares[0][index]; |
||
700 | |||
701 | memcpy(currentSquare, info->setSquares, info->numSetSquares); |
||
702 | currentSquare += info->numSetSquares; |
||
703 | } |
||
704 | |||
705 | if ((index = (int) (0xFFFF & (board >> 16))) != 0) |
||
706 | { |
||
707 | const SetSquaresInfo *info = &setSquares[1][index]; |
||
708 | |||
709 | memcpy(currentSquare, info->setSquares, info->numSetSquares); |
||
710 | currentSquare += info->numSetSquares; |
||
711 | } |
||
712 | |||
713 | if ((index = (int) (0xFFFF & (board >> 32))) != 0) |
||
714 | { |
||
715 | const SetSquaresInfo *info = &setSquares[2][index]; |
||
716 | |||
717 | memcpy(currentSquare, info->setSquares, info->numSetSquares); |
||
718 | currentSquare += info->numSetSquares; |
||
719 | } |
||
720 | |||
721 | if ((index = (int) (board >> 48)) != 0) |
||
722 | { |
||
723 | const SetSquaresInfo *info = &setSquares[3][index]; |
||
724 | |||
725 | memcpy(currentSquare, info->setSquares, info->numSetSquares); |
||
726 | currentSquare += info->numSetSquares; |
||
727 | } |
||
728 | |||
729 | return (int) (currentSquare - &squares[0]); |
||
730 | } |
||
731 | |||
732 | Bitboard getMultipleSquaresBetween(const Square origin, Bitboard targets) |
||
733 | { |
||
734 | Bitboard squares = targets; |
||
735 | Square targetSquare; |
||
736 | Bitboard *sqb = &(squaresBetween[origin][0]); |
||
737 | |||
738 | ITERATE_BITBOARD(&targets, targetSquare) |
||
739 | { |
||
740 | squares |= sqb[targetSquare]; |
||
741 | } |
||
742 | |||
743 | return squares; |
||
744 | } |
||
745 | |||
746 | int getFloodValue(const Square origin, const Bitboard targets, |
||
747 | const Bitboard permittedSquares) |
||
748 | { |
||
749 | Bitboard floodedSquares = getKingMoves(origin) & permittedSquares; |
||
750 | Bitboard oldFloodedSquares = minValue[origin]; |
||
751 | int numSteps = 1; |
||
752 | |||
753 | while ((targets & floodedSquares) == EMPTY_BITBOARD && |
||
754 | floodedSquares != oldFloodedSquares) |
||
755 | { |
||
756 | oldFloodedSquares = floodedSquares; |
||
757 | floodBoard(&floodedSquares); |
||
758 | floodedSquares |= oldFloodedSquares; |
||
759 | floodedSquares &= permittedSquares; |
||
760 | numSteps++; |
||
761 | } |
||
762 | |||
763 | return numSteps; |
||
764 | } |
||
765 | |||
766 | static void initializeKingMoves() |
||
767 | { |
||
768 | int offset[] = { 1, -1, 7, -7, 8, -8, 9, -9 }, direction; |
||
769 | Square square; |
||
770 | |||
771 | ITERATE(square) |
||
772 | { |
||
773 | for (direction = 0; direction < 8; direction++) |
||
774 | { |
||
775 | Square target = (Square) (square + offset[direction]); |
||
776 | |||
777 | if (squareIsValid(target) && distance(square, target) == 1) |
||
778 | { |
||
779 | generalMoves[KING][square] |= minValue[target]; |
||
780 | } |
||
781 | } |
||
782 | } |
||
783 | } |
||
784 | |||
785 | static void initializeRookMoves() |
||
786 | { |
||
787 | int offset[] = { 1, -1, 8, -8 }, direction, moveLength; |
||
788 | Square square; |
||
789 | |||
790 | ITERATE(square) |
||
791 | { |
||
792 | for (direction = 0; direction < 4; direction++) |
||
793 | { |
||
794 | for (moveLength = 1; moveLength <= 7; moveLength++) |
||
795 | { |
||
796 | Square target = |
||
797 | (Square) (square + offset[direction] * moveLength); |
||
798 | bool sameFile = (bool) (file(square) == file(target)); |
||
799 | bool sameRow = (bool) (rank(square) == rank(target)); |
||
800 | |||
801 | if (squareIsValid(target) && (sameFile || sameRow)) |
||
802 | { |
||
803 | generalMoves[ROOK][square] |= minValue[target]; |
||
804 | } |
||
805 | else |
||
806 | { |
||
807 | break; |
||
808 | } |
||
809 | } |
||
810 | } |
||
811 | } |
||
812 | } |
||
813 | |||
814 | static void initializeBishopMoves() |
||
815 | { |
||
816 | int offset[] = { 7, -7, 9, -9 }, direction, moveLength; |
||
817 | Square square; |
||
818 | |||
819 | ITERATE(square) |
||
820 | { |
||
821 | for (direction = 0; direction < 4; direction++) |
||
822 | { |
||
823 | for (moveLength = 1; moveLength <= 7; moveLength++) |
||
824 | { |
||
825 | Square target = |
||
826 | (Square) (square + offset[direction] * moveLength); |
||
827 | int hDistance = horizontalDistance(square, target); |
||
828 | int vDistance = verticalDistance(square, target); |
||
829 | |||
830 | if (squareIsValid(target) && hDistance == vDistance) |
||
831 | { |
||
832 | generalMoves[BISHOP][square] |= minValue[target]; |
||
833 | } |
||
834 | else |
||
835 | { |
||
836 | break; |
||
837 | } |
||
838 | } |
||
839 | } |
||
840 | } |
||
841 | } |
||
842 | |||
843 | static void initializeQueenMoves() |
||
844 | { |
||
845 | Square square; |
||
846 | |||
847 | ITERATE(square) |
||
848 | { |
||
849 | generalMoves[QUEEN][square] = |
||
850 | generalMoves[ROOK][square] | generalMoves[BISHOP][square]; |
||
851 | } |
||
852 | } |
||
853 | |||
854 | static void initializeKnightMoves() |
||
855 | { |
||
856 | int offset[] = { 6, -6, 10, -10, 15, -15, 17, -17 }, direction; |
||
857 | Square square; |
||
858 | |||
859 | ITERATE(square) |
||
860 | { |
||
861 | for (direction = 0; direction < 8; direction++) |
||
862 | { |
||
863 | Square target = (Square) (square + offset[direction]); |
||
864 | |||
865 | if (squareIsValid(target) && distance(square, target) <= 2) |
||
866 | { |
||
867 | generalMoves[KNIGHT][square] |= minValue[target]; |
||
868 | } |
||
869 | } |
||
870 | } |
||
871 | } |
||
872 | |||
873 | static void initializePawnMoves() |
||
874 | { |
||
875 | Square square; |
||
876 | |||
877 | ITERATE(square) |
||
878 | { |
||
879 | if (file(square) != FILE_A) |
||
880 | { |
||
881 | if (square <= H8 - 7) |
||
882 | { |
||
883 | generalMoves[WHITE_PAWN][square] |= minValue[square + 7]; |
||
884 | } |
||
885 | |||
886 | if (square >= A1 + 9) |
||
887 | { |
||
888 | generalMoves[BLACK_PAWN][square] |= minValue[square - 9]; |
||
889 | } |
||
890 | } |
||
891 | |||
892 | if (file(square) != FILE_H) |
||
893 | { |
||
894 | if (square <= H8 - 9) |
||
895 | { |
||
896 | generalMoves[WHITE_PAWN][square] |= minValue[square + 9]; |
||
897 | } |
||
898 | |||
899 | if (square >= A1 + 7) |
||
900 | { |
||
901 | generalMoves[BLACK_PAWN][square] |= minValue[square - 7]; |
||
902 | } |
||
903 | } |
||
904 | } |
||
905 | } |
||
906 | |||
907 | static Bitboard calculateSquaresBehind(Square square, int offset) |
||
908 | { |
||
909 | Bitboard squares = EMPTY_BITBOARD; |
||
910 | |||
911 | for (square = (Square) (square + offset); |
||
912 | squareIsValid(square) && |
||
913 | distance(square, (Square) (square - offset)) == 1; |
||
914 | square = (Square) (square + offset)) |
||
915 | { |
||
916 | Bitboard mv = minValue[square]; |
||
917 | |||
918 | squares |= mv; |
||
919 | } |
||
920 | |||
921 | return squares; |
||
922 | } |
||
923 | |||
924 | static void initializeSquaresBehind() |
||
925 | { |
||
926 | Square sq1, sq2; |
||
927 | |||
928 | ITERATE(sq1) |
||
929 | { |
||
930 | Bitboard squares = generalMoves[QUEEN][sq1]; |
||
931 | |||
932 | ITERATE_BITBOARD(&squares, sq2) |
||
933 | { |
||
934 | int offset = offset(sq1, sq2); |
||
935 | |||
936 | squaresBehind[sq2][sq1] = calculateSquaresBehind(sq2, offset); |
||
937 | } |
||
938 | } |
||
939 | } |
||
940 | |||
941 | static Bitboard calculateSquaresBetween(Square sq1, Square sq2) |
||
942 | { |
||
943 | Bitboard squares = EMPTY_BITBOARD; |
||
944 | int _offset = offset(sq1, sq2), square; |
||
945 | |||
946 | for (square = sq1 + _offset; square != sq2; square += _offset) |
||
947 | { |
||
948 | squares |= minValue[square]; |
||
949 | } |
||
950 | |||
951 | return squares; |
||
952 | } |
||
953 | |||
954 | static void initializeSquaresBetween() |
||
955 | { |
||
956 | Square sq1, sq2; |
||
957 | |||
958 | ITERATE(sq1) |
||
959 | { |
||
960 | Bitboard squares = generalMoves[QUEEN][sq1]; |
||
961 | |||
962 | ITERATE_BITBOARD(&squares, sq2) |
||
963 | { |
||
964 | squaresBetween[sq1][sq2] = calculateSquaresBetween(sq1, sq2); |
||
965 | } |
||
966 | } |
||
967 | } |
||
968 | |||
969 | static void initializeSquareLaneInfo() |
||
970 | { |
||
971 | Square square; |
||
972 | |||
973 | ITERATE(square) |
||
974 | { |
||
975 | SquareLaneInfo *sqi = &squareLaneInfo[square]; |
||
976 | |||
977 | sqi->hLane = hLaneNumber[square] = HLANE(square); |
||
978 | sqi->hLaneSetMask = (BYTE) minValue[HLANEBIT(square)]; |
||
979 | sqi->hLaneClearMask = (BYTE) ~ sqi->hLaneSetMask; |
||
980 | |||
981 | sqi->vLane = vLaneNumber[square] = VLANE(square) + 8; |
||
982 | sqi->vLaneSetMask = (BYTE) minValue[VLANEBIT(square)]; |
||
983 | sqi->vLaneClearMask = (BYTE) ~ sqi->vLaneSetMask; |
||
984 | |||
985 | sqi->uLane = uLaneNumber[square] = ULANE(square) + 16; |
||
986 | sqi->uLaneSetMask = (BYTE) minValue[ULANEBIT(square)]; |
||
987 | sqi->uLaneClearMask = (BYTE) ~ sqi->uLaneSetMask; |
||
988 | |||
989 | sqi->dLane = dLaneNumber[square] = DLANE(square) + 31; |
||
990 | sqi->dLaneSetMask = (BYTE) minValue[DLANEBIT(square)]; |
||
991 | sqi->dLaneClearMask = (BYTE) ~ sqi->dLaneSetMask; |
||
992 | } |
||
993 | } |
||
994 | |||
995 | static Bitboard getHlaneVector(int lane, BYTE mask) |
||
996 | { |
||
997 | int i; |
||
998 | Bitboard v = EMPTY_BITBOARD; |
||
999 | |||
1000 | for (i = 0; i < 8; i++) |
||
1001 | { |
||
1002 | if (mask & minValue[i]) |
||
1003 | { |
||
1004 | v |= minValue[7 - i]; |
||
1005 | } |
||
1006 | } |
||
1007 | |||
1008 | v <<= 8 * lane; |
||
1009 | |||
1010 | return v; |
||
1011 | } |
||
1012 | |||
1013 | static Bitboard getVlaneVector(int lane, BYTE mask) |
||
1014 | { |
||
1015 | int i; |
||
1016 | Bitboard v = EMPTY_BITBOARD; |
||
1017 | |||
1018 | for (i = 0; i < 8; i++) |
||
1019 | { |
||
1020 | if (mask & minValue[i]) |
||
1021 | { |
||
1022 | v |= minValue[8 * (7 - i)]; |
||
1023 | } |
||
1024 | } |
||
1025 | |||
1026 | v <<= lane; |
||
1027 | |||
1028 | return v; |
||
1029 | } |
||
1030 | |||
1031 | static Bitboard getUlaneVector(int lane, BYTE mask) |
||
1032 | { |
||
1033 | int i; |
||
1034 | Bitboard v = EMPTY_BITBOARD; |
||
1035 | |||
1036 | for (i = 0; i < 8; i++) |
||
1037 | { |
||
1038 | v <<= 8; |
||
1039 | |||
1040 | if (mask & minValue[i]) |
||
1041 | { |
||
1042 | v |= minValue[7 - i]; |
||
1043 | } |
||
1044 | } |
||
1045 | |||
1046 | if (lane < 7) |
||
1047 | { |
||
1048 | for (i = lane; i < 7; i++) |
||
1049 | { |
||
1050 | v = (v & nonA) >> 1; |
||
1051 | } |
||
1052 | } |
||
1053 | else |
||
1054 | { |
||
1055 | for (i = lane; i > 7; i--) |
||
1056 | { |
||
1057 | v = (v & nonH) << 1; |
||
1058 | } |
||
1059 | } |
||
1060 | |||
1061 | return v; |
||
1062 | } |
||
1063 | |||
1064 | static Bitboard getDlaneVector(int lane, BYTE mask) |
||
1065 | { |
||
1066 | int i; |
||
1067 | Bitboard v = EMPTY_BITBOARD; |
||
1068 | |||
1069 | for (i = 0; i < 8; i++) |
||
1070 | { |
||
1071 | v <<= 8; |
||
1072 | |||
1073 | if (mask & minValue[7 - i]) |
||
1074 | { |
||
1075 | v |= minValue[i]; |
||
1076 | } |
||
1077 | } |
||
1078 | |||
1079 | if (lane < 7) |
||
1080 | { |
||
1081 | for (i = lane; i < 7; i++) |
||
1082 | { |
||
1083 | v = (v & nonA) >> 1; |
||
1084 | } |
||
1085 | } |
||
1086 | else |
||
1087 | { |
||
1088 | for (i = lane; i > 7; i--) |
||
1089 | { |
||
1090 | v = (v & nonH) << 1; |
||
1091 | } |
||
1092 | } |
||
1093 | |||
1094 | return v; |
||
1095 | } |
||
1096 | |||
1097 | static Bitboard getLaneMask(Square square, int offset, |
||
1098 | Bitboard legalSquares, Bitboard obstacles) |
||
1099 | { |
||
1100 | Bitboard laneMask = EMPTY_BITBOARD, mv = EMPTY_BITBOARD; |
||
1101 | |||
1102 | while ((square = (Square) (square + offset)) >= A1 && |
||
1103 | square <= H8 && ((mv = minValue[square]) & legalSquares)) |
||
1104 | { |
||
1105 | laneMask |= mv; |
||
1106 | |||
1107 | if (mv & obstacles) |
||
1108 | { |
||
1109 | break; |
||
1110 | } |
||
1111 | } |
||
1112 | |||
1113 | return laneMask; |
||
1114 | } |
||
1115 | |||
1116 | static Bitboard getHLaneMask(Square square, BYTE mask) |
||
1117 | { |
||
1118 | int lane = HLANE(square); |
||
1119 | Bitboard legalSquares = getHlaneVector(lane, 255); |
||
1120 | Bitboard obstacles = getHlaneVector(lane, mask); |
||
1121 | |||
1122 | Bitboard laneMask = getLaneMask(square, 1, legalSquares, obstacles); |
||
1123 | |||
1124 | laneMask |= getLaneMask(square, -1, legalSquares, obstacles); |
||
1125 | |||
1126 | return laneMask; |
||
1127 | } |
||
1128 | |||
1129 | static Bitboard getVLaneMask(Square square, BYTE mask) |
||
1130 | { |
||
1131 | int lane = VLANE(square); |
||
1132 | Bitboard legalSquares = getVlaneVector(lane, 255); |
||
1133 | Bitboard obstacles = getVlaneVector(lane, mask); |
||
1134 | |||
1135 | Bitboard laneMask = getLaneMask(square, 8, legalSquares, obstacles); |
||
1136 | |||
1137 | laneMask |= getLaneMask(square, -8, legalSquares, obstacles); |
||
1138 | |||
1139 | return laneMask; |
||
1140 | } |
||
1141 | |||
1142 | static Bitboard getULaneMask(Square square, BYTE mask) |
||
1143 | { |
||
1144 | int lane = ULANE(square); |
||
1145 | Bitboard legalSquares = getUlaneVector(lane, 255); |
||
1146 | Bitboard obstacles = getUlaneVector(lane, mask); |
||
1147 | |||
1148 | Bitboard laneMask = getLaneMask(square, 9, legalSquares, obstacles); |
||
1149 | |||
1150 | laneMask |= getLaneMask(square, -9, legalSquares, obstacles); |
||
1151 | |||
1152 | return laneMask; |
||
1153 | } |
||
1154 | |||
1155 | static Bitboard getDLaneMask(Square square, BYTE mask) |
||
1156 | { |
||
1157 | int lane = DLANE(square); |
||
1158 | Bitboard legalSquares = getDlaneVector(lane, 255); |
||
1159 | Bitboard obstacles = getDlaneVector(lane, mask); |
||
1160 | |||
1161 | Bitboard laneMask = getLaneMask(square, 7, legalSquares, obstacles); |
||
1162 | |||
1163 | laneMask |= getLaneMask(square, -7, legalSquares, obstacles); |
||
1164 | |||
1165 | return laneMask; |
||
1166 | } |
||
1167 | |||
1168 | static Bitboard getWhitePawnMoves(Square square, BYTE laneMask) |
||
1169 | { |
||
1170 | int lane = VLANE(square); |
||
1171 | Bitboard moves = EMPTY_BITBOARD, board = getVlaneVector(lane, laneMask); |
||
1172 | |||
1173 | if (square >= A2 && square <= H7 && (board & minValue[square + 8]) == 0) |
||
1174 | { |
||
1175 | moves |= minValue[square + 8]; |
||
1176 | |||
1177 | if (square <= H2 && (board & minValue[square + 16]) == 0) |
||
1178 | { |
||
1179 | moves |= minValue[square + 16]; |
||
1180 | } |
||
1181 | } |
||
1182 | |||
1183 | return moves; |
||
1184 | } |
||
1185 | |||
1186 | static Bitboard getInterestedWhitePawns(Square square, BYTE laneMask) |
||
1187 | { |
||
1188 | int lane = VLANE(square); |
||
1189 | Bitboard pawns = EMPTY_BITBOARD, board = getVlaneVector(lane, laneMask); |
||
1190 | |||
1191 | if (square >= A3 && square <= H8 && (board & minValue[square]) == 0) |
||
1192 | { |
||
1193 | pawns |= minValue[square - 8]; |
||
1194 | |||
1195 | if (rank(square) == RANK_4 && (board & minValue[square - 8]) == 0) |
||
1196 | { |
||
1197 | pawns |= minValue[square - 16]; |
||
1198 | } |
||
1199 | } |
||
1200 | |||
1201 | return pawns; |
||
1202 | } |
||
1203 | |||
1204 | static Bitboard getBlackPawnMoves(Square square, BYTE laneMask) |
||
1205 | { |
||
1206 | int lane = VLANE(square); |
||
1207 | Bitboard moves = EMPTY_BITBOARD, board = getVlaneVector(lane, laneMask); |
||
1208 | |||
1209 | if (square >= A2 && square <= H7 && (board & minValue[square - 8]) == 0) |
||
1210 | { |
||
1211 | moves |= minValue[square - 8]; |
||
1212 | |||
1213 | if (square >= A7 && (board & minValue[square - 16]) == 0) |
||
1214 | { |
||
1215 | moves |= minValue[square - 16]; |
||
1216 | } |
||
1217 | } |
||
1218 | |||
1219 | return moves; |
||
1220 | } |
||
1221 | |||
1222 | static Bitboard getInterestedBlackPawns(Square square, BYTE laneMask) |
||
1223 | { |
||
1224 | int lane = VLANE(square); |
||
1225 | Bitboard pawns = EMPTY_BITBOARD, board = getVlaneVector(lane, laneMask); |
||
1226 | |||
1227 | if (square >= A1 && square <= H6 && (board & minValue[square]) == 0) |
||
1228 | { |
||
1229 | pawns |= minValue[square + 8]; |
||
1230 | |||
1231 | if (rank(square) == RANK_5 && (board & minValue[square + 8]) == 0) |
||
1232 | { |
||
1233 | pawns |= minValue[square + 16]; |
||
1234 | } |
||
1235 | } |
||
1236 | |||
1237 | return pawns; |
||
1238 | } |
||
1239 | |||
1240 | static void initializeLaneMasks() |
||
1241 | { |
||
1242 | Square square; |
||
1243 | int i; |
||
1244 | |||
1245 | ITERATE(square) |
||
1246 | { |
||
1247 | for (i = 0; i <= 255; i++) |
||
1248 | { |
||
1249 | BYTE mask = (BYTE) i; |
||
1250 | |||
1251 | hlane[square][i] = getHLaneMask(square, mask); |
||
1252 | vlane[square][i] = getVLaneMask(square, mask); |
||
1253 | ulane[square][i] = getULaneMask(square, mask); |
||
1254 | dlane[square][i] = getDLaneMask(square, mask); |
||
1255 | pawnMoves[WHITE][square][i] = getWhitePawnMoves(square, mask); |
||
1256 | pawnMoves[BLACK][square][i] = getBlackPawnMoves(square, mask); |
||
1257 | interestedPawns[WHITE][square][i] = |
||
1258 | getInterestedWhitePawns(square, mask); |
||
1259 | interestedPawns[BLACK][square][i] = |
||
1260 | getInterestedBlackPawns(square, mask); |
||
1261 | } |
||
1262 | } |
||
1263 | |||
1264 | ITERATE(square) |
||
1265 | { |
||
1266 | int i; |
||
1267 | |||
1268 | obsi[square].hLaneNumber = hLaneNumber[square]; |
||
1269 | obsi[square].vLaneNumber = vLaneNumber[square]; |
||
1270 | obsi[square].uLaneNumber = uLaneNumber[square]; |
||
1271 | obsi[square].dLaneNumber = dLaneNumber[square]; |
||
1272 | |||
1273 | for (i = 0; i < 256; i++) |
||
1274 | { |
||
1275 | obsi[square].hLane[i] = hlane[square][i]; |
||
1276 | obsi[square].vLane[i] = vlane[square][i]; |
||
1277 | obsi[square].uLane[i] = ulane[square][i]; |
||
1278 | obsi[square].dLane[i] = dlane[square][i]; |
||
1279 | } |
||
1280 | } |
||
1281 | } |
||
1282 | |||
1283 | static Bitboard getCastlings(const Bitboard obstacles) |
||
1284 | { |
||
1285 | Bitboard castlings = EMPTY_BITBOARD; |
||
1286 | |||
1287 | if ((obstacles & minValue[F1]) == EMPTY_BITBOARD && |
||
1288 | (obstacles & minValue[G1]) == EMPTY_BITBOARD) |
||
1289 | { |
||
1290 | castlings |= minValue[G1]; |
||
1291 | } |
||
1292 | |||
1293 | if ((obstacles & minValue[B1]) == EMPTY_BITBOARD && |
||
1294 | (obstacles & minValue[C1]) == EMPTY_BITBOARD && |
||
1295 | (obstacles & minValue[D1]) == EMPTY_BITBOARD) |
||
1296 | { |
||
1297 | castlings |= minValue[C1]; |
||
1298 | } |
||
1299 | |||
1300 | return castlings; |
||
1301 | } |
||
1302 | |||
1303 | static void initializeCastlings() |
||
1304 | { |
||
1305 | int i, c; |
||
1306 | |||
1307 | for (i = 0; i <= 255; i++) |
||
1308 | { |
||
1309 | BYTE mask = (BYTE) i; |
||
1310 | Bitboard moves = getCastlings((Bitboard) mask); |
||
1311 | |||
1312 | for (c = 0; c <= 15; c++) |
||
1313 | { |
||
1314 | castlings[WHITE][c][mask] = castlings[BLACK][c][mask] = 0; |
||
1315 | |||
1316 | if (moves & minValue[G1]) |
||
1317 | { |
||
1318 | if (c & WHITE_00) |
||
1319 | { |
||
1320 | castlings[WHITE][c][mask] |= minValue[G1]; |
||
1321 | } |
||
1322 | |||
1323 | if (c & BLACK_00) |
||
1324 | { |
||
1325 | castlings[BLACK][c][mask] |= minValue[G8]; |
||
1326 | } |
||
1327 | } |
||
1328 | |||
1329 | if (moves & minValue[C1]) |
||
1330 | { |
||
1331 | if (c & WHITE_000) |
||
1332 | { |
||
1333 | castlings[WHITE][c][mask] |= minValue[C1]; |
||
1334 | } |
||
1335 | |||
1336 | if (c & BLACK_000) |
||
1337 | { |
||
1338 | castlings[BLACK][c][mask] |= minValue[C8]; |
||
1339 | } |
||
1340 | } |
||
1341 | } |
||
1342 | } |
||
1343 | } |
||
1344 | |||
1345 | static INT8 _getNumberOfSetBits(INT32 v) |
||
1346 | { |
||
1347 | int count = 0, i; |
||
1348 | |||
1349 | for (i = 0; i < 16; i++) |
||
1350 | { |
||
1351 | count += (v >> i) & 1; |
||
1352 | } |
||
1353 | |||
1354 | return (INT8) count; |
||
1355 | } |
||
1356 | |||
1357 | static UINT8 _getRankOverlay(INT32 v) |
||
1358 | { |
||
1359 | return (UINT8) ((v & 0xff) | ((v >> 8) & 0xff)); |
||
1360 | } |
||
1361 | |||
1362 | unsigned int getMinimumDistance(const Bitboard targets, const Square square) |
||
1363 | { |
||
1364 | unsigned int distance; |
||
1365 | |||
1366 | for (distance = 1; distance <= 7; distance++) |
||
1367 | { |
||
1368 | if ((squaresInDistance[distance][square] & targets) != EMPTY_BITBOARD) |
||
1369 | { |
||
1370 | return distance; |
||
1371 | } |
||
1372 | } |
||
1373 | |||
1374 | return 0; |
||
1375 | } |
||
1376 | |||
1377 | unsigned int getMaximumDistance(const Bitboard targets, const Square square) |
||
1378 | { |
||
1379 | unsigned int distance; |
||
1380 | |||
1381 | for (distance = 7; distance > 0; distance--) |
||
1382 | { |
||
1383 | if ((squaresInDistance[distance][square] & targets) != EMPTY_BITBOARD) |
||
1384 | { |
||
1385 | return distance; |
||
1386 | } |
||
1387 | } |
||
1388 | |||
1389 | return 0; |
||
1390 | } |
||
1391 | |||
1392 | static Bitboard getPremaskExclusions(const Square square) |
||
1393 | { |
||
1394 | if (testSquare(border, square)) |
||
1395 | { |
||
1396 | Bitboard exclusions = EMPTY_BITBOARD; |
||
1397 | |||
1398 | if (testSquare(squaresOfFile[FILE_A], square) == FALSE) |
||
1399 | { |
||
1400 | exclusions |= squaresOfFile[FILE_A]; |
||
1401 | } |
||
1402 | |||
1403 | if (testSquare(squaresOfFile[FILE_H], square) == FALSE) |
||
1404 | { |
||
1405 | exclusions |= squaresOfFile[FILE_H]; |
||
1406 | } |
||
1407 | |||
1408 | if (testSquare(squaresOfRank[RANK_1], square) == FALSE) |
||
1409 | { |
||
1410 | exclusions |= squaresOfRank[RANK_1]; |
||
1411 | } |
||
1412 | |||
1413 | if (testSquare(squaresOfRank[RANK_8], square) == FALSE) |
||
1414 | { |
||
1415 | exclusions |= squaresOfRank[RANK_8]; |
||
1416 | } |
||
1417 | |||
1418 | return exclusions; |
||
1419 | } |
||
1420 | else |
||
1421 | { |
||
1422 | return border; |
||
1423 | } |
||
1424 | } |
||
1425 | |||
1426 | static void initializePremasks() |
||
1427 | { |
||
1428 | Square square; |
||
1429 | |||
1430 | ITERATE(square) |
||
1431 | { |
||
1432 | preMaskRook[square] = generalMoves[WHITE_ROOK][square] & |
||
1433 | ~getPremaskExclusions(square); |
||
1434 | preMaskBishop[square] = generalMoves[WHITE_BISHOP][square] & |
||
1435 | ~getPremaskExclusions(square); |
||
1436 | } |
||
1437 | } |
||
1438 | |||
1439 | static void initializeMagicRookMoves(const Square square) |
||
1440 | { |
||
1441 | Square squareOfIndex[12]; |
||
1442 | Bitboard allMoves = preMaskRook[square]; |
||
1443 | const Bitboard premask = preMaskRook[square]; |
||
1444 | int i, pieceSetup; |
||
1445 | Square sq1; |
||
1446 | BYTE obstacles[NUM_LANES]; |
||
1447 | const Bitboard magicNumber = magicRookNumber[square]; |
||
1448 | |||
1449 | for (i = 0; i < IMAX_ROOK; i++) |
||
1450 | { |
||
1451 | magicRookMoves[square][i] = EMPTY_BITBOARD; |
||
1452 | } |
||
1453 | |||
1454 | for (i = 0; i < 12; i++) |
||
1455 | { |
||
1456 | squareOfIndex[i] = NO_SQUARE; |
||
1457 | } |
||
1458 | |||
1459 | i = 0; |
||
1460 | |||
1461 | ITERATE_BITBOARD(&allMoves, sq1) |
||
1462 | { |
||
1463 | assert(i < 12); |
||
1464 | |||
1465 | squareOfIndex[i++] = sq1; |
||
1466 | } |
||
1467 | |||
1468 | for (pieceSetup = 0; pieceSetup < 4096; pieceSetup++) |
||
1469 | { |
||
1470 | Bitboard currentSetup = EMPTY_BITBOARD, effectiveMoves; |
||
1471 | int j = 1; |
||
1472 | Bitboard magicIndex; |
||
1473 | |||
1474 | for (i = 0; i < 12 && squareOfIndex[i] != NO_SQUARE; i++) |
||
1475 | { |
||
1476 | if ((pieceSetup & j) != 0) |
||
1477 | { |
||
1478 | setSquare(currentSetup, squareOfIndex[i]); |
||
1479 | } |
||
1480 | |||
1481 | j *= 2; |
||
1482 | } |
||
1483 | |||
1484 | calculateObstacles(currentSetup, obstacles); |
||
1485 | effectiveMoves = getRookMoves(square, obstacles); |
||
1486 | magicIndex = ((currentSetup & premask) * magicNumber) >> 52; |
||
1487 | magicRookMoves[square][magicIndex] = effectiveMoves; |
||
1488 | } |
||
1489 | } |
||
1490 | |||
1491 | static void initializeMagicBishopMoves(const Square square) |
||
1492 | { |
||
1493 | Square squareOfIndex[12]; |
||
1494 | Bitboard allMoves = preMaskBishop[square]; |
||
1495 | const Bitboard premask = preMaskBishop[square]; |
||
1496 | int i, pieceSetup; |
||
1497 | Square sq1; |
||
1498 | BYTE obstacles[NUM_LANES]; |
||
1499 | const Bitboard magicNumber = magicBishopNumber[square]; |
||
1500 | |||
1501 | for (i = 0; i < IMAX_BISHOP; i++) |
||
1502 | { |
||
1503 | magicBishopMoves[square][i] = EMPTY_BITBOARD; |
||
1504 | } |
||
1505 | |||
1506 | for (i = 0; i < 12; i++) |
||
1507 | { |
||
1508 | squareOfIndex[i] = NO_SQUARE; |
||
1509 | } |
||
1510 | |||
1511 | i = 0; |
||
1512 | |||
1513 | ITERATE_BITBOARD(&allMoves, sq1) |
||
1514 | { |
||
1515 | assert(i < 12); |
||
1516 | |||
1517 | squareOfIndex[i++] = sq1; |
||
1518 | } |
||
1519 | |||
1520 | for (pieceSetup = 0; pieceSetup < 4096; pieceSetup++) |
||
1521 | { |
||
1522 | Bitboard currentSetup = EMPTY_BITBOARD, effectiveMoves; |
||
1523 | int j = 1; |
||
1524 | Bitboard magicIndex; |
||
1525 | |||
1526 | for (i = 0; i < 12 && squareOfIndex[i] != NO_SQUARE; i++) |
||
1527 | { |
||
1528 | if ((pieceSetup & j) != 0) |
||
1529 | { |
||
1530 | setSquare(currentSetup, squareOfIndex[i]); |
||
1531 | } |
||
1532 | |||
1533 | j *= 2; |
||
1534 | } |
||
1535 | |||
1536 | calculateObstacles(currentSetup, obstacles); |
||
1537 | effectiveMoves = getBishopMoves(square, obstacles); |
||
1538 | magicIndex = ((currentSetup & premask) * magicNumber) >> 55; |
||
1539 | magicBishopMoves[square][magicIndex] = effectiveMoves; |
||
1540 | } |
||
1541 | } |
||
1542 | |||
1543 | /* #define GENERATE_MAGIC_NUMBERS */ |
||
1544 | #ifdef GENERATE_MAGIC_NUMBERS |
||
1545 | |||
1546 | #define IMAX 4096 |
||
1547 | #define BMAX 12 |
||
1548 | Bitboard collisions[IMAX]; |
||
1549 | |||
1550 | static bool testMagicNumber(const Bitboard magicNumber, const Square square, |
||
1551 | const bool rookMoves) |
||
1552 | { |
||
1553 | Square squareOfIndex[BMAX]; |
||
1554 | const Bitboard premask = |
||
1555 | (rookMoves ? preMaskRook[square] : preMaskBishop[square]); |
||
1556 | Bitboard allMoves = premask; |
||
1557 | int i, pieceSetup; |
||
1558 | Square sq1; |
||
1559 | BYTE obstacles[NUM_LANES]; |
||
1560 | |||
1561 | for (i = 0; i < IMAX; i++) |
||
1562 | { |
||
1563 | collisions[i] = EMPTY_BITBOARD; |
||
1564 | } |
||
1565 | |||
1566 | for (i = 0; i < BMAX; i++) |
||
1567 | { |
||
1568 | squareOfIndex[i] = NO_SQUARE; |
||
1569 | } |
||
1570 | |||
1571 | i = 0; |
||
1572 | |||
1573 | ITERATE_BITBOARD(&allMoves, sq1) |
||
1574 | { |
||
1575 | assert(i < BMAX); |
||
1576 | |||
1577 | squareOfIndex[i++] = sq1; |
||
1578 | } |
||
1579 | |||
1580 | for (pieceSetup = 0; pieceSetup < IMAX; pieceSetup++) |
||
1581 | { |
||
1582 | Bitboard currentSetup = EMPTY_BITBOARD, effectiveMoves, calcBase; |
||
1583 | int j = 1; |
||
1584 | Bitboard magicIndex; |
||
1585 | const int shift = (rookMoves ? 64 - 12 : 64 - 9); |
||
1586 | |||
1587 | for (i = 0; i < BMAX && squareOfIndex[i] != NO_SQUARE; i++) |
||
1588 | { |
||
1589 | if ((pieceSetup & j) != 0) |
||
1590 | { |
||
1591 | setSquare(currentSetup, squareOfIndex[i]); |
||
1592 | } |
||
1593 | |||
1594 | j *= 2; |
||
1595 | } |
||
1596 | |||
1597 | calculateObstacles(currentSetup, obstacles); |
||
1598 | effectiveMoves = |
||
1599 | (rookMoves ? getRookMoves(square, obstacles) : |
||
1600 | getBishopMoves(square, obstacles)); |
||
1601 | calcBase = currentSetup & premask; |
||
1602 | magicIndex = (calcBase * magicNumber) >> shift; |
||
1603 | |||
1604 | if (collisions[magicIndex] == EMPTY_BITBOARD) |
||
1605 | { |
||
1606 | collisions[magicIndex] = effectiveMoves; |
||
1607 | } |
||
1608 | else |
||
1609 | { |
||
1610 | if (effectiveMoves != collisions[magicIndex]) |
||
1611 | { |
||
1612 | return FALSE; /* severe collision -> magic number not suitable */ |
||
1613 | } |
||
1614 | } |
||
1615 | } |
||
1616 | |||
1617 | return TRUE; /* the given magic number is valid */ |
||
1618 | } |
||
1619 | |||
1620 | static UINT64 get64bitRandom() |
||
1621 | { |
||
1622 | const UINT64 limit = (RAND_MAX * 13) / 100; |
||
1623 | UINT64 rn = 0, runningOne = 1; |
||
1624 | int i; |
||
1625 | |||
1626 | for (i = 0; i < 64; i++) |
||
1627 | { |
||
1628 | if (rand() <= limit) |
||
1629 | { |
||
1630 | rn |= runningOne; |
||
1631 | } |
||
1632 | |||
1633 | runningOne *= 2; |
||
1634 | } |
||
1635 | |||
1636 | return rn; |
||
1637 | } |
||
1638 | |||
1639 | static void calculateMagicNumbers() |
||
1640 | { |
||
1641 | Square square; |
||
1642 | |||
1643 | printf("{"); |
||
1644 | |||
1645 | ITERATE(square) |
||
1646 | { |
||
1647 | Bitboard magicNumber = get64bitRandom(); |
||
1648 | |||
1649 | while (testMagicNumber(magicNumber, square, TRUE) == FALSE) |
||
1650 | { |
||
1651 | magicNumber = get64bitRandom(); |
||
1652 | } |
||
1653 | |||
1654 | printf("%llu, ", magicNumber); |
||
1655 | |||
1656 | if ((square % 2) == 1) |
||
1657 | { |
||
1658 | printf("\n"); |
||
1659 | } |
||
1660 | } |
||
1661 | |||
1662 | printf("};\n{"); |
||
1663 | |||
1664 | ITERATE(square) |
||
1665 | { |
||
1666 | Bitboard magicNumber = get64bitRandom(); |
||
1667 | |||
1668 | while (testMagicNumber(magicNumber, square, FALSE) == FALSE) |
||
1669 | { |
||
1670 | magicNumber = get64bitRandom(); |
||
1671 | } |
||
1672 | |||
1673 | printf("%llu, ", magicNumber); |
||
1674 | |||
1675 | if ((square % 2) == 1) |
||
1676 | { |
||
1677 | printf("\n"); |
||
1678 | } |
||
1679 | } |
||
1680 | |||
1681 | printf("};\n"); |
||
1682 | getKeyStroke(); |
||
1683 | } |
||
1684 | |||
1685 | #endif /* GENREATE_MAGIC_NUMBERS */ |
||
1686 | |||
1687 | Bitboard getFlippedBitboard(Bitboard original) |
||
1688 | { |
||
1689 | Bitboard flipped = EMPTY_BITBOARD; |
||
1690 | Square square; |
||
1691 | |||
1692 | ITERATE_BITBOARD(&original, square) |
||
1693 | { |
||
1694 | setSquare(flipped, getFlippedSquare(square)); |
||
1695 | } |
||
1696 | |||
1697 | return flipped; |
||
1698 | } |
||
1699 | |||
1700 | int initializeModuleBitboard() |
||
1701 | { |
||
1702 | INT32 i; |
||
1703 | UINT32 j; |
||
1704 | INT8 k, indexLow, indexHigh; |
||
1705 | UINT64 min = 1; |
||
1706 | Square square; |
||
1707 | |||
1708 | if (isInitialized) |
||
1709 | { |
||
1710 | return 0; |
||
1711 | } |
||
1712 | else |
||
1713 | { |
||
1714 | isInitialized = TRUE; |
||
1715 | } |
||
1716 | |||
1717 | ITERATE(i) |
||
1718 | { |
||
1719 | minValue[i] = min; |
||
1720 | maxValue[i] = ~min; |
||
1721 | |||
1722 | min *= 2; |
||
1723 | } |
||
1724 | |||
1725 | lowestBit[0] = highestBit[0] = NO_SQUARE; |
||
1726 | numSetBits[0] = rankOverlay[0] = 0; |
||
1727 | |||
1728 | for (i = 1; i <= 0xffffL; i++) |
||
1729 | { |
||
1730 | numSetBits[i] = _getNumberOfSetBits(i); |
||
1731 | rankOverlay[i] = _getRankOverlay(i); |
||
1732 | |||
1733 | j = i; |
||
1734 | indexLow = indexHigh = NO_SQUARE; |
||
1735 | |||
1736 | for (k = 0x00; k <= 0x0f; k++) |
||
1737 | { |
||
1738 | if ((j & 1) == 1) |
||
1739 | { |
||
1740 | if (indexLow == NO_SQUARE) |
||
1741 | { |
||
1742 | indexLow = k; |
||
1743 | } |
||
1744 | |||
1745 | indexHigh = k; |
||
1746 | } |
||
1747 | |||
1748 | j >>= 1; |
||
1749 | } |
||
1750 | |||
1751 | lowestBit[i] = indexLow; |
||
1752 | highestBit[i] = indexHigh; |
||
1753 | } |
||
1754 | |||
1755 | ITERATE(square) |
||
1756 | { |
||
1757 | int distance; |
||
1758 | |||
1759 | if (squareColor(square) == DARK) |
||
1760 | { |
||
1761 | setSquare(darkSquares, square); |
||
1762 | clearSquare(lightSquares, square); |
||
1763 | } |
||
1764 | else |
||
1765 | { |
||
1766 | clearSquare(darkSquares, square); |
||
1767 | setSquare(lightSquares, square); |
||
1768 | } |
||
1769 | |||
1770 | for (distance = 0; distance <= 7; distance++) |
||
1771 | { |
||
1772 | Square square2; |
||
1773 | |||
1774 | squaresInDistance[distance][square] = EMPTY_BITBOARD; |
||
1775 | |||
1776 | ITERATE(square2) |
||
1777 | { |
||
1778 | if (distance(square, square2) <= distance) |
||
1779 | { |
||
1780 | setSquare(squaresInDistance[distance][square], square2); |
||
1781 | } |
||
1782 | } |
||
1783 | } |
||
1784 | |||
1785 | for (distance = 0; distance <= 14; distance++) |
||
1786 | { |
||
1787 | Square square2; |
||
1788 | |||
1789 | squaresInTaxiDistance[distance][square] = EMPTY_BITBOARD; |
||
1790 | |||
1791 | ITERATE(square2) |
||
1792 | { |
||
1793 | if (taxiDistance(square, square2) <= distance) |
||
1794 | { |
||
1795 | setSquare(squaresInTaxiDistance[distance][square], square2); |
||
1796 | } |
||
1797 | } |
||
1798 | } |
||
1799 | } |
||
1800 | |||
1801 | for (i = FILE_A; i <= FILE_H; i++) |
||
1802 | { |
||
1803 | int j; |
||
1804 | |||
1805 | for (j = FILE_A; j <= FILE_H; j++) |
||
1806 | { |
||
1807 | int k; |
||
1808 | |||
1809 | squaresOfFileRange[i][j] = squaresOfRankRange[i][j] = EMPTY_BITBOARD; |
||
1810 | |||
1811 | for (k = FILE_A; k <= FILE_H; k++) |
||
1812 | { |
||
1813 | if ((k >= i && k <= j) || (k >= j && k <= i)) |
||
1814 | { |
||
1815 | squaresOfFileRange[i][j] |= squaresOfFile[k]; |
||
1816 | squaresOfRankRange[i][j] |= squaresOfRank[k]; |
||
1817 | } |
||
1818 | } |
||
1819 | } |
||
1820 | } |
||
1821 | |||
1822 | nonA = ~squaresOfFile[FILE_A], nonH = ~squaresOfFile[FILE_H]; |
||
1823 | center = minValue[D4] | minValue[D5] | minValue[E4] | minValue[E5]; |
||
1824 | extendedCenter = |
||
1825 | (squaresOfFile[FILE_C] | squaresOfFile[FILE_D] | |
||
1826 | squaresOfFile[FILE_E] | squaresOfFile[FILE_F]) & |
||
1827 | (squaresOfRank[RANK_3] | squaresOfRank[RANK_4] | |
||
1828 | squaresOfRank[RANK_5] | squaresOfRank[RANK_6]); |
||
1829 | border = squaresOfFile[FILE_A] | squaresOfFile[FILE_H] | |
||
1830 | squaresOfRank[RANK_1] | squaresOfRank[RANK_8]; |
||
1831 | queenSide = |
||
1832 | squaresOfFile[FILE_A] | squaresOfFile[FILE_B] | squaresOfFile[FILE_C]; |
||
1833 | kingSide = |
||
1834 | squaresOfFile[FILE_F] | squaresOfFile[FILE_G] | squaresOfFile[FILE_H]; |
||
1835 | centerFiles = squaresOfFile[FILE_D] | squaresOfFile[FILE_E]; |
||
1836 | promotionCandidates[WHITE] = squaresOfRank[RANK_7]; |
||
1837 | promotionCandidates[BLACK] = squaresOfRank[RANK_2]; |
||
1838 | |||
1839 | initializeKingMoves(); |
||
1840 | initializeRookMoves(); |
||
1841 | initializeBishopMoves(); |
||
1842 | initializeQueenMoves(); |
||
1843 | initializeKnightMoves(); |
||
1844 | initializePawnMoves(); |
||
1845 | initializeSquaresBehind(); |
||
1846 | initializeSquaresBetween(); |
||
1847 | initializeSquareLaneInfo(); |
||
1848 | initializeLaneMasks(); |
||
1849 | initializeCastlings(); |
||
1850 | |||
1851 | ITERATE(square) |
||
1852 | { |
||
1853 | const Bitboard corona = generalMoves[KING][square]; |
||
1854 | Square square2; |
||
1855 | |||
1856 | orthoKingAttackers[square] = diaKingAttackers[square] = |
||
1857 | knightKingAttackers[square] = pawnKingAttackers[WHITE][square] = |
||
1858 | pawnKingAttackers[BLACK][square] = EMPTY_BITBOARD; |
||
1859 | squaresAbove[WHITE][square] = squaresAbove[BLACK][square] = |
||
1860 | squaresBelow[WHITE][square] = squaresBelow[BLACK][square] = |
||
1861 | squaresLeftOf[square] = squaresRightOf[square] = EMPTY_BITBOARD; |
||
1862 | |||
1863 | ITERATE(square2) |
||
1864 | { |
||
1865 | const Bitboard orthoSquares = generalMoves[ROOK][square2]; |
||
1866 | const Bitboard diaSquares = generalMoves[BISHOP][square2]; |
||
1867 | const Bitboard knightSquares = generalMoves[KNIGHT][square2]; |
||
1868 | const Bitboard whitePawnSquares = generalMoves[WHITE_PAWN][square2]; |
||
1869 | const Bitboard blackPawnSquares = generalMoves[BLACK_PAWN][square2]; |
||
1870 | |||
1871 | if (square != square2 && (corona & orthoSquares) != EMPTY_BITBOARD && |
||
1872 | taxiDistance(square, square2) > 1) |
||
1873 | { |
||
1874 | setSquare(orthoKingAttackers[square], square2); |
||
1875 | } |
||
1876 | |||
1877 | if (square != square2 && (corona & diaSquares) != EMPTY_BITBOARD && |
||
1878 | (distance(square, square2) > 1 || |
||
1879 | taxiDistance(square, square2) != 2)) |
||
1880 | { |
||
1881 | setSquare(diaKingAttackers[square], square2); |
||
1882 | } |
||
1883 | |||
1884 | if (square != square2 && |
||
1885 | (corona & knightSquares) != EMPTY_BITBOARD && |
||
1886 | testSquare(knightSquares, square) == EMPTY_BITBOARD) |
||
1887 | { |
||
1888 | setSquare(knightKingAttackers[square], square2); |
||
1889 | } |
||
1890 | |||
1891 | if (square != square2 && |
||
1892 | (corona & whitePawnSquares) != EMPTY_BITBOARD && |
||
1893 | testSquare(whitePawnSquares, square) == EMPTY_BITBOARD) |
||
1894 | { |
||
1895 | setSquare(pawnKingAttackers[WHITE][square], square2); |
||
1896 | } |
||
1897 | |||
1898 | if (square != square2 && |
||
1899 | (corona & blackPawnSquares) != EMPTY_BITBOARD && |
||
1900 | testSquare(blackPawnSquares, square) == EMPTY_BITBOARD) |
||
1901 | { |
||
1902 | setSquare(pawnKingAttackers[BLACK][square], square2); |
||
1903 | } |
||
1904 | |||
1905 | if (rank(square2) < rank(square)) |
||
1906 | { |
||
1907 | setSquare(squaresBelow[WHITE][square], square2); |
||
1908 | setSquare(squaresAbove[BLACK][square], square2); |
||
1909 | } |
||
1910 | |||
1911 | if (rank(square2) > rank(square)) |
||
1912 | { |
||
1913 | setSquare(squaresAbove[WHITE][square], square2); |
||
1914 | setSquare(squaresBelow[BLACK][square], square2); |
||
1915 | } |
||
1916 | |||
1917 | if (file(square2) < file(square)) |
||
1918 | { |
||
1919 | setSquare(squaresLeftOf[square], square2); |
||
1920 | } |
||
1921 | |||
1922 | if (file(square2) > file(square)) |
||
1923 | { |
||
1924 | setSquare(squaresRightOf[square], square2); |
||
1925 | } |
||
1926 | } |
||
1927 | } |
||
1928 | |||
1929 | for (i = 0; i < 256; i++) |
||
1930 | { |
||
1931 | for (j = 0; j < 8; j++) |
||
1932 | { |
||
1933 | bitshiftGap[j][i] = (i == 0 ? 0 : 8); |
||
1934 | |||
1935 | for (k = 0; k < 8; k++) |
||
1936 | { |
||
1937 | if ((minValue[(int) k] & i) != 0 |
||
1938 | && abs(j - k) < bitshiftGap[j][i]) |
||
1939 | { |
||
1940 | bitshiftGap[j][i] = (UINT8) abs(j - k); |
||
1941 | } |
||
1942 | } |
||
1943 | } |
||
1944 | } |
||
1945 | |||
1946 | for (i = 0; i < 4; i++) |
||
1947 | { |
||
1948 | UINT64 bitMask; |
||
1949 | |||
1950 | for (bitMask = 0; bitMask < 0x10000; bitMask++) |
||
1951 | { |
||
1952 | SetSquaresInfo *info = &setSquares[i][bitMask]; |
||
1953 | Bitboard board = bitMask << (16 * i); |
||
1954 | Square square; |
||
1955 | |||
1956 | info->numSetSquares = 0; |
||
1957 | |||
1958 | ITERATE_BITBOARD(&board, square) |
||
1959 | { |
||
1960 | info->setSquares[info->numSetSquares++] = (UINT8) square; |
||
1961 | } |
||
1962 | } |
||
1963 | } |
||
1964 | |||
1965 | initializePremasks(); |
||
1966 | |||
1967 | ITERATE(square) |
||
1968 | { |
||
1969 | initializeMagicRookMoves(square); |
||
1970 | initializeMagicBishopMoves(square); |
||
1971 | } |
||
1972 | |||
1973 | ITERATE(square) |
||
1974 | { |
||
1975 | int i; |
||
1976 | |||
1977 | magicSquareInfoRook[square].preMask = preMaskRook[square]; |
||
1978 | magicSquareInfoRook[square].magicNumber = magicRookNumber[square]; |
||
1979 | |||
1980 | for (i = 0; i < IMAX_ROOK; i++) |
||
1981 | { |
||
1982 | magicSquareInfoRook[square].moves[i] = magicRookMoves[square][i]; |
||
1983 | } |
||
1984 | |||
1985 | magicSquareInfoBishop[square].preMask = preMaskBishop[square]; |
||
1986 | magicSquareInfoBishop[square].magicNumber = magicBishopNumber[square]; |
||
1987 | |||
1988 | for (i = 0; i < IMAX_BISHOP; i++) |
||
1989 | { |
||
1990 | magicSquareInfoBishop[square].moves[i] = magicBishopMoves[square][i]; |
||
1991 | } |
||
1992 | } |
||
1993 | |||
1994 | /* |
||
1995 | for (i = 0; i < 8; i++) |
||
1996 | { |
||
1997 | logDebug("0x%016llx,\n", squaresOfLateralFiles[i]); |
||
1998 | } |
||
1999 | |||
2000 | getKeyStroke(); |
||
2001 | */ |
||
2002 | |||
2003 | #ifdef GENERATE_MAGIC_NUMBERS |
||
2004 | calculateMagicNumbers(); |
||
2005 | #endif |
||
2006 | |||
2007 | return 0; |
||
2008 | } |
||
2009 | |||
2010 | #ifndef NDEBUG |
||
2011 | |||
2012 | static int testBitOperations() |
||
2013 | { |
||
2014 | Bitboard b = EMPTY_BITBOARD; |
||
2015 | |||
2016 | assert(testSquare(lightSquares, A1) == 0); |
||
2017 | assert(testSquare(lightSquares, B1)); |
||
2018 | assert(testSquare(lightSquares, G8)); |
||
2019 | assert(testSquare(lightSquares, H8) == 0); |
||
2020 | |||
2021 | assert(testSquare(darkSquares, A1)); |
||
2022 | assert(testSquare(darkSquares, B1) == 0); |
||
2023 | assert(testSquare(darkSquares, G8) == 0); |
||
2024 | assert(testSquare(darkSquares, H8)); |
||
2025 | |||
2026 | assert(highestBit[0x0f] == 3); |
||
2027 | assert(highestBit[0xffff] == 15); |
||
2028 | assert(numSetBits[0] == 0); |
||
2029 | assert(numSetBits[0x5555] == 8); |
||
2030 | assert(numSetBits[0xaaaa] == 8); |
||
2031 | assert(numSetBits[0xffff] == 16); |
||
2032 | |||
2033 | assert(testSquare(b, D4) == 0); |
||
2034 | setSquare(b, D4); |
||
2035 | assert(testSquare(b, D4) != 0); |
||
2036 | clearSquare(b, D4); |
||
2037 | assert(testSquare(b, D4) == 0); |
||
2038 | |||
2039 | assert(testSquare(b, H8) == 0); |
||
2040 | setSquare(b, H8); |
||
2041 | assert(testSquare(b, H8) != 0); |
||
2042 | clearSquare(b, H8); |
||
2043 | assert(testSquare(b, H8) == 0); |
||
2044 | |||
2045 | assert(getLastSquare(&b) == NO_SQUARE); |
||
2046 | setSquare(b, H8); |
||
2047 | assert(getLastSquare(&b) == H8); |
||
2048 | assert(getLastSquare(&b) == NO_SQUARE); |
||
2049 | |||
2050 | assert(testSquare(squaresBehind[D4][C3], E5)); |
||
2051 | assert(testSquare(squaresBehind[D4][C3], F6)); |
||
2052 | assert(testSquare(squaresBehind[D4][C3], G7)); |
||
2053 | assert(testSquare(squaresBehind[D4][C3], H8)); |
||
2054 | assert(getNumberOfSetSquares(squaresBehind[D4][C3]) == 4); |
||
2055 | |||
2056 | assert(testSquare(squaresBetween[B3][F7], C4)); |
||
2057 | assert(testSquare(squaresBetween[B3][F7], D5)); |
||
2058 | assert(testSquare(squaresBetween[B3][F7], E6)); |
||
2059 | assert(getNumberOfSetSquares(squaresBetween[B3][F7]) == 3); |
||
2060 | |||
2061 | assert(rankOverlay[0x8143] == 0xC3); |
||
2062 | |||
2063 | b = EMPTY_BITBOARD; |
||
2064 | setSquare(b, A4); |
||
2065 | setSquare(b, E1); |
||
2066 | setSquare(b, E8); |
||
2067 | setSquare(b, H7); |
||
2068 | assert(getRankOverlay(b) == 0x91); |
||
2069 | |||
2070 | assert(testSquare(squaresInDistance[1][C3], C4) != FALSE); |
||
2071 | assert(testSquare(squaresInDistance[1][C3], C5) == FALSE); |
||
2072 | assert(testSquare(squaresInDistance[3][E5], E2) != FALSE); |
||
2073 | assert(testSquare(squaresInDistance[3][E5], E1) == FALSE); |
||
2074 | assert(testSquare(squaresInDistance[5][H8], C3) != FALSE); |
||
2075 | assert(testSquare(squaresInDistance[5][H8], B2) == FALSE); |
||
2076 | |||
2077 | assert(bitshiftGap[5][0] == 0); |
||
2078 | assert(bitshiftGap[1][129] == 1); |
||
2079 | assert(bitshiftGap[4][129] == 3); |
||
2080 | |||
2081 | return 0; |
||
2082 | } |
||
2083 | |||
2084 | static int testGeneralMoves() |
||
2085 | { |
||
2086 | assert(testSquare(generalMoves[KING][C3], C4)); |
||
2087 | assert(testSquare(generalMoves[KING][C3], D4)); |
||
2088 | assert(testSquare(generalMoves[KING][C3], D3)); |
||
2089 | assert(testSquare(generalMoves[KING][C3], D2)); |
||
2090 | assert(testSquare(generalMoves[KING][C3], C2)); |
||
2091 | assert(testSquare(generalMoves[KING][C3], B2)); |
||
2092 | assert(testSquare(generalMoves[KING][C3], B3)); |
||
2093 | assert(testSquare(generalMoves[KING][C3], B4)); |
||
2094 | assert(getNumberOfSetSquares(generalMoves[KING][C3]) == 8); |
||
2095 | |||
2096 | assert(testSquare(generalMoves[ROOK][C3], C8)); |
||
2097 | assert(testSquare(generalMoves[ROOK][C3], H3)); |
||
2098 | assert(testSquare(generalMoves[ROOK][C3], C1)); |
||
2099 | assert(testSquare(generalMoves[ROOK][C3], A3)); |
||
2100 | assert(getNumberOfSetSquares(generalMoves[ROOK][C3]) == 14); |
||
2101 | |||
2102 | assert(testSquare(generalMoves[BISHOP][C3], H8)); |
||
2103 | assert(testSquare(generalMoves[BISHOP][C3], E1)); |
||
2104 | assert(testSquare(generalMoves[BISHOP][C3], A1)); |
||
2105 | assert(testSquare(generalMoves[BISHOP][C3], A5)); |
||
2106 | assert(getNumberOfSetSquares(generalMoves[BISHOP][C3]) == 11); |
||
2107 | |||
2108 | assert(testSquare(generalMoves[QUEEN][C3], C8)); |
||
2109 | assert(testSquare(generalMoves[QUEEN][C3], H8)); |
||
2110 | assert(testSquare(generalMoves[QUEEN][C3], H3)); |
||
2111 | assert(testSquare(generalMoves[QUEEN][C3], E1)); |
||
2112 | assert(testSquare(generalMoves[QUEEN][C3], C1)); |
||
2113 | assert(testSquare(generalMoves[QUEEN][C3], A1)); |
||
2114 | assert(testSquare(generalMoves[QUEEN][C3], A3)); |
||
2115 | assert(testSquare(generalMoves[QUEEN][C3], A5)); |
||
2116 | assert(getNumberOfSetSquares(generalMoves[QUEEN][C3]) == 25); |
||
2117 | |||
2118 | assert(testSquare(generalMoves[KNIGHT][C3], A2)); |
||
2119 | assert(testSquare(generalMoves[KNIGHT][C3], A4)); |
||
2120 | assert(testSquare(generalMoves[KNIGHT][C3], B5)); |
||
2121 | assert(testSquare(generalMoves[KNIGHT][C3], D5)); |
||
2122 | assert(testSquare(generalMoves[KNIGHT][C3], E4)); |
||
2123 | assert(testSquare(generalMoves[KNIGHT][C3], E2)); |
||
2124 | assert(testSquare(generalMoves[KNIGHT][C3], D1)); |
||
2125 | assert(testSquare(generalMoves[KNIGHT][C3], B1)); |
||
2126 | assert(getNumberOfSetSquares(generalMoves[KNIGHT][C3]) == 8); |
||
2127 | assert(getNumberOfSetSquares(generalMoves[KNIGHT][A1]) == 2); |
||
2128 | assert(getNumberOfSetSquares(generalMoves[KNIGHT][H8]) == 2); |
||
2129 | |||
2130 | assert(testSquare(generalMoves[WHITE_PAWN][A2], B3)); |
||
2131 | assert(getNumberOfSetSquares(generalMoves[WHITE_PAWN][A2]) == 1); |
||
2132 | assert(testSquare(generalMoves[WHITE_PAWN][B2], A3)); |
||
2133 | assert(testSquare(generalMoves[WHITE_PAWN][B2], C3)); |
||
2134 | assert(getNumberOfSetSquares(generalMoves[WHITE_PAWN][B2]) == 2); |
||
2135 | assert(testSquare(generalMoves[WHITE_PAWN][H2], G3)); |
||
2136 | assert(getNumberOfSetSquares(generalMoves[WHITE_PAWN][H2]) == 1); |
||
2137 | |||
2138 | assert(testSquare(generalMoves[BLACK_PAWN][A7], B6)); |
||
2139 | assert(getNumberOfSetSquares(generalMoves[BLACK_PAWN][A7]) == 1); |
||
2140 | assert(testSquare(generalMoves[BLACK_PAWN][B7], A6)); |
||
2141 | assert(testSquare(generalMoves[BLACK_PAWN][B7], C6)); |
||
2142 | assert(getNumberOfSetSquares(generalMoves[BLACK_PAWN][B7]) == 2); |
||
2143 | assert(testSquare(generalMoves[BLACK_PAWN][H7], G6)); |
||
2144 | assert(getNumberOfSetSquares(generalMoves[BLACK_PAWN][H7]) == 1); |
||
2145 | |||
2146 | return 0; |
||
2147 | } |
||
2148 | |||
2149 | static int testPieces() |
||
2150 | { |
||
2151 | Bitboard b = EMPTY_BITBOARD, moves; |
||
2152 | BYTE obstacles[NUM_LANES]; |
||
2153 | |||
2154 | setSquare(b, C3); |
||
2155 | setSquare(b, C6); |
||
2156 | setSquare(b, F6); |
||
2157 | |||
2158 | calculateObstacles(b, obstacles); |
||
2159 | |||
2160 | moves = getMagicRookMoves(C4, b); |
||
2161 | assert(testSquare(moves, C3)); |
||
2162 | assert(testSquare(moves, C5)); |
||
2163 | assert(testSquare(moves, C6)); |
||
2164 | assert(testSquare(moves, A4)); |
||
2165 | assert(testSquare(moves, B4)); |
||
2166 | assert(testSquare(moves, D4)); |
||
2167 | assert(testSquare(moves, E4)); |
||
2168 | assert(testSquare(moves, F4)); |
||
2169 | assert(testSquare(moves, G4)); |
||
2170 | assert(testSquare(moves, H4)); |
||
2171 | assert(getNumberOfSetSquares(moves) == 10); |
||
2172 | |||
2173 | moves = getMagicBishopMoves(E5, b); |
||
2174 | assert(testSquare(moves, D4)); |
||
2175 | assert(testSquare(moves, C3)); |
||
2176 | assert(testSquare(moves, D6)); |
||
2177 | assert(testSquare(moves, C7)); |
||
2178 | assert(testSquare(moves, B8)); |
||
2179 | assert(testSquare(moves, F6)); |
||
2180 | assert(testSquare(moves, F4)); |
||
2181 | assert(testSquare(moves, G3)); |
||
2182 | assert(testSquare(moves, H2)); |
||
2183 | assert(getNumberOfSetSquares(moves) == 9); |
||
2184 | |||
2185 | moves = getMagicQueenMoves(F3, b); |
||
2186 | assert(testSquare(moves, F2)); |
||
2187 | assert(testSquare(moves, F1)); |
||
2188 | assert(testSquare(moves, F4)); |
||
2189 | assert(testSquare(moves, F5)); |
||
2190 | assert(testSquare(moves, F6)); |
||
2191 | assert(testSquare(moves, E3)); |
||
2192 | assert(testSquare(moves, D3)); |
||
2193 | assert(testSquare(moves, C3)); |
||
2194 | assert(testSquare(moves, G3)); |
||
2195 | assert(testSquare(moves, H3)); |
||
2196 | assert(testSquare(moves, E4)); |
||
2197 | assert(testSquare(moves, D5)); |
||
2198 | assert(testSquare(moves, C6)); |
||
2199 | assert(testSquare(moves, G4)); |
||
2200 | assert(testSquare(moves, H5)); |
||
2201 | assert(testSquare(moves, G2)); |
||
2202 | assert(testSquare(moves, H1)); |
||
2203 | assert(testSquare(moves, E2)); |
||
2204 | assert(testSquare(moves, D1)); |
||
2205 | assert(getNumberOfSetSquares(moves) == 19); |
||
2206 | |||
2207 | moves = getKnightMoves(A8); |
||
2208 | assert(testSquare(moves, B6)); |
||
2209 | assert(testSquare(moves, C7)); |
||
2210 | assert(getNumberOfSetSquares(moves) == 2); |
||
2211 | |||
2212 | moves = getKnightMoves(E5); |
||
2213 | assert(testSquare(moves, F7)); |
||
2214 | assert(testSquare(moves, G6)); |
||
2215 | assert(testSquare(moves, G4)); |
||
2216 | assert(testSquare(moves, F3)); |
||
2217 | assert(testSquare(moves, D3)); |
||
2218 | assert(testSquare(moves, C4)); |
||
2219 | assert(testSquare(moves, C6)); |
||
2220 | assert(testSquare(moves, D7)); |
||
2221 | assert(getNumberOfSetSquares(moves) == 8); |
||
2222 | |||
2223 | return 0; |
||
2224 | } |
||
2225 | |||
2226 | static int testPawns() |
||
2227 | { |
||
2228 | Bitboard b = EMPTY_BITBOARD, moves, pawns; |
||
2229 | BYTE obstacles[NUM_LANES]; |
||
2230 | |||
2231 | setSquare(b, B3); |
||
2232 | setSquare(b, C4); |
||
2233 | setSquare(b, E4); |
||
2234 | setSquare(b, F6); |
||
2235 | setSquare(b, E5); |
||
2236 | setSquare(b, D6); |
||
2237 | setSquare(b, G2); |
||
2238 | setSquare(b, G3); |
||
2239 | setSquare(b, H2); |
||
2240 | setSquare(b, H7); |
||
2241 | |||
2242 | calculateObstacles(b, obstacles); |
||
2243 | |||
2244 | moves = getPawnAdvances(WHITE, A2, b); |
||
2245 | assert(testSquare(moves, A3)); |
||
2246 | assert(testSquare(moves, A4)); |
||
2247 | assert(getNumberOfSetSquares(moves) == 2); |
||
2248 | |||
2249 | moves = getPawnAdvances(WHITE, B2, b); |
||
2250 | assert(getNumberOfSetSquares(moves) == 0); |
||
2251 | |||
2252 | moves = getPawnAdvances(WHITE, C2, b); |
||
2253 | assert(testSquare(moves, C3)); |
||
2254 | assert(getNumberOfSetSquares(moves) == 1); |
||
2255 | |||
2256 | moves = getPawnAdvances(BLACK, H7, b); |
||
2257 | assert(testSquare(moves, H6)); |
||
2258 | assert(testSquare(moves, H5)); |
||
2259 | assert(getNumberOfSetSquares(moves) == 2); |
||
2260 | |||
2261 | moves = getPawnAdvances(BLACK, F7, b); |
||
2262 | assert(getNumberOfSetSquares(moves) == 0); |
||
2263 | |||
2264 | moves = getPawnAdvances(BLACK, E7, b); |
||
2265 | assert(testSquare(moves, E6)); |
||
2266 | assert(getNumberOfSetSquares(moves) == 1); |
||
2267 | |||
2268 | moves = getPawnCaptures(WHITE_PAWN, A2, b); |
||
2269 | assert(testSquare(moves, B3)); |
||
2270 | assert(getNumberOfSetSquares(moves) == 1); |
||
2271 | |||
2272 | moves = getPawnCaptures(WHITE_PAWN, D3, b); |
||
2273 | assert(testSquare(moves, C4)); |
||
2274 | assert(testSquare(moves, E4)); |
||
2275 | assert(getNumberOfSetSquares(moves) == 2); |
||
2276 | |||
2277 | moves = getPawnCaptures(BLACK_PAWN, G7, b); |
||
2278 | assert(testSquare(moves, F6)); |
||
2279 | assert(getNumberOfSetSquares(moves) == 1); |
||
2280 | |||
2281 | moves = getPawnCaptures(BLACK_PAWN, E7, b); |
||
2282 | assert(testSquare(moves, D6)); |
||
2283 | assert(testSquare(moves, F6)); |
||
2284 | assert(getNumberOfSetSquares(moves) == 2); |
||
2285 | |||
2286 | pawns = getInterestedPawns(BLACK, D5, b); |
||
2287 | assert(testSquare(pawns, D6)); |
||
2288 | assert(getNumberOfSetSquares(pawns) == 1); |
||
2289 | |||
2290 | pawns = getInterestedPawns(BLACK, H5, b); |
||
2291 | assert(testSquare(pawns, H7)); |
||
2292 | assert(testSquare(pawns, H6)); |
||
2293 | assert(getNumberOfSetSquares(pawns) == 2); |
||
2294 | |||
2295 | pawns = getInterestedPawns(WHITE, H4, b); |
||
2296 | assert(testSquare(pawns, H2)); |
||
2297 | assert(testSquare(pawns, H3)); |
||
2298 | assert(getNumberOfSetSquares(pawns) == 2); |
||
2299 | |||
2300 | pawns = getInterestedPawns(WHITE, G4, b); |
||
2301 | assert(testSquare(pawns, G3)); |
||
2302 | assert(getNumberOfSetSquares(pawns) == 1); |
||
2303 | |||
2304 | return 0; |
||
2305 | } |
||
2306 | |||
2307 | static int testKings() |
||
2308 | { |
||
2309 | Bitboard obstacles = EMPTY_BITBOARD, moves; |
||
2310 | BYTE castlingRights = WHITE_00 | WHITE_000 | BLACK_000 | BLACK_00; |
||
2311 | |||
2312 | moves = getKingMoves(A1); |
||
2313 | assert(testSquare(moves, B1)); |
||
2314 | assert(testSquare(moves, B2)); |
||
2315 | assert(testSquare(moves, A2)); |
||
2316 | assert(getNumberOfSetSquares(moves) == 3); |
||
2317 | |||
2318 | moves = getKingMoves(D5); |
||
2319 | assert(testSquare(moves, D6)); |
||
2320 | assert(testSquare(moves, E6)); |
||
2321 | assert(testSquare(moves, E5)); |
||
2322 | assert(testSquare(moves, E4)); |
||
2323 | assert(testSquare(moves, D4)); |
||
2324 | assert(testSquare(moves, C4)); |
||
2325 | assert(testSquare(moves, C5)); |
||
2326 | assert(testSquare(moves, C6)); |
||
2327 | assert(getNumberOfSetSquares(moves) == 8); |
||
2328 | |||
2329 | moves = getKingMoves(D5); |
||
2330 | assert(testSquare(moves, D6)); |
||
2331 | assert(testSquare(moves, E6)); |
||
2332 | assert(testSquare(moves, E5)); |
||
2333 | assert(testSquare(moves, E4)); |
||
2334 | assert(testSquare(moves, D4)); |
||
2335 | assert(testSquare(moves, C4)); |
||
2336 | assert(testSquare(moves, C5)); |
||
2337 | assert(testSquare(moves, C6)); |
||
2338 | assert(getNumberOfSetSquares(moves) == 8); |
||
2339 | |||
2340 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2341 | assert(testSquare(moves, G1)); |
||
2342 | assert(testSquare(moves, C1)); |
||
2343 | assert(getNumberOfSetSquares(moves) == 2); |
||
2344 | |||
2345 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2346 | assert(testSquare(moves, G8)); |
||
2347 | assert(testSquare(moves, C8)); |
||
2348 | assert(getNumberOfSetSquares(moves) == 2); |
||
2349 | |||
2350 | castlingRights = WHITE_00 | BLACK_00; |
||
2351 | |||
2352 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2353 | assert(testSquare(moves, G1)); |
||
2354 | assert(getNumberOfSetSquares(moves) == 1); |
||
2355 | |||
2356 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2357 | assert(testSquare(moves, G8)); |
||
2358 | assert(getNumberOfSetSquares(moves) == 1); |
||
2359 | |||
2360 | castlingRights = WHITE_000 | BLACK_000; |
||
2361 | |||
2362 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2363 | assert(testSquare(moves, C1)); |
||
2364 | assert(getNumberOfSetSquares(moves) == 1); |
||
2365 | |||
2366 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2367 | assert(testSquare(moves, C8)); |
||
2368 | assert(getNumberOfSetSquares(moves) == 1); |
||
2369 | |||
2370 | castlingRights = WHITE_00 | WHITE_000 | BLACK_000 | BLACK_00; |
||
2371 | setSquare(obstacles, D1); |
||
2372 | setSquare(obstacles, D8); |
||
2373 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2374 | assert(testSquare(moves, G1)); |
||
2375 | assert(getNumberOfSetSquares(moves) == 1); |
||
2376 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2377 | assert(testSquare(moves, G8)); |
||
2378 | assert(getNumberOfSetSquares(moves) == 1); |
||
2379 | clearSquare(obstacles, D1); |
||
2380 | clearSquare(obstacles, D8); |
||
2381 | |||
2382 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2383 | assert(testSquare(moves, G1)); |
||
2384 | assert(testSquare(moves, C1)); |
||
2385 | assert(getNumberOfSetSquares(moves) == 2); |
||
2386 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2387 | assert(testSquare(moves, G8)); |
||
2388 | assert(testSquare(moves, C8)); |
||
2389 | assert(getNumberOfSetSquares(moves) == 2); |
||
2390 | |||
2391 | setSquare(obstacles, C1); |
||
2392 | setSquare(obstacles, C8); |
||
2393 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2394 | assert(testSquare(moves, G1)); |
||
2395 | assert(getNumberOfSetSquares(moves) == 1); |
||
2396 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2397 | assert(testSquare(moves, G8)); |
||
2398 | assert(getNumberOfSetSquares(moves) == 1); |
||
2399 | clearSquare(obstacles, C1); |
||
2400 | clearSquare(obstacles, C8); |
||
2401 | |||
2402 | setSquare(obstacles, F1); |
||
2403 | setSquare(obstacles, F8); |
||
2404 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2405 | assert(testSquare(moves, C1)); |
||
2406 | assert(getNumberOfSetSquares(moves) == 1); |
||
2407 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2408 | assert(testSquare(moves, C8)); |
||
2409 | assert(getNumberOfSetSquares(moves) == 1); |
||
2410 | clearSquare(obstacles, F1); |
||
2411 | clearSquare(obstacles, F8); |
||
2412 | |||
2413 | setSquare(obstacles, G1); |
||
2414 | setSquare(obstacles, G8); |
||
2415 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2416 | assert(testSquare(moves, C1)); |
||
2417 | assert(getNumberOfSetSquares(moves) == 1); |
||
2418 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2419 | assert(testSquare(moves, C8)); |
||
2420 | assert(getNumberOfSetSquares(moves) == 1); |
||
2421 | clearSquare(obstacles, G1); |
||
2422 | clearSquare(obstacles, G8); |
||
2423 | |||
2424 | setSquare(obstacles, G1); |
||
2425 | setSquare(obstacles, G8); |
||
2426 | setSquare(obstacles, C1); |
||
2427 | setSquare(obstacles, C8); |
||
2428 | moves = getCastlingMoves(WHITE, castlingRights, obstacles); |
||
2429 | assert(getNumberOfSetSquares(moves) == 0); |
||
2430 | moves = getCastlingMoves(BLACK, castlingRights, obstacles); |
||
2431 | assert(getNumberOfSetSquares(moves) == 0); |
||
2432 | clearSquare(obstacles, G1); |
||
2433 | clearSquare(obstacles, G8); |
||
2434 | clearSquare(obstacles, C1); |
||
2435 | clearSquare(obstacles, C8); |
||
2436 | |||
2437 | return 0; |
||
2438 | } |
||
2439 | |||
2440 | static int testFlooding() |
||
2441 | { |
||
2442 | Bitboard kingMoves = getKingMoves(D4); |
||
2443 | Bitboard expected; |
||
2444 | |||
2445 | floodBoard(&kingMoves); |
||
2446 | expected = squaresBetween[A6][G6] | squaresBetween[A5][G5] | |
||
2447 | squaresBetween[A4][G4] | squaresBetween[A3][G3] | |
||
2448 | squaresBetween[A2][G2]; |
||
2449 | assert(kingMoves == expected); |
||
2450 | |||
2451 | kingMoves = getKingMoves(H1); |
||
2452 | floodBoard(&kingMoves); |
||
2453 | expected = squaresBehind[E3][A3] | squaresBehind[E2][A2] | |
||
2454 | squaresBehind[E1][A1]; |
||
2455 | assert(kingMoves == expected); |
||
2456 | |||
2457 | kingMoves = getKingMoves(A8); |
||
2458 | floodBoard(&kingMoves); |
||
2459 | expected = squaresBehind[D8][H8] | squaresBehind[D7][H7] | |
||
2460 | squaresBehind[D6][H6]; |
||
2461 | assert(kingMoves == expected); |
||
2462 | |||
2463 | return 0; |
||
2464 | } |
||
2465 | |||
2466 | static int testGetSetSquares() |
||
2467 | { |
||
2468 | UINT8 moveSquares[_64_]; |
||
2469 | Bitboard kingMoves = getKingMoves(D4); |
||
2470 | int numMoves = getSetSquares(kingMoves, moveSquares), i; |
||
2471 | |||
2472 | assert(numMoves == 8); |
||
2473 | |||
2474 | for (i = 0; i < numMoves; i++) |
||
2475 | { |
||
2476 | const Square square = (Square) moveSquares[i]; |
||
2477 | |||
2478 | assert(testSquare(kingMoves, square) == TRUE); |
||
2479 | } |
||
2480 | |||
2481 | return 0; |
||
2482 | } |
||
2483 | |||
2484 | #endif |
||
2485 | |||
2486 | int testModuleBitboard() |
||
2487 | { |
||
2488 | #ifndef NDEBUG |
||
2489 | int result; |
||
2490 | |||
2491 | if ((result = testBitOperations()) != 0) |
||
2492 | { |
||
2493 | return result; |
||
2494 | } |
||
2495 | |||
2496 | if ((result = testGeneralMoves()) != 0) |
||
2497 | { |
||
2498 | return result; |
||
2499 | } |
||
2500 | |||
2501 | if ((result = testPieces()) != 0) |
||
2502 | { |
||
2503 | return result; |
||
2504 | } |
||
2505 | |||
2506 | if ((result = testPawns()) != 0) |
||
2507 | { |
||
2508 | return result; |
||
2509 | } |
||
2510 | |||
2511 | if ((result = testKings()) != 0) |
||
2512 | { |
||
2513 | return result; |
||
2514 | } |
||
2515 | |||
2516 | if ((result = testFlooding()) != 0) |
||
2517 | { |
||
2518 | return result; |
||
2519 | } |
||
2520 | |||
2521 | if ((result = testGetSetSquares()) != 0) |
||
2522 | { |
||
2523 | return result; |
||
2524 | } |
||
2525 | #endif |
||
2526 | |||
2527 | return 0; |
||
2528 | } |