]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Position::is_ok()give more info on failed test
[stockfish] / src / position.cpp
index 8d63c52f10b92512ebf5589ce33243e43eddcd6c..ba57657e11b81000f6026116646af2f10b490c50 100644 (file)
@@ -48,6 +48,13 @@ Key Position::zobSideToMove;
 Value Position::MgPieceSquareTable[16][64];
 Value Position::EgPieceSquareTable[16][64];
 
+const Piece_attacks_fn piece_attacks_fn[] =
+  { 0, 0, 
+    &Position::knight_attacks,
+    &Position::bishop_attacks,
+    &Position::rook_attacks,
+    &Position::queen_attacks,
+    &Position::king_attacks };
 
 ////
 //// Functions
@@ -70,7 +77,7 @@ Position::Position(const std::string &fen) {
 
 void Position::from_fen(const std::string &fen) {
 
-  static const std::string piecesStr = "KQRBNPkqrbnp";
+  static const std::string pieceLetters = "KQRBNPkqrbnp";
   static const Piece pieces[] = { WK, WQ, WR, WB, WN, WP, BK, BQ, BR, BB, BN, BP };
 
   clear();
@@ -93,7 +100,7 @@ void Position::from_fen(const std::string &fen) {
           rank--;
           continue;
       }
-      size_t idx = piecesStr.find(fen[i]);
+      size_t idx = pieceLetters.find(fen[i]);
       if (idx == std::string::npos)
       {
            std::cout << "Error in FEN at character " << i << std::endl;
@@ -106,7 +113,7 @@ void Position::from_fen(const std::string &fen) {
 
   // Side to move
   i++;
-  if (fen[i] != 'w' && fen[i] == 'b')
+  if (fen[i] != 'w' && fen[i] != 'b')
   {
       std::cout << "Error in FEN at character " << i << std::endl;
       return;
@@ -214,40 +221,50 @@ void Position::from_fen(const std::string &fen) {
 /// probably only useful for debugging.
 
 const std::string Position::to_fen() const {
-  char pieceLetters[] = " PNBRQK  pnbrqk";
-  std::string result;
+
+  static const std::string pieceLetters = " PNBRQK  pnbrqk";
+  std::string fen;
   int skip;
 
-  for(Rank rank = RANK_8; rank >= RANK_1; rank--) {
-    skip = 0;
-    for(File file = FILE_A; file <= FILE_H; file++) {
-      Square square = make_square(file, rank);
-      if(square_is_occupied(square)) {
-        if(skip > 0) result += (char)skip + '0';
-        result += pieceLetters[piece_on(square)];
-        skip = 0;
+  for (Rank rank = RANK_8; rank >= RANK_1; rank--)
+  {
+      skip = 0;
+      for (File file = FILE_A; file <= FILE_H; file++)
+      {
+          Square sq = make_square(file, rank);
+          if (!square_is_occupied(sq))
+          {   skip++;
+              continue;
+          }
+          if (skip > 0)
+          {
+              fen += (char)skip + '0';
+              skip = 0;
+          }
+          fen += pieceLetters[piece_on(sq)];         
       }
-      else skip++;
-    }
-    if(skip > 0) result += (char)skip + '0';
-    result += (rank > RANK_1)? '/' : ' ';
-  }
+      if (skip > 0)
+          fen += (char)skip + '0';
 
-  result += (sideToMove == WHITE)? 'w' : 'b';
-  result += ' ';
-  if(castleRights == NO_CASTLES) result += '-';
-  else {
-    if(can_castle_kingside(WHITE)) result += 'K';
-    if(can_castle_queenside(WHITE)) result += 'Q';
-    if(can_castle_kingside(BLACK)) result += 'k';
-    if(can_castle_queenside(BLACK)) result += 'q';
+      fen += (rank > RANK_1 ? '/' : ' ');
   }
+  fen += (sideToMove == WHITE ? 'w' : 'b') + ' ';
+  if (castleRights != NO_CASTLES)
+  {
+    if (can_castle_kingside(WHITE))  fen += 'K';
+    if (can_castle_queenside(WHITE)) fen += 'Q';
+    if (can_castle_kingside(BLACK))  fen += 'k';
+    if (can_castle_queenside(BLACK)) fen += 'q';
+  } else
+      fen += '-';
+
+  fen += ' ';
+  if (ep_square() != SQ_NONE)
+      fen += square_to_string(ep_square());
+  else
+      fen += '-';
 
-  result += ' ';
-  if(ep_square() == SQ_NONE) result += '-';
-  else result += square_to_string(ep_square());
-
-  return result;
+  return fen;
 }
 
 
@@ -2099,7 +2116,7 @@ void Position::flipped_copy(const Position &pos) {
 /// Position::is_ok() performs some consitency checks for the position object.
 /// This is meant to be helpful when debugging.
 
-bool Position::is_ok() const {
+bool Position::is_ok(int* failedStep) const {
 
   // What features of the position should be verified?
   static const bool debugBitboards = false;
@@ -2114,23 +2131,30 @@ bool Position::is_ok() const {
   static const bool debugPieceCounts = false;
   static const bool debugPieceList = false;
 
+  if (failedStep) *failedStep = 1;
+
   // Side to move OK?
   if(!color_is_ok(side_to_move()))
     return false;
 
   // Are the king squares in the position correct?
+  if (failedStep) (*failedStep)++;
   if(piece_on(king_square(WHITE)) != WK)
     return false;
+
+  if (failedStep) (*failedStep)++;
   if(piece_on(king_square(BLACK)) != BK)
     return false;
 
   // Castle files OK?
+  if (failedStep) (*failedStep)++;
   if(!file_is_ok(initialKRFile))
     return false;
   if(!file_is_ok(initialQRFile))
     return false;
 
   // Do both sides have exactly one king?
+  if (failedStep) (*failedStep)++;
   if(debugKingCount) {
     int kingCount[2] = {0, 0};
     for(Square s = SQ_A1; s <= SQ_H8; s++)
@@ -2141,6 +2165,7 @@ bool Position::is_ok() const {
   }
 
   // Can the side to move capture the opponent's king?
+  if (failedStep) (*failedStep)++;
   if(debugKingCapture) {
     Color us = side_to_move();
     Color them = opposite_color(us);
@@ -2150,10 +2175,12 @@ bool Position::is_ok() const {
   }
 
   // Is there more than 2 checkers?
+  if (failedStep) (*failedStep)++;
   if(debugCheckerCount && count_1s(checkersBB) > 2)
     return false;
 
   // Bitboards OK?
+  if (failedStep) (*failedStep)++;
   if(debugBitboards) {
     // The intersection of the white and black pieces must be empty:
     if((pieces_of_color(WHITE) & pieces_of_color(BLACK))
@@ -2174,6 +2201,7 @@ bool Position::is_ok() const {
   }
 
   // En passant square OK?
+  if (failedStep) (*failedStep)++;
   if(ep_square() != SQ_NONE) {
     // The en passant square must be on rank 6, from the point of view of the
     // side to move.
@@ -2182,18 +2210,22 @@ bool Position::is_ok() const {
   }
 
   // Hash key OK?
+  if (failedStep) (*failedStep)++;
   if(debugKey && key != compute_key())
     return false;
 
   // Pawn hash key OK?
+  if (failedStep) (*failedStep)++;
   if(debugPawnKey && pawnKey != compute_pawn_key())
     return false;
 
   // Material hash key OK?
+  if (failedStep) (*failedStep)++;
   if(debugMaterialKey && materialKey != compute_material_key())
     return false;
 
   // Incremental eval OK?
+  if (failedStep) (*failedStep)++;
   if(debugIncrementalEval) {
     if(mgValue != compute_mg_value())
       return false;
@@ -2202,6 +2234,7 @@ bool Position::is_ok() const {
   }
 
   // Non-pawn material OK?
+  if (failedStep) (*failedStep)++;
   if(debugNonPawnMaterial) {
     if(npMaterial[WHITE] != compute_non_pawn_material(WHITE))
       return false;
@@ -2210,12 +2243,14 @@ bool Position::is_ok() const {
   }
 
   // Piece counts OK?
+  if (failedStep) (*failedStep)++;
   if(debugPieceCounts)
     for(Color c = WHITE; c <= BLACK; c++)
       for(PieceType pt = PAWN; pt <= KING; pt++)
         if(pieceCount[c][pt] != count_1s(pieces_of_color_and_type(c, pt)))
           return false;
 
+  if (failedStep) (*failedStep)++;
   if(debugPieceList) {
     for(Color c = WHITE; c <= BLACK; c++)
       for(PieceType pt = PAWN; pt <= KING; pt++)
@@ -2227,6 +2262,6 @@ bool Position::is_ok() const {
             return false;
         }
   }
-
+  if (failedStep) *failedStep = 0;
   return true;
 }