void MoHexEngine::MoHexPolicyParam(HtpCommand& cmd)
{
    HexUctPolicyConfig& config = m_player.SharedPolicy().Config();
    if (cmd.NuArg() == 0)
    {
        cmd << '\n'
            << "pattern_check_percent "
            << config.pattern_check_percent << '\n'
            << "pattern_heuristic "
            << config.patternHeuristic << '\n'
            << "response_heuristic "
            << config.responseHeuristic << '\n'
            << "response_threshold "
            << config.response_threshold << '\n';
    }
    else if (cmd.NuArg() == 2)
    {
        std::string name = cmd.Arg(0);
        if (name == "pattern_check_percent")
            config.pattern_check_percent = cmd.IntArg(1, 0, 100);
        else if (name == "pattern_heuristic")
            config.patternHeuristic = cmd.BoolArg(1);
        else if (name == "response_heuristic")
            config.responseHeuristic = cmd.BoolArg(1);
        else if (name == "response_threshold")
            config.response_threshold = cmd.SizeTypeArg(1, 0);
        else
            throw HtpFailure("Unknown option!");
    }
    else
        throw HtpFailure("Expected 0 or 2 arguments!");
}
void BookBuilderCommands<PLAYER>::CmdBookExpand(HtpCommand& cmd)
{
    if (m_book.get() == 0) 
        throw HtpFailure() << "No open book.";
    cmd.CheckNuArg(1);
    int iterations = cmd.IntArg(0, 1);
    HexState state(m_game.Board(), m_game.Board().WhoseTurn());
    HexBoard& brd = m_env.SyncBoard(m_game.Board());
    m_bookBuilder.SetState(*m_book, state);
    m_bookBuilder.SetWorkBoard(brd);
    m_bookBuilder.Expand(iterations);
}
/** Saves the search tree from the previous search to the specified
    file.  The optional second parameter sets the max depth to
    output. If not given, entire tree is saved.    
*/
void MoHexEngine::SaveTree(HtpCommand& cmd)
{
    HexUctSearch& search = m_player.Search();

    cmd.CheckNuArg(1);
    std::string filename = cmd.Arg(0);
    int maxDepth = -1;
    std::ofstream file(filename.c_str());
    if (!file)
        throw HtpFailure() << "Could not open '" << filename << "'";
    if (cmd.NuArg() == 2)
        maxDepth = cmd.IntArg(1, 0);
    search.SaveTree(file, maxDepth);
}
void MoHexEngine::MoHexParam(HtpCommand& cmd)
{
    HexUctSearch& search = m_player.Search();

    if (cmd.NuArg() == 0) 
    {
        cmd << '\n'
            << "[bool] backup_ice_info "
            << m_player.BackupIceInfo() << '\n'
            << "[bool] lock_free " 
            << search.LockFree() << '\n'
            << "[bool] keep_games "
            << search.KeepGames() << '\n'
            << "[bool] perform_pre_search " 
            << m_player.PerformPreSearch() << '\n'
            << "[bool] ponder "
            << m_player.Ponder() << '\n'
            << "[bool] reuse_subtree " 
            << m_player.ReuseSubtree() << '\n'
            << "[bool] search_singleton "
            << m_player.SearchSingleton() << '\n'
            << "[bool] use_livegfx "
            << search.LiveGfx() << '\n'
            << "[bool] use_parallel_solver "
            << m_useParallelSolver << '\n'
            << "[bool] use_rave "
            << search.Rave() << '\n'
            << "[bool] use_time_management "
            << m_player.UseTimeManagement() << '\n'
            << "[bool] weight_rave_updates "
            << search.WeightRaveUpdates() << '\n'
            << "[string] bias_term "
            << search.BiasTermConstant() << '\n'
            << "[string] expand_threshold "
            << search.ExpandThreshold() << '\n'
            << "[string] knowledge_threshold "
            << KnowledgeThresholdToString(search.KnowledgeThreshold()) << '\n'
            << "[string] livegfx_interval "
            << search.LiveGfxInterval() << '\n'
            << "[string] max_games "
            << m_player.MaxGames() << '\n'
            << "[string] max_memory "
            << search.MaxNodes() * 2 * sizeof(SgUctNode) << '\n'
            << "[string] max_nodes "
            << search.MaxNodes() << '\n'
            << "[string] max_time "
            << m_player.MaxTime() << '\n'
            << "[string] num_threads "
            << search.NumberThreads() << '\n'
            << "[string] playout_update_radius "
            << search.PlayoutUpdateRadius() << '\n'
            << "[string] randomize_rave_frequency "
            << search.RandomizeRaveFrequency() << '\n'
            << "[string] rave_weight_final "
            << search.RaveWeightFinal() << '\n'
            << "[string] rave_weight_initial "
            << search.RaveWeightInitial() << '\n'
            << "[string] tree_update_radius " 
            << search.TreeUpdateRadius() << '\n';
    }
    else if (cmd.NuArg() == 2)
    {
        std::string name = cmd.Arg(0);
        if (name == "backup_ice_info")
            m_player.SetBackupIceInfo(cmd.BoolArg(1));
        else if (name == "lock_free")
            search.SetLockFree(cmd.BoolArg(1));
        else if (name == "keep_games")
            search.SetKeepGames(cmd.BoolArg(1));
        else if (name == "perform_pre_search")
            m_player.SetPerformPreSearch(cmd.BoolArg(1));
        else if (name == "ponder")
            m_player.SetPonder(cmd.BoolArg(1));
        else if (name == "use_livegfx")
            search.SetLiveGfx(cmd.BoolArg(1));
        else if (name == "use_rave")
            search.SetRave(cmd.BoolArg(1));
        else if (name == "randomize_rave_frequency")
            search.SetRandomizeRaveFrequency(cmd.IntArg(1, 0));
        else if (name == "reuse_subtree")
           m_player.SetReuseSubtree(cmd.BoolArg(1));
        else if (name == "bias_term")
            search.SetBiasTermConstant(cmd.FloatArg(1));
        else if (name == "expand_threshold")
            search.SetExpandThreshold(cmd.IntArg(1, 0));
        else if (name == "knowledge_threshold")
            search.SetKnowledgeThreshold
                (KnowledgeThresholdFromString(cmd.Arg(1)));
        else if (name == "livegfx_interval")
            search.SetLiveGfxInterval(cmd.IntArg(1, 0));
        else if (name == "max_games")
            m_player.SetMaxGames(cmd.IntArg(1, 0));
        else if (name == "max_memory")
            search.SetMaxNodes(cmd.SizeTypeArg(1, 1) / sizeof(SgUctNode) / 2);
        else if (name == "max_time")
            m_player.SetMaxTime(cmd.FloatArg(1));
        else if (name == "max_nodes")
            search.SetMaxNodes(cmd.SizeTypeArg(1, 1));
        else if (name == "num_threads")
            search.SetNumberThreads(cmd.IntArg(1, 0));
        else if (name == "playout_update_radius")
            search.SetPlayoutUpdateRadius(cmd.IntArg(1, 0));
        else if (name == "rave_weight_final")
            search.SetRaveWeightFinal(cmd.IntArg(1, 0));
        else if (name == "rave_weight_initial")
            search.SetRaveWeightInitial(cmd.IntArg(1, 0));
        else if (name == "weight_rave_updates")
            search.SetWeightRaveUpdates(cmd.BoolArg(1));
        else if (name == "tree_update_radius")
            search.SetTreeUpdateRadius(cmd.IntArg(1, 0));
        else if (name == "search_singleton")
            m_player.SetSearchSingleton(cmd.BoolArg(1));
        else if (name == "use_parallel_solver")
            m_useParallelSolver = cmd.BoolArg(1);
        else if (name == "use_time_management")
            m_player.SetUseTimeManagement(cmd.BoolArg(1));
        else
            throw HtpFailure() << "Unknown parameter: " << name;
    }
    else 
        throw HtpFailure("Expected 0 or 2 arguments");
}