Update codebase to remove clang warnings (and a couple of legit errors
[typhoon.git] / src / testmove.c
1 /**
2
3 Copyright (c) Scott Gasch
4
5 Module Name:
6
7     testmove.c
8
9 Abstract:
10
11 Author:
12
13     Scott Gasch ([email protected]) 11 May 2004
14
15 Revision History:
16
17     $Id: testmove.c 345 2007-12-02 22:56:42Z scott $
18
19 **/
20
21 #include "chess.h"
22
23 #ifdef TEST
24
25 static COOR 
26 _TestPickRandomPieceLocation(POSITION *pos)
27 /**
28
29 Routine description:
30
31     Test code: supports TestLiftPlaceSlidePiece.  Picks a random square
32     where there is a piece on board.
33
34 Parameters:
35
36     POSITION *pos
37
38 Return value:
39
40     static COOR
41
42 **/
43 {
44     ULONG u = RANDOM_COLOR;
45     ULONG v = rand() & 1;
46     ULONG w;
47     COOR c;
48     
49     if ((TRUE == v) && (pos->uPawnCount[u]))
50     {
51         w = rand() % pos->uPawnCount[u];
52         c = pos->cPawns[u][w];
53     }
54     else
55     {
56         ASSERT(pos->uNonPawnCount[u][0]);
57         w = rand() % pos->uNonPawnCount[u][0];
58         c = pos->cNonPawns[u][w];
59     }
60     ASSERT(IS_ON_BOARD(c));
61     return(c);
62 }
63
64
65 void 
66 TestLiftPlaceSlidePiece(void)
67 /**
68
69 Routine description:
70
71     Test code.  Tests LiftPiece, PlacePiece and SlidePiece.
72
73 Parameters:
74
75     POSITION *pos
76
77 Return value:
78
79     void
80
81 **/
82 {
83 #define NUM_LOOPS 1000000
84     POSITION pos;
85     PIECE p[30];
86     ULONG u = 0;
87     UINT v = 0;
88     COOR cFrom, cTo;
89     UINT64 u64Start = SystemReadTimeStampCounter();
90     UINT64 u64End;
91
92     Trace("Testing Lift/Place/Slide Piece... ");
93     if (FALSE ==  FenToPosition(&pos, 
94                                 "RNBKQBNR/PPPPPPPP/8/8/8/8/pppppppp/rnbkqbnr"
95                                 " w KQkq - 0 1"))
96     {
97         UtilPanic(TESTCASE_FAILURE,
98                   NULL, NULL, NULL, NULL, 
99                   __FILE__, __LINE__);
100     }
101     
102     memset(p, 0, sizeof(p));
103     do
104     {
105         switch(rand() % 3)
106         {
107             case 0:                           // slide piece
108                 cFrom = _TestPickRandomPieceLocation(&pos);
109                 do
110                 {
111                     cTo = RANDOM_COOR;
112                 }
113                 while(!IS_EMPTY(pos.rgSquare[cTo].pPiece));
114
115                 //
116                 // Make sure bishops slide to their color or else
117                 // pos->uWhiteSqBishopCount gets messed up.
118                 //
119                 if (IS_BISHOP(pos.rgSquare[cFrom].pPiece))
120                 {
121                     while ((IS_WHITE_SQUARE_COOR(cTo) !=
122                             IS_WHITE_SQUARE_COOR(cFrom)) ||
123                             (!IS_EMPTY(pos.rgSquare[cTo].pPiece)))
124                     {
125                         cTo = RANDOM_COOR;
126                     }
127                 }
128
129                 //
130                 // Note: a speedup in move.c caused a divorce between
131                 // SlidePiece and SlidePawn and caused the necessity
132                 // of this test.
133                 //
134                 if (IS_PAWN(pos.rgSquare[cFrom].pPiece)) 
135                 {
136                     SlidePawn(&pos, cFrom, cTo);
137                 }
138                 else
139                 {
140                     SlidePiece(&pos, cFrom, cTo);
141                 }
142                 break;
143             
144             case 1:                           // LiftPiece
145                 if (u < 20)
146                 {
147                     do
148                     {
149                         cFrom = _TestPickRandomPieceLocation(&pos);
150                     }
151                     while(IS_KING(pos.rgSquare[cFrom].pPiece));
152                     p[u] = LiftPiece(&pos, cFrom);
153                     u++;
154                 }
155                 break;
156                     
157             case 2:                           // PlacePiece
158                 if (u > 0)
159                 {
160                     u--;
161                     do
162                     {
163                         cTo = RANDOM_COOR;
164                     }
165                     while(!IS_EMPTY(pos.rgSquare[cTo].pPiece));
166                     PlacePiece(&pos, cTo, p[u]);
167                 }
168                 break;
169         }
170         v++;
171     }
172     while(v < NUM_LOOPS);
173     u64End = SystemReadTimeStampCounter();
174
175     printf("\n");
176     printf(" L/P/S bench:    %" COMPILER_LONGLONG_UNSIGNED_FORMAT
177            " cycles/loop.\n",
178            (u64End - u64Start) / (UINT64)NUM_LOOPS);
179 }
180
181
182 void 
183 TestExposesCheck(void)
184 /**
185
186 Routine description:
187
188     Test code.  Tests ExposesCheck.
189
190 Parameters:
191
192     void
193
194 Return value:
195
196     void
197
198 **/
199 {
200     typedef struct _TEST_EXPOSES_CHECK
201     {
202         CHAR *szFen;
203         COOR cFrom;
204         COOR cTo;
205         COOR cRemove;
206     }
207     TEST_EXPOSES_CHECK;
208     
209     ULONG u;
210     POSITION pos;
211     TEST_EXPOSES_CHECK x[] = 
212     {
213         { "k2r4/8/8/3p4/8/8/3K4/8 w - - 0 1",
214           D8, D2, D5 },
215         { "k2q4/8/8/3p4/8/8/3K4/8 w - - 0 1",
216           D8, D2, D5 },
217         { "k5b1/8/8/3p4/8/1K6/8/8 w - - 0 1",
218           G8, B3, D5 },
219         { "k5q1/8/8/3p4/8/1K6/8/8 w - - 0 1",
220           G8, B3, D5 },
221         { "k7/8/8/1K1p2r1/8/8/8/8 w - - 0 1",
222           G5, B5, D5 },
223         { "k7/8/8/1K1p2q1/8/8/8/8 w - - 0 1",
224           G5, B5, D5 },
225         { "k7/8/2K5/3p4/8/8/6b1/8 w - - 0 1",
226           G2, C6, D5 },
227         { "k7/8/2K5/3p4/8/8/6q1/8 w - - 0 1",
228           G2, C6, D5 },
229         { "k7/3K4/8/3p4/8/8/3r4/8 w - - 0 1",
230           D2, D7, D5 },
231         { "k7/3K4/8/3p4/8/8/3q4/8 w - - 0 1",
232           D2, D7, D5 },
233         { "k7/5K2/8/3p4/2b5/8/8/8 w - - 0 1",
234           C4, F7, D5 },
235         { "k7/5K2/8/3p4/2q5/8/8/8 w - - 0 1",
236           C4, F7, D5 },
237         { "k7/8/8/1r1pK3/8/8/8/8 w - - 0 1",
238           B5, E5, D5 },
239         { "k7/8/8/1q1pK3/8/8/8/8 w - - 0 1",
240           B5, E5, D5 },
241         { "k7/8/2b5/3p4/8/5K2/8/8 w - - 0 1",
242           C6, F3, D5 },
243         { "k7/8/2q5/3p4/8/5K2/8/8 w - - 0 1",
244           C6, F3, D5 },
245         //
246         { "8/5k2/8/3N4/8/1B6/8/6K1 w - - 0 1",
247           B3, F7, D5 },
248         { "8/5k2/8/3N4/8/1Q6/8/6K1 w - - 0 1",
249           B3, F7, D5 },
250         { "3k4/8/8/3N4/8/8/8/3R2K1 w - - 0 1",
251           D1, D8, D5 },
252         { "8/3k4/8/3N4/8/8/8/3Q2K1 w - - 0 1",
253           D1, D7, D5 },
254         { "8/8/8/Q2Nk3/8/8/8/6K1 w - - 0 1",
255           A5, E5, D5 },
256         { "8/8/8/R2Nk3/8/8/8/6K1 w - - 0 1",
257           A5, E5, D5 },
258         { "8/1Q6/8/3N4/8/5k2/8/6K1 w - - 0 1",
259           B7, F3, D5 },
260         { "8/1B6/8/3N4/8/5k2/8/6K1 w - - 0 1",
261           B7, F3, D5 },
262         { "8/3R4/8/3N4/8/3k4/8/6K1 w - - 0 1",
263           D7, D3, D5 },
264         { "8/3Q4/8/3N4/8/3k4/8/6K1 w - - 0 1",
265           D7, D3, D5 },
266         { "6Q1/8/8/3N4/8/8/k7/6K1 w - - 0 1",
267           G8, A2, D5 },
268         { "6B1/8/8/3N4/8/8/k7/6K1 w - - 0 1",
269           G8, A2, D5 },
270         { "8/8/8/k2N1R2/8/8/8/6K1 w - - 0 1",
271           F5, A5, D5 },
272         { "8/8/8/k2N1Q2/8/8/8/6K1 w - - 0 1",
273           F5, A5, D5 },
274         { "8/1k6/8/3N4/8/5Q2/8/6K1 w - - 0 1",
275           F3, B7, D5 },
276         { "8/1k6/8/3N4/8/5B2/8/6K1 w - - 0 1",
277           F3, B7, D5 },
278         { "8/5k2/4p3/3N4/8/1Q6/8/6K1 w - - 0 1",
279           0x88, F7, D5 },
280         { "8/5k2/4p3/3N4/8/1B6/8/6K1 w - - 0 1",
281           0x88, F7, D5 },
282         { "8/8/8/1Q1Np1k1/8/8/8/6K1 w - - 0 1",
283           0x88, G5, D5 },
284         { "8/8/8/1R1Np1k1/8/8/8/6K1 w - - 0 1",
285           0x88, G5, D5 },
286         { "8/1B6/8/3N4/4p3/5k2/8/6K1 w - - 0 1",
287           0x88, F3, D5 },
288         { "8/1Q6/8/3N4/4p3/5k2/8/6K1 w - - 0 1",
289           0x88, F3, D5 },
290         { "8/3R4/8/3N4/3p4/3k4/8/6K1 w - - 0 1",
291           0x88, D3, D5 },
292         { "8/3Q4/8/3N4/3p4/3k4/8/6K1 w - - 0 1",
293           0x88, D3, D5 },
294         { "8/5B2/8/3N4/2p5/1k6/8/6K1 w - - 0 1",
295           0x88, B3, D5 },
296         { "8/5Q2/8/3N4/2p5/1k6/8/6K1 w - - 0 1",
297           0x88, B3, D5 },
298         { "8/8/8/1krN1R2/8/8/8/6K1 w - - 0 1",
299           0x88, B5, D5 },
300         { "8/8/8/1krN1Q2/8/8/8/6K1 w - - 0 1",
301           0x88, B5, D5 },
302         { "8/1k6/2r5/3N4/8/5Q2/8/6K1 w - - 0 1",
303           0x88, B7, D5 },
304     };
305
306     Trace("Testing ExposesCheck...\n");
307     for (u = 0; 
308          u < ARRAY_LENGTH(x);
309          u++)
310     {
311         if (FALSE == FenToPosition(&pos, x[u].szFen))
312         {
313             Bug("TestExposesCheck: FEN reader choked on a good FEN.\n");
314             ASSERT(FALSE);
315         }
316         if (x[u].cFrom != ExposesCheck(&pos, x[u].cRemove, x[u].cTo))
317         {
318             Bug("TestExposesCheck: ExposesCheck is broken on position %u!\n",
319                 u);
320             ASSERT(FALSE);
321         }
322     }
323 }
324
325
326 void 
327 TestIsAttacked(void)
328 /**
329
330 Routine description:
331
332     Test code.  Tests IsAttacked (and InCheck).
333
334 Parameters:
335
336     void
337
338 Return value:
339
340     void
341
342 **/
343 {
344     typedef struct _TEST_IS_ATTACKED
345     {
346         CHAR *szFen;
347         ULONG uSide;
348         COOR cSquare;
349         FLAG fAnswer;
350     }
351     TEST_IS_ATTACKED;
352
353     POSITION pos;
354     ULONG u;
355     TEST_IS_ATTACKED x[] = 
356     {
357         { "7k/4n3/3P4/3K4/8/8/8/8 w - - 0 1",
358           BLACK, D5, TRUE },
359         { "7k/8/3Pp3/3K4/8/8/8/8 w - - 0 1",
360           BLACK, D5, TRUE },
361         { "7k/8/2pP4/3K4/8/8/8/8 w - - 0 1",
362           BLACK, D5, TRUE },
363         { "7k/2n5/3P4/3K4/8/8/8/8 w - - 0 1",
364           BLACK, D5, TRUE },
365         { "7k/8/1n1P4/3K4/8/8/8/8 w - - 0 1",
366           BLACK, D5, TRUE },
367         { "7k/8/3P1n2/3K4/8/8/8/8 w - - 0 1",
368           BLACK, D5, TRUE },
369         { "6bk/8/3P4/3K4/8/8/8/8 w - - 0 1",
370           BLACK, D5, TRUE },
371         { "6qk/8/3P4/3K4/8/8/8/8 w - - 0 1",
372           BLACK, D5, TRUE },
373         { "6bk/8/3PN3/3K4/8/8/8/8 w - - 0 1",
374           BLACK, D5, FALSE },
375         { "6bk/8/3Pr3/3K4/8/8/8/8 w - - 0 1",
376           BLACK, D5, FALSE },
377         { "7k/8/3P4/3K3q/8/8/8/8 w - - 0 1",
378           BLACK, D5, TRUE },
379         { "7k/8/3P4/3K3r/8/8/8/8 w - - 0 1",
380           BLACK, D5, TRUE },
381         { "7k/8/3P4/3KQ2q/8/8/8/8 w - - 0 1",
382           BLACK, D5, FALSE },
383         { "7k/8/3P4/3K4/8/8/8/7b w - - 0 1",
384           BLACK, D5, TRUE },
385         { "7k/8/3P4/3K4/8/8/8/7q w - - 0 1",
386           BLACK, D5, TRUE },
387         { "7k/8/3P4/3K4/8/3r4/3q4/3r4 w - - 0 1",
388           BLACK, D5, TRUE },
389         { "7k/8/3P4/3K4/3P4/3r4/3q4/3r4 w - - 0 1",
390           BLACK, D5, FALSE },
391         { "7k/8/3P4/3K4/3p4/3r4/3q4/3r4 w - - 0 1",
392           BLACK, D5, FALSE },
393         { "7k/8/3P4/3K4/3p4/3rn3/3q4/3r4 w - - 0 1",
394           BLACK, D5, TRUE },
395         { "7k/8/3P4/3K4/2b5/1b6/b7/8 w - - 0 1",
396           BLACK, D5, TRUE },
397         { "7k/8/3P4/3K4/2r5/1b6/b7/8 w - - 0 1",
398           BLACK, D5, FALSE },
399         { "K7/8/8/3k4/3p1N2/8/8/8 w - - 0 1",
400           WHITE, D5, TRUE },
401         { "K7/8/8/3k4/3p4/4N3/8/8 w - - 0 1",
402           WHITE, D5, TRUE },
403         { "K7/8/8/3k4/3p4/2N5/8/8 w - - 0 1",
404           WHITE, D5, TRUE },
405         { "K7/8/8/3k4/1N1p4/8/8/8 w - - 0 1", 
406           WHITE, D5, TRUE },
407         { "K7/8/8/3k4/2Pp4/8/8/8 w - - 0 1",
408           WHITE, D5, TRUE },
409         { "K7/8/8/3k4/3pP3/8/8/8 w - - 0 1",
410           WHITE, D5, TRUE },
411         { "K5Q1/5B2/8/3k4/3p4/8/8/8 w - - 0 1",
412           WHITE, D5, TRUE },
413         { "K5Q1/5B2/4R3/3k4/3p4/8/8/8 w - - 0 1",
414           WHITE, D5, FALSE },
415         { "K5Q1/8/8/3k4/3p4/8/8/8 w - - 0 1",
416           WHITE, D5, TRUE },
417         { "K2R4/8/8/3k4/3p4/8/8/8 w - - 0 1",
418           WHITE, D5, TRUE },
419         { "K2R4/3Q4/8/3k4/3p4/8/8/8 w - - 0 1",
420           WHITE, D5, TRUE },
421         { "K2R4/3Q4/3p4/3k4/3p4/8/8/8 w - - 0 1",
422           WHITE, D5, FALSE },
423         { "K2R4/3Q4/3p1N2/3k4/3p4/8/8/8 w - - 0 1",
424           WHITE, D5, TRUE },
425         { "K7/1B6/8/3k4/3p4/8/8/8 w - - 0 1",
426           WHITE, D5, TRUE },
427         { "K7/8/8/Q2k4/3p4/8/8/8 w - - 0 1",
428           WHITE, D5, TRUE },
429         { "K7/8/8/3k4/3p4/8/B7/8 w - - 0 1",
430           WHITE, D5, TRUE }
431     };
432
433     Trace("Testing IsAttacked...\n");
434     for (u = 0;
435          u < ARRAY_SIZE(x);
436          u++)
437     {
438         if (FALSE == FenToPosition(&pos, x[u].szFen))
439         {
440             Bug("TestIsAttacked: FEN reader choked on a good FEN.\n");
441             ASSERT(FALSE);
442         }
443         if (x[u].fAnswer != IsAttacked(x[u].cSquare, &pos, x[u].uSide))
444         {
445             Bug("TestIsAttacked: ExposesCheck is broken on position %u!\n",
446                 u);
447             ASSERT(FALSE);
448         }
449     }
450 }
451
452
453 void 
454 TestMakeUnmakeMove(void)
455 {
456     typedef struct _TEST_MAKE_MOVE
457     {
458         CHAR *szFen;
459         MOVE mv[10];
460         FLAG ok[10];
461     }
462     TEST_MAKE_MOVE;
463
464     ULONG u = 0;
465     ULONG v = 0;
466     SEARCHER_THREAD_CONTEXT *ctx;
467     POSITION p;
468     POSITION *pos = NULL;
469     FLAG fOk;
470     TEST_MAKE_MOVE x[] = 
471     {
472         { 
473             "8/8/8/2k5/4p3/8/2KP4/8 w - - 0 1",
474             { 
475                 { MAKE_MOVE(D2, D4, WHITE_PAWN, 0, 0, MOVE_FLAG_SPECIAL) },
476                 { MAKE_MOVE(E4, D3, BLACK_PAWN, WHITE_PAWN, 0, MOVE_FLAG_SPECIAL | MOVE_FLAG_CHECKING | MOVE_FLAG_ESCAPING_CHECK)},
477                 { MAKE_MOVE(C2, D3, WHITE_KING, BLACK_PAWN, 0, MOVE_FLAG_ESCAPING_CHECK) },
478                 { MAKE_MOVE(0, 0, 0, 0, 0, 0) }
479             },
480             { TRUE, TRUE, TRUE }
481         },
482         { 
483             "5r1k/3KP3/8/8/8/8/8/8 w - - 0 1",
484             { 
485                 { MAKE_MOVE(E7, F8, WHITE_PAWN, BLACK_ROOK, WHITE_QUEEN, MOVE_FLAG_SPECIAL | MOVE_FLAG_CHECKING) }, 
486                 { MAKE_MOVE(H8, G8, BLACK_KING, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
487                 { MAKE_MOVE(H8, H7, BLACK_KING, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
488                 { MAKE_MOVE(0, 0, 0, 0, 0, 0) }
489             },
490             { TRUE, FALSE, TRUE }
491         },
492         { 
493             "8/8/4K3/8/k2p3R/8/4P3/8 w - - 0 1",
494             { 
495                 { MAKE_MOVE(E2, E4, WHITE_PAWN, 0, 0, MOVE_FLAG_SPECIAL) },
496                 { MAKE_MOVE(D4, E3, BLACK_PAWN, WHITE_PAWN, 0, MOVE_FLAG_SPECIAL) },
497                 { MAKE_MOVE(D4, D3, BLACK_PAWN, 0, 0, 0) },
498                 { MAKE_MOVE(E4, E5, WHITE_PAWN, 0, 0, MOVE_FLAG_CHECKING) },
499                 { MAKE_MOVE(D3, D2, BLACK_PAWN, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
500                 { MAKE_MOVE(A4, B4, BLACK_KING, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
501                 { MAKE_MOVE(A4, A3, BLACK_KING, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
502                 { MAKE_MOVE(0, 0, 0, 0, 0, 0) }
503             },
504             { TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE }
505         },
506         { 
507             "3k4/8/6r1/8/8/8/8/R3K2R w KQ - 0 1",
508             { 
509                 { MAKE_MOVE(E1, G1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL) },
510                 { MAKE_MOVE(H1, H2, WHITE_ROOK, 0, 0, 0) },
511                 { MAKE_MOVE(G6, D6, BLACK_ROOK, 0, 0, 0) },
512                 { MAKE_MOVE(E1, C1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL) },
513                 { MAKE_MOVE(H2, H1, WHITE_ROOK, 0, 0, 0) },
514                 { MAKE_MOVE(D6, A6, BLACK_ROOK, 0, 0, 0) },
515                 { MAKE_MOVE(E1, G1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL) },
516                 { MAKE_MOVE(E1, C1, WHITE_KING, 0, 0, MOVE_FLAG_SPECIAL | MOVE_FLAG_CHECKING) },
517                 { MAKE_MOVE(A6, D6, BLACK_ROOK, 0, 0, MOVE_FLAG_ESCAPING_CHECK) },
518                 { MAKE_MOVE(0, 0, 0, 0, 0, 0) }
519             },
520             { FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE }
521         }
522     };
523
524     //
525     // Setup
526     //
527     ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
528     ASSERT(ctx);
529     pos = SystemAllocateMemory(sizeof(POSITION) * 10);
530     ASSERT(ctx);
531
532     for (u = 0; u < ARRAY_LENGTH(x); u++)
533     {
534         if (FALSE == FenToPosition(&p, x[u].szFen))
535         {
536             UtilPanic(INCONSISTENT_STATE,
537                       NULL, NULL, NULL, NULL,
538                       __FILE__, __LINE__);
539         }
540         InitializeSearcherContext(&p, ctx);
541         
542         for (v = 0; v < ARRAY_LENGTH(x[u].mv); v++)
543         {
544             if (x[u].mv[v].uMove == 0) break;
545             memcpy(&(pos[v]), &(ctx->sPosition), sizeof(POSITION));
546             
547             fOk = MakeUserMove(ctx, x[u].mv[v]);
548             if (fOk != x[u].ok[v]) 
549             {
550                 UtilPanic(TESTCASE_FAILURE,
551                           NULL, "MakeUserMove", NULL, NULL,
552                           __FILE__, __LINE__);
553             }
554             if (fOk)
555             {
556                 UnmakeMove(ctx, x[u].mv[v]);
557                 if (FALSE == PositionsAreEquivalent(&(ctx->sPosition),
558                                                     &(pos[v])))
559                 {
560                     UtilPanic(TESTCASE_FAILURE,
561                               NULL, "MakeMove / UnmakeMove", NULL, NULL,
562                               __FILE__, __LINE__);
563                 }
564                 fOk = MakeUserMove(ctx, x[u].mv[v]);
565                 ASSERT(fOk);
566             }
567         }
568     }
569     SystemFreeMemory(ctx);
570     SystemFreeMemory(pos);
571 }
572 #endif