X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fevaluate.cpp;h=a1a120435a8d38194bc306a1f7b2917a77f779b9;hp=fb11b262fd7877bc453bed1976a15d5d8aac804a;hb=e6310b3469b07b6bbecf8d8f75367a655090f22b;hpb=966bc477af9eae9be63b08111a76e8306263e4a3 diff --git a/src/evaluate.cpp b/src/evaluate.cpp index fb11b262..a1a12043 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -124,23 +124,11 @@ namespace { S( 94, 99), S( 96,100), S(99,111), S(99,112) } }; - // Outpost[Bishop/Knight][Square] contains bonuses for knights and bishops - // outposts, indexed by piece type and square (from white's point of view). - const Value Outpost[][SQUARE_NB] = { - {// A B C D E F G H - V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // Knights - V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), - V(0), V(0), V(3), V(9), V(9), V(3), V(0), V(0), - V(0), V(4),V(18),V(25),V(25),V(18), V(4), V(0), - V(4), V(9),V(29),V(38),V(38),V(29), V(9), V(4), - V(2), V(9),V(19),V(15),V(15),V(19), V(9), V(2) }, - { - V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), // Bishops - V(0), V(0), V(0), V(0), V(0), V(0), V(0), V(0), - V(2), V(4), V(3), V(8), V(8), V(3), V(4), V(2), - V(1), V(9), V(9),V(13),V(13), V(9), V(9), V(1), - V(2), V(8),V(21),V(24),V(24),V(21), V(8), V(2), - V(0), V(4), V(6), V(6), V(6), V(6), V(4), V(0) } + // 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(28, 7), S(42,11) }, // Knights + { S(12, 3), S(18, 5) } // Bishops }; // Threat[defended/weak][minor/major attacking][attacked PieceType] contains @@ -158,6 +146,8 @@ namespace { S(0, 0), S(0, 0), S(107, 138), S(84, 122), S(114, 203), S(121, 217) }; + const Score ThreatenedByHangingPawn = S(40, 60); + // Assorted bonuses and penalties used by evaluation const Score KingOnOne = S( 2, 58); const Score KingOnMany = S( 6,125); @@ -218,7 +208,7 @@ namespace { ei.pinnedPieces[Us] = pos.pinned_pieces(Us); ei.attackedBy[Us][ALL_PIECES] = ei.attackedBy[Us][PAWN] = ei.pi->pawn_attacks(Us); - Bitboard b = ei.attackedBy[Them][KING] = pos.attacks_from(pos.king_square(Them)); + Bitboard b = ei.attackedBy[Them][KING] = pos.attacks_from(pos.square(Them)); // Init king safety tables only if we are going to use them if (pos.non_pawn_material(Us) >= QueenValueMg) @@ -233,33 +223,6 @@ namespace { } - // evaluate_outpost() evaluates bishop and knight outpost squares - - template - Score evaluate_outpost(const Position& pos, const EvalInfo& ei, Square s) { - - const Color Them = (Us == WHITE ? BLACK : WHITE); - - assert (Pt == BISHOP || Pt == KNIGHT); - - // Initial bonus based on square - Value bonus = Outpost[Pt == BISHOP][relative_square(Us, s)]; - - // Increase bonus if supported by pawn, especially if the opponent has - // no minor piece which can trade with the outpost piece. - if (bonus && (ei.attackedBy[Us][PAWN] & s)) - { - if ( !pos.pieces(Them, KNIGHT) - && !(squares_of_color(s) & pos.pieces(Them, BISHOP))) - bonus += bonus + bonus / 2; - else - bonus += bonus / 2; - } - - return make_score(bonus * 2, bonus / 2); - } - - // evaluate_pieces() assigns bonuses and penalties to the pieces of a given color template @@ -271,7 +234,7 @@ namespace { const PieceType NextPt = (Us == WHITE ? Pt : PieceType(Pt + 1)); const Color Them = (Us == WHITE ? BLACK : WHITE); - const Square* pl = pos.list(Us); + const Square* pl = pos.squares(Us); ei.attackedBy[Us][Pt] = 0; @@ -283,7 +246,7 @@ namespace { : pos.attacks_from(s); if (ei.pinnedPieces[Us] & s) - b &= LineBB[pos.king_square(Us)][s]; + b &= LineBB[pos.square(Us)][s]; ei.attackedBy[Us][ALL_PIECES] |= ei.attackedBy[Us][Pt] |= b; @@ -305,16 +268,12 @@ namespace { mobility[Us] += MobilityBonus[Pt][mob]; - // Decrease score if we are attacked by an enemy pawn. The remaining part - // of threat evaluation must be done later when we have full attack info. - if (ei.attackedBy[Them][PAWN] & s) - score -= ThreatenedByPawn[Pt]; - if (Pt == BISHOP || Pt == KNIGHT) { // Bonus for outpost square - if (!(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s))) - score += evaluate_outpost(pos, ei, s); + if ( relative_rank(Us, s) >= RANK_4 + && !(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s))) + score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)]; // Bonus when behind a pawn if ( relative_rank(Us, s) < RANK_5 @@ -357,7 +316,7 @@ namespace { // Penalize when trapped by the king, even more if king cannot castle if (mob <= 3 && !ei.pi->semiopen_file(Us, file_of(s))) { - Square ksq = pos.king_square(Us); + Square ksq = pos.square(Us); if ( ((file_of(ksq) < FILE_E) == (file_of(s) < file_of(ksq))) && (rank_of(ksq) == rank_of(s) || relative_rank(Us, ksq) == RANK_1) @@ -389,7 +348,7 @@ namespace { Bitboard undefended, b, b1, b2, safe; int attackUnits; - const Square ksq = pos.king_square(Us); + const Square ksq = pos.square(Us); // King shelter and enemy pawns storm Score score = ei.pi->king_safety(pos, ksq); @@ -441,7 +400,7 @@ namespace { { // ...and then remove squares not supported by another enemy piece b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT] - | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][QUEEN]); + | ei.attackedBy[Them][BISHOP]); if (b) attackUnits += RookContactCheck * popcount(b); @@ -501,9 +460,26 @@ namespace { enum { Defended, Weak }; enum { Minor, Major }; - Bitboard b, weak, defended; + Bitboard b, weak, defended, safeThreats; Score score = SCORE_ZERO; + // Non-pawn enemies attacked by a pawn + weak = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Us][PAWN]; + + if (weak) + { + b = pos.pieces(Us, PAWN) & ( ~ei.attackedBy[Them][ALL_PIECES] + | ei.attackedBy[Us][ALL_PIECES]); + + safeThreats = (shift_bb(b) | shift_bb(b)) & weak; + + if (weak ^ safeThreats) + score += ThreatenedByHangingPawn; + + while (safeThreats) + score += ThreatenedByPawn[type_of(pos.piece_on(pop_lsb(&safeThreats)))]; + } + // Non-pawn enemies defended by a pawn defended = (pos.pieces(Them) ^ pos.pieces(Them, PAWN)) & ei.attackedBy[Them][PAWN]; @@ -599,12 +575,12 @@ namespace { Square blockSq = s + pawn_push(Us); // Adjust bonus based on the king's proximity - ebonus += distance(pos.king_square(Them), blockSq) * 5 * rr - - distance(pos.king_square(Us ), blockSq) * 2 * rr; + ebonus += distance(pos.square(Them), blockSq) * 5 * rr + - distance(pos.square(Us ), blockSq) * 2 * rr; // If blockSq is not the queening square then consider also a second push if (relative_rank(Us, blockSq) != RANK_8) - ebonus -= distance(pos.king_square(Us), blockSq + pawn_push(Us)) * rr; + ebonus -= distance(pos.square(Us), blockSq + pawn_push(Us)) * rr; // If the pawn is free to advance, then increase the bonus if (pos.empty(blockSq)) @@ -725,9 +701,18 @@ namespace { ei.attackedBy[WHITE][ALL_PIECES] |= ei.attackedBy[WHITE][KING]; ei.attackedBy[BLACK][ALL_PIECES] |= ei.attackedBy[BLACK][KING]; - // Do not include in mobility squares protected by enemy pawns or occupied by our pawns or king - Bitboard mobilityArea[] = { ~(ei.attackedBy[BLACK][PAWN] | pos.pieces(WHITE, PAWN, KING)), - ~(ei.attackedBy[WHITE][PAWN] | pos.pieces(BLACK, PAWN, KING)) }; + // Pawns blocked or on ranks 2 and 3. Will be excluded from the mobility area + Bitboard blockedPawns[] = { + pos.pieces(WHITE, PAWN) & (shift_bb(pos.pieces()) | Rank2BB | Rank3BB), + pos.pieces(BLACK, PAWN) & (shift_bb(pos.pieces()) | Rank7BB | Rank6BB) + }; + + // Do not include in mobility squares protected by enemy pawns, or occupied + // by our blocked pawns or king. + Bitboard mobilityArea[] = { + ~(ei.attackedBy[BLACK][PAWN] | blockedPawns[WHITE] | pos.square(WHITE)), + ~(ei.attackedBy[WHITE][PAWN] | blockedPawns[BLACK] | pos.square(BLACK)) + }; // Evaluate pieces and mobility score += evaluate_pieces(pos, ei, mobility, mobilityArea); @@ -787,7 +772,7 @@ namespace { // pawns are drawish. else if ( abs(eg_value(score)) <= BishopValueEg && ei.pi->pawn_span(strongSide) <= 1 - && !pos.pawn_passed(~strongSide, pos.king_square(~strongSide))) + && !pos.pawn_passed(~strongSide, pos.square(~strongSide))) sf = ei.pi->pawn_span(strongSide) ? ScaleFactor(56) : ScaleFactor(38); }