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] =
84 silver, gold, bishop, rook, pbishop, prook, king,
93 /* FIXME: all bishops and rooks are black ? */
94 const small_short side_of_ptype[NO_PTYPE_PIECES] =
100 black, black, black, black, black, black, black,
109 const small_short psweep[NO_PTYPE_PIECES] =
111 false, true, false, false, false, true, true, true, true, false,
112 false, true, false, false, false
116 const small_short sweep[NO_PIECES] =
122 false, false, true, true,
127 false, true, true, false
132 * Determine the minimum number of moves for a piece from
133 * square "f" to square "t". If the piece cannot reach "t",
134 * the count is set to CANNOT_REACH.
137 #define csquare(sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
138 #define crow(sq) row(csquare(sq))
139 #define ccol(sq) column(csquare(sq))
142 ptype_distance(short ptyp, short f, short t)
145 short colf, colt, rowf, rowt, dcol, drow;
150 piece = piece_of_ptype[ptyp];
151 side = side_of_ptype[ptyp];
153 dcol = (colt = ccol(t)) - (colf = ccol(f));
154 drow = (rowt = crow(t)) - (rowf = crow(f));
159 if ((dcol != 0) || (drow < 1))
166 if ((dcol != 0) || (drow < 1))
172 if (odd(drow) || (odd(drow / 2) != odd(dcol)))
174 else if ((drow == 0) || ((drow / 2) < abs(dcol)))
183 if (odd(drow) == odd(dcol))
185 return max(abs(drow), abs(dcol));
189 if (abs(dcol) <= drow)
192 return (max(abs(drow), abs(dcol)) + 1);
197 if (odd(drow) == odd(dcol))
198 return (max(abs(drow), abs(dcol)));
200 return (max(abs(drow) + 1, abs(dcol)) + 1);
213 return max(drow, abs(dcol));
215 return (abs(dcol) - drow);
218 if (odd(dcol) != odd(drow))
221 return ((abs(dcol) == abs(drow)) ? 1 : 2);
224 if (odd(dcol) != odd(drow))
226 if ((abs(dcol) <= 1) && (abs(drow) <= 1))
228 else if (abs(abs(dcol) - abs(drow)) == 1)
235 return ((abs(dcol) == abs(drow)) ? 1 : 2);
239 if ((dcol == 0) || (drow == 0))
245 if ((dcol == 0) || (drow == 0))
247 else if ((abs(dcol) == 1) && (abs(drow) == 1))
253 return max(abs(drow), abs(dcol));
256 /* should never occur */
257 return (CANNOT_REACH);
264 distance(short a, short b)
266 return (short)computed_distance(a, b);
270 distance(short a, short b)
273 ? (short)(*distdata)[(int)a][(int)b]
274 : (short)computed_distance(a, b));
279 #ifdef SAVE_PTYPE_DISTDATA
281 piece_distance(short side, short piece, short f, short t)
283 return ((f > NO_SQUARES)
285 : (short)ptype_distance(ptype[side][piece], f, t));
289 piece_distance(short side, short piece, short f, short t)
291 return ((f > NO_SQUARES)
293 : (use_ptype_distdata
294 ? (short)(*ptype_distdata[ptype[side][piece]])[f][t]
295 : (short)ptype_distance(ptype[side][piece], f, t)));
301 Initialize_dist(void)
303 short a, b, d, di, ptyp;
304 #ifndef SAVE_DISTDATA
305 for (a = 0; a < NO_SQUARES; a++)
307 for (b = 0; b < NO_SQUARES; b++)
309 d = abs(column(a) - column(b));
310 di = abs(row(a) - row(b));
311 (*distdata)[a][b] = (small_short)((d > di) ? d : di);
315 #ifndef SAVE_PTYPE_DISTDATA
316 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
318 for (a = 0; a < NO_SQUARES; a++)
319 for (b = 0; b < NO_SQUARES; b++)
320 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
327 * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
328 * of positions reachable from from-square in ppos with ptype such that the
331 * ppos = nextpos[ptype][from-square];
332 * pdir = nextdir[ptype][from-square];
339 * if(color[u] != neutral)
344 * will generate the sequence of all squares reachable from sq.
346 * If the path is blocked u = pdir[sq] will generate the continuation of the
347 * sequence in other directions.
352 * ptype is used to separate black and white pawns, like this; ptyp =
353 * ptype[side][piece] piece can be used directly in nextpos/nextdir when
354 * generating moves for pieces that are not white pawns.
357 const small_short ptype[2][NO_PIECES] =
360 ptype_no_piece, ptype_pawn,
362 ptype_lance, ptype_knight,
364 ptype_silver, ptype_gold, ptype_bishop, ptype_rook,
367 ptype_gold, ptype_gold,
370 ptype_pbishop, ptype_prook, ptype_king
373 ptype_no_piece, ptype_wpawn,
375 ptype_wlance, ptype_wknight,
377 ptype_wsilver, ptype_wgold, ptype_bishop, ptype_rook,
380 ptype_wgold, ptype_wgold,
383 ptype_pbishop, ptype_prook, ptype_king
387 const small_short promoted[NO_PIECES] =
393 psilver, gold, pbishop, prook,
398 psilver, pbishop, prook, king
401 const small_short unpromoted[NO_PIECES] =
407 silver, gold, bishop, rook,
412 silver, bishop, rook, king
415 const small_short is_promoted[NO_PIECES] =
421 false, false, false, false,
426 true, true, true, false
429 /* data used to generate nextpos/nextdir */
431 /* FIXME: use predefined constants ! */
432 #if !defined SAVE_NEXTPOS
435 const small_short direc[NO_PTYPE_PIECES][8] =
437 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
438 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
439 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
440 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
441 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
442 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
443 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
444 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
445 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
446 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
447 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
448 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
449 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
450 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
451 { -10, -11, -12, 1, -1, 11, 0, 0 } /* 14 ptype_wgold */
454 #if !defined SAVE_NEXTPOS
457 const small_short direc[NO_PTYPE_PIECES][8] =
459 { 7, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
460 { 6, 7, 8, -8, -6, 0, 0, 0 }, /* 3 ptype_silver */
461 { 6, 7, 8, -1, 1, -7, 0, 0 }, /* 4 ptype_gold */
462 { 6, 8, -8, -6, 0, 0, 0, 0 }, /* 5 ptype_bishop */
463 { 7, -1, 1, -7, 0, 0, 0, 0 }, /* 6 ptype_rook */
464 { 6, 8, -8, -6, 7, -1, 1, -7 }, /* 7 ptype_pbishop */
465 { 7, -1, 1, -7, 6, 8, -8, -6 }, /* 8 ptype_prook */
466 { 6, 7, 8, -1, 1, -8, -7, -6 }, /* 9 ptype_king */
467 { -7, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
468 { -6, -7, -8, 8, 6, 0, 0, 0 }, /* 13 ptype_wsilver */
469 { -6, -7, -8, 1, -1, 7, 0, 0 } /* 14 ptype_wgold */
474 small_short diagonal(short d)
476 return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
482 static const small_short max_steps[NO_PTYPE_PIECES] =
484 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
487 static const small_short max_steps[NO_PTYPE_PIECES] =
489 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
494 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
496 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
497 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
498 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
499 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
500 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
501 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
502 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
503 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
504 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
505 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
506 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
507 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
508 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
512 const small_short inunmap[NO_SQUARES] =
514 23, 24, 25, 26, 27, 28, 29, 30, 31,
515 34, 35, 36, 37, 38, 39, 40, 41, 42,
516 45, 46, 47, 48, 49, 50, 51, 52, 53,
517 56, 57, 58, 59, 60, 61, 62, 63, 64,
518 67, 68, 69, 70, 71, 72, 73, 74, 75,
519 78, 79, 80, 81, 82, 83, 84, 85, 86,
520 89, 90, 91, 92, 93, 94, 95, 96, 97,
521 100, 101, 102, 103, 104, 105, 106, 107, 108,
522 111, 112, 113, 114, 115, 116, 117, 118, 119
525 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 2)] =
527 -1, -1, -1, -1, -1, -1, -1,
528 -1, 0, 1, 2, 3, 4, -1,
529 -1, 5, 6, 7, 8, 9, -1,
530 -1, 10, 11, 12, 13, 14, -1,
531 -1, 15, 16, 17, 18, 19, -1,
532 -1, 20, 21, 22, 23, 24, -1,
533 -1, -1, -1, -1, -1, -1, -1,
537 const small_short inunmap[NO_SQUARES] =
547 int InitFlag = false;
550 #if defined SAVE_NEXTPOS
553 next_direction(short ptyp, short *d, short sq)
555 short delta, to, sfrom = inunmap[sq];
563 delta = direc[ptyp][*d];
567 to = nunmap[sfrom + delta];
576 next_position(short ptyp, short *d, short sq, short u)
578 if (*d < 4 && psweep[ptyp])
580 short to = nunmap[inunmap[u] + direc[ptyp][*d]];
583 return next_direction(ptyp, d, sq);
589 return next_direction(ptyp, d, sq);
595 first_direction(short ptyp, short *d, short sq)
598 return next_direction(ptyp, d, sq);
604 * This procedure pre-calculates all moves for every piece from every
605 * square. This data is stored in nextpos/nextdir and used later in the
606 * move generation routines.
610 Initialize_moves(void)
612 short ptyp, po, p0, d, di, s, delta;
613 unsigned char *ppos, *pdir;
617 short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
619 /* pre-fill nextpos and nextdir with source position, probably so
620 * (color[u] == neutral) stops to match once all moves have been seen
622 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
624 for (po = 0; po < NO_SQUARES; po++)
626 for (p0 = 0; p0 < NO_SQUARES; p0++)
628 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
629 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
634 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
636 for (po = fpo; po < tpo; po++)
638 if (nunmap[po] >= (small_short)0)
640 ppos = (*nextpos[ptyp])[nunmap[po]];
641 pdir = (*nextdir[ptyp])[nunmap[po]];
643 /* dest is a function of direction and steps */
644 for (d = 0; d < 8; d++)
646 dest[d][0] = nunmap[po];
647 delta = direc[ptyp][d];
653 for (s = 0; s < max_steps[ptyp]; s++)
658 * break if (off board) or (promoted rooks
659 * wishes to move two steps diagonal) or
660 * (promoted bishops wishes to move two steps
663 if ((nunmap[p0] < (small_short)0)
664 || ((ptyp == ptype_prook)
667 || ((ptyp == ptype_pbishop)
669 && !diagonal(delta)))
672 dest[d][s] = nunmap[p0];
681 * Sort dest in number of steps order; currently no sort
682 * is done due to compatibility with the move generation
683 * order in old gnuchess.
688 for (di = d; s > 0 && di > 0; di--)
690 if (steps[sorted[di - 1]] == 0) /* should be: < s */
691 sorted[di] = sorted[di - 1];
700 * update nextpos/nextdir
704 pdir[p0] = (unsigned char)dest[sorted[0]][0];
706 for (d = 0; d < 8; d++)
708 for (s = 0; s < steps[sorted[d]]; s++)
710 ppos[p0] = (unsigned char)dest[sorted[d]][s];
711 p0 = dest[sorted[d]][s];
714 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
717 * else is already initialized
731 * Reset the board and other variables to start a new game.
737 short l, c, p, max_opening_sequence;
738 #ifdef HAVE_GETTIMEOFDAY
741 compptr = oppptr = 0;
743 stage2 = -1; /* the game is not yet started */
744 flag.illegal = flag.mate = flag.post = flag.quit
745 = flag.reverse = flag.bothsides = flag.onemove = flag.force
747 flag.material = flag.coords = flag.hash = flag.easy
748 = flag.beep = flag.rcptr
750 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
755 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
764 MaxSearchDepth = MAXDEPTH - 1;
769 CptrFlag[0] = TesujiFlag[0] = false;
772 GameType[0] = GameType[1] = UNKNOWN;
773 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
774 opponent = player = black;
777 for (l = 0; l < TREE; l++)
778 Tree[l].f = Tree[l].t = 0;
780 gsrand((unsigned int) 1);
784 for (c = black; c <= white; c++)
786 for (p = pawn; p <= king; p++)
788 for (l = 0; l < NO_SQUARES; l++)
790 (*hashcode)[c][p][l].key
791 = (((unsigned long) urand()));
792 (*hashcode)[c][p][l].key
793 += (((unsigned long) urand()) << 16);
794 (*hashcode)[c][p][l].bd
795 = (((unsigned long) urand()));
796 (*hashcode)[c][p][l].bd
797 += (((unsigned long) urand()) << 16);
798 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
799 (*hashcode)[c][p][l].key
800 += (((unsigned long) urand()) << 32);
801 (*hashcode)[c][p][l].key
802 += (((unsigned long) urand()) << 48);
803 (*hashcode)[c][p][l].bd
804 += (((unsigned long) urand()) << 32);
805 (*hashcode)[c][p][l].bd
806 += (((unsigned long) urand()) << 48);
812 for (c = black; c <= white; c++)
814 for (p = pawn; p <= king; p++)
816 for (l = 0; l < MAX_CAPTURED; l++)
818 (*drop_hashcode)[c][p][l].key
819 = (((unsigned long) urand()));
820 (*drop_hashcode)[c][p][l].key
821 += (((unsigned long) urand()) << 16);
822 (*drop_hashcode)[c][p][l].bd
823 = (((unsigned long) urand()));
824 (*drop_hashcode)[c][p][l].bd
825 += (((unsigned long) urand()) << 16);
826 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
827 (*drop_hashcode)[c][p][l].key
828 += (((unsigned long) urand()) << 32);
829 (*drop_hashcode)[c][p][l].key
830 += (((unsigned long) urand()) << 48);
831 (*drop_hashcode)[c][p][l].bd
832 += (((unsigned long) urand()) << 32);
833 (*drop_hashcode)[c][p][l].bd
834 += (((unsigned long) urand()) << 48);
841 for (l = 0; l < NO_SQUARES; l++)
843 board[l] = Stboard[l];
844 color[l] = Stcolor[l];
852 #ifdef HAVE_GETTIMEOFDAY
853 gettimeofday(&tv, NULL);
854 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
856 time0 = time((long *) 0);
859 /* resetting reference time */
860 ElapsedTime(COMPUTE_AND_INIT_MODE);
861 flag.regularstart = true;
871 else if (MaxResponseTime == 0)
874 UpdateDisplay(0, 0, 1, 0);
876 GetOpeningPatterns(&max_opening_sequence);
889 hashbd = hashkey = 0;
896 Initialize_data(void)
908 ShowMessage("datatype 'small_short' is unsigned; "
909 "check gnushogi.h\n");
914 n = sizeof(struct leaf) * (size_t)TREE;
919 sprintf(buffer, "Cannot allocate %ld bytes for search tree",
925 n = sizeof(hashcode_array);
926 hashcode = malloc(n);
930 sprintf(buffer, "Cannot allocate %ld bytes for hashcode", (long)n);
935 n = sizeof(drop_hashcode_array);
936 drop_hashcode = malloc(n);
941 "Cannot allocate %ld bytes for drop_hashcode",
947 n = sizeof(struct GameRec) * (size_t)(MAXMOVES + MAXDEPTH);
948 GameList = malloc(n);
953 "Cannot allocate %ld bytes for game record",
959 #if !defined SAVE_NEXTPOS
960 n = sizeof(next_array);
962 for (i = 0; i < NO_PTYPE_PIECES; i++)
964 nextdir[i] = use_nextpos ? malloc(n) : NULL;
970 sprintf(buffer, "cannot allocate %ld space for nextdir %d",
979 nextpos[i] = use_nextpos ? malloc(n) : NULL;
985 sprintf(buffer, "cannot allocate %ld space for nextpos %d",
1000 n = sizeof(value_array);
1005 ShowMessage("cannot allocate value space");
1009 n = sizeof(fscore_array);
1014 ShowMessage("cannot allocate fscore space");
1020 history = malloc(n);
1024 sprintf(buffer, "Cannot allocate %ld bytes for history table",
1025 (long)sizeof_history);
1026 ShowMessage(buffer);
1027 use_history = false;
1032 n = sizeof(struct etable) * (size_t)ETABLE;
1034 for (i = 0; i < 2; i++)
1036 etab[i] = use_etable ? malloc(n) : 0;
1040 sprintf(buffer, "Cannot allocate %ld bytes for cache table %ld",
1042 ShowMessage(buffer);
1053 n = sizeof(struct hashentry)*(ttblsize + rehash);
1055 while (doit && ttblsize > MINTTABLE)
1057 ttable[0] = malloc(n); /* FIXME: cast to the correct type. */
1058 ttable[1] = ttable[0] ? malloc(n) : NULL;
1060 if (!ttable[0] || !ttable[1])
1068 ttblsize = ttblsize >> 1;
1069 n = sizeof(struct hashentry) * (ttblsize + rehash);
1077 if (ttblsize <= MINTTABLE)
1084 /* CHECKME: is the precedence here correct? */
1085 /* ttbllimit = ttblsize << 1 - ttblsize >> 2; */
1086 ttbllimit = (ttblsize << 1) - (ttblsize >> 2);
1090 sprintf(buffer, "Cannot allocate %ld bytes for transposition table",
1092 ShowMessage(buffer);
1093 ttable[0] = ttable[1] = NULL;
1097 #if !defined SAVE_DISTDATA
1098 n = sizeof(distdata_array);
1099 distdata = malloc(n);
1103 ShowMessage("cannot allocate distdata space...");
1104 use_distdata = false;
1108 #if !defined SAVE_PTYPE_DISTDATA
1109 n = sizeof(distdata_array);
1111 for (i = 0; i < NO_PTYPE_PIECES; i++)
1113 ptype_distdata[i] = use_ptype_distdata ? malloc(n) : 0;
1115 if (!ptype_distdata[i])
1118 "cannot allocate %ld bytes for ptype_distdata %d...",
1120 use_ptype_distdata = false;
1132 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
1139 if (Initialize_data() != 0)
1142 strcpy(ColorStr[0], "Black");
1143 strcpy(ColorStr[1], "White");
1146 MaxResponseTime = 0;
1169 #if !defined SAVE_NEXTPOS
1187 hashfile = fopen(HASHFILE, RWA_ACC);
1191 fseek(hashfile, 0L, SEEK_END);
1192 filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
1193 hashmask = filesz >> 1;
1194 hashbase = hashmask + 1;
1196 #endif /* HASHFILE */
1213 #endif /* HASHFILE */