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')
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
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
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
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
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)
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
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
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")
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)
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
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')
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
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')
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)
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
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")
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)
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
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)
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