version 1.4.46b
[polyglot.git] / option.c
1 \r
2 // option.c\r
3 \r
4 // includes\r
5 \r
6 #include <stdlib.h>\r
7 #include <string.h>\r
8 \r
9 #include "option.h"\r
10 #include "util.h"\r
11 \r
12 // constants\r
13 \r
14 static const bool UseDebug = FALSE;\r
15 static const int  StringSize = 4096;\r
16 \r
17 // variables\r
18 \r
19 #define NNB { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL }\r
20 \r
21 option_list_t Option[1];\r
22 \r
23 option_t DefaultOptions[] = {    \r
24     { "OptionFile",       "file","0","0",     "polyglot.ini", NULL,0,NNB,  PG}, \r
25 \r
26    // options\r
27 \r
28     { "Persist",          "check","0","0",      "true"      , NULL,0,NNB,  PG|XBOARD},\r
29     { "PersistFile",      "file","0","0",     "<empty>"   , NULL,0,NNB,  PG},\r
30     { "PersistDir",       "path","0","0",     "<empty>"   , NULL,0,NNB,  PG},\r
31     \r
32     { "EngineName",       "string","0","0",     "<empty>"   , NULL,0,NNB,  PG}, \r
33     { "EngineDir",        "path","0","0",     "."         , NULL,0,NNB,  PG}, \r
34     { "EngineCommand",    "string","0","0",     "<empty>"   , NULL,0,NNB,  PG}, \r
35 \r
36     { "Log",              "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD|UCI}, \r
37     { "LogFile",          "file","0","0",     "polyglot.log", NULL,0,NNB,  PG|XBOARD|UCI}, \r
38 \r
39     { "UCI",              "check","0","0",      "false"     , NULL,0,NNB,  PG}, \r
40 \r
41     { "UseNice",          "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD|UCI}, \r
42     { "NiceValue",        "spin", "0","20",     "5"         , NULL,0,NNB,  PG|XBOARD|UCI}, \r
43 \r
44     { "Chess960",         "check","0","0",      "false"     , NULL,0,NNB,  PG}, \r
45 \r
46     { "Resign",           "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
47     { "ResignMoves",      "spin","0","10000",    "3"        , NULL,0,NNB,  PG|XBOARD}, \r
48     { "ResignScore",      "spin","0","10000",   "600"       , NULL,0,NNB,  PG|XBOARD}, \r
49 \r
50     { "MateScore",        "spin","0","100000",  "10000"     , NULL,0,NNB,  PG|XBOARD}, \r
51 \r
52     { "Book",             "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD|UCI}, \r
53     { "BookFile",         "file","0","0",     "book.bin"  , NULL,0,NNB,  PG|XBOARD|UCI}, \r
54 \r
55     { "BookRandom",       "check","0","0",      "true"      , NULL,0,NNB,  PG|XBOARD|UCI}, \r
56     { "BookDepth",        "spin","0","256",     "256"       , NULL,0,NNB,  PG|XBOARD}, \r
57     { "BookTreshold",     "spin","0","1000",    "5"         , NULL,0,NNB,  PG|XBOARD|UCI}, \r
58     { "BookLearn",        "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
59 \r
60     { "KibitzMove",       "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
61     { "KibitzPV",         "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
62 \r
63     { "KibitzCommand",    "string","0","0",     "tellall"   , NULL,0,NNB,  PG|XBOARD}, \r
64     { "KibitzDelay",      "spin","0","1000",    "5"         , NULL,0,NNB,  PG|XBOARD}, \r
65     { "KibitzInterval",   "spin","0","1000",    "0"         , NULL,0,NNB,  PG|XBOARD}, \r
66 \r
67     { "ShowPonder",       "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
68     { "ScoreWhite",       "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
69 \r
70    // work-arounds\r
71 \r
72     { "UCIVersion",       "spin","1","2",       "2"         , NULL,0,NNB,  PG|XBOARD}, \r
73     { "CanPonder",        "check","1","2",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
74     { "SyncStop",         "check","1","2",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
75     { "Affinity",         "spin","-1","32",     "-1"        , NULL,0,NNB,  PG}, \r
76     { "RepeatPV",         "check","0","0",      "true"      , NULL,0,NNB,  PG|XBOARD},\r
77     { "PromoteWorkAround","check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
78 \r
79     { "WbWorkArounds",    "check","0","0",      "true"      , NULL,0,NNB,  PG|XBOARD}, \r
80     { "WbWorkArounds2",   "check","0","0",      "false"     , NULL,0,NNB,  PG|XBOARD}, \r
81 \r
82     // Buttons\r
83 \r
84 //    { "Defaults",         "reset","0","0",     "false"     , NULL,0,NNB,  PG|XBOARD},\r
85 \r
86     { NULL,               NULL,"0","0",         NULL        , NULL,0,NNB,  0},\r
87 \r
88 };\r
89 \r
90 \r
91 // functions\r
92 \r
93 // option_is_ok()\r
94 \r
95 bool option_is_ok(const option_list_t *option) {\r
96     if(option->option_nb<0 || option->option_nb>=OptionNb){\r
97         return FALSE;\r
98     }\r
99     return TRUE;\r
100 }\r
101 \r
102 // option_init_pg()\r
103 \r
104 void option_init_pg() {\r
105 \r
106     int i;\r
107     option_t *p=DefaultOptions;\r
108     char *home_dir;\r
109     char PersistDir[StringSize];\r
110     \r
111     option_init(Option);\r
112     while(p){\r
113         if(p->name){\r
114             option_insert(Option,p);\r
115             p++;\r
116         }else{\r
117             break;\r
118         }\r
119     }\r
120     for(i=0;i<Option->option_nb;i++){\r
121         Option->options[i].value=my_strdup(Option->options[i].default_);\r
122     }\r
123 #ifndef _WIN32\r
124     home_dir=getenv("HOME");\r
125     if(!home_dir){\r
126         home_dir=".";\r
127     }\r
128     snprintf(PersistDir,sizeof(PersistDir),"%s/.polyglot",home_dir);\r
129     PersistDir[sizeof(PersistDir)-1]='\0';\r
130 #else\r
131     sprintf(PersistDir,".\\_PG");\r
132 #endif\r
133     option_set(Option,"PersistDir",PersistDir);\r
134     option_set_default(Option,"PersistDir",PersistDir);\r
135 }\r
136 \r
137 // option_init()\r
138 \r
139 void option_init(option_list_t *option){\r
140     ASSERT(option!=NULL);\r
141     option->option_nb=0;\r
142     option->iter=0;\r
143     memset(option->options,0,sizeof(option->options));\r
144 }\r
145 \r
146 // option_insert()\r
147 \r
148 void option_insert(option_list_t *option, option_t *new_option){\r
149     int i;\r
150     option_t *opt;\r
151     ASSERT(option!=NULL);\r
152     ASSERT(new_option!=NULL);\r
153     ASSERT(new_option->name!=NULL);\r
154     opt=option_find(option,new_option->name);\r
155     if(!opt){\r
156         opt=&option->options[option->option_nb];\r
157         option->option_nb++;\r
158     }\r
159     if(option->option_nb>=OptionNb){\r
160         my_fatal("option_insert(): option list overflow\n");\r
161     }\r
162     if(new_option->name)     my_string_set(&opt->name,     new_option->name);\r
163     if(new_option->value)    my_string_set(&opt->value,    new_option->value);\r
164     if(new_option->min)      my_string_set(&opt->min,      new_option->min);\r
165     if(new_option->max)      my_string_set(&opt->max,      new_option->max);\r
166     if(new_option->default_) my_string_set(&opt->default_, new_option->default_);\r
167     if(new_option->type)     my_string_set(&opt->type,     new_option->type);\r
168     opt->var_nb=new_option->var_nb;\r
169     for(i=0;i<new_option->var_nb;i++){\r
170         my_string_set(&opt->var[i], new_option->var[i]);\r
171     }\r
172     opt->mode=new_option->mode;\r
173 }\r
174 \r
175 // option_set()\r
176 \r
177 bool option_set(option_list_t *option, \r
178                 const char name[], \r
179                 const char value[]) {\r
180 \r
181    option_t * opt;\r
182    ASSERT(option!=NULL);\r
183    ASSERT(name!=NULL);\r
184    ASSERT(value!=NULL);\r
185 \r
186    opt = option_find(option,name);\r
187    if (opt == NULL) return FALSE;\r
188 \r
189    if(my_string_case_equal(opt->type,"check")){\r
190       value=(my_string_equal(value,"1")||\r
191              my_string_case_equal(value,"true"))?"true":"false";\r
192    }\r
193 \r
194    my_string_set(&opt->value,value);\r
195 \r
196    if (UseDebug) my_log("POLYGLOT OPTION SET \"%s\" -> \"%s\"\n",opt->name,opt->value);\r
197 \r
198    return TRUE;\r
199 }\r
200 \r
201 // option_set_default()\r
202 \r
203 bool option_set_default(option_list_t *option,\r
204                            const char name[], \r
205                            const char value[]) {\r
206 \r
207    option_t * opt;\r
208    ASSERT(name!=NULL);\r
209    ASSERT(value!=NULL);\r
210 \r
211    opt = option_find(option,name);\r
212    if (opt == NULL) return FALSE;\r
213 \r
214    if(my_string_case_equal(opt->type,"check")){\r
215       value=(my_string_equal(value,"1")||\r
216              my_string_case_equal(value,"true"))?"true":"false";\r
217    }\r
218 \r
219    my_string_set(&opt->default_,value);\r
220 \r
221    if (UseDebug) my_log("POLYGLOT OPTION DEFAULT SET \"%s\" -> \"%s\"\n",opt->name,opt->default_);\r
222 \r
223    return TRUE;\r
224 }\r
225 \r
226 // option_get()\r
227 \r
228 const char * option_get(option_list_t *option, const char name[]) {\r
229 \r
230    option_t * opt;\r
231 \r
232    ASSERT(name!=NULL);\r
233 \r
234    opt = option_find(option,name);\r
235    if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",name);\r
236    if (UseDebug) my_log("POLYGLOT OPTION GET \"%s\" -> \"%s\"\n",opt->name,opt->value);\r
237 \r
238    return opt->value;\r
239 }\r
240 \r
241 // option_get_default()\r
242 \r
243 const char * option_get_default(option_list_t *option, const char name[]) {\r
244 \r
245    option_t * opt;\r
246 \r
247    ASSERT(name!=NULL);\r
248 \r
249    opt = option_find(option,name);\r
250    if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",name);\r
251 \r
252    if (UseDebug) my_log("POLYGLOT OPTION GET \"%s\" -> \"%s\"\n",opt->name,opt->value);\r
253 \r
254    return opt->default_;\r
255 }\r
256 \r
257 // option_get_bool()\r
258 \r
259 bool option_get_bool(option_list_t *option, const char name[]) {\r
260 \r
261    const char * value;\r
262 \r
263    value = option_get(option,name);\r
264 \r
265    if (FALSE) {\r
266    } else if (my_string_case_equal(value,"true") || my_string_case_equal(value,"yes") || my_string_equal(value,"1")) {\r
267       return TRUE;\r
268    } else if (my_string_case_equal(value,"false") || my_string_case_equal(value,"no") || my_string_equal(value,"0")) {\r
269       return FALSE;\r
270    }\r
271 \r
272    ASSERT(FALSE);\r
273 \r
274    return FALSE;\r
275 }\r
276 \r
277 \r
278 // option_get_double()\r
279 \r
280 double option_get_double(option_list_t *option, const char name[]) {\r
281 \r
282    const char * value;\r
283 \r
284    value = option_get(option,name);\r
285 \r
286    return atof(value);\r
287 }\r
288 \r
289 // option_get_int()\r
290 \r
291 int option_get_int(option_list_t *option, const char name[]) {\r
292 \r
293    const char * value;\r
294 \r
295    value = option_get(option,name);\r
296 \r
297    return atoi(value);\r
298 }\r
299 \r
300 // option_get_string()\r
301 \r
302 const char * option_get_string(option_list_t *option, const char name[]) {\r
303 \r
304    const char * value;\r
305 \r
306    value = option_get(option,name);\r
307 \r
308    return value;\r
309 }\r
310 \r
311 // option_find()\r
312 \r
313 option_t * option_find(option_list_t *option, const char name[]) {\r
314 \r
315    option_t * opt;\r
316    int i;\r
317 \r
318    ASSERT(name!=NULL);\r
319    for (i=0; i<option->option_nb; i++){\r
320        opt=option->options+i;\r
321        if (my_string_case_equal(opt->name,name)){\r
322            return opt;\r
323        }\r
324    }\r
325    \r
326    return NULL;\r
327 }\r
328 \r
329 // option_start_iter()\r
330 \r
331 void option_start_iter(option_list_t *option){\r
332     option->iter=0;\r
333 }\r
334 \r
335 // option_next()\r
336 \r
337 option_t * option_next(option_list_t *option){\r
338     ASSERT(option->iter<=option->option_nb);\r
339     if(option->iter==option->option_nb){\r
340         return NULL;\r
341     }\r
342     return &option->options[option->iter++];\r
343         \r
344 }\r
345 \r
346 void option_free(option_t *option){\r
347       int i;\r
348       my_string_clear(&option->name);\r
349       my_string_clear(&option->type);\r
350       my_string_clear(&option->min);\r
351       my_string_clear(&option->max);\r
352       my_string_clear(&option->default_);\r
353       my_string_clear(&option->value);\r
354       for(i=0;i<option->var_nb;i++){\r
355          my_string_clear(&option->var[i]);\r
356       }\r
357       option->var_nb=0;\r
358       option->mode=0;\r
359 }\r
360 \r
361 // option_clear()\r
362 \r
363 void option_clear(option_list_t *option){\r
364     int i;\r
365     for (i = 0; i < option->option_nb; i++) {\r
366         option_free(option->options+i);\r
367    }\r
368    option->option_nb=0;\r
369 }\r
370 \r
371 // option_from_ini()\r
372 \r
373 void option_from_ini(option_list_t *option,\r
374                      ini_t *ini,\r
375                      const char *section){\r
376     ini_entry_t *entry;\r
377     ini_start_iter(ini);\r
378     while((entry=ini_next(ini))){\r
379         option_set(option,entry->name,entry->value);\r
380         option_set_default(option,entry->name,entry->value);\r
381     }\r
382 }\r
383 \r
384 // end of option.cpp\r
385 \r