def record(node): if not node["is_root"]: annotations.annotate_sgf( self.cursor, annotations.format_winrate(node["stats"], node["move_list"], self.board_size, None), [], []) move_list_to_display = [] # Only display info for the principal variation or for lines that have been explored for i in range(len(node["children"])): child = node["children"][i] if child is not None and (i == 0 or child["explored"]): move_list_to_display.append(node["move_list"][i]) (comment, lb_values, tr_values) = annotations.format_analysis( node["stats"], move_list_to_display, None, self.board_size) annotations.annotate_sgf(self.cursor, comment, lb_values, tr_values) for i in range(len(node["children"])): child = node["children"][i] if child is not None: if child["explored"]: advance(node["color"], child["history"][-1]) record(child) self.cursor.previous() # Only show variations for the principal line, to prevent info overload elif i == 0: pv = node["move_list"][i]["pv"] color = node["color"] if CONFIG['num_to_show']: num_to_show = min(len(pv), CONFIG['num_to_show']) else: num_to_show = len(pv) for k in range(int(num_to_show)): advance(color, pv[k]) color = 'black' if color == 'white' else 'white' for k in range(int(num_to_show)): self.cursor.previous()
def analyze_main_line(self): logger.info("Started analyzing main line.") move_num = -1 prev_stats = {} prev_move_list = [] has_prev = False previous_player = None logger.info(f"Executing analysis for %d moves", len(self.moves_to_analyze)) moves_count = 0 self.cursor.reset() self.bot = self.factory() self.bot.time_per_move = CONFIG['analyze_time'] self.bot.start() # analyze main line, without variations while not self.cursor.atEnd: self.cursor.next() move_num += 1 this_move = self.add_moves_to_bot() current_player = 'black' if 'W' in self.cursor.node else 'white' if previous_player == current_player: raise BotException('Two consecutive moves.') if move_num in self.moves_to_analyze: stats, move_list = self.do_analyze() # Here we store ALL statistics self.all_stats[move_num] = stats self.all_move_lists[move_num] = move_list if move_list and 'winrate' in move_list[0]: self.best_moves[move_num] = move_list[0] delta = 0.0 if 'winrate' in stats and (move_num - 1) in self.best_moves: if this_move != self.best_moves[move_num - 1]['pos']: delta = stats['winrate'] - self.best_moves[move_num - 1]['winrate'] delta = min(0.0, (-delta if self.bot.whose_turn() == "black" else delta)) if -delta > CONFIG['analyze_threshold']: (delta_comment, delta_lb_values) = annotations.format_delta_info(delta, this_move, self.board_size) annotations.annotate_sgf(self.cursor, delta_comment, delta_lb_values, []) if has_prev and delta <= -CONFIG['variations_threshold']: self.moves_to_variations[move_num - 1] = True if -delta > CONFIG['analyze_threshold']: logger.warning("Move %d: %s %s is a mistake (winrate dropped by %.2f%%)", move_num + 1, previous_player, convert_position(self.board_size, this_move), -delta * 100) next_game_move = self.next_move_pos() annotations.annotate_sgf(self.cursor, annotations.format_winrate(stats, move_list, self.board_size, next_game_move), [], []) if has_prev and ((move_num - 1) in self.moves_to_analyze and -delta > CONFIG['analyze_threshold'] or ( move_num - 1) in self.moves_to_variations): (analysis_comment, lb_values, tr_values) = annotations.format_analysis( prev_stats, filter_move_list(prev_move_list), this_move, self.board_size) self.cursor.previous() # adding comment to sgf with suggested alternative variations annotations.annotate_sgf(self.cursor, analysis_comment, lb_values, tr_values) self.cursor.next() prev_stats = stats prev_move_list = move_list has_prev = True self.save_to_file() self.graph_winrates() if 'winrate' in stats \ and (1 - CONFIG['stop_on_winrate'] > stats['winrate'] or stats['winrate'] > CONFIG['stop_on_winrate']): break moves_count += 1 logger.info("Analysis done for %d/%d move.", moves_count, len(self.moves_to_analyze)) else: prev_stats = {} prev_move_list = [] has_prev = False previous_player = current_player logger.info("Finished analyzing main line.")