Update codebase to remove clang warnings (and a couple of legit errors
[typhoon.git] / src / testsup.c
1 /**
2
3 Copyright (c) Scott Gasch
4
5 Module Name:
6
7     testgenerate.c
8
9 Abstract:
10
11     Test the move generator.
12
13 Author:
14
15     Scott Gasch ([email protected]) 8 April 2005
16
17 Revision History:
18
19     $Id: testsup.c 345 2007-12-02 22:56:42Z scott $
20
21 **/
22
23 #include "chess.h"
24
25 FLAG
26 IsBoardLegal(POSITION *pos)
27 {
28     COOR c;
29     
30     for (c = A1; c <= H1; c++)
31     {
32         if (!IS_EMPTY(pos->rgSquare[c].pPiece))
33         {
34             if (IS_PAWN(pos->rgSquare[c].pPiece))
35             {
36                 return(FALSE);
37             }
38         }
39     }
40     
41     for (c = A8; c <= H8; c++)
42     {
43         if (!IS_EMPTY(pos->rgSquare[c].pPiece))
44         {
45             if (IS_PAWN(pos->rgSquare[c].pPiece))
46             {
47                 return(FALSE);
48             }
49         }
50     }
51     
52     if (InCheck(pos, WHITE) &&
53         InCheck(pos, BLACK))
54     {
55         return(FALSE);
56     }
57
58     if (InCheck(pos, FLIP(pos->uToMove)))
59     {
60         return(FALSE);
61     }
62     return(TRUE);
63 }
64
65
66 void
67 GenerateRandomLegalPosition(POSITION *pos)
68 {
69     COOR c, c1;
70     ULONG x, uIndex;
71     ULONG uColor;
72     PIECE p;
73     ULONG u;
74
75     do
76     {
77         //
78         // Clear the board
79         //
80         memset(pos, 0, sizeof(POSITION));
81         for (u = 0; u < ARRAY_SIZE(pos->cPawns[WHITE]); u++)
82         {
83             pos->cPawns[WHITE][u] = pos->cPawns[BLACK][u] = ILLEGAL_COOR;
84         }
85         
86         for (u = 0; u < ARRAY_SIZE(pos->cNonPawns[WHITE]); u++)
87         {
88             pos->cNonPawns[WHITE][u] = pos->cNonPawns[BLACK][u] = ILLEGAL_COOR;
89         }
90         
91         //
92         // Place both kings legally
93         //
94         c = RANDOM_COOR;
95         ASSERT(IS_ON_BOARD(c));
96         pos->rgSquare[c].pPiece = WHITE_KING;
97         ASSERT(pos->cNonPawns[WHITE][0] == ILLEGAL_COOR);
98         pos->cNonPawns[WHITE][0] = c;
99         pos->uNonPawnCount[WHITE][KING] = 1;
100         pos->uNonPawnCount[WHITE][0] = 1;
101         pos->uNonPawnMaterial[WHITE] = VALUE_KING;
102         
103         do
104         {
105             c1 = RANDOM_COOR;
106         }
107         while(DISTANCE(c, c1) < 2);
108         ASSERT(IS_ON_BOARD(c1));
109         pos->rgSquare[c1].pPiece = BLACK_KING;
110         ASSERT(pos->cNonPawns[BLACK][0] == ILLEGAL_COOR);
111         pos->cNonPawns[BLACK][0] = c1;
112         pos->uNonPawnCount[BLACK][KING] = 1;
113         pos->uNonPawnCount[BLACK][0] = 1;
114         pos->uNonPawnMaterial[BLACK] = VALUE_KING;
115         
116         //
117         // Place the rest of the armies
118         //
119         FOREACH_COLOR(uColor)
120         {
121             ASSERT(IS_VALID_COLOR(uColor));
122
123             for (x = 0;
124                  x < (ULONG)(rand() % 15 + 1);
125                  x++)
126             {
127                 //
128                 // Pick a random empty square
129                 //
130                 do
131                 {
132                     c = RANDOM_COOR;
133                 }
134                 while((pos->rgSquare[c].pPiece) || (RANK1(c) || RANK8(c)));
135
136                 do
137                 {
138                     p = RANDOM_PIECE;
139                     if (WHITE == uColor)
140                     {
141                         p |= WHITE;
142                     }
143                     else
144                     {
145                         p &= ~WHITE;
146                     }
147                     ASSERT(GET_COLOR(p) == uColor);
148                     
149                     if (IS_PAWN(p) &&
150                         (pos->uPawnCount[uColor] < 8) &&
151                         (!RANK1(c)) && 
152                         (!RANK8(c)))
153                     {
154                         //
155                         // The pawn list is not ordered at all, add
156                         // the new pawn's location to the list and
157                         // point from the pawn to the list.
158                         //
159                         pos->cPawns[uColor][pos->uPawnCount[uColor]] = c;
160                         pos->rgSquare[c].uIndex = pos->uPawnCount[uColor];
161                         pos->rgSquare[c].pPiece = p;
162                         pos->uPawnCount[uColor]++;
163                         pos->uPawnMaterial[uColor] += VALUE_PAWN;
164                         break;
165                     }
166                     else if (!IS_KING(p) &&
167                              (IS_VALID_PIECE(p)))
168                     {
169                         uIndex = pos->uNonPawnCount[uColor][0];
170                         pos->cNonPawns[uColor][uIndex] = c;
171                         pos->uNonPawnCount[uColor][0]++;
172                         pos->uNonPawnCount[uColor][PIECE_TYPE(p)]++;
173                         pos->rgSquare[c].pPiece = p;
174                         pos->rgSquare[c].uIndex = uIndex;
175                         pos->uNonPawnMaterial[uColor] += PIECE_VALUE(p);
176                         if (IS_BISHOP(p))
177                         {
178                             if (IS_WHITE_SQUARE_COOR(c))
179                             {
180                                 pos->uWhiteSqBishopCount[uColor]++;
181                             }
182                         }
183                         break;
184                     }
185                 }
186                 while(1);
187
188             } // next piece
189
190         } // next color
191         ASSERT(pos->uNonPawnCount[WHITE][KING] == 1);
192         ASSERT(pos->uNonPawnCount[BLACK][KING] == 1);
193         //pos->uNonPawnCount[WHITE][0]--;
194         //pos->uNonPawnCount[BLACK][0]--;
195
196         //
197         // Do the rest of the position
198         //
199         pos->iMaterialBalance[WHITE] =
200             ((SCORE)(pos->uNonPawnMaterial[WHITE] +
201                      pos->uPawnMaterial[WHITE]) -
202              (SCORE)(pos->uNonPawnMaterial[BLACK] +
203                      pos->uPawnMaterial[BLACK]));
204         pos->iMaterialBalance[BLACK] = -pos->iMaterialBalance[WHITE];
205         pos->uToMove = RANDOM_COLOR;
206         pos->uFifty = rand() % 100;
207         if (pos->rgSquare[E1].pPiece == WHITE_KING)
208         {
209             if (pos->rgSquare[A1].pPiece == WHITE_ROOK)
210             {
211                 pos->bvCastleInfo |= CASTLE_WHITE_SHORT;
212             }
213             if (pos->rgSquare[H1].pPiece == WHITE_ROOK)
214             {
215                 pos->bvCastleInfo |= CASTLE_WHITE_LONG;
216             }
217         }
218         if (pos->rgSquare[E8].pPiece == BLACK_KING)
219         {
220             if (pos->rgSquare[A8].pPiece == BLACK_ROOK)
221             {
222                 pos->bvCastleInfo |= CASTLE_BLACK_SHORT;
223             }
224             if (pos->rgSquare[H8].pPiece == BLACK_ROOK)
225             {
226                 pos->bvCastleInfo |= CASTLE_BLACK_LONG;
227             }
228         }
229         pos->u64NonPawnSig = ComputeSig(pos);
230         pos->u64PawnSig = ComputePawnSig(pos);
231
232         //
233         // See if it's legal
234         //
235         if (VerifyPositionConsistency(pos, TRUE) &&
236             !InCheck(pos, FLIP(pos->uToMove)))
237         {
238             break;
239         }
240     }
241     while(1);
242 }
243
244
245 #define SYM_SQ(c)                  ((7 - (((c) & 0xF0) >> 4)) << 4) \
246                                        | (7 - ((c) & 0x0F))
247 void
248 GenerateRandomLegalSymetricPosition(POSITION *pos)
249 {
250     CHAR szFen[256];
251     CHAR *p;
252     ULONG uPieceCount[7];
253     COOR c, xc;
254     PIECE pPiece = KING;
255     PIECE pBoard[128];
256     ULONG x, y;
257
258     do
259     {
260         memset(pBoard, 0, sizeof(pBoard));
261         memset(uPieceCount, 0, sizeof(uPieceCount));
262
263         y = (ULONG)((rand() % 15) + 1);
264         for (x = 0;
265              x < y;
266              x++)
267         {
268             //
269             // Pick a piece type
270             //
271             do
272             {
273                 pPiece = (rand() % 5) + 1;
274                 switch(pPiece)
275                 {
276                     case PAWN:
277                         if (uPieceCount[PAWN] < 8)
278                         {
279                             uPieceCount[PAWN]++;
280                         }
281                         else
282                         {
283                             pPiece = 0;
284                         }
285                         break;
286                     case KNIGHT:
287                     case BISHOP:
288                     case ROOK:
289                     case QUEEN:
290                         if (uPieceCount[pPiece] < 2)
291                         {
292                             uPieceCount[pPiece]++;
293                         }
294                         else
295                         {
296                             if (uPieceCount[PAWN] < 8)
297                             {
298                                 uPieceCount[PAWN]++;
299                                 pPiece = PAWN;
300                             }
301                         }
302                         break;
303                     default:
304                         pPiece = 0;
305                         break;
306                 }
307             }
308             while(pPiece == 0);
309             
310             //
311             // Pick a location
312             //
313             do
314             {
315                 c = RANDOM_COOR;
316             }
317             while (!IS_ON_BOARD(c) ||
318                    (pBoard[c] != 0) ||
319                    ((pPiece == PAWN) && ((RANK(c) == 1) || (RANK(c) == 8))));
320             xc = SYM_SQ(c);
321             ASSERT(IS_ON_BOARD(xc));
322             ASSERT(IS_EMPTY(pBoard[xc]));
323             
324             pBoard[c] = (pPiece << 1) | WHITE;
325             pBoard[xc] = (pPiece << 1) | BLACK;
326             pPiece = 0;
327         }
328         
329         do
330         {
331             c = RANDOM_COOR;
332         }
333         while (!IS_ON_BOARD(c) ||
334                (pBoard[c] != 0));
335         xc = SYM_SQ(c);
336         ASSERT(IS_ON_BOARD(xc));
337         ASSERT(IS_EMPTY(pBoard[xc]));
338         pBoard[c] = WHITE_KING;
339         pBoard[xc] = BLACK_KING;
340         
341         memset(szFen, 0, sizeof(szFen));
342         p = szFen;
343         for (x = 0; x < 120; x++)
344         {
345             if ((x % 15 == 0) && 
346                 (x != 120) && 
347                 (x != 0)) *p++ = '/';
348             
349             if (!IS_ON_BOARD(x)) continue;
350             if (0 == pBoard[x]) *p++ = '1';
351             else *p++ = *(PieceAbbrev(pBoard[x]) + 1);
352         }
353         strcat(p, " w - - 0 0");
354         FenToPosition(pos, szFen);
355     }
356     while(!IsBoardLegal(pos));
357 }