bug-gnu-chess
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Memory leak in Chess 5.00, 5.03 related to InitHashTable()


From: Sven Coenye
Subject: Memory leak in Chess 5.00, 5.03 related to InitHashTable()
Date: Wed, 13 Mar 2002 22:55:38 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.8) Gecko/20020204

I would like to report a memory leak in GNU Chess 5.03 and below.

The InitHashTable function in file init.c can be called at will through the 'hashsize' command. However, InitHashTable() fails to free the two blocks of memory that were allocated for the pawn tables on the previous call. I have been able to verify this with memwatch and its logs report that 12288 bytes of memory are lost with each invocation of InitHashTable() (using an unmodified common.h).

There is a second problem in InitHashTable() as well. As written, the function attempts to free memory that was never allocated. This may become a partability issue on platforms where variables are not automatically zeroed out when they are created, or where free() doesn't work as advertised.

And finally, the PawnTab memory that was allocated last never gets freed when GNUChess exits. There are free() calls for allocated HashTab memory at the end of main(), but none for PawnTab.

I have attached patched versions of GNU Chess 5.03 main.c and init.c to address these issues.

Hoping this is useful,

Sven Coenye
/* GNU Chess 5.0 - init.c - initialization of variables code
   Copyright (c) 1999 Free Software Foundation, Inc.

   GNU Chess is based on the two research programs 
   Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.

   GNU Chess 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, or (at your option)
   any later version.

   GNU Chess 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 GNU Chess; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Contact Info: 
     address@hidden
     address@hidden, address@hidden, address@hidden
*/
/*
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "common.h"
#include "version.h"

#ifdef HAVE_READLINE_H
#include <history.h>
#elif HAVE_READLINE_READLINE_H
#include <readline/history.h>
#endif

void Initialize ()
/**************************************************************************
 *
 *  The main initialization driver.
 *
 **************************************************************************/
{
   InitLzArray ();
   InitBitPosArray ();
   InitMoveArray ();
   InitRay ();
   InitFromToRay (); 
   InitRankFileBit ();
   InitPassedPawnMask ();
   InitIsolaniMask ();
   InitSquarePawnMask ();
   InitBitCount ();
   InitRotAtak ();
   InitRandomMasks ();

   InitDistance ();
   InitVars ();
   InitHashCode ();
   InitHashTable ();
   CalcHashKey ();

#ifdef HAVE_LIBREADLINE
   using_history();
#endif
}


void InitFICS ()
{
   if (flags & XBOARD) {
     printf ("tellics shout Greetings from %s %s. Ready for a game.\n", 
PROGRAM, VERSION);
     printf ("tellics set 1 %s %s.\n",PROGRAM,VERSION);
   }

}

#define NBITS 16

void InitLzArray ()
/***************************************************************************
 *
 *  The lzArray is created.  This array is used when the position
 *  of the leading non-zero bit is required.  The convention used
 *  is that the leftmost bit is considered as position 0 and the
 *  rightmost bit position 63.
 *
 ***************************************************************************/
{
   int i, j, s, n;

   s = n = 1;
   for (i = 0; i < NBITS; i++)
   {
      for (j = s; j < s + n; j++)
         lzArray[j] = NBITS - 1 - i;
      s += n;
      n += n;
   }
}


void InitBitPosArray ()
/***************************************************************************
 *
 *  BitPosArray[i] returns the bitboard whose ith bit is set to 1 
 *  and every other bits 0.  This ought to be faster than doing
 *  shifting all the time (I think).  
 *  Also compute the NotBitPosArray = ~BitPosArray.
 *
 ***************************************************************************/
{
   BitBoard b;
   short i;

   b = (BitBoard) 1;  
   for (i = 63; i >= 0; i--, b <<= 1)
   {
      BitPosArray[i] = b;
      NotBitPosArray[i] = ~b;
   }
}
 


/*  Data used for generating MoveArray  */

static const short dir[8][8] =
{
  { 0, 0, 0, 0, 0, 0, 0, 0 },
  { 9, 11, 0, 0, 0, 0, 0, 0 },
  { -21, -19, -12, -8, 8, 12, 19, 21 },
  { -11, -9, 9, 11, 0, 0, 0, 0 },
  { -10, -1, 1, 10, 0, 0, 0, 0 },
  { -11, -10, -9, -1, 1, 9, 10, 11 },
  { -11, -10, -9, -1, 1, 9, 10, 11 },
  { -9, -11, 0, 0, 0, 0, 0, 0 }
};
static const short ndir[8] = 
{ 0, 2, 8, 4, 4, 8, 8, 2 };

static const short map[120] =
{
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1,  0,  1,  2,  3,  4,  5,  6,  7, -1,
  -1,  8,  9, 10, 11, 12, 13, 14, 15, -1,
  -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 
};


