]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Enable easy move detection only for recaptures
[stockfish] / src / position.cpp
index 605cc1ae63f3e63c0f4bd0f13cc68b40b0b979cb..ccc29acf20974d8a09c6a26ccdc209150c76ce1a 100644 (file)
@@ -1,7 +1,7 @@
 /*
   Stockfish, a UCI chess playing engine derived from Glaurung 2.1
   Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
-  Copyright (C) 2008-2010 Marco Costalba, Joona Kiiski, Tord Romstad
+  Copyright (C) 2008-2012 Marco Costalba, Joona Kiiski, Tord Romstad
 
   Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -22,6 +22,7 @@
 #include <fstream>
 #include <iostream>
 #include <sstream>
+#include <algorithm>
 
 #include "bitcount.h"
 #include "movegen.h"
@@ -69,7 +70,7 @@ namespace {
   const Score TempoValue = make_score(48, 22);
 
   // To convert a Piece to and from a FEN char
-  const string PieceToChar(".PNBRQK  pnbrqk  ");
+  const string PieceToChar(" PNBRQK  pnbrqk  .");
 }
 
 
@@ -77,8 +78,8 @@ namespace {
 
 CheckInfo::CheckInfo(const Position& pos) {
 
-  Color them = flip(pos.side_to_move());
-  Square ksq = pos.king_square(them);
+  Color them = ~pos.side_to_move();
+  ksq = pos.king_square(them);
 
   pinned = pos.pinned_pieces();
   dcCandidates = pos.discovered_check_candidates();
@@ -88,7 +89,7 @@ CheckInfo::CheckInfo(const Position& pos) {
   checkSq[BISHOP] = pos.attacks_from<BISHOP>(ksq);
   checkSq[ROOK]   = pos.attacks_from<ROOK>(ksq);
   checkSq[QUEEN]  = checkSq[BISHOP] | checkSq[ROOK];
-  checkSq[KING]   = EmptyBoardBB;
+  checkSq[KING]   = 0;
 }
 
 
@@ -96,9 +97,11 @@ CheckInfo::CheckInfo(const Position& pos) {
 /// or the FEN string, we want the new born Position object do not depend
 /// on any external data so we detach state pointer from the source one.
 
-Position::Position(const Position& pos, int th) {
+void Position::copy(const Position& pos, int th) {
 
   memcpy(this, &pos, sizeof(Position));
+  startState = *st;
+  st = &startState;
   threadID = th;
   nodes = 0;
 
@@ -120,29 +123,35 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
 /*
    A FEN string defines a particular position using only the ASCII character set.
 
-   A FEN string contains six fields. The separator between fields is a space. The fields are:
+   A FEN string contains six fields separated by a space. The fields are:
 
-   1) Piece placement (from white's perspective). Each rank is described, starting with rank 8 and ending
-      with rank 1; within each rank, the contents of each square are described from file A through file H.
-      Following the Standard Algebraic Notation (SAN), each piece is identified by a single letter taken
-      from the standard English names. White pieces are designated using upper-case letters ("PNBRQK")
-      while Black take lowercase ("pnbrqk"). Blank squares are noted using digits 1 through 8 (the number
-      of blank squares), and "/" separate ranks.
+   1) Piece placement (from white's perspective). Each rank is described, starting
+      with rank 8 and ending with rank 1; within each rank, the contents of each
+      square are described from file A through file H. Following the Standard
+      Algebraic Notation (SAN), each piece is identified by a single letter taken
+      from the standard English names. White pieces are designated using upper-case
+      letters ("PNBRQK") while Black take lowercase ("pnbrqk"). Blank squares are
+      noted using digits 1 through 8 (the number of blank squares), and "/"
+      separates ranks.
 
    2) Active color. "w" means white moves next, "b" means black.
 
-   3) Castling availability. If neither side can castle, this is "-". Otherwise, this has one or more
-      letters: "K" (White can castle kingside), "Q" (White can castle queenside), "k" (Black can castle
-      kingside), and/or "q" (Black can castle queenside).
+   3) Castling availability. If neither side can castle, this is "-". Otherwise,
+      this has one or more letters: "K" (White can castle kingside), "Q" (White
+      can castle queenside), "k" (Black can castle kingside), and/or "q" (Black
+      can castle queenside).
 
-   4) En passant target square in algebraic notation. If there's no en passant target square, this is "-".
-      If a pawn has just made a 2-square move, this is the position "behind" the pawn. This is recorded
-      regardless of whether there is a pawn in position to make an en passant capture.
+   4) En passant target square (in algebraic notation). If there's no en passant
+      target square, this is "-". If a pawn has just made a 2-square move, this
+      is the position "behind" the pawn. This is recorded regardless of whether
+      there is a pawn in position to make an en passant capture.
 
-   5) Halfmove clock: This is the number of halfmoves since the last pawn advance or capture. This is used
-      to determine if a draw can be claimed under the fifty-move rule.
+   5) Halfmove clock. This is the number of halfmoves since the last pawn advance
+      or capture. This is used to determine if a draw can be claimed under the
+      fifty-move rule.
 
-   6) Fullmove number: The number of the full move. It starts at 1, and is incremented after Black's move.
+   6) Fullmove number. The number of the full move. It starts at 1, and is
+      incremented after Black's move.
 */
 
   char col, row, token;
