~ubuntu-branches/ubuntu/warty/gnushogi/warty

« back to all changes in this revision

Viewing changes to src/book.c

  • Committer: Bazaar Package Importer
  • Author(s): Javier Fernandez-Sanguino Pen~a
  • Date: 2004-01-09 16:06:59 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040109160659-n26nu7009llm247p
Tags: 1.3-3.1
* NMU
 - Minimal testing done and looks quite OK (even if I don't know
   how to play the game...)
 - Build-Depends move from libxaw-dev to libxaw6-dev (Closes: #169975)
 - Included errno.h in gnushogi which makes the binary build properly
   now (and is usable with xshogi) (Closes: #226319)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * book.c - C source for GNU SHOGI
3
 
 *
4
 
 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
5
 
 *
6
 
 * GNU SHOGI is based on GNU CHESS
7
 
 *
8
 
 * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
9
 
 * Foundation
10
 
 *
11
 
 * This file is part of GNU SHOGI.
12
 
 *
13
 
 * GNU Shogi is free software; you can redistribute it and/or modify it under
14
 
 * the terms of the GNU General Public License as published by the Free
15
 
 * Software Foundation; either version 1, or (at your option) any later
16
 
 * version.
17
 
 *
18
 
 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT ANY
19
 
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20
 
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
21
 
 * details.
22
 
 *
23
 
 * You should have received a copy of the GNU General Public License along with
24
 
 * GNU Shogi; see the file COPYING.  If not, write to the Free Software
25
 
 * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26
 
 */
27
 
 
28
 
#include "gnushogi.h"
29
 
#ifdef MSDOS
30
 
#include <io.h>
31
 
#endif
32
 
#if !defined MSDOS && !defined THINK_C
33
 
#define O_BINARY 0
34
 
#endif
35
 
#include <fcntl.h>
36
 
#ifdef THINK_C
37
 
#include <unix.h>
38
 
/* #define BOOKTEST */
39
 
#endif
40
 
 
41
 
 
42
 
#include "book.h"
43
 
 
44
 
 
45
 
 
46
 
unsigned booksize = BOOKSIZE;
47
 
unsigned short bookmaxply = BOOKMAXPLY;
48
 
unsigned bookcount = 0;
49
 
 
50
 
#ifdef BOOK
51
 
char *bookfile = BOOK;
52
 
#else
53
 
char *bookfile = NULL;
54
 
#endif
55
 
#ifdef BINBOOK
56
 
char *binbookfile = BINBOOK;
57
 
#else
58
 
char *binbookfile = NULL;
59
 
#endif
60
 
 
61
 
 
62
 
 
63
 
static char bmvstr[3][7];
64
 
 
65
 
static ULONG bhashbd;
66
 
static ULONG bhashkey;
67
 
 
68
 
 
69
 
void
70
 
Balgbr (short int f, short int t, short int flag)
71
 
 
72
 
 
73
 
     /*
74
 
      * Generate move strings in different formats.
75
 
      */
76
 
 
77
 
{
78
 
  short promoted = false;
79
 
 
80
 
  if ( (f & 0x80) != 0)
81
 
    {                
82
 
      f &= 0x7f;
83
 
      promoted = true;
84
 
    }
85
 
 
86
 
  if ( f > NO_SQUARES ) 
87
 
    { short piece;
88
 
      piece = f - NO_SQUARES;
89
 
      if ( f > (NO_SQUARES+NO_PIECES) )
90
 
        piece -= NO_PIECES;
91
 
      flag = (dropmask | piece); 
92
 
    }
93
 
  if ( (t & 0x80) != 0 )
94
 
    {
95
 
      flag |= promote;
96
 
      t &= 0x7f;
97
 
    }
98
 
  if ( f == t && (f != 0 || t != 0) ) 
99
 
    { 
100
 
#if !defined XSHOGI
101
 
      char buffer[80];
102
 
      sprintf(buffer,"error in algbr: FROM=TO=%d, flag=0x%4x\n",t,flag);
103
 
      ShowMessage(buffer);
104
 
#endif
105
 
      bmvstr[0][0] = bmvstr[1][0] = bmvstr[2][0] = '\0';
106
 
    }
107
 
  else
108
 
  if ( (flag & dropmask) != 0 )
109
 
    {
110
 
      /* bmvstr[0]: P*3c bmvstr[1]: P'3c */ 
111
 
      short piece = flag & pmask;
112
 
      bmvstr[0][0] = pxx[piece];
113
 
      bmvstr[0][1] = '*';
114
 
      bmvstr[0][2] = cxx[column (t)];
115
 
      bmvstr[0][3] = rxx[row (t)];
116
 
      bmvstr[0][4] = bmvstr[2][0] = '\0';
117
 
      strcpy (bmvstr[1], bmvstr[0]);
118
 
      bmvstr[1][1] = '\'';
119
 
    }
120
 
  else
121
 
  if (f != 0 || t != 0)
122
 
    {
123
 
      /* algebraic notation */
124
 
      /* bmvstr[0]: 7g7f bmvstr[1]: (+)P7g7f(+) bmvstr[2]: (+)P7f(+) */
125
 
      bmvstr[0][0] = cxx[column (f)];
126
 
      bmvstr[0][1] = rxx[row (f)];
127
 
      bmvstr[0][2] = cxx[column (t)];
128
 
      bmvstr[0][3] = rxx[row (t)];
129
 
      bmvstr[0][4] = '\0';
130
 
      if (promoted)
131
 
        {
132
 
          bmvstr[1][0] = bmvstr[2][0] = '+';
133
 
          bmvstr[1][1] = bmvstr[2][1] = pxx[board[f]];
134
 
          strcpy(&bmvstr[1][2],&bmvstr[0][0]);
135
 
          strcpy(&bmvstr[2][2],&bmvstr[0][2]);
136
 
        }                                  
137
 
      else
138
 
        {
139
 
          bmvstr[1][0] = bmvstr[2][0] = pxx[board[f]];
140
 
          strcpy(&bmvstr[1][1],&bmvstr[0][0]);
141
 
          strcpy(&bmvstr[2][1],&bmvstr[0][2]);
142
 
        }
143
 
      if (flag & promote)
144
 
        {
145
 
                strcat(bmvstr[0], "+");
146
 
                strcat(bmvstr[1], "+");
147
 
                strcat(bmvstr[2], "+");
148
 
        }
149
 
    }
150
 
  else
151
 
    bmvstr[0][0] = bmvstr[1][0] = bmvstr[2][0] = '\0';
152
 
}
153
 
 
154
 
 
155
 
 
156
 
 
157
 
#ifndef QUIETBOOKGEN
158
 
void
159
 
bkdisplay (s, cnt, moveno)
160
 
     char *s;
161
 
     int cnt;
162
 
     int moveno;
163
 
{
164
 
    static short pnt;
165
 
    struct leaf far *node;
166
 
    int r, c, l;
167
 
 
168
 
    pnt = TrPnt[2];
169
 
    printf ("matches = %d\n", cnt);
170
 
    printf ("inout move is :%s: move number %d side %s\n", 
171
 
                s, moveno / 2 + 1, (moveno & 1) ? "white" : "black");
172
 
#ifndef SEMIQUIETBOOKGEN
173
 
    printf ("legal moves are \n");
174
 
    while (pnt < TrPnt[3])
175
 
      {
176
 
          node = &Tree[pnt++];
177
 
          if ( is_promoted[board[node->f]] )
178
 
            Balgbr (node->f | 0x80, node->t, (short) node->flags);
179
 
          else
180
 
            Balgbr (node->f, node->t, (short) node->flags);
181
 
          printf ("%s %s %s\n", 
182
 
            bmvstr[0], bmvstr[1], bmvstr[2]);
183
 
      }
184
 
    printf ("\n current board is\n");
185
 
    for (r = (NO_ROWS-1); r >= 0; r--)
186
 
        {
187
 
          for (c = 0; c <= (NO_COLS-1); c++)
188
 
            { char pc;
189
 
              l = locn (r, c);
190
 
              pc = (is_promoted[board[l]] ? '+' : ' ');
191
 
              if (color[l] == neutral)
192
 
                printf (" -");
193
 
              else if (color[l] == black)
194
 
                printf ("%c%c", pc, qxx[board[l]]);
195
 
              else
196
 
                printf ("%c%c", pc, pxx[board[l]]);
197
 
            }
198
 
          printf ("\n");
199
 
        }
200
 
    printf ("\n");
201
 
    {  
202
 
        short color;
203
 
        for (color = black; color <= white; color++)
204
 
          { short piece, c;
205
 
            printf((color==black)?"black ":"white ");
206
 
            for (piece = pawn; piece <= king; piece++)
207
 
              if (c = Captured[color][piece]) 
208
 
                printf("%i%c ",c,pxx[piece]);
209
 
            printf("\n");
210
 
          };
211
 
    }
212
 
#endif /* SEMIQUIETBOOKGEN */
213
 
}
214
 
 
215
 
#endif /* QUIETBOOKGEN */
216
 
 
217
 
int
218
 
BVerifyMove (char *s, short unsigned int *mv, int moveno)
219
 
 
220
 
     /*
221
 
      * Compare the string 's' to the list of legal moves available for the
222
 
      * opponent. If a match is found, make the move on the board.
223
 
      */
224
 
 
225
 
{
226
 
    static short pnt, tempb, tempc, tempsf, tempst, cnt;
227
 
    static struct leaf xnode;
228
 
    struct leaf far *node;
229
 
 
230
 
    *mv = 0;
231
 
    cnt = 0;
232
 
    MoveList (opponent, 2, -2, true);
233
 
    pnt = TrPnt[2];
234
 
    while (pnt < TrPnt[3])
235
 
      {
236
 
          node = &Tree[pnt++];
237
 
          if ( is_promoted[board[node->f]] )
238
 
            Balgbr (node->f | 0x80, node->t, (short) node->flags);
239
 
          else
240
 
            Balgbr (node->f, node->t, (short) node->flags);
241
 
          if (strcmp (s, bmvstr[0]) == 0 || strcmp (s, bmvstr[1]) == 0 ||
242
 
              strcmp (s, bmvstr[2]) == 0)
243
 
            {
244
 
                cnt++;
245
 
                xnode = *node;
246
 
            }
247
 
      }
248
 
    if (cnt == 1)
249
 
      {   short blockable;
250
 
          MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
251
 
          if (SqAtakd (PieceList[opponent][0], computer, &blockable))
252
 
            {
253
 
                UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
254
 
                /* Illegal move in check */
255
 
#if !defined QUIETBOOKGEN
256
 
#ifdef XSHOGI
257
 
                printf ("Illegal move (in check)");
258
 
#else
259
 
                printf (CP[77]);
260
 
#endif
261
 
                printf ("\n");
262
 
                bkdisplay (s, cnt, moveno);
263
 
#endif
264
 
                return (false);
265
 
            }
266
 
          else
267
 
            {
268
 
                *mv = (xnode.f << 8) | xnode.t;
269
 
                if ( is_promoted[board[xnode.t]] )
270
 
                  Balgbr (xnode.f | 0x80, xnode.t, false);
271
 
                else
272
 
                  Balgbr (xnode.f, xnode.t, false);
273
 
                return (true);
274
 
            }
275
 
      }
276
 
    /* Illegal move */
277
 
#if !defined QUIETBOOKGEN
278
 
#ifdef XSHOGI
279
 
    printf ("Illegal move (no match) %s\n", s);
280
 
#else
281
 
    printf (CP[75], s);
282
 
#endif
283
 
    bkdisplay (s, cnt, moveno);
284
 
#endif
285
 
    return (false);
286
 
}
287
 
 
288
 
void
289
 
RESET (void)
290
 
 
291
 
     /*
292
 
      * Reset the board and other variables to start a new game.
293
 
      */
294
 
 
295
 
{
296
 
    short int l;
297
 
 
298
 
    flag.illegal = flag.mate = flag.post = flag.quit = flag.reverse = flag.bothsides = flag.onemove = flag.force = false;
299
 
    flag.material = flag.coords = flag.hash = flag.easy = flag.beep = flag.rcptr = true;
300
 
    flag.stars = flag.shade = flag.back = flag.musttimeout = false;
301
 
    flag.gamein = false;
302
 
    GenCnt = 0;
303
 
    GameCnt = 0;
304
 
    CptrFlag[0] = TesujiFlag[0] = false;
305
 
    opponent = black;
306
 
    computer = white;
307
 
    for (l = 0; l < NO_SQUARES; l++)
308
 
      {
309
 
          board[l] = Stboard[l];
310
 
          color[l] = Stcolor[l];
311
 
          Mvboard[l] = 0;
312
 
      }
313
 
    ClearCaptured ();
314
 
    InitializeStats ();
315
 
    hashbd = hashkey = 0; 
316
 
}
317
 
 
318
 
static
319
 
int
320
 
Vparse (FILE * fd, USHORT *mv, USHORT *flags, USHORT side, int moveno)
321
 
{
322
 
    int c, i;
323
 
    char s[255];
324
 
 
325
 
    *flags = 0;
326
 
 
327
 
    while (true)
328
 
      {
329
 
          
330
 
          while ((c = getc (fd)) == ' ' || c == '!' || c == '/' || c == '\n');
331
 
 
332
 
          if ( c == '(' ) 
333
 
            {   /* amount of time spent for the last move */
334
 
                while ((c = getc(fd)) != ')' && c != EOF);
335
 
                if ( c == ')' ) 
336
 
                  while ((c = getc (fd)) == ' ' || c == '\n');
337
 
            }
338
 
 
339
 
          if (c == '[')
340
 
            {   /* comment for the actual game */
341
 
                while ( (c = getc(fd)) != ']' && c != EOF );
342
 
                if ( c == ']' ) 
343
 
                  while ((c = getc (fd)) == ' ' || c == '\n');
344
 
            }
345
 
          
346
 
          if (c == '\r')
347
 
              continue;
348
 
 
349
 
          if (c == '#')
350
 
            {   /* comment */
351
 
                do
352
 
                  {
353
 
                      c = getc (fd);
354
 
                      if (c == '\r')
355
 
                          continue;
356
 
                      /* goes to end of line */
357
 
                      if (c == '\n')
358
 
                        {
359
 
                            return 0;
360
 
                        } 
361
 
                      if (c == EOF)
362
 
                        return -1;
363
 
                  }
364
 
                while (true);
365
 
            }
366
 
 
367
 
          s[i = 0] = (char) c;
368
 
 
369
 
          while ( c >= '0' && c <= '9' )
370
 
            { 
371
 
              c = getc(fd);
372
 
              s[++i] = (char) c;
373
 
            }
374
 
 
375
 
          if ( c == '.' )
376
 
            { 
377
 
              while ((c = getc (fd)) == ' ' || c == '.' || c == '\n');
378
 
              s[i = 0] = (char) c;
379
 
            }     
380
 
 
381
 
          while ((c = getc (fd)) != '?' && c != '!' && c != ' ' && c != '(' && c != '\n' && c != '\t' && c != EOF)
382
 
            {
383
 
                if (c == '\r')
384
 
                    continue;
385
 
                if (c != 'x' && c != '-' && c != ',' && c != ';' && c != '=')
386
 
                    s[++i] = (char) c;
387
 
            }
388
 
          s[++i] = '\0';
389
 
 
390
 
          if ( c == '(' ) 
391
 
            {
392
 
              while ((c = getc(fd)) != ')' && c != EOF);
393
 
              if ( c == ')' ) 
394
 
                c = getc(fd);
395
 
            }
396
 
 
397
 
          if (c == EOF)
398
 
              return (-1);
399
 
 
400
 
          if (s[0] == '#')
401
 
            {
402
 
                while (c != '\n' && c != EOF)
403
 
                    c = getc (fd);
404
 
                if (c == EOF)
405
 
                    return -1;
406
 
                else
407
 
                    return (0);
408
 
            }
409
 
 
410
 
          if (strcmp (s, "draw") == 0)
411
 
              continue;
412
 
          else if (strcmp (s, "1-0") == 0)
413
 
              continue;
414
 
          else if (strcmp (s, "0-1") == 0)
415
 
              continue;
416
 
          else if (strcmp (s, "Resigns") == 0)
417
 
              continue;
418
 
          else if (strcmp (s, "Resigns.") == 0)
419
 
              continue;
420
 
          else if (strcmp (s, "Sennichite") == 0)
421
 
              continue;
422
 
          else if (strcmp (s, "Sennichite.") == 0)
423
 
              continue;
424
 
          else if (strcmp (s, "Jishogi") == 0)
425
 
              continue;
426
 
          else if (strcmp (s, "Jishogi.") == 0)
427
 
              continue;
428
 
 
429
 
          bhashkey = hashkey;
430
 
          bhashbd  = hashbd;
431
 
 
432
 
          i = BVerifyMove (s, mv, moveno);
433
 
 
434
 
          if (c == '?')
435
 
            {                   /* Bad move, not for the program to play */
436
 
                *flags |= BADMOVE;      /* Flag it ! */
437
 
                while ((c = getc (fd)) == '?' || c == '!' || c == '/');
438
 
            }                      
439
 
#ifdef EASY_OPENINGS
440
 
          else if (c == '~')
441
 
            {                   /* Do not use by computer */
442
 
                *flags |= BADMOVE;      /* Flag it ! */
443
 
                while ((c = getc (fd)) == '?' || c == '!' || c == '/');
444
 
            }            
445
 
#endif
446
 
          else if (c == '!')
447
 
            {                   /* Good move */
448
 
                *flags |= GOODMOVE;     /* Flag it ! */
449
 
                while ((c = getc (fd)) == '?' || c == '!' || c == '/');
450
 
            }
451
 
          else if (c == '\r')
452
 
              c = getc (fd);
453
 
 
454
 
          if ( c == '(' ) 
455
 
            while ((c = getc(fd)) != ')' && c != EOF);
456
 
 
457
 
          if (!i)
458
 
            {
459
 
                /* flush to start of next */
460
 
                while ((c = getc (fd)) != '#' && c != EOF);
461
 
                if (c == EOF)
462
 
                    return -1;
463
 
                else
464
 
                  {
465
 
                      ungetc (c, fd);
466
 
                      return i;
467
 
                  }
468
 
            }
469
 
 
470
 
          return (i);
471
 
      }
472
 
}
473
 
 
474
 
 
475
 
static struct gdxadmin ADMIN;
476
 
struct gdxadmin B;
477
 
 
478
 
static struct gdxdata DATA;
479
 
 
480
 
 
481
 
 
482
 
/* lts(l) returns most significant 16 bits of l */
483
 
 
484
 
#ifdef LONG64
485
 
#define lts(x) (USHORT)(((x>>48)&0xfffe)|side)
486
 
#else
487
 
#if defined THINK_C || defined USE_LTSIMP
488
 
static USHORT ltsimp (long x)
489
 
{ USHORT n;
490
 
  n = (((x>>16)&0xfffe));
491
 
#if 0
492
 
  printf("x=0x%lx lts(x)=0x%x\n",x,n);
493
 
#endif
494
 
  return(n);
495
 
}
496
 
#define lts(x) (USHORT)(ltsimp(x) | side)
497
 
#else
498
 
#define lts(x) (USHORT)(((x>>16)&0xfffe) | side)
499
 
#endif
500
 
#endif
501
 
 
502
 
 
503
 
/* #define HashValue(l) lts(l) */
504
 
#define HashValue(l) (USHORT)(l & 0xffff)
505
 
 
506
 
 
507
 
static int gfd;
508
 
 
509
 
 
510
 
static ULONG currentoffset;
511
 
 
512
 
 
513
 
#define MAXOFFSET(B) ((B.booksize-1)*sizeof_gdxdata + sizeof_gdxadmin)
514
 
 
515
 
#define HashOffset(hashkey,B) { \
516
 
  currentoffset = ((ULONG)hashkey % B.booksize)*sizeof_gdxdata + sizeof_gdxadmin; \
517
 
}
518
 
 
519
 
#define NextOffset(B) { \
520
 
  currentoffset += sizeof_gdxdata; \
521
 
  if (currentoffset > B.maxoffset) \
522
 
    currentoffset = sizeof_gdxadmin; \
523
 
}
524
 
 
525
 
 
526
 
 
527
 
 
528
 
