]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Big Position renaming
[stockfish] / src / position.cpp
index 085b9a3b1312771512a0b8615678d27283e4c983..57d6dc09bce917c7d9014f1d31340b6ed6134dd8 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <cassert>
 #include <cstring>
-#include <fstream>
 #include <iostream>
 #include <sstream>
 #include <algorithm>
@@ -37,7 +36,7 @@ using std::cout;
 using std::endl;
 
 Key Position::zobrist[2][8][64];
-Key Position::zobEp[64];
+Key Position::zobEp[8];
 Key Position::zobCastle[16];
 Key Position::zobSideToMove;
 Key Position::zobExclusion;
@@ -67,7 +66,7 @@ const Value PieceValueEndgame[17] = {
 namespace {
 
   // Bonus for having the side to move (modified by Joona Kiiski)
-  const Score TempoValue = make_score(48, 22);
+  const Score Tempo = make_score(48, 22);
 
   // To convert a Piece to and from a FEN char
   const string PieceToChar(" PNBRQK  pnbrqk  .");
@@ -78,7 +77,7 @@ namespace {
 
 CheckInfo::CheckInfo(const Position& pos) {
 
-  Color them = flip(pos.side_to_move());
+  Color them = ~pos.side_to_move();
   ksq = pos.king_square(them);
 
   pinned = pos.pinned_pieces();
@@ -165,11 +164,11 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
   // 1. Piece placement
   while ((fen >> token) && !isspace(token))
   {
-      if (token == '/')
-          sq -= Square(16); // Jump back of 2 rows
+      if (isdigit(token))
+          sq += Square(token - '0'); // Advance the given number of files
 
-      else if (isdigit(token))
-          sq += Square(token - '0'); // Skip the given number of files
+      else if (token == '/')
+          sq = make_square(FILE_A, rank_of(sq) - Rank(2));
 
       else if ((p = PieceToChar.find(token)) != string::npos)
       {
@@ -192,15 +191,14 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
   {
       Square rsq;
       Color c = islower(token) ? BLACK : WHITE;
-      Piece rook = make_piece(c, ROOK);
 
       token = char(toupper(token));
 
       if (token == 'K')
-          for (rsq = relative_square(c, SQ_H1); piece_on(rsq) != rook; rsq--) {}
+          for (rsq = relative_square(c, SQ_H1); type_of(piece_on(rsq)) != ROOK; rsq--) {}
 
       else if (token == 'Q')
-          for (rsq = relative_square(c, SQ_A1); piece_on(rsq) != rook; rsq++) {}
+          for (rsq = relative_square(c, SQ_A1); type_of(piece_on(rsq)) != ROOK; rsq++) {}
 
       else if (token >= 'A' && token <= 'H')
           rsq = make_square(File(token - 'A'), relative_rank(c, RANK_1));
@@ -208,7 +206,7 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
       else
           continue;
 
-      set_castle_right(king_square(c), rsq);
+      set_castle_right(c, rsq);
   }
 
   // 4. En passant square. Ignore if no pawn capture is possible
@@ -231,10 +229,10 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
   st->key = compute_key();
   st->pawnKey = compute_pawn_key();
   st->materialKey = compute_material_key();
-  st->value = compute_value();
+  st->psqScore = compute_psq_score();
   st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
   st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
-  st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(flip(sideToMove));
+  st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove);
   chess960 = isChess960;
 
   assert(pos_is_ok());
@@ -242,16 +240,29 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
 
 
 /// Position::set_castle_right() is an helper function used to set castling
-/// rights given the corresponding king and rook starting squares.
+/// rights given the corresponding color and the rook starting square.
 
-void Position::set_castle_right(Square ksq, Square rsq) {
+void Position::set_castle_right(Color c, Square rfrom) {
 
-  int f = (rsq < ksq ? WHITE_OOO : WHITE_OO) << color_of(piece_on(ksq));
+  Square kfrom = king_square(c);
+  bool kingSide = kfrom < rfrom;
+  int cr = (kingSide ? WHITE_OO : WHITE_OOO) << c;
 
-  st->castleRights |= f;
-  castleRightsMask[ksq] ^= f;
-  castleRightsMask[rsq] ^= f;
-  castleRookSquare[f] = rsq;
+  st->castleRights |= cr;
+  castleRightsMask[kfrom] |= cr;
+  castleRightsMask[rfrom] |= cr;
+  castleRookSquare[cr] = rfrom;
+
+  Square kto = relative_square(c, kingSide ? SQ_G1 : SQ_C1);
+  Square rto = relative_square(c, kingSide ? SQ_F1 : SQ_D1);
+
+  for (Square s = std::min(rfrom, rto); s <= std::max(rfrom, rto); s++)
+      if (s != kfrom && s != rfrom)
+          castlePath[cr] |= s;
+
+  for (Square s = std::min(kfrom, kto); s <= std::max(kfrom, kto); s++)
+      if (s != kfrom && s != rfrom)
+          castlePath[cr] |= s;
 }
 
 
@@ -272,7 +283,7 @@ const string Position::to_fen() const {
       {
           sq = make_square(file, rank);
 
-          if (square_is_empty(sq))
+          if (square_empty(sq))
               emptyCnt++;
           else
           {
@@ -325,7 +336,7 @@ void Position::print(Move move) const {
 
   if (move)
   {
-      Position p(*this, thread());
+      Position p(*this, this_thread());
       cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move);
   }
 
@@ -357,8 +368,8 @@ Bitboard Position::hidden_checkers() const {
 
   // Pinned pieces protect our king, dicovery checks attack the enemy king
   Bitboard b, result = 0;
-  Bitboard pinners = pieces(FindPinned ? flip(sideToMove) : sideToMove);
-  Square ksq = king_square(FindPinned ? sideToMove : flip(sideToMove));
+  Bitboard pinners = pieces(FindPinned ? ~sideToMove : sideToMove);
+  Square ksq = king_square(FindPinned ? sideToMove : ~sideToMove);
 
   // Pinners are sliders, that give check when candidate pinned is removed
   pinners &=  (pieces(ROOK, QUEEN) & PseudoAttacks[ROOK][ksq])
@@ -366,10 +377,9 @@ Bitboard Position::hidden_checkers() const {
 
   while (pinners)
   {
-      b = squares_between(ksq, pop_1st_bit(&pinners)) & occupied_squares();
+      b = squares_between(ksq, pop_1st_bit(&pinners)) & pieces();
 
-      // Only one bit set and is an our piece?
-      if (b && !(b & (b - 1)) && (b & pieces(sideToMove)))
+      if (b && single_bit(b) && (b & pieces(sideToMove)))
           result |= b;
   }
   return result;
@@ -388,8 +398,8 @@ Bitboard Position::attackers_to(Square s, Bitboard occ) const {
   return  (attacks_from<PAWN>(s, BLACK) & pieces(PAWN, WHITE))
         | (attacks_from<PAWN>(s, WHITE) & pieces(PAWN, BLACK))
         | (attacks_from<KNIGHT>(s)      & pieces(KNIGHT))
-        | (rook_attacks_bb(s, occ)      & pieces(ROOK, QUEEN))
-        | (bishop_attacks_bb(s, occ)    & pieces(BISHOP, QUEEN))
+        | (attacks_bb<ROOK>(s, occ)     & pieces(ROOK, QUEEN))
+        | (attacks_bb<BISHOP>(s, occ)   & pieces(BISHOP, QUEEN))
         | (attacks_from<KING>(s)        & pieces(KING));
 }
 
@@ -399,13 +409,13 @@ Bitboard Position::attackers_to(Square s, Bitboard occ) const {
 
 Bitboard Position::attacks_from(Piece p, Square s, Bitboard occ) {
 
-  assert(square_is_ok(s));
+  assert(is_ok(s));
 
   switch (type_of(p))
   {
-  case BISHOP: return bishop_attacks_bb(s, occ);
-  case ROOK  : return rook_attacks_bb(s, occ);
-  case QUEEN : return bishop_attacks_bb(s, occ) | rook_attacks_bb(s, occ);
+  case BISHOP: return attacks_bb<BISHOP>(s, occ);
+  case ROOK  : return attacks_bb<ROOK>(s, occ);
+  case QUEEN : return attacks_bb<BISHOP>(s, occ) | attacks_bb<ROOK>(s, occ);
   default    : return StepAttacksBB[p][s];
   }
 }
@@ -417,26 +427,25 @@ Bitboard Position::attacks_from(Piece p, Square s, Bitboard occ) {
 bool Position::move_attacks_square(Move m, Square s) const {
 
   assert(is_ok(m));
-  assert(square_is_ok(s));
+  assert(is_ok(s));
 
   Bitboard occ, xray;
   Square from = from_sq(m);
   Square to = to_sq(m);
-  Piece piece = piece_on(from);
+  Piece piece = piece_moved(m);
 
-  assert(!square_is_empty(from));
+  assert(!square_empty(from));
 
   // Update occupancy as if the piece is moving
-  occ = occupied_squares();
-  do_move_bb(&occ, make_move_bb(from, to));
+  occ = pieces() ^ from ^ to;
 
   // The piece moved in 'to' attacks the square 's' ?
-  if (bit_is_set(attacks_from(piece, to, occ), s))
+  if (attacks_from(piece, to, occ) & s)
       return true;
 
   // Scan for possible X-ray attackers behind the moved piece
-  xray = (rook_attacks_bb(s, occ)   & pieces(ROOK, QUEEN, color_of(piece)))
-        |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN, color_of(piece)));
+  xray = (attacks_bb<ROOK>(s, occ)   & pieces(ROOK, QUEEN, color_of(piece)))
+        |(attacks_bb<BISHOP>(s, occ) & pieces(BISHOP, QUEEN, color_of(piece)));
 
   // Verify attackers are triggered by our move and not already existing
   return xray && (xray ^ (xray & attacks_from<QUEEN>(s)));
@@ -450,10 +459,10 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   assert(is_ok(m));
   assert(pinned == pinned_pieces());
 
-  Color us = side_to_move();
+  Color us = sideToMove;
   Square from = from_sq(m);
 
-  assert(color_of(piece_on(from)) == us);
+  assert(color_of(piece_moved(m)) == us);
   assert(piece_on(king_square(us)) == make_piece(us, KING));
 
   // En passant captures are a tricky special case. Because they are rather
@@ -461,35 +470,31 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   // the move is made.
   if (is_enpassant(m))
   {
-      Color them = flip(us);
+      Color them = ~us;
       Square to = to_sq(m);
       Square capsq = to + pawn_push(them);
       Square ksq = king_square(us);
-      Bitboard b = occupied_squares();
+      Bitboard b = (pieces() ^ from ^ capsq) | to;
 
       assert(to == ep_square());
-      assert(piece_on(from) == make_piece(us, PAWN));
+      assert(piece_moved(m) == make_piece(us, PAWN));
       assert(piece_on(capsq) == make_piece(them, PAWN));
       assert(piece_on(to) == NO_PIECE);
 
-      clear_bit(&b, from);
-      clear_bit(&b, capsq);
-      set_bit(&b, to);
-
-      return   !(rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them))
-            && !(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them));
+      return   !(attacks_bb<ROOK>(ksq, b) & pieces(ROOK, QUEEN, them))
+            && !(attacks_bb<BISHOP>(ksq, b) & pieces(BISHOP, QUEEN, them));
   }
 
   // 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(piece_on(from)) == KING)
-      return is_castle(m) || !(attackers_to(to_sq(m)) & pieces(flip(us)));
+      return is_castle(m) || !(attackers_to(to_sq(m)) & pieces(~us));
 
   // 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
-        || !bit_is_set(pinned, from)
+        || !(pinned & from)
         ||  squares_aligned(from, to_sq(m), king_square(us));
 }
 
@@ -515,17 +520,17 @@ bool Position::move_is_legal(const Move m) const {
 bool Position::is_pseudo_legal(const Move m) const {
 
   Color us = sideToMove;
-  Color them = flip(sideToMove);
+  Color them = ~sideToMove;
   Square from = from_sq(m);
   Square to = to_sq(m);
-  Piece pc = piece_on(from);
+  Piece pc = piece_moved(m);
 
   // Use a slower but simpler function for uncommon cases
   if (is_special(m))
       return move_is_legal(m);
 
   // Is not a promotion, so promotion piece must be empty
-  if (promotion_piece_type(m) - 2 != NO_PIECE_TYPE)
+  if (promotion_type(m) - 2 != NO_PIECE_TYPE)
       return false;
 
   // If the from square is not occupied by a piece belonging to the side to
@@ -571,7 +576,7 @@ bool Position::is_pseudo_legal(const Move m) const {
       case DELTA_N:
       case DELTA_S:
       // Pawn push. The destination square must be empty.
-      if (!square_is_empty(to))
+      if (!square_empty(to))
           return false;
       break;
 
@@ -580,8 +585,8 @@ bool Position::is_pseudo_legal(const Move m) const {
       // rank, and both the destination square and the square between the
       // source and destination squares must be empty.
       if (   rank_of(to) != RANK_4
-          || !square_is_empty(to)
-          || !square_is_empty(from + DELTA_N))
+          || !square_empty(to)
+          || !square_empty(from + DELTA_N))
           return false;
       break;
 
@@ -590,8 +595,8 @@ bool Position::is_pseudo_legal(const Move m) const {
       // rank, and both the destination square and the square between the
       // source and destination squares must be empty.
       if (   rank_of(to) != RANK_5
-          || !square_is_empty(to)
-          || !square_is_empty(from + DELTA_S))
+          || !square_empty(to)
+          || !square_empty(from + DELTA_S))
           return false;
       break;
 
@@ -599,7 +604,7 @@ bool Position::is_pseudo_legal(const Move m) const {
           return false;
       }
   }
-  else if (!bit_is_set(attacks_from(pc, from), to))
+  else if (!(attacks_from(pc, from) & to))
       return false;
 
   // Evasions generator already takes care to avoid some kind of illegal moves
@@ -607,28 +612,22 @@ bool Position::is_pseudo_legal(const Move m) const {
   // same kind of moves are filtered out here.
   if (in_check())
   {
-      // In case of king moves under check we have to remove king so to catch
-      // as invalid moves like b1a1 when opposite queen is on c1.
-      if (type_of(piece_on(from)) == KING)
-      {
-          Bitboard b = occupied_squares();
-          clear_bit(&b, from);
-          if (attackers_to(to_sq(m), b) & pieces(flip(us)))
-              return false;
-      }
-      else
+      if (type_of(pc) != KING)
       {
-          Bitboard target = checkers();
-          Square checksq = pop_1st_bit(&target);
+          Bitboard b = checkers();
+          Square checksq = pop_1st_bit(&b);
 
-          if (target) // double check ? In this case a king move is required
+          if (b) // double check ? In this case a king move is required
               return false;
 
           // Our move must be a blocking evasion or a capture of the checking piece
-          target = squares_between(checksq, king_square(us)) | checkers();
-          if (!bit_is_set(target, to_sq(m)))
+          if (!((squares_between(checksq, king_square(us)) | checkers()) & to))
               return false;
       }
+      // In case of king moves under check we have to remove king so to catch
+      // as invalid moves like b1a1 when opposite queen is on c1.
+      else if (attackers_to(to, pieces() ^ from) & pieces(~us))
+          return false;
   }
 
   return true;
@@ -641,22 +640,22 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
 
   assert(is_ok(m));
   assert(ci.dcCandidates == discovered_check_candidates());
-  assert(color_of(piece_moved(m)) == side_to_move());
+  assert(color_of(piece_moved(m)) == sideToMove);
 
   Square from = from_sq(m);
   Square to = to_sq(m);
   PieceType pt = type_of(piece_on(from));
 
   // Direct check ?
-  if (bit_is_set(ci.checkSq[pt], to))
+  if (ci.checkSq[pt] & to)
       return true;
 
   // Discovery check ?
-  if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from))
+  if (ci.dcCandidates && (ci.dcCandidates & from))
   {
       // For pawn and king moves we need to verify also direction
       if (  (pt != PAWN && pt != KING)
-          || !squares_aligned(from, to, king_square(flip(side_to_move()))))
+          || !squares_aligned(from, to, king_square(~sideToMove)))
           return true;
   }
 
@@ -664,16 +663,12 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
   if (!is_special(m))
       return false;
 
-  Color us = side_to_move();
-  Bitboard b = occupied_squares();
-  Square ksq = king_square(flip(us));
+  Color us = sideToMove;
+  Square ksq = king_square(~us);
 
   // Promotion with check ?
   if (is_promotion(m))
-  {
-      clear_bit(&b, from);
-      return bit_is_set(attacks_from(Piece(promotion_piece_type(m)), to, b), ksq);
-  }
+      return attacks_from(Piece(promotion_type(m)), to, pieces() ^ from) & ksq;
 
   // En passant capture with check ? We have already handled the case
   // of direct checks and ordinary discovered check, the only case we
@@ -682,33 +677,22 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
   if (is_enpassant(m))
   {
       Square capsq = make_square(file_of(to), rank_of(from));
-      clear_bit(&b, from);
-      clear_bit(&b, capsq);
-      set_bit(&b, to);
-      return  (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us))
-            ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us));
+      Bitboard b = (pieces() ^ from ^ capsq) | to;
+
+      return  (attacks_bb<  ROOK>(ksq, b) & pieces(  ROOK, QUEEN, us))
+            | (attacks_bb<BISHOP>(ksq, b) & pieces(BISHOP, QUEEN, us));
   }
 
   // Castling with check ?
   if (is_castle(m))
   {
-      Square kfrom, kto, rfrom, rto;
-      kfrom = from;
-      rfrom = to;
+      Square kfrom = from;
+      Square rfrom = to; // 'King captures the rook' notation
+      Square kto = relative_square(us, rfrom > kfrom ? SQ_G1 : SQ_C1);
+      Square rto = relative_square(us, rfrom > kfrom ? SQ_F1 : SQ_D1);
+      Bitboard b = (pieces() ^ kfrom ^ rfrom) | rto | kto;
 
-      if (rfrom > kfrom)
-      {
-          kto = relative_square(us, SQ_G1);
-          rto = relative_square(us, SQ_F1);
-      } else {
-          kto = relative_square(us, SQ_C1);
-          rto = relative_square(us, SQ_D1);
-      }
-      clear_bit(&b, kfrom);
-      clear_bit(&b, rfrom);
-      set_bit(&b, rto);
-      set_bit(&b, kto);
-      return bit_is_set(rook_attacks_bb(rto, b), ksq);
+      return attacks_bb<ROOK>(rto, b) & ksq;
   }
 
   return false;
@@ -740,7 +724,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
     Key pawnKey, materialKey;
     Value npMaterial[2];
     int castleRights, rule50, pliesFromNull;
-    Score value;
+    Score psq_score;
     Square epSquare;
   };
 
@@ -753,7 +737,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   k ^= zobSideToMove;
 
   // Increment the 50 moves rule draw counter. Resetting it to zero in the
-  // case of non-reversible moves is taken care of later.
+  // case of a capture or a pawn move is taken care of later.
   st->rule50++;
   st->pliesFromNull++;
 
@@ -764,8 +748,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
       return;
   }
 
-  Color us = side_to_move();
-  Color them = flip(us);
+  Color us = sideToMove;
+  Color them = ~us;
   Square from = from_sq(m);
   Square to = to_sq(m);
   Piece piece = piece_on(from);
@@ -803,9 +787,9 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
           st->npMaterial[them] -= PieceValueMidgame[capture];
 
       // Remove the captured piece
-      clear_bit(&byColorBB[them], capsq);
-      clear_bit(&byTypeBB[capture], capsq);
-      clear_bit(&occupied, capsq);
+      byTypeBB[ALL_PIECES] ^= capsq;
+      byTypeBB[capture] ^= capsq;
+      byColorBB[them] ^= capsq;
 
       // Update piece list, move the last piece at index[capsq] position and
       // shrink the list.
@@ -824,7 +808,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
       st->materialKey ^= zobrist[them][capture][pieceCount[them][capture]];
 
       // Update incremental scores
-      st->value -= pst(make_piece(them, capture), capsq);
+      st->psqScore -= pieceSquareTable[make_piece(them, capture)][capsq];
 
       // Reset rule 50 counter
       st->rule50 = 0;
@@ -836,27 +820,26 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   // Reset en passant square
   if (st->epSquare != SQ_NONE)
   {
-      k ^= zobEp[st->epSquare];
+      k ^= zobEp[file_of(st->epSquare)];
       st->epSquare = SQ_NONE;
   }
 
   // Update castle rights if needed
-  if (    st->castleRights != CASTLES_NONE
-      && (castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
+  if (st->castleRights && (castleRightsMask[from] | castleRightsMask[to]))
   {
-      k ^= zobCastle[st->castleRights];
-      st->castleRights &= castleRightsMask[from] & castleRightsMask[to];
-      k ^= zobCastle[st->castleRights];
+      int cr = castleRightsMask[from] | castleRightsMask[to];
+      k ^= zobCastle[st->castleRights & cr];
+      st->castleRights &= ~cr;
   }
 
   // Prefetch TT access as soon as we know key is updated
   prefetch((char*)TT.first_entry(k));
 
   // Move the piece
-  Bitboard move_bb = make_move_bb(from, to);
-  do_move_bb(&byColorBB[us], move_bb);
-  do_move_bb(&byTypeBB[pt], move_bb);
-  do_move_bb(&occupied, move_bb);
+  Bitboard from_to_bb = SquareBB[from] | SquareBB[to];
+  byTypeBB[ALL_PIECES] ^= from_to_bb;
+  byTypeBB[pt] ^= from_to_bb;
+  byColorBB[us] ^= from_to_bb;
 
   board[to] = board[from];
   board[from] = NO_PIECE;
@@ -870,23 +853,23 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   if (pt == PAWN)
   {
       // Set en-passant square, only if moved pawn can be captured
-      if (   (to ^ from) == 16
+      if (   (int(to) ^ int(from)) == 16
           && (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(PAWN, them)))
       {
           st->epSquare = Square((from + to) / 2);
-          k ^= zobEp[st->epSquare];
+          k ^= zobEp[file_of(st->epSquare)];
       }
 
       if (is_promotion(m))
       {
-          PieceType promotion = promotion_piece_type(m);
+          PieceType promotion = promotion_type(m);
 
           assert(relative_rank(us, to) == RANK_8);
           assert(promotion >= KNIGHT && promotion <= QUEEN);
 
           // Replace the pawn with the promoted piece
-          clear_bit(&byTypeBB[PAWN], to);
-          set_bit(&byTypeBB[promotion], to);
+          byTypeBB[PAWN] ^= to;
+          byTypeBB[promotion] |= to;
           board[to] = make_piece(us, promotion);
 
           // Update piece lists, move the last pawn at index[to] position
@@ -905,8 +888,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
                             ^ zobrist[us][PAWN][pieceCount[us][PAWN]];
 
           // Update incremental score
-          st->value +=  pst(make_piece(us, promotion), to)
-                      - pst(make_piece(us, PAWN), to);
+          st->psqScore +=  pieceSquareTable[make_piece(us, promotion)][to]
+                         - pieceSquareTable[make_piece(us, PAWN)][to];
 
           // Update material
           st->npMaterial[us] += PieceValueMidgame[promotion];
@@ -920,11 +903,11 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   }
 
   // Prefetch pawn and material hash tables
-  Threads[threadID].pawnTable.prefetch(st->pawnKey);
-  Threads[threadID].materialTable.prefetch(st->materialKey);
+  prefetch((char*)Threads[threadID].pawnTable.entries[st->pawnKey]);
+  prefetch((char*)Threads[threadID].materialTable.entries[st->materialKey]);
 
   // Update incremental scores
-  st->value += pst_delta(piece, from, to);
+  st->psqScore += psq_delta(piece, from, to);
 
   // Set capture piece
   st->capturedType = capture;
@@ -942,11 +925,11 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
       else
       {
           // Direct checks
-          if (bit_is_set(ci.checkSq[pt], to))
-              st->checkersBB = SetMaskBB[to];
+          if (ci.checkSq[pt] & to)
+              st->checkersBB |= to;
 
           // Discovery checks
-          if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from))
+          if (ci.dcCandidates && (ci.dcCandidates & from))
           {
               if (pt != ROOK)
                   st->checkersBB |= attacks_from<ROOK>(king_square(them)) & pieces(ROOK, QUEEN, us);
@@ -958,8 +941,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   }
 
   // Finish
-  sideToMove = flip(sideToMove);
-  st->value += (sideToMove == WHITE ?  TempoValue : -TempoValue);
+  sideToMove = ~sideToMove;
+  st->psqScore += (sideToMove == WHITE ?  Tempo : -Tempo);
 
   assert(pos_is_ok());
 }
@@ -972,7 +955,7 @@ void Position::undo_move(Move m) {
 
   assert(is_ok(m));
 
-  sideToMove = flip(sideToMove);
+  sideToMove = ~sideToMove;
 
   if (is_castle(m))
   {
@@ -980,29 +963,29 @@ void Position::undo_move(Move m) {
       return;
   }
 
-  Color us = side_to_move();
-  Color them = flip(us);
+  Color us = sideToMove;
+  Color them = ~us;
   Square from = from_sq(m);
   Square to = to_sq(m);
   Piece piece = piece_on(to);
   PieceType pt = type_of(piece);
   PieceType capture = st->capturedType;
 
-  assert(square_is_empty(from));
+  assert(square_empty(from));
   assert(color_of(piece) == us);
   assert(capture != KING);
 
   if (is_promotion(m))
   {
-      PieceType promotion = promotion_piece_type(m);
+      PieceType promotion = promotion_type(m);
 
       assert(promotion == pt);
       assert(relative_rank(us, to) == RANK_8);
       assert(promotion >= KNIGHT && promotion <= QUEEN);
 
       // Replace the promoted piece with the pawn
-      clear_bit(&byTypeBB[promotion], to);
-      set_bit(&byTypeBB[PAWN], to);
+      byTypeBB[promotion] ^= to;
+      byTypeBB[PAWN] |= to;
       board[to] = make_piece(us, PAWN);
 
       // Update piece lists, move the last promoted piece at index[to] position
@@ -1018,10 +1001,10 @@ void Position::undo_move(Move m) {
   }
 
   // Put the piece back at the source square
-  Bitboard move_bb = make_move_bb(to, from);
-  do_move_bb(&byColorBB[us], move_bb);
-  do_move_bb(&byTypeBB[pt], move_bb);
-  do_move_bb(&occupied, move_bb);
+  Bitboard from_to_bb = SquareBB[from] | SquareBB[to];
+  byTypeBB[ALL_PIECES] ^= from_to_bb;
+  byTypeBB[pt] ^= from_to_bb;
+  byColorBB[us] ^= from_to_bb;
 
   board[from] = board[to];
   board[to] = NO_PIECE;
@@ -1046,9 +1029,9 @@ void Position::undo_move(Move m) {
       }
 
       // Restore the captured piece
-      set_bit(&byColorBB[them], capsq);
-      set_bit(&byTypeBB[capture], capsq);
-      set_bit(&occupied, capsq);
+      byTypeBB[ALL_PIECES] |= capsq;
+      byTypeBB[capture] |= capsq;
+      byColorBB[them] |= capsq;
 
       board[capsq] = make_piece(them, capture);
 
@@ -1076,7 +1059,7 @@ void Position::do_castle_move(Move m) {
 
   Square kto, kfrom, rfrom, rto, kAfter, rAfter;
 
-  Color us = side_to_move();
+  Color us = sideToMove;
   Square kBefore = from_sq(m);
   Square rBefore = to_sq(m);
 
@@ -1102,20 +1085,20 @@ void Position::do_castle_move(Move m) {
   assert(piece_on(rfrom) == make_piece(us, ROOK));
 
   // Remove pieces from source squares
-  clear_bit(&byColorBB[us], kfrom);
-  clear_bit(&byTypeBB[KING], kfrom);
-  clear_bit(&occupied, kfrom);
-  clear_bit(&byColorBB[us], rfrom);
-  clear_bit(&byTypeBB[ROOK], rfrom);
-  clear_bit(&occupied, rfrom);
+  byTypeBB[ALL_PIECES] ^= kfrom;
+  byTypeBB[KING] ^= kfrom;
+  byColorBB[us] ^= kfrom;
+  byTypeBB[ALL_PIECES] ^= rfrom;
+  byTypeBB[ROOK] ^= rfrom;
+  byColorBB[us] ^= rfrom;
 
   // Put pieces on destination squares
-  set_bit(&byColorBB[us], kto);
-  set_bit(&byTypeBB[KING], kto);
-  set_bit(&occupied, kto);
-  set_bit(&byColorBB[us], rto);
-  set_bit(&byTypeBB[ROOK], rto);
-  set_bit(&occupied, rto);
+  byTypeBB[ALL_PIECES] |= kto;
+  byTypeBB[KING] |= kto;
+  byColorBB[us] |= kto;
+  byTypeBB[ALL_PIECES] |= rto;
+  byTypeBB[ROOK] |= rto;
+  byColorBB[us] |= rto;
 
   // Update board
   Piece king = make_piece(us, KING);
@@ -1137,8 +1120,8 @@ void Position::do_castle_move(Move m) {
       st->capturedType = NO_PIECE_TYPE;
 
       // Update incremental scores
-      st->value += pst_delta(king, kfrom, kto);
-      st->value += pst_delta(rook, rfrom, rto);
+      st->psqScore += psq_delta(king, kfrom, kto);
+      st->psqScore += psq_delta(rook, rfrom, rto);
 
       // Update hash key
       st->key ^= zobrist[us][KING][kfrom] ^ zobrist[us][KING][kto];
@@ -1147,24 +1130,20 @@ void Position::do_castle_move(Move m) {
       // Clear en passant square
       if (st->epSquare != SQ_NONE)
       {
-          st->key ^= zobEp[st->epSquare];
+          st->key ^= zobEp[file_of(st->epSquare)];
           st->epSquare = SQ_NONE;
       }
 
       // Update castling rights
-      st->key ^= zobCastle[st->castleRights];
-      st->castleRights &= castleRightsMask[kfrom];
-      st->key ^= zobCastle[st->castleRights];
-
-      // Reset rule 50 counter
-      st->rule50 = 0;
+      st->key ^= zobCastle[st->castleRights & castleRightsMask[kfrom]];
+      st->castleRights &= ~castleRightsMask[kfrom];
 
       // Update checkers BB
-      st->checkersBB = attackers_to(king_square(flip(us))) & pieces(us);
+      st->checkersBB = attackers_to(king_square(~us)) & pieces(us);
 
       // Finish
-      sideToMove = flip(sideToMove);
-      st->value += (sideToMove == WHITE ?  TempoValue : -TempoValue);
+      sideToMove = ~sideToMove;
+      st->psqScore += (sideToMove == WHITE ?  Tempo : -Tempo);
   }
   else
       // Undo: point our state pointer back to the previous state
@@ -1190,16 +1169,16 @@ void Position::do_null_move(StateInfo& backupSt) {
 
   dst->key      = src->key;
   dst->epSquare = src->epSquare;
-  dst->value    = src->value;
+  dst->psqScore = src->psqScore;
   dst->rule50   = src->rule50;
   dst->pliesFromNull = src->pliesFromNull;
 
-  sideToMove = flip(sideToMove);
+  sideToMove = ~sideToMove;
 
   if (Do)
   {
       if (st->epSquare != SQ_NONE)
-          st->key ^= zobEp[st->epSquare];
+          st->key ^= zobEp[file_of(st->epSquare)];
 
       st->key ^= zobSideToMove;
       prefetch((char*)TT.first_entry(st->key));
@@ -1207,7 +1186,7 @@ void Position::do_null_move(StateInfo& backupSt) {
       st->epSquare = SQ_NONE;
       st->rule50++;
       st->pliesFromNull = 0;
-      st->value += (sideToMove == WHITE) ?  TempoValue : -TempoValue;
+      st->psqScore += (sideToMove == WHITE ?  Tempo : -Tempo);
   }
 
   assert(pos_is_ok());
@@ -1228,13 +1207,10 @@ int Position::see_sign(Move m) const {
 
   assert(is_ok(m));
 
-  Square from = from_sq(m);
-  Square to = to_sq(m);
-
   // Early return if SEE cannot be negative because captured piece value
   // is not less then capturing one. Note that king moves always return
   // here because king midgame value is set to 0.
-  if (PieceValueMidgame[piece_on(to)] >= PieceValueMidgame[piece_on(from)])
+  if (PieceValueMidgame[piece_on(to_sq(m))] >= PieceValueMidgame[piece_moved(m)])
       return 1;
 
   return see(m);
@@ -1259,28 +1235,28 @@ int Position::see(Move m) const {
   from = from_sq(m);
   to = to_sq(m);
   capturedType = type_of(piece_on(to));
-  occ = occupied_squares();
+  occ = pieces();
 
   // Handle en passant moves
   if (is_enpassant(m))
   {
-      Square capQq = to - pawn_push(side_to_move());
+      Square capQq = to - pawn_push(sideToMove);
 
-      assert(capturedType == NO_PIECE_TYPE);
+      assert(!capturedType);
       assert(type_of(piece_on(capQq)) == PAWN);
 
       // Remove the captured pawn
-      clear_bit(&occ, capQq);
+      occ ^= capQq;
       capturedType = PAWN;
   }
 
   // Find all attackers to the destination square, with the moving piece
   // removed, but possibly an X-ray attacker added behind it.
-  clear_bit(&occ, from);
+  occ ^= from;
   attackers = attackers_to(to, occ);
 
   // If the opponent has no attackers we are finished
-  stm = flip(color_of(piece_on(from)));
+  stm = ~color_of(piece_on(from));
   stmAttackers = attackers & pieces(stm);
   if (!stmAttackers)
       return PieceValueMidgame[capturedType];
@@ -1305,8 +1281,8 @@ int Position::see(Move m) const {
       // and scan for new X-ray attacks behind the attacker.
       b = stmAttackers & pieces(pt);
       occ ^= (b & (~b + 1));
-      attackers |=  (rook_attacks_bb(to, occ)   & pieces(ROOK, QUEEN))
-                  | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN));
+      attackers |=  (attacks_bb<ROOK>(to, occ)   & pieces(ROOK, QUEEN))
+                  | (attacks_bb<BISHOP>(to, occ) & pieces(BISHOP, QUEEN));
 
       attackers &= occ; // Cut out pieces we've already done
 
@@ -1318,7 +1294,7 @@ int Position::see(Move m) const {
       // Remember the value of the capturing piece, and change the side to
       // move before beginning the next iteration.
       capturedType = pt;
-      stm = flip(stm);
+      stm = ~stm;
       stmAttackers = attackers & pieces(stm);
 
       // Stop before processing a king capture
@@ -1344,27 +1320,16 @@ int Position::see(Move m) const {
 
 void Position::clear() {
 
+  memset(this, 0, sizeof(Position));
+  startState.epSquare = SQ_NONE;
   st = &startState;
-  memset(st, 0, sizeof(StateInfo));
-  st->epSquare = SQ_NONE;
-
-  memset(byColorBB,  0, sizeof(Bitboard) * 2);
-  memset(byTypeBB,   0, sizeof(Bitboard) * 8);
-  memset(pieceCount, 0, sizeof(int) * 2 * 8);
-  memset(index,      0, sizeof(int) * 64);
 
   for (int i = 0; i < 8; i++)
       for (int j = 0; j < 16; j++)
           pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE;
 
   for (Square sq = SQ_A1; sq <= SQ_H8; sq++)
-  {
       board[sq] = NO_PIECE;
-      castleRightsMask[sq] = ALL_CASTLES;
-  }
-  sideToMove = WHITE;
-  nodes = 0;
-  occupied = 0;
 }
 
 
@@ -1380,9 +1345,9 @@ void Position::put_piece(Piece p, Square s) {
   index[s] = pieceCount[c][pt]++;
   pieceList[c][pt][index[s]] = s;
 
-  set_bit(&byTypeBB[pt], s);
-  set_bit(&byColorBB[c], s);
-  set_bit(&occupied, s);
+  byTypeBB[ALL_PIECES] |= s;
+  byTypeBB[pt] |= s;
+  byColorBB[c] |= s;
 }
 
 
@@ -1396,13 +1361,13 @@ Key Position::compute_key() const {
   Key result = zobCastle[st->castleRights];
 
   for (Square s = SQ_A1; s <= SQ_H8; s++)
-      if (!square_is_empty(s))
+      if (!square_empty(s))
           result ^= zobrist[color_of(piece_on(s))][type_of(piece_on(s))][s];
 
   if (ep_square() != SQ_NONE)
-      result ^= zobEp[ep_square()];
+      result ^= zobEp[file_of(ep_square())];
 
-  if (side_to_move() == BLACK)
+  if (sideToMove == BLACK)
       result ^= zobSideToMove;
 
   return result;
@@ -1449,11 +1414,11 @@ Key Position::compute_material_key() const {
 }
 
 
-/// Position::compute_value() compute the incremental scores for the middle
+/// Position::compute_psq_score() computes the incremental scores for the middle
 /// game and the endgame. These functions are used to initialize the incremental
 /// scores when a new position is set up, and to verify that the scores are correctly
 /// updated by do_move and undo_move when the program is running in debug mode.
-Score Position::compute_value() const {
+Score Position::compute_psq_score() const {
 
   Bitboard b;
   Score result = SCORE_ZERO;
@@ -1463,10 +1428,10 @@ Score Position::compute_value() const {
       {
           b = pieces(pt, c);
           while (b)
-              result += pst(make_piece(c, pt), pop_1st_bit(&b));
+              result += pieceSquareTable[make_piece(c, pt)][pop_1st_bit(&b)];
       }
 
-  result += (side_to_move() == WHITE ? TempoValue / 2 : -TempoValue / 2);
+  result += (sideToMove == WHITE ? Tempo / 2 : -Tempo / 2);
   return result;
 }
 
@@ -1499,7 +1464,7 @@ bool Position::is_draw() const {
       return true;
 
   // Draw by the 50 moves rule?
-  if (st->rule50 > 99 && !is_mate())
+  if (st->rule50 > 99 && (!in_check() || MoveList<MV_LEGAL>(*this).size()))
       return true;
 
   // Draw by repetition?
@@ -1531,15 +1496,6 @@ template bool Position::is_draw<false>() const;
 template bool Position::is_draw<true>() const;
 
 
-/// Position::is_mate() returns true or false depending on whether the
-/// side to move is checkmated.
-
-bool Position::is_mate() const {
-
-  return in_check() && !MoveList<MV_LEGAL>(*this).size();
-}
-
-
 /// Position::init() is a static member function which initializes at startup
 /// the various arrays used to compute hash keys and the piece square tables.
 /// The latter is a two-step operation: First, the white halves of the tables
@@ -1555,11 +1511,18 @@ void Position::init() {
           for (Square s = SQ_A1; s <= SQ_H8; s++)
               zobrist[c][pt][s] = rk.rand<Key>();
 
-  for (Square s = SQ_A1; s <= SQ_H8; s++)
-      zobEp[s] = rk.rand<Key>();
+  for (File f = FILE_A; f <= FILE_H; f++)
+      zobEp[f] = rk.rand<Key>();
 
-  for (int i = 0; i < 16; i++)
-      zobCastle[i] = rk.rand<Key>();
+  for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++)
+  {
+      Bitboard b = cr;
+      while (b)
+      {
+          Key k = zobCastle[1ULL << pop_1st_bit(&b)];
+          zobCastle[cr] ^= k ? k : rk.rand<Key>();
+      }
+  }
 
   zobSideToMove = rk.rand<Key>();
   zobExclusion  = rk.rand<Key>();
@@ -1571,47 +1534,47 @@ void Position::init() {
       for (Square s = SQ_A1; s <= SQ_H8; s++)
       {
           pieceSquareTable[p][s] = ps + PSQT[p][s];
-          pieceSquareTable[p+8][flip(s)] = -pieceSquareTable[p][s];
+          pieceSquareTable[p+8][~s] = -pieceSquareTable[p][s];
       }
   }
 }
 
 
-/// Position::flip_me() flips position with the white and black sides reversed. This
+/// Position::flip() flips position with the white and black sides reversed. This
 /// is only useful for debugging especially for finding evaluation symmetry bugs.
 
-void Position::flip_me() {
+void Position::flip() {
 
   // Make a copy of current position before to start changing
   const Position pos(*this, threadID);
 
   clear();
-  threadID = pos.thread();
+  threadID = pos.this_thread();
 
   // Board
   for (Square s = SQ_A1; s <= SQ_H8; s++)
-      if (!pos.square_is_empty(s))
-          put_piece(Piece(pos.piece_on(s) ^ 8), flip(s));
+      if (!pos.square_empty(s))
+          put_piece(Piece(pos.piece_on(s) ^ 8), ~s);
 
   // Side to move
-  sideToMove = flip(pos.side_to_move());
+  sideToMove = ~pos.side_to_move();
 
   // Castling rights
   if (pos.can_castle(WHITE_OO))
-      set_castle_right(king_square(BLACK), flip(pos.castle_rook_square(WHITE_OO)));
+      set_castle_right(BLACK, ~pos.castle_rook_square(WHITE_OO));
   if (pos.can_castle(WHITE_OOO))
-      set_castle_right(king_square(BLACK), flip(pos.castle_rook_square(WHITE_OOO)));
+      set_castle_right(BLACK, ~pos.castle_rook_square(WHITE_OOO));
   if (pos.can_castle(BLACK_OO))
-      set_castle_right(king_square(WHITE), flip(pos.castle_rook_square(BLACK_OO)));
+      set_castle_right(WHITE, ~pos.castle_rook_square(BLACK_OO));
   if (pos.can_castle(BLACK_OOO))
-      set_castle_right(king_square(WHITE), flip(pos.castle_rook_square(BLACK_OOO)));
+      set_castle_right(WHITE, ~pos.castle_rook_square(BLACK_OOO));
 
   // En passant square
   if (pos.st->epSquare != SQ_NONE)
-      st->epSquare = flip(pos.st->epSquare);
+      st->epSquare = ~pos.st->epSquare;
 
   // Checkers
-  st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(flip(sideToMove));
+  st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove);
 
   // Hash keys
   st->key = compute_key();
@@ -1619,7 +1582,7 @@ void Position::flip_me() {
   st->materialKey = compute_material_key();
 
   // Incremental scores
-  st->value = compute_value();
+  st->psqScore = compute_psq_score();
 
   // Material
   st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
@@ -1653,7 +1616,7 @@ bool Position::pos_is_ok(int* failedStep) const {
   if (failedStep) *failedStep = 1;
 
   // Side to move OK?
-  if (side_to_move() != WHITE && side_to_move() != BLACK)
+  if (sideToMove != WHITE && sideToMove != BLACK)
       return false;
 
   // Are the king squares in the position correct?
@@ -1682,8 +1645,8 @@ bool Position::pos_is_ok(int* failedStep) const {
   if (failedStep) (*failedStep)++;
   if (debugKingCapture)
   {
-      Color us = side_to_move();
-      Color them = flip(us);
+      Color us = sideToMove;
+      Color them = ~us;
       Square ksq = king_square(them);
       if (attackers_to(ksq) & pieces(us))
           return false;
@@ -1699,12 +1662,12 @@ bool Position::pos_is_ok(int* failedStep) const {
   if (debugBitboards)
   {
       // The intersection of the white and black pieces must be empty
-      if (!(pieces(WHITE) & pieces(BLACK)))
+      if (pieces(WHITE) & pieces(BLACK))
           return false;
 
       // The union of the white and black pieces must be equal to all
       // occupied squares
-      if ((pieces(WHITE) | pieces(BLACK)) != occupied_squares())
+      if ((pieces(WHITE) | pieces(BLACK)) != pieces())
           return false;
 
       // Separate piece type bitboards must have empty intersections
@@ -1720,7 +1683,7 @@ bool Position::pos_is_ok(int* failedStep) const {
   {
       // The en passant square must be on rank 6, from the point of view of the
       // side to move.
-      if (relative_rank(side_to_move(), ep_square()) != RANK_6)
+      if (relative_rank(sideToMove, ep_square()) != RANK_6)
           return false;
   }
 
@@ -1741,7 +1704,7 @@ bool Position::pos_is_ok(int* failedStep) const {
 
   // Incremental eval OK?
   if (failedStep) (*failedStep)++;
-  if (debugIncrementalEval && st->value != compute_value())
+  if (debugIncrementalEval && st->psqScore != compute_psq_score())
       return false;
 
   // Non-pawn material OK?
@@ -1785,8 +1748,8 @@ bool Position::pos_is_ok(int* failedStep) const {
 
           Piece rook = (f & (WHITE_OO | WHITE_OOO) ? W_ROOK : B_ROOK);
 
-          if (   castleRightsMask[castleRookSquare[f]] != (ALL_CASTLES ^ f)
-              || piece_on(castleRookSquare[f]) != rook)
+          if (   piece_on(castleRookSquare[f]) != rook
+              || castleRightsMask[castleRookSquare[f]] != f)
               return false;
       }