def optimal_stalemate(pos1, pos2, pos3): """ Returns the least amount of goats required to stalemate the tigers and the board at the end of the game """ # Clear Board board = Board() board.place_tiger(pos1) board.place_tiger(pos2) board.place_tiger(pos3) tiger_positions = pos1, pos2, pos3 positions = board.positions for tiger_addr in tiger_positions: tiger_pos = board.get_pos(tiger_addr) tiger: Tiger = tiger_pos.piece # place goats in all positions adjacent to the tiger for adj_pos in tiger_pos.get_adjacent_positions(): if adj_pos.is_empty(): adj_pos.place_goat() # place goats in all capturing positions for capturing_addr in tiger.get_capturing_moves(): board.place_goat(capturing_addr) num_goats = board.num_pieces()[1] return num_goats, board
def edit_distance(board: Board) -> int: # Determines the edit distance between the board positions and the stalemate positions # input: board positions # return: edit distance value tigers = board.get_all_tiger_positions() numGoats = len(board.get_all_goat_positions()) _, stalemate_board = optimal_stalemate(tigers[0].address, tigers[1].address, tigers[2].address) # _, stalematePositions = stalemate(tigers[0], tigers[1], tigers[2]) possible_pos = board.get_all_addresses() # Initializing Bipartite graph B = nx.Graph() B.add_nodes_from(list(range(23)), bipartite=0) B.add_nodes_from(possible_pos, bipartite=1) # Populate graph for i, pos in enumerate(possible_pos): for stalematePos in stalemate_board.get_all_positions(): # print('DEBUG: pos ', pos, ' stalematePos ',stalematePos) # print('DEBUG: possible_pos[pos] ', boardPosition[possible_pos[pos]], ' stalematePositions[stalematePos] ', stalematePositions[stalematePos]) # print('DEBUG: pos ', possible_pos[pos], ' stalematePos ',stalematePos) # print(10 - num_moves(pos,stalematePos)) if (board.get_pos(stalematePos.address).is_goat() and stalematePos.is_goat()): # print('stalematePos',stalematePos, 'weight',10 - num_moves(possible_pos[pos],stalematePos)) B.add_edge( i, stalematePos, weight=-10 + num_moves(pos, stalematePos.address), ) # elif boardPosition[possible_pos[pos]] == stalematePositions[stalematePos] and possible_pos[pos] == stalematePos: # B.add_edge(pos,stalematePos, weight = -1e20) else: B.add_edge(i, stalematePos.address, weight=1e20) # Bipartite Max Matching # print(B.edges(data=True)) maxMatching = bipartite.minimum_weight_full_matching(B) # print(maxMatching) Sum = 0 # Collect sum of weights n = 0 for key, item in maxMatching.items(): if n == 23: break # # print(B.get_edge_data(key,item)['weight']) if board.get_pos(possible_pos[key]).is_goat(): Sum = Sum + num_moves(possible_pos[key], item) # print(Sum) n = n + 1 return Sum
def get_optimal_stalemate(pos1: str, pos2: str, pos3: str) -> Board: """ Returns the least amount of goats required to stalemate the tigers and the board at the end of the game """ # create a new board board = Board() # start by placing the three tigers board.place_tiger(pos1) board.place_tiger(pos2) board.place_tiger(pos3) tigers = board.get_all_tigers() positions = board.positions # first pass: place goats in all positions adjacent to the tigers for tiger in tigers: # place goats in all positions adjacent to the tiger for adj_pos in tiger.pos.get_adjacent_positions(): if adj_pos.is_empty(): adj_pos.place_goat() # second pass: place goats to block all capturing moves for tiger in tigers: # place goats in all capturing positions for capturing_addr in tiger.get_capturing_moves(): board.place_goat(capturing_addr) return board
def compute_tiger_move(board: Board) -> Optional[tuple]: """Compute a move as the Tiger. If a move was found, a tuple is returned containing the start and end positions if a piece needs to be moved, or a tuple containing a position if a piece needs to be placed. """ # Randomize tiger positions tiger_list = board.get_all_tiger_positions() if len(tiger_list) < 3: # place tigers empty_list = board.get_all_empty_positions() empty_pos_choice = random.choice(empty_list) return (empty_pos_choice.address, ) else: # move tiger if len(board.get_tiger_possible_moves()) == 0: return None # cannot do a move move_choice = None # try to find a capturing move first # XXX: makes it difficult for CPU goats to win # for tiger_pos in tiger_list: # capturing_moves = tiger_pos.piece.get_capturing_moves() # if capturing_moves: # tiger_pos_choice = tiger_pos # move_choice = random.choice(capturing_moves) # break # find a random move while move_choice is None: tiger_pos_choice = random.choice(tiger_list) valid_moves = tiger_pos_choice.piece.get_valid_moves() if valid_moves: move_choice = random.choice(valid_moves) return (tiger_pos_choice.address, move_choice)
fontSize = 15 buttonStyle = 30 elif platform == "win32" or platform == "cygwin": # Windows boardSize = 500 fontSize = 12 buttonStyle = 0 elif platform == "linux": # Linux boardSize = 500 fontSize = 12 buttonStyle = 0 boardSize = 500 board = Board() board.clear() possible_pos = [ "a1", "a2", "a3", "b0", "b1", "b2", "b3", "b4", "c1", "c2", "c3", "c4",
def compute_goat_move(board: Board) -> Optional[tuple]: """Compute a move as the Goat. If a move was found, a tuple is returned containing the start and end positions if a piece needs to be moved, or a tuple containing a position if a piece needs to be placed. """ # list of goats that are about to be captured danger_goats = board.get_tiger_capturing_moves() goat_list = board.get_all_goat_positions() tiger_list = board.get_all_tiger_positions() if len(tiger_list) < 3: # skip this turn, wait until all tigers are placed return None elif not board.is_all_goats_placed: # place a goat # ------------ if danger_goats: # choose a position that saves a goat landing_pos, goat_pos = random.choice(danger_goats) pos_choice = landing_pos else: # try to choose a position that blocks a tiger pos_choice = None empty_list = board.get_all_empty_positions() for pos in empty_list: if board.is_pos_blocking(pos.address) and board.is_pos_safe( pos.address): pos_choice = pos break # if cannot find a blocking move, choose a random position if pos_choice is None: pos_choice = random.choice(empty_list) if pos_choice: return (pos_choice.address, ) else: return None else: # move goat # --------- goat_pos_choice = None move_choice = None if danger_goats: # try to move the goat in danger somewhere else landing_pos, goat_pos = random.choice(danger_goats) goat_pos_choice = goat_pos move_choice = random.choice(goat_pos.piece.get_valid_moves()) else: # try to find a safe move for goat_pos in goat_list: # this goat is blocking a tiger, try to find another one if board.is_pos_blocking(goat_pos.address): continue for move in goat_pos.piece.get_valid_moves(): if board.is_pos_safe(move): goat_pos_choice = goat_pos move_choice = move break # if couldn't find a goat yet, pick one at random if goat_pos_choice is None: goat_pos_choice = random.choice(goat_list) # if couldn't find a move yet, pick one at random if move_choice is None: valid_moves = goat_pos_choice.piece.get_valid_moves() if valid_moves: move_choice = random.choice(valid_moves) if move_choice: return (goat_pos_choice.address, move_choice) else: return None