X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=f6764b18466ae4ad010f3ec57b7ed105b1314f04;hp=0022ae4c26d28fcae3d329032d730a627b1ed9e9;hb=c3af52c43bc91ef15fea6c0bedd556754412f737;hpb=52f92d05a9eae0cc68a3cd157f8df35802a98297 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 0022ae4c..f6764b18 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -165,16 +165,18 @@ namespace { // Assorted bonuses and penalties const Score BishopPawns = S( 8, 12); const Score CloseEnemies = S( 7, 0); + const Score Connectivity = S( 3, 1); const Score Hanging = S( 52, 30); const Score HinderPassedPawn = S( 8, 1); + const Score KnightOnQueen = S( 21, 11); 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 SliderOnQueen = S( 42, 21); 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); @@ -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, @@ -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 @@ -306,16 +305,13 @@ namespace { : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK)) : pos.attacks_from(s); - if (pos.pinned_pieces(Us) & s) + if (pos.blockers_for_king(Us) & s) b &= LineBB[pos.square(Us)][s]; attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b; 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]++; @@ -392,8 +388,8 @@ namespace { if (Pt == QUEEN) { // Penalty if any relative pin or discovered attack against the queen - Bitboard pinners; - if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners)) + Bitboard queenPinners; + if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, queenPinners)) score -= WeakQueen; } } @@ -413,7 +409,7 @@ namespace { : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB); const Square ksq = pos.square(Us); - Bitboard weak, b, b1, b2, safe, unsafeChecks; + Bitboard weak, b, b1, b2, safe, unsafeChecks, pinned; // King shelter and enemy pawns storm Score score = pe->king_safety(pos, ksq); @@ -464,11 +460,12 @@ namespace { // Unsafe or occupied checking squares will also be considered, as long as // the square is in the attacker's mobility area. unsafeChecks &= mobilityArea[Them]; + pinned = pos.blockers_for_king(Us) & pos.pieces(Us); kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them] + 102 * kingAdjacentZoneAttacksCount[Them] + 191 * popcount(kingRing[Us] & weak) - + 143 * popcount(pos.pinned_pieces(Us) | unsafeChecks) + + 143 * popcount(pinned | unsafeChecks) - 848 * !pos.count(Them) - 9 * mg_value(score) / 8 + 40; @@ -481,22 +478,20 @@ namespace { score -= make_score(kingDanger * kingDanger / 4096, kingDanger / 16); } } - // Penalty when our king is on a pawnless flank - if (!(pos.pieces(PAWN) & KingFlank[file_of(ksq)])) - score -= PawnlessFlank; - // King tropism: firstly, find attacked squares in our king flank - b = attackedBy[Them][ALL_PIECES] & KingFlank[file_of(ksq)] & Camp; + Bitboard kf = KingFlank[file_of(ksq)]; - assert(((Us == WHITE ? b << 4 : b >> 4) & b) == 0); - assert(popcount(Us == WHITE ? b << 4 : b >> 4) == popcount(b)); + // Penalty when our king is on a pawnless flank + if (!(pos.pieces(PAWN) & kf)) + score -= PawnlessFlank; - // Secondly, add the squares which are attacked twice in that flank and - // which are not defended by our pawns. - b = (Us == WHITE ? b << 4 : b >> 4) - | (b & attackedBy2[Them] & ~attackedBy[Us][PAWN]); + // 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]; - score -= CloseEnemies * popcount(b); + // King tropism, to anticipate slow motion attacks on our king + score -= CloseEnemies * (popcount(b1) + popcount(b2)); if (T) Trace::add(KING, Us, score); @@ -510,9 +505,9 @@ namespace { template template Score Evaluation::threats() const { - const Color Them = (Us == WHITE ? BLACK : WHITE); - const Direction Up = (Us == WHITE ? NORTH : SOUTH); - const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); + const Color Them = (Us == WHITE ? BLACK : WHITE); + const Direction Up = (Us == WHITE ? NORTH : SOUTH); + const Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB); Bitboard b, weak, defended, nonPawnEnemies, stronglyProtected, safeThreats; Score score = SCORE_ZERO; @@ -589,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; - score += ThreatOnQueen * popcount(b & safeThreats); + b = attackedBy[Us][KNIGHT] & pos.attacks_from(s); + + score += KnightOnQueen * 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); @@ -727,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) @@ -879,7 +884,8 @@ namespace { Trace::add(TOTAL, score); } - return pos.side_to_move() == WHITE ? v : -v; // Side to move point of view + return (pos.side_to_move() == WHITE ? v : -v) // Side to move point of view + + Eval::Tempo; } } // namespace @@ -889,7 +895,7 @@ namespace { /// evaluation of the position from the point of view of the side to move. Value Eval::evaluate(const Position& pos) { - return Evaluation(pos).value() + Eval::Tempo; + return Evaluation(pos).value(); } @@ -903,7 +909,7 @@ std::string Eval::trace(const Position& pos) { Eval::Contempt = SCORE_ZERO; // Reset any dynamic contempt - Value v = Evaluation(pos).value() + Eval::Tempo; + Value v = Evaluation(pos).value(); v = pos.side_to_move() == WHITE ? v : -v; // Trace scores are from white's point of view