Merge branch 'maint'
[gnushogi.git] / gnushogi / util.c
blob3968ecf323e0c8c967e0b17ec0a37705055c9111
1 /*
2 * FILE: util.c
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
23 * for more details.
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 * ----------------------------------------------------------------------
32 #include "gnushogi.h"
34 unsigned int TTadd = 0;
35 short recycle;
36 short ISZERO = 1;
38 #if 0
39 int
40 parse(FILE * fd, unsigned short *mv, char *opening)
42 int c, i, r1, r2, c1, c2;
43 char s[128];
44 char *p;
46 while (((c = getc(fd)) == ' ') || (c == '\n'));
48 i = 0;
49 s[0] = (char) c;
51 if (c == '!')
53 p = opening;
56 *p++ = c;
57 c = getc(fd);
59 if ((c == '\n') || (c == EOF))
61 *p = '\0';
62 return 0;
65 while (true);
68 while ((c != '?') && (c != ' ')
69 && (c != '\t') && (c != '\n') && (c != EOF))
71 s[++i] = (char) (c = getc(fd));
74 s[++i] = '\0';
76 if (c == EOF)
77 return (-1);
79 if ((s[0] == '!') || (s[0] == ';') || (i < 3))
81 while ((c != '\n') && (c != EOF))
82 c = getc(fd);
84 return 0;
87 c1 = COL_NAME(s[0]);
88 r1 = ROW_NAME(s[1]);
89 c2 = COL_NAME(s[2]);
90 r2 = ROW_NAME(s[3]);
91 *mv = (locn(r1, c1) << 8) | locn(r2, c2);
93 if (c == '?')
95 /* Bad move, not for the program to play */
96 *mv |= 0x8000; /* Flag it ! */
97 c = getc(fd);
100 return 1;
102 #endif
105 * The field of a hashtable is computed as follows:
106 * if sq is on board (< NO_SQUARES) the field gets the value
107 * of the piece on the square sq;
108 * if sq is off board (>= NO_SQUARES) it is a catched figure,
109 * and the field gets the number of catched pieces for
110 * each side.
113 inline unsigned char
114 CB(short sq)
116 short i = sq;
118 if (i < NO_SQUARES)
120 return ((color[i] == white) ? (0x80 | board[i]) : board[i]);
122 else
124 i -= NO_SQUARES;
125 return ((Captured[black][i] << 4) | Captured[white][i]);
132 #if ttblsz
135 * Look for the current board position in the transposition table.
139 ProbeTTable (short side,
140 short depth,
141 short ply,
142 short *alpha,
143 short *beta,
144 short *score)
146 struct hashentry *ptbl;
147 /*unsigned*/ short i = 0; /* to match new type of rehash --tpm */
149 ptbl = &ttable[side][hashkey % ttblsize];
151 while (true)
153 if ((ptbl->depth) == 0)
154 return false;
156 if (ptbl->hashbd == hashbd)
157 break;
159 if (++i > rehash)
160 return false;
162 ptbl++;
165 /* rehash max rehash times */
167 if (((short)(ptbl->depth) >= (short) depth))
169 #ifdef HASHTEST
170 for (i = 0; i < PTBLBDSIZE; i++)
172 if (ptbl->bd[i] != CB(i))
174 HashCol++;
176 if (!barebones)
178 ShowMessage("ttable collision detected");
179 ShowBD(ptbl->bd);
180 printf("hashkey = 0x%x, hashbd = 0x%x\n",
181 hashkey, hashbd);
184 break;
187 #endif /* HASHTEST */
190 PV = SwagHt = ptbl->mv;
192 HashCnt++;
194 if (ptbl->flags & truescore)
196 *score = ptbl->score;
197 /* adjust *score so moves to mate is from root */
199 if (*score > SCORE_LIMIT)
200 *score -= ply;
201 else if (*score < -SCORE_LIMIT)
202 *score += ply;
204 *beta = -2 * (SCORE_LIMIT + 1000);
206 else if (ptbl->flags & lowerbound)
208 if (ptbl->score > *alpha)
209 *alpha = ptbl->score - 1;
212 return true;
215 return false;
221 * Store the current board position in the transposition table.
225 PutInTTable(short side,
226 short score,
227 short depth,
228 short ply,
229 short beta,
230 unsigned short mv)
232 struct hashentry *ptbl;
233 /*unsigned*/ short i = 0; /* to match new type of rehash --tpm */
235 ptbl = &ttable[side][hashkey % ttblsize];
237 while (true)
239 if ((ptbl->depth) == 0 || ptbl->hashbd == hashbd)
240 break;
242 if (++i > rehash)
244 THashCol++;
245 ptbl += recycle;
247 break;
250 ptbl++;
253 TTadd++;
254 HashAdd++;
256 /* adjust score so moves to mate is from this ply */
258 if (score > SCORE_LIMIT)
259 score += ply;
260 else if (score < -SCORE_LIMIT)
261 score -= ply;
263 ptbl->hashbd = hashbd;
264 ptbl->depth = (unsigned char) depth;
265 ptbl->score = score;
266 ptbl->mv = mv;
268 if (score > beta)
270 ptbl->flags = lowerbound;
271 ptbl->score = beta + 1;
273 else
275 ptbl->flags = truescore;
278 #if defined HASHTEST
279 for (i = 0; i < PTBLBDSIZE; i++)
280 ptbl->bd[i] = CB(i);
281 #endif /* HASHTEST */
283 return true;
288 void
289 ZeroTTable(void)
291 array_zero(ttable[black], (ttblsize + rehash));
292 array_zero(ttable[white], (ttblsize + rehash));
294 #ifdef CACHE
295 array_zero(etab[0], sizeof(struct etable)*(size_t)ETABLE);
296 array_zero(etab[1], sizeof(struct etable)*(size_t)ETABLE);
297 #endif
299 TTadd = 0;
305 #ifdef HASHFILE
307 Fbdcmp(unsigned char *a, unsigned char *b)
309 int i;
311 for (i = 0; i < PTBLBDSIZE; i++)
313 if (a[i] != b[i])
314 return false;
317 return true;
323 * Look for the current board position in the persistent transposition table.
327 ProbeFTable(short side,
328 short depth,
329 short ply,
330 short *alpha,
331 short *beta,
332 short *score)
334 short i;
335 unsigned long hashix;
336 struct fileentry new, t;
338 hashix = ((side == black) ? (hashkey & 0xFFFFFFFE)
339 : (hashkey | 1)) % filesz;
341 for (i = 0; i < PTBLBDSIZE; i++)
342 new.bd[i] = CB(i);
344 new.flags = 0;
346 for (i = 0; i < frehash; i++)
348 fseek(hashfile,
349 sizeof(struct fileentry) * ((hashix + 2 * i) % (filesz)),
350 SEEK_SET);
351 fread(&t, sizeof(struct fileentry), 1, hashfile);
353 if (!t.depth)
354 break;
356 if (!Fbdcmp(t.bd, new.bd))
357 continue;
359 if (((short) t.depth >= depth)
360 && (new.flags == (unsigned short)(t.flags
361 & (kingcastle | queencastle))))
363 FHashCnt++;
365 PV = (t.f << 8) | t.t;
366 *score = (t.sh << 8) | t.sl;
368 /* adjust *score so moves to mate is from root */
369 if (*score > SCORE_LIMIT)
370 *score -= ply;
371 else if (*score < -SCORE_LIMIT)
372 *score += ply;
374 if (t.flags & truescore)
376 *beta = -((SCORE_LIMIT + 1000)*2);
378 else if (t.flags & lowerbound)
380 if (*score > *alpha)
381 *alpha = *score - 1;
383 else if (t.flags & upperbound)
385 if (*score < *beta)
386 *beta = *score + 1;
389 return (true);
393 return (false);
399 * Store the current board position in the persistent transposition table.
402 void
403 PutInFTable(short side,
404 short score,
405 short depth,
406 short ply,
407 short alpha,
408 short beta,
409 unsigned short f,
410 unsigned short t)
412 unsigned short i;
413 unsigned long hashix;
414 struct fileentry new, tmp;
416 hashix = ((side == black) ? (hashkey & 0xFFFFFFFE)
417 : (hashkey | 1)) % filesz;
419 for (i = 0; i < PTBLBDSIZE; i++)
420 new.bd[i] = CB(i);
422 new.f = (unsigned char) f;
423 new.t = (unsigned char) t;
425 if (score < alpha)
426 new.flags = upperbound;
427 else
428 new.flags = ((score > beta) ? lowerbound : truescore);
430 new.depth = (unsigned char) depth;
432 /* adjust *score so moves to mate is from root */
433 if (score > SCORE_LIMIT)
434 score += ply;
435 else if (score < -SCORE_LIMIT)
436 score -= ply;
439 new.sh = (unsigned char) (score >> 8);
440 new.sl = (unsigned char) (score & 0xFF);
442 for (i = 0; i < frehash; i++)
444 fseek(hashfile,
445 sizeof(struct fileentry) * ((hashix + 2 * i) % (filesz)),
446 SEEK_SET);
448 if (!fread(&tmp, sizeof(struct fileentry), 1, hashfile) )
450 perror("hashfile");
451 exit(1);
454 if (tmp.depth && !Fbdcmp(tmp.bd, new.bd))
455 continue;
457 if (tmp.depth == depth)
458 break;
460 if (!tmp.depth || ((short) tmp.depth < depth))
462 fseek(hashfile,
463 sizeof(struct fileentry) * ((hashix + 2 * i) % (filesz)),
464 SEEK_SET);
466 fwrite(&new, sizeof(struct fileentry), 1, hashfile);
467 FHashAdd++;
469 break;
474 #endif /* HASHFILE */
475 #endif /* ttblsz */
479 void
480 ZeroRPT(void)
482 if (ISZERO )
484 array_zero(rpthash, sizeof(rpthash));
485 ISZERO = 0;
491 #if defined CACHE
494 * Store the current eval position in the transposition table.
497 void
498 PutInEETable(short side, int score)
500 struct etable *ptbl;
502 ptbl = &(*etab[side])[hashkey % (ETABLE)];
503 ptbl->ehashbd = hashbd;
504 ptbl->escore[black] = pscore[black];
505 ptbl->escore[white] = pscore[white];
506 ptbl->hung[black] = hung[black];
507 ptbl->hung[white] = hung[white];
508 ptbl->score = score;
510 #if !defined SAVE_SSCORE
511 array_copy(svalue, &(ptbl->sscore), sizeof(svalue));
512 #endif
514 EADD++;
516 return;
521 /* Get an evaluation from the transposition table */
524 CheckEETable(short side)
526 struct etable *ptbl;
528 ptbl = &(*etab[side])[hashkey % (ETABLE)];
530 if (hashbd == ptbl->ehashbd)
531 return true;
533 return false;
538 /* Get an evaluation from the transposition table */
541 ProbeEETable(short side, short *score)
543 struct etable *ptbl;
545 ptbl = &(*etab[side])[hashkey % (ETABLE)];
547 if (hashbd == ptbl->ehashbd)
549 pscore[black] = ptbl->escore[black];
550 pscore[white] = ptbl->escore[white];
552 #if defined SAVE_SSCORE
553 array_zero(svalue, sizeof(svalue));
554 #else
555 array_copy(&(ptbl->sscore), svalue, sizeof(svalue));
556 #endif
558 *score = ptbl->score;
559 hung[black] = ptbl->hung[black];
560 hung[white] = ptbl->hung[white];
562 EGET++;
564 return true;
567 return false;
570 #endif /* CACHE */