]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Second take at unifying bitboard representation access
[stockfish] / src / position.cpp
index c5d057980c55fdf4320d088b308d307a6681e42b..770d47f5d17026ef0e0d0f53c7dabfcc502b4354 100644 (file)
@@ -340,8 +340,8 @@ Bitboard Position::hidden_checkers(Color c) const {
 
   // Pinners are sliders, not checkers, that give check when
   // candidate pinned is removed.
-  pinners =  (rooks_and_queens(FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq])
-           | (bishops_and_queens(FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]);
+  pinners =  (pieces(ROOK, QUEEN, FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq])
+           | (pieces(BISHOP, QUEEN, FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]);
 
   if (FindPinned && pinners)
       pinners &= ~st->checkersBB;
@@ -384,12 +384,12 @@ Bitboard Position::discovered_check_candidates(Color c) const {
 
 Bitboard Position::attacks_to(Square s) const {
 
-  return  (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));
+  return  (pawn_attacks(BLACK, s)   & pieces(PAWN, WHITE))
+        | (pawn_attacks(WHITE, s)   & pieces(PAWN, BLACK))
+        | (piece_attacks<KNIGHT>(s) & pieces(KNIGHT))
+        | (piece_attacks<ROOK>(s)   & pieces(ROOK, QUEEN))
+        | (piece_attacks<BISHOP>(s) & pieces(BISHOP, QUEEN))
+        | (piece_attacks<KING>(s)   & pieces(KING));
 }
 
 /// Position::piece_attacks_square() tests whether the piece on square f
@@ -435,8 +435,8 @@ bool Position::move_attacks_square(Move m, Square s) const {
   Color us = color_of_piece_on(f);
   clear_bit(&occ, f);
   set_bit(&occ, t);
-  Bitboard xray = ( (rook_attacks_bb(s, occ) & rooks_and_queens())
-                   |(bishop_attacks_bb(s, occ) & bishops_and_queens())) & pieces_of_color(us);
+  Bitboard xray = ( (rook_attacks_bb(s, occ) &  pieces(ROOK, QUEEN))
+                   |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN))) & pieces_of_color(us);
 
   // If we have attacks we need to verify that are caused by our move
   // and are not already existent ones.
@@ -503,8 +503,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
       clear_bit(&b, capsq);
       set_bit(&b, to);
 
-      return   !(rook_attacks_bb(ksq, b) & rooks_and_queens(them))
-            && !(bishop_attacks_bb(ksq, b) & bishops_and_queens(them));
+      return   !(rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them))
+            && !(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them));
   }
 
   // If the moving piece is a king, check whether the destination
@@ -586,8 +586,8 @@ bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
           clear_bit(&b, from);
           clear_bit(&b, capsq);
           set_bit(&b, to);
-          return  (rook_attacks_bb(ksq, b) & rooks_and_queens(us))
-                ||(bishop_attacks_bb(ksq, b) & bishops_and_queens(us));
+          return  (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us))
+                ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us));
       }
       return false;
 
@@ -674,10 +674,10 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square
   if (Piece != QUEEN && bit_is_set(dcCandidates, from))
   {
       if (Piece != ROOK)
-          (*pCheckersBB) |= (piece_attacks<ROOK>(ksq) & rooks_and_queens(side_to_move()));
+          (*pCheckersBB) |= (piece_attacks<ROOK>(ksq) & pieces(ROOK, QUEEN, side_to_move()));
 
       if (Piece != BISHOP)
-          (*pCheckersBB) |= (piece_attacks<BISHOP>(ksq) & bishops_and_queens(side_to_move()));
+          (*pCheckersBB) |= (piece_attacks<BISHOP>(ksq) & pieces(BISHOP, QUEEN, side_to_move()));
   }
 }
 
