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