1 /* GNU Chess 6 - main.cc - entry point
2
3 Copyright (c) 2001-2021 Free Software Foundation, Inc.
4
5 GNU Chess is based on the two research programs
6 Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21 Contact Info:
22 bug-gnu-chess@gnu.org
23 cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
24 */
25
26 #include "components.h"
27
28 #include <time.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <getopt.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <locale.h>
36 #include <signal.h>
37
38 #include "frontend/common.h"
39 #include "gettext.h"
40
41 #define _(str) gettext (str)
42
43 unsigned char lzArray[65536];
44 BitBoard BitPosArray[64];
45 BitBoard NotBitPosArray[64];
46 BitBoard MoveArray[8][64];
47 BitBoard Ray[64][8];
48 BitBoard FromToRay[64][64];
49 BitBoard RankBit[8];
50 BitBoard FileBit[8];
51 BitBoard Ataks[2][7];
52 BitBoard Rook00Atak[64][256];
53 BitBoard Rook90Atak[64][256];
54 BitBoard Bishop45Atak[64][256];
55 BitBoard Bishop315Atak[64][256];
56 short directions[64][64];
57 unsigned char BitCount[65536];
58 leaf Tree[MAXTREEDEPTH];
59 leaf *TreePtr[MAXPLYDEPTH];
60 GameRec Game[MAXGAMEDEPTH];
61 int GameCnt;
62 int RealGameCnt;
63 short RealSide;
64 int computer;
65 unsigned int flags;
66 unsigned int preanalyze_flags;
67 int cboard[64];
68 int Mvboard[64];
69 Board board;
70 HashType hashcode[2][7][64];
71 HashType ephash[64];
72 HashType WKCastlehash;
73 HashType WQCastlehash;
74 HashType BKCastlehash;
75 HashType BQCastlehash;
76 HashType Sidehash;
77 HashType HashKey;
78 HashType PawnHashKey;
79 int Game50;
80 unsigned long GenCnt;
81 char SANmv[SANSZ];
82 char id[32];
83 char solution[64];
84 float SearchTime;
85 int MoveLimit[2];
86 float TimeLimit[2];
87 int TCMove;
88 int TCinc;
89 float TCTime;
90 int phase;
91 short bookfirstlast;
92 short graphicmodeoutput;
93 short coords;
94 short pgnloaded = 0;
95 int pgncnt = 0;
96
97 char *progname;
98 FILE *ofp;
99 int myrating, opprating;
100 char name[50];
101 int computerplays; /* Side computer is playing */
102 int n; /* Last mobility returned by CTL */
103 int ExchCnt[2]; /* How many exchanges? */
104
105 int slider[8] = { 0, 0, 0, 1, 1, 1, 0, 0 };
106 int Value[7] = { 0, ValueP, ValueN, ValueB, ValueR, ValueQ, ValueK};
107 int range[8] = { 0, 0, 0, 1, 1, 1, 0, 0 };
108 int ptype[2] = { pawn, bpawn };
109 char algbr[64][3] =
110 { "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",
111 "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
112 "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",
113 "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",
114 "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",
115 "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",
116 "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
117 "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"
118 };
119 char algbrfile[9] = "abcdefgh";
120 char algbrrank[9] = "12345678";
121
122 char notation[8] = { " PNBRQK" };
123 char lnotation[8] = { " pnbrqk" };
124
125 short Shift00[64] =
126 { 56, 56, 56, 56, 56, 56, 56, 56,
127 48, 48, 48, 48, 48, 48, 48, 48,
128 40, 40, 40, 40, 40, 40, 40, 40,
129 32, 32, 32, 32, 32, 32, 32, 32,
130 24, 24, 24, 24, 24, 24, 24, 24,
131 16, 16, 16, 16, 16, 16, 16, 16,
132 8, 8, 8, 8, 8, 8, 8, 8,
133 0, 0, 0, 0, 0, 0, 0, 0
134 };
135
136 int r90[64] =
137 { A8, A7, A6, A5, A4, A3, A2, A1,
138 B8, B7, B6, B5, B4, B3, B2, B1,
139 C8, C7, C6, C5, C4, C3, C2, C1,
140 D8, D7, D6, D5, D4, D3, D2, D1,
141 E8, E7, E6, E5, E4, E3, E2, E1,
142 F8, F7, F6, F5, F4, F3, F2, F1,
143 G8, G7, G6, G5, G4, G3, G2, G1,
144 H8, H7, H6, H5, H4, H3, H2, H1 };
145
146 short Shift90[64] =
147 { 0, 8, 16, 24, 32, 40, 48, 56,
148 0, 8, 16, 24, 32, 40, 48, 56,
149 0, 8, 16, 24, 32, 40, 48, 56,
150 0, 8, 16, 24, 32, 40, 48, 56,
151 0, 8, 16, 24, 32, 40, 48, 56,
152 0, 8, 16, 24, 32, 40, 48, 56,
153 0, 8, 16, 24, 32, 40, 48, 56,
154 0, 8, 16, 24, 32, 40, 48, 56
155 };
156
157 int r45[64] =
158 { E4, F3, H2, C2, G1, D1, B1, A1,
159 E5, F4, G3, A3, D2, H1, E1, C1,
160 D6, F5, G4, H3, B3, E2, A2, F1,
161 B7, E6, G5, H4, A4, C3, F2, B2,
162 G7, C7, F6, H5, A5, B4, D3, G2,
163 C8, H7, D7, G6, A6, B5, C4, E3,
164 F8, D8, A8, E7, H6, B6, C5, D4,
165 H8, G8, E8, B8, F7, A7, C6, D5 };
166
167 short Shift45[64] =
168 { 28, 36, 43, 49, 54, 58, 61, 63,
169 21, 28, 36, 43, 49, 54, 58, 61,
170 15, 21, 28, 36, 43, 49, 54, 58,
171 10, 15, 21, 28, 36, 43, 49, 54,
172 6, 10, 15, 21, 28, 36, 43, 49,
173 3, 6, 10, 15, 21, 28, 36, 43,
174 1, 3, 6, 10, 15, 21, 28, 36,
175 0, 1, 3, 6, 10, 15, 21, 28 };
176
177 int Mask45[64] =
178 { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01,
179 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03,
180 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07,
181 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
182 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F,
183 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F,
184 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F,
185 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
186
187 int r315[64] =
188 { A1, C1, F1, B2, G2, E3, D4, D5,
189 B1, E1, A2, F2, D3, C4, C5, C6,
190 D1, H1, E2, C3, B4, B5, B6, A7,
191 G1, D2, B3, A4, A5, A6, H6, F7,
192 C2, A3, H3, H4, H5, G6, E7, B8,
193 H2, G3, G4, G5, F6, D7, A8, E8,
194 F3, F4, F5, E6, C7, H7, D8, G8,
195 E4, E5, D6, B7, G7, C8, F8, H8 };
196
197 short Shift315[64] =
198 { 63, 61, 58, 54, 49, 43, 36, 28,
199 61, 58, 54, 49, 43, 36, 28, 21,
200 58, 54, 49, 43, 36, 28, 21, 15,
201 54, 49, 43, 36, 28, 21, 15, 10,
202 49, 43, 36, 28, 21, 15, 10, 6,
203 43, 36, 28, 21, 15, 10, 6, 3,
204 36, 28, 21, 15, 10, 6, 3, 1,
205 28, 21, 15, 10, 6, 3, 1, 0 };
206
207 int Mask315[64] =
208 { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF,
209 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F,
210 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F,
211 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F,
212 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
213 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07,
214 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03,
215 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
216
217 extern char userinputbuf[];
218
EndProg(int sig)219 void EndProg( int sig __attribute__ ((unused)) )
220 {
221 int r = system( "stty sane" );
222 exit(r);
223 }
224
main(int argc,char * argv[])225 int main (int argc, char *argv[])
226 {
227 int i;
228
229 /* Set locale via LC_ALL. */
230 setlocale (LC_ALL, "");
231
232 #if ENABLE_NLS
233 /* Set the text message domain. */
234 bindtextdomain (PACKAGE, LOCALEDIR);
235 textdomain (PACKAGE);
236 #endif
237
238 /*
239 * Parse command line arguments conforming with getopt_long syntax
240 * Note: we have to support "xboard" and "post" as bare strings
241 * for backward compatibility.
242 */
243
244 int c;
245 int opt_help = 0, opt_version = 0, opt_post = 0, opt_xboard = 0, opt_memory = 0,
246 opt_easy = 0, opt_manual = 0, opt_quiet = 0, opt_uci = 0, opt_graphic = 0;
247 char opt_addbook[MAXSTR+1] = "";
248 char *endptr;
249
250 /*disable graphic output by default */
251 graphicmodeoutput = 0;
252
253
254 progname = argv[0]; /* Save in global for cmd_usage */
255
256 while (1)
257 {
258 static struct option long_options[] =
259 {
260 {"memory", 1, 0, 'M'},
261 {"version", 0, 0, 'v'},
262 {"quiet", 0, 0, 'q'},
263 {"silent", 0, 0, 'q'},
264 {"help", 0, 0, 'h'},
265 {"xboard", 0, 0, 'x'},
266 {"post", 0, 0, 'p'},
267 {"easy", 0, 0, 'e'},
268 {"manual", 0, 0, 'm'},
269 {"uci", 0, 0, 'u'},
270 {"addbook", 1, 0, 'a'},
271 {"graphic", 0, 0, 'g'},
272 {0, 0, 0, 0}
273 };
274
275 /* getopt_long stores the option index here. */
276
277 int option_index = 0;
278
279 c = getopt_long (argc, argv, "qehmpvxgM:ua:",
280 long_options, &option_index);
281
282 /* Detect the end of the options. */
283 if (c == -1)
284 break;
285
286 /*
287 * Options with a straight flag, could use getoopt_long
288 * flag setting but this is more "obvious" and easier to
289 * modify.
290 */
291 switch (c)
292 {
293 case 'v':
294 opt_version = 1;
295 break;
296 case 'h':
297 opt_help = 1;
298 break;
299 case 'q':
300 opt_quiet = 1;
301 break;
302 case 'x':
303 opt_xboard = 1;
304 break;
305 case 'p':
306 opt_post = 1;
307 break;
308 case 'e':
309 opt_easy = 1;
310 break;
311 case 'g':
312 opt_graphic = 1;
313 break;
314 case 'm':
315 opt_manual = 1;
316 break;
317 case 'M':
318 if ( optarg == NULL ){ /* we have error such as two -M */
319 opt_help = 1;
320 break;
321 }
322 errno = 0; /* zero error indicator */
323 opt_memory = strtol (optarg, &endptr, 10);
324 if ( errno != 0 || *endptr != '\0' ){
325 printf(_("Memory out of range or invalid.\n"));
326 return(1);
327 }
328 break;
329 case '?': /* On error give help - getopt does a basic message. */
330 opt_help = 1;
331 break;
332 case 'u':
333 opt_uci = 1;
334 break;
335 case 'a':
336 if ( optarg == NULL ){ /* we have error such as two -a */
337 opt_help = 1;
338 break;
339 }
340 errno = 0; /* zero error indicator */
341 if ( strlen( optarg ) > MAXSTR ) {
342 printf( _("File name is too long (max = %d).\n"), MAXSTR );
343 return(1);
344 }
345 strcpy( opt_addbook, optarg );
346 break;
347 default:
348 puts (_("Option processing failed.\n"));
349 abort();
350 }
351 } /* end of getopt_long style parsing */
352
353 /* Initialize random number generator */
354 srand((unsigned int) time(NULL));
355
356 /* initialize control flags */
357 flags = ULL(0);
358
359 /* output for thinking */
360 ofp = stdout;
361
362 /* Handle old style command line options */
363 if (argc > 1) {
364 for (i = 0; i < argc; i++) {
365 if (strcmp(argv[i],"xboard") == 0) {
366 SET (flags, XBOARD);
367 } else if (strcmp(argv[i],"post") == 0) {
368 SET (flags, POST);
369 }
370 }
371 }
372 if (opt_xboard == 1)
373 SET (flags, XBOARD);
374 if (opt_uci == 1)
375 SET (flags, UCI);
376 if (opt_post == 1) {
377 SET (flags, POST);
378 }
379 if (opt_manual ==1)
380 SET (flags, MANUAL);
381 cmd_version();
382
383 /* If the version option was specified we can exit here */
384 if (opt_version == 1)
385 return(0);
386
387 /* Startup output */
388 if ( !( flags & XBOARD ) && ( !opt_quiet ) && ( !opt_uci) ) {
389 printf ( _("\
390 Copyright (C) %s Free Software Foundation, Inc.\n\
391 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
392 This is free software: you are free to change and redistribute it.\n\
393 There is NO WARRANTY, to the extent permitted by law.\n"),
394 "2021" );
395 }
396
397 /* If a usage statement is required output it here */
398 if (opt_help == 1){
399 cmd_usage();
400 return (1); /* Maybe an error if due to bad arguments. */
401 }
402
403 dbg_open(NULL);
404
405 if ( opt_memory != 0 )
406 ; /* TODO: to be removed - this is handled by the adapter */
407
408 /* Catch SIGINT to exit. */
409 struct sigaction action;
410 memset( &action, 0, sizeof(struct sigaction) );
411 action.sa_handler = EndProg;
412 sigaction( SIGINT, &action, NULL );
413
414 Initialize ();
415 if ( ! (flags & UCI ) ) {
416 /* Initialize the frontend */
417 InitFrontend();
418 /* Initialize the adapter, which in turn initializes the engine */
419 InitAdapter();
420 } else {
421 /* Initialize the engine only; no adapter */
422 InitEngine();
423 }
424
425 /* Compile book if the addbook option was specified. Ignore any other options. */
426 if ( strlen( opt_addbook ) > 0 ) {
427 char data[9+MAXSTR+1+4]="";
428 sprintf( data, "book add %s\nquit", opt_addbook );
429 SendToEngine( data );
430 SET (flags, QUIT);
431 }
432
433 if ( opt_easy == 0 )
434 SET (flags, HARD);
435 else {
436 char data[9];
437 strcpy( data, "easy" );
438 SendToEngine( data );
439 }
440
441 if ( opt_memory > 0 ) {
442 char data[20];
443 sprintf( data, "memory %d", opt_memory );
444 SendToEngine( data );
445 }
446
447 if (opt_post == 1) {
448 SET (flags, POST);
449 char data[9];
450 strcpy( data, "post" );
451 SendToEngine( data );
452 }
453
454 if (opt_manual == 1) {
455 SET (flags, MANUAL);
456 char data[9];
457 strcpy( data, "force" );
458 SendToEngine( data );
459 }
460
461 if (argc > 1) {
462 for (i = 0; i < argc; i++) {
463 if (strcmp(argv[i],"xboard") == 0) {
464 SET (flags, XBOARD);
465 } else if (strcmp(argv[i],"post") == 0) {
466 SET (flags, POST);
467 }
468 }
469
470 if ( opt_graphic == 1) {
471 graphicmodeoutput = 1;
472 }
473
474 }
475
476 bookfirstlast = 3;
477
478
479 /* While not quit
480 * If user input buffer not empty
481 * Read next line from user input buffer
482 * Process user input at front-end level
483 * If user input must be passed to engine
484 * Send user input to engine
485 * If engine input buffer not empty
486 * Read next line from engine input buffer
487 * Process engine input at front-end level
488 * Send user input to user (print on term)
489 * If engine input must be passed to user
490 * If user input is ready for reading (select)
491 * Add user input to user input buffer
492 * If engine input is ready for reading (select)
493 * Add engine input to engine input buffer
494 */
495
496 //usleep(3000); /* So that Polyglot's and Fruit's banner has enough time to be displayed */
497 //strcpy( userinputbuf, "protover 2\n" );
498 while (!(flags & QUIT)) {
499 if ( flags & UCI ) {
500 /* In UCI mode, just forward input/output to/from engine - no adapter */
501 ForwardUserInputToEngine();
502 ForwardEngineOutputToUser();
503 } else { /* Classical GNU Chess mode */
504 /* Check if there is a new command from the user */
505 NextUserCmd();
506 /* Show thinking message */
507 if ((flags & THINK) && !(flags & MANUAL) && !(flags & ENDED)) {
508 if (!(flags & XBOARD)) printf(_("Thinking...\n"));
509 CLEAR (flags, THINK);
510 }
511 /* Check if there is a new command from the engine */
512 NextEngineCmd();
513 /* Check if user input ready for reading. If so, store it in a buffer. */
514 ReadFromUser();
515 /* Check if engine input ready for reading. If so, store it in a buffer. */
516 ReadFromEngine();
517 }
518 /* Avoid using 100% CPU */
519 usleep(100);
520 }
521
522 dbg_close();
523
524 /* Termintate adapter and engine threads and join them */
525 TerminateAdapterEngine();
526 TerminateInput();
527
528 return (0);
529 }
530