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
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 * ----------------------------------------------------------------------
35 #if defined HAVE_GETTIMEOFDAY
43 /****************************************
44 * A variety of global flags.
45 ****************************************/
48 * If hard_time_limit is nonzero, exceeding the time limit means
52 short hard_time_limit = 1;
54 short nolist = 0; /* List the game after exit. */
56 short nolist = 1; /* Don't list the game after exit. */
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 .... */
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
76 const small_short sweep[NO_PIECES] =
82 false, false, true, true,
87 false, true, true, false
93 distance(short a, short b)
95 return (short)computed_distance(a, b);
99 distance(short a, short b)
102 ? (short)(*distdata)[(int)a][(int)b]
103 : (short)computed_distance(a, b));
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);
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);
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
139 * ppos = nextpos[ptype][from-square];
140 * pdir = nextdir[ptype][from-square];
147 * if(color[u] != neutral)
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] =
165 false, false, false, false,
170 true, true, true, false
173 /* data used to generate nextpos/nextdir */
175 /* FIXME: use predefined constants ! */
176 #if !defined SAVE_NEXTPOS
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 */
198 #if !defined SAVE_NEXTPOS
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 */
218 small_short diagonal(short d)
220 return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
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
231 static const small_short max_steps[NO_PTYPE_PIECES] =
233 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
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
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] =
291 int InitFlag = false;
294 #if defined SAVE_NEXTPOS
297 next_direction(short ptyp, short *d, short sq)
299 short delta, to, sfrom = inunmap[sq];
307 delta = direc[ptyp][*d];
311 to = nunmap[sfrom + delta];
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]];
327 return next_direction(ptyp, d, sq);
333 return next_direction(ptyp, d, sq);
339 first_direction(short ptyp, short *d, short sq)
342 return next_direction(ptyp, d, sq);
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.
354 Initialize_moves(void)
356 short ptyp, po, p0, d, di, s, delta;
357 unsigned char *ppos, *pdir;
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];
397 for (s = 0; s < max_steps[ptyp]; s++)
402 * break if (off board) or (promoted rooks
403 * wishes to move two steps diagonal) or
404 * (promoted bishops wishes to move two steps
407 if ((nunmap[p0] < (small_short)0)
408 || ((ptyp == ptype_prook)
411 || ((ptyp == ptype_pbishop)
413 && !diagonal(delta)))
416 dest[d][s] = nunmap[p0];
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.
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];
444 * update nextpos/nextdir
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];
458 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
461 * else is already initialized
475 * Reset the board and other variables to start a new game.
481 short l, c, p, max_opening_sequence;
482 #ifdef HAVE_GETTIMEOFDAY
485 compptr = oppptr = 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
491 flag.material = flag.coords = flag.hash = flag.easy
492 = flag.beep = flag.rcptr
494 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
499 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
508 MaxSearchDepth = MAXDEPTH - 1;
513 CptrFlag[0] = TesujiFlag[0] = false;
516 GameType[0] = GameType[1] = UNKNOWN;
517 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
518 opponent = player = black;
521 for (l = 0; l < TREE; l++)
522 Tree[l].f = Tree[l].t = 0;
524 gsrand((unsigned int) 1);
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);
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);
585 for (l = 0; l < NO_SQUARES; l++)
587 board[l] = Stboard[l];
588 color[l] = Stcolor[l];
596 #ifdef HAVE_GETTIMEOFDAY
597 gettimeofday(&tv, NULL);
598 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
600 time0 = time((long *) 0);
603 /* resetting reference time */
604 ElapsedTime(COMPUTE_AND_INIT_MODE);
605 flag.regularstart = true;
615 else if (MaxResponseTime == 0)
616 dsp->SelectLevel(sx);
618 dsp->UpdateDisplay(0, 0, 1, 0);
620 GetOpeningPatterns(&max_opening_sequence);
633 hashbd = hashkey = 0;
643 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
650 if (Initialize_data() != 0)
653 strcpy(ColorStr[0], "Black");
654 strcpy(ColorStr[1], "White");
678 #if !defined SAVE_NEXTPOS
696 hashfile = fopen(HASHFILE, RWA_ACC);
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 */
722 #endif /* HASHFILE */