void InitMoveArray ()
/***************************************************************************
 * 
 *  Generate the move bitboards.  For e.g. the bitboard for all
 *  the moves of a knight on f3 is given by MoveArray[knight][21].
 *
 ***************************************************************************/
{
   short piece, fsq, tsq, f, t, n;
   BitBoard *b;

   for (piece = pawn; piece <= bpawn; piece++)
   {
      for (fsq = 0; fsq < 120; fsq++)
      {
         if ((f = map[fsq]) == -1) continue;
         b = &MoveArray[piece][f];
         *b = NULLBITBOARD;
         for (n = 0; n < ndir[piece]; n++)
         {
            tsq = fsq;
            do
            {
               tsq += dir[piece][n];
               if ((t = map[tsq]) != -1)
                  SETBIT (*b, t);
            } while (range[piece] && t != -1);
         }
      }
   }
}


void InitRay ()
/**************************************************************************
 *
 *  For each square, there are 8 rays.  The first 4 rays are diagonals 
 *  for the bishops and the next 4  are file/rank for the rooks.  
 *  The queen uses all 8 rays.
 *  These rays are used for move generation rather than MoveArray[].
 *  Also initialize the directions[][] array.  directions[f][t] returns
 *  the index into Ray[f] array allow us to find the ray in that direction.
 *
 **************************************************************************/
{
   short piece, fsq, tsq, f, t, n, ray;
   BitBoard *b;

   memset (directions, -1, sizeof (directions));
   for (fsq = 0; fsq < 120; fsq++)
   {
      if ((f = map[fsq]) == -1) continue;
      ray = -1;
      for (piece = bishop; piece <= rook; piece++)
      {
         for (n = 0; n < ndir[piece]; n++)
         {
            b = &Ray[f][++ray];
            *b = NULLBITBOARD;
            tsq = fsq;
            do
            {
               tsq += dir[piece][n];
               if ((t = map[tsq]) != -1)
               {
                  SETBIT (*b, t);
                  directions[f][t] = ray;
               }
            } while (t != -1);
         }
      }
   }
}


void InitFromToRay ()
/***************************************************************************
 *
 *  The FromToRay[b2][f6] gives the diagonal ray from c3 to f6;
 *  It also produces horizontal/vertical rays as well.   If no
 *  ray is possible, then a 0 is returned.
 *
 ***************************************************************************/
{
   short piece, fsq, tsq, f, t, n;
   BitBoard *b;

   memset (FromToRay, 0, sizeof (FromToRay));
   for (piece = bishop; piece <= rook; piece++)
   {
      for (fsq = 0; fsq < 120; fsq++)
      {
         if ((f = map[fsq]) == -1) continue;
         for (n = 0; n < ndir[piece]; n++)
         {
            tsq = fsq;
            t = map[tsq];
            do
            {
               b = &FromToRay[f][t];
               tsq += dir[piece][n];         
               if ((t = map[tsq]) != -1)
               {
                  SETBIT (FromToRay[f][t], t);
                  FromToRay[f][t] |= *b;
               }
            } while (t != -1);
         }
      }
   }
}


void InitRankFileBit ()
/***************************************************************************
 *
 *  RankBit[2] has all the bits on the 3rd rank 1 and others 0.
 *  FileBit[2] has all the bits on the 3rd file 1 and others 0.
 *
 ***************************************************************************/
{
   BitBoard b;
   short i;

   i = 8;
   b = (BitBoard) 255;
   while (i--)
   {
      RankBit[i] = b;
      b <<= 8;
   }
   
   i = 8;
   b = 0x0101010101010101ULL;
   while (i--)
   {
      FileBit[i] = b;
      b <<= 1;
   }
}


void InitRandomMasks ()
{
  mask_kr_trapped_w[0]=BitPosArray[H2];
  mask_kr_trapped_w[1]=BitPosArray[H1]|BitPosArray[H2];
  mask_kr_trapped_w[2]=BitPosArray[G1]|BitPosArray[H1]|BitPosArray[H2];
  mask_qr_trapped_w[0]=BitPosArray[A2];
  mask_qr_trapped_w[1]=BitPosArray[A1]|BitPosArray[A2];
  mask_qr_trapped_w[2]=BitPosArray[A1]|BitPosArray[B1]|BitPosArray[A2];
  mask_kr_trapped_b[0]=BitPosArray[H7];
  mask_kr_trapped_b[1]=BitPosArray[H8]|BitPosArray[H7];
  mask_kr_trapped_b[2]=BitPosArray[H8]|BitPosArray[G8]|BitPosArray[H7];
  mask_qr_trapped_b[0]=BitPosArray[A7];
  mask_qr_trapped_b[1]=BitPosArray[A8]|BitPosArray[A7];
  mask_qr_trapped_b[2]=BitPosArray[A8]|BitPosArray[B8]|BitPosArray[A7];
}

