X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=fee181aeb2c61d9f564ca2d81ecad77ccefc9cf9;hp=0ee89e4d8236999815797272c92efe1c772c4c5e;hb=96362fe3df141eeead4bdb863d2bb2d891886abf;hpb=de642f16db0c443de2dc0ddf7b06c0a7d1c5b8b7 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 0ee89e4d..fee181ae 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -163,22 +163,24 @@ namespace { const Score KingProtector[] = { S(3, 5), S(4, 3), S(3, 0), S(1, -1) }; // Assorted bonuses and penalties - const Score BishopPawns = S( 8, 12); - const Score CloseEnemies = S( 7, 0); - const Score Hanging = S( 52, 30); - const Score HinderPassedPawn = S( 8, 1); - const Score LongRangedBishop = S( 22, 0); - const Score MinorBehindPawn = S( 16, 0); - const Score PawnlessFlank = S( 20, 80); - const Score RookOnPawn = S( 8, 24); - const Score ThreatByPawnPush = S( 47, 26); - const Score ThreatByRank = S( 16, 3); - const Score ThreatBySafePawn = S(175,168); - const Score ThreatOnQueen = S( 42, 21); - const Score TrappedBishopA1H1 = S( 50, 50); - const Score TrappedRook = S( 92, 0); - const Score WeakQueen = S( 50, 10); - const Score WeakUnopposedPawn = S( 5, 25); + const Score BishopPawns = S( 8, 12); + const Score CloseEnemies = S( 7, 0); + const Score Connectivity = S( 3, 1); + const Score CorneredBishop = S( 50, 50); + const Score Hanging = S( 52, 30); + const Score HinderPassedPawn = S( 8, 1); + const Score KnightOnQueen = S( 21, 11); + const Score LongDiagonalBishop = S( 22, 0); + const Score MinorBehindPawn = S( 16, 0); + const Score PawnlessFlank = S( 20, 80); + const Score RookOnPawn = S( 8, 24); + const Score SliderOnQueen = S( 42, 21); + const Score ThreatByPawnPush = S( 47, 26); + const Score ThreatByRank = S( 16, 3); + const Score ThreatBySafePawn = S(175,168); + const Score TrappedRook = S( 92, 0); + const Score WeakQueen = S( 50, 10); + const Score WeakUnopposedPawn = S( 5, 25); #undef S @@ -210,7 +212,7 @@ namespace { // attackedBy[color][piece type] is a bitboard representing all squares // attacked by a given color and piece type. Special "piece types" which - // are also calculated are QUEEN_DIAGONAL and ALL_PIECES. + // is also calculated is ALL_PIECES. Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB]; // attackedBy2[color] are the squares attacked by 2 pieces of a given color, @@ -228,18 +230,18 @@ namespace { // which attack a square in the kingRing of the enemy king. int kingAttackersCount[COLOR_NB]; - // kingAttackersWeight[color] is the sum of the "weights" of the pieces of the - // given color which attack a square in the kingRing of the enemy king. The - // weights of the individual piece types are given by the elements in the - // KingAttackWeights array. + // kingAttackersWeight[color] is the sum of the "weights" of the pieces of + // the given color which attack a square in the kingRing of the enemy king. + // The weights of the individual piece types are given by the elements in + // the KingAttackWeights array. int kingAttackersWeight[COLOR_NB]; - // kingAdjacentZoneAttacksCount[color] is the number of attacks by the given - // color to squares directly adjacent to the enemy king. Pieces which attack - // more than one square are counted multiple times. For instance, if there is + // kingAttacksCount[color] is the number of attacks by the given color to + // squares directly adjacent to the enemy king. Pieces which attack more + // than one square are counted multiple times. For instance, if there is // a white knight on g5 and black's king is on g8, this white knight adds 2 - // to kingAdjacentZoneAttacksCount[WHITE]. - int kingAdjacentZoneAttacksCount[COLOR_NB]; + // to kingAttacksCount[WHITE]. + int kingAttacksCount[COLOR_NB]; }; @@ -274,7 +276,7 @@ namespace { kingRing[Us] |= shift(kingRing[Us]); kingAttackersCount[Them] = popcount(attackedBy[Us][KING] & pe->pawn_attacks(Them)); - kingAdjacentZoneAttacksCount[Them] = kingAttackersWeight[Them] = 0; + kingAttacksCount[Them] = kingAttackersWeight[Them] = 0; } else kingRing[Us] = kingAttackersCount[Them] = 0; @@ -296,9 +298,6 @@ namespace { attackedBy[Us][Pt] = 0; - if (Pt == QUEEN) - attackedBy[Us][QUEEN_DIAGONAL] = 0; - while ((s = *pl++) != SQ_NONE) { // Find attacked squares, including x-ray attacks for bishops and rooks @@ -313,14 +312,11 @@ namespace { attackedBy[Us][Pt] |= b; attackedBy[Us][ALL_PIECES] |= b; - if (Pt == QUEEN) - attackedBy[Us][QUEEN_DIAGONAL] |= b & PseudoAttacks[BISHOP][s]; - if (b & kingRing[Them]) { kingAttackersCount[Us]++; kingAttackersWeight[Us] += KingAttackWeights[Pt]; - kingAdjacentZoneAttacksCount[Us] += popcount(b & attackedBy[Them][KING]); + kingAttacksCount[Us] += popcount(b & attackedBy[Them][KING]); } int mob = popcount(b & mobilityArea[Us]); @@ -352,7 +348,7 @@ namespace { // Bonus for bishop on a long diagonal which can "see" both center squares if (more_than_one(Center & (attacks_bb(s, pos.pieces(PAWN)) | s))) - score += LongRangedBishop; + score += LongDiagonalBishop; } // An important Chess960 pattern: A cornered bishop blocked by a friendly @@ -364,9 +360,9 @@ namespace { { Direction d = pawn_push(Us) + (file_of(s) == FILE_A ? EAST : WEST); if (pos.piece_on(s + d) == make_piece(Us, PAWN)) - score -= !pos.empty(s + d + pawn_push(Us)) ? TrappedBishopA1H1 * 4 - : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? TrappedBishopA1H1 * 2 - : TrappedBishopA1H1; + score -= !pos.empty(s + d + pawn_push(Us)) ? CorneredBishop * 4 + : pos.piece_on(s + d + d) == make_piece(Us, PAWN) ? CorneredBishop * 2 + : CorneredBishop; } } @@ -467,7 +463,7 @@ namespace { pinned = pos.blockers_for_king(Us) & pos.pieces(Us); kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them] - + 102 * kingAdjacentZoneAttacksCount[Them] + + 102 * kingAttacksCount[Them] + 191 * popcount(kingRing[Us] & weak) + 143 * popcount(pinned | unsafeChecks) - 848 * !pos.count(Them) @@ -489,7 +485,7 @@ namespace { if (!(pos.pieces(PAWN) & kf)) score -= PawnlessFlank; - // Find the squares that opponent attacks in our king flank, and the squares + // Find the squares that opponent attacks in our king flank, and the squares // which are attacked twice in that flank but not defended by our pawns. b1 = attackedBy[Them][ALL_PIECES] & kf & Camp; b2 = b1 & attackedBy2[Them] & ~attackedBy[Us][PAWN]; @@ -588,12 +584,25 @@ namespace { score += ThreatByPawnPush * popcount(b); - // Bonus for safe slider threats on the next move toward enemy queen - safeThreats = ~pos.pieces(Us) & ~attackedBy2[Them] & attackedBy2[Us]; - b = (attackedBy[Us][BISHOP] & attackedBy[Them][QUEEN_DIAGONAL]) - | (attackedBy[Us][ROOK ] & attackedBy[Them][QUEEN] & ~attackedBy[Them][QUEEN_DIAGONAL]); + // Bonus for threats on the next moves against enemy queen + if (pos.count(Them) == 1) + { + Square s = pos.square(Them); + safeThreats = mobilityArea[Us] & ~stronglyProtected; + + b = attackedBy[Us][KNIGHT] & pos.attacks_from(s); + + score += KnightOnQueen * popcount(b & safeThreats); - score += ThreatOnQueen * popcount(b & safeThreats); + b = (attackedBy[Us][BISHOP] & pos.attacks_from(s)) + | (attackedBy[Us][ROOK ] & pos.attacks_from(s)); + + score += SliderOnQueen * popcount(b & safeThreats & attackedBy2[Us]); + } + + // Connectivity: ensure that knights, bishops, rooks, and queens are protected + b = (pos.pieces(Us) ^ pos.pieces(Us, PAWN, KING)) & attackedBy[Us][ALL_PIECES]; + score += Connectivity * popcount(b); if (T) Trace::add(THREAT, Us, score); @@ -726,12 +735,9 @@ namespace { behind |= (Us == WHITE ? behind >> 8 : behind << 8); behind |= (Us == WHITE ? behind >> 16 : behind << 16); - // Since SpaceMask[Us] is fully on our half of the board... - assert(unsigned(safe >> (Us == WHITE ? 32 : 0)) == 0); - - // ...count safe + (behind & safe) with a single popcount. - int bonus = popcount((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe)); + int bonus = popcount(safe) + popcount(behind & safe); int weight = pos.count(Us) - 2 * pe->open_files(); + Score score = make_score(bonus * weight * weight / 16, 0); if (T) @@ -759,6 +765,7 @@ namespace { + 8 * pe->pawn_asymmetry() + 12 * pos.count() + 16 * pawnsOnBothFlanks + + 48 * !pos.non_pawn_material() -136 ; // Now apply the bonus: note that we find the attacking side by extracting