def knockoutScenario(plrs, FOLDER): # 屏蔽AI自带print class null_stream: def read(*args): pass def write(*args): pass def flush(*args): pass sys.stdout = null_stream # 设置比赛参数 GAMES = 10 # 作为先后手各比赛场数,总场次 2 * GAMES HALFWIDTH, HEIGHT, TIMELIMIT, ROUNDSPERGAME = 51, 101, 30, 2000 CLEAR = 'cls' if platform.system() == 'Windows' else 'clear' # 设置清屏指令 # 创建赛程 name1, func1, name2, func2 = plrs[0][0], plrs[0][1], plrs[1][0], plrs[1][1] # 图形化计分表,比赛结果统计表 x = PrettyTable([' # ', ' Endgame Winner ', ' Game State ', ' Rmk ']) pairResult = [0, 0] # 图形化计分表与比赛结果统计表绘图工具 def outputer(match_result, i, GAMES, pairResult, name1, name2, x): # 统计胜方 gameResult = match_result['result'] gameWinner = gameResult[0] if gameWinner == None: winner = 'None' elif i <= GAMES: # 前 GAMES 局 if gameWinner == 0: pairResult[0] += 1 winner = '(A) ' + name1 elif gameWinner == 1: pairResult[1] += 1 winner = '(B) ' + name2 else: # 后 GAMES 局 if gameWinner == 1: pairResult[0] += 1 winner = '(B) ' + name1 elif gameWinner == 0: pairResult[1] += 1 winner = '(A) ' + name2 # 即时比赛结果的输出文字内容准备 flag = gameResult[1] state = 'KO' if abs(flag) == 3: state = str(gameResult[2]) flag = flag + 3 rmklst = ['END', 'OVT', 'ERR', 'WAL', 'TAP', 'SID', 'FAC', 'CIT'] gameRounds = len(match_result['log']) - 1 x.add_row(['%2d'%i, winner, state, rmklst[flag] + ', %4d'%gameRounds]) # 更新即时比赛结果 os.system(CLEAR) print( name1, ' ' * (21 - len(name1)), '%2d' % pairResult[0], ': ', '%2d' % pairResult[1], ' ' * (23 - len(name2)), name2, file=sys.__stdout__) print(x, file=sys.__stdout__) # 初始化存储空间 storageAB, storageBA = [{}, {}], [{}, {}] for match_core.STORAGE in storageAB, storageBA: for i in range(2): try: exec('func%d.init(match_core.STORAGE[%d])' % (i+1, i)) except: pass storageBA = storageBA[::-1] # 根据赛程比赛 # A vs B 顺序存储空间,先赛GAMES局 for i in range(1, 1+GAMES): match_core.STORAGE = storageAB match_result = match((func1, func2), (name1, name2), HALFWIDTH, HEIGHT, ROUNDSPERGAME, TIMELIMIT) log_name = '%s/log/%s-VS-%s(%s).zlog' % (FOLDER, name1, name2, i) save_match_log(match_result, log_name) outputer(match_result, i, GAMES, pairResult, name1, name2, x) # B vs A 顺序存储空间,再赛GAMES局 for i in range(1+GAMES, 1+GAMES*2): match_core.STORAGE = storageBA match_result = match((func2, func1), (name2, name1), HALFWIDTH, HEIGHT, ROUNDSPERGAME, TIMELIMIT) log_name = '%s/log/%s-VS-%s(%s).zlog' % (FOLDER, name2, name1, i-GAMES) save_match_log(match_result, log_name) outputer(match_result, i, GAMES, pairResult, name1, name2, x) if pairResult[0] > GAMES or pairResult[1] > GAMES: break # 总结函数 storageBA = storageBA[::-1] for match_core.STORAGE in storageAB, storageBA: for i in range(2): try: exec('func%d.summaryall(match_core.STORAGE[%d])' % (i+1, i)) except: pass # 单挑结束,输出结果 if pairResult[0] > pairResult[1]: totalwinner = name1 output = [(name1, func1)], [(name2, func2)] elif pairResult[0] < pairResult[1]: totalwinner = name2 output = [(name2, func2)], [(name1, func1)] else: totalwinner = 'No one' output = [['No one']], None print('Knockout Result:', totalwinner, 'wins.', '\nPress enter to continue:', file=sys.__stdout__) input() return output
def worker(id, net, data_queue, save=False): EPS_START = 0.9 EPS_END = 0.2 EPS_DECAY = 5000 class player1: def load(self, stat, storage): storage['field_size'] = 0 if 'tensor' in storage: del storage['tensor'] def play(self, stat, storage): tensor, field_size = getFeatureMap(stat) reward = field_size - storage['field_size'] if 'tensor' in storage: data_queue.put( (storage['tensor'], storage['action'], tensor, reward)) storage['tensor'] = tensor storage['field_size'] = field_size if 'steps_done' in storage: storage['steps_done'] += 1 else: storage['steps_done'] = 1 #print(tensor.shape) sample = random.random() eps_threshold = EPS_END + (EPS_START - EPS_END) * \ math.exp(-1. * storage['steps_done'] / EPS_DECAY) #print('EPS: ', storage['steps_done'], eps_threshold) choices = ['l', 's', 'r'] if sample > eps_threshold: #print('Using Net') with torch.no_grad(): res = net(tensor).max(1)[1] ret = choices[res] else: ret = random.choice(['l', 'r', 's']) storage['action'] = ret #print(ret) return ret def summary(self, result, stat, storage): tensor, field_size = getFeatureMap(stat) eps_threshold = EPS_END + (EPS_START - EPS_END) * \ math.exp(-1. * storage['steps_done'] / EPS_DECAY) if id == 0: print('EPS: ', storage['steps_done'], eps_threshold, "Size: ", tensor[0][0].sum()) if result[0] is not None and result[1] >= 0: if result[0] == stat['log'][0]['me']['id'] - 1: reward = 0 else: reward = -0 data_queue.put( (storage['tensor'], storage['action'], None, reward)) class player2: def load(self, stat, storage): return p2.load(stat, storage) def play(self, stat, storage): return "r" return p2.play(stat, storage) gameCnt = 1 while True: t1 = pf() res = match((player1(), player2())) t2 = pf() if id == 0: print("Time: ", t2 - t1) print(gameCnt, ' Match Done') if save: save_match_log(res, 'saves/' + str(gameCnt % 100) + '.zlog') gameCnt += 1 if 'DEBUG_TRACEBACK' in dir(match): print(match.DEBUG_TRACEBACK) exit()
def process_task(data_queue, path, names, log_format, rounds, match_params): ''' 子进程执行两玩家多局对决 params: data_queue - 数据队列 path - 玩家模块所在路径 names - 玩家名称 log_format - 记录文件名格式 比赛记录将保存为log_format % (*names, index)路径 rounds - 单向比赛局数(双向进行) match_params - 比赛参数 ''' # 读取玩家 sys.path.append(path) players = [__import__(n) for n in names] # 双向比赛 win_counts = [0, 0] for i in 0, 1: # 初始化存储空间、局数统计 match_core.STORAGE = [{}, {}] # 第二次交换比赛 if i: players = players[::-1] names = names[::-1] win_counts = win_counts[::-1] # 总初始化函数 for i in range(2): try: players[i].init(match_core.STORAGE[i]) except: pass # 运行多局比赛 for i in range(rounds): # 进行比赛,获取记录 match_log = match_core.match(players, names, *match_params) # 生成比赛记录 log_name = log_format % (*names, i) match_interface.save_match_log(match_log, log_name) # 比赛结果传递至队列 result = match_log['result'] data_queue.put((names, result)) # 统计比赛结果,若胜利过半则跳出 if result[0] is not None: win_counts[result[0]] += 1 if win_counts[result[0]] > rounds: break # 总总结函数 for i in range(2): try: players[i].summaryall(match_core.STORAGE[i]) except: pass
storageAB, storageBA = [{}, {}], [{}, {}] for match_core.STORAGE in storageAB, storageBA: for i in range(2): try: exec('func%d.init(match_core.STORAGE[0])' % i) except: pass for i in range(GAMES): # A vs B 顺序存储空间 match_core.STORAGE = storageAB match_result = match((func1, func2), (name1, name2), HALFWIDTH, HEIGHT, ROUNDSPERGAME, TIMELIMIT) log_name = '%s/log/%s-VS-%s(%s).zlog' % (FOLDER, name1, name2, 1 + i) save_match_log(match_result, log_name) os.system('clear') gameWinner = match_result['result'][0] if gameWinner == 0: gameResult[0] += 1 winner = '(A) ' + name1 elif gameWinner == 1: gameResult[1] += 1 winner = '(B) ' + name2 else: winner = 'None' ''' 终局原因 : 0 - WAL 撞墙
def knockoutScenario(plrs, FOLDER): # 单挑赛脚本:读取目录内两个文件,提取play函数并执行 # 屏蔽AI自带print class null_stream: def read(*args): pass def write(*args): pass def flush(*args): pass sys.stdout = null_stream # 设置比赛参数 GAMES = 10 # 作为先后手各比赛场数,总场次 2 * GAMES HALFWIDTH, HEIGHT, TIMELIMIT, ROUNDSPERGAME, = 51, 101, 30, 20 CLEAR = 'cls' if platform.system() == 'Windows' else 'clear' # 设置清屏指令 # 创建赛程 name1, func1, name2, func2 = plrs[0][0], plrs[0][1], plrs[1][0], plrs[1][1] # 图形化计分表,比赛结果统计表 x = PrettyTable([' #', 'Endgame Winner', 'Game State', ' Rmk ']) pairResult = [0, 0] # 图形化计分表与比赛结果统计表绘图工具 def outputer(match_result, i, GAMES, pairResult, name1, name2, x): # 统计胜方 gameResult = match_result['result'] gameWinner = gameResult[0] if gameWinner == None: winner = 'None' elif i < GAMES: # 前 GAMES 局 if gameWinner == 0: pairResult[0] += 1 winner = '(A) ' + name1 elif gameWinner == 1: pairResult[1] += 1 winner = '(B) ' + name2 else: # 后 GAMES 局 if gameWinner == 1: pairResult[0] += 1 winner = '(B) ' + name1 elif gameWinner == 0: pairResult[1] += 1 winner = '(A) ' + name2 # 即时比赛结果的输出文字内容准备 flag = gameResult[1] if flag < 0: flag += 8 rmklst = ['WAL', 'TAP', 'SID', 'FAC', 'CIT', 'END', 'OVT', 'ERR'] reason = 'KO' if flag == 3 or flag == 5: reason = str(gameResult[2]) gameRounds = len(match_result['log']) - 1 x.add_row(['%2d'%i, winner, reason, rmklst[flag] + ', %4d'%gameRounds]) # 更新即时比赛结果 os.system(CLEAR) print( name1, ' ' * (17 - len(name1)), '%2d' % pairResult[0], ': ', '%2d' % pairResult[1], ' ' * (19 - len(name2)), name2, file=sys.__stdout__) print(x, file=sys.__stdout__) # 初始化存储空间 storageAB, storageBA = [{}, {}], [{}, {}] for match_core.STORAGE in storageAB, storageBA: for i in range(2): try: exec('func%d.init(match_core.STORAGE[%d])' % (i + 1, i)) except: pass storageBA = storageBA[::-1] # 根据赛程比赛 for i in range(GAMES): # A vs B 顺序存储空间,先赛GAMES局 match_core.STORAGE = storageAB match_result = match((func1, func2), (name1, name2), HALFWIDTH, HEIGHT, ROUNDSPERGAME, TIMELIMIT) log_name = '%s/log/%s-VS-%s(%s).zlog' % (FOLDER, name1, name2, 1 + i) save_match_log(match_result, log_name) outputer(match_result, i, GAMES, pairResult, name1, name2, x) for i in range(GAMES, GAMES*2): # B vs A 顺序存储空间,再赛GAMES局 match_core.STORAGE = storageBA match_result = match((func2, func1), (name2, name1), HALFWIDTH, HEIGHT, ROUNDSPERGAME, TIMELIMIT) log_name = '%s/log/%s-VS-%s(%s).zlog' % (FOLDER, name2, name1, 1 + i) save_match_log(match_result, log_name) outputer(match_result, i, GAMES, pairResult, name1, name2, x) if pairResult[0] > GAMES or pairResult[1] > GAMES: break # 总结函数 storageBA = storageBA[::-1] for match_core.STORAGE in storageAB, storageBA: for i in range(2): try: exec('func%d.summaryall(match_core.STORAGE[%d])' % (i + 1, i)) except: pass # 单挑结束,输出结果;平手的话该对重赛一次 if pairResult[0] > pairResult[1]: totalresult = name1 + ' wins.' output = [(name1, func1)], [(name2, func2)] elif pairResult[0] < pairResult[1]: totalresult = name2 + ' wins.' output = [(name2, func2)], [(name1, func1)] else: totalresult = 'Ties.' output = [['No one']], None print('Knockout Result:', totalresult, file=sys.__stdout__) time.sleep(5) if output is not None: return output else: return knockout20(plrs, FOLDER)