void InitPassedPawnMask ()
/**************************************************************************
 *
 *  The PassedPawnMask variable is used to determine if a pawn is passed.
 *  This mask is basically all 1's from the square in front of the pawn to
 *  the promotion square, also duplicated on both files besides the pawn
 *  file.  Other bits will be set to zero.
 *  E.g. PassedPawnMask[white][b3] = 1's in a4-c4-c8-a8 rect, 0 otherwise.
 *
 **************************************************************************/
{
   unsigned short sq;

   memset (PassedPawnMask, 0, sizeof (PassedPawnMask));

   /*  Do for white pawns first */
   for (sq = 0; sq < 64; sq++)
   {
      PassedPawnMask[white][sq] = Ray[sq][7];
      if (ROW(sq) != 0)
         PassedPawnMask[white][sq] |= Ray[sq-1][7];
      if (ROW(sq) != 7)
         PassedPawnMask[white][sq] |= Ray[sq+1][7];
   }

   /*  Do for black pawns */
   for (sq = 0; sq < 64; sq++)
   {
      PassedPawnMask[black][sq] = Ray[sq][4];
      if (ROW(sq) != 0)
         PassedPawnMask[black][sq] |= Ray[sq-1][4];
      if (ROW(sq) != 7)
         PassedPawnMask[black][sq] |= Ray[sq+1][4];
   }
}


void InitIsolaniMask ()
/**************************************************************************
 *
 *  The IsolaniMask variable is used to determine if a pawn is an isolani.
 *  This mask is basically all 1's on files beside the file the pawn is on.
 *  Other bits will be set to zero.
 *  E.g. IsolaniMask[d-file] = 1's in c-file & e-file, 0 otherwise.
 *  IMPORTANT:!!!!
 *  Make sure this routine is called AFTER InitRankFileBit().
 *
 **************************************************************************/
{
   short i;

   IsolaniMask[0] = FileBit[1];
   IsolaniMask[7] = FileBit[6];
   for (i = 1; i <= 6; i++)
      IsolaniMask[i] = FileBit[i-1] | FileBit[i+1];
      
}


void InitSquarePawnMask ()
/**************************************************************************
 *
 *  The SquarePawnMask is used to determine if a king is in the square of
 *  the passed pawn and is able to prevent it from queening.  
 *  Caveat:  Pawns on 2nd rank have the same mask as pawns on the 3rd rank
 *  as they can advance 2 squares.
 *
 **************************************************************************/
{
   unsigned short sq;
   short len, i, j;

   memset (SquarePawnMask, 0, sizeof (PassedPawnMask));
   for (sq = 0; sq < 64; sq++)
   {
      /*  White mask  */
      len = 7 - RANK (sq);
      i = MAX (sq & 56, sq - len);
      j = MIN (sq | 7, sq + len);
      while (i <= j)
      {
         SquarePawnMask[white][sq] |= (BitPosArray[i] | FromToRay[i][i|56]);
         i++;
      }

      /*  Black mask  */
      len = RANK (sq);
      i = MAX (sq & 56, sq - len);
      j = MIN (sq | 7, sq + len);
      while (i <= j)
      {
         SquarePawnMask[black][sq] |= (BitPosArray[i] | FromToRay[i][i&7]);
         i++;
      }
   }

   /*  For pawns on 2nd rank, they have same mask as pawns on 3rd rank */
   for (sq = A2; sq <= H2; sq++)
      SquarePawnMask[white][sq] = SquarePawnMask[white][sq+8];
   for (sq = A7; sq <= H7; sq++)
      SquarePawnMask[black][sq] = SquarePawnMask[black][sq-8];
}

 
void InitBitCount ()
/**************************************************************************
 *
 *  The BitCount array returns the no. of bits present in the 16 bit
 *  input argument.  This is use for counting the number of bits set
 *  in a BitBoard (e.g. for mobility count).
 *
 **************************************************************************/
{
   int i, j, n;
 
   BitCount[0] = 0;
   BitCount[1] = 1; 
   i = 1;
   for (n = 2; n <= 16; n++)
   {
      i <<= 1;
      for (j = i; j <= i + (i-1); j++)  
         BitCount[j] = 1 + BitCount[j - i]; 
   }
} 


