def get_input(self, go: Game, piece_type): self.load_dict() # print(board.n_move) # go.visualize_board() if go.count_player_stones(piece_type) <= 0: self.side = piece_type self.opponent = 1 if self.side == 2 else 2 self.cache = {} open("cache.txt", "w").close() if go.is_position_valid(2, 2, self.side, True): copy_board = copy.deepcopy(go) copy_board.next_board(2, 2, self.side, True) # print("Minimax: piece_type = {}".format(self.side), \ # "current board value = {}".format(self.total_score(copy_board, self.side))) return 2, 2 if go.is_game_finished(): return else: # score, action = self._max(board) depth = DEPTH if go.n_move > 18: depth = 24 - go.n_move elif go.n_move < 8: # return aggressive_action(go, piece_type) depth = 1 action = self.alpha_beta_cutoff_search(go, depth) copy_board = copy.deepcopy(go) if action != "PASS": # print(action) copy_board.next_board(action[0], action[1], self.side, True) # print("Minimax: piece_type = {}".format(self.side), \ # "current board value = {}".format(self.total_score(copy_board, self.side))) self.save_dict() return action # board.move(action[0], action[1], self.side)
def get_input(self, board: Game, piece_type): if board.count_player_stones(piece_type) <= 0: self.side = piece_type self.opponent = 1 if self.side == 2 else 2 if board.is_position_valid(2, 2, self.side, True): copy_board = copy.deepcopy(board) copy_board.next_board(2, 2, self.side, True) # print("Minimax_old: piece_type = {}".format(self.side), \ # "current board value = {}".format(self.total_score(copy_board, self.side))) return 2, 2 if board.is_game_finished(): return else: # score, action = self._max(board) action = self.alpha_beta_cutoff_search(board, DEPTH) if action != "PASS": copy_board = copy.deepcopy(board) copy_board.next_board(action[0], action[1], self.side, True) # print("Minimax_old: piece_type = {}".format(self.side), \ # "current board value = {}".format(self.total_score(copy_board, self.side))) return action # board.move(action[0], action[1], self.side)
def alpha_beta_cutoff_search(self, go: Game, depth=4): def max_value(board, alpha, beta, depth): state = board.state_string() if depth == 0 or board.is_game_finished(): if state in self.cache: return self.cache[state] return self.total_score(board, self.side) v_max = -numpy.inf candidates = [] for i in range(board.size): for j in range(board.size): if board.is_position_valid(i, j, self.side, test_check=True): candidates.append((i, j)) random.shuffle(candidates) if not candidates: action = "PASS" v_max = max(v_max, min_value(board, alpha, beta, depth - 1)) if v_max <= alpha: return v_max alpha = max(alpha, v_max) else: for i, j in candidates: copyBoard = copy.deepcopy(board) copyBoard.next_board(i, j, self.side, False) copyBoard.n_move += 1 v_max = max(v_max, min_value(copyBoard, alpha, beta, depth - 1)) if v_max is not None: self.cache[state] = v_max if v_max >= beta: return v_max alpha = max(alpha, v_max) return v_max def min_value(board, alpha, beta, depth): state = board.state_string() if depth == 0 or board.is_game_finished(): if state in self.cache: return self.cache[state] return self.total_score(board, self.side) v_min = numpy.inf candidates = [] for i in range(board.size): for j in range(board.size): if board.is_position_valid(i, j, self.opponent, test_check=True): candidates.append((i, j)) random.shuffle(candidates) if not candidates: action = "PASS" v_min = min(v_min, max_value(board, alpha, beta, depth - 1)) if v_min <= alpha: return v_min beta = min(beta, v_min) else: for i, j in candidates: copyBoard = copy.deepcopy(board) valid = copyBoard.next_board(i, j, self.opponent, True) copyBoard.n_move += 1 if not valid: raise ValueError("in min invalid move") v_min = min(v_min, max_value(copyBoard, alpha, beta, depth - 1)) if v_min is not None: self.cache[state] = v_min if v_min <= alpha: return v_min beta = min(beta, v_min) return v_min best_score = -numpy.inf beta = numpy.inf best_action = None candidates = [] for i in range(go.size): for j in range(go.size): if go.is_position_valid(i, j, self.side, test_check=True): candidates.append((i, j)) random.shuffle(candidates) if not candidates: best_action = "PASS" else: for i, j in candidates: copyBoard = copy.deepcopy(go) copyBoard.next_board(i, j, self.side, True) copyBoard.n_move += 1 if go.n_move < 8: value = max_value(copyBoard, best_score, beta, depth) else: value = min_value(copyBoard, best_score, beta, depth) if value > best_score: best_score = value best_action = (i, j) return best_action
count_white = 2.5 for i in range(self.size): for j in range(self.size): if board[i][j] == 1: count_black += 1 elif board[i][j] == 2: count_white += 1 if piece_type == 1: diff = count_black - count_white else: diff = count_white - count_black return diff if __name__ == "__main__": N = 5 go_game = Game(N) game_piece_type, previous_board, current_board, go_game.n_move = go_game.read_input( ) go_game.set_board(game_piece_type, previous_board, current_board) player = Minimax() if go_game.new_game: player.cache = {} open("cache.txt", "w").close() player.side = game_piece_type next_action = player.get_input(go_game, game_piece_type) go_game.n_move += 2 go_game.write_output(next_action)