summaryrefslogtreecommitdiff
path: root/src/testgenerate.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-25 10:39:58 -0700
committerScott Gasch <[email protected]>2026-10-25 10:39:58 -0700
commitf97b2710981e936cfb500ad0cdf1ceab233efad8 (patch)
tree0004275d9dae8f7df4b5f86f3b750d80bc3f4a52 /src/testgenerate.c
parent3927a4cac6ec254a8e34a5e864300f75c3efc9f3 (diff)
Make bitboard move generation unconditional; delete the mailbox fallback
All GENERATE_*_BITBOARD/EXPOSESCHECK_BITBOARD/ISATTACKED_BITBOARD/ UNBLOCKED_BITBOARD flags were already default-on (ifndef DISABLE_BITBOARD_MOVEGEN); this removes that opt-out entirely (GNUmakefile) and deletes the mailbox-era code the flags used to toggle between, since there's no longer a build configuration that still needs it: - generate.c: the mailbox per-piece generators and escape-generators (GenerateKnight/GenerateWhiteKnight/GenerateBishop/GenerateRook/ GenerateQueen/GenerateBlackKing/GenerateWhiteKing/GenerateWhitePawn/ GenerateBlackPawn and their SaveMe* escape-generator counterparts), _FindUnblockedSquares and its DEBUG-build cross-check inside _FindUnblockedSquaresBB, and the dispatch-table #if/#else pairs that chose between mailbox and bitboard functions (now unconditionally bitboard). WouldGiveCheck simplified to its UNBLOCKED_BITBOARD-only body. g_iBDeltas/g_iRDeltas (orphaned once their only consumers were deleted) removed; g_iNDeltas (still used by data.c's InitMagic) moved there, next to its real consumer. - movesup.c: mailbox FasterExposesCheck/ExposesCheck/ExposesCheckEp/ IsAttacked/InCheck deleted; chess.h's three-way macro choice simplified to a direct #define onto the BB versions (ExposesCheckBB/ IsAttackedBB/etc. are simply "the" implementation now). - testsee.c/testgenerate.c: deleted the mailbox-vs-BB comparison/speed harnesses that only existed to validate code just removed (TestIsAttackedBB, TestGenerateKnightSpeed/KingSpeed/RookSpeed/ BishopSpeed/QueenSpeed, TestFindUnblockedSquaresSpeed's mailbox arm). TestGetAttacks and the _GenerateAllMoves-vs-_GenerateAllMovesBB dispatch-overhead benchmark are unaffected -- GetAttacks' mailbox/asm predecessors were already retired independently, and that pair compares two still-live BB-only dispatch strategies, not mailbox vs BB. Verified: clean release build and a clean DEBUG=1 TEST=1 self-test run (move generation, perft-style legal-move checks, SAN/ICS parsing, search smoke test) with no assertion failures. Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/testgenerate.c')
-rw-r--r--src/testgenerate.c406
1 files changed, 6 insertions, 400 deletions
diff --git a/src/testgenerate.c b/src/testgenerate.c
index 83c187d..30f26e9 100644
--- a/src/testgenerate.c
+++ b/src/testgenerate.c
@@ -245,384 +245,10 @@ TestLegalMoveGenerator(void)
SystemFreeMemory(ctx);
}
-//
-// board_representation/MOVEGEN_MIGRATION.md section 5's isolated
-// cycles/call microbenchmark for the knight generator -- modeled
-// directly on testsee.c's TestGetAttacks speed block (interleaved
-// call-by-call across opening/middlegame/endgame positions, to cancel
-// shared-box noise). Correctness for this piece type is already
-// covered by TestMoveGenerator's perft counts (with
-// GENERATE_KNIGHT_BITBOARD defined) -- this only answers "is it
-// faster," the section 5 gate before a piece type's toggle is
-// considered for default-on.
-//
-void
-TestGenerateKnightSpeed(void)
-{
- static const char *rgszFen[3] =
- {
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
- "r1bq1rk1/pp2bppp/2n1pn2/2pp4/3P4/2NBPN2/PP3PPP/R1BQ1RK1 w - - 0 1",
- "8/5k2/8/3KN3/8/8/8/8 w - - 0 1",
- };
- static const char *rgszLabel[3] =
- {
- "opening ", "middlegame", "endgame ",
- };
- static const COOR rgcKnight[3] = { B1, C3, E5 };
- POSITION posBench;
- SEARCHER_THREAD_CONTEXT *ctx;
- UINT64 u64MailboxTotal, u64BBTotal, u64Start;
- ULONG uIter, u;
- ULONG uPly;
- const ULONG uCallsPerPosition = 200000;
-
- Trace("Benchmarking knight move generation: mailbox vs "
- "_GenerateKnightBB (interleaved, %lu calls/position)...\n",
- uCallsPerPosition);
-
- ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
- ASSERT(ctx);
- uPly = ctx->uPly;
-
- for (u = 0; u < 3; u++)
- {
- FenToPosition(&posBench, (char *)rgszFen[u]);
- InitializeSearcherContext(&posBench, ctx);
- ASSERT(IS_KNIGHT(posBench.rgSquare[rgcKnight[u]].pPiece));
- ASSERT(GET_COLOR(posBench.rgSquare[rgcKnight[u]].pPiece) ==
- posBench.uToMove);
-
- // _GenerateKnightBB relies on this being set by its caller
- // (normally _GenerateAllMoves, once per node) -- see
- // MOVE_STACK's bbFriendlyOccupied field comment in chess.h.
- // Computed once per benchmark position, not per call, matching
- // how the real call site amortizes it.
- ctx->sMoveStack.bbFriendlyOccupied =
- _BuildFriendlySideBB(&posBench, posBench.uToMove);
-
- u64MailboxTotal = 0;
- u64BBTotal = 0;
- for (uIter = 0; uIter < uCallsPerPosition; uIter++)
- {
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- GenerateWhiteKnight(&ctx->sMoveStack, &posBench, rgcKnight[u]);
- u64MailboxTotal += (SystemReadTimeStampCounter() - u64Start);
-
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- _GenerateKnightBB(&ctx->sMoveStack, &posBench, rgcKnight[u]);
- u64BBTotal += (SystemReadTimeStampCounter() - u64Start);
- }
- printf(" %s: mailbox %" COMPILER_LONGLONG_UNSIGNED_FORMAT
- " cycles/call, _GenerateKnightBB %"
- COMPILER_LONGLONG_UNSIGNED_FORMAT " cycles/call "
- "(BB is %.2fx mailbox)\n",
- rgszLabel[u],
- u64MailboxTotal / uCallsPerPosition,
- u64BBTotal / uCallsPerPosition,
- (double)u64BBTotal / (double)u64MailboxTotal);
- }
- SystemFreeMemory(ctx);
-}
-
-//
-// Same shape as TestGenerateKnightSpeed, for the king. Opening position
-// has castling rights but blocked by intervening pieces (exercises the
-// emptiness-check branch's cost without ever actually reaching
-// _AddCastle); middlegame is already castled (no rights, cheapest
-// castling-tail exit); endgame is a bare king on an open board (no
-// rights either, but the most normal-move destinations to enumerate).
-//
-void
-TestGenerateKingSpeed(void)
-{
- static const char *rgszFen[3] =
- {
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
- "r1bq1rk1/pp2bppp/2n1pn2/2pp4/3P4/2NBPN2/PP3PPP/R1BQ1RK1 w - - 0 1",
- "8/5k2/8/4K3/8/8/8/8 w - - 0 1",
- };
- static const char *rgszLabel[3] =
- {
- "opening ", "middlegame", "endgame ",
- };
- static const COOR rgcKing[3] = { E1, G1, E5 };
- POSITION posBench;
- SEARCHER_THREAD_CONTEXT *ctx;
- UINT64 u64MailboxTotal, u64BBTotal, u64Start;
- ULONG uIter, u;
- ULONG uPly;
- const ULONG uCallsPerPosition = 200000;
-
- Trace("Benchmarking king move generation: mailbox vs "
- "_GenerateKingBB (interleaved, %lu calls/position)...\n",
- uCallsPerPosition);
-
- ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
- ASSERT(ctx);
- uPly = ctx->uPly;
-
- for (u = 0; u < 3; u++)
- {
- FenToPosition(&posBench, (char *)rgszFen[u]);
- InitializeSearcherContext(&posBench, ctx);
- ASSERT(IS_KING(posBench.rgSquare[rgcKing[u]].pPiece));
- ASSERT(GET_COLOR(posBench.rgSquare[rgcKing[u]].pPiece) ==
- posBench.uToMove);
-
- ctx->sMoveStack.bbFriendlyOccupied =
- _BuildFriendlySideBB(&posBench, posBench.uToMove);
-
- u64MailboxTotal = 0;
- u64BBTotal = 0;
- for (uIter = 0; uIter < uCallsPerPosition; uIter++)
- {
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- GenerateWhiteKing(&ctx->sMoveStack, &posBench, rgcKing[u]);
- u64MailboxTotal += (SystemReadTimeStampCounter() - u64Start);
-
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- _GenerateKingBB(&ctx->sMoveStack, &posBench, rgcKing[u]);
- u64BBTotal += (SystemReadTimeStampCounter() - u64Start);
- }
- printf(" %s: mailbox %" COMPILER_LONGLONG_UNSIGNED_FORMAT
- " cycles/call, _GenerateKingBB %"
- COMPILER_LONGLONG_UNSIGNED_FORMAT " cycles/call "
- "(BB is %.2fx mailbox)\n",
- rgszLabel[u],
- u64MailboxTotal / uCallsPerPosition,
- u64BBTotal / uCallsPerPosition,
- (double)u64BBTotal / (double)u64MailboxTotal);
- }
- SystemFreeMemory(ctx);
-}
-
-//
-// Same shape as TestGenerateKnightSpeed/TestGenerateKingSpeed, for the
-// rook -- but unlike those two, this piece type is expected to
-// actually win: rook a1 is fully blocked in the opening (0
-// destinations, cheapest case either way), partially open in the
-// middlegame, and nearly fully open in the endgame (up to 13
-// destinations along an empty file/rank) -- exactly the case a
-// 4-direction ray walk pays for and a magic lookup doesn't.
-//
-void
-TestGenerateRookSpeed(void)
-{
- static const char *rgszFen[3] =
- {
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
- "r1bq1rk1/pp2bppp/2n1pn2/2pp4/3P4/2NBPN2/PP3PPP/R1BQ1RK1 w - - 0 1",
- "8/5k2/8/3K4/8/8/8/R7 w - - 0 1",
- };
- static const char *rgszLabel[3] =
- {
- "opening ", "middlegame", "endgame ",
- };
- static const COOR rgcRook[3] = { A1, A1, A1 };
- POSITION posBench;
- SEARCHER_THREAD_CONTEXT *ctx;
- UINT64 u64MailboxTotal, u64BBTotal, u64Start;
- ULONG uIter, u;
- ULONG uPly;
- const ULONG uCallsPerPosition = 200000;
-
- Trace("Benchmarking rook move generation: mailbox vs "
- "_GenerateRookBB (interleaved, %lu calls/position)...\n",
- uCallsPerPosition);
-
- ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
- ASSERT(ctx);
- uPly = ctx->uPly;
-
- for (u = 0; u < 3; u++)
- {
- FenToPosition(&posBench, (char *)rgszFen[u]);
- InitializeSearcherContext(&posBench, ctx);
- ASSERT(IS_ROOK(posBench.rgSquare[rgcRook[u]].pPiece));
- ASSERT(GET_COLOR(posBench.rgSquare[rgcRook[u]].pPiece) ==
- posBench.uToMove);
-
- ctx->sMoveStack.bbFriendlyOccupied =
- _BuildFriendlySideBB(&posBench, posBench.uToMove);
- ctx->sMoveStack.bbOccupied = _BuildFullOccupiedBB(&posBench);
-
- u64MailboxTotal = 0;
- u64BBTotal = 0;
- for (uIter = 0; uIter < uCallsPerPosition; uIter++)
- {
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- GenerateRook(&ctx->sMoveStack, &posBench, rgcRook[u]);
- u64MailboxTotal += (SystemReadTimeStampCounter() - u64Start);
-
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- _GenerateRookBB(&ctx->sMoveStack, &posBench, rgcRook[u]);
- u64BBTotal += (SystemReadTimeStampCounter() - u64Start);
- }
- printf(" %s: mailbox %" COMPILER_LONGLONG_UNSIGNED_FORMAT
- " cycles/call, _GenerateRookBB %"
- COMPILER_LONGLONG_UNSIGNED_FORMAT " cycles/call "
- "(BB is %.2fx mailbox)\n",
- rgszLabel[u],
- u64MailboxTotal / uCallsPerPosition,
- u64BBTotal / uCallsPerPosition,
- (double)u64BBTotal / (double)u64MailboxTotal);
- }
- SystemFreeMemory(ctx);
-}
-
-//
-// Same shape as TestGenerateRookSpeed, for the bishop -- expect the
-// same parity result (see MOVEGEN_MIGRATION.md section 3's rook
-// entry for why), not a different outcome, since the underlying
-// reason applies identically to diagonals.
-//
-void
-TestGenerateBishopSpeed(void)
-{
- static const char *rgszFen[3] =
- {
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
- "r1bq1rk1/pp2bppp/2n1pn2/2pp4/3P4/2NBPN2/PP3PPP/R1BQ1RK1 w - - 0 1",
- "8/5k2/8/3K4/8/8/8/B7 w - - 0 1",
- };
- static const char *rgszLabel[3] =
- {
- "opening ", "middlegame", "endgame ",
- };
- static const COOR rgcBishop[3] = { C1, D3, A1 };
- POSITION posBench;
- SEARCHER_THREAD_CONTEXT *ctx;
- UINT64 u64MailboxTotal, u64BBTotal, u64Start;
- ULONG uIter, u;
- ULONG uPly;
- const ULONG uCallsPerPosition = 200000;
-
- Trace("Benchmarking bishop move generation: mailbox vs "
- "_GenerateBishopBB (interleaved, %lu calls/position)...\n",
- uCallsPerPosition);
-
- ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
- ASSERT(ctx);
- uPly = ctx->uPly;
-
- for (u = 0; u < 3; u++)
- {
- FenToPosition(&posBench, (char *)rgszFen[u]);
- InitializeSearcherContext(&posBench, ctx);
- ASSERT(IS_BISHOP(posBench.rgSquare[rgcBishop[u]].pPiece));
- ASSERT(GET_COLOR(posBench.rgSquare[rgcBishop[u]].pPiece) ==
- posBench.uToMove);
-
- ctx->sMoveStack.bbFriendlyOccupied =
- _BuildFriendlySideBB(&posBench, posBench.uToMove);
- ctx->sMoveStack.bbOccupied = _BuildFullOccupiedBB(&posBench);
-
- u64MailboxTotal = 0;
- u64BBTotal = 0;
- for (uIter = 0; uIter < uCallsPerPosition; uIter++)
- {
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- GenerateBishop(&ctx->sMoveStack, &posBench, rgcBishop[u]);
- u64MailboxTotal += (SystemReadTimeStampCounter() - u64Start);
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- _GenerateBishopBB(&ctx->sMoveStack, &posBench, rgcBishop[u]);
- u64BBTotal += (SystemReadTimeStampCounter() - u64Start);
- }
- printf(" %s: mailbox %" COMPILER_LONGLONG_UNSIGNED_FORMAT
- " cycles/call, _GenerateBishopBB %"
- COMPILER_LONGLONG_UNSIGNED_FORMAT " cycles/call "
- "(BB is %.2fx mailbox)\n",
- rgszLabel[u],
- u64MailboxTotal / uCallsPerPosition,
- u64BBTotal / uCallsPerPosition,
- (double)u64BBTotal / (double)u64MailboxTotal);
- }
- SystemFreeMemory(ctx);
-}
-
-//
-// Same shape as TestGenerateRookSpeed/TestGenerateBishopSpeed, for the
-// queen -- expect the same parity-or-slightly-worse result, plus an
-// extra fixed cost this time (two magic lookups instead of one) --
-// see MOVEGEN_MIGRATION.md section 3's rook entry for why a win was
-// never really on the table for this piece type either.
-//
-void
-TestGenerateQueenSpeed(void)
-{
- static const char *rgszFen[3] =
- {
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
- "r1b2rk1/pp2bppp/2n1pn2/2pp4/3P4/1QNBPN2/PP3PPP/R3KB1R w - - 0 1",
- "8/5k2/8/3K4/8/8/8/Q7 w - - 0 1",
- };
- static const char *rgszLabel[3] =
- {
- "opening ", "middlegame", "endgame ",
- };
- static const COOR rgcQueen[3] = { D1, B3, A1 };
- POSITION posBench;
- SEARCHER_THREAD_CONTEXT *ctx;
- UINT64 u64MailboxTotal, u64BBTotal, u64Start;
- ULONG uIter, u;
- ULONG uPly;
- const ULONG uCallsPerPosition = 200000;
-
- Trace("Benchmarking queen move generation: mailbox vs "
- "_GenerateQueenBB (interleaved, %lu calls/position)...\n",
- uCallsPerPosition);
-
- ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
- ASSERT(ctx);
- uPly = ctx->uPly;
- for (u = 0; u < 3; u++)
- {
- FenToPosition(&posBench, (char *)rgszFen[u]);
- InitializeSearcherContext(&posBench, ctx);
- ASSERT(IS_QUEEN(posBench.rgSquare[rgcQueen[u]].pPiece));
- ASSERT(GET_COLOR(posBench.rgSquare[rgcQueen[u]].pPiece) ==
- posBench.uToMove);
- ctx->sMoveStack.bbFriendlyOccupied =
- _BuildFriendlySideBB(&posBench, posBench.uToMove);
- ctx->sMoveStack.bbOccupied = _BuildFullOccupiedBB(&posBench);
-
- u64MailboxTotal = 0;
- u64BBTotal = 0;
- for (uIter = 0; uIter < uCallsPerPosition; uIter++)
- {
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- GenerateQueen(&ctx->sMoveStack, &posBench, rgcQueen[u]);
- u64MailboxTotal += (SystemReadTimeStampCounter() - u64Start);
- ctx->sMoveStack.uEnd[uPly] = ctx->sMoveStack.uBegin[uPly];
- u64Start = SystemReadTimeStampCounter();
- _GenerateQueenBB(&ctx->sMoveStack, &posBench, rgcQueen[u]);
- u64BBTotal += (SystemReadTimeStampCounter() - u64Start);
- }
- printf(" %s: mailbox %" COMPILER_LONGLONG_UNSIGNED_FORMAT
- " cycles/call, _GenerateQueenBB %"
- COMPILER_LONGLONG_UNSIGNED_FORMAT " cycles/call "
- "(BB is %.2fx mailbox)\n",
- rgszLabel[u],
- u64MailboxTotal / uCallsPerPosition,
- u64BBTotal / uCallsPerPosition,
- (double)u64BBTotal / (double)u64MailboxTotal);
- }
- SystemFreeMemory(ctx);
-}
//
// Whole-node dispatch benchmark: _GenerateAllMoves (mailbox
@@ -700,21 +326,16 @@ TestGenerateAllMovesSpeed(void)
//
// board_representation/MOVEGEN_MIGRATION.md's never-started
-// _FindUnblockedSquares/WouldGiveCheck candidate. Unlike every other
+// _FindUnblockedSquaresBB/WouldGiveCheck candidate. Unlike every other
// benchmark in this file, this does NOT measure the generator call in
-// isolation: _FindUnblockedSquares writes ~20 square entries that may
+// isolation: _FindUnblockedSquaresBB writes ~20 square entries that may
// never be read, and WouldGiveCheck reads only 1-3 of them per move,
// so a bitboard version that looks like a big win building the table
// can give some of it back at query time. The real per-node cost is
-// the pair -- one _FindUnblockedSquares(BB) call followed by
+// the pair -- one _FindUnblockedSquaresBB call followed by
// WouldGiveCheck over every move actually generated at that node --
// so that's what gets timed here, same interleaved-call methodology
-// as the rest of this file. WouldGiveCheck's own body is selected at
-// compile time by UNBLOCKED_BITBOARD (SQUARE_IS_UNBLOCKED/
-// DIR_FROM_SQ_TO_KING), so unlike TestGenerateAllMovesSpeed this can't
-// compare both implementations by name in one binary -- run this test
-// in two builds (with and without -DUNBLOCKED_BITBOARD) and compare
-// the printed cycles/pair across them.
+// as the rest of this file.
//
void
TestFindUnblockedSquaresSpeed(void)
@@ -737,15 +358,8 @@ TestFindUnblockedSquaresSpeed(void)
MOVE_STACK *pStack;
const ULONG uCallsPerPosition = 50000;
- Trace("Benchmarking _FindUnblockedSquares%s + WouldGiveCheck over "
- "a generated move list (%lu calls/position) -- compare this "
- "build's numbers against a build with the opposite "
- "-DUNBLOCKED_BITBOARD setting...\n",
-#ifdef UNBLOCKED_BITBOARD
- "BB",
-#else
- " (mailbox)",
-#endif
+ Trace("Benchmarking _FindUnblockedSquaresBB + WouldGiveCheck over "
+ "a generated move list (%lu calls/position)...\n",
uCallsPerPosition);
ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
@@ -763,11 +377,7 @@ TestFindUnblockedSquaresSpeed(void)
// what's under test here, not generation itself.
pStack->uEnd[uPly] = pStack->uBegin[uPly];
pStack->sGenFlags[uPly].uAllGenFlags = 0;
-#ifdef UNBLOCKED_BITBOARD
_FindUnblockedSquaresBB(pStack, &posBench);
-#else
- _FindUnblockedSquares(pStack, &posBench);
-#endif
_GenerateAllMoves(pStack, &posBench);
uNumMoves = MOVE_COUNT(ctx, uPly);
ASSERT(uNumMoves > 0);
@@ -794,11 +404,7 @@ TestFindUnblockedSquaresSpeed(void)
for (uIter = 0; uIter < uCallsPerPosition; uIter++)
{
u64Start = SystemReadTimeStampCounter();
-#ifdef UNBLOCKED_BITBOARD
_FindUnblockedSquaresBB(pStack, &posBench);
-#else
- _FindUnblockedSquares(pStack, &posBench);
-#endif
for (uMove = pStack->uBegin[uPly];
uMove < pStack->uEnd[uPly];
uMove++)