@@ -806,7 +806,7 @@ void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
       // Set en passant square, only if moved pawn can be captured
       if (abs(int(to) - int(from)) == 16)
       {
-          if (pawn_attacks(us, from + (us == WHITE ? DELTA_N : DELTA_S)) & pawns(them))
+          if (pawn_attacks(us, from + (us == WHITE ? DELTA_N : DELTA_S)) & pieces(PAWN, them))
           {
               st->epSquare = Square((int(from) + int(to)) / 2);
               key ^= zobEp[st->epSquare];
@@ -939,6 +939,12 @@ void Position::do_capture_move(Bitboard& key, PieceType capture, Color them, Squ
     pieceCount[them][capture]--;
 
     // Update piece list, move the last piece at index[capsq] position
+    //
+    // WARNING: This is a not perfectly revresible operation. When we
+    // will reinsert the captured piece in undo_move() we will put it
+    // at the end of the list and not in its original place, it means
+    // index[] and pieceList[] are not guaranteed to be invariant to a
+    // do_move() + undo_move() sequence.
     Square lastPieceSquare = pieceList[them][capture][pieceCount[them][capture]];
     index[lastPieceSquare] = index[capsq];
     pieceList[them][capture][index[lastPieceSquare]] = lastPieceSquare;
@@ -1360,12 +1366,12 @@ int Position::see(Square from, Square to) const {
   while (true)
   {
       clear_bit(&occ, from);
-      attackers =  (rook_attacks_bb(to, occ)   & rooks_and_queens())
-                 | (bishop_attacks_bb(to, occ) & bishops_and_queens())
-                 | (piece_attacks<KNIGHT>(to)  & knights())
-                 | (piece_attacks<KING>(to)    & kings())
-                 | (pawn_attacks(WHITE, to)    & pawns(BLACK))
-                 | (pawn_attacks(BLACK, to)    & pawns(WHITE));
+      attackers =  (rook_attacks_bb(to, occ)   & pieces(ROOK, QUEEN))
+                 | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN))
+                 | (piece_attacks<KNIGHT>(to)  & pieces(KNIGHT))
+                 | (piece_attacks<KING>(to)    & pieces(KING))
+                 | (pawn_attacks(WHITE, to)    & pieces(PAWN, BLACK))
+                 | (pawn_attacks(BLACK, to)    & pieces(PAWN, WHITE));
 
       if (from != SQ_NONE)
           break;
@@ -1376,11 +1382,12 @@ int Position::see(Square from, Square to) const {
 
       // Locate the least valuable attacker to the destination square
       // and use it to initialize from square.
+      stmAttackers = attackers & pieces_of_color(us);
       PieceType pt;
-      for (pt = PAWN; !(attackers & pieces_of_color_and_type(us, pt)); pt++)
+      for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
           assert(pt < KING);
 
-      from = first_1(attackers & pieces_of_color_and_type(us, pt));
+      from = first_1(stmAttackers & pieces(pt));
       piece = piece_on(from);
   }
 
@@ -1408,15 +1415,15 @@ int Position::see(Square from, Square to) const {
       // Locate the least valuable attacker for the side to move. The loop
       // below looks like it is potentially infinite, but it isn't. We know
       // that the side to move still has at least one attacker left.
-      for (pt = PAWN; !(stmAttackers & pieces_of_type(pt)); pt++)
+      for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
           assert(pt < KING);
 
       // Remove the attacker we just found from the 'attackers' bitboard,
       // and scan for new X-ray attacks behind the attacker.
-      b = stmAttackers & pieces_of_type(pt);
+      b = stmAttackers & pieces(pt);
       occ ^= (b & (~b + 1));
-      attackers |=  (rook_attacks_bb(to, occ) & rooks_and_queens())
-                  | (bishop_attacks_bb(to, occ) & bishops_and_queens());
+      attackers |=  (rook_attacks_bb(to, occ) &  pieces(ROOK, QUEEN))
+                  | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN));
 
       attackers &= occ;
 
@@ -1582,7 +1589,7 @@ Key Position::compute_pawn_key() const {
 
   for (Color c = WHITE; c <= BLACK; c++)
   {
-      b = pawns(c);
+      b = pieces(PAWN, c);
       while(b)
       {
           s = pop_1st_bit(&b);
@@ -1627,7 +1634,7 @@ Value Position::compute_value() const {
   for (Color c = WHITE; c <= BLACK; c++)
       for (PieceType pt = PAWN; pt <= KING; pt++)
       {
-          b = pieces_of_color_and_type(c, pt);
+          b = pieces(pt, c);
           while(b)
           {
               s = pop_1st_bit(&b);
@@ -1653,7 +1660,7 @@ Value Position::compute_non_pawn_material(Color c) const {
 
   for (PieceType pt = KNIGHT; pt <= QUEEN; pt++)
   {
-      Bitboard b = pieces_of_color_and_type(c, pt);
+      Bitboard b = pieces(pt, c);
       while (b)
       {
           assert(piece_on(first_1(b)) == piece_of_color_and_type(c, pt));
@@ -1672,7 +1679,7 @@ Value Position::compute_non_pawn_material(Color c) const {
 bool Position::is_draw() const {
 
   // Draw by material?
-  if (   !pawns()
+  if (   !pieces(PAWN)
       && (non_pawn_material(WHITE) + non_pawn_material(BLACK) <= BishopValueMidgame))
       return true;
 
@@ -1696,7 +1703,7 @@ bool Position::is_mate() const {
 
   MoveStack moves[256];
 
-  return is_check() && !generate_evasions(*this, moves, pinned_pieces(sideToMove));
+  return is_check() && (generate_evasions(*this, moves, pinned_pieces(sideToMove)) == moves);
 }
 
 
@@ -1716,20 +1723,18 @@ bool Position::has_mate_threat(Color c) {
       do_null_move(st1);
 
   MoveStack mlist[120];
-  int count;
   bool result = false;
   Bitboard dc = discovered_check_candidates(sideToMove);
   Bitboard pinned = pinned_pieces(sideToMove);
 
   // Generate pseudo-legal non-capture and capture check moves
-  count = generate_non_capture_checks(*this, mlist, dc);
-  count += generate_captures(*this, mlist + count);
+  MoveStack* last = generate_non_capture_checks(*this, mlist, dc);
+  last = generate_captures(*this, last);
 
   // Loop through the moves, and see if one of them is mate
-  for (int i = 0; i < count; i++)
+  for (MoveStack* cur = mlist; cur != last; cur++)
   {
-      Move move = mlist[i].move;
-
+      Move move = cur->move;
       if (!pl_move_is_legal(move, pinned))
           continue;
 
@@ -1951,7 +1956,7 @@ bool Position::is_ok(int* failedStep) const {
       // Separate piece type bitboards must have empty intersections
       for (PieceType p1 = PAWN; p1 <= KING; p1++)
           for (PieceType p2 = PAWN; p2 <= KING; p2++)
-              if (p1 != p2 && (pieces_of_type(p1) & pieces_of_type(p2)))
+              if (p1 != p2 && (pieces(p1) & pieces(p2)))
                   return false;
   }
 
@@ -2007,7 +2012,7 @@ bool Position::is_ok(int* failedStep) const {
   if (debugPieceCounts)
       for (Color c = WHITE; c <= BLACK; c++)
           for (PieceType pt = PAWN; pt <= KING; pt++)
-              if (pieceCount[c][pt] != count_1s(pieces_of_color_and_type(c, pt)))
+              if (pieceCount[c][pt] != count_1s(pieces(pt, c)))
                   return false;
 
   if (failedStep) (*failedStep)++;
@@ -2017,7 +2022,7 @@ bool Position::is_ok(int* failedStep) const {
           for(PieceType pt = PAWN; pt <= KING; pt++)
               for(int i = 0; i < pieceCount[c][pt]; i++)
               {
-                  if (piece_on(piece_list(c, pt, i)) != piece_of_color_and_type(c, pt))
+                  if (piece_on(piece_list(c, pt, i)) != (pieces(pt, c)))
                       return false;
 
                   if (index[piece_list(c, pt, i)] != i)