const std::string move_to_san(Position &pos, Move m) {
  std::string str;

  assert(pos.is_ok());
  assert(move_is_ok(m));

  Square from, to;
  Piece pc;

  from = move_from(m);
  to = move_to(m);
  pc = pos.piece_on(move_from(m));

  if(m == MOVE_NONE) {
    str = "(none)";
    return str;
  }
  else if(m == MOVE_NULL) {
    str = "(null)";
    return str;
  }
  else if(move_is_long_castle(m)
          || (int(to - from) == -2 && type_of_piece(pc) == KING))
    str = "O-O-O";
  else if(move_is_short_castle(m)
          || (int(to - from) == 2 && type_of_piece(pc) == KING))
    str = "O-O";
  else {
    str = "";

    if(type_of_piece(pc) == PAWN) {
      if(pos.move_is_capture(m))
        str += file_to_char(square_file(move_from(m)));
    }
    else {
      str += piece_type_to_char(type_of_piece(pc), true);

      Ambiguity amb = move_ambiguity(pos, m);
      switch(amb) {

      case AMBIGUITY_NONE:
        break;

      case AMBIGUITY_FILE:
        str += file_to_char(square_file(from));
        break;

      case AMBIGUITY_RANK:
        str += rank_to_char(square_rank(from));
        break;

      case AMBIGUITY_BOTH:
        str += square_to_string(from);
        break;

      default:
        assert(false);
      }
    }

    if(pos.move_is_capture(m))
      str += "x";

    str += square_to_string(move_to(m));

    if(move_promotion(m)) {
      str += "=";
      str += piece_type_to_char(move_promotion(m), true);
    }
  }

  // Is the move check?  We don't use pos.move_is_check(m) here, because
  // Position::move_is_check doesn't detect all checks (not castling moves,
  // promotions and en passant captures).
  UndoInfo u;
  pos.do_move(m, u);
  if(pos.is_check())
    str += pos.is_mate()? "#" : "+";
  pos.undo_move(m, u);

  return str;
}
Exemple #2
0
bool move_to_san(int move, const board_t * board, char string[], int size) {

   int from, to, piece;
   char tmp_string[256];

   ASSERT(move_is_ok(move));
   ASSERT(board_is_ok(board));
   ASSERT(string!=NULL);
   ASSERT(size>=8);

   ASSERT(move_is_legal(move,board));

   if (size < 8) return false;

   // init

   from = move_from(move);
   to = move_to(move);

   string[0] = '\0';

   // castle

   if (move_is_castle(move,board)) {

      if (to > from) {
         strcat(string,"O-O");
      } else {
         strcat(string,"O-O-O");
      }

      goto check;
   }

   // from

   piece = board->square[from];

   if (piece_is_pawn(piece)) {

      // pawn

      if (move_is_capture(move,board)) {
         sprintf(tmp_string,"%c",file_to_char(square_file(from)));
         strcat(string,tmp_string);
      }

   } else {

      // piece

      sprintf(tmp_string,"%c",toupper(piece_to_char(piece)));
      strcat(string,tmp_string);

      // ambiguity

      switch (ambiguity(move,board)) {
      case AMBIGUITY_NONE:
         break;
      case AMBIGUITY_FILE:
         sprintf(tmp_string,"%c",file_to_char(square_file(from)));
         strcat(string,tmp_string);
         break;
      case AMBIGUITY_RANK:
         sprintf(tmp_string,"%c",rank_to_char(square_rank(from)));
         strcat(string,tmp_string);
         break;
      case AMBIGUITY_SQUARE:
         if (!square_to_string(from,tmp_string,256)) return false;
         strcat(string,tmp_string);
         break;
      default:
         ASSERT(false);
         break;
      }
   }

   // capture

   if (move_is_capture(move,board)) strcat(string,"x");

   // to

   if (!square_to_string(to,tmp_string,256)) return false;
   strcat(string,tmp_string);

   // promote

   if (move_is_promote(move)) {
      sprintf(tmp_string,"=%c",toupper(piece_to_char(move_promote(move,board))));
      strcat(string,tmp_string);
   }

   // check

check:

   if (move_is_mate(move,board)) {
      strcat(string,"#");
   } else if (move_is_check(move,board)) {
      strcat(string,"+");
   }

   return true;
}
Exemple #3
0
bool board_to_fen(const board_t * board, char string[], int size) {

   int pos;
   int file, rank;
   int sq, piece;
   int c;
   int len;
   int old_pos;

   ASSERT(board_is_ok(board));
   ASSERT(string!=NULL);
   ASSERT(size>=92);

   // init

   if (size < 92) return false;

   pos = 0;

   // piece placement

   for (rank = 7; rank >= 0; rank--) {

      for (file = 0; file < 8;) {

         sq = square_make(file,rank);
         piece = board->square[sq];
         ASSERT(piece==Empty||piece_is_ok(piece));

         if (piece == Empty) {

            len = 0;
            for (; file < 8 && board->square[square_make(file,rank)] == Empty; file++) {
               len++;
            }

            ASSERT(len>=1&&len<=8);
            c = '0' + len;

         } else {

            c = piece_to_char(piece);
            file++;
         }

         string[pos++] = c;
      }

      string[pos++] = '/';
   }

   string[pos-1] = ' '; // HACK: remove the last '/'

   // active colour

   string[pos++] = (colour_is_white(board->turn)) ? 'w' : 'b';
   string[pos++] = ' ';

   // castling

   old_pos = pos;

   if (option_get_bool("Chess960")) {

      // FEN-960

      if (board->castle[White][SideH] != SquareNone) {
         string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideH])));
      }

      if (board->castle[White][SideA] != SquareNone) {
         string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideA])));
      }

      if (board->castle[Black][SideH] != SquareNone) {
         string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideH])));
      }

      if (board->castle[Black][SideA] != SquareNone) {
         string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideA])));
      }

   } else {

      // FEN

      if (board->castle[White][SideH] != SquareNone) string[pos++] = 'K';
      if (board->castle[White][SideA] != SquareNone) string[pos++] = 'Q';
      if (board->castle[Black][SideH] != SquareNone) string[pos++] = 'k';
      if (board->castle[Black][SideA] != SquareNone) string[pos++] = 'q';
   }

   if (pos == old_pos) string[pos++] = '-';

   string[pos++] = ' ';

   // en-passant

   if (board->ep_square == SquareNone) {
      string[pos++] = '-';
   } else {
      if (!square_to_string(board->ep_square,&string[pos],3)) return false;
      pos += 2;
   }

   string[pos++] = ' ';

   // halfmove clock and fullmove number

   sprintf(&string[pos],"%d %d",board->ply_nb,board->move_nb+1);

   return true;
}
Exemple #4
0
static int move_from_lan(const char string[], const board_t * board) {

   int len;
   int move;
   int promote;
   char s[256];
   int from, to;
   int colour;
   int inc;
   int piece_char;
   int n;
   const uint8 * ptr;
   int piece;
   int side;

   ASSERT(string!=NULL);
   ASSERT(board_is_ok(board));

   // init

   len = strlen(string);
   if (len != 7) return MoveNone;

   move = MoveNone;
   colour = board->turn;

   // promote

   promote = 0;

   switch (string[6]) {
   case '?': // not a promotion
      break;
   case 'N':
      promote = MovePromoteKnight;
      break;
   case 'B':
      promote = MovePromoteBishop;
      break;
   case 'R':
      promote = MovePromoteRook;
      break;
   case 'Q':
      promote = MovePromoteQueen;
      break;
   default:
      return MoveNone;
      break;
   }

   // to square

   s[0] = string[4];
   s[1] = string[5];
   s[2] = '\0';

   to = square_from_string(s);
   if (to == SquareNone) return MoveNone;

   // known from square?

   if (string[1] != '?' && string[2] != '?') {

      // from square

      s[0] = string[1];
      s[1] = string[2];
      s[2] = '\0';

      from = square_from_string(s);
      if (from == SquareNone) return MoveNone;

      // convert "king slide" castling to KxR

      if (piece_is_king(board->square[from])
       && square_rank(to) == square_rank(from)
       && abs(to-from) > 1) {
         side = (to > from) ? SideH : SideA;
         to = board->castle[colour][side];
         if (to == SquareNone) return MoveNone;
      }

      // move

      move = move_make(from,to) | promote;

      return move;
   }

   // pawn non-capture?

   if (string[0] == '?' && string[1] == '?') {

      if (board->square[to] != Empty) return MoveNone; // useful?

      inc = (colour_is_white(colour)) ? +16 : -16;

      from = to - inc;
      if (board->square[from] == Empty && square_side_rank(to,colour) == Rank4) {
         from -= inc;
      }

      if (board->square[from] != piece_make_pawn(colour)) { // useful?
         return MoveNone;
      }

      // move

      move = move_make(from,to) | promote;

      return move;
   }

   // pawn capture?

   piece_char = string[0];

   if (piece_char == '?' && string[1] != '?') {
      piece_char = 'P';
   }

   // attack loop

   n = 0;

   for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) {

      piece = board->square[from];

      if (toupper(piece_to_char(piece)) == piece_char) {
         if (piece_attack(board,piece,from,to)) {
            if (true
             && (string[1] == '?' || file_to_char(square_file(from)) == string[1])
             && (string[2] == '?' || rank_to_char(square_rank(from)) == string[2])) {
               if (!is_pinned(board,from,to,colour)) {
                  move = move_make(from,to) | promote;
                  n++;
               }
            }
         }
      }
   }

   if (n != 1) move = MoveNone;

   return move;
}