Exemplo n.º 1
0
    def set_board(self):
        for board_file in BOARD_FILES:
            file_ = board_file[0]
            white_pawn = Piece()
            white_pawn.color = Piece.WHITE
            white_pawn.name = Piece.PAWN
            self.square(file_, 2).piece = white_pawn

        for board_file in BOARD_FILES:
            file_ = board_file[0]
            black_pawn = Piece()
            black_pawn.color = Piece.BLACK
            black_pawn.name = Piece.PAWN
            self.square(file_, 7).piece = black_pawn

        for board_file in BOARD_FILES:
            file_ = board_file[0]
            white_piece = Piece()
            white_piece.color = Piece.WHITE
            white_piece.name = board_file[1]
            self.square(file_, 1).piece = white_piece

            black_piece = Piece()
            black_piece.color = Piece.BLACK
            black_piece.name = board_file[1]
            self.square(file_, 8).piece = black_piece

        for board_file in BOARD_FILES:
            file_ = board_file[0]
            self.square(file_, 3).piece = None
            self.square(file_, 4).piece = None
            self.square(file_, 5).piece = None
            self.square(file_, 6).piece = None
Exemplo n.º 2
0
    def get_attackers(self, color, square):
        """Gets the attackers of a specific square.

        :param color:
            Filter attackers by this piece color.
        :param square:
            The square to check for.

        :yield:
            Source squares of the attack.
        """
        if not color in [BLACK, WHITE]:
            raise KeyError("Invalid color: %s." % repr(color))


        for x88, source in Square._x88_squares.iteritems():

            piece = self._pieces[x88]
            if not piece or Piece.color(piece) != color:
                continue

            difference = x88 - square._x88
            index = difference + X88.ATTACKER_DIFF
            klass = Piece.klass(piece)

            if X88.ATTACKS[index] & (1 << X88.SHIFTS[klass]):
                # Handle pawns.
                if klass == PAWN:
                    if difference > 0:
                        if Piece.color(piece) == WHITE:
                            yield source
                    else:
                        if Piece.color(piece) == BLACK:
                            yield source
                    continue

                # Handle knights and king.
                if klass in [KNIGHT, KING]:
                    yield source

                # Handle the others.
                offset = X88.RAYS[index]
                j = source._x88 + offset
                blocked = False
                while j != square._x88:
                    if self._pieces[j]:
                        blocked = True
                        break
                    j += offset
                if not blocked:
                    yield source
Exemplo n.º 3
0
    def get_attackers(self, color, square):
        """Gets the attackers of a specific square.

        :param color:
            Filter attackers by this piece color.
        :param square:
            The square to check for.

        :yield:
            Source squares of the attack.
        """
        if not color in [BLACK, WHITE]:
            raise KeyError("Invalid color: %s." % repr(color))

        for x88, source in Square._x88_squares.iteritems():

            piece = self._pieces[x88]
            if not piece or Piece.color(piece) != color:
                continue

            difference = x88 - square._x88
            index = difference + X88.ATTACKER_DIFF
            klass = Piece.klass(piece)

            if X88.ATTACKS[index] & (1 << X88.SHIFTS[klass]):
                # Handle pawns.
                if klass == PAWN:
                    if difference > 0:
                        if Piece.color(piece) == WHITE:
                            yield source
                    else:
                        if Piece.color(piece) == BLACK:
                            yield source
                    continue

                # Handle knights and king.
                if klass in [KNIGHT, KING]:
                    yield source

                # Handle the others.
                offset = X88.RAYS[index]
                j = source._x88 + offset
                blocked = False
                while j != square._x88:
                    if self._pieces[j]:
                        blocked = True
                        break
                    j += offset
                if not blocked:
                    yield source
Exemplo n.º 4
0
    def get_piece_counts(self, colors=[WHITE, BLACK]):
        """Counts the pieces on the board.

        :param color:
            list of colors to check. Defualts to black and white

        :return:
            A dictionary of piece counts, keyed by lowercase piece type
            letters.
        """
        #if not color in ["w", "b", "wb", "bw"]:
        #   raise KeyError(
        #       "Expected color filter to be one of 'w', 'b', 'wb', 'bw', "
        #       "got: %s." % repr(color))

        counts = {
            PAWN: 0,
            BISHOP: 0,
            KNIGHT: 0,
            ROOK: 0,
            KING: 0,
            QUEEN: 0,
        }
        for piece in self._pieces:
            if piece and Piece.color(piece) in colors:
                counts[Piece.klass(piece)] += 1
        return counts
Exemplo n.º 5
0
    def get_piece_counts(self, colors=[WHITE, BLACK]):
        """Counts the pieces on the board.

        :param color:
            list of colors to check. Defualts to black and white

        :return:
            A dictionary of piece counts, keyed by lowercase piece type
            letters.
        """
        #if not color in ["w", "b", "wb", "bw"]:
        #   raise KeyError(
        #       "Expected color filter to be one of 'w', 'b', 'wb', 'bw', "
        #       "got: %s." % repr(color))

        counts = {
            PAWN:   0,
            BISHOP: 0,
            KNIGHT: 0,
            ROOK:   0,
            KING:   0,
            QUEEN:  0,
        }
        for piece in self._pieces:
            if piece and Piece.color(piece) in colors:
                counts[Piece.klass(piece)] += 1
        return counts
Exemplo n.º 6
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)
Exemplo n.º 7
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)
Exemplo n.º 8
0
 def test_color(self):
     self.assertEqual(piece.WHITE, Piece.color('P'))
     self.assertEqual(piece.BLACK, Piece.color('p'))