def run_games(self, generations): for generation in range(generations): print(f"Generation: {generation}") if generation == 0: self.genes = np.random.normal(0,1,(self.count, self.gene_size)) else: # selection new_genes = np.zeros((self.count, self.gene_size)) best_genes = self.get_best() new_genes[:len(best_genes)] = best_genes for i in range(len(best_genes), self.count): new_genes[i] = self.create() self.genes = new_genes self.fitness = np.zeros(self.count) # crossover self.players = [Negamax(self.depth, scoring=self.scoring(gene), tt=TT()) for gene in self.genes] num_games = self.count * self.count game_count = 0 for i, gene1 in enumerate(self.genes): for j, gene2 in enumerate(self.genes): if game_count % 100 == 0: self.tt.tofile(self.tt_file_name) print(f"Played game: {game_count} / {num_games}") game_count += 1 if i == j: continue result = self.game(self.players[i],self.players[j]) if result == 0: self.fitness[i] += 0.5 self.fitness[j] += 0.5 if result == 1: self.fitness[i] += 1 if result == 2: self.fitness[j] += 1 self.prob = self.fitness / self.fitness.sum() idx = np.argmax(self.prob) best_gene = self.genes[idx] print(f"Best player: {best_gene}") print(f"Best fitness: {np.max(self.fitness)/(2*(self.count - 1))}") negamax = Negamax(self.depth, tt=TT()) negamax_best = self.players[idx] score1 = self.game(negamax, negamax_best) print(f"When normal Negamax started: {score1}") score2 = self.game(negamax_best, negamax) print(f"When best player started: {score2}")
def __init__(self, depth, size, tt_file_name=None, count=1, mutation_rate=1e-2, best_percent=0.2, gene_size=7): self.count = count self.genes = None self.mutation_rate = mutation_rate self.best_percent = best_percent self.depth = depth self.size = size # Board size self.gene_size = gene_size self.tt_file_name = tt_file_name try: self.tt = TT.fromfile(self.tt_file_name) print("Loaded TT") except Exception as e: print("TT could not be found in memory") self.tt = TT()
def play_game_transposition_table(): ai_algo = Negamax(5, tt=TT()) game = Gomoku_optimized([Human_Player(), AI_Player(ai_algo)], 5) game.play() if game.lose(): print("Player %d wins!" % game.nopponent) else: print("Draw!")
def play_game_transposition_table(size=6): ai_algo = Negamax(4, tt=TT()) game = Gomoku_Strategic([Human_Player(), AI_Player(ai_algo)], size) game.play() if game.lose(): print("Player %d wins!" % game.nopponent) else: print("Draw!")
def create_players(parser): commands = parser.add_subparsers(title='sub-commands') parser.add_argument('--size', type=int) parser.add_argument('--wall_dist', type=str) for i in range(2): sub_parser = commands.add_parser(f'player{i+1}') sub_parser.add_argument('--type') sub_parser.add_argument('--depth', type=int) sub_parser.add_argument('--iterations', type=int) sub_parser.add_argument('--time_limit', type=int) sub_parser.add_argument('--tt', type=bool) sub_parser.add_argument('--n_playout', type=int) args = parse_args(parser, commands) players = [None] * 2 args = vars(args) for i in range(2): args_player = args[f'player{i+1}'] args_player = vars(args_player) player_type = args_player.pop("type") args_player = {k: v for k, v in args_player.items() if v is not None} if "tt" in args_player: args_player.pop("tt") player = players_dict[player_type](win_score=1000, tt=TT(), **args_player) else: player = players_dict[player_type](win_score=1000, **args_player) players[i] = player wall_dist = [int(x) for x in args['wall_dist'].split(",") ] if args['wall_dist'] else [100, 100] return Game(args['size'], wall_dist=wall_dist), players
def create_negamax_tt(depth): ai_algo_neg = Negamax(depth, tt=TT()) return create_benchmark_game(ai_algo_neg)
def create_dual_tt(depth): ai_algo_dual = DUAL(depth, tt=TT()) return create_benchmark_game(ai_algo_dual)
{{ttt.spot_string(j, i)}} </button> </td> {% endfor %} </tr> {% endfor %} </table> <button type="submit" name="reset">Start Over</button> </form> </body> </html> ''' app = Flask(__name__) # ai_algo = Negamax(2 ) ai_algo = Negamax(3, tt = TT()) width = 15 @app.route("/", methods=['GET', 'POST']) def play_game(): global ttt reset = False if "choice" in request.form: req = (request.form["choice"].split(',')) coord = [ int(req[0]), int(req[1])] ttt.play_move(coord) if not ttt.is_over2(): ai_move = ttt.get_move() ttt.play_move(ai_move) if "reset" in request.form: ttt.hboard = tuple(np.zeros((width, width), np.int8)) ttt.htob()
table1 = np.zeros((5,5)) table2 = np.zeros((5,5)) table3 = np.zeros((5,5)) # NOTICE THE SIZES!!!! players_list = [] for i in range(MAX_DEPTH): # try: # str = f'TT_folder/size{SIZE}/TT_depth{i + 1}/wall_score_0.0.data' # print(str) # tt_loaded = TT.fromfile(str) # players_list.append(Negamax(i + 1, tt=tt_loaded)) # print("loaded") # except Exception as x: # print(f"i dont have depth {i + 1} in memory") players_list.append(Negamax(i + 1, tt=TT())) print("NO WALL RESTRICTION!!! DONT USE TT ") for size in [5]: for depth1 in depths[size]: for depth2 in depths[size]: wins_white = 0 draws = 0 for i in range(TOTAL_GAMES): players = [players_list[depth1 - 1], players_list[depth2 - 1]] game = Game(size, wall_dist=[100, 100]) moves = [] index = 0
from easyAI import Human_Player, AI_Player, Negamax from easyAI import TwoPlayersGame, Human_Player, AI_Player, DUAL from negamax import Negamax from pprint import pprint from flask import Flask, render_template_string, request, make_response from ai_negamax_faster import GomokuGame from easyAI import TT ai = Negamax(7, tt=TT()) game = GomokuGame([AI_Player(ai), Human_Player()], 15, 1) import cProfile cProfile.run("game.play(1)")
import sys sys.path.insert(0, '..') from quoridor.game import Game from mcts.mcts_pure import MCTSPlayer from easyAI import Negamax, TT from tqdm import tqdm n_games = 10 tt = TT() offset = 100 max_exp = 10 depth = 3 def f(offset, max_exp): if max_exp == 0: return offset for i in range(max_exp + 1): n_playout = offset + 2**i print(f"Number of playouts {n_playout}") draws = 0 wins = [0, 0] player1 = MCTSPlayer(n_playout=n_playout, win_score=100) player2 = Negamax(depth=depth, tt=tt) players = [player1, player2] game = Game(9) while not game.is_terminal():
def __init__(self, timeout=5, name='AI_iterative'): self.name = name self.move = {} self.tt = TT() self.timeout = timeout
depth = 4 NUM_PLAYERS = 30 SIZE = 5 NUM_GAMES_EACH = 1 # has to be odd number MIN_WALL_SCORE_BOUND = 1 MAX_WALL_SCORE_BOUND = 2 players_list = [] wall_scores = np.linspace(MIN_WALL_SCORE_BOUND, MAX_WALL_SCORE_BOUND, NUM_PLAYERS) player_scores = [0] * NUM_PLAYERS for i in range(NUM_PLAYERS): try: str = f'TT_folder/size5/TT_depth{depth}/wall_score_{wall_scores[i]}.data' tt_loaded = TT.fromfile(str) players_list.append(Negamax(depth, tt=tt_loaded)) print("loaded") except Exception as x: print(f"i dont have {wall_scores[i]} in memory") players_list.append(Negamax(depth, tt=TT())) start_time = time.time() #score_func consideres both player1 and player2!!! not only one player for i1, player1 in enumerate(players_list): for i2, player2 in enumerate(players_list): if player1 == player2: continue curr_time = time.time() players = [players_list[i1], players_list[i2]] for j in range(NUM_GAMES_EACH):
def solve_game(): tt = TT() r, d, m = id_solve(Gomoku_Strategic, range(2, 7), win_score=100, tt=tt) print r, d, m
@author: Junxiao Song """ import sys sys.path.insert(0, '..') import numpy as np import copy from operator import itemgetter from quoridor.game import Game from tqdm import tqdm from easyAI import Negamax, TT from scipy.special import softmax import random # negamax = Negamax(depth=1, tt=TT(), win_score=100) saved_games = {} negamax = Negamax(depth=1, tt=TT()) def rollout_policy_fn(game): # """a coarse, fast version of policy_fn used in the rollout phase.""" # return negamax(game) return min(game.availables, key=lambda move: game.move_score(move)) # def rollout_policy_fn(game): # """a coarse, fast version of policy_fn used in the rollout phase.""" # # rollout randomly # return random.choice(game.availables) def policy_value_fn(game): """a function that takes in a game and outputs a list of (action, probability) tuples and a score for the game""" # return uniform probabilities and 0 score for pure MCTS # action_probs = np.ones(len(game.availables))/len(game.availables)
# Constants. Notice that they are low. depth = 4 NUM_PLAYERS = 5 SIZE = 5 NUM_GAMES_EACH = 1 # has to be odd number MIN_WALL_SCORE_BOUND = 0 MAX_WALL_SCORE_BOUND = 3 players_list = [] wall_scores = np.linspace(MIN_WALL_SCORE_BOUND, MAX_WALL_SCORE_BOUND, NUM_PLAYERS) player_scores = [0] * NUM_PLAYERS for _ in range(NUM_PLAYERS): players_list.append(Negamax(depth, tt=TT())) #score_func consideres both player1 and player2!!! not only one player for i1, player1 in enumerate(players_list): for i2, player2 in enumerate(players_list): if player1 == player2 or i2 <= i1: continue curr_time = time.time() players = [players_list[i1], players_list[i2]] for j in range(NUM_GAMES_EACH): game = Game(SIZE, wall_scores=[wall_scores[i1], wall_scores[i2]]) moves = [] index = 0 while not game.is_terminal() and len(moves) < SIZE * 15: move = players[index](game)
import argparse from datetime import datetime import json import numpy as np import create from easyAI import Negamax, TT # Constants. Notice that they are low. DEPTH1 = 1 DEPTH2 = 3 SIZE = 5 NUM_GAMES_EACH = 45 # has to be odd number WALL_SCORE = 0 # NOTICE THAT!!!!!!!!!!!!!!!!!!!!!! players_list_no_shuffle = [ Negamax(i + 1, tt=TT(), shuffle=False) for i in range(5) ] players_list_yes_shuffle = [ Negamax(i + 1, tt=TT(), shuffle=True) for i in range(5) ] for depth1 in [1, 2, 3, 4, 5]: for depth2 in [1, 2, 3, 4, 5]: white_wins = 0 draws = 0 curr_time = time.time() players = [ players_list_no_shuffle[depth1 - 1], players_list_yes_shuffle[depth2 - 1] ]
def create_sss_tt(depth): ai_algo_sss = SSS(depth, tt=TT()) return create_benchmark_game(ai_algo_sss)
DEPTH = 1 SIZE = 5 player = create.Human() pop = Population(DEPTH, SIZE) #gene = [1.53276322, -0.31481973, 0.91032865, 0.10268689, 0.41397708, 0.93256447, 0.067119] #gene = [2.17708616, 0.14143157, -0.39465167, 2.45134455, -1.29809957, 1.35924934, 0.1645196] #gene = [ 2.17708616, 0.14143157, -0.39465167, 2.45134455, -1.29809957, -0.00416553, -0.38419192] # gene = [2.17708616, 0.44166281, -0.39465167, 0.65901557, -1.29809957, -0.00416553, -0.38419192] #gene = [ 2.17708616, 0.14143157, -0.39465167, 0.70410026, -1.29809957, -0.00416553, -0.38419192] gene = [ 2.17708616, -1.0604653, -1.29051458, 0.70410026, -1.29809957, -0.00416553, -0.38419192 ] negamax_good = Negamax(depth=DEPTH, scoring=pop.scoring(gene), tt=TT()) gene = [1, 0, 0, 0, 0, 0, 0] negamax_bad = Negamax(depth=3, scoring=pop.scoring(gene), tt=TT()) def main(size, game, players): root = tk.Tk() GUI(root, game, players) root.mainloop() if __name__ == '__main__': game = Game(SIZE) #main(SIZE, game, [negamax_good, negamax_bad]) main(SIZE, game, [Negamax(depth=1, tt=TT()), Negamax(depth=3, tt=TT())])
class Population: def __init__(self, depth, size, tt_file_name=None, count=1, mutation_rate=1e-2, best_percent=0.2, gene_size=7): self.count = count self.genes = None self.mutation_rate = mutation_rate self.best_percent = best_percent self.depth = depth self.size = size # Board size self.gene_size = gene_size self.tt_file_name = tt_file_name try: self.tt = TT.fromfile(self.tt_file_name) print("Loaded TT") except Exception as e: print("TT could not be found in memory") self.tt = TT() def calculate(self, game): average_degrees = self.average_degrees(game) # + jump = self.jump(game) # + center = self.center(game) # 0 side = self.side(game) # + wall = self.wall(game) # + dist_player = self.dist_between_players(game) # - dist = self.distance(game) # + # [ 2.17708616, 0.14143157, -0.39465167, 2.45134455, -1.29809957, -0.00416553, -0.38419192] return np.array([dist, wall, jump, side, average_degrees, center, dist_player])[:self.gene_size] def walking_moves(self, game): return len(game.available_cells()) def average_degrees(self, game): # average of possible walking moves moves = list(game.available_cells()) sum_degrees = 0 for cell in moves: sum_degrees += game.graph.degree(tuple(cell)) return sum_degrees/len(moves) def jump(self, game): for cell in game.available_cells(): if game.distance(game.index, cell) == 2: return 1 return 0 def center(self, game): CENTER = np.array([game.size // 2, game.size // 2]) d1 = game.distance(game.index, CENTER) d2 = game.distance(1 - game.index, CENTER) return (d1 - d2) def side(self, game): score = 0 if abs(game.players_loc[game.index][1] - game.end_loc[game.index]) <= game.size // 2: score += 1 if abs(game.players_loc[1 - game.index][1] - game.end_loc[1 - game.index]) <= game.size // 2: score -= 1 return score def wall(self, game): return game.wall_counts[game.index] - game.wall_counts[1 - game.index] def dist_between_players(self, game): locs = game.players_loc p0_loc = locs[game.index] p1_loc = locs[1 - game.index] return np.abs(p0_loc-p1_loc).sum() def distance(self, game): con1 = nx.node_connected_component(game.graph, tuple(game.players_loc[0])) con1 = filter(lambda x: x[1] == game.size - 1, con1) d1 = min(nx.shortest_path_length(game.graph, tuple(game.players_loc[0]), node) for node in con1) con2 = nx.node_connected_component(game.graph, tuple(game.players_loc[1])) con2 = filter(lambda x: x[1] == 0, con2) d2 = min(nx.shortest_path_length(game.graph, tuple(game.players_loc[1]), node) for node in con2) distance_score = d2 - d1 if game.index == 0: return distance_score else: return -distance_score def scoring(self, gene): def gene_scoring(game): if game.players_loc[0][1] == game.size - 1: if game.index == 0: return 1000 else: return -1000 if game.players_loc[1][1] == 0: if game.index == 0: return -1000 else: return 1000 lookup = self.tt.lookup(game) if lookup is None: score = self.calculate(game) self.tt.store(game=game, score=score) return score @ gene return lookup['score'] @ gene return gene_scoring def mutate(self, gene): new_gene = gene.copy() for i in range(self.gene_size): if np.random.random() > 1 - self.mutation_rate: new_gene[i] = np.random.normal(0, 1) return new_gene def crossover(self, i, j): fit1 = self.fitness[i] fit2 = self.fitness[j] gene1 = self.genes[i] gene2 = self.genes[j] fit = (fit1 + 1e-3) / (fit1 + fit2 + 2e-3) chosen = np.random.choice(2, self.gene_size, p=[fit, 1-fit]) new_gene = np.zeros(self.gene_size) new_gene[chosen == 0] = gene1[chosen == 0] new_gene[chosen == 1] = gene2[chosen == 1] return new_gene def calculate_fitnesses(self): pass def create(self): a = self.selection() b = self.selection() return self.mutate(self.crossover(a,b)) def get_best(self): best_idx = np.argsort(self.prob)[int(-self.best_percent * len(self.prob)):] return self.genes[best_idx] def selection(self): return np.random.choice(a=range(self.count), p=self.prob) def game(self, player1, player2): players = [player1, player2] game = Game(self.size) moves = [] index = 0 while not game.is_terminal() and len(moves) < self.size*50: move = players[index](game) end = time.time() game.play_game(*move) moves.append(move) index = 1 - index if len(moves) == self.size*50: return 0 if index == 1: return 1 else: return 2 def run_games(self, generations): for generation in range(generations): print(f"Generation: {generation}") if generation == 0: self.genes = np.random.normal(0,1,(self.count, self.gene_size)) else: # selection new_genes = np.zeros((self.count, self.gene_size)) best_genes = self.get_best() new_genes[:len(best_genes)] = best_genes for i in range(len(best_genes), self.count): new_genes[i] = self.create() self.genes = new_genes self.fitness = np.zeros(self.count) # crossover self.players = [Negamax(self.depth, scoring=self.scoring(gene), tt=TT()) for gene in self.genes] num_games = self.count * self.count game_count = 0 for i, gene1 in enumerate(self.genes): for j, gene2 in enumerate(self.genes): if game_count % 100 == 0: self.tt.tofile(self.tt_file_name) print(f"Played game: {game_count} / {num_games}") game_count += 1 if i == j: continue result = self.game(self.players[i],self.players[j]) if result == 0: self.fitness[i] += 0.5 self.fitness[j] += 0.5 if result == 1: self.fitness[i] += 1 if result == 2: self.fitness[j] += 1 self.prob = self.fitness / self.fitness.sum() idx = np.argmax(self.prob) best_gene = self.genes[idx] print(f"Best player: {best_gene}") print(f"Best fitness: {np.max(self.fitness)/(2*(self.count - 1))}") negamax = Negamax(self.depth, tt=TT()) negamax_best = self.players[idx] score1 = self.game(negamax, negamax_best) print(f"When normal Negamax started: {score1}") score2 = self.game(negamax_best, negamax) print(f"When best player started: {score2}")
import numpy as np import create from easyAI import Negamax, TT # Constants. Notice that they are low. DEPTH1 = 1 DEPTH2 = 3 SIZE = 5 NUM_GAMES_EACH = 30 # has to be odd number WALL_SCORE = 0 players_list_no_shuffle = [] players_list_yes_shuffle = [] for i in range(5): players_list_no_shuffle.append(Negamax(i+1, tt=TT(), shuffle=False)) players_list_yes_shuffle.append(Negamax(i+1, tt=TT(), shuffle=True)) for depth1 in [1,2,3,4,5]: for depth2 in [1,2,3,4,5]: white_wins = 0 draws = 0 curr_time = time.time() player1 = players_list_no_shuffle[depth1 - 1] player2 = players_list_yes_shuffle[depth2 - 1] players = [player1, player2] for _ in range(NUM_GAMES_EACH):
def solve_game_df(): # to run this method we need to modify the max score to 100(check with self.win()) ai_algo = Negamax(10, tt=TT()) game = Gomoku_Strategic([Human_Player(), AI_Player(ai_algo)], 5) result = df_solve(game, win_score=100, maxdepth=10, tt=TT(), depth=0) print result
def solve_game_df(): ai_algo = Negamax(10, tt=TT()) game = Gomoku_optimized([Human_Player(), AI_Player(ai_algo)], 5) result = df_solve(game, win_score=100, maxdepth=10, tt=TT(), depth=0) print result
players_list = [] wall_scores = np.linspace(MIN_WALL_SCORE_BOUND, MAX_WALL_SCORE_BOUND, NUM_PLAYERS) player_scores = [0] * NUM_PLAYERS for i in range(NUM_PLAYERS): players_list.append(Negamax(DEPTH1)) #score_func consideres both player1 and player2!!! not only one player for i1, player1 in enumerate(players_list): for i2, player2 in enumerate(players_list): if player1 == player2 or i2 <= i1: continue curr_time = time.time() players = [Negamax(DEPTH1, tt=TT()), Negamax(DEPTH1, tt=TT())] for j in range(NUM_GAMES_EACH): game = Game(SIZE, wall_scores[i1], wall_scores[i2]) moves = [] index = 0 while not game.is_terminal() and len(moves) < SIZE * 15: move = players[index](game) game.play_game(*move) moves.append(move) index = 1 - index if index == 1: player_scores[i1] += 1 else: player_scores[i2] += 1
def solve_game(): tt = TT() r, d, m = id_solve(Gomoku_optimized, range(2, 20), win_score=100, tt=tt) print r, d, m
def solve_game(): #to run this method we need to modify the max score to 100(check with self.win()) tt = TT() r, d, m = id_solve(Gomoku_Strategic, range(2, 20), win_score=100, tt=tt) print r, d, m