Value Entry::shelter_storm(const Position& pos, Square ksq) { const Color Them = (Us == WHITE ? BLACK : WHITE); const Bitboard Edges = (FileABB | FileHBB) & (Rank2BB | Rank3BB); Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq)); Bitboard ourPawns = b & pos.pieces(Us); Bitboard theirPawns = b & pos.pieces(Them); Value safety = MaxSafetyBonus; File kf = std::max(FILE_B, std::min(FILE_G, file_of(ksq))); for (File f = kf - File(1); f <= kf + File(1); ++f) { b = ourPawns & file_bb(f); Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1; b = theirPawns & file_bb(f); Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; if ( (Edges & make_square(f, rkThem)) && file_of(ksq) == f && relative_rank(Us, ksq) == rkThem - 1) safety += 200; else safety -= ShelterWeakness[rkUs] + StormDanger[rkUs == RANK_1 ? 0 : rkThem != rkUs + 1 ? 1 : 2][rkThem]; } return safety; }
Value Entry::shelter_storm(const Position& pos, Square ksq) { const Color Them = (Us == WHITE ? BLACK : WHITE); enum { NoFriendlyPawn, Unblocked, BlockedByPawn, BlockedByKing }; Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq)); Bitboard ourPawns = b & pos.pieces(Us); Bitboard theirPawns = b & pos.pieces(Them); Value safety = MaxSafetyBonus; File center = std::max(FILE_B, std::min(FILE_G, file_of(ksq))); for (File f = center - File(1); f <= center + File(1); ++f) { b = ourPawns & file_bb(f); Rank rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1; b = theirPawns & file_bb(f); Rank rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; safety -= ShelterWeakness[std::min(f, FILE_H - f)][rkUs] + StormDanger [f == file_of(ksq) && rkThem == relative_rank(Us, ksq) + 1 ? BlockedByKing : rkUs == RANK_1 ? NoFriendlyPawn : rkThem == rkUs + 1 ? BlockedByPawn : Unblocked] [std::min(f, FILE_H - f)][rkThem]; } return safety; }
Value Entry::shelter_storm(const Position& pos, Square ksq) { const Color Them = (Us == WHITE ? BLACK : WHITE); Value safety = MaxSafetyBonus; Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq)); Bitboard ourPawns = b & pos.pieces(Us); Bitboard theirPawns = b & pos.pieces(Them); Rank rkUs, rkThem; File kf = file_of(ksq); kf = (kf == FILE_A) ? FILE_B : (kf == FILE_H) ? FILE_G : kf; for (int f = kf - 1; f <= kf + 1; f++) { b = ourPawns & FileBB[f]; rkUs = b ? relative_rank(Us, Us == WHITE ? lsb(b) : msb(b)) : RANK_1; safety -= ShelterWeakness[rkUs]; b = theirPawns & FileBB[f]; rkThem = b ? relative_rank(Us, Us == WHITE ? lsb(b) : msb(b)) : RANK_1; safety -= StormDanger[rkUs == RANK_1 ? 0 : rkThem == rkUs + 1 ? 2 : 1][rkThem]; } return safety; }
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; }
Value Entry::shelter_storm(const Position& pos, Square ksq) { const Color Them = (Us == WHITE ? BLACK : WHITE); Value safety = MaxSafetyBonus; Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq)); Bitboard ourPawns = b & pos.pieces(Us); Bitboard theirPawns = b & pos.pieces(Them); Rank rkUs, rkThem; File kf = std::max(FILE_B, std::min(FILE_G, file_of(ksq))); for (File f = kf - File(1); f <= kf + File(1); ++f) { b = ourPawns & file_bb(f); rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1; safety -= ShelterWeakness[rkUs]; b = theirPawns & file_bb(f); rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1; safety -= StormDanger[rkUs == RANK_1 ? 0 : rkThem == rkUs + 1 ? 2 : 1][rkThem]; } return safety; }
// Entry::shelter_storm() calculates shelter and storm penalties for the file // the king is on, as well as the two adjacent files. Value Entry::shelter_storm (const Position &pos, Square k_sq) { const Color C_ = ((WHITE == C) ? BLACK : WHITE); Value safety = MaxSafetyBonus; Bitboard front_pawns = pos.pieces (PAWN) & (front_ranks_bb (C, _rank (k_sq)) | rank_bb (k_sq)); Bitboard pawns[CLR_NO] = { front_pawns & pos.pieces (C ), front_pawns & pos.pieces (C_), }; File kf = max (F_B, min (F_G, _file (k_sq))); for (File f = kf - 1; f <= kf + 1; ++f) { Bitboard mid_pawns; mid_pawns = pawns[1] & file_bb (f); Rank b_rk = mid_pawns ? rel_rank (C, scan_rel_frntmost_sq (C_, mid_pawns)) : R_1; if ((MID_EDGE_bb & (f | b_rk)) && _file (k_sq) == f && rel_rank (C, k_sq) == b_rk - 1) { safety += Value (200); } else { mid_pawns = pawns[0] & file_bb (f); Rank w_rk = mid_pawns ? rel_rank (C, scan_rel_backmost_sq (C , mid_pawns)) : R_1; int8_t danger = (w_rk != R_1) ? ((b_rk == w_rk + 1) ? 2 : 1) : 0; safety -= ShelterWeakness[w_rk] + StormDanger[danger][b_rk]; } } return safety; }