Bool transition: init.c and friends
[gnushogi.git] / gnushogi / init.c
blobd6babdf51452ae45fef624dedf1441a73bcdc49e
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 #ifdef LIST_ON_EXIT
54 short nolist = 0; /* List the game after exit. */
55 #else
56 short nolist = 1; /* Don't list the game after exit. */
57 #endif
60 * The default display type can be DISPLAY_RAW, DISPLAY_CURSES,
61 * or DISPLAY_X; the default is DISPLAY_X to make life easier for xshogi.
64 display_t display_type = DISPLAY_X;
66 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
68 #ifdef SAVE_NEXTPOS
69 static const bool psweep[NO_PTYPE_PIECES] =
71 false,
72 #ifndef MINISHOGI
73 true, false,
74 #endif
75 false, false, true, true,
76 true, true, false, false,
77 #ifndef MINISHOGI
78 true, false,
79 #endif
80 false, false
82 #endif
84 const bool sweep[NO_PIECES] =
86 false, false,
87 #ifndef MINISHOGI
88 true, false,
89 #endif
90 false, false, true, true,
91 false,
92 #ifndef MINISHOGI
93 false, false,
94 #endif
95 false, true, true, false
99 #ifdef SAVE_DISTDATA
100 short
101 distance(short a, short b)
103 return (short)computed_distance(a, b);
105 #else
106 short
107 distance(short a, short b)
109 return (use_distdata
110 ? (short)(*distdata)[(int)a][(int)b]
111 : (short)computed_distance(a, b));
113 #endif
116 void
117 Initialize_dist(void)
119 short a, b, d, di, ptyp;
120 #ifndef SAVE_DISTDATA
121 for (a = 0; a < NO_SQUARES; a++)
123 for (b = 0; b < NO_SQUARES; b++)
125 d = abs(column(a) - column(b));
126 di = abs(row(a) - row(b));
127 (*distdata)[a][b] = (small_short)((d > di) ? d : di);
130 #endif
131 #ifndef SAVE_PTYPE_DISTDATA
132 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
134 for (a = 0; a < NO_SQUARES; a++)
135 for (b = 0; b < NO_SQUARES; b++)
136 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
138 #endif
143 * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
144 * of positions reachable from from-square in ppos with ptype such that the
145 * sequence
147 * ppos = nextpos[ptype][from-square];
148 * pdir = nextdir[ptype][from-square];
149 * u = ppos[sq];
151 * do
153 * u = ppos[u];
155 * if(color[u] != neutral)
156 * u = pdir[u];
158 * while (sq != u);
160 * will generate the sequence of all squares reachable from sq.
162 * If the path is blocked u = pdir[sq] will generate the continuation of the
163 * sequence in other directions.
167 const bool is_promoted[NO_PIECES] =
169 false, false,
170 #ifndef MINISHOGI
171 false, false,
172 #endif
173 false, false, false, false,
174 true,
175 #ifndef MINISHOGI
176 true, true,
177 #endif
178 true, true, true, false
181 /* data used to generate nextpos/nextdir */
182 #ifndef MINISHOGI
183 /* FIXME: use predefined constants ! */
184 #if !defined SAVE_NEXTPOS
185 static
186 #endif
187 const small_short direc[NO_PTYPE_PIECES][8] =
189 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
190 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
191 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
192 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
193 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
194 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
195 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
196 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
197 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
198 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
199 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
200 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
201 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
202 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
203 { -10, -11, -12, 1, -1, 11, 0, 0 } /* 14 ptype_wgold */
205 #else
206 #if !defined SAVE_NEXTPOS
207 static
208 #endif
209 const small_short direc[NO_PTYPE_PIECES][8] =
211 { 7, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
212 { 6, 7, 8, -8, -6, 0, 0, 0 }, /* 3 ptype_silver */
213 { 6, 7, 8, -1, 1, -7, 0, 0 }, /* 4 ptype_gold */
214 { 6, 8, -8, -6, 0, 0, 0, 0 }, /* 5 ptype_bishop */
215 { 7, -1, 1, -7, 0, 0, 0, 0 }, /* 6 ptype_rook */
216 { 6, 8, -8, -6, 7, -1, 1, -7 }, /* 7 ptype_pbishop */
217 { 7, -1, 1, -7, 6, 8, -8, -6 }, /* 8 ptype_prook */
218 { 6, 7, 8, -1, 1, -8, -7, -6 }, /* 9 ptype_king */
219 { -7, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
220 { -6, -7, -8, 8, 6, 0, 0, 0 }, /* 13 ptype_wsilver */
221 { -6, -7, -8, 1, -1, 7, 0, 0 } /* 14 ptype_wgold */
223 #endif
226 small_short diagonal(short d)
228 return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
232 #ifndef MINISHOGI
233 /* FIXME */
234 static const small_short max_steps[NO_PTYPE_PIECES] =
236 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
238 #else
239 static const small_short max_steps[NO_PTYPE_PIECES] =
241 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
243 #endif
245 #ifndef MINISHOGI
246 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
248 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
249 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
250 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
251 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
252 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
253 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
254 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
255 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
256 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
257 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
258 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
259 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
260 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
264 const small_short inunmap[NO_SQUARES] =
266 23, 24, 25, 26, 27, 28, 29, 30, 31,
267 34, 35, 36, 37, 38, 39, 40, 41, 42,
268 45, 46, 47, 48, 49, 50, 51, 52, 53,
269 56, 57, 58, 59, 60, 61, 62, 63, 64,
270 67, 68, 69, 70, 71, 72, 73, 74, 75,
271 78, 79, 80, 81, 82, 83, 84, 85, 86,
272 89, 90, 91, 92, 93, 94, 95, 96, 97,
273 100, 101, 102, 103, 104, 105, 106, 107, 108,
274 111, 112, 113, 114, 115, 116, 117, 118, 119
276 #else
277 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 2)] =
279 -1, -1, -1, -1, -1, -1, -1,
280 -1, 0, 1, 2, 3, 4, -1,
281 -1, 5, 6, 7, 8, 9, -1,
282 -1, 10, 11, 12, 13, 14, -1,
283 -1, 15, 16, 17, 18, 19, -1,
284 -1, 20, 21, 22, 23, 24, -1,
285 -1, -1, -1, -1, -1, -1, -1,
289 const small_short inunmap[NO_SQUARES] =
291 8, 9, 10, 11, 12,
292 15, 16, 17, 18, 19,
293 22, 23, 24, 25, 26,
294 29, 30, 31, 32, 33,
295 36, 37, 38, 39, 40,
297 #endif
299 static bool InitFlag = false;
302 #if defined SAVE_NEXTPOS
304 short
305 next_direction(short ptyp, short *d, short sq)
307 short delta, to, sfrom = inunmap[sq];
311 (*d)++;
312 if (*d >= 8)
313 return sq;
315 delta = direc[ptyp][*d];
316 if (delta == 0)
317 return sq;
319 to = nunmap[sfrom + delta];
321 while (to < 0);
323 return to;
327 short
328 next_position(short ptyp, short *d, short sq, short u)
330 if (*d < 4 && psweep[ptyp])
332 short to = nunmap[inunmap[u] + direc[ptyp][*d]];
334 if (to < 0)
335 return next_direction(ptyp, d, sq);
336 else
337 return to;
339 else
341 return next_direction(ptyp, d, sq);
346 short
347 first_direction(short ptyp, short *d, short sq)
349 *d = -1;
350 return next_direction(ptyp, d, sq);
353 #else
356 * This procedure pre-calculates all moves for every piece from every
357 * square. This data is stored in nextpos/nextdir and used later in the
358 * move generation routines.
361 void
362 Initialize_moves(void)
364 short ptyp, po, p0, d, di, s, delta;
365 unsigned char *ppos, *pdir;
366 short dest[8][9];
367 short sorted[9];
368 short steps[8];
369 short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
371 /* pre-fill nextpos and nextdir with source position, probably so
372 * (color[u] == neutral) stops to match once all moves have been seen
374 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
376 for (po = 0; po < NO_SQUARES; po++)
378 for (p0 = 0; p0 < NO_SQUARES; p0++)
380 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
381 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
386 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
388 for (po = fpo; po < tpo; po++)
390 if (nunmap[po] >= (small_short)0)
392 ppos = (*nextpos[ptyp])[nunmap[po]];
393 pdir = (*nextdir[ptyp])[nunmap[po]];
395 /* dest is a function of direction and steps */
396 for (d = 0; d < 8; d++)
398 dest[d][0] = nunmap[po];
399 delta = direc[ptyp][d];
401 if (delta != 0)
403 p0 = po;
405 for (s = 0; s < max_steps[ptyp]; s++)
407 p0 = p0 + delta;
410 * break if (off board) or (promoted rooks
411 * wishes to move two steps diagonal) or
412 * (promoted bishops wishes to move two steps
413 * non-diagonal)
415 if ((nunmap[p0] < (small_short)0)
416 || ((ptyp == ptype_prook)
417 && (s > 0)
418 && diagonal(delta))
419 || ((ptyp == ptype_pbishop)
420 && (s > 0)
421 && !diagonal(delta)))
422 break;
423 else
424 dest[d][s] = nunmap[p0];
427 else
429 s = 0;
433 * Sort dest in number of steps order; currently no sort
434 * is done due to compatibility with the move generation
435 * order in old gnuchess.
438 steps[d] = s;
440 for (di = d; s > 0 && di > 0; di--)
442 if (steps[sorted[di - 1]] == 0) /* should be: < s */
443 sorted[di] = sorted[di - 1];
444 else
445 break;
448 sorted[di] = d;
452 * update nextpos/nextdir
455 p0 = nunmap[po];
456 pdir[p0] = (unsigned char)dest[sorted[0]][0];
458 for (d = 0; d < 8; d++)
460 for (s = 0; s < steps[sorted[d]]; s++)
462 ppos[p0] = (unsigned char)dest[sorted[d]][s];
463 p0 = dest[sorted[d]][s];
465 if (d < 7)
466 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
469 * else is already initialized
478 #endif
483 * Reset the board and other variables to start a new game.
486 void
487 NewGame(void)
489 short l, c, p, max_opening_sequence;
490 #ifdef HAVE_GETTIMEOFDAY
491 struct timeval tv;
492 #endif
493 compptr = oppptr = 0;
494 stage = 0;
495 stage2 = -1; /* the game is not yet started */
496 flag.illegal = flag.mate = flag.quit
497 = flag.reverse = flag.bothsides = flag.onemove = flag.force
498 = false;
499 flag.post &= xboard; /* xboard: do not alter post status on 'new' */
500 flag.material = flag.coords = flag.hash = flag.easy
501 = flag.beep = flag.rcptr
502 = true;
503 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
504 flag.gamein = false;
505 flag.rv = true;
507 mycnt1 = mycnt2 = 0;
508 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
509 znodes = ZNODES;
510 WAwindow = WAWNDW;
511 WBwindow = WBWNDW;
512 BAwindow = BAWNDW;
513 BBwindow = BBWNDW;
514 xwndw = BXWNDW;
516 if (!MaxSearchDepth)
517 MaxSearchDepth = MAXDEPTH - 1;
519 contempt = 0;
520 GameCnt = 0;
521 Game50 = 1;
522 CptrFlag[0] = TesujiFlag[0] = false;
523 hint = OPENING_HINT;
524 ZeroRPT();
525 GameType[0] = GameType[1] = UNKNOWN;
526 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
527 opponent = player = black;
528 computer = white;
530 for (l = 0; l < TREE; l++)
531 Tree[l].f = Tree[l].t = 0;
533 gsrand((unsigned int) 1);
535 if (!InitFlag)
537 for (c = black; c <= white; c++)
539 for (p = pawn; p <= king; p++)
541 for (l = 0; l < NO_SQUARES; l++)
543 (*hashcode)[c][p][l].key
544 = (((unsigned long) urand()));
545 (*hashcode)[c][p][l].key
546 += (((unsigned long) urand()) << 16);
547 (*hashcode)[c][p][l].bd
548 = (((unsigned long) urand()));
549 (*hashcode)[c][p][l].bd
550 += (((unsigned long) urand()) << 16);
551 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
552 (*hashcode)[c][p][l].key
553 += (((unsigned long) urand()) << 32);
554 (*hashcode)[c][p][l].key
555 += (((unsigned long) urand()) << 48);
556 (*hashcode)[c][p][l].bd
557 += (((unsigned long) urand()) << 32);
558 (*hashcode)[c][p][l].bd
559 += (((unsigned long) urand()) << 48);
560 #endif
565 for (c = black; c <= white; c++)
567 for (p = pawn; p <= king; p++)
569 for (l = 0; l < MAX_CAPTURED; l++)
571 (*drop_hashcode)[c][p][l].key
572 = (((unsigned long) urand()));
573 (*drop_hashcode)[c][p][l].key
574 += (((unsigned long) urand()) << 16);
575 (*drop_hashcode)[c][p][l].bd
576 = (((unsigned long) urand()));
577 (*drop_hashcode)[c][p][l].bd
578 += (((unsigned long) urand()) << 16);
579 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
580 (*drop_hashcode)[c][p][l].key
581 += (((unsigned long) urand()) << 32);
582 (*drop_hashcode)[c][p][l].key
583 += (((unsigned long) urand()) << 48);
584 (*drop_hashcode)[c][p][l].bd
585 += (((unsigned long) urand()) << 32);
586 (*drop_hashcode)[c][p][l].bd
587 += (((unsigned long) urand()) << 48);
588 #endif
594 for (l = 0; l < NO_SQUARES; l++)
596 board[l] = Stboard[l];
597 color[l] = Stcolor[l];
598 Mvboard[l] = 0;
601 ClearCaptured();
602 dsp->ClearScreen();
603 InitializeStats();
605 #ifdef HAVE_GETTIMEOFDAY
606 gettimeofday(&tv, NULL);
607 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
608 #else
609 time0 = time((long *) 0);
610 #endif
612 /* resetting reference time */
613 ElapsedTime(COMPUTE_AND_INIT_MODE);
614 flag.regularstart = true;
615 Book = BOOKFAIL;
617 if (!InitFlag)
619 char sx[256];
620 strcpy(sx, "level");
622 if (TCflag)
623 SetTimeControl();
624 else if (MaxResponseTime == 0)
625 dsp->SelectLevel(sx);
627 dsp->UpdateDisplay(0, 0, 1, 0);
628 GetOpenings();
629 GetOpeningPatterns(&max_opening_sequence);
631 InitFlag = true;
634 #if ttblsz
635 if (TTadd)
637 ZeroTTable();
638 TTadd = 0;
640 #endif /* ttblsz */
642 hashbd = hashkey = 0;
643 return;
650 InitMain(void)
652 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
654 #if ttblsz
655 ttblsize = ttblsz;
656 rehash = -1;
657 #endif /* ttblsz */
659 if (Initialize_data() != 0)
660 return 1;
662 XC = 0;
663 MaxResponseTime = 0;
665 if (XSHOGI)
667 TCmoves = 40;
668 TCminutes = 5;
669 TCseconds = 0;
670 TCadd = 0;
672 TCflag = true;
673 OperatorTime = 0;
675 else
677 TCflag = false;
678 OperatorTime = 0;
681 dsp->Initialize();
682 Initialize_dist();
683 Initialize_eval();
684 #if !defined SAVE_NEXTPOS
685 Initialize_moves();
686 #endif
688 NewGame();
690 flag.easy = ahead;
691 flag.hash = hash;
693 if (xwin)
694 xwndw = atoi(xwin);
696 #ifdef HASHFILE
697 hashfile = NULL;
698 #endif
700 #if ttblsz
701 #ifdef HASHFILE
702 hashfile = fopen(HASHFILE, RWA_ACC);
704 if (hashfile)
706 fseek(hashfile, 0L, SEEK_END);
707 filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
708 hashmask = filesz >> 1;
709 hashbase = hashmask + 1;
711 #endif /* HASHFILE */
712 #endif /* ttblsz */
714 savefile[0] = '\0';
715 listfile[0] = '\0';
717 return 0;
721 void
722 ExitMain(void)
724 #if ttblsz
725 #ifdef HASHFILE
726 if (hashfile)
727 fclose(hashfile);
728 #endif /* HASHFILE */
729 #endif /* ttblsz */
731 dsp->ExitShogi();