Update codebase to remove clang warnings (and a couple of legit errors
[typhoon.git] / src / testgenerate.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]) 12 May 2004
16
17 Revision History:
18
19     $Id: testgenerate.c 345 2007-12-02 22:56:42Z scott $
20
21 **/
22
23 #ifdef TEST
24 #include "chess.h"
25
26 UINT64 g_uPlyTestLeafNodeCount = 0;
27 UINT64 g_uPlyTestTotalNodeCount = 0;
28
29 extern CHAR *GenerateRandomLegalFenString();
30
31 void 
32 PlyTest(SEARCHER_THREAD_CONTEXT *ctx,
33         ULONG uDepth,
34         FLAG fInCheck)
35 {
36     ULONG u;
37     MOVE mv;
38     ULONG uPly = ctx->uPly;
39     ULONG uLegalMoves = 0;
40     FLAG fGivesCheck;
41 #if DEBUG
42     POSITION board;
43     memcpy(&board, &(ctx->sPosition), sizeof(POSITION));
44 #endif
45     
46     if (uDepth > MAX_PLY_PER_SEARCH) 
47     {
48         return;
49     }
50     else if (uDepth == 0)
51     {
52         g_uPlyTestTotalNodeCount++;
53         g_uPlyTestLeafNodeCount++;
54         return;
55     }
56     g_uPlyTestTotalNodeCount++;
57
58     mv.uMove = 0;
59     GenerateMoves(ctx, mv, (fInCheck ? GENERATE_ESCAPES : GENERATE_ALL_MOVES));
60     for (u = ctx->sMoveStack.uBegin[uPly];
61          u < ctx->sMoveStack.uEnd[uPly];
62          u++)
63     {
64         mv = ctx->sMoveStack.mvf[u].mv;
65         mv.bvFlags |= WouldGiveCheck(ctx, mv);
66         
67         if (MakeMove(ctx, mv))
68         {
69             uLegalMoves++;
70             ASSERT(!InCheck(&ctx->sPosition, GET_COLOR(mv.pMoved)));
71             fGivesCheck = IS_CHECKING_MOVE(mv);
72 #ifdef DEBUG
73             if (fGivesCheck)
74             {
75                 ASSERT(InCheck(&ctx->sPosition, FLIP(GET_COLOR(mv.pMoved))));
76             }
77             else
78             {
79                 ASSERT(!InCheck(&ctx->sPosition, FLIP(GET_COLOR(mv.pMoved))));
80             }
81 #endif
82             PlyTest(ctx, uDepth - 1, fGivesCheck);
83             UnmakeMove(ctx, mv);
84             ASSERT(PositionsAreEquivalent(&board, &ctx->sPosition));
85         }
86     }
87 }
88
89
90 void 
91 TestMoveGenerator(void)
92 {
93     typedef struct _TEST_MOVEGEN
94     {
95         char *szFen;
96         UINT64 uLeaves[7];
97     }
98     TEST_MOVEGEN;
99     
100     TEST_MOVEGEN x[] = 
101     {
102      {
103       "3Q4/1Q4Q1/4Q3/2Q4R/Q4Q2/3Q4/1Q4Rp/1K1BBNNk w - - 0 1",
104       { 218, 0, 0, 0, 0, 0, 0 }
105      },
106      {
107       "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - - 0 0",
108       { 48, 2039, 97862, 4085603, 193690690ULL, 8031647685ULL }
109      },
110      {
111       "8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 0",
112       { 18, 290, 5044, 89363, 1745545, 34336777ULL, 749660761ULL }
113      },
114      { 
115       "8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 0",
116       { 14, 191, 2812, 43238, 674624, 11030083ULL, 78633661ULL }
117      },
118      {
119       "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w - - 0 0",
120       { 20, 400, 8902, 197281, 4865609, 119060324ULL, 3195901860ULL }
121      },
122     };
123     ULONG u, v;
124     
125     SEARCHER_THREAD_CONTEXT *ctx;
126     POSITION pos;
127
128     Trace("Testing move generator...\n");
129     ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
130     ASSERT(ctx);
131     for (u = 0; u < ARRAY_LENGTH(x); u++)
132     {
133         if (FALSE == FenToPosition(&pos, x[u].szFen)) 
134         {
135             UtilPanic(INCONSISTENT_STATE,
136                       NULL, NULL, NULL, NULL,
137                       __FILE__, __LINE__);
138         }
139         InitializeSearcherContext(&pos, ctx);
140
141         for (v = 1; v <= 4; v++)
142         {
143             g_uPlyTestLeafNodeCount = 0;
144             g_uPlyTestTotalNodeCount = 0;
145             PlyTest(ctx, v, FALSE);
146             
147             if ((x[u].uLeaves[v-1]) &&
148                 (g_uPlyTestLeafNodeCount != x[u].uLeaves[v-1]))
149             {
150                 UtilPanic(TESTCASE_FAILURE,
151                           NULL, "Perft", NULL, NULL,
152                           __FILE__, __LINE__);
153             }
154         }
155     }
156     SystemFreeMemory(ctx);
157 }
158
159
160 void
161 TestLegalMoveGenerator(void)
162 {
163     ULONG u, v;
164     CHAR *p;
165     POSITION pos;
166     SEARCHER_THREAD_CONTEXT *ctx;
167     MOVE mv;
168     ULONG uLegalKingMoves;
169     ULONG uTotalLegalMoves;
170     ULONG uGen;
171
172     Trace("Testing legal move generator...\n");
173     ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
174     ASSERT(ctx);
175     u = 0;
176     do
177     {
178         switch(rand() % 10) 
179         {
180             case 0:
181                 p = "8/2K1p2k/1Q2B1p1/2N5/q4q2/3p2Pp/7P/8 w  - - 2 0";
182                 break;
183             default:
184                 p = GenerateRandomLegalFenString();
185                 break;
186         }
187
188         if (FALSE == FenToPosition(&pos, p))
189         {
190             UtilPanic(TESTCASE_FAILURE,
191                       NULL, "FenToPosition", NULL, NULL,
192                       __FILE__, __LINE__);
193         }
194         
195         if (FALSE == IsBoardLegal(&pos))
196         {
197             continue;
198         }
199
200         if (TRUE == InCheck(&pos, pos.uToMove))
201         {
202             uLegalKingMoves = uTotalLegalMoves = 0;
203             InitializeSearcherContext(&pos, ctx);
204             
205             mv.uMove = 0;
206             GenerateMoves(ctx, mv, GENERATE_ESCAPES);
207             for (v = ctx->sMoveStack.uBegin[0]; 
208                  v < ctx->sMoveStack.uEnd[0];
209                  v++)
210             {
211                 mv = ctx->sMoveStack.mvf[v].mv;
212                 ASSERT(mv.bvFlags & MOVE_FLAG_ESCAPING_CHECK);
213                 if (TRUE == MakeMove(ctx, mv))
214                 {
215                     uTotalLegalMoves++;
216                     if (IS_KING(mv.pMoved))
217                     {
218                         uLegalKingMoves++;
219                     }
220                     UnmakeMove(ctx, mv);
221                 }
222                 else
223                 {
224                     ctx->sMoveStack.mvf[v].mv.uMove = 0;
225                 }
226             }
227
228             ASSERT(NUM_KING_MOVES(ctx, ctx->uPly) == uLegalKingMoves);
229             if (uTotalLegalMoves > 1) 
230             {
231                 ASSERT(!ONE_LEGAL_MOVE(ctx, ctx->uPly));
232             }
233             else if (uTotalLegalMoves == 1) 
234             {
235                 ASSERT(ONE_LEGAL_MOVE(ctx, ctx->uPly));
236             }
237             u++;
238         }
239     }
240     while(u < 1000);
241     SystemFreeMemory(ctx);
242 }
243 #endif