@@ -156,11 +165,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)
       {
@@ -183,15 +192,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));
@@ -199,7 +207,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
@@ -217,7 +225,7 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
 
   // Convert from fullmove starting from 1 to ply starting from 0,
   // handle also common incorrect FEN with fullmove = 0.
-  startPosPly = Max(2 * (startPosPly - 1), 0) + int(sideToMove == BLACK);
+  startPosPly = std::max(2 * (startPosPly - 1), 0) + int(sideToMove == BLACK);
 
   st->key = compute_key();
   st->pawnKey = compute_pawn_key();
@@ -225,7 +233,7 @@ void Position::from_fen(const string& fenStr, bool isChess960) {
   st->value = compute_value();
   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());
@@ -233,14 +241,14 @@ 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 rsq) {
 
-  int f = (rsq < ksq ? WHITE_OOO : WHITE_OO) << color_of(piece_on(ksq));
+  int f = (rsq < king_square(c) ? WHITE_OOO : WHITE_OO) << c;
 
   st->castleRights |= f;
-  castleRightsMask[ksq] ^= f;
+  castleRightsMask[king_square(c)] ^= f;
   castleRightsMask[rsq] ^= f;
   castleRookSquare[f] = rsq;
 }
@@ -263,20 +271,20 @@ const string Position::to_fen() const {
       {
           sq = make_square(file, rank);
 
-          if (!square_is_empty(sq))
+          if (square_is_empty(sq))
+              emptyCnt++;
+          else
           {
-              if (emptyCnt)
+              if (emptyCnt > 0)
               {
                   fen << emptyCnt;
                   emptyCnt = 0;
               }
               fen << PieceToChar[piece_on(sq)];
           }
-          else
-              emptyCnt++;
       }
 
-      if (emptyCnt)
+      if (emptyCnt > 0)
           fen << emptyCnt;
 
       if (rank > RANK_1)
@@ -285,24 +293,23 @@ const string Position::to_fen() const {
 
   fen << (sideToMove == WHITE ? " w " : " b ");
 
-  if (st->castleRights != CASTLES_NONE)
-  {
-      if (can_castle(WHITE_OO))
-          fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OO))))) : 'K');
+  if (can_castle(WHITE_OO))
+      fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OO))))) : 'K');
 
-      if (can_castle(WHITE_OOO))
-          fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OOO))))) : 'Q');
+  if (can_castle(WHITE_OOO))
+      fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OOO))))) : 'Q');
 
-      if (can_castle(BLACK_OO))
-          fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OO))) : 'k');
+  if (can_castle(BLACK_OO))
+      fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OO))) : 'k');
 
-      if (can_castle(BLACK_OOO))
-          fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OOO))) : 'q');
-  } else
+  if (can_castle(BLACK_OOO))
+      fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OOO))) : 'q');
+
+  if (st->castleRights == CASTLES_NONE)
       fen << '-';
 
-  fen << (ep_square() == SQ_NONE ? " -" : " " + square_to_string(ep_square()))
-      << " " << st->rule50 << " " << 1 + (startPosPly - int(sideToMove == BLACK)) / 2;
+  fen << (ep_square() == SQ_NONE ? " - " : " " + square_to_string(ep_square()) + " ")
+      << st->rule50 << " " << 1 + (startPosPly - int(sideToMove == BLACK)) / 2;
 
   return fen.str();
 }
@@ -318,8 +325,7 @@ void Position::print(Move move) const {
   if (move)
   {
       Position p(*this, thread());
-      string dd = (sideToMove == BLACK ? ".." : "");
-      cout << "\nMove is: " << dd << move_to_san(p, move);
+      cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move);
   }
 
   for (Rank rank = RANK_8; rank >= RANK_1; rank--)
@@ -329,11 +335,11 @@ void Position::print(Move move) const {
       {
           Square sq = make_square(file, rank);
           Piece piece = piece_on(sq);
+          char c = (color_of(piece) == BLACK ? '=' : ' ');
 
-          if (piece == PIECE_NONE && color_of(sq) == DARK)
-              piece = PIECE_NONE_DARK_SQ;
+          if (piece == NO_PIECE && !opposite_colors(sq, SQ_A1))
+              piece++; // Index the dot
 
-          char c = (color_of(piece_on(sq)) == BLACK ? '=' : ' ');
           cout << c << PieceToChar[piece] << c << '|';
       }
   }
