Beispiel #1
0
    def get_theoretical_ep_right(self, x):
        """Checks if a player could have an ep-move in theory from
        looking just at the piece positions.

        :param file:
            The file to check as a letter between `"a"` and `"h"`.

        :return:
            A boolean indicating whether the player could theoretically
            have that en-passant move.

        """
        if x < 0 or x > 7:
            raise ValueError(x)
        '''
        3 states of en-passant
        p.  pP  ..
        ..  ..  .p
        .P  ..  ..
        '''

        # Check there is a pawn on the right rank for e.p.
        y = 3 if self.fen._to_move == WHITE else 4
        x88 = X88.from_x_and_y(x, y)

        piece = self._pieces[x88]
        if not piece:
            return False

        # If the square is not an opposite colored pawn then its not possible.
        ocolor = Piece.opposite_color(self.fen._to_move)
        if not Piece.is_klass_and_color(piece, PAWN, ocolor):
            return False

        # If the square below the pawn is not empty then it not possible.
        y = 2 if self.fen.turn == WHITE else 5
        x88 = X88.from_x_and_y(x, y)
        if self[x88]:
            return False

        # If there is not pawn of opposite color on a neighboring file then its not possible.
        xs = [_x for _x in range(8) if _x >= 0 and _x < 8 and abs(x - _x) == 1]
        for _x in xs:
            x88 = X88.from_x_and_y(_x, y)
            piece = self._pieces[x88]
            if Piece.is_klass_and_color(
                    piece, PAWN, Piece.opposite_color(self.fen._to_move)):
                return True
        # Else its just not possible.
        return False
Beispiel #2
0
    def get_theoretical_ep_right(self, x):
        """Checks if a player could have an ep-move in theory from
        looking just at the piece positions.

        :param file:
            The file to check as a letter between `"a"` and `"h"`.

        :return:
            A boolean indicating whether the player could theoretically
            have that en-passant move.

        """
        if x < 0 or x > 7:
            raise ValueError(x)

        '''
        3 states of en-passant
        p.  pP  ..
        ..  ..  .p
        .P  ..  ..
        '''

        # Check there is a pawn on the right rank for e.p.
        y = 3 if self.fen._to_move == WHITE else 4
        x88 = X88.from_x_and_y(x, y) 

        piece = self._pieces[x88]
        if not piece:
            return False

        # If the square is not an opposite colored pawn then its not possible.
        ocolor = Piece.opposite_color(self.fen._to_move)
        if not Piece.is_klass_and_color(piece, PAWN, ocolor):
            return False

        # If the square below the pawn is not empty then it not possible.
        y = 2 if self.fen.turn == WHITE else 5
        x88 = X88.from_x_and_y(x, y) 
        if self[x88]:
            return False

        # If there is not pawn of opposite color on a neighboring file then its not possible.
        xs = [_x for _x in range(8) if _x>=0 and  _x<8 and abs(x-_x) == 1]
        for _x in xs:
            x88 = X88.from_x_and_y(_x, y) 
            piece = self._pieces[x88] 
            if Piece.is_klass_and_color(piece, PAWN, Piece.opposite_color(self.fen._to_move)):
                return True
        # Else its just not possible.
        return False
Beispiel #3
0
    def __init__(self, label):

        if len(label) != 2:
            raise ValueError(square)

        try:
            x = self.files.index(label[0])
            y = self.ranks.index(label[1])
        except ValueError:
            raise ValueError(label)

        self._x88 = X88.from_x_and_y(x, y)
Beispiel #4
0
    def __init__(self, label):

        if len(label) != 2:
            raise ValueError(square)

        try:
            x = self.files.index(label[0])
            y = self.ranks.index(label[1])
        except ValueError:
            raise ValueError(label)

        self._x88 = X88.from_x_and_y(x, y)
Beispiel #5
0
 def test_to_index(self):
     self.assertEqual(X88.to_index(0), 0)
Beispiel #6
0
 def test_is_backrank(self):
     self.assertEqual(X88.is_backrank(0, piece.BLACK), True)
Beispiel #7
0
 def file(self):
     """The file as a character in %s""" % self.files
     return self.files[X88.to_x(self._x88)]
Beispiel #8
0
 def y(self):
     """The y-coordinate, starting with 0 for the first rank."""
     return X88.to_y(self._x88)
Beispiel #9
0
 def y(self):
     """The y-coordinate, starting with 0 for the first rank."""
     return X88.to_y(self._x88)
Beispiel #10
0
 def x(self):
     """The x-coordinate, starting with 0 for the a-file."""
     return X88.to_x(self._x88)
