diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 884b1d85..11a6fa27 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -306,7 +306,7 @@ namespace { : Pt == ROOK ? attacks_bb< ROOK>(s, pos.pieces() ^ pos.pieces(QUEEN) ^ pos.pieces(Us, ROOK)) : pos.attacks_from(s); - if (pos.pinned_pieces(Us) & s) + if (pos.blockers_for_king(Us) & s) b &= LineBB[pos.square(Us)][s]; attackedBy2[Us] |= attackedBy[Us][ALL_PIECES] & b; @@ -392,8 +392,8 @@ namespace { if (Pt == QUEEN) { // Penalty if any relative pin or discovered attack against the queen - Bitboard pinners; - if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners)) + Bitboard queenPinners; + if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, queenPinners)) score -= WeakQueen; } } @@ -413,7 +413,7 @@ namespace { : AllSquares ^ Rank1BB ^ Rank2BB ^ Rank3BB); const Square ksq = pos.square(Us); - Bitboard weak, b, b1, b2, safe, unsafeChecks; + Bitboard weak, b, b1, b2, safe, unsafeChecks, pinned; // King shelter and enemy pawns storm Score score = pe->king_safety(pos, ksq); @@ -464,11 +464,12 @@ namespace { // Unsafe or occupied checking squares will also be considered, as long as // the square is in the attacker's mobility area. unsafeChecks &= mobilityArea[Them]; + pinned = pos.blockers_for_king(Us) & pos.pieces(Us); kingDanger += kingAttackersCount[Them] * kingAttackersWeight[Them] + 102 * kingAdjacentZoneAttacksCount[Them] + 191 * popcount(kingRing[Us] & weak) - + 143 * popcount(pos.pinned_pieces(Us) | unsafeChecks) + + 143 * popcount(pinned | unsafeChecks) - 848 * !pos.count(Them) - 9 * mg_value(score) / 8 + 40; diff --git a/src/movegen.cpp b/src/movegen.cpp index 14f30ea0..cb221d95 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -135,7 +135,7 @@ namespace { // if the pawn is not on the same file as the enemy king, because we // don't generate captures. Note that a possible discovery check // promotion has been already generated amongst the captures. - Bitboard dcCandidates = pos.discovered_check_candidates(); + Bitboard dcCandidates = pos.blockers_for_king(Them); if (pawnsNotOn7 & dcCandidates) { Bitboard dc1 = shift(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq); @@ -241,7 +241,7 @@ namespace { && !(PseudoAttacks[Pt][from] & target & pos.check_squares(Pt))) continue; - if (pos.discovered_check_candidates() & from) + if (pos.blockers_for_king(~us) & from) continue; } @@ -336,7 +336,7 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) { assert(!pos.checkers()); Color us = pos.side_to_move(); - Bitboard dc = pos.discovered_check_candidates(); + Bitboard dc = pos.blockers_for_king(~us) & pos.pieces(us); while (dc) { @@ -403,8 +403,9 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) { template<> ExtMove* generate(const Position& pos, ExtMove* moveList) { - Bitboard pinned = pos.pinned_pieces(pos.side_to_move()); - Square ksq = pos.square(pos.side_to_move()); + Color us = pos.side_to_move(); + Bitboard pinned = pos.blockers_for_king(us) & pos.pieces(us); + Square ksq = pos.square(us); ExtMove* cur = moveList; moveList = pos.checkers() ? generate(pos, moveList) diff --git a/src/position.cpp b/src/position.cpp index fdae0ae0..d48ec18c 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -464,7 +464,7 @@ const string Position::fen() const { Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const { - Bitboard result = 0; + Bitboard blockers = 0; pinners = 0; // Snipers are sliders that attack 's' when a piece is removed @@ -476,14 +476,14 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners Square sniperSq = pop_lsb(&snipers); Bitboard b = between_bb(s, sniperSq) & pieces(); - if (!more_than_one(b)) + if (b && !more_than_one(b)) { - result |= b; + blockers |= b; if (b & pieces(color_of(piece_on(s)))) pinners |= sniperSq; } } - return result; + return blockers; } @@ -540,7 +540,7 @@ bool Position::legal(Move m) const { // A non-king move is legal if and only if it is not pinned or it // is moving along the ray towards or away from the king. - return !(pinned_pieces(us) & from) + return !(blockers_for_king(us) & from) || aligned(from, to_sq(m), square(us)); } @@ -632,7 +632,7 @@ bool Position::gives_check(Move m) const { return true; // Is there a discovered check? - if ( (discovered_check_candidates() & from) + if ( (st->blockersForKing[~sideToMove] & from) && !aligned(from, to, square(~sideToMove))) return true; diff --git a/src/position.h b/src/position.h index 34e2f7ee..18c783f0 100644 --- a/src/position.h +++ b/src/position.h @@ -105,8 +105,7 @@ public: // Checking Bitboard checkers() const; - Bitboard discovered_check_candidates() const; - Bitboard pinned_pieces(Color c) const; + Bitboard blockers_for_king(Color c) const; Bitboard check_squares(PieceType pt) const; // Attacks to/from a given square @@ -296,12 +295,8 @@ inline Bitboard Position::checkers() const { return st->checkersBB; } -inline Bitboard Position::discovered_check_candidates() const { - return st->blockersForKing[~sideToMove] & pieces(sideToMove); -} - -inline Bitboard Position::pinned_pieces(Color c) const { - return st->blockersForKing[c] & pieces(c); +inline Bitboard Position::blockers_for_king(Color c) const { + return st->blockersForKing[c]; } inline Bitboard Position::check_squares(PieceType pt) const { diff --git a/src/search.cpp b/src/search.cpp index ca5a107e..394f228f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -108,6 +108,13 @@ namespace { void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus); void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus); + inline bool gives_check(const Position& pos, Move move) { + Color us = pos.side_to_move(); + return type_of(move) == NORMAL && !(pos.blockers_for_king(~us) & pos.pieces(us)) + ? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move) + : pos.gives_check(move); + } + // perft() is our utility to verify move generation. All the leaf nodes up // to the given depth are generated and counted, and the sum is returned. template @@ -823,10 +830,7 @@ moves_loop: // When in check, search starts from here extension = DEPTH_ZERO; captureOrPromotion = pos.capture_or_promotion(move); movedPiece = pos.moved_piece(move); - - givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates() - ? pos.check_squares(type_of(movedPiece)) & to_sq(move) - : pos.gives_check(move); + givesCheck = gives_check(pos, move); moveCountPruning = depth < 16 * ONE_PLY && moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY]; @@ -1238,9 +1242,7 @@ moves_loop: // When in check, search starts from here { assert(is_ok(move)); - givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates() - ? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move) - : pos.gives_check(move); + givesCheck = gives_check(pos, move); moveCount++;