@@ -345,18 +351,17 @@ void Position::print(Move move) const {
 /// king) pieces for the given color. Or, when template parameter FindPinned is
 /// false, the function return the pieces of the given color candidate for a
 /// discovery check against the enemy king.
-
 template<bool FindPinned>
 Bitboard Position::hidden_checkers() const {
 
   // Pinned pieces protect our king, dicovery checks attack the enemy king
-  Bitboard b, result = EmptyBoardBB;
-  Bitboard pinners = pieces(FindPinned ? flip(sideToMove) : sideToMove);
-  Square ksq = king_square(FindPinned ? sideToMove : flip(sideToMove));
+  Bitboard b, result = 0;
+  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) & RookPseudoAttacks[ksq])
-            | (pieces(BISHOP, QUEEN) & BishopPseudoAttacks[ksq]);
+  pinners &=  (pieces(ROOK, QUEEN) & PseudoAttacks[ROOK][ksq])
+            | (pieces(BISHOP, QUEEN) & PseudoAttacks[BISHOP][ksq]);
 
   while (pinners)
   {
@@ -369,26 +374,12 @@ Bitboard Position::hidden_checkers() const {
   return result;
 }
 
+// Explicit template instantiations
+template Bitboard Position::hidden_checkers<true>() const;
+template Bitboard Position::hidden_checkers<false>() const;
 
-/// Position:pinned_pieces() returns a bitboard of all pinned (against the
-/// king) pieces for the side to move.
-
-Bitboard Position::pinned_pieces() const {
-
-  return hidden_checkers<true>();
-}
-
-
-/// Position:discovered_check_candidates() returns a bitboard containing all
-/// pieces for the side to move which are candidates for giving a discovered
-/// check.
-
-Bitboard Position::discovered_check_candidates() const {
-
-  return hidden_checkers<false>();
-}
 
-/// Position::attackers_to() computes a bitboard of all pieces which attacks a
+/// Position::attackers_to() computes a bitboard of all pieces which attack a
 /// given square. Slider attacks use occ bitboard as occupancy.
 
 Bitboard Position::attackers_to(Square s, Bitboard occ) const {
@@ -401,6 +392,7 @@ Bitboard Position::attackers_to(Square s, Bitboard occ) const {
         | (attacks_from<KING>(s)        & pieces(KING));
 }
 
+
 /// Position::attacks_from() computes a bitboard of all attacks of a given piece
 /// put in a given square. Slider attacks use occ bitboard as occupancy.
 
@@ -408,12 +400,12 @@ Bitboard Position::attacks_from(Piece p, Square s, Bitboard occ) {
 
   assert(square_is_ok(s));
 
-  switch (p)
+  switch (type_of(p))
   {
-  case WB: case BB: return bishop_attacks_bb(s, occ);
-  case WR: case BR: return rook_attacks_bb(s, occ);
-  case WQ: case BQ: return bishop_attacks_bb(s, occ) | rook_attacks_bb(s, occ);
-  default: return StepAttacksBB[p][s];
+  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);
+  default    : return StepAttacksBB[p][s];
   }
 }
 
@@ -427,22 +419,25 @@ bool Position::move_attacks_square(Move m, Square s) const {
   assert(square_is_ok(s));
 
   Bitboard occ, xray;
-  Square f = move_from(m), t = move_to(m);
+  Square from = from_sq(m);
+  Square to = to_sq(m);
+  Piece piece = piece_on(from);
+
+  assert(!square_is_empty(from));
 
-  assert(!square_is_empty(f));
+  // Update occupancy as if the piece is moving
+  occ = occupied_squares();
+  do_move_bb(&occ, make_move_bb(from, to));
 
-  if (bit_is_set(attacks_from(piece_on(f), t), s))
+  // The piece moved in 'to' attacks the square 's' ?
+  if (bit_is_set(attacks_from(piece, to, occ), s))
       return true;
 
-  // Move the piece and scan for X-ray attacks behind it
-  occ = occupied_squares();
-  do_move_bb(&occ, make_move_bb(f, t));
-  xray = ( (rook_attacks_bb(s, occ)   & pieces(ROOK, QUEEN))
-          |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN)))
-         & pieces(color_of(piece_on(f)));
+  // 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)));
 
-  // If we have attacks we need to verify that are caused by our move
-  // and are not already existent ones.
+  // Verify attackers are triggered by our move and not already existing
   return xray && (xray ^ (xray & attacks_from<QUEEN>(s)));
 }
 
@@ -454,8 +449,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   assert(is_ok(m));
   assert(pinned == pinned_pieces());
 
-  Color us = side_to_move();
-  Square from = move_from(m);
+  Color us = sideToMove;
+  Square from = from_sq(m);
 
   assert(color_of(piece_on(from)) == us);
   assert(piece_on(king_square(us)) == make_piece(us, KING));
@@ -465,8 +460,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   // the move is made.
   if (is_enpassant(m))
   {
-      Color them = flip(us);
-      Square to = move_to(m);
+      Color them = ~us;
+      Square to = to_sq(m);
       Square capsq = to + pawn_push(them);
       Square ksq = king_square(us);
       Bitboard b = occupied_squares();
@@ -474,7 +469,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
       assert(to == ep_square());
       assert(piece_on(from) == make_piece(us, PAWN));
       assert(piece_on(capsq) == make_piece(them, PAWN));
-      assert(piece_on(to) == PIECE_NONE);
+      assert(piece_on(to) == NO_PIECE);
 
       clear_bit(&b, from);
       clear_bit(&b, capsq);
@@ -488,19 +483,19 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   // 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(move_to(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)
-        ||  squares_aligned(from, move_to(m), king_square(us));
+        ||  squares_aligned(from, to_sq(m), king_square(us));
 }
 
 
 /// Position::move_is_legal() takes a random move and tests whether the move
