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