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