diff options
| author | Scott Gasch <[email protected]> | 2026-10-09 14:18:52 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-09 14:18:52 -0700 |
| commit | fbdcb9d76dd2444d8bc631331eaeb9435cc247f8 (patch) | |
| tree | 602ab360462d6f23188ba51f962c4abb2dc6c7e5 /src/eval.c | |
| parent | 73b4afb12abf7cc442831dea42b41b63a2ce07be (diff) | |
* Grab bag of eval.c changes.
* Don't bother not hashing when moves are pruned.
* Prune moves move librerally with LMP.
Inexplicably, this is slightly shallower than HEAD (despite pruning
MORE). It may be because it is slightly slower.
It consistently beats HEAD in match_play.py though (3x now).
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 298 |
1 files changed, 131 insertions, 167 deletions
@@ -95,7 +95,7 @@ static ULONG REDUCED_MATERIAL_DOWN_SCALER[32] = 0, 0, 0, 0, 0, 0, 0, 0, // Rm 3m/Q 2R R2m 4m/Qm 2Rm R3m/QR Q2m - 0, 1, 1, 1, 1, 1, 2, 3, + 0, 1, 1, 1, 2, 2, 2, 3, // 2R2m R4m/QRm Q3m 2R3m/ QR2m Q4m 2R4m/ QR3m // Q2R Q2Rm @@ -385,14 +385,13 @@ SCORE RACER_WINS_RACE = +300; static SCORE UNDEVELOPED_MINORS_IN_OPENING[5] = {// 0 1 2 3 4 - 0, -8, -14, -20, -23 + 0, -14, -18, -24, -30 }; // // Bishop eval terms // --------------------------------------------------------------------------- // -static SCORE BISHOP_OVER_KNIGHT_IN_ENDGAME = +33; // // "The bishop pair has an average value of half a pawn (more when the @@ -527,6 +526,7 @@ static SCORE KNIGHT_IN_CLOSED_POSITION[33] = static SCORE ROOK_ON_FULL_OPEN = 18; static SCORE ROOK_ON_HALF_OPEN_WITH_ENEMY = 9; static SCORE ROOK_ON_HALF_OPEN_WITH_FRIEND = 10; + // Cache of the three constants above, indexed [friend pawn on file?] // [enemy pawn on file?] so _EvalRook's hot path is a single array read // instead of rebuilding a local array every call. Not `static const` @@ -553,18 +553,6 @@ static SCORE ROOK_WITH_FRIEND_PASSER = 10; static const BITBOARD BBROOK_7TH_RANK[2] = { BBRANK22, BBRANK77 }; // [BLACK], [WHITE] static SCORE ROOK_ON_SEVENTH_BONUS = 9; -static SCORE ROOK_BEHIND_PASSER_BY_PASSER_RANK[2][9] = -{// 0 1 2 3 4 5 6 7 8 - { +0, +0, +25, +17, +12, +6, +1, +0, +0 }, // black - { +0, +0, +0, +1, +6, +12, +17, +25, +0 } // white -}; - -static SCORE ROOK_LEADS_PASSER_BY_PASSER_RANK[2][9] = -{// 0 1 2 3 4 5 6 7 8 - { +0, +0, -22, -16, -13, -9, -5, -3, +0 }, // black - { +0, +0, -3, -5, -9, -13, -16, -22, +0 } // white -}; - static SCORE ROOK_VALUE_AS_PAWNS_COME_OFF[17] = {// 0 1 2 3 4 5 6 7 8 +55, +51, +44, +38, +33, +27, +22, +16, +7, @@ -598,7 +586,6 @@ static SCORE ROOK_MOBILITY_BY_SQUARES[15] = // --------------------------------------------------------------------------- // - // // A queen can move to between 0..27 squares // ----------------------------------------- @@ -733,7 +720,7 @@ static SCORE KING_TO_CENTER[128] = // the stay-home bonus now uses this same threshold, so "safety scored" // and "stay-home bonus applies" are exactly the same condition. #define DO_KING_SAFETY_THRESHOLD \ - (VALUE_ROOK + VALUE_BISHOP + VALUE_KING + 1) + (VALUE_ROOK + VALUE_BISHOP + VALUE_BISHOP + VALUE_KING) static ULONG KING_COUNTER_BY_ATTACK_PATTERN[32] = { @@ -798,7 +785,7 @@ static SCORE KING_SAFETY_BY_COUNTER[42] = // another ~33% to -14/count. static SCORE KING_QUEEN_PROXIMITY_DANGER[7] = {// 0 1 2 3 4 5 6 - +0, -14, -28, -42, -56, -70, -84 + +0, -10, -18, -25, -32, -39, -55 }; static SCORE KING_MISSING_ONE_CASTLE_OPTION = -23; @@ -942,7 +929,6 @@ static DNA_BASE_SIZE g_EvalDNA[] = { DNA_ARRAY(PASSER_BONUS_AS_MATERIAL_COMES_OFF), DNA_VAR(RACER_WINS_RACE), DNA_ARRAY(UNDEVELOPED_MINORS_IN_OPENING), - DNA_VAR(BISHOP_OVER_KNIGHT_IN_ENDGAME), DNA_VAR(BISHOP_PAIR_BONUS), DNA_ARRAY(STATIONARY_PAWN_ON_BISHOP_COLOR), DNA_ARRAY(TRANSIENT_PAWN_ON_BISHOP_COLOR), @@ -961,8 +947,6 @@ static DNA_BASE_SIZE g_EvalDNA[] = { DNA_VAR(ROOK_WITH_ENEMY_PASSER), DNA_VAR(ROOK_WITH_FRIEND_PASSER), DNA_VAR(ROOK_ON_SEVENTH_BONUS), - DNA_MATRIX(ROOK_BEHIND_PASSER_BY_PASSER_RANK), - DNA_MATRIX(ROOK_LEADS_PASSER_BY_PASSER_RANK), DNA_ARRAY(ROOK_VALUE_AS_PAWNS_COME_OFF), DNA_VAR(ROOK_CONNECTED_VERT), DNA_VAR(ROOK_CONNECTED_HORIZ), @@ -2773,9 +2757,19 @@ Return value: { +0, +6, +3, +1, 0, 0, 0, 0 }; - static SCORE KingFileDefects[3] = + // Indexed by (fOwn << 1) | fEnemy: 0=open (neither side has a pawn + // here), 1=half-open toward the enemy only (their pawn gone, ours + // still there), 2=half-open toward us only (ours gone, theirs still + // there), 3=closed (both present). Previously collapsed 1 and 2 + // into a single "half-open" bucket (uCountPerFile[WHITE][u]>0) + + // (uCountPerFile[BLACK][u]>0) summed to 1 either way) -- split + // 2026-10-08 since the two cases aren't symmetric (an enemy pawn + // left behind is a real storming threat already priced by + // KingStormingPawnDefects below, whereas our own pawn being the + // only one left is comparatively mild). + static SCORE KingFileDefects[4] = { - -10, -5, 0 + -18, -10, -5, 0 }; // Old code's edge-file (a/h) kicker was a flat +1 counter-unit; // scaled by the same filestormopenfile-derived factor. @@ -2796,14 +2790,11 @@ Return value: continue; } u = FILE(cFileSq) + 1; - v = (pHash->uCountPerFile[WHITE][u] > 0) + - (pHash->uCountPerFile[BLACK][u] > 0); - ASSERT((v >= 0) && (v <= 2)); + v = ((pHash->uCountPerFile[uColor][u] > 0) << 1) | + (pHash->uCountPerFile[ufColor][u] > 0); + ASSERT(v <= 3); iScore += KingFileDefects[v]; - if ((v < 2) && ((u == 1) || (u == 8))) - { - iScore += KING_FILE_EDGE_KICKER; - } + iScore += ((v != 3) && ((u == 1) || (u == 8))) * KING_FILE_EDGE_KICKER; bb = pos->bbPawns[ufColor] & BBFILE[u - 1]; if (bb) { @@ -5100,19 +5091,6 @@ Return value: ASSERT(IS_ON_BOARD(cKing)); ASSERT(IS_KING(pos->rgSquare[cKing].pPiece)); - // Encourage enemy king tropism, but not too early. - if ((TRUE == pos->fCastled[uColor]) || (pos->uMinorsAtHome[uColor] <= 1)) - { - u = DISTANCE(c, cKing); - ASSERT((u <= 7) && (u > 0)); - EVAL_TERM(uColor, - QUEEN, - c, - pos->iScore[uColor], - QUEEN_KING_TROPISM[u], - "enemy king tropism"); - } - // // Do queen mobility (and update attack tables) -- two-pass // rook-direction/bishop-direction magic lookups, board_ @@ -5134,85 +5112,82 @@ Return value: // one case that's a *fewer*-cases asymmetry versus bishop, not // more), so the enemy side of each pass's continue-set is empty. // - { - BITBOARD bbEnemyOcc = _BuildFriendlySideBB(pos, xColor); - BITBOARD bbEnemyGE = pos->bbPieces[xColor][QUEEN] | - COOR_TO_BB(cKing); - // - // Enemy king attacks are also unsafe for the queen -- a free - // O(1) table lookup by king square, independent of eval order - // (unlike the enemy minor/rook attacks above, which do need - // both colors' knight/bishop/rook passes to finish first, and - // already have by queen's turn: see the eval call order in - // Eval() below). Only unsafe when the queen wouldn't be - // recaptured by something of our own first -- if a friendly - // pawn/minor/rook already covers that square, the king can't - // just take the queen for free. Every one of those tables (ours - // AND the enemy's) is fully populated by now: pawns, minors, - // and rooks all run their own eval pass before queen does. - // - BITBOARD bbUnsafeForQueen = pos->bbPawnAttacks[xColor] | - pos->bbMinorAttacks[xColor] | - pos->bbRookAttacks[xColor] | - (g_KingAttacksBB[cKing] & - ~(pos->bbPawnAttacks[uColor] | - pos->bbMinorAttacks[uColor] | - pos->bbRookAttacks[uColor])); - BITBOARD bbAttackTotal = 0; - BITBOARD bbXrayAccum = 0; - BITBOARD bbMobility = 0; - ULONG uPass; + BITBOARD bbEnemyOcc = _BuildFriendlySideBB(pos, xColor); + BITBOARD bbEnemyGE = pos->bbPieces[xColor][QUEEN] | + COOR_TO_BB(cKing); + // + // Enemy king attacks are also unsafe for the queen -- a free + // O(1) table lookup by king square, independent of eval order + // (unlike the enemy minor/rook attacks above, which do need + // both colors' knight/bishop/rook passes to finish first, and + // already have by queen's turn: see the eval call order in + // Eval() below). Only unsafe when the queen wouldn't be + // recaptured by something of our own first -- if a friendly + // pawn/minor/rook already covers that square, the king can't + // just take the queen for free. Every one of those tables (ours + // AND the enemy's) is fully populated by now: pawns, minors, + // and rooks all run their own eval pass before queen does. + // + BITBOARD bbUnsafeForQueen = pos->bbPawnAttacks[xColor] | + pos->bbMinorAttacks[xColor] | + pos->bbRookAttacks[xColor] | + (g_KingAttacksBB[cKing] & + ~(pos->bbPawnAttacks[uColor] | + pos->bbMinorAttacks[uColor] | + pos->bbRookAttacks[uColor])); + BITBOARD bbAttackTotal = 0; + BITBOARD bbXrayAccum = 0; + BITBOARD bbMobility = 0; - for (uPass = 0; uPass < 2; uPass++) - { - BITBOARD bbFriendContinue = (uPass == 0) ? - (pos->bbPieces[uColor][ROOK] | pos->bbPieces[uColor][QUEEN]) : - (pos->bbPieces[uColor][BISHOP] | pos->bbPieces[uColor][QUEEN]); - BITBOARD bbInitial = (uPass == 0) ? - _RookAttacksBB(c, pos->bbOccupied) : - _BishopAttacksBB(c, pos->bbOccupied); - BITBOARD bbExclude = 0; - BITBOARD bbSeen = 0; - BITBOARD bbLayer = bbInitial; - BITBOARD bbFirstLayerMask = 0; + ULONG uPass; + for (uPass = 0; uPass < 2; uPass++) + { + BITBOARD bbFriendContinue = (uPass == 0) ? + (pos->bbPieces[uColor][ROOK] | pos->bbPieces[uColor][QUEEN]) : + (pos->bbPieces[uColor][BISHOP] | pos->bbPieces[uColor][QUEEN]); + BITBOARD bbInitial = (uPass == 0) ? + _RookAttacksBB(c, pos->bbOccupied) : + _BishopAttacksBB(c, pos->bbOccupied); + BITBOARD bbExclude = 0; + BITBOARD bbSeen = 0; + BITBOARD bbLayer = bbInitial; + BITBOARD bbFirstLayerMask = 0; - bbAttackTotal |= bbInitial; + bbAttackTotal |= bbInitial; - for (;;) - { - BITBOARD bbNew = bbLayer & ~bbSeen; - BITBOARD bbBlockersHere = bbNew & pos->bbOccupied; - BITBOARD bbEmptyHere = bbNew & ~pos->bbOccupied; - BITBOARD bbFriendContinueHere = bbBlockersHere & - bbFriendContinue; - BITBOARD bbEnemyGEHere = bbBlockersHere & bbEnemyGE; - BITBOARD bbEnemyLEHere = bbBlockersHere & bbEnemyOcc & - ~bbEnemyGEHere; + for (;;) + { + BITBOARD bbNew = bbLayer & ~bbSeen; + BITBOARD bbBlockersHere = bbNew & pos->bbOccupied; + BITBOARD bbEmptyHere = bbNew & ~pos->bbOccupied; + BITBOARD bbFriendContinueHere = bbBlockersHere & + bbFriendContinue; + BITBOARD bbEnemyGEHere = bbBlockersHere & bbEnemyGE; + BITBOARD bbEnemyLEHere = bbBlockersHere & bbEnemyOcc & + ~bbEnemyGEHere; - bbSeen |= bbNew; - bbXrayAccum |= (bbNew & bbFirstLayerMask); - bbFirstLayerMask = ~(BITBOARD)0; + bbSeen |= bbNew; + bbXrayAccum |= (bbNew & bbFirstLayerMask); + bbFirstLayerMask = ~(BITBOARD)0; - bbMobility |= (bbEmptyHere & ~bbUnsafeForQueen) | - bbEnemyGEHere | - (bbEnemyLEHere & ~bbUnsafeForQueen); + bbMobility |= (bbEmptyHere & ~bbUnsafeForQueen) | + bbEnemyGEHere | + (bbEnemyLEHere & ~bbUnsafeForQueen); - if (!bbFriendContinueHere) - { - break; - } - bbExclude |= bbFriendContinueHere; - bbLayer = (uPass == 0) ? - _RookAttacksBB(c, pos->bbOccupied & ~bbExclude) : - _BishopAttacksBB(c, pos->bbOccupied & ~bbExclude); + if (!bbFriendContinueHere) + { + break; } + bbExclude |= bbFriendContinueHere; + bbLayer = (uPass == 0) ? + _RookAttacksBB(c, pos->bbOccupied & ~bbExclude) : + _BishopAttacksBB(c, pos->bbOccupied & ~bbExclude); } - pos->bbQueenAttacks[uColor] |= bbAttackTotal; - pos->bbQueenXrayAttacks[uColor] |= bbXrayAccum; - - uTotalMobility = FastCountBits(bbMobility); } + pos->bbQueenAttacks[uColor] |= bbAttackTotal; + pos->bbQueenXrayAttacks[uColor] |= bbXrayAccum; + uTotalMobility = FastCountBits(bbMobility); ASSERT(uTotalMobility <= 27); EVAL_TERM(uColor, QUEEN, @@ -5353,6 +5328,8 @@ Return value: (SCORE)KING_COUNTER_BY_ATTACK_PATTERN[bvPattern]; // Count how many ring squares are attacked by the enemy queen. + // Note: we remove queen-king tropism bonus from EvalQueen in + // favor of this. uQueenNearKing = FastCountBits( bbRing & (pos->bbQueenAttacks[xColor] | pos->bbQueenXrayAttacks[xColor]) ); @@ -5495,12 +5472,7 @@ Return value: pDump->uFileStormStormingPawn; #endif - // Unconditional within this whole function now -- KEEP_KING_AT_HOME_ - // THRESHOLD (a separate, stricter bar than DO_KING_SAFETY_THRESHOLD) - // used to gate this specifically, leaving a dead band between the - // two. Retired; see DO_KING_SAFETY_THRESHOLD's comment. - iSafety += KING_INITIAL_LOCATION_SCALE * - KING_EVAL_INITIAL_LOCATION[uColor][c]; + iSafety += KING_INITIAL_LOCATION_SCALE * KING_EVAL_INITIAL_LOCATION[uColor][c]; #ifdef KING_DEFECT_DUMP pDump->uInitialCounterByLocation = (ULONG)KING_EVAL_INITIAL_LOCATION[uColor][c]; @@ -5607,8 +5579,7 @@ Return value: 0, ILLEGAL_COOR, pos->iScore[uColor], - (SCORE)(((uRightsRemaining > 0) * - UNDEVELOPED_MINORS_IN_OPENING[pos->uMinorsAtHome[uColor]] * + (SCORE)((UNDEVELOPED_MINORS_IN_OPENING[pos->uMinorsAtHome[uColor]] * (SCORE)uDevelopmentScaler) / 8), "development"); @@ -5798,7 +5769,7 @@ Return value: // this king out. u = pos->uNonPawnMaterial[xColor]; ASSERT(u >= VALUE_KING); - if (u >= DO_KING_SAFETY_THRESHOLD) + if (u > DO_KING_SAFETY_THRESHOLD) { iKingScore = _EvalKingSafety(pos, c, pHash, ctx, uColor, xColor, bbRing); } @@ -6379,7 +6350,7 @@ Return value: // KNB vs KRP - the side with the pawn has the winning chances. // ULONG uAheadPawnCount = FastCountBits(pos->bbPawns[uAhead]); - ULONG uInverseBehindPieceCount = 9 - MINU(9, TotalNonPawnCount(pos, uBehind)); + ULONG uInverseBehindPieceCount = 11 - MINU(9, TotalNonPawnCount(pos, uBehind)); // // "No mating material" here means the SAME lone-minor-piece test // SideHasWinningChances (above) already uses: king + exactly one @@ -6426,6 +6397,7 @@ Return value: "don't trade pawns"); } +#if 0 static void _EvalLookForDanger(IN OUT SEARCHER_THREAD_CONTEXT *ctx) /** @@ -6479,6 +6451,7 @@ Return value: } } } +#endif static void @@ -6704,7 +6677,7 @@ Return value: FLAG FORCEINLINE SideHasWinningChances(IN POSITION *pos, - IN ULONG uSide) + IN ULONG uColor) /** Routine description: @@ -6744,20 +6717,13 @@ Return value: **/ { - ULONG uEnemy = FLIP(uSide); + ULONG xColor = FLIP(uColor); + ASSERT(IS_VALID_COLOR(uColor) && IS_VALID_COLOR(xColor)); INT iMajorDiff; INT iMinorDiff; - ULONG uSideKnights; - ULONG uSideBishops; - - // uSide's bishop count is needed by the wrong-bishop-fortress check - // immediately below (which must run BEFORE the "any pawn -> TRUE" - // early return that follows it) and is reused again later by the - // lone-minor/iMinorDiff/two-knights checks -- compute it once, up - // front. - uSideBishops = FastCountBits(pos->bbPieces[uSide][BISHOP]); + ULONG uColorKnights; + ULONG uColorBishops = FastCountBits(pos->bbPieces[uColor][BISHOP]); - // // Wrong-bishop rook-pawn fortress: a lone bishop + rook-pawn(s) (all // on the A- or H-file), with the bishop unable to control the // promotion square, is a known draw once the defending bare king @@ -6777,43 +6743,42 @@ Return value: // shrink), never used as a search-terminating bound the way // recogn.c's tighter dist<=1-only version is, so a wrong FALSE here // is tolerable in a way it would not be in recogn.c. - // - if ((2 == TotalNonPawnCount(pos, uSide)) && - (1 == uSideBishops) && - (1 == TotalNonPawnCount(pos, uEnemy)) && - (0 == FastCountBits(pos->bbPawns[uEnemy])) && - (FastCountBits(pos->bbPawns[uSide]) > 0)) + if ((2 == TotalNonPawnCount(pos, uColor)) && + (1 == uColorBishops) && + (1 == TotalNonPawnCount(pos, xColor)) && + (0 == FastCountBits(pos->bbPawns[xColor])) && + (FastCountBits(pos->bbPawns[uColor]) > 0)) { - BITBOARD bbPawns = pos->bbPawns[uSide]; + BITBOARD bbPawns = pos->bbPawns[uColor]; COOR cPromote = ILLEGAL_COOR; + ULONG uColorWhiteSquareBishopCount = WhiteSqBishopCount(pos, uColor); - if (uSide == WHITE) + if (uColor == WHITE) { - if (!(bbPawns & ~BBFILE[A]) && (WhiteSqBishopCount(pos, WHITE) == 0)) + if (!(bbPawns & ~BBFILE[A]) && (uColorWhiteSquareBishopCount == 0)) { cPromote = A8; } - else if (!(bbPawns & ~BBFILE[H]) && (WhiteSqBishopCount(pos, WHITE) == 1)) + else if (!(bbPawns & ~BBFILE[H]) && (uColorWhiteSquareBishopCount == 1)) { cPromote = H8; } } else { - if (!(bbPawns & ~BBFILE[A]) && (WhiteSqBishopCount(pos, BLACK) == 1)) + if (!(bbPawns & ~BBFILE[A]) && (uColorWhiteSquareBishopCount == 1)) { cPromote = A1; } - else if (!(bbPawns & ~BBFILE[H]) && (WhiteSqBishopCount(pos, BLACK) == 0)) + else if (!(bbPawns & ~BBFILE[H]) && (uColorWhiteSquareBishopCount == 0)) { cPromote = H1; } } - if (IS_ON_BOARD(cPromote)) { - COOR cWeakKing = KingPosition(pos, uEnemy); - int iTempo = (pos->uToMove == uEnemy) ? 1 : 0; + COOR cWeakKing = KingPosition(pos, xColor); + int iTempo = (pos->uToMove == xColor) ? 1 : 0; if (((int)DISTANCE(cWeakKing, cPromote) - iTempo) < 1) { return(FALSE); @@ -6825,7 +6790,7 @@ Return value: // A pawn always gives some winning chances (it can always try to // queen with support) -- nothing below applies. // - if (FastCountBits(pos->bbPawns[uSide]) > 0) + if (FastCountBits(pos->bbPawns[uColor]) > 0) { return(TRUE); } @@ -6833,15 +6798,15 @@ Return value: // uSide's knight count is read twice below (the lone-minor check // and the two-knights check); uSideBishops was already computed // above. - uSideKnights = FastCountBits(pos->bbPieces[uSide][KNIGHT]); + uColorKnights = FastCountBits(pos->bbPieces[uColor][KNIGHT]); // // No pawns and the only piece besides the king is a single minor: // never enough material to force mate (K+N or K+B vs anything is // never a forced win on material alone). // - if ((2 == TotalNonPawnCount(pos, uSide)) && - (1 == (uSideKnights + uSideBishops))) + if ((2 == TotalNonPawnCount(pos, uColor)) && + (1 == (uColorKnights + uColorBishops))) { return(FALSE); } @@ -6852,15 +6817,15 @@ Return value: // force a win either -- e.g. KRB vs KR can be held by the // defender with correct play. // - iMajorDiff = (INT)(FastCountBits(pos->bbPieces[uSide][ROOK]) + - 2 * FastCountBits(pos->bbPieces[uSide][QUEEN])) - - (INT)(FastCountBits(pos->bbPieces[uEnemy][ROOK]) + - 2 * FastCountBits(pos->bbPieces[uEnemy][QUEEN])); + iMajorDiff = (INT)(FastCountBits(pos->bbPieces[uColor][ROOK]) + + 2 * FastCountBits(pos->bbPieces[uColor][QUEEN])) - + (INT)(FastCountBits(pos->bbPieces[xColor][ROOK]) + + 2 * FastCountBits(pos->bbPieces[xColor][QUEEN])); if ((1 == iMajorDiff) || (-1 == iMajorDiff)) { - iMinorDiff = (INT)(FastCountBits(pos->bbPieces[uEnemy][KNIGHT]) + - FastCountBits(pos->bbPieces[uEnemy][BISHOP])) - - (INT)(uSideKnights + uSideBishops); + iMinorDiff = (INT)(FastCountBits(pos->bbPieces[xColor][KNIGHT]) + + FastCountBits(pos->bbPieces[xColor][BISHOP])) - + (INT)(uColorKnights + uColorBishops); if (iMajorDiff == iMinorDiff) { return(FALSE); @@ -6875,16 +6840,15 @@ Return value: // excluded, since that has one bishop, not zero) -- both are // genuine, if sometimes technique-heavy, forced wins. // - if ((2 == uSideKnights) && - (0 == uSideBishops) && - (0 == FastCountBits(pos->bbPieces[uSide][ROOK])) && - (0 == FastCountBits(pos->bbPieces[uSide][QUEEN])) && - (1 == TotalNonPawnCount(pos, uEnemy)) && - (0 == FastCountBits(pos->bbPawns[uEnemy]))) + if ((2 == uColorKnights) && + (0 == uColorBishops) && + (0 == FastCountBits(pos->bbPieces[uColor][ROOK])) && + (0 == FastCountBits(pos->bbPieces[uColor][QUEEN])) && + (1 == TotalNonPawnCount(pos, xColor)) && + (0 == FastCountBits(pos->bbPawns[xColor]))) { return(FALSE); } - return(TRUE); } |
