home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / games / gnuchess.zip / GNUCHESS.C1 < prev    next >
Text File  |  1988-10-23  |  43KB  |  1,505 lines

  1. /* Compile via: cc gnuchess.c -o gnuchess. For display version,
  2.    add -DDISPLAY flag and -lcurses -ltermcap libraries to
  3.    command-line. For SUN Chesstool version, add -DCHESSTOOL
  4.    but don't include display options in last sentence.
  5.    For faster version, add -O flag to any of these flags.
  6. */
  7. /* This file contains code for CHESS.
  8.    Copyright (C) 1986, 1987 Free Software Foundation, Inc.
  9.  
  10. This file is part of CHESS.
  11.  
  12. CHESS is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY.  No author or distributor
  14. accepts responsibility to anyone for the consequences of using it
  15. or for whether it serves any particular purpose or works at all,
  16. unless he says so in writing.  Refer to the CHESS General Public
  17. License for full details.
  18.  
  19. Everyone is granted permission to copy, modify and redistribute
  20. CHESS, but only under the conditions described in the
  21. CHESS General Public License.   A copy of this license is
  22. supposed to have been given to you along with CHESS so you
  23. can know your rights and responsibilities.  It should be in a
  24. file named COPYING.  Among other things, the copyright notice
  25. and this notice must be preserved on all copies.  */
  26.  
  27. /* Modified 12/18/87 by Bill Randle (billr@tekred.tek.com) to
  28.    remove a redundant #include and #ifdef section.
  29. */
  30.  
  31. #include <stdio.h>
  32. #include <ctype.h>
  33. #include <signal.h>
  34.  
  35. #ifdef MSDOS
  36. #include <dos.h>
  37. #include <stdlib.h>
  38. #include <time.h>
  39. #include <alloc.h>
  40. #define printz printf
  41. #define scanz scanf
  42. #define refresh();   
  43. #define initscr();  
  44. #define crmode();   
  45. #define nocrmode();   
  46. #define endwin();   
  47. #define _stklen 8000
  48. #define ttblsz 4096
  49. #else
  50. #include <sys/param.h>
  51. #include <sys/times.h>
  52. #define ttblsz 16384
  53. #ifdef DISPLAY
  54. #include <curses.h>
  55. #define printz printw
  56. #define scanz fflush(stdout), scanw
  57. #else
  58. #define printz printf
  59. #define scanz fflush(stdout), scanf
  60. #define refresh();   
  61. #define initscr();  
  62. #define crmode();   
  63. #define nocrmode();   
  64. #define endwin();   
  65. #endif DISPLAY
  66. #endif MSDOS
  67. #ifndef HZ
  68. #define HZ 60
  69. #endif
  70.  
  71. #define neutral 0
  72. #define white 1
  73. #define black 2 
  74. #define no_piece 0
  75. #define pawn 1
  76. #define knight 2
  77. #define bishop 3
  78. #define rook 4
  79. #define queen 5
  80. #define king 6
  81. #define valueP 100
  82. #define valueN 330
  83. #define valueB 330
  84. #define valueR 520
  85. #define valueQ 980
  86. #define valueK 999
  87. #define ctlP 0x4000
  88. #define ctlN 0x2800
  89. #define ctlB 0x1800
  90. #define ctlR 0x0400
  91. #define ctlQ 0x0200
  92. #define ctlK 0x0100
  93. #define ctlBQ 0x1200
  94. #define ctlRQ 0x0600
  95. #define ctlNN 0x2000
  96. #define px " PNBRQK"
  97. #define qx " pnbrqk"
  98. #define rx "12345678"
  99. #define cx "abcdefgh"
  100. #define check 0x0001
  101. #define capture 0x0002
  102. #define draw 0x0004
  103. #define promote 0x0008
  104. #define cstlmask 0x0010
  105. #define epmask 0x0020
  106. #define exact 0x0040
  107. #define pwnthrt 0x0080
  108. #define truescore 0x0001
  109. #define lowerbound 0x0002
  110. #define upperbound 0x0004
  111. #define maxdepth 30
  112. #define true 1
  113. #define false 0
  114. #define absv(x) ((x) < 0 ? -(x) : (x))
  115. #define taxicab(a,b) (absv(col[a]-col[b]) + absv(row[a]-row[b]))
  116.  
  117. struct leaf
  118.   {
  119.     short f,t,score,reply;
  120.     unsigned short flags;
  121.   };
  122. struct GameRec
  123.   {
  124.     unsigned short gmove;
  125.     short score,depth,time,piece,color;
  126.     long nodes;
  127.   };
  128. struct TimeControlRec
  129.   {
  130.     short moves[3];
  131.     long clock[3];
  132.   };
  133. struct hashval
  134.   {
  135.     unsigned long bd;
  136.     unsigned short key;
  137.   };
  138. struct hashentry
  139.   {
  140.     unsigned long hashbd;
  141.     unsigned short reply,flags;
  142.     short score,depth;
  143.   };
  144.  
  145. char mvstr1[5],mvstr2[5];
  146. struct leaf Tree[2000],*root;
  147. short TrPnt[maxdepth],board[64],color[64];
  148. short row[64],col[64],locn[8][8],Pindex[64],svalue[64];
  149. short PieceList[3][16],PieceCnt[3],atak[3][64],PawnCnt[3][8];
  150. short castld[3],kingmoved[3],mtl[3],pmtl[3],emtl[3],hung[3];
  151. short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,randflag;
  152. long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft;
  153. long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt;
  154. long OperatorTime;
  155. short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep;
  156. short wking,bking,TOsquare,timeout,Zscore,zwndw,cptrval,prune,slk;
  157. short HasPawn[3],HasKnight[3],HasBishop[3],HasRook[3],HasQueen[3];
  158. short ChkFlag[maxdepth],CptrFlag[maxdepth],PawnThreat[maxdepth];
  159. short Pscore[maxdepth],Tscore[maxdepth],Threat[maxdepth];
  160. struct GameRec GameList[240];
  161. short GameCnt,Game50,epsquare,lpost;
  162. short BookSize,BookDepth,MaxSearchDepth;
  163. struct TimeControlRec TimeControl;
  164. short TCflag,TCmoves,mycnt1,mycnt2;
  165. #ifdef MSDOS
  166. unsigned short Book[80][24];
  167. #else
  168. unsigned short Book[250][50];
  169. struct tms tmbuf1,tmbuf2;
  170. #endif
  171. short otherside[3]={0,2,1};
  172. short map[64]=
  173.    {26,27,28,29,30,31,32,33,38,39,40,41,42,43,44,45,
  174.     50,51,52,53,54,55,56,57,62,63,64,65,66,67,68,69,
  175.     74,75,76,77,78,79,80,81,86,87,88,89,90,91,92,93,
  176.     98,99,100,101,102,103,104,105,110,111,112,113,114,115,116,117};
  177. short unmap[144]=
  178.    {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  179.     -1,-1,0,1,2,3,4,5,6,7,-1,-1,-1,-1,8,9,10,11,12,13,14,15,-1,-1,
  180.     -1,-1,16,17,18,19,20,21,22,23,-1,-1,-1,-1,24,25,26,27,28,29,30,31,-1,-1,
  181.     -1,-1,32,33,34,35,36,37,38,39,-1,-1,-1,-1,40,41,42,43,44,45,46,47,-1,-1,
  182.     -1,-1,48,49,50,51,52,53,54,55,-1,-1,-1,-1,56,57,58,59,60,61,62,63,-1,-1,
  183.     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
  184. short Stboard[64]=
  185.    {rook,knight,bishop,queen,king,bishop,knight,rook,
  186.     pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
  187.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  188.     pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
  189.     rook,knight,bishop,queen,king,bishop,knight,rook};
  190. short Stcolor[64]=
  191.    {white,white,white,white,white,white,white,white,
  192.     white,white,white,white,white,white,white,white,
  193.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  194.     black,black,black,black,black,black,black,black,
  195.     black,black,black,black,black,black,black,black};
  196. short sweep[7]= {false,false,false,true,true,true,false};
  197. short sweep1[7]= {false,false,false,false,true,true,false};
  198. short sweep2[7]= {false,false,false,true,false,true,false};
  199. short Dpwn[3]={0,4,6};
  200. short Dstart[7]={6,4,8,4,0,0,0};
  201. short Dstop[7]={7,5,15,7,3,7,7};
  202. short Dir[16]={1,12,-1,-12,11,13,-11,-13,10,-10,14,-14,23,-23,25,-25};
  203. short rank7[3] = {0,6,1};
  204. unsigned short killr0[maxdepth],killr1[maxdepth],killr2[maxdepth];
  205. unsigned short killr3[maxdepth],Qkillr[maxdepth],PrVar[maxdepth];
  206. unsigned short PV,hint,Swag0,Swag1,Swag2,Swag3,Swag4,Swag5;
  207. unsigned short hashkey;
  208. unsigned long hashbd;
  209. struct hashval hashcode[3][7][64];
  210. #ifdef MSDOS
  211. struct hashentry far *ttable,*ptbl;
  212. #else
  213. struct hashentry *ttable,*ptbl;
  214. int TerminateSearch(),Die();
  215. #endif MSDOS
  216. unsigned char history[2][64][64];
  217.  
  218. short Mwpawn[64],Mbpawn[64],Mknight[3][64],Mbishop[3][64],Mking[3][64];
  219. short WeakSq[3][64],Kfield[3][64],contempt[3];
  220. short value[7]={0,valueP,valueN,valueB,valueR,valueQ,valueK};
  221. short control[7]={0,ctlP,ctlN,ctlB,ctlR,ctlQ,ctlK};
  222. short passed_pawn1[8]={0,15,30,60,100,180,280,800};
  223. short passed_pawn2[8]={0,15,25,35,50,90,140,800};
  224. short passed_pawn3[8]={0,5,10,15,20,30,120,800};
  225. short ISOLANI[8] = {-12,-14,-16,-20,-20,-16,-14,-12};
  226. short DOUBLED[8] = {-12,-12,-12,-10,-10,-12,-12,-12};
  227. short BMBLTY[30] = {-4,-2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,13,14,14,
  228.                     15,15,16,16,17,17,18,18,18,18,18};
  229. short RMBLTY[30] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,14,15,15,
  230.                     16,16,17,17,18,18,19,19,20,20,20,20};
  231. short Kthreat[16] = {0,-6,-16,-32,-48,-64,-64,-64,-64,-64,-64,-64,
  232.                      -64,-64,-64,-64};
  233. short KNIGHTPOST,KNIGHTSTRONG,BISHOPSTRONG,KATAK;
  234. short PEDRNK2B,PBKWRD,PWEAKA,PWEAKH,PADVNCM,PAWNSHIELD;
  235. short RHOPN,RHOPNX,KHOPN,KHOPNX;
  236. short ATAKD,HUNGP,HUNGX,KCASTLD,KMOVD,XRAY;
  237. short stage,Zwmtl,Zbmtl,c1,c2,KSFTY,Developed[3];
  238. short KingOpening[64]=
  239.    {  0,  0, -4, -8, -8, -4,  0,  0,
  240.      -4, -4, -8,-12,-12, -8, -4, -4,
  241.     -12,-16,-20,-20,-20,-20,-16,-12,
  242.     -16,-20,-24,-24,-24,-24,-20,-16,
  243.     -16,-20,-24,-24,-24,-24,-20,-16,
  244.     -12,-16,-20,-20,-20,-20,-16,-12,
  245.      -4, -4, -8,-12,-12, -8, -4, -4,
  246.       0,  0, -4, -8, -8, -4,  0,  0};
  247. short KingEnding[64]=
  248.    { 0, 6,12,18,18,12, 6, 0,
  249.      6,12,18,24,24,18,12, 6,
  250.     12,18,24,30,30,24,18,12,
  251.     18,24,30,36,36,30,24,18,
  252.     18,24,30,36,36,30,24,18,
  253.     12,18,24,30,30,24,18,12,
  254.      6,12,18,24,24,18,12, 6,
  255.      0, 6,12,18,18,12, 6, 0};
  256. short DyingKing[64]=
  257.    { 0, 8,16,24,24,16, 8, 0,
  258.      8,32,40,48,48,40,32, 8,
  259.     16,40,56,64,64,56,40,16,
  260.     24,48,64,72,72,64,48,24,
  261.     24,48,64,72,72,64,48,24,
  262.     16,40,56,64,64,56,40,16,
  263.      8,32,40,48,48,40,32, 8,
  264.      0, 8,16,24,24,16, 8, 0};
  265. short pknight[64]=
  266.    { 0, 4, 8,10,10, 8, 4, 0,
  267.      4, 8,16,20,20,16, 8, 4,
  268.      8,16,24,28,28,24,16, 8,
  269.     10,20,28,32,32,28,20,10,
  270.     10,20,28,32,32,28,20,10,
  271.      8,16,24,28,28,24,16, 8,
  272.      4, 8,16,20,20,16, 8, 4,
  273.      0, 4, 8,10,10, 8, 4, 0};
  274. short pbishop[64]=
  275.    {14,14,14,14,14,14,14,14,
  276.     14,22,18,18,18,18,22,14,
  277.     14,18,22,22,22,22,18,14,
  278.     14,18,22,22,22,22,18,14,
  279.     14,18,22,22,22,22,18,14,
  280.     14,18,22,22,22,22,18,14,
  281.     14,22,18,18,18,18,22,14,
  282.     14,14,14,14,14,14,14,14};
  283. short PawnAdvance[64]=
  284.    { 0, 0, 0, 0, 0, 0, 0, 0,
  285.      0, 2, 4, 0, 0, 4, 2, 0,
  286.      6, 8,10,12,12,10, 8, 6,
  287.      8,12,20,32,32,20,12, 8,
  288.     12,20,28,40,40,28,20,12,
  289.     16,28,36,48,48,36,28,16,
  290.     16,28,36,48,48,36,28,16,
  291.      0, 0, 0, 0, 0, 0, 0, 0};
  292.  
  293.  
  294. main(argc,argv)
  295. int argc; char *argv[];
  296. {
  297. #ifdef MSDOS
  298.   ttable = (struct hashentry far *)farmalloc(ttblsz *
  299.            (unsigned long)sizeof(struct hashentry));
  300.   printf("%lu bytes free\n",farcoreleft());
  301. #else
  302.   ttable = (struct hashentry *)malloc(ttblsz *
  303.            (unsigned long)sizeof(struct hashentry));
  304.   signal(SIGINT,Die); signal(SIGQUIT,Die);
  305. #endif MSDOS
  306. #ifdef CHESSTOOL
  307.   setlinebuf(stdout);
  308.   if (argc > 1) Level = atoi(argv[1]);
  309.   else Level = 30; /* Default to 30 seconds */
  310. #endif CHESSTOOL
  311.   initscr();
  312.   crmode();
  313.   NewGame();
  314.   while (!(quit))
  315.     {
  316.       if (bothsides && !mate) SelectMove(opponent,1); else input_command();
  317.       if (!(quit || mate || force)) SelectMove(computer,1);
  318.     }
  319.   nocrmode();
  320.   endwin();
  321. }
  322.  
  323.  
  324. #ifndef MSDOS
  325. Die()
  326. {
  327. char s[80];
  328.   signal(SIGINT,SIG_IGN);
  329.   signal(SIGQUIT,SIG_IGN);
  330.   gotoXY(50,24);
  331.   printz("Abort? ");
  332.   scanz("%s",s);
  333.   if (strcmp(s,"yes") == 0)
  334.     {
  335. #ifdef DISPLAY
  336.       gotoXY(1,24);
  337.       nocrmode();
  338.       endwin();
  339. #endif DISPLAY
  340.       exit(0);
  341.     }
  342.   signal(SIGINT,Die); signal(SIGQUIT,Die);
  343. }
  344.  
  345. TerminateSearch()
  346. {
  347.   signal(SIGINT,SIG_IGN);
  348.   signal(SIGQUIT,SIG_IGN);
  349.   timeout = true;
  350.   bothsides = false;
  351.   signal(SIGINT,Die); signal(SIGQUIT,Die);
  352. }
  353. #endif
  354.  
  355.  
  356. OpeningBook()
  357. {
  358. short i,j,r0,pnt;
  359. unsigned m,r;
  360.   srand((unsigned)time0);
  361.   r0 = m = 0;
  362.   for (i = 0; i < BookSize; i++)
  363.     {
  364.       for (j = 0; j <= GameCnt; j++)
  365.         if (GameList[j].gmove != Book[i][j]) break;
  366.       if (j > GameCnt)
  367.         if ((r=rand()) > r0)
  368.           {
  369.             r0 = r; m = Book[i][GameCnt+1];
  370.             hint = Book[i][GameCnt+2];
  371.           }
  372.     }
  373.   for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
  374.     if ((Tree[pnt].f<<8) + Tree[pnt].t == m) Tree[pnt].score = 0;
  375.   sort(TrPnt[1],TrPnt[2]-1);
  376.   if (Tree[TrPnt[1]].score < 0) BookDepth = -1;
  377. }
  378.  
  379.  
  380. ShowDepth(ch)
  381. char ch;
  382. {
  383. #ifdef DISPLAY
  384.   gotoXY(75,1); printz("%2d%c",Sdepth,ch); ClrEoln();
  385. #endif DISPLAY
  386. }
  387.  
  388. ShowResults(ch)
  389. char ch;
  390. {
  391. #ifndef DISPLAY
  392. #ifndef CHESSTOOL
  393. register int i;
  394.   printz("%2d%c  %5d %4ld %7ld   ",Sdepth,ch,root->score,et,NodeCnt);
  395.   for (i = 1; PrVar[i] > 0; i++)
  396.     {
  397.       algbr((short)(PrVar[i] >> 8),(short)(PrVar[i] & 0xFF),false);
  398.       if (i == 9 || i == 17) printz("\n                          ");
  399.       printz("%5s ",mvstr1);
  400.     }
  401.   printz("\n");
  402.   fflush(stdout);
  403. #endif CHESSTOOL
  404. #endif DISPLAY
  405. }
  406.  
  407.  
  408. int SelectMove(side,iop)
  409. short side,iop;
  410.  
  411. /*
  412.     Select a move by calling function search() at progressively deeper 
  413.     ply until time is up or a mate or draw is reached. An alpha-beta 
  414.     window of -9000 to +90 points is set around the score returned from the 
  415.     previous iteration. 
  416. */
  417.  
  418. {
  419. static short i,j,alpha,beta,score,tempb,tempc,temps,xside,rpt;
  420.  
  421. #ifndef MSDOS
  422.   (void) times(&tmbuf1);
  423.   signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch);
  424. #endif MSDOS
  425.   timeout = false;
  426.   xside = otherside[side];
  427.   if (iop != 2) player = side;
  428.   if (TCflag)
  429.     {
  430.       ResponseTime = (TimeControl.clock[side]) /
  431.                      (TimeControl.moves[side] + 3) -
  432.                      OperatorTime;
  433.       ResponseTime += (ResponseTime*TimeControl.moves[side])/(2*TCmoves+1);
  434.     }
  435.   else ResponseTime = Level;
  436.   if (iop == 2) ResponseTime = 999;
  437.   if (Sdepth > 0 && root->score > Zscore-zwndw) ResponseTime -= ft;
  438.   else if (ResponseTime < 1) ResponseTime = 1;
  439.   ExtraTime = 0;
  440.   
  441.   if (Sdepth == 0)
  442.   {
  443.     ExaminePosition();
  444.     ptbl = ttable;
  445.     for (i = 0; i < ttblsz; i++,ptbl++) ptbl->depth = 0;
  446.     for (i = 0; i < 64; i++)
  447.       for (j = 0; j < 64; j++)
  448.         history[0][i][j] = history[1][i][j] = 0;
  449.     TOsquare = -1;
  450.     PV = 0;
  451.     if (iop != 2) hint = 0;
  452.     for (i = 0; i < maxdepth; i++)
  453.      PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = Qkillr[i] = 0;
  454. #ifdef DISPLAY
  455.     for (i = 1; i < 17; i++)
  456.       {
  457.         gotoXY(50,i); ClrEoln();
  458.       }
  459. #else
  460.     post = false;
  461. #ifndef CHESSTOOL
  462.    printz("\nMove# %d    Target= %ld    Clock: %ld\n",TimeControl.moves[side],
  463.            ResponseTime,TimeControl.clock[side]);
  464. #endif CHESSTOOL
  465. #endif DISPLAY  
  466.     alpha = -9000; beta = 9000; rpt = 0;
  467.     TrPnt[1] = 0; root = &Tree[0];
  468.     MoveList(side,1);
  469.     if (GameCnt < BookDepth) OpeningBook(); else BookDepth = -1;
  470.     if (BookDepth > 0) timeout = true;
  471.     NodeCnt = ETnodes = EvalNodes = HashCnt = 0;
  472.     Zscore = 0; zwndw = 25;
  473.   }
  474.   
  475.   while (!timeout && Sdepth < MaxSearchDepth)
  476.     {
  477.       Sdepth++;
  478.       ShowDepth(' ');
  479.       score = search(side,1,Sdepth,alpha,beta,PrVar,&rpt);
  480.       for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
  481.       if (score < alpha)
  482.         {
  483.           ShowDepth('-');
  484.           ExtraTime = 5*ResponseTime;
  485.           score = search(side,1,Sdepth,-9000,beta,PrVar,&rpt);
  486.         }
  487.       if (score > beta && !(root->flags & exact))
  488.         {
  489.           ShowDepth('+');
  490.           ExtraTime = 0;
  491.           score = search(side,1,Sdepth,alpha,9000,PrVar,&rpt);
  492.         }
  493.       score = root->score;
  494.       ShowResults('.');
  495.       beta = score + Bwindow;
  496.       if (Awindow != 9000) alpha = score - Awindow;
  497.       for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
  498.       if (!timeout) sort(0,TrPnt[2]-1);
  499.       if (score > Zscore-zwndw && score > Tree[1].score+250) ExtraTime = 0;
  500.       else if (score > Zscore-3*zwndw) ExtraTime = ResponseTime;
  501.       else ExtraTime = 3*ResponseTime;
  502.       if (root->flags & exact) timeout = true;
  503.       if (Tree[1].score < -9000) timeout = true;
  504.       if (4*et > 2*ResponseTime + ExtraTime) timeout = true;
  505.       if (!timeout)
  506.         {
  507.           Tscore[0] = score;
  508.           if (Zscore == 0) Zscore = score;
  509.           else Zscore = (Zscore+score)/2;
  510.         }
  511.       zwndw = 25+absv(Zscore/12);
  512.     }
  513.  
  514.   score = root->score;
  515.   if (rpt >= 2 || score < -12000) root->flags |= draw;
  516.   if (iop == 2) return(0);
  517.   if (BookDepth < 0) hint = PrVar[2];
  518.   ElapsedTime(1);
  519. #ifdef DISPLAY
  520.   gotoXY(50,22); printz("Nodes=   %6ld",NodeCnt); ClrEoln();
  521.   gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate); ClrEoln();
  522. #else
  523. #ifndef CHESSTOOL
  524. printz("Nodes= %ld  Eval= %ld  Hash= %ld  Rate= %ld  ",
  525.         NodeCnt,EvalNodes,HashCnt,evrate);
  526. printz("CPU= %.2ld:%.2ld.%.2ld\n",
  527.         cputimer/6000,(cputimer % 6000)/100,cputimer % 100);
  528. #endif CHESSTOOL
  529. #endif DISPLAY
  530.  
  531.   if (score > -9999 && rpt <= 2)
  532.     {
  533.       MakeMove(side,root,&tempb,&tempc,&temps);
  534.       algbr(root->f,root->t,root->flags & cstlmask);
  535.     }
  536.   else algbr(PieceList[side][0],PieceList[side][0],false);
  537.   if (root->flags & epmask) UpdateDisplay(0,0,1,0);
  538.   else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask);
  539. #ifdef CHESSTOOL
  540.   gotoXY(50,17); printz("%d. ... %s",++mycnt1,mvstr1); ClrEoln();
  541.   if (root->flags & draw) printz("Draw\n");
  542.   if (score == -9999)
  543.     if (opponent == white) printz("White\n"); else printz("Black\n");
  544.   if (score == 9998)
  545.     if (computer == white) printz("White\n"); else printz("Black\n");
  546. #else
  547.   gotoXY(50,17); printz("My move is: %s",mvstr1);
  548.   if (beep) printz("%c",7);
  549.   ClrEoln();
  550.   gotoXY(50,24);
  551.   if (root->flags & draw) printz("Draw game!");
  552.   if (score == -9999) printz("opponent mates!");
  553.   else if (score == 9998) printz("computer mates!");
  554.   else if (score < -9000) printz("opponent will soon mate!");
  555.   else if (score > 9000)  printz("computer will soon mate!");
  556.   ClrEoln();
  557. #endif CHESSTOOL
  558. #ifndef DISPLAY
  559.   printz("\n");
  560. #endif DISPLAY
  561.   if (score == -9999 || score == 9998) mate = true;
  562.   if (mate) hint = 0;
  563.   if (post) post_move(root);
  564.   if (root->flags & cstlmask) Game50 = GameCnt;
  565.   else if (board[root->t] == pawn || (root->flags & capture)) 
  566.     Game50 = GameCnt;
  567.   GameList[GameCnt].score = score;
  568.   GameList[GameCnt].nodes = NodeCnt;
  569.   GameList[GameCnt].time = (short)et;
  570.   GameList[GameCnt].depth = Sdepth;
  571.   if (TCflag)
  572.     {
  573.       TimeControl.clock[side] -= (et + OperatorTime);
  574.       if (--TimeControl.moves[side] == 0)
  575.         SetTimeControl();
  576.     }
  577. #ifdef MSDOS
  578.   if (kbhit()) bothsides = false;
  579. #endif
  580.   if ((root->flags & draw) && bothsides) quit = true;
  581.   if (GameCnt > 238) quit = true;
  582.   player = xside;
  583.   Sdepth = 0;
  584.   fflush(stdin);
  585.   return(0);
  586. }
  587.  
  588.  
  589. #ifdef CHESSTOOL
  590. #define illegalmsg printz("illegal move\n")
  591. #else
  592. #define illegalmsg {gotoXY(50,24); printz("illegal move!"); ClrEoln();}
  593. #endif
  594.  
  595. int VerifyMove(s,iop,mv)
  596. char s[];
  597. short iop;
  598. unsigned short *mv;
  599. {
  600. static short pnt,tempb,tempc,temps,cnt;
  601. static struct leaf xnode;
  602. struct leaf *node;
  603.  
  604.   *mv = 0;
  605.   if (iop == 2)
  606.     {
  607.       UnmakeMove(opponent,&xnode,&tempb,&tempc,&temps);
  608.       return(false);
  609.     }
  610.   cnt = 0;
  611.   MoveList(opponent,2);
  612.   pnt = TrPnt[2];
  613.   while (pnt < TrPnt[3])
  614.     {
  615.       node = &Tree[pnt]; pnt++;
  616.       algbr(node->f,node->t,node->flags & cstlmask);
  617.       if (strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0)
  618.         {
  619.           cnt++; xnode = *node;
  620.         }
  621.     }
  622.   if (cnt == 0)
  623.     if (isdigit(s[1]) || isdigit(s[2])) illegalmsg;
  624.   if (cnt == 1)
  625.     {
  626.       MakeMove(opponent,&xnode,&tempb,&tempc,&temps);
  627.       if (SqAtakd(PieceList[opponent][0],computer))
  628.         {
  629.           UnmakeMove(opponent,&xnode,&tempb,&tempc,&temps);
  630.           illegalmsg;
  631.           return(false);
  632.         }
  633.       else
  634.         {
  635.           if (iop == 1) return(true);
  636.           if (xnode.flags & epmask) UpdateDisplay(0,0,1,0);
  637.           else UpdateDisplay(xnode.f,xnode.t,0,xnode.flags & cstlmask);
  638.           if (xnode.flags & cstlmask) Game50 = GameCnt;
  639.           else if (board[xnode.t] == pawn || (xnode.flags & capture)) 
  640.             Game50 = GameCnt;
  641.           GameList[GameCnt].depth = GameList[GameCnt].score = 0;
  642.           GameList[GameCnt].nodes = 0;
  643.           ElapsedTime(1);
  644.           GameList[GameCnt].time = (short)et;
  645.           TimeControl.clock[opponent] -= et;
  646.           --TimeControl.moves[opponent];
  647.           *mv = (xnode.f << 8) + xnode.t;
  648.           return(true);
  649.         } 
  650.     }
  651.   else if (cnt > 1)
  652.     {
  653.       gotoXY(50,24); printz("ambiguous move!"); ClrEoln();
  654.     }
  655.   return(false);
  656. }
  657.  
  658.       
  659. input_command()
  660. {
  661. short ok,i,f,t,c,p,tc,tp;
  662. unsigned short mv;
  663. char s[80],fname[20];
  664.  
  665.   ok=quit=false;
  666.   player = opponent;
  667.   ataks(white,atak[white]); ataks(black,atak[black]);
  668. #ifdef DISPLAY
  669.   gotoXY(50,19); printz("Your move is? "); ClrEoln();
  670. #endif
  671.   ft = 0;
  672.   if (hint > 0 && !easy && BookDepth < 0)
  673.     {
  674.       fflush(stdout);
  675.       time0 = time((long *)0);
  676.       algbr(hint>>8,hint & 0xFF,false);
  677.       strcpy(s,mvstr1);
  678.       f = epsquare;
  679.       if (VerifyMove(s,1,&mv))
  680.         {
  681.           SelectMove(computer,2);
  682.           VerifyMove(mvstr1,2,&mv);
  683.           if (Sdepth > 0) Sdepth--;
  684.         }
  685.       ft = time((long *)0) - time0;
  686.       epsquare = f;
  687.     }
  688.   fflush(stdin);
  689.   
  690.   while (!(ok || quit))
  691.     {
  692. #ifndef CHESSTOOL
  693.       gotoXY(50,19); printz("Your move is? "); ClrEoln();
  694. #endif CHESSTOOL
  695.       scanz("%s",s);
  696.       player = opponent;
  697.       ok = VerifyMove(s,0,&mv);
  698.       if (ok && mv != hint)
  699.         {
  700.           Sdepth = 0;
  701.           ft = 0;
  702.         }
  703.       if (strcmp(s,"bd") == 0)
  704.         {
  705. #ifdef DISPLAY
  706.           ClrScreen();  UpdateDisplay(0,0,1,0);
  707. #else
  708.           PrintBoard();
  709. #endif DISPLAY
  710.         }
  711.       if (strcmp(s,"quit") == 0) quit = true;
  712.       if (strcmp(s,"post") == 0) post = !post;
  713.       if (strcmp(s,"set") == 0) SetBoard();
  714.       if (strcmp(s,"go") == 0) ok = true;
  715.       if (strcmp(s,"help") == 0) help();
  716.       if (strcmp(s,"force") == 0) force = !force;
  717.       if (strcmp(s,"random") == 0) randflag = !randflag; 
  718.       if (strcmp(s,"book") == 0) BookDepth = -1;
  719.       if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo();
  720.       if (strcmp(s,"new") == 0) NewGame();
  721.       if (strcmp(s,"list") == 0) ListGame();
  722.       if (strcmp(s,"clock") == 0) SetTimeControl();
  723.       if (strcmp(s,"hash") == 0) hashflag = !hashflag;
  724.       if (strcmp(s,"beep") == 0) beep = !beep;
  725.       if (strcmp(s,"Awindow") == 0)
  726.         {
  727.           gotoXY(50,24); printz("window: "); ClrEoln();
  728.           scanz("%hd",&Awindow);
  729.         }
  730.       if (strcmp(s,"Bwindow") == 0)
  731.         {
  732.           gotoXY(50,24); printz("window: "); ClrEoln();
  733.           scanz("%hd",&Bwindow);
  734.         }
  735.       if (strcmp(s,"hint") == 0)
  736.         {
  737.           algbr((short)(hint>>8),(short)(hint & 0xFF),false);
  738.           gotoXY(50,24); printz("try  %5s",mvstr1); ClrEoln();
  739.         }
  740.       if (strcmp(s,"both") == 0)
  741.         {
  742.           bothsides = !bothsides;
  743.           Sdepth = 0;
  744.           SelectMove(opponent,1);
  745.           ok = true;
  746.         }
  747.       if (strcmp(s,"reverse") == 0)
  748.         {
  749.           reverse = !reverse;
  750.           ClrScreen();
  751.           UpdateDisplay(0,0,1,0);
  752.         }
  753.       if (strcmp(s,"switch") == 0)
  754.         {
  755.           computer = otherside[computer];
  756.           opponent = otherside[opponent];
  757.           UpdateDisplay(0,0,1,0);
  758.           force = false;
  759.           ok = true;
  760.           Sdepth = 0;
  761.         }
  762.       if (strcmp(s,"white") == 0)
  763.         {
  764.           computer = white; opponent = black;
  765.           UpdateDisplay(0,0,1,0);
  766.           ok = true; force = false;
  767.           Sdepth = 0;
  768.         }
  769.       if (strcmp(s,"black") == 0)
  770.         {
  771.           computer = black; opponent = white;
  772.           UpdateDisplay(0,0,1,0);
  773.           ok = true; force = false;
  774.           Sdepth = 0;
  775.         }
  776.       if (strcmp(s,"time") == 0)
  777.         {
  778.           gotoXY(50,24); printz("enter time: "); ClrEoln();
  779.           scanz("%ld",&Level);
  780.           TCflag = false;
  781.         }
  782.       if (strcmp(s,"remove") == 0 && GameCnt >= 1) 
  783.         {
  784.           Undo(); Undo();
  785.         }
  786.       if (strcmp(s,"get") == 0)
  787.         {
  788.           gotoXY(50,24); printz("fname? "); ClrEoln(); scanz("%s",fname);
  789.           GetGame(fname);
  790.           InitializeStats();
  791.           UpdateDisplay(0,0,1,0);
  792.           Sdepth = 0;
  793.         }
  794.       if (strcmp(s,"save") == 0)
  795.         {
  796.           gotoXY(50,24); printz("fname? "); ClrEoln(); scanz("%s",fname);
  797.           SaveGame(fname);
  798.         }
  799.       if (strcmp(s,"depth") == 0)
  800.         {
  801.           gotoXY(50,24); printz("depth= "); ClrEoln();
  802.           scanz("%hd",&MaxSearchDepth);
  803.         }
  804.       if (strcmp(s,"verify") == 0) VerifyBook();
  805.       if (strcmp(s,"easy") == 0) easy = !easy;
  806.       if (strcmp(s,"contempt") == 0)
  807.         {
  808.           gotoXY(50,24); printz("contempt= "); ClrEoln();
  809.           scanz("%hd",&c);
  810.           contempt[computer] = c;
  811.           contempt[opponent] = -c;
  812.         }
  813.       if (strcmp(s,"prune") == 0)
  814.         {
  815.           gotoXY(50,24); printz("prune= "); ClrEoln();
  816.           scanz("%hd",&prune);
  817.         }
  818.       if (strcmp(s,"debug") == 0)
  819.         {
  820.           ExaminePosition();
  821.           gotoXY(50,24); printz("enter piece: "); ClrEoln();
  822.           scanz("%s",s);
  823.           if (s[0] == 'w') c = white; else c = black;
  824.           if (s[1] == 'p') p = pawn;
  825.           else if (s[1] == 'n') p = knight;
  826.           else if (s[1] == 'b') p = bishop;
  827.           else if (s[1] == 'r') p = rook;
  828.           else if (s[1] == 'q') p = queen;
  829.           else if (s[1] == 'k') p = king;
  830.           else p = no_piece;
  831.           for (i = 0; i < 64; i++)
  832.             {
  833.               gotoXY(4+5*col[i],5+2*(7-row[i]));
  834.               tp = board[i]; tc = color[i];
  835.               board[i] = p; color[i] = c;
  836.               c1 = c; c2 = otherside[c1];
  837.               printz("%3d ",SqValue(i,opponent));
  838.               board[i] = tp; color[i] = tc;
  839.             }
  840.           refresh();
  841.         }
  842.     }
  843. #ifdef CHESSTOOL
  844.   printf("%d. %s\n",++mycnt2,s);
  845. #endif CHESSTOOL
  846.   gotoXY(50,24); ClrEoln();
  847.   ElapsedTime(1);
  848.   if (force)
  849.     {
  850.       computer = opponent; opponent = otherside[computer];
  851.     }
  852. }
  853.  
  854.  
  855. gotoXY(x,y)
  856. short x,y;
  857. {
  858. #ifdef DISPLAY
  859. #ifdef MSDOS
  860. union REGS r1,r2;
  861.   r1.h.ah = 0x02; r1.h.bh = 0x00;
  862.   r1.h.dl = x-1; r1.h.dh = y-1;
  863.   int86(0x10,&r1,&r2);
  864. #else
  865.   move(y-1,x-1);
  866. #endif MSDOS
  867. #else
  868. #ifndef CHESSTOOL
  869.   printz("\n");
  870. #endif CHESSTOOL
  871. #endif DISPLAY
  872. }
  873.  
  874.  
  875. ClrScreen()
  876. {
  877. #ifdef DISPLAY
  878. #ifdef MSDOS
  879. union REGS r1,r2;
  880.   gotoXY(1,1);
  881.   r1.h.ah = 0x08; r1.h.bh = 0x00;
  882.   int86(0x10,&r1,&r2);
  883.   r1.h.ah = 0x09; r1.h.al = 0x20;
  884.   r1.h.bh = 0x00; r1.h.bl = r2.h.ah; 
  885.   r1.h.ch = 0x07; r1.h.cl = 0xD0;
  886.   int86(0x10,&r1,&r2);
  887.   gotoXY(1,1);
  888. #else
  889.   clear(); refresh();
  890. #endif MSDOS
  891. #else
  892.   printz("\n\n");
  893. #endif DISPLAY
  894. }
  895.  
  896.  
  897. ClrEoln()
  898. {
  899. #ifdef DISPLAY
  900. #ifdef MSDOS
  901. union REGS r1,r2;
  902. char x,y;
  903.   r1.h.ah = 0x03; r1.h.bh = 0x00;
  904.   int86(0x10,&r1,&r2);
  905.   x = r2.h.dl+1; y = r2.h.dh+1;
  906.   r1.h.ah = 0x08; r1.h.bh = 0x00;
  907.   int86(0x10,&r1,&r2);
  908.   r1.h.ah = 0x09; r1.h.al = 0x20;
  909.   r1.h.bh = 0x00; r1.h.bl = r2.h.ah; 
  910.   r1.h.ch = 0x00; r1.h.cl = 81-x;
  911.   int86(0x10,&r1,&r2);
  912.   gotoXY(x,y);
  913. #else
  914.   clrtoeol(); refresh();
  915. #endif MSDOS
  916. #endif DISPLAY
  917. }
  918.  
  919.  
  920. algbr(f,t,iscastle)
  921. short f,t,iscastle;
  922. {
  923.   mvstr1[0] = cx[col[f]]; mvstr1[1] = rx[row[f]];
  924.   mvstr1[2] = cx[col[t]]; mvstr1[3] = rx[row[t]];
  925.   mvstr2[0] = qx[board[f]];
  926.   mvstr2[1] = mvstr1[2]; mvstr2[2] = mvstr1[3];
  927.   mvstr1[4] = '\0'; mvstr2[3] = '\0';
  928.   if (iscastle)
  929.     if (t > f) strcpy(mvstr2,"o-o");
  930.     else strcpy(mvstr2,"o-o-o");
  931. }
  932.  
  933.  
  934. Undo()
  935. {
  936. short f,t;
  937.   f = GameList[GameCnt].gmove>>8;
  938.   t = GameList[GameCnt].gmove & 0xFF;
  939.   if (board[t] == king && distance(t,f) > 1)
  940.     castle(GameList[GameCnt].color,f,t,2);
  941.   else
  942.     {
  943.       board[f] = board[t]; color[f] = color[t];
  944.       board[t] = GameList[GameCnt].piece;
  945.       color[t] = GameList[GameCnt].color;
  946.       if (board[f] == king) --kingmoved[color[f]];
  947.     }
  948.   if (TCflag) ++TimeControl.moves[color[f]];
  949.   GameCnt--; mate = false; Sdepth = 0;
  950.   UpdateDisplay(0,0,1,0);
  951.   InitializeStats();
  952. }
  953.  
  954.  
  955. parse(s,m,j)
  956. unsigned short *m; char s[];
  957. short j;
  958. {
  959. short r1,r2,c1,c2;
  960.   if (s[4] == 'o')
  961.     if (j & 1) *m = 0x3C3A; else *m = 0x0402;
  962.   else if (s[0] == 'o')
  963.     if (j & 1) *m = 0x3C3E; else *m = 0x0406;
  964.   else
  965.     {
  966.       c1 = s[0] - 'a'; r1 = s[1] - '1';
  967.       c2 = s[2] - 'a'; r2 = s[3] - '1';
  968.       *m = (locn[r1][c1]<<8) + locn[r2][c2];
  969.     }
  970. }
  971.  
  972.  
  973. GetOpenings()
  974. {
  975. FILE *fd;
  976. int c,j;
  977. char s[80],*p;
  978.   if ((fd = fopen("gnuchess.book","r")) != NULL)
  979.     {
  980.       BookSize = 0; j = 0; c = '?'; p = s;
  981.       while ((c = getc(fd)) != EOF)
  982.         if (c != '\n') *(p++) = c;
  983.         else
  984.           {
  985.             *p = '\0';
  986.             if (s[0] == '!')
  987.               {
  988.                 if (j > 0)
  989.                   {
  990.                     while (j < BookDepth) Book[BookSize][j++] = 0; 
  991.                     BookSize++; j = 0;
  992.                   }
  993.               }
  994.             else
  995.               {
  996.                 parse(&s[0],&Book[BookSize][j],j); j++;
  997.                 parse(&s[6],&Book[BookSize][j],j); j++;
  998.               } 
  999.             p = s;
  1000.           }
  1001.       fclose(fd);
  1002.     }
  1003. }
  1004.  
  1005.  
  1006. GetGame(fname)
  1007. char fname[20];
  1008. {
  1009. FILE *fd;
  1010. int c;
  1011. short loc;
  1012. unsigned short m;
  1013.  
  1014.   if (fname[0] == '\0') strcpy(fname,"chess.000");
  1015.   if ((fd = fopen(fname,"r")) != NULL)
  1016.     {
  1017.       fscanf(fd,"%hd%hd%hd",&computer,&opponent,&Game50);
  1018.       fscanf(fd,"%hd%hd%hd%hd",
  1019.              &castld[white],&castld[black],
  1020.              &kingmoved[white],&kingmoved[black]);
  1021.       fscanf(fd,"%hd%hd",&TCflag,&OperatorTime);
  1022.       fscanf(fd,"%ld%ld%hd%ld",
  1023.              &TimeControl.clock[white],&TimeControl.clock[black],
  1024.              &TimeControl.moves[white],&TimeControl.moves[black]);
  1025.       for (loc = 0; loc < 64; loc++)
  1026.         {
  1027.           fscanf(fd,"%hd",&m); board[loc] = (m >> 8); color[loc] = (m & 0xFF);
  1028.         }
  1029.       GameCnt = -1; c = '?';
  1030.       while (c != EOF)
  1031.         {
  1032.           ++GameCnt;
  1033.           c = fscanf(fd,"%hd%hd%hd%ld%hd%hd%hd",&GameList[GameCnt].gmove,
  1034.                      &GameList[GameCnt].score,&GameList[GameCnt].depth,
  1035.                      &GameList[GameCnt].nodes,&GameList[GameCnt].time,
  1036.                      &GameList[GameCnt].piece,&GameList[GameCnt].color);
  1037.         }
  1038.       GameCnt--;
  1039.     }
  1040.   fclose(fd);
  1041. }
  1042.  
  1043.  
  1044. SaveGame(fname)
  1045. char fname[20];
  1046. {
  1047. FILE *fd;
  1048. short loc,i;
  1049.  
  1050.   if (fname[0] == '\0') strcpy(fname,"chess.000");
  1051.   fd = fopen(fname,"w");
  1052.   fprintf(fd,"%d %d %d\n",computer,opponent,Game50);
  1053.   fprintf(fd,"%d %d %d %d\n",
  1054.           castld[white],castld[black],kingmoved[white],kingmoved[black]);
  1055.   fprintf(fd,"%d %d\n",TCflag,OperatorTime);
  1056.   fprintf(fd,"%ld %ld %d %ld\n",
  1057.           TimeControl.clock[white],TimeControl.clock[black],
  1058.           TimeControl.moves[white],TimeControl.moves[black]);
  1059.   for (loc = 0; loc < 64; loc++)
  1060.     fprintf(fd,"%d\n",256*board[loc] + color[loc]);
  1061.   for (i = 0; i <= GameCnt; i++)
  1062.     fprintf(fd,"%d %d %d %ld %d %d %d\n",
  1063.             GameList[i].gmove,GameList[i].score,GameList[i].depth,
  1064.             GameList[i].nodes,GameList[i].time,
  1065.             GameList[i].piece,GameList[i].color);
  1066.   fclose(fd);
  1067. }
  1068.  
  1069.  
  1070. ListGame()
  1071. {
  1072. FILE *fd;
  1073. short i,f,t;
  1074.   fd = fopen("chess.lst","w");
  1075.   fprintf(fd,"\n");
  1076.   fprintf(fd,"       score  depth  nodes  time         ");
  1077.   fprintf(fd,"       score  depth  nodes  time\n");
  1078.   for (i = 0; i <= GameCnt; i++)
  1079.     {
  1080.       f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF);
  1081.       algbr(f,t,false);
  1082.       if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd,"         ");
  1083.       fprintf(fd,"%5s  %5d     %2d %6ld %5d",mvstr1,
  1084.               GameList[i].score,GameList[i].depth,
  1085.               GameList[i].nodes,GameList[i].time);
  1086.     }
  1087.   fprintf(fd,"\n\n");
  1088.   fclose(fd);
  1089.  
  1090.  
  1091. VerifyBook()
  1092. {
  1093. short i,j,side,found,pnt,tempb,tempc,temps;
  1094. unsigned short mv;
  1095. struct leaf *node;
  1096.   ClrScreen();
  1097.   for (i = 0; i < BookSize; i++)
  1098.     {
  1099.       CopyBoard(Stboard,board); CopyBoard(Stcolor,color);
  1100.       InitializeStats(); GameCnt = 0;
  1101.       kingmoved[white] = kingmoved[black] = false;
  1102.       castld[white] = castld[black] = false;
  1103.       side = white;
  1104.       for (j = 0; Book[i][j] > 0; j++)
  1105.         {
  1106.           MoveList(side,1);
  1107.           found = false;
  1108.           for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
  1109.             {
  1110.               node = &Tree[pnt];
  1111.               mv = (node->f << 8) + node->t;
  1112.               if (mv == Book[i][j])
  1113.                 {
  1114.                   found = true;
  1115.                   MakeMove(side,node,&tempb,&tempc,&temps);
  1116.                   break;
  1117.                 }
  1118.             }
  1119.           if (!found) break;
  1120.           side = otherside[side];
  1121.         }
  1122.       if (found) printz("%d   ok\n",i);
  1123.       else printz("%d   bad (%d)\n",i,j);
  1124.     }
  1125. }
  1126.  
  1127.  
  1128. SetTimeControl()
  1129. {
  1130. long minutes;
  1131.   
  1132.   TCmoves = 0; OperatorTime = 30000;
  1133.   while (TCmoves <= 0)
  1134.     {
  1135.       gotoXY(50,24); printz("Enter #moves #minutes: "); ClrEoln();
  1136.       scanz("%hd %ld",&TCmoves,&minutes);
  1137.     }
  1138.   while (OperatorTime * TCmoves > 60*minutes + TCmoves)
  1139.     {
  1140.       gotoXY(50,24); printz("Operator time= "); ClrEoln();
  1141.       scanz("%ld",&OperatorTime);
  1142.     }
  1143.   TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  1144.   TimeControl.clock[white] = TimeControl.clock[black] = 60*minutes;
  1145.   TCflag = true;
  1146.   et = 0;
  1147. #ifndef MSDOS
  1148.   (void) times(&tmbuf1);
  1149. #endif MSDOS
  1150.   ElapsedTime(1);
  1151. }
  1152.  
  1153.  
  1154. ElapsedTime(iop)
  1155. short iop;
  1156. {
  1157. short m,s;
  1158.   et = time((long *)0) - time0;
  1159.   if (et < 0) et = 0;
  1160.   ETnodes += 50;
  1161.   if (et > et0 || iop == 1)
  1162.     {
  1163.       if (et > ResponseTime+ExtraTime) timeout = true;
  1164. #ifdef MSDOS
  1165.       if (kbhit()) timeout = true;
  1166. #endif MSDOS
  1167.       et0 = et;
  1168.       if (iop == 1)
  1169.         {
  1170.           time0 = time((long *)0); et0 = 0;
  1171.         }
  1172. #ifdef DISPLAY
  1173.       m = et/60; s = (et - 60*m);
  1174.       if (TCflag)
  1175.         {
  1176.           m = (TimeControl.clock[player] - et) / 60;
  1177.           s = absv(TimeControl.clock[player]) - et - 60*m;
  1178.         }
  1179.       if (player == white)
  1180.         if (reverse) gotoXY(20,2); else gotoXY(20,23);
  1181.       else
  1182.         if (reverse) gotoXY(20,23); else gotoXY(20,2);
  1183.       printz("%d:%2d   ",m,s);
  1184. #endif DISPLAY
  1185. #ifdef MSDOS
  1186.       cputimer = 100*et;
  1187.       if (et > 0) evrate = NodeCnt/(et+ft); else evrate = 0;
  1188. #else
  1189.       (void) times(&tmbuf2);
  1190.       cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ;
  1191.       if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft);
  1192.       else evrate = 0;
  1193. #endif MSDOS
  1194.       ETnodes = NodeCnt + 50;
  1195.       if (post)
  1196.         {
  1197.           gotoXY(50,22); printz("Nodes=   %6ld",NodeCnt);
  1198.           gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate);
  1199.         }
  1200.       refresh();
  1201.     }
  1202. }
  1203.  
  1204.  
  1205. post_move(node)
  1206. struct leaf *node;
  1207. {
  1208. short c,d,e,ply;
  1209.   e = lpost; c = player;
  1210.   gotoXY(50,3); printz("Score= %6d",node->score);
  1211.   if (c == white) d = 4; else d = 5;
  1212.   for (ply = 1; PrVar[ply] > 0; ply++)
  1213.     {
  1214.       algbr((short)(PrVar[ply]>>8),(short)(PrVar[ply] & 0x00FF),false);
  1215.       if (c == white) gotoXY(50,++d); else gotoXY(60,d);
  1216.       printz("%5s",mvstr1);
  1217.       c = otherside[c];
  1218.     }
  1219.   ClrEoln();
  1220.   lpost = d;
  1221.   while (++d <= e)
  1222.     {
  1223.       gotoXY(50,d); ClrEoln();
  1224.     }
  1225. }
  1226.  
  1227.  
  1228. DrawPiece(loc)
  1229. short loc;
  1230. {
  1231. #ifdef DISPLAY
  1232. short r,c; char x;
  1233.   if (reverse) r = 7-row[loc]; else r = row[loc];
  1234.   if (reverse) c = 7-col[loc]; else c = col[loc];
  1235.   if (color[loc] == black) x = '*'; else x = ' ';
  1236.   gotoXY(5+5*c,5+2*(7-r)); printz("%c%c ",x,px[board[loc]]);
  1237. #endif DISPLAY
  1238. }
  1239.  
  1240.  
  1241. UpdateDisplay(f,t,flag,iscastle)
  1242. short f,t,flag,iscastle;
  1243. {
  1244. #ifdef DISPLAY
  1245. short i,l,c,z; 
  1246.   if (flag)
  1247.     {
  1248.       i = 3;
  1249.       gotoXY(3,++i);
  1250.       printz("|----|----|----|----|----|----|----|----|");
  1251.       while (i<19)
  1252.         {
  1253.           gotoXY(1,++i);
  1254.           if (reverse) z = (i/2)-1; else z = 10-(i/2);
  1255.           printz("%d |    |    |    |    |    |    |    |    |",z);
  1256.           gotoXY(3,++i);
  1257.           printz("|----|----|----|----|----|----|----|----|");
  1258.         }
  1259.       gotoXY(3,21);
  1260.       if (reverse) printz("  h    g    f    e    d    c    b    a");
  1261.               else printz("  a    b    c    d    e    f    g    h");
  1262.       if (reverse) gotoXY(5,23); else gotoXY(5,2);
  1263.       if (computer == black) printz("Computer"); else printz("Human   ");
  1264.       if (reverse) gotoXY(5,2); else gotoXY(5,23);
  1265.       if (computer == white) printz("Computer"); else printz("Human   ");
  1266.       for (l = 0; l < 64; l++) DrawPiece(l);
  1267.     }
  1268.   else
  1269.     {
  1270.       DrawPiece(f); DrawPiece(t);
  1271.       if (iscastle)
  1272.         if (t > f)
  1273.           { DrawPiece(f+3); DrawPiece(t-1); }
  1274.         else
  1275.           { DrawPiece(f-4); DrawPiece(t+1); }
  1276.     }
  1277.   refresh();
  1278. #endif DISPLAY
  1279. }
  1280.  
  1281.  
  1282. PrintBoard()
  1283. {
  1284. short r,c,l;
  1285. #ifndef DISPLAY
  1286. printz("\n");
  1287. for (r = 7; r >= 0; r--)
  1288.   {
  1289.     for (c = 0; c <= 7; c++)
  1290.       {
  1291.         if (reverse) l = locn[7-r][7-c]; else l = locn[r][c];
  1292.         if (color[l] == neutral) printz(" -");
  1293.         else if (color[l] == white) printz(" %c",qx[board[l]]);
  1294.         else printz(" %c",px[board[l]]);
  1295.       }
  1296.     printz("\n");
  1297.   }
  1298. #endif DISPLAY
  1299. }
  1300.  
  1301.  
  1302. SetBoard()
  1303. {
  1304. short a,r,c,loc;
  1305. char s[80];
  1306.  
  1307.   ClrScreen(); UpdateDisplay(0,0,1,0);
  1308.   gotoXY(50,2); printz(".   exit to main");
  1309.   gotoXY(50,3); printz("#   clear board");
  1310.   a = white;
  1311.   do
  1312.   {
  1313.     gotoXY(49,5);
  1314.     printz("enter piece & location: "); ClrEoln(); scanz("%s",s);
  1315.     if (s[0] == '#')
  1316.       {
  1317.         for (loc = 0; loc < 64; loc++)
  1318.           { board[loc] = no_piece; color[loc] = neutral; }
  1319.         UpdateDisplay(0,0,1,0);
  1320.       }
  1321.     if (s[0] == 'c' || s[0] == 'C') a = otherside[a];
  1322.     c = s[1]-'a'; r = s[2]-'1';
  1323.     if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
  1324.       {
  1325.         loc = locn[r][c];
  1326.         color[loc] = a;
  1327.         if (s[0] == 'p') board[loc] = pawn;
  1328.         else if (s[0] == 'n') board[loc] = knight;
  1329.         else if (s[0] == 'b') board[loc] = bishop;
  1330.         else if (s[0] == 'r') board[loc] = rook;
  1331.         else if (s[0] == 'q') board[loc] = queen;
  1332.         else if (s[0] == 'k') board[loc] = king;
  1333.         else { board[loc] = no_piece; color[loc] = neutral; }
  1334.         DrawPiece(loc);
  1335.       }
  1336.   }
  1337.   while (s[0] != '.');
  1338.   if (board[4] != king) kingmoved[white] = 10;
  1339.   if (board[60] != king) kingmoved[black] = 10;
  1340.   GameCnt = -1; Game50 = 0; BookDepth = -1; Sdepth = 0;
  1341.   InitializeStats(); ClrScreen(); UpdateDisplay(0,0,1,0);
  1342. }
  1343.   
  1344.  
  1345. NewGame()
  1346. {
  1347. short l,r,c,p;
  1348.  
  1349.   mate = quit = reverse = bothsides = post = randflag = TCflag = false;
  1350.   hashflag = force = easy = false;
  1351.   beep = true;
  1352.   mycnt1 = mycnt2 = 0;
  1353.   lpost =  NodeCnt = epsquare = et0 = 0;
  1354.   Awindow = 9000;
  1355.   Bwindow = 90;
  1356.   MaxSearchDepth = 30;
  1357.   prune = 50;
  1358.   contempt[white] = contempt[black] = 0;
  1359. #ifdef MSDOS
  1360.   BookDepth = 24;
  1361. #else
  1362.   BookDepth = 50;
  1363. #endif MSDOS
  1364.   GameCnt = -1; Game50 = 0;
  1365.   Zwmtl = Zbmtl = 0;
  1366.   Developed[white] = Developed[black] = false;
  1367.   castld[white] = castld[black] = false;
  1368.   kingmoved[white] = kingmoved[black] = 0;
  1369.   PawnThreat[0] = CptrFlag[0] = Threat[0] = false;
  1370.   Pscore[0] = 12000; Tscore[0] = 12000;
  1371.   TimeControl.clock[white] = TimeControl.clock[black] = 0;
  1372.   TimeControl.moves[white] = TimeControl.moves[black] = 0;
  1373.   opponent = white; computer = black;
  1374.   for (r = 0; r < 8; r++)
  1375.     for (c = 0; c < 8; c++)
  1376.       {
  1377.         l = 8*r+c; locn[r][c] = l;
  1378.         row[l] = r; col[l] = c;
  1379.         board[l] = Stboard[l]; color[l] = Stcolor[l];
  1380.       }
  1381.   for (c = white; c <= black; c++)
  1382.     for (p = pawn; p <= king; p++)
  1383.       for (l = 0; l < 64; l++)
  1384.         {
  1385.           hashcode[c][p][l].key = (unsigned short)rand();
  1386.           hashcode[c][p][l].bd = ((unsigned long)rand() << 16) +
  1387.                                  (unsigned long)rand();
  1388.         }
  1389. #ifdef CHESSTOOL
  1390.   printf("Chess\n");
  1391.   easy = true;
  1392. #else
  1393.   ClrScreen(); gotoXY(1,20);
  1394.   printz("enter response time: "); ClrEoln();
  1395.   scanz("%ld",&Level);
  1396.   ClrScreen();
  1397. #endif CHESSTOOL
  1398.   UpdateDisplay(0,0,1,0);
  1399.   InitializeStats();
  1400.   time0 = time((long *)0);
  1401.   ElapsedTime(1);
  1402.   GetOpenings();
  1403. }
  1404.  
  1405.  
  1406. help()
  1407. {
  1408.   ClrScreen();
  1409.   gotoXY(28,1); printz("CHESS command summary");
  1410.   gotoXY(1,3); printz("g1f3      move from g1 to f3");
  1411.   gotoXY(1,4); printz("nf3       move knight to f3");
  1412.   gotoXY(1,5); printz("o-o       castle king side");
  1413.   gotoXY(1,6); printz("o-o-o     castle queen side");
  1414.   gotoXY(1,7); printz("set       edit board");
  1415.   gotoXY(1,8); printz("switch    sides with computer");
  1416.   gotoXY(1,9); printz("white     computer plays white");
  1417.   gotoXY(1,10); printz("black     computer plays black");
  1418.   gotoXY(1,11); printz("reverse   board display");
  1419.   gotoXY(1,12); printz("both      computer match");
  1420.   gotoXY(1,13); printz("random    randomize play");
  1421.   gotoXY(1,14); printz("undo      undo last move");
  1422.   gotoXY(42,3); printz("time      change level");
  1423.   gotoXY(42,4); printz("depth     set search depth");
  1424.   gotoXY(42,5); printz("post      principle variation");
  1425.   gotoXY(42,6); printz("hint      suggest a move");
  1426.   gotoXY(42,7); printz("bd        redraw board");
  1427.   gotoXY(42,8); printz("clock     set time control");
  1428.   gotoXY(42,9); printz("force     enter game moves");
  1429.   gotoXY(42,10); printz("list      game to chess.lst");
  1430.   gotoXY(42,11); printz("save      game to file");
  1431.   gotoXY(42,12); printz("get       game from file");
  1432.   gotoXY(42,13); printz("new       start new game");
  1433.   gotoXY(42,14); printz("quit      exit CHESS");
  1434.   gotoXY(10,21); printz("Computer: ");
  1435.   if (computer == white) printz("WHITE"); else printz("BLACK");
  1436.   gotoXY(10,22); printz("Opponent: ");
  1437.   if (opponent == white) printz("WHITE"); else printz("BLACK");
  1438.   gotoXY(10,23); printz("Response time: %ld",Level," sec.");
  1439.   gotoXY(10,24); printz("Easy mode: ");
  1440.   if (easy) printz("ON"); else printz("OFF");
  1441.   gotoXY(40,21); printz("Depth: %d",MaxSearchDepth);
  1442.   gotoXY(40,22); printz("Random: "); 
  1443.   if (randflag) printz("ON"); else printz("OFF");
  1444.   gotoXY(40,23); printz("Transposition table: ");
  1445.   if (hashflag) printz("ON"); else printz("OFF");
  1446.   refresh();
  1447.   while (getchar() != '\n');
  1448.   ClrScreen();
  1449.   UpdateDisplay(0,0,1,0);
  1450. }
  1451.  
  1452.  
  1453. UpdateHashbd(side,piece,f,t)
  1454. short side,piece,f,t;
  1455. /*
  1456.    hashbd contains a 32 bit "signature" of the board position.
  1457.    hashkey contains a 16 bit code used to address the hash table.
  1458.    When a move is made, XOR'ing the hashcode of moved piece on the from and
  1459.    to squares with the hashbd and hashkey values keeps things current.
  1460. */
  1461. {
  1462.   if (f >= 0)
  1463.     {
  1464.       hashbd ^= hashcode[side][piece][f].bd;
  1465.       hashkey ^= hashcode[side][piece][f].key;
  1466.     }
  1467.   if (t >= 0)
  1468.     {
  1469.       hashbd ^= hashcode[side][piece][t].bd;
  1470.       hashkey ^= hashcode[side][piece][t].key;
  1471.     }
  1472. }
  1473.  
  1474.  
  1475. UpdatePieceList(side,loc,iop)
  1476. short side,loc,iop;
  1477.  
  1478. /*
  1479.     Array PieceList[side][Pindx] contains the location of all the pieces of
  1480.     either side. Array Pindex[loc] contains the indx into PieceList for a
  1481.     given square.
  1482. */
  1483.  
  1484. {
  1485. register short i;
  1486.   if (iop == 1)
  1487.     {
  1488.       PieceCnt[side]--;
  1489.       for (i = Pindex[loc]; i <= PieceCnt[side]; i++)
  1490.         {
  1491.           PieceList[side][i] = PieceList[side][i+1];
  1492.           Pindex[PieceList[side][i]] = i;
  1493.         }
  1494.     }
  1495.   else
  1496.     {
  1497.       PieceCnt[side]++;
  1498.       PieceList[side][PieceCnt[side]] = loc;
  1499.       Pindex[loc] = PieceCnt[side];
  1500.     }
  1501. }
  1502.  
  1503.  
  1504.