-/// is legal. This version is not very fast and should be used only
-/// in non time-critical paths.
+/// is legal. This version is not very fast and should be used only in non
+/// time-critical paths.
 
 bool Position::move_is_legal(const Move m) const {
 
@@ -519,9 +514,9 @@ 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);
-  Square from = move_from(m);
-  Square to = move_to(m);
+  Color them = ~sideToMove;
+  Square from = from_sq(m);
+  Square to = to_sq(m);
   Piece pc = piece_on(from);
 
   // Use a slower but simpler function for uncommon cases
@@ -529,12 +524,12 @@ bool Position::is_pseudo_legal(const Move m) const {
       return move_is_legal(m);
 
   // Is not a promotion, so promotion piece must be empty
-  if (promotion_piece_type(m) - 2 != PIECE_TYPE_NONE)
+  if (promotion_piece_type(m) - 2 != NO_PIECE_TYPE)
       return false;
 
   // If the from square is not occupied by a piece belonging to the side to
   // move, the move is obviously not legal.
-  if (pc == PIECE_NONE || color_of(pc) != us)
+  if (pc == NO_PIECE || color_of(pc) != us)
       return false;
 
   // The destination square cannot be occupied by a friendly piece
@@ -617,7 +612,7 @@ bool Position::is_pseudo_legal(const Move m) const {
       {
           Bitboard b = occupied_squares();
           clear_bit(&b, from);
-          if (attackers_to(move_to(m), b) & pieces(flip(us)))
+          if (attackers_to(to_sq(m), b) & pieces(~us))
               return false;
       }
       else
@@ -630,7 +625,7 @@ bool Position::is_pseudo_legal(const Move m) const {
 
           // 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, move_to(m)))
+          if (!bit_is_set(target, to_sq(m)))
               return false;
       }
   }
@@ -645,10 +640,10 @@ 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_on(move_from(m))) == side_to_move());
+  assert(color_of(piece_moved(m)) == sideToMove);
 
-  Square from = move_from(m);
-  Square to = move_to(m);
+  Square from = from_sq(m);
+  Square to = to_sq(m);
   PieceType pt = type_of(piece_on(from));
 
   // Direct check ?
@@ -660,7 +655,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
   {
       // 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;
   }
 
@@ -668,9 +663,9 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
   if (!is_special(m))
       return false;
 
-  Color us = side_to_move();
+  Color us = sideToMove;
   Bitboard b = occupied_squares();
-  Square ksq = king_square(flip(us));
+  Square ksq = king_square(~us);
 
   // Promotion with check ?
   if (is_promotion(m))
@@ -735,11 +730,11 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   assert(&newSt != st);
 
   nodes++;
-  Key key = st->key;
+  Key k = st->key;
 
