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