3 Copyright (c) Scott Gasch
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.
33 DebugSEERecursive(SEARCHER_THREAD_CONTEXT *ctx,
39 ULONG uToMove = ctx->sPosition.uToMove;
42 // Make the move, this is not optional
44 ASSERT(GET_COLOR(mv.pMoved) == uToMove);
45 if (FALSE == MakeMove(ctx, mv))
47 return(INVALID_SCORE);
51 // Initialize MinMax to the stand pat score here so that the reply
52 // can be "something else".
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)]));
60 // Generate the reply moves.
62 GenerateMoves(ctx, (MOVE){0}, GENERATE_DONT_SCORE);
63 for (x = ctx->sMoveStack.uBegin[ctx->uPly];
64 x < ctx->sMoveStack.uEnd[ctx->uPly];
68 // Only consider replies that end up on the same sq as the
71 mvReply = ctx->sMoveStack.mvf[x].mv;
72 ASSERT(SanityCheckMove(&ctx->sPosition, mvReply));
73 if (mvReply.cTo != mv.cTo)
78 i = DebugSEERecursive(ctx, mvReply);
79 if (INVALID_SCORE != i)
81 if ((ctx->uPly % 2) == 0)
83 if (i > iMinMax) iMinMax = i;
87 if (i < iMinMax) iMinMax = i;
93 // Unmake the original move
101 DebugSEE(POSITION *pos,
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));
112 g_uRootOnMove = pos->uToMove;
115 pos->uDangerCount[BLACK] = pos->uDangerCount[WHITE] = 0;
116 InitializeSearcherContext(pos, ctx);
118 GenerateMoves(ctx, (MOVE){0}, GENERATE_DONT_SCORE);
119 mv.bvFlags |= WouldGiveCheck(ctx, mv);
120 if (InCheck(pos, pos->uToMove))
122 mv.bvFlags |= MOVE_FLAG_ESCAPING_CHECK;
125 iAfterExchange = DebugSEERecursive(ctx, mv);
126 if (iAfterExchange != INVALID_SCORE)
128 iAfterExchange -= iRootBalance;
132 return(iAfterExchange);
138 SeeListsAreEqual(SEE_LIST *pA, SEE_LIST *pB)
141 if (pA->uCount != pB->uCount) return FALSE;
142 for (u = 0; u < pA->uCount; u++)
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))
168 Trace("Testing GetAttacks...\n");
169 for (u = 0; u < 20000; u++)
171 GenerateRandomLegalPosition(&pos);
174 if (!IS_ON_BOARD(c)) continue;
175 for (color = BLACK; color <= WHITE; color++)
177 SlowGetAttacks(&rgSlowList,
181 GetAttacks(&rgAsmList,
185 if (!SeeListsAreEqual(&rgSlowList, &rgAsmList))
187 UtilPanic(TESTCASE_FAILURE,
189 "SEE_LIST mismatch", &rgSlowList, &rgAsmList,