Update codebase to remove clang warnings (and a couple of legit errors
[typhoon.git] / src / testeval.c
1 /**
2
3 Copyright (c) Scott Gasch
4
5 Module Name:
6
7     testeval.c
8
9 Abstract:
10
11     An eval term storage and dumping mechanism.  Also code to sanity
12     check the evaluator routines.
13
14 Author:
15
16     Scott Gasch ([email protected]) 18 Jun 2004
17
18 Revision History:
19
20     $Id: testeval.c 345 2007-12-02 22:56:42Z scott $
21
22 **/
23 #ifdef EVAL_DUMP
24
25 #include "chess.h"
26
27 typedef struct _EVALTERM
28 {
29     CHAR szMessage[SMALL_STRING_LEN_CHAR];
30     COOR cLoc;
31     SCORE iVal;
32     DLIST_ENTRY links;
33 }
34 EVALTERM;
35
36 static EVALTERM g_EvalData[2][8][32];
37 static ULONG g_EvalCounts[2][8];
38
39 void 
40 EvalTraceClear(void)
41 /**
42
43 Routine description:
44
45 Parameters:
46
47     void
48
49 Return value:
50
51     void
52
53 **/
54 {
55     memset(g_EvalData, 0, sizeof(g_EvalData));
56     memset(g_EvalCounts, 0, sizeof(g_EvalCounts));
57 }
58
59 void 
60 EvalTrace(IN ULONG uColor, 
61           IN PIECE p,
62           IN COOR c,
63           IN SCORE iVal,
64           IN CHAR *szMessage)
65 /**
66
67 Routine description:
68
69     Add a term to the current positions evaluation trace database.
70
71 Parameters:
72
73     IN ULONG uColor,
74     IN PIECE p,
75     IN COOR c,
76     IN SCORE iVal,
77     IN CHAR *szMessage
78
79 Return value:
80
81     void
82
83 **/
84 {
85     if ((iVal == 0) && (c != ILLEGAL_COOR)) return;
86
87     ASSERT(p <= 7);
88     ASSERT(iVal < +2000);
89     ASSERT(iVal > -2000);
90
91     //
92     // Note: The square control code in eval does this to avoid an if.
93     // Just ignore anything that is passed to us that is not BLACK or
94     // WHITE.
95     //
96     if (!IS_VALID_COLOR(uColor))
97     {
98         return;
99     }
100     g_EvalData[uColor][p][g_EvalCounts[uColor][p]].cLoc = c;
101     g_EvalData[uColor][p][g_EvalCounts[uColor][p]].iVal = iVal;
102     strncpy(g_EvalData[uColor][p][g_EvalCounts[uColor][p]].szMessage,
103             szMessage, 
104             SMALL_STRING_LEN_CHAR);
105     g_EvalCounts[uColor][p]++;
106 }
107
108
109 SCORE 
110 EvalSigmaForPiece(IN POSITION *pos, IN COOR c)
111 /**
112
113 Routine description:
114
115 Parameters:
116
117     IN POSITION *pos,
118     IN COOR c
119
120 Return value:
121
122     SCORE
123
124 **/
125 {
126     SCORE iSum[2] = {0, 0};
127     ULONG uColor;
128     ULONG u, v;
129     
130     FOREACH_COLOR(uColor)
131     {
132         for (u = 0; u < 8; u++)
133         {
134             for (v = 0; v < g_EvalCounts[uColor][u]; v++)
135             {
136                 if (g_EvalData[uColor][u][v].cLoc == c)
137                 {
138                     Trace("%s %-30s%-3s%4d\n",
139                           (uColor == WHITE) ? "white" : "black",
140                           g_EvalData[uColor][u][v].szMessage,
141                           CoorToString(g_EvalData[uColor][u][v].cLoc),
142                           g_EvalData[uColor][u][v].iVal);
143                     iSum[uColor] += g_EvalData[uColor][u][v].iVal;
144                 }
145             }
146         }
147     }
148     Trace("Totals are BLACK: %d, WHITE: %d.\n", iSum[BLACK], iSum[WHITE]);
149     
150     if (IS_ON_BOARD(c))
151     {
152         if (pos->rgSquare[c].pPiece)
153         {
154             return(iSum[GET_COLOR(pos->rgSquare[c].pPiece)]);
155         }
156     }
157     return(0);
158 }
159
160
161 void 
162 EvalTraceReport(void)
163 /**
164
165 Routine description:
166
167 Parameters:
168
169     void
170
171 Return value:
172
173     void
174
175 **/
176 {
177     PIECE p;
178     ULONG uWhitePtr, uBlackPtr;
179     CHAR szLine[SMALL_STRING_LEN_CHAR];
180     SCORE iPieceTotal[2];
181     
182     Trace(
183 "--- WHITE -------------------LOC--VAL---- BLACK --------------------LOC--VAL-\n"
184         );
185
186     for (p = 0; 
187          p < 8;
188          p++)
189     {
190         if ((g_EvalCounts[WHITE][p] + g_EvalCounts[BLACK][p]) == 0)
191         {
192             continue;
193         }
194
195         Trace("\n");
196         iPieceTotal[WHITE] = iPieceTotal[BLACK] = 0;
197
198         Trace("%s:\n---------------\n", g_PieceData[p].szName);
199
200         for (uWhitePtr = 0, uBlackPtr = 0; 
201              ((uWhitePtr < g_EvalCounts[WHITE][p]) ||
202               (uBlackPtr < g_EvalCounts[BLACK][p]));
203              uWhitePtr++, uBlackPtr++)
204         {
205             memset(szLine, 0, sizeof(szLine));
206             
207             if (uWhitePtr < g_EvalCounts[WHITE][p])
208             {
209                 sprintf(szLine, "%-30s%-3s%4d",
210                         g_EvalData[WHITE][p][uWhitePtr].szMessage,
211                         CoorToString(g_EvalData[WHITE][p][uWhitePtr].cLoc),
212                         g_EvalData[WHITE][p][uWhitePtr].iVal);
213                 iPieceTotal[WHITE] += 
214                     g_EvalData[WHITE][p][uWhitePtr].iVal;
215             }
216             else
217             {
218                 sprintf(szLine, "                                     ");
219             }
220             
221             if (uBlackPtr < g_EvalCounts[BLACK][p])
222             {
223                 sprintf(szLine, "%s  %-30s%-3s%4d",
224                         szLine,
225                         g_EvalData[BLACK][p][uBlackPtr].szMessage,
226                         CoorToString(g_EvalData[BLACK][p][uBlackPtr].cLoc),
227                         g_EvalData[BLACK][p][uBlackPtr].iVal);
228                 iPieceTotal[BLACK] += 
229                     g_EvalData[BLACK][p][uBlackPtr].iVal;
230             }
231             strcat(szLine, "\n");
232             Trace(szLine);
233         }
234
235         if ((iPieceTotal[WHITE] != 0) || (iPieceTotal[BLACK] != 0))
236         {
237             Trace("       TOTAL WHITE . . . . . . . %4d"
238                   "         TOTAL BLACK . . . . . . . %4d\n", 
239                   iPieceTotal[WHITE], iPieceTotal[BLACK]);
240         }
241     }
242 }         
243
244     
245 void 
246 TestEvalWithSymmetry(void)
247 /**
248
249 Routine description:
250
251 Parameters:
252
253     void
254
255 Return value:
256
257     void
258
259 **/
260 {
261     SEARCHER_THREAD_CONTEXT *ctx = malloc(sizeof(SEARCHER_THREAD_CONTEXT));
262     POSITION pos;
263     SCORE i;
264     
265     GenerateRandomLegalSymetricPosition(&pos);
266     InitializeSearcherContext(&pos, ctx);
267         
268     i = Eval(ctx, -INFINITY, INFINITY);
269     if (i != 0)
270     {
271         DumpPosition(&ctx->sPosition);
272         Trace(">>>> ");
273     }
274     Trace("Eval: %s\n", ScoreToString(i));
275     free(ctx);
276 }
277
278 typedef struct _EVAL_TEST
279 {
280     CHAR *szFen;
281     CHAR *szFeature[5];
282 } EVAL_TEST;
283
284 void 
285 TestEvalWithKnownPositions(void)
286 /**
287
288 Routine description:
289
290 Parameters:
291
292     void
293
294 Return value:
295
296     void
297
298 **/
299 {
300     static const EVAL_TEST x[] =
301     {
302         {
303             // htryc pg 388
304             "r1br2k1/pp2pp1p/6p1/3P4/4P3/8/P2KBPPP/1R5R w - - 0 1",
305             { "w>b", NULL, NULL, NULL, NULL }
306         },
307         {
308             // trryc pg 389
309             "r1r3k1/p2qpp1p/np1p2p1/3P4/PP1QP3/4BP2/6PP/2RR2K1 w - - 0 1",
310             { "w>b", "E3>A6", NULL, NULL, NULL }
311         },
312         {
313             // htryc pg 180
314             "2r1b1k1/1qr2p2/p1p1p1p1/2R4p/1P5P/P1R1PBP1/5P2/2Q3K1 w - - 0 1",
315             { "w>b", "F3>E8", NULL, NULL, NULL }
316         },
317         {
318             // htryc pg 209
319             "8/4b3/pp2kppp/2p1p3/P1K1P1PP/1PP1NP2/8/8 w - - 0 1",
320             { "w>b", "E3>E7", NULL, NULL, NULL }
321         },
322         {
323             // htryc pg 227
324             "1q1rrbk1/1p3p1p/p2p2p1/3Pp3/1P2P3/P3BP2/3Q2PP/R2R2K1 w - - 0 1",
325             { "w>b", "E3>F8", NULL, NULL, NULL }
326         },
327         {
328             // htryc 117
329             "4r2k/4qp1p/p4p2/2b2P2/2p5/3brRP1/PP1Q2BP/3R2NK w - - 0 1",
330             { "b>w", NULL, NULL, NULL, NULL }
331         },
332         {
333             // htryc 161b
334             "r2r2k1/pbq3bp/1p4p1/4n3/3BP1Q1/2P3NP/P7/1B1R1RK1 b - - 0 1",
335             { "b>w", "B7>B1", "e5>g3", NULL, NULL }
336         },
337         {
338             // htryc 161
339             "r2r2k1/pb1q2bp/1p2p1p1/n1p2p2/3PPPP1/2PBB1NP/P7/2R1QRK1 b - - 0 1",
340             { "b>w", NULL, NULL, NULL, NULL }
341         },
342         {
343             // htryc pg 136
344             "6rr/1pqbkn1p/1Pp1p1pP/2Pp1pP1/3P1P2/Q2BPN2/5K1R/7R b - - 0 1",
345             { "w>b", "F3>D7", "d3>d7", NULL, NULL }
346         },
347         {   
348             // htryc pg 133
349             "r4rk1/pp1bqn1p/2p1pnp1/3pNp2/2PP1P2/3BP3/PPQN2PP/1R3RK1 b - - 0 1",
350             { "w>b", "E5>D7", "d2>d7", "d3>d7", NULL }
351         },
352         {
353             // ppic pg 7
354             "6k1/5ppp/8/P7/2p5/8/5PPP/6K1 w - - 0 1",
355             { "w>b", NULL, NULL, NULL, NULL }
356         },
357         {
358             // htryc pg 120
359             "r4rk1/pp3ppp/5n2/2pPp3/2P1B2n/P3PP2/5P1P/R1B2RK1 b - - 0 1",
360             { "b>w", "H4>E4", "h4>c1", "f6>c1", NULL }
361         },
362         {
363             // htryc pg 111
364             "8/1p6/npn2k2/3p3p/P2P1B2/2K5/7P/1B6 b - - 0 1",
365             { "w>b", NULL, NULL, NULL, NULL }
366         },
367         {
368             // htryc pg 98
369             "4r1k1/1p1rq1pp/2p1p3/p1P1Ppb1/P2P4/1PNR1QP1/6KP/3R4 b - - 0 1",
370             { "g5>c3", NULL, NULL, NULL, NULL }
371         },
372         {
373             "4rqk1/1pbr2pp/2pNp3/p1P1Pp2/P2P4/1P1R1QP1/6KP/3R4 b - - 0 1",
374             { "w>b", "D6>C7", NULL, NULL, NULL }
375         },
376         {
377             // htryc pg 96
378             "r2q1rk1/pb3ppp/1p6/3p4/3N4/1Q6/PP2RPPP/R5K1 b - - 0 1",
379             { "d4>b7", NULL, NULL, NULL, NULL }
380         },
381         {
382             // htryc pg 96
383             "r2q1rk1/pb2nppp/1p2p3/8/3P4/1QN2N2/PP2RPPP/R5K1 b - - 0 1",
384             { "b7>c3", "B7>F3", NULL, NULL, NULL }
385         },
386         {
387             // htryc pg 95
388             "r3r1k1/pp3ppp/3p1b2/3NpP2/2q1P3/8/PPP3PP/R3QRK1 w - - 0 1",
389             { "d5>f6", "w>b", NULL, NULL, NULL }
390         },
391         {
392             // htryc pg 95
393             "2rbr1k1/p4ppp/3p4/1pqNpP2/4P3/1PP2R2/P5PP/R3Q2K b - - 0 1",
394             { "w>b", NULL, NULL, NULL, NULL }
395         },
396         {
397             //
398             "2br2k1/5pp1/1p3q1p/2pBpP2/2P1P3/P6P/2Q3P1/5RK1 w - - 0 1",
399             { "d5>c8", NULL, NULL, NULL, NULL }
400         },
401         {
402             // htryc pg 59a
403             "k5B1/n7/7P/2p5/1p4P1/p7/7K/8 w - - 0 1",
404             { "g8>a7", NULL, NULL, NULL, NULL }
405         },
406         {
407             // htryc pg 59b
408             "2br2k1/5pp1/1p3q1p/2p1pP2/2P1P3/P2B3P/2Q3P1/5RK1 w - - 0 1",
409             { "b>w", "c8>d3", NULL, NULL, NULL }
410         },
411     };
412
413     ULONG u, v;
414     SEARCHER_THREAD_CONTEXT ctx;
415     CHAR *p;
416     COOR c1, c2;
417     SCORE i, w, b, i1st, i2nd;
418     CHAR cRelationship;
419     
420     Trace("Testing static eval code...\n");
421     for (u = 0;
422          u < ARRAY_LENGTH(x);
423          u++)
424     {
425         ctx.uPositional = 0;
426         if (FALSE == FenToPosition(&(ctx.sPosition), x[u].szFen))
427         {
428             UtilPanic(INCONSISTENT_STATE,
429                       NULL, NULL, NULL, NULL,
430                       __FILE__, __LINE__);
431         }
432         
433         i = Eval(&ctx, -INFINITY, +INFINITY);
434         Trace("Position %u: SCORE %d for side to move.\n", u, i);
435         if (ctx.sPosition.uToMove == WHITE)
436         {
437             w = i;
438             b = -i;
439         }
440         else
441         {
442             b = i;
443             w = -i;
444         }
445         
446         for (v = 0;
447              v < ARRAY_LENGTH(x[u].szFeature);
448              v++)
449         {
450             p = x[u].szFeature[v];
451             if (p != NULL)
452             {
453                 Trace("Testing feature \"%s\"\n", p);
454                 
455                 cRelationship = '=';
456                 i1st = INVALID_SCORE;
457                 i2nd = INVALID_SCORE;
458                 c1 = ILLEGAL_COOR;
459                 c2 = ILLEGAL_COOR;
460                 
461                 while(*p)
462                 {
463                     if (LooksLikeCoor(p))
464                     {
465                         if (IS_ON_BOARD(c1))
466                         {
467                             c2 = FILE_RANK_TO_COOR((tolower(p[0]) - 'a'),
468                                                    (tolower(p[1]) - '0'));
469                             if (INVALID_SCORE == i1st)
470                             {
471                                 i1st = EvalSigmaForPiece(&(ctx.sPosition), c2);
472                             }
473                             else
474                             {
475                                 i2nd = EvalSigmaForPiece(&(ctx.sPosition), c2);
476                             }
477                             p += 2;
478                         }
479                         else
480                         {
481                             c1 = FILE_RANK_TO_COOR((tolower(p[0]) - 'a'),
482                                                    (tolower(p[1]) - '0'));
483                             if (INVALID_SCORE == i1st)
484                             {
485                                 i1st = EvalSigmaForPiece(&(ctx.sPosition), c1);
486                             }
487                             else
488                             {
489                                 i2nd = EvalSigmaForPiece(&(ctx.sPosition), c1);
490                             }
491                             p += 2;
492                         }
493                     }
494                     else
495                     {
496                         switch(*p)
497                         {
498                             case 'w':
499                                 if (INVALID_SCORE == i1st)
500                                 {
501                                     i1st = w;
502                                 }
503                                 else
504                                 {
505                                     i2nd = w;
506                                 }
507                                 break;
508                             case 'b':
509                                 if (INVALID_SCORE == i1st)
510                                 {
511                                     i1st = b;
512                                 }
513                                 else
514                                 {
515                                     i2nd = b;
516                                 }
517                                 break;
518                             case '<':
519                                 cRelationship = '<';
520                                 break;
521                             case '>':
522                                 cRelationship = '>';
523                                 break;
524                             default:
525                                 break;
526                         }
527                         p++;
528                     }
529                 }
530             
531                 switch(cRelationship)
532                 {
533                     case '<':
534                         if (i1st >= i2nd)
535                         {
536                             Trace("%s NOT TRUE.\n", x[u].szFeature[v]);
537                             EvalTraceReport();
538                             DumpPosition(&(ctx.sPosition));
539                             BREAKPOINT;
540                         }
541                         break;
542                     case '>':
543                         if (i2nd >= i1st)
544                         {
545                             Trace("%s NOT TRUE.\n", x[u].szFeature[v]);
546                             EvalTraceReport();
547                             DumpPosition(&(ctx.sPosition));
548                             BREAKPOINT;
549                         }
550                         break;
551                     default:
552                         Trace("Unknown cRelationship.\n");
553                         break;
554                 }
555             }
556             
557         } // v
558         
559     } // u
560 }
561 #endif