#define WriteAdmin() { \
529
 
  lseek (gfd, 0, 0); \
530
 
  write (gfd, (char *)&ADMIN, sizeof_gdxadmin); \
531
 
}
532
 
 
533
 
#define WriteData() { \
534
 
  if ( mustwrite ) { \
535
 
    lseek (gfd, currentoffset, 0); \
536
 
    write (gfd, (char *)&DATA, sizeof_gdxdata); \
537
 
    mustwrite = false; \
538
 
  } \
539
 
}
540
 
 
541
 
static int ReadAdmin(void) {
542
 
  lseek (gfd, 0, 0); 
543
 
  return (sizeof_gdxadmin == read (gfd, (char *)&ADMIN, sizeof_gdxadmin));
544
 
}
545
 
 
546
 
static int ReadData(struct gdxdata *DATA) {
547
 
  lseek (gfd, currentoffset, 0); 
548
 
  return (sizeof_gdxdata == read (gfd, (char *)DATA, sizeof_gdxdata));
549
 
}
550
 
 
551
 
 
552
 
void
553
 
GetOpenings (void)
554
 
 
555
 
     /*
556
 
      * Read in the Opening Book file and parse the algebraic notation for a move
557
 
      * into an unsigned integer format indicating the from and to square. Create
558
 
      * a linked list of opening lines of play, with entry->next pointing to the
559
 
      * next line and entry->move pointing to a chunk of memory containing the
560
 
      * moves. More Opening lines of up to 100 half moves may be added to
561
 
      gnuchess.book. But now its a hashed table by position which yields a move
562
 
      * or moves for each position. It no longer knows about openings per say only
563
 
      * positions and recommended moves in those positions.
564
 
      */
