summaryrefslogtreecommitdiff
path: root/src/recogn.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-09-16 08:02:21 -0700
committerScott Gasch <[email protected]>2026-09-16 08:02:21 -0700
commit966a0ef4da9cf3911eb3da0533179199808717b4 (patch)
treee09363b574215ef0d8996155a5ab24314db2dd69 /src/recogn.c
parentb91c8453f3fe21c8ccd3568923d8e39141c9c945 (diff)
Retire cPawns/cNonPawns piece-location lists in favor of bbPawns/bbPieces/cKingSq, and hoist two redundant TotalNonPawnCount POPCNT calls out of per-node hot loops.
POSITION no longer stores cPawns[2][8], cNonPawns[2][16], uPawnCount[2], uNonPawnCount[2][8], or uWhiteSqBishopCount[2] -- every reader now goes through PawnMaterial/TotalNonPawnCount/WhiteSqBishopCount/KingPosition (chess.h), computed from the already-incrementally-maintained bbPawns/ bbPieces/cKingSq bitboards via a single -mpopcnt POPCNT instead of a stored counter. move.c's make/unmake loses the list-swap-on-removal bookkeeping entirely. GNUmakefile now passes -mpopcnt so the popcount builtins actually compile to one instruction instead of clang's ~15-op SWAR fallback. Measured a small but real nps regression from the naive swap (search.c's QSearch move-filter and eval.c's _EvalKing were each recomputing the same TotalNonPawnCount sum on every candidate move / twice per node); hoisted both to a single call per node instead. Net result across a same-code self-play match: ~1541.5 knps candidate vs ~1505.7 knps head_reference. A third hoist (FindEnprisePiece out of SelectBestWithHistory) was tried and reverted -- its cache isn't actually loop-invariant within a node (populated from inside Eval(), which doesn't run before every selection call), caught by a DEBUG-build ASSERT before it landed. Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/recogn.c')
-rw-r--r--src/recogn.c256
1 files changed, 133 insertions, 123 deletions
diff --git a/src/recogn.c b/src/recogn.c
index 32a618d..deb2285 100644
--- a/src/recogn.c
+++ b/src/recogn.c
@@ -23,6 +23,15 @@ Revision History:
#include "chess.h"
+// See eval.c's identical comment: routes this file's KBNK/KBKB
+// adjacency-check bitboard-scan loops (called every node via
+// RecognLookup in search.c) to the inlined
+// FastCoorFromBitBoardRank8ToRank1 (chess.h) instead of the real
+// out-of-line extern call.
+#ifndef CROUTINES
+#define CoorFromBitBoardRank8ToRank1 FastCoorFromBitBoardRank8ToRank1
+#endif
+
extern ULONG g_uIterateDepth;
static COOR QUEENING_SQUARE_BY_COLOR_FILE[2][8] =
{
@@ -211,14 +220,14 @@ static FLAG
if (!(p & PAWN))
{
- if (pos->uPawnCount[uColor] > 0) return(FALSE);
+ if (FastCountBits(pos->bbPawns[uColor]) > 0) return(FALSE);
}
for (u = 0; u < ARRAY_LENGTH(q); u++)
{
if (!(p & q[u]))
{
- if (pos->uNonPawnCount[uColor][q[u]] > 0) return(FALSE);
+ if (FastCountBits(pos->bbPieces[uColor][q[u]]) > 0) return(FALSE);
}
}
return(TRUE);
@@ -276,8 +285,8 @@ Return value:
ULONG uAdjacent;
POSITION *pos = &ctx->sPosition;
- ASSERT((pos->uNonPawnCount[WHITE][0] <= 3) &&
- (pos->uNonPawnCount[BLACK][0] <= 3));
+ ASSERT((TotalNonPawnCount(pos, WHITE) <= 3) &&
+ (TotalNonPawnCount(pos, BLACK) <= 3));
ASSERT(_NothingBut(pos, BISHOP, WHITE));
ASSERT(_NothingBut(pos, BISHOP, BLACK));
@@ -285,11 +294,11 @@ Return value:
// Recognize KBKB as a draw unless there's a cornered king (in
// which case it may be a mate-in-1)
//
- if ((pos->uNonPawnCount[WHITE][0] == 2) &&
- (pos->uNonPawnCount[BLACK][0] == 2))
+ if ((TotalNonPawnCount(pos, WHITE) == 2) &&
+ (TotalNonPawnCount(pos, BLACK) == 2))
{
- if ((CORNER_DISTANCE(pos->cNonPawns[WHITE][0]) != 0) &&
- (CORNER_DISTANCE(pos->cNonPawns[BLACK][0]) != 0))
+ if ((CORNER_DISTANCE(KingPosition(pos, WHITE)) != 0) &&
+ (CORNER_DISTANCE(KingPosition(pos, BLACK)) != 0))
{
*piScore = 0;
return(RECOGN_EXACT);
@@ -300,8 +309,8 @@ Return value:
// Otherwise we want to deal with KB+ vs lone K. KBKBB etc are
// too hard to recognize.
//
- if ((pos->uNonPawnCount[WHITE][0] != 1) &&
- (pos->uNonPawnCount[BLACK][0] != 1))
+ if ((TotalNonPawnCount(pos, WHITE) != 1) &&
+ (TotalNonPawnCount(pos, BLACK) != 1))
{
return(UNRECOGNIZED);
}
@@ -310,21 +319,21 @@ Return value:
// If we get here then one side has no pieces (except the king).
//
uStrong = BLACK;
- if (pos->uNonPawnCount[WHITE][0] > 1)
+ if (TotalNonPawnCount(pos, WHITE) > 1)
{
uStrong = WHITE;
}
- ASSERT(pos->uNonPawnCount[uStrong][0] > 1);
- ASSERT(pos->uNonPawnCount[FLIP(uStrong)][0] == 1);
+ ASSERT(TotalNonPawnCount(pos, uStrong) > 1);
+ ASSERT(TotalNonPawnCount(pos, FLIP(uStrong)) == 1);
//
// KB vs K is a draw, KB+ vs K is still a draw if all bishops are the
// same color.
//
- uBishops = pos->uNonPawnCount[uStrong][BISHOP];
+ uBishops = FastCountBits(pos->bbPieces[uStrong][BISHOP]);
if ((uBishops == 1) ||
- (pos->uWhiteSqBishopCount[uStrong] == 0) ||
- (pos->uWhiteSqBishopCount[uStrong] == uBishops))
+ (WhiteSqBishopCount(pos, uStrong) == 0) ||
+ (WhiteSqBishopCount(pos, uStrong) == uBishops))
{
*piScore = 0;
return(RECOGN_EXACT);
@@ -341,12 +350,16 @@ Return value:
// move. Note: we allow the weak king to be adjacent to up to one
// enemy bishop as long as it's the strong side's turn to move.
//
- cWeakKing = pos->cNonPawns[FLIP(uStrong)][0];
- ASSERT(DISTANCE(cWeakKing, pos->cNonPawns[uStrong][0]) > 1);
+ cWeakKing = KingPosition(pos, FLIP(uStrong));
+ ASSERT(DISTANCE(cWeakKing, KingPosition(pos, uStrong)) > 1);
uAdjacent = 0;
- for (u = 1; u < pos->uNonPawnCount[uStrong][0]; u++)
{
- uAdjacent += (DISTANCE(cWeakKing, pos->cNonPawns[uStrong][u]) == 1);
+ BITBOARD bbPieces = NON_KING_PIECES_BB(pos, uStrong);
+ COOR c;
+ while (IS_ON_BOARD(c = CoorFromBitBoardRank8ToRank1(&bbPieces)))
+ {
+ uAdjacent += (DISTANCE(cWeakKing, c) == 1);
+ }
}
if (uAdjacent > 1)
{
@@ -357,9 +370,9 @@ Return value:
// If it's the weak side's turn and the strong king is close
// enough that the weak side may be stalemated, fail to recognize.
//
- ASSERT(IS_ON_BOARD(pos->cNonPawns[uStrong][0]));
- ASSERT(IS_KING(pos->rgSquare[pos->cNonPawns[uStrong][0]].pPiece));
- u = DISTANCE(cWeakKing, pos->cNonPawns[uStrong][0]);
+ ASSERT(IS_ON_BOARD(KingPosition(pos, uStrong)));
+ ASSERT(IS_KING(pos->rgSquare[KingPosition(pos, uStrong)].pPiece));
+ u = DISTANCE(cWeakKing, KingPosition(pos, uStrong));
ASSERT(u != 1);
if (pos->uToMove != uStrong)
{
@@ -413,8 +426,8 @@ Return value:
POSITION *pos = &ctx->sPosition;
ULONG uStrong;
- ASSERT((pos->uNonPawnCount[WHITE][0] <= 3) &&
- (pos->uNonPawnCount[BLACK][0] <= 3));
+ ASSERT((TotalNonPawnCount(pos, WHITE) <= 3) &&
+ (TotalNonPawnCount(pos, BLACK) <= 3));
ASSERT(_NothingBut(pos, KNIGHT, WHITE));
ASSERT(_NothingBut(pos, KNIGHT, BLACK));
@@ -422,11 +435,11 @@ Return value:
// KNKN is a draw unless someone has a K in the corner (in which case,
// with the friend knight in the way, there's a possible mate)
//
- if ((pos->uNonPawnCount[WHITE][0] == 2) &&
- (pos->uNonPawnCount[BLACK][0] == 2))
+ if ((TotalNonPawnCount(pos, WHITE) == 2) &&
+ (TotalNonPawnCount(pos, BLACK) == 2))
{
- if ((CORNER_DISTANCE(pos->cNonPawns[WHITE][0]) != 0) &&
- (CORNER_DISTANCE(pos->cNonPawns[BLACK][0]) != 0))
+ if ((CORNER_DISTANCE(KingPosition(pos, WHITE)) != 0) &&
+ (CORNER_DISTANCE(KingPosition(pos, BLACK)) != 0))
{
*piScore = 0;
return(RECOGN_EXACT);
@@ -438,8 +451,8 @@ Return value:
// KNNKN etc... unrecognized. Heinz says "exceptional wins possible for
// any side by mates in seven or less moves." TODO: add this knowledge.
//
- if ((pos->uNonPawnCount[WHITE][0] != 1) ||
- (pos->uNonPawnCount[BLACK][0] != 1))
+ if ((TotalNonPawnCount(pos, WHITE) != 1) ||
+ (TotalNonPawnCount(pos, BLACK) != 1))
{
return(UNRECOGNIZED);
}
@@ -448,20 +461,20 @@ Return value:
// If we get here somebody has no pieces (except a lone king).
//
uStrong = WHITE;
- if (pos->uNonPawnCount[BLACK][0] > 1)
+ if (TotalNonPawnCount(pos, BLACK) > 1)
{
uStrong = BLACK;
}
- ASSERT(pos->uNonPawnCount[uStrong][0] > 1);
- ASSERT(pos->uNonPawnCount[FLIP(uStrong)][0] == 1);
+ ASSERT(TotalNonPawnCount(pos, uStrong) > 1);
+ ASSERT(TotalNonPawnCount(pos, FLIP(uStrong)) == 1);
//
// Call KNNK a draw unless the weak K is on the edge of the board
// where a checkmate is possible (e.g. 8/8/8/8/8/N2N4/4K3/2k5 b - -)
// Everything else in here is a draw.
//
- ASSERT(pos->uNonPawnCount[uStrong][0] < 4);
- if (ON_EDGE(pos->cNonPawns[FLIP(uStrong)][0]))
+ ASSERT(TotalNonPawnCount(pos, uStrong) < 4);
+ if (ON_EDGE(KingPosition(pos, FLIP(uStrong))))
{
return(UNRECOGNIZED);
}
@@ -506,18 +519,18 @@ Return value:
ULONG uAdjacent;
POSITION *pos = &ctx->sPosition;
- ASSERT((pos->uNonPawnCount[WHITE][0] <= 3) &&
- (pos->uNonPawnCount[BLACK][0] <= 3));
+ ASSERT((TotalNonPawnCount(pos, WHITE) <= 3) &&
+ (TotalNonPawnCount(pos, BLACK) <= 3));
ASSERT(_NothingBut(pos, BISHOP | KNIGHT, WHITE));
ASSERT(_NothingBut(pos, BISHOP | KNIGHT, BLACK));
- if ((pos->uNonPawnCount[WHITE][0] > 1) &&
- (pos->uNonPawnCount[BLACK][0] > 1))
+ if ((TotalNonPawnCount(pos, WHITE) > 1) &&
+ (TotalNonPawnCount(pos, BLACK) > 1))
{
//
// Do not recognize stuff like KNNKB or KNKBB etc...
//
- if (pos->uNonPawnCount[WHITE][0] + pos->uNonPawnCount[BLACK][0] > 4)
+ if (TotalNonPawnCount(pos, WHITE) + TotalNonPawnCount(pos, BLACK) > 4)
{
return(UNRECOGNIZED);
}
@@ -526,10 +539,10 @@ Return value:
// This is KNKB; unless someone's king is on the edge,
// recognize a draw.
//
- ASSERT((pos->uNonPawnCount[WHITE][0] == 2) &&
- (pos->uNonPawnCount[BLACK][0] == 2));
- if (ON_EDGE(pos->cNonPawns[WHITE][0]) ||
- ON_EDGE(pos->cNonPawns[BLACK][0]))
+ ASSERT((TotalNonPawnCount(pos, WHITE) == 2) &&
+ (TotalNonPawnCount(pos, BLACK) == 2));
+ if (ON_EDGE(KingPosition(pos, WHITE)) ||
+ ON_EDGE(KingPosition(pos, BLACK)))
{
return(UNRECOGNIZED);
}
@@ -541,13 +554,13 @@ Return value:
// If we get here we are in a KBNK endgame.
//
uStrong = WHITE;
- if (pos->uNonPawnCount[BLACK][0] > 1)
+ if (TotalNonPawnCount(pos, BLACK) > 1)
{
uStrong = BLACK;
}
- ASSERT(pos->uNonPawnCount[uStrong][0] > 1);
- ASSERT(pos->uNonPawnCount[FLIP(uStrong)][0] == 1);
- cWeakKing = pos->cNonPawns[FLIP(uStrong)][0];
+ ASSERT(TotalNonPawnCount(pos, uStrong) > 1);
+ ASSERT(TotalNonPawnCount(pos, FLIP(uStrong)) == 1);
+ cWeakKing = KingPosition(pos, FLIP(uStrong));
ASSERT(IS_ON_BOARD(cWeakKing));
ASSERT(IS_KING(pos->rgSquare[cWeakKing].pPiece));
@@ -556,7 +569,7 @@ Return value:
// lone king. It's possible for the lone king to trap it there
// thus drawing the game.
//
- cKnight = pos->cNonPawns[uStrong][KNIGHT];
+ cKnight = CoorOfSingleBit(pos->bbPieces[uStrong][KNIGHT]);
if ((CORNER_DISTANCE(cKnight) == 0) &&
(DISTANCE(cWeakKing, cKnight) == 1))
{
@@ -568,9 +581,13 @@ Return value:
// piece.
//
uAdjacent = 0;
- for (u = 1; u < pos->uNonPawnCount[uStrong][0]; u++)
{
- uAdjacent += (DISTANCE(pos->cNonPawns[uStrong][u], cWeakKing) == 1);
+ BITBOARD bbPieces = NON_KING_PIECES_BB(pos, uStrong);
+ COOR c;
+ while (IS_ON_BOARD(c = CoorFromBitBoardRank8ToRank1(&bbPieces)))
+ {
+ uAdjacent += (DISTANCE(c, cWeakKing) == 1);
+ }
}
if (uAdjacent)
{
@@ -582,9 +599,9 @@ Return value:
// that there might be a stalemate if the weak side is on move and
// on the edge.
//
- ASSERT(IS_ON_BOARD(pos->cNonPawns[uStrong][0]));
- ASSERT(IS_KING(pos->rgSquare[pos->cNonPawns[uStrong][0]].pPiece));
- u = DISTANCE(cWeakKing, pos->cNonPawns[uStrong][0]);
+ ASSERT(IS_ON_BOARD(KingPosition(pos, uStrong)));
+ ASSERT(IS_KING(pos->rgSquare[KingPosition(pos, uStrong)].pPiece));
+ u = DISTANCE(cWeakKing, KingPosition(pos, uStrong));
ASSERT(u != 1);
if (pos->uToMove != uStrong)
{
@@ -600,7 +617,7 @@ Return value:
// progress towards driving the weak king to the correct corner to
// mate him.
//
- if (pos->uWhiteSqBishopCount[uStrong] > 0)
+ if (WhiteSqBishopCount(pos, uStrong) > 0)
{
uDist = WHITE_CORNER_DISTANCE(cWeakKing);
}
@@ -666,8 +683,8 @@ Return value:
ULONG uStrong;
POSITION *pos = &ctx->sPosition;
- ASSERT((pos->uNonPawnCount[WHITE][0] <= 3) &&
- (pos->uNonPawnCount[BLACK][0] <= 3));
+ ASSERT((TotalNonPawnCount(pos, WHITE) <= 3) &&
+ (TotalNonPawnCount(pos, BLACK) <= 3));
ASSERT(_NothingBut(pos, PAWN | KNIGHT, WHITE));
ASSERT(_NothingBut(pos, PAWN | KNIGHT, BLACK));
@@ -675,21 +692,21 @@ Return value:
// Call the side with the knight "strong"
//
uStrong = WHITE;
- if (pos->uNonPawnCount[BLACK][0] > 1)
+ if (TotalNonPawnCount(pos, BLACK) > 1)
{
uStrong = BLACK;
}
- ASSERT(pos->uNonPawnCount[uStrong][0] > 1);
- ASSERT(pos->uNonPawnCount[FLIP(uStrong)][0] == 1);
+ ASSERT(TotalNonPawnCount(pos, uStrong) > 1);
+ ASSERT(TotalNonPawnCount(pos, FLIP(uStrong)) == 1);
//
// Exhaustively proven correct only for exactly one knight and
// exactly one pawn (see the comment above) -- also still exclude
// K on the edge, per the original ON_EDGE reasoning.
//
- if ((pos->uNonPawnCount[uStrong][KNIGHT] != 1) ||
- (pos->uPawnCount[FLIP(uStrong)] != 1) ||
- (ON_EDGE(pos->cNonPawns[FLIP(uStrong)][0])))
+ if ((FastCountBits(pos->bbPieces[uStrong][KNIGHT]) != 1) ||
+ (FastCountBits(pos->bbPawns[FLIP(uStrong)]) != 1) ||
+ (ON_EDGE(KingPosition(pos, FLIP(uStrong)))))
{
return(UNRECOGNIZED);
}
@@ -730,13 +747,11 @@ Return value:
{
ULONG uStrong;
BITBOARD bb;
- ULONG u;
- COOR c;
COOR cWeakKing;
POSITION *pos = &ctx->sPosition;
- ASSERT((pos->uNonPawnCount[WHITE][0] <= 3) &&
- (pos->uNonPawnCount[BLACK][0] <= 3));
+ ASSERT((TotalNonPawnCount(pos, WHITE) <= 3) &&
+ (TotalNonPawnCount(pos, BLACK) <= 3));
ASSERT(_NothingBut(pos, PAWN | BISHOP, WHITE));
ASSERT(_NothingBut(pos, PAWN | BISHOP, BLACK));
@@ -744,36 +759,30 @@ Return value:
// Call the side with bishop(s) "strong"
//
uStrong = WHITE;
- if (pos->uNonPawnCount[BLACK][BISHOP] > 0)
+ if (FastCountBits(pos->bbPieces[BLACK][BISHOP]) > 0)
{
uStrong = BLACK;
}
- ASSERT(pos->uNonPawnCount[uStrong][0] > 1);
- ASSERT(pos->uNonPawnCount[FLIP(uStrong)][0] == 1);
+ ASSERT(TotalNonPawnCount(pos, uStrong) > 1);
+ ASSERT(TotalNonPawnCount(pos, FLIP(uStrong)) == 1);
- cWeakKing = pos->cNonPawns[FLIP(uStrong)][0];
+ cWeakKing = KingPosition(pos, FLIP(uStrong));
ASSERT(IS_ON_BOARD(cWeakKing));
ASSERT(IS_KING(pos->rgSquare[cWeakKing].pPiece));
//
- // Construct a strong side bitboard of pawn locations
+ // Strong side's pawn locations
//
- bb = 0ULL;
- for (u = 0; u < pos->uPawnCount[uStrong]; u++)
- {
- c = pos->cPawns[uStrong][u];
- ASSERT(IS_ON_BOARD(c));
- bb |= COOR_TO_BB(c);
- }
+ bb = pos->bbPawns[uStrong];
- if ((pos->uNonPawnCount[BLACK][0] + pos->uPawnCount[BLACK] > 1) &&
- (pos->uNonPawnCount[WHITE][0] + pos->uPawnCount[WHITE] > 1))
+ if ((TotalNonPawnCount(pos, BLACK) + FastCountBits(pos->bbPawns[BLACK]) > 1) &&
+ (TotalNonPawnCount(pos, WHITE) + FastCountBits(pos->bbPawns[WHITE]) > 1))
{
//
// Neither side has a lone king. This is either KBKP+ or
// KBP+KP+.
//
- if (pos->uPawnCount[uStrong] > 0)
+ if (FastCountBits(pos->bbPawns[uStrong]) > 0)
{
//
// Strong side can maybe take an adjacent pawn and survive the
@@ -791,15 +800,15 @@ Return value:
if (uStrong == WHITE)
{
if (!(bb & ~BBFILE[A]) &&
- (pos->uWhiteSqBishopCount[WHITE] == 0) &&
+ (WhiteSqBishopCount(pos, WHITE) == 0) &&
(DISTANCE(cWeakKing, A8) <= 1))
{
goto at_best_draw_for_strong;
}
if (!(bb & ~BBFILE[H]) &&
- (pos->uWhiteSqBishopCount[WHITE] ==
- pos->uNonPawnCount[WHITE][BISHOP]) &&
+ (WhiteSqBishopCount(pos, WHITE) ==
+ FastCountBits(pos->bbPieces[WHITE][BISHOP])) &&
(DISTANCE(cWeakKing, H8) <= 1))
{
goto at_best_draw_for_strong;
@@ -808,15 +817,15 @@ Return value:
else
{
if (!(bb & ~BBFILE[A]) &&
- (pos->uWhiteSqBishopCount[BLACK] ==
- pos->uNonPawnCount[BLACK][BISHOP]) &&
+ (WhiteSqBishopCount(pos, BLACK) ==
+ FastCountBits(pos->bbPieces[BLACK][BISHOP])) &&
(DISTANCE(cWeakKing, A1) <= 1))
{
goto at_best_draw_for_strong;
}
if (!(bb & ~BBFILE[H]) &&
- (pos->uWhiteSqBishopCount[BLACK] == 0) &&
+ (WhiteSqBishopCount(pos, BLACK) == 0) &&
(DISTANCE(cWeakKing, H1) <= 1))
{
goto at_best_draw_for_strong;
@@ -830,7 +839,7 @@ Return value:
// Strong side has no pawns... there's a mate-in-1 here if
// the weak king is stuck in the corner.
//
- if ((pos->uNonPawnCount[uStrong][BISHOP] > 1) ||
+ if ((FastCountBits(pos->bbPieces[uStrong][BISHOP]) > 1) ||
(CORNER_DISTANCE(cWeakKing) == 0))
{
return(UNRECOGNIZED);
@@ -844,20 +853,20 @@ Return value:
// KBPK: make sure the bishop is the right color. This time
// there is no need to check for on-move.
//
- ASSERT(pos->uNonPawnCount[FLIP(uStrong)][0] == 1);
- ASSERT(pos->uNonPawnCount[uStrong][0] > 1);
+ ASSERT(TotalNonPawnCount(pos, FLIP(uStrong)) == 1);
+ ASSERT(TotalNonPawnCount(pos, uStrong) > 1);
if (uStrong == WHITE)
{
if (!(bb & ~BBFILE[A]) &&
- (pos->uWhiteSqBishopCount[WHITE] == 0) &&
+ (WhiteSqBishopCount(pos, WHITE) == 0) &&
(DISTANCE(cWeakKing, A8) <= 1))
{
goto draw;
}
if (!(bb & ~BBFILE[H]) &&
- (pos->uWhiteSqBishopCount[WHITE] ==
- pos->uNonPawnCount[WHITE][BISHOP]) &&
+ (WhiteSqBishopCount(pos, WHITE) ==
+ FastCountBits(pos->bbPieces[WHITE][BISHOP])) &&
(DISTANCE(cWeakKing, H8) <= 1))
{
goto draw;
@@ -866,14 +875,14 @@ Return value:
else
{
if (!(bb & ~BBFILE[A]) &&
- (pos->uWhiteSqBishopCount[BLACK] ==
- pos->uNonPawnCount[BLACK][BISHOP]) &&
+ (WhiteSqBishopCount(pos, BLACK) ==
+ FastCountBits(pos->bbPieces[BLACK][BISHOP])) &&
(DISTANCE(cWeakKing, A1) <= 1))
{
goto draw;
}
if (!(bb & ~BBFILE[H]) &&
- (pos->uWhiteSqBishopCount[BLACK] == 0) &&
+ (WhiteSqBishopCount(pos, BLACK) == 0) &&
(DISTANCE(cWeakKing, H1) <= 1))
{
goto draw;
@@ -983,6 +992,7 @@ Return value:
}
+// BUG: 7k/8/5KP1/8/8/8/8/8 w - -
static ULONG
_RecognizeKPK(IN SEARCHER_THREAD_CONTEXT *ctx,
IN OUT SCORE *piScore)
@@ -1012,8 +1022,8 @@ Return value:
PAWN_HASH_ENTRY *pHash;
POSITION *pos = &ctx->sPosition;
- ASSERT(pos->uNonPawnCount[WHITE][0] == 1);
- ASSERT(pos->uNonPawnCount[BLACK][0] == 1);
+ ASSERT(TotalNonPawnCount(pos, WHITE) == 1);
+ ASSERT(TotalNonPawnCount(pos, BLACK) == 1);
ASSERT(_NothingBut(pos, PAWN, WHITE));
ASSERT(_NothingBut(pos, PAWN, BLACK));
@@ -1064,7 +1074,7 @@ Return value:
//
// No one has a winning passer or we did not find the hash entry.
//
- if ((pos->uPawnCount[WHITE] > 0) && (pos->uPawnCount[BLACK] > 0))
+ if ((FastCountBits(pos->bbPawns[WHITE]) > 0) && (FastCountBits(pos->bbPawns[BLACK]) > 0))
{
return(UNRECOGNIZED);
}
@@ -1076,15 +1086,15 @@ Return value:
// draw for the weak side.
//
uStrong = WHITE;
- if (pos->uPawnCount[WHITE] == 0)
+ if (FastCountBits(pos->bbPawns[WHITE]) == 0)
{
uStrong = BLACK;
}
- ASSERT(pos->uPawnCount[uStrong] > 0);
+ ASSERT(FastCountBits(pos->bbPawns[uStrong]) > 0);
uWeak = FLIP(uStrong);
- ASSERT(pos->uPawnCount[uWeak] == 0);
+ ASSERT(FastCountBits(pos->bbPawns[uWeak]) == 0);
- if (pos->uPawnCount[uStrong] > 1)
+ if (FastCountBits(pos->bbPawns[uStrong]) > 1)
{
*piScore = 0;
if (pos->uToMove == uStrong)
@@ -1099,8 +1109,8 @@ Return value:
// sophisticated analysis here to spot winning KPK
// configurations earlier by using "critical squares"
//
- ASSERT(pos->uPawnCount[uStrong] == 1);
- cPawn = pos->cPawns[uStrong][0];
+ ASSERT(FastCountBits(pos->bbPawns[uStrong]) == 1);
+ cPawn = CoorOfSingleBit(pos->bbPawns[uStrong]);
ASSERT(IS_ON_BOARD(cPawn));
ASSERT(IS_PAWN(pos->rgSquare[cPawn].pPiece));
@@ -1108,9 +1118,9 @@ Return value:
// Step 1: the strong king must be closer to the pawn than
// the weak king.
//
- uDist[uStrong] = DISTANCE(pos->cNonPawns[uStrong][0], cPawn);
+ uDist[uStrong] = DISTANCE(KingPosition(pos, uStrong), cPawn);
ASSERT((1 <= uDist[uStrong]) && (uDist[uStrong] <= 7));
- uDist[uWeak] = DISTANCE(pos->cNonPawns[uWeak][0], cPawn);
+ uDist[uWeak] = DISTANCE(KingPosition(pos, uWeak), cPawn);
ASSERT((1 <= uDist[uWeak]) && (uDist[uWeak] <= 7));
if (uDist[uStrong] <= uDist[uWeak])
{
@@ -1121,10 +1131,10 @@ Return value:
_GetPassersCriticalSquares(uStrong, cPawn, cCritical);
for (u = 0; u < 3; u++)
{
- uDist[uStrong] = DISTANCE(pos->cNonPawns[uStrong][0],
+ uDist[uStrong] = DISTANCE(KingPosition(pos, uStrong),
cCritical[u]);
ASSERT((0 <= uDist[uStrong]) && (uDist[uStrong] <= 7));
- uDist[uWeak] = DISTANCE(pos->cNonPawns[uWeak][0],
+ uDist[uWeak] = DISTANCE(KingPosition(pos, uWeak),
cCritical[u]);
//
@@ -1333,19 +1343,19 @@ Return value:
//
// Try interior node recognizers
//
- if ((pos->uNonPawnCount[WHITE][0] <= 3) &&
- (pos->uNonPawnCount[BLACK][0] <= 3))
+ if ((TotalNonPawnCount(pos, WHITE) <= 3) &&
+ (TotalNonPawnCount(pos, BLACK) <= 3))
{
- uSig[BLACK] = _MakeMaterialSig((pos->uPawnCount[BLACK] > 0),
- (pos->uNonPawnCount[BLACK][KNIGHT] > 0),
- (pos->uNonPawnCount[BLACK][BISHOP] > 0),
- (pos->uNonPawnCount[BLACK][ROOK] > 0),
- (pos->uNonPawnCount[BLACK][QUEEN] > 0));
- uSig[WHITE] = _MakeMaterialSig((pos->uPawnCount[WHITE] > 0),
- (pos->uNonPawnCount[WHITE][KNIGHT] > 0),
- (pos->uNonPawnCount[WHITE][BISHOP] > 0),
- (pos->uNonPawnCount[WHITE][ROOK] > 0),
- (pos->uNonPawnCount[WHITE][QUEEN] > 0));
+ uSig[BLACK] = _MakeMaterialSig((FastCountBits(pos->bbPawns[BLACK]) > 0),
+ (FastCountBits(pos->bbPieces[BLACK][KNIGHT]) > 0),
+ (FastCountBits(pos->bbPieces[BLACK][BISHOP]) > 0),
+ (FastCountBits(pos->bbPieces[BLACK][ROOK]) > 0),
+ (FastCountBits(pos->bbPieces[BLACK][QUEEN]) > 0));
+ uSig[WHITE] = _MakeMaterialSig((FastCountBits(pos->bbPawns[WHITE]) > 0),
+ (FastCountBits(pos->bbPieces[WHITE][KNIGHT]) > 0),
+ (FastCountBits(pos->bbPieces[WHITE][BISHOP]) > 0),
+ (FastCountBits(pos->bbPieces[WHITE][ROOK]) > 0),
+ (FastCountBits(pos->bbPieces[WHITE][QUEEN]) > 0));
pRec = g_pRecognizers[RECOGN_INDEX(uSig[WHITE], uSig[BLACK])];
if (NULL != pRec)
{