class ObSelfPlay: def __init__(self, config: Config): self.config = config self.env = CChessEnv() self.model = None self.pipe = None self.ai = None self.chessmans = None def load_model(self): self.model = CChessModel(self.config) if self.config.opts.new or not load_best_model_weight(self.model): self.model.build() def start(self): self.env.reset() self.load_model() self.pipe = self.model.get_pipes() self.ai = CChessPlayer(self.config, search_tree=defaultdict(VisitState), pipes=self.pipe, enable_resign=True, debugging=False) labels = ActionLabelsRed labels_n = len(ActionLabelsRed) self.env.board.print_to_cl() history = [self.env.get_state()] while not self.env.board.is_end(): no_act = None state = self.env.get_state() if state in history[:-1]: no_act = [] for i in range(len(history) - 1): if history[i] == state: no_act.append(history[i + 1]) action, _ = self.ai.action(state, self.env.num_halfmoves, no_act) history.append(action) if action is None: print("AI投降了!") break move = self.env.board.make_single_record(int(action[0]), int(action[1]), int(action[2]), int(action[3])) if not self.env.red_to_move: action = flip_move(action) self.env.step(action) history.append(self.env.get_state()) print(f"AI选择移动 {move}") self.env.board.print_to_cl() sleep(1) self.ai.close() print(f"胜者是 is {self.env.board.winner} !!!") self.env.board.print_record()
def load_game(self, init, move_list, winner, idx, title, url): turns = 0 env = CChessEnv(self.config).reset(init) red_moves = [] black_moves = [] moves = [move_list[i:i+4] for i in range(len(move_list)) if i % 4 == 0] for move in moves: action = senv.parse_onegreen_move(move) try: if turns % 2 == 0: red_moves.append([env.observation, self.build_policy(action, flip=False)]) else: black_moves.append([env.observation, self.build_policy(action, flip=True)]) env.step(action) except: logger.error(f"Invalid Action: idx = {idx}, action = {action}, turns = {turns}, moves = {moves}, " f"winner = {winner}, init = {init}, title: {title}, url: {url}") return turns += 1 if winner == Winner.red: red_win = 1 elif winner == Winner.black: red_win = -1 else: red_win = senv.evaluate(env.get_state()) if not env.red_to_move: red_win = -red_win for move in red_moves: move += [red_win] for move in black_moves: move += [-red_win] data = [] for i in range(len(red_moves)): data.append(red_moves[i]) if i < len(black_moves): data.append(black_moves[i]) self.buffer += data return red_win
class PlayWithHuman: def __init__(self, config: Config): self.config = config self.env = CChessEnv() self.model = None self.pipe = None self.ai = None self.winstyle = 0 self.chessmans = None self.human_move_first = True self.screen_width = 720 self.height = 577 self.width = 521 self.chessman_w = 57 self.chessman_h = 57 self.disp_record_num = 30 self.rec_labels = [None] * self.disp_record_num self.nn_value = 0 self.mcts_moves = {} self.history = [] if self.config.opts.bg_style == 'WOOD': self.chessman_w += 1 self.chessman_h += 1 def load_model(self): sess = set_session_config(per_process_gpu_memory_fraction=1, allow_growth=True, device_list=self.config.opts.device_list) self.model = CChessModel(self.config) if self.config.opts.new or not load_best_model_weight(self.model): self.model.build() self.model.sess = sess def init_screen(self): bestdepth = pygame.display.mode_ok([self.screen_width, self.height], self.winstyle, 32) screen = pygame.display.set_mode([self.screen_width, self.height], self.winstyle, bestdepth) pygame.display.set_caption("人机对弈") # create the background, tile the bgd image bgdtile = load_image(f'{self.config.opts.bg_style}.GIF') bgdtile = pygame.transform.scale(bgdtile, (self.width, self.height)) board_background = pygame.Surface([self.width, self.height]) board_background.blit(bgdtile, (0, 0)) widget_background = pygame.Surface( [self.screen_width - self.width, self.height]) white_rect = Rect(0, 0, self.screen_width - self.width, self.height) widget_background.fill((255, 255, 255), white_rect) #create text label font_file = self.config.resource.font_path font = pygame.font.Font(font_file, 16) font_color = (0, 0, 0) font_background = (255, 255, 255) t = font.render("着法记录", True, font_color, font_background) t_rect = t.get_rect() t_rect.x = 10 t_rect.y = 10 widget_background.blit(t, t_rect) screen.blit(board_background, (0, 0)) screen.blit(widget_background, (self.width, 0)) pygame.display.flip() self.chessmans = pygame.sprite.Group() creat_sprite_group(self.chessmans, self.env.board.chessmans_hash, self.chessman_w, self.chessman_h) return screen, board_background, widget_background def start(self, human_first=True): self.env.reset() self.load_model() self.pipe = self.model.get_pipes() self.ai = CChessPlayer(self.config, search_tree=defaultdict(VisitState), pipes=self.pipe, enable_resign=True, debugging=True) self.human_move_first = human_first pygame.init() screen, board_background, widget_background = self.init_screen() framerate = pygame.time.Clock() labels = ActionLabelsRed labels_n = len(ActionLabelsRed) current_chessman = None if human_first: self.env.board.calc_chessmans_moving_list() ai_worker = Thread(target=self.ai_move, name="ai_worker") ai_worker.daemon = True ai_worker.start() while not self.env.board.is_end(): for event in pygame.event.get(): if event.type == pygame.QUIT: self.env.board.print_record() self.ai.close(wait=False) game_id = datetime.now().strftime("%Y%m%d-%H%M%S") path = os.path.join( self.config.resource.play_record_dir, self.config.resource.play_record_filename_tmpl % game_id) self.env.board.save_record(path) sys.exit() elif event.type == VIDEORESIZE: pass elif event.type == MOUSEBUTTONDOWN: if human_first == self.env.red_to_move: pressed_array = pygame.mouse.get_pressed() for index in range(len(pressed_array)): if index == 0 and pressed_array[index]: mouse_x, mouse_y = pygame.mouse.get_pos() col_num, row_num = translate_hit_area( mouse_x, mouse_y, self.chessman_w, self.chessman_h) chessman_sprite = select_sprite_from_group( self.chessmans, col_num, row_num) if current_chessman is None and chessman_sprite != None: if chessman_sprite.chessman.is_red == self.env.red_to_move: current_chessman = chessman_sprite chessman_sprite.is_selected = True elif current_chessman != None and chessman_sprite != None: if chessman_sprite.chessman.is_red == self.env.red_to_move: current_chessman.is_selected = False current_chessman = chessman_sprite chessman_sprite.is_selected = True else: move = str(current_chessman.chessman.col_num) + str(current_chessman.chessman.row_num) +\ str(col_num) + str(row_num) success = current_chessman.move( col_num, row_num, self.chessman_w, self.chessman_h) self.history.append(move) if success: self.chessmans.remove( chessman_sprite) chessman_sprite.kill() current_chessman.is_selected = False current_chessman = None self.history.append( self.env.get_state()) elif current_chessman != None and chessman_sprite is None: move = str(current_chessman.chessman.col_num) + str(current_chessman.chessman.row_num) +\ str(col_num) + str(row_num) success = current_chessman.move( col_num, row_num, self.chessman_w, self.chessman_h) self.history.append(move) if success: current_chessman.is_selected = False current_chessman = None self.history.append( self.env.get_state()) self.draw_widget(screen, widget_background) framerate.tick(20) # clear/erase the last drawn sprites self.chessmans.clear(screen, board_background) # update all the sprites self.chessmans.update() self.chessmans.draw(screen) pygame.display.update() self.draw_widget(screen, widget_background) self.ai.close(wait=False) logger.info(f"Winner is {self.env.board.winner} !!!") self.env.board.print_record() game_id = datetime.now().strftime("%Y%m%d-%H%M%S") path = os.path.join( self.config.resource.play_record_dir, self.config.resource.play_record_filename_tmpl % game_id) self.env.board.save_record(path) sleep(5) def ai_move(self): ai_move_first = not self.human_move_first self.history = [self.env.get_state()] no_act = None while not self.env.done: if ai_move_first == self.env.red_to_move: labels = ActionLabelsRed labels_n = len(ActionLabelsRed) self.ai.search_results = {} state = self.env.get_state() logger.info(f"state = {state}") _, _, _, check = senv.done(state, need_check=True) if not check and state in self.history[:-1]: no_act = [] free_move = defaultdict(int) for i in range(len(self.history) - 1): if self.history[i] == state: # 如果走了下一步是将军或捉:禁止走那步 if senv.will_check_or_catch( state, self.history[i + 1]): no_act.append(self.history[i + 1]) # 否则当作闲着处理 else: free_move[state] += 1 if free_move[state] >= 2: # 作和棋处理 self.env.winner = Winner.draw self.env.board.winner = Winner.draw break if no_act: logger.debug(f"no_act = {no_act}") action, policy = self.ai.action(state, self.env.num_halfmoves, no_act) if action is None: logger.info("AI has resigned!") return self.history.append(action) if not self.env.red_to_move: action = flip_move(action) key = self.env.get_state() p, v = self.ai.debug[key] logger.info(f"check = {check}, NN value = {v:.3f}") self.nn_value = v logger.info("MCTS results:") self.mcts_moves = {} for move, action_state in self.ai.search_results.items(): move_cn = self.env.board.make_single_record( int(move[0]), int(move[1]), int(move[2]), int(move[3])) logger.info( f"move: {move_cn}-{move}, visit count: {action_state[0]}, Q_value: {action_state[1]:.3f}, Prior: {action_state[2]:.3f}" ) self.mcts_moves[move_cn] = action_state x0, y0, x1, y1 = int(action[0]), int(action[1]), int( action[2]), int(action[3]) chessman_sprite = select_sprite_from_group( self.chessmans, x0, y0) sprite_dest = select_sprite_from_group(self.chessmans, x1, y1) if sprite_dest: self.chessmans.remove(sprite_dest) sprite_dest.kill() chessman_sprite.move(x1, y1, self.chessman_w, self.chessman_h) self.history.append(self.env.get_state()) def draw_widget(self, screen, widget_background): white_rect = Rect(0, 0, self.screen_width - self.width, self.height) widget_background.fill((255, 255, 255), white_rect) # pygame.draw.line(widget_background, (255, 0, 0), (10, 285), (self.screen_width - self.width - 10, 285)) screen.blit(widget_background, (self.width, 0)) self.draw_records(screen, widget_background) # self.draw_evaluation(screen, widget_background) def draw_records(self, screen, widget_background): text = '着法记录' if self.env.board.is_end(): result_text = "黑胜!!!" if self.env.winner == Winner.red: result_text = "红胜!!!" self.draw_label(screen, widget_background, result_text, 500, 48, 10) self.draw_label(screen, widget_background, text, 10, 16, 10) records = self.env.board.record.split('\n') font_file = self.config.resource.font_path font = pygame.font.Font(font_file, 12) i = 0 for record in records[-self.disp_record_num:]: self.rec_labels[i] = font.render(record, True, (0, 0, 0), (255, 255, 255)) t_rect = self.rec_labels[i].get_rect() # t_rect.centerx = (self.screen_width - self.width) / 2 t_rect.y = 35 + i * 15 t_rect.x = 10 t_rect.width = self.screen_width - self.width widget_background.blit(self.rec_labels[i], t_rect) i += 1 screen.blit(widget_background, (self.width, 0)) def draw_evaluation(self, screen, widget_background): title_label = 'AI信息' self.draw_label(screen, widget_background, title_label, 300, 16, 10) info_label = f'MCTS搜索次数:{self.config.play.simulation_num_per_move}' self.draw_label(screen, widget_background, info_label, 335, 14, 10) eval_label = f"当前局势评估: {self.nn_value:.3f}" self.draw_label(screen, widget_background, eval_label, 360, 14, 10) label = f"MCTS搜索结果:" self.draw_label(screen, widget_background, label, 395, 14, 10) label = f"着法 访问计数 动作价值 先验概率" self.draw_label(screen, widget_background, label, 415, 12, 10) i = 0 tmp = copy.deepcopy(self.mcts_moves) for mov, action_state in tmp.items(): label = f"{mov}" self.draw_label(screen, widget_background, label, 435 + i * 20, 12, 10) label = f"{action_state[0]}" self.draw_label(screen, widget_background, label, 435 + i * 20, 12, 70) label = f"{action_state[1]:.2f}" self.draw_label(screen, widget_background, label, 435 + i * 20, 12, 100) label = f"{action_state[2]:.3f}" self.draw_label(screen, widget_background, label, 435 + i * 20, 12, 150) i += 1 def draw_label(self, screen, widget_background, text, y, font_size, x=None): font_file = self.config.resource.font_path font = pygame.font.Font(font_file, font_size) label = font.render(text, True, (0, 0, 0), (255, 255, 255)) t_rect = label.get_rect() t_rect.y = y if x != None: t_rect.x = x else: t_rect.centerx = (self.screen_width - self.width) / 2 widget_background.blit(label, t_rect) screen.blit(widget_background, (self.width, 0))
class PlayWithHuman: def __init__(self, config: Config): self.config = config self.env = CChessEnv() self.model = None self.pipe = None self.ai = None self.chessmans = None self.human_move_first = True def load_model(self): self.model = CChessModel(self.config) if self.config.opts.new or not load_best_model_weight(self.model): self.model.build() def start(self, human_first=True): self.env.reset() self.load_model() self.pipe = self.model.get_pipes() self.ai = CChessPlayer(self.config, search_tree=defaultdict(VisitState), pipes=self.pipe, enable_resign=True, debugging=False) self.human_move_first = human_first labels = ActionLabelsRed labels_n = len(ActionLabelsRed) self.env.board.print_to_cl() while not self.env.board.is_end(): if human_first == self.env.red_to_move: self.env.board.calc_chessmans_moving_list() is_correct_chessman = False is_correct_position = False chessman = None while not is_correct_chessman: title = "请输入棋子位置: " input_chessman_pos = input(title) x, y = int(input_chessman_pos[0]), int( input_chessman_pos[1]) chessman = self.env.board.chessmans[x][y] if chessman != None and chessman.is_red == self.env.board.is_red_turn: is_correct_chessman = True print(f"当前棋子为{chessman.name_cn},可以落子的位置有:") for point in chessman.moving_list: print(point.x, point.y) else: print("没有找到此名字的棋子或未轮到此方走子") while not is_correct_position: title = "请输入落子的位置: " input_chessman_pos = input(title) x, y = int(input_chessman_pos[0]), int( input_chessman_pos[1]) is_correct_position = chessman.move(x, y) if is_correct_position: self.env.board.print_to_cl() self.env.board.clear_chessmans_moving_list() else: action, policy = self.ai.action(self.env.get_state(), self.env.num_halfmoves) if not self.env.red_to_move: action = flip_move(action) if action is None: print("AI投降了!") break self.env.step(action) print(f"AI选择移动 {action}") self.env.board.print_to_cl() self.ai.close() print(f"胜者是 is {self.env.board.winner} !!!") self.env.board.print_record()
class PlayWithHuman: def __init__(self, config: Config): self.config = config self.env = CChessEnv() self.model = None self.pipe = None self.ai = None self.chessmans = None self.human_move_first = True def load_model(self): self.model = CChessModel(self.config) if self.config.opts.new or not load_best_model_weight(self.model): self.model.build() def start(self, human_first=True): self.env.reset() self.load_model() self.pipe = self.model.get_pipes() self.ai = CChessPlayer(self.config, search_tree=defaultdict(VisitState), pipes=self.pipe, enable_resign=True, debugging=False) self.human_move_first = human_first labels = ActionLabelsRed labels_n = len(ActionLabelsRed) self.env.board.print_to_cl() while not self.env.board.is_end(): if human_first == self.env.red_to_move: self.env.board.calc_chessmans_moving_list() is_correct_chessman = False is_correct_position = False chessman = None while not is_correct_chessman: title = "请输入棋子位置: " input_chessman_pos = input(title) x, y = int(input_chessman_pos[0]), int(input_chessman_pos[1]) chessman = self.env.board.chessmans[x][y] if chessman != None and chessman.is_red == self.env.board.is_red_turn: is_correct_chessman = True print(f"当前棋子为{chessman.name_cn},可以落子的位置有:") for point in chessman.moving_list: print(point.x, point.y) else: print("没有找到此名字的棋子或未轮到此方走子") while not is_correct_position: title = "请输入落子的位置: " input_chessman_pos = input(title) x, y = int(input_chessman_pos[0]), int(input_chessman_pos[1]) is_correct_position = chessman.move(x, y) if is_correct_position: self.env.board.print_to_cl() self.env.board.clear_chessmans_moving_list() else: action, policy = self.ai.action(self.env.get_state(), self.env.num_halfmoves) if not self.env.red_to_move: action = flip_move(action) if action is None: print("AI投降了!") break self.env.step(action) print(f"AI选择移动 {action}") self.env.board.print_to_cl() self.ai.close() print(f"胜者是 is {self.env.board.winner} !!!") self.env.board.print_record()
class PlayWithHuman: def __init__(self, config: Config): self.config = config self.env = CChessEnv() self.model = None self.pipe = None self.ai = None self.chessmans = None self.human_move_first = True def load_model(self): self.model = CChessModel(self.config) if self.config.opts.new or not load_best_model_weight(self.model): self.model.build() def start(self, human_first=True): self.env.reset() self.load_model() self.pipe = self.model.get_pipes() self.ai = CChessPlayer(self.config, search_tree=defaultdict(VisitState), pipes=self.pipe, enable_resign=True, debugging=False) self.human_move_first = human_first labels = ActionLabelsRed labels_n = len(ActionLabelsRed) self.env.board.print_to_cl() while not self.env.board.is_end(): if human_first == self.env.red_to_move: self.env.board.calc_chessmans_moving_list() is_correct_chessman = False is_correct_position = False chessman = None while not is_correct_chessman: title = "Please enter the chess piece position: " input_chessman_pos = input(title) print(input_chessman_pos) x, y = int(input_chessman_pos[0]), int( input_chessman_pos[1]) chessman = self.env.board.chessmans[x][y] if chessman != None and chessman.is_red == self.env.board.is_red_turn: is_correct_chessman = True print( f"The current chess piece is {chessman.name},places where you can play:" ) for point in chessman.moving_list: print(point.x, point.y) else: print( "No chess piece with this name was found or it was not his turn to walk" ) while not is_correct_position: title = "Please enter the location of the child: " input_chessman_pos = input(title) x, y = int(input_chessman_pos[0]), int( input_chessman_pos[1]) is_correct_position = chessman.move(x, y) if is_correct_position: self.env.board.print_to_cl() self.env.board.clear_chessmans_moving_list() else: action, policy = self.ai.action(self.env.get_state(), self.env.num_halfmoves) if not self.env.red_to_move: action = flip_move(action) if action is None: print("AI surrendered!") break self.env.step(action) print(f"AI chooses to move {action}") self.env.board.print_to_cl() self.ai.close() print(f"The winner is is {self.env.board.winner} !!!") self.env.board.print_record()
class ObSelfPlayUCCI: def __init__(self, config: Config, ai_move_first=True): self.config = config self.env = CChessEnv() self.model = None self.pipe = None self.ai = None self.chessmans = None self.ai_move_first = ai_move_first def load_model(self): self.model = CChessModel(self.config) if self.config.opts.new or not load_best_model_weight(self.model): self.model.build() def start(self): self.env.reset() self.load_model() self.pipe = self.model.get_pipes() self.ai = CChessPlayer(self.config, search_tree=defaultdict(VisitState), pipes=self.pipe, enable_resign=True, debugging=False) labels = ActionLabelsRed labels_n = len(ActionLabelsRed) self.env.board.print_to_cl() history = [self.env.get_state()] turns = 0 game_over = False final_move = None while not game_over: if (self.ai_move_first and turns % 2 == 0) or (not self.ai_move_first and turns % 2 == 1): start_time = time() no_act = None state = self.env.get_state() if state in history[:-1]: no_act = [] for i in range(len(history) - 1): if history[i] == state: act = history[i + 1] if not self.env.red_to_move: act = flip_move(act) no_act.append(act) action, _ = self.ai.action(state, self.env.num_halfmoves, no_act) end_time = time() if action is None: print("AlphaZero 投降了!") break move = self.env.board.make_single_record( int(action[0]), int(action[1]), int(action[2]), int(action[3])) print( f"AlphaZero 选择移动 {move}, 消耗时间 {(end_time - start_time):.2f}s" ) if not self.env.red_to_move: action = flip_move(action) else: state = self.env.get_state() print(state) fen = senv.state_to_fen(state, turns) action = self.get_ucci_move(fen) if action is None: print("Eleeye 投降了!") break print(action) if not self.env.red_to_move: rec_action = flip_move(action) else: rec_action = action move = self.env.board.make_single_record( int(rec_action[0]), int(rec_action[1]), int(rec_action[2]), int(rec_action[3])) print(f"Eleeye 选择移动 {move}") history.append(action) self.env.step(action) history.append(self.env.get_state()) self.env.board.print_to_cl() turns += 1 sleep(1) game_over, final_move = self.env.board.is_end_final_move() print(game_over, final_move) if final_move: move = self.env.board.make_single_record(int(final_move[0]), int(final_move[1]), int(final_move[2]), int(final_move[3])) print(f"Final Move {move}") if not self.env.red_to_move: final_move = flip_move(final_move) self.env.step(final_move) self.env.board.print_to_cl() self.ai.close() print(f"胜者是 is {self.env.board.winner} !!!") self.env.board.print_record() def get_ucci_move(self, fen, time=3): p = subprocess.Popen(self.config.resource.eleeye_path, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) setfen = f'position fen {fen}\n' setrandom = 'setoption randomness small\n' cmd = 'ucci\n' + setrandom + setfen + f'go time {time * 1000}\n' try: out, err = p.communicate(cmd, timeout=time + 0.5) except: p.kill() try: out, err = p.communicate() except Exception as e: logger.error(f"{e}, cmd = {cmd}") return self.get_ucci_move(fen, time + 1) print(out) lines = out.split('\n') if lines[-2] == 'nobestmove': return None move = lines[-2].split(' ')[1] if move == 'depth': move = lines[-1].split(' ')[6] return senv.parse_ucci_move(move)
class ObSelfPlayUCCI: def __init__(self, config: Config, ai_move_first=True): self.config = config self.env = CChessEnv() self.model = None self.pipe = None self.ai = None self.chessmans = None self.ai_move_first = ai_move_first def load_model(self): self.model = CChessModel(self.config) if self.config.opts.new or not load_best_model_weight(self.model): self.model.build() def start(self): self.env.reset() self.load_model() self.pipe = self.model.get_pipes() self.ai = CChessPlayer(self.config, search_tree=defaultdict(VisitState), pipes=self.pipe, enable_resign=True, debugging=False) labels = ActionLabelsRed labels_n = len(ActionLabelsRed) self.env.board.print_to_cl() history = [self.env.get_state()] turns = 0 game_over = False final_move = None while not game_over: if (self.ai_move_first and turns % 2 == 0) or (not self.ai_move_first and turns % 2 == 1): start_time = time() no_act = None state = self.env.get_state() if state in history[:-1]: no_act = [] for i in range(len(history) - 1): if history[i] == state: act = history[i + 1] if not self.env.red_to_move: act = flip_move(act) no_act.append(act) action, _ = self.ai.action(state, self.env.num_halfmoves, no_act) end_time = time() if action is None: print("AlphaZero 投降了!") break move = self.env.board.make_single_record(int(action[0]), int(action[1]), int(action[2]), int(action[3])) print(f"AlphaZero 选择移动 {move}, 消耗时间 {(end_time - start_time):.2f}s") if not self.env.red_to_move: action = flip_move(action) else: state = self.env.get_state() print(state) fen = senv.state_to_fen(state, turns) action = self.get_ucci_move(fen) if action is None: print("Eleeye 投降了!") break print(action) if not self.env.red_to_move: rec_action = flip_move(action) else: rec_action = action move = self.env.board.make_single_record(int(rec_action[0]), int(rec_action[1]), int(rec_action[2]), int(rec_action[3])) print(f"Eleeye 选择移动 {move}") history.append(action) self.env.step(action) history.append(self.env.get_state()) self.env.board.print_to_cl() turns += 1 sleep(1) game_over, final_move = self.env.board.is_end_final_move() print(game_over, final_move) if final_move: move = self.env.board.make_single_record(int(final_move[0]), int(final_move[1]), int(final_move[2]), int(final_move[3])) print(f"Final Move {move}") if not self.env.red_to_move: final_move = flip_move(final_move) self.env.step(final_move) self.env.board.print_to_cl() self.ai.close() print(f"胜者是 is {self.env.board.winner} !!!") self.env.board.print_record() def get_ucci_move(self, fen, time=3): p = subprocess.Popen(self.config.resource.eleeye_path, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) setfen = f'position fen {fen}\n' setrandom = 'setoption randomness small\n' cmd = 'ucci\n' + setrandom + setfen + f'go time {time * 1000}\n' try: out, err = p.communicate(cmd, timeout=time+0.5) except: p.kill() try: out, err = p.communicate() except Exception as e: logger.error(f"{e}, cmd = {cmd}") return self.get_ucci_move(fen, time+1) print(out) lines = out.split('\n') if lines[-2] == 'nobestmove': return None move = lines[-2].split(' ')[1] if move == 'depth': move = lines[-1].split(' ')[6] return senv.parse_ucci_move(move)