Пример #1
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
 def balestra(self, available_squares, square):
     for attacker in self.board.attackers(self.winner(),
                                          available_squares[2]):
         if (chess.square_distance(square, self.board.king(not self.winner))
                 == 2 and chess.square_distance(
                     attacker, self.board.king(not self.winner)) == 2
                 and chess.square_distance(square, attacker) == 3):
             print('Balestra mate')
    def kill_box(self, available_squares, square):
        if square == available_squares[0]:  
            for defender in self.board.attackers(self.winner(), square):
                if (str(self.board.piece_at(defender)).upper() == 'Q' and chess.square_distance(square, defender) == 2 and 
                (available_squares[3] and available_squares[4] in self.board.attacks(defender))):
                    print('Kill box mate')

        elif square == available_squares[4]:
            for defender in self.board.attackers(self.winner(), square):
                if (str(self.board.piece_at(defender)).upper() == 'Q' and chess.square_distance(square, defender) == 2 and 
                (available_squares[0] and available_squares[1] in self.board.attacks(defender))):
                    print('Kill box mate')
    def triangle(self, available_squares, square):
        if square == available_squares[1]:
            for defender in self.board.attackers(self.winner(), square):
                if (str(self.board.piece_at(defender)).upper() == 'R' and chess.square_distance(square, defender) == 2 and 
                (available_squares[2] and available_squares[4] in self.board.attacks(defender))):
                    print('Triangle mate')

        elif square == available_squares[3]:
            for defender in self.board.attackers(self.winner(), square):
                if (str(self.board.piece_at(defender)).upper() == 'R' and chess.square_distance(square, defender) == 2 and 
                (available_squares[2] and available_squares[0] in self.board.attacks(defender))):
                    print('Triangle mate')
Пример #5
0
def king_safety(board: Board):
    wpieces = board.occupied_co[WHITE]
    bpieces = board.occupied_co[BLACK]
    wkingloc = lsb(board.kings & wpieces)
    bkingloc = lsb(board.kings & bpieces)
    safety: float = 0
    safety += sum(
        chess.square_distance(bkingloc, sq) * 2
        for sq in scan_forward(board.queens & wpieces))
    safety -= sum(
        chess.square_distance(wkingloc, sq) * 2
        for sq in scan_forward(board.queens & bpieces))
    safety += sum(
        chess.square_distance(bkingloc, sq) / 2
        for sq in scan_forward(board.bishops & wpieces))
    safety -= sum(
        chess.square_distance(wkingloc, sq) / 2
        for sq in scan_forward(board.bishops & bpieces))
    safety += sum(
        chess.square_distance(bkingloc, sq) / 2
        for sq in scan_forward(board.rooks & wpieces))
    safety -= sum(
        chess.square_distance(wkingloc, sq) / 2
        for sq in scan_forward(board.rooks & bpieces))
    safety += sum(
        chess.square_distance(bkingloc, sq)
        for sq in scan_forward(board.knights & wpieces))
    safety -= sum(
        chess.square_distance(wkingloc, sq)
        for sq in scan_forward(board.knights & bpieces))
    return safety
Пример #6
0
def hook_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 util.moved_piece_type(node) == ROOK and square_distance(node.move.to_square, king) == 1:
        for rook_defender_square in board.attackers(puzzle.pov, node.move.to_square):
            defender = board.piece_at(rook_defender_square)
            if defender and defender.piece_type == KNIGHT and square_distance(rook_defender_square, king) == 1:
                for knight_defender_square in board.attackers(puzzle.pov, rook_defender_square):
                    pawn = board.piece_at(knight_defender_square)
                    if pawn and pawn.piece_type == PAWN:
                        return True
    return False
    def create_move_encoding(self, move):
        assert isinstance(move, chess.Move)
        index = 0
        move_key = (chess.square_rank(move.to_square) -
                    chess.square_rank(move.from_square),
                    chess.square_file(move.to_square) -
                    chess.square_file(move.from_square),
                    0 if move.promotion is None else move.promotion)
        init_vector = [0 for x in range(64 * 73)]
        if move is None or move == chess.Move.null():
            return init_vector
        if self.board.piece_at(move.from_square).piece_type == chess.KNIGHT \
                or move.promotion is not None and move.promotion != chess.QUEEN:
            index = 56 + self.special_move_indices[move_key]
        else:
            king_steps = chess.square_distance(move.from_square,
                                               move.to_square)
            unit_vector = (move_key[0], move_key[1])
            if king_steps != 0:
                unit_vector = (move_key[0] / king_steps,
                               move_key[1] / king_steps)

            if unit_vector != (0, 0):
                index = 7 * self.unit_moves[unit_vector] + king_steps - 1

        print(index)
        init_vector[move.from_square * 73 + index] = 1
        return init_vector