-  // Copy some fields of old state to our new StateInfo object except the
-  // ones which are recalculated from scratch anyway, then switch our state
-  // pointer to point to the new, ready to be updated, state.
+  // Copy some fields of old state to our new StateInfo object except the ones
+  // which are recalculated from scratch anyway, then switch our state pointer
+  // to point to the new, ready to be updated, state.
   struct ReducedStateInfo {
     Key pawnKey, materialKey;
     Value npMaterial[2];
@@ -754,7 +749,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   st = &newSt;
 
   // Update side to move
-  key ^= zobSideToMove;
+  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.
@@ -763,45 +758,42 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
 
   if (is_castle(m))
   {
-      st->key = key;
+      st->key = k;
       do_castle_move<true>(m);
       return;
   }
 
-  Color us = side_to_move();
-  Color them = flip(us);
-  Square from = move_from(m);
-  Square to = move_to(m);
-  bool ep = is_enpassant(m);
-  bool pm = is_promotion(m);
-
+  Color us = sideToMove;
+  Color them = ~us;
+  Square from = from_sq(m);
+  Square to = to_sq(m);
   Piece piece = piece_on(from);
   PieceType pt = type_of(piece);
-  PieceType capture = ep ? PAWN : type_of(piece_on(to));
+  PieceType capture = is_enpassant(m) ? PAWN : type_of(piece_on(to));
 
-  assert(color_of(piece_on(from)) == us);
-  assert(color_of(piece_on(to)) == them || square_is_empty(to));
+  assert(color_of(piece) == us);
+  assert(color_of(piece_on(to)) != us);
   assert(capture != KING);
 
   if (capture)
   {
       Square capsq = to;
 
-      // If the captured piece was a pawn, update pawn hash key, otherwise
+      // If the captured piece is a pawn, update pawn hash key, otherwise
       // update non-pawn material.
       if (capture == PAWN)
       {
-          if (ep) // En passant?
+          if (is_enpassant(m))
           {
               capsq += pawn_push(them);
 
               assert(pt == PAWN);
               assert(to == st->epSquare);
               assert(relative_rank(us, to) == RANK_6);
-              assert(piece_on(to) == PIECE_NONE);
+              assert(piece_on(to) == NO_PIECE);
               assert(piece_on(capsq) == make_piece(them, PAWN));
 
-              board[capsq] = PIECE_NONE;
+              board[capsq] = NO_PIECE;
           }
 
           st->pawnKey ^= zobrist[them][PAWN][capsq];
@@ -809,46 +801,41 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
       else
           st->npMaterial[them] -= PieceValueMidgame[capture];
 
-      // Remove captured piece
+      // Remove the captured piece
       clear_bit(&byColorBB[them], capsq);
       clear_bit(&byTypeBB[capture], capsq);
       clear_bit(&occupied, capsq);
 
-      // Update hash key
-      key ^= zobrist[them][capture][capsq];
-
-      // Update incremental scores
-      st->value -= pst(make_piece(them, capture), capsq);
-
-      // Update piece count
-      pieceCount[them][capture]--;
+      // Update piece list, move the last piece at index[capsq] position and
+      // shrink the list.
+      //
+      // WARNING: This is a not 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 lastSquare = pieceList[them][capture][--pieceCount[them][capture]];
+      index[lastSquare] = index[capsq];
+      pieceList[them][capture][index[lastSquare]] = lastSquare;
+      pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE;
 
-      // Update material hash key
+      // Update hash keys
+      k ^= zobrist[them][capture][capsq];
       st->materialKey ^= zobrist[them][capture][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;
-      pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE;
+      // Update incremental scores
+      st->value -= pst(make_piece(them, capture), capsq);
 
       // Reset rule 50 counter
       st->rule50 = 0;
   }
 
   // Update hash key
-  key ^= zobrist[us][pt][from] ^ zobrist[us][pt][to];
+  k ^= zobrist[us][pt][from] ^ zobrist[us][pt][to];
 
   // Reset en passant square
   if (st->epSquare != SQ_NONE)
   {
-      key ^= zobEp[st->epSquare];
+      k ^= zobEp[st->epSquare];
       st->epSquare = SQ_NONE;
   }
 
@@ -856,13 +843,13 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   if (    st->castleRights != CASTLES_NONE
       && (castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
   {
-      key ^= zobCastle[st->castleRights];
+      k ^= zobCastle[st->castleRights];
       st->castleRights &= castleRightsMask[from] & castleRightsMask[to];
-      key ^= zobCastle[st->castleRights];
+      k ^= zobCastle[st->castleRights];
   }
 
   // Prefetch TT access as soon as we know key is updated
-  prefetch((char*)TT.first_entry(key));
+  prefetch((char*)TT.first_entry(k));
 
   // Move the piece
   Bitboard move_bb = make_move_bb(from, to);
@@ -871,72 +858,64 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   do_move_bb(&occupied, move_bb);
 
   board[to] = board[from];
-  board[from] = PIECE_NONE;
+  board[from] = NO_PIECE;
 
-  // Update piece lists, note that index[from] is not updated and
-  // becomes stale. This works as long as index[] is accessed just
-  // by known occupied squares.
+  // Update piece lists, index[from] is not updated and becomes stale. This
+  // works as long as index[] is accessed just by known occupied squares.
   index[to] = index[from];
   pieceList[us][pt][index[to]] = to;
 
-  // If the moving piece was a pawn do some special extra work
+  // If the moving piece is a pawn do some special extra work
   if (pt == PAWN)
   {
-      // Reset rule 50 draw counter
-      st->rule50 = 0;
-
-      // Update pawn hash key and prefetch in L1/L2 cache
-      st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
-
-      // Set en passant square, only if moved pawn can be captured
-      if ((to ^ from) == 16)
+      // Set en-passant square, only if moved pawn can be captured
+      if (   (to ^ from) == 16
+          && (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(PAWN, them)))
       {
-          if (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(PAWN, them))
-          {
-              st->epSquare = Square((int(from) + int(to)) / 2);
-              key ^= zobEp[st->epSquare];
-          }
+          st->epSquare = Square((from + to) / 2);
+          k ^= zobEp[st->epSquare];
       }
 
-      if (pm) // promotion ?
+      if (is_promotion(m))
       {
           PieceType promotion = promotion_piece_type(m);
 
+          assert(relative_rank(us, to) == RANK_8);
           assert(promotion >= KNIGHT && promotion <= QUEEN);
 
-          // Insert promoted piece instead of pawn
+          // Replace the pawn with the promoted piece
           clear_bit(&byTypeBB[PAWN], to);
           set_bit(&byTypeBB[promotion], to);
           board[to] = make_piece(us, promotion);
 
-          // Update piece counts
-          pieceCount[us][promotion]++;
-          pieceCount[us][PAWN]--;
-
-          // Update material key
-          st->materialKey ^= zobrist[us][PAWN][pieceCount[us][PAWN]];
-          st->materialKey ^= zobrist[us][promotion][pieceCount[us][promotion]-1];
-
           // Update piece lists, move the last pawn at index[to] position
           // and shrink the list. Add a new promotion piece to the list.
-          Square lastPawnSquare = pieceList[us][PAWN][pieceCount[us][PAWN]];
-          index[lastPawnSquare] = index[to];
-          pieceList[us][PAWN][index[lastPawnSquare]] = lastPawnSquare;
+          Square lastSquare = pieceList[us][PAWN][--pieceCount[us][PAWN]];
+          index[lastSquare] = index[to];
+          pieceList[us][PAWN][index[lastSquare]] = lastSquare;
           pieceList[us][PAWN][pieceCount[us][PAWN]] = SQ_NONE;
-          index[to] = pieceCount[us][promotion] - 1;
+          index[to] = pieceCount[us][promotion];
           pieceList[us][promotion][index[to]] = to;
 
-          // Partially revert hash keys update
-          key ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to];
+          // Update hash keys
+          k ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to];
           st->pawnKey ^= zobrist[us][PAWN][to];
+          st->materialKey ^=  zobrist[us][promotion][pieceCount[us][promotion]++]
+                            ^ zobrist[us][PAWN][pieceCount[us][PAWN]];
 
-          // Partially revert and update incremental scores
-          st->value -= pst(make_piece(us, PAWN), to);
-          st->value += pst(make_piece(us, promotion), to);
+          // Update incremental score
+          st->value +=  pst(make_piece(us, promotion), to)
+                      - pst(make_piece(us, PAWN), to);
 
           // Update material
           st->npMaterial[us] += PieceValueMidgame[promotion];
       }
+
+      // Update pawn hash key
+      st->pawnKey ^= zobrist[us][PAWN][from] ^ zobrist[us][PAWN][to];
+
+      // Reset rule 50 draw counter
+      st->rule50 = 0;
   }
 
   // Prefetch pawn and material hash tables
@@ -950,14 +929,14 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   st->capturedType = capture;
 
   // Update the key with the final value
-  st->key = key;
+  st->key = k;
 
   // Update checkers bitboard, piece must be already moved
-  st->checkersBB = EmptyBoardBB;
+  st->checkersBB = 0;
 
   if (moveIsCheck)
   {
-      if (ep | pm)
+      if (is_special(m))
           st->checkersBB = attackers_to(king_square(them)) & pieces(us);
       else
       {
@@ -969,22 +948,121 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
           if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from))
           {
               if (pt != ROOK)
-                  st->checkersBB |= (attacks_from<ROOK>(king_square(them)) & pieces(ROOK, QUEEN, us));
+                  st->checkersBB |= attacks_from<ROOK>(king_square(them)) & pieces(ROOK, QUEEN, us);
 
               if (pt != BISHOP)
-                  st->checkersBB |= (attacks_from<BISHOP>(king_square(them)) & pieces(BISHOP, QUEEN, us));
+                  st->checkersBB |= attacks_from<BISHOP>(king_square(them)) & pieces(BISHOP, QUEEN, us);
           }
       }
   }
 
   // Finish
-  sideToMove = flip(sideToMove);
+  sideToMove = ~sideToMove;
   st->value += (sideToMove == WHITE ?  TempoValue : -TempoValue);
 
   assert(pos_is_ok());
 }
 
 
