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 unsigned int ttbllimit;
69 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
73 #define max(a, b) (((a) < (b))?(b):(a))
75 #define odd(a) ((a) & 1)
78 const small_short piece_of_ptype[NO_PTYPE_PIECES] =
80 pawn, lance, knight, silver, gold, bishop, rook, pbishop, prook, king,
81 pawn, lance, knight, silver, gold
85 const small_short side_of_ptype[NO_PTYPE_PIECES] =
87 black, black, black, black, black, black, black, black, black, black,
88 white, white, white, white, white
92 const small_short psweep[NO_PTYPE_PIECES] =
94 false, true, false, false, false, true, true, true, true, false,
95 false, true, false, false, false
99 const small_short sweep[NO_PIECES] =
101 false, false, true, false, false, false, true, true,
102 false, false, false, false, true, true, false
107 * Determine the minimum number of moves for a piece from
108 * square "f" to square "t". If the piece cannot reach "t",
109 * the count is set to CANNOT_REACH.
112 #define csquare(sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
113 #define crow(sq) row(csquare(sq))
114 #define ccol(sq) column(csquare(sq))
117 ptype_distance(short ptyp, short f, short t)
120 short colf, colt, rowf, rowt, dcol, drow;
125 piece = piece_of_ptype[ptyp];
126 side = side_of_ptype[ptyp];
128 dcol = (colt = ccol(t)) - (colf = ccol(f));
129 drow = (rowt = crow(t)) - (rowf = crow(f));
134 if ((dcol != 0) || (drow < 1))
140 if ((dcol != 0) || (drow < 1))
146 if (odd(drow) || (odd(drow / 2) != odd(dcol)))
148 else if ((drow == 0) || ((drow / 2) < abs(dcol)))
156 if (odd(drow) == odd(dcol))
158 return max(abs(drow), abs(dcol));
162 if (abs(dcol) <= drow)
165 return (max(abs(drow), abs(dcol)) + 1);
170 if (odd(drow) == odd(dcol))
171 return (max(abs(drow), abs(dcol)));
173 return (max(abs(drow) + 1, abs(dcol)) + 1);
184 return max(drow, abs(dcol));
186 return (abs(dcol) - drow);
189 if (odd(dcol) != odd(drow))
192 return ((abs(dcol) == abs(drow)) ? 1 : 2);
195 if (odd(dcol) != odd(drow))
197 if ((abs(dcol) <= 1) && (abs(drow) <= 1))
199 else if (abs(abs(dcol) - abs(drow)) == 1)
206 return ((abs(dcol) == abs(drow)) ? 1 : 2);
210 if ((dcol == 0) || (drow == 0))
216 if ((dcol == 0) || (drow == 0))
218 else if ((abs(dcol) == 1) && (abs(drow) == 1))
224 return max(abs(drow), abs(dcol));
227 /* should never occur */
228 return (CANNOT_REACH);
235 distance(short a, short b)
237 return (short)computed_distance(a, b);
241 distance(short a, short b)
244 ? (short)(*distdata)[(int)a][(int)b]
245 : (short)computed_distance(a, b));
250 #ifdef SAVE_PTYPE_DISTDATA
252 piece_distance(short side, short piece, short f, short t)
254 return ((f > NO_SQUARES)
256 : (short)ptype_distance(ptype[side][piece], f, t));
260 piece_distance(short side, short piece, short f, short t)
262 return ((f > NO_SQUARES)
264 : (use_ptype_distdata
265 ? (short)(*ptype_distdata[ptype[side][piece]])[f][t]
266 : (short)ptype_distance(ptype[side][piece], f, t)));
272 Initialize_dist(void)
274 short a, b, d, di, ptyp;
275 #ifndef SAVE_DISTDATA
276 for (a = 0; a < NO_SQUARES; a++)
278 for (b = 0; b < NO_SQUARES; b++)
280 d = abs(column(a) - column(b));
281 di = abs(row(a) - row(b));
282 (*distdata)[a][b] = (small_short)((d > di) ? d : di);
286 #ifndef SAVE_PTYPE_DISTDATA
287 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
289 for (a = 0; a < NO_SQUARES; a++)
290 for (b = 0; b < NO_SQUARES; b++)
291 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
298 * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
299 * of positions reachable from from-square in ppos with ptype such that the
302 * ppos = nextpos[ptype][from-square];
303 * pdir = nextdir[ptype][from-square];
310 * if(color[u] != neutral)
315 * will generate the sequence of all squares reachable from sq.
317 * If the path is blocked u = pdir[sq] will generate the continuation of the
318 * sequence in other directions.
323 * ptype is used to separate black and white pawns, like this; ptyp =
324 * ptype[side][piece] piece can be used directly in nextpos/nextdir when
325 * generating moves for pieces that are not white pawns.
328 const small_short ptype[2][NO_PIECES] =
331 ptype_no_piece, ptype_pawn, ptype_lance, ptype_knight,
332 ptype_silver, ptype_gold, ptype_bishop, ptype_rook,
333 ptype_gold, ptype_gold, ptype_gold, ptype_gold,
334 ptype_pbishop, ptype_prook, ptype_king
337 ptype_no_piece, ptype_wpawn, ptype_wlance, ptype_wknight,
338 ptype_wsilver, ptype_wgold, ptype_bishop, ptype_rook,
339 ptype_wgold, ptype_wgold, ptype_wgold, ptype_wgold,
340 ptype_pbishop, ptype_prook, ptype_king
344 const small_short promoted[NO_PIECES] =
346 no_piece, ppawn, plance, pknight, psilver, gold, pbishop, prook,
347 ppawn, plance, pknight, psilver, pbishop, prook, king
350 const small_short unpromoted[NO_PIECES] =
352 no_piece, pawn, lance, knight, silver, gold, bishop, rook,
353 pawn, lance, knight, silver, bishop, rook, king
356 const small_short is_promoted[NO_PIECES] =
358 false, false, false, false, false, false, false, false,
359 true, true, true, true, true, true, false
362 /* data used to generate nextpos/nextdir */
363 #if !defined SAVE_NEXTPOS
366 const small_short direc[NO_PTYPE_PIECES][8] =
368 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
369 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
370 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
371 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
372 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
373 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
374 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
375 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
376 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
377 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
378 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
379 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
380 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
381 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
382 { -10, -11, -12, 1, -1, 11, 0, 0 }
383 }; /* 14 ptype_wgold */
386 small_short diagonal(short d)
388 return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
392 static const small_short max_steps[NO_PTYPE_PIECES] =
394 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
398 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
400 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
401 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
402 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
403 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
404 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
405 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
406 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
407 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
408 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
409 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
410 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
411 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
412 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
416 const small_short inunmap[NO_SQUARES] =
418 23, 24, 25, 26, 27, 28, 29, 30, 31,
419 34, 35, 36, 37, 38, 39, 40, 41, 42,
420 45, 46, 47, 48, 49, 50, 51, 52, 53,
421 56, 57, 58, 59, 60, 61, 62, 63, 64,
422 67, 68, 69, 70, 71, 72, 73, 74, 75,
423 78, 79, 80, 81, 82, 83, 84, 85, 86,
424 89, 90, 91, 92, 93, 94, 95, 96, 97,
425 100, 101, 102, 103, 104, 105, 106, 107, 108,
426 111, 112, 113, 114, 115, 116, 117, 118, 119
430 int InitFlag = false;
433 #if defined SAVE_NEXTPOS
436 next_direction(short ptyp, short *d, short sq)
438 short delta, to, sfrom = inunmap[sq];
446 delta = direc[ptyp][*d];
450 to = nunmap[sfrom + delta];
459 next_position(short ptyp, short *d, short sq, short u)
461 if (*d < 4 && psweep[ptyp])
463 short to = nunmap[inunmap[u] + direc[ptyp][*d]];
466 return next_direction(ptyp, d, sq);
472 return next_direction(ptyp, d, sq);
478 first_direction(short ptyp, short *d, short sq)
481 return next_direction(ptyp, d, sq);
487 * This procedure pre-calculates all moves for every piece from every
488 * square. This data is stored in nextpos/nextdir and used later in the
489 * move generation routines.
493 Initialize_moves(void)
495 short ptyp, po, p0, d, di, s, delta;
496 unsigned char *ppos, *pdir;
500 short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
502 /* pre-fill nextpos and nextdir with source position, probably so
503 * (color[u] == neutral) stops to match once all moves have been seen
505 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
507 for (po = 0; po < NO_SQUARES; po++)
509 for (p0 = 0; p0 < NO_SQUARES; p0++)
511 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
512 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
517 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
519 for (po = fpo; po < tpo; po++)
521 if (nunmap[po] >= (small_short)0)
523 ppos = (*nextpos[ptyp])[nunmap[po]];
524 pdir = (*nextdir[ptyp])[nunmap[po]];
526 /* dest is a function of direction and steps */
527 for (d = 0; d < 8; d++)
529 dest[d][0] = nunmap[po];
530 delta = direc[ptyp][d];
536 for (s = 0; s < max_steps[ptyp]; s++)
541 * break if (off board) or (promoted rooks
542 * wishes to move two steps diagonal) or
543 * (promoted bishops wishes to move two steps
546 if ((nunmap[p0] < (small_short)0)
547 || ((ptyp == ptype_prook)
550 || ((ptyp == ptype_pbishop)
552 && !diagonal(delta)))
555 dest[d][s] = nunmap[p0];
564 * Sort dest in number of steps order; currently no sort
565 * is done due to compatibility with the move generation
566 * order in old gnuchess.
571 for (di = d; s > 0 && di > 0; di--)
573 if (steps[sorted[di - 1]] == 0) /* should be: < s */
574 sorted[di] = sorted[di - 1];
583 * update nextpos/nextdir
587 pdir[p0] = (unsigned char)dest[sorted[0]][0];
589 for (d = 0; d < 8; d++)
591 for (s = 0; s < steps[sorted[d]]; s++)
593 ppos[p0] = (unsigned char)dest[sorted[d]][s];
594 p0 = dest[sorted[d]][s];
597 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
600 * else is already initialized
614 * Reset the board and other variables to start a new game.
620 short l, c, p, max_opening_sequence;
621 #ifdef HAVE_GETTIMEOFDAY
624 compptr = oppptr = 0;
626 stage2 = -1; /* the game is not yet started */
627 flag.illegal = flag.mate = flag.post = flag.quit
628 = flag.reverse = flag.bothsides = flag.onemove = flag.force
630 flag.material = flag.coords = flag.hash = flag.easy
631 = flag.beep = flag.rcptr
633 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
638 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
647 MaxSearchDepth = MAXDEPTH - 1;
652 CptrFlag[0] = TesujiFlag[0] = false;
655 GameType[0] = GameType[1] = UNKNOWN;
656 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
657 opponent = player = black;
660 for (l = 0; l < TREE; l++)
661 Tree[l].f = Tree[l].t = 0;
663 gsrand((unsigned int) 1);
667 for (c = black; c <= white; c++)
669 for (p = pawn; p <= king; p++)
671 for (l = 0; l < NO_SQUARES; l++)
673 (*hashcode)[c][p][l].key
674 = (((unsigned long) urand()));
675 (*hashcode)[c][p][l].key
676 += (((unsigned long) urand()) << 16);
677 (*hashcode)[c][p][l].bd
678 = (((unsigned long) urand()));
679 (*hashcode)[c][p][l].bd
680 += (((unsigned long) urand()) << 16);
681 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
682 (*hashcode)[c][p][l].key
683 += (((unsigned long) urand()) << 32);
684 (*hashcode)[c][p][l].key
685 += (((unsigned long) urand()) << 48);
686 (*hashcode)[c][p][l].bd
687 += (((unsigned long) urand()) << 32);
688 (*hashcode)[c][p][l].bd
689 += (((unsigned long) urand()) << 48);
695 for (c = black; c <= white; c++)
697 for (p = pawn; p <= king; p++)
699 for (l = 0; l < MAX_CAPTURED; l++)
701 (*drop_hashcode)[c][p][l].key
702 = (((unsigned long) urand()));
703 (*drop_hashcode)[c][p][l].key
704 += (((unsigned long) urand()) << 16);
705 (*drop_hashcode)[c][p][l].bd
706 = (((unsigned long) urand()));
707 (*drop_hashcode)[c][p][l].bd
708 += (((unsigned long) urand()) << 16);
709 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
710 (*drop_hashcode)[c][p][l].key
711 += (((unsigned long) urand()) << 32);
712 (*drop_hashcode)[c][p][l].key
713 += (((unsigned long) urand()) << 48);
714 (*drop_hashcode)[c][p][l].bd
715 += (((unsigned long) urand()) << 32);
716 (*drop_hashcode)[c][p][l].bd
717 += (((unsigned long) urand()) << 48);
724 for (l = 0; l < NO_SQUARES; l++)
726 board[l] = Stboard[l];
727 color[l] = Stcolor[l];
735 #ifdef HAVE_GETTIMEOFDAY
736 gettimeofday(&tv, NULL);
737 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
739 time0 = time((long *) 0);
742 /* resetting reference time */
743 ElapsedTime(COMPUTE_AND_INIT_MODE);
744 flag.regularstart = true;
754 else if (MaxResponseTime == 0)
757 UpdateDisplay(0, 0, 1, 0);
759 GetOpeningPatterns(&max_opening_sequence);
772 hashbd = hashkey = 0;
779 Initialize_data(void)
791 ShowMessage("datatype 'small_short' is unsigned; "
792 "check gnushogi.h\n");
797 n = sizeof(struct leaf) * (size_t)TREE;
802 sprintf(buffer, "Cannot allocate %ld bytes for search tree",
808 n = sizeof(hashcode_array);
809 hashcode = malloc(n);
813 sprintf(buffer, "Cannot allocate %ld bytes for hashcode", (long)n);
818 n = sizeof(drop_hashcode_array);
819 drop_hashcode = malloc(n);
824 "Cannot allocate %ld bytes for drop_hashcode",
830 n = sizeof(struct GameRec) * (size_t)(MAXMOVES + MAXDEPTH);
831 GameList = malloc(n);
836 "Cannot allocate %ld bytes for game record",
842 #if !defined SAVE_NEXTPOS
843 n = sizeof(next_array);
845 for (i = 0; i < NO_PTYPE_PIECES; i++)
847 nextdir[i] = use_nextpos ? malloc(n) : NULL;
853 sprintf(buffer, "cannot allocate %ld space for nextdir %d",
862 nextpos[i] = use_nextpos ? malloc(n) : NULL;
868 sprintf(buffer, "cannot allocate %ld space for nextpos %d",
883 n = sizeof(value_array);
888 ShowMessage("cannot allocate value space");
892 n = sizeof(fscore_array);
897 ShowMessage("cannot allocate fscore space");
907 sprintf(buffer, "Cannot allocate %ld bytes for history table",
908 (long)sizeof_history);
915 n = sizeof(struct etable) * (size_t)ETABLE;
917 for (i = 0; i < 2; i++)
919 etab[i] = use_etable ? malloc(n) : 0;
923 sprintf(buffer, "Cannot allocate %ld bytes for cache table %ld",
936 n = sizeof(struct hashentry)*(ttblsize + rehash);
938 while (doit && ttblsize > MINTTABLE)
940 ttable[0] = malloc(n); /* FIXME: cast to the correct type. */
941 ttable[1] = ttable[0] ? malloc(n) : NULL;
943 if (!ttable[0] || !ttable[1])
951 ttblsize = ttblsize >> 1;
952 n = sizeof(struct hashentry) * (ttblsize + rehash);
960 if (ttblsize <= MINTTABLE)
967 /* CHECKME: is the precedence here correct? */
968 /* ttbllimit = ttblsize << 1 - ttblsize >> 2; */
969 ttbllimit = (ttblsize << 1) - (ttblsize >> 2);
973 sprintf(buffer, "Cannot allocate %ld bytes for transposition table",
976 ttable[0] = ttable[1] = NULL;
980 #if !defined SAVE_DISTDATA
981 n = sizeof(distdata_array);
982 distdata = malloc(n);
986 ShowMessage("cannot allocate distdata space...");
987 use_distdata = false;
991 #if !defined SAVE_PTYPE_DISTDATA
992 n = sizeof(distdata_array);
994 for (i = 0; i < NO_PTYPE_PIECES; i++)
996 ptype_distdata[i] = use_ptype_distdata ? malloc(n) : 0;
998 if (!ptype_distdata[i])
1001 "cannot allocate %ld bytes for ptype_distdata %d...",
1003 use_ptype_distdata = false;
1015 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
1022 if (Initialize_data() != 0)
1025 strcpy(ColorStr[0], "Black");
1026 strcpy(ColorStr[1], "White");
1029 MaxResponseTime = 0;
1052 #if !defined SAVE_NEXTPOS
1070 hashfile = fopen(HASHFILE, RWA_ACC);
1074 fseek(hashfile, 0L, SEEK_END);
1075 filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
1076 hashmask = filesz >> 1;
1077 hashbase = hashmask + 1;
1079 #endif /* HASHFILE */
1096 #endif /* HASHFILE */