The Pedigree Project  0.1
BoardState.cc
1 /*
2  *
3  * Copyright (c) 2008-2014, Pedigree Developers
4  *
5  * Please see the CONTRIB file in the root of the source tree for a full
6  * list of contributors.
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include "BoardState.h"
22 #include "moves.h"
23 #include "SearchAlgorithm.h"
24 #include "hashes.h"
25 #include "StateStore.h"
26 
27 long g_nHashes=0;
28 long g_nIsLegal = 0;
29 long g_nInCheck = 0;
30 
32  whiteInCheck(false), whiteCheckStateCalculated(false),
33  blackInCheck(false), blackCheckStateCalculated(false),
34  whiteInMate(false), whiteMateStateCalculated(false),
35  blackInMate(false), blackMateStateCalculated(false),
36  cachedHash(0), hashCalculated(false),
37  cachedHash2(0), hash2Calculated(false)
38 {
39  // Black needs its queen and king swapped around.
40  Bitboard tmp = black.queen;
41  black.queen = black.king;
42  black.king = tmp;
43 }
44 
45 BoardState::~BoardState()
46 {
47 }
48 
49 void BoardState::move(Move m, Side s, Piece promotion)
50 {
51  if (s == White)
52  {
53  Bitboard tmp = white.pawns;
54  white.friendlyMove(m, promotion);
55  tmp.rotate180();
56  Move m2 = m;
57  m2.rotate180();
58  black.enemyMove(m2, tmp);
59  }
60  else
61  {
62  Move m2 = m;
63  m2.rotate180();
64  Bitboard tmp = black.pawns;
65  black.friendlyMove(m2, promotion);
66  tmp.rotate180();
67  white.enemyMove(m, tmp);
68  }
69  whiteCheckStateCalculated = whiteMateStateCalculated = blackCheckStateCalculated = blackMateStateCalculated = false;
70  hashCalculated = hash2Calculated = false;
71 }
72 
73 bool BoardState::isLegal(Move m, Side s)
74 {
75  g_nIsLegal++;
76  if (s == White)
77  {
78  Bitboard b = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
79  b.rotate180();
80  Bitboard ep = black.enPassant;
81  ep.rotate180();
82  return white.isLegal(m, b, ep);
83  }
84  else
85  {
86  m.rotate180();
87  Bitboard b = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
88  b.rotate180();
89  Bitboard ep = white.enPassant;
90  ep.rotate180();
91  return black.isLegal(m, b, ep);
92  }
93 }
94 
95 bool BoardState::inCheck(Side side)
96 {
97  if (side == White)
98  {
99  if (whiteCheckStateCalculated)
100  return whiteInCheck;
101  else
102  {
103  whiteCheckStateCalculated = true;
104  g_nInCheck++;
105  whiteInCheck = underAttack(white.firstKing(), Black);
106  return whiteInCheck;
107  }
108  }
109  else
110  {
111  if (blackCheckStateCalculated)
112  return blackInCheck;
113  else
114  {
115  Square sq = black.firstKing();
116  sq.rotate180();
117  blackCheckStateCalculated = true;
118  g_nInCheck++;
119  blackInCheck = underAttack(sq, White);
120  return blackInCheck;
121  }
122  }
123 }
124 
125 bool BoardState::inCheckmate(Side side)
126 {
127  bool *result;
128  if (side == White && whiteMateStateCalculated)
129  return whiteInMate;
130  else if (side == Black && blackMateStateCalculated)
131  return blackInMate;
132  else if (side == White)
133  {
134  whiteMateStateCalculated = true;
135  result = &whiteInMate;
136  }
137  else
138  {
139  blackMateStateCalculated = true;
140  result = &blackInMate;
141  }
142 
143  // It's false unless we get to the end.
144  *result = false;
145 
146  if (!inCheck(side))
147  {
148  return false;
149  }
150 
151  Bitboard b;
152  Square sq;
153  for (sq = firstPawn(side, &b);
154  !sq.invalid();
155  sq = nextPawn(side, &b))
156  {
157  for (Square sq2 = b.getAndClearFirstSetBit();
158  !sq2.invalid();
159  sq2 = b.getAndClearFirstSetBit())
160  {
161  MoveList tmpList, tmpList2;
162  BoardState newState = *this;
163  newState.move( Move(sq.col, sq.row, sq2.col, sq2.row), side, Queen /* Default promotion piece */ );
164  if (!newState.inCheck(side))
165  return false;
166  }
167  }
168  for (sq = firstKnight(side, &b);
169  !sq.invalid();
170  sq = nextKnight(side, &b))
171  {
172  for (Square sq2 = b.getAndClearFirstSetBit();
173  !sq2.invalid();
174  sq2 = b.getAndClearFirstSetBit())
175  {
176  MoveList tmpList, tmpList2;
177  BoardState newState = *this;
178  newState.move( Move(sq.col, sq.row, sq2.col, sq2.row), side, Queen /* Default promotion piece */ );
179  if (!newState.inCheck(side))
180  return false;
181  }
182  }
183  for (sq = firstRook(side, &b);
184  !sq.invalid();
185  sq = nextRook(side, &b))
186  {
187  for (Square sq2 = b.getAndClearFirstSetBit();
188  !sq2.invalid();
189  sq2 = b.getAndClearFirstSetBit())
190  {
191  MoveList tmpList, tmpList2;
192  BoardState newState = *this;
193  newState.move( Move(sq.col, sq.row, sq2.col, sq2.row), side, Queen /* Default promotion piece */ );
194  if (!newState.inCheck(side))
195  return false;
196  }
197  }
198  for (sq = firstBishop(side, &b);
199  !sq.invalid();
200  sq = nextBishop(side, &b))
201  {
202  for (Square sq2 = b.getAndClearFirstSetBit();
203  !sq2.invalid();
204  sq2 = b.getAndClearFirstSetBit())
205  {
206  MoveList tmpList, tmpList2;
207  BoardState newState = *this;
208  newState.move( Move(sq.col, sq.row, sq2.col, sq2.row), side, Queen /* Default promotion piece */ );
209  if (!newState.inCheck(side))
210  return false;
211  }
212  }
213  for (sq = firstQueen(side, &b);
214  !sq.invalid();
215  sq = nextQueen(side, &b))
216  {
217  for (Square sq2 = b.getAndClearFirstSetBit();
218  !sq2.invalid();
219  sq2 = b.getAndClearFirstSetBit())
220  {
221  MoveList tmpList, tmpList2;
222  BoardState newState = *this;
223  newState.move( Move(sq.col, sq.row, sq2.col, sq2.row), side, Queen /* Default promotion piece */ );
224  if (!newState.inCheck(side))
225  return false;
226  }
227  }
228  sq = firstKing(side, &b);
229  for (Square sq2 = b.getAndClearFirstSetBit();
230  !sq2.invalid();
231  sq2 = b.getAndClearFirstSetBit())
232  {
233  MoveList tmpList, tmpList2;
234  BoardState newState = *this;
235  newState.move( Move(sq.col, sq.row, sq2.col, sq2.row), side, Queen /* Default promotion piece */ );
236  if (!newState.inCheck(side))
237  return false;
238  }
239  *result = true;
240  return true;
241 }
242 
243 bool BoardState::underAttack(Square sq, Side side)
244 {
245  if (side == White)
246  {
247  Bitboard b = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
248  b.rotate180();
249  return white.isAttacking(sq, b);
250  }
251  else
252  {
253  Bitboard b = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
254  b.rotate180();
255  sq.rotate180();
256  return black.isAttacking(sq, b);
257  }
258 }
259 
261 {
262  if (s == White)
263  {
264  Square sq = white.firstPawn();
265  if (b && !sq.invalid())
266  {
267  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
268  allPieces.rotate180(); // Black goes at the bottom.
269  Bitboard enemyPieces = allPieces;
270  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
271  Bitboard enPassant = black.enPassant;
272  enPassant.rotate180();
273  *b = pawnMoves(allPieces, enemyPieces, enPassant,sq);
274  }
275  return sq;
276  }
277  else
278  {
279  Square sq = black.firstPawn();
280  if (b && !sq.invalid())
281  {
282  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
283  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
284  Bitboard enemyPieces = allPieces;
285  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
286  Square sq2 = sq;
287  sq2.rotate180();
288  Bitboard enPassant = white.enPassant;
289  enPassant.rotate180();
290  *b = pawnMoves(allPieces, enemyPieces, enPassant, sq);
291  b->rotate180(); // Move the bitboard back the right way around.
292  return sq2;
293  }
294  return sq;
295  }
296 }
297 
298 Square BoardState::nextPawn(Side s, Bitboard *b)
299 {
300  if (s == White)
301  {
302  Square sq = white.next();
303  if (b && !sq.invalid())
304  {
305  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
306  allPieces.rotate180(); // Black goes at the bottom.
307  Bitboard enemyPieces = allPieces;
308  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
309  Bitboard enPassant = black.enPassant;
310  enPassant.rotate180();
311  *b = pawnMoves(allPieces, enemyPieces, enPassant,sq);
312  }
313  return sq;
314  }
315  else
316  {
317  Square sq = black.next();
318  if (b && !sq.invalid())
319  {
320  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
321  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
322  Bitboard enemyPieces = allPieces;
323  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
324  Square sq2 = sq;
325  sq2.rotate180();
326  Bitboard enPassant = white.enPassant;
327  enPassant.rotate180();
328  *b = pawnMoves(allPieces, enemyPieces, enPassant, sq);
329  b->rotate180(); // Move the bitboard back the right way around.
330  return sq2;
331  }
332  return sq;
333  }
334 }
335 
336 Square BoardState::firstRook(Side s, Bitboard *b)
337 {
338  if (s == White)
339  {
340  Square sq = white.firstRook();
341  if (b && !sq.invalid())
342  {
343  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
344  allPieces.rotate180(); // Black goes at the bottom.
345  Bitboard enemyPieces = allPieces;
346  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
347  *b = rookMoves(allPieces, enemyPieces, sq);
348  }
349  return sq;
350  }
351  else
352  {
353  Square sq = black.firstRook();
354  if (b && !sq.invalid())
355  {
356  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
357  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
358  Bitboard enemyPieces = allPieces;
359  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
360  Square sq2 = sq;
361  sq2.rotate180();
362  *b = rookMoves(allPieces, enemyPieces, sq);
363  b->rotate180(); // Move the bitboard back the right way around.
364  return sq2;
365  }
366  return sq;
367  }
368 }
369 
370 Square BoardState::nextRook(Side s, Bitboard *b)
371 {
372  if (s == White)
373  {
374  Square sq = white.next();
375  if (b && !sq.invalid())
376  {
377  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
378  allPieces.rotate180(); // Black goes at the bottom.
379  Bitboard enemyPieces = allPieces;
380  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
381  *b = rookMoves(allPieces, enemyPieces, sq);
382  }
383  return sq;
384  }
385  else
386  {
387  Square sq = black.next();
388  if (b && !sq.invalid())
389  {
390  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
391  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
392  Bitboard enemyPieces = allPieces;
393  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
394  Square sq2 = sq;
395  sq2.rotate180();
396  *b = rookMoves(allPieces, enemyPieces, sq);
397  b->rotate180(); // Move the bitboard back the right way around.
398  return sq2;
399  }
400  return sq;
401  }
402 }
403 
404 Square BoardState::firstKnight(Side s, Bitboard *b)
405 {
406  if (s == White)
407  {
408  Square sq = white.firstKnight();
409  if (b && !sq.invalid())
410  {
411  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
412  allPieces.rotate180(); // Black goes at the bottom.
413  Bitboard enemyPieces = allPieces;
414  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
415  *b = knightMoves(allPieces, enemyPieces, sq);
416  }
417  return sq;
418  }
419  else
420  {
421  Square sq = black.firstKnight();
422  if (b && !sq.invalid())
423  {
424  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
425  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
426  Bitboard enemyPieces = allPieces;
427  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
428  Square sq2 = sq;
429  sq2.rotate180();
430  *b = knightMoves(allPieces, enemyPieces, sq);
431  b->rotate180(); // Move the bitboard back the right way around.
432  return sq2;
433  }
434  return sq;
435  }
436 }
437 
438 Square BoardState::nextKnight(Side s, Bitboard *b)
439 {
440  if (s == White)
441  {
442  Square sq = white.next();
443  if (b && !sq.invalid())
444  {
445  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
446  allPieces.rotate180(); // Black goes at the bottom.
447  Bitboard enemyPieces = allPieces;
448  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
449  *b = knightMoves(allPieces, enemyPieces, sq);
450  }
451  return sq;
452  }
453  else
454  {
455  Square sq = black.next();
456  if (b && !sq.invalid())
457  {
458  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
459  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
460  Bitboard enemyPieces = allPieces;
461  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
462  Square sq2 = sq;
463  sq2.rotate180();
464  *b = knightMoves(allPieces, enemyPieces, sq);
465  b->rotate180(); // Move the bitboard back the right way around.
466  return sq2;
467  }
468  return sq;
469  }
470 }
471 
472 Square BoardState::firstBishop(Side s, Bitboard *b)
473 {
474  if (s == White)
475  {
476  Square sq = white.firstBishop();
477  if (b && !sq.invalid())
478  {
479  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
480  allPieces.rotate180(); // Black goes at the bottom.
481  Bitboard enemyPieces = allPieces;
482  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
483  *b = bishopMoves(allPieces, enemyPieces, sq);
484  }
485  return sq;
486  }
487  else
488  {
489  Square sq = black.firstBishop();
490  if (b && !sq.invalid())
491  {
492  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
493  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
494  Bitboard enemyPieces = allPieces;
495  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
496  Square sq2 = sq;
497  sq2.rotate180();
498  *b = bishopMoves(allPieces, enemyPieces, sq);
499  b->rotate180(); // Move the bitboard back the right way around.
500  return sq2;
501  }
502  return sq;
503  }
504 }
505 
506 Square BoardState::nextBishop(Side s, Bitboard *b)
507 {
508  if (s == White)
509  {
510  Square sq = white.next();
511  if (b && !sq.invalid())
512  {
513  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
514  allPieces.rotate180(); // Black goes at the bottom.
515  Bitboard enemyPieces = allPieces;
516  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
517  *b = bishopMoves(allPieces, enemyPieces, sq);
518  }
519  return sq;
520  }
521  else
522  {
523  Square sq = black.next();
524  if (b && !sq.invalid())
525  {
526  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
527  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
528  Bitboard enemyPieces = allPieces;
529  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
530  Square sq2 = sq;
531  sq2.rotate180();
532  *b = bishopMoves(allPieces, enemyPieces, sq);
533  b->rotate180(); // Move the bitboard back the right way around.
534  return sq2;
535  }
536  return sq;
537  }
538 }
539 
540 Square BoardState::firstQueen(Side s, Bitboard *b)
541 {
542  if (s == White)
543  {
544  Square sq = white.firstQueen();
545  if (b && !sq.invalid())
546  {
547  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
548  allPieces.rotate180(); // Black goes at the bottom.
549  Bitboard enemyPieces = allPieces;
550  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
551  *b = queenMoves(allPieces, enemyPieces, sq);
552  }
553  return sq;
554  }
555  else
556  {
557  Square sq = black.firstQueen();
558  if (b && !sq.invalid())
559  {
560  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
561  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
562  Bitboard enemyPieces = allPieces;
563  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
564  Square sq2 = sq;
565  sq2.rotate180();
566  *b = queenMoves(allPieces, enemyPieces, sq);
567  b->rotate180(); // Move the bitboard back the right way around.
568  return sq2;
569  }
570  return sq;
571  }
572 }
573 
574 Square BoardState::nextQueen(Side s, Bitboard *b)
575 {
576  if (s == White)
577  {
578  Square sq = white.next();
579  if (b && !sq.invalid())
580  {
581  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
582  allPieces.rotate180(); // Black goes at the bottom.
583  Bitboard enemyPieces = allPieces;
584  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
585  *b = queenMoves(allPieces, enemyPieces, sq);
586  }
587  return sq;
588  }
589  else
590  {
591  Square sq = black.next();
592  if (b && !sq.invalid())
593  {
594  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
595  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
596  Bitboard enemyPieces = allPieces;
597  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
598  Square sq2 = sq;
599  sq2.rotate180();
600  *b = queenMoves(allPieces, enemyPieces, sq);
601  b->rotate180(); // Move the bitboard back the right way around.
602  return sq2;
603  }
604  return sq;
605  }
606 }
607 
608 Square BoardState::firstKing(Side s, Bitboard *b)
609 {
610  if (s == White)
611  {
612  Square sq = white.firstKing();
613  if (b && !sq.invalid())
614  {
615  Bitboard allPieces = black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
616  allPieces.rotate180(); // Black goes at the bottom.
617  Bitboard enemyPieces = allPieces;
618  allPieces = allPieces | white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
619  *b = kingMoves(allPieces, enemyPieces, sq, white.rooksMoved[0], white.rooksMoved[1], white.kingMoved);
620  }
621  return sq;
622  }
623  else
624  {
625  Square sq = black.firstKing();
626  if (b && !sq.invalid())
627  {
628  Bitboard allPieces = white.pawns|white.knights|white.rooks|white.bishops|white.queen|white.king;
629  allPieces.rotate180(); // White goes at the bottom, as it is technically "black" :S
630  Bitboard enemyPieces = allPieces;
631  allPieces = allPieces | black.pawns|black.knights|black.rooks|black.bishops|black.queen|black.king;
632  Square sq2 = sq;
633  sq2.rotate180();
634  *b = kingMoves(allPieces, enemyPieces, sq, black.rooksMoved[0], black.rooksMoved[1], black.kingMoved);
635  b->rotate180(); // Move the bitboard back the right way around.
636  return sq2;
637  }
638  return sq;
639  }
640 }
641 
643 {
644  SideState tmp = white;
645  white = black;
646  black = tmp;
647 }
648 
649 long BoardState::heuristic(Side side)
650 {
651  if (side == White)
652  return white.heuristic() - black.heuristic();
653  else
654  return black.heuristic() - white.heuristic();
655 }
656 
658 {
659  printf("+-+-+-+-+-+-+-+-+\n");
660  for (int row = 7; row >= 0; row--)
661  {
662  printf("|");
663  for (int col = 0; col < 8; col++)
664  {
665  Bitboard b, b2;
666  b.set(row, col);
667  b2 = b;
668  b2.rotate180();
669  if (b2 & black.pawns)
670  printf("P");
671  else if (b2 & black.knights)
672  printf("H"); // H for 'horse' - K is taken.
673  else if (b2 & black.rooks)
674  printf("R");
675  else if (b2 & black.bishops)
676  printf("B");
677  else if (b2 & black.queen)
678  printf("Q");
679  else if (b2 & black.king)
680  printf("K");
681  else if (b & white.pawns)
682  printf("p");
683  else if (b & white.knights)
684  printf("h"); // H for 'horse' - K is taken.
685  else if (b & white.rooks)
686  printf("r");
687  else if (b & white.bishops)
688  printf("b");
689  else if (b & white.queen)
690  printf("q");
691  else if (b & white.king)
692  printf("k");
693  else
694  printf(" ");
695  printf("|");
696  }
697  printf(" %d\n+-+-+-+-+-+-+-+-+\n", row);
698  }
699  printf(" A B C D E F G H\n");
700 }
701 
702 extern StateStore stateStore;
703 
704 bool BoardState::load(int minPly, Side toPlay, MoveList &ml, long &h)
705 {
706  return stateStore.lookup(this, minPly, toPlay, h, ml);
707 }
708 
709 void BoardState::save(int ply, Side toPlay, long h, MoveList &ml)
710 {
711  stateStore.insert(this, toPlay, h, ply, ml);
712 }
713 
714 void BoardState::savePartial()
715 {
716  stateStore.insertPartial(this);
717 }
718 
719 void BoardState::uncache(Side toPlay)
720 {
721  stateStore.remove(this, toPlay);
722 }
723 
724 uint32_t BoardState::hash()
725 {
726  if (hashCalculated)
727  return cachedHash;
728 
729  hashCalculated = true;
730  g_nHashes++;
731  uint32_t accum = 0;
732  Square sq;
733  for (sq = firstPawn(White);
734  !sq.invalid();
735  sq = nextPawn(White))
736  {
737  accum ^= hashes[White][0][sq.col][sq.row];
738  }
739  for (sq = firstKnight(White);
740  !sq.invalid();
741  sq = nextKnight(White))
742  {
743  accum ^= hashes[White][1][sq.col][sq.row];
744  }
745  for (sq = firstRook(White);
746  !sq.invalid();
747  sq = nextRook(White))
748  {
749  accum ^= hashes[White][2][sq.col][sq.row];
750  }
751  for (sq = firstBishop(White);
752  !sq.invalid();
753  sq = nextBishop(White))
754  {
755  accum ^= hashes[White][3][sq.col][sq.row];
756  }
757  for (sq = firstQueen(White);
758  !sq.invalid();
759  sq = nextQueen(White))
760  {
761  accum ^= hashes[White][4][sq.col][sq.row];
762  }
763  sq = firstKing(White);
764  accum ^= hashes[White][5][sq.col][sq.row];
765 
766  for (sq = firstPawn(Black);
767  !sq.invalid();
768  sq = nextPawn(Black))
769  {
770  accum ^= hashes[Black][0][sq.col][sq.row];
771  }
772  for (sq = firstKnight(Black);
773  !sq.invalid();
774  sq = nextKnight(Black))
775  {
776  accum ^= hashes[Black][1][sq.col][sq.row];
777  }
778  for (sq = firstRook(Black);
779  !sq.invalid();
780  sq = nextRook(Black))
781  {
782  accum ^= hashes[Black][2][sq.col][sq.row];
783  }
784  for (sq = firstBishop(Black);
785  !sq.invalid();
786  sq = nextBishop(Black))
787  {
788  accum ^= hashes[Black][3][sq.col][sq.row];
789  }
790  for (sq = firstQueen(Black);
791  !sq.invalid();
792  sq = nextQueen(Black))
793  {
794  accum ^= hashes[Black][4][sq.col][sq.row];
795  }
796  sq = firstKing(Black);
797  accum ^= hashes[Black][5][sq.col][sq.row];
798 
799  if (white.rooksMoved[0])
800  accum ^= hashWhiteRookMovedL;
801  if (white.rooksMoved[1])
802  accum ^= hashWhiteRookMovedR;
803  if (white.kingMoved)
804  accum ^= hashWhiteKingMoved;
805  if (black.rooksMoved[0])
806  accum ^= hashBlackRookMovedL;
807  if (black.rooksMoved[1])
808  accum ^= hashBlackRookMovedR;
809  if (black.kingMoved)
810  accum ^= hashBlackKingMoved;
811 
812  sq = white.enPassant.getAndClearFirstSetBit();
813  if (!sq.invalid())
814  accum ^= hashes[White][6 /*En Passant*/][sq.col][sq.row];
815  sq = black.enPassant.getAndClearFirstSetBit();
816  if (!sq.invalid())
817  accum ^= hashes[Black][6 /*En Passant*/][sq.col][sq.row];
818 
819  cachedHash = accum;
820  return accum;
821 }
822 
823 uint32_t BoardState::hash2()
824 {
825  if (hash2Calculated)
826  return cachedHash2;
827 
828  hash2Calculated = true;
829  uint32_t accum = 0;
830  Square sq;
831  for (sq = firstPawn(White);
832  !sq.invalid();
833  sq = nextPawn(White))
834  {
835  accum ^= hashes2[White][0][sq.col][sq.row];
836  }
837  for (sq = firstKnight(White);
838  !sq.invalid();
839  sq = nextKnight(White))
840  {
841  accum ^= hashes2[White][1][sq.col][sq.row];
842  }
843  for (sq = firstRook(White);
844  !sq.invalid();
845  sq = nextRook(White))
846  {
847  accum ^= hashes2[White][2][sq.col][sq.row];
848  }
849  for (sq = firstBishop(White);
850  !sq.invalid();
851  sq = nextBishop(White))
852  {
853  accum ^= hashes2[White][3][sq.col][sq.row];
854  }
855  for (sq = firstQueen(White);
856  !sq.invalid();
857  sq = nextQueen(White))
858  {
859  accum ^= hashes2[White][4][sq.col][sq.row];
860  }
861  sq = firstKing(White);
862  accum ^= hashes2[White][5][sq.col][sq.row];
863 
864  for (sq = firstPawn(Black);
865  !sq.invalid();
866  sq = nextPawn(Black))
867  {
868  accum ^= hashes2[Black][0][sq.col][sq.row];
869  }
870  for (sq = firstKnight(Black);
871  !sq.invalid();
872  sq = nextKnight(Black))
873  {
874  accum ^= hashes2[Black][1][sq.col][sq.row];
875  }
876  for (sq = firstRook(Black);
877  !sq.invalid();
878  sq = nextRook(Black))
879  {
880  accum ^= hashes2[Black][2][sq.col][sq.row];
881  }
882  for (sq = firstBishop(Black);
883  !sq.invalid();
884  sq = nextBishop(Black))
885  {
886  accum ^= hashes2[Black][3][sq.col][sq.row];
887  }
888  for (sq = firstQueen(Black);
889  !sq.invalid();
890  sq = nextQueen(Black))
891  {
892  accum ^= hashes2[Black][4][sq.col][sq.row];
893  }
894  sq = firstKing(Black);
895  accum ^= hashes2[Black][5][sq.col][sq.row];
896 
897  if (white.rooksMoved[0])
898  accum ^= hashWhiteRookMovedL2;
899  if (white.rooksMoved[1])
900  accum ^= hashWhiteRookMovedR2;
901  if (white.kingMoved)
902  accum ^= hashWhiteKingMoved2;
903  if (black.rooksMoved[0])
904  accum ^= hashBlackRookMovedL2;
905  if (black.rooksMoved[1])
906  accum ^= hashBlackRookMovedR2;
907  if (black.kingMoved)
908  accum ^= hashBlackKingMoved2;
909 
910  sq = white.enPassant.getAndClearFirstSetBit();
911  if (!sq.invalid())
912  accum ^= hashes2[White][6 /*En Passant*/][sq.col][sq.row];
913  sq = black.enPassant.getAndClearFirstSetBit();
914  if (!sq.invalid())
915  accum ^= hashes2[Black][6 /*En Passant*/][sq.col][sq.row];
916 
917  cachedHash2 = accum;
918  return accum;
919 }
void move(Move m, Side s, Piece promotion=Pawn)
Definition: BoardState.cc:49
Bitboard pawns
Definition: SideState.h:100
bool load(int minPly, Side toPlay, MoveList &ml, long &h)
Definition: BoardState.cc:704
void rotate180()
Definition: Bitboard.cc:77
void friendlyMove(Move m, Piece promotion=Pawn)
Definition: SideState.cc:239
bool rooksMoved[2]
Definition: SideState.h:93
Square firstPawn(Side s, Bitboard *b=NULL)
Definition: BoardState.cc:260
long heuristic(Side side)
Definition: BoardState.cc:649
Definition: Move.h:29
bool isAttacking(Square sq, Bitboard enemyPieces)
Definition: SideState.cc:139
void save(int ply, Side toPlay, long h, MoveList &ml)
Definition: BoardState.cc:709
Square firstPawn()
Definition: SideState.cc:92
void swapSides()
Definition: BoardState.cc:642
bool set(int rank, int file)
Definition: Bitboard.h:83
bool isLegal(Move m, Bitboard enemyPieces, Bitboard enemyPawnsEnPassant)
Definition: SideState.cc:194
void dump()
Definition: BoardState.cc:657
Definition: Square.h:24
bool isLegal(Move m, Side s)
Definition: BoardState.cc:73