Remove xshogi-only contributions from CONTRIB file.
[gnushogi.git] / gnushogi / init.c
blob06f4b4e757dd0b17171e29dc510b6d492b40ff95
1 /*
2 * FILE: init.c
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
9 * GNU SHOGI is based on GNU CHESS
11 * Copyright (c) 1988, 1989, 1990 John Stanback
12 * Copyright (c) 1992 Free Software Foundation
14 * This file is part of GNU SHOGI.
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.
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.
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 * ----------------------------------------------------------------------
33 #include "gnushogi.h"
35 #if defined HAVE_GETTIMEOFDAY
36 #include <sys/time.h>
37 #endif
39 #include <signal.h>
41 #include "pattern.h"
43 /****************************************
44 * A variety of global flags.
45 ****************************************/
48 * If hard_time_limit is nonzero, exceeding the time limit means
49 * losing the game.
52 short hard_time_limit = 1;
53 short barebones = 0; /* Suppress printing of statistics
54 * (mainly for xshogi). */
55 #ifdef LIST_ON_EXIT
56 short nolist = 0; /* List the game after exit. */
57 #else
58 short nolist = 1; /* Don't list the game after exit. */
59 #endif
62 * The default display type can be DISPLAY_RAW, DISPLAY_CURSES,
63 * or DISPLAY_X; the default is DISPLAY_X to make life easier for xshogi.
66 display_t display_type = DISPLAY_X;
68 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
70 #ifdef SAVE_NEXTPOS
71 const small_short psweep[NO_PTYPE_PIECES] =
73 false,
74 #ifndef MINISHOGI
75 true, false,
76 #endif
77 false, false, true, true,
78 true, true, false, false,
79 #ifndef MINISHOGI
80 true, false,
81 #endif
82 false, false
84 #endif
86 const small_short sweep[NO_PIECES] =
88 false, false,
89 #ifndef MINISHOGI
90 true, false,
91 #endif
92 false, false, true, true,
93 false,
94 #ifndef MINISHOGI
95 false, false,
96 #endif
97 false, true, true, false
101 #ifdef SAVE_DISTDATA
102 short
103 distance(short a, short b)
105 return (short)computed_distance(a, b);
107 #else
108 short
109 distance(short a, short b)
111 return (use_distdata
112 ? (short)(*distdata)[(int)a][(int)b]
113 : (short)computed_distance(a, b));
115 #endif
118 void
119 Initialize_dist(void)
121 short a, b, d, di, ptyp;
122 #ifndef SAVE_DISTDATA
123 for (a = 0; a < NO_SQUARES; a++)
125 for (b = 0; b < NO_SQUARES; b++)
127 d = abs(column(a) - column(b));
128 di = abs(row(a) - row(b));
129 (*distdata)[a][b] = (small_short)((d > di) ? d : di);
132 #endif
133 #ifndef SAVE_PTYPE_DISTDATA
134 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
136 for (a = 0; a < NO_SQUARES; a++)
137 for (b = 0; b < NO_SQUARES; b++)
138 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
140 #endif
145 * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
146 * of positions reachable from from-square in ppos with ptype such that the
147 * sequence
149 * ppos = nextpos[ptype][from-square];
150 * pdir = nextdir[ptype][from-square];
151 * u = ppos[sq];
153 * do
155 * u = ppos[u];
157 * if(color[u] != neutral)
158 * u = pdir[u];
160 * while (sq != u);
162 * will generate the sequence of all squares reachable from sq.
164 * If the path is blocked u = pdir[sq] will generate the continuation of the
165 * sequence in other directions.
169 const small_short is_promoted[NO_PIECES] =
171 false, false,
172 #ifndef MINISHOGI
173 false, false,
174 #endif
175 false, false, false, false,
176 true,
177 #ifndef MINISHOGI
178 true, true,
179 #endif
180 true, true, true, false
183 /* data used to generate nextpos/nextdir */
184 #ifndef MINISHOGI
185 /* FIXME: use predefined constants ! */
186 #if !defined SAVE_NEXTPOS
187 static
188 #endif
189 const small_short direc[NO_PTYPE_PIECES][8] =
191 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
192 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
193 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
194 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
195 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
196 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
197 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
198 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
199 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
200 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
201 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
202 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
203 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
204 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
205 { -10, -11, -12, 1, -1, 11, 0, 0 } /* 14 ptype_wgold */
207 #else
208 #if !defined SAVE_NEXTPOS
209 static
210 #endif
211 const small_short direc[NO_PTYPE_PIECES][8] =
213 { 7, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
214 { 6, 7, 8, -8, -6, 0, 0, 0 }, /* 3 ptype_silver */
215 { 6, 7, 8, -1, 1, -7, 0, 0 }, /* 4 ptype_gold */
216 { 6, 8, -8, -6, 0, 0, 0, 0 }, /* 5 ptype_bishop */
217 { 7, -1, 1, -7, 0, 0, 0, 0 }, /* 6 ptype_rook */
218 { 6, 8, -8, -6, 7, -1, 1, -7 }, /* 7 ptype_pbishop */
219 { 7, -1, 1, -7, 6, 8, -8, -6 }, /* 8 ptype_prook */
220 { 6, 7, 8, -1, 1, -8, -7, -6 }, /* 9 ptype_king */
221 { -7, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
222 { -6, -7, -8, 8, 6, 0, 0, 0 }, /* 13 ptype_wsilver */
223 { -6, -7, -8, 1, -1, 7, 0, 0 } /* 14 ptype_wgold */
225 #endif
228 small_short diagonal(short d)
230 return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
234 #ifndef MINISHOGI
235 /* FIXME */
236 static const small_short max_steps[NO_PTYPE_PIECES] =
238 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
240 #else
241 static const small_short max_steps[NO_PTYPE_PIECES] =
243 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
245 #endif
247 #ifndef MINISHOGI
248 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
250 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
251 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
252 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
253 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
254 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
255 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
256 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
257 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
258 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
259 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
260 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
261 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
262 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
266 const small_short inunmap[NO_SQUARES] =
268 23, 24, 25, 26, 27, 28, 29, 30, 31,
269 34, 35, 36, 37, 38, 39, 40, 41, 42,
270 45, 46, 47, 48, 49, 50, 51, 52, 53,
271 56, 57, 58, 59, 60, 61, 62, 63, 64,
272 67, 68, 69, 70, 71, 72, 73, 74, 75,
273 78, 79, 80, 81, 82, 83, 84, 85, 86,
274 89, 90, 91, 92, 93, 94, 95, 96, 97,
275 100, 101, 102, 103, 104, 105, 106, 107, 108,
276 111, 112, 113, 114, 115, 116, 117, 118, 119
278 #else
279 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 2)] =
281 -1, -1, -1, -1, -1, -1, -1,
282 -1, 0, 1, 2, 3, 4, -1,
283 -1, 5, 6, 7, 8, 9, -1,
284 -1, 10, 11, 12, 13, 14, -1,
285 -1, 15, 16, 17, 18, 19, -1,
286 -1, 20, 21, 22, 23, 24, -1,
287 -1, -1, -1, -1, -1, -1, -1,
291 const small_short inunmap[NO_SQUARES] =
293 8, 9, 10, 11, 12,
294 15, 16, 17, 18, 19,
295 22, 23, 24, 25, 26,
296 29, 30, 31, 32, 33,
297 36, 37, 38, 39, 40,
299 #endif
301 int InitFlag = false;
304 #if defined SAVE_NEXTPOS
306 short
307 next_direction(short ptyp, short *d, short sq)
309 short delta, to, sfrom = inunmap[sq];
313 (*d)++;
314 if (*d >= 8)
315 return sq;
317 delta = direc[ptyp][*d];
318 if (delta == 0)
319 return sq;
321 to = nunmap[sfrom + delta];
323 while (to < 0);
325 return to;
329 short
330 next_position(short ptyp, short *d, short sq, short u)
332 if (*d < 4 && psweep[ptyp])
334 short to = nunmap[inunmap[u] + direc[ptyp][*d]];
336 if (to < 0)
337 return next_direction(ptyp, d, sq);
338 else
339 return to;
341 else
343 return next_direction(ptyp, d, sq);
348 short
349 first_direction(short ptyp, short *d, short sq)
351 *d = -1;
352 return next_direction(ptyp, d, sq);
355 #else
358 * This procedure pre-calculates all moves for every piece from every
359 * square. This data is stored in nextpos/nextdir and used later in the
360 * move generation routines.
363 void
364 Initialize_moves(void)
366 short ptyp, po, p0, d, di, s, delta;
367 unsigned char *ppos, *pdir;
368 short dest[8][9];
369 short sorted[9];
370 short steps[8];
371 short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
373 /* pre-fill nextpos and nextdir with source position, probably so
374 * (color[u] == neutral) stops to match once all moves have been seen
376 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
378 for (po = 0; po < NO_SQUARES; po++)
380 for (p0 = 0; p0 < NO_SQUARES; p0++)
382 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
383 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
388 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
390 for (po = fpo; po < tpo; po++)
392 if (nunmap[po] >= (small_short)0)
394 ppos = (*nextpos[ptyp])[nunmap[po]];
395 pdir = (*nextdir[ptyp])[nunmap[po]];
397 /* dest is a function of direction and steps */
398 for (d = 0; d < 8; d++)
400 dest[d][0] = nunmap[po];
401 delta = direc[ptyp][d];
403 if (delta != 0)
405 p0 = po;
407 for (s = 0; s < max_steps[ptyp]; s++)
409 p0 = p0 + delta;
412 * break if (off board) or (promoted rooks
413 * wishes to move two steps diagonal) or
414 * (promoted bishops wishes to move two steps
415 * non-diagonal)
417 if ((nunmap[p0] < (small_short)0)
418 || ((ptyp == ptype_prook)
419 && (s > 0)
420 && diagonal(delta))
421 || ((ptyp == ptype_pbishop)
422 && (s > 0)
423 && !diagonal(delta)))
424 break;
425 else
426 dest[d][s] = nunmap[p0];
429 else
431 s = 0;
435 * Sort dest in number of steps order; currently no sort
436 * is done due to compatibility with the move generation
437 * order in old gnuchess.
440 steps[d] = s;
442 for (di = d; s > 0 && di > 0; di--)
444 if (steps[sorted[di - 1]] == 0) /* should be: < s */
445 sorted[di] = sorted[di - 1];
446 else
447 break;
450 sorted[di] = d;
454 * update nextpos/nextdir
457 p0 = nunmap[po];
458 pdir[p0] = (unsigned char)dest[sorted[0]][0];
460 for (d = 0; d < 8; d++)
462 for (s = 0; s < steps[sorted[d]]; s++)
464 ppos[p0] = (unsigned char)dest[sorted[d]][s];
465 p0 = dest[sorted[d]][s];
467 if (d < 7)
468 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
471 * else is already initialized
480 #endif
485 * Reset the board and other variables to start a new game.
488 void
489 NewGame(void)
491 short l, c, p, max_opening_sequence;
492 #ifdef HAVE_GETTIMEOFDAY
493 struct timeval tv;
494 #endif
495 compptr = oppptr = 0;
496 stage = 0;
497 stage2 = -1; /* the game is not yet started */
498 flag.illegal = flag.mate = flag.post = flag.quit
499 = flag.reverse = flag.bothsides = flag.onemove = flag.force
500 = false;
501 flag.material = flag.coords = flag.hash = flag.easy
502 = flag.beep = flag.rcptr
503 = true;
504 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
505 flag.gamein = false;
506 flag.rv = true;
508 mycnt1 = mycnt2 = 0;
509 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
510 znodes = ZNODES;
511 WAwindow = WAWNDW;
512 WBwindow = WBWNDW;
513 BAwindow = BAWNDW;
514 BBwindow = BBWNDW;
515 xwndw = BXWNDW;
517 if (!MaxSearchDepth)
518 MaxSearchDepth = MAXDEPTH - 1;
520 contempt = 0;
521 GameCnt = 0;
522 Game50 = 1;
523 CptrFlag[0] = TesujiFlag[0] = false;
524 hint = OPENING_HINT;
525 ZeroRPT();
526 GameType[0] = GameType[1] = UNKNOWN;
527 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
528 opponent = player = black;
529 computer = white;
531 for (l = 0; l < TREE; l++)
532 Tree[l].f = Tree[l].t = 0;
534 gsrand((unsigned int) 1);
536 if (!InitFlag)
538 for (c = black; c <= white; c++)
540 for (p = pawn; p <= king; p++)
542 for (l = 0; l < NO_SQUARES; l++)
544 (*hashcode)[c][p][l].key
545 = (((unsigned long) urand()));
546 (*hashcode)[c][p][l].key
547 += (((unsigned long) urand()) << 16);
548 (*hashcode)[c][p][l].bd
549 = (((unsigned long) urand()));
550 (*hashcode)[c][p][l].bd
551 += (((unsigned long) urand()) << 16);
552 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
553 (*hashcode)[c][p][l].key
554 += (((unsigned long) urand()) << 32);
555 (*hashcode)[c][p][l].key
556 += (((unsigned long) urand()) << 48);
557 (*hashcode)[c][p][l].bd
558 += (((unsigned long) urand()) << 32);
559 (*hashcode)[c][p][l].bd
560 += (((unsigned long) urand()) << 48);
561 #endif
566 for (c = black; c <= white; c++)
568 for (p = pawn; p <= king; p++)
570 for (l = 0; l < MAX_CAPTURED; l++)
572 (*drop_hashcode)[c][p][l].key
573 = (((unsigned long) urand()));
574 (*drop_hashcode)[c][p][l].key
575 += (((unsigned long) urand()) << 16);
576 (*drop_hashcode)[c][p][l].bd
577 = (((unsigned long) urand()));
578 (*drop_hashcode)[c][p][l].bd
579 += (((unsigned long) urand()) << 16);
580 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
581 (*drop_hashcode)[c][p][l].key
582 += (((unsigned long) urand()) << 32);
583 (*drop_hashcode)[c][p][l].key
584 += (((unsigned long) urand()) << 48);
585 (*drop_hashcode)[c][p][l].bd
586 += (((unsigned long) urand()) << 32);
587 (*drop_hashcode)[c][p][l].bd
588 += (((unsigned long) urand()) << 48);
589 #endif
595 for (l = 0; l < NO_SQUARES; l++)
597 board[l] = Stboard[l];
598 color[l] = Stcolor[l];
599 Mvboard[l] = 0;
602 ClearCaptured();
603 ClearScreen();
604 InitializeStats();
606 #ifdef HAVE_GETTIMEOFDAY
607 gettimeofday(&tv, NULL);
608 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
609 #else
610 time0 = time((long *) 0);
611 #endif
613 /* resetting reference time */
614 ElapsedTime(COMPUTE_AND_INIT_MODE);
615 flag.regularstart = true;
616 Book = BOOKFAIL;
618 if (!InitFlag)
620 char sx[256];
621 strcpy(sx, "level");
623 if (TCflag)
624 SetTimeControl();
625 else if (MaxResponseTime == 0)
626 SelectLevel(sx);
628 UpdateDisplay(0, 0, 1, 0);
629 GetOpenings();
630 GetOpeningPatterns(&max_opening_sequence);
632 InitFlag = true;
635 #if ttblsz
636 if (TTadd)
638 ZeroTTable();
639 TTadd = 0;
641 #endif /* ttblsz */
643 hashbd = hashkey = 0;
644 return;
651 InitMain(void)
653 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
655 #if ttblsz
656 ttblsize = ttblsz;
657 rehash = -1;
658 #endif /* ttblsz */
660 if (Initialize_data() != 0)
661 return 1;
663 strcpy(ColorStr[0], "Black");
664 strcpy(ColorStr[1], "White");
666 XC = 0;
667 MaxResponseTime = 0;
669 if (XSHOGI)
671 TCmoves = 40;
672 TCminutes = 5;
673 TCseconds = 0;
674 TCadd = 0;
676 TCflag = true;
677 OperatorTime = 0;
678 barebones = 1;
680 else
682 TCflag = false;
683 OperatorTime = 0;
684 barebones = 0;
687 Initialize();
688 Initialize_dist();
689 Initialize_eval();
690 #if !defined SAVE_NEXTPOS
691 Initialize_moves();
692 #endif
694 NewGame();
696 flag.easy = ahead;
697 flag.hash = hash;
699 if (xwin)
700 xwndw = atoi(xwin);
702 #ifdef HASHFILE
703 hashfile = NULL;
704 #endif
706 #if ttblsz
707 #ifdef HASHFILE
708 hashfile = fopen(HASHFILE, RWA_ACC);
710 if (hashfile)
712 fseek(hashfile, 0L, SEEK_END);
713 filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
714 hashmask = filesz >> 1;
715 hashbase = hashmask + 1;
717 #endif /* HASHFILE */
718 #endif /* ttblsz */
720 savefile[0] = '\0';
721 listfile[0] = '\0';
723 return 0;
727 void
728 ExitMain(void)
730 #if ttblsz
731 #ifdef HASHFILE
732 if (hashfile)
733 fclose(hashfile);
734 #endif /* HASHFILE */
735 #endif /* ttblsz */
737 ExitShogi();