]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Assume input FEN string is correct in from_fen()
[stockfish] / src / position.cpp
index 8f70b5dfd3ab3af4c644072396622c75257ce381..0dbbbddf81449b399386e7ae8e87585ffb4f90ca 100644 (file)
@@ -45,31 +45,24 @@ Key Position::zobExclusion;
 Score Position::PieceSquareTable[16][64];
 
 // Material values arrays, indexed by Piece
-const Value Position::PieceValueMidgame[17] = {
+const Value PieceValueMidgame[17] = {
   VALUE_ZERO,
   PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
-  RookValueMidgame, QueenValueMidgame, VALUE_ZERO,
-  VALUE_ZERO, VALUE_ZERO,
+  RookValueMidgame, QueenValueMidgame,
+  VALUE_ZERO, VALUE_ZERO, VALUE_ZERO,
   PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
   RookValueMidgame, QueenValueMidgame
 };
 
-const Value Position::PieceValueEndgame[17] = {
+const Value PieceValueEndgame[17] = {
   VALUE_ZERO,
   PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
-  RookValueEndgame, QueenValueEndgame, VALUE_ZERO,
-  VALUE_ZERO, VALUE_ZERO,
+  RookValueEndgame, QueenValueEndgame,
+  VALUE_ZERO, VALUE_ZERO, VALUE_ZERO,
   PawnValueEndgame, KnightValueEndgame, BishopValueEndgame,
   RookValueEndgame, QueenValueEndgame
 };
 
-// Material values array used by SEE, indexed by PieceType
-const Value Position::seeValues[] = {
-    VALUE_ZERO,
-    PawnValueMidgame, KnightValueMidgame, BishopValueMidgame,
-    RookValueMidgame, QueenValueMidgame, QueenValueMidgame*10
-};
-
 
 namespace {
 
@@ -87,16 +80,17 @@ CheckInfo::CheckInfo(const Position& pos) {
 
   Color us = pos.side_to_move();
   Color them = opposite_color(us);
+  Square ksq = pos.king_square(them);
 
-  ksq = pos.king_square(them);
   dcCandidates = pos.discovered_check_candidates(us);
+  pinned = pos.pinned_pieces(us);
 
-  checkSq[PAWN] = pos.attacks_from<PAWN>(ksq, them);
+  checkSq[PAWN]   = pos.attacks_from<PAWN>(ksq, them);
   checkSq[KNIGHT] = pos.attacks_from<KNIGHT>(ksq);
   checkSq[BISHOP] = pos.attacks_from<BISHOP>(ksq);
-  checkSq[ROOK] = pos.attacks_from<ROOK>(ksq);
-  checkSq[QUEEN] = checkSq[BISHOP] | checkSq[ROOK];
-  checkSq[KING] = EmptyBoardBB;
+  checkSq[ROOK]   = pos.attacks_from<ROOK>(ksq);
+  checkSq[QUEEN]  = checkSq[BISHOP] | checkSq[ROOK];
+  checkSq[KING]   = EmptyBoardBB;
 }
 
 
@@ -127,7 +121,7 @@ void Position::detach() {
 
   startState = *st;
   st = &startState;
-  st->previous = NULL; // as a safe guard
+  st->previous = NULL; // As a safe guard
 }
 
 
@@ -165,64 +159,56 @@ void Position::from_fen(const string& fen, bool isChess960) {
 */
 
   char token;
-  int hmc, fmn;
   size_t p;
+  string ep;
   Square sq = SQ_A8;
   std::istringstream ss(fen);
 
   clear();
-  ss >> std::noskipws;
+  ss >> std::skipws >> token >> std::noskipws;
 
-  // 1. Piece placement field
-  while ((ss >> token) && !isspace(token))
+  // 1. Piece placement
+  while (!isspace(token))
   {
-      if ((p = PieceToChar.find(token)) != string::npos)
+      if (token == '/')
+          sq -= Square(16); // Jump back of 2 rows
+
+      else if (isdigit(token))
+          sq += Square(token - '0'); // Skip the given number of files
+
+      else if ((p = PieceToChar.find(token)) != string::npos)
       {
           put_piece(Piece(p), sq);
           sq++;
       }
-      else if (isdigit(token))
-          sq += Square(token - '0'); // Skip the given number of files
-      else if (token == '/')
-          sq -= SQ_A3; // Jump back of 2 rows
-      else
-          goto incorrect_fen;
+
+      ss >> token;
   }
 
   // 2. Active color
-  if (!(ss >> token) || (token != 'w' && token != 'b'))
-      goto incorrect_fen;
-
+  ss >> std::skipws >> token;
   sideToMove = (token == 'w' ? WHITE : BLACK);
 
-  if (!(ss >> token) || !isspace(token))
-      goto incorrect_fen;
-
   // 3. Castling availability
-  while ((ss >> token) && !isspace(token))
-      if (!set_castling_rights(token))
-          goto incorrect_fen;
-
-  // 4. En passant square
-  char col, row;
-  if (   ((ss >> col) && (col >= 'a' && col <= 'h'))
-      && ((ss >> row) && (row == '3' || row == '6')))
+  ss >> token >> std::noskipws;
+  while (token != '-' && !isspace(token))
+  {
+      set_castling_rights(token);
+      ss >> token;
+  }
+
+  // 4. En passant square. Ignore if no pawn capture is possible
+  ss >> std::skipws >> ep;
+  if (ep.size() == 2)
   {
-      st->epSquare = make_square(file_from_char(col), rank_from_char(row));
+      st->epSquare = make_square(File(ep[0] - 'a'), Rank(ep[1] - '1'));
 
-      // Ignore if no capture is possible
-      Color them = opposite_color(sideToMove);
-      if (!(attacks_from<PAWN>(st->epSquare, them) & pieces(PAWN, sideToMove)))
+      if (!(attackers_to(st->epSquare) & pieces(PAWN, sideToMove)))
           st->epSquare = SQ_NONE;
   }
 
-  // 5. Halfmove clock
-  if (ss >> std::skipws >> hmc)
-      st->rule50 = hmc;
-
-  // 6. Fullmove number
-  if (ss >> fmn)
-      startPosPlyCounter = (fmn - 1) * 2 + int(sideToMove == BLACK);
+  // 5-6. Halfmove clock and fullmove number
+  ss >> st->rule50 >> fullMoves;
 
   // Various initialisations
   castleRightsMask[make_square(initialKFile,  RANK_1)] ^= WHITE_OO | WHITE_OOO;
@@ -241,10 +227,6 @@ void Position::from_fen(const string& fen, bool isChess960) {
   st->value = compute_value();
   st->npMaterial[WHITE] = compute_non_pawn_material(WHITE);
   st->npMaterial[BLACK] = compute_non_pawn_material(BLACK);
-  return;
-
-incorrect_fen:
-  cout << "Error in FEN string: " << fen << endl;
 }
 
 
@@ -255,39 +237,39 @@ incorrect_fen:
 /// associated with the castling right, the traditional castling tag will be replaced
 /// by the file letter of the involved rook as for the Shredder-FEN.
 
-bool Position::set_castling_rights(char token) {
+void Position::set_castling_rights(char token) {
 
-    Color c = token >= 'a' ? BLACK : WHITE;
-    Square sqA = (c == WHITE ? SQ_A1 : SQ_A8);
-    Square sqH = (c == WHITE ? SQ_H1 : SQ_H8);
-    Piece rook = (c == WHITE ? WR : BR);
+    Color c = islower(token) ? BLACK : WHITE;
+
+    Square sqA = relative_square(c, SQ_A1);
+    Square sqH = relative_square(c, SQ_H1);
 
     initialKFile = square_file(king_square(c));
-    token = char(toupper(token));
 
-    if (token == 'K')
+    if (toupper(token) == 'K')
     {
         for (Square sq = sqH; sq >= sqA; sq--)
-            if (piece_on(sq) == rook)
+            if (piece_on(sq) == make_piece(c, ROOK))
             {
                 set_castle_kingside(c);
                 initialKRFile = square_file(sq);
                 break;
             }
     }
-    else if (token == 'Q')
+    else if (toupper(token) == 'Q')
     {
         for (Square sq = sqA; sq <= sqH; sq++)
-            if (piece_on(sq) == rook)
+            if (piece_on(sq) == make_piece(c, ROOK))
             {
                 set_castle_queenside(c);
                 initialQRFile = square_file(sq);
                 break;
             }
     }
-    else if (token >= 'A' && token <= 'H')
+    else if (toupper(token) >= 'A' && toupper(token) <= 'H')
     {
-        File rookFile = File(token - 'A') + FILE_A;
+        File rookFile = File(toupper(token) - 'A');
+
         if (rookFile < initialKFile)
         {
             set_castle_queenside(c);
@@ -299,10 +281,6 @@ bool Position::set_castling_rights(char token) {
             initialKRFile = rookFile;
         }
     }
-    else
-        return token == '-';
-
-  return true;
 }
 
 
@@ -372,7 +350,7 @@ void Position::print(Move move) const {
   if (move)
   {
       Position p(*this, thread());
-      string dd = (color_of_piece_on(move_from(move)) == BLACK ? ".." : "");
+      string dd = (piece_color(piece_on(move_from(move))) == BLACK ? ".." : "");
       cout << "\nMove is: " << dd << move_to_san(p, move);
   }
 
@@ -387,7 +365,7 @@ void Position::print(Move move) const {
           if (piece == PIECE_NONE && square_color(sq) == DARK)
               piece = PIECE_NONE_DARK_SQ;
 
-          char c = (color_of_piece_on(sq) == BLACK ? '=' : ' ');
+          char c = (piece_color(piece_on(sq)) == BLACK ? '=' : ' ');
           cout << c << PieceToChar[piece] << c << '|';
       }
   }
@@ -526,7 +504,7 @@ bool Position::move_attacks_square(Move m, Square s) const {
   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_of_color(color_of_piece_on(f));
+         & pieces_of_color(piece_color(piece_on(f)));
 
   // If we have attacks we need to verify that are caused by our move
   // and are not already existent ones.
@@ -558,7 +536,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   Color us = side_to_move();
   Square from = move_from(m);
 
-  assert(color_of_piece_on(from) == us);
+  assert(piece_color(piece_on(from)) == us);
   assert(piece_on(king_square(us)) == make_piece(us, KING));
 
   // En passant captures are a tricky special case. Because they are
@@ -588,7 +566,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   // 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)
+  if (piece_type(piece_on(from)) == KING)
       return move_is_castle(m) || !(attackers_to(move_to(m)) & pieces_of_color(opposite_color(us)));
 
   // A non-king move is legal if and only if it is not pinned or it
@@ -599,8 +577,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
 }
 
 
-/// Position::move_is_pl_slow() takes a position and a move and tests whether
-/// the move is pseudo legal. This version is not very fast and should be used
+/// Position::move_is_pl_slow() takes a move and tests whether the move
+/// is pseudo legal. This version is not very fast and should be used
 /// only in non time-critical paths.
 
 bool Position::move_is_pl_slow(const Move m) const {
@@ -619,8 +597,8 @@ bool Position::move_is_pl_slow(const Move m) const {
 }
 
 
-/// Fast version of Position::move_is_pl() that takes a position a move and a
-/// bitboard of pinned pieces as input, and tests whether the move is pseudo legal.
+/// Fast version of Position::move_is_pl() that takes a move and a bitboard
+/// of pinned pieces as input, and tests whether the move is pseudo legal.
 
 bool Position::move_is_pl(const Move m) const {
 
@@ -642,15 +620,15 @@ bool Position::move_is_pl(const Move m) const {
 
   // 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_piece(pc) != us)
+  if (pc == PIECE_NONE || piece_color(pc) != us)
       return false;
 
   // The destination square cannot be occupied by a friendly piece
-  if (color_of_piece_on(to) == us)
+  if (piece_color(piece_on(to)) == us)
       return false;
 
   // Handle the special case of a pawn move
-  if (type_of_piece(pc) == PAWN)
+  if (piece_type(pc) == PAWN)
   {
       // Move direction must be compatible with pawn color
       int direction = to - from;
@@ -672,7 +650,7 @@ bool Position::move_is_pl(const Move m) const {
       case DELTA_SE:
       // Capture. The destination square must be occupied by an enemy
       // piece (en passant captures was handled earlier).
-      if (color_of_piece_on(to) != them)
+      if (piece_color(piece_on(to)) != them)
           return false;
 
       // From and to files must be one file apart, avoids a7h5
@@ -718,7 +696,7 @@ bool Position::move_is_pl(const Move m) const {
   {
       // 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)
+      if (piece_type(piece_on(from)) == KING)
       {
           Bitboard b = occupied_squares();
           clear_bit(&b, from);
@@ -746,22 +724,16 @@ bool Position::move_is_pl(const Move m) const {
 
 /// Position::move_gives_check() tests whether a pseudo-legal move is a check
 
-bool Position::move_gives_check(Move m) const {
-
-  return move_gives_check(m, CheckInfo(*this));
-}
-
 bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
 
   assert(is_ok());
   assert(move_is_ok(m));
   assert(ci.dcCandidates == discovered_check_candidates(side_to_move()));
-  assert(color_of_piece_on(move_from(m)) == side_to_move());
-  assert(piece_on(ci.ksq) == make_piece(opposite_color(side_to_move()), KING));
+  assert(piece_color(piece_on(move_from(m))) == side_to_move());
 
   Square from = move_from(m);
   Square to = move_to(m);
-  PieceType pt = type_of_piece_on(from);
+  PieceType pt = piece_type(piece_on(from));
 
   // Direct check ?
   if (bit_is_set(ci.checkSq[pt], to))
@@ -772,7 +744,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, ci.ksq))
+          || !squares_aligned(from, to, king_square(opposite_color(side_to_move()))))
           return true;
   }
 
@@ -782,6 +754,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
 
   Color us = side_to_move();
   Bitboard b = occupied_squares();
+  Square ksq = king_square(opposite_color(us));
 
   // Promotion with check ?
   if (move_is_promotion(m))
@@ -791,13 +764,13 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
       switch (promotion_piece_type(m))
       {
       case KNIGHT:
-          return bit_is_set(attacks_from<KNIGHT>(to), ci.ksq);
+          return bit_is_set(attacks_from<KNIGHT>(to), ksq);
       case BISHOP:
-          return bit_is_set(bishop_attacks_bb(to, b), ci.ksq);
+          return bit_is_set(bishop_attacks_bb(to, b), ksq);
       case ROOK:
-          return bit_is_set(rook_attacks_bb(to, b), ci.ksq);
+          return bit_is_set(rook_attacks_bb(to, b), ksq);
       case QUEEN:
-          return bit_is_set(queen_attacks_bb(to, b), ci.ksq);
+          return bit_is_set(queen_attacks_bb(to, b), ksq);
       default:
           assert(false);
       }
@@ -813,8 +786,8 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
       clear_bit(&b, from);
       clear_bit(&b, capsq);
       set_bit(&b, to);
-      return  (rook_attacks_bb(ci.ksq, b) & pieces(ROOK, QUEEN, us))
-            ||(bishop_attacks_bb(ci.ksq, b) & pieces(BISHOP, QUEEN, us));
+      return  (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us))
+            ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us));
   }
 
   // Castling with check ?
@@ -836,7 +809,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const {
       clear_bit(&b, rfrom);
       set_bit(&b, rto);
       set_bit(&b, kto);
-      return bit_is_set(rook_attacks_bb(rto, b), ci.ksq);
+      return bit_is_set(rook_attacks_bb(rto, b), ksq);
   }
 
   return false;
@@ -850,6 +823,10 @@ void Position::do_setup_move(Move m) {
 
   StateInfo newSt;
 
+  // Update the number of full moves after black's move
+  if (sideToMove == BLACK)
+      fullMoves++;
+
   do_move(m, newSt);
 
   // Reset "game ply" in case we made a non-reversible move.
@@ -857,9 +834,6 @@ void Position::do_setup_move(Move m) {
   if (st->rule50 == 0)
       st->gamePly = 0;
 
-  // Update the number of plies played from the starting position
-  startPosPlyCounter++;
-
   // Our StateInfo newSt is about going out of scope so copy
   // its content before it disappears.
   detach();
@@ -928,11 +902,11 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
   bool pm = move_is_promotion(m);
 
   Piece piece = piece_on(from);
-  PieceType pt = type_of_piece(piece);
-  PieceType capture = ep ? PAWN : type_of_piece_on(to);
+  PieceType pt = piece_type(piece);
+  PieceType capture = ep ? PAWN : piece_type(piece_on(to));
 
-  assert(color_of_piece_on(from) == us);
-  assert(color_of_piece_on(to) == them || square_is_empty(to));
+  assert(piece_color(piece_on(from)) == us);
+  assert(piece_color(piece_on(to)) == them || square_is_empty(to));
   assert(!(ep || pm) || piece == make_piece(us, PAWN));
   assert(!pm || relative_rank(us, to) == RANK_8);
 
@@ -1066,10 +1040,10 @@ 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>(ci.ksq) & pieces(ROOK, QUEEN, us));
+                  st->checkersBB |= (attacks_from<ROOK>(king_square(them)) & pieces(ROOK, QUEEN, us));
 
               if (pt != BISHOP)
-                  st->checkersBB |= (attacks_from<BISHOP>(ci.ksq) & pieces(BISHOP, QUEEN, us));
+                  st->checkersBB |= (attacks_from<BISHOP>(king_square(them)) & pieces(BISHOP, QUEEN, us));
           }
       }
   }
@@ -1266,10 +1240,10 @@ void Position::undo_move(Move m) {
   bool ep = move_is_ep(m);
   bool pm = move_is_promotion(m);
 
-  PieceType pt = type_of_piece_on(to);
+  PieceType pt = piece_type(piece_on(to));
 
   assert(square_is_empty(from));
-  assert(color_of_piece_on(to) == us);
+  assert(piece_color(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);
@@ -1489,7 +1463,7 @@ int Position::see_sign(Move m) const {
   // 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 (midgame_value_of_piece_on(to) >= midgame_value_of_piece_on(from))
+  if (piece_value_midgame(piece_on(to)) >= piece_value_midgame(piece_on(from)))
       return 1;
 
   return see(m);
@@ -1513,16 +1487,16 @@ int Position::see(Move m) const {
 
   from = move_from(m);
   to = move_to(m);
-  capturedType = type_of_piece_on(to);
+  capturedType = piece_type(piece_on(to));
   occupied = occupied_squares();
 
   // Handle en passant moves
-  if (st->epSquare == to && type_of_piece_on(from) == PAWN)
+  if (st->epSquare == to && piece_type(piece_on(from)) == PAWN)
   {
       Square capQq = (side_to_move() == WHITE ? to - DELTA_N : to - DELTA_S);
 
       assert(capturedType == PIECE_TYPE_NONE);
-      assert(type_of_piece_on(capQq) == PAWN);
+      assert(piece_type(piece_on(capQq)) == PAWN);
 
       // Remove the captured pawn
       clear_bit(&occupied, capQq);
@@ -1535,10 +1509,10 @@ int Position::see(Move m) const {
   attackers = attackers_to(to, occupied);
 
   // If the opponent has no attackers we are finished
-  stm = opposite_color(color_of_piece_on(from));
+  stm = opposite_color(piece_color(piece_on(from)));
   stmAttackers = attackers & pieces_of_color(stm);
   if (!stmAttackers)
-      return seeValues[capturedType];
+      return PieceValueMidgame[capturedType];
 
   // The destination square is defended, which makes things rather more
   // difficult to compute. We proceed by building up a "swap list" containing
@@ -1546,8 +1520,8 @@ int Position::see(Move m) const {
   // destination square, where the sides alternately capture, and always
   // capture with the least valuable piece. After each capture, we look for
   // new X-ray attacks from behind the capturing piece.
-  swapList[0] = seeValues[capturedType];
-  capturedType = type_of_piece_on(from);
+  swapList[0] = PieceValueMidgame[capturedType];
+  capturedType = piece_type(piece_on(from));
 
   do {
       // Locate the least valuable attacker for the side to move. The loop
@@ -1567,7 +1541,7 @@ int Position::see(Move m) const {
 
       // Add the new entry to the swap list
       assert(slIndex < 32);
-      swapList[slIndex] = -swapList[slIndex - 1] + seeValues[capturedType];
+      swapList[slIndex] = -swapList[slIndex - 1] + PieceValueMidgame[capturedType];
       slIndex++;
 
       // Remember the value of the capturing piece, and change the side to
@@ -1602,7 +1576,7 @@ void Position::clear() {
   st = &startState;
   memset(st, 0, sizeof(StateInfo));
   st->epSquare = SQ_NONE;
-  startPosPlyCounter = 0;
+  fullMoves = 1;
   nodes = 0;
 
   memset(byColorBB,  0, sizeof(Bitboard) * 2);
@@ -1632,8 +1606,8 @@ void Position::clear() {
 
 void Position::put_piece(Piece p, Square s) {
 
-  Color c = color_of_piece(p);
-  PieceType pt = type_of_piece(p);
+  Color c = piece_color(p);
+  PieceType pt = piece_type(p);
 
   board[s] = p;
   index[s] = pieceCount[c][pt]++;
@@ -1656,7 +1630,7 @@ Key Position::compute_key() const {
 
   for (Square s = SQ_A1; s <= SQ_H8; s++)
       if (square_is_occupied(s))
-          result ^= zobrist[color_of_piece_on(s)][type_of_piece_on(s)][s];
+          result ^= zobrist[piece_color(piece_on(s))][piece_type(piece_on(s))][s];
 
   if (ep_square() != SQ_NONE)
       result ^= zobEp[ep_square()];
@@ -1788,35 +1762,30 @@ bool Position::is_mate() const {
 }
 
 
-/// Position::init_zobrist() is a static member function which initializes at
-/// startup the various arrays used to compute hash keys.
+/// 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 are copied from the MgPST[][] and EgPST[][] arrays.
+/// Second, the black halves of the tables are initialized by mirroring
+/// and changing the sign of the corresponding white scores.
 
-void Position::init_zobrist() {
+void Position::init() {
 
-  int i,j, k;
   RKISS rk;
 
-  for (i = 0; i < 2; i++) for (j = 0; j < 8; j++) for (k = 0; k < 64; k++)
-      zobrist[i][j][k] = rk.rand<Key>();
+  for (Color c = WHITE; c <= BLACK; c++)
+      for (PieceType pt = PAWN; pt <= KING; pt++)
+          for (Square s = SQ_A1; s <= SQ_H8; s++)
+              zobrist[c][pt][s] = rk.rand<Key>();
 
-  for (i = 0; i < 64; i++)
-      zobEp[i] = rk.rand<Key>();
+  for (Square s = SQ_A1; s <= SQ_H8; s++)
+      zobEp[s] = rk.rand<Key>();
 
-  for (i = 0; i < 16; i++)
+  for (int i = 0; i < 16; i++)
       zobCastle[i] = rk.rand<Key>();
 
   zobSideToMove = rk.rand<Key>();
   zobExclusion  = rk.rand<Key>();
-}
-
-
-/// Position::init_piece_square_tables() initializes the piece square tables.
-/// This is a two-step operation: First, the white halves of the tables are
-/// copied from the MgPST[][] and EgPST[][] arrays. Second, the black halves
-/// of the tables are initialized by mirroring and changing the sign of the
-/// corresponding white scores.
-
-void Position::init_piece_square_tables() {
 
   for (Square s = SQ_A1; s <= SQ_H8; s++)
       for (Piece p = WP; p <= WK; p++)
@@ -1913,7 +1882,7 @@ bool Position::is_ok(int* failedStep) const {
   if (failedStep) *failedStep = 1;
 
   // Side to move OK?
-  if (!color_is_ok(side_to_move()))
+  if (side_to_move() != WHITE && side_to_move() != BLACK)
       return false;
 
   // Are the king squares in the position correct?
@@ -1927,10 +1896,10 @@ bool Position::is_ok(int* failedStep) const {
 
   // Castle files OK?
   if (failedStep) (*failedStep)++;
-  if (!file_is_ok(initialKRFile))
+  if (!square_is_ok(make_square(initialKRFile, RANK_1)))
       return false;
 
-  if (!file_is_ok(initialQRFile))
+  if (!square_is_ok(make_square(initialQRFile, RANK_1)))
       return false;
 
   // Do both sides have exactly one king?
@@ -1939,8 +1908,8 @@ bool Position::is_ok(int* failedStep) const {
   {
       int kingCount[2] = {0, 0};
       for (Square s = SQ_A1; s <= SQ_H8; s++)
-          if (type_of_piece_on(s) == KING)
-              kingCount[color_of_piece_on(s)]++;
+          if (piece_type(piece_on(s)) == KING)
+              kingCount[piece_color(piece_on(s))]++;
 
       if (kingCount[0] != 1 || kingCount[1] != 1)
           return false;