Move strings back into source code, from .lng support.
[gnushogi.git] / gnushogi / util.c
blobaf57cae9fda099c0b26062abca6447ac7ac80d41
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;
39 int
40 parse(FILE * fd, unsigned short *mv, short side, 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;
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 alpha,
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 */