home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / GNU Chess 3.0.3 / src / gnuchess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-26  |  73.4 KB  |  3,260 lines  |  [TEXT/CWIE]

  1. /*
  2.   C source for GNU CHESS
  3.  
  4.   Modified : 20-3-91 Airy ANDRE.
  5.  
  6.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  7.   Copyright (c) 1988, 1989, 1990  John Stanback
  8.   Copyright (c) 1991 Airy AndrĂ©
  9.  
  10.   This file is part of CHESS.
  11.  
  12.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  13.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  14.   the consequences of using it or for whether it serves any particular
  15.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  16.   General Public License for full details.
  17.  
  18.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  19.   only under the conditions described in the CHESS General Public License. A
  20.   copy of this license is supposed to have been given to you along with
  21.   CHESS so you can know your rights and responsibilities.  It should be in a
  22.   file named COPYING.  Among other things, the copyright notice and this
  23.   notice must be preserved on all copies.
  24. */
  25.  
  26. /* This file is the original "gnuchess.c" modified to allow a Mac interface
  27.    and a few new options.
  28.    It is for Mac version ONLY
  29.    --------------------------
  30. */
  31.  
  32. #include <stdio.h>
  33.  
  34.  
  35. #include <ctype.h>
  36.  
  37. /*
  38.   ttblsz must be a power of 2.
  39.   Setting ttblsz 0 removes the transposition tables.
  40. */
  41. #include <time.h>
  42. #define ttblsz 65536
  43. #define huge
  44.  
  45. extern int abs ();
  46. extern int atoi ();
  47.  
  48. extern void *memset(void *, int, size_t);
  49.  
  50. #include "gnuchess.h"
  51.  
  52. #define bpawn 7
  53. #define valueP 100
  54. #define valueN 350
  55. #define valueB 355
  56. #define valueR 550
  57. #define valueQ 1100
  58. #define valueK 1200
  59. #define ctlP 0x4000
  60. #define ctlN 0x2800
  61. #define ctlB 0x1800
  62. #define ctlR 0x0400
  63. #define ctlQ 0x0200
  64. #define ctlK 0x0100
  65. #define ctlBQ 0x1200
  66. #define ctlRQ 0x0600
  67. #define ctlNN 0x2000
  68.  
  69.  
  70. #if ttblsz
  71. #define truescore 0x0001
  72. #define lowerbound 0x0002
  73. #define upperbound 0x0004
  74. #define kingcastle 0x0008
  75. #define queencastle 0x0010
  76.  
  77. struct hashval
  78. {
  79.   unsigned long key,bd;
  80. };
  81.  
  82. struct hashentry
  83. {
  84.   unsigned long hashbd;
  85.   unsigned short mv;
  86.   unsigned char flags, depth;    /* char saves some space */
  87.   short score;
  88. #ifdef HASHTEST
  89.   unsigned char bd[32];
  90. #endif /* HASHTEST */
  91. };
  92.  
  93. #ifdef HASHFILE
  94. /*
  95.   persistent transposition table.
  96.   The size must be a power of 2. If you change the size,
  97.   be sure to run gnuchess -t before anything else.
  98. */
  99. #define frehash 6
  100. #define filesz 131072
  101. struct fileentry
  102. {
  103.   unsigned char bd[32];
  104.   unsigned char f, t, flags, depth, sh, sl;
  105. };
  106. /*
  107.   In a networked enviroment gnuchess might be compiled on different
  108.   hosts with different random number generators, that is not acceptable
  109.   if they are going to share the same transposition table.
  110. */
  111. unsigned long int next = 1;
  112.  
  113. unsigned int rand()
  114. {
  115.   next *= 1103515245;
  116.   next += 12345;
  117.   return ((unsigned int) (next >> 16) & 0xFFFF);
  118. }
  119.  
  120. void srand (seed)
  121.      unsigned int seed;
  122. {
  123.   next = seed;
  124. }
  125.  
  126. #endif /* HASHFILE */
  127.  
  128. static unsigned long hashkey, hashbd;
  129. static struct hashval *hashcode[2][7];
  130. static struct hashentry huge *ttable[2];
  131. #endif /* ttblsz */
  132.  
  133. int hashfile;
  134. struct leaf *Tree, *root;
  135. short TrPnt[maxdepth];
  136. short PieceList[2][16], PawnCnt[2][8];
  137. short castld[2], Mvboard[64];
  138. short c1, c2, *atk1, *atk2, *PC1, *PC2, atak[2][64];
  139. short mate, post, opponent, computer, Sdepth, Awindow, Bwindow, dither;
  140. long ResponseTime, ExtraTime, Level[2], et, et0, ft;
  141. unsigned long time0;
  142. long NodeCnt, ETnodes, EvalNodes, HashCnt, FHashCnt, HashCol;
  143. short quit, reverse, bothsides, hashflag, InChk, player, force, easy, beep;
  144. short timeout, xwndw, rehash;
  145. struct GameRec *GameList;
  146. short GameCnt, Game50, epsquare, lpost, rcptr, contempt;
  147. short MaxSearchDepth;
  148. struct BookEntry *Book;
  149. struct TimeControlRec TimeControl;
  150. short TCflag[2], TCmoves[2], TCminutes[2], OperatorTime[2];
  151.  
  152. short donotplay;
  153.  
  154. #ifdef ttblsz
  155. static unsigned long real_ttblsz = ttblsz;
  156. #endif /* ttblsz */
  157.  
  158. const short otherside[3] =
  159. {1, 0, 2};
  160. unsigned short hint, PrVar[maxdepth];
  161.  
  162. static short Pindex[64], svalue[64];
  163. static short PieceCnt[2];
  164. static short mtl[2], pmtl[2], emtl[2], hung[2];
  165. static short EnemyKing;
  166. static short wking, bking, FROMsquare, TOsquare, Zscore, zwndw, slk;
  167. static short INCscore;
  168. static short HasPawn[2], HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
  169. static short ChkFlag[maxdepth], CptrFlag[maxdepth], PawnThreat[maxdepth];
  170. static short Pscore[maxdepth], Tscore[maxdepth];
  171. static const short qrook[3] =
  172. {0, 56, 0};
  173. static const short krook[3] =
  174. {7, 63, 0};
  175. static const short kingP[3] =
  176. {4, 60, 0};
  177. static const short rank7[3] =
  178. {6, 1, 0};
  179. static const short sweep[7] =
  180. {false, false, false, true, true, true, false};
  181. static unsigned short *killr0, *killr1, *killr2;
  182. static unsigned short *killr3;
  183. static unsigned short PV, Swag0, Swag1, Swag2, Swag3, Swag4;
  184. static unsigned char *history;
  185.  
  186. static short *Mwpawn, *Mbpawn, *Mknight[2], *Mbishop[2];
  187. static short *Mking[2], *Kfield[2];
  188. static const short value[7] =
  189. {0, valueP, valueN, valueB, valueR, valueQ, valueK};
  190. static const short control[7] =
  191. {0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
  192. static const short PassedPawn0[8] =
  193. {0, 60, 80, 120, 200, 360, 600, 800};
  194. static const short PassedPawn1[8] =
  195. {0, 30, 40, 60, 100, 180, 300, 800};
  196. static const short PassedPawn2[8] =
  197. {0, 15, 25, 35, 50, 90, 140, 800};
  198. static const short PassedPawn3[8] =
  199. {0, 5, 10, 15, 20, 30, 140, 800};
  200. static const short ISOLANI[8] =
  201. {-12, -16, -20, -24, -24, -20, -16, -12};
  202. static const short BACKWARD[16] =
  203. {-6, -10, -15, -21, -28, -28, -28, -28,
  204.  -28, -28, -28, -28, -28, -28, -28, -28};
  205. static const short BMBLTY[14] =
  206. {-2, 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 16, 16, 16};
  207. static const short RMBLTY[15] =
  208. {0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14};
  209. static const short KTHRT[36] =
  210. {0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
  211.  -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
  212.  -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
  213. static short KNIGHTPOST, KNIGHTSTRONG, BISHOPSTRONG, KATAK, KBNKsq;
  214. static short PEDRNK2B, PWEAKH, PADVNCM, PADVNCI, PAWNSHIELD, PDOUBLED, PBLOK;
  215. static short RHOPN, RHOPNX, KHOPN, KHOPNX, KSFTY;
  216. static short ATAKD, HUNGP, HUNGX, KCASTLD, KMOVD, XRAY, PINVAL;
  217. static short stage, stage2, Zwmtl, Zbmtl, Developed[2], PawnStorm;
  218. static short PawnBonus, BishopBonus, RookBonus;
  219. static const short KingOpening[64] =
  220. {0, 0, -4, -10, -10, -4, 0, 0,
  221.  -4, -4, -8, -12, -12, -8, -4, -4,
  222.  -12, -16, -20, -20, -20, -20, -16, -12,
  223.  -16, -20, -24, -24, -24, -24, -20, -16,
  224.  -16, -20, -24, -24, -24, -24, -20, -16,
  225.  -12, -16, -20, -20, -20, -20, -16, -12,
  226.  -4, -4, -8, -12, -12, -8, -4, -4,
  227.  0, 0, -4, -10, -10, -4, 0, 0};
  228. static const short KingEnding[64] =
  229. {0, 6, 12, 18, 18, 12, 6, 0,
  230.  6, 12, 18, 24, 24, 18, 12, 6,
  231.  12, 18, 24, 30, 30, 24, 18, 12,
  232.  18, 24, 30, 36, 36, 30, 24, 18,
  233.  18, 24, 30, 36, 36, 30, 24, 18,
  234.  12, 18, 24, 30, 30, 24, 18, 12,
  235.  6, 12, 18, 24, 24, 18, 12, 6,
  236.  0, 6, 12, 18, 18, 12, 6, 0};
  237. static const short DyingKing[64] =
  238. {0, 8, 16, 24, 24, 16, 8, 0,
  239.  8, 32, 40, 48, 48, 40, 32, 8,
  240.  16, 40, 56, 64, 64, 56, 40, 16,
  241.  24, 48, 64, 72, 72, 64, 48, 24,
  242.  24, 48, 64, 72, 72, 64, 48, 24,
  243.  16, 40, 56, 64, 64, 56, 40, 16,
  244.  8, 32, 40, 48, 48, 40, 32, 8,
  245.  0, 8, 16, 24, 24, 16, 8, 0};
  246. static const short KBNK[64] =
  247. {99, 90, 80, 70, 60, 50, 40, 40,
  248.  90, 80, 60, 50, 40, 30, 20, 40,
  249.  80, 60, 40, 30, 20, 10, 30, 50,
  250.  70, 50, 30, 10, 0, 20, 40, 60,
  251.  60, 40, 20, 0, 10, 30, 50, 70,
  252.  50, 30, 10, 20, 30, 40, 60, 80,
  253.  40, 20, 30, 40, 50, 60, 80, 90,
  254.  40, 40, 50, 60, 70, 80, 90, 99};
  255. static const short pknight[64] =
  256. {0, 4, 8, 10, 10, 8, 4, 0,
  257.  4, 8, 16, 20, 20, 16, 8, 4,
  258.  8, 16, 24, 28, 28, 24, 16, 8,
  259.  10, 20, 28, 32, 32, 28, 20, 10,
  260.  10, 20, 28, 32, 32, 28, 20, 10,
  261.  8, 16, 24, 28, 28, 24, 16, 8,
  262.  4, 8, 16, 20, 20, 16, 8, 4,
  263.  0, 4, 8, 10, 10, 8, 4, 0};
  264. static const short pbishop[64] =
  265. {14, 14, 14, 14, 14, 14, 14, 14,
  266.  14, 22, 18, 18, 18, 18, 22, 14,
  267.  14, 18, 22, 22, 22, 22, 18, 14,
  268.  14, 18, 22, 22, 22, 22, 18, 14,
  269.  14, 18, 22, 22, 22, 22, 18, 14,
  270.  14, 18, 22, 22, 22, 22, 18, 14,
  271.  14, 22, 18, 18, 18, 18, 22, 14,
  272.  14, 14, 14, 14, 14, 14, 14, 14};
  273. static const short PawnAdvance[64] =
  274. {0, 0, 0, 0, 0, 0, 0, 0,
  275.  4, 4, 4, 0, 0, 4, 4, 4,
  276.  6, 8, 2, 10, 10, 2, 8, 6,
  277.  6, 8, 12, 16, 16, 12, 8, 6,
  278.  8, 12, 16, 24, 24, 16, 12, 8,
  279.  12, 16, 24, 32, 32, 24, 16, 12,
  280.  12, 16, 24, 32, 32, 24, 16, 12,
  281.  0, 0, 0, 0, 0, 0, 0, 0};
  282.  
  283.  
  284. /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
  285.  
  286.  
  287. #define taxicab(a,b) taxidata[a][b]
  288. short *distdata[64], *taxidata[64];
  289.  
  290. inline void
  291. Initialize_dist (void)
  292. {
  293.   register short a, b, d, di;
  294.  
  295.   for (a = 0; a < 64; a++)
  296.     for (b = 0; b < 64; b++)
  297.       {
  298.     d = abs (column (a) - column (b));
  299.     di = abs (row (a) - row (b));
  300.     taxidata[a][b] = d + di;
  301.     distdata[a][b] = (d > di ? d : di);
  302.       }
  303. }
  304.  
  305. const short Stboard[64] =
  306. {rook, knight, bishop, queen, king, bishop, knight, rook,
  307.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  308.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  309.  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  310.  pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
  311.  rook, knight, bishop, queen, king, bishop, knight, rook};
  312. const short Stcolor[64] =
  313. {white, white, white, white, white, white, white, white,
  314.  white, white, white, white, white, white, white, white,
  315.  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  316.  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  317.  black, black, black, black, black, black, black, black,
  318.  black, black, black, black, black, black, black, black};
  319. short board[64], color[64];
  320. static unsigned char *nextpos[8][64];
  321. static unsigned char *nextdir[8][64];
  322. /*
  323.   ptype is used to separate white and black pawns, like this;
  324.   ptyp = ptype[side][piece]
  325.   piece can be used directly in nextpos/nextdir when generating moves
  326.   for pieces that are not black pawns.
  327. */
  328. static const short ptype[2][8] =
  329. {
  330.   no_piece, pawn, knight, bishop, rook, queen, king, no_piece,
  331.   no_piece, bpawn, knight, bishop, rook, queen, king, no_piece};
  332. static const short direc[8][8] =
  333. {
  334.   0, 0, 0, 0, 0, 0, 0, 0,
  335.   10, 9, 11, 0, 0, 0, 0, 0,
  336.   8, -8, 12, -12, 19, -19, 21, -21,
  337.   9, 11, -9, -11, 0, 0, 0, 0,
  338.   1, 10, -1, -10, 0, 0, 0, 0,
  339.   1, 10, -1, -10, 9, 11, -9, -11,
  340.   1, 10, -1, -10, 9, 11, -9, -11,
  341.   -10, -9, -11, 0, 0, 0, 0, 0};
  342. static const short max_steps[8] =
  343. {0, 2, 1, 7, 7, 7, 1, 2};
  344. static const short nunmap[120] =
  345. {
  346.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  347.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  348.   -1, 0, 1, 2, 3, 4, 5, 6, 7, -1,
  349.   -1, 8, 9, 10, 11, 12, 13, 14, 15, -1,
  350.   -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  351.   -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  352.   -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  353.   -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  354.   -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  355.   -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  356.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  357.   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
  358.  
  359.  
  360. #ifdef HASHFILE
  361.  
  362. /* 
  363.    Check if hashfile exists. If it doesn't, ask if a new one have to be
  364.    created
  365. */
  366.  
  367. int CheckHashFile(void)
  368. {
  369.   if (FSOpen (HASHFILE, 0, &hashfile) == fnfErr)
  370.   {
  371.           if (!AreYouSure(_NEWTABLE_STR)) return 0;
  372.           Create(HASHFILE, 0, 'GCHS', 'GCht');
  373.          if (FSOpen (HASHFILE, 0, &hashfile) != noErr)
  374.           {
  375.               ShowError(_CREATE_STR);
  376.               hashfile = 0;
  377.               return 0;
  378.           }
  379.         if (hashfile != 0)
  380.         {
  381.             long i, j;
  382.             struct fileentry n;
  383.             long count;
  384.             
  385.             for(j = 0; j < 32; j++)
  386.               n.bd[j] = 0;
  387.             n.f = n.t = 0;
  388.             n.flags = 0;
  389.             n.depth = 0;
  390.             n.sh = n.sl = 0;
  391.             for (j = 0; j < filesz; j++) {
  392.               long count = sizeof(struct fileentry);
  393.               if (FSWrite(hashfile, &count, &n) != noErr) {
  394.                   ShowError(_WRITE_STR);
  395.                   FSClose(hashfile);
  396.                   FSDelete(HASHFILE, 0);
  397.                   hashfile = 0;
  398.                   return 0;
  399.               }
  400.             }
  401.         }
  402.     }
  403.     return 1;
  404. }
  405. #endif
  406.  
  407. static void alloc_tables()
  408. {
  409.     int i,j;
  410.     
  411. #if ttblsz
  412.     void *reserved;
  413.     
  414.     for (i=0; i<2; i++)
  415.         for (j=0; j<7; j++) {
  416.             hashcode[i][j] = (struct hashval*)NewPtr(64*sizeof(struct hashval));
  417.             if (hashcode[i][j] == NULL)
  418.                 ExitToShell();
  419.     }
  420.     
  421.     reserved = NewPtr(200000);
  422.     
  423.     if (reserved == NULL) ExitToShell();
  424.     while (real_ttblsz) {
  425.         ttable[0] = (struct hashentry*)NewPtr(real_ttblsz*sizeof(struct hashentry));
  426.         if (ttable[0] == NULL) {
  427.             real_ttblsz >>= 1;
  428.             continue;
  429.         }
  430.         ttable[1] = (struct hashentry*)NewPtr(real_ttblsz*sizeof(struct hashentry));
  431.         if (ttable[1] == NULL) {
  432.             DisposPtr((Ptr)ttable[0]);
  433.             real_ttblsz >>= 1;
  434.             continue;
  435.         }
  436.         break;
  437.     }
  438.     DisposPtr(reserved);
  439.     if (real_ttblsz == 0) ExitToShell();
  440.     
  441. #endif /* ttblsz */
  442.  
  443.     killr0 = (unsigned short *)NewPtr(maxdepth*sizeof(unsigned short ));
  444.     killr1 = (unsigned short *)NewPtr(maxdepth*sizeof(unsigned short ));
  445.     killr2 = (unsigned short *)NewPtr(maxdepth*sizeof(unsigned short ));
  446.     killr3 = (unsigned short *)NewPtr(maxdepth*sizeof(unsigned short ));
  447.     history = (unsigned char*)NewPtr(8192 * sizeof(unsigned char));
  448.  
  449.     Mwpawn = (short *)NewPtr(64*sizeof(short ));
  450.     Mbpawn = (short *)NewPtr(64*sizeof(short ));
  451.     Mknight[0] = (short *)NewPtr(64*sizeof(short ));
  452.     Mknight[1] = (short *)NewPtr(64*sizeof(short ));
  453.     Mking[0] = (short *)NewPtr(64*sizeof(short ));
  454.     Mking[1] = (short *)NewPtr(64*sizeof(short ));
  455.     Mbishop[0] = (short *)NewPtr(64*sizeof(short ));
  456.     Mbishop[1] = (short *)NewPtr(64*sizeof(short ));
  457.     Kfield[0] = (short *)NewPtr(64*sizeof(short ));
  458.     Kfield[1] = (short *)NewPtr(64*sizeof(short ));
  459.     
  460.     GameList = (struct GameRec*)NewPtr(500 * sizeof(struct GameRec));
  461.     for (i=0; i<64; i++) {
  462.         distdata[i] = (short*)NewPtr(64*sizeof(short));
  463.         taxidata[i] = (short*)NewPtr(64*sizeof(short));
  464.     }
  465.     for (i=0; i<8; i++)
  466.         for (j=0; j<64; j++) {
  467.             nextpos[i][j] = (unsigned char *)NewPtr(64L);
  468.             nextdir[i][j] = (unsigned char *)NewPtr(64L);
  469.         }
  470.         
  471.     root = Tree = (struct leaf *)NewPtr(2000*sizeof(struct leaf));
  472.  
  473. }
  474.  
  475. void
  476. Initialize_moves ()
  477.  
  478. /*
  479.   This procedure pre-calculates all moves for every piece from every square.
  480.   This data is stored in nextpos/nextdir and used later in the move generation
  481.   routines.
  482. */
  483.  
  484. {
  485.   short ptyp, po, p0, d, di, s, delta;
  486.   unsigned char *ppos, *pdir;
  487.   short dest[8][8];
  488.   short steps[8];
  489.   short sorted[8];
  490.  
  491.   for (ptyp = 0; ptyp < 8; ptyp++)
  492.     for (po = 0; po < 64; po++)
  493.       for (p0 = 0; p0 < 64; p0++)
  494.     {
  495.       nextpos[ptyp][po][p0] = po;
  496.       nextdir[ptyp][po][p0] = po;
  497.     }
  498.   for (ptyp = 1; ptyp < 8; ptyp++)
  499.     for (po = 21; po < 99; po++)
  500.       if (nunmap[po] >= 0)
  501.     {
  502.       ppos = nextpos[ptyp][nunmap[po]];
  503.       pdir = nextdir[ptyp][nunmap[po]];
  504.       /* dest is a function of direction and steps */
  505.       for (d = 0; d < 8; d++)
  506.         {
  507.           dest[d][0] = nunmap[po];
  508.           delta = direc[ptyp][d];
  509.           if (delta != 0)
  510.         {
  511.           p0 = po;
  512.           for (s = 0; s < max_steps[ptyp]; s++)
  513.             {
  514.               p0 = p0 + delta;
  515.               /*
  516.             break if (off board) or
  517.             (pawns only move two steps from home square)
  518.               */
  519.               if (nunmap[p0] < 0 || (ptyp == pawn || ptyp == bpawn)
  520.               && s > 0 && (d > 0 || Stboard[nunmap[po]] != pawn))
  521.             break;
  522.               else
  523.             dest[d][s] = nunmap[p0];
  524.             }
  525.         }
  526.           else
  527.         s = 0;
  528.  
  529.           /*
  530.             sort dest in number of steps order
  531.             currently no sort is done due to compability with
  532.             the move generation order in old gnu chess
  533.           */
  534.           steps[d] = s;
  535.           for (di = d; s > 0 && di > 0; di--)
  536.         if (steps[sorted[di - 1]] == 0)    /* should be: < s */
  537.           sorted[di] = sorted[di - 1];
  538.         else
  539.           break;
  540.           sorted[di] = d;
  541.         }
  542.  
  543.       /*
  544.         update nextpos/nextdir,
  545.         pawns have two threads (capture and no capture)
  546.       */
  547.       p0 = nunmap[po];
  548.       if (ptyp == pawn || ptyp == bpawn)
  549.         {
  550.           for (s = 0; s < steps[0]; s++)
  551.         {
  552.           ppos[p0] = dest[0][s];
  553.           p0 = dest[0][s];
  554.         }
  555.           p0 = nunmap[po];
  556.           for (d = 1; d < 3; d++)
  557.         {
  558.           pdir[p0] = dest[d][0];
  559.           p0 = dest[d][0];
  560.         }
  561.         }
  562.       else
  563.         {
  564.           pdir[p0] = dest[sorted[0]][0];
  565.           for (d = 0; d < 8; d++)
  566.         for (s = 0; s < steps[sorted[d]]; s++)
  567.           {
  568.             ppos[p0] = dest[sorted[d]][s];
  569.             p0 = dest[sorted[d]][s];
  570.             if (d < 7)
  571.               pdir[p0] = dest[sorted[d + 1]][0];
  572.             /* else is already initialized */
  573.           }
  574.         }
  575.     }
  576. }
  577.  
  578. /* Dispose memory allocated for the Opening Book */
  579. void DisposBook()
  580. {
  581.     struct BookEntry *p;
  582.     
  583.     while (Book != NULL) {
  584.         p = Book;
  585.         Book = Book->next;
  586.         free((Ptr)(p->mv));
  587.         free((Ptr)p);
  588.     }
  589. }
  590.  
  591. void
  592. NewGame ()
  593. /*
  594.   Reset the board and other variables to start a new game.
  595. */
  596. {
  597.   short l, c, p;
  598.  
  599.   stage = stage2 = -1;        /* the game is not yet started */
  600.   mate = quit = false;
  601.   PawnStorm = false;
  602.   beep = rcptr = true; 
  603.   
  604.   NodeCnt = et0 = epsquare = lpost = 0;
  605.   dither = 0;
  606.   Awindow = 90;
  607.   Bwindow = 90;
  608.   xwndw = 90;
  609.   MaxSearchDepth = 29;
  610.   contempt = 0;
  611.   GameCnt = -1;
  612.   Game50 = 0;
  613.   Zwmtl = Zbmtl = 0;
  614.   Developed[white] = Developed[black] = false;
  615.   castld[white] = castld[black] = false;
  616.   PawnThreat[0] = CptrFlag[0] = false;
  617.   Pscore[0] = 12000;
  618.   Tscore[0] = 12000;
  619.  
  620.   for (l = 0; l < 2000; l++)
  621.     Tree[l].f = Tree[l].t = 0;
  622. #if ttblsz
  623.   rehash = 6;
  624.   ZeroTTable ();
  625.   srand ((unsigned int) 1);
  626.   for (c = white; c <= black; c++)
  627.     for (p = pawn; p <= king; p++)
  628.       for (l = 0; l < 64; l++)
  629.     {
  630.       hashcode[c][p][l].key = (((unsigned long) rand ()));
  631.       hashcode[c][p][l].key += (((unsigned long) rand ()) << 16);
  632.       hashcode[c][p][l].bd = (((unsigned long) rand ()));
  633.       hashcode[c][p][l].bd += (((unsigned long) rand ()) << 16);
  634.       if (sizeof(long) > 4)
  635.         {
  636.           hashcode[c][p][l].key += (((unsigned long) rand ()) << 32);
  637.           hashcode[c][p][l].key += (((unsigned long) rand ()) << 48);
  638.           hashcode[c][p][l].bd += (((unsigned long) rand ()) << 32);
  639.           hashcode[c][p][l].bd += (((unsigned long) rand ()) << 48);
  640.         }
  641.     }
  642. #endif /* ttblsz */
  643.   for (l = 0; l < 64; l++)
  644.     {
  645.       board[l] = Stboard[l];
  646.       color[l] = Stcolor[l];
  647.       Mvboard[l] = 0;
  648.     }
  649.   if (TCflag[white]) SetTimeControl (white);
  650.   if (TCflag[black]) SetTimeControl (black);
  651.  
  652.   InitializeStats ();
  653.   DisposBook();
  654.   GetOpenings ();
  655.   time0 = TickCount();
  656.   ElapsedTime (1);
  657. }
  658.  
  659.  
  660. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  661.  
  662. inline void
  663. pick (p1, p2)
  664.      short int p1;
  665.      register short int p2;
  666.  
  667. /*
  668.   Find the best move in the tree between indexes p1 and p2. Swap the best
  669.   move into the p1 element.
  670. */
  671.  
  672. {
  673.   register short p, s;
  674.   register short p0, s0;
  675.   struct leaf temp;
  676.  
  677.   s0 = Tree[p1].score;
  678.   p0 = p1;
  679.   for (p = p1 + 1; p <= p2; p++)
  680.     if ((s = Tree[p].score) > s0)
  681.       {
  682.     s0 = s;
  683.     p0 = p;
  684.       }
  685.   if (p0 != p1)
  686.     {
  687.       temp = Tree[p1];
  688.       Tree[p1] = Tree[p0];
  689.       Tree[p0] = temp;
  690.     }
  691. }
  692.  
  693. void
  694. SelectMove (side, iop)
  695.      short int side;
  696.      short int iop;
  697. /*
  698.   Select a move by calling function search() at progressively deeper ply
  699.   until time is up or a mate or draw is reached. An alpha-beta window of -90
  700.   to +90 points is set around the score returned from the previous
  701.   iteration. If Sdepth != 0 then the program has correctly predicted the
  702.   opponents move and the search will start at a depth of Sdepth+1 rather
  703.   than a depth of 1.
  704. */
  705. {
  706.   static alpha, beta, score, tempb, tempc, tempsf, tempst, xside, rpt;
  707.   register short i;
  708.   
  709.   timeout = false;
  710.   xside = otherside[side];
  711.   if (iop != 2)
  712.     player = side;
  713.   if (TCflag[side])
  714.     {
  715.       if ((TimeControl.moves[side] + 3) != 0)
  716.     ResponseTime = (TimeControl.clock[side]) /
  717.       (TimeControl.moves[side] + 3) -
  718.       OperatorTime[side];
  719.       else
  720.     ResponseTime = 0;
  721.       ResponseTime += (ResponseTime * TimeControl.moves[side]) / (2 * TCmoves[side] + 1);
  722.     }
  723.   else
  724.     ResponseTime = Level[side];
  725.   if (iop == 2)
  726.     ResponseTime = 99999;
  727.   if (Sdepth > 0 && root->score > Zscore - zwndw)
  728.     ResponseTime -= ft;
  729.   else if (ResponseTime < 1)
  730.     ResponseTime = 1;
  731.   ExtraTime = 0;
  732.   ExaminePosition ();
  733.   ScorePosition (side, &score);
  734.   /* Pscore[0] = -score; */
  735.  
  736.   if (Sdepth == 0)
  737.     {
  738. #if ttblsz
  739.       /* ZeroTTable (); */
  740. #endif /* ttblsz */
  741.       SearchStartStuff (side);
  742. #ifdef NOMEMSET
  743.       for (i = 0; i < 8192; i++)
  744.     history[i] = 0;
  745. #else
  746.       memset ((char *) history, 0, sizeof (history));
  747. #endif /* NOMEMSET */
  748.       FROMsquare = TOsquare = -1;
  749.       PV = 0;
  750.       if (iop != 2)
  751.         hint = 0;
  752.       for (i = 0; i < maxdepth; i++)
  753.         PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  754.       alpha = score - 90;
  755.       beta = score + 90;
  756.       rpt = 0;
  757.       TrPnt[1] = 0;
  758.       root = &Tree[0];
  759.       MoveList (side, 1);
  760.       for (i = TrPnt[1]; i < TrPnt[2]; i++)
  761.         pick (i, TrPnt[2] - 1);
  762.       if (Book != NULL)
  763.             OpeningBook ();
  764.       if (Book != NULL)
  765.             timeout = true;
  766.       NodeCnt = ETnodes = EvalNodes = HashCnt = FHashCnt = HashCol = 0;
  767.       Zscore = 0;
  768.       zwndw = 20;
  769.     }
  770.     while (!timeout && Sdepth < MaxSearchDepth)
  771.     {
  772.       Sdepth++;
  773.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  774.       for (i = 1; i <= Sdepth; i++)
  775.         killr0[i] = PrVar[i];
  776.       if (score < alpha)
  777.     {
  778.       ExtraTime = 10 * ResponseTime;
  779.       /* ZeroTTable (); */
  780.       score = search (side, 1, Sdepth, -9000, score, PrVar, &rpt);
  781.     }
  782.       if (score > beta && !(root->flags & exact))
  783.     {
  784.       ExtraTime = 0;
  785.       /* ZeroTTable (); */
  786.       score = search (side, 1, Sdepth, score, 9000, PrVar, &rpt);
  787.     }
  788.       score = root->score;
  789.       if (!timeout)
  790.     for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
  791.       pick (i, TrPnt[2] - 1);
  792.       ShowResults (score, PrVar, '.');
  793.       for (i = 1; i <= Sdepth; i++)
  794.         killr0[i] = PrVar[i];
  795.     if (score > Zscore - zwndw && score > Tree[1].score + 250)
  796.         ExtraTime = 0;
  797.       else if (score > Zscore - 3 * zwndw)
  798.     ExtraTime = ResponseTime;
  799.       else
  800.     ExtraTime = 3 * ResponseTime;
  801.       if (root->flags & exact)
  802.     timeout = true;
  803.       if (Tree[1].score < -9000)
  804.     timeout = true;
  805.       if (4 * et > 2 * ResponseTime + ExtraTime)
  806.     timeout = true;
  807.       if (!timeout)
  808.         {
  809.           Tscore[0] = score;
  810.     
  811.           Zscore = Zscore?(Zscore + score) / 2:score;
  812.         }
  813.       zwndw = 20 + abs (Zscore / 12);
  814.       beta = score + Bwindow;
  815.       if (Zscore < score)
  816.     alpha = Zscore - Awindow - zwndw;
  817.       else
  818.     alpha = score - Awindow - zwndw;
  819.     }
  820.  
  821.   if (donotplay) return;
  822.  
  823.   score = root->score;
  824.   if (rpt >= 2 || score < -12000)
  825.     root->flags |= draw;
  826.   if (iop == 2)
  827.     return;
  828.  
  829.   ElapsedTime (1);
  830.   if (Book == NULL)
  831.     hint = PrVar[2];
  832.  
  833.   if (score > -9999 && rpt <= 2)
  834.     {
  835.       MakeMove (side, root, &tempb, &tempc, &tempsf, &tempst);
  836.       algbr (root->f, root->t, (short) root->flags);
  837.     }
  838.   else
  839.     algbr (0, 0, 0);
  840.     
  841.   if (score == -9999 || score == 9998)
  842.     mate = true;
  843.   if (mate)
  844.     hint = 0;
  845.   if (root->flags & cstlmask)
  846.     Game50 = GameCnt;
  847.   else if (board[root->t] == pawn || (root->flags & capture))
  848.     Game50 = GameCnt;
  849.   GameList[GameCnt].score = score;
  850.   GameList[GameCnt].nodes = NodeCnt;
  851.   GameList[GameCnt].time = (short) et;
  852.   GameList[GameCnt].depth = Sdepth;
  853.   if (TCflag[side])
  854.     {
  855.       TimeControl.clock[side] -= (et + OperatorTime[side]);
  856.       if (--TimeControl.moves[side] == 0)
  857.                     SetTimeControl (side);
  858.     }
  859.   if ((root->flags & draw) && bothsides)
  860.     mate = true;
  861.   if (GameCnt > 498)
  862.     mate = true; /* out of move store, you loose */
  863.   player = xside;
  864.   Sdepth = 0;
  865.  
  866.   OutputMove ();
  867.   return;
  868. }
  869.  
  870. void
  871. OpeningBook ()
  872. /*
  873.   Go thru each of the opening lines of play and check for a match with the
  874.   current game listing. If a match occurs, generate a random number. If this
  875.   number is the largest generated so far then the next move in this line
  876.   becomes the current "candidate". After all lines are checked, the
  877.   candidate move is put at the top of the Tree[] array and will be played by
  878.   the program. Note that the program does not handle book transpositions.
  879. */
  880. {
  881.   short j, pnt;
  882.   unsigned short m, *mp;
  883.   unsigned r, r0;
  884.   struct BookEntry *p;
  885.  
  886.   srand ((unsigned short) time0);
  887.   r0 = m = 0;
  888.   p = Book;
  889.   while (p != NULL)
  890.     {
  891.       mp = p->mv;
  892.       for (j = 0; j <= GameCnt; j++)
  893.     if (GameList[j].gmove != *(mp++))
  894.       break;
  895.       if (j > GameCnt)
  896.     if ((r = rand ()) > r0)
  897.       {
  898.         r0 = r;
  899.         m = *mp;
  900.         hint = *(++mp);
  901.       }
  902.       p = p->next;
  903.     }
  904.  
  905.   for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
  906.     if (((Tree[pnt].f << 8) | Tree[pnt].t) == m)
  907.       Tree[pnt].score = 0;
  908.   pick (TrPnt[1], TrPnt[2] - 1);
  909.   if (Tree[TrPnt[1]].score < 0)
  910.     DisposBook();
  911. }
  912.  
  913.  
  914. inline void
  915. repetition (cnt)
  916.      short int *cnt;
  917.  
  918. /*
  919.   Check for draw by threefold repetition.
  920. */
  921.  
  922. {
  923.   register short i, c, f, t;
  924.   short b[64];
  925.   unsigned short m;
  926.  
  927.   *cnt = c = 0;
  928.   if (GameCnt > Game50 + 3)
  929.     {
  930. #ifdef NOMEMSET
  931.       for (i = 0; i < 64; b[i++] = 0) ;
  932. #else
  933.       memset ((char *) b, 0, sizeof (b));
  934. #endif /* NOMEMSET */
  935.       for (i = GameCnt; i > Game50; i--)
  936.     {
  937.       m = GameList[i].gmove;
  938.       f = m >> 8;
  939.       t = m & 0xFF;
  940.       if (++b[f] == 0)
  941.         c--;
  942.       else
  943.         c++;
  944.       if (--b[t] == 0)
  945.         c--;
  946.       else
  947.         c++;
  948.       if (c == 0)
  949.         (*cnt)++;
  950.     }
  951.     }
  952. }
  953.  
  954. int
  955. search (side, ply, depth, alpha, beta, bstline, rpt)
  956.      short int side;
  957.      short int ply;
  958.      short int depth;
  959.      short int alpha;
  960.      short int beta;
  961.      short unsigned int *bstline;
  962.      short int *rpt;
  963.  
  964. /*
  965.   Perform an alpha-beta search to determine the score for the current board
  966.   position. If depth <= 0 only capturing moves, pawn promotions and
  967.   responses to check are generated and searched, otherwise all moves are
  968.   processed. The search depth is modified for check evasions, certain
  969.   re-captures and threats. Extensions may continue for up to 11 ply beyond
  970.   the nominal search depth.
  971. */
  972.  
  973. #define UpdateSearchStatus \
  974. {\
  975.    if (post) ShowCurrentMove(pnt,node->f,node->t);\
  976.      if (pnt > TrPnt[1])\
  977.        {\
  978.       d = best-Zscore; e = best-node->score;\
  979.         if (best < alpha) ExtraTime = 10*ResponseTime;\
  980.         else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
  981.         else if (d > -zwndw) ExtraTime = 0;\
  982.         else if (d > -3*zwndw) ExtraTime = ResponseTime;\
  983.         else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
  984.         else ExtraTime = 5*ResponseTime;\
  985.         }\
  986.         }
  987. #define prune (cf && score+node->score < alpha)
  988. #define ReCapture (rcptr && score > alpha && score < beta &&\
  989.            ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
  990.             /* && depth == Sdepth-ply+1 */
  991. #define Parry (hung[side] > 1 && ply == Sdepth+1)
  992. #define MateThreat (ply < Sdepth+4 && ply > 4 &&\
  993.             ChkFlag[ply-2] && ChkFlag[ply-4] &&\
  994.             ChkFlag[ply-2] != ChkFlag[ply-4])
  995.  
  996. {
  997.   register short j, pnt;
  998.   short best, tempb, tempc, tempsf, tempst;
  999.   short xside, pbst, d, e, cf, score, rcnt;
  1000.   unsigned short mv, nxtline[maxdepth];
  1001.   struct leaf *node, tmp;
  1002.  
  1003.   NodeCnt++;
  1004.   xside = otherside[side];
  1005.  
  1006.   /* could this be removed ? */
  1007.   if (depth < 0)
  1008.     depth = 0;
  1009.  
  1010.   if (ply <= Sdepth + 3)
  1011.     repetition (rpt);
  1012.   else
  1013.     *rpt = 0;
  1014.   /* Detect repetitions a bit earlier. SMC. 12/89 */
  1015.   if (*rpt == 1 && ply > 1)
  1016.     return (0);
  1017.   /* if (*rpt >= 2) return(0); */
  1018.  
  1019.   score = evaluate (side, xside, ply, alpha, beta);
  1020.   if (score > 9000)
  1021.     {
  1022.       bstline[ply] = 0;
  1023.       return (score);
  1024.     }
  1025.   if (depth > 0)
  1026.     {
  1027.       /* Allow opponent a chance to check again */
  1028.       if (InChk) {
  1029.         if (depth < 2) depth = 2;
  1030.     }
  1031.       else if (PawnThreat[ply - 1] || ReCapture)
  1032.     ++depth;
  1033.     }
  1034.   else
  1035.     {
  1036.       if (score >= alpha &&
  1037.       (InChk || PawnThreat[ply - 1] || Parry))
  1038.     depth = 1;
  1039.       else if (score <= beta && MateThreat)
  1040.     depth = 1;
  1041.     }
  1042.  
  1043. #if ttblsz
  1044.   if (depth > 0 && hashflag && ply > 1)
  1045.     {
  1046.       if (ProbeTTable (side, depth, &alpha, &beta, &score) == false)
  1047. #ifdef HASHFILE    
  1048.     if ((depth > 4) && (GameCnt < 12) && hashfile)
  1049.       ProbeFTable (side, depth, &alpha, &beta, &score);
  1050. #else
  1051.       /* do nothing */;
  1052. #endif /* HASHFILE */      
  1053.       bstline[ply] = PV;
  1054.       bstline[ply + 1] = 0;
  1055.       if (beta == -20000)
  1056.     return (score);
  1057.       if (alpha > beta)
  1058.     return (alpha);
  1059.     }
  1060. #endif /* ttblsz */
  1061.   d = (Sdepth == 1)?7:11;
  1062.   if (ply > Sdepth + d || (depth < 1 && score > beta))
  1063.     /* score >= beta ?? */
  1064.     return (score);
  1065.  
  1066.   if (ply > 1)
  1067.     if (depth > 0)
  1068.       MoveList (side, ply);
  1069.     else
  1070.       CaptureList (side, xside, ply);
  1071.  
  1072.   if (TrPnt[ply] == TrPnt[ply + 1])
  1073.     return (score);
  1074.  
  1075.   cf = (depth < 1 && ply > Sdepth + 1 && !ChkFlag[ply - 2] && !slk);
  1076.  
  1077.   if (depth > 0)
  1078.     best = -12000;
  1079.   else
  1080.     best = score;
  1081.   if (best > alpha)
  1082.     alpha = best;
  1083.  
  1084.   for (pnt = pbst = TrPnt[ply];
  1085.        pnt < TrPnt[ply + 1] && best <= beta;    /* best < beta ?? */
  1086.        pnt++)
  1087.     {
  1088.       if (ply > 1)
  1089.     pick (pnt, TrPnt[ply + 1] - 1);
  1090.       node = &Tree[pnt];
  1091.       mv = (node->f << 8) | node->t;
  1092.       nxtline[ply + 1] = 0;
  1093.  
  1094.       if (prune)
  1095.     break;
  1096.       if (ply == 1)
  1097.     UpdateSearchStatus;
  1098.  
  1099.       if (!(node->flags & exact))
  1100.     {
  1101.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1102.       CptrFlag[ply] = (node->flags & capture);
  1103.       PawnThreat[ply] = (node->flags & pwnthrt);
  1104.       Tscore[ply] = node->score;
  1105.       PV = node->reply;
  1106.       node->score = -search (xside, ply + 1, depth - 1, -beta, -alpha,
  1107.                  nxtline, &rcnt);
  1108.       if (abs (node->score) > 9000)
  1109.         node->flags |= exact;
  1110.       else if (rcnt == 1)
  1111.         node->score /= 2;
  1112.       if (rcnt >= 2 || GameCnt - Game50 > 99 ||
  1113.           (node->score == 9999 - ply && !ChkFlag[ply]))
  1114.         {
  1115.           node->flags |= draw;
  1116.           node->flags |= exact;
  1117.           if (side == computer)
  1118.         node->score = contempt;
  1119.           else
  1120.         node->score = -contempt;
  1121.         }
  1122.       node->reply = nxtline[ply + 1];
  1123.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1124.     }
  1125.       if (node->score > best && !timeout)
  1126.     {
  1127.       if (depth > 0)
  1128.         if (node->score > alpha && !(node->flags & exact))
  1129.           node->score += depth;
  1130.       best = node->score;
  1131.       pbst = pnt;
  1132.       if (best > alpha)
  1133.         alpha = best;
  1134.       for (j = ply + 1; nxtline[j] > 0; j++)
  1135.         bstline[j] = nxtline[j];
  1136.       bstline[j] = 0;
  1137.       bstline[ply] = mv;
  1138.       if (ply == 1)
  1139.         {
  1140.           if (best > root->score)
  1141.         {
  1142.           tmp = Tree[pnt];
  1143.           for (j = pnt - 1; j >= 0; j--)
  1144.             Tree[j + 1] = Tree[j];
  1145.           Tree[0] = tmp;
  1146.           pbst = 0;
  1147.         }
  1148.           if (Sdepth > 4)
  1149.         if (best > beta)
  1150.           ShowResults (best, bstline, '+');
  1151.         else if (best < alpha)
  1152.           ShowResults (best, bstline, '-');
  1153.         else
  1154.           ShowResults (best, bstline, '&');
  1155.         }
  1156.     }
  1157.       if (NodeCnt > ETnodes)
  1158.     ElapsedTime (0);
  1159.       if (timeout)
  1160.     return (-Tscore[ply - 1]);
  1161.     }
  1162.  
  1163.   node = &Tree[pbst];
  1164.   mv = (node->f << 8) | node->t;
  1165. #if ttblsz
  1166.   if (hashflag && ply <= Sdepth && *rpt == 0 && best == alpha)
  1167.     {
  1168.       PutInTTable (side, best, depth, alpha, beta, mv);
  1169. #ifdef HASHFILE      
  1170.       if ((depth > 4) && (GameCnt < 12) && hashfile)
  1171.     PutInFTable (side, best, depth, alpha, beta, node->f, node->t);
  1172. #endif /* HASHFILE */      
  1173.     }
  1174. #endif /* ttblsz */
  1175.   if (depth > 0)
  1176.     {
  1177.       j = (node->f << 6) | node->t;
  1178.       if (side == black)
  1179.     j |= 0x1000;
  1180.       if (history[j] < 150)
  1181.     history[j] += 2 * depth;
  1182.       if (node->t != (GameList[GameCnt].gmove & 0xFF))
  1183.     if (best <= beta)
  1184.       killr3[ply] = mv;
  1185.     else if (mv != killr1[ply])
  1186.       {
  1187.         killr2[ply] = killr1[ply];
  1188.         killr1[ply] = mv;
  1189.       }
  1190.       if (best > 9000)
  1191.     killr0[ply] = mv;
  1192.       else
  1193.     killr0[ply] = 0;
  1194.     }
  1195.   return (best);
  1196. }
  1197.  
  1198. #if ttblsz
  1199. #define CB(i) ((color[2 * (i)] ? 0x80 : 0)\
  1200.            | (board[2 * (i)] << 4)\
  1201.            | (color[2 * (i) + 1] ? 0x8 : 0)\
  1202.            | (board[2 * (i) + 1]))
  1203.  
  1204. int
  1205. ProbeTTable (side, depth, alpha, beta, score)
  1206.      short int side;
  1207.      short int depth;
  1208.      short int *alpha;
  1209.      short int *beta;
  1210.      short int *score;
  1211.  
  1212. /*
  1213.   Look for the current board position in the transposition table.
  1214. */
  1215.  
  1216. {
  1217.   register struct hashentry *ptbl;
  1218.   register unsigned short i;
  1219.  
  1220.   ptbl = &ttable[side][hashkey & (real_ttblsz - 1)];
  1221.  
  1222.   /* rehash max rehash times */
  1223.   for (i = 1; ptbl->hashbd != hashbd && i <= rehash; i++)
  1224.     ptbl = &ttable[side][(hashkey + i) & (real_ttblsz - 1)];
  1225.   if (ptbl->depth >= depth && ptbl->hashbd == hashbd)
  1226.     {
  1227.       HashCnt++;
  1228. #ifdef HASHTEST
  1229.       for (i = 0; i < 32; i++)
  1230.     {
  1231.       if (ptbl->bd[i] != CB(i))
  1232.         {
  1233.           HashCol++;
  1234.           break;
  1235.         }
  1236.     }
  1237. #endif /* HASHTEST */
  1238.  
  1239.       PV = ptbl->mv;
  1240.       if (ptbl->flags & truescore)
  1241.     {
  1242.       *score = ptbl->score;
  1243.       *beta = -20000;
  1244.     }
  1245. #if 0 /* commented out, why? */
  1246.       else if (ptbl->flags & upperbound)
  1247.     {
  1248.       if (ptbl->score < *beta) *beta = ptbl->score+1;
  1249.     }
  1250. #endif
  1251.       else if (ptbl->flags & lowerbound)
  1252.     {
  1253.       if (ptbl->score > *alpha)
  1254.         *alpha = ptbl->score - 1;
  1255.     }
  1256.       return(true);
  1257.     }
  1258.   return(false);
  1259. }
  1260.  
  1261. void
  1262. PutInTTable (side, score, depth, alpha, beta, mv)
  1263.      short int side;
  1264.      short int score;
  1265.      short int depth;
  1266.      short int alpha;
  1267.      short int beta;
  1268.      short unsigned int mv;
  1269.  
  1270. /*
  1271.   Store the current board position in the transposition table.
  1272. */
  1273.  
  1274. {
  1275.   register struct hashentry *ptbl;
  1276.   register unsigned short i;
  1277.  
  1278.   ptbl = &ttable[side][hashkey & (real_ttblsz - 1)];
  1279.  
  1280.   /* rehash max rehash times */
  1281.   for (i = 1; depth < ptbl->depth && ptbl->hashbd != hashbd && i <= rehash; i++)
  1282.     ptbl = &ttable[side][(hashkey + i) & (real_ttblsz - 1)];
  1283.   if (depth > ptbl->depth || ptbl->hashbd != hashbd)
  1284.     {
  1285.       ptbl->hashbd = hashbd;
  1286.       ptbl->depth = depth;
  1287.       ptbl->score = score;
  1288.       ptbl->mv = mv;
  1289.       ptbl->flags = 0;
  1290.       if (score < alpha)
  1291.     ptbl->flags |= upperbound;
  1292.       else if (score > beta)
  1293.     ptbl->flags |= lowerbound;
  1294.       else
  1295.     ptbl->flags |= truescore;
  1296. #ifdef HASHTEST
  1297.       for (i = 0; i < 32; i++)
  1298.     {
  1299.       ptbl->bd[i] = CB(i);
  1300.     }
  1301. #endif /* HASHTEST */
  1302.     }
  1303. }
  1304.  
  1305. void
  1306. ZeroTTable ()
  1307. {
  1308.   register unsigned long side, i;
  1309.  
  1310.   if (hashflag)
  1311.     for (side = 0; side < 2; side++)
  1312.       for (i = 0; i < real_ttblsz; i++)
  1313.         ttable[side][i].depth = 0;
  1314. }
  1315.  
  1316. #ifdef HASHFILE
  1317. short
  1318. ProbeFTable(side, depth, alpha, beta, score)
  1319.      short int side;
  1320.      short int depth;
  1321.      short int *alpha;
  1322.      short int *beta;
  1323.      short int *score;
  1324.  
  1325. /*
  1326.   Look for the current board position in the persistent transposition table.
  1327. */
  1328.  
  1329. {
  1330.   register unsigned short i, j;
  1331.   register unsigned long hashix;
  1332.   short s;
  1333.   struct fileentry new, t;
  1334.  
  1335.   if (side == white)
  1336.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  1337.   else
  1338.     hashix = hashkey | 1 & (filesz - 1);
  1339.  
  1340.   for (i = 0; i < 32; i++)
  1341.     new.bd[i] = CB(i);
  1342.   new.flags = 0;
  1343.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  1344.     new.flags |= queencastle;
  1345.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  1346.     new.flags |= kingcastle;
  1347.  
  1348.   for (i = 0; i < frehash; i++)
  1349.     {
  1350.       long count;
  1351.       
  1352.       SetFPos(hashfile,
  1353.         fsFromStart,
  1354.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1))
  1355.         );
  1356.       count = sizeof(struct fileentry);
  1357.       FSRead(hashfile, &count, &t);
  1358.       for (j = 0; j < 32; j++)
  1359.     if (t.bd[j] != new.bd[j])
  1360.       break;
  1361.       if ((t.depth >= depth) && (j >= 32)
  1362.       && (new.flags == (t.flags & (kingcastle | queencastle))))
  1363.     {
  1364.       FHashCnt++;
  1365.       PV = (t.f << 8) | t.t;
  1366.       s = (t.sh << 8) | t.sl;
  1367.       if (t.flags & truescore)
  1368.         {
  1369.           *score = s;
  1370.           *beta = -20000;
  1371.         }
  1372.       else if (t.flags & lowerbound)
  1373.         {
  1374.           if (s > *alpha)
  1375.         *alpha = s - 1;
  1376.         }
  1377.       return(true);
  1378.     }
  1379.     }
  1380.   return(false);
  1381. }
  1382.  
  1383. void
  1384. PutInFTable (side, score, depth, alpha, beta, f, t)
  1385.      short int side;
  1386.      short int score;
  1387.      short int depth;
  1388.      short int alpha;
  1389.      short int beta;
  1390.      short unsigned int f;
  1391.      short unsigned int t;
  1392.  
  1393. /*
  1394.   Store the current board position in the persistent transposition table.
  1395. */
  1396.  
  1397. {
  1398.   register unsigned short i;
  1399.   register unsigned long hashix;
  1400.   struct fileentry new, tmp;
  1401.  
  1402.   if (side == white)
  1403.     hashix = hashkey & 0xFFFFFFFE & (filesz - 1);
  1404.   else
  1405.     hashix = hashkey | 1 & (filesz - 1);
  1406.  
  1407.   for (i = 0; i < 32; i++)
  1408.     new.bd[i] = CB(i);
  1409.   new.f = f;
  1410.   new.t = t;
  1411.   new.flags = 0;
  1412.   if (score < alpha)
  1413.     new.flags |= upperbound;
  1414.   else if (score > beta)
  1415.     new.flags |= lowerbound;
  1416.   else
  1417.     new.flags |= truescore;
  1418.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[qrook[side]] == 0))
  1419.     new.flags |= queencastle;
  1420.   if ((Mvboard[kingP[side]] == 0) && (Mvboard[krook[side]] == 0))
  1421.     new.flags |= kingcastle;
  1422.   new.depth = depth;
  1423.   new.sh = score >> 8;
  1424.   new.sl = score & 0xFF;
  1425.  
  1426.   for (i = 0; i < frehash; i++)
  1427.     {
  1428.       long count;
  1429.       
  1430.       SetFPos(hashfile,
  1431.           fsFromStart,
  1432.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1))
  1433.         );
  1434.       count = sizeof(struct fileentry);
  1435.       FSRead(hashfile, &count, &tmp);
  1436.        if (tmp.depth <= depth)
  1437.     {
  1438.       SetFPos(hashfile,
  1439.           fsFromStart,
  1440.         sizeof(struct fileentry) * ((hashix + 2 * i) & (filesz - 1))
  1441.         );
  1442.       count = sizeof(struct fileentry);
  1443.       FSWrite(hashfile, &count, &new);
  1444.       break;
  1445.     }
  1446.  
  1447.     }
  1448. }
  1449. #endif /* HASHFILE */
  1450. #endif /* ttblsz */
  1451.  
  1452. #define Link(from,to,flag,s) \
  1453. {\
  1454.    node->f = from; node->t = to;\
  1455.    node->reply = 0;\
  1456.    node->flags = flag;\
  1457.    node->score = s;\
  1458.    ++node;\
  1459.    ++TrPnt[ply+1];\
  1460. }
  1461.  
  1462. inline void
  1463. LinkMove (ply, f, t, flag, xside)
  1464.      short int ply;
  1465.      short int f;
  1466.      short int t;
  1467.      short int flag;
  1468.      short int xside;
  1469.  
  1470. /*
  1471.   Add a move to the tree.  Assign a bonus to order the moves
  1472.   as follows:
  1473.   1. Principle variation
  1474.   2. Capture of last moved piece
  1475.   3. Other captures (major pieces first)
  1476.   4. Killer moves
  1477.   5. "history" killers
  1478. */
  1479.  
  1480. {
  1481.   register short s, z;
  1482.   register unsigned short mv;
  1483.   register struct leaf *node;
  1484.  
  1485.   node = &Tree[TrPnt[ply + 1]];
  1486.   mv = (f << 8) | t;
  1487.   s = 0;
  1488.   if (mv == Swag0)
  1489.     s = 2000;
  1490.   else if (mv == Swag1)
  1491.     s = 60;
  1492.   else if (mv == Swag2)
  1493.     s = 50;
  1494.   else if (mv == Swag3)
  1495.     s = 40;
  1496.   else if (mv == Swag4)
  1497.     s = 30;
  1498.   z = (f << 6) | t;
  1499.   if (xside == white)
  1500.     z |= 0x1000;
  1501.   s += history[z];
  1502.   if (color[t] != neutral)
  1503.     {
  1504.       flag |= capture;
  1505.       if (t == TOsquare)
  1506.     s += 500;
  1507.       s += value[board[t]] - board[f];
  1508.     }
  1509.   if (board[f] == pawn)
  1510.     if (row (t) == 0 || row (t) == 7)
  1511.       {
  1512.     flag |= promote;
  1513.     s += 800;
  1514.     Link (f, t, flag | queen, s - 20000);
  1515.     s -= 200;
  1516.     Link (f, t, flag | knight, s - 20000);
  1517.     s -= 50;
  1518.     Link (f, t, flag | rook, s - 20000);
  1519.     flag |= bishop;
  1520.     s -= 50;
  1521.       }
  1522.     else if (row (t) == 1 || row (t) == 6)
  1523.       {
  1524.     flag |= pwnthrt;
  1525.     s += 600;
  1526.       }
  1527.     else if (t == epsquare)
  1528.       flag |= epmask;
  1529.   Link (f, t, flag, s - 20000);
  1530. }
  1531.  
  1532.  
  1533. inline void
  1534. GenMoves (ply, sq, side, xside)
  1535.      short int ply;
  1536.      short int sq;
  1537.      short int side;
  1538.      short int xside;
  1539.  
  1540. /*
  1541.   Generate moves for a piece. The moves are taken from the precalulated
  1542.   array nextpos/nextdir. If the board is free, next move is choosen from
  1543.   nextpos else from nextdir.
  1544. */
  1545.  
  1546. {
  1547.   register short u, piece;
  1548.   register unsigned char *ppos, *pdir;
  1549.  
  1550.   piece = board[sq];
  1551.   ppos = nextpos[ptype[side][piece]][sq];
  1552.   pdir = nextdir[ptype[side][piece]][sq];
  1553.   if (piece == pawn)
  1554.     {
  1555.       u = ppos[sq];    /* follow no captures thread */
  1556.       if (color[u] == neutral)
  1557.     {
  1558.       LinkMove (ply, sq, u, 0, xside);
  1559.       u = ppos[u];
  1560.       if (color[u] == neutral)
  1561.         LinkMove (ply, sq, u, 0, xside);
  1562.     }
  1563.       u = pdir[sq];    /* follow captures thread */
  1564.       if (color[u] == xside || u == epsquare)
  1565.     LinkMove (ply, sq, u, capture, xside);
  1566.       u = pdir[u];
  1567.       if (color[u] == xside || u == epsquare)
  1568.     LinkMove (ply, sq, u, capture, xside);
  1569.     }
  1570.   else
  1571.     {
  1572.       u = ppos[sq];
  1573.       do
  1574.     {
  1575.       if (color[u] == neutral)
  1576.         {
  1577.           LinkMove (ply, sq, u, 0, xside);
  1578.           u = ppos[u];
  1579.         }
  1580.       else
  1581.         {
  1582.           if (color[u] == xside)
  1583.         LinkMove (ply, sq, u, capture, xside);
  1584.           u = pdir[u];
  1585.         }
  1586.       } while (u != sq);
  1587.     }
  1588. }
  1589.  
  1590. void
  1591. MoveList (side, ply)
  1592.      short int side;
  1593.      short int ply;
  1594.  
  1595. /*
  1596.   Fill the array Tree[] with all available moves for side to play. Array
  1597.   TrPnt[ply] contains the index into Tree[] of the first move at a ply.
  1598. */
  1599.  
  1600. {
  1601.   register short i, xside, f;
  1602.  
  1603.   xside = otherside[side];
  1604.   TrPnt[ply + 1] = TrPnt[ply];
  1605.   if (PV == 0)
  1606.     Swag0 = killr0[ply];
  1607.   else
  1608.     Swag0 = PV;
  1609.   Swag1 = killr1[ply];
  1610.   Swag2 = killr2[ply];
  1611.   Swag3 = killr3[ply];
  1612.   Swag4 = 0;
  1613.   if (ply > 2)
  1614.     Swag4 = killr1[ply - 2];
  1615.   for (i = PieceCnt[side]; i >= 0; i--)
  1616.     GenMoves (ply, PieceList[side][i], side, xside);
  1617.   if (!castld[side])
  1618.     {
  1619.       f = PieceList[side][0];
  1620.       if (castle (side, f, f + 2, 0))
  1621.     {
  1622.       LinkMove (ply, f, f + 2, cstlmask, xside);
  1623.     }
  1624.       if (castle (side, f, f - 2, 0))
  1625.     {
  1626.       LinkMove (ply, f, f - 2, cstlmask, xside);
  1627.     }
  1628.     }
  1629. }
  1630.  
  1631. void
  1632. CaptureList (side, xside, ply)
  1633.      short int side;
  1634.      short int xside;
  1635.      short int ply;
  1636.  
  1637. /*
  1638.   Fill the array Tree[] with all available cature and promote moves for
  1639.   side to play. Array TrPnt[ply] contains the index into Tree[]
  1640.   of the first move at a ply.
  1641. */
  1642.  
  1643. {
  1644.   register short u, sq;
  1645.   register unsigned char *ppos, *pdir;
  1646.   short i, piece, *PL, r7;
  1647.   struct leaf *node;
  1648.  
  1649.   TrPnt[ply + 1] = TrPnt[ply];
  1650.   node = &Tree[TrPnt[ply]];
  1651.   r7 = rank7[side];
  1652.   PL = PieceList[side];
  1653.   for (i = 0; i <= PieceCnt[side]; i++)
  1654.     {
  1655.       sq = PL[i];
  1656.       piece = board[sq];
  1657.       if (sweep[piece])
  1658.     {
  1659.       ppos = nextpos[piece][sq];
  1660.       pdir = nextdir[piece][sq];
  1661.       u = ppos[sq];
  1662.       do
  1663.         {
  1664.           if (color[u] == neutral)
  1665.         u = ppos[u];
  1666.           else
  1667.         {
  1668.           if (color[u] == xside)
  1669.             Link (sq, u, capture,
  1670.               value[board[u]] + svalue[board[u]] - piece);
  1671.           u = pdir[u];
  1672.         }
  1673.       } while (u != sq);
  1674.     }
  1675.       else
  1676.     {
  1677.       pdir = nextdir[ptype[side][piece]][sq];
  1678.       if (piece == pawn && row (sq) == r7)
  1679.         {
  1680.           u = pdir[sq];
  1681.           if (color[u] == xside)
  1682.         Link (sq, u, capture | promote | queen, valueQ);
  1683.           u = pdir[u];
  1684.           if (color[u] == xside)
  1685.         Link (sq, u, capture | promote | queen, valueQ);
  1686.           ppos = nextpos[ptype[side][piece]][sq];
  1687.           u = ppos[sq]; /* also generate non capture promote */
  1688.           if (color[u] == neutral)
  1689.         Link (sq, u, promote | queen, valueQ);
  1690.         }
  1691.       else
  1692.         {
  1693.           u = pdir[sq];
  1694.           do
  1695.         {
  1696.           if (color[u] == xside)
  1697.             Link (sq, u, capture,
  1698.               value[board[u]] + svalue[board[u]] - piece);
  1699.           u = pdir[u];
  1700.           } while (u != sq);
  1701.         }
  1702.     }
  1703.     }
  1704. }
  1705.  
  1706.  
  1707. int
  1708. castle (side, kf, kt, iop)
  1709.      short int side;
  1710.      short int kf;
  1711.      short int kt;
  1712.      short int iop;
  1713.  
  1714. /* Make or Unmake a castling move. */
  1715.  
  1716. {
  1717.   register short rf, rt, t0, xside;
  1718.  
  1719.   xside = otherside[side];
  1720.   if (kt > kf)
  1721.     {
  1722.       rf = kf + 3;
  1723.       rt = kt - 1;
  1724.     }
  1725.   else
  1726.     {
  1727.       rf = kf - 4;
  1728.       rt = kt + 1;
  1729.     }
  1730.   if (iop == 0)
  1731.     {
  1732.       if (kf != kingP[side] ||
  1733.       board[kf] != king ||
  1734.       board[rf] != rook ||
  1735.       Mvboard[kf] != 0 ||
  1736.       Mvboard[rf] != 0 ||
  1737.       color[kt] != neutral ||
  1738.       color[rt] != neutral ||
  1739.       color[kt - 1] != neutral ||
  1740.       SqAtakd (kf, xside) ||
  1741.       SqAtakd (kt, xside) ||
  1742.       SqAtakd (rt, xside))
  1743.     return (false);
  1744.  
  1745.     }
  1746.   else
  1747.     {
  1748.       if (iop == 1)
  1749.     {
  1750.       castld[side] = true;
  1751.       Mvboard[kf]++;
  1752.       Mvboard[rf]++;
  1753.     }
  1754.       else
  1755.     {
  1756.       castld[side] = false;
  1757.       Mvboard[kf]--;
  1758.       Mvboard[rf]--;
  1759.       t0 = kt;
  1760.       kt = kf;
  1761.       kf = t0;
  1762.       t0 = rt;
  1763.       rt = rf;
  1764.       rf = t0;
  1765.     }
  1766.       board[kt] = king;
  1767.       color[kt] = side;
  1768.       Pindex[kt] = 0;
  1769.       board[kf] = no_piece;
  1770.       color[kf] = neutral;
  1771.       board[rt] = rook;
  1772.       color[rt] = side;
  1773.       Pindex[rt] = Pindex[rf];
  1774.       board[rf] = no_piece;
  1775.       color[rf] = neutral;
  1776.       PieceList[side][Pindex[kt]] = kt;
  1777.       PieceList[side][Pindex[rt]] = rt;
  1778. #if ttblsz
  1779.       if (hashflag)
  1780.     {
  1781.       UpdateHashbd (side, king, kf, kt);
  1782.       UpdateHashbd (side, rook, rf, rt);
  1783.     }
  1784. #endif /* ttblsz */
  1785.     }
  1786.   return (true);
  1787. }
  1788.  
  1789.  
  1790. inline void
  1791. EnPassant (xside, f, t, iop)
  1792.      short int xside;
  1793.      short int f;
  1794.      short int t;
  1795.      short int iop;
  1796.  
  1797. /*
  1798.   Make or unmake an en passant move.
  1799. */
  1800.  
  1801. {
  1802.   register short l;
  1803.  
  1804.   if (t > f)
  1805.     l = t - 8;
  1806.   else
  1807.     l = t + 8;
  1808.   if (iop == 1)
  1809.     {
  1810.       board[l] = no_piece;
  1811.       color[l] = neutral;
  1812.     }
  1813.   else
  1814.     {
  1815.       board[l] = pawn;
  1816.       color[l] = xside;
  1817.     }
  1818.   InitializeStats ();
  1819. }
  1820.  
  1821.  
  1822. inline void
  1823. UpdatePieceList (side, sq, iop)
  1824.      short int side;
  1825.      short int sq;
  1826.      short int iop;
  1827.  
  1828. /*
  1829.   Update the PieceList and Pindex arrays when a piece is captured or when a
  1830.   capture is unmade.
  1831. */
  1832.  
  1833. {
  1834.   register short i;
  1835.   if (iop == 1)
  1836.     {
  1837.       PieceCnt[side]--;
  1838.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1839.     {
  1840.       PieceList[side][i] = PieceList[side][i + 1];
  1841.       Pindex[PieceList[side][i]] = i;
  1842.     }
  1843.     }
  1844.   else
  1845.     {
  1846.       PieceCnt[side]++;
  1847.       PieceList[side][PieceCnt[side]] = sq;
  1848.       Pindex[sq] = PieceCnt[side];
  1849.     }
  1850. }
  1851.  
  1852. void
  1853. MakeMove (side, node, tempb, tempc, tempsf, tempst)
  1854.      short int side;
  1855.      struct leaf *node;
  1856.      short int *tempb;
  1857.      short int *tempc;
  1858.      short int *tempsf;
  1859.      short int *tempst;
  1860.  
  1861. /*
  1862.   Update Arrays board[], color[], and Pindex[] to reflect the new board
  1863.   position obtained after making the move pointed to by node. Also update
  1864.   miscellaneous stuff that changes when a move is made.
  1865. */
  1866.  
  1867. {
  1868.   register short f, t, xside, ct, cf;
  1869.  
  1870.   xside = otherside[side];
  1871.   f = node->f;
  1872.   t = node->t;
  1873.   epsquare = -1;
  1874.   FROMsquare = f;
  1875.   TOsquare = t;
  1876.   INCscore = 0;
  1877.   GameList[++GameCnt].gmove = (f << 8) | t;
  1878.  
  1879.   if (node->flags & cstlmask)
  1880.     {
  1881.       GameList[GameCnt].piece = no_piece;
  1882.       GameList[GameCnt].color = side;
  1883.       (void) castle (side, f, t, 1);
  1884.     }
  1885.   else
  1886.     {
  1887.       *tempc = color[t];
  1888.       *tempb = board[t];
  1889.       *tempsf = svalue[f];
  1890.       *tempst = svalue[t];
  1891.       GameList[GameCnt].piece = *tempb;
  1892.       GameList[GameCnt].color = *tempc;
  1893.       if (*tempc != neutral)
  1894.     {
  1895.       UpdatePieceList (*tempc, t, 1);
  1896.       if (*tempb == pawn)
  1897.         --PawnCnt[*tempc][column (t)];
  1898.       if (board[f] == pawn)
  1899.         {
  1900.           --PawnCnt[side][column (f)];
  1901.           ++PawnCnt[side][column (t)];
  1902.           cf = column (f);
  1903.           ct = column (t);
  1904.           if (PawnCnt[side][ct] > 1 + PawnCnt[side][cf])
  1905.         INCscore -= 15;
  1906.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1907.         INCscore += 15;
  1908.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1909.         INCscore -= 15;
  1910.         }
  1911.       mtl[xside] -= value[*tempb];
  1912.       if (*tempb == pawn)
  1913.         pmtl[xside] -= valueP;
  1914. #if ttblsz
  1915.       if (hashflag)
  1916.         UpdateHashbd (xside, *tempb, -1, t);
  1917. #endif /* ttblsz */
  1918.       INCscore += *tempst;
  1919.       Mvboard[t]++;
  1920.     }
  1921.       color[t] = color[f];
  1922.       board[t] = board[f];
  1923.       svalue[t] = svalue[f];
  1924.       Pindex[t] = Pindex[f];
  1925.       PieceList[side][Pindex[t]] = t;
  1926.       color[f] = neutral;
  1927.       board[f] = no_piece;
  1928.       if (board[t] == pawn)
  1929.     if (t - f == 16)
  1930.       epsquare = f + 8;
  1931.     else if (f - t == 16)
  1932.       epsquare = f - 8;
  1933.       if (node->flags & promote)
  1934.     {
  1935.       board[t] = node->flags & pmask;
  1936.       if (board[t] == queen)
  1937.         HasQueen[side]++;
  1938.       else if (board[t] == rook)
  1939.         HasRook[side]++;
  1940.       else if (board[t] == bishop)
  1941.         HasBishop[side]++;
  1942.       else if (board[t] == knight)
  1943.         HasKnight[side]++;
  1944.       --PawnCnt[side][column (t)];
  1945.       mtl[side] += value[board[t]] - valueP;
  1946.       pmtl[side] -= valueP;
  1947. #if ttblsz
  1948.       if (hashflag)
  1949.         {
  1950.           UpdateHashbd (side, pawn, f, -1);
  1951.           UpdateHashbd (side, board[t], f, -1);
  1952.         }
  1953. #endif /* ttblsz */
  1954.       INCscore -= *tempsf;
  1955.     }
  1956.       if (node->flags & epmask)
  1957.     EnPassant (xside, f, t, 1);
  1958.       else
  1959. #if ttblsz
  1960.       if (hashflag)
  1961.     UpdateHashbd (side, board[t], f, t);
  1962. #endif /* ttblsz */
  1963.       Mvboard[f]++;
  1964.     }
  1965. }
  1966.  
  1967. void
  1968. UnmakeMove (side, node, tempb, tempc, tempsf, tempst)
  1969.      short int side;
  1970.      struct leaf *node;
  1971.      short int *tempb;
  1972.      short int *tempc;
  1973.      short int *tempsf;
  1974.      short int *tempst;
  1975.  
  1976. /*
  1977.   Take back a move.
  1978. */
  1979.  
  1980. {
  1981.   register short f, t, xside;
  1982.  
  1983.   xside = otherside[side];
  1984.   f = node->f;
  1985.   t = node->t;
  1986.   epsquare = -1;
  1987.   GameCnt--;
  1988.   if (node->flags & cstlmask)
  1989.     (void) castle (side, f, t, 2);
  1990.   else
  1991.     {
  1992.       color[f] = color[t];
  1993.       board[f] = board[t];
  1994.       svalue[f] = *tempsf;
  1995.       Pindex[f] = Pindex[t];
  1996.       PieceList[side][Pindex[f]] = f;
  1997.       color[t] = *tempc;
  1998.       board[t] = *tempb;
  1999.       svalue[t] = *tempst;
  2000.       if (node->flags & promote)
  2001.     {
  2002.       board[f] = pawn;
  2003.       ++PawnCnt[side][column (t)];
  2004.       mtl[side] += valueP - value[node->flags & pmask];
  2005.       pmtl[side] += valueP;
  2006. #if ttblsz
  2007.       if (hashflag)
  2008.         {
  2009.           UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  2010.           UpdateHashbd (side, pawn, -1, t);
  2011.         }
  2012. #endif /* ttblsz */
  2013.     }
  2014.       if (*tempc != neutral)
  2015.     {
  2016.       UpdatePieceList (*tempc, t, 2);
  2017.       if (*tempb == pawn)
  2018.         ++PawnCnt[*tempc][column (t)];
  2019.       if (board[f] == pawn)
  2020.         {
  2021.           --PawnCnt[side][column (t)];
  2022.           ++PawnCnt[side][column (f)];
  2023.         }
  2024.       mtl[xside] += value[*tempb];
  2025.       if (*tempb == pawn)
  2026.         pmtl[xside] += valueP;
  2027. #if ttblsz
  2028.       if (hashflag)
  2029.         UpdateHashbd (xside, *tempb, -1, t);
  2030. #endif /* ttblsz */
  2031.       Mvboard[t]--;
  2032.     }
  2033.       if (node->flags & epmask)
  2034.     EnPassant (xside, f, t, 2);
  2035.       else
  2036. #if ttblsz
  2037.       if (hashflag)
  2038.     UpdateHashbd (side, board[f], f, t);
  2039. #endif /* ttblsz */
  2040.       Mvboard[f]--;
  2041.     }
  2042. }
  2043.  
  2044.  
  2045. #if ttblsz
  2046. void
  2047. UpdateHashbd (side, piece, f, t)
  2048.      short int side;
  2049.      short int piece;
  2050.      short int f;
  2051.      short int t;
  2052.  
  2053. /*
  2054.   hashbd contains a 32 bit "signature" of the board position. hashkey
  2055.   contains a 16 bit code used to address the hash table. When a move is
  2056.   made, XOR'ing the hashcode of moved piece on the from and to squares with
  2057.   the hashbd and hashkey values keeps things current.
  2058. */
  2059.  
  2060. {
  2061.   if (f >= 0)
  2062.     {
  2063.       hashbd ^= hashcode[side][piece][f].bd;
  2064.       hashkey ^= hashcode[side][piece][f].key;
  2065.     }
  2066.   if (t >= 0)
  2067.     {
  2068.       hashbd ^= hashcode[side][piece][t].bd;
  2069.       hashkey ^= hashcode[side][piece][t].key;
  2070.     }
  2071. }
  2072.  
  2073. #endif /* ttblsz */
  2074.  
  2075. void
  2076. InitializeStats ()
  2077. /*
  2078.   Scan thru the board seeing what's on each square. If a piece is found,
  2079.   update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  2080.   determine the material for each side and set the hashkey and hashbd
  2081.   variables to represent the current board position. Array
  2082.   PieceList[side][indx] contains the location of all the pieces of either
  2083.   side. Array Pindex[sq] contains the indx into PieceList for a given
  2084.   square.
  2085. */
  2086. {
  2087.   register short i, sq;
  2088.   epsquare = -1;
  2089.   for (i = 0; i < 8; i++)
  2090.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  2091.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  2092.   PieceCnt[white] = PieceCnt[black] = 0;
  2093. #if ttblsz
  2094.   hashbd = hashkey = 0;
  2095. #endif /* ttblsz */
  2096.   for (sq = 0; sq < 64; sq++)
  2097.     if (color[sq] != neutral)
  2098.       {
  2099.     mtl[color[sq]] += value[board[sq]];
  2100.     if (board[sq] == pawn)
  2101.       {
  2102.         pmtl[color[sq]] += valueP;
  2103.         ++PawnCnt[color[sq]][column (sq)];
  2104.       }
  2105.     if (board[sq] == king)
  2106.       Pindex[sq] = 0;
  2107.     else
  2108.       Pindex[sq] = ++PieceCnt[color[sq]];
  2109.     PieceList[color[sq]][Pindex[sq]] = sq;
  2110. #if ttblsz
  2111.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  2112.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  2113. #endif /* ttblsz */
  2114.       }
  2115. }
  2116.  
  2117.  
  2118. int
  2119. SqAtakd (sq, side)
  2120.      short int sq;
  2121.      short int side;
  2122.  
  2123. /*
  2124.   See if any piece with color 'side' ataks sq.  First check pawns then Queen,
  2125.   Bishop, Rook and King and last Knight.
  2126. */
  2127.  
  2128. {
  2129.   register short u;
  2130.   register unsigned char *ppos, *pdir;
  2131.   short xside;
  2132.  
  2133.   xside = otherside[side];
  2134.   pdir = nextdir[ptype[xside][pawn]][sq];
  2135.   u = pdir[sq];        /* follow captures thread */
  2136.   if (u != sq)
  2137.     {
  2138.       if (board[u] == pawn && color[u] == side)
  2139.     return (true);
  2140.       u = pdir[u];
  2141.       if (u != sq && board[u] == pawn && color[u] == side)
  2142.     return (true);
  2143.     }
  2144.   /* king capture */
  2145.   if (distance (sq, PieceList[side][0]) == 1)
  2146.     return (true);
  2147.   /* try a queen bishop capture */
  2148.   ppos = nextpos[bishop][sq];
  2149.   pdir = nextdir[bishop][sq];
  2150.   u = ppos[sq];
  2151.   do
  2152.     {
  2153.       if (color[u] == neutral)
  2154.     u = ppos[u];
  2155.       else
  2156.     {
  2157.       if (color[u] == side &&
  2158.           (board[u] == queen || board[u] == bishop))
  2159.         return (true);
  2160.       u = pdir[u];
  2161.     }
  2162.   } while (u != sq);
  2163.   /* try a queen rook capture */
  2164.   ppos = nextpos[rook][sq];
  2165.   pdir = nextdir[rook][sq];
  2166.   u = ppos[sq];
  2167.   do
  2168.     {
  2169.       if (color[u] == neutral)
  2170.     u = ppos[u];
  2171.       else
  2172.     {
  2173.       if (color[u] == side &&
  2174.           (board[u] == queen || board[u] == rook))
  2175.         return (true);
  2176.       u = pdir[u];
  2177.     }
  2178.   } while (u != sq);
  2179.   /* try a knight capture */
  2180.   ppos = nextpos[knight][sq];
  2181.   pdir = nextdir[knight][sq];
  2182.   u = ppos[sq];
  2183.   do
  2184.     {
  2185.       if (color[u] == side && board[u] == knight)
  2186.     return (true);
  2187.       u = pdir[u];
  2188.   } while (u != sq);
  2189.   return (false);
  2190. }
  2191.  
  2192. inline void
  2193. ataks (side, a)
  2194.      short int side;
  2195.      short int *a;
  2196.  
  2197. /*
  2198.   Fill array atak[][] with info about ataks to a square.  Bits 8-15 are set
  2199.   if the piece (king..pawn) ataks the square.  Bits 0-7 contain a count of
  2200.   total ataks to the square.
  2201. */
  2202.  
  2203. {
  2204.   register short u, c, sq;
  2205.   register unsigned char *ppos, *pdir;
  2206.   short i, piece, *PL;
  2207.  
  2208. #ifdef NOMEMSET
  2209.   for (u = 64; u; a[--u] = 0) ;
  2210. #else
  2211.   memset ((char *) a, 0, 64 * sizeof (a[0]));
  2212. #endif /* NOMEMSET */
  2213.   PL = PieceList[side];
  2214.   for (i = PieceCnt[side]; i >= 0; i--)
  2215.     {
  2216.       sq = PL[i];
  2217.       piece = board[sq];
  2218.       c = control[piece];
  2219.       if (sweep[piece])
  2220.     {
  2221.       ppos = nextpos[piece][sq];
  2222.       pdir = nextdir[piece][sq];
  2223.       u = ppos[sq];
  2224.       do
  2225.         {
  2226.           a[u] = ++a[u] | c;
  2227.           u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2228.       } while (u != sq);
  2229.     }
  2230.       else
  2231.     {
  2232.       pdir = nextdir[ptype[side][piece]][sq];
  2233.       u = pdir[sq];    /* follow captures thread for pawns */
  2234.       do
  2235.         {
  2236.           a[u] = ++a[u] | c;
  2237.           u = pdir[u];
  2238.       } while (u != sq);
  2239.     }
  2240.     }
  2241. }
  2242.  
  2243. /* ............    POSITIONAL EVALUATION ROUTINES    ............ */
  2244.  
  2245. int
  2246. evaluate (side, xside, ply, alpha, beta)
  2247.      short int side;
  2248.      short int xside;
  2249.      short int ply;
  2250.      short int alpha;
  2251.      short int beta;
  2252. /*
  2253.   Compute an estimate of the score by adding the positional score from the
  2254.   previous ply to the material difference. If this score falls inside a
  2255.   window which is 180 points wider than the alpha-beta window (or within a
  2256.   50 point window during quiescence search) call ScorePosition() to
  2257.   determine a score, otherwise return the estimated score. If one side has
  2258.   only a king and the other either has no pawns or no pieces then the
  2259.   function ScoreLoneKing() is called.
  2260. */
  2261.  
  2262. {
  2263.   register short evflag;
  2264.   short s;
  2265.  
  2266.   s = -Pscore[ply - 1] + mtl[side] - mtl[xside] - INCscore;
  2267.   hung[white] = hung[black] = 0;
  2268.  
  2269.   if (slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
  2270.      (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0))))
  2271.     evflag = false;
  2272.   else
  2273.     evflag =
  2274.         (ply == 1 || ply < Sdepth ||
  2275.         ((ply == Sdepth + 1 || ply == Sdepth + 2) &&
  2276.         (s > alpha - xwndw && s < beta + xwndw)) ||
  2277.         (ply > Sdepth + 2 && s >= alpha - 25 && s <= beta + 25));
  2278.  
  2279.   if (evflag)
  2280.     {
  2281.       EvalNodes++;
  2282.       ataks (side, atak[side]);
  2283.       if (atak[side][PieceList[xside][0]] > 0)
  2284.             return (10001 - ply);
  2285.       ataks (xside, atak[xside]);
  2286.       InChk = (atak[xside][PieceList[side][0]] > 0);
  2287.       ScorePosition (side, &s);
  2288.     }
  2289.   else
  2290.     {
  2291.       if (SqAtakd (PieceList[xside][0], side))
  2292.             return (10001 - ply);
  2293.       InChk = SqAtakd (PieceList[side][0], xside);
  2294.       if (slk)
  2295.             ScoreLoneKing (side, &s);
  2296.     }
  2297.  
  2298.   Pscore[ply] = s - mtl[side] + mtl[xside];
  2299.   if (InChk)
  2300.     ChkFlag[ply - 1] = Pindex[TOsquare];
  2301.   else
  2302.     ChkFlag[ply - 1] = 0;
  2303.   return (s);
  2304. }
  2305.  
  2306. void
  2307. ScorePosition (side, score)
  2308.      short int side;
  2309.      short int *score;
  2310. /*
  2311.   Perform normal static evaluation of board position. A score is generated
  2312.   for each piece and these are summed to get a score for each side.
  2313. */
  2314.  
  2315. {
  2316.   register short sq, s, i, xside;
  2317.   short pscore[3];
  2318.  
  2319.   wking = PieceList[white][0];
  2320.   bking = PieceList[black][0];
  2321.   UpdateWeights ();
  2322.   xside = otherside[side];
  2323.   pscore[white] = pscore[black] = 0;
  2324.  
  2325.   for (c1 = white; c1 <= black; c1++)
  2326.     {
  2327.       c2 = otherside[c1];
  2328.       if (c1 == white)
  2329.             EnemyKing = bking;
  2330.       else
  2331.             EnemyKing = wking;
  2332.       atk1 = atak[c1];
  2333.       atk2 = atak[c2];
  2334.       PC1 = PawnCnt[c1];
  2335.       PC2 = PawnCnt[c2];
  2336.       for (i = 0; i <= PieceCnt[c1]; i++)
  2337.     {
  2338.       sq = PieceList[c1][i];
  2339.       s = SqValue (sq, side);
  2340.       pscore[c1] += s;
  2341.       svalue[sq] = s;
  2342.     }
  2343.     }
  2344.   if (hung[side] > 1)
  2345.     pscore[side] += HUNGX;
  2346.   if (hung[xside] > 1)
  2347.     pscore[xside] += HUNGX;
  2348.  
  2349.   *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
  2350.   if (dither)
  2351.     *score += rand () % dither;
  2352.  
  2353.   if (*score > 0 && pmtl[side] == 0)
  2354.     if (emtl[side] < valueR)
  2355.       *score = 0;
  2356.     else if (*score < valueR)
  2357.       *score /= 2;
  2358.   if (*score < 0 && pmtl[xside] == 0)
  2359.     if (emtl[xside] < valueR)
  2360.       *score = 0;
  2361.     else if (-*score < valueR)
  2362.       *score /= 2;
  2363.  
  2364.   if (mtl[xside] == valueK && emtl[side] > valueB)
  2365.     *score += 200;
  2366.   if (mtl[side] == valueK && emtl[xside] > valueB)
  2367.     *score -= 200;
  2368. }
  2369.  
  2370. void
  2371. ScoreLoneKing (side, score)
  2372.      short int side;
  2373.      short int *score;
  2374.  
  2375. /*
  2376.   Static evaluation when loser has only a king and winner has no pawns or no
  2377.   pieces.
  2378. */
  2379.  
  2380. {
  2381.   register short winner, loser, king1, king2, s, i;
  2382.  
  2383.   UpdateWeights ();
  2384.   if (mtl[white] > mtl[black])
  2385.     winner = white;
  2386.   else
  2387.     winner = black;
  2388.   loser = otherside[winner];
  2389.   king1 = PieceList[winner][0];
  2390.   king2 = PieceList[loser][0];
  2391.  
  2392.   s = 0;
  2393.  
  2394.   if (pmtl[winner] > 0)
  2395.     for (i = 1; i <= PieceCnt[winner]; i++)
  2396.       s += ScoreKPK (side, winner, loser, king1, king2, PieceList[winner][i]);
  2397.  
  2398.   else if (emtl[winner] == valueB + valueN)
  2399.     s = ScoreKBNK (winner, king1, king2);
  2400.  
  2401.   else if (emtl[winner] > valueB)
  2402.     s = 500 + emtl[winner] - DyingKing[king2] - 2 * distance (king1, king2);
  2403.  
  2404.   if (side == winner)
  2405.     *score = s;
  2406.   else
  2407.     *score = -s;
  2408. }
  2409.  
  2410.  
  2411. int
  2412. ScoreKPK (side, winner, loser, king1, king2, sq)
  2413.      short int side;
  2414.      short int winner;
  2415.      short int loser;
  2416.      short int king1;
  2417.      short int king2;
  2418.      short int sq;
  2419.  
  2420. /*
  2421.   Score King and Pawns versus King endings.
  2422. */
  2423.  
  2424. {
  2425.   register short s, r;
  2426.  
  2427.   if (PieceCnt[winner] == 1)
  2428.     s = 50;
  2429.   else
  2430.     s = 120;
  2431.   if (winner == white)
  2432.     {
  2433.       if (side == loser)
  2434.     r = row (sq) - 1;
  2435.       else
  2436.     r = row (sq);
  2437.       if (row (king2) >= r && distance (sq, king2) < 8 - r)
  2438.     s += 10 * row (sq);
  2439.       else
  2440.     s = 500 + 50 * row (sq);
  2441.       if (row (sq) < 6)
  2442.     sq += 16;
  2443.       else
  2444.     sq += 8;
  2445.     }
  2446.   else
  2447.     {
  2448.       if (side == loser)
  2449.     r = row (sq) + 1;
  2450.       else
  2451.     r = row (sq);
  2452.       if (row (king2) <= r && distance (sq, king2) < r + 1)
  2453.     s += 10 * (7 - row (sq));
  2454.       else
  2455.     s = 500 + 50 * (7 - row (sq));
  2456.       if (row (sq) > 1)
  2457.     sq -= 16;
  2458.       else
  2459.     sq -= 8;
  2460.     }
  2461.   s += 8 * (taxicab (king2, sq) - taxicab (king1, sq));
  2462.   return (s);
  2463. }
  2464.  
  2465.  
  2466. int
  2467. ScoreKBNK (winner, king1, king2)
  2468.      short int winner;
  2469.      short int king1;
  2470.      short int king2;
  2471.  
  2472.  
  2473. /*
  2474.   Score King+Bishop+Knight versus King endings.
  2475.   This doesn't work all that well but it's better than nothing.
  2476. */
  2477.  
  2478. {
  2479.   register short s;
  2480.  
  2481.   s = emtl[winner] - 300;
  2482.   if (KBNKsq == 0)
  2483.     s += KBNK[king2];
  2484.   else
  2485.     s += KBNK[locn (row (king2), 7 - column (king2))];
  2486.   s -= taxicab (king1, king2);
  2487.   s -= distance (PieceList[winner][1], king2);
  2488.   s -= distance (PieceList[winner][2], king2);
  2489.   return (s);
  2490. }
  2491.  
  2492.  
  2493. inline void
  2494. BRscan (sq, s, mob)
  2495.      short int sq;
  2496.      short int *s;
  2497.      short int *mob;
  2498.  
  2499. /*
  2500.   Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
  2501.   hung[] array if a pin is found.
  2502. */
  2503. {
  2504.   register short u, piece, pin;
  2505.   register unsigned char *ppos, *pdir;
  2506.   short *Kf;
  2507.  
  2508.   Kf = Kfield[c1];
  2509.   *mob = 0;
  2510.   piece = board[sq];
  2511.   ppos = nextpos[piece][sq];
  2512.   pdir = nextdir[piece][sq];
  2513.   u = ppos[sq];
  2514.   pin = -1;            /* start new direction */
  2515.   do
  2516.     {
  2517.       *s += Kf[u];
  2518.       if (color[u] == neutral)
  2519.     {
  2520.       (*mob)++;
  2521.       if (ppos[u] == pdir[u])
  2522.         pin = -1;        /* oops new direction */
  2523.       u = ppos[u];
  2524.     }
  2525.       else if (pin < 0)
  2526.     {
  2527.       if (board[u] == pawn || board[u] == king)
  2528.         u = pdir[u];
  2529.       else
  2530.         {
  2531.           if (ppos[u] != pdir[u])
  2532.         pin = u;    /* not on the edge and on to find a pin */
  2533.           u = ppos[u];
  2534.         }
  2535.     }
  2536.       else
  2537.     {
  2538.       if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
  2539.         {
  2540.           if (color[pin] == c2)
  2541.         {
  2542.           *s += PINVAL;
  2543.           if (atk2[pin] == 0 ||
  2544.               atk1[pin] > control[board[pin]] + 1)
  2545.             ++hung[c2];
  2546.         }
  2547.           else
  2548.         *s += XRAY;
  2549.         }
  2550.       pin = -1;        /* new direction */
  2551.       u = pdir[u];
  2552.     }
  2553.   } while (u != sq);
  2554. }
  2555.  
  2556. int
  2557. SqValue (sq, side)
  2558.      short int sq;
  2559.      short int side;
  2560.  
  2561. /*
  2562.   Calculate the positional value for the piece on 'sq'.
  2563. */
  2564.  
  2565. {
  2566.   register short j, fyle, rank;
  2567.   short s, piece, a1, a2, in_square, r, mob, e, c;
  2568.  
  2569.   piece = board[sq];
  2570.   a1 = (atk1[sq] & 0x4FFF);
  2571.   a2 = (atk2[sq] & 0x4FFF);
  2572.   rank = row (sq);
  2573.   fyle = column (sq);
  2574.   s = 0;
  2575.   if (piece == pawn && c1 == white)
  2576.     {
  2577.       s = Mwpawn[sq];
  2578.       if (sq == 11 || sq == 12)
  2579.     if (color[sq + 8] != neutral)
  2580.       s += PEDRNK2B;
  2581.       if ((fyle == 0 || PC1[fyle - 1] == 0) &&
  2582.       (fyle == 7 || PC1[fyle + 1] == 0))
  2583.     s += ISOLANI[fyle];
  2584.       else if (PC1[fyle] > 1)
  2585.     s += PDOUBLED;
  2586.       if (a1 < ctlP && atk1[sq + 8] < ctlP)
  2587.     {
  2588.       s += BACKWARD[a2 & 0xFF];
  2589.       if (PC2[fyle] == 0)
  2590.         s += PWEAKH;
  2591.       if (color[sq + 8] != neutral)
  2592.         s += PBLOK;
  2593.     }
  2594.       if (PC2[fyle] == 0)
  2595.     {
  2596.       if (side == black)
  2597.         r = rank - 1;
  2598.       else
  2599.         r = rank;
  2600.       in_square = (row (bking) >= r && distance (sq, bking) < 8 - r);
  2601.       if (a2 == 0 || side == white)
  2602.         e = 0;
  2603.       else
  2604.         e = 1;
  2605.       for (j = sq + 8; j < 64; j += 8)
  2606.         if (atk2[j] >= ctlP)
  2607.           {
  2608.         e = 2;
  2609.         break;
  2610.           }
  2611.         else if (atk2[j] > 0 || color[j] != neutral)
  2612.           e = 1;
  2613.       if (e == 2)
  2614.         s += (stage * PassedPawn3[rank]) / 10;
  2615.       else if (in_square || e == 1)
  2616.         s += (stage * PassedPawn2[rank]) / 10;
  2617.       else if (emtl[black] > 0)
  2618.         s += (stage * PassedPawn1[rank]) / 10;
  2619.       else
  2620.         s += PassedPawn0[rank];
  2621.     }
  2622.     }
  2623.   else if (piece == pawn && c1 == black)
  2624.     {
  2625.       s = Mbpawn[sq];
  2626.       if (sq == 51 || sq == 52)
  2627.     if (color[sq - 8] != neutral)
  2628.       s += PEDRNK2B;
  2629.       if ((fyle == 0 || PC1[fyle - 1] == 0) &&
  2630.       (fyle == 7 || PC1[fyle + 1] == 0))
  2631.     s += ISOLANI[fyle];
  2632.       else if (PC1[fyle] > 1)
  2633.     s += PDOUBLED;
  2634.       if (a1 < ctlP && atk1[sq - 8] < ctlP)
  2635.     {
  2636.       s += BACKWARD[a2 & 0xFF];
  2637.       if (PC2[fyle] == 0)
  2638.         s += PWEAKH;
  2639.       if (color[sq - 8] != neutral)
  2640.         s += PBLOK;
  2641.     }
  2642.       if (PC2[fyle] == 0)
  2643.     {
  2644.       if (side == white)
  2645.         r = rank + 1;
  2646.       else
  2647.         r = rank;
  2648.       in_square = (row (wking) <= r && distance (sq, wking) < r + 1);
  2649.       if (a2 == 0 || side == black)
  2650.         e = 0;
  2651.       else
  2652.         e = 1;
  2653.       for (j = sq - 8; j >= 0; j -= 8)
  2654.         if (atk2[j] >= ctlP)
  2655.           {
  2656.         e = 2;
  2657.         break;
  2658.           }
  2659.         else if (atk2[j] > 0 || color[j] != neutral)
  2660.           e = 1;
  2661.       if (e == 2)
  2662.         s += (stage * PassedPawn3[7 - rank]) / 10;
  2663.       else if (in_square || e == 1)
  2664.         s += (stage * PassedPawn2[7 - rank]) / 10;
  2665.       else if (emtl[white] > 0)
  2666.         s += (stage * PassedPawn1[7 - rank]) / 10;
  2667.       else
  2668.         s += PassedPawn0[7 - rank];
  2669.     }
  2670.     }
  2671.   else if (piece == knight)
  2672.     {
  2673.       s = Mknight[c1][sq];
  2674.     }
  2675.   else if (piece == bishop)
  2676.     {
  2677.       s = Mbishop[c1][sq];
  2678.       BRscan (sq, &s, &mob);
  2679.       s += BMBLTY[mob];
  2680.     }
  2681.   else if (piece == rook)
  2682.     {
  2683.       s += RookBonus;
  2684.       BRscan (sq, &s, &mob);
  2685.       s += RMBLTY[mob];
  2686.       if (PC1[fyle] == 0)
  2687.     s += RHOPN;
  2688.       if (PC2[fyle] == 0)
  2689.     s += RHOPNX;
  2690.       if (rank == rank7[c1] && pmtl[c2] > 100)
  2691.     s += 10;
  2692.       if (stage > 2)
  2693.     s += 14 - taxicab (sq, EnemyKing);
  2694.     }
  2695.   else if (piece == queen)
  2696.     {
  2697.       if (stage > 2)
  2698.     s += 14 - taxicab (sq, EnemyKing);
  2699.       if (distance (sq, EnemyKing) < 3)
  2700.     s += 12;
  2701.     }
  2702.   else if (piece == king)
  2703.     {
  2704.       s = Mking[c1][sq];
  2705.       if (KSFTY > 0)
  2706.     if (Developed[c2] || stage > 0)
  2707.       KingScan (sq, &s);
  2708.       if (castld[c1])
  2709.     s += KCASTLD;
  2710.       else if (Mvboard[kingP[c1]])
  2711.     s += KMOVD;
  2712.  
  2713.       if (PC1[fyle] == 0)
  2714.     s += KHOPN;
  2715.       if (PC2[fyle] == 0)
  2716.     s += KHOPNX;
  2717.       if (fyle == 1 || fyle == 2 || fyle == 3 || fyle == 7)
  2718.     {
  2719.       if (PC1[fyle - 1] == 0)
  2720.         s += KHOPN;
  2721.       if (PC2[fyle - 1] == 0)
  2722.         s += KHOPNX;
  2723.     }
  2724.       if (fyle == 4 || fyle == 5 || fyle == 6 || fyle == 0)
  2725.     {
  2726.       if (PC1[fyle + 1] == 0)
  2727.         s += KHOPN;
  2728.       if (PC2[fyle + 1] == 0)
  2729.         s += KHOPNX;
  2730.     }
  2731.       if (fyle == 2)
  2732.     {
  2733.       if (PC1[0] == 0)
  2734.         s += KHOPN;
  2735.       if (PC2[0] == 0)
  2736.         s += KHOPNX;
  2737.     }
  2738.       if (fyle == 5)
  2739.     {
  2740.       if (PC1[7] == 0)
  2741.         s += KHOPN;
  2742.       if (PC2[7] == 0)
  2743.         s += KHOPNX;
  2744.     }
  2745.     }
  2746.   if (a2 > 0)
  2747.     {
  2748.       c = (control[piece] & 0x4FFF);
  2749.       if (a1 == 0 || a2 > c + 1)
  2750.     {
  2751.       s += HUNGP;
  2752.       ++hung[c1];
  2753.       if (piece != king && trapped (sq, piece))
  2754.         ++hung[c1];
  2755.     }
  2756.       else if (piece != pawn || a2 > a1)
  2757.     if (a2 >= c || a1 < ctlP)
  2758.       s += ATAKD;
  2759.     }
  2760.   return (s);
  2761. }
  2762.  
  2763. void
  2764. KingScan (sq, s)
  2765.      short int sq;
  2766.      short int *s;
  2767.  
  2768. /*
  2769.   Assign penalties if king can be threatened by checks, if squares
  2770.   near the king are controlled by the enemy (especially the queen),
  2771.   or if there are no pawns near the king.
  2772.   The following must be true:
  2773.   board[sq] == king
  2774.   c1 == color[sq]
  2775.   c2 == otherside[c1]
  2776. */
  2777.  
  2778. #define ScoreThreat \
  2779. if (color[u] != c2)\
  2780.   if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
  2781.   else *s -= 3
  2782.  
  2783. {
  2784.   register short u;
  2785.   register unsigned char *ppos, *pdir;
  2786.   register short cnt, ok;
  2787.  
  2788.   cnt = 0;
  2789.   if (HasBishop[c2] || HasQueen[c2])
  2790.     {
  2791.       ppos = nextpos[bishop][sq];
  2792.       pdir = nextdir[bishop][sq];
  2793.       u = ppos[sq];
  2794.       do
  2795.     {
  2796.       if (atk2[u] & ctlBQ)
  2797.         ScoreThreat;
  2798.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2799.       } while (u != sq);
  2800.     }
  2801.   if (HasRook[c2] || HasQueen[c2])
  2802.     {
  2803.       ppos = nextpos[rook][sq];
  2804.       pdir = nextdir[rook][sq];
  2805.       u = ppos[sq];
  2806.       do
  2807.     {
  2808.       if (atk2[u] & ctlRQ)
  2809.         ScoreThreat;
  2810.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2811.       } while (u != sq);
  2812.     }
  2813.   if (HasKnight[c2])
  2814.     {
  2815.       pdir = nextdir[knight][sq];
  2816.       u = pdir[sq];
  2817.       do
  2818.     {
  2819.       if (atk2[u] & ctlNN)
  2820.         ScoreThreat;
  2821.       u = pdir[u];
  2822.       } while (u != sq);
  2823.     }
  2824.   *s += (KSFTY * KTHRT[cnt]) / 16;
  2825.  
  2826.   cnt = 0;
  2827.   ok = false;
  2828.   pdir = nextpos[king][sq];
  2829.   u = pdir[sq];
  2830.   do
  2831.     {
  2832.       if (board[u] == pawn)
  2833.     ok = true;
  2834.       if (atk2[u] > atk1[u])
  2835.     {
  2836.       ++cnt;
  2837.       if (atk2[u] & ctlQ)
  2838.         if (atk2[u] > ctlQ + 1 && atk1[u] < ctlQ)
  2839.           *s -= 4 * KSFTY;
  2840.     }
  2841.       u = pdir[u];
  2842.   } while (u != sq);
  2843.   if (!ok)
  2844.     *s -= KSFTY;
  2845.   if (cnt > 1)
  2846.     *s -= KSFTY;
  2847. }
  2848.  
  2849.  
  2850. int
  2851. trapped (sq, piece)
  2852.      short int sq;
  2853.      short int piece;
  2854.  
  2855. /*
  2856.   See if the attacked piece has unattacked squares to move to.
  2857.   The following must be true:
  2858.   piece == board[sq]
  2859.   c1 == color[sq]
  2860.   c2 == otherside[c1]
  2861. */
  2862.  
  2863. {
  2864.   register short u;
  2865.   register unsigned char *ppos, *pdir;
  2866.  
  2867.   ppos = nextpos[ptype[c1][piece]][sq];
  2868.   pdir = nextdir[ptype[c1][piece]][sq];
  2869.   if (piece == pawn)
  2870.     {
  2871.       u = ppos[sq];    /* follow no captures thread */
  2872.       if (color[u] == neutral)
  2873.     {
  2874.       if (atk1[u] >= atk2[u])
  2875.         return (false);
  2876.       if (atk2[u] < ctlP)
  2877.         {
  2878.           u = ppos[u];
  2879.           if (color[u] == neutral && atk1[u] >= atk2[u])
  2880.         return (false);
  2881.         }
  2882.     }
  2883.       u = pdir[sq];    /* follow captures thread */
  2884.       if (color[u] == c2)
  2885.     return (false);
  2886.       u = pdir[u];
  2887.       if (color[u] == c2)
  2888.     return (false);
  2889.     }
  2890.   else
  2891.     {
  2892.       u = ppos[sq];
  2893.       do
  2894.     {
  2895.       if (color[u] != c1)
  2896.         if (atk2[u] == 0 || board[u] >= piece)
  2897.           return (false);
  2898.       u = (color[u] == neutral) ? ppos[u] : pdir[u];
  2899.       } while (u != sq);
  2900.     }
  2901.   return (true);
  2902. }
  2903.  
  2904.  
  2905. inline void
  2906. BlendBoard (a, b, c)
  2907.      const short int *a;
  2908.      const short int *b;
  2909.      short int *c;
  2910. {
  2911.   register int sq;
  2912.  
  2913.   for (sq = 0; sq < 64; sq++)
  2914.     c[sq] = (a[sq] * (10 - stage) + b[sq] * stage) / 10;
  2915. }
  2916.  
  2917.  
  2918. inline void
  2919. CopyBoard (a, b)
  2920.      const short int *a;
  2921.      short int *b;
  2922. {
  2923.   register int sq;
  2924.  
  2925.   for (sq = 0; sq < 64; sq++)
  2926.     b[sq] = a[sq];
  2927. }
  2928.  
  2929. void
  2930. ExaminePosition ()
  2931.  
  2932. /*
  2933.   This is done one time before the search is started. Set up arrays
  2934.   Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the
  2935.   SqValue() function to determine the positional value of each piece.
  2936. */
  2937.  
  2938. {
  2939.   register short i, sq;
  2940.   short wpadv, bpadv, wstrong, bstrong, z, side, pp, j, k, val, Pd, fyle, rank;
  2941.  
  2942.   wking = PieceList[white][0];
  2943.   bking = PieceList[black][0];
  2944.   ataks (white, atak[white]);
  2945.   ataks (black, atak[black]);
  2946.   Zwmtl = Zbmtl = 0;
  2947.   UpdateWeights ();
  2948.   HasPawn[white] = HasPawn[black] = 0;
  2949.   HasKnight[white] = HasKnight[black] = 0;
  2950.   HasBishop[white] = HasBishop[black] = 0;
  2951.   HasRook[white] = HasRook[black] = 0;
  2952.   HasQueen[white] = HasQueen[black] = 0;
  2953.   for (side = white; side <= black; side++)
  2954.     for (i = 0; i <= PieceCnt[side]; i++)
  2955.       switch (board[PieceList[side][i]])
  2956.     {
  2957.     case pawn:
  2958.       ++HasPawn[side];
  2959.       break;
  2960.     case knight:
  2961.       ++HasKnight[side];
  2962.       break;
  2963.     case bishop:
  2964.       ++HasBishop[side];
  2965.       break;
  2966.     case rook:
  2967.       ++HasRook[side];
  2968.       break;
  2969.     case queen:
  2970.       ++HasQueen[side];
  2971.       break;
  2972.     }
  2973.   if (!Developed[white])
  2974.     Developed[white] = (board[1] != knight && board[2] != bishop &&
  2975.             board[5] != bishop && board[6] != knight);
  2976.   if (!Developed[black])
  2977.     Developed[black] = (board[57] != knight && board[58] != bishop &&
  2978.             board[61] != bishop && board[62] != knight);
  2979.   if (!PawnStorm && stage < 5)
  2980.     PawnStorm = ((column (wking) < 3 && column (bking) > 4) ||
  2981.          (column (wking) > 4 && column (bking) < 3));
  2982.  
  2983.   CopyBoard (pknight, Mknight[white]);
  2984.   CopyBoard (pknight, Mknight[black]);
  2985.   CopyBoard (pbishop, Mbishop[white]);
  2986.   CopyBoard (pbishop, Mbishop[black]);
  2987.   BlendBoard (KingOpening, KingEnding, Mking[white]);
  2988.   BlendBoard (KingOpening, KingEnding, Mking[black]);
  2989.  
  2990.   for (sq = 0; sq < 64; sq++)
  2991.     {
  2992.       fyle = column (sq);
  2993.       rank = row (sq);
  2994.       wstrong = bstrong = true;
  2995.       for (i = sq; i < 64; i += 8)
  2996.     if (atak[black][i] >= ctlP)
  2997.       {
  2998.         wstrong = false;
  2999.         break;
  3000.       }
  3001.       for (i = sq; i >= 0; i -= 8)
  3002.     if (atak[white][i] >= ctlP)
  3003.       {
  3004.         bstrong = false;
  3005.         break;
  3006.       }
  3007.       wpadv = bpadv = PADVNCM;
  3008.       if ((fyle == 0 || PawnCnt[white][fyle - 1] == 0) &&
  3009.       (fyle == 7 || PawnCnt[white][fyle + 1] == 0))
  3010.     wpadv = PADVNCI;
  3011.       if ((fyle == 0 || PawnCnt[black][fyle - 1] == 0) &&
  3012.       (fyle == 7 || PawnCnt[black][fyle + 1] == 0))
  3013.     bpadv = PADVNCI;
  3014.       Mwpawn[sq] = (wpadv * PawnAdvance[sq]) / 10;
  3015.       Mbpawn[sq] = (bpadv * PawnAdvance[63 - sq]) / 10;
  3016.       Mwpawn[sq] += PawnBonus;
  3017.       Mbpawn[sq] += PawnBonus;
  3018.       if (Mvboard[kingP[white]])
  3019.     {
  3020.       if ((fyle < 3 || fyle > 4) && distance (sq, wking) < 3)
  3021.         Mwpawn[sq] += PAWNSHIELD;
  3022.     }
  3023.       else if (rank < 3 && (fyle < 2 || fyle > 5))
  3024.     Mwpawn[sq] += PAWNSHIELD / 2;
  3025.       if (Mvboard[kingP[black]])
  3026.     {
  3027.       if ((fyle < 3 || fyle > 4) && distance (sq, bking) < 3)
  3028.         Mbpawn[sq] += PAWNSHIELD;
  3029.     }
  3030.       else if (rank > 4 && (fyle < 2 || fyle > 5))
  3031.     Mbpawn[sq] += PAWNSHIELD / 2;
  3032.       if (PawnStorm)
  3033.     {
  3034.       if ((column (wking) < 4 && fyle > 4) ||
  3035.           (column (wking) > 3 && fyle < 3))
  3036.         Mwpawn[sq] += 3 * rank - 21;
  3037.       if ((column (bking) < 4 && fyle > 4) ||
  3038.           (column (bking) > 3 && fyle < 3))
  3039.         Mbpawn[sq] -= 3 * rank;
  3040.     }
  3041.       Mknight[white][sq] += 5 - distance (sq, bking);
  3042.       Mknight[white][sq] += 5 - distance (sq, wking);
  3043.       Mknight[black][sq] += 5 - distance (sq, wking);
  3044.       Mknight[black][sq] += 5 - distance (sq, bking);
  3045.       Mbishop[white][sq] += BishopBonus;
  3046.       Mbishop[black][sq] += BishopBonus;
  3047.       for (i = 0; i <= PieceCnt[black]; i++)
  3048.     if (distance (sq, PieceList[black][i]) < 3)
  3049.       Mknight[white][sq] += KNIGHTPOST;
  3050.       for (i = 0; i <= PieceCnt[white]; i++)
  3051.     if (distance (sq, PieceList[white][i]) < 3)
  3052.       Mknight[black][sq] += KNIGHTPOST;
  3053.       if (wstrong)
  3054.     Mknight[white][sq] += KNIGHTSTRONG;
  3055.       if (bstrong)
  3056.     Mknight[black][sq] += KNIGHTSTRONG;
  3057.       if (wstrong)
  3058.     Mbishop[white][sq] += BISHOPSTRONG;
  3059.       if (bstrong)
  3060.     Mbishop[black][sq] += BISHOPSTRONG;
  3061.  
  3062.       if (HasBishop[white] == 2)
  3063.     Mbishop[white][sq] += 8;
  3064.       if (HasBishop[black] == 2)
  3065.     Mbishop[black][sq] += 8;
  3066.       if (HasKnight[white] == 2)
  3067.     Mknight[white][sq] += 5;
  3068.       if (HasKnight[black] == 2)
  3069.     Mknight[black][sq] += 5;
  3070.  
  3071.       if (board[sq] == bishop)
  3072.     if (rank % 2 == fyle % 2)
  3073.       KBNKsq = 0;
  3074.     else
  3075.       KBNKsq = 7;
  3076.  
  3077.       Kfield[white][sq] = Kfield[black][sq] = 0;
  3078.       if (distance (sq, wking) == 1)
  3079.     Kfield[black][sq] = KATAK;
  3080.       if (distance (sq, bking) == 1)
  3081.     Kfield[white][sq] = KATAK;
  3082.  
  3083.       Pd = 0;
  3084.       for (k = 0; k <= PieceCnt[white]; k++)
  3085.     {
  3086.       i = PieceList[white][k];
  3087.       if (board[i] == pawn)
  3088.         {
  3089.           pp = true;
  3090.           if (row (i) == 6)
  3091.         z = i + 8;
  3092.           else
  3093.         z = i + 16;
  3094.           for (j = i + 8; j < 64; j += 8)
  3095.         if (atak[black][j] > ctlP || board[j] == pawn)
  3096.           {
  3097.             pp = false;
  3098.             break;
  3099.           }
  3100.           if (pp)
  3101.         Pd += 5 * taxicab (sq, z);
  3102.           else
  3103.         Pd += taxicab (sq, z);
  3104.         }
  3105.     }
  3106.       for (k = 0; k <= PieceCnt[black]; k++)
  3107.     {
  3108.       i = PieceList[black][k];
  3109.       if (board[i] == pawn)
  3110.         {
  3111.           pp = true;
  3112.           if (row (i) == 1)
  3113.         z = i - 8;
  3114.           else
  3115.         z = i - 16;
  3116.           for (j = i - 8; j >= 0; j -= 8)
  3117.         if (atak[white][j] > ctlP || board[j] == pawn)
  3118.           {
  3119.             pp = false;
  3120.             break;
  3121.           }
  3122.           if (pp)
  3123.         Pd += 5 * taxicab (sq, z);
  3124.           else
  3125.         Pd += taxicab (sq, z);
  3126.         }
  3127.     }
  3128.       if (Pd != 0)
  3129.     {
  3130.       val = (Pd * stage2) / 10;
  3131.       Mking[white][sq] -= val;
  3132.       Mking[black][sq] -= val;
  3133.     }
  3134.     }
  3135. }
  3136.  
  3137. void
  3138. UpdateWeights ()
  3139.  
  3140. /*
  3141.   If material balance has changed, determine the values for the positional
  3142.   evaluation terms.
  3143. */
  3144.  
  3145. {
  3146.   register short tmtl, s1;
  3147.  
  3148.   if (mtl[white] != Zwmtl || mtl[black] != Zbmtl)
  3149.     {
  3150.       Zwmtl = mtl[white];
  3151.       Zbmtl = mtl[black];
  3152.       emtl[white] = Zwmtl - pmtl[white] - valueK;
  3153.       emtl[black] = Zbmtl - pmtl[black] - valueK;
  3154.       tmtl = emtl[white] + emtl[black];
  3155.       s1 = (tmtl > 6600) ? 0 : ((tmtl < 1400) ? 10 : (6600 - tmtl) / 520);
  3156.       if (s1 != stage)
  3157.     {
  3158.       stage = s1;
  3159.       stage2 = (tmtl > 3600) ? 0 : ((tmtl < 1400) ? 10 : (3600 - tmtl) / 220);
  3160.       PEDRNK2B = -15;    /* centre pawn on 2nd rank & blocked */
  3161.       PBLOK = -4;        /* blocked backward pawn */
  3162.       PDOUBLED = -14;    /* doubled pawn */
  3163.       PWEAKH = -4;        /* weak pawn on half open file */
  3164.       PAWNSHIELD = 10 - stage;    /* pawn near friendly king */
  3165.       PADVNCM = 10;        /* advanced pawn multiplier */
  3166.       PADVNCI = 7;        /* muliplier for isolated pawn */
  3167.       PawnBonus = stage;
  3168.  
  3169.       KNIGHTPOST = (stage + 2) / 3;    /* knight near enemy pieces */
  3170.       KNIGHTSTRONG = (stage + 6) / 2;    /* occupies pawn hole */
  3171.  
  3172.       BISHOPSTRONG = (stage + 6) / 2;    /* occupies pawn hole */
  3173.       BishopBonus = 2 * stage;
  3174.  
  3175.       RHOPN = 10;        /* rook on half open file */
  3176.       RHOPNX = 4;
  3177.       RookBonus = 6 * stage;
  3178.  
  3179.       XRAY = 8;        /* Xray attack on piece */
  3180.       PINVAL = 10;        /* Pin */
  3181.  
  3182.       KHOPN = (3 * stage - 30) / 2;    /* king on half open file */
  3183.       KHOPNX = KHOPN / 2;
  3184.       KCASTLD = 10 - stage;
  3185.       KMOVD = -40 / (stage + 1);    /* king moved before castling */
  3186.       KATAK = (10 - stage) / 2;    /* B,R attacks near enemy king */
  3187.       if (stage < 8)
  3188.         KSFTY = 16 - 2 * stage;
  3189.       else
  3190.         KSFTY = 0;
  3191.  
  3192.       ATAKD = -6;        /* defender > attacker */
  3193.       HUNGP = -8;        /* each hung piece */
  3194.       HUNGX = -12;        /* extra for >1 hung piece */
  3195.     }
  3196.     }
  3197. }
  3198.  
  3199.  
  3200. short
  3201. main ()
  3202. {
  3203.   short ahead = 0;
  3204.   short hash = 0;
  3205.   char *xwin = 0;
  3206.   short l;
  3207.  
  3208.   SetUpThing();
  3209.   SetupMenus();
  3210.   alloc_tables();
  3211.  
  3212.   Level[black] = 1;
  3213.   Level[white] = 1;
  3214.   TCflag[black] = true;
  3215.   TCflag[white] = true;
  3216.   OperatorTime[white] = 0;
  3217.   OperatorTime[black] = 0;
  3218.   Book = NULL;
  3219.   for (l = 0; l < 64; l++)
  3220.     {
  3221.       board[l] = Stboard[l];
  3222.       color[l] = Stcolor[l];
  3223.       Mvboard[l] = 0;
  3224.     }
  3225.   Initialize ();
  3226.   Initialize_dist ();
  3227.   Initialize_moves ();
  3228.  
  3229.   TCmoves[white] = 60;
  3230.   TCmoves[black] = 60;
  3231.   TCminutes[white] = 5;
  3232.   TCminutes[black] = 5;
  3233.   SetTimeControl (white);
  3234.   SetTimeControl (black);
  3235.  
  3236.   if (ahead)
  3237.     seteasy ();
  3238.   if (hash)
  3239.     hashflag = 1;
  3240.   if (xwin)
  3241.     xwndw = atoi (xwin);
  3242.  
  3243. #if ttblsz
  3244. #ifdef HASHFILE
  3245.   hashfile = 0;
  3246. #endif /* HASHFILE */
  3247. #endif  /* ttblsz */
  3248.  
  3249.   loop();
  3250.   
  3251. #if ttblsz
  3252. #ifdef HASHFILE
  3253.   if (hashfile) FSClose(hashfile);
  3254. #endif /* HASHFILE */
  3255. #endif /* ttblsz */
  3256.  
  3257.   ExitChess ();
  3258.   return (0);
  3259. }
  3260.