Subversion Repositories Games.Chess Giants

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
33 pmbaty 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