X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fpawns.cpp;h=c3f7872f9e7bb38ec40bc3d9134e7a57de7e11eb;hp=8022ae51c20d811adac0d0cb22d8208af8515e1b;hb=7f623206f413b96170d432b401fe3c647325d01a;hpb=e6f4b5f46344d638c5e3b27cdbc966899e80e8d6 diff --git a/src/pawns.cpp b/src/pawns.cpp index 8022ae51..c3f7872f 100644 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@ -2,7 +2,7 @@ Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad - Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad + Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,10 +56,10 @@ namespace { // is behind our king. Note that UnblockedStorm[0][1-2] accommodate opponent pawn // on edge, likely blocked by our king. constexpr Value UnblockedStorm[int(FILE_NB) / 2][RANK_NB] = { - { V( 89), V(-285), V(-185), V(93), V(57), V( 45), V( 51) }, - { V( 44), V( -18), V( 123), V(46), V(39), V( -7), V( 23) }, - { V( 4), V( 52), V( 162), V(37), V( 7), V(-14), V( -2) }, - { V(-10), V( -14), V( 90), V(15), V( 2), V( -7), V(-16) } + { V( 85), V(-289), V(-166), V(97), V(50), V( 45), V( 50) }, + { V( 46), V( -25), V( 122), V(45), V(37), V(-10), V( 20) }, + { V( -6), V( 51), V( 168), V(34), V(-2), V(-22), V(-14) }, + { V(-15), V( -11), V( 101), V( 4), V(11), V(-15), V(-29) } }; #undef S @@ -69,10 +69,10 @@ namespace { Score evaluate(const Position& pos, Pawns::Entry* e) { constexpr Color Them = (Us == WHITE ? BLACK : WHITE); - constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH); + constexpr Direction Up = pawn_push(Us); Bitboard neighbours, stoppers, support, phalanx, opposed; - Bitboard lever, leverPush; + Bitboard lever, leverPush, blocked; Square s; bool backward, passed, doubled; Score score = SCORE_ZERO; @@ -83,9 +83,9 @@ namespace { Bitboard doubleAttackThem = pawn_double_attacks_bb(theirPawns); - e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0; + e->passedPawns[Us] = 0; e->kingSquares[Us] = SQ_NONE; - e->pawnAttacks[Us] = pawn_attacks_bb(ourPawns); + e->pawnAttacks[Us] = e->pawnAttacksSpan[Us] = pawn_attacks_bb(ourPawns); // Loop through all pawns of the current color and score each pawn while ((s = *pl++) != SQ_NONE) @@ -96,6 +96,7 @@ namespace { // Flag the pawn opposed = theirPawns & forward_file_bb(Us, s); + blocked = theirPawns & (s + Up); stoppers = theirPawns & passed_pawn_span(Us, s); lever = theirPawns & PawnAttacks[Us][s]; leverPush = theirPawns & PawnAttacks[Us][s + Up]; @@ -105,21 +106,13 @@ namespace { support = neighbours & rank_bb(s - Up); // A pawn is backward when it is behind all pawns of the same color on - // the adjacent files and cannot safely advance. Phalanx and isolated - // pawns will be excluded when the pawn is scored. - backward = !(neighbours & forward_ranks_bb(Them, s)) - && (stoppers & (leverPush | (s + Up))); - - // Span of backward pawns and span behind opposing pawns are not included - // in the pawnAttacksSpan bitboard. - if (!backward || phalanx) - { - if (opposed) - e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s) & - ~pawn_attack_span(Us, frontmost_sq(Them, opposed)); - else - e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s); - } + // the adjacent files and cannot safely advance. + backward = !(neighbours & forward_ranks_bb(Them, s + Up)) + && (leverPush | blocked); + + // Compute additional span if pawn is not backward nor blocked + if (!backward && !blocked) + e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s); // A pawn is passed if one of the three following conditions is true: // (a) there is no stoppers except some levers @@ -128,7 +121,7 @@ namespace { passed = !(stoppers ^ lever) || ( !(stoppers ^ leverPush) && popcount(phalanx) >= popcount(leverPush)) - || ( stoppers == square_bb(s + Up) && r >= RANK_5 + || ( stoppers == blocked && r >= RANK_5 && (shift(support) & ~(theirPawns | doubleAttackThem))); // Passed pawns will be properly scored later in evaluation when we have @@ -231,21 +224,17 @@ Score Entry::do_king_safety(const Position& pos) { Square ksq = pos.square(Us); kingSquares[Us] = ksq; castlingRights[Us] = pos.castling_rights(Us); + auto compare = [](Score a, Score b) { return mg_value(a) < mg_value(b); }; - Score shelters[3] = { evaluate_shelter(pos, ksq), - make_score(-VALUE_INFINITE, 0), - make_score(-VALUE_INFINITE, 0) }; + Score shelter = evaluate_shelter(pos, ksq); // If we can castle use the bonus after castling if it is bigger + if (pos.can_castle(Us & KING_SIDE)) - shelters[1] = evaluate_shelter(pos, relative_square(Us, SQ_G1)); + shelter = std::max(shelter, evaluate_shelter(pos, relative_square(Us, SQ_G1)), compare); if (pos.can_castle(Us & QUEEN_SIDE)) - shelters[2] = evaluate_shelter(pos, relative_square(Us, SQ_C1)); - - for (int i : {1, 2}) - if (mg_value(shelters[i]) > mg_value(shelters[0])) - shelters[0] = shelters[i]; + shelter = std::max(shelter, evaluate_shelter(pos, relative_square(Us, SQ_C1)), compare); // In endgame we like to bring our king near our closest pawn Bitboard pawns = pos.pieces(Us, PAWN); @@ -256,7 +245,7 @@ Score Entry::do_king_safety(const Position& pos) { else while (pawns) minPawnDist = std::min(minPawnDist, distance(ksq, pop_lsb(&pawns))); - return shelters[0] - make_score(0, 16 * minPawnDist); + return shelter - make_score(0, 16 * minPawnDist); } // Explicit template instantiation