Пример #8
0
def gen_labels(valid, board, next_move, extended=False):
    if not extended:
        return [int(valid), int(not valid)]

    uci = str(next_move)
    from_pos, to_pos = uci[:2], uci[2:]

    from_square = chess.square(ord(from_pos[0]) - ord('a'), int(from_pos[1])-1)
    to_square = chess.square(ord(to_pos[0]) - ord('a'), int(to_pos[1])-1)

    distance = chess.square_distance(from_square, to_square)
    distance_vec = [0] * 8
    distance_vec[distance-1] = 1

    symbol = board.piece_at(from_square).symbol()
    is_black, is_white = int(symbol.islower()), int(symbol.isupper())

    symbol_vec = [0] * len(PIECE_TO_INT)
    symbol_vec[PIECE_TO_INT[symbol.lower()]] = 1

    labels = []
    labels.extend([int(valid), int(not valid)]) # is valid or not valid
    labels.extend(distance_vec) # what distance
    labels.extend([is_black, is_white]) # is black or white
    labels.extend(symbol_vec) # which symbol
    return labels
Пример #9
0
def king_activity(board):
    w_king = board.king(chess.WHITE)
    b_king = board.king(chess.BLACK)
    w_score, b_score = 0, 0

    if len(board.pieces(chess.PAWN, chess.BLACK)) > 0:
        w_score = min(
            chess.square_distance(w_king, pawn)
            for pawn in board.pieces(chess.PAWN, chess.BLACK))

    if len(board.pieces(chess.PAWN, chess.WHITE)) > 0:
        b_score = min(
            chess.square_distance(b_king, pawn)
            for pawn in board.pieces(chess.PAWN, chess.WHITE))

    return -(w_score - b_score)  # negate because closer is better
Пример #10
0
    def get_model_num_from_move(self, move):
        directions = [-1, 1, -7, 7, -8, 8, -9, 9]
        knight_moves = [17, 15, 10, 6, -17, -15, -10, -6]
        diff = move.to_square - move.from_square

        # Underpromotion
        if move.promotion != 5 and move.promotion != None:
            directions = [7, 8, 9]
            for d in directions:
                if abs(diff) == d:
                    direction = d
            _type = 3 * directions.index(direction) + move.promotion - 2 + 64
        # Knight move
        elif diff in knight_moves and square_distance(move.to_square,
                                                      move.from_square) == 2:
            _type = 56 + knight_moves.index(diff)
        else:
            direction = 0
            for d in reversed(directions):
                if np.sign(diff) == np.sign(d) and diff % d == 0:
                    direction = d
                    break
            if square_rank(move.to_square) == square_rank(move.from_square):
                direction = np.sign(diff) * 1
            elif square_file(move.to_square) == square_file(move.from_square):
                direction = np.sign(diff) * 8

            distance = abs(diff / direction)
            _type = 7 * directions.index(direction) + (distance - 1)

        move_num = move.from_square * (7 * 8 + 8 + 9) + _type
        return int(move_num)
Пример #11
0
def get_moves_from_piece(pa1, pa2):
    moves_total = 0
    p1 = pa1[1]
    p2 = pa2[1]
    sq1 = pa1[0]
    sq2 = pa2[0]
    if p1.piece_type == 1:  # PAWN
        moves_total += abs(chess.square_rank(sq1) - chess.square_rank(sq2))
    elif p1.piece_type == 2:  # KNIGHT
        # TODO
        moves_total = 3  # idk for now
    elif p1.piece_type == 3:  # BISHOP
        rank_diff = abs(chess.square_rank(sq1) - chess.square_rank(sq2))
        file_diff = abs(chess.square_file(sq1) - chess.square_file(sq2))
        if not (rank_diff == 0 and file_diff == 0):  # didn't move
            if rank_diff == file_diff:
                moves_total += 1  # diagonal
            else:
                moves_total += 2  # 2 moves
    elif p1.piece_type == 4:  # ROOK
        if abs(chess.square_rank(sq1) - chess.square_rank(sq2)) != 0:
            moves_total += 1
        if abs(chess.square_file(sq1) - chess.square_file(sq2)) != 0:
            moves_total += 1
    elif p1.piece_type == 5:  # QUEEN
        if abs(chess.square_rank(sq1) - chess.square_rank(sq2)) != 0:
            moves_total += 1
        if abs(chess.square_file(sq1) - chess.square_file(sq2)) != 0:
            moves_total += 1
    elif p1.piece_type == 6:  # KING
        moves_total = chess.square_distance(sq1, sq2)
    return moves_total