+/// Position::undo_move() unmakes a move. When it returns, the position should
+/// be restored to exactly the same state as before the move was made.
+
+void Position::undo_move(Move m) {
+
+  assert(is_ok(m));
+
+  sideToMove = ~sideToMove;
+
+  if (is_castle(m))
+  {
+      do_castle_move<false>(m);
+      return;
+  }
+
+  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(color_of(piece) == us);
+  assert(capture != KING);
+
+  if (is_promotion(m))
+  {
+      PieceType promotion = promotion_piece_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);
+      board[to] = make_piece(us, PAWN);
+
+      // Update piece lists, move the last promoted piece at index[to] position
+      // and shrink the list. Add a new pawn to the list.
+      Square lastSquare = pieceList[us][promotion][--pieceCount[us][promotion]];
+      index[lastSquare] = index[to];
+      pieceList[us][promotion][index[lastSquare]] = lastSquare;
+      pieceList[us][promotion][pieceCount[us][promotion]] = SQ_NONE;
+      index[to] = pieceCount[us][PAWN]++;
+      pieceList[us][PAWN][index[to]] = to;
+
+      pt = PAWN;
+  }
+
+  // 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);
+
+  board[from] = board[to];
+  board[to] = NO_PIECE;
+
+  // Update piece lists, index[to] is not updated and becomes stale. This
+  // works as long as index[] is accessed just by known occupied squares.
+  index[from] = index[to];
+  pieceList[us][pt][index[from]] = from;
+
+  if (capture)
+  {
+      Square capsq = to;
+
+      if (is_enpassant(m))
+      {
+          capsq -= pawn_push(us);
+
+          assert(pt == PAWN);
+          assert(to == st->previous->epSquare);
+          assert(relative_rank(us, to) == RANK_6);
+          assert(piece_on(capsq) == NO_PIECE);
+      }
+
+      // Restore the captured piece
+      set_bit(&byColorBB[them], capsq);
+      set_bit(&byTypeBB[capture], capsq);
+      set_bit(&occupied, capsq);
+
+      board[capsq] = make_piece(them, capture);
+
+      // Update piece list, add a new captured piece in capsq square
+      index[capsq] = pieceCount[them][capture]++;
+      pieceList[them][capture][index[capsq]] = capsq;
+  }
+
+  // Finally point our state pointer back to the previous state
+  st = st->previous;
+
+  assert(pos_is_ok());
+}
+
+
 /// Position::do_castle_move() is a private method used to do/undo a castling
 /// move. Note that castling moves are encoded as "king captures friendly rook"
 /// moves, for instance white short castling in a non-Chess960 game is encoded
