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 1, or (at your option) any
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, write to the Free
27 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
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 .... */
72 #define max(a, b) (((a) < (b))?(b):(a))
73 #define odd(a) ((a) & 1)
76 const small_short piece_of_ptype[NO_PTYPE_PIECES] =
78 pawn, lance, knight, silver, gold, bishop, rook, pbishop, prook, king,
79 pawn, lance, knight, silver, gold
83 const small_short side_of_ptype[NO_PTYPE_PIECES] =
85 black, black, black, black, black, black, black, black, black, black,
86 white, white, white, white, white
90 const small_short psweep[NO_PTYPE_PIECES] =
92 false, true, false, false, false, true, true, true, true, false,
93 false, true, false, false, false
97 const small_short sweep[NO_PIECES] =
99 false, false, true, false, false, false, true, true,
100 false, false, false, false, true, true, false
104 #if !defined EXTLANGFILE
113 #include "gnushogi.lng"
125 * Determine the minimum number of moves for a piece from
126 * square "f" to square "t". If the piece cannot reach "t",
127 * the count is set to CANNOT_REACH.
130 #define csquare(sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
131 #define crow(sq) row(csquare(sq))
132 #define ccol(sq) column(csquare(sq))
135 ptype_distance(short ptyp, short f, short t)
138 short colf, colt, rowf, rowt, dcol, drow;
143 piece = piece_of_ptype[ptyp];
144 side = side_of_ptype[ptyp];
146 dcol = (colt = ccol(t)) - (colf = ccol(f));
147 drow = (rowt = crow(t)) - (rowf = crow(f));
152 if ((dcol != 0) || (drow < 1))
158 if ((dcol != 0) || (drow < 1))
164 if (odd(drow) || (odd(drow / 2) != odd(dcol)))
166 else if ((drow == 0) || ((drow / 2) < abs(dcol)))
174 if (odd(drow) == odd(dcol))
176 return max(abs(drow), abs(dcol));
180 if (abs(dcol) <= drow)
183 return (max(abs(drow), abs(dcol)) + 1);
188 if (odd(drow) == odd(dcol))
189 return (max(abs(drow), abs(dcol)));
191 return (max(abs(drow) + 1, abs(dcol)) + 1);
202 return max(drow, abs(dcol));
204 return (abs(dcol) - drow);
207 if (odd(dcol) != odd(drow))
210 return ((abs(dcol) == abs(drow)) ? 1 : 2);
213 if (odd(dcol) != odd(drow))
215 if ((abs(dcol) <= 1) && (abs(drow) <= 1))
217 else if (abs(abs(dcol) - abs(drow)) == 1)
224 return ((abs(dcol) == abs(drow)) ? 1 : 2);
228 if ((dcol == 0) || (drow == 0))
234 if ((dcol == 0) || (drow == 0))
236 else if ((abs(dcol) == 1) && (abs(drow) == 1))
242 return max(abs(drow), abs(dcol));
245 /* should never occur */
246 return (CANNOT_REACH);
253 distance(short a, short b)
255 return (short)computed_distance(a, b);
259 distance(short a, short b)
262 ? (short)(*distdata)[(int)a][(int)b]
263 : (short)computed_distance(a, b));
268 #ifdef SAVE_PTYPE_DISTDATA
270 piece_distance(short side, short piece, short f, short t)
272 return ((f > NO_SQUARES)
274 : (short)ptype_distance(ptype[side][piece], f, t));
278 piece_distance(short side, short piece, short f, short t)
280 return ((f > NO_SQUARES)
282 : (use_ptype_distdata
283 ? (short)(*ptype_distdata[ptype[side][piece]])[f][t]
284 : (short)ptype_distance(ptype[side][piece], f, t)));
290 Initialize_dist(void)
292 short a, b, d, di, ptyp;
293 #ifndef SAVE_DISTDATA
294 for (a = 0; a < NO_SQUARES; a++)
296 for (b = 0; b < NO_SQUARES; b++)
298 d = abs(column(a) - column(b));
299 di = abs(row(a) - row(b));
300 (*distdata)[a][b] = (small_short)((d > di) ? d : di);
304 #ifndef SAVE_PTYPE_DISTDATA
305 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
307 for (a = 0; a < NO_SQUARES; a++)
308 for (b = 0; b < NO_SQUARES; b++)
309 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
316 * nextpos[piece][from-square], nextdir[piece][from-square] gives vector
317 * of positions reachable from from-square in ppos with piece such that the
320 * ppos = nextpos[piece][from-square];
321 * pdir = nextdir[piece][from-square];
328 * if(color[u] != neutral)
333 * will generate the sequence of all squares reachable from sq.
335 * If the path is blocked u = pdir[sq] will generate the continuation of the
336 * sequence in other directions.
341 * ptype is used to separate black and white pawns, like this; ptyp =
342 * ptype[side][piece] piece can be used directly in nextpos/nextdir when
343 * generating moves for pieces that are not white pawns.
346 const small_short ptype[2][NO_PIECES] =
349 ptype_no_piece, ptype_pawn, ptype_lance, ptype_knight,
350 ptype_silver, ptype_gold, ptype_bishop, ptype_rook,
351 ptype_gold, ptype_gold, ptype_gold, ptype_gold,
352 ptype_pbishop, ptype_prook, ptype_king
355 ptype_no_piece, ptype_wpawn, ptype_wlance, ptype_wknight,
356 ptype_wsilver, ptype_wgold, ptype_bishop, ptype_rook,
357 ptype_wgold, ptype_wgold, ptype_wgold, ptype_wgold,
358 ptype_pbishop, ptype_prook, ptype_king
362 const small_short promoted[NO_PIECES] =
364 no_piece, ppawn, plance, pknight, psilver, gold, pbishop, prook,
365 ppawn, plance, pknight, psilver, pbishop, prook, king
368 const small_short unpromoted[NO_PIECES] =
370 no_piece, pawn, lance, knight, silver, gold, bishop, rook,
371 pawn, lance, knight, silver, bishop, rook, king
374 const small_short is_promoted[NO_PIECES] =
376 false, false, false, false, false, false, false, false,
377 true, true, true, true, true, true, false
380 /* data used to generate nextpos/nextdir */
381 #if !defined SAVE_NEXTPOS
384 const small_short direc[NO_PTYPE_PIECES][8] =
386 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
387 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
388 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
389 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
390 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
391 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
392 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
393 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
394 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
395 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
396 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
397 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
398 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
399 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
400 { -10, -11, -12, 1, -1, 11, 0, 0 }
401 }; /* 14 ptype_wgold */
404 small_short diagonal(short d)
406 return (abs(d) == 10 || abs(d) == 12);
410 static const small_short max_steps[NO_PTYPE_PIECES] =
412 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
416 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
418 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
419 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
420 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
421 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
422 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
423 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
424 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
425 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
426 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
427 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
428 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
429 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
430 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
434 const small_short inunmap[NO_SQUARES] =
436 23, 24, 25, 26, 27, 28, 29, 30, 31,
437 34, 35, 36, 37, 38, 39, 40, 41, 42,
438 45, 46, 47, 48, 49, 50, 51, 52, 53,
439 56, 57, 58, 59, 60, 61, 62, 63, 64,
440 67, 68, 69, 70, 71, 72, 73, 74, 75,
441 78, 79, 80, 81, 82, 83, 84, 85, 86,
442 89, 90, 91, 92, 93, 94, 95, 96, 97,
443 100, 101, 102, 103, 104, 105, 106, 107, 108,
444 111, 112, 113, 114, 115, 116, 117, 118, 119
448 int InitFlag = false;
451 #if defined SAVE_NEXTPOS
454 next_direction(short ptyp, short *d, short sq)
456 short delta, to, sfrom = inunmap[sq];
464 delta = direc[ptyp][*d];
468 to = nunmap[sfrom + delta];
477 next_position(short ptyp, short *d, short sq, short u)
479 if (*d < 4 && psweep[ptyp])
481 short to = nunmap[inunmap[u] + direc[ptyp][*d]];
484 return next_direction(ptyp, d, sq);
490 return next_direction(ptyp, d, sq);
496 first_direction(short ptyp, short *d, short sq)
499 return next_direction(ptyp, d, sq);
505 * This procedure pre-calculates all moves for every piece from every
506 * square. This data is stored in nextpos/nextdir and used later in the
507 * move generation routines.
511 Initialize_moves(void)
513 short ptyp, po, p0, d, di, s, delta;
514 unsigned char *ppos, *pdir;
518 short fpo = 23, tpo = 120;
520 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
522 for (po = 0; po < NO_SQUARES; po++)
524 for (p0 = 0; p0 < NO_SQUARES; p0++)
526 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
527 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
532 for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
534 for (po = fpo; po < tpo; po++)
536 if (nunmap[po] >= (small_short)0)
538 ppos = (*nextpos[ptyp])[nunmap[po]];
539 pdir = (*nextdir[ptyp])[nunmap[po]];
541 /* dest is a function of direction and steps */
542 for (d = 0; d < 8; d++)
544 dest[d][0] = nunmap[po];
545 delta = direc[ptyp][d];
551 for (s = 0; s < max_steps[ptyp]; s++)
556 * break if (off board) or (promoted rooks
557 * wishes to move two steps diagonal) or
558 * (promoted bishops wishes to move two steps
561 if ((nunmap[p0] < (small_short)0)
562 || ((ptyp == ptype_prook)
565 || ((ptyp == ptype_pbishop)
567 && !diagonal(delta)))
570 dest[d][s] = nunmap[p0];
579 * Sort dest in number of steps order; currently no sort
580 * is done due to compatibility with the move generation
581 * order in old gnuchess.
586 for (di = d; s > 0 && di > 0; di--)
588 if (steps[sorted[di - 1]] == 0) /* should be: < s */
589 sorted[di] = sorted[di - 1];
598 * update nextpos/nextdir
602 pdir[p0] = (unsigned char)dest[sorted[0]][0];
604 for (d = 0; d < 8; d++)
606 for (s = 0; s < steps[sorted[d]]; s++)
608 ppos[p0] = (unsigned char)dest[sorted[d]][s];
609 p0 = dest[sorted[d]][s];
612 pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
615 * else is already initialized
629 * Reset the board and other variables to start a new game.
635 short l, c, p, max_opening_sequence;
636 #ifdef HAVE_GETTIMEOFDAY
639 compptr = oppptr = 0;
641 stage2 = -1; /* the game is not yet started */
642 flag.illegal = flag.mate = flag.post = flag.quit
643 = flag.reverse = flag.bothsides = flag.onemove = flag.force
645 flag.material = flag.coords = flag.hash = flag.easy
646 = flag.beep = flag.rcptr
648 flag.stars = flag.shade = flag.back = flag.musttimeout = false;
653 GenCnt = NodeCnt = et0 = dither = XCmore = 0;
662 MaxSearchDepth = MAXDEPTH - 1;
667 CptrFlag[0] = TesujiFlag[0] = false;
670 GameType[0] = GameType[1] = UNKNOWN;
671 Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
672 opponent = player = black;
675 for (l = 0; l < TREE; l++)
676 Tree[l].f = Tree[l].t = 0;
678 gsrand((unsigned int) 1);
682 for (c = black; c <= white; c++)
684 for (p = pawn; p <= king; p++)
686 for (l = 0; l < NO_SQUARES; l++)
688 (*hashcode)[c][p][l].key
689 = (((unsigned long) urand()));
690 (*hashcode)[c][p][l].key
691 += (((unsigned long) urand()) << 16);
692 (*hashcode)[c][p][l].bd
693 = (((unsigned long) urand()));
694 (*hashcode)[c][p][l].bd
695 += (((unsigned long) urand()) << 16);
696 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
697 (*hashcode)[c][p][l].key
698 += (((unsigned long) urand()) << 32);
699 (*hashcode)[c][p][l].key
700 += (((unsigned long) urand()) << 48);
701 (*hashcode)[c][p][l].bd
702 += (((unsigned long) urand()) << 32);
703 (*hashcode)[c][p][l].bd
704 += (((unsigned long) urand()) << 48);
710 for (c = black; c <= white; c++)
712 for (p = pawn; p <= king; p++)
714 for (l = 0; l < MAX_CAPTURED; l++)
716 (*drop_hashcode)[c][p][l].key
717 = (((unsigned long) urand()));
718 (*drop_hashcode)[c][p][l].key
719 += (((unsigned long) urand()) << 16);
720 (*drop_hashcode)[c][p][l].bd
721 = (((unsigned long) urand()));
722 (*drop_hashcode)[c][p][l].bd
723 += (((unsigned long) urand()) << 16);
724 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
725 (*drop_hashcode)[c][p][l].key
726 += (((unsigned long) urand()) << 32);
727 (*drop_hashcode)[c][p][l].key
728 += (((unsigned long) urand()) << 48);
729 (*drop_hashcode)[c][p][l].bd
730 += (((unsigned long) urand()) << 32);
731 (*drop_hashcode)[c][p][l].bd
732 += (((unsigned long) urand()) << 48);
739 for (l = 0; l < NO_SQUARES; l++)
741 board[l] = Stboard[l];
742 color[l] = Stcolor[l];
750 #ifdef HAVE_GETTIMEOFDAY
751 gettimeofday(&tv, NULL);
752 time0 = tv.tv_sec*100 + tv.tv_usec/10000;
754 time0 = time((long *) 0);
757 /* resetting reference time */
758 ElapsedTime(COMPUTE_AND_INIT_MODE);
759 flag.regularstart = true;
769 else if (MaxResponseTime == 0)
772 UpdateDisplay(0, 0, 1, 0);
774 GetOpeningPatterns(&max_opening_sequence);
787 hashbd = hashkey = 0;
794 Initialize_data(void)
806 ShowMessage("datatype 'small_short' is unsigned; "
807 "check gnushogi.h\n");
812 n = sizeof(struct leaf) * (size_t)TREE;
817 sprintf(buffer, "Cannot allocate %ld bytes for search tree",
823 n = sizeof(hashcode_array);
824 hashcode = malloc(n);
828 sprintf(buffer, "Cannot allocate %ld bytes for hashcode", (long)n);
833 n = sizeof(drop_hashcode_array);
834 drop_hashcode = malloc(n);
839 "Cannot allocate %ld bytes for drop_hashcode",
845 n = sizeof(struct GameRec) * (size_t)(MAXMOVES + MAXDEPTH);
846 GameList = malloc(n);
851 "Cannot allocate %ld bytes for game record",
857 #if !defined SAVE_NEXTPOS
858 n = sizeof(next_array);
860 for (i = 0; i < NO_PTYPE_PIECES; i++)
862 nextdir[i] = use_nextpos ? malloc(n) : NULL;
868 sprintf(buffer, "cannot allocate %ld space for nextdir %d",
877 nextpos[i] = use_nextpos ? malloc(n) : NULL;
883 sprintf(buffer, "cannot allocate %ld space for nextpos %d",
898 n = sizeof(value_array);
903 ShowMessage("cannot allocate value space");
907 n = sizeof(fscore_array);
912 ShowMessage("cannot allocate fscore space");
922 sprintf(buffer, "Cannot allocate %ld bytes for history table",
923 (long)sizeof_history);
930 n = sizeof(struct etable) * (size_t)ETABLE;
932 for (i = 0; i < 2; i++)
934 etab[i] = use_etable ? malloc(n) : 0;
938 sprintf(buffer, "Cannot allocate %ld bytes for cache table %ld",
951 n = sizeof(struct hashentry)*(ttblsize + rehash);
953 while (doit && ttblsize > MINTTABLE)
955 ttable[0] = malloc(n); /* FIXME: cast to the correct type. */
956 ttable[1] = ttable[0] ? malloc(n) : NULL;
958 if (!ttable[0] || !ttable[1])
966 ttblsize = ttblsize >> 1;
967 n = sizeof(struct hashentry) * (ttblsize + rehash);
975 if (ttblsize <= MINTTABLE)
982 /* CHECKME: is the precedence here correct? */
983 /* ttbllimit = ttblsize << 1 - ttblsize >> 2; */
984 ttbllimit = (ttblsize << 1) - (ttblsize >> 2);
988 sprintf(buffer, "Cannot allocate %ld bytes for transposition table",
991 ttable[0] = ttable[1] = NULL;
995 #if !defined SAVE_DISTDATA
996 n = sizeof(distdata_array);
997 distdata = malloc(n);
1001 ShowMessage("cannot allocate distdata space...");
1002 use_distdata = false;
1006 #if !defined SAVE_PTYPE_DISTDATA
1007 n = sizeof(distdata_array);
1009 for (i = 0; i < NO_PTYPE_PIECES; i++)
1011 ptype_distdata[i] = use_ptype_distdata ? malloc(n) : 0;
1013 if (!ptype_distdata[i])
1016 "cannot allocate %ld bytes for ptype_distdata %d...",
1018 use_ptype_distdata = false;
1027 #if defined EXTLANGFILE
1032 InitConst(char *lang)
1040 constfile = fopen(LANGFILE, "r");
1044 ShowMessage("NO LANGFILE");
1048 while (fgets(s, sizeof(s), constfile))
1055 for (q = &s[len]; q > &s[8]; q--)
1061 ShowMessage("{ error in cinstfile");
1067 if ((s[3] != ':') || (s[7] != ':') || (s[8] != '{'))
1069 sprintf(buffer, "Langfile format error %s", s);
1070 ShowMessage(buffer);
1082 if (strcmp(&s[4], lang))
1087 if ((entry < 0) || (entry >= CPSIZE))
1089 ShowMessage("Langfile number error");
1093 for (q = p = &s[9]; *p; p++)
1099 else if (*(p + 1) == 'n')
1108 if ((entry < 0) || (entry > 255))
1110 sprintf(buffer, "Langfile error %d\n", entry);
1111 ShowMessage(buffer);
1115 CP[entry] = (char *)GLOBAL_ALLOC((unsigned) strlen(&s[9]) + 1);
1117 if (CP[entry] == NULL)
1120 sprintf(buffer, "CP MALLOC, entry %d", entry);
1125 strcpy(CP[entry], &s[9]);
1134 InitConst(char *lang)
1142 constfile = fopen(LANGFILE, "r");
1146 ShowMessage("NO LANGFILE");
1150 while (fgets(s, sizeof(s), constfile))
1157 if ((len > 3) && (s[3] == ':') || (len > 7) && (s[7] == ':'))
1159 ShowMessage("old Langfile error");
1165 ShowMessage("length error in Langfile");
1169 for (q = &s[len]; q > &s[15]; q--)
1177 ShowMessage("\" error in Langfile");
1183 if ((s[6] != ':') || (s[10] != ':') || (s[15] != '"'))
1185 sprintf(buffer, "Langfile format error %s", s);
1186 ShowMessage(buffer);
1190 s[6] = s[10] = '\0';
1198 if (strcmp(&s[7], lang))
1201 entry = atoi(&s[3]);
1203 if ((entry < 0) || (entry >= CPSIZE))
1205 ShowMessage("Langfile number error");
1209 for (q = p = &s[16]; *p; p++)
1215 else if (*(p + 1) == 'n')
1224 if ((entry < 0) || (entry > 255))
1226 sprintf(buffer, "Langfile error %d\n", entry);
1227 ShowMessage(buffer);
1231 CP[entry] = (char *)GLOBAL_ALLOC((unsigned)strlen(&s[16]) + 1);
1233 if (CP[entry] == NULL)
1236 sprintf(buffer, "CP MALLOC, entry %d", entry);
1241 strcpy(CP[entry], &s[16]);
1255 gsrand(starttime = ((unsigned int)time((long *)0))); /* init urand */
1262 if (Initialize_data() != 0)
1265 #if defined EXTLANGFILE
1269 strcpy(ColorStr[0], CP[118]);
1270 strcpy(ColorStr[1], CP[119]);
1273 MaxResponseTime = 0;
1277 signal(SIGINT, TerminateSearch);
1298 #if !defined SAVE_NEXTPOS
1316 hashfile = fopen(HASHFILE, RWA_ACC);
1320 fseek(hashfile, 0L, SEEK_END);
1321 filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
1322 hashmask = filesz >> 1;
1323 hashbase = hashmask + 1;
1325 #endif /* HASHFILE */
1342 #endif /* HASHFILE */