Get rid of redundant "barebones" flag, essentially used as synonym for "XSHOGI".
[gnushogi.git] / gnushogi / init.c
blob679b38207f830ba32677025b586b60db4e2a621c
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 const small_short psweep[NO_PTYPE_PIECES] =
71 false, true, false, false, false, true, true, true, true, false,
72 false, true, false, false, false
74 #endif
76 const small_short sweep[NO_PIECES] =
78 false, false,
79 #ifndef MINISHOGI
80 true, false,
81 #endif
82 false, false, true, true,
83 false,
84 #ifndef MINISHOGI
85 false, false,
86 #endif
87 false, true, true, false
91 #ifdef SAVE_DISTDATA
92 short
93 distance(short a, short b)
95 return (short)computed_distance(a, b);
97 #else
98 short
99 distance(short a, short b)
101 return (use_distdata
102 ? (short)(*distdata)[(int)a][(int)b]
103 : (short)computed_distance(a, b));
105 #endif
108 void
109 Initialize_dist(void)
111 short a, b, d, di, ptyp;
112 #ifndef SAVE_DISTDATA
113 for (a = 0; a < NO_SQUARES; a++)
115 for (b = 0; b < NO_SQUARES; b++)
117 d = abs(column(a) - column(b));
118 di = abs(row(a) - row(b));
119 (*distdata)[a][b] = (small_short)((d > di) ? d : di);
122 #endif
123 #ifndef SAVE_PTYPE_DISTDATA
124 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
126 for (a = 0; a < NO_SQUARES; a++)
127 for (b = 0; b < NO_SQUARES; b++)
128 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
130 #endif
135 * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
136 * of positions reachable from from-square in ppos with ptype such that the
137 * sequence
139 * ppos = nextpos[ptype][from-square];
140 * pdir = nextdir[ptype][from-square];
141 * u = ppos[sq];
143 * do
145 * u = ppos[u];
147 * if(color[u] != neutral)
148 * u = pdir[u];
150 * while (sq != u);
152 * will generate the sequence of all squares reachable from sq.
154 * If the path is blocked u = pdir[sq] will generate the continuation of the
155 * sequence in other directions.
159 const small_short is_promoted[NO_PIECES] =
161 false, false,
162 #ifndef MINISHOGI
163 false, false,
164 #endif
165 false, false, false, false,
166 true,
167 #ifndef MINISHOGI
168 true, true,
169 #endif
170 true, true, true, false
173 /* data used to generate nextpos/nextdir */
174 #ifndef MINISHOGI
175 /* FIXME: use predefined constants ! */
176 #if !defined SAVE_NEXTPOS
177 static
178 #endif
179 const small_short direc[NO_PTYPE_PIECES][8] =
181 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
182 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
183 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
184 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
185 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
186 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
187 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
188 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
189 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
190 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
191 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
192 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
193 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
194 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
195 { -10, -11, -12, 1, -1, 11, 0, 0 } /* 14 ptype_wgold */
197 #else
198 #if !defined SAVE_NEXTPOS
199 static
200 #endif
201 const small_short direc[NO_PTYPE_PIECES][8] =
203 { 7, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
204 { 6, 7, 8, -8, -6, 0, 0, 0 }, /* 3 ptype_silver */
205 { 6, 7, 8, -1, 1, -7, 0, 0 }, /* 4 ptype_gold */
206 { 6, 8, -8, -6, 0, 0, 0, 0 }, /* 5 ptype_bishop */
207 { 7, -1, 1, -7, 0, 0, 0, 0 }, /* 6 ptype_rook */
208 { 6, 8, -8, -6, 7, -1, 1, -7 }, /* 7 ptype_pbishop */
209 { 7, -1, 1, -7, 6, 8, -8, -6 }, /* 8 ptype_prook */
210 { 6, 7, 8, -1, 1, -8, -7, -6 }, /* 9 ptype_king */
211 { -7, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
212 { -6, -7, -8, 8, 6, 0, 0, 0 }, /* 13 ptype_wsilver */
213 { -6, -7, -8, 1, -1, 7, 0, 0 } /* 14 ptype_wgold */
215 #endif
218 small_short diagonal(short d)
220 return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
224 #ifndef MINISHOGI
225 /* FIXME */
226 static const small_short max_steps[NO_PTYPE_PIECES] =
228 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
230 #else
231 static const small_short max_steps[NO_PTYPE_PIECES] =
233 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
235 #endif
237 #ifndef MINISHOGI
238 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
240 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
241 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
242 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
243 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
244 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
245 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
246 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
247 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
248 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
249 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
250 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
251 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
252 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
256 const small_short inunmap[NO_SQUARES] =
258 23, 24, 25, 26, 27, 28, 29, 30, 31,
259 34, 35, 36, 37, 38, 39, 40, 41, 42,
260 45, 46, 47, 48, 49, 50, 51, 52, 53,
261 56, 57, 58, 59, 60, 61, 62, 63, 64,
262 67, 68, 69, 70, 71, 72, 73, 74, 75,
263 78, 79, 80, 81, 82, 83, 84, 85, 86,
264 89, 90, 91, 92, 93, 94, 95, 96, 97,
265 100, 101, 102, 103, 104, 105, 106, 107, 108,
266 111, 112, 113, 114, 115, 116, 117, 118, 119
268 #else
269 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 2)] =
271 -1, -1, -1, -1, -1, -1, -1,
272 -1, 0, 1, 2, 3, 4, -1,
273 -1, 5, 6, 7, 8, 9, -1,
274 -1, 10, 11, 12, 13, 14, -1,
275 -1, 15, 16, 17, 18, 19, -1,
276 -1, 20, 21, 22, 23, 24, -1,
277 -1, -1, -1, -1, -1, -1, -1,
281 const small_short inunmap[NO_SQUARES] =
283 8, 9, 10, 11, 12,
284 15, 16, 17, 18, 19,
285 22, 23, 24, 25, 26,
286 29, 30, 31, 32, 33,
287 36, 37, 38, 39, 40,
289 #endif
291 int InitFlag = false;
294 #if defined SAVE_NEXTPOS
296 short
297 next_direction(short ptyp, short *d, short sq)
299 short delta, to, sfrom = inunmap[sq];
303 (*d)++;
304 if (*d >= 8)
305 return sq;
307 delta = direc[ptyp][*d];
308 if (delta == 0)
309 return sq;
311 to = nunmap[sfrom + delta];
313 while (to < 0);
315 return to;
319 short
320 next_position(short ptyp, short *d, short sq, short u)
322 if (*d < 4 && psweep[ptyp])
324 short to = nunmap[inunmap[u] + direc[ptyp][*d]];
326 if (to < 0)
327 return next_direction(ptyp, d, sq);
328 else
329 return to;
331 else
333 return next_direction(ptyp, d, sq);
338 short
339 first_direction(short ptyp, short *d, short sq)
341 *d = -1;
342 return next_direction(ptyp, d, sq);
345 #else
348 * This procedure pre-calculates all moves for every piece from every
349 * square. This data is stored in nextpos/nextdir and used later in the
350 * move generation routines.
353 void
354 Initialize_moves(void)
356 short ptyp, po, p0, d, di, s, delta;
357 unsigned char *ppos, *pdir;
358 short dest[8][9];
359 short sorted[9];
360 short steps[8];
361 short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
363 /* pre-fill nextpos and nextdir with source position, probably so
364 * (color[u] == neutral) stops to match once all moves have been seen
366 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
368 for (po = 0; po < NO_SQUARES; po++)
370 for (p0 = 0; p0 < NO_SQUARES; p0++)
372 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
373 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
378 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
380 for (po = fpo; po < tpo; po++)
382 if (nunmap[po] >= (small_short)0)
384 ppos = (*nextpos[ptyp])[nunmap[po]];
385 pdir = (*nextdir[ptyp])[nunmap[po]];
387 /* dest is a function of direction and steps */
388 for (d = 0; d < 8; d++)
390 dest[d][0] = nunmap[po];
391 delta = direc[ptyp][d];
393 if (delta != 0)
395 p0 = po;
397 for (s = 0; s < max_steps[ptyp]; s++)
399 p0 = p0 + delta;
402 * break if (off board) or (promoted rooks
403 * wishes to move two steps diagonal) or
404 * (promoted bishops wishes to move two steps
405 * non-diagonal)
407 if ((nunmap[p0] < (small_short)0)
408 || ((ptyp == ptype_prook)
409 && (s > 0)
410 && diagonal(delta))
411 || ((ptyp == ptype_pbishop)
412 && (s > 0)
413 && !diagonal(delta)))
414 break;
415 else
416 dest[d][s] = nunmap[p0];
419 else
421 s = 0;
425 * Sort dest in number of steps order; currently no sort
426 * is done due to compatibility with the move generation
427 * order in old gnuchess.
430 steps[d] = s;
432 for (di = d; s > 0 && di > 0; di--)
434 if (steps[sorted[di - 1]] == 0) /* should be: < s */
435 sorted[di] = sorted[di - 1];
436 else
437 break;
440 sorted[di] = d;
444 * update nextpos/nextdir
447 p0 = nunmap[po];
448 pdir[p0] = (unsigned char)dest[sorted[0]][0];
450 for (d = 0; d < 8; d++)
452 for (s = 0; s < steps[sorted[d]]; s++)
454 ppos[p0] = (unsigned char)dest[sorted[d]][s];
455 p0 = dest[sorted[d]][s];
457 if (d < 7)
458 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
461 * else is already initialized
470 #endif
475 * Reset the board and other variables to start a new game.
478 void
479 NewGame(void)
481 short l, c, p, max_opening_sequence;
482 #ifdef HAVE_GETTIMEOFDAY
483 struct timeval tv;
484 #endif
485 compptr = oppptr = 0;
486 stage = 0;
487 stage2 = -1; /* the game is not yet started */
488 flag.illegal = flag.mate = flag.post = flag.quit
489 = flag.reverse = flag.bothsides = flag.onemove = flag.force
490 = false;
491 flag.material = flag.coords = flag.hash = flag.easy
492 = flag.beep = flag.rcptr
493 = true;
494 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
495 flag.gamein = false;
496 flag.rv = true;
498 mycnt1 = mycnt2 = 0;
499 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
500 znodes = ZNODES;
501 WAwindow = WAWNDW;
502 WBwindow = WBWNDW;
503 BAwindow = BAWNDW;
504 BBwindow = BBWNDW;
505 xwndw = BXWNDW;
507 if (!MaxSearchDepth)
508 MaxSearchDepth = MAXDEPTH - 1;
510 contempt = 0;
511 GameCnt = 0;
512 Game50 = 1;
513 CptrFlag[0] = TesujiFlag[0] = false;
514 hint = OPENING_HINT;
515 ZeroRPT();
516 GameType[0] = GameType[1] = UNKNOWN;
517 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
518 opponent = player = black;
519 computer = white;
521 for (l = 0; l < TREE; l++)
522 Tree[l].f = Tree[l].t = 0;
524 gsrand((unsigned int) 1);
526 if (!InitFlag)
528 for (c = black; c <= white; c++)
530 for (p = pawn; p <= king; p++)
532 for (l = 0; l < NO_SQUARES; l++)
534 (*hashcode)[c][p][l].key
535 = (((unsigned long) urand()));
536 (*hashcode)[c][p][l].key
537 += (((unsigned long) urand()) << 16);
538 (*hashcode)[c][p][l].bd
539 = (((unsigned long) urand()));
540 (*hashcode)[c][p][l].bd
541 += (((unsigned long) urand()) << 16);
542 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
543 (*hashcode)[c][p][l].key
544 += (((unsigned long) urand()) << 32);
545 (*hashcode)[c][p][l].key
546 += (((unsigned long) urand()) << 48);
547 (*hashcode)[c][p][l].bd
548 += (((unsigned long) urand()) << 32);
549 (*hashcode)[c][p][l].bd
550 += (((unsigned long) urand()) << 48);
551 #endif
556 for (c = black; c <= white; c++)
558 for (p = pawn; p <= king; p++)
560 for (l = 0; l < MAX_CAPTURED; l++)
562 (*drop_hashcode)[c][p][l].key
563 = (((unsigned long) urand()));
564 (*drop_hashcode)[c][p][l].key
565 += (((unsigned long) urand()) << 16);
566 (*drop_hashcode)[c][p][l].bd
567 = (((unsigned long) urand()));
568 (*drop_hashcode)[c][p][l].bd
569 += (((unsigned long) urand()) << 16);
570 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
571 (*drop_hashcode)[c][p][l].key
572 += (((unsigned long) urand()) << 32);
573 (*drop_hashcode)[c][p][l].key
574 += (((unsigned long) urand()) << 48);
575 (*drop_hashcode)[c][p][l].bd
576 += (((unsigned long) urand()) << 32);
577 (*drop_hashcode)[c][p][l].bd
578 += (((unsigned long) urand()) << 48);
579 #endif
585 for (l = 0; l < NO_SQUARES; l++)
587 board[l] = Stboard[l];
588 color[l] = Stcolor[l];
589 Mvboard[l] = 0;
592 ClearCaptured();
593 dsp->ClearScreen();
594 InitializeStats();
596 #ifdef HAVE_GETTIMEOFDAY
597 gettimeofday(&tv, NULL);
598 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
599 #else
600 time0 = time((long *) 0);
601 #endif
603 /* resetting reference time */
604 ElapsedTime(COMPUTE_AND_INIT_MODE);
605 flag.regularstart = true;
606 Book = BOOKFAIL;
608 if (!InitFlag)
610 char sx[256];
611 strcpy(sx, "level");
613 if (TCflag)
614 SetTimeControl();
615 else if (MaxResponseTime == 0)
616 dsp->SelectLevel(sx);
618 dsp->UpdateDisplay(0, 0, 1, 0);
619 GetOpenings();
620 GetOpeningPatterns(&max_opening_sequence);
622 InitFlag = true;
625 #if ttblsz
626 if (TTadd)
628 ZeroTTable();
629 TTadd = 0;
631 #endif /* ttblsz */
633 hashbd = hashkey = 0;
634 return;
641 InitMain(void)
643 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
645 #if ttblsz
646 ttblsize = ttblsz;
647 rehash = -1;
648 #endif /* ttblsz */
650 if (Initialize_data() != 0)
651 return 1;
653 strcpy(ColorStr[0], "Black");
654 strcpy(ColorStr[1], "White");
656 XC = 0;
657 MaxResponseTime = 0;
659 if (XSHOGI)
661 TCmoves = 40;
662 TCminutes = 5;
663 TCseconds = 0;
664 TCadd = 0;
666 TCflag = true;
667 OperatorTime = 0;
669 else
671 TCflag = false;
672 OperatorTime = 0;
675 dsp->Initialize();
676 Initialize_dist();
677 Initialize_eval();
678 #if !defined SAVE_NEXTPOS
679 Initialize_moves();
680 #endif
682 NewGame();
684 flag.easy = ahead;
685 flag.hash = hash;
687 if (xwin)
688 xwndw = atoi(xwin);
690 #ifdef HASHFILE
691 hashfile = NULL;
692 #endif
694 #if ttblsz
695 #ifdef HASHFILE
696 hashfile = fopen(HASHFILE, RWA_ACC);
698 if (hashfile)
700 fseek(hashfile, 0L, SEEK_END);
701 filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
702 hashmask = filesz >> 1;
703 hashbase = hashmask + 1;
705 #endif /* HASHFILE */
706 #endif /* ttblsz */
708 savefile[0] = '\0';
709 listfile[0] = '\0';
711 return 0;
715 void
716 ExitMain(void)
718 #if ttblsz
719 #ifdef HASHFILE
720 if (hashfile)
721 fclose(hashfile);
722 #endif /* HASHFILE */
723 #endif /* ttblsz */
725 dsp->ExitShogi();