Prepare v1.4.2.
[gnushogi.git] / gnushogi / init.c
blob742b754aa6d62e1858d064593aa7030b0990bdc8
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, true, false, false, false, true, true, true, true, false,
74 false, true, false, false, false
76 #endif
78 const small_short sweep[NO_PIECES] =
80 false, false,
81 #ifndef MINISHOGI
82 true, false,
83 #endif
84 false, false, true, true,
85 false,
86 #ifndef MINISHOGI
87 false, false,
88 #endif
89 false, true, true, false
93 #ifdef SAVE_DISTDATA
94 short
95 distance(short a, short b)
97 return (short)computed_distance(a, b);
99 #else
100 short
101 distance(short a, short b)
103 return (use_distdata
104 ? (short)(*distdata)[(int)a][(int)b]
105 : (short)computed_distance(a, b));
107 #endif
110 void
111 Initialize_dist(void)
113 short a, b, d, di, ptyp;
114 #ifndef SAVE_DISTDATA
115 for (a = 0; a < NO_SQUARES; a++)
117 for (b = 0; b < NO_SQUARES; b++)
119 d = abs(column(a) - column(b));
120 di = abs(row(a) - row(b));
121 (*distdata)[a][b] = (small_short)((d > di) ? d : di);
124 #endif
125 #ifndef SAVE_PTYPE_DISTDATA
126 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
128 for (a = 0; a < NO_SQUARES; a++)
129 for (b = 0; b < NO_SQUARES; b++)
130 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
132 #endif
137 * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
138 * of positions reachable from from-square in ppos with ptype such that the
139 * sequence
141 * ppos = nextpos[ptype][from-square];
142 * pdir = nextdir[ptype][from-square];
143 * u = ppos[sq];
145 * do
147 * u = ppos[u];
149 * if(color[u] != neutral)
150 * u = pdir[u];
152 * while (sq != u);
154 * will generate the sequence of all squares reachable from sq.
156 * If the path is blocked u = pdir[sq] will generate the continuation of the
157 * sequence in other directions.
161 const small_short is_promoted[NO_PIECES] =
163 false, false,
164 #ifndef MINISHOGI
165 false, false,
166 #endif
167 false, false, false, false,
168 true,
169 #ifndef MINISHOGI
170 true, true,
171 #endif
172 true, true, true, false
175 /* data used to generate nextpos/nextdir */
176 #ifndef MINISHOGI
177 /* FIXME: use predefined constants ! */
178 #if !defined SAVE_NEXTPOS
179 static
180 #endif
181 const small_short direc[NO_PTYPE_PIECES][8] =
183 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
184 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
185 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
186 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
187 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
188 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
189 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
190 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
191 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
192 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
193 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
194 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
195 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
196 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
197 { -10, -11, -12, 1, -1, 11, 0, 0 } /* 14 ptype_wgold */
199 #else
200 #if !defined SAVE_NEXTPOS
201 static
202 #endif
203 const small_short direc[NO_PTYPE_PIECES][8] =
205 { 7, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
206 { 6, 7, 8, -8, -6, 0, 0, 0 }, /* 3 ptype_silver */
207 { 6, 7, 8, -1, 1, -7, 0, 0 }, /* 4 ptype_gold */
208 { 6, 8, -8, -6, 0, 0, 0, 0 }, /* 5 ptype_bishop */
209 { 7, -1, 1, -7, 0, 0, 0, 0 }, /* 6 ptype_rook */
210 { 6, 8, -8, -6, 7, -1, 1, -7 }, /* 7 ptype_pbishop */
211 { 7, -1, 1, -7, 6, 8, -8, -6 }, /* 8 ptype_prook */
212 { 6, 7, 8, -1, 1, -8, -7, -6 }, /* 9 ptype_king */
213 { -7, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
214 { -6, -7, -8, 8, 6, 0, 0, 0 }, /* 13 ptype_wsilver */
215 { -6, -7, -8, 1, -1, 7, 0, 0 } /* 14 ptype_wgold */
217 #endif
220 small_short diagonal(short d)
222 return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
226 #ifndef MINISHOGI
227 /* FIXME */
228 static const small_short max_steps[NO_PTYPE_PIECES] =
230 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
232 #else
233 static const small_short max_steps[NO_PTYPE_PIECES] =
235 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
237 #endif
239 #ifndef MINISHOGI
240 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
242 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
243 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
244 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
245 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
246 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
247 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
248 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
249 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
250 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
251 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
252 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
253 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
254 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
258 const small_short inunmap[NO_SQUARES] =
260 23, 24, 25, 26, 27, 28, 29, 30, 31,
261 34, 35, 36, 37, 38, 39, 40, 41, 42,
262 45, 46, 47, 48, 49, 50, 51, 52, 53,
263 56, 57, 58, 59, 60, 61, 62, 63, 64,
264 67, 68, 69, 70, 71, 72, 73, 74, 75,
265 78, 79, 80, 81, 82, 83, 84, 85, 86,
266 89, 90, 91, 92, 93, 94, 95, 96, 97,
267 100, 101, 102, 103, 104, 105, 106, 107, 108,
268 111, 112, 113, 114, 115, 116, 117, 118, 119
270 #else
271 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 2)] =
273 -1, -1, -1, -1, -1, -1, -1,
274 -1, 0, 1, 2, 3, 4, -1,
275 -1, 5, 6, 7, 8, 9, -1,
276 -1, 10, 11, 12, 13, 14, -1,
277 -1, 15, 16, 17, 18, 19, -1,
278 -1, 20, 21, 22, 23, 24, -1,
279 -1, -1, -1, -1, -1, -1, -1,
283 const small_short inunmap[NO_SQUARES] =
285 8, 9, 10, 11, 12,
286 15, 16, 17, 18, 19,
287 22, 23, 24, 25, 26,
288 29, 30, 31, 32, 33,
289 36, 37, 38, 39, 40,
291 #endif
293 int InitFlag = false;
296 #if defined SAVE_NEXTPOS
298 short
299 next_direction(short ptyp, short *d, short sq)
301 short delta, to, sfrom = inunmap[sq];
305 (*d)++;
306 if (*d >= 8)
307 return sq;
309 delta = direc[ptyp][*d];
310 if (delta == 0)
311 return sq;
313 to = nunmap[sfrom + delta];
315 while (to < 0);
317 return to;
321 short
322 next_position(short ptyp, short *d, short sq, short u)
324 if (*d < 4 && psweep[ptyp])
326 short to = nunmap[inunmap[u] + direc[ptyp][*d]];
328 if (to < 0)
329 return next_direction(ptyp, d, sq);
330 else
331 return to;
333 else
335 return next_direction(ptyp, d, sq);
340 short
341 first_direction(short ptyp, short *d, short sq)
343 *d = -1;
344 return next_direction(ptyp, d, sq);
347 #else
350 * This procedure pre-calculates all moves for every piece from every
351 * square. This data is stored in nextpos/nextdir and used later in the
352 * move generation routines.
355 void
356 Initialize_moves(void)
358 short ptyp, po, p0, d, di, s, delta;
359 unsigned char *ppos, *pdir;
360 short dest[8][9];
361 short sorted[9];
362 short steps[8];
363 short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
365 /* pre-fill nextpos and nextdir with source position, probably so
366 * (color[u] == neutral) stops to match once all moves have been seen
368 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
370 for (po = 0; po < NO_SQUARES; po++)
372 for (p0 = 0; p0 < NO_SQUARES; p0++)
374 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
375 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
380 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
382 for (po = fpo; po < tpo; po++)
384 if (nunmap[po] >= (small_short)0)
386 ppos = (*nextpos[ptyp])[nunmap[po]];
387 pdir = (*nextdir[ptyp])[nunmap[po]];
389 /* dest is a function of direction and steps */
390 for (d = 0; d < 8; d++)
392 dest[d][0] = nunmap[po];
393 delta = direc[ptyp][d];
395 if (delta != 0)
397 p0 = po;
399 for (s = 0; s < max_steps[ptyp]; s++)
401 p0 = p0 + delta;
404 * break if (off board) or (promoted rooks
405 * wishes to move two steps diagonal) or
406 * (promoted bishops wishes to move two steps
407 * non-diagonal)
409 if ((nunmap[p0] < (small_short)0)
410 || ((ptyp == ptype_prook)
411 && (s > 0)
412 && diagonal(delta))
413 || ((ptyp == ptype_pbishop)
414 && (s > 0)
415 && !diagonal(delta)))
416 break;
417 else
418 dest[d][s] = nunmap[p0];
421 else
423 s = 0;
427 * Sort dest in number of steps order; currently no sort
428 * is done due to compatibility with the move generation
429 * order in old gnuchess.
432 steps[d] = s;
434 for (di = d; s > 0 && di > 0; di--)
436 if (steps[sorted[di - 1]] == 0) /* should be: < s */
437 sorted[di] = sorted[di - 1];
438 else
439 break;
442 sorted[di] = d;
446 * update nextpos/nextdir
449 p0 = nunmap[po];
450 pdir[p0] = (unsigned char)dest[sorted[0]][0];
452 for (d = 0; d < 8; d++)
454 for (s = 0; s < steps[sorted[d]]; s++)
456 ppos[p0] = (unsigned char)dest[sorted[d]][s];
457 p0 = dest[sorted[d]][s];
459 if (d < 7)
460 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
463 * else is already initialized
472 #endif
477 * Reset the board and other variables to start a new game.
480 void
481 NewGame(void)
483 short l, c, p, max_opening_sequence;
484 #ifdef HAVE_GETTIMEOFDAY
485 struct timeval tv;
486 #endif
487 compptr = oppptr = 0;
488 stage = 0;
489 stage2 = -1; /* the game is not yet started */
490 flag.illegal = flag.mate = flag.post = flag.quit
491 = flag.reverse = flag.bothsides = flag.onemove = flag.force
492 = false;
493 flag.material = flag.coords = flag.hash = flag.easy
494 = flag.beep = flag.rcptr
495 = true;
496 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
497 flag.gamein = false;
498 flag.rv = true;
500 mycnt1 = mycnt2 = 0;
501 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
502 znodes = ZNODES;
503 WAwindow = WAWNDW;
504 WBwindow = WBWNDW;
505 BAwindow = BAWNDW;
506 BBwindow = BBWNDW;
507 xwndw = BXWNDW;
509 if (!MaxSearchDepth)
510 MaxSearchDepth = MAXDEPTH - 1;
512 contempt = 0;
513 GameCnt = 0;
514 Game50 = 1;
515 CptrFlag[0] = TesujiFlag[0] = false;
516 hint = OPENING_HINT;
517 ZeroRPT();
518 GameType[0] = GameType[1] = UNKNOWN;
519 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
520 opponent = player = black;
521 computer = white;
523 for (l = 0; l < TREE; l++)
524 Tree[l].f = Tree[l].t = 0;
526 gsrand((unsigned int) 1);
528 if (!InitFlag)
530 for (c = black; c <= white; c++)
532 for (p = pawn; p <= king; p++)
534 for (l = 0; l < NO_SQUARES; l++)
536 (*hashcode)[c][p][l].key
537 = (((unsigned long) urand()));
538 (*hashcode)[c][p][l].key
539 += (((unsigned long) urand()) << 16);
540 (*hashcode)[c][p][l].bd
541 = (((unsigned long) urand()));
542 (*hashcode)[c][p][l].bd
543 += (((unsigned long) urand()) << 16);
544 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
545 (*hashcode)[c][p][l].key
546 += (((unsigned long) urand()) << 32);
547 (*hashcode)[c][p][l].key
548 += (((unsigned long) urand()) << 48);
549 (*hashcode)[c][p][l].bd
550 += (((unsigned long) urand()) << 32);
551 (*hashcode)[c][p][l].bd
552 += (((unsigned long) urand()) << 48);
553 #endif
558 for (c = black; c <= white; c++)
560 for (p = pawn; p <= king; p++)
562 for (l = 0; l < MAX_CAPTURED; l++)
564 (*drop_hashcode)[c][p][l].key
565 = (((unsigned long) urand()));
566 (*drop_hashcode)[c][p][l].key
567 += (((unsigned long) urand()) << 16);
568 (*drop_hashcode)[c][p][l].bd
569 = (((unsigned long) urand()));
570 (*drop_hashcode)[c][p][l].bd
571 += (((unsigned long) urand()) << 16);
572 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
573 (*drop_hashcode)[c][p][l].key
574 += (((unsigned long) urand()) << 32);
575 (*drop_hashcode)[c][p][l].key
576 += (((unsigned long) urand()) << 48);
577 (*drop_hashcode)[c][p][l].bd
578 += (((unsigned long) urand()) << 32);
579 (*drop_hashcode)[c][p][l].bd
580 += (((unsigned long) urand()) << 48);
581 #endif
587 for (l = 0; l < NO_SQUARES; l++)
589 board[l] = Stboard[l];
590 color[l] = Stcolor[l];
591 Mvboard[l] = 0;
594 ClearCaptured();
595 ClearScreen();
596 InitializeStats();
598 #ifdef HAVE_GETTIMEOFDAY
599 gettimeofday(&tv, NULL);
600 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
601 #else
602 time0 = time((long *) 0);
603 #endif
605 /* resetting reference time */
606 ElapsedTime(COMPUTE_AND_INIT_MODE);
607 flag.regularstart = true;
608 Book = BOOKFAIL;
610 if (!InitFlag)
612 char sx[256];
613 strcpy(sx, "level");
615 if (TCflag)
616 SetTimeControl();
617 else if (MaxResponseTime == 0)
618 SelectLevel(sx);
620 UpdateDisplay(0, 0, 1, 0);
621 GetOpenings();
622 GetOpeningPatterns(&max_opening_sequence);
624 InitFlag = true;
627 #if ttblsz
628 if (TTadd)
630 ZeroTTable();
631 TTadd = 0;
633 #endif /* ttblsz */
635 hashbd = hashkey = 0;
636 return;
643 InitMain(void)
645 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
647 #if ttblsz
648 ttblsize = ttblsz;
649 rehash = -1;
650 #endif /* ttblsz */
652 if (Initialize_data() != 0)
653 return 1;
655 strcpy(ColorStr[0], "Black");
656 strcpy(ColorStr[1], "White");
658 XC = 0;
659 MaxResponseTime = 0;
661 if (XSHOGI)
663 TCmoves = 40;
664 TCminutes = 5;
665 TCseconds = 0;
666 TCadd = 0;
668 TCflag = true;
669 OperatorTime = 0;
670 barebones = 1;
672 else
674 TCflag = false;
675 OperatorTime = 0;
676 barebones = 0;
679 Initialize();
680 Initialize_dist();
681 Initialize_eval();
682 #if !defined SAVE_NEXTPOS
683 Initialize_moves();
684 #endif
686 NewGame();
688 flag.easy = ahead;
689 flag.hash = hash;
691 if (xwin)
692 xwndw = atoi(xwin);
694 #ifdef HASHFILE
695 hashfile = NULL;
696 #endif
698 #if ttblsz
699 #ifdef HASHFILE
700 hashfile = fopen(HASHFILE, RWA_ACC);
702 if (hashfile)
704 fseek(hashfile, 0L, SEEK_END);
705 filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
706 hashmask = filesz >> 1;
707 hashbase = hashmask + 1;
709 #endif /* HASHFILE */
710 #endif /* ttblsz */
712 savefile[0] = '\0';
713 listfile[0] = '\0';
715 return 0;
719 void
720 ExitMain(void)
722 #if ttblsz
723 #ifdef HASHFILE
724 if (hashfile)
725 fclose(hashfile);
726 #endif /* HASHFILE */
727 #endif /* ttblsz */
729 ExitShogi();