Beispiel #11
0
 def test_from_index(self):
     self.assertEqual(X88.from_index(0), 0)
Beispiel #12
0
 def test_to_y(self):
     self.assertEqual(X88.to_y(0), 0)
Beispiel #13
0
 def test_to_index(self):
     self.assertEqual(X88.to_index(0), 0)
Beispiel #14
0
 def test_is_secondrank(self):
     self.assertEqual(X88.is_secondrank(8, piece.WHITE), True)
Beispiel #15
0
 def test_to_y(self):
     self.assertEqual(X88.to_y(0), 0)
Beispiel #16
0
 def rank(self):
     """The rank as a character in %s""" % self.ranks
     return self.ranks[X88.to_y(self._x88)]
Beispiel #17
0
 def test_from_index(self):
     self.assertEqual(X88.from_index(0), 0)
Beispiel #18
0
 def file(self):
     """The file as a character in %s""" % self.files
     return self.files[X88.to_x(self._x88)]
Beispiel #19
0
 def x(self):
     """The x-coordinate, starting with 0 for the a-file."""
     return X88.to_x(self._x88)
Beispiel #20
0
 def index(self):
     """An integer between 0 and %s where 0 represents Square('a1').""" % (
         len(self.ranks) * len(self.files) - 1)
     return X88.to_index(self._x88)
Beispiel #21
0
 def rank(self):
     """The rank as a character in %s""" % self.ranks
     return self.ranks[X88.to_y(self._x88)]
Beispiel #22
0
 def test_from_x_and_y(self):
     self.assertEqual(X88.from_x_and_y(0, 0), 0)
Beispiel #23
0
 def index(self):
     """An integer between 0 and %s where 0 represents Square('a1').""" % (
         len(self.ranks) * len(self.files) - 1)
     return X88.to_index(self._x88)
Beispiel #24
0
 def test_is_backrank(self):
     self.assertEqual(X88.is_backrank(0, piece.BLACK), True)
Beispiel #25
0
    def get_pseudo_legal_moves(self, source=None):
        """:yield: Pseudo legal moves in the current position.
         
        :param source: The source square to limit moves or None for
            all possible moves.
        """

        tomove = self.fen._to_move

        for x88 in [ x88 for x88 in Square._x88_squares.keys() 
            if self._pieces[x88] 
            and Piece.color(self._pieces[x88]) == tomove
            and (source is None or x88 == source._x88)]:

            piece = self._pieces[x88]
            klass = Piece.klass(piece)

            # pawn moves
            if klass == PAWN:
                single, double, capleft, capright = X88.PAWN_OFFSETS[tomove]

                # Single square ahead. Do not capture.
                offset = x88 + single
                if not self._pieces[offset]:
                    # Promotion.
                    if X88.is_backrank(offset, tomove):
                        for promote_to in Piece.promote_to:
                            yield Move.from_x88(x88, offset, promote_to)
                    else:
                        yield Move.from_x88(x88, offset)

                    # Two squares ahead. Do not capture.
                    if X88.is_secondrank(x88, tomove):
                        offset = x88 + double
                        if not self._pieces[offset]:
                            yield Move.from_x88(x88, offset)

                # Pawn captures.
                for cap in [capleft, capright]:
                    offset = x88 + cap
                    if offset & X88.X88:
                        continue
                    target = self._pieces[offset]
                    if target and Piece.color(target) != tomove:
                       # Promotion.
                        if X88.is_backrank(offset, tomove):
                            for promote_to in Piece.promote_to:
                                yield Move.from_x88(x88, offset, promote_to)
                        else:
                            yield Move.from_x88(x88, offset)
                   # En-passant.
                    elif not target and offset == self.fen._ep:
                        yield Move.from_x88(target, self.fen._ep)
            
            #piece moves
            else:
                # for each a direction a piece moves in
                for offset in X88.PIECE_OFFSETS[Piece.klass(piece)]:

                    t_x88 = x88 + offset

                    # while we do not fall off the board
                    while not t_x88 & 0x88:
                        
                        # if there was not piece to attack then yield a quiet move
                        if not self._pieces[t_x88]:
                            yield Move.from_x88(x88, t_x88)
                            # do not break out

                        # else there is a piece there
                        else:
                            # if we can attack generate a move
                            if Piece.color(self._pieces[t_x88]) != tomove:
                                yield Move.from_x88(x88, t_x88)
                            # we hit something so break out
                            break

                        # Knight and king do not go multiple times in their direction.
                        if klass in [KNIGHT, KING]:
                            break

                        # travel down the board in the direction
                        t_x88 += offset


        # castling moves
        opponent = Piece.opposite_color(tomove)
        ok = True

        # get possible castling for the side to move
        for castle in [c for c in self.fen._castle_rights if Piece.color(c) == tomove]:

            (square, enum), _ = Piece.castle_squares[castle]
            king = Square(square)

            if Piece.klass(castle) == KING:
                direc = 1
            else:
                direc = -1

            # for offset in the squares the king will travel
            for offset in range(0, 3):
                s = Square.from_x88(king._x88 + (offset * direc))

                # if we are not the king square and we are occuppied
                if offset and self._pieces[s._x88]:
                    ok = False
                    break
                    
                # if we are trying to travel through check
                if self.is_attacked(opponent, s):
                    ok = False
                    break

            # kludge: we have to check occupancy for one more square on the queen side
            if direc == -1 and self._pieces[s._x88 - 1]:
                    ok = False
            if ok:
                yield Move(king, s)
