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