X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fevaluate.cpp;h=981c97db9b33628ca7fa7237de74a7c956dcc61d;hb=15d265cc664e0e49fa82cccb7471da0a5612ce25;hp=aeecc0b7ff8b19c815a65e3cc22a9715d89847d3;hpb=00469d1798920b6272e9d92e250db0a388b5afd9;p=stockfish diff --git a/src/evaluate.cpp b/src/evaluate.cpp index aeecc0b7..981c97db 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -38,6 +38,54 @@ namespace { + // Struct EvalInfo contains various information computed and collected + // by the evaluation functions. + struct EvalInfo { + + // Middle and end game position's static evaluations + Score value; + + // margin[color] stores the evaluation margins we should consider for + // the given position. This is a kind of uncertainty estimation and + // typically is used by the search for pruning decisions. + Value margin[2]; + + // Pointers to material and pawn hash table entries + MaterialInfo* mi; + PawnInfo* pi; + + // attackedBy[color][piece type] is a bitboard representing all squares + // attacked by a given color and piece type, attackedBy[color][0] contains + // all squares attacked by the given color. + Bitboard attackedBy[2][8]; + + // kingZone[color] is the zone around the enemy king which is considered + // by the king safety evaluation. This consists of the squares directly + // adjacent to the king, and the three (or two, for a king on an edge file) + // squares two ranks in front of the king. For instance, if black's king + // is on g8, kingZone[WHITE] is a bitboard containing the squares f8, h8, + // f7, g7, h7, f6, g6 and h6. + Bitboard kingZone[2]; + + // kingAttackersCount[color] is the number of pieces of the given color + // which attack a square in the kingZone of the enemy king. + int kingAttackersCount[2]; + + // kingAttackersWeight[color] is the sum of the "weight" of the pieces of the + // given color which attack a square in the kingZone of the enemy king. The + // weights of the individual piece types are given by the variables + // QueenAttackWeight, RookAttackWeight, BishopAttackWeight and + // KnightAttackWeight in evaluate.cpp + int kingAttackersWeight[2]; + + // kingAdjacentZoneAttacksCount[color] is the number of attacks to squares + // directly adjacent to the king of the given color. Pieces which attack + // more than one square are counted multiple times. For instance, if black's + // king is on g8 and there's a white knight on g5, this knight adds + // 2 to kingAdjacentZoneAttacksCount[BLACK]. + int kingAdjacentZoneAttacksCount[2]; + }; + const int Sign[2] = { 1, -1 }; // Evaluation grain size, must be a power of 2 @@ -187,7 +235,7 @@ namespace { // Function prototypes template - Value do_evaluate(const Position& pos, EvalInfo& ei); + Value do_evaluate(const Position& pos, Value margins[]); template void init_attack_tables(const Position& pos, EvalInfo& ei); @@ -229,17 +277,18 @@ void prefetchPawn(Key key, int threadID) { /// evaluate() is the main evaluation function. It always computes two /// values, an endgame score and a middle game score, and interpolates /// between them based on the remaining material. -Value evaluate(const Position& pos, EvalInfo& ei) { +Value evaluate(const Position& pos, Value margins[]) { - return CpuHasPOPCNT ? do_evaluate(pos, ei) - : do_evaluate(pos, ei); + return CpuHasPOPCNT ? do_evaluate(pos, margins) + : do_evaluate(pos, margins); } namespace { template -Value do_evaluate(const Position& pos, EvalInfo& ei) { +Value do_evaluate(const Position& pos, Value margins[]) { + EvalInfo ei; ScaleFactor factor[2]; Score mobility; @@ -344,6 +393,10 @@ Value do_evaluate(const Position& pos, EvalInfo& ei) { factor[BLACK] = sf; } + // Populate margins[] + margins[WHITE] = ei.margin[WHITE]; + margins[BLACK] = ei.margin[BLACK]; + // Interpolate between the middle game and the endgame score return Sign[pos.side_to_move()] * scale_by_game_phase(ei.value, phase, factor); } @@ -652,10 +705,10 @@ namespace { // Find the attacked squares around the king which has no defenders // apart from the king itself - undefended = ei.attacked_by(Them) & ei.attacked_by(Us, KING); - undefended &= ~( ei.attacked_by(Us, PAWN) | ei.attacked_by(Us, KNIGHT) - | ei.attacked_by(Us, BISHOP) | ei.attacked_by(Us, ROOK) - | ei.attacked_by(Us, QUEEN)); + undefended = ei.attackedBy[Them][0] & ei.attackedBy[Us][KING]; + undefended &= ~( ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT] + | ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK] + | ei.attackedBy[Us][QUEEN]); // Initialize the 'attackUnits' variable, which is used later on as an // index to the KingDangerTable[] array. The initial value is based on @@ -669,39 +722,39 @@ namespace { // Analyse enemy's safe queen contact checks. First find undefended // squares around the king attacked by enemy queen... - b = undefended & ei.attacked_by(Them, QUEEN) & ~pos.pieces_of_color(Them); + b = undefended & ei.attackedBy[Them][QUEEN] & ~pos.pieces_of_color(Them); if (b) { // ...then remove squares not supported by another enemy piece - b &= ( ei.attacked_by(Them, PAWN) | ei.attacked_by(Them, KNIGHT) - | ei.attacked_by(Them, BISHOP) | ei.attacked_by(Them, ROOK)); + b &= ( ei.attackedBy[Them][PAWN] | ei.attackedBy[Them][KNIGHT] + | ei.attackedBy[Them][BISHOP] | ei.attackedBy[Them][ROOK]); if (b) attackUnits += QueenContactCheckBonus * count_1s_max_15(b) * (sente ? 2 : 1); } // Analyse enemy's safe distance checks for sliders and knights - safe = ~(pos.pieces_of_color(Them) | ei.attacked_by(Us)); + safe = ~(pos.pieces_of_color(Them) | ei.attackedBy[Us][0]); b1 = pos.attacks_from(ksq) & safe; b2 = pos.attacks_from(ksq) & safe; // Enemy queen safe checks - b = (b1 | b2) & ei.attacked_by(Them, QUEEN); + b = (b1 | b2) & ei.attackedBy[Them][QUEEN]; if (b) attackUnits += QueenCheckBonus * count_1s_max_15(b); // Enemy rooks safe checks - b = b1 & ei.attacked_by(Them, ROOK); + b = b1 & ei.attackedBy[Them][ROOK]; if (b) attackUnits += RookCheckBonus * count_1s_max_15(b); // Enemy bishops safe checks - b = b2 & ei.attacked_by(Them, BISHOP); + b = b2 & ei.attackedBy[Them][BISHOP]; if (b) attackUnits += BishopCheckBonus * count_1s_max_15(b); // Enemy knights safe checks - b = pos.attacks_from(ksq) & ei.attacked_by(Them, KNIGHT) & safe; + b = pos.attacks_from(ksq) & ei.attackedBy[Them][KNIGHT] & safe; if (b) attackUnits += KnightCheckBonus * count_1s_max_15(b); @@ -709,14 +762,14 @@ namespace { attackUnits = Min(99, Max(0, attackUnits)); // Finally, extract the king danger score from the KingDangerTable[] - // array and subtract the score from evaluation. Set also ei.kingDanger[] + // array and subtract the score from evaluation. Set also ei.margin[] // value that will be used for pruning because this value can sometimes // be very big, and so capturing a single attacking piece can therefore // result in a score change far bigger than the value of the captured piece. ei.value -= Sign[Us] * KingDangerTable[Us][attackUnits]; - ei.kingDanger[Us] = mg_value(KingDangerTable[Us][attackUnits]); + ei.margin[Us] = mg_value(KingDangerTable[Us][attackUnits]); } else - ei.kingDanger[Us] = VALUE_ZERO; + ei.margin[Us] = VALUE_ZERO; } @@ -759,7 +812,7 @@ namespace { if (pos.square_is_empty(blockSq)) { squaresToQueen = squares_in_front_of(Us, s); - defendedSquares = squaresToQueen & ei.attacked_by(Us); + defendedSquares = squaresToQueen & ei.attackedBy[Us][0]; // If there is an enemy rook or queen attacking the pawn from behind, // add all X-ray attacks by the rook or queen. Otherwise consider only @@ -768,7 +821,7 @@ namespace { && (squares_behind(Us, s) & pos.pieces(ROOK, QUEEN, Them) & pos.attacks_from(s))) unsafeSquares = squaresToQueen; else - unsafeSquares = squaresToQueen & (ei.attacked_by(Them) | pos.pieces_of_color(Them)); + unsafeSquares = squaresToQueen & (ei.attackedBy[Them][0] | pos.pieces_of_color(Them)); // If there aren't enemy attacks or pieces along the path to queen give // huge bonus. Even bigger if we protect the pawn's path. @@ -834,8 +887,8 @@ namespace { // pawn, or if it is undefended and attacked by an enemy piece. Bitboard safe = SpaceMask[Us] & ~pos.pieces(PAWN, Us) - & ~ei.attacked_by(Them, PAWN) - & (ei.attacked_by(Us) | ~ei.attacked_by(Them)); + & ~ei.attackedBy[Them][PAWN] + & (ei.attackedBy[Us][0] | ~ei.attackedBy[Them][0]); // Find all squares which are at most three squares behind some friendly pawn Bitboard behind = pos.pieces(PAWN, Us);