Update codebase to remove clang warnings (and a couple of legit errors
[typhoon.git] / src / testsee.c
1 /**
2
3 Copyright (c) Scott Gasch
4
5 Module Name:
6
7     testsee.c
8
9 Abstract:
10
11     This code is meant to sanity check the SEE routine.  It works by
12     using the generator and MakeMove/UnmakeMove to play out a sequence
13     of moves on a single square.  It's somewhat useful code but right
14     now I don't really use it because it is too good: it detects
15     things like pieces that are pinned against the king whereas the
16     SEE itself does not.  Still, I'd want to run it and verify the
17     discrepencies if I was doing much work in the SEE code.
18
19 Author:
20
21     Scott Gasch ([email protected]) 21 Oct 2004
22
23 Revision History:
24
25 **/
26
27 #include "chess.h"
28
29 #ifdef TEST_BROKEN
30 ULONG g_uRootOnMove;
31
32 SCORE
33 DebugSEERecursive(SEARCHER_THREAD_CONTEXT *ctx,
34                   MOVE mv)
35 {
36     SCORE i, iMinMax;
37     ULONG x;
38     MOVE mvReply;
39     ULONG uToMove = ctx->sPosition.uToMove;
40
41     //
42     // Make the move, this is not optional
43     //
44     ASSERT(GET_COLOR(mv.pMoved) == uToMove);
45     if (FALSE == MakeMove(ctx, mv))
46     {
47         return(INVALID_SCORE);
48     }
49
50     //
51     // Initialize MinMax to the stand pat score here so that the reply
52     // can be "something else".
53     //
54     iMinMax = ((ctx->sPosition.uPawnMaterial[g_uRootOnMove] +
55                 ctx->sPosition.uNonPawnMaterial[g_uRootOnMove]) -
56                (ctx->sPosition.uPawnMaterial[FLIP(g_uRootOnMove)] +
57                 ctx->sPosition.uNonPawnMaterial[FLIP(g_uRootOnMove)]));
58
59     //
60     // Generate the reply moves.
61     //
62     GenerateMoves(ctx, (MOVE){0}, GENERATE_DONT_SCORE);
63     for (x = ctx->sMoveStack.uBegin[ctx->uPly];
64          x < ctx->sMoveStack.uEnd[ctx->uPly];
65          x++)
66     {
67         //
68         // Only consider replies that end up on the same sq as the
69         // move.
70         //
71         mvReply = ctx->sMoveStack.mvf[x].mv;
72         ASSERT(SanityCheckMove(&ctx->sPosition, mvReply));
73         if (mvReply.cTo != mv.cTo)
74         {
75             continue;
76         }
77         
78         i = DebugSEERecursive(ctx, mvReply);
79         if (INVALID_SCORE != i)
80         {
81             if ((ctx->uPly % 2) == 0)
82             {
83                 if (i > iMinMax) iMinMax = i;
84             }
85             else
86             {
87                 if (i < iMinMax) iMinMax = i;
88             }
89         }
90     }
91
92     //
93     // Unmake the original move
94     //
95     UnmakeMove(ctx, mv);
96     return(iMinMax);
97 }
98
99     
100 SCORE
101 DebugSEE(POSITION *pos,
102          MOVE mv)
103 {
104     SCORE iRootBalance = ((pos->uPawnMaterial[pos->uToMove] +
105                            pos->uNonPawnMaterial[pos->uToMove]) -
106                           (pos->uPawnMaterial[FLIP(pos->uToMove)] +
107                            pos->uNonPawnMaterial[FLIP(pos->uToMove)]));
108     SCORE iAfterExchange = iRootBalance;
109     SEARCHER_THREAD_CONTEXT *ctx = 
110         malloc(sizeof(SEARCHER_THREAD_CONTEXT));
111
112     g_uRootOnMove = pos->uToMove;
113     if (NULL != ctx)
114     {
115         pos->uDangerCount[BLACK] = pos->uDangerCount[WHITE] = 0;
116         InitializeSearcherContext(pos, ctx);
117         
118         GenerateMoves(ctx, (MOVE){0}, GENERATE_DONT_SCORE);
119         mv.bvFlags |= WouldGiveCheck(ctx, mv);
120         if (InCheck(pos, pos->uToMove))
121         {
122             mv.bvFlags |= MOVE_FLAG_ESCAPING_CHECK;
123         }
124
125         iAfterExchange = DebugSEERecursive(ctx, mv);
126         if (iAfterExchange != INVALID_SCORE)
127         {
128             iAfterExchange -= iRootBalance;
129         }
130         free(ctx);
131     }
132     return(iAfterExchange);
133 }
134 #endif
135
136 #ifdef TEST
137 FLAG 
138 SeeListsAreEqual(SEE_LIST *pA, SEE_LIST *pB)
139 {
140     ULONG u;
141     if (pA->uCount != pB->uCount) return FALSE;
142     for (u = 0; u < pA->uCount; u++) 
143     {
144         if ((pA->data[u].pPiece != pB->data[u].pPiece) ||
145             (pA->data[u].cLoc != pB->data[u].cLoc) ||
146             (pA->data[u].uVal != pB->data[u].uVal)) 
147         {
148             return FALSE;
149         }
150     }
151     return TRUE;
152 }
153
154 void
155 TestGetAttacks(void) 
156 {
157     POSITION pos;
158     ULONG u;
159     COOR c;
160     SEE_LIST rgSlowList;
161     SEE_LIST rgAsmList;
162     ULONG color;
163     
164 #ifndef _X86_
165     return;
166 #endif
167     
168     Trace("Testing GetAttacks...\n");
169     for (u = 0; u < 20000; u++)
170     {
171         GenerateRandomLegalPosition(&pos);
172         FOREACH_SQUARE(c) 
173         {
174             if (!IS_ON_BOARD(c)) continue;
175             for (color = BLACK; color <= WHITE; color++) 
176             {
177                 SlowGetAttacks(&rgSlowList,
178                                &pos,
179                                c,
180                                color);
181                 GetAttacks(&rgAsmList,
182                            &pos,
183                            c,
184                            color);
185                 if (!SeeListsAreEqual(&rgSlowList, &rgAsmList))
186                 {
187                     UtilPanic(TESTCASE_FAILURE,
188                               &pos, 
189                               "SEE_LIST mismatch", &rgSlowList, &rgAsmList,
190                               __FILE__, __LINE__);
191                 }
192             }
193         }
194     }
195 }
196 #endif // TEST