@@ -997,9 +1075,9 @@ void Position::do_castle_move(Move m) {
 
   Square kto, kfrom, rfrom, rto, kAfter, rAfter;
 
-  Color us = side_to_move();
-  Square kBefore = move_from(m);
-  Square rBefore = move_to(m);
+  Color us = sideToMove;
+  Square kBefore = from_sq(m);
+  Square rBefore = to_sq(m);
 
   // Find after-castle squares for king and rook
   if (rBefore > kBefore) // O-O
@@ -1041,7 +1119,7 @@ void Position::do_castle_move(Move m) {
   // Update board
   Piece king = make_piece(us, KING);
   Piece rook = make_piece(us, ROOK);
-  board[kfrom] = board[rfrom] = PIECE_NONE;
+  board[kfrom] = board[rfrom] = NO_PIECE;
   board[kto] = king;
   board[rto] = rook;
 
@@ -1055,7 +1133,7 @@ void Position::do_castle_move(Move m) {
   if (Do)
   {
       // Reset capture field
-      st->capturedType = PIECE_TYPE_NONE;
+      st->capturedType = NO_PIECE_TYPE;
 
       // Update incremental scores
       st->value += pst_delta(king, kfrom, kto);
@@ -1081,10 +1159,10 @@ void Position::do_castle_move(Move m) {
       st->rule50 = 0;
 
       // 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);
+      sideToMove = ~sideToMove;
       st->value += (sideToMove == WHITE ?  TempoValue : -TempoValue);
   }
   else
@@ -1095,107 +1173,6 @@ void Position::do_castle_move(Move m) {
 }
 
 
-/// Position::undo_move() unmakes a move. When it returns, the position should
-/// be restored to exactly the same state as before the move was made.
-
-void Position::undo_move(Move m) {
-
-  assert(is_ok(m));
-
-  sideToMove = flip(sideToMove);
-
-  if (is_castle(m))
-  {
-      do_castle_move<false>(m);
-      return;
-  }
-
-  Color us = side_to_move();
-  Color them = flip(us);
-  Square from = move_from(m);
-  Square to = move_to(m);
-  bool ep = is_enpassant(m);
-  bool pm = is_promotion(m);
-
-  PieceType pt = type_of(piece_on(to));
-
-  assert(square_is_empty(from));
-  assert(color_of(piece_on(to)) == us);
-  assert(!pm || relative_rank(us, to) == RANK_8);
-  assert(!ep || to == st->previous->epSquare);
-  assert(!ep || relative_rank(us, to) == RANK_6);
-  assert(!ep || piece_on(to) == make_piece(us, PAWN));
-
-  if (pm) // promotion ?
-  {
-      PieceType promotion = promotion_piece_type(m);
-      pt = PAWN;
-
-      assert(promotion >= KNIGHT && promotion <= QUEEN);
-      assert(piece_on(to) == make_piece(us, promotion));
-
-      // Replace promoted piece with a pawn
-      clear_bit(&byTypeBB[promotion], to);
-      set_bit(&byTypeBB[PAWN], to);
-
-      // Update piece counts
-      pieceCount[us][promotion]--;
-      pieceCount[us][PAWN]++;
-
-      // Update piece list replacing promotion piece with a pawn
-      Square lastPromotionSquare = pieceList[us][promotion][pieceCount[us][promotion]];
-      index[lastPromotionSquare] = index[to];
-      pieceList[us][promotion][index[lastPromotionSquare]] = lastPromotionSquare;
-      pieceList[us][promotion][pieceCount[us][promotion]] = SQ_NONE;
-      index[to] = pieceCount[us][PAWN] - 1;
-      pieceList[us][PAWN][index[to]] = to;
-  }
-
-  // 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);
-
-  board[from] = make_piece(us, pt);
-  board[to] = PIECE_NONE;
-
-  // Update piece list
-  index[from] = index[to];
-  pieceList[us][pt][index[from]] = from;
-
-  if (st->capturedType)
-  {
-      Square capsq = to;
-
-      if (ep)
-          capsq = to - pawn_push(us);
-
-      assert(st->capturedType != KING);
-      assert(!ep || square_is_empty(capsq));
-
-      // Restore the captured piece
-      set_bit(&byColorBB[them], capsq);
-      set_bit(&byTypeBB[st->capturedType], capsq);
-      set_bit(&occupied, capsq);
-
-      board[capsq] = make_piece(them, st->capturedType);
-
-      // Update piece count
-      pieceCount[them][st->capturedType]++;
-
-      // Update piece list, add a new captured piece in capsq square
-      index[capsq] = pieceCount[them][st->capturedType] - 1;
-      pieceList[them][st->capturedType][index[capsq]] = capsq;
-  }
-
-  // Finally point our state pointer back to the previous state
-  st = st->previous;
-
-  assert(pos_is_ok());
-}
-
-
 /// Position::do_null_move() is used to do/undo a "null move": It flips the side
 /// to move and updates the hash key without executing any move on the board.
 template<bool Do>
@@ -1216,7 +1193,7 @@ void Position::do_null_move(StateInfo& backupSt) {
   dst->rule50   = src->rule50;
   dst->pliesFromNull = src->pliesFromNull;
 
-  sideToMove = flip(sideToMove);
+  sideToMove = ~sideToMove;
 
   if (Do)
   {
@@ -1250,8 +1227,8 @@ int Position::see_sign(Move m) const {
 
   assert(is_ok(m));
 
-  Square from = move_from(m);
-  Square to = move_to(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
@@ -1278,17 +1255,17 @@ int Position::see(Move m) const {
   if (is_castle(m))
       return 0;
 
-  from = move_from(m);
-  to = move_to(m);
+  from = from_sq(m);
+  to = to_sq(m);
   capturedType = type_of(piece_on(to));
   occ = occupied_squares();
 
   // Handle en passant moves
-  if (st->epSquare == to && type_of(piece_on(from)) == PAWN)
+  if (is_enpassant(m))
   {
-      Square capQq = to - pawn_push(side_to_move());
+      Square capQq = to - pawn_push(sideToMove);
 
-      assert(capturedType == PIECE_TYPE_NONE);
+      assert(!capturedType);
       assert(type_of(piece_on(capQq)) == PAWN);
 
       // Remove the captured pawn
@@ -1302,7 +1279,7 @@ int Position::see(Move m) const {
   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];
@@ -1340,7 +1317,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
@@ -1355,7 +1332,7 @@ int Position::see(Move m) const {
   // Having built the swap list, we negamax through it to find the best
   // achievable score from the point of view of the side to move.
   while (--slIndex)
-      swapList[slIndex-1] = Min(-swapList[slIndex], swapList[slIndex-1]);
+      swapList[slIndex-1] = std::min(-swapList[slIndex], swapList[slIndex-1]);
 
   return swapList[0];
 }
@@ -1381,7 +1358,7 @@ void Position::clear() {
 
   for (Square sq = SQ_A1; sq <= SQ_H8; sq++)
   {
-      board[sq] = PIECE_NONE;
+      board[sq] = NO_PIECE;
       castleRightsMask[sq] = ALL_CASTLES;
   }
   sideToMove = WHITE;
@@ -1424,7 +1401,7 @@ Key Position::compute_key() const {
   if (ep_square() != SQ_NONE)
       result ^= zobEp[ep_square()];
 
-  if (side_to_move() == BLACK)
+  if (sideToMove == BLACK)
       result ^= zobSideToMove;
 
   return result;
@@ -1488,7 +1465,7 @@ Score Position::compute_value() const {
               result += pst(make_piece(c, pt), pop_1st_bit(&b));
       }
 
-  result += (side_to_move() == WHITE ? TempoValue / 2 : -TempoValue / 2);
+  result += (sideToMove == WHITE ? TempoValue / 2 : -TempoValue / 2);
   return result;
 }
 
@@ -1521,13 +1498,13 @@ 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?
   if (!SkipRepetition)
   {
-      int i = 4, e = Min(st->rule50, st->pliesFromNull);
+      int i = 4, e = std::min(st->rule50, st->pliesFromNull);
 
       if (i <= e)
       {
@@ -1553,15 +1530,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
@@ -1586,14 +1554,14 @@ void Position::init() {
   zobSideToMove = rk.rand<Key>();
   zobExclusion  = rk.rand<Key>();
 
-  for (Piece p = WP; p <= WK; p++)
+  for (Piece p = W_PAWN; p <= W_KING; p++)
   {
       Score ps = make_score(PieceValueMidgame[p], PieceValueEndgame[p]);
 
       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];
       }
   }
 }
@@ -1613,27 +1581,27 @@ void Position::flip_me() {
   // 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));
+          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();
@@ -1675,16 +1643,16 @@ 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?
   if (failedStep) (*failedStep)++;
-  if (piece_on(king_square(WHITE)) != WK)
+  if (piece_on(king_square(WHITE)) != W_KING)
       return false;
 
   if (failedStep) (*failedStep)++;
-  if (piece_on(king_square(BLACK)) != BK)
+  if (piece_on(king_square(BLACK)) != B_KING)
       return false;
 
   // Do both sides have exactly one king?
@@ -1704,8 +1672,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;
@@ -1713,7 +1681,7 @@ bool Position::pos_is_ok(int* failedStep) const {
 
   // Is there more than 2 checkers?
   if (failedStep) (*failedStep)++;
-  if (debugCheckerCount && count_1s<CNT32>(st->checkersBB) > 2)
+  if (debugCheckerCount && popcount<Full>(st->checkersBB) > 2)
       return false;
 
   // Bitboards OK?
@@ -1721,7 +1689,7 @@ 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)) != EmptyBoardBB)
+      if (!(pieces(WHITE) & pieces(BLACK)))
           return false;
 
       // The union of the white and black pieces must be equal to all
@@ -1742,7 +1710,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;
   }
 
@@ -1782,7 +1750,7 @@ bool Position::pos_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<CNT32>(pieces(pt, c)))
+              if (pieceCount[c][pt] != popcount<Full>(pieces(pt, c)))
                   return false;
 
   if (failedStep) (*failedStep)++;
@@ -1805,7 +1773,7 @@ bool Position::pos_is_ok(int* failedStep) const {
           if (!can_castle(f))
               continue;
 
-          Piece rook = (f & (WHITE_OO | WHITE_OOO) ? WR : BR);
+          Piece rook = (f & (WHITE_OO | WHITE_OOO) ? W_ROOK : B_ROOK);
 
           if (   castleRightsMask[castleRookSquare[f]] != (ALL_CASTLES ^ f)
               || piece_on(castleRookSquare[f]) != rook)