ScaleFactor ScalingFunction<KPsK>::apply(const Position& pos) const { assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO); assert(pos.piece_count(strongerSide, PAWN) >= 2); assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO); assert(pos.piece_count(weakerSide, PAWN) == 0); Square ksq = pos.king_square(weakerSide); Bitboard pawns = pos.pieces(PAWN, strongerSide); // Are all pawns on the 'a' file? if ((pawns & ~FileABB) == EmptyBoardBB) { // Does the defending king block the pawns? if ( square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1 || ( square_file(ksq) == FILE_A && (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB)) return SCALE_FACTOR_ZERO; } // Are all pawns on the 'h' file? else if ((pawns & ~FileHBB) == EmptyBoardBB) { // Does the defending king block the pawns? if ( square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1 || ( square_file(ksq) == FILE_H && (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB)) return SCALE_FACTOR_ZERO; } return SCALE_FACTOR_NONE; }
Score Entry::do_king_safety(const Position& pos, Square ksq) { kingSquares[Us] = ksq; castlingRights[Us] = pos.can_castle(Us); int minKingPawnDistance = 0; #ifdef THREECHECK CheckCount checks = pos.is_three_check() ? pos.checks_given(~Us) : CHECKS_0; #endif Bitboard pawns = pos.pieces(Us, PAWN); if (pawns) while (!(DistanceRingBB[ksq][minKingPawnDistance++] & pawns)) {} Value bonus = shelter_storm<Us>(pos, ksq); // If we can castle use the bonus after the castling if it is bigger if (pos.can_castle(MakeCastling<Us, KING_SIDE>::right)) bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_G1))); if (pos.can_castle(MakeCastling<Us, QUEEN_SIDE>::right)) bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_C1))); #ifdef THREECHECK // Decrease score when checks have been taken return make_score(bonus, (-16 * minKingPawnDistance) + (-2 * checks)); #else return make_score(bonus, -16 * minKingPawnDistance); #endif }
Score Entry::do_king_safety(const Position& pos, Square ksq) { kingSquares[Us] = ksq; castlingRights[Us] = pos.can_castle(Us); int minKingPawnDistance = 0; Bitboard pawns = pos.pieces(Us, PAWN); if (pawns) while (!(DistanceRingBB[ksq][minKingPawnDistance++] & pawns)) {} Value bonus = shelter_storm<Us>(pos, ksq); // If we can castle use the bonus after the castling if it is bigger if (pos.can_castle(MakeCastling<Us, KING_SIDE>::right)) bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_G1))); if (pos.can_castle(MakeCastling<Us, QUEEN_SIDE>::right)) bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_C1))); return make_score(bonus, -16 * minKingPawnDistance); }
ScaleFactor ScalingFunction<KNPK>::apply(const Position& pos) const { assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame); assert(pos.piece_count(strongerSide, KNIGHT) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1); assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO); assert(pos.piece_count(weakerSide, PAWN) == 0); Square pawnSq = pos.piece_list(strongerSide, PAWN, 0); Square weakerKingSq = pos.king_square(weakerSide); if ( pawnSq == relative_square(strongerSide, SQ_A7) && square_distance(weakerKingSq, relative_square(strongerSide, SQ_A8)) <= 1) return SCALE_FACTOR_ZERO; if ( pawnSq == relative_square(strongerSide, SQ_H7) && square_distance(weakerKingSq, relative_square(strongerSide, SQ_H8)) <= 1) return SCALE_FACTOR_ZERO; return SCALE_FACTOR_NONE; }
Score Entry::do_king_safety(const Position& pos) { Square ksq = pos.square<KING>(Us); kingSquares[Us] = ksq; castlingRights[Us] = pos.can_castle(Us); int minKingPawnDistance = 0; Bitboard pawns = pos.pieces(Us, PAWN); if (pawns) while (!(DistanceRingBB[ksq][++minKingPawnDistance] & pawns)) {} Value bonus = evaluate_shelter<Us>(pos, ksq); // If we can castle use the bonus after the castling if it is bigger if (pos.can_castle(Us | KING_SIDE)) bonus = std::max(bonus, evaluate_shelter<Us>(pos, relative_square(Us, SQ_G1))); if (pos.can_castle(Us | QUEEN_SIDE)) bonus = std::max(bonus, evaluate_shelter<Us>(pos, relative_square(Us, SQ_C1))); return make_score(bonus, -16 * minKingPawnDistance); }
Score Entry::update_safety(const Position& pos, Square ksq) { kingSquares[Us] = ksq; castleRights[Us] = pos.can_castle(Us); minKPdistance[Us] = 0; Bitboard pawns = pos.pieces(Us, PAWN); if (pawns) while (!(DistanceRingsBB[ksq][minKPdistance[Us]++] & pawns)) {} if (relative_rank(Us, ksq) > RANK_4) return kingSafety[Us] = make_score(0, -16 * minKPdistance[Us]); Value bonus = shelter_storm<Us>(pos, ksq); // If we can castle use the bonus after the castle if is bigger if (pos.can_castle(make_castle_right(Us, KING_SIDE))) bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_G1))); if (pos.can_castle(make_castle_right(Us, QUEEN_SIDE))) bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_C1))); return kingSafety[Us] = make_score(bonus, -16 * minKPdistance[Us]); }
ScaleFactor ScalingFunction<KBPsK>::apply(const Position& pos) const { assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame); assert(pos.piece_count(strongerSide, BISHOP) == 1); assert(pos.piece_count(strongerSide, PAWN) >= 1); // No assertions about the material of weakerSide, because we want draws to // be detected even when the weaker side has some pawns. Bitboard pawns = pos.pieces(PAWN, strongerSide); File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0)); // All pawns are on a single rook file ? if ( (pawnFile == FILE_A || pawnFile == FILE_H) && (pawns & ~file_bb(pawnFile)) == EmptyBoardBB) { Square bishopSq = pos.piece_list(strongerSide, BISHOP, 0); Square queeningSq = relative_square(strongerSide, make_square(pawnFile, RANK_8)); Square kingSq = pos.king_square(weakerSide); if ( !same_color_squares(queeningSq, bishopSq) && file_distance(square_file(kingSq), pawnFile) <= 1) { // The bishop has the wrong color, and the defending king is on the // file of the pawn(s) or the neighboring file. Find the rank of the // frontmost pawn. Rank rank; if (strongerSide == WHITE) { for (rank = RANK_7; (rank_bb(rank) & pawns) == EmptyBoardBB; rank--) {} assert(rank >= RANK_2 && rank <= RANK_7); } else { for (rank = RANK_2; (rank_bb(rank) & pawns) == EmptyBoardBB; rank++) {} rank = Rank(rank ^ 7); // HACK to get the relative rank assert(rank >= RANK_2 && rank <= RANK_7); } // If the defending king has distance 1 to the promotion square or // is placed somewhere in front of the pawn, it's a draw. if ( square_distance(kingSq, queeningSq) <= 1 || relative_rank(strongerSide, kingSq) >= rank) return SCALE_FACTOR_ZERO; } } return SCALE_FACTOR_NONE; }