Пример #12
0
    def legality(self, origin_square, target_square):
        if not self.periodic_boundaries:
            origin_chess_square = self.convert_to_chess_square(origin_square)
            target_chess_square = self.convert_to_chess_square(target_square)
            distance = chess.square_distance(origin_chess_square,
                                             target_chess_square)
            valid_piece_chess_square = self.convert_to_chess_square(
                self.board.index("K"))
            distance_to_valid_piece = chess.square_distance(
                origin_chess_square, valid_piece_chess_square)
            return distance_to_valid_piece, distance

        distance = self.distance_pbc(origin_square, target_square)
        distance_to_valid_piece = self.distance_pbc(origin_square,
                                                    self.board.index("K"))
        return distance_to_valid_piece, distance
Пример #13
0
def get_queen_move(move, color):
    return '_'.join([
        chess.SQUARE_NAMES[get_from_square(move, color)],
        QUEEN_MOVE_PREFIX,
        str(chess.square_distance(move.from_square, move.to_square)),
        get_queen_move_direction(move, color),
    ])
 def swallows_tail(self, available_squares, square):
     if ((self.is_blocked(available_squares[0]) and self.is_blocked(available_squares[2]) and square == available_squares[6]) or 
     (self.is_blocked(available_squares[2]) and self.is_blocked(available_squares[7]) and square == available_squares[3]) or 
     (self.is_blocked(available_squares[7]) and self.is_blocked(available_squares[5]) and square == available_squares[1]) or 
     (self.is_blocked(available_squares[5]) and self.is_blocked(available_squares[0]) and square == available_squares[4]) and 
     chess.square_distance(self.board.king(not self.winner()), square) == 1):
         print("Swallow's tail mate")
Пример #15
0
    def sense_update(self, sense_result):
        for result in sense_result:
            position = self.square2point(result[0])
            piece = result[1]

            if piece == None or piece.color == self.mycolor:
                self.probability_board[:, position[0], position[1]] = 0.0
            else:
                # Find most likely piece was moved to get there
                best_prob = 0.0
                best_idx = None
                for idx in self.piece_type2indices[piece.piece_type]:
                    current_posiiton = self.piece_idx2loc[idx]
                    current_posiiton = self.point2square(current_posiiton)
                    prob = self.probability_board[
                        idx, position[0],
                        position[1]] + (1 - chess.square_distance(
                            result[0], current_posiiton) / 16.0)

                    if prob >= best_prob:
                        best_prob = prob
                        best_idx = idx

                # Changed Probablility to match Sense
                self.probability_board[best_idx, :, :] = 0.0
                self.probability_board[best_idx, position[0],
                                       position[1]] = 1.0

        # Update Predict Board
        self.update_piece_location_dict()
        self.set_pieces_position(self.your_board)
Пример #16
0
    def remove_closest(self, pieces_squares, square, piece_type):
        #skip if the list of possible squares is empty
        if not pieces_squares:
            return

        min = 100
        pr = 0
        sr = chess.square_file(square)
        if piece_type is chess.PAWN:
            #print("pawn")
            new_ps = []
            for ps in pieces_squares:
                if chess.square_file(ps) is sr:
                    new_ps.append(ps)
            if new_ps:
                pieces_squares = new_ps

        for ps in pieces_squares:
            dist = chess.square_distance(ps, square)
            if dist < min:
                pr = ps
                min = dist

        self.board.remove_piece_at(pr)
        #print(pr)
        return
Пример #17
0
  def __score(self, state: State) -> int:

    h = 0 
    for piece_type in PIECE_TYPES:
      for piece_square in state.board.pieces(piece_type, state.board.turn):
        h -= square_distance(piece_square, self.enemy_king_square)
    
    return h
 def damianos_bishop_and_lollis(self, available_squares, square):
     if square == available_squares[2]:
         for defender in self.board.attackers(self.winner(), available_squares[2]):
             if chess.square_distance(self.board.king(not self.winner), defender) == 2:
                 if str(self.board.piece_at(defender)).upper() == 'B':
                     print("Damiano's bishop mate")
                 elif str(self.board.piece_at(defender)).upper() == 'P':
                     print("Lolli's mate")
    def epaulette(self, available_squares, queen_pos):
        # If the losing king is blocked by 2 pieces each on each side and the queen is 2 squares away from him
        distance_king_queen = chess.square_distance(
            self.board.king(not self.winner()), queen_pos)

        if self.is_blocked(available_squares[0]) and self.is_blocked(
                available_squares[4]) and distance_king_queen == 2:
            print('Epaulette mate')
