Subversion Repositories Games.Chess Giants

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #if defined(DEBUG)
  2. #  include "chess.h"
  3. #  include "data.h"
  4. /* last modified 02/26/14 */
  5. /*
  6.  *******************************************************************************
  7.  *                                                                             *
  8.  *   ValidatePosition() is a debugging tool that is enabled by using the       *
  9.  *   -DDEBUG compilation flag.  This procedure tests the various data          *
  10.  *   structures used in Crafty related to the chess board and incrementally    *
  11.  *   updated values like hash signatures and so forth.  It simply looks for    *
  12.  *   consistency between the various bitboards, and recomputes the hash        *
  13.  *   signatures to determine if they are correct.  If anything fails to pass   *
  14.  *   the validation test, we print out a dump of the moves made in this path   *
  15.  *   through the tree, and then exit since things are corrupted.               *
  16.  *                                                                             *
  17.  *   This greatly slows the program down, because ValidatePosition() is called *
  18.  *   after each Make()/Unmake() (these are the functions that modify the       *
  19.  *   primary data structures).  In general, this will not be used by users     *
  20.  *   unless they are modifying the source code themselves.                     *
  21.  *                                                                             *
  22.  *******************************************************************************
  23.  */
  24. void ValidatePosition(TREE * RESTRICT tree, int ply, int move, char *caller) {
  25.   uint64_t temp, temp1, temp_occ;
  26.   uint64_t temp_occx;
  27.   int i, square, error;
  28.   int side, piece, temp_score;
  29.  
  30. /*
  31.  ************************************************************
  32.  *                                                          *
  33.  *  First, test occupied[side] which should match the OR    *
  34.  *  result of all pieces[side].                             *
  35.  *                                                          *
  36.  ************************************************************
  37.  */
  38.   error = 0;
  39.   for (side = black; side <= white; side++) {
  40.     temp_occ =
  41.         Pawns(side) | Knights(side) | Bishops(side) | Rooks(side) |
  42.         Queens(side)
  43.         | Kings(side);
  44.     if (Occupied(side) ^ temp_occ) {
  45.       Print(128, "ERROR %s occupied squares is bad!\n",
  46.           (side) ? "white" : "black");
  47.       Display2BitBoards(temp_occ, Occupied(white));
  48.       error = 1;
  49.     }
  50.   }
  51. /*
  52.  ************************************************************
  53.  *                                                          *
  54.  *  Now we do some sanity tests on the actual chess board   *
  55.  *  information.  The first test is to make sure that no    *
  56.  *  bitmap square is set in more than one bitmap, which     *
  57.  *  would imply two different pieces on the same square.    *
  58.  *                                                          *
  59.  ************************************************************
  60.  */
  61.   temp_occ =
  62.       Pawns(white) ^ Knights(white) ^ Bishops(white) ^ Rooks(white) ^
  63.       Queens(white) ^ Pawns(black) ^ Knights(black) ^ Bishops(black) ^
  64.       Rooks(black) ^ Queens(black) ^ Kings(white) ^ Kings(black);
  65.   temp_occx =
  66.       Pawns(white) | Knights(white) | Bishops(white) | Rooks(white) |
  67.       Queens(white) | Pawns(black) | Knights(black) | Bishops(black) |
  68.       Rooks(black) | Queens(black) | Kings(white) | Kings(black);
  69.   if (temp_occ ^ temp_occx) {
  70.     Print(128, "ERROR two pieces on same square\n");
  71.     error = 1;
  72.   }
  73. /*
  74.  ************************************************************
  75.  *                                                          *
  76.  *  Add up all the pieces (material values) to see if this  *
  77.  *  matches the incrementally updated value.                *
  78.  *                                                          *
  79.  ************************************************************
  80.  */
  81.   temp_score = 0;
  82.   for (side = black; side <= white; side++)
  83.     for (piece = pawn; piece < king; piece++)
  84.       temp_score += PopCnt(Pieces(side, piece)) * PieceValues(side, piece);
  85.   if (temp_score != Material) {
  86.     Print(128, "ERROR  material evaluation is wrong, good=%d, bad=%d\n",
  87.         temp_score, Material);
  88.     error = 1;
  89.   }
  90. /*
  91.  ************************************************************
  92.  *                                                          *
  93.  *  Next, check the incrementally updated piece counts for  *
  94.  *  both sides.  ditto for pawn counts.                     *
  95.  *                                                          *
  96.  ************************************************************
  97.  */
  98.   for (side = black; side <= white; side++) {
  99.     temp_score = 0;
  100.     for (piece = knight; piece < king; piece++)
  101.       temp_score += PopCnt(Pieces(side, piece)) * p_vals[piece];
  102.     if (temp_score != TotalPieces(side, occupied)) {
  103.       Print(128, "ERROR  %s pieces is wrong, good=%d, bad=%d\n",
  104.           (side) ? "white" : "black", temp_score, TotalPieces(side,
  105.               occupied));
  106.       error = 1;
  107.     }
  108.   }
  109.   for (side = black; side <= white; side++) {
  110.     temp_score = PopCnt(Pawns(side));
  111.     if (temp_score != TotalPieces(side, pawn)) {
  112.       Print(128, "ERROR  %s pawns is wrong, good=%d, bad=%d\n",
  113.           (side) ? "white" : "black", temp_score, TotalPieces(side, pawn));
  114.       error = 1;
  115.     }
  116.   }
  117.   i = PopCnt(OccupiedSquares);
  118.   if (i != TotalAllPieces) {
  119.     Print(128, "ERROR!  TotalAllPieces is wrong, correct=%d  bad=%d\n", i,
  120.         TotalAllPieces);
  121.     error = 1;
  122.   }
  123. /*
  124.  ************************************************************
  125.  *                                                          *
  126.  *  Now we cycle through each different chessboard bitmap   *
  127.  *  and verify that each piece in a bitmap matches the same *
  128.  *  piece type in the board[64] array.                      *
  129.  *                                                          *
  130.  ************************************************************
  131.  */
  132.   for (side = black; side <= white; side++)
  133.     for (piece = pawn; piece <= king; piece++) {
  134.       temp = Pieces(side, piece);
  135.       while (temp) {
  136.         square = LSB(temp);
  137.         if (PcOnSq(square) != pieces[side][piece]) {
  138.           Print(128, "ERROR!  board[%d]=%d, should be %d\n", square,
  139.               PcOnSq(square), pieces[side][piece]);
  140.           error = 1;
  141.         }
  142.         temp &= temp - 1;
  143.       }
  144.     }
  145. /*
  146.  ************************************************************
  147.  *                                                          *
  148.  *  And then we look at the board[64] array and make sure   *
  149.  *  that any non-zero piece matches the proper bitmap for   *
  150.  *  that particular piece type.                             *
  151.  *                                                          *
  152.  ************************************************************
  153.  */
  154.   for (i = 0; i < 64; i++) {
  155.     if (!PcOnSq(i))
  156.       continue;
  157.     side = (PcOnSq(i) > 0) ? 1 : 0;
  158.     if (SetMask(i) & Pieces(side, Abs(PcOnSq(i))))
  159.       continue;
  160.     Print(128, "ERROR!  bitboards/board[%d] don't agree!\n", i);
  161.     error = 1;
  162.     break;
  163.   }
  164. /*
  165.  ************************************************************
  166.  *                                                          *
  167.  *  The last chess board test is to make sure that any      *
  168.  *  square that is empty according to board[64] is also     *
  169.  *  empty according to the occupied squares bitmap.         *
  170.  *                                                          *
  171.  ************************************************************
  172.  */
  173.   temp = ~(temp_occ | temp_occx);
  174.   while (temp) {
  175.     square = LSB(temp);
  176.     if (PcOnSq(square)) {
  177.       Print(128, "ERROR!  board[%d]=%d, should be 0\n", square,
  178.           PcOnSq(square));
  179.       error = 1;
  180.     }
  181.     temp &= temp - 1;
  182.   }
  183. /*
  184.  ************************************************************
  185.  *                                                          *
  186.  *  Finally, we re-compute the pawn hash signature and the  *
  187.  *  normal hash signature and verify that they match the    *
  188.  *  incrementally updated values.                           *
  189.  *                                                          *
  190.  ************************************************************
  191.  */
  192.   temp = 0;
  193.   temp1 = 0;
  194.   for (i = 0; i < 64; i++) {
  195.     side = (PcOnSq(i) > 0) ? 1 : 0;
  196.     temp ^= randoms[side][Abs(PcOnSq(i))][i];
  197.     if (Abs(PcOnSq(i)) == pawn)
  198.       temp1 ^= randoms[side][Abs(PcOnSq(i))][i];
  199.   }
  200.   if (EnPassant(ply))
  201.     temp ^= enpassant_random[EnPassant(ply)];
  202.   for (side = black; side <= white; side++) {
  203.     if (Castle(ply, side) < 0 || !(Castle(ply, side) & 1))
  204.       temp ^= castle_random[0][side];
  205.     if (Castle(ply, side) < 0 || !(Castle(ply, side) & 2))
  206.       temp ^= castle_random[1][side];
  207.   }
  208.   if (temp ^ HashKey) {
  209.     Print(128, "ERROR!  hash_key is bad.\n");
  210.     error = 1;
  211.   }
  212.   if (temp1 ^ PawnHashKey) {
  213.     Print(128, "ERROR!  pawn_hash_key is bad.\n");
  214.     error = 1;
  215.   }
  216. /*
  217.  ************************************************************
  218.  *                                                          *
  219.  *  If any inconsistencies/errors were found, we are going  *
  220.  *  to dump as much debugging information as possible to    *
  221.  *  help pinpoint the source of the problem.                *
  222.  *                                                          *
  223.  ************************************************************
  224.  */
  225.   if (error) {
  226.     Print(4095, "processor id: cpu-%d\n", tree->thread_id);
  227.     Print(4095, "current move:\n");
  228.     DisplayChessMove("move=", move);
  229.     DisplayChessBoard(stdout, tree->position);
  230.     Print(4095, "called from %s, ply=%d\n", caller, ply);
  231.     Print(4095, "node=%" PRIu64 "\n", tree->nodes_searched);
  232.     Print(4095, "active path:\n");
  233.     for (i = 1; i <= ply; i++)
  234.       DisplayChessMove("move=", tree->curmv[i]);
  235.     CraftyExit(1);
  236.   }
  237. }
  238. #endif
  239.