From 13ae7450a25cf3efdbc4a47ff8f29195c78d8cb1 Mon Sep 17 00:00:00 2001 From: Fabian Fichter Date: Sun, 11 Nov 2018 22:58:16 +0100 Subject: [PATCH] Speed up attackers_to No functional change. --- src/movegen.cpp | 5 ++--- src/position.cpp | 25 ++++++++++++++----------- src/position.h | 6 ++++++ src/search.cpp | 2 +- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/movegen.cpp b/src/movegen.cpp index 910717e..1d79d67 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -39,7 +39,6 @@ namespace { Square rfrom = pos.castling_rook_square(Cr); Square kto = make_square(KingSide ? pos.castling_kingside_file() : pos.castling_queenside_file(), relative_rank(us, RANK_1, pos.max_rank())); - Bitboard enemies = pos.pieces(~us); assert(!pos.checkers()); @@ -49,13 +48,13 @@ namespace { if (type_of(pos.piece_on(kfrom)) == KING) { for (Square s = kto; s != kfrom; s += step) - if (pos.attackers_to(s) & enemies) + if (pos.attackers_to(s, ~us)) return moveList; // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. - if (Chess960 && (pos.attackers_to(kto, pos.pieces() ^ rfrom) & pos.pieces(~us))) + if (Chess960 && pos.attackers_to(kto, pos.pieces() ^ rfrom, ~us)) return moveList; } diff --git a/src/position.cpp b/src/position.cpp index 67c38d0..c487707 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -489,7 +489,7 @@ void Position::set_state(StateInfo* si) const { si->pawnKey = Zobrist::noPawns; si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO; si->psq = SCORE_ZERO; - si->checkersBB = count(sideToMove) ? attackers_to(square(sideToMove)) & pieces(~sideToMove) : 0; + si->checkersBB = count(sideToMove) ? attackers_to(square(sideToMove), ~sideToMove) : 0; set_check_info(si); @@ -679,16 +679,20 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners /// Position::attackers_to() computes a bitboard of all pieces which attack a /// given square. Slider attacks use the occupied bitboard to indicate occupancy. -Bitboard Position::attackers_to(Square s, Bitboard occupied) const { +Bitboard Position::attackers_to(Square s, Bitboard occupied, Color c) const { Bitboard b = 0; - for (Color c = WHITE; c <= BLACK; ++c) - for (PieceType pt : piece_types()) - b |= attacks_bb(~c, pt, s, occupied) & pieces(c, pt); + for (PieceType pt : piece_types()) + b |= attacks_bb(~c, pt, s, occupied) & pieces(c, pt); return b; } +Bitboard Position::attackers_to(Square s, Bitboard occupied) const { + return attackers_to(s, occupied, WHITE) | attackers_to(s, occupied, BLACK); +} + + /// Position::legal() tests whether a pseudo-legal move is legal bool Position::legal(Move m) const { @@ -784,18 +788,17 @@ bool Position::legal(Move m) const { assert(piece_on(capsq) == make_piece(~us, PAWN)); assert(piece_on(to) == NO_PIECE); - return !count(us) || !(attackers_to(ksq, occupied) & pieces(~us) & occupied); + return !count(us) || !(attackers_to(ksq, occupied, ~us) & occupied); } // If the moving piece is a king, check whether the destination // square is attacked by the opponent. Castling moves are checked // for legality during move generation. if (type_of(moved_piece(m)) == KING) - return type_of(m) == CASTLING || !(attackers_to(to) & pieces(~us)); + return type_of(m) == CASTLING || !attackers_to(to, ~us); // A non-king move is legal if the king is not under attack after the move. - return !count(us) || !( attackers_to(ksq, (type_of(m) != DROP ? pieces() ^ from : pieces()) | to) - & pieces(~us) & ~SquareBB[to]); + return !count(us) || !(attackers_to(ksq, (type_of(m) != DROP ? pieces() ^ from : pieces()) | to, ~us) & ~SquareBB[to]); } @@ -866,7 +869,7 @@ bool Position::pseudo_legal(const Move m) const { } // In case of king moves under check we have to remove king so as to catch // invalid moves like b1a1 when opposite queen is on c1. - else if (attackers_to(to, pieces() ^ from) & pieces(~us)) + else if (attackers_to(to, pieces() ^ from, ~us)) return false; } @@ -895,7 +898,7 @@ bool Position::gives_check(Move m) const { // Is there a discovered check? if ( type_of(m) != DROP && (st->blockersForKing[~sideToMove] & from) - && (attackers_to(square(~sideToMove), (pieces() ^ from) | to) & pieces(sideToMove))) + && attackers_to(square(~sideToMove), (pieces() ^ from) | to, sideToMove)) return true; switch (type_of(m)) diff --git a/src/position.h b/src/position.h index fb82d93..a993671 100644 --- a/src/position.h +++ b/src/position.h @@ -170,7 +170,9 @@ public: // Attacks to/from a given square Bitboard attackers_to(Square s) const; + Bitboard attackers_to(Square s, Color c) const; Bitboard attackers_to(Square s, Bitboard occupied) const; + Bitboard attackers_to(Square s, Bitboard occupied, Color c) const; Bitboard attacks_from(Color c, PieceType pt, Square s) const; template Bitboard attacks_from(Color c, Square s) const; Bitboard moves_from(Color c, PieceType pt, Square s) const; @@ -691,6 +693,10 @@ inline Bitboard Position::attackers_to(Square s) const { return attackers_to(s, byTypeBB[ALL_PIECES]); } +inline Bitboard Position::attackers_to(Square s, Color c) const { + return attackers_to(s, byTypeBB[ALL_PIECES], c); +} + inline Bitboard Position::checkers() const { return st->checkersBB; } diff --git a/src/search.cpp b/src/search.cpp index e8a274e..6942725 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -941,7 +941,7 @@ moves_loop: // When in check, search starts from here { if ( !captureOrPromotion && !givesCheck - && (!pos.must_capture() || !(pos.attackers_to(to_sq(move)) & pos.pieces(~pos.side_to_move()))) + && (!pos.must_capture() || !pos.attackers_to(to_sq(move), ~pos.side_to_move())) && (!pos.advanced_pawn_push(move) || pos.non_pawn_material() >= Value(5000))) { // Move count based pruning (~30 Elo) -- 1.7.0.4