4 * ----------------------------------------------------------------------
5 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
6 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
8 * GNU SHOGI is based on GNU CHESS
10 * Copyright (c) 1988, 1989, 1990 John Stanback
11 * Copyright (c) 1992 Free Software Foundation
13 * This file is part of GNU SHOGI.
15 * GNU Shogi is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 3 of the License,
18 * or (at your option) any later version.
20 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
21 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 * You should have received a copy of the GNU General Public License along
26 * with GNU Shogi; see the file COPYING. If not, see
27 * <http://www.gnu.org/licenses/>.
28 * ----------------------------------------------------------------------
34 #if defined HAVE_GETTIMEOFDAY
42 /****************************************
43 * A variety of global flags.
44 ****************************************/
47 * If hard_time_limit is nonzero, exceeding the time limit means
51 short hard_time_limit = 1;
52 short barebones = 0; /* Suppress printing of statistics
53 * (mainly for xshogi). */
55 short nolist = 0; /* List the game after exit. */
57 short nolist = 1; /* Don't list the game after exit. */
61 * The default display type can be DISPLAY_RAW, DISPLAY_CURSES,
62 * or DISPLAY_X; the default is DISPLAY_X to make life easier for xshogi.
65 display_t display_type = DISPLAY_X;
67 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
70 const small_short psweep[NO_PTYPE_PIECES] =
72 false, true, false, false, false, true, true, true, true, false,
73 false, true, false, false, false
77 const small_short sweep[NO_PIECES] =
83 false, false, true, true,
88 false, true, true, false
94 distance(short a, short b)
96 return (short)computed_distance(a, b);
100 distance(short a, short b)
103 ? (short)(*distdata)[(int)a][(int)b]
104 : (short)computed_distance(a, b));
110 Initialize_dist(void)
112 short a, b, d, di, ptyp;
113 #ifndef SAVE_DISTDATA
114 for (a = 0; a < NO_SQUARES; a++)
116 for (b = 0; b < NO_SQUARES; b++)
118 d = abs(column(a) - column(b));
119 di = abs(row(a) - row(b));
120 (*distdata)[a][b] = (small_short)((d > di) ? d : di);
124 #ifndef SAVE_PTYPE_DISTDATA
125 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
127 for (a = 0; a < NO_SQUARES; a++)
128 for (b = 0; b < NO_SQUARES; b++)
129 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
136 * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
137 * of positions reachable from from-square in ppos with ptype such that the
140 * ppos = nextpos[ptype][from-square];
141 * pdir = nextdir[ptype][from-square];
148 * if(color[u] != neutral)
153 * will generate the sequence of all squares reachable from sq.
155 * If the path is blocked u = pdir[sq] will generate the continuation of the
156 * sequence in other directions.
160 const small_short is_promoted[NO_PIECES] =
166 false, false, false, false,
171 true, true, true, false
174 /* data used to generate nextpos/nextdir */
176 /* FIXME: use predefined constants ! */
177 #if !defined SAVE_NEXTPOS
180 const small_short direc[NO_PTYPE_PIECES][8] =
182 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
183 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
184 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
185 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
186 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
187 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
188 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
189 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
190 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
191 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
192 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
193 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
194 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
195 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
196 { -10, -11, -12, 1, -1, 11, 0, 0 } /* 14 ptype_wgold */
199 #if !defined SAVE_NEXTPOS
202 const small_short direc[NO_PTYPE_PIECES][8] =
204 { 7, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
205 { 6, 7, 8, -8, -6, 0, 0, 0 }, /* 3 ptype_silver */
206 { 6, 7, 8, -1, 1, -7, 0, 0 }, /* 4 ptype_gold */
207 { 6, 8, -8, -6, 0, 0, 0, 0 }, /* 5 ptype_bishop */
208 { 7, -1, 1, -7, 0, 0, 0, 0 }, /* 6 ptype_rook */
209 { 6, 8, -8, -6, 7, -1, 1, -7 }, /* 7 ptype_pbishop */
210 { 7, -1, 1, -7, 6, 8, -8, -6 }, /* 8 ptype_prook */
211 { 6, 7, 8, -1, 1, -8, -7, -6 }, /* 9 ptype_king */
212 { -7, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
213 { -6, -7, -8, 8, 6, 0, 0, 0 }, /* 13 ptype_wsilver */
214 { -6, -7, -8, 1, -1, 7, 0, 0 } /* 14 ptype_wgold */
219 small_short diagonal(short d)
221 return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
227 static const small_short max_steps[NO_PTYPE_PIECES] =
229 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
232 static const small_short max_steps[NO_PTYPE_PIECES] =
234 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
239 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
241 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
242 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
243 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
244 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
245 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
246 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
247 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
248 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
249 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
250 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
251 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
252 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
253 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
257 const small_short inunmap[NO_SQUARES] =
259 23, 24, 25, 26, 27, 28, 29, 30, 31,
260 34, 35, 36, 37, 38, 39, 40, 41, 42,
261 45, 46, 47, 48, 49, 50, 51, 52, 53,
262 56, 57, 58, 59, 60, 61, 62, 63, 64,
263 67, 68, 69, 70, 71, 72, 73, 74, 75,
264 78, 79, 80, 81, 82, 83, 84, 85, 86,
265 89, 90, 91, 92, 93, 94, 95, 96, 97,
266 100, 101, 102, 103, 104, 105, 106, 107, 108,
267 111, 112, 113, 114, 115, 116, 117, 118, 119
270 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 2)] =
272 -1, -1, -1, -1, -1, -1, -1,
273 -1, 0, 1, 2, 3, 4, -1,
274 -1, 5, 6, 7, 8, 9, -1,
275 -1, 10, 11, 12, 13, 14, -1,
276 -1, 15, 16, 17, 18, 19, -1,
277 -1, 20, 21, 22, 23, 24, -1,
278 -1, -1, -1, -1, -1, -1, -1,
282 const small_short inunmap[NO_SQUARES] =
292 int InitFlag = false;
295 #if defined SAVE_NEXTPOS
298 next_direction(short ptyp, short *d, short sq)
300 short delta, to, sfrom = inunmap[sq];
308 delta = direc[ptyp][*d];
312 to = nunmap[sfrom + delta];
321 next_position(short ptyp, short *d, short sq, short u)
323 if (*d < 4 && psweep[ptyp])
325 short to = nunmap[inunmap[u] + direc[ptyp][*d]];
328 return next_direction(ptyp, d, sq);
334 return next_direction(ptyp, d, sq);
340 first_direction(short ptyp, short *d, short sq)
343 return next_direction(ptyp, d, sq);
349 * This procedure pre-calculates all moves for every piece from every
350 * square. This data is stored in nextpos/nextdir and used later in the
351 * move generation routines.
355 Initialize_moves(void)
357 short ptyp, po, p0, d, di, s, delta;
358 unsigned char *ppos, *pdir;
362 short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
364 /* pre-fill nextpos and nextdir with source position, probably so
365 * (color[u] == neutral) stops to match once all moves have been seen
367 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
369 for (po = 0; po < NO_SQUARES; po++)
371 for (p0 = 0; p0 < NO_SQUARES; p0++)
373 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
374 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
379 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
381 for (po = fpo; po < tpo; po++)
383 if (nunmap[po] >= (small_short)0)
385 ppos = (*nextpos[ptyp])[nunmap[po]];
386 pdir = (*nextdir[ptyp])[nunmap[po]];
388 /* dest is a function of direction and steps */
389 for (d = 0; d < 8; d++)
391 dest[d][0] = nunmap[po];
392 delta = direc[ptyp][d];
398 for (s = 0; s < max_steps[ptyp]; s++)
403 * break if (off board) or (promoted rooks
404 * wishes to move two steps diagonal) or
405 * (promoted bishops wishes to move two steps
408 if ((nunmap[p0] < (small_short)0)
409 || ((ptyp == ptype_prook)
412 || ((ptyp == ptype_pbishop)
414 && !diagonal(delta)))
417 dest[d][s] = nunmap[p0];
426 * Sort dest in number of steps order; currently no sort
427 * is done due to compatibility with the move generation
428 * order in old gnuchess.
433 for (di = d; s > 0 && di > 0; di--)
435 if (steps[sorted[di - 1]] == 0) /* should be: < s */
436 sorted[di] = sorted[di - 1];
445 * update nextpos/nextdir
449 pdir[p0] = (unsigned char)dest[sorted[0]][0];
451 for (d = 0; d < 8; d++)
453 for (s = 0; s < steps[sorted[d]]; s++)
455 ppos[p0] = (unsigned char)dest[sorted[d]][s];
456 p0 = dest[sorted[d]][s];
459 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
462 * else is already initialized
476 * Reset the board and other variables to start a new game.
482 short l, c, p, max_opening_sequence;
483 #ifdef HAVE_GETTIMEOFDAY
486 compptr = oppptr = 0;
488 stage2 = -1; /* the game is not yet started */
489 flag.illegal = flag.mate = flag.post = flag.quit
490 = flag.reverse = flag.bothsides = flag.onemove = flag.force
492 flag.material = flag.coords = flag.hash = flag.easy
493 = flag.beep = flag.rcptr
495 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
500 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
509 MaxSearchDepth = MAXDEPTH - 1;
514 CptrFlag[0] = TesujiFlag[0] = false;
517 GameType[0] = GameType[1] = UNKNOWN;
518 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
519 opponent = player = black;
522 for (l = 0; l < TREE; l++)
523 Tree[l].f = Tree[l].t = 0;
525 gsrand((unsigned int) 1);
529 for (c = black; c <= white; c++)
531 for (p = pawn; p <= king; p++)
533 for (l = 0; l < NO_SQUARES; l++)
535 (*hashcode)[c][p][l].key
536 = (((unsigned long) urand()));
537 (*hashcode)[c][p][l].key
538 += (((unsigned long) urand()) << 16);
539 (*hashcode)[c][p][l].bd
540 = (((unsigned long) urand()));
541 (*hashcode)[c][p][l].bd
542 += (((unsigned long) urand()) << 16);
543 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
544 (*hashcode)[c][p][l].key
545 += (((unsigned long) urand()) << 32);
546 (*hashcode)[c][p][l].key
547 += (((unsigned long) urand()) << 48);
548 (*hashcode)[c][p][l].bd
549 += (((unsigned long) urand()) << 32);
550 (*hashcode)[c][p][l].bd
551 += (((unsigned long) urand()) << 48);
557 for (c = black; c <= white; c++)
559 for (p = pawn; p <= king; p++)
561 for (l = 0; l < MAX_CAPTURED; l++)
563 (*drop_hashcode)[c][p][l].key
564 = (((unsigned long) urand()));
565 (*drop_hashcode)[c][p][l].key
566 += (((unsigned long) urand()) << 16);
567 (*drop_hashcode)[c][p][l].bd
568 = (((unsigned long) urand()));
569 (*drop_hashcode)[c][p][l].bd
570 += (((unsigned long) urand()) << 16);
571 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
572 (*drop_hashcode)[c][p][l].key
573 += (((unsigned long) urand()) << 32);
574 (*drop_hashcode)[c][p][l].key
575 += (((unsigned long) urand()) << 48);
576 (*drop_hashcode)[c][p][l].bd
577 += (((unsigned long) urand()) << 32);
578 (*drop_hashcode)[c][p][l].bd
579 += (((unsigned long) urand()) << 48);
586 for (l = 0; l < NO_SQUARES; l++)
588 board[l] = Stboard[l];
589 color[l] = Stcolor[l];
597 #ifdef HAVE_GETTIMEOFDAY
598 gettimeofday(&tv, NULL);
599 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
601 time0 = time((long *) 0);
604 /* resetting reference time */
605 ElapsedTime(COMPUTE_AND_INIT_MODE);
606 flag.regularstart = true;
616 else if (MaxResponseTime == 0)
619 UpdateDisplay(0, 0, 1, 0);
621 GetOpeningPatterns(&max_opening_sequence);
634 hashbd = hashkey = 0;
644 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
651 if (Initialize_data() != 0)
654 strcpy(ColorStr[0], "Black");
655 strcpy(ColorStr[1], "White");
681 #if !defined SAVE_NEXTPOS
699 hashfile = fopen(HASHFILE, RWA_ACC);
703 fseek(hashfile, 0L, SEEK_END);
704 filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
705 hashmask = filesz >> 1;
706 hashbase = hashmask + 1;
708 #endif /* HASHFILE */
725 #endif /* HASHFILE */