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