Update codebase to remove clang warnings (and a couple of legit errors
[typhoon.git] / src / vars.c
1 /**
2
3 Copyright (c) Scott Gasch
4
5 Module Name:
6
7     vars.c
8
9 Abstract:
10
11     This is code that implements variables in the engine.  Some of
12     these variables are read only but others can be set by the engine
13     user to affect certain aspects of engine operation.
14
15 Author:
16
17     Scott Gasch ([email protected]) 18 May 2004
18
19 Revision History:
20
21     $Id: vars.c 354 2008-06-30 05:10:08Z scott $
22
23 **/
24
25 #include "chess.h"
26
27 extern ULONG g_uNumInputEvents;
28
29 typedef void(PUSERVARFUN)(void);
30
31 //
32 // Here's how we expose engine variables to the user.
33 // 
34 typedef struct _USER_VARIABLE
35 {
36     char *szName;                             // variable name
37     char *szType;                             // variable type:
38                                               //   * - char *, strdup/free
39                                               //   H - hash size
40                                               //   B - boolean
41                                               //   U - unsigned
42                                               //   I - int
43                                               //   M - move
44                                               //   D - double
45                                               //   S - string buffer
46     void *pValue;                             // pointer to value
47     PUSERVARFUN *pFunction;                   // funct to call when it changes
48 } USER_VARIABLE;
49
50 extern ULONG g_uBookProbeFailures;
51
52 USER_VARIABLE g_UserVarList[] = 
53 {
54     { "AnnounceOpening",
55       "B",
56       (void *)&(g_Options.fShouldAnnounceOpening),
57       NULL },
58     { "BatchMode",
59       "b",
60       (void *)&(g_Options.fNoInputThread),
61       NULL },
62     { "BlackPlayer",
63       "*",
64       (void *)&(g_GameData.sHeader.sPlayer[BLACK].szName),
65       NULL },
66     { "BlackRating",
67       "U",
68       (void *)&(g_GameData.sHeader.sPlayer[BLACK].uRating),
69       NULL },
70     { "BlackDescription",
71       "*",
72       (void *)&(g_GameData.sHeader.sPlayer[BLACK].szDescription),
73       NULL },
74     { "BlackIsComputer",
75       "B",
76       (void *)&(g_GameData.sHeader.sPlayer[BLACK].fIsComputer),
77       NULL },
78     { "BookFileName",
79       "S",
80       (void *)&(g_Options.szBookName),
81       NULL },
82     { "BookProbeFailures",
83       "u",
84       (void *)&(g_uBookProbeFailures),
85       NULL },
86     { "ComputerTimeRemainingSec",
87       "U",
88       (void *)&(g_Options.uOpponentsClock),
89       NULL }, //&DoVerifyClocks },
90     { "EGTBPath",
91       "S",
92       (void *)&(g_Options.szEGTBPath),
93       InitializeEGTB },
94     { "FastScript",
95       "B",
96       (void *)&(g_Options.fFastScript),
97       NULL },
98     { "GameDescription",
99       "*",
100       (void *)&(g_GameData.sHeader.szGameDescription),
101       NULL },
102     { "GameLocation",
103       "*",
104       (void *)&(g_GameData.sHeader.szLocation),
105       NULL },
106     { "GameIsRated",
107       "B",
108       (void *)&(g_GameData.sHeader.fGameIsRated),
109       NULL },
110     { "GameResultComment",
111       "*",
112       (void *)&(g_GameData.sHeader.result.szDescription),
113       NULL },
114     { "LastEval",
115       "I",
116       (void *)&(g_Options.iLastEvalScore),
117       NULL },
118     { "LogfileName",
119       "S",
120       (void *)&(g_Options.szLogfile),
121       NULL },
122     { "MoveToPonder",
123       "m",
124       (void *)&(g_Options.mvPonder),
125       NULL },
126     { "MovesPerTimePeriod",
127       "U",
128       (void *)&(g_Options.uMovesPerTimePeriod),
129       NULL },
130     { "OpponentTimeRemainingSec",
131       "U",
132       (void *)&(g_Options.uMyClock),
133       NULL }, //&DoVerifyClocks },
134     { "PendingInputEvents",
135       "u",
136       (void *)&(g_uNumInputEvents),
137       NULL },
138     { "PonderingNow",
139       "b", 
140       (void *)&(g_Options.fPondering),
141       NULL },
142     { "PostLines",
143       "B",
144       (void *)&(g_Options.fShouldPost),
145       NULL },
146     { "ResignThreshold",
147       "I",
148       (void *)&(g_Options.iResignThreshold),
149       NULL },
150     { "SearchDepthLimit",
151       "U",
152       (void *)&(g_Options.uMaxDepth),
153       NULL }, //&DoVerifySearchDepth },
154     { "SearchTimeLimit",
155       "U",
156       (void *)&(g_Options.uMyIncrement),
157       NULL }, //&DoVerifySearchTime },
158     { "SearchStartedTime",
159       "d",
160       (void *)&(g_MoveTimer.dStartTime),
161       NULL },
162     { "SearchSoftTimeLimit",
163       "d",
164       (void *)&(g_MoveTimer.dSoftTimeLimit),
165       NULL },
166     { "SearchHardTimeLimit",
167       "d",
168       (void *)&(g_MoveTimer.dHardTimeLimit),
169       NULL },
170     { "SearchNodesBetweenTimeCheck",
171       "u",
172       (void *)&(g_MoveTimer.uNodeCheckMask),
173       NULL },
174     { "StatusLine",
175       "B",
176       (void *)&(g_Options.fStatusLine),
177       NULL },
178     { "ThinkOnOpponentsTime",
179       "B",
180       (void *)&(g_Options.fShouldPonder),
181       NULL },
182     { "ThinkingNow",
183       "b",
184       (void *)&(g_Options.fThinking),
185       NULL },
186     { "TournamentMode",
187       "B",
188       (void *)&(g_fTournamentMode),
189       NULL },
190     { "VerbosePosting",
191       "B",
192       (void *)&(g_Options.fVerbosePosting),
193       NULL },
194     { "WhitePlayer",
195       "*",
196       (void *)&(g_GameData.sHeader.sPlayer[WHITE].szName),
197       NULL },
198     { "WhiteRating",
199       "U",
200       (void *)&(g_GameData.sHeader.sPlayer[WHITE].uRating),
201       NULL },
202     { "WhiteDescription",
203       "*",
204       (void *)&(g_GameData.sHeader.sPlayer[WHITE].szDescription),
205       NULL },
206     { "WhiteIsComputer",
207       "B",
208       (void *)&(g_GameData.sHeader.sPlayer[WHITE].fIsComputer),
209       NULL },
210     { "Xboard",
211       "B",
212       (void *)&(g_Options.fRunningUnderXboard),
213       NULL }
214 };
215
216
217
218
219 COMMAND(SetCommand)
220 /**
221
222 Routine description:
223
224     This function implements the 'set' engine command.  
225
226     Usage:
227     
228         set [variable name [value]]
229
230         With no arguments, set dumps a list of all variables and their
231         current values.
232
233         With one argument, set displays the specified variable's value.
234
235         With two arguments, set changes the value of the specified 
236         variable to the given value.
237
238 Parameters:
239
240     The COMMAND macro hides four arguments from the input parser:
241
242         CHAR *szInput : the full line of input
243         ULONG argc    : number of argument chunks
244         CHAR *argv[]  : array of ptrs to each argument chunk
245         POSITION *pos : a POSITION pointer to operate on
246
247 Return value:
248
249     void
250
251 **/
252 {
253     ULONG x, y;
254     FLAG fFound;
255     
256     if (argc == 1)
257     {
258         for (x = 0;
259              x < ARRAY_SIZE(g_UserVarList);
260              x++)
261         {
262             switch(toupper(g_UserVarList[x].szType[0]))
263             {
264                 case 'H':
265                 case 'U':
266                     Trace("%-28s => %u\n", 
267                           g_UserVarList[x].szName,
268                           *((unsigned int *)g_UserVarList[x].pValue));
269                     break;
270                 case 'I':
271                     Trace("%-28s => %d\n",
272                           g_UserVarList[x].szName,
273                           *((int *)g_UserVarList[x].pValue));
274                     break;
275                 case 'S':
276                     Trace("%-28s => \"%s\"\n",
277                           g_UserVarList[x].szName,
278                           (char *)g_UserVarList[x].pValue);
279                     break;
280                 case 'M':
281                     Trace("%-28s => \"%s\"\n",
282                           g_UserVarList[x].szName,
283                           MoveToIcs(*((MOVE *)g_UserVarList[x].pValue)));
284                     break;
285                 case 'B':
286                     Trace("%-28s => \"%s\"\n",
287                           g_UserVarList[x].szName,
288                           (*((FLAG *)g_UserVarList[x].pValue) == TRUE) ?
289                           "TRUE" : "FALSE");
290                     break;
291                 case 'D':
292                     Trace("%-28s => %f\n",
293                           g_UserVarList[x].szName,
294                           *((double *)g_UserVarList[x].pValue));
295                     break;
296                 case '*':
297                     Trace("%-28s => \"%s\"\n",
298                           g_UserVarList[x].szName,
299                           *((char **)g_UserVarList[x].pValue));
300                     break;
301                 default:
302                     Trace("%-28s => ???\n",
303                           g_UserVarList[x].szName);
304                     // ASSERT(FALSE);
305                     break;
306             }
307         }
308         return;
309     }
310     else if (argc == 2)
311     {
312         fFound = FALSE;
313         for (x = 0;
314              x < ARRAY_SIZE(g_UserVarList);
315              x++)
316         {
317             if (!STRNCMPI(argv[1], 
318                           g_UserVarList[x].szName,
319                           strlen(argv[1])))
320             {
321                 fFound = TRUE;
322                 switch(toupper(g_UserVarList[x].szType[0]))
323                 {
324                     case 'H':
325                     case 'U':
326                         Trace("%-28s => %u\n", 
327                               g_UserVarList[x].szName,
328                               *((unsigned int *)g_UserVarList[x].pValue));
329                         break;
330                     case 'I':
331                         Trace("%-28s => %d\n",
332                               g_UserVarList[x].szName,
333                               *((int *)g_UserVarList[x].pValue));
334                         break;
335                     case 'S':
336                         Trace("%-28s => \"%s\"\n",
337                               g_UserVarList[x].szName,
338                               (char *)g_UserVarList[x].pValue);
339                         break;
340                     case 'M':
341                         Trace("%-28s => \"%s\"\n",
342                               g_UserVarList[x].szName,
343                               MoveToIcs(*((MOVE *)g_UserVarList[x].pValue)));
344                         break;
345                     case 'B':
346                         Trace("%-28s => \"%s\"\n",
347                               g_UserVarList[x].szName,
348                               (*((FLAG *)g_UserVarList[x].pValue) == TRUE) ?
349                               "TRUE" : "FALSE");
350                         break;
351                     case 'D':
352                         Trace("%-28s => %f\n",
353                               g_UserVarList[x].szName,
354                               *((double *)g_UserVarList[x].pValue));
355                         break;
356                     case '*':
357                         Trace("%-28s => \"%s\"\n",
358                               g_UserVarList[x].szName,
359                               *((char **)g_UserVarList[x].pValue));
360                         break;
361                     default:
362                         Trace("%-28s => ???\n",
363                               g_UserVarList[x].szName);
364                         // ASSERT(FALSE);
365                         break;
366                 }
367             }
368         }
369         
370         if (FALSE == fFound)
371         {
372             Trace("Error (invalid variable): %s\n", argv[1]);
373         }
374         return;
375     }
376     else 
377     {
378         ASSERT(argc > 2);
379         
380         fFound = FALSE;
381         
382         for (x = 0;
383              x < ARRAY_SIZE(g_UserVarList);
384              x++)
385         {
386             if (!STRNCMPI(argv[1], 
387                          g_UserVarList[x].szName,
388                          strlen(argv[1])))
389             {
390                 fFound = TRUE;
391                 
392                 if (islower(g_UserVarList[x].szType[0]))
393                 {
394                     Trace("Error (variable is read only): %s\n",
395                           argv[1]);
396                 }
397                 
398                 switch(g_UserVarList[x].szType[0])
399                 {
400                     case 'H':
401                         y = atoi(argv[2]);
402                         if ((y < 0) || (y & (y - 1)))
403                         {
404                             Trace("Error (invalid size): %d\n", y);
405                         }
406                         else
407                         {
408                             *((int *)g_UserVarList[x].pValue) = y;
409                         }
410                         break;
411                         
412                     case '*':
413                         if (NULL != *((char **)g_UserVarList[x].pValue))
414                         {
415                             SystemFreeMemory( *((char **)g_UserVarList[x].pValue ) );
416                         }
417                         *((char **)g_UserVarList[x].pValue) = STRDUP(argv[2]);
418                         if (NULL == *((char **)g_UserVarList[x].pValue))
419                         {
420                             Trace("Error (out of memory)\n");
421                             return;
422                         }
423                         break;
424                         
425                     case 'S':
426                         strncpy(((char *)g_UserVarList[x].pValue),
427                                 argv[2], 
428                                 127);
429                         break;
430                         
431                     case 'U':
432                         y = atoi(argv[2]);
433                         if (y < 0)
434                         {
435                             Trace("Error (invalid value): %d\n", y);
436                             return;
437                         }
438                         *((unsigned *)g_UserVarList[x].pValue) = y;
439                         break;
440
441                     case 'I':
442                         y = atoi(argv[2]);
443                         *((int *)g_UserVarList[x].pValue) = y;
444                         break;
445                         
446                     case 'B':
447                         if (toupper(*(argv[2])) == 'T')
448                         {
449                             *((FLAG *)g_UserVarList[x].pValue) = TRUE;
450                         }
451                         else if (toupper(*(argv[2])) == 'F')
452                         {
453                             *((FLAG *)g_UserVarList[x].pValue) = FALSE;
454                         }
455                         else
456                         {
457                             Trace("Error (invalid value, must be TRUE or "
458                                   "FALSE): %s\n", argv[2]);
459                         }
460                         break;
461                         
462                     default:
463                         ASSERT(FALSE);
464                         break;
465                 }
466                 
467                 if (NULL != g_UserVarList[x].pFunction)
468                 {
469                     (void)(g_UserVarList[x].pFunction)();
470                 }
471             }
472         }
473         
474         if (FALSE == fFound)
475         {
476             Trace("Error (invalid variable): %s\n", argv[1]);
477         }
478     }
479 }
480
481 //
482 // TODO: unset?
483 //