]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Small touches in FEN decoding
[stockfish] / src / position.cpp
index d14f04169b95b1a2751711756dea4e730fc7f098..907357bd1f90ba09f6197f15763248970997965b 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
@@ -79,7 +79,7 @@ namespace {
 CheckInfo::CheckInfo(const Position& pos) {
 
   Color them = flip(pos.side_to_move());
-  Square ksq = pos.king_square(them);
+  ksq = pos.king_square(them);
 
   pinned = pos.pinned_pieces();
   dcCandidates = pos.discovered_check_candidates();
@@ -165,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)
       {
@@ -192,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));
@@ -208,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
@@ -242,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;
 }
@@ -361,8 +360,8 @@ Bitboard Position::hidden_checkers() const {
   Square ksq = king_square(FindPinned ? sideToMove : flip(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)
   {
@@ -420,8 +419,8 @@ bool Position::move_attacks_square(Move m, Square s) const {
   assert(square_is_ok(s));
 
   Bitboard occ, xray;
-  Square from = move_from(m);
-  Square to = move_to(m);
+  Square from = from_sq(m);
+  Square to = to_sq(m);
   Piece piece = piece_on(from);
 
   assert(!square_is_empty(from));
@@ -451,7 +450,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   assert(pinned == pinned_pieces());
 
   Color us = side_to_move();
-  Square from = move_from(m);
+  Square from = from_sq(m);
 
   assert(color_of(piece_on(from)) == us);
   assert(piece_on(king_square(us)) == make_piece(us, KING));
@@ -462,7 +461,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   if (is_enpassant(m))
   {
       Color them = flip(us);
-      Square to = move_to(m);
+      Square to = to_sq(m);
       Square capsq = to + pawn_push(them);
       Square ksq = king_square(us);
       Bitboard b = occupied_squares();
@@ -484,13 +483,13 @@ 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(flip(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));
 }
 
 
@@ -516,8 +515,8 @@ 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);
+  Square from = from_sq(m);
+  Square to = to_sq(m);
   Piece pc = piece_on(from);
 
   // Use a slower but simpler function for uncommon cases
@@ -613,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(flip(us)))
               return false;
       }
       else
@@ -626,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;
       }
   }
@@ -641,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)) == side_to_move());
 
-  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 ?
@@ -766,8 +765,8 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI
 
   Color us = side_to_move();
   Color them = flip(us);
-  Square from = move_from(m);
-  Square to = move_to(m);
+  Square from = from_sq(m);
+  Square to = to_sq(m);
   Piece piece = piece_on(from);
   PieceType pt = type_of(piece);
   PieceType capture = is_enpassant(m) ? PAWN : type_of(piece_on(to));
@@ -982,8 +981,8 @@ void Position::undo_move(Move m) {
 
   Color us = side_to_move();
   Color them = flip(us);
-  Square from = move_from(m);
-  Square to = move_to(m);
+  Square from = from_sq(m);
+  Square to = to_sq(m);
   Piece piece = piece_on(to);
   PieceType pt = type_of(piece);
   PieceType capture = st->capturedType;
@@ -1077,8 +1076,8 @@ 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);
+  Square kBefore = from_sq(m);
+  Square rBefore = to_sq(m);
 
   // Find after-castle squares for king and rook
   if (rBefore > kBefore) // O-O
@@ -1228,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
@@ -1256,8 +1255,8 @@ 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();
 
@@ -1499,7 +1498,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 +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
@@ -1598,13 +1588,13 @@ void Position::flip_me() {
 
   // 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, flip(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, flip(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, flip(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, flip(pos.castle_rook_square(BLACK_OOO)));
 
   // En passant square
   if (pos.st->epSquare != SQ_NONE)
@@ -1691,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?
@@ -1760,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)++;