X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=09f06d2983e0b644bf9dadd94fa6efc7baae1051;hp=a63b40ae98403a69153a2782c1bd066c75f2d153;hb=20023ac9b8c28d8b15308d7bf5be4fad8501535d;hpb=24dac5ccd309837c6767dcf6b145be385eea2e21 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index a63b40ae..09f06d29 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -24,7 +24,7 @@ #include #include -#include "bitcount.h" +#include "bitboard.h" #include "evaluate.h" #include "material.h" #include "pawns.h" @@ -132,21 +132,21 @@ namespace { // Outpost[knight/bishop][supported by pawn] contains bonuses for knights and // bishops outposts, bigger if outpost piece is supported by a pawn. const Score Outpost[][2] = { - { S(42,11), S(63,17) }, // Knights - { S(18, 5), S(27, 8) } // Bishops + { S(43,11), S(65,20) }, // Knights + { S(20, 3), S(29, 8) } // Bishops }; // ReachableOutpost[knight/bishop][supported by pawn] contains bonuses for // knights and bishops which can reach an outpost square in one move, bigger // if outpost square is supported by a pawn. const Score ReachableOutpost[][2] = { - { S(21, 5), S(31, 8) }, // Knights - { S( 8, 2), S(13, 4) } // Bishops + { S(21, 5), S(35, 8) }, // Knights + { S( 8, 0), S(14, 4) } // Bishops }; // RookOnFile[semiopen/open] contains bonuses for each rook when there is no // friendly pawn on the rook file. - const Score RookOnFile[2] = { S(19, 10), S(43, 21) }; + const Score RookOnFile[2] = { S(20, 7), S(45, 20) }; // ThreatBySafePawn[PieceType] contains bonuses according to which piece // type is attacked by a pawn which is protected or is not attacked. @@ -181,13 +181,15 @@ namespace { // Assorted bonuses and penalties used by evaluation const Score MinorBehindPawn = S(16, 0); const Score BishopPawns = S( 8, 12); - const Score RookOnPawn = S( 7, 27); + const Score RookOnPawn = S( 8, 24); const Score TrappedRook = S(92, 0); - const Score Checked = S(20, 20); - const Score ThreatByHangingPawn = S(70, 63); + const Score SafeCheck = S(20, 20); + const Score OtherCheck = S(10, 10); + const Score ThreatByHangingPawn = S(71, 61); const Score LooseEnemies = S( 0, 25); - const Score Hanging = S(48, 28); - const Score ThreatByPawnPush = S(31, 19); + const Score WeakQueen = S(35, 0); + const Score Hanging = S(48, 27); + const Score ThreatByPawnPush = S(38, 22); const Score Unstoppable = S( 0, 20); // Penalty for a bishop on a1/h1 (a8/h8 for black) which is trapped by @@ -209,10 +211,10 @@ namespace { // Penalties for enemy's safe checks const int QueenContactCheck = 89; - const int QueenCheck = 50; - const int RookCheck = 45; - const int BishopCheck = 6; - const int KnightCheck = 14; + const int QueenCheck = 62; + const int RookCheck = 57; + const int BishopCheck = 48; + const int KnightCheck = 78; // eval_init() initializes king and attack bitboards for a given color @@ -234,7 +236,7 @@ namespace { { ei.kingRing[Them] = b | shift_bb(b); b &= ei.attackedBy[Us][PAWN]; - ei.kingAttackersCount[Us] = b ? popcount(b) : 0; + ei.kingAttackersCount[Us] = popcount(b); ei.kingAdjacentZoneAttacksCount[Us] = ei.kingAttackersWeight[Us] = 0; } else @@ -276,9 +278,7 @@ namespace { { ei.kingAttackersCount[Us]++; ei.kingAttackersWeight[Us] += KingAttackWeights[Pt]; - bb = b & ei.attackedBy[Them][KING]; - if (bb) - ei.kingAdjacentZoneAttacksCount[Us] += popcount(bb); + ei.kingAdjacentZoneAttacksCount[Us] += popcount(b & ei.attackedBy[Them][KING]); } if (Pt == QUEEN) @@ -286,7 +286,7 @@ namespace { | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]); - int mob = popcount(b & mobilityArea[Us]); + int mob = popcount(b & mobilityArea[Us]); mobility[Us] += MobilityBonus[Pt][mob]; @@ -331,11 +331,7 @@ namespace { { // Bonus for aligning with enemy pawns on the same rank/file if (relative_rank(Us, s) >= RANK_5) - { - Bitboard alignedPawns = pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]; - if (alignedPawns) - score += RookOnPawn * popcount(alignedPawns); - } + score += RookOnPawn * popcount(pos.pieces(Them, PAWN) & PseudoAttacks[ROOK][s]); // Bonus when on an open or semi-open file if (ei.pi->semiopen_file(Us, file_of(s))) @@ -372,9 +368,10 @@ namespace { template Score evaluate_king(const Position& pos, const EvalInfo& ei) { - const Color Them = (Us == WHITE ? BLACK : WHITE); + const Color Them = (Us == WHITE ? BLACK : WHITE); + const Square Up = (Us == WHITE ? DELTA_N : DELTA_S); - Bitboard undefended, b, b1, b2, safe; + Bitboard undefended, b, b1, b2, safe, other; int attackUnits; const Square ksq = pos.square(Us); @@ -384,14 +381,17 @@ namespace { // Main king safety evaluation if (ei.kingAttackersCount[Them]) { - // Find the attacked squares around the king which have no defenders - // apart from the king itself. + // Find the attacked squares which are defended only by the king... undefended = ei.attackedBy[Them][ALL_PIECES] & ei.attackedBy[Us][KING] & ~( ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT] | ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK] | ei.attackedBy[Us][QUEEN]); + // ... and those which are not defended at all in the larger king ring + b = ei.attackedBy[Them][ALL_PIECES] & ~ei.attackedBy[Us][ALL_PIECES] + & ei.kingRing[Us] & ~pos.pieces(Them); + // Initialize the 'attackUnits' variable, which is used later on as an // index into the KingDanger[] array. The initial value is based on the // number and types of the enemy's attacking pieces, the number of @@ -399,8 +399,8 @@ namespace { // the pawn shelter (current 'score' value). attackUnits = std::min(72, ei.kingAttackersCount[Them] * ei.kingAttackersWeight[Them]) + 9 * ei.kingAdjacentZoneAttacksCount[Them] - + 27 * popcount(undefended) - + 11 * !!ei.pinnedPieces[Us] + + 21 * popcount(undefended) + + 12 * (popcount(b) + !!ei.pinnedPieces[Us]) - 64 * !pos.count(Them) - mg_value(score) / 8; @@ -414,31 +414,45 @@ namespace { | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK] | ei.attackedBy[Them][KING]; - if (b) - attackUnits += QueenContactCheck * popcount(b); + attackUnits += QueenContactCheck * popcount(b); } - // Analyse the enemy's safe distance checks for sliders and knights - safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them)); + // Analyse the safe enemy's checks which are possible on next move... + safe = ~(ei.attackedBy[Us][ALL_PIECES] | pos.pieces(Them)); + + // ... and some other potential checks, only requiring the square to be + // safe from pawn-attacks, and not being occupied by a blocked pawn. + other = ~( ei.attackedBy[Us][PAWN] + | (pos.pieces(Them, PAWN) & shift_bb(pos.pieces(PAWN)))); - b1 = pos.attacks_from(ksq) & safe; - b2 = pos.attacks_from(ksq) & safe; + b1 = pos.attacks_from(ksq); + b2 = pos.attacks_from(ksq); // Enemy queen safe checks - if ((b1 | b2) & ei.attackedBy[Them][QUEEN]) - attackUnits += QueenCheck, score -= Checked; + if ((b1 | b2) & ei.attackedBy[Them][QUEEN] & safe) + attackUnits += QueenCheck, score -= SafeCheck; + + // Enemy rooks safe and other checks + if (b1 & ei.attackedBy[Them][ROOK] & safe) + attackUnits += RookCheck, score -= SafeCheck; - // Enemy rooks safe checks - if (b1 & ei.attackedBy[Them][ROOK]) - attackUnits += RookCheck, score -= Checked; + else if (b1 & ei.attackedBy[Them][ROOK] & other) + score -= OtherCheck; - // Enemy bishops safe checks - if (b2 & ei.attackedBy[Them][BISHOP]) - attackUnits += BishopCheck, score -= Checked; + // Enemy bishops safe and other checks + if (b2 & ei.attackedBy[Them][BISHOP] & safe) + attackUnits += BishopCheck, score -= SafeCheck; - // Enemy knights safe checks - if (pos.attacks_from(ksq) & ei.attackedBy[Them][KNIGHT] & safe) - attackUnits += KnightCheck, score -= Checked; + else if (b2 & ei.attackedBy[Them][BISHOP] & other) + score -= OtherCheck; + + // Enemy knights safe and other checks + b = pos.attacks_from(ksq) & ei.attackedBy[Them][KNIGHT]; + if (b & safe) + attackUnits += KnightCheck, score -= SafeCheck; + + else if (b & other) + score -= OtherCheck; // Finally, extract the king danger score from the KingDanger[] // array and subtract the score from the evaluation. @@ -475,6 +489,13 @@ namespace { & ~(ei.attackedBy[Us][ALL_PIECES] | ei.attackedBy[Them][ALL_PIECES])) score += LooseEnemies; + // Bonus for pin or discovered attack on the opponent queen + if ( pos.count(Them) == 1 + && pos.slider_blockers(pos.pieces(), + pos.pieces(Us, ROOK, BISHOP), + pos.square(Them))) + score += WeakQueen; + // Non-pawn enemies attacked by a pawn weak = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Us][PAWN]; @@ -511,9 +532,7 @@ namespace { while (b) score += Threat[Rook ][type_of(pos.piece_on(pop_lsb(&b)))]; - b = weak & ~ei.attackedBy[Them][ALL_PIECES]; - if (b) - score += Hanging * popcount(b); + score += Hanging * popcount(weak & ~ei.attackedBy[Them][ALL_PIECES]); b = weak & ei.attackedBy[Us][KING]; if (b) @@ -532,8 +551,7 @@ namespace { & pos.pieces(Them) & ~ei.attackedBy[Us][PAWN]; - if (b) - score += ThreatByPawnPush * popcount(b); + score += ThreatByPawnPush * popcount(b); if (DoTrace) Trace::add(THREAT, Us, score); @@ -611,9 +629,6 @@ namespace { mbonus += rr + r * 2, ebonus += rr + r * 2; } // rr != 0 - if (pos.count(Us) < pos.count(Them)) - ebonus += ebonus / 4; - score += make_score(mbonus, ebonus) + PassedFile[file_of(s)]; } @@ -656,7 +671,7 @@ namespace { 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((Us == WHITE ? safe << 32 : safe >> 32) | (behind & safe)); int weight = pos.count(Us) + pos.count(Us) + pos.count(Them) + pos.count(Them);