Пример #20
0
 def tot_dis_from(board: chess.BoardT, target_sq: chess.Square) -> int:
     tot_dis = 0
     for sq in chess.SQUARES:
         pc = board.piece_at(sq)
         if pc and pc.color == board.turn:
             tot_dis += chess.square_distance(target_sq,
                                              chess.square_rank(sq))
     return tot_dis
Пример #21
0
 def _slide_move(self, board, move):
     psuedo_legal_moves = list(board.generate_pseudo_legal_moves())
     squares = list(chess.SquareSet(chess.BB_BETWEEN[move.from_square][move.to_square])) + [move.to_square]
     squares = sorted(squares, key=lambda s: chess.square_distance(s, move.from_square), reverse=True)
     for slide_square in squares:
         revised = chess.Move(move.from_square, slide_square, move.promotion)
         if revised in psuedo_legal_moves:
             return revised
     return None
 def triangle_center(self, available_squares, square):
     for defender in self.board.attackers(self.winner(), square):
         if str(self.board.piece_at(defender)).upper(
         ) == 'R' and chess.square_distance(
                 square, defender) == 2 and (defender in available_squares):
             if self.is_blocked(available_squares[1]) or self.is_blocked(
                     available_squares[3]) or self.is_blocked(
                         available_squares[4]) or self.is_blocked(
                             available_squares[6]):
                 print('Triangle mate')
Пример #23
0
def encode_queen_move(move):
    # Only need 7 distances (1,2,3,4,5,6,7) when applied to queen-type moves (no non-moves so no 0)
    distance = chess.square_distance(move.from_square, move.to_square) - 1

    file_delta = chess.square_file(move.to_square) - chess.square_file(move.from_square)
    rank_delta = chess.square_rank(move.to_square) - chess.square_rank(move.from_square)
    heading = math.atan2(file_delta, rank_delta)
    direction = round((math.degrees(heading) % 360) / 45)  # Convert heading to cardinal direction: N=0, NE=1 etc...

    return flatten_2d_coords((direction, distance), QUEEN_MOVE_SHAPE)
Пример #24
0
def is_knight_move(move):
    if chess.square_distance(move.from_square, move.to_square) == 2:
        from_rank = chess.square_rank(move.from_square)
        from_file = chess.square_file(move.from_square)
        to_rank = chess.square_rank(move.to_square)
        to_file = chess.square_file(move.to_square)

        # it's a knight move if the diff of rank or file is 1
        if abs(to_rank - from_rank) == 1 or abs(to_file - from_file) == 1:
            return True

    return False
Пример #25
0
def slide_move(board: chess.Board, move: chess.Move) -> Optional[chess.Move]:
    psuedo_legal_moves = list(board.generate_pseudo_legal_moves())
    squares = list(
        chess.SquareSet(chess.between(move.from_square,
                                      move.to_square))) + [move.to_square]
    squares = sorted(squares,
                     key=lambda s: chess.square_distance(s, move.from_square),
                     reverse=True)
    for slide_square in squares:
        revised = chess.Move(move.from_square, slide_square, move.promotion)
        if revised in psuedo_legal_moves:
            return revised
    return None
    def damianos_bishop_corner_and_lollis_corner(self, available_squares, square):
        possible_squares = [available_squares[0], available_squares[2]]

        for i in possible_squares:
            if square == i:
                for defender in self.board.attackers(self.winner(), i):
                    if chess.square_distance(self.board.king(not self.winner), defender) == 2:
                        if str(self.board.piece_at(defender)).upper() == 'B':
                            print("Damiano's bishop mate")
                        elif str(self.board.piece_at(defender)).upper() == 'P':
                            if ((chess.square_rank(square) == 6 and chess.square_rank(self.board.king(not self.winner())) == 7) or 
                            (chess.square_rank(square) == 1 and chess.square_rank(self.board.king(not self.winner())) == 0)):
                                print("Lolli's mate")
Пример #27
0
    def king_safety(self):
        w_king = self.board.king(chess.WHITE)
        b_king = self.board.king(chess.BLACK)
        w_score, b_score = 0, 0

        safe_wpawns = self.board.pieces(chess.PAWN, chess.WHITE) & safe_cols
        safe_bpawns = self.board.pieces(chess.PAWN, chess.BLACK) & safe_cols

        if len(safe_wpawns) > 0:
            distances = [
                chess.square_distance(w_king, pawn) for pawn in safe_wpawns
            ]
            distances.sort()
            w_score = sum(distances[:3])

        if len(safe_bpawns) > 0:
            distances = [
                chess.square_distance(b_king, pawn) for pawn in safe_bpawns
            ]
            distances.sort()
            b_score = sum(distances[:3])

        return 20 * -(w_score - b_score)
