Пример #1
0
  public void setPieceAt(long square, char piece) {
    pawns &= ~square;
    queens &= ~square;
    rooks &= ~square;
    bishops &= ~square;
    knights &= ~square;
    kings &= ~square;

    if (piece == ' ' || piece == '.') {
      whites &= ~square;
      blacks &= ~square;
      return;
    } else if (piece == Character.toLowerCase(piece)) {
      whites &= ~square;
      blacks |= square;
    } else {
      whites |= square;
      blacks &= ~square;
    }

    switch (Character.toLowerCase(piece)) {
      case 'p':
        pawns |= square;
        break;
      case 'q':
        queens |= square;
        break;
      case 'r':
        rooks |= square;
        break;
      case 'b':
        bishops |= square;
        break;
      case 'n':
        knights |= square;
        break;
      case 'k':
        kings |= square;
        break;
    }

    key = ZobristKey.getKey(this);
    setCheckFlags();
  }
Пример #2
0
  /** Sets fen without destroying move history. If lastMove = null destroy the move history */
  public void setFenMove(String fen, String lastMove) {
    long tmpWhites = 0;
    long tmpBlacks = 0;
    long tmpPawns = 0;
    long tmpRooks = 0;
    long tmpQueens = 0;
    long tmpBishops = 0;
    long tmpKnights = 0;
    long tmpKings = 0;
    long tmpFlags;
    int tmpFiftyMovesRule = 0;
    long tmpCastlingRooks[] = {0, 0, 0, 0};
    int fenMoveNumber = 0;

    int i = 0;
    long j = Square.A8;
    String[] tokens = fen.split("[ \\t\\n\\x0B\\f\\r]+");
    String board = tokens[0];

    while ((i < board.length()) && (j != 0)) {
      char p = board.charAt(i++);
      if (p != '/') {
        int number = 0;
        try {
          number = Integer.parseInt(String.valueOf(p));
        } catch (Exception ignored) {
        }

        for (int k = 0; k < (number == 0 ? 1 : number); k++) {
          tmpWhites = (tmpWhites & ~j) | ((number == 0) && (p == Character.toUpperCase(p)) ? j : 0);
          tmpBlacks = (tmpBlacks & ~j) | ((number == 0) && (p == Character.toLowerCase(p)) ? j : 0);
          tmpPawns = (tmpPawns & ~j) | (Character.toUpperCase(p) == 'P' ? j : 0);
          tmpRooks = (tmpRooks & ~j) | (Character.toUpperCase(p) == 'R' ? j : 0);
          tmpQueens = (tmpQueens & ~j) | (Character.toUpperCase(p) == 'Q' ? j : 0);
          tmpBishops = (tmpBishops & ~j) | (Character.toUpperCase(p) == 'B' ? j : 0);
          tmpKnights = (tmpKnights & ~j) | (Character.toUpperCase(p) == 'N' ? j : 0);
          tmpKings = (tmpKings & ~j) | (Character.toUpperCase(p) == 'K' ? j : 0);
          j >>>= 1;
          if (j == 0) {
            break; // security
          }
        }
      }
    }

    // Now the rest ...
    String turn = tokens[1];
    tmpFlags = 0;
    if ("b".equals(turn)) {
      tmpFlags |= FLAG_TURN;
    }
    if (tokens.length > 2) {
      // Set castling rights supporting XFEN to disambiguate positions in Chess960
      String castlings = tokens[2];

      chess960 = false;
      // Squares to the sides of the kings {White Kingside, White Queenside, Black Kingside, Black
      // Queenside}
      long whiteKingLateralSquares[] = {
        BitboardUtils.b_d & ((tmpKings & tmpWhites) - 1),
            BitboardUtils.b_d & ~(((tmpKings & tmpWhites) - 1) | tmpKings & tmpWhites),
        BitboardUtils.b_u & ((tmpKings & tmpBlacks) - 1),
            BitboardUtils.b_u & ~(((tmpKings & tmpBlacks) - 1) | tmpKings & tmpBlacks)
      };

      // Squares where we can find a castling rook
      long possibleCastlingRookSquares[] = {0, 0, 0, 0};

      for (int k = 0; k < castlings.length(); k++) {
        char c = castlings.charAt(k);
        switch (c) {
          case 'K':
            possibleCastlingRookSquares[0] = whiteKingLateralSquares[0];
            break;
          case 'Q':
            possibleCastlingRookSquares[1] = whiteKingLateralSquares[1];
            break;
          case 'k':
            possibleCastlingRookSquares[2] = whiteKingLateralSquares[2];
            break;
          case 'q':
            possibleCastlingRookSquares[3] = whiteKingLateralSquares[3];
            break;
          default:
            // Shredder-FEN receives the name of the file where the castling rook is
            int whiteFile = "ABCDEFGH".indexOf(c);
            int blackFile = "abcdefgh".indexOf(c);
            if (whiteFile >= 0) {
              long rookSquare = BitboardUtils.b_d & BitboardUtils.FILE[whiteFile];
              if ((rookSquare & whiteKingLateralSquares[0]) != 0) {
                possibleCastlingRookSquares[0] = rookSquare;
              } else if ((rookSquare & whiteKingLateralSquares[1]) != 0) {
                possibleCastlingRookSquares[1] = rookSquare;
              }
            } else if (blackFile >= 0) {
              long rookSquare = BitboardUtils.b_u & BitboardUtils.FILE[blackFile];
              if ((rookSquare & whiteKingLateralSquares[2]) != 0) {
                possibleCastlingRookSquares[2] = rookSquare;
              } else if ((rookSquare & whiteKingLateralSquares[3]) != 0) {
                possibleCastlingRookSquares[3] = rookSquare;
              }
            }
        }
      }

      // Now store the squares of the castling rooks
      tmpCastlingRooks[0] =
          BitboardUtils.lsb(tmpRooks & tmpWhites & possibleCastlingRookSquares[0]);
      tmpCastlingRooks[1] =
          BitboardUtils.msb(tmpRooks & tmpWhites & possibleCastlingRookSquares[1]);
      tmpCastlingRooks[2] =
          BitboardUtils.lsb(tmpRooks & tmpBlacks & possibleCastlingRookSquares[2]);
      tmpCastlingRooks[3] =
          BitboardUtils.msb(tmpRooks & tmpBlacks & possibleCastlingRookSquares[3]);

      // Set the castling flags and detect Chess960
      if (tmpCastlingRooks[0] != 0) {
        tmpFlags |= FLAG_WHITE_KINGSIDE_CASTLING;
        if ((tmpWhites & tmpKings) != 1L << 3 || tmpCastlingRooks[0] != 1L) {
          chess960 = true;
        }
      }
      if (tmpCastlingRooks[1] != 0) {
        tmpFlags |= FLAG_WHITE_QUEENSIDE_CASTLING;
        if ((tmpWhites & tmpKings) != 1L << 3 || tmpCastlingRooks[1] != 1L << 7) {
          chess960 = true;
        }
      }
      if (tmpCastlingRooks[2] != 0) {
        tmpFlags |= FLAG_BLACK_KINGSIDE_CASTLING;
        if ((tmpBlacks & tmpKings) != 1L << 59 || tmpCastlingRooks[2] != 1L << 56) {
          chess960 = true;
        }
      }
      if (tmpCastlingRooks[3] != 0) {
        tmpFlags |= FLAG_BLACK_QUEENSIDE_CASTLING;
        if ((tmpBlacks & tmpKings) != 1L << 59 || tmpCastlingRooks[3] != 1L << 63) {
          chess960 = true;
        }
      }
      // END FEN castlings

      if (tokens.length > 3) {
        String passant = tokens[3];
        tmpFlags |= FLAGS_PASSANT & BitboardUtils.algebraic2Square(passant);
        if (tokens.length > 4) {
          try {
            tmpFiftyMovesRule = Integer.parseInt(tokens[4]);
          } catch (Exception e) {
            tmpFiftyMovesRule = 0;
          }
          if (tokens.length > 5) {
            String moveNumberString = tokens[5];
            int aux = Integer.parseInt(moveNumberString);
            fenMoveNumber =
                ((aux > 0 ? aux - 1 : aux) << 1) + ((tmpFlags & FLAG_TURN) == 0 ? 0 : 1);
            if (fenMoveNumber < 0) {
              fenMoveNumber = 0;
            }
          }
        }
      }
    }

    // try to apply the last move to see if we are advancing or undoing moves
    if ((moveNumber + 1) == fenMoveNumber && lastMove != null) {
      doMove(Move.getFromString(this, lastMove, true));
    } else if (fenMoveNumber < moveNumber) {
      for (int k = moveNumber; k > fenMoveNumber; k--) {
        undoMove();
      }
    }

    // Check if board changed or if we can keep the history
    if (whites != tmpWhites //
        || blacks != tmpBlacks //
        || pawns != tmpPawns //
        || rooks != tmpRooks //
        || queens != tmpQueens //
        || bishops != tmpBishops //
        || knights != tmpKnights //
        || kings != tmpKings //
        || (flags & FLAG_TURN) != (tmpFlags & FLAG_TURN)) {

      // board reset
      movesSan.clear();

      initialFen = fen;
      initialMoveNumber = fenMoveNumber;
      moveNumber = fenMoveNumber;
      outBookMove = Integer.MAX_VALUE;

      whites = tmpWhites;
      blacks = tmpBlacks;
      pawns = tmpPawns;
      rooks = tmpRooks;
      queens = tmpQueens;
      bishops = tmpBishops;
      knights = tmpKnights;
      kings = tmpKings;
      fiftyMovesRule = tmpFiftyMovesRule;

      // Flags are not completed till verify, so skip checking
      flags = tmpFlags;

      castlingRooks[0] = tmpCastlingRooks[0];
      castlingRooks[1] = tmpCastlingRooks[1];
      castlingRooks[2] = tmpCastlingRooks[2];
      castlingRooks[3] = tmpCastlingRooks[3];

      // Set zobrist key and check flags
      key = ZobristKey.getKey(this);
      setCheckFlags();

      // and save history
      resetHistory();
      saveHistory(0, false);
    } else {
      if (moveNumber < outBookMove) {
        outBookMove = Integer.MAX_VALUE;
      }
    }
  }