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