565
 
{
566
 
    short int i;
567
 
    char opening[80];
568
 
    char msg[80];
569
 
    int mustwrite = false, first;
570
 
    unsigned short xside, side;
571
 
    short int c;
572
 
    USHORT mv, flags; unsigned int x;
573
 
    unsigned int games = 0;
574
 
    LONG collisions = 0;
575
 
 
576
 
    FILE *fd;
577
 
 
578
 
    if ((fd = fopen (bookfile, "r")) == NULL)
579
 
        fd = fopen ("gnushogi.tbk", "r");
580
 
    if (fd != NULL)
581
 
      {
582
 
          /* yes add to book */
583
 
          /* open book as writer */
584
 
          gfd = open (binbookfile, O_RDONLY | O_BINARY);
585
 
          if (gfd >= 0)
586
 
            {
587
 
                if ( ReadAdmin() ) 
588
 
                  {
589
 
                      B.bookcount = ADMIN.bookcount;
590
 
                      B.booksize = ADMIN.booksize;
591
 
                      B.maxoffset = ADMIN.maxoffset;
592
 
                      if (B.booksize && !(B.maxoffset == MAXOFFSET(B)))
593
 
                        {
594
 
                            printf ("bad format %s\n", binbookfile);
595
 
                            exit (1);
596
 
                        }
597
 
                  }
598
 
                else
599
 
                  {
600
 
                      printf ("bad format %s\n", binbookfile);
601
 
                      exit (1);
602
 
                  }
603
 
                close (gfd);
604
 
                gfd = open (binbookfile, O_RDWR | O_BINARY);
605
 
 
606
 
            }
607
 
          else
608
 
            {
609
 
#if defined THINK_C || defined MSDOS
610
 
                gfd = open (binbookfile, O_RDWR | O_CREAT | O_BINARY);
611
 
#else
612
 
                gfd = open (binbookfile, O_RDWR | O_CREAT | O_BINARY, 0644);
613
 
#endif
614
 
                ADMIN.bookcount = B.bookcount = 0;
615
 
                ADMIN.booksize = B.booksize = booksize;
616
 
                B.maxoffset = ADMIN.maxoffset = MAXOFFSET(B);
617
 
                DATA.hashbd = 0;
618
 
                DATA.hashkey = 0;
619
 
                DATA.bmove = 0;
620
 
                DATA.flags = 0;
621
 
                DATA.hint = 0;
622
 
                DATA.count = 0;
623
 
                write (gfd, (char *)&ADMIN, sizeof_gdxadmin);
624
 
                printf ("creating bookfile %s  %ld %d\n", binbookfile, B.maxoffset, B.booksize);
625
 
                for (x = 0; x < B.booksize; x++)
626
 
                  {
627
 
                      write (gfd, (char *)&DATA, sizeof_gdxdata);
628
 
                  }
629
 
 
630
 
 
631
 
            }
632
 
          if (gfd >= 0)
633
 
            {
634
 
 
635
 
 
636
 
                /* setvbuf(fd,buffr,_IOFBF,2048); */
637
 
                side = black;
638
 
                xside = white;
639
 
                hashbd = hashkey = 0;
640
 
                i = 0;
641
 
 
642
 
                while ((c = Vparse (fd, &mv, &flags, side, i)) >= 0)
643
 
                  {
644
 
                      if (c == 1)
645
 
                        {
646
 
 
647
 
                            /*
648
 
                             * if not first move of an opening and first
649
 
                             * time we have seen it save next move as
650
 
                             * hint
651
 
                             */
652
 
                            i++;
653
 
                            if (i < bookmaxply + 2)
654
 
                              {
655
 
                                  if (i > 1 && !(flags & BADMOVE)) {
656
 
                                    DATA.hint = mv;
657
 
                                  }
658
 
                                  if (i < bookmaxply + 1)
659
 
                                    {
660
 
                                        /*
661
 
                                         * see if this position and
662
 
                                         * move already exist from
663
 
                                         * some other opening
664
 
                                         */
665
 
 
666
 
                                        WriteData();
667
 
                                        HashOffset(bhashkey,B);
668
 
                                        first = true;
669
 
                                        while (true) {
670
 
                                          if (!ReadData(&DATA)) break; /* corrupted binbook file */
671
 
                                          if (DATA.bmove == 0) break;  /* free entry */
672
 
                                          if (DATA.hashkey == HashValue(bhashkey) && DATA.hashbd == bhashbd) {
673
 
                                            if (DATA.bmove == mv) {
674
 
                                              /*
675
 
                                               * yes so just bump count - count is
676
 
                                               * used to choose opening move in
677
 
                                               * proportion to its presence in the book
678
 
                                               */
679
 
                                              DATA.count++;
680
 
                                              DATA.flags |= flags;
681
 
                                              mustwrite = true;
682
 
                                              break;   
683
 
                                            } else {
684
 
                                              if ( first ) collisions++;
685
 
                                              if (DATA.flags & LASTMOVE) {
686
 
                                                DATA.flags &= (~LASTMOVE);
687
 
                                                mustwrite = true;
688
 
                                                WriteData();
689
 
                                              }
690
 
                                            }
691
 
                                          }
692
 
                                          NextOffset(B);
693
 
                                          first = false;
694
 
                                        }
695
 
 
696
 
                                        /*
697
 
                                         * doesn`t exist so add it to
698
 
                                         * the book
699
 
                                         */
700
 
                                        if (!mustwrite)
701
 
                                          {
702
 
                                              B.bookcount++;
703
 
#if !defined XSHOGI
704
 
#if defined THINK_C || defined MSDOS
705
 
                                              if (B.bookcount % 100 == 0)
706
 
#else
707
 
                                              if (B.bookcount % 1000 == 0)
708
 
#endif
709
 
                                                  printf ("%d rec %d openings processed\n", B.bookcount, games);
710
 
#endif
711
 
                                              /* initialize a record */
712
 
                                              DATA.hashbd = bhashbd;
713
 
                                              DATA.hashkey = HashValue(bhashkey);
714
 
                                              DATA.bmove = mv;
715
 
                                              DATA.flags = flags | LASTMOVE;
716
 
                                              DATA.count = 1;
717
 
                                              DATA.hint = 0;
718
 
                                              mustwrite = true;
719
 
                                          }
720
 
                                    }
721
 
                              }
722
 
                            computer = opponent;
723
 
                            opponent = computer ^ 1;
724
 
 
725
 
                            xside = side;
726
 
                            side = side ^ 1;
727
 
                        }
728
 
                      else if (i > 0)
729
 
                        {
730
 
                            /* reset for next opening */
731
 
                            games++;
732
 
                            WriteData();
733
 
                            RESET ();
734
 
                            i = 0;
735
 
                            side = black;
736
 
                            xside = white;
737
 
 
738
 
                        }
739
 
                  }
740
 
                WriteData();
741
 
                fclose (fd);
742
 
                /* write admin rec with counts */
743
 
                ADMIN.bookcount = B.bookcount;
744
 
                WriteAdmin();
745
 
 
746
 
                close (gfd);
747
 
            }
748
 
      }
749
 
    if (binbookfile != NULL)
750
 
      {
751
 
          /* open book as reader */
752
 
          gfd = open (binbookfile, O_RDONLY | O_BINARY);
753
 
          if (gfd >= 0)
754
 
            {
755
 
                if ( ReadAdmin() && (!ADMIN.booksize || ADMIN.maxoffset == MAXOFFSET(ADMIN)) ) 
756
 
                  {
757
 
                    B.bookcount = ADMIN.bookcount;
758
 
                    B.booksize = ADMIN.booksize;
759
 
                    B.maxoffset = ADMIN.maxoffset;
760
 
                  }
761
 
                else
762
 
                  {
763
 
                    printf ("bad format %s\n", binbookfile);
764
 
                    exit (1);
765
 
                  }
766
 
 
767
 
            }
768
 
          else
769
 
            {
770
 
                B.bookcount = 0;
771
 
                B.booksize = booksize;
772
 
 
773
 
            }
774
 
 
775
 
#if !defined XSHOGI
776
 
          sprintf (msg, CP[213], B.bookcount, B.booksize);
777
 
          ShowMessage (msg);
778
 
          /* printf("%ld collisions\n", collisions); */
779
 
#endif
780
 
      }
781
 
    /* set every thing back to start game */
782
 
    Book = BOOKFAIL;
783
 
    RESET ();
784
 
    /* now get ready to play */
785
 
    if (!B.bookcount)
786
 
      {
787
 
#if !defined XSHOGI
788
 
          ShowMessage (CP[212]);
789
 
#endif
790
 
          Book = 0;
791
 
      }
792
 
}
793
 
 
794
 
 
795
 
