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