]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Refactor Position::pinned_pieces() to use templates
[stockfish] / src / position.cpp
index ba57657e11b81000f6026116646af2f10b490c50..e33b65fc050e4988f646cbdc2324c9962ccb4eb8 100644 (file)
@@ -1,13 +1,14 @@
 /*
-  Glaurung, a UCI chess playing engine.
-  Copyright (C) 2004-2008 Tord Romstad
+  Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+  Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+  Copyright (C) 2008 Marco Costalba
 
-  Glaurung is free software: you can redistribute it and/or modify
+  Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
-  Glaurung is distributed in the hope that it will be useful,
+  Stockfish is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
@@ -48,13 +49,6 @@ Key Position::zobSideToMove;
 Value Position::MgPieceSquareTable[16][64];
 Value Position::EgPieceSquareTable[16][64];
 
-const Piece_attacks_fn piece_attacks_fn[] =
-  { 0, 0, 
-    &Position::knight_attacks,
-    &Position::bishop_attacks,
-    &Position::rook_attacks,
-    &Position::queen_attacks,
-    &Position::king_attacks };
 
 ////
 //// Functions
@@ -302,40 +296,53 @@ void Position::copy(const Position &pos) {
 }
 
 
-/// Position:pinned_pieces() returns a bitboard of all pinned (against the
-/// king) pieces for the given color.
+/// Position:pinned_pieces<>() returns a bitboard of all pinned (against the
+/// king) pieces for the given color and for the given pinner type.
+template<PieceType Piece>
+Bitboard Position::pinned_pieces(Color c, Square ksq) const {
 
-Bitboard Position::pinned_pieces(Color c) const {
-  Bitboard b1, b2, pinned, pinners, sliders;
-  Square ksq = king_square(c), s;
-  Color them = opposite_color(c);
+  Square s;
+  Bitboard sliders, pinned = EmptyBoardBB;
+  
+  if (Piece == ROOK) // Resolved at compile time
+      sliders = rooks_and_queens(opposite_color(c)) & RookPseudoAttacks[ksq];
+  else
+      sliders = bishops_and_queens(opposite_color(c)) & BishopPseudoAttacks[ksq];
 
-  pinned = EmptyBoardBB;
-  b1 = occupied_squares();
+  if (sliders && (sliders & ~checkersBB))
+  {
+       // Our king blockers are candidate pinned pieces
+      Bitboard candidate_pinned = piece_attacks<Piece>(ksq) & pieces_of_color(c);
+
+      // Pinners are sliders, not checkers, that give check when 
+      // candidate pinned are removed.
+      Bitboard pinners =  sliders & ~checkersBB;
+      if (Piece == ROOK)
+          pinners &= rook_attacks_bb(ksq, occupied_squares() ^ candidate_pinned);
+      else
+          pinners &= bishop_attacks_bb(ksq, occupied_squares() ^ candidate_pinned);
 
-  sliders = rooks_and_queens(them) & ~checkers();
-  if(sliders & RookPseudoAttacks[ksq]) {
-    b2 = rook_attacks(ksq) & pieces_of_color(c);
-    pinners = rook_attacks_bb(ksq, b1 ^ b2) & sliders;
-    while(pinners) {
-      s = pop_1st_bit(&pinners);
-      pinned |= (squares_between(s, ksq) & b2);
-    }
+      // Finally for each pinner find the corresponding pinned piece
+      // among the candidates.
+      while (pinners)
+      {
+          s = pop_1st_bit(&pinners);
+          pinned |= (squares_between(s, ksq) & candidate_pinned);
+      }
   }
+  return pinned;
+}
 
-  sliders = bishops_and_queens(them) & ~checkers();
-  if(sliders & BishopPseudoAttacks[ksq]) {
-    b2 = bishop_attacks(ksq) & pieces_of_color(c);
-    pinners = bishop_attacks_bb(ksq, b1 ^ b2) & sliders;
-    while(pinners) {
-      s = pop_1st_bit(&pinners);
-      pinned |= (squares_between(s, ksq) & b2);
-    }
-  }
 
-  return pinned;
+/// Position:pinned_pieces() returns a bitboard of all pinned (against the
+/// king) pieces for the given color.
+Bitboard Position::pinned_pieces(Color c) const {
+
+  Square ksq = king_square(c);
+  return pinned_pieces<ROOK>(c, ksq) | pinned_pieces<BISHOP>(c, ksq);
 }
 
+
 /// Position:discovered_check_candidates() returns a bitboard containing all
 /// pieces for the given side which are candidates for giving a discovered
 /// check.  The code is almost the same as the function for finding pinned
@@ -350,7 +357,7 @@ Bitboard Position::discovered_check_candidates(Color c) const {
 
   sliders = rooks_and_queens(c);
   if(sliders & RookPseudoAttacks[ksq]) {
-    b2 = rook_attacks(ksq) & pieces_of_color(c);
+    b2 = piece_attacks<ROOK>(ksq) & pieces_of_color(c);
     checkers = rook_attacks_bb(ksq, b1 ^ b2) & sliders;
     while(checkers) {
       s = pop_1st_bit(&checkers);
@@ -360,7 +367,7 @@ Bitboard Position::discovered_check_candidates(Color c) const {
 
   sliders = bishops_and_queens(c);
   if(sliders & BishopPseudoAttacks[ksq]) {
-    b2 = bishop_attacks(ksq) & pieces_of_color(c);
+    b2 = piece_attacks<BISHOP>(ksq) & pieces_of_color(c);
     checkers = bishop_attacks_bb(ksq, b1 ^ b2) & sliders;
     while(checkers) {
       s = pop_1st_bit(&checkers);
@@ -378,10 +385,10 @@ Bitboard Position::discovered_check_candidates(Color c) const {
 bool Position::square_is_attacked(Square s, Color c) const {
   return
     (pawn_attacks(opposite_color(c), s) & pawns(c)) ||
-    (knight_attacks(s) & knights(c)) ||
-    (king_attacks(s) & kings(c)) ||
-    (rook_attacks(s) & rooks_and_queens(c)) ||
-    (bishop_attacks(s) & bishops_and_queens(c));
+    (piece_attacks<KNIGHT>(s) & knights(c)) ||
+    (piece_attacks<KING>(s)   & kings(c)) ||
+    (piece_attacks<ROOK>(s)   & rooks_and_queens(c)) ||
+    (piece_attacks<BISHOP>(s) & bishops_and_queens(c));
 }
 
 
@@ -392,12 +399,12 @@ bool Position::square_is_attacked(Square s, Color c) const {
 
 Bitboard Position::attacks_to(Square s) const {
   return
-    (black_pawn_attacks(s) & pawns(WHITE)) |
-    (white_pawn_attacks(s) & pawns(BLACK)) |
-    (knight_attacks(s) & pieces_of_type(KNIGHT)) |
-    (rook_attacks(s) & rooks_and_queens()) |
-    (bishop_attacks(s) & bishops_and_queens()) |
-    (king_attacks(s) & pieces_of_type(KING));
+    (pawn_attacks(BLACK, s) & pawns(WHITE)) |
+    (pawn_attacks(WHITE, s) & pawns(BLACK)) |
+    (piece_attacks<KNIGHT>(s) & pieces_of_type(KNIGHT)) |
+    (piece_attacks<ROOK>(s) & rooks_and_queens()) |
+    (piece_attacks<BISHOP>(s) & bishops_and_queens()) |
+    (piece_attacks<KING>(s) & pieces_of_type(KING));
 }
 
 Bitboard Position::attacks_to(Square s, Color c) const {
@@ -413,13 +420,13 @@ bool Position::piece_attacks_square(Square f, Square t) const {
   assert(square_is_ok(t));
 
   switch(piece_on(f)) {
-  case WP: return white_pawn_attacks_square(f, t);
-  case BP: return black_pawn_attacks_square(f, t);
-  case WN: case BN: return knight_attacks_square(f, t);
-  case WB: case BB: return bishop_attacks_square(f, t);
-  case WR: case BR: return rook_attacks_square(f, t);
-  case WQ: case BQ: return queen_attacks_square(f, t);
-  case WK: case BK: return king_attacks_square(f, t);
+  case WP: return pawn_attacks_square(WHITE, f, t);
+  case BP: return pawn_attacks_square(BLACK, f, t);
+  case WN: case BN: return piece_attacks_square<KNIGHT>(f, t);
+  case WB: case BB: return piece_attacks_square<BISHOP>(f, t);
+  case WR: case BR: return piece_attacks_square<ROOK>(f, t);
+  case WQ: case BQ: return piece_attacks_square<QUEEN>(f, t);
+  case WK: case BK: return piece_attacks_square<KING>(f, t);
   default: return false;
   }
 
@@ -556,7 +563,7 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
 
       switch(move_promotion(m)) {
       case KNIGHT:
-        return knight_attacks_square(to, ksq);
+        return piece_attacks_square<KNIGHT>(to, ksq);
       case BISHOP:
         return bit_is_set(bishop_attacks_bb(to, b), ksq);
       case ROOK:
@@ -588,7 +595,7 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
       return true;
     // Normal check?
     else
-      return bit_is_set(knight_attacks(ksq), to);
+      return bit_is_set(piece_attacks<KNIGHT>(ksq), to);
 
   case BISHOP:
     // Discovered check?
@@ -596,7 +603,7 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
       return true;
     // Normal check?
     else
-      return bit_is_set(bishop_attacks(ksq), to);
+      return bit_is_set(piece_attacks<BISHOP>(ksq), to);
 
   case ROOK:
     // Discovered check?
@@ -604,13 +611,13 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
       return true;
     // Normal check?
     else
-      return bit_is_set(rook_attacks(ksq), to);
+      return bit_is_set(piece_attacks<ROOK>(ksq), to);
 
   case QUEEN:
     // Discovered checks are impossible!
     assert(!bit_is_set(dcCandidates, from));
     // Normal check?
-    return bit_is_set(queen_attacks(ksq), to);
+    return bit_is_set(piece_attacks<QUEEN>(ksq), to);
 
   case KING:
     // Discovered check?
@@ -675,13 +682,13 @@ bool Position::move_attacks_square(Move m, Square s) const {
   assert(square_is_occupied(f));
 
   switch(piece_on(f)) {
-  case WP: return white_pawn_attacks_square(t, s);
-  case BP: return black_pawn_attacks_square(t, s);
-  case WN: case BN: return knight_attacks_square(t, s);
-  case WB: case BB: return bishop_attacks_square(t, s);
-  case WR: case BR: return rook_attacks_square(t, s);
-  case WQ: case BQ: return queen_attacks_square(t, s);
-  case WK: case BK: return king_attacks_square(t, s);
+  case WP: return pawn_attacks_square(WHITE, t, s);
+  case BP: return pawn_attacks_square(BLACK, t, s);
+  case WN: case BN: return piece_attacks_square<KNIGHT>(t, s);
+  case WB: case BB: return piece_attacks_square<BISHOP>(t, s);
+  case WR: case BR: return piece_attacks_square<ROOK>(t, s);
+  case WQ: case BQ: return piece_attacks_square<QUEEN>(t, s);
+  case WK: case BK: return piece_attacks_square<KING>(t, s);
   default: assert(false);
   }
 
@@ -854,9 +861,9 @@ void Position::do_move(Move m, UndoInfo &u, Bitboard dcCandidates) {
     }
     if(piece == PAWN) {
       if(abs(int(to) - int(from)) == 16) {
-        if((us == WHITE && (white_pawn_attacks(from + DELTA_N) &
+        if((us == WHITE && (pawn_attacks(WHITE, from + DELTA_N) &
                             pawns(BLACK))) ||
-           (us == BLACK && (black_pawn_attacks(from + DELTA_S) &
+           (us == BLACK && (pawn_attacks(BLACK, from + DELTA_S) &
                             pawns(WHITE)))) {
           epSquare = Square((int(from) + int(to)) / 2);
           key ^= zobEp[epSquare];
@@ -889,45 +896,45 @@ void Position::do_move(Move m, UndoInfo &u, Bitboard dcCandidates) {
         set_bit(&checkersBB, to);
       if(bit_is_set(dcCandidates, from))
         checkersBB |=
-          ((rook_attacks(ksq) & rooks_and_queens(us)) |
-           (bishop_attacks(ksq) & bishops_and_queens(us)));
+          ((piece_attacks<ROOK>(ksq) & rooks_and_queens(us)) |
+           (piece_attacks<BISHOP>(ksq) & bishops_and_queens(us)));
       break;
 
     case KNIGHT:
-      if(bit_is_set(knight_attacks(ksq), to))
+      if(bit_is_set(piece_attacks<KNIGHT>(ksq), to))
         set_bit(&checkersBB, to);
       if(bit_is_set(dcCandidates, from))
         checkersBB |=
-          ((rook_attacks(ksq) & rooks_and_queens(us)) |
-           (bishop_attacks(ksq) & bishops_and_queens(us)));
+          ((piece_attacks<ROOK>(ksq) & rooks_and_queens(us)) |
+           (piece_attacks<BISHOP>(ksq) & bishops_and_queens(us)));
       break;
 
     case BISHOP:
-      if(bit_is_set(bishop_attacks(ksq), to))
+      if(bit_is_set(piece_attacks<BISHOP>(ksq), to))
         set_bit(&checkersBB, to);
       if(bit_is_set(dcCandidates, from))
         checkersBB |=
-          (rook_attacks(ksq) & rooks_and_queens(us));
+          (piece_attacks<ROOK>(ksq) & rooks_and_queens(us));
       break;
 
     case ROOK:
-      if(bit_is_set(rook_attacks(ksq), to))
+      if(bit_is_set(piece_attacks<ROOK>(ksq), to))
         set_bit(&checkersBB, to);
       if(bit_is_set(dcCandidates, from))
         checkersBB |=
-          (bishop_attacks(ksq) & bishops_and_queens(us));
+          (piece_attacks<BISHOP>(ksq) & bishops_and_queens(us));
       break;
 
     case QUEEN:
-      if(bit_is_set(queen_attacks(ksq), to))
+      if(bit_is_set(piece_attacks<QUEEN>(ksq), to))
         set_bit(&checkersBB, to);
       break;
 
     case KING:
       if(bit_is_set(dcCandidates, from))
         checkersBB |=
-          ((rook_attacks(ksq) & rooks_and_queens(us)) |
-           (bishop_attacks(ksq) & bishops_and_queens(us)));
+          ((piece_attacks<ROOK>(ksq) & rooks_and_queens(us)) |
+           (piece_attacks<BISHOP>(ksq) & bishops_and_queens(us)));
       break;
 
     default:
@@ -1637,10 +1644,10 @@ int Position::see(Square from, Square to) const {
   attackers =
     (rook_attacks_bb(to, occ) & rooks_and_queens()) |
     (bishop_attacks_bb(to, occ) & bishops_and_queens()) |
-    (knight_attacks(to) & knights()) |
-    (king_attacks(to) & kings()) |
-    (white_pawn_attacks(to) & pawns(BLACK)) |
-    (black_pawn_attacks(to) & pawns(WHITE));
+    (piece_attacks<KNIGHT>(to) & knights()) |
+    (piece_attacks<KING>(to) & kings()) |
+    (pawn_attacks(WHITE, to) & pawns(BLACK)) |
+    (pawn_attacks(BLACK, to) & pawns(WHITE));
   attackers &= occ;
 
   // If the opponent has no attackers, we are finished: