Esempio n. 1
0
bool piece_is_ok(Piece pc) {
  return
    piece_type_is_ok(type_of_piece(pc)) &&
    color_is_ok(color_of_piece(pc));
}
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;
}
bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {

  assert(pos.is_ok());
  assert(move_is_ok(m));
  assert(pinned == pos.pinned_pieces(pos.side_to_move()));

  Color us = pos.side_to_move();
  Color them = opposite_color(us);
  Square from = move_from(m);
  Square to = move_to(m);
  Piece pc = pos.piece_on(from);

  // Use a slower but simpler function for uncommon cases
  if (move_is_ep(m) || move_is_castle(m))
      return move_is_legal(pos, m);

  // If the from square is not occupied by a piece belonging to the side to
  // move, the move is obviously not legal.
  if (color_of_piece(pc) != us)
      return false;

  // The destination square cannot be occupied by a friendly piece
  if (pos.color_of_piece_on(to) == us)
      return false;

  // Handle the special case of a pawn move
  if (type_of_piece(pc) == PAWN)
  {
      // Move direction must be compatible with pawn color
      int direction = to - from;
      if ((us == WHITE) != (direction > 0))
          return false;

      // A pawn move is a promotion iff the destination square is
      // on the 8/1th rank.
      if ((  (square_rank(to) == RANK_8 && us == WHITE)
           ||(square_rank(to) == RANK_1 && us != WHITE)) != bool(move_is_promotion(m)))
          return false;

      // Proceed according to the square delta between the origin and
      // destination squares.
      switch (direction)
      {
      case DELTA_NW:
      case DELTA_NE:
      case DELTA_SW:
      case DELTA_SE:
      // Capture. The destination square must be occupied by an enemy
      // piece (en passant captures was handled earlier).
          if (pos.color_of_piece_on(to) != them)
              return false;
          break;

      case DELTA_N:
      case DELTA_S:
      // Pawn push. The destination square must be empty.
          if (!pos.square_is_empty(to))
              return false;
          break;

      case DELTA_NN:
      // Double white pawn push. The destination square must be on the fourth
      // rank, and both the destination square and the square between the
      // source and destination squares must be empty.
      if (   square_rank(to) != RANK_4
          || !pos.square_is_empty(to)
          || !pos.square_is_empty(from + DELTA_N))
          return false;
          break;

      case DELTA_SS:
      // Double black pawn push. The destination square must be on the fifth
      // rank, and both the destination square and the square between the
      // source and destination squares must be empty.
          if (   square_rank(to) != RANK_5
              || !pos.square_is_empty(to)
              || !pos.square_is_empty(from + DELTA_S))
              return false;
          break;

      default:
          return false;
      }
      // The move is pseudo-legal, check if it is also legal
      return pos.is_check() ? pos.pl_move_is_evasion(m, pinned) : pos.pl_move_is_legal(m, pinned);
  }

  // Luckly we can handle all the other pieces in one go
  return    bit_is_set(pos.attacks_from(pc, from), to)
        && (pos.is_check() ? pos.pl_move_is_evasion(m, pinned) : pos.pl_move_is_legal(m, pinned))
        && !move_is_promotion(m);
}