Пример #28
0
def smothered_mate(puzzle: Puzzle) -> bool:
    board = puzzle.game.end().board()
    king_square = board.king(not puzzle.pov)
    assert king_square is not None
    for checker_square in board.checkers():
        piece = board.piece_at(checker_square)
        assert piece
        if piece.piece_type == KNIGHT:
            for escape_square in [s for s in chess.SQUARES if square_distance(s, king_square) == 1]:
                blocker = board.piece_at(escape_square)
                if not blocker or blocker.color == puzzle.pov:
                    return False
            return True
    return False
Пример #29
0
    def get_move_from_model(self, move):
        starting_square = move // (7 * 8 + 8 + 9)
        _type = move % (7 * 8 + 8 + 9)
        promotion = None

        # Sliding move
        if _type < 56:
            direction = _type // 7
            distance = (_type % 7) + 1
            directions = [-1, 1, -7, 7, -8, 8, -9, 9]
            direction = directions[direction]
            ending_square = starting_square + distance * direction
            # Direction should be 1 if and only if the squares are on the same rank
            if ((square_rank(starting_square) == square_rank(ending_square)) !=
                (abs(direction) == 1)):
                return None
            # Direction should be 8 if and only if the squares are on the same file
            if ((square_file(starting_square) == square_file(ending_square)) !=
                    abs(direction) == 8):
                return None

            # If promoting, promote as queen
            if ((self.pawns & self.occupied_co[self.turn]
                 & BB_SQUARES[starting_square])
                    and ((self.turn and starting_square // 8 == 6) or
                         (not self.turn and starting_square // 8 == 1))):
                promotion = 5
        # Knight move
        elif _type >= 56 and _type < 64:
            knight_moves = [17, 15, 10, 6, -17, -15, -10, -6]
            ending_square = starting_square + knight_moves[_type - 56]
            if (square_distance(starting_square, ending_square) != 2):
                return None
        # Underpromotion
        else:
            _type = _type - 64
            direction = _type // 3
            promotion = (_type % 3) + 2
            directions = [7, 8, 9]
            direction = directions[direction]
            if not self.turn:
                direction *= -1
            ending_square = starting_square + direction

        if ending_square < 0 or ending_square > 63:
            return None
        else:
            return Move(starting_square, ending_square, promotion=promotion)
Пример #30
0
    def build_binary_move(self):
        '''Javascript chess gui uses binary encoding to represent moves:
        0000 0000 0000 0000 0000 0111 1111 -> From 0x7F
        0000 0000 0000 0011 1111 1000 0000 -> To >> 7, 0x7F
        0000 0000 0011 1100 0000 0000 0000 -> Captured >> 14, 0xF
        0000 0000 0100 0000 0000 0000 0000 -> EP 0x40000
        0000 0000 1000 0000 0000 0000 0000 -> Pawn Start 0x80000
        0000 1111 0000 0000 0000 0000 0000 -> Promoted Piece >> 20, 0xF
        0001 0000 0000 0000 0000 0000 0000 -> Castle 0x1000000
        This function takes moves made and converts them to binary form.
        '''
        captured_piece_binary = '0000'
        en_passant_binary = '0'
        pawn_start_binary = '0'
        promoted_binary = '0000'
        castling_binary = '0'
        white_queen = chess.Piece(piece_type=chess.QUEEN, color=chess.WHITE)
        black_queen = chess.Piece(piece_type=chess.QUEEN, color=chess.BLACK)

        if self.board.is_capture(self.uci_move):
            if self.board.is_en_passant(self.uci_move):
                captured_piece = self.board.piece_at(self.board.ep_square)
            else:
                captured_piece = self.board.piece_at(self.move_to_square)
            captured_piece_binary = bin(
                self.pieces[str(captured_piece)])[2:].zfill(4)

        if self.board.is_en_passant(self.uci_move):
            en_passant_binary = '1'

        if self.board.piece_at(self.move_from_square).piece_type == chess.PAWN:
            if chess.square_distance(self.move_from_square,
                                     self.move_to_square) == 2:
                pawn_start_binary = '1'

        if len(str(self.uci_move)) > 4:
            promoted_piece = str(self.uci_move)[4]
            if self.side == 'w':
                promoted_piece = promoted_piece.upper()
            promoted_binary = bin(self.pieces[promoted_piece])[2:].zfill(4)

        if self.board.is_castling(self.uci_move):
            castling_binary = '1'

        result = castling_binary + promoted_binary + pawn_start_binary + \
            en_passant_binary + captured_piece_binary

        return result