Merge branch 'maint'
[gnushogi.git] / gnushogi / util.c
blob96c702f604bfa6d2188094a7245cc461e75fec54
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
7 * Copyright (c) 2008, 2013, 2014 Yann Dirson and the Free Software Foundation
9 * GNU SHOGI is based on GNU CHESS
11 * Copyright (c) 1988, 1989, 1990 John Stanback
12 * Copyright (c) 1992 Free Software Foundation
14 * This file is part of GNU SHOGI.
16 * GNU Shogi is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 3 of the License,
19 * or (at your option) any later version.
21 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with GNU Shogi; see the file COPYING. If not, see
28 * <http://www.gnu.org/licenses/>.
29 * ----------------------------------------------------------------------
33 #include "gnushogi.h"
35 unsigned int TTadd = 0;
36 short recycle;
37 short ISZERO = 1;
39 #if 0
40 int
41 parse(FILE * fd, unsigned short *mv, char *opening)
43 int c, i, r1, r2, c1, c2;
44 char s[128];
45 char *p;
47 while (((c = getc(fd)) == ' ') || (c == '\n'));
49 i = 0;
50 s[0] = (char) c;
52 if (c == '!')
54 p = opening;
57 *p++ = c;
58 c = getc(fd);
60 if ((c == '\n') || (c == EOF))
62 *p = '\0';
63 return 0;
66 while (true);
69 while ((c != '?') && (c != ' ')
70 && (c != '\t') && (c != '\n') && (c != EOF))
72 s[++i] = (char) (c = getc(fd));
75 s[++i] = '\0';
77 if (c == EOF)
78 return (-1);
80 if ((s[0] == '!') || (s[0] == ';') || (i < 3))
82 while ((c != '\n') && (c != EOF))
83 c = getc(fd);
85 return 0;
88 c1 = COL_NUM(s[0]);
89 r1 = ROW_NUM(s[1]);
90 c2 = COL_NUM(s[2]);
91 r2 = ROW_NUM(s[3]);
92 *mv = (locn(r1, c1) << 8) | locn(r2, c2);
94 if (c == '?')
96 /* Bad move, not for the program to play */
97 *mv |= 0x8000; /* Flag it ! */
98 c = getc(fd);
101 return 1;
103 #endif
106 * The field of a hashtable is computed as follows:
107 * if sq is on board (< NO_SQUARES) the field gets the value
108 * of the piece on the square sq;
109 * if sq is off board (>= NO_SQUARES) it is a catched figure,
110 * and the field gets the number of catched pieces for
111 * each side.
114 inline unsigned char
115 CB(short sq)
117 short i = sq;
119 if (i < NO_SQUARES)
121 return ((color[i] == white) ? (0x80 | board[i]) : board[i]);
123 else
125 i -= NO_SQUARES;
126 return ((Captured[black][i] << 4) | Captured[white][i]);
133 #if ttblsz
136 * Look for the current board position in the transposition table.
140 ProbeTTable (short side,
141 short depth,
142 short ply,
143 short *alpha,
144 short *beta,
145 short *score)
147 struct hashentry *ptbl;
148 /*unsigned*/ short i = 0; /* to match new type of rehash --tpm */
150 ptbl = &ttable[side][hashkey % ttblsize];
152 while (true)
154 if ((ptbl->depth) == 0)
155 return false;
157 if (ptbl->hashbd == hashbd)
158 break;
160 if (++i > rehash)
161 return false;
163 ptbl++;
166 /* rehash max rehash times */
168 if (((short)(ptbl->depth) >= (short) depth))
170 #ifdef HASHTEST
171 for (i = 0; i < PTBLBDSIZE; i++)
173 if (ptbl->bd[i] != CB(i))
175 HashCol++;
177 if (!XSHOGI)
179 ShowMessage("ttable collision detected");
180 ShowBD(ptbl->bd);
181 printf("hashkey = 0x%x, hashbd = 0x%x\n",
182 hashkey, hashbd);
185 break;
188 #endif /* HASHTEST */
191 PV = SwagHt = ptbl->mv;
193 HashCnt++;
195 if (ptbl->flags & truescore)
197 *score = ptbl->score;
198 /* adjust *score so moves to mate is from root */
200 if (*score > SCORE_LIMIT)
201 *score -= ply;
202 else if (*score < -SCORE_LIMIT)
203 *score += ply;
205 *beta = -2 * (SCORE_LIMIT + 1000);
207 else if (ptbl->flags & lowerbound)
209 if (ptbl->score > *alpha)
210 *alpha = ptbl->score - 1;
213 return true;
216 return false;
222 * Store the current board position in the transposition table.
226 PutInTTable(short side,
227 short score,
228 short depth,
229 short ply,
230 short beta,
231 unsigned short mv)
233 struct hashentry *ptbl;
234 /*unsigned*/ short i = 0; /* to match new type of rehash --tpm */
236 ptbl = &ttable[side][hashkey % ttblsize];
238 while (true)
240 if ((ptbl->depth) == 0 || ptbl->hashbd == hashbd)
241 break;
243 if (++i > rehash)
245 THashCol++;
246 ptbl += recycle;
248 break;
251 ptbl++;
254 TTadd++;
255 HashAdd++;
257 /* adjust score so moves to mate is from this ply */
259 if (score > SCORE_LIMIT)
260 score += ply;
261 else if (score < -SCORE_LIMIT)
262 score -= ply;
264 ptbl->hashbd = hashbd;
265 ptbl->depth = (unsigned char) depth;
266 ptbl->score = score;
267 ptbl->mv = mv;
269 if (score > beta)
271 ptbl->flags = lowerbound;
272 ptbl->score = beta + 1;
274 else
276 ptbl->flags = truescore;
279 #if defined HASHTEST
280 for (i = 0; i < PTBLBDSIZE; i++)
281 ptbl->bd[i] = CB(i);
282 #endif /* HASHTEST */
284 return true;
289 void
290 ZeroTTable(void)
292 array_zero(ttable[black], (ttblsize + rehash));
293 array_zero(ttable[white], (ttblsize + rehash));
295 #ifdef CACHE
296 array_zero(etab[0], sizeof(struct etable)*(size_t)ETABLE);
297 array_zero(etab[1], sizeof(struct etable)*(size_t)ETABLE);
298 #endif
300 TTadd = 0;
306 #ifdef HASHFILE
308 Fbdcmp(unsigned char *a, unsigned char *b)
310 int i;
312 for (i = 0; i < PTBLBDSIZE; i++)
314 if (a[i] != b[i])
315 return false;
318 return true;
324 * Look for the current board position in the persistent transposition table.
328 ProbeFTable(short side,
329 short depth,
330 short ply,
331 short *alpha,
332 short *beta,
333 short *score)
335 short i;
336 unsigned long hashix;
337 struct fileentry new, t;
339 hashix = ((side == black) ? (hashkey & 0xFFFFFFFE)
340 : (hashkey | 1)) % filesz;
342 for (i = 0; i < PTBLBDSIZE; i++)
343 new.bd[i] = CB(i);
345 new.flags = 0;
347 for (i = 0; i < frehash; i++)
349 fseek(hashfile,
350 sizeof(struct fileentry) * ((hashix + 2 * i) % (filesz)),
351 SEEK_SET);
352 fread(&t, sizeof(struct fileentry), 1, hashfile);
354 if (!t.depth)
355 break;
357 if (!Fbdcmp(t.bd, new.bd))
358 continue;
360 if (((short) t.depth >= depth)
361 && (new.flags == (unsigned short)(t.flags
362 & (kingcastle | queencastle))))
364 FHashCnt++;
366 PV = (t.f << 8) | t.t;
367 *score = (t.sh << 8) | t.sl;
369 /* adjust *score so moves to mate is from root */
370 if (*score > SCORE_LIMIT)
371 *score -= ply;
372 else if (*score < -SCORE_LIMIT)
373 *score += ply;
375 if (t.flags & truescore)
377 *beta = -((SCORE_LIMIT + 1000)*2);
379 else if (t.flags & lowerbound)
381 if (*score > *alpha)
382 *alpha = *score - 1;
384 else if (t.flags & upperbound)
386 if (*score < *beta)
387 *beta = *score + 1;
390 return (true);
394 return (false);
400 * Store the current board position in the persistent transposition table.
403 void
404 PutInFTable(short side,
405 short score,
406 short depth,
407 short ply,
408 short alpha,
409 short beta,
410 unsigned short f,
411 unsigned short t)
413 unsigned short i;
414 unsigned long hashix;
415 struct fileentry new, tmp;
417 hashix = ((side == black) ? (hashkey & 0xFFFFFFFE)
418 : (hashkey | 1)) % filesz;
420 for (i = 0; i < PTBLBDSIZE; i++)
421 new.bd[i] = CB(i);
423 new.f = (unsigned char) f;
424 new.t = (unsigned char) t;
426 if (score < alpha)
427 new.flags = upperbound;
428 else
429 new.flags = ((score > beta) ? lowerbound : truescore);
431 new.depth = (unsigned char) depth;
433 /* adjust *score so moves to mate is from root */
434 if (score > SCORE_LIMIT)
435 score += ply;
436 else if (score < -SCORE_LIMIT)
437 score -= ply;
440 new.sh = (unsigned char) (score >> 8);
441 new.sl = (unsigned char) (score & 0xFF);
443 for (i = 0; i < frehash; i++)
445 fseek(hashfile,
446 sizeof(struct fileentry) * ((hashix + 2 * i) % (filesz)),
447 SEEK_SET);
449 if (!fread(&tmp, sizeof(struct fileentry), 1, hashfile) )
451 perror("hashfile");
452 exit(1);
455 if (tmp.depth && !Fbdcmp(tmp.bd, new.bd))
456 continue;
458 if (tmp.depth == depth)
459 break;
461 if (!tmp.depth || ((short) tmp.depth < depth))
463 fseek(hashfile,
464 sizeof(struct fileentry) * ((hashix + 2 * i) % (filesz)),
465 SEEK_SET);
467 fwrite(&new, sizeof(struct fileentry), 1, hashfile);
468 FHashAdd++;
470 break;
475 #endif /* HASHFILE */
476 #endif /* ttblsz */
480 void
481 ZeroRPT(void)
483 if (ISZERO )
485 array_zero(rpthash, sizeof(rpthash));
486 ISZERO = 0;
492 #if defined CACHE
495 * Store the current eval position in the transposition table.
498 void
499 PutInEETable(short side, int score)
501 struct etable *ptbl;
503 ptbl = &(*etab[side])[hashkey % (ETABLE)];
504 ptbl->ehashbd = hashbd;
505 ptbl->escore[black] = pscore[black];
506 ptbl->escore[white] = pscore[white];
507 ptbl->hung[black] = hung[black];
508 ptbl->hung[white] = hung[white];
509 ptbl->score = score;
511 #if !defined SAVE_SSCORE
512 array_copy(svalue, &(ptbl->sscore), sizeof(svalue));
513 #endif
515 EADD++;
517 return;
522 /* Get an evaluation from the transposition table */
525 CheckEETable(short side)
527 struct etable *ptbl;
529 ptbl = &(*etab[side])[hashkey % (ETABLE)];
531 if (hashbd == ptbl->ehashbd)
532 return true;
534 return false;
539 /* Get an evaluation from the transposition table */
542 ProbeEETable(short side, short *score)
544 struct etable *ptbl;
546 ptbl = &(*etab[side])[hashkey % (ETABLE)];
548 if (hashbd == ptbl->ehashbd)
550 pscore[black] = ptbl->escore[black];
551 pscore[white] = ptbl->escore[white];
553 #if defined SAVE_SSCORE
554 array_zero(svalue, sizeof(svalue));
555 #else
556 array_copy(&(ptbl->sscore), svalue, sizeof(svalue));
557 #endif
559 *score = ptbl->score;
560 hung[black] = ptbl->hung[black];
561 hung[white] = ptbl->hung[white];
563 EGET++;
565 return true;
568 return false;
571 #endif /* CACHE */