2 Glaurung, a UCI chess playing engine.
3 Copyright (C) 2004-2008 Tord Romstad
5 Glaurung is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 Glaurung is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
31 #include "ucioption.h"
38 bool Chess960
= false;
42 //// Local definitions
51 enum OptionType
{ SPIN
, COMBO
, CHECK
, STRING
, BUTTON
};
53 typedef std::vector
<std::string
> ComboValues
;
57 std::string name
, defaultValue
, currentValue
;
59 int minValue
, maxValue
;
60 ComboValues comboValues
;
62 Option(const char* name
, const char* defaultValue
, OptionType
= STRING
);
63 Option(const char* name
, bool defaultValue
, OptionType
= CHECK
);
64 Option(const char* name
, int defaultValue
, int minValue
, int maxValue
);
67 typedef std::vector
<Option
> Options
;
73 // load_defaults populates the options vector with the hard
74 // coded names and default values.
76 void load_defaults(Options
& o
) {
78 o
.push_back(Option("Use Search Log", false));
79 o
.push_back(Option("Search Log Filename", "SearchLog.txt"));
80 o
.push_back(Option("Book File", "book.bin"));
81 o
.push_back(Option("Mobility (Middle Game)", 100, 0, 200));
82 o
.push_back(Option("Mobility (Endgame)", 100, 0, 200));
83 o
.push_back(Option("Pawn Structure (Middle Game)", 100, 0, 200));
84 o
.push_back(Option("Pawn Structure (Endgame)", 100, 0, 200));
85 o
.push_back(Option("Passed Pawns (Middle Game)", 100, 0, 200));
86 o
.push_back(Option("Passed Pawns (Endgame)", 100, 0, 200));
87 o
.push_back(Option("Aggressiveness", 100, 0, 200));
88 o
.push_back(Option("Cowardice", 100, 0, 200));
89 o
.push_back(Option("King Safety Curve", "Quadratic", COMBO
));
91 o
.back().comboValues
.push_back("Quadratic");
92 o
.back().comboValues
.push_back("Linear"); /*, "From File"*/
94 o
.push_back(Option("King Safety Coefficient", 40, 1, 100));
95 o
.push_back(Option("King Safety X Intercept", 0, 0, 20));
96 o
.push_back(Option("King Safety Max Slope", 30, 10, 100));
97 o
.push_back(Option("King Safety Max Value", 500, 100, 1000));
98 o
.push_back(Option("Queen Contact Check Bonus", 4, 0, 8));
99 o
.push_back(Option("Rook Contact Check Bonus", 2, 0, 4));
100 o
.push_back(Option("Queen Check Bonus", 2, 0, 4));
101 o
.push_back(Option("Rook Check Bonus", 1, 0, 4));
102 o
.push_back(Option("Bishop Check Bonus", 1, 0, 4));
103 o
.push_back(Option("Knight Check Bonus", 1, 0, 4));
104 o
.push_back(Option("Discovered Check Bonus", 3, 0, 8));
105 o
.push_back(Option("Mate Threat Bonus", 3, 0, 8));
106 o
.push_back(Option("Check Extension (PV nodes)", 2, 0, 2));
107 o
.push_back(Option("Check Extension (non-PV nodes)", 1, 0, 2));
108 o
.push_back(Option("Single Reply Extension (PV nodes)", 2, 0, 2));
109 o
.push_back(Option("Single Reply Extension (non-PV nodes)", 2, 0, 2));
110 o
.push_back(Option("Mate Threat Extension (PV nodes)", 0, 0, 2));
111 o
.push_back(Option("Mate Threat Extension (non-PV nodes)", 0, 0, 2));
112 o
.push_back(Option("Pawn Push to 7th Extension (PV nodes)", 1, 0, 2));
113 o
.push_back(Option("Pawn Push to 7th Extension (non-PV nodes)", 1, 0, 2));
114 o
.push_back(Option("Passed Pawn Extension (PV nodes)", 1, 0, 2));
115 o
.push_back(Option("Passed Pawn Extension (non-PV nodes)", 0, 0, 2));
116 o
.push_back(Option("Pawn Endgame Extension (PV nodes)", 2, 0, 2));
117 o
.push_back(Option("Pawn Endgame Extension (non-PV nodes)", 2, 0, 2));
118 o
.push_back(Option("Full Depth Moves (PV nodes)", 14, 1, 100));
119 o
.push_back(Option("Full Depth Moves (non-PV nodes)", 3, 1, 100));
120 o
.push_back(Option("Threat Depth", 5, 0, 100));
121 o
.push_back(Option("Selective Plies", 7, 0, 10));
122 o
.push_back(Option("Futility Pruning (Main Search)", true));
123 o
.push_back(Option("Futility Pruning (Quiescence Search)", true));
124 o
.push_back(Option("Futility Margin 0", 50, 0, 1000));
125 o
.push_back(Option("Futility Margin 1", 100, 0, 1000));
126 o
.push_back(Option("Futility Margin 2", 300, 0, 1000));
127 o
.push_back(Option("Maximum Razoring Depth", 3, 0, 4));
128 o
.push_back(Option("Razoring Margin", 300, 150, 600));
129 o
.push_back(Option("Randomness", 0, 0, 10));
130 o
.push_back(Option("Minimum Split Depth", 4, 4, 7));
131 o
.push_back(Option("Maximum Number of Threads per Split Point", 5, 4, 8));
132 o
.push_back(Option("Threads", 1, 1, 8));
133 o
.push_back(Option("Hash", 32, 4, 4096));
134 o
.push_back(Option("Clear Hash", false, BUTTON
));
135 o
.push_back(Option("Ponder", true));
136 o
.push_back(Option("OwnBook", true));
137 o
.push_back(Option("MultiPV", 1, 1, 500));
138 o
.push_back(Option("UCI_ShowCurrLine", false));
139 o
.push_back(Option("UCI_Chess960", false));
149 Options::iterator
option_with_name(const std::string
& optionName
);
151 // stringify converts a value of type T to a std::string
153 std::string
stringify(const T
& v
) {
155 std::ostringstream ss
;
160 // We want conversion from a bool value to be "true" or "false",
161 // not "1" or "0", so add a specialization for bool type.
163 std::string stringify
<bool>(const bool& v
) {
165 return v
? "true" : "false";
168 // get_option_value implements the various get_option_value_<type>
169 // functions defined later, because only the option value
170 // type changes a template seems a proper solution.
173 T
get_option_value(const std::string
& optionName
) {
176 Options::iterator it
= option_with_name(optionName
);
178 if (it
!= options
.end())
180 std::istringstream
ss(it
->currentValue
);
186 // Unfortunatly we need a specialization to convert "false" and "true"
187 // to proper bool values. The culprit is that we use a non standard way
188 // to store a bool value in a string, in particular we use "false" and
189 // "true" instead of "0" and "1" due to how UCI protocol works.
192 bool get_option_value
<bool>(const std::string
& optionName
) {
194 Options::iterator it
= option_with_name(optionName
);
196 return it
!= options
.end() && it
->currentValue
== "true";
204 /// init_uci_options() initializes the UCI options. Currently, the only
205 /// thing this function does is to initialize the default value of the
206 /// "Threads" parameter to the number of available CPU cores.
208 void init_uci_options() {
210 load_defaults(options
);
212 // Limit the default value of "Threads" to 7 even if we have 8 CPU cores.
213 // According to Ken Dail's tests, Glaurung plays much better with 7 than
214 // with 8 threads. This is weird, but it is probably difficult to find out
215 // why before I have a 8-core computer to experiment with myself.
216 Options::iterator it
= option_with_name("Threads");
218 assert(it
!= options
.end());
220 it
->defaultValue
= stringify(Min(cpu_count(), 7));
221 it
->currentValue
= stringify(Min(cpu_count(), 7));
223 // Increase the minimum split depth when the number of CPUs is big.
224 // It would probably be better to let this depend on the number of threads
228 it
= option_with_name("Minimum Split Depth");
230 assert(it
!= options
.end());
232 it
->defaultValue
= "6";
233 it
->currentValue
= "6";
238 /// print_uci_options() prints all the UCI options to the standard output,
239 /// in the format defined by the UCI protocol.
241 void print_uci_options() {
243 static const char optionTypeName
[][16] = {
244 "spin", "combo", "check", "string", "button"
247 for (Options::iterator it
= options
.begin(); it
!= options
.end(); ++it
)
249 std::cout
<< "option name " << it
->name
250 << " type " << optionTypeName
[it
->type
];
252 if (it
->type
!= BUTTON
)
254 std::cout
<< " default " << it
->defaultValue
;
256 if (it
->type
== SPIN
)
257 std::cout
<< " min " << it
->minValue
258 << " max " << it
->maxValue
;
260 else if (it
->type
== COMBO
)
261 for(ComboValues::iterator itc
= it
->comboValues
.begin();
262 itc
!= it
->comboValues
.end(); ++itc
)
263 std::cout
<< " var " << *itc
;
265 std::cout
<< std::endl
;
269 /// get_option_value_bool() returns the current value of a UCI parameter of
272 bool get_option_value_bool(const std::string
& optionName
) {
274 return get_option_value
<bool>(optionName
);
278 /// get_option_value_int() returns the value of a UCI parameter as an integer.
279 /// Normally, this function will be used for a parameter of type "spin", but
280 /// it could also be used with a "combo" parameter, where all the available
281 /// values are integers.
283 int get_option_value_int(const std::string
& optionName
) {
285 return get_option_value
<int>(optionName
);
289 /// get_option_value_string() returns the current value of a UCI parameter as
290 /// a string. It is used with parameters of type "combo" and "string".
292 const std::string
get_option_value_string(const std::string
& optionName
) {
294 return get_option_value
<std::string
>(optionName
);
298 /// button_was_pressed() tests whether a UCI parameter of type "button" has
299 /// been selected since the last time the function was called.
301 bool button_was_pressed(const std::string
& buttonName
) {
303 if (get_option_value
<bool>(buttonName
))
305 set_option_value(buttonName
, "false");
313 /// set_option_value() inserts a new value for a UCI parameter. Note that
314 /// the function does not check that the new value is legal for the given
315 /// parameter: This is assumed to be the responsibility of the GUI.
317 void set_option_value(const std::string
& optionName
,
318 const std::string
& newValue
) {
320 Options::iterator it
= option_with_name(optionName
);
322 if (it
!= options
.end())
323 it
->currentValue
= newValue
;
325 std::cout
<< "No such option: " << optionName
<< std::endl
;
329 /// push_button() is used to tell the engine that a UCI parameter of type
330 /// "button" has been selected:
332 void push_button(const std::string
& buttonName
) {
334 set_option_value(buttonName
, "true");
340 // Define constructors of Option class.
342 Option::Option(const char* nm
, const char* def
, OptionType t
)
343 : name(nm
), defaultValue(def
), currentValue(def
), type(t
), minValue(0), maxValue(0) {}
345 Option::Option(const char* nm
, bool def
, OptionType t
)
346 : name(nm
), defaultValue(stringify(def
)), currentValue(stringify(def
)), type(t
), minValue(0), maxValue(0) {}
348 Option::Option(const char* nm
, int def
, int minv
, int maxv
)
349 : name(nm
), defaultValue(stringify(def
)), currentValue(stringify(def
)), type(SPIN
), minValue(minv
), maxValue(maxv
) {}
351 // option_with_name() tries to find a UCI option with a given
352 // name. It returns an iterator to the UCI option or to options.end(),
353 // depending on whether an option with the given name exists.
355 Options::iterator
option_with_name(const std::string
& optionName
) {
357 for (Options::iterator it
= options
.begin(); it
!= options
.end(); ++it
)
358 if (it
->name
== optionName
)
361 return options
.end();