Exemplo n.º 1
0
    def __init__(self, position, move):

        resulting_position = position.copy().make_move(move)
        captured = position._pieces[move.target._x88]
        piece = position._pieces[move.source._x88]
        ocolor = Piece.opposite_color(position.fen._to_move)

        # Pawn moves.
        enpassant = False
        if Piece.klass(piece) == PAWN:
            # En-passant.
            if move.target.file != move.source.file and not captured:
                enpassant = True
                captured = Piece.from_klass_and_color(PAWN, ocolor)

        # Castling.
        # TODO: Support Chess960.
        # TODO: Validate the castling move.
        if Piece.klass(piece) == KING:
            self.is_king_side_castle = move.target.x - move.source.x == 2
            self.is_queen_side_castle = move.target.x - move.source.x == -2
        else:
            self.is_king_side_castle = self.is_queen_side_castle = False

        # Checks.
        self.is_check = resulting_position.is_check()
        self.is_checkmate = resulting_position.is_checkmate()

        self.move = move
        self.piece = piece
        self.captured = captured
        self.is_enpassant = enpassant

        self._set_text(position)
Exemplo n.º 2
0
    def __init__(self, position, move):

        resulting_position = position.copy().make_move(move)
        captured = position._pieces[move.target._x88]
        piece = position._pieces[move.source._x88]
        ocolor = Piece.opposite_color(position.fen._to_move)

        # Pawn moves.
        enpassant = False
        if Piece.klass(piece) == PAWN:
            # En-passant.
            if move.target.file != move.source.file and not captured:
                enpassant = True
                captured = Piece.from_klass_and_color(PAWN, ocolor)

        # Castling.
        # TODO: Support Chess960.
        # TODO: Validate the castling move.
        if Piece.klass(piece) == KING:
            self.is_king_side_castle = move.target.x - move.source.x == 2
            self.is_queen_side_castle = move.target.x - move.source.x == -2
        else:
            self.is_king_side_castle = self.is_queen_side_castle = False

        # Checks.
        self.is_check = resulting_position.is_check()
        self.is_checkmate = resulting_position.is_checkmate()

        self.move = move
        self.piece = piece
        self.captured = captured
        self.is_enpassant = enpassant

        self._set_text(position)
Exemplo n.º 3
0
    def to_move(cls, position, san):
        
        san = str(san)

        # Castling moves.
        if san == "O-O" or san == "O-O-O":
            # TODO: Support Chess960, check the castling moves are valid.
            rank = 1 if position.fen.turn == "w" else 8
            if san == "O-O":
                return Move(
                    source=Square.from_rank_and_file(rank, 'e'),
                    target=Square.from_rank_and_file(rank, 'g'))
            else:
                return Move(
                    source=Square.from_rank_and_file(rank, 'e'),
                    target=Square.from_rank_and_file(rank, 'c'))
        # Regular moves.
        else:
            matches = cls.san_regex.match(san)
            if not matches:
                raise ValueError("Invalid SAN: %s." % repr(san))

            if matches.group(1):
                klass = Piece.klass(matches.group(1).lower())
            else:
                klass = PAWN
            piece = Piece.from_klass_and_color(klass, position.fen._to_move)
            target = Square(matches.group(4))

            source = None
            for m in position.get_legal_moves():
                if position._pieces[m.source._x88] != piece or m.target != target:
                    continue

                if matches.group(2) and matches.group(2) != m.source.file:
                    continue
                if matches.group(3) and matches.group(3) != str(m.source.rank):
                    continue

                # Move matches. Assert it is not ambiguous.
                if source:
                    raise MoveError(
                        "Move is ambiguous: %s matches %s and %s."
                            % san, source, m)
                source = m.source

            if not source:
                raise MoveError("No legal move matches %s." % san)

            return Move(source, target, matches.group(5) or None)
Exemplo n.º 4
0
    def to_move(cls, position, san):

        san = str(san)

        # Castling moves.
        if san == "O-O" or san == "O-O-O":
            # TODO: Support Chess960, check the castling moves are valid.
            rank = 1 if position.fen.turn == "w" else 8
            if san == "O-O":
                return Move(source=Square.from_rank_and_file(rank, 'e'),
                            target=Square.from_rank_and_file(rank, 'g'))
            else:
                return Move(source=Square.from_rank_and_file(rank, 'e'),
                            target=Square.from_rank_and_file(rank, 'c'))
        # Regular moves.
        else:
            matches = cls.san_regex.match(san)
            if not matches:
                raise ValueError("Invalid SAN: %s." % repr(san))

            if matches.group(1):
                klass = Piece.klass(matches.group(1).lower())
            else:
                klass = PAWN
            piece = Piece.from_klass_and_color(klass, position.fen._to_move)
            target = Square(matches.group(4))

            source = None
            for m in position.get_legal_moves():
                if position._pieces[
                        m.source._x88] != piece or m.target != target:
                    continue

                if matches.group(2) and matches.group(2) != m.source.file:
                    continue
                if matches.group(3) and matches.group(3) != str(m.source.rank):
                    continue

                # Move matches. Assert it is not ambiguous.
                if source:
                    raise MoveError(
                        "Move is ambiguous: %s matches %s and %s." % san,
                        source, m)
                source = m.source

            if not source:
                raise MoveError("No legal move matches %s." % san)

            return Move(source, target, matches.group(5) or None)
Exemplo n.º 5
0
    def _set_text(self, position):

        move = self.move

        piece_klass = Piece.klass(self.piece)

        # Generate the SAN.
        san = ""
        if self.is_king_side_castle:
            san += "O-O"
        elif self.is_queen_side_castle:
            san += "O-O-O"
        else:
            if piece_klass != PAWN:
                san += Piece.from_klass_and_color(piece_klass, WHITE)

            if position:
                san += self._get_disambiguator(move, position)

            if self.captured:
                if piece_klass == PAWN:
                    san += move.source.file
                san += "x"
            san += move.target.name

            if move.promotion:
                san += "="
                san += move.promotion.upper()

        if self.is_checkmate:
            san += "#"
        elif self.is_check:
            san += "+"

        if self.is_enpassant:
            san += " (e.p.)"

        self._text = san
Exemplo n.º 6
0
    def _set_text(self, position):

        move = self.move

        piece_klass = Piece.klass(self.piece)

        # Generate the SAN.
        san = ""
        if self.is_king_side_castle:
            san += "O-O"
        elif self.is_queen_side_castle:
            san += "O-O-O"
        else:
            if piece_klass != PAWN:
                san += Piece.from_klass_and_color(piece_klass, WHITE)

            if position:
                san += self._get_disambiguator(move, position)

            if self.captured:
                if piece_klass == PAWN:
                    san += move.source.file
                san += "x"
            san += move.target.name

            if move.promotion:
                san += "="
                san += move.promotion.upper()

        if self.is_checkmate:
            san += "#"
        elif self.is_check:
            san += "+"

        if self.is_enpassant:
            san += " (e.p.)"

        self._text = san
Exemplo n.º 7
0
 def test_from_klass_and_color(self):
     self.assertEqual('P', Piece.from_klass_and_color(piece.PAWN, piece.WHITE))