/*1Stockfish, a UCI chess playing engine derived from Glaurung 2.12Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)34Stockfish is free software: you can redistribute it and/or modify5it under the terms of the GNU General Public License as published by6the Free Software Foundation, either version 3 of the License, or7(at your option) any later version.89Stockfish is distributed in the hope that it will be useful,10but WITHOUT ANY WARRANTY; without even the implied warranty of11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12GNU General Public License for more details.1314You should have received a copy of the GNU General Public License15along with this program. If not, see <http://www.gnu.org/licenses/>.16*/1718#include "tune.h"1920#include <algorithm>21#include <iostream>22#include <map>23#include <optional>24#include <sstream>25#include <string>2627#include "ucioption.h"2829using std::string;3031namespace Stockfish {3233bool Tune::update_on_last;34const Option* LastOption = nullptr;35OptionsMap* Tune::options;36namespace {37std::map<std::string, int> TuneResults;3839std::optional<std::string> on_tune(const Option& o) {4041if (!Tune::update_on_last || LastOption == &o)42Tune::read_options();4344return std::nullopt;45}46}4748void Tune::make_option(OptionsMap* opts, const string& n, int v, const SetRange& r) {4950// Do not generate option when there is nothing to tune (ie. min = max)51if (r(v).first == r(v).second)52return;5354if (TuneResults.count(n))55v = TuneResults[n];5657opts->add(n, Option(v, r(v).first, r(v).second, on_tune));58LastOption = &((*opts)[n]);5960// Print formatted parameters, ready to be copy-pasted in Fishtest61std::cout << n << "," //62<< v << "," //63<< r(v).first << "," //64<< r(v).second << "," //65<< (r(v).second - r(v).first) / 20.0 << "," //66<< "0.0020" << std::endl;67}6869string Tune::next(string& names, bool pop) {7071string name;7273do74{75string token = names.substr(0, names.find(','));7677if (pop)78names.erase(0, token.size() + 1);7980std::stringstream ws(token);81name += (ws >> token, token); // Remove trailing whitespace8283} while (std::count(name.begin(), name.end(), '(') - std::count(name.begin(), name.end(), ')'));8485return name;86}878889template<>90void Tune::Entry<int>::init_option() {91make_option(options, name, value, range);92}9394template<>95void Tune::Entry<int>::read_option() {96if (options->count(name))97value = int((*options)[name]);98}99100// Instead of a variable here we have a PostUpdate function: just call it101template<>102void Tune::Entry<Tune::PostUpdate>::init_option() {}103template<>104void Tune::Entry<Tune::PostUpdate>::read_option() {105value();106}107108} // namespace Stockfish109110111// Init options with tuning session results instead of default values. Useful to112// get correct bench signature after a tuning session or to test tuned values.113// Just copy fishtest tuning results in a result.txt file and extract the114// values with:115//116// cat results.txt | sed 's/^param: \([^,]*\), best: \([^,]*\).*/ TuneResults["\1"] = int(round(\2));/'117//118// Then paste the output below, as the function body119120121namespace Stockfish {122123void Tune::read_results() { /* ...insert your values here... */ }124125} // namespace Stockfish126127128