Speed up attackers_to
authorFabian Fichter <ianfab@users.noreply.github.com>
Sun, 11 Nov 2018 21:58:16 +0000 (22:58 +0100)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sun, 11 Nov 2018 21:58:16 +0000 (22:58 +0100)
No functional change.

src/movegen.cpp
src/position.cpp
src/position.h
src/search.cpp

index 910717e..1d79d67 100644 (file)
@@ -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;
     }
 
index 67c38d0..c487707 100644 (file)
@@ -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<KING>(sideToMove) ? attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove) : 0;
+  si->checkersBB = count<KING>(sideToMove) ? attackers_to(square<KING>(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<KING>(us) || !(attackers_to(ksq, occupied) & pieces(~us) & occupied);
+      return !count<KING>(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<KING>(us) || !(  attackers_to(ksq, (type_of(m) != DROP ? pieces() ^ from : pieces()) | to)
-           & pieces(~us) & ~SquareBB[to]);
+  return !count<KING>(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<KING>(~sideToMove), (pieces() ^ from) | to) & pieces(sideToMove)))
+      && attackers_to(square<KING>(~sideToMove), (pieces() ^ from) | to, sideToMove))
       return true;
 
   switch (type_of(m))
index fb82d93..a993671 100644 (file)
@@ -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<PieceType> 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;
 }
index e8a274e..6942725 100644 (file)
@@ -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)