int
796
 
OpeningBook (unsigned short *hint, short int side)
797
 
 
798
 
     /*
799
 
      * Go thru each of the opening lines of play and check for a match with the
800
 
      * current game listing. If a match occurs, generate a random number. If this
801
 
      * number is the largest generated so far then the next move in this line
802
 
      * becomes the current "candidate". After all lines are checked, the
803
 
      * candidate move is put at the top of the Tree[] array and will be played by
804
 
      * the program. Note that the program does not handle book transpositions.
805
 
      */
806
 
 
807
 
{
808
 
    unsigned short r, m;
809
 
    int possibles = TrPnt[2] - TrPnt[1];
810
 
 
811
 
    gsrand ((unsigned int) time ((long *) 0));
812
 
    m = 0;
813
 
 
814
 
    /*
815
 
     * find all the moves for this position  - count them and get their
816
 
     * total count
817
 
     */
818
 
    {
819
 
        USHORT i, x;
820
 
        USHORT rec = 0;
821
 
        USHORT summ = 0;
822
 
        USHORT h = 0, b = 0;
823
 
        struct gdxdata OBB[128];
824
 
        if (B.bookcount == 0)
825
 
          {
826
 
              Book--;
827
 
              return false;
828
 
          }
829
 
        x = 0;
830
 
        HashOffset(hashkey,B);
831
 
#ifdef BOOKTEST
832
 
        printf("looking for book move, bhashbd = 0x%lx bhashkey = 0x%x\n", (ULONG)hashbd, HashValue(hashkey));
833
 
#endif
834
 
        while (true)
835
 
          {
836
 
              if (!ReadData(&OBB[x])) break;
837
 
              if (OBB[x].bmove == 0) break;
838
 
#ifdef BOOKTEST
839
 
              printf("compare with bhashbd = 0x%lx bhashkey = 0x%x\n", OBB[x].hashbd, OBB[x].hashkey);
840
 
#endif
841
 
              if (OBB[x].hashkey == HashValue(hashkey) && OBB[x].hashbd == (ULONG)hashbd)
842
 
                {
843
 
                    x++;
844
 
                    if (OBB[x-1].flags & LASTMOVE) break;
845
 
                }
846
 
              NextOffset(B);
847
 
          }
848
 
#ifdef BOOKTEST
849
 
        printf("%d book move(s) found.\n",x);
850
 
#endif
851
 
        if (x == 0)
852
 
          {
853
 
              Book--;
854
 
              return false;
855
 
          }
856
 
        for (i = 0; i < x; i++)
857
 
          {
858
 
              if (OBB[i].flags & BADMOVE)
859
 
                {
860
 
                    m = OBB[i].bmove;
861
 
                    /* is the move is in the MoveList */
862
 
                    for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
863
 
                      {
864
 
                          if (((Tree[b].f << 8) | Tree[b].t) == m)
865
 
                            {
866
 
 
867
 
                                if (--possibles)
868
 
                                    Tree[b].score = DONTUSE;
869
 
                                break;
870
 
                            }
871
 
                      }
872
 
                }
873
 
              else 
874
 
                {
875
 
#if defined BOOKTEST
876
 
                  char s[20];
877
 
                  movealgbr(m = OBB[i].bmove,s); 
878
 
                  printf("finding book move: %s\n",s);
879
 
#endif
880
 
                  summ += OBB[i].count;
881
 
                }
882
 
          }
883
 
        if (summ == 0)
884
 
          {
885
 
              Book--;
886
 
              return false;
887
 
          }
888
 
 
889
 
        r = (urand () % summ);
890
 
        for (i = 0; i < x; i++)
891
 
            if (!(OBB[i].flags & BADMOVE) ){
892
 
                if( r < OBB[i].count)
893
 
                    {
894
 
                        rec = i;
895
 
                        break;
896
 
                    }
897
 
                  else
898
 
                      r -= OBB[i].count;
899
 
            } 
900
 
 
901
 
        h = OBB[rec].hint;
902
 
        m = OBB[rec].bmove;
903
 
        /* make sure the move is in the MoveList */
904
 
        for (b = TrPnt[1]; b < (unsigned) TrPnt[2]; b++)
905
 
          {
906
 
              if (((Tree[b].f << 8) | Tree[b].t) == m)
907
 
                {
908
 
                    Tree[b].flags |= book;
909
 
                    Tree[b].score = 0;
910
 
                    break;
911
 
                }
912
 
          }
913
 
        /* Make sure its the best */
914
 
 
915
 
        pick (TrPnt[1], TrPnt[2] - 1);
916
 
        if (Tree[TrPnt[1]].score)
917
 
          {
918
 
              /* no! */
919
 
              Book--;
920
 
              return false;
921
 
          }
922
 
        /* ok pick up the hint and go */
923
 
        *hint = h;
924
 
        return true;
925
 
    }
926
 
    Book--;
927
 
    return false;
928
 
}
929
 
 
930
 
 
931