Esempio n. 1
0
def boardToPieceFeatures(board, player = chess.WHITE):
    boardState = np.zeros((0, 8, 8))

    # Pawn = 1, King = 6
    for currPiece in range(1,7):
        pieceBits = np.array(SquareSet(board.pieces(currPiece, player)).tolist(), dtype = np.uint8).reshape(8, 8)
        pieceBits = np.flip(pieceBits)

        # If the current player is black, then rotate the board 180 degrees.
        if player == chess.BLACK:
            pieceBits = np.rot90(pieceBits, k=2)

        boardState = np.append(boardState, [pieceBits], axis = 0)

    for currPiece in range(1,7):
        pieceBits = np.array(SquareSet(board.pieces(currPiece, not player)).tolist(), dtype = np.uint8).reshape(8, 8)
        pieceBits = np.flip(pieceBits)

        # If the current player is black, then rotate the board 180 degrees.
        if player == chess.BLACK:
            pieceBits = np.rot90(pieceBits, k=2)

        boardState = np.append(boardState, [pieceBits], axis = 0)

    # Returns a 12 x 8 x 8 array of the current board state.
    return boardState
Esempio n. 2
0
 def develops(self, move):
   if self.board.san(move) == 'O-O' or self.board.san(move) == 'O-O-O':
     return True
   to_move = self.board.turn
   piece_type = self.board.piece_type_at(move.from_square)
   if piece_type == chess.ROOK:
     return True
   elif piece_type == chess.PAWN or piece_type == chess.KING:
     return False
   if to_move == chess.WHITE:
     return move.from_square in SquareSet(chess.BB_RANK_1)
   elif to_move == chess.BLACK:
     return move.from_square in SquareSet(chess.BB_RANK_8)
   return False
Esempio n. 3
0
def back_rank_mate(puzzle: Puzzle) -> bool:
    node = puzzle.game.end()
    board = node.board()
    king = board.king(not puzzle.pov)
    assert king is not None
    assert isinstance(node, ChildNode)
    back_rank = 7 if puzzle.pov else 0
    if board.is_checkmate() and square_rank(king) == back_rank:
        squares = SquareSet.from_square(king + (-8 if puzzle.pov else 8))
        if puzzle.pov:
            if chess.square_file(king) < 7:
                squares.add(king - 7)
            if chess.square_file(king) > 0:
                squares.add(king - 9)
        else:
            if chess.square_file(king) < 7:
                squares.add(king + 9)
            if chess.square_file(king) > 0:
                squares.add(king + 7)
        for square in squares:
            piece = board.piece_at(square)
            if piece is None or piece.color == puzzle.pov or board.attackers(
                    puzzle.pov, square):
                return False
        return any(
            square_rank(checker) == back_rank for checker in board.checkers())
    return False
Esempio n. 4
0
def _generate_svg(x, y, previous_positions):
    """
    Generate a single svg for one frame of the animation

    Parameters
    ----------
    x: int
        the current x position of the knight starting from the top left (zero-indexed)
    y: int
        the current y position of the knight starting from the top left (zero-indexed)
    previous_positions: list
        a list of previous positions of the knight, which will be marked with an 'x' symbol in the animation

    Returns
    -------
    str
        the SVG of the current position of the knight with previous steps shown

    """

    # represent the knight on the board
    board = Board(_convert_coord_to_fen(x, y))

    # represent the previous positions of the knight
    squares = SquareSet(
        [square(prev_x, 7 - prev_y) for prev_x, prev_y in previous_positions])

    # generate SVG
    return svg_board(board=board, squares=squares)
Esempio n. 5
0
def exposed_king(puzzle: Puzzle) -> bool:
    if puzzle.pov:
        pov = puzzle.pov
        board = puzzle.mainline[0].board()
    else:
        pov = not puzzle.pov
        board = puzzle.mainline[0].board().mirror()
    king = board.king(not pov)
    assert king is not None
    if chess.square_rank(king) < 5:
        return False
    squares = SquareSet.from_square(king - 8)
    if chess.square_file(king) > 0:
        squares.add(king - 1)
        squares.add(king - 9)
    if chess.square_file(king) < 7:
        squares.add(king + 1)
        squares.add(king - 7)
    for square in squares:
        if board.piece_at(square) == Piece(PAWN, not pov):
            return False
    for node in puzzle.mainline[1::2][1:-1]:
        if node.board().is_check():
            return True
    return False
Esempio n. 6
0
def dovetail_mate(puzzle: Puzzle) -> bool:
    node = puzzle.game.end()
    board = node.board()
    king = board.king(not puzzle.pov)
    assert king is not None
    assert isinstance(node, ChildNode)
    if square_file(king) in [0, 7] or square_rank(king) in [0, 7]:
        return False
    queen_square = node.move.to_square
    if (util.moved_piece_type(node) != QUEEN
            or square_file(queen_square) == square_file(king)
            or square_rank(queen_square) == square_rank(king)
            or square_distance(queen_square, king) > 1):
        return False
    for square in [
            s for s in SquareSet(chess.BB_ALL) if square_distance(s, king) == 1
    ]:
        if square == queen_square:
            continue
        attackers = list(board.attackers(puzzle.pov, square))
        if attackers == [queen_square]:
            if board.piece_at(square):
                return False
        elif attackers:
            return False
    return True
