int main()

in rts/backend/main_loop.cc [337:458]


int main(int argc, char *argv[]) {
    const map<string, function<RTSGameOptions (const Parser &, string *)> > func_mapping = {
        { "selfplay", ai_vs_ai },
        { "selfplay2", ai_vs_ai2 },
        { "mcts", ai_vs_mcts },

        { "replay", replay },
        { "replay_cmd", replay_cmd },
        { "humanplay", ai_vs_human },
        { "multiple_selfplay", nullptr},
        //{ "replay_rollout", nullptr},
        //{ "replay_mcts", nullptr},

        // capture the flag
        { "flag_selfplay", flag_ai_vs_ai },
        //{ "flag_mcts", flag_ai_vs_mcts },

        // tower defense
        { "td_simple", td_simple },
    };

    GameDef::GlobalInit();

    CmdLineUtils::CmdLineParser parser("playstyle --save_replay --load_replay --vis_after[-1] --save_snapshot_prefix --load_snapshot_prefix --seed[0] \
--load_snapshot_length --max_tick[30000] --binary_io[1] --games[16] --frame_skip[1] --tick_prompt_n_step[2000] --cmd_verbose[0] --peek_ticks --cmd_dumper_prefix \
--output_file[cout] --mcts_threads[16] --mcts_rollout_per_thread[100] --threads[64] --load_binary_string --mcts_verbose --mcts_prerun_cmds --handicap_level[0]");

    if (! parser.Parse(argc, argv)) {
        cout << parser.PrintHelper() << endl;
        return 0;
    }

    cout << "Cmd Options: " << endl;
    cout << parser.PrintParsed() << endl;
    auto playstyle = parser.GetItem<string>("playstyle");
    auto it = func_mapping.find(playstyle);
    if (it == func_mapping.end()) {
        cout << "Unknown command " << playstyle << "! Available commands are: " << endl;
        for (auto it = func_mapping.begin(); it != func_mapping.end(); ++it) {
            cout << it->first << endl;
        }
        return 0;
    }

    RTSGameOptions options;
    string players;
    try {
        if (it->second != nullptr) options = it->second(parser, &players);
    } catch(const std::exception& e) {
        cout << e.what() << endl;
        return 1;
    }

    int frame_skip = parser.GetItem<int>("frame_skip", 1);

    auto time_start = chrono::system_clock::now();
    // if (playstyle == "replay_rollout") {
    //    replay_rollout(parser);
    // } else if (playstyle == "replay_mcts") {
    //    replay_mcts(parser);
    // } else

    if (playstyle == "multiple_selfplay") {
        int threads = parser.GetItem<int>("threads");
        int games = parser.GetItem<int>("games");
        int seed0 = parser.GetItem<int>("seed");
        ctpl::thread_pool p(threads + 1);
        const int print_per_n = (games == 0 ? 5000 : games * threads / 10);
        GlobalStats gstats(print_per_n);

        for (int i = 0; i < threads; i++) {
            p.push([=, &gstats](int /*thread_id*/){
                RTSGameOptions options;
                options.main_loop_quota = 0;
                options.output_file = "";
                options.tick_prompt_n_step = -1;
                if (seed0 == 0) options.seed = 0;
                else options.seed = seed0 + i * 241;

                RTSStateExtend state(options);
                RTSGame game(&state);
                //game.AddBot(new SimpleAI(INVALID, frame_skip, nullptr));
                //
                //game.AddBot(new SimpleAI(INVALID, frame_skip, nullptr));
                game.AddBot(AIFactory<AI>::CreateAI("simple", ""), frame_skip);
                game.AddBot(AIFactory<AI>::CreateAI("simple", ""), frame_skip);
                state.AppendPlayer("simple1");
                state.AppendPlayer("simple2");

                state.SetGlobalStats(&gstats);
                bool infinite = (games == 0);
                for (int j = 0; j < games || infinite; ++j) {
                    game.MainLoop();
                    game.Reset();
                }
            });
            this_thread::sleep_for(std::chrono::milliseconds(10));
        }
        p.stop(true);
        std::cout << gstats.PrintInfo() << std::endl;
    } else {
        RTSStateExtend state(options);
        RTSGame game(&state);
        cout << "Players: " << players << endl;
        add_players(players, frame_skip, &game);
        cout << "Finish adding players" << endl;

        chrono::duration<double> duration = chrono::system_clock::now() - time_start;
        cout << "Total time spent = " << duration.count() << "s" << endl;
        game.MainLoop();
        /*
            // Load replay etc.
            for (size_t i = 0; i < options.load_replay_filenames.size(); ++i) {
                game.MainLoop();
                game.Reset();
            }
        }
        */
    }

    return 0;
}