void InitRotAtak ()
/**************************************************************************
 *
 *  The attack tables for a normal chessboard and the rotated chess board
 *  are calculated here.
 *
 **************************************************************************/
{
   short sq, map, sq1, sq2;
   short cmap[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
   short rot1[8] = { A1, A2, A3, A4, A5, A6, A7, A8 };
   short rot2[8] = { A1, B2, C3, D4, E5, F6, G7, H8 };
   short rot3[8] = { A8, B7, C6, D5, E4, F3, G2, H1 };
   
   for (sq = A1; sq <= H1; sq++)
   {
      for (map = 0; map < 256; map++)
      {
         Rook00Atak[sq][map] = 0;
         Rook90Atak[rot1[sq]][map] = 0;
         Bishop45Atak[rot2[sq]][map] = 0;
         Bishop315Atak[rot3[sq]][map] = 0;
            sq1 = sq2 = sq;
            while (sq1 > 0)
            {
               if (cmap[--sq1] & map)
                  break;
            }
            while (sq2 < 7)
            {
               if (cmap[++sq2] & map)
                  break;
            }
            Rook00Atak[sq][map] = 
                FromToRay[sq][sq1] | FromToRay[sq][sq2];
            Rook90Atak[rot1[sq]][map] =
                FromToRay[rot1[sq]][rot1[sq1]] | 
                FromToRay[rot1[sq]][rot1[sq2]];
            Bishop45Atak[rot2[sq]][map] =
                FromToRay[rot2[sq]][rot2[sq1]] |
                FromToRay[rot2[sq]][rot2[sq2]];
            Bishop315Atak[rot3[sq]][map] =
                FromToRay[rot3[sq]][rot3[sq1]] |
                FromToRay[rot3[sq]][rot3[sq2]];
      }
   } 

   for (map = 0; map < 256; map++)
   {
      for (sq = A2; sq <= H8; sq++)
      {
         Rook00Atak[sq][map] = Rook00Atak[sq-8][map] >> 8;
      }

      for (sq1 = B_FILE; sq1 <= H_FILE; sq1++)
      {
         for (sq2 = 0; sq2 < 64; sq2+=8)
         {
            sq = sq2 + sq1;
            Rook90Atak[sq][map] = Rook90Atak[sq-1][map] >> 1;
         }
      }

      for (sq1 = B1, sq2 = H7; sq1 <= H1; sq1++, sq2-=8)
      {
         for (sq = sq1; sq <= sq2; sq += 9)
         {
            Bishop45Atak[sq][map] = Bishop45Atak[sq+8][map] << 8;
         }
      }
      for (sq1 = A2, sq2 = G8; sq1 <= A8; sq1+=8, sq2--)
      {
         for (sq = sq1; sq <= sq2; sq += 9)
         {
            Bishop45Atak[sq][map] = 
                (Bishop45Atak[sq+1][map] & NotBitPosArray[sq1-8]) << 1;
         }
      }

      for (sq1 = H2, sq2 = B8; sq1 <= H8; sq1+=8, sq2++)
      {
         for (sq = sq1; sq <= sq2; sq += 7)
         {
            Bishop315Atak[sq][map] = Bishop315Atak[sq-8][map] >> 8;
         }
      }
      for (sq1 = G1, sq2 = A7; sq1 >= A1; sq1--, sq2-=8)
      {
         for (sq = sq1; sq <= sq2; sq += 7)
         {
            Bishop315Atak[sq][map] = 
                (Bishop315Atak[sq+1][map] & NotBitPosArray[sq2+8]) << 1;
         }
      }
   }
}


void InitDistance ()
/**************************************************************************
 *
 *  There are two arrays dealing with distances.  The distance[s1][s2]
 *  array gives the minimum number of moves a king takes to get from s1
 *  to s2.  The taxicab[s1][s2] array is the taxicab distance.  Example:
 *  distance[a1][b3] = 2;  taxicab[a1[b3] = 3;
 *
 *************************************************************************/
{
   register short f, t, j;
   short d1, d2;

   for (f = 0; f < 64; f++)
     for (t = 0; t < 8; t++)
       DistMap[f][t] = 0ull;


   for (f = 0; f < 64; f++)
      for (t = f; t < 64; t++)
      {
         d1 = (t & 0x07) - (f & 0x07);
         if (d1 < 0) d1 = -d1;
         d2 = (t >> 3) - (f >> 3);
         if (d2 < 0) d2 = -d2;
         distance[f][t] = MAX (d1, d2);
         distance[t][f] = MAX (d1, d2);
         taxicab[f][t] = d1 + d2;
         taxicab[t][f] = d1 + d2;
      }

   for (f = 0; f < 64; f++)
     for (t = 0; t < 64; t++)
         DistMap[f][distance[t][f]] |= BitPosArray[t];

   for (f = 0; f < 64; f++)
     for (t = 0; t < 8; t++)
       for (j = 0; j < t; j++)
         DistMap[f][t] |= DistMap[f][j];
}


void InitVars ()
/***************************************************************************
 *
 *  Initialize various variables, especially for new game.
 *
 ***************************************************************************/
{
   int i;

   /* Initialize board */
   memset (&board, 0, sizeof (board));
   for (i = 8; i < 16; i++)
      SETBIT (board.b[white][pawn], i);
   SETBIT (board.b[white][rook], 0);
   SETBIT (board.b[white][knight], 1);
   SETBIT (board.b[white][bishop], 2);
   SETBIT (board.b[white][queen], 3);
   SETBIT (board.b[white][king], 4);
   SETBIT (board.b[white][bishop], 5);
   SETBIT (board.b[white][knight], 6);
   SETBIT (board.b[white][rook], 7);
   for (i = 48; i < 56; i++)
      SETBIT (board.b[black][pawn], i);
   SETBIT (board.b[black][rook], 56);
   SETBIT (board.b[black][knight], 57);
   SETBIT (board.b[black][bishop], 58);
   SETBIT (board.b[black][queen], 59);
   SETBIT (board.b[black][king], 60);
   SETBIT (board.b[black][bishop], 61);
   SETBIT (board.b[black][knight], 62);
   SETBIT (board.b[black][rook], 63);

   SETBIT (stonewall[white], D4); /* SMC */
   SETBIT (stonewall[white], E3); /* SMC */
   SETBIT (stonewall[white], F4); /* SMC */

   SETBIT (stonewall[black], D5); /* SMC */
   SETBIT (stonewall[black], E6); /* SMC */
   SETBIT (stonewall[black], F5); /* SMC */

   SETBIT (rings[0], D4);
   SETBIT (rings[0], D5);
   SETBIT (rings[0], E4);
   SETBIT (rings[0], E5);
   SETBIT (rings[1], C3);
   SETBIT (rings[1], D3);
   SETBIT (rings[1], E3);
   SETBIT (rings[1], F3);
   SETBIT (rings[1], C4);
   SETBIT (rings[1], F4);
   SETBIT (rings[1], C5);
   SETBIT (rings[1], F5);
   SETBIT (rings[1], C6);
   SETBIT (rings[1], D6);
   SETBIT (rings[1], E6);
   SETBIT (rings[1], F6);
   SETBIT (rings[2], B2);
   SETBIT (rings[2], C2);
   SETBIT (rings[2], D2);
   SETBIT (rings[2], E2);
   SETBIT (rings[2], F2);
   SETBIT (rings[2], G2);
   SETBIT (rings[2], B3);
   SETBIT (rings[2], G3);
   SETBIT (rings[2], B4);
   SETBIT (rings[2], G4);
   SETBIT (rings[2], B5);
   SETBIT (rings[2], G5);
   SETBIT (rings[2], B6);
   SETBIT (rings[2], G6);
   SETBIT (rings[2], B7);
   SETBIT (rings[2], C7);
   SETBIT (rings[2], D7);
   SETBIT (rings[2], E7);
   SETBIT (rings[2], F7);
   SETBIT (rings[2], G7);
   SETBIT (rings[3], A1);
   SETBIT (rings[3], B1);
   SETBIT (rings[3], C1);
   SETBIT (rings[3], D1);
   SETBIT (rings[3], E1);
   SETBIT (rings[3], F1);
   SETBIT (rings[3], G1);
   SETBIT (rings[3], H1);
   SETBIT (rings[3], A2);
   SETBIT (rings[3], H2);
   SETBIT (rings[3], A3);
   SETBIT (rings[3], H3);
   SETBIT (rings[3], A4);
   SETBIT (rings[3], H4);
   SETBIT (rings[3], A5);
   SETBIT (rings[3], H5);
   SETBIT (rings[3], A6);
   SETBIT (rings[3], H6);
   SETBIT (rings[3], A7);
   SETBIT (rings[3], H7);
   SETBIT (rings[3], A8);
   SETBIT (rings[3], B8);
   SETBIT (rings[3], C8);
   SETBIT (rings[3], D8);
   SETBIT (rings[3], E8);
   SETBIT (rings[3], F8);
   SETBIT (rings[3], G8);
   SETBIT (rings[3], H8);

   boardhalf[white] = RankBit[0]|RankBit[1]|RankBit[2]|RankBit[3];
   boardhalf[black] = RankBit[4]|RankBit[5]|RankBit[6]|RankBit[7];
   boardside[ks] = FileBit[4]|FileBit[5]|FileBit[6]|FileBit[7];
   boardside[qs] = FileBit[0]|FileBit[1]|FileBit[2]|FileBit[3];

   board.flag |= (WCASTLE | BCASTLE);
   board.side = white;
   board.ep = -1;
   board.king[white] = E1;
   board.king[black] = E8;
   GameCnt = -1;
   Game50 = 0;
   computer = black;
   CalcHashKey ();
   Game[0].hashkey = HashKey;
   board.pmaterial[white] = board.pmaterial[black] =
      2*ValueR + 2*ValueN + 2*ValueB + ValueQ;
   board.material[white] = board.material[black] =
      board.pmaterial[white] + 8*ValueP;

   UpdateFriends ();
   UpdateCBoard ();
   UpdateMvboard ();

   for (i = A1; i <= H8; i++)
   {
      if (cboard[i])
      {
         SETBIT (board.blockerr90, r90[i]);
         SETBIT (board.blockerr45, r45[i]);
         SETBIT (board.blockerr315, r315[i]);
      }
   }

   /* TreePtr[0] is practically unused.  TreePtr[1] points to the
    * base of the tree.
    */
   TreePtr[0] = TreePtr[1] = Tree;

   /* Initialize some of the game flags */
   SET (flags, USEHASH);
   SET (flags, USENULL);
   SearchTime = 5;
   SearchDepth = 0;
   board.castled[white] = board.castled[black] = false;
   phase = PHASE;

/*  Calculate the ttable hashmask & pawntable hashmask */
   i = HASHSLOTS;
   TTHashMask = 0;
   while ((i>>=1) > 0)
   {
      TTHashMask <<= 1;
      TTHashMask |= 1;
   }
   HashSize = TTHashMask + 1; 
   i = PAWNSLOTS;
   PHashMask = 0;
   while ((i>>=1) > 0)
   {
      PHashMask <<= 1;
      PHashMask |= 1;
   }

   DebugPly = 99;
   DebugDepth = 0;
   DebugNode = 999999999;
   signal (SIGINT, EndSearch);

   nmovesfrombook = 0;
}


void InitHashCode ()
/***************************************************************************
 *
 *  The hash code for the various pieces standing on the various squares
 *  are initialized here.  When a particular piece is move from square A
 *  to square B, the current hashkey is XORed against the hash code for
 *  the A square and B square to give the new hashkey.
 *
 ***************************************************************************/
{
   short color, piece, sq;

   for (color = white; color <= black; color++)
   {
      for (piece = pawn; piece <= king; piece++)
      {
         for (sq = 0; sq < 64; sq++)
         {
            hashcode[color][piece][sq] = Rand64 ();
         }
      }
   }
   for (sq = 0; sq < 64; sq++)
      ephash[sq] = Rand64 ();
   WKCastlehash = Rand64 ();
   WQCastlehash = Rand64 ();
   BKCastlehash = Rand64 ();
   BQCastlehash = Rand64 ();
   Sidehash = Rand64 ();
}

void InitHashTable ()
/****************************************************************************
 *
 *  Allocate memory for our transposition tables.  By default, the
 *  transposition table will have 16K entries; 8K for each color.
 *  Add code to allocated memory for pawn table as well.
 *
 ****************************************************************************/
{
 
   static int prev_hash_alloc = false;
   static int prev_pawn_alloc = false;
   unsigned int size;
 
   if (prev_hash_alloc) {
         free (HashTab[0]);
     free (HashTab[1]);
   }
   HashTab[0] = (HashSlot *) calloc (HashSize, sizeof (HashSlot));
   HashTab[1] = (HashSlot *) calloc (HashSize, sizeof (HashSlot));
   if (HashTab[0] == NULL || HashTab[1] == NULL)
      printf ("Not enough memory for transposition table\n");
   else
   {
      prev_hash_alloc = true;
      size = (HashSize * 2 * sizeof (HashSlot)) >> 10;
      if (!(flags & XBOARD))
        printf ("Transposition table:  Entries=%dK Size=%dK\n", 
                HashSize>>10, size);
   }

   if (prev_pawn_alloc) {
     free (PawnTab[0]);
         free (PawnTab[1]);
   }
   PawnTab[0] = (PawnSlot *) calloc (PAWNSLOTS, sizeof (PawnSlot));
   PawnTab[1] = (PawnSlot *) calloc (PAWNSLOTS, sizeof (PawnSlot));
   if (PawnTab[0] == NULL || PawnTab[1] == NULL)
      printf ("Not enough memory for pawn table\n");
   else
   {
          prev_pawn_alloc = true;
      size = (PAWNSLOTS * 2 * sizeof (PawnSlot)) >> 10;
      if (!(flags & XBOARD))
        printf ("Pawn hash table: Entries=%dK Size=%dK\n",
                PAWNSLOTS >> 10, size);
   }
   return;
}


void NewPosition ()
/****************************************************************************
 *
 *  Reset some flags for a new game/position.
 *
 ****************************************************************************/
{
   CLEAR (flags, ENDED);
   Game50 = 0;
   GameCnt = -1;
   Game[0].hashkey = HashKey;
   TTClear ();
   PTClear ();
   nmovesfrombook = 0;
   ExchCnt[white] = ExchCnt[black] = 0;
}
/* GNU Chess 5.0 - main.c - entry point
   Copyright (c) 1999 Free Software Foundation, Inc.

   GNU Chess is based on the two research programs 
   Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.

   GNU Chess 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, or (at your option)
   any later version.

   GNU Chess 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 GNU Chess; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Contact Info: 
     address@hidden
     address@hidden, address@hidden, address@hidden
*/
/*
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
#include "book.h"
#include <time.h>
#ifdef UNIVERSAL
#include "univ.h"
#include <signal.h>
#endif

short distance[64][64];
short taxicab[64][64];
short lzArray[65536];
BitBoard DistMap[64][8];
BitBoard BitPosArray[64];
BitBoard NotBitPosArray[64];
BitBoard MoveArray[8][64];
BitBoard Ray[64][8];
BitBoard FromToRay[64][64];
BitBoard RankBit[8];
BitBoard FileBit[8];
BitBoard Ataks[2][7];
BitBoard PassedPawnMask[2][64];
BitBoard IsolaniMask[8];
BitBoard SquarePawnMask[2][64];
BitBoard Rook00Atak[64][256];
BitBoard Rook90Atak[64][256];
BitBoard Bishop45Atak[64][256];
BitBoard Bishop315Atak[64][256];
BitBoard pinned;
BitBoard rings[4];
BitBoard stonewall[2];
BitBoard pieces[2];
BitBoard mask_kr_trapped_w[3];
BitBoard mask_kr_trapped_b[3];
BitBoard mask_qr_trapped_w[3];
BitBoard mask_qr_trapped_b[3];
BitBoard boardhalf[2];
BitBoard boardside[2];
short directions[64][64];
short BitCount[65536];
leaf Tree[MAXTREEDEPTH];
leaf *TreePtr[MAXPLYDEPTH];
int RootPV;
GameRec Game[MAXGAMEDEPTH];
short GameCnt;
short computer;
unsigned int flags;
short cboard[64];
short Mvboard[64];
Board board;
HashType hashcode[2][7][64];
HashType ephash[64];
HashType WKCastlehash;
HashType WQCastlehash;
HashType BKCastlehash;
HashType BQCastlehash;
HashType Sidehash;
HashType HashKey;
HashType PawnHashKey;
HashSlot *HashTab[2];
PawnSlot *PawnTab[2];
short Idepth;
short SxDec;
short Game50;
int lazyscore[2];
int maxposnscore[2];
int rootscore;
int lastrootscore;
unsigned long GenCnt;
unsigned long NodeCnt;
unsigned long QuiesCnt;
unsigned long EvalCnt;
unsigned long EvalCall;
unsigned long ChkExtCnt;
unsigned long OneRepCnt;
unsigned long RcpExtCnt;
unsigned long PawnExtCnt;
unsigned long HorzExtCnt;
unsigned long ThrtExtCnt;
unsigned long KingExtCnt;
unsigned long NullCutCnt;
unsigned long FutlCutCnt;
unsigned long RazrCutCnt;
unsigned long TotalGetHashCnt;
unsigned long GoodGetHashCnt;
unsigned long TotalPutHashCnt;
unsigned long CollHashCnt;
unsigned long TotalPawnHashCnt;
unsigned long GoodPawnHashCnt;
unsigned long RepeatCnt;
unsigned HashSize;
unsigned long TTHashMask;
unsigned long PHashMask;
char SANmv[10];
unsigned long history[2][4096];
int killer1[MAXPLYDEPTH];
int killer2[MAXPLYDEPTH];
short ChkCnt[MAXPLYDEPTH];
short ThrtCnt[MAXPLYDEPTH];
char id[32];
char solution[64];
double et;
float SearchTime;
short SearchDepth;
short MoveLimit[2];
float TimeLimit[2];
short TCMove;
short TCinc;
float TCTime;
short castled[2];
short hunged[2];
short phase;
int Hashmv[MAXPLYDEPTH];
short DebugPly;
short DebugDepth;
long DebugNode;
int Debugmv[MAXPLYDEPTH];
short Debugmvl;
short Debugline;
short RootPieces;
short RootPawns;
short RootMaterial;
short RootAlpha;
short RootBeta;
short pickphase[MAXPLYDEPTH];
short InChk[MAXPLYDEPTH];
short KingThrt[2][MAXPLYDEPTH];
short threatmv;
short threatply;
short KingSafety[2];
short pscore[64];
short bookmode;
short bookfirstlast;
FILE *ofp;
short myrating, opprating, suddendeath, TCionc;
char name[50];
short computerplays;            /* Side computer is playing */
short wasbookmove;              /* True if last move was book move */
int nmovesfrombook;             /* Number of moves since last book move */
int newpos, existpos;           /* For book statistics */
float maxtime;          /* Max time for the next searched move */
short n;                /* Last mobility returned by CTL */
short ExchCnt[2];       /* How many exchanges? */
short bookloaded = 0;   /* Is the book loaded already into memory? */

short slider[8] = { 0, 0, 0, 1, 1, 1, 0, 0 };
short Value[7] = { 0, ValueP, ValueN, ValueB, ValueR, ValueQ, ValueK};
short range[8] = { 0, 0, 0, 1, 1, 1, 0, 0 };
short ptype[2] = { pawn, bpawn };
char algbr[64][3] =
{ "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",
  "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
  "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",
  "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",
  "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",
  "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",
  "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
  "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8" 
};
char algbrfile[9] = "abcdefgh";
char algbrrank[9] = "12345678";
  
char notation[8] = { " PNBRQK" };
char lnotation[8] = { " pnbrqk" };

short Shift00[64] =
{ 56, 56, 56, 56, 56, 56, 56, 56,
  48, 48, 48, 48, 48, 48, 48, 48,
  40, 40, 40, 40, 40, 40, 40, 40,
  32, 32, 32, 32, 32, 32, 32, 32,
  24, 24, 24, 24, 24, 24, 24, 24,
  16, 16, 16, 16, 16, 16, 16, 16,
   8,  8,  8,  8,  8,  8,  8,  8,
   0,  0,  0,  0,  0,  0,  0,  0
};

short r90[64] =
{ A8, A7, A6, A5, A4, A3, A2, A1,
  B8, B7, B6, B5, B4, B3, B2, B1,
  C8, C7, C6, C5, C4, C3, C2, C1,
  D8, D7, D6, D5, D4, D3, D2, D1,
  E8, E7, E6, E5, E4, E3, E2, E1,
  F8, F7, F6, F5, F4, F3, F2, F1,
  G8, G7, G6, G5, G4, G3, G2, G1,
  H8, H7, H6, H5, H4, H3, H2, H1 };

short Shift90[64] =
{ 0, 8, 16, 24, 32, 40, 48, 56,
  0, 8, 16, 24, 32, 40, 48, 56,
  0, 8, 16, 24, 32, 40, 48, 56,
  0, 8, 16, 24, 32, 40, 48, 56,
  0, 8, 16, 24, 32, 40, 48, 56,
  0, 8, 16, 24, 32, 40, 48, 56,
  0, 8, 16, 24, 32, 40, 48, 56,
  0, 8, 16, 24, 32, 40, 48, 56
};

short r45[64] =
{ E4, F3, H2, C2, G1, D1, B1, A1,
  E5, F4, G3, A3, D2, H1, E1, C1,
  D6, F5, G4, H3, B3, E2, A2, F1, 
  B7, E6, G5, H4, A4, C3, F2, B2,
  G7, C7, F6, H5, A5, B4, D3, G2, 
  C8, H7, D7, G6, A6, B5, C4, E3, 
  F8, D8, A8, E7, H6, B6, C5, D4, 
  H8, G8, E8, B8, F7, A7, C6, D5 };

short Shift45[64] =
{ 28, 36, 43, 49, 54, 58, 61, 63,
  21, 28, 36, 43, 49, 54, 58, 61,
  15, 21, 28, 36, 43, 49, 54, 58,
  10, 15, 21, 28, 36, 43, 49, 54,
   6, 10, 15, 21, 28, 36, 43, 49,
   3,  6, 10, 15, 21, 28, 36, 43,
   1,  3,  6, 10, 15, 21, 28, 36,
   0,  1,  3,  6, 10, 15, 21, 28 };

short Mask45[64] =
{ 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01,
  0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 
  0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 
  0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 
  0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 
  0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 
  0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 
  0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };

short r315[64] =
{ A1, C1, F1, B2, G2, E3, D4, D5,
  B1, E1, A2, F2, D3, C4, C5, C6,
  D1, H1, E2, C3, B4, B5, B6, A7,
  G1, D2, B3, A4, A5, A6, H6, F7,
  C2, A3, H3, H4, H5, G6, E7, B8,
  H2, G3, G4, G5, F6, D7, A8, E8,
  F3, F4, F5, E6, C7, H7, D8, G8,
  E4, E5, D6, B7, G7, C8, F8, H8 };

short Shift315[64] =
{ 63, 61, 58, 54, 49, 43, 36, 28,
  61, 58, 54, 49, 43, 36, 28, 21,
  58, 54, 49, 43, 36, 28, 21, 15,
  54, 49, 43, 36, 28, 21, 15, 10,
  49, 43, 36, 28, 21, 15, 10,  6,
  43, 36, 28, 21, 15, 10,  6,  3,
  36, 28, 21, 15, 10,  6,  3,  1,
  28, 21, 15, 10,  6,  3,  1,  0 };

short Mask315[64] =
{ 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF,
  0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F,
  0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F,
  0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F,
  0x1F, 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
  0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07,
  0x7F, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03,
  0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };

int main (int argc, char *argv[])
{
  int compilebook = 0;
  time_t now; 
  int i;

#ifdef UNIVERSAL
  char buf[10];
#endif

  /* Initialize random number generator */
  time(&now);
  srand((unsigned) now);
  
  /* initialize control flags */
  flags = 0ull;

  /* output for thinking */
  ofp = stdout;

  if (argc > 1) {
    for (i = 0; i < argc; i++) {
      if (strcmp(argv[i],"xboard") == 0) {
        SET (flags, XBOARD);
      } else if (strcmp(argv[i],"post") == 0) {
        SET (flags, POST);
      } else if (strcmp(argv[i],"compile") == 0)
        compilebook++;
    }
  }
  
  if (!(flags & XBOARD))
    SET (flags, POST);
  ShowVersion ();
  Initialize ();

  if (argc > 1) {
    for (i = 0; i < argc; i++) {
      if (strcmp(argv[i],"xboard") == 0) {
        SET (flags, XBOARD);
      } else if (strcmp(argv[i],"post") == 0) {
        SET (flags, POST);
      } 
    }
  }

  bookmode = BOOKPREFER;
  bookfirstlast = 3;

   while (!(flags & QUIT))
   {
      InputCmd (); 
      if ((flags & THINK) && !(flags & MANUAL) && !(flags & ENDED)) {
#ifdef UNIVERSAL
      if (flags & UNIV) {
        signal(SIGALRM,SIG_IGN);
      }
#endif
        
      if (!(flags & XBOARD)) printf("Thinking...\n");
      Iterate ();
#ifdef UNIVERSAL
      if (flags & UNIV /* && !(flags & SELF) */) {
          if (Game[GameCnt].move & PROMOTION) {
            sprintf(buf,"M%s-%s/%c\r\n",
                 algbr[FROMSQ(Game[GameCnt].move)],
                 algbr[TOSQ(Game[GameCnt].move)],
                 notation[PROMOTEPIECE(Game[GameCnt].move)]);
            printf("Sent M%s-%s/%c to Universal\n",
                 algbr[FROMSQ(Game[GameCnt].move)],
                 algbr[TOSQ(Game[GameCnt].move)],
                 notation[PROMOTEPIECE(Game[GameCnt].move)]);
          } else {
            sprintf(buf,"M%s-%s\r\n",
                 algbr[FROMSQ(Game[GameCnt].move)],
                 algbr[TOSQ(Game[GameCnt].move)]);
            printf("Sent M%s-%s to Universal\n",
                 algbr[FROMSQ(Game[GameCnt].move)],
                 algbr[TOSQ(Game[GameCnt].move)]);
          }
          univ_write(buf);
          signal(SIGALRM, univ_check);
          alarm(1);
      }
#endif
      }
   }

   /*  Some cleaning up  */
   free (HashTab[0]);
   free (HashTab[1]);
   free (PawnTab[0]);
   free (PawnTab[1]);
   return (0);
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]