Esempio n. 7
0
    def get_attacked_defended(self):
        attacked = np.full(64, 0.0)
        defended = np.full(64, 0.0)

        our = self.occupied_co[self.turn]
        their = self.occupied_co[not self.turn]

        for square in SquareSet(our):
            for our_defended in SquareSet(self.attacks_mask(square)):
                defended[our_defended] = 1.0

        for square in SquareSet(their):
            for our_attacked in SquareSet(self.attacks_mask(square)):
                attacked[our_attacked] = 1.0

        return attacked, defended
Esempio n. 8
0
def clearance(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        board = node.board()
        if not node.parent.board().piece_at(node.move.to_square):
            piece = board.piece_at(node.move.to_square)
            if piece and piece.piece_type in util.ray_piece_types:
                prev = node.parent.parent
                assert prev
                prev_move = prev.move
                assert prev_move
                assert isinstance(node.parent, ChildNode)
                if (not prev_move.promotion
                        and prev_move.to_square != node.move.from_square
                        and prev_move.to_square != node.move.to_square
                        and not node.parent.board().is_check()
                        and (not board.is_check()
                             or util.moved_piece_type(node.parent) != KING)):
                    if (prev_move.from_square == node.move.to_square
                            or prev_move.from_square in SquareSet.between(
                                node.move.from_square, node.move.to_square)):
                        if prev.parent and not prev.parent.board().piece_at(
                                prev_move.to_square) or util.is_in_bad_spot(
                                    prev.board(), prev_move.to_square):
                            return True
    return False
Esempio n. 9
0
 def dims_knight(self, move):
   '''Knight on the rim is dim'''
   if self.board.piece_type_at(move.from_square) == chess.KNIGHT:
     rim = SquareSet(
         chess.BB_RANK_1 | \
         chess.BB_RANK_8 | \
         chess.BB_FILE_A | \
         chess.BB_FILE_H)
     return move.to_square in rim
Esempio n. 10
0
 def opens_position(self, move):
   to_move = self.board.turn
   if self.board.piece_type_at(move.from_square) == chess.PAWN:
     if move.to_square not in SquareSet(chess.BB_RANK_1 | chess.BB_RANK_8):
       num_pawns_before = len(self.board.pieces(chess.PAWN, not to_move))
       analysis_board = chess.Board(self.board.fen())
       analysis_board.push(move)
       num_pawns_after = len(analysis_board.pieces(chess.PAWN, not to_move))
       return num_pawns_before != num_pawns_after
   return False
Esempio n. 11
0
 def controls(self, move):
   '''Returns a set of attacked/defended squares'''
   to_move = self.board.turn
   analysis_board = chess.Board(self.board.fen())
   analysis_board.push(move)
   squares = 0
   for square in chess.SQUARES:
     if move.to_square in analysis_board.attackers(to_move, square):
       squares |= chess.BB_SQUARES[square]
   return SquareSet(squares)
Esempio n. 12
0
def discovered_attack(puzzle: Puzzle) -> bool:
    if discovered_check(puzzle):
        return True
    for node in puzzle.mainline[1::2][1:]:
        if util.is_capture(node):
            between = SquareSet.between(node.move.from_square,
                                        node.move.to_square)
            if node.parent.move.to_square == node.move.to_square:
                return False
            prev = node.parent.parent
            if prev.move.from_square in between and node.move.to_square != prev.move.to_square:
                return True
    return False
Esempio n. 13
0
def self_interference(puzzle: Puzzle) -> bool:
    # intereference by opponent piece
    for node in puzzle.mainline[1::2][1:]:
        prev_board = node.parent.board()
        square = node.move.to_square
        capture = prev_board.piece_at(square)
        if capture and util.is_hanging(prev_board, capture, square):
            init_board = node.parent.parent.board()
            defenders = init_board.attackers(capture.color, square)
            defender = defenders.pop() if defenders else None
            if defender and init_board.piece_at(
                    defender).piece_type in util.ray_piece_types:
                if node.parent.move.to_square in SquareSet.between(
                        square, defender):
                    return True
    return False
Esempio n. 14
0
def skewer(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        prev = node.parent
        assert isinstance(prev, ChildNode)
        capture = prev.board().piece_at(node.move.to_square)
        if capture and util.moved_piece_type(node) in util.ray_piece_types and not node.board().is_checkmate():
            between = SquareSet.between(node.move.from_square, node.move.to_square)
            op_move = prev.move
            assert op_move
            if op_move.to_square == node.move.to_square or not op_move.from_square in between:
                continue
            if util.king_values[util.moved_piece_type(prev)] > util.king_values[capture.piece_type] and util.is_in_bad_spot(
                prev.board(), node.move.to_square
            ):
                return True
    return False
Esempio n. 15
0
def x_ray(puzzle: Puzzle) -> bool:
    for node in puzzle.mainline[1::2][1:]:
        if not util.is_capture(node):
            continue
        prev_op_node = node.parent
        assert isinstance(prev_op_node, ChildNode)
        if prev_op_node.move.to_square != node.move.to_square or util.moved_piece_type(prev_op_node) == KING:
            continue
        prev_pl_node = prev_op_node.parent
        assert isinstance(prev_pl_node, ChildNode)
        if prev_pl_node.move.to_square != prev_op_node.move.to_square:
            continue
        if prev_op_node.move.from_square in SquareSet.between(node.move.from_square, node.move.to_square):
            return True

    return False
Esempio n. 16
0
def boden_or_double_bishop_mate(puzzle: Puzzle):
    node = puzzle.game.end()
    board = node.board()
    king = board.king(not puzzle.pov)
    assert king is not None
    assert isinstance(node, ChildNode)
    bishop_squares = list(board.pieces(BISHOP, puzzle.pov))
    if len(bishop_squares) < 2:
        return None
    for square in [s for s in SquareSet(chess.BB_ALL) if square_distance(s, king) < 2]:
        if not all([p.piece_type == BISHOP for p in util.attacker_pieces(board, puzzle.pov, square)]):
            return None
    if (square_file(bishop_squares[0]) < square_file(king)) == (square_file(bishop_squares[1]) > square_file(king)):
        return "bodenMate"
    else:
        return "doubleBishopMate"
Esempio n. 17
0
def discovered_attack(puzzle: Puzzle) -> bool:
    if discovered_check(puzzle):
        return True
    for node in puzzle.mainline[1::2][1:]:
        if util.is_capture(node):
            between = SquareSet.between(node.move.from_square,
                                        node.move.to_square)
            assert isinstance(node.parent, ChildNode)
            if node.parent.move.to_square == node.move.to_square:
                return False
            prev = node.parent.parent
            assert isinstance(prev, ChildNode)
            if (prev.move.from_square in between
                    and node.move.to_square != prev.move.to_square
                    and node.move.from_square != prev.move.to_square
                    and not util.is_castling(prev)):
                return True
    return False
Esempio n. 18
0
def skewer(puzzle: Puzzle) -> bool:
    def value(pt: PieceType):
        return 10 if pt == KING else util.values[pt]

    for node in puzzle.mainline[1::2][1:]:
        prev = node.parent
        capture = prev.board().piece_at(node.move.to_square)
        if capture and util.moved_piece_type(
                node
        ) in util.ray_piece_types and not node.board().is_checkmate():
            between = SquareSet.between(node.move.from_square,
                                        node.move.to_square)
            op_move = prev.move
            if (op_move.to_square == node.move.to_square
                    or not op_move.from_square in between):
                continue
            if value(util.moved_piece_type(prev)) > value(capture.piece_type):
                return True
    return False
Esempio n. 19
0
 def closes_position(self, move):
   piece = self.board.piece_at(move.from_square)
   if piece and piece.piece_type == chess.PAWN:
     if not self.opens_position(move):
       from_bb_square = chess.BB_SQUARES[move.from_square]
       pawn_attack = 0
       if piece.color == chess.WHITE:
         pawn_attack |= chess.shift_up_left(from_bb_square)
         pawn_attack |=  chess.shift_up_right(from_bb_square)
       elif piece.color == chess.BLACK:
         pawn_attack |= chess.shift_down_left(from_bb_square)
         pawn_attack |= chess.shift_down_right(from_bb_square)
       for square in SquareSet(pawn_attack):
         passed_up_piece = self.board.piece_at(square)
         if passed_up_piece:
           if passed_up_piece.color != self.board.turn and \
               passed_up_piece.piece_type == chess.PAWN:
             return True
   return False
Esempio n. 20
0
def interference(puzzle: Puzzle) -> bool:
    # intereference by player piece
    for node in puzzle.mainline[1::2][1:]:
        prev_board = node.parent.board()
        square = node.move.to_square
        capture = prev_board.piece_at(square)
        assert node.parent.move
        if capture and square != node.parent.move.to_square and util.is_hanging(prev_board, capture, square):
            assert node.parent
            assert node.parent.parent
            assert node.parent.parent.parent
            init_board = node.parent.parent.parent.board()
            defenders = init_board.attackers(capture.color, square)
            defender = defenders.pop() if defenders else None
            defender_piece = init_board.piece_at(defender) if defender else None
            if defender and defender_piece and defender_piece.piece_type in util.ray_piece_types:
                interfering = node.parent.parent
                if interfering.move and interfering.move.to_square in SquareSet.between(square, defender):
                    return True
    return False
Esempio n. 21
0
def bit_set_count(square_set: chess.SquareSet):
    result = 0
    while square_set:
        square_set.pop()
        result += 1
    return result
Esempio n. 22
0
 def controls_center(self, move):
   center = SquareSet(chess.BB_D4 | chess.BB_D5 | chess.BB_E4 | chess.BB_E5)
   for square in self.controls(move):
     if square in center:
       return True
   return False