Subversion Repositories Games.Chess Giants

Rev

Rev 33 | 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 = 0;
  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.   for (side = black; side <= white; side++) {
  39.     temp_occ =
  40.         Pawns(side) | Knights(side) | Bishops(side) | Rooks(side) |
  41.         Queens(side)
  42.         | Kings(side);
  43.     if (Occupied(side) ^ temp_occ) {
  44.       if (!error)
  45.         Print(2048, "\n");
  46.       Print(2048, "ERROR %s occupied squares is bad!\n",
  47.           (side) ? "white" : "black");
  48.       Display2BitBoards(temp_occ, Occupied(white));
  49.       error = 1;
  50.     }
  51.   }
  52. /*
  53.  ************************************************************
  54.  *                                                          *
  55.  *  Now we do some sanity tests on the actual chess board   *
  56.  *  information.  The first test is to make sure that no    *
  57.  *  bitmap square is set in more than one bitmap, which     *
  58.  *  would imply two different pieces on the same square.    *
  59.  *                                                          *
  60.  ************************************************************
  61.  */
  62.   temp_occ =
  63.       Pawns(white) ^ Knights(white) ^ Bishops(white) ^ Rooks(white) ^
  64.       Queens(white) ^ Pawns(black) ^ Knights(black) ^ Bishops(black) ^
  65.       Rooks(black) ^ Queens(black) ^ Kings(white) ^ Kings(black);
  66.   temp_occx =
  67.       Pawns(white) | Knights(white) | Bishops(white) | Rooks(white) |
  68.       Queens(white) | Pawns(black) | Knights(black) | Bishops(black) |
  69.       Rooks(black) | Queens(black) | Kings(white) | Kings(black);
  70.   if (temp_occ ^ temp_occx) {
  71.     if (!error)
  72.       Print(2048, "\n");
  73.     Print(2048, "ERROR two pieces on same square\n");
  74.     error = 1;
  75.   }
  76. /*
  77.  ************************************************************
  78.  *                                                          *
  79.  *  Add up all the pieces (material values) to see if this  *
  80.  *  matches the incrementally updated value.                *
  81.  *                                                          *
  82.  ************************************************************
  83.  */
  84.   temp_score = 0;
  85.   for (side = black; side <= white; side++)
  86.     for (piece = pawn; piece < king; piece++)
  87.       temp_score += PopCnt(Pieces(side, piece)) * PieceValues(side, piece);
  88.   if (temp_score != Material) {
  89.     if (!error)
  90.       Print(2048, "\n");
  91.     Print(2048, "ERROR  material evaluation is wrong, good=%d, bad=%d\n",
  92.         temp_score, Material);
  93.     error = 1;
  94.   }
  95. /*
  96.  ************************************************************
  97.  *                                                          *
  98.  *  Next, check the incrementally updated piece counts for  *
  99.  *  both sides.  ditto for pawn counts.                     *
  100.  *                                                          *
  101.  ************************************************************
  102.  */
  103.   for (side = black; side <= white; side++) {
  104.     temp_score = 0;
  105.     for (piece = knight; piece < king; piece++)
  106.       temp_score += PopCnt(Pieces(side, piece)) * p_vals[piece];
  107.     if (temp_score != TotalPieces(side, occupied)) {
  108.       if (!error)
  109.         Print(2048, "\n");
  110.       Print(2048, "ERROR  %s pieces is wrong, good=%d, bad=%d\n",
  111.           (side) ? "white" : "black", temp_score, TotalPieces(side,
  112.               occupied));
  113.       error = 1;
  114.     }
  115.   }
  116.   for (side = black; side <= white; side++) {
  117.     temp_score = PopCnt(Pawns(side));
  118.     if (temp_score != TotalPieces(side, pawn)) {
  119.       if (!error)
  120.         Print(2048, "\n");
  121.       Print(2048, "ERROR  %s pawns is wrong, good=%d, bad=%d\n",
  122.           (side) ? "white" : "black", temp_score, TotalPieces(side, pawn));
  123.       error = 1;
  124.     }
  125.   }
  126.   i = PopCnt(OccupiedSquares);
  127.   if (i != TotalAllPieces) {
  128.     if (!error)
  129.       Print(2048, "\n");
  130.     Print(2048, "ERROR!  TotalAllPieces is wrong, correct=%d  bad=%d\n", i,
  131.         TotalAllPieces);
  132.     error = 1;
  133.   }
  134. /*
  135.  ************************************************************
  136.  *                                                          *
  137.  *  Now we cycle through each different chessboard bitmap   *
  138.  *  and verify that each piece in a bitmap matches the same *
  139.  *  piece type in the board[64] array.                      *
  140.  *                                                          *
  141.  ************************************************************
  142.  */
  143.   for (side = black; side <= white; side++)
  144.     for (piece = pawn; piece <= king; piece++) {
  145.       temp = Pieces(side, piece);
  146.       while (temp) {
  147.         square = LSB(temp);
  148.         if (PcOnSq(square) != pieces[side][piece]) {
  149.           if (!error)
  150.             Print(2048, "\n");
  151.           Print(2048, "ERROR!  board[%d]=%d, should be %d\n", square,
  152.               PcOnSq(square), pieces[side][piece]);
  153.           error = 1;
  154.         }
  155.         temp &= temp - 1;
  156.       }
  157.     }
  158. /*
  159.  ************************************************************
  160.  *                                                          *
  161.  *  And then we look at the board[64] array and make sure   *
  162.  *  that any non-zero piece matches the proper bitmap for   *
  163.  *  that particular piece type.                             *
  164.  *                                                          *
  165.  ************************************************************
  166.  */
  167.   for (i = 0; i < 64; i++) {
  168.     if (!PcOnSq(i))
  169.       continue;
  170.     side = (PcOnSq(i) > 0) ? 1 : 0;
  171.     if (SetMask(i) & Pieces(side, Abs(PcOnSq(i))))
  172.       continue;
  173.     if (!error)
  174.       Print(2048, "\n");
  175.     Print(2048, "ERROR!  bitboards/board[%d] don't agree!\n", i);
  176.     error = 1;
  177.     break;
  178.   }
  179. /*
  180.  ************************************************************
  181.  *                                                          *
  182.  *  The last chess board test is to make sure that any      *
  183.  *  square that is empty according to board[64] is also     *
  184.  *  empty according to the occupied squares bitmap.         *
  185.  *                                                          *
  186.  ************************************************************
  187.  */
  188.   temp = ~(temp_occ | temp_occx);
  189.   while (temp) {
  190.     square = LSB(temp);
  191.     if (PcOnSq(square)) {
  192.       if (!error)
  193.         Print(2048, "\n");
  194.       Print(2048, "ERROR!  board[%d]=%d, should be 0\n", square,
  195.           PcOnSq(square));
  196.       error = 1;
  197.     }
  198.     temp &= temp - 1;
  199.   }
  200. /*
  201.  ************************************************************
  202.  *                                                          *
  203.  *  Finally, we re-compute the pawn hash signature and the  *
  204.  *  normal hash signature and verify that they match the    *
  205.  *  incrementally updated values.                           *
  206.  *                                                          *
  207.  ************************************************************
  208.  */
  209.   temp = 0;
  210.   temp1 = 0;
  211.   for (i = 0; i < 64; i++) {
  212.     side = (PcOnSq(i) > 0) ? 1 : 0;
  213.     temp ^= randoms[side][Abs(PcOnSq(i))][i];
  214.     if (Abs(PcOnSq(i)) == pawn)
  215.       temp1 ^= randoms[side][Abs(PcOnSq(i))][i];
  216.   }
  217.   if (EnPassant(ply))
  218.     temp ^= enpassant_random[EnPassant(ply)];
  219.   for (side = black; side <= white; side++) {
  220.     if (Castle(ply, side) < 0 || !(Castle(ply, side) & 1))
  221.       temp ^= castle_random[0][side];
  222.     if (Castle(ply, side) < 0 || !(Castle(ply, side) & 2))
  223.       temp ^= castle_random[1][side];
  224.   }
  225.   if (temp ^ HashKey) {
  226.     if (!error)
  227.       Print(2048, "\n");
  228.     Print(2048, "ERROR!  hash_key is bad.\n");
  229.     error = 1;
  230.   }
  231.   if (temp1 ^ PawnHashKey) {
  232.     if (!error)
  233.       Print(2048, "\n");
  234.     Print(2048, "ERROR!  pawn_hash_key is bad.\n");
  235.     error = 1;
  236.   }
  237. /*
  238.  ************************************************************
  239.  *                                                          *
  240.  *  If any inconsistencies/errors were found, we are going  *
  241.  *  to dump as much debugging information as possible to    *
  242.  *  help pinpoint the source of the problem.                *
  243.  *                                                          *
  244.  ************************************************************
  245.  */
  246.   if (error) {
  247.     Lock(lock_smp);
  248.     Unlock(lock_smp);
  249.     Print(2048, "ply=%d\n", tree->ply);
  250.     Print(2048, "phase[%d]=%d  current move:\n", ply, tree->phase[ply]);
  251.     DisplayChessMove("move=", move);
  252.     DisplayChessBoard(stdout, tree->position);
  253.     Print(2048, "called from %s, ply=%d\n", caller, ply);
  254.     Print(2048, "node=%" PRIu64 "\n", tree->nodes_searched);
  255.     Print(2048, "active path:\n");
  256.     for (i = 1; i <= ply; i++) {
  257.       Print(2048, "ply=%d  ", i);
  258.       DisplayChessMove("move=", tree->curmv[i]);
  259.     }
  260.     CraftyExit(1);
  261.   }
  262. }
  263. #endif
  264.