Beispiel #26
0
 def test_is_secondrank(self):
     self.assertEqual(X88.is_secondrank(8, piece.WHITE), True)
Beispiel #27
0
    def get_pseudo_legal_moves(self, source=None):
        """:yield: Pseudo legal moves in the current position.
         
        :param source: The source square to limit moves or None for
            all possible moves.
        """

        tomove = self.fen._to_move

        for x88 in [
                x88 for x88 in Square._x88_squares.keys()
                if self._pieces[x88] and Piece.color(self._pieces[x88]) ==
                tomove and (source is None or x88 == source._x88)
        ]:

            piece = self._pieces[x88]
            klass = Piece.klass(piece)

            # pawn moves
            if klass == PAWN:
                single, double, capleft, capright = X88.PAWN_OFFSETS[tomove]

                # Single square ahead. Do not capture.
                offset = x88 + single
                if not self._pieces[offset]:
                    # Promotion.
                    if X88.is_backrank(offset, tomove):
                        for promote_to in Piece.promote_to:
                            yield Move.from_x88(x88, offset, promote_to)
                    else:
                        yield Move.from_x88(x88, offset)

                    # Two squares ahead. Do not capture.
                    if X88.is_secondrank(x88, tomove):
                        offset = x88 + double
                        if not self._pieces[offset]:
                            yield Move.from_x88(x88, offset)

                # Pawn captures.
                for cap in [capleft, capright]:
                    offset = x88 + cap
                    if offset & X88.X88:
                        continue
                    target = self._pieces[offset]
                    if target and Piece.color(target) != tomove:
                        # Promotion.
                        if X88.is_backrank(offset, tomove):
                            for promote_to in Piece.promote_to:
                                yield Move.from_x88(x88, offset, promote_to)
                        else:
                            yield Move.from_x88(x88, offset)
                # En-passant.
                    elif not target and offset == self.fen._ep:
                        yield Move.from_x88(target, self.fen._ep)

            #piece moves
            else:
                # for each a direction a piece moves in
                for offset in X88.PIECE_OFFSETS[Piece.klass(piece)]:

                    t_x88 = x88 + offset

                    # while we do not fall off the board
                    while not t_x88 & 0x88:

                        # if there was not piece to attack then yield a quiet move
                        if not self._pieces[t_x88]:
                            yield Move.from_x88(x88, t_x88)
                            # do not break out

                        # else there is a piece there
                        else:
                            # if we can attack generate a move
                            if Piece.color(self._pieces[t_x88]) != tomove:
                                yield Move.from_x88(x88, t_x88)
                            # we hit something so break out
                            break

                        # Knight and king do not go multiple times in their direction.
                        if klass in [KNIGHT, KING]:
                            break

                        # travel down the board in the direction
                        t_x88 += offset

        # castling moves
        opponent = Piece.opposite_color(tomove)
        ok = True

        # get possible castling for the side to move
        for castle in [
                c for c in self.fen._castle_rights if Piece.color(c) == tomove
        ]:

            (square, enum), _ = Piece.castle_squares[castle]
            king = Square(square)

            if Piece.klass(castle) == KING:
                direc = 1
            else:
                direc = -1

            # for offset in the squares the king will travel
            for offset in range(0, 3):
                s = Square.from_x88(king._x88 + (offset * direc))

                # if we are not the king square and we are occuppied
                if offset and self._pieces[s._x88]:
                    ok = False
                    break

                # if we are trying to travel through check
                if self.is_attacked(opponent, s):
                    ok = False
                    break

            # kludge: we have to check occupancy for one more square on the queen side
            if direc == -1 and self._pieces[s._x88 - 1]:
                ok = False
            if ok:
                yield Move(king, s)
Beispiel #28
0
 def test_from_x_and_y(self):
     self.assertEqual(X88.from_x_and_y(0,0), 0)