/*  C source for BuildOpenBook
  Revision: 5-23-88, 08-31-2002

  OpenChess version 1.0, is a CHESS game for Palm Pilot, adapted
    from GNU Chess 2, for Unix/DOS environments
  The BuildOpenBook program is used to build the OpenBook resource data,
  which is then included as a resource in the OpenChess.prc executable.
  Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
  Copyright (c) 1988  John Stanback
  Copyright (C) 2002, Son Altesse.

 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  This file is part of CHESS.

  CHESS is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY.  No author or distributor
  accepts responsibility to anyone for the consequences of using it
  or for whether it serves any particular purpose or works at all,
  unless he says so in writing.  Refer to the CHESS General Public
  License for full details.

  Everyone is granted permission to copy, modify and redistribute
  CHESS, but only under the conditions described in the
  CHESS General Public License.   A copy of this license is
  supposed to have been given to you along with CHESS so you
  can know your rights and responsibilities.  It should be in a
  file named COPYING.  Among other things, the copyright notice
  and this notice must be preserved on all copies.
*/

#include <stdio.h>
#include <string.h>

#define neutral 2
#define white 0
#define black 1

struct BookEntry
  {
    struct BookEntry *next;
    unsigned short *mv;
  };

struct BookEntry *Book;
short row[64],column[64],locn[8][8],Pindex[64],svalue[64];
short otherside[3]={1,0,2};
short cnt,cnts;  // # of openings found

main()
{
short l,r,c,p,i,is;
unsigned short *mp;
FILE *fd;
struct BookEntry *entry;
unsigned short tmp[100];

  for (r = 0; r < 8; r++)
    for (c = 0; c < 8; c++)
      {
        l = 8*r+c; locn[r][c] = l;
        row[l] = r; column[l] = c;
      }

  cnt = -1;
  GetOpenings();
  /* Write the opening book into the binary file OpenBook.hex, used then by
     Pilrc to build the corresponding resource. The format of OpenBook.hex is
     the following:

     |openings count|Opening 1|0000|Opening 2|0000|...|Opening #count|0000|

     Each opening contains a binary encoding of each ascii move for this opening,
     in the order they appear in gnuchess.book
  */
  if ((fd = fopen("OpenBook.hex","wb")) != NULL) {
    entry = Book; i = 0;
    printf("%d openings found in gnuchess.book\n", cnt);
    /*  IMPORTANT HERE: The use of swab is necessary for Intel platforms, as
        they uses the Intel convention for byte representation. On the other
        hand, PalmOS will use the Motorola convention, which is opposite.
    */
    swab(&cnt, &cnts, sizeof(short));
    fwrite(&cnts,sizeof(short), 1, fd);
    while (entry != NULL) {
      mp = entry->mv;
      for (i = 1; *mp != 0; i++, mp++);
      swab(entry->mv, tmp, sizeof(short) * i);
      fwrite(tmp, sizeof(short), i , fd);
      entry = entry->next;
      }
    fclose(fd);
    printf("done.\n");
    }
  else printf("Error: Cannot write OpenBook.hex\n");
}

/* The following procedures have been extracted from uxdsp.c, they are
   used to pre-build a binary file OpenBook.hex, which is the memory
   representation of the ascii text file gnuchess.book, used by GNUChess.
   OpenBook.hex is used as a resource, and placed in the executable
   OpenChess.prc, to be used later by the GetOpenings() procedure in OpenChess.
   The resulting binary resource is 1/3 the original ascii text book!
*/

GetOpenings()

/*
   Read in the Opening Book file and parse the algebraic notation for a
   move into an unsigned integer format indicating the from and to
   square. Create a linked list of opening lines of play, with
   entry->next pointing to the next line and entry->move pointing to a
   chunk of memory containing the moves. More Opening lines of up to 256
   half moves may be added to gnuchess.book.
*/

{
FILE *fd;
int c,i,j,side;
struct BookEntry *entry;
unsigned short mv,*mp,tmp[100];

  if ((fd = fopen("gnuchess.book","r")) != NULL)
    {
      Book = NULL;
      i = 0; side = white; cnt = 0;
      while ((c = parse(fd,&mv,side)) >= 0)
        if (c == 1)
          {
            tmp[++i] = mv;
            side = otherside[side];
          }
        else if (c == 0 && i > 0)
          {
            entry = (struct BookEntry *)malloc(sizeof(struct BookEntry));
            mp = (unsigned short *)malloc((i+1)*sizeof(unsigned short));
            entry->mv = mp;
            entry->next = Book;
            Book = entry;
            for (j = 1; j <= i; j++) *(mp++) = tmp[j];
            *mp = 0;
            i = 0; side = white; cnt++;
          }
      fclose(fd);
    }
    else printf("Error: Cannot open gnuchess.book\n");
}


int parse(fd,mv,side)
FILE *fd;
unsigned short *mv;
short side;
{
int c,i,r1,r2,c1,c2;
char s[100];
  while ((c = getc(fd)) == ' ');
  i = 0; s[0] = c;
  while (c != ' ' && c != '\n' && c != EOF) s[++i] = c = getc(fd);
  s[++i] = '\0';
  if (c == EOF) return(-1);
  if (s[0] == '!' || i < 3)
    {
      while (c != '\n' && c != EOF) c = getc(fd);
      return(0);
    }
  if (s[4] == 'o')
    if (side == black) *mv = 0x3C3A; else *mv = 0x0402;
  else if (s[0] == 'o')
    if (side == black) *mv = 0x3C3E; else *mv = 0x0406;
  else
    {
      c1 = s[0] - 'a'; r1 = s[1] - '1';
      c2 = s[2] - 'a'; r2 = s[3] - '1';
      *mv = (locn[r1][c1]<<8) + locn[r2][c2];
    }
  return(1);
}


