def next_move_min_max(self, max_depth): v = float('-inf') best_move = (-1, -1) if len(self.available_moves) > 0: # se existe algum movimento possivel for i, move in enumerate(self.available_moves): # para cada movimento disponivel with MonitorPerformance(False,"evaluating move " + str(i) + "/" + str(len(self.available_moves))): imaginary_board = board.from_string(str(self.board)) # cria um tabuleiro "imaginario" score = self.min_max_max(imaginary_board, max_depth) if v < score: v = score best_move = move self.show_move_result(best_move) return best_move
def alfa_beta_max(self, a_board, alfa, beta, max_depth): if (len(a_board.legal_moves(self.my_color)) > 0) \ and (max_depth > 0) \ and (perf_counter_ns() - self.start_time) < self.max_time: depth = max_depth - 1 for move in a_board.legal_moves(self.my_color): imaginary_board = board.from_string(str(a_board)) imaginary_board.process_move(move, self.my_color) self.node_expands_counter += 1 v = self.alfa_beta_min(imaginary_board, alfa, beta, depth) alfa = max(v, alfa) if beta < alfa: self.pruning_counter += 1 return alfa return alfa else: score = self.__get_board_score(a_board) return score
def min_value(the_board, color, alpha, beta, start_time, remaining_depth): opponent_color = the_board.opponent(color) current_legal_moves = the_board.legal_moves(color) debugPrint(f'[MIN] Current legal moves: { current_legal_moves }') if len(current_legal_moves) == 0: debugPrint('[MIN] Stopping because found no further possible moves') return utility(the_board, opponent_color), INVALID_MOVE best_move = current_legal_moves[0] if time.time() - start_time >= MAX_RUN_TIME: debugPrint('[MAX] Stopping because time is up') debugPrint(f" Depth was: { remaining_depth }") return utility(the_board, opponent_color), best_move if remaining_depth == 0: debugPrint('[MAX] Stopping because reach MAX_DEPTH') return utility(the_board, opponent_color), best_move min_max_value = INFINITY for s in current_legal_moves: other_board = board.from_string(str(the_board)) other_board.process_move(s, color) max_val = max_value(other_board, opponent_color, alpha, beta, start_time, remaining_depth - 1)[0] debugPrint(f'[MIN] MaxVal { max_val }') if max_val < min_max_value: debugPrint(f'[MIN] Found better move { s }') min_max_value = max_val best_move = s if min_max_value < beta: debugPrint(f'[MIN] Found better beta { s }') beta = max_val if beta <= alpha: debugPrint('[MIN] Alpha-beta pruned') return min_max_value, best_move return min_max_value, best_move
def next_move(self, human_player=False): v = float('-inf') best_move = None if len(self.available_moves) > 0: # se existe algum movimento possivel for i, move in enumerate(self.available_moves): # para cada movimento disponivel imaginary_board = board.from_string(str(self.board)) # cria um tabuleiro "imaginario" score = self.min_max_max(imaginary_board) self.__append_to_console_out(i, move, score) if v < score: v = score best_move = move selected_move = self.get_selected_move(best_move, human_player, v) selected_move = self.execute_move(selected_move) return selected_move
def get_ordered_best_moves_for_player(self, a_board): best_moves = [] heapq.heapify(best_moves) for move in a_board.legal_moves(self.my_color): imaginary_board = board.from_string(str(a_board)) imaginary_board.process_move(move, self.my_color) score = self.__get_board_score(imaginary_board) move_score = MoveScore(move, (-1 * score), self.my_color) heapq.heappush(best_moves, move_score) # score invertido para ordenar pelo de maior valor ;) ordered_moves = [] while len(best_moves) > 0: best_move = heapq.heappop(best_moves) ordered_moves.append(best_move.get_move()) return ordered_moves
def min_max_min(self, a_board, max_depth): # se existe algum movimento possivel do oponente if (len(a_board.legal_moves(self.opponent_color)) > 0) and (max_depth > 0): depth = max_depth - 1 v = float('+inf') for opponent_move in a_board.legal_moves(self.opponent_color): # para cada movimento disponivel do oponente imaginary_board = board.from_string(str(a_board)) imaginary_board.process_move(opponent_move, self.opponent_color) # executa o movimento #imaginary_board.print_board() score = self.min_max_max(imaginary_board, depth) v = min(v, score) return v else: score = self.__get_board_score(a_board) return score
def get_ordered_best_moves_for_oponent(self, a_board): best_moves = [] heapq.heapify(best_moves) for move in a_board.legal_moves(self.opponent_color): imaginary_board = board.from_string(str(a_board)) imaginary_board.process_move(move, self.opponent_color) score = self.__get_board_score(imaginary_board) move_score = MoveScore(move, score, self.opponent_color) heapq.heappush(best_moves, move_score) # o heap vai ordenar pelo menor valor ordered_moves = [] # o melhor movimento do oponente é o que ao jogador menos pontos while len(best_moves) > 0: best_move = heapq.heappop(best_moves) ordered_moves.append(best_move.get_move()) return ordered_moves
def alfa_beta_min(self, a_board, alfa, beta, max_depth): if (len(a_board.legal_moves(self.opponent_color)) > 0) \ and (max_depth > 0) \ and (perf_counter_ns() - self.start_time) < self.max_time: depth = max_depth - 1 for move in a_board.legal_moves(self.opponent_color): imaginary_board = board.from_string(str(a_board)) imaginary_board.process_move(move, self.opponent_color) self.node_expands_counter += 1 v = self.alfa_beta_max(imaginary_board, alfa, beta, depth) beta = min(v, beta) if alfa >= beta: self.pruning_counter += 1 return beta return beta else: score = self.__get_board_score( a_board) # Retorna o valor do ultimo nó expandido return score
def alfa_beta_max(self, a_board, alfa, beta, max_depth): if (len(a_board.legal_moves(self.my_color)) > 0) and (max_depth > 0): depth = max_depth - 1 #for move in self.get_ordered_best_moves_for_oponent(a_board): #for move in self.get_ordered_best_moves_for_player(a_board): #for i, move in enumerate(a_board.legal_moves(self.my_color)): for move in a_board.legal_moves(self.my_color): imaginary_board = board.from_string(str(a_board)) imaginary_board.process_move(move, self.my_color) self.node_expands_counter += 1 v = self.alfa_beta_min(imaginary_board, alfa, beta, depth) alfa = max(v, alfa) if beta < alfa: self.pruning_counter += 1 #print("Nós podados na profundidade [" + str(max_depth) + "]=" + str(len(a_board.legal_moves(self.my_color)) - i) + " - MAX") return alfa return alfa else: score = self.__get_board_score(a_board) return score
def max_value(the_board, color, alpha, beta, start_time, remaining_depth): current_legal_moves = the_board.legal_moves(color) debugPrint(f'[MAX] Current legal moves: { current_legal_moves }') if len(current_legal_moves) == 0: debugPrint('[MAX] Stopping because found no further possible moves') return utility(the_board, color), INVALID_MOVE best_move = current_legal_moves[0] best_score = -INFINITY if time.time() - start_time >= MAX_RUN_TIME: debugPrint('[MAX] Stopping because time is up') return utility(the_board, color), best_move if remaining_depth == 0: debugPrint('[MAX] Stopping because reach MAX_DEPTH') return utility(the_board, color), best_move for s in current_legal_moves: other_board = board.from_string(str(the_board)) other_board.process_move(s, color) min_val = min_value(other_board, the_board.opponent(color), alpha, beta, start_time, remaining_depth - 1)[0] debugPrint(f'[MAX] MinVal { min_val }') if min_val > best_score: debugPrint(f'[MAX] Found better move { s }') best_score = min_val best_move = s if best_score >= beta: debugPrint('[MAX] Alpha-beta pruned') return best_score, best_move alpha = max(alpha, best_score) return best_score, best_move
def next_move_alfa_beta(self, max_depth): alfa = float('-inf') beta = float('+inf') v = float('-inf') best_move = (-1, -1) if len(self.available_moves) > 0: # se existe algum movimento possivel for move in self.available_moves: # para cada movimento disponivel imaginary_board = board.from_string(str( self.board)) # cria um tabuleiro "imaginario" score = self.alfa_beta_max(imaginary_board, alfa, beta, max_depth) #score += self.move_eval(imaginary_board, move) if score > v: v = score best_move = move self.show_move_result(best_move) return best_move