2dd78b8ee8285af902ed4e12fd40a82b79899f52
[gnushogi.git] / gnushogi / main.c
1 /*
2  * FILE: main.c
3  *
4  * ----------------------------------------------------------------------
5  * Copyright (c) 1993, 1994, 1995 Matthias Mutz
6  * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
7  *
8  * GNU SHOGI is based on GNU CHESS
9  *
10  * Copyright (c) 1988, 1989, 1990 John Stanback
11  * Copyright (c) 1992 Free Software Foundation
12  *
13  * This file is part of GNU SHOGI.
14  *
15  * GNU Shogi is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the
17  * Free Software Foundation; either version 3 of the License,
18  * or (at your option) any later version.
19  *
20  * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
21  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with GNU Shogi; see the file COPYING. If not, see
27  * <http://www.gnu.org/licenses/>.
28  * ----------------------------------------------------------------------
29  *
30  */
31
32 #include "gnushogi.h"
33
34 #include <signal.h>
35
36
37 void print_arglist(int argc, char **argv)
38 {
39     int i;
40
41     for (i = 0; i < argc; i++)
42         printf("argv[%d] = %s\n", i, argv[i]);
43
44     printf("\n");
45 }
46
47
48 int
49 main (int argc, char **argv)
50 {
51     /*
52      * Process command-line arguments.
53      */
54
55     /* Get rid of the program name. */
56
57     argc--;
58     argv++;
59
60     /* CHECKME: get rid of the '+' syntax? */
61
62     while ((argc > 0) && ((argv[0][0] == '-') || (argv[0][0] == '+')))
63     {
64         switch (argv[0][1])
65         {
66         case 'a':
67             /* Need the "+" syntax here... */
68             ahead = ((argv[0][0] == '-') ? false : true);
69             break;
70
71
72         case 'b':
73             argc--;
74             argv++;
75
76             if (argc > 0)
77             {
78                 bookfile = argv[0];
79 #ifdef BINBOOK
80                 binbookfile = NULL;
81 #endif
82             }
83
84             break;
85
86 #ifdef BINBOOK
87         case 'B':
88             argc--;
89             argv++;
90
91             if (argc > 0)
92                 binbookfile = argv[0];
93
94             break;
95 #endif
96
97 #ifdef HAVE_LIBCURSES
98         case 'C':
99             /* Curses interface. */
100             display_type = DISPLAY_CURSES;
101
102             break;
103 #endif
104
105         case 'h':
106             /* Need the "+" syntax here... */
107             hash = ((argv[0][0] == '-') ? false : true);
108             break;
109
110
111         case 'l':
112             argc--;
113             argv++;
114
115             if (argc > 0)
116                 Lang = argv[0];
117
118             break;
119
120
121         case 'L':
122             argc--;
123             argv++;
124
125             if (argc > 0)
126                 strcpy(listfile, argv[0]);
127             break;
128
129
130         case 's':
131             argc--;
132             argv++;
133
134             if (argc > 0)
135                 strcpy(savefile, argv[0]);
136
137             break;
138
139
140         case 'P':
141             argc--;
142             argv++;
143
144             if (argc > 0)
145                 bookmaxply = atoi(argv[0]);
146
147             break;
148
149
150         case 'R':
151             /* Raw text interface. */
152             display_type = DISPLAY_RAW;
153
154             break;
155
156
157         case 'S':
158             argc--;
159             argv++;
160
161             if (argc > 0)
162                 booksize = atoi(argv[0]);
163             break;
164
165 #if ttblsz
166         case 'r':
167             argc--;
168             argv++;
169
170             if (argc > 0)
171                 rehash = atoi(argv[0]);
172
173             if (rehash > MAXrehash)
174                 rehash = MAXrehash;
175
176             break;
177
178
179         case 'T':
180             argc--;
181             argv++;
182
183             if (argc > 0)
184                 ttblsize = atoi(argv[0]);
185
186             if ((ttblsize <= MINTTABLE))
187                 ttblsize = (MINTTABLE) + 1;
188
189             break;
190
191 #ifdef HASHFILE
192         case 'c':   /* Create or test persistent transposition table. */
193             argc--;
194             argv++;
195
196             if (argc > 0)
197                 filesz = atoi(argv[0]);
198             else
199                 filesz = vfilesz;
200
201             if ((filesz > 0) && (filesz < 24))
202                 filesz = (1 << filesz) - 1 + MAXrehash;
203             else
204                 filesz = filesz + MAXrehash;
205
206             if ((hashfile = fopen(HASHFILE, RWA_ACC)) == NULL)
207                 hashfile = fopen(HASHFILE, WA_ACC);
208
209             if (hashfile != NULL)
210             {
211                 long j;
212                 struct fileentry n;
213
214                 fputs("Filling transposition file, wait!\n", stdout);
215                 n.f = n.t = 0;
216                 n.flags = 0;
217                 n.depth = 0;
218                 n.sh = n.sl = 0;
219
220                 for (j = 0; j < filesz + 1; j++)
221                     fwrite(&n, sizeof(struct fileentry), 1, hashfile);
222
223                 fclose(hashfile);
224             }
225             else
226             {
227                 printf("Create failed for %s\n", HASHFILE);
228             }
229
230             return 0;
231
232
233         case 't':   /* Create or test persistent transposition table. */
234             hashfile = fopen(HASHFILE, RWA_ACC);
235
236             if (hashfile)
237             {
238                 fseek(hashfile, 0L, SEEK_END);
239                 filesz = (ftell(hashfile) / (sizeof(struct fileentry))) - 1;
240             }
241
242             if (hashfile != NULL)
243             {
244                 long i, j;
245                 int nr[MAXDEPTH];
246                 struct fileentry n;
247
248                 fputs("Counting transposition file entries, wait!\n", stdout);
249
250                 for (i = 0; i < MAXDEPTH; i++)
251                     nr[i] = 0;
252
253                 fseek(hashfile, 0L, SEEK_END);
254                 i = ftell(hashfile) / (sizeof(struct fileentry));
255                 fseek(hashfile, 0L, SEEK_SET);
256
257                 for (j = 0; j < i + 1; j++)
258                 {
259                     fread(&n, sizeof(struct fileentry), 1, hashfile);
260
261                     if (n.depth > MAXDEPTH)
262                     {
263                         printf("ERROR\n");
264                         exit(1);
265                     }
266
267                     if (n.depth)
268                     {
269                         nr[n.depth]++;
270                         nr[0]++;
271                     }
272                 }
273
274                 printf("The file contains %d entries out of max %d\n", nr[0], i);
275
276                 for (j = 1; j < MAXDEPTH; j++)
277                     printf("%d ", nr[j]);
278
279                 printf("\n");
280             }
281
282             return 0;
283
284
285 #endif /* HASHFILE */
286 #endif /* ttblsz */
287
288         case 'v':
289             fprintf(stderr, "gnushogi version %s\n", PACKAGE_VERSION);
290             exit(1);
291
292
293         case 'X':
294             /* X interface. */
295             display_type = DISPLAY_X;
296
297             break;
298
299
300         case 'x':
301             argc--;
302             argv++;
303
304             if (argc > 0)
305                 xwin = argv[0];
306
307             break;
308
309
310         default:
311             fputs("Usage: gnushogi [-a] [-t] [-c size] [-s savefile][-l listfile] [-x xwndw]\n", stderr);
312             exit(1);
313         }
314
315         argc--;
316         argv++;
317     }
318
319     if (argc == 2)
320     {
321         char *p;
322
323         MaxResponseTime = 100L * strtol(argv[1], &p, 10);
324
325         if (*p == ':')
326         {
327             MaxResponseTime = 60L * MaxResponseTime +
328                 100L * strtol(++p, (char **) NULL, 10);
329         }
330
331         TCflag    = false;
332         TCmoves   = 0;
333         TCminutes = 0;
334         TCseconds = 0;
335     }
336
337     if (argc >= 3)
338     {
339         char *p;
340
341         if (argc > 9)
342         {
343             printf("Time Control Error\n");
344             exit(1);
345         }
346
347         TCmoves   = atoi(argv[1]);
348         TCminutes = (short)strtol(argv[2], &p, 10);
349
350         if (*p == ':')
351             TCseconds = (short)strtol(p + 1, (char **) NULL, 10);
352         else
353             TCseconds = 0;
354
355         TCflag = true;
356         argc -= 3;
357         argv += 3;
358
359         while (argc > 1)
360         {
361             XCmoves[XC]   = atoi(argv[0]);
362             XCminutes[XC] = (short)strtol(argv[1], &p, 10);
363
364             if (*p == ':')
365                 XCseconds[XC] = (short)strtol(p + 1, (char **) NULL, 10);
366             else
367                 XCseconds[XC] = 0;
368
369             if (XCmoves[XC] && (XCminutes[XC] || XCseconds[XC]))
370                 XC++;
371             else
372             {
373                 printf("Time Control Error\n");
374                 exit(1);
375             }
376
377             argc -= 2;
378             argv += 2;
379         }
380
381         if (argc)
382         {
383             /*
384              * If we got here, there are unknown arguments, so issue
385              * an error message and quit.
386              */
387
388             printf("Invalid command-line arguments:\n");
389             print_arglist(argc, argv);
390             exit(1);
391         }
392     }
393
394     if (InitMain() != 0)
395         exit(1);
396
397     while (!flag.quit)
398     {
399         oppptr = (oppptr + 1) % MINGAMEIN;
400
401         if (flag.bothsides && !flag.mate)
402             SelectMove(opponent, FOREGROUND_MODE);
403         else
404             InputCommand(NULL);
405
406         if (opponent == white)
407         {
408             if (flag.gamein || TCadd)
409             {
410                 TimeCalc();
411             }
412             else if (TimeControl.moves[opponent] == 0)
413             {
414                 if (XC)
415                 {
416                     if (XCmore < XC)
417                     {
418                         TCmoves   = XCmoves[XCmore];
419                         TCminutes = XCminutes[XCmore];
420                         TCseconds = XCseconds[XCmore];
421                         XCmore++;
422                     }
423                 }
424
425                 SetTimeControl();
426             }
427         }
428
429         compptr = (compptr + 1) % MINGAMEIN;
430
431         if (!(flag.quit || flag.mate || flag.force))
432         {
433 #ifdef INTERRUPT_TEST
434             printf("starting search...\n");
435 #endif
436             SelectMove(computer, FOREGROUND_MODE);
437
438             if (computer == white)
439             {
440                 if (flag.gamein)
441                 {
442                     TimeCalc();
443                 }
444                 else if (TimeControl.moves[computer] == 0)
445                 {
446                     if (XC)
447                     {
448                         if (XCmore < XC)
449                         {
450                             TCmoves = XCmoves[XCmore];
451                             TCminutes = XCminutes[XCmore];
452                             TCseconds = XCseconds[XCmore];
453                             XCmore++;
454                         }
455                     }
456
457                     SetTimeControl();
458                 }
459             }
460         }
461     }
462
463     ExitMain();
464
465     return 0;
466 }
467
468