386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 1 Jun 1990 20:03:08 +0000 (12:03 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 1 Jun 1990 20:03:08 +0000 (12:03 -0800)
Work on file usr/othersrc/games/chess/gnuchess.c
Work on file usr/othersrc/games/chess/gnuchess.h
Work on file usr/othersrc/games/chess/move.c
Work on file usr/othersrc/games/chess/move.h
Work on file usr/othersrc/games/chess/nondsp.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/othersrc/games/chess/gnuchess.c [new file with mode: 0644]
usr/othersrc/games/chess/gnuchess.h [new file with mode: 0644]
usr/othersrc/games/chess/move.c [new file with mode: 0644]
usr/othersrc/games/chess/move.h [new file with mode: 0644]
usr/othersrc/games/chess/nondsp.c [new file with mode: 0644]

diff --git a/usr/othersrc/games/chess/gnuchess.c b/usr/othersrc/games/chess/gnuchess.c
new file mode 100644 (file)
index 0000000..ac62953
--- /dev/null
@@ -0,0 +1,2307 @@
+/*
+  C source for CHESS  
+
+  Revision: 4-25-88
+
+  Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+  Copyright (c) 1988   John Stanback
+
+  This file is part of CHESS.
+
+  CHESS is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY.  No author or distributor
+  accepts responsibility to anyone for the consequences of using it
+  or for whether it serves any particular purpose or works at all,
+  unless he says so in writing.  Refer to the CHESS General Public
+  License for full details.
+
+  Everyone is granted permission to copy, modify and redistribute
+  CHESS, but only under the conditions described in the
+  CHESS General Public License.   A copy of this license is
+  supposed to have been given to you along with CHESS so you
+  can know your rights and responsibilities.  It should be in a
+  file named COPYING.  Among other things, the copyright notice
+  and this notice must be preserved on all copies.
+*/
+
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef MSDOS
+#include <stdlib.h>
+#include <time.h>
+#include <alloc.h>
+#define ttblsz 4096
+#else
+#include <sys/param.h>
+#include <sys/times.h>
+#define ttblsz 16384
+#define huge
+#endif MSDOS
+
+#include "move.h"
+
+#define neutral 2
+#define white 0
+#define black 1 
+#define no_piece 0
+#define pawn 1
+#define knight 2
+#define bishop 3
+#define rook 4
+#define queen 5
+#define king 6
+#define valueP 100
+#define valueN 350
+#define valueB 355
+#define valueR 550
+#define valueQ 1100
+#define valueK 1200
+#define ctlP 0x4000
+#define ctlN 0x2800
+#define ctlB 0x1800
+#define ctlR 0x0400
+#define ctlQ 0x0200
+#define ctlK 0x0100
+#define ctlBQ 0x1200
+#define ctlRQ 0x0600
+#define ctlNN 0x2000
+#define pxx " PNBRQK"
+#define qxx " pnbrqk"
+#define rxx "12345678"
+#define cxx "abcdefgh"
+#define check 0x0001
+#define capture 0x0002
+#define draw 0x0004
+#define promote 0x0008
+#define cstlmask 0x0010
+#define epmask 0x0020
+#define exact 0x0040
+#define pwnthrt 0x0080
+#define truescore 0x0001
+#define lowerbound 0x0002
+#define upperbound 0x0004
+#define maxdepth 30
+#define true 1
+#define false 0
+#define absv(x) ((x) < 0 ? -(x) : (x))
+#if (NEWMOVE < 1)
+#define taxicab(a,b) (abs(column[a]-column[b]) + abs(row[a]-row[b]))
+#endif
+struct leaf
+  {
+    short f,t,score,reply;
+    unsigned short flags;
+  };
+struct GameRec
+  {
+    unsigned short gmove;
+    short score,depth,time,piece,color;
+    long nodes;
+  };
+struct TimeControlRec
+  {
+    short moves[2];
+    long clock[2];
+  };
+struct BookEntry
+  {
+    struct BookEntry *next;
+    unsigned short *mv;
+  };
+struct hashval
+  {
+    unsigned long bd;
+    unsigned short key;
+  };
+struct hashentry
+  {
+    unsigned long hashbd;
+    unsigned short mv,flags;
+    short score,depth;
+  };
+
+char mvstr1[5],mvstr2[5];
+struct leaf Tree[2000],*root;
+short TrPnt[maxdepth],board[64],color[64];
+short row[64],column[64],locn[8][8],Pindex[64],svalue[64];
+short PieceList[2][16],PieceCnt[2],atak[2][64],PawnCnt[2][8];
+short castld[2],kingmoved[2],mtl[2],pmtl[2],emtl[2],hung[2];
+short c1,c2,*atk1,*atk2,*PC1,*PC2,EnemyKing;
+short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,dither;
+long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft;
+long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt;
+short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep;
+short wking,bking,FROMsquare,TOsquare,timeout,Zscore,zwndw,xwndw,slk;
+short INCscore;
+short HasPawn[2],HasKnight[2],HasBishop[2],HasRook[2],HasQueen[2];
+short ChkFlag[maxdepth],CptrFlag[maxdepth],PawnThreat[maxdepth];
+short Pscore[maxdepth],Tscore[maxdepth],Threat[maxdepth];
+struct GameRec GameList[240];
+short GameCnt,Game50,epsquare,lpost,rcptr,contempt;
+short MaxSearchDepth;
+struct BookEntry *Book;
+struct TimeControlRec TimeControl;
+short TCflag,TCmoves,TCminutes,OperatorTime;
+short otherside[3]={1,0,2};
+short rank7[3]={6,1,0};
+short map[64]=
+   {0,1,2,3,4,5,6,7,
+    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
+    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
+    0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
+    0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
+    0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
+    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77};
+short unmap[120]=
+   {0,1,2,3,4,5,6,7,-1,-1,-1,-1,-1,-1,-1,-1,
+    8,9,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,
+    16,17,18,19,20,21,22,23,-1,-1,-1,-1,-1,-1,-1,-1,
+    24,25,26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1,
+    32,33,34,35,36,37,38,39,-1,-1,-1,-1,-1,-1,-1,-1,
+    40,41,42,43,44,45,46,47,-1,-1,-1,-1,-1,-1,-1,-1,
+    48,49,50,51,52,53,54,55,-1,-1,-1,-1,-1,-1,-1,-1,
+    56,57,58,59,60,61,62,63};
+short Dcode[120]= 
+   {0,1,1,1,1,1,1,1,0,0,0,0,0,0,0x0E,0x0F,
+    0x10,0x11,0x12,0,0,0,0,0,0,0,0,0,0,0,0x0F,0x1F,
+    0x10,0x21,0x11,0,0,0,0,0,0,0,0,0,0,0x0F,0,0,
+    0x10,0,0,0x11,0,0,0,0,0,0,0,0,0x0F,0,0,0,
+    0x10,0,0,0,0x11,0,0,0,0,0,0,0x0F,0,0,0,0,
+    0x10,0,0,0,0,0x11,0,0,0,0,0x0F,0,0,0,0,0,
+    0x10,0,0,0,0,0,0x11,0,0,0x0F,0,0,0,0,0,0,
+    0x10,0,0,0,0,0,0,0x11};
+short Stboard[64]=
+   {rook,knight,bishop,queen,king,bishop,knight,rook,
+    pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
+    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,
+    pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
+    rook,knight,bishop,queen,king,bishop,knight,rook};
+short Stcolor[64]=
+   {white,white,white,white,white,white,white,white,
+    white,white,white,white,white,white,white,white,
+    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+    black,black,black,black,black,black,black,black,
+    black,black,black,black,black,black,black,black};
+short sweep[7]= {false,false,false,true,true,true,false};
+short Dpwn[3]={4,6,0};
+short Dstart[7]={6,4,8,4,0,0,0};
+short Dstop[7]={7,5,15,7,3,7,7};
+short Dir[16]={1,0x10,-1,-0x10,0x0F,0x11,-0x0F,-0x11,
+               0x0E,-0x0E,0x12,-0x12,0x1F,-0x1F,0x21,-0x21};
+short Pdir[34]={0,0x38,0,0,0,0,0,0,0,0,0,0,0,0,0x02,0x35,
+                0x38,0x35,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0x02,
+                0,0x02};
+short pbit[7]={0,0x01,0x02,0x04,0x08,0x10,0x20};
+unsigned short killr0[maxdepth],killr1[maxdepth],killr2[maxdepth];
+unsigned short killr3[maxdepth],PrVar[maxdepth];
+unsigned short PV,hint,Swag0,Swag1,Swag2,Swag3,Swag4;
+unsigned short hashkey;
+unsigned long hashbd;
+struct hashval hashcode[2][7][64];
+struct hashentry huge *ttable,*ptbl;
+unsigned char history[8192];
+
+short Mwpawn[64],Mbpawn[64],Mknight[2][64],Mbishop[2][64];
+short Mking[2][64],Kfield[2][64];
+short value[7]={0,valueP,valueN,valueB,valueR,valueQ,valueK};
+short control[7]={0,ctlP,ctlN,ctlB,ctlR,ctlQ,ctlK};
+short PassedPawn0[8]={0,60,80,120,200,360,600,800};
+short PassedPawn1[8]={0,30,40,60,100,180,300,800};
+short PassedPawn2[8]={0,15,25,35,50,90,140,800};
+short PassedPawn3[8]={0,5,10,15,20,30,140,800};
+short ISOLANI[8] = {-12,-16,-20,-24,-24,-20,-16,-12};
+short BACKWARD[8] = {-6,-10,-15,-21,-28,-28,-28,-28};
+short BMBLTY[14] = {-2,0,2,4,6,8,10,12,13,14,15,16,16,16};
+short RMBLTY[14] = {0,2,4,6,8,10,11,12,13,14,14,14,14,14};
+short Kthreat[16] = {0,-8,-20,-36,-52,-68,-80,-80,-80,-80,-80,-80,
+                     -80,-80,-80,-80};
+short KNIGHTPOST,KNIGHTSTRONG,BISHOPSTRONG,KATAK,KBNKsq;
+short PEDRNK2B,PWEAKH,PADVNCM,PADVNCI,PAWNSHIELD,PDOUBLED,PBLOK;
+short RHOPN,RHOPNX,KHOPN,KHOPNX,KSFTY;
+short ATAKD,HUNGP,HUNGX,KCASTLD,KMOVD,XRAY,PINVAL;
+short stage,stage2,Zwmtl,Zbmtl,Developed[2],PawnStorm;
+short PawnBonus,BishopBonus,RookBonus;
+short KingOpening[64]=
+   {  0,  0, -4,-10,-10, -4,  0,  0,
+     -4, -4, -8,-12,-12, -8, -4, -4,
+    -12,-16,-20,-20,-20,-20,-16,-12,
+    -16,-20,-24,-24,-24,-24,-20,-16,
+    -16,-20,-24,-24,-24,-24,-20,-16,
+    -12,-16,-20,-20,-20,-20,-16,-12,
+     -4, -4, -8,-12,-12, -8, -4, -4,
+      0,  0, -4,-10,-10, -4,  0,  0};
+short KingEnding[64]=
+   { 0, 6,12,18,18,12, 6, 0,
+     6,12,18,24,24,18,12, 6,
+    12,18,24,30,30,24,18,12,
+    18,24,30,36,36,30,24,18,
+    18,24,30,36,36,30,24,18,
+    12,18,24,30,30,24,18,12,
+     6,12,18,24,24,18,12, 6,
+     0, 6,12,18,18,12, 6, 0};
+short DyingKing[64]=
+   { 0, 8,16,24,24,16, 8, 0,
+     8,32,40,48,48,40,32, 8,
+    16,40,56,64,64,56,40,16,
+    24,48,64,72,72,64,48,24,
+    24,48,64,72,72,64,48,24,
+    16,40,56,64,64,56,40,16,
+     8,32,40,48,48,40,32, 8,
+     0, 8,16,24,24,16, 8, 0};
+short KBNK[64]=
+   {99,90,80,70,60,50,40,40,
+    90,80,60,50,40,30,20,40,
+    80,60,40,30,20,10,30,50,
+    70,50,30,10, 0,20,40,60,
+    60,40,20, 0,10,30,50,70,
+    50,30,10,20,30,40,60,80,
+    40,20,30,40,50,60,80,90,
+    40,40,50,60,70,80,90,99};
+short pknight[64]=
+   { 0, 4, 8,10,10, 8, 4, 0,
+     4, 8,16,20,20,16, 8, 4,
+     8,16,24,28,28,24,16, 8,
+    10,20,28,32,32,28,20,10,
+    10,20,28,32,32,28,20,10,
+     8,16,24,28,28,24,16, 8,
+     4, 8,16,20,20,16, 8, 4,
+     0, 4, 8,10,10, 8, 4, 0};
+short pbishop[64]=
+   {14,14,14,14,14,14,14,14,
+    14,22,18,18,18,18,22,14,
+    14,18,22,22,22,22,18,14,
+    14,18,22,22,22,22,18,14,
+    14,18,22,22,22,22,18,14,
+    14,18,22,22,22,22,18,14,
+    14,22,18,18,18,18,22,14,
+    14,14,14,14,14,14,14,14};
+short PawnAdvance[64]=
+   { 0, 0, 0, 0, 0, 0, 0, 0,
+     4, 4, 4, 0, 0, 4, 4, 4,
+     6, 8, 2,10,10, 2, 8, 6,
+     6, 8,12,16,16,12, 8, 6,
+     8,12,16,24,24,16,12, 8,
+    12,16,24,32,32,24,16,12,
+    12,16,24,32,32,24,16,12,
+     0, 0, 0, 0, 0, 0, 0, 0};
+     
+
+main(argc,argv)
+int argc; char *argv[];
+{
+#ifdef MSDOS
+  ttable = (struct hashentry huge *)farmalloc(ttblsz *
+           (unsigned long)sizeof(struct hashentry));
+#else
+  ttable = (struct hashentry *)malloc(ttblsz *
+           (unsigned long)sizeof(struct hashentry));
+#endif
+  Level = 0; TCflag = false; OperatorTime = 0;
+  if (argc == 2) Level = atoi(argv[1]);
+  if (argc == 3)
+    {
+      TCmoves = atoi(argv[1]); TCminutes = atoi(argv[2]); TCflag = true;
+    }
+  Initialize();
+  NewGame();
+#if (NEWMOVE > 0)
+  Initialize_dist();
+#if (NEWMOVE > 1)
+  Initialize_moves();
+#endif
+#endif
+  while (!(quit))
+    {
+      if (bothsides && !mate) SelectMove(opponent,1); else InputCommand();
+      if (!(quit || mate || force)) SelectMove(computer,1);
+    }
+  ExitChess();
+}
+
+
+
+/* ............    INTERFACE ROUTINES    ........................... */
+
+int VerifyMove(s,iop,mv)
+char s[];
+short iop;
+unsigned short *mv;
+
+/*
+   Compare the string 's' to the list of legal moves available for the 
+   opponent. If a match is found, make the move on the board. 
+*/
+
+{
+static short pnt,tempb,tempc,tempsf,tempst,cnt;
+static struct leaf xnode;
+struct leaf *node;
+
+  *mv = 0;
+  if (iop == 2)
+    {
+      UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
+      return(false);
+    }
+  cnt = 0;
+  MoveList(opponent,2);
+  pnt = TrPnt[2];
+  while (pnt < TrPnt[3])
+    {
+      node = &Tree[pnt++];
+      algbr(node->f,node->t,(short) node->flags & cstlmask);
+      if (strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0)
+        {
+          cnt++; xnode = *node;
+        }
+    }
+  if (cnt == 1)
+    {
+      MakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
+      if (SqAtakd(PieceList[opponent][0],computer))
+        {
+          UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
+          ShowMessage("Illegal Move!!");
+          return(false);
+        }
+      else
+        {
+          if (iop == 1) return(true);
+          if (xnode.flags & epmask) UpdateDisplay(0,0,1,0);
+          else UpdateDisplay(xnode.f,xnode.t,0,xnode.flags & cstlmask);
+          if (xnode.flags & cstlmask) Game50 = GameCnt;
+          else if (board[xnode.t] == pawn || (xnode.flags & capture)) 
+            Game50 = GameCnt;
+          GameList[GameCnt].depth = GameList[GameCnt].score = 0;
+          GameList[GameCnt].nodes = 0;
+          ElapsedTime(1);
+          GameList[GameCnt].time = (short)et;
+          TimeControl.clock[opponent] -= et;
+          --TimeControl.moves[opponent];
+          *mv = (xnode.f << 8) + xnode.t;
+          algbr(xnode.f,xnode.t,false);
+          return(true);
+        } 
+    }
+  if (cnt > 1) ShowMessage("Ambiguous Move!");
+  return(false);
+}
+
+
+NewGame()
+
+/*
+   Reset the board and other variables to start a new game.
+*/
+
+{
+short l,r,c,p;
+
+  mate = quit = reverse = bothsides = post = false;
+  hashflag = force = PawnStorm = false;
+  beep = rcptr = easy = true;
+  lpost =  NodeCnt = epsquare = et0 = 0;
+  dither = 0;
+  Awindow = 90;
+  Bwindow = 90;
+  xwndw = 90;
+  MaxSearchDepth = 29;
+  contempt = 0;
+  GameCnt = -1; Game50 = 0;
+  Zwmtl = Zbmtl = 0;
+  Developed[white] = Developed[black] = false;
+  castld[white] = castld[black] = false;
+  kingmoved[white] = kingmoved[black] = 0;
+  PawnThreat[0] = CptrFlag[0] = Threat[0] = false;
+  Pscore[0] = 12000; Tscore[0] = 12000;
+  opponent = white; computer = black;
+  for (r = 0; r < 8; r++)
+    for (c = 0; c < 8; c++)
+      {
+        l = 8*r+c; locn[r][c] = l;
+        row[l] = r; column[l] = c;
+        board[l] = Stboard[l]; color[l] = Stcolor[l];
+      }
+  for (c = white; c <= black; c++)
+    for (p = pawn; p <= king; p++)
+      for (l = 0; l < 64; l++)
+        {
+          hashcode[c][p][l].key = (unsigned short)rand();
+          hashcode[c][p][l].bd = ((unsigned long)rand() << 16) +
+                                 (unsigned long)rand();
+        }
+  ClrScreen();
+  if (TCflag) SetTimeControl();
+  else if (Level == 0) SelectLevel();
+  UpdateDisplay(0,0,1,0);
+  InitializeStats();
+  time0 = time((long *)0);
+  ElapsedTime(1);
+  GetOpenings();
+}
+
+
+algbr(f,t,iscastle)
+short f,t,iscastle;
+{
+  mvstr1[0] = cxx[column[f]]; mvstr1[1] = rxx[row[f]];
+  mvstr1[2] = cxx[column[t]]; mvstr1[3] = rxx[row[t]];
+  mvstr2[0] = qxx[board[f]];
+  mvstr2[1] = mvstr1[2]; mvstr2[2] = mvstr1[3];
+  mvstr1[4] = '\0'; mvstr2[3] = '\0';
+  if (iscastle)
+    if (t > f) strcpy(mvstr2,"o-o");
+    else strcpy(mvstr2,"o-o-o");
+}
+
+
+/* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
+
+SelectMove(side,iop)
+short side,iop;
+
+/*
+   Select a move by calling function search() at progressively deeper 
+   ply until time is up or a mate or draw is reached. An alpha-beta 
+   window of -90 to +90 points is set around the score returned from the 
+   previous iteration. If Sdepth != 0 then the program has correctly 
+   predicted the opponents move and the search will start at a depth of 
+   Sdepth+1 rather than a depth of 1. 
+*/
+
+{
+static short i,alpha,beta,score,tempb,tempc,tempsf,tempst,xside,rpt;
+
+  timeout = false;
+  xside = otherside[side];
+  if (iop != 2) player = side;
+  if (TCflag)
+    {
+      if (((TimeControl.moves[side] + 3) - OperatorTime) != 0)
+       ResponseTime = (TimeControl.clock[side]) /
+                      (TimeControl.moves[side] + 3) -
+                       OperatorTime;
+      else ResponseTime = 0;
+      ResponseTime += (ResponseTime*TimeControl.moves[side])/(2*TCmoves+1);
+    }
+  else ResponseTime = Level;
+  if (iop == 2) ResponseTime = 999;
+  if (Sdepth > 0 && root->score > Zscore-zwndw) ResponseTime -= ft;
+  else if (ResponseTime < 1) ResponseTime = 1;
+  ExtraTime = 0;
+  ExaminePosition();
+  ScorePosition(side,&score);
+  ShowSidetomove();
+  
+  if (Sdepth == 0)
+  {
+    ZeroTTable();
+    SearchStartStuff(side);
+    for (i = 0; i < 8192; i++) history[i] = 0;
+    FROMsquare = TOsquare = -1;
+    PV = 0;
+    if (iop != 2) hint = 0;
+    for (i = 0; i < maxdepth; i++)
+     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
+    alpha = score-90; beta = score+90;
+    rpt = 0;
+    TrPnt[1] = 0; root = &Tree[0];
+    MoveList(side,1);
+    for (i = TrPnt[1]; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1);
+    if (Book != NULL) OpeningBook();
+    if (Book != NULL) timeout = true;
+    NodeCnt = ETnodes = EvalNodes = HashCnt = 0;
+    Zscore = 0; zwndw = 20;
+  }
+  
+  while (!timeout && Sdepth < MaxSearchDepth)
+    {
+      Sdepth++;
+      ShowDepth(' ');
+      score = search(side,1,Sdepth,alpha,beta,PrVar,&rpt);
+      for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
+      if (score < alpha)
+        {
+          ShowDepth('-');
+          ExtraTime = 10*ResponseTime;
+          ZeroTTable();
+          score = search(side,1,Sdepth,-9000,beta,PrVar,&rpt);
+        }
+      if (score > beta && !(root->flags & exact))
+        {
+          ShowDepth('+');
+          ExtraTime = 0;
+          ZeroTTable();
+          score = search(side,1,Sdepth,alpha,9000,PrVar,&rpt);
+        }
+      score = root->score;
+      if (!timeout)
+        for (i = TrPnt[1]+1; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1);
+      ShowResults(score,PrVar,'.');
+      for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
+      if (score > Zscore-zwndw && score > Tree[1].score+250) ExtraTime = 0;
+      else if (score > Zscore-3*zwndw) ExtraTime = ResponseTime;
+      else ExtraTime = 3*ResponseTime;
+      if (root->flags & exact) timeout = true;
+      if (Tree[1].score < -9000) timeout = true;
+      if (4*et > 2*ResponseTime + ExtraTime) timeout = true;
+      if (!timeout)
+        {
+          Tscore[0] = score;
+          if (Zscore == 0) Zscore = score;
+          else Zscore = (Zscore+score)/2;
+        }
+      zwndw = 20+abs(Zscore/12);
+      beta = score + Bwindow;
+      if (Zscore < score) alpha = Zscore - Awindow - zwndw;
+      else alpha = score - Awindow - zwndw;
+    }
+
+  score = root->score;
+  if (rpt >= 2 || score < -12000) root->flags |= draw;
+  if (iop == 2) return(0);
+  if (Book == NULL) hint = PrVar[2];
+  ElapsedTime(1);
+
+  if (score > -9999 && rpt <= 2)
+    {
+      MakeMove(side,root,&tempb,&tempc,&tempsf,&tempst);
+      algbr(root->f,root->t,(short) root->flags & cstlmask);
+    }
+  else mvstr1[0] = '\0';
+  OutputMove();
+  if (score == -9999 || score == 9998) mate = true;
+  if (mate) hint = 0;
+  if (root->flags & cstlmask) Game50 = GameCnt;
+  else if (board[root->t] == pawn || (root->flags & capture)) 
+    Game50 = GameCnt;
+  GameList[GameCnt].score = score;
+  GameList[GameCnt].nodes = NodeCnt;
+  GameList[GameCnt].time = (short)et;
+  GameList[GameCnt].depth = Sdepth;
+  if (TCflag)
+    {
+      TimeControl.clock[side] -= (et + OperatorTime);
+      if (--TimeControl.moves[side] == 0) SetTimeControl();
+    }
+  if ((root->flags & draw) && bothsides) quit = true;
+  if (GameCnt > 238) quit = true;
+  player = xside;
+  Sdepth = 0;
+  fflush(stdin);
+  return(0);
+}
+
+
+OpeningBook()
+
+/*
+   Go thru each of the opening lines of play and check for a match with 
+   the current game listing. If a match occurs, generate a random number. 
+   If this number is the largest generated so far then the next move in 
+   this line becomes the current "candidate". After all lines are 
+   checked, the candidate move is put at the top of the Tree[] array and 
+   will be played by the program. Note that the program does not handle 
+   book transpositions. 
+*/
+
+{
+short j,pnt;
+unsigned short m,*mp;
+unsigned r,r0;
+struct BookEntry *p;
+
+  srand((unsigned)time0);
+  r0 = m = 0;
+  p = Book;
+  while (p != NULL)
+    {
+      mp = p->mv;
+      for (j = 0; j <= GameCnt; j++)
+        if (GameList[j].gmove != *(mp++)) break;
+      if (j > GameCnt)
+        if ((r=rand()) > r0)
+          {
+            r0 = r; m = *mp;
+            hint = *(++mp);
+          }
+      p = p->next;
+    }
+    
+  for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
+    if ((Tree[pnt].f<<8) + Tree[pnt].t == m) Tree[pnt].score = 0;
+  pick(TrPnt[1],TrPnt[2]-1);
+  if (Tree[TrPnt[1]].score < 0) Book = NULL;
+}
+
+
+#define UpdateSearchStatus\
+{\
+  if (post) ShowCurrentMove(pnt,node->f,node->t);\
+  if (pnt > TrPnt[1])\
+    {\
+      d = best-Zscore; e = best-node->score;\
+      if (best < alpha) ExtraTime = 10*ResponseTime;\
+      else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
+      else if (d > -zwndw) ExtraTime = 0;\
+      else if (d > -3*zwndw) ExtraTime = ResponseTime;\
+      else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
+      else ExtraTime = 5*ResponseTime;\
+    }\
+}
+
+int search(side,ply,depth,alpha,beta,bstline,rpt)
+short side,ply,depth,alpha,beta,*rpt;
+unsigned short bstline[];
+
+/*
+   Perform an alpha-beta search to determine the score for the current 
+   board position. If depth <= 0 only capturing moves, pawn promotions 
+   and responses to check are generated and searched, otherwise all 
+   moves are processed. The search depth is modified for check evasions, 
+   certain re-captures and threats. Extensions may continue for up to 11 
+   ply beyond the nominal search depth. 
+*/
+
+#define prune (cf && score+node->score < alpha)
+#define ReCapture (rcptr && score > alpha && score < beta &&\
+                   ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
+#define MateThreat (ply < Sdepth+4 && ply > 4 &&\
+                    ChkFlag[ply-2] && ChkFlag[ply-4] &&\
+                    ChkFlag[ply-2] != ChkFlag[ply-4])
+
+{
+register short j,pnt;
+short best,tempb,tempc,tempsf,tempst;
+short xside,pbst,d,e,cf,score,rcnt;
+unsigned short mv,nxtline[maxdepth];
+struct leaf *node,tmp;
+
+  NodeCnt++;
+  xside = otherside[side];
+  if (depth < 0) depth = 0;
+  
+  if (ply <= Sdepth+3) repetition(rpt); else *rpt = 0;
+  if (*rpt >= 2) return(0);
+
+  score = evaluate(side,xside,ply,alpha,beta);
+  if (score > 9000)
+    {
+      bstline[ply] = 0;
+      return(score);
+    }
+                
+  if (depth > 0)
+    {
+      if (InChk || PawnThreat[ply-1] || ReCapture) ++depth;
+    }
+  else
+    {
+      if (score >= alpha &&
+         (InChk || PawnThreat[ply-1] || Threat[ply-1])) ++depth;
+      else if (score <= beta && MateThreat) ++depth;
+    }
+    
+  if (depth > 0 && hashflag && ply > 1)
+    {
+      ProbeTTable(side,depth,&alpha,&beta,&score);
+      bstline[ply] = PV;
+      bstline[ply+1] = 0;
+      if (beta == -20000) return(score);
+      if (alpha > beta) return(alpha);
+    }
+    
+  if (Sdepth == 1) d = 7; else d = 11;
+  if (ply > Sdepth+d || (depth < 1 && score > beta)) return(score);
+
+  if (ply > 1)
+    if (depth > 0) MoveList(side,ply);
+    else CaptureList(side,xside,ply);
+    
+  if (TrPnt[ply] == TrPnt[ply+1]) return(score);
+    
+  cf = (depth < 1 && ply > Sdepth+1 && !ChkFlag[ply-2] && !slk);
+
+  if (depth > 0) best = -12000; else best = score;
+  if (best > alpha) alpha = best;
+  
+  for (pnt = pbst = TrPnt[ply];
+       pnt < TrPnt[ply+1] && best <= beta;
+       pnt++)
+    {
+      if (ply > 1) pick(pnt,TrPnt[ply+1]-1);
+      node = &Tree[pnt];
+      mv = (node->f << 8) + node->t;
+      nxtline[ply+1] = 0;
+      
+      if (prune) break;
+      if (ply == 1) UpdateSearchStatus;
+
+      if (!(node->flags & exact))
+        {
+          MakeMove(side,node,&tempb,&tempc,&tempsf,&tempst);
+          CptrFlag[ply] = (node->flags & capture);
+          PawnThreat[ply] = (node->flags & pwnthrt);
+          Tscore[ply] = node->score;
+          PV = node->reply;
+          node->score = -search(xside,ply+1,depth-1,-beta,-alpha,
+                                nxtline,&rcnt);
+          if (abs(node->score) > 9000) node->flags |= exact;
+          else if (rcnt == 1) node->score /= 2;
+          if (rcnt >= 2 || GameCnt-Game50 > 99 ||
+             (node->score == 9999-ply && !ChkFlag[ply]))
+            {
+              node->flags |= draw; node->flags |= exact;
+              if (side == computer) node->score = contempt;
+              else node->score = -contempt;
+            }
+          node->reply = nxtline[ply+1];
+          UnmakeMove(side,node,&tempb,&tempc,&tempsf,&tempst);
+        }
+      if (node->score > best && !timeout)
+        {
+          if (depth > 0)
+            if (node->score > alpha && !(node->flags & exact))
+              node->score += depth;
+          best = node->score; pbst = pnt;
+          if (best > alpha) alpha = best;
+          for (j = ply+1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
+          bstline[j] = 0;
+          bstline[ply] = mv;
+          if (ply == 1)
+            {
+              if (best == alpha)
+                {
+                  tmp = Tree[pnt];
+                  for (j = pnt-1; j >= 0; j--) Tree[j+1] = Tree[j];
+                  Tree[0] = tmp;
+                  pbst = 0;
+                }
+              if (Sdepth > 2)
+                if (best > beta) ShowResults(best,bstline,'+');
+                else if (best < alpha) ShowResults(best,bstline,'-');
+                else ShowResults(best,bstline,'&');
+            }
+        }
+      if (NodeCnt > ETnodes) ElapsedTime(0);
+      if (timeout) return(-Tscore[ply-1]);
+    }
+    
+  node = &Tree[pbst];
+  mv = (node->f<<8) + node->t;
+  if (hashflag && ply <= Sdepth && *rpt == 0 && best == alpha)
+    PutInTTable(side,best,depth,alpha,beta,mv);
+  if (depth > 0)
+    {
+      j = (node->f<<6) + node->t; if (side == black) j |= 0x1000;
+      if (history[j] < 150) history[j] += 2*depth;
+      if (node->t != (GameList[GameCnt].gmove & 0xFF))
+        if (best <= beta) killr3[ply] = mv;
+        else if (mv != killr1[ply])
+          {
+            killr2[ply] = killr1[ply];
+            killr1[ply] = mv;
+          }
+      if (best > 9000) killr0[ply] = mv; else killr0[ply] = 0;
+    }
+  return(best);
+}
+
+
+evaluate(side,xside,ply,alpha,beta)
+short side,xside,ply,alpha,beta;
+
+/*
+   Compute an estimate of the score by adding the positional score from 
+   the previous ply to the material difference. If this score falls 
+   inside a window which is 180 points wider than the alpha-beta window 
+   (or within a 50 point window during quiescence search) call 
+   ScorePosition() to determine a score, otherwise return the estimated 
+   score. If one side has only a king and the other either has no pawns 
+   or no pieces then the function ScoreLoneKing() is called. 
+*/
+
+{
+short s,evflag;
+
+  hung[white] = hung[black] = 0;
+  slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
+         (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
+  s = -Pscore[ply-1] + mtl[side] - mtl[xside];
+  s -= INCscore;
+  
+  if (slk) evflag = false;
+  else evflag = 
+     (ply == 1 || ply < Sdepth ||
+     ((ply == Sdepth+1 || ply == Sdepth+2) &&
+      (s > alpha-xwndw && s < beta+xwndw)) ||
+     (ply > Sdepth+2 && s >= alpha-25 && s <= beta+25));
+    
+  if (evflag)
+    {
+      EvalNodes++;
+      ataks(side,atak[side]);
+      if (atak[side][PieceList[xside][0]] > 0) return(10001-ply);
+      ataks(xside,atak[xside]);
+      InChk = (atak[xside][PieceList[side][0]] > 0);
+      ScorePosition(side,&s);
+    }
+  else
+    {
+      if (SqAtakd(PieceList[xside][0],side)) return(10001-ply);
+      InChk = SqAtakd(PieceList[side][0],xside);
+      if (slk) ScoreLoneKing(side,&s);
+    }
+    
+  Pscore[ply] = s - mtl[side] + mtl[xside];
+  if (InChk) ChkFlag[ply-1] = Pindex[TOsquare];
+  else ChkFlag[ply-1] = 0;
+  Threat[ply-1] = (hung[side] > 1 && ply == Sdepth+1);
+  return(s);
+}
+
+
+ProbeTTable(side,depth,alpha,beta,score)
+short side,depth,*alpha,*beta,*score;
+
+/* 
+   Look for the current board position in the transposition table.
+*/
+
+{
+short hindx;
+  if (side == white) hashkey |= 1; else hashkey &= 0xFFFE;
+  hindx = (hashkey & (ttblsz-1));
+  ptbl = (ttable + hindx);
+  if (ptbl->depth >= depth && ptbl->hashbd == hashbd)
+    {
+      HashCnt++;
+      PV = ptbl->mv;
+      if (ptbl->flags & truescore)
+        {
+          *score = ptbl->score;
+          *beta = -20000;
+          return(true);
+        }
+/*
+      else if (ptbl->flags & upperbound)
+        {
+          if (ptbl->score < *beta) *beta = ptbl->score+1;
+        }
+*/
+      else if (ptbl->flags & lowerbound)
+        {
+          if (ptbl->score > *alpha) *alpha = ptbl->score-1;
+        }
+    }
+  return(false);
+}
+
+
+PutInTTable(side,score,depth,alpha,beta,mv)
+short side,score,depth,alpha,beta;
+unsigned short mv;
+
+/*
+   Store the current board position in the transposition table.
+*/
+
+{
+short hindx;
+  if (side == white) hashkey |= 1; else hashkey &= 0xFFFE;
+  hindx = (hashkey & (ttblsz-1));
+  ptbl = (ttable + hindx);
+  ptbl->hashbd = hashbd;
+  ptbl->depth = depth;
+  ptbl->score = score; 
+  ptbl->mv = mv;
+  ptbl->flags = 0;
+  if (score < alpha) ptbl->flags |= upperbound;
+  else if (score > beta) ptbl->flags |= lowerbound;
+  else ptbl->flags |= truescore;
+}
+
+
+ZeroTTable()
+{
+int i;
+  if (hashflag)
+    for (i = 0; i < ttblsz; i++)
+      {
+        ptbl = (ttable + i);
+        ptbl->depth = 0;
+      }
+}
+
+
+MoveList(side,ply)
+short side,ply;
+
+/*
+   Fill the array Tree[] with all available moves for side to play. Array 
+   TrPnt[ply] contains the index into Tree[] of the first move at a ply. 
+*/
+    
+{
+register short i;
+short xside,f;
+
+  xside = otherside[side];
+  if (PV == 0) Swag0 = killr0[ply]; else Swag0 = PV;
+  Swag1 = killr1[ply]; Swag2 = killr2[ply];
+  Swag3 = killr3[ply]; Swag4 = 0;
+  if (ply > 2) Swag4 = killr1[ply-2];
+  TrPnt[ply+1] = TrPnt[ply];
+  Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
+  for (i = PieceCnt[side]; i >= 0; i--)
+    GenMoves(ply,PieceList[side][i],side,xside);
+  if (kingmoved[side] == 0 && !castld[side])
+    {
+      f = PieceList[side][0];
+      if (castle(side,f,f+2,0))
+        {
+          LinkMove(ply,f,f+2,xside);
+          Tree[TrPnt[ply+1]-1].flags |= cstlmask;
+        }
+      if (castle(side,f,f-2,0))
+        {
+          LinkMove(ply,f,f-2,xside);
+          Tree[TrPnt[ply+1]-1].flags |= cstlmask;
+        }
+    }
+}
+
+#if (NEWMOVE < 11)
+GenMoves(ply,sq,side,xside)
+short ply,sq,side,xside;
+
+/*
+   Generate moves for a piece. The from square is mapped onto a special  
+   board and offsets (taken from array Dir[]) are added to the mapped 
+   location. The newly generated square is tested to see if it falls off 
+   the board by ANDing the square with 88 HEX. Legal moves are linked 
+   into the tree. 
+*/
+    
+{
+register short m,u,d;
+short i,m0,piece; 
+
+  piece = board[sq]; m0 = map[sq];
+  if (sweep[piece])
+    for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+      {
+        d = Dir[i]; m = m0+d;
+        while (!(m & 0x88))
+          {
+            u = unmap[m];
+            if (color[u] == neutral)
+              {
+                LinkMove(ply,sq,u,xside);
+                m += d;
+              }
+            else if (color[u] == xside)
+              {
+                LinkMove(ply,sq,u,xside);
+                break;
+              }
+            else break;
+          }
+      }
+  else if (piece == pawn)
+    {
+      if (side == white && color[sq+8] == neutral)
+        {
+          LinkMove(ply,sq,sq+8,xside);
+          if (row[sq] == 1)
+            if (color[sq+16] == neutral)
+              LinkMove(ply,sq,sq+16,xside);
+        }
+      else if (side == black && color[sq-8] == neutral)
+        {
+          LinkMove(ply,sq,sq-8,xside);
+          if (row[sq] == 6)
+            if (color[sq-16] == neutral)
+              LinkMove(ply,sq,sq-16,xside);
+        }
+      for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+        if (!((m = m0+Dir[i]) & 0x88))
+          {
+            u = unmap[m];
+            if (color[u] == xside || u == epsquare)
+              LinkMove(ply,sq,u,xside);
+          }
+    }
+  else
+    {
+      for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+        if (!((m = m0+Dir[i]) & 0x88))
+          {
+            u = unmap[m];
+            if (color[u] != side) LinkMove(ply,sq,u,xside);
+          }
+    }
+}
+#endif
+
+LinkMove(ply,f,t,xside)
+short ply,f,t,xside;
+
+/*
+   Add a move to the tree.  Assign a bonus to order the moves
+   as follows:
+     1. Principle variation
+     2. Capture of last moved piece
+     3. Other captures (major pieces first)
+     4. Killer moves
+     5. "history" killers    
+*/
+
+{
+register short s,z;
+unsigned short mv;
+struct leaf *node;
+
+  node = &Tree[TrPnt[ply+1]];
+  ++TrPnt[ply+1];
+  node->flags = node->reply = 0;
+  node->f = f; node->t = t;
+  mv = (f<<8) + t;
+  s = 0;
+  if (mv == Swag0) s = 2000;
+  else if (mv == Swag1) s = 60;
+  else if (mv == Swag2) s = 50;
+  else if (mv == Swag3) s = 40;
+  else if (mv == Swag4) s = 30;
+  if (color[t] != neutral)
+    {
+      node->flags |= capture;
+      if (t == TOsquare) s += 500;
+      s += value[board[t]] - board[f];
+    }
+  if (board[f] == pawn)
+    if (row[t] == 0 || row[t] == 7)
+      {
+        node->flags |= promote;
+        s += 800;
+      }
+    else if (row[t] == 1 || row[t] == 6)
+      {
+        node->flags |= pwnthrt;
+        s += 600;
+      }
+    else if (t == epsquare) node->flags |= epmask;
+  z = (f<<6) + t; if (xside == white) z |= 0x1000;
+  s += history[z];
+  node->score = s - 20000;
+}
+
+#if (NEWMOVE < 10)
+CaptureList(side,xside,ply)
+short side,xside,ply;
+
+/*
+    Generate captures and Pawn promotions only.
+*/
+
+#define LinkCapture\
+{\
+  node->f = sq; node->t = u;\
+  node->reply = 0;\
+  node->flags = capture;\
+  node->score = value[board[u]] + svalue[board[u]] - piece;\
+  if (piece == pawn && (u < 8 || u > 55))\
+    {\
+      node->flags |= promote;\
+      node->score = valueQ;\
+    }\
+  ++node;\
+  ++TrPnt[ply+1];\
+}
+
+{
+register short m,u;
+short d,sq,i,j,j1,j2,m0,r7,d0,piece,*PL;
+struct leaf *node;
+
+  TrPnt[ply+1] = TrPnt[ply];
+  node = &Tree[TrPnt[ply]];
+  Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
+  if (side == white)
+    {
+      r7 = 6; d0 = 8;
+    }
+  else
+    {
+      r7 = 1; d0 = -8;
+    }
+  PL = PieceList[side];
+  for (i = 0; i <= PieceCnt[side]; i++)
+    { 
+      sq = PL[i];
+      m0 = map[sq]; piece = board[sq];
+      j1 = Dstart[piece]; j2 = Dstop[piece];
+      if (sweep[piece])
+        for (j = j1; j <= j2; j++)
+          {
+            d = Dir[j]; m = m0+d;
+            while (!(m & 0x88))
+              {
+                u = unmap[m];
+                if (color[u] == neutral) m += d;
+                else
+                  {
+                    if (color[u] == xside) LinkCapture;
+                    break;
+                  }
+              }
+          }
+      else
+        {
+          for (j = j1; j <= j2; j++)
+            if (!((m = m0+Dir[j]) & 0x88))
+              {
+                u = unmap[m];
+                if (color[u] == xside) LinkCapture;
+              }
+          if (piece == pawn && row[sq] == r7)
+            {
+              u = sq+d0;
+              if (color[u] == neutral) LinkCapture;
+            }
+        }
+    }
+}
+#endif
+  
+int castle(side,kf,kt,iop)
+short side,kf,kt,iop;
+
+/*
+   Make or Unmake a castling move.
+*/
+
+{
+short rf,rt,d,t0,xside;
+
+  xside = otherside[side];
+  if (kt > kf)
+    {
+      rf = kf+3; rt = kt-1; d = 1;
+    }
+  else
+    {
+      rf = kf-4; rt = kt+1; d = -1;
+    }
+  if (iop == 0)
+    {
+      if (board[kf] != king || board[rf] != rook || color[rf] != side)
+        return(false);
+      if (color[kt] != neutral || color[rt] != neutral) return(false);
+      if (d == -1 && color[kt+d] != neutral) return(false);
+      if (SqAtakd(kf,xside)) return(false);
+      if (SqAtakd(kt,xside)) return(false);
+      if (SqAtakd(kf+d,xside)) return(false);
+    }
+  else
+    {
+      if (iop == 1) castld[side] = true; else castld[side] = false;
+      if (iop == 2)
+        {
+          t0 = kt; kt = kf; kf = t0;
+          t0 = rt; rt = rf; rf = t0;
+        }
+      board[kt] = king; color[kt] = side; Pindex[kt] = 0;
+      board[kf] = no_piece; color[kf] = neutral;
+      board[rt] = rook; color[rt] = side; Pindex[rt] = Pindex[rf];
+      board[rf] = no_piece; color[rf] = neutral;
+      PieceList[side][Pindex[kt]] = kt;
+      PieceList[side][Pindex[rt]] = rt;
+      if (hashflag)
+        {
+          UpdateHashbd(side,king,kf,kt);
+          UpdateHashbd(side,rook,rf,rt);
+        }
+    }
+  return(true);
+}
+
+
+EnPassant(xside,f,t,iop)
+short xside,f,t,iop;
+
+/*
+   Make or unmake an en passant move.
+*/
+
+{
+short l;
+  if (t > f) l = t-8; else l = t+8;
+  if (iop == 1)
+    {
+      board[l] = no_piece; color[l] = neutral;
+    }
+  else 
+    {
+      board[l] = pawn; color[l] = xside;
+    }
+  InitializeStats();
+}
+
+
+MakeMove(side,node,tempb,tempc,tempsf,tempst)
+short side,*tempc,*tempb,*tempsf,*tempst;
+struct leaf *node;
+
+/*
+   Update Arrays board[], color[], and Pindex[] to reflect the new board 
+   position obtained after making the move pointed to by node. Also 
+   update miscellaneous stuff that changes when a move is made. 
+*/
+    
+{
+register short f,t;
+short xside,ct,cf;
+
+  xside = otherside[side];
+  f = node->f; t = node->t; epsquare = -1;
+  FROMsquare = f; TOsquare = t;
+  INCscore = 0;
+  GameList[++GameCnt].gmove = (f<<8) + t;
+  if (node->flags & cstlmask)
+    {
+      GameList[GameCnt].piece = no_piece;
+      GameList[GameCnt].color = side;
+      castle(side,f,t,1);
+    }
+  else
+    {
+      *tempc = color[t]; *tempb = board[t];
+      *tempsf = svalue[f]; *tempst = svalue[t];
+      GameList[GameCnt].piece = *tempb;
+      GameList[GameCnt].color = *tempc;
+      if (*tempc != neutral)
+        {
+          UpdatePieceList(*tempc,t,1);
+          if (*tempb == pawn) --PawnCnt[*tempc][column[t]];
+          if (board[f] == pawn)
+            {
+              --PawnCnt[side][column[f]];
+              ++PawnCnt[side][column[t]];
+              cf = column[f]; ct = column[t];
+              if (PawnCnt[side][ct] > 1+PawnCnt[side][cf])
+                INCscore -= 15;
+              else if (PawnCnt[side][ct] < 1+PawnCnt[side][cf])
+                INCscore += 15;
+              else if (ct == 0 || ct == 7 || PawnCnt[side][ct+ct-cf] == 0)
+                INCscore -= 15;
+            }
+          mtl[xside] -= value[*tempb];
+          if (*tempb == pawn) pmtl[xside] -= valueP;
+          if (hashflag) UpdateHashbd(xside,*tempb,-1,t);
+          INCscore += *tempst;
+        }
+      color[t] = color[f]; board[t] = board[f]; svalue[t] = svalue[f];
+      Pindex[t] = Pindex[f]; PieceList[side][Pindex[t]] = t;
+      color[f] = neutral; board[f] = no_piece;
+      if (board[t] == pawn)
+        if (t-f == 16) epsquare = f+8;
+        else if (f-t == 16) epsquare = f-8;
+      if (node->flags & promote)
+        {
+          board[t] = queen;
+          --PawnCnt[side][column[t]];
+          mtl[side] += valueQ - valueP;
+          pmtl[side] -= valueP;
+          HasQueen[side] = true;
+          if (hashflag)
+            {
+              UpdateHashbd(side,pawn,f,-1);
+              UpdateHashbd(side,queen,f,-1);
+            }
+          INCscore -= *tempsf;
+        } 
+      if (board[t] == king) ++kingmoved[side];
+      if (node->flags & epmask) EnPassant(xside,f,t,1);
+      else if (hashflag) UpdateHashbd(side,board[t],f,t);
+    }
+}
+
+
+UnmakeMove(side,node,tempb,tempc,tempsf,tempst)
+short side,*tempc,*tempb,*tempsf,*tempst;
+struct leaf *node;
+
+/*
+   Take back a move.
+*/
+
+{
+register short f,t;
+short xside;
+
+  xside = otherside[side];
+  f = node->f; t = node->t; epsquare = -1;
+  GameCnt--;
+  if (node->flags & cstlmask) castle(side,f,t,2);
+  else
+    {
+      color[f] = color[t]; board[f] = board[t]; svalue[f] = *tempsf;
+      Pindex[f] = Pindex[t]; PieceList[side][Pindex[f]] = f;
+      color[t] = *tempc; board[t] = *tempb; svalue[t] = *tempst;
+      if (node->flags & promote)
+        {
+          board[f] = pawn;
+          ++PawnCnt[side][column[t]];
+          mtl[side] += valueP - valueQ;
+          pmtl[side] += valueP;
+          if (hashflag)
+            {
+              UpdateHashbd(side,queen,-1,t);
+              UpdateHashbd(side,pawn,-1,t);
+            }
+        } 
+      if (*tempc != neutral)
+        {
+          UpdatePieceList(*tempc,t,2);
+          if (*tempb == pawn) ++PawnCnt[*tempc][column[t]];
+          if (board[f] == pawn)
+            {
+              --PawnCnt[side][column[t]];
+              ++PawnCnt[side][column[f]];
+            }
+          mtl[xside] += value[*tempb];
+          if (*tempb == pawn) pmtl[xside] += valueP;
+          if (hashflag) UpdateHashbd(xside,*tempb,-1,t);
+        }
+      if (board[f] == king) --kingmoved[side];
+      if (node->flags & epmask) EnPassant(xside,f,t,2);
+      else if (hashflag) UpdateHashbd(side,board[f],f,t);
+    }
+}
+
+
+UpdateHashbd(side,piece,f,t)
+short side,piece,f,t;
+
+/*
+   hashbd contains a 32 bit "signature" of the board position. hashkey 
+   contains a 16 bit code used to address the hash table. When a move is 
+   made, XOR'ing the hashcode of moved piece on the from and to squares 
+   with the hashbd and hashkey values keeps things current. 
+*/
+
+{
+  if (f >= 0)
+    {
+      hashbd ^= hashcode[side][piece][f].bd;
+      hashkey ^= hashcode[side][piece][f].key;
+    }
+  if (t >= 0)
+    {
+      hashbd ^= hashcode[side][piece][t].bd;
+      hashkey ^= hashcode[side][piece][t].key;
+    }
+}
+
+
+UpdatePieceList(side,sq,iop)
+short side,sq,iop;
+
+/*
+   Update the PieceList and Pindex arrays when a piece is captured or 
+   when a capture is unmade. 
+*/
+
+{
+register short i;
+  if (iop == 1)
+    {
+      PieceCnt[side]--;
+      for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
+        {
+          PieceList[side][i] = PieceList[side][i+1];
+          Pindex[PieceList[side][i]] = i;
+        }
+    }
+  else
+    {
+      PieceCnt[side]++;
+      PieceList[side][PieceCnt[side]] = sq;
+      Pindex[sq] = PieceCnt[side];
+    }
+}
+
+
+InitializeStats()
+
+/*
+   Scan thru the board seeing what's on each square. If a piece is found, 
+   update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also 
+   determine the material for each side and set the hashkey and hashbd 
+   variables to represent the current board position. Array 
+   PieceList[side][indx] contains the location of all the pieces of 
+   either side. Array Pindex[sq] contains the indx into PieceList for a 
+   given square. 
+*/
+
+{
+register short i,sq;
+  epsquare = -1;
+  for (i = 0; i < 8; i++)
+    PawnCnt[white][i] = PawnCnt[black][i] = 0;
+  mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
+  PieceCnt[white] = PieceCnt[black] = 0;
+  hashbd = hashkey = 0;
+  for (sq = 0; sq < 64; sq++)
+    if (color[sq] != neutral)
+      {
+        mtl[color[sq]] += value[board[sq]];
+        if (board[sq] == pawn)
+          {
+            pmtl[color[sq]] += valueP;
+            ++PawnCnt[color[sq]][column[sq]];
+          }
+        if (board[sq] == king) Pindex[sq] = 0;
+          else Pindex[sq] = ++PieceCnt[color[sq]];
+        PieceList[color[sq]][Pindex[sq]] = sq;
+        hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
+        hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
+      }
+}
+
+
+pick(p1,p2)
+short p1,p2;
+
+/*  
+   Find the best move in the tree between indexes p1 and p2. Swap the 
+   best move into the p1 element. 
+*/
+
+{
+register short p,s;
+short p0,s0;
+struct leaf temp;
+
+  s0 = Tree[p1].score; p0 = p1;
+  for (p = p1+1; p <= p2; p++)
+    if ((s = Tree[p].score) > s0)
+      {
+        s0 = s; p0 = p;
+      }
+  if (p0 != p1)
+    {
+      temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp;
+    }
+}
+
+
+repetition(cnt)
+short *cnt;
+
+/*
+    Check for draw by threefold repetition.
+*/
+
+{
+register short i,c;
+short f,t,b[64];
+unsigned short m;
+  *cnt = c = 0;
+  if (GameCnt > Game50+3)
+    {
+/*
+      memset((char *)b,0,64*sizeof(short));
+*/
+      for (i = 0; i < 64; b[i++] = 0);
+      for (i = GameCnt; i > Game50; i--)
+        {
+          m = GameList[i].gmove; f = m>>8; t = m & 0xFF;
+          if (++b[f] == 0) c--; else c++;
+          if (--b[t] == 0) c--; else c++;
+          if (c == 0) (*cnt)++;
+        }
+    }
+}
+
+#if (NEWMOVE < 3)
+int SqAtakd(sq,side)
+short sq,side;
+
+/*
+  See if any piece with color 'side' ataks sq.  First check for pawns
+  or king, then try other pieces. Array Dcode is used to check for
+  knight attacks or R,B,Q co-linearity.  
+*/
+
+{
+register short m,d;
+short i,m0,m1,loc,piece,*PL;
+
+  m1 = map[sq];
+  if (side == white) m = m1-0x0F; else m = m1+0x0F;
+  if (!(m & 0x88))
+    if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true);
+  if (side == white) m = m1-0x11; else m = m1+0x11;
+  if (!(m & 0x88))
+    if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true);
+  if (distance(sq,PieceList[side][0]) == 1) return(true);
+  
+  PL = PieceList[side];
+  for (i = 1; i <= PieceCnt[side]; i++)
+    {
+      loc = PL[i]; piece = board[loc];
+      if (piece == pawn) continue;
+      m0 = map[loc]; d = Dcode[abs(m1-m0)];
+      if (d == 0 || (Pdir[d] & pbit[piece]) == 0) continue;
+      if (piece == knight) return(true);
+      else
+        {
+          if (m1 < m0) d = -d;
+          for (m = m0+d; m != m1; m += d)
+            if (color[unmap[m]] != neutral) break;
+          if (m == m1) return(true);
+        }
+    }
+  return(false);
+}
+#endif
+
+#if (NEWMOVE < 2)
+ataks(side,a)
+short side,*a;
+
+/*
+    Fill array atak[][] with info about ataks to a square.  Bits 8-15
+    are set if the piece (king..pawn) ataks the square. Bits 0-7
+    contain a count of total ataks to the square.
+*/
+
+{
+register short u,m;
+short d,c,j,j1,j2,piece,i,m0,sq,*PL;
+/*
+  memset((char *)a,0,64*sizeof(short));
+*/
+  for (u = 0; u < 64; a[u++] = 0);
+  Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
+  PL = PieceList[side];
+  for (i = 0; i <= PieceCnt[side]; i++)
+    {
+      sq = PL[i];
+      m0 = map[sq];
+      piece = board[sq];
+      c = control[piece]; j1 = Dstart[piece]; j2 = Dstop[piece];
+      if (sweep[piece])
+        for (j = j1; j <= j2; j++)
+          {
+            d = Dir[j]; m = m0+d;
+            while (!(m & 0x88))
+              {
+                u = unmap[m];
+                a[u] = ++a[u] | c;
+                if (color[u] == neutral) m += d;
+                else break;
+              }
+          }
+      else
+        for (j = j1; j <= j2; j++)
+          if (!((m = m0+Dir[j]) & 0x88))
+            {
+              u = unmap[m];
+              a[u] = ++a[u] | c;
+            }
+    }
+}
+#endif
+
+/* ............    POSITIONAL EVALUATION ROUTINES    ............ */
+
+ScorePosition(side,score)
+short side,*score;
+
+/*
+   Perform normal static evaluation of board position. A score is 
+   generated for each piece and these are summed to get a score for each 
+   side. 
+*/
+
+{
+register short sq,s;
+short i,xside,pscore[3];
+
+  wking = PieceList[white][0]; bking = PieceList[black][0];
+  UpdateWeights();
+  xside = otherside[side];
+  pscore[white] = pscore[black] = 0;
+
+  for (c1 = white; c1 <= black; c1++)
+    {
+      c2 = otherside[c1];
+      if (c1 == white) EnemyKing = bking; else EnemyKing = wking;
+      atk1 = atak[c1]; atk2 = atak[c2];
+      PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2];
+      for (i = 0; i <= PieceCnt[c1]; i++)
+        {
+          sq = PieceList[c1][i];
+          s = SqValue(sq,side);
+          pscore[c1] += s;
+          svalue[sq] = s;
+        }
+    }
+  if (hung[side] > 1) pscore[side] += HUNGX;
+  if (hung[xside] > 1) pscore[xside] += HUNGX;
+  
+  *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
+  if (dither) *score += rand() % dither;
+  
+  if (*score > 0 && pmtl[side] == 0)
+    if (emtl[side] < valueR) *score = 0;
+    else if (*score < valueR) *score /= 2;
+  if (*score < 0 && pmtl[xside] == 0)
+    if (emtl[xside] < valueR) *score = 0;
+    else if (-*score < valueR) *score /= 2;
+    
+  if (mtl[xside] == valueK && emtl[side] > valueB) *score += 200;
+  if (mtl[side] == valueK && emtl[xside] > valueB) *score -= 200;
+}
+
+
+ScoreLoneKing(side,score)
+short side,*score;
+
+/* 
+   Static evaluation when loser has only a king and winner has no pawns
+   or no pieces.
+*/
+
+{
+short winner,loser,king1,king2,s,i;
+
+  UpdateWeights();
+  if (mtl[white] > mtl[black]) winner = white; else winner = black;
+  loser = otherside[winner];
+  king1 = PieceList[winner][0]; king2 = PieceList[loser][0];
+  
+  s = 0;
+  
+  if (pmtl[winner] > 0)
+    for (i = 1; i <= PieceCnt[winner]; i++)
+      s += ScoreKPK(side,winner,loser,king1,king2,PieceList[winner][i]);
+      
+  else if (emtl[winner] == valueB+valueN)
+    s = ScoreKBNK(winner,king1,king2);
+    
+  else if (emtl[winner] > valueB)
+    s = 500 + emtl[winner] - DyingKing[king2] - 2*distance(king1,king2);
+    
+  if (side == winner) *score = s; else *score = -s;
+}
+
+
+int ScoreKPK(side,winner,loser,king1,king2,sq)
+short side,winner,loser,king1,king2,sq;
+
+/*
+   Score King and Pawns versus King endings.
+*/
+
+{
+short s,r;
+  
+  if (PieceCnt[winner] == 1) s = 50; else s = 120;
+  if (winner == white)
+    {
+      if (side == loser) r = row[sq]-1; else r = row[sq];
+      if (row[king2] >= r && distance(sq,king2) < 8-r) s += 10*row[sq];
+      else s = 500+50*row[sq];
+      if (row[sq] < 6) sq += 16; else sq += 8;
+    }
+  else
+    {
+      if (side == loser) r = row[sq]+1; else r = row[sq];
+      if (row[king2] <= r && distance(sq,king2) < r+1) s += 10*(7-row[sq]);
+      else s = 500+50*(7-row[sq]);
+      if (row[sq] > 1) sq -= 16; else sq -= 8;
+    }
+  s += 8*(taxicab(king2,sq) - taxicab(king1,sq));
+  return(s);
+}
+
+
+int ScoreKBNK(winner,king1,king2)
+short winner,king1,king2;
+
+/*
+   Score King+Bishop+Knight versus King endings.
+   This doesn't work all that well but it's better than nothing.
+*/
+
+{
+short s;
+  s = emtl[winner] - 300;
+  if (KBNKsq == 0) s += KBNK[king2];
+  else s += KBNK[locn[row[king2]][7-column[king2]]];
+  s -= taxicab(king1,king2);
+  s -= distance(PieceList[winner][1],king2);
+  s -= distance(PieceList[winner][2],king2);
+  return(s);
+}
+
+
+SqValue(sq,side)
+short sq,side;
+
+/*
+   Calculate the positional value for the piece on 'sq'.
+*/
+
+{
+register short j,fyle,rank;
+short s,piece,a1,a2,in_square,r,mob,e,c;
+
+  piece = board[sq];
+  a1 = (atk1[sq] & 0x4FFF); a2 = (atk2[sq] & 0x4FFF);
+  rank = row[sq]; fyle = column[sq];
+  s = 0;
+  if (piece == pawn && c1 == white)
+    {
+      s = Mwpawn[sq];
+      if (sq == 11 || sq == 12)
+        if (color[sq+8] != neutral) s += PEDRNK2B;
+      if ((fyle == 0 || PC1[fyle-1] == 0) &&
+          (fyle == 7 || PC1[fyle+1] == 0))
+        s += ISOLANI[fyle];
+      else if (PC1[fyle] > 1) s += PDOUBLED;
+      if (a1 < ctlP && atk1[sq+8] < ctlP)
+        {
+          s += BACKWARD[a2 & 0xFF];
+          if (PC2[fyle] == 0) s += PWEAKH;
+          if (color[sq+8] != neutral) s += PBLOK;
+        }
+      if (PC2[fyle] == 0)
+        {
+          if (side == black) r = rank-1; else r = rank;
+          in_square = (row[bking] >= r && distance(sq,bking) < 8-r);
+          if (a2 == 0 || side == white) e = 0; else e = 1;
+          for (j = sq+8; j < 64; j += 8)
+            if (atk2[j] >= ctlP) { e = 2; break; }
+            else if (atk2[j] > 0 || color[j] != neutral) e = 1;
+          if (e == 2) s += (stage*PassedPawn3[rank]) / 10;
+          else if (in_square || e == 1) s += (stage*PassedPawn2[rank]) / 10;
+          else if (emtl[black] > 0) s += (stage*PassedPawn1[rank]) / 10;
+          else s += PassedPawn0[rank];
+        }
+    }
+  else if (piece == pawn && c1 == black)
+    {
+      s = Mbpawn[sq];
+      if (sq == 51 || sq == 52)
+        if (color[sq-8] != neutral) s += PEDRNK2B;
+      if ((fyle == 0 || PC1[fyle-1] == 0) &&
+          (fyle == 7 || PC1[fyle+1] == 0))
+        s += ISOLANI[fyle];
+      else if (PC1[fyle] > 1) s += PDOUBLED;
+      if (a1 < ctlP && atk1[sq-8] < ctlP)
+        {
+          s += BACKWARD[a2 & 0xFF];
+          if (PC2[fyle] == 0) s += PWEAKH;
+          if (color[sq-8] != neutral) s += PBLOK;
+        }
+      if (PC2[fyle] == 0)
+        {
+          if (side == white) r = rank+1; else r = rank;
+          in_square = (row[wking] <= r && distance(sq,wking) < r+1);
+          if (a2 == 0 || side == black) e = 0; else e = 1;
+          for (j = sq-8; j >= 0; j -= 8)
+            if (atk2[j] >= ctlP) { e = 2; break; }
+            else if (atk2[j] > 0 || color[j] != neutral) e = 1;
+          if (e == 2) s += (stage*PassedPawn3[7-rank]) / 10;
+          else if (in_square || e == 1) s += (stage*PassedPawn2[7-rank]) / 10;
+          else if (emtl[white] > 0) s += (stage*PassedPawn1[7-rank]) / 10;
+          else s += PassedPawn0[7-rank];
+        }
+    }
+  else if (piece == knight)
+    {
+      s = Mknight[c1][sq];
+    }
+  else if (piece == bishop)
+    {
+      s = Mbishop[c1][sq];
+      BRscan(sq,&s,&mob);
+      s += BMBLTY[mob];
+    }
+  else if (piece == rook)
+    {
+      s += RookBonus;
+      BRscan(sq,&s,&mob);
+      s += RMBLTY[mob];
+      if (PC1[fyle] == 0) s += RHOPN;
+      if (PC2[fyle] == 0) s += RHOPNX;
+      if (rank == rank7[c1] && pmtl[c2] > 100) s += 10;
+      if (stage > 2) s += 14 - taxicab(sq,EnemyKing);
+    }
+  else if (piece == queen)
+    {
+      if (stage > 2) s += 14 - taxicab(sq,EnemyKing);
+      if (distance(sq,EnemyKing) < 3) s += 12;
+    }
+  else if (piece == king)
+    {
+      s = Mking[c1][sq];
+      if (KSFTY > 0)
+        if (Developed[c2] || stage > 0) KingScan(sq,&s);
+      if (castld[c1]) s += KCASTLD;
+      else if (kingmoved[c1]) s += KMOVD;
+
+      if (PC1[fyle] == 0) s += KHOPN;
+      if (PC2[fyle] == 0) s += KHOPNX;
+      if (fyle == 1 || fyle == 2 || fyle == 3 || fyle == 7)
+        {
+          if (PC1[fyle-1] == 0) s += KHOPN;
+          if (PC2[fyle-1] == 0) s += KHOPNX;
+        }
+      if (fyle == 4 || fyle == 5 || fyle == 6 || fyle == 0)
+        {
+          if (PC1[fyle+1] == 0) s += KHOPN;
+          if (PC2[fyle+1] == 0) s += KHOPNX;
+        }
+      if (fyle == 2)
+        {
+          if (PC1[0] == 0) s += KHOPN;
+          if (PC2[0] == 0) s += KHOPNX;
+        }
+      if (fyle == 5)
+        {
+          if (PC1[7] == 0) s += KHOPN;
+          if (PC2[7] == 0) s += KHOPNX;
+        }
+    }
+    
+  if (a2 > 0) 
+    {
+      c = (control[piece] & 0x4FFF);
+      if (a1 == 0 || a2 > c+1)
+        {
+          s += HUNGP;
+          ++hung[c1];
+          if (piece != king && trapped(sq,piece)) ++hung[c1];
+        }
+      else if (piece != pawn || a2 > a1)
+        if (a2 >= c || a1 < ctlP) s += ATAKD;
+    }
+  return(s);
+}
+
+#if (NEWMOVE > 6)
+KingScan(sq,s)
+short sq,*s;
+
+/*
+   Assign penalties if king can be threatened by checks, if squares
+   near the king are controlled by the enemy (especially the queen),
+   or if there are no pawns near the king.
+*/
+
+#define ScoreThreat\
+  if (color[u] != c2)\
+    if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
+    else *s -= 3
+
+{
+register short m,u;
+short d,i,m0,cnt,ok;
+
+  cnt = 0;
+  m0 = map[sq];
+  if (HasBishop[c2] || HasQueen[c2])
+    for (i = Dstart[bishop]; i <= Dstop[bishop]; i++)
+      {
+        d = Dir[i]; m = m0+d;
+        while (!(m & 0x88))
+          {
+            u = unmap[m];
+            if (atk2[u] & ctlBQ) ScoreThreat;
+            if (color[u] != neutral) break;
+            m += d;
+          }
+      }
+  if (HasRook[c2] || HasQueen[c2])
+    for (i = Dstart[rook]; i <= Dstop[rook]; i++)
+      {
+        d = Dir[i]; m = m0+d;
+        while (!(m & 0x88))
+          {
+            u = unmap[m];
+            if (atk2[u] & ctlRQ) ScoreThreat;
+            if (color[u] != neutral) break;
+            m += d;
+          }
+      }
+  if (HasKnight[c2])
+    for (i = Dstart[knight]; i <= Dstop[knight]; i++)
+      if (!((m = m0+Dir[i]) & 0x88))
+        {
+          u = unmap[m];
+          if (atk2[u] & ctlNN) ScoreThreat;
+        }
+  *s += (KSFTY*Kthreat[cnt]) / 16;
+
+  cnt = 0; ok = false;
+  m0 = map[sq];
+  for (i = Dstart[king]; i <= Dstop[king]; i++)
+    if (!((m = m0+Dir[i]) & 0x88))
+      {
+        u = unmap[m];
+        if (board[u] == pawn) ok = true;
+        if (atk2[u] > atk1[u])
+          {
+            ++cnt;
+            if (atk2[u] & ctlQ)
+              if (atk2[u] > ctlQ+1 && atk1[u] < ctlQ) *s -= 4*KSFTY;
+          }
+      }
+  if (!ok) *s -= KSFTY;
+  if (cnt > 1) *s -= KSFTY;
+}
+#endif
+
+#if (NEWMOVE < 4)
+BRscan(sq,s,mob)
+short sq,*s,*mob;
+
+/*
+   Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the 
+   hung[] array if a pin is found. 
+*/
+
+{
+register short m,u;
+short d,j,m0,piece,pin,*Kf;
+
+  Kf = Kfield[c1];
+  *mob = 0;
+  m0 = map[sq]; piece = board[sq];
+  for (j = Dstart[piece]; j <= Dstop[piece]; j++)
+    {
+      pin = -1;
+      d = Dir[j]; m = m0+d;
+      while (!(m & 0x88))
+        {
+          u = unmap[m]; *s += Kf[u];
+          if (color[u] == neutral)
+            {
+              (*mob)++;
+              m += d;
+            }
+          else if (pin < 0)
+            {
+              if (board[u] == pawn || board[u] == king) break;
+              pin = u;
+              m += d;
+            }
+          else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
+            {
+              if (color[pin] == c2)
+                {
+                  *s += PINVAL;
+                  if (atk2[pin] == 0 ||
+                      atk1[pin] > control[board[pin]]+1)
+                    ++hung[c2];
+                }
+              else *s += XRAY;
+              break;
+            }
+          else break;
+        }
+    }
+}
+#endif
+
+#if (NEWMOVE > 5)
+int trapped(sq,piece)
+short sq,piece;
+
+/*
+   See if the attacked piece has unattacked squares to move to.
+*/
+
+{
+register short u,m,d;
+short i,m0;
+
+  m0 = map[sq];
+  if (sweep[piece])
+    for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+      {
+        d = Dir[i]; m = m0+d;
+        while (!(m & 0x88))
+          {
+            u = unmap[m];
+            if (color[u] == c1) break;
+            if (atk2[u] == 0 || board[u] >= piece) return(false);
+            if (color[u] == c2) break;
+            m += d;
+          }
+      }
+  else if (piece == pawn)
+    {
+      if (c1 == white) u = sq+8; else u = sq-8;
+      if (color[u] == neutral && atk1[u] >= atk2[u])
+        return(false);
+      if (!((m = m0+Dir[Dpwn[c1]]) & 0x88))
+        if (color[unmap[m]] == c2) return(false);
+      if (!((m = m0+Dir[Dpwn[c1]+1]) & 0x88))
+        if (color[unmap[m]] == c2) return(false);
+    }
+  else
+    {
+      for (i = Dstart[piece]; i <= Dstop[piece]; i++)
+        if (!((m = m0+Dir[i]) & 0x88))
+          {
+            u = unmap[m];
+            if (color[u] != c1)
+              if (atk2[u] == 0 || board[u] >= piece) return(false);
+          }
+    }
+  return(true);
+}
+#endif
+
+ExaminePosition()
+
+/*
+   This is done one time before the search is started. Set up arrays 
+   Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the 
+   SqValue() function to determine the positional value of each piece. 
+*/
+
+{
+register short i,sq;
+short wpadv,bpadv,wstrong,bstrong,z,side,pp,j,val,Pd,fyle,rank;
+
+  wking = PieceList[white][0]; bking = PieceList[black][0];
+  ataks(white,atak[white]); ataks(black,atak[black]);
+  Zwmtl = Zbmtl = 0;
+  UpdateWeights();
+  HasPawn[white] = HasPawn[black] = 0;
+  HasKnight[white] = HasKnight[black] = 0;
+  HasBishop[white] = HasBishop[black] = 0;
+  HasRook[white] = HasRook[black] = 0;
+  HasQueen[white] = HasQueen[black] = 0;
+  for (side = white; side <= black; side++)
+    for (i = 0; i <= PieceCnt[side]; i++)
+      switch (board[PieceList[side][i]])
+        {
+          case pawn : ++HasPawn[side]; break;
+          case knight : ++HasKnight[side]; break;
+          case bishop : ++HasBishop[side]; break;
+          case rook : ++HasRook[side]; break;
+          case queen : ++HasQueen[side]; break;
+        }
+  if (!Developed[white])
+    Developed[white] = (board[1] != knight && board[2] != bishop &&
+                        board[5] != bishop && board[6] != knight);
+  if (!Developed[black])
+    Developed[black] = (board[57] != knight && board[58] != bishop &&
+                        board[61] != bishop && board[62] != knight);
+  if (!PawnStorm && stage < 5)
+    PawnStorm = ((column[wking] < 3 && column[bking] > 4) ||
+                 (column[wking] > 4 && column[bking] < 3));
+  
+  CopyBoard(pknight,Mknight[white]);
+  CopyBoard(pknight,Mknight[black]);
+  CopyBoard(pbishop,Mbishop[white]);
+  CopyBoard(pbishop,Mbishop[black]);
+  BlendBoard(KingOpening,KingEnding,Mking[white]);
+  BlendBoard(KingOpening,KingEnding,Mking[black]);
+  
+  for (sq = 0; sq < 64; sq++)
+    {
+      fyle = column[sq]; rank = row[sq];
+      wstrong = bstrong = true;
+      for (i = sq; i < 64; i += 8)
+        if (atak[black][i] >= ctlP) wstrong = false;
+      for (i = sq; i >= 0; i -= 8)
+        if (atak[white][i] >= ctlP) bstrong = false;
+      wpadv = bpadv = PADVNCM;
+      if ((fyle == 0 || PawnCnt[white][fyle-1] == 0) &&
+          (fyle == 7 || PawnCnt[white][fyle+1] == 0)) wpadv = PADVNCI;
+      if ((fyle == 0 || PawnCnt[black][fyle-1] == 0) &&
+          (fyle == 7 || PawnCnt[black][fyle+1] == 0)) bpadv = PADVNCI;
+      Mwpawn[sq] = (wpadv*PawnAdvance[sq]) / 10;
+      Mbpawn[sq] = (bpadv*PawnAdvance[63-sq]) / 10;
+      Mwpawn[sq] += PawnBonus; Mbpawn[sq] += PawnBonus;
+      if (castld[white] || kingmoved[white])
+        {
+          if ((fyle < 3 || fyle > 4) && distance(sq,wking) < 3)
+            Mwpawn[sq] += PAWNSHIELD;
+        }
+      else if (rank < 3 && (fyle < 2 || fyle > 5))
+        Mwpawn[sq] += PAWNSHIELD / 2;
+      if (castld[black] || kingmoved[black])
+        {
+          if ((fyle < 3 || fyle > 4) && distance(sq,bking) < 3)
+            Mbpawn[sq] += PAWNSHIELD;
+        }
+      else if (rank > 4 && (fyle < 2 || fyle > 5))
+        Mbpawn[sq] += PAWNSHIELD / 2;
+      if (PawnStorm)
+        {
+          if ((column[wking] < 4 && fyle > 4) ||
+              (column[wking] > 3 && fyle < 3)) Mwpawn[sq] += 3*rank - 21;
+          if ((column[bking] < 4 && fyle > 4) ||
+              (column[bking] > 3 && fyle < 3)) Mbpawn[sq] -= 3*rank;
+        }
+        
+      Mknight[white][sq] += 5 - distance(sq,bking);
+      Mknight[white][sq] += 5 - distance(sq,wking);
+      Mknight[black][sq] += 5 - distance(sq,wking);
+      Mknight[black][sq] += 5 - distance(sq,bking);
+      Mbishop[white][sq] += BishopBonus;
+      Mbishop[black][sq] += BishopBonus;
+      for (i = 0; i <= PieceCnt[black]; i++)
+        if (distance(sq,PieceList[black][i]) < 3)
+          Mknight[white][sq] += KNIGHTPOST;
+      for (i = 0; i <= PieceCnt[white]; i++)
+        if (distance(sq,PieceList[white][i]) < 3)
+          Mknight[black][sq] += KNIGHTPOST;
+      if (wstrong) Mknight[white][sq] += KNIGHTSTRONG;
+      if (bstrong) Mknight[black][sq] += KNIGHTSTRONG;
+      if (wstrong) Mbishop[white][sq] += BISHOPSTRONG;
+      if (bstrong) Mbishop[black][sq] += BISHOPSTRONG;
+      
+      if (HasBishop[white] == 2) Mbishop[white][sq] += 8;
+      if (HasBishop[black] == 2) Mbishop[black][sq] += 8;
+      if (HasKnight[white] == 2) Mknight[white][sq] += 5;
+      if (HasKnight[black] == 2) Mknight[black][sq] += 5;
+      
+      if (board[sq] == bishop)
+        if (rank % 2 == fyle % 2) KBNKsq = 0; else KBNKsq = 7;
+        
+      Kfield[white][sq] = Kfield[black][sq] = 0;
+      if (distance(sq,wking) == 1) Kfield[black][sq] = KATAK;
+      if (distance(sq,bking) == 1) Kfield[white][sq] = KATAK;
+      
+      Pd = 0;
+      for (i = 0; i < 64; i++)
+        if (board[i] == pawn)
+          {
+            if (color[i] == white)
+              {
+                pp = true;
+                if (row[i] == 6) z = i+8; else z = i+16;
+                for (j = i+8; j < 64; j += 8)
+                  if (atak[black][j] > ctlP || board[j] == pawn) pp = false;
+              }
+            else
+              {
+                pp = true;
+                if (row[i] == 1) z = i-8; else z = i-16;
+                for (j = i-8; j >= 0; j -= 8)
+                  if (atak[white][j] > ctlP || board[j] == pawn) pp = false;
+              }
+            if (pp) Pd += 5*taxicab(sq,z); else Pd += taxicab(sq,z);
+          }
+      if (Pd != 0)
+        {
+          val = (Pd*stage2) / 10;
+          Mking[white][sq] -= val;
+          Mking[black][sq] -= val;
+        }
+    }
+}
+
+
+UpdateWeights()
+
+/* 
+   If material balance has changed, determine the values for the 
+   positional evaluation terms. 
+*/
+
+{
+short tmtl;
+
+  if (mtl[white] != Zwmtl || mtl[black] != Zbmtl)
+    {
+      Zwmtl = mtl[white]; Zbmtl = mtl[black];
+      emtl[white] = Zwmtl - pmtl[white] - valueK;
+      emtl[black] = Zbmtl - pmtl[black] - valueK;
+      tmtl = emtl[white] + emtl[black];
+      if (tmtl > 6600) stage = 0;
+      else if (tmtl < 1400) stage = 10;
+      else stage = (6600-tmtl) / 520;
+      if (tmtl > 3600) stage2 = 0;
+      else if (tmtl < 1400) stage2 = 10;
+      else stage2 = (3600-tmtl) / 220;
+      
+      PEDRNK2B = -15;         /* centre pawn on 2nd rank & blocked */
+      PBLOK = -4;             /* blocked backward pawn */
+      PDOUBLED = -14;         /* doubled pawn */
+      PWEAKH  = -4;           /* weak pawn on half open file */
+      PAWNSHIELD = 10-stage;  /* pawn near friendly king */
+      PADVNCM =  10;          /* advanced pawn multiplier */
+      PADVNCI = 7;            /* muliplier for isolated pawn */
+      PawnBonus = stage;
+      
+      KNIGHTPOST = (stage+2)/3;   /* knight near enemy pieces */
+      KNIGHTSTRONG = (stage+6)/2; /* occupies pawn hole */
+      
+      BISHOPSTRONG = (stage+6)/2; /* occupies pawn hole */
+      BishopBonus = 2*stage;
+      
+      RHOPN    = 10;          /* rook on half open file */
+      RHOPNX   = 4;
+      RookBonus = 6*stage;
+      
+      XRAY     = 8;           /* Xray attack on piece */
+      PINVAL   = 10;          /* Pin */
+      
+      KHOPN    = (3*stage-30) / 2; /* king on half open file */
+      KHOPNX   = KHOPN / 2;
+      KCASTLD  = 10 - stage;
+      KMOVD    = -40 / (stage+1);  /* king moved before castling */
+      KATAK    = (10-stage) / 2;   /* B,R attacks near enemy king */
+      if (stage < 8) KSFTY = 16-2*stage; else KSFTY = 0;
+      
+      ATAKD    = -6;          /* defender > attacker */
+      HUNGP    = -8;          /* each hung piece */
+      HUNGX    = -12;         /* extra for >1 hung piece */
+    }
+}
+
+#if (NEWMOVE < 1)
+int distance(a,b)
+short a,b;
+{
+register short d1,d2;
+
+  d1 = abs(column[a]-column[b]);
+  d2 = abs(row[a]-row[b]);
+  return(d1 > d2 ? d1 : d2);
+}
+#endif
+
+BlendBoard(a,b,c)
+short a[64],b[64],c[64];
+{
+register int sq;
+  for (sq = 0; sq < 64; sq++)
+    c[sq] = (a[sq]*(10-stage) + b[sq]*stage) / 10;
+}
+
+
+CopyBoard(a,b)
+short a[64],b[64];
+{
+register int sq;
+  for (sq = 0; sq < 64; sq++)
+    b[sq] = a[sq];
+}
diff --git a/usr/othersrc/games/chess/gnuchess.h b/usr/othersrc/games/chess/gnuchess.h
new file mode 100644 (file)
index 0000000..6e9c74b
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+  This file contains code for CHESS.
+  Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+
+  This file is part of CHESS.
+
+  CHESS is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY.  No author or distributor
+  accepts responsibility to anyone for the consequences of using it
+  or for whether it serves any particular purpose or works at all,
+  unless he says so in writing.  Refer to the CHESS General Public
+  License for full details.
+
+  Everyone is granted permission to copy, modify and redistribute
+  CHESS, but only under the conditions described in the
+  CHESS General Public License.   A copy of this license is
+  supposed to have been given to you along with CHESS so you
+  can know your rights and responsibilities.  It should be in a
+  file named COPYING.  Among other things, the copyright notice
+  and this notice must be preserved on all copies.
+*/
+
+
+/* Header file for GNU CHESS */  
+
+#define neutral 2
+#define white 0
+#define black 1 
+#define no_piece 0
+#define pawn 1
+#define knight 2
+#define bishop 3
+#define rook 4
+#define queen 5
+#define king 6
+#define pxx " PNBRQK"
+#define qxx " pnbrqk"
+#define rxx "12345678"
+#define cxx "abcdefgh"
+#define check 0x0001
+#define capture 0x0002
+#define draw 0x0004
+#define promote 0x0008
+#define cstlmask 0x0010
+#define epmask 0x0020
+#define exact 0x0040
+#define pwnthrt 0x0080
+#define maxdepth 30
+#define true 1
+#define false 0
+
+struct leaf
+  {
+    short f,t,score,reply;
+    unsigned short flags;
+  };
+struct GameRec
+  {
+    unsigned short gmove;
+    short score,depth,time,piece,color;
+    long nodes;
+  };
+struct TimeControlRec
+  {
+    short moves[2];
+    long clock[2];
+  };
+struct BookEntry
+  {
+    struct BookEntry *next;
+    unsigned short *mv;
+  };
+
+extern char mvstr1[5],mvstr2[5];
+extern struct leaf Tree[2000],*root;
+extern short TrPnt[maxdepth],board[64],color[64];
+extern short row[64],column[64],locn[8][8];
+extern short atak[2][64],PawnCnt[2][8];
+extern short castld[2],kingmoved[2];
+extern short c1,c2,*atk1,*atk2,*PC1,*PC2;
+extern short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,dither;
+extern long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft;
+extern long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt;
+extern short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep,meter;
+extern short timeout,xwndw;
+extern struct GameRec GameList[240];
+extern short GameCnt,Game50,epsquare,lpost,rcptr,contempt;
+extern short MaxSearchDepth;
+extern struct BookEntry *Book;
+extern struct TimeControlRec TimeControl;
+extern short TCflag,TCmoves,TCminutes,OperatorTime;
+extern short otherside[3];
+extern short Stboard[64];
+extern short Stcolor[64];
+extern unsigned short hint,PrVar[maxdepth];
+
+#define HZ 60
diff --git a/usr/othersrc/games/chess/move.c b/usr/othersrc/games/chess/move.c
new file mode 100644 (file)
index 0000000..4ce686c
--- /dev/null
@@ -0,0 +1,357 @@
+/* move generator hes@log-sv.se 890318
+   Modified: 890606 NEWMOVE Levels 1-6 for easier debugging */
+#include "move.h"
+#include "gnuchess.h"
+
+short distdata[64][64];
+short taxidata[64][64];
+
+void Initialize_dist() {
+register short a,b,d,di;
+
+  /* init taxi and dist data */
+  for(a=0;a<64;a++)
+    for(b=0;b<64;b++) {
+      d = abs(column[a]-column[b]);
+      di = abs(row[a]-row[b]);
+      taxidata[a][b] = d + di;
+      distdata[a][b] = (d > di ? d : di);
+    };
+}
+
+#if (NEWMOVE > 1)
+struct sqdata posdata[3][8][64][64];
+
+static short direc[8][8] = {
+    0,  0,  0,  0,  0,  0,  0,  0, /* no_piece = 0 */
+  -10,-11, -9,  0,  0,  0,  0,  0, /* wpawn    = 1 */
+  -21,-19,-12, -8, 21, 19, 12,  8, /* knight   = 2 */
+  -11, -9, 11,  9,  0,  0,  0,  0, /* bishop   = 3 */
+  -10, -1, 10,  1,  0,  0,  0,  0, /* rook     = 4 */
+  -11, -9,-10, -1, 11,  9, 10,  1, /* queen    = 5 */
+  -11, -9,-10, -1, 11,  9, 10,  1, /* king     = 6 */
+    0,  0,  0,  0,  0,  0,  0,  0};/* no_piece = 7 */
+
+static short dc[3] = {-1,1,0};
+
+static short max_steps [8] = {0,2,1,7,7,7,1,0};
+
+static short unmap[120] = {
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1, 0, 1, 2, 3, 4, 5, 6, 7,-1,
+  -1, 8, 9,10,11,12,13,14,15,-1,
+  -1,16,17,18,19,20,21,22,23,-1,
+  -1,24,25,26,27,28,29,30,31,-1,
+  -1,32,33,34,35,36,37,38,39,-1,
+  -1,40,41,42,43,44,45,46,47,-1,
+  -1,48,49,50,51,52,53,54,55,-1,
+  -1,56,57,58,59,60,61,62,63,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
+
+void Initialize_moves() {
+  short c,ptyp,po,p0,d,di,s;
+  struct sqdata *p;
+  short dest[8][8];
+  short steps[8];
+  short sorted[8];
+
+  /* init posdata */
+  for(c=0;c<3;c++)
+    for(ptyp=0;ptyp<8;ptyp++)
+      for(po=0;po<64;po++)
+       for(p0=0;p0<64;p0++) {
+         posdata[c][ptyp][po][p0].nextpos = po;
+         posdata[c][ptyp][po][p0].nextdir = po;
+       };
+  /* dest is a function of dir and step */
+  for(c=0;c<2;c++)
+    for(ptyp=1;ptyp<7;ptyp++)
+      for(po=21;po<99;po++)
+       if (unmap[po] >= 0) {
+          p = posdata[c][ptyp][unmap[po]];
+         for(d=0;d<8;d++) {
+           dest[d][0] = unmap[po];
+           if (dc[c]*direc[ptyp][d] != 0) {
+             p0=po;
+             for(s=0;s<max_steps[ptyp];s++) {
+               p0 = p0 + dc[c]*direc[ptyp][d];
+               /* break if (off board) or
+                  (pawns move two steps from home square) */
+               if (unmap[p0] < 0 ||
+                   (ptyp == pawn && s>0 && (d>0 || Stboard[unmap[po]] != ptyp)))
+                 break;
+               else
+                 dest[d][s] = unmap[p0];
+             }
+           }
+           else s=0;
+           /* sort dest in number of steps order */
+           steps[d] = s;
+           for(di=d;di>0;di--)
+             if (steps[sorted[di-1]] < s)
+               sorted[di] = sorted[di-1];
+             else
+               break;
+           sorted[di] = d;
+         }
+         /* update posdata, pawns have two threads (capture and no capture) */
+         p0=unmap[po];
+         if (ptyp == pawn) {
+           for(s=0;s<steps[0];s++) {
+             p[p0].nextpos = dest[0][s];
+             p0 = dest[0][s];
+           }
+           p0=unmap[po];
+           for(d=1;d<3;d++) {
+             p[p0].nextdir = dest[d][0];
+             p0 = dest[d][0];
+           }
+         }
+         else {
+           p[p0].nextdir = dest[sorted[0]][0];
+           for(d=0;d<8;d++)
+             for(s=0;s<steps[sorted[d]];s++) {
+               p[p0].nextpos = dest[sorted[d]][s];
+               p0 = dest[sorted[d]][s];
+               if (d < 7)
+                 p[p0].nextdir = dest[sorted[d+1]][0];
+               /* else is already initialised */
+             }
+         }
+#ifdef DEBUG
+         printf("Ptyp:%d Position:%d\n{",ptyp,unmap[po]);
+         for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextpos);
+         printf("%d};\n",p[63].nextpos);
+         for(p0=0;p0<63;p0++) printf("%d,",p[p0].nextdir);
+         printf("%d};\n",p[63].nextdir);
+#endif DEBUG
+       }
+}
+#endif
+
+
+#if (NEWMOVE > 2)
+int SqAtakd(sq,side)
+short sq,side;
+
+/*
+  See if any piece with color 'side' ataks sq. First check pawns
+  Then Queen, Bishop, Rook and King and last Knight.
+*/
+
+{
+  register short u;
+  register struct sqdata *p;
+
+  p = posdata[1-side][pawn][sq];
+  u = p[sq].nextdir; /* follow captures thread */
+  while (u != sq) {
+    if (board[u] == pawn && color[u] == side) return(true);
+    u = p[u].nextdir;
+  }
+  /* king capture */
+  if (distance(sq,PieceList[side][0]) == 1) return(true);
+  /* try a queen bishop capture */
+  p = posdata[side][bishop][sq];
+  u = p[sq].nextpos;
+  while (u != sq) {
+    if (color[u] == neutral) {
+      u = p[u].nextpos;
+    }
+    else {
+      if (color[u] == side && 
+         (board[u] == queen || board[u] == bishop))
+       return(true);
+      u = p[u].nextdir;
+    }
+  }
+  /* try a queen rook capture */
+  p = posdata[side][rook][sq];
+  u = p[sq].nextpos;
+  while (u != sq) {
+    if (color[u] == neutral) {
+      u = p[u].nextpos;
+    }
+    else {
+      if (color[u] == side && 
+         (board[u] == queen || board[u] == rook))
+       return(true);
+      u = p[u].nextdir;
+    }
+  }
+  /* try a knight capture */
+  p = posdata[side][knight][sq];
+  u = p[sq].nextpos;
+  while (u != sq) {
+    if (color[u] == neutral) {
+      u = p[u].nextpos;
+    }
+    else {
+      if (color[u] == side && board[u] == knight) return(true);
+      u = p[u].nextdir;
+    }
+  }
+  return(false);
+}
+#endif
+
+#if (NEWMOVE > 3)
+BRscan(sq,s,mob)
+short sq,*s,*mob;
+/*
+   Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the 
+   hung[] array if a pin is found. 
+*/
+{
+  register short u,piece,pin;
+  register struct sqdata *p;
+  short *Kf;
+
+  Kf = Kfield[c1];
+  *mob = 0;
+  piece = board[sq];
+  p = posdata[color[sq]][piece][sq];
+  u = p[sq].nextpos;
+  pin = -1; /* start new direction */
+  while (u != sq) {
+    *s += Kf[u];
+    if (color[u] == neutral) {
+      (*mob)++;
+      if (p[u].nextpos == p[u].nextdir) pin = -1; /* oops new direction */
+      u = p[u].nextpos;
+    }
+    else if (pin < 0) {
+      if (board[u] == pawn || board[u] == king)
+       u = p[u].nextdir;
+      else {
+       if (p[u].nextpos != p[u].nextdir)
+         pin = u; /* not on the edge and on to find a pin */
+       u = p[u].nextpos;
+      }
+    }
+    else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
+      {
+       if (color[pin] == c2)
+         {
+           *s += PINVAL;
+           if (atk2[pin] == 0 ||
+               atk1[pin] > control[board[pin]]+1)
+             ++hung[c2];
+         }
+       else *s += XRAY;
+       pin = -1; /* new direction */
+       u = p[u].nextdir;
+      }
+    else {
+      pin = -1; /* new direction */
+      u = p[u].nextdir;
+    }
+  }
+}
+#endif
+
+#if (NEWMOVE >= 5)
+CaptureList(side,xside,ply)
+short side,xside,ply;
+{
+  register short u,sq;
+  register struct sqdata *p;
+  short i,piece,*PL;
+  struct leaf *node;
+  
+  TrPnt[ply+1] = TrPnt[ply];
+  node = &Tree[TrPnt[ply]];
+  PL = PieceList[side];
+  for (i = 0; i <= PieceCnt[side]; i++)
+    {
+      sq = PL[i];
+      piece = board[sq];
+      p = posdata[side][piece][sq];
+      if (piece == pawn) {
+       u = p[sq].nextdir; /* follow captures thread */
+       while (u != sq) {
+         if (color[u] == xside) {
+            node->f = sq; node->t = u;
+            node->flags = capture;
+            if (u < 8 || u > 55)
+              {
+                node->flags |= promote;
+                node->score = valueQ;
+              }
+           else
+              node->score = value[board[u]] + svalue[board[u]] - piece;
+            ++node;
+            ++TrPnt[ply+1];
+           }
+         u = p[u].nextdir;
+       }
+      }
+      else {
+       u = p[sq].nextpos;
+       while (u != sq) {
+          if (color[u] == neutral)
+          u = p[u].nextpos;
+          else {
+          if (color[u] == xside) {
+              node->f = sq; node->t = u;
+              node->flags = capture;
+              node->score = value[board[u]] + svalue[board[u]] - piece;
+              ++node;
+              ++TrPnt[ply+1];
+             }
+          u = p[u].nextdir;
+        }
+       }
+     }
+   }
+}
+#endif
+
+#if (NEWMOVE > 5)
+GenMoves(ply,sq,side,xside)
+     short ply,sq,side,xside;
+/*
+  Generate moves for a piece. The moves are taken from the
+  precalulated array posdata. If the board is free, next move
+  is choosen from nextpos else from nextdir.
+*/
+{
+  register short u,piece;
+  register struct sqdata *p;
+        
+  piece = board[sq];
+  p = posdata[side][piece][sq];
+  if (piece == pawn) {
+    u = p[sq].nextdir; /* follow captures thread */
+    while (u != sq) {
+      if (color[u] == xside) LinkMove(ply,sq,u,xside);
+      u = p[u].nextdir;
+    }
+    u = p[sq].nextpos; /* and follow no captures thread */
+    while (u != sq) {
+      if (color[u] == neutral && (u != sq+16 || color[u-8] == neutral)
+          && (u != sq-16 || color[u+8] == neutral)) {
+        LinkMove(ply,sq,u,xside);
+      }
+      u = p[u].nextpos;
+    }
+  }  
+  else {
+    u = p[sq].nextpos;
+    while (u != sq) {
+      if (color[u] == neutral) {
+        LinkMove(ply,sq,u,xside);
+        u = p[u].nextpos;
+      }
+      else {
+        if (color[u] == xside) LinkMove(ply,sq,u,xside);
+       u = p[u].nextdir;
+      }
+    }
+  }    
+} 
+#endif
diff --git a/usr/othersrc/games/chess/move.h b/usr/othersrc/games/chess/move.h
new file mode 100644 (file)
index 0000000..2f32830
--- /dev/null
@@ -0,0 +1,81 @@
+/* header file for move generator hes 890318
+   Modified: 890510 minor bug fixed in Newataks
+             890606 NEWMOVE levels 1-6 */
+
+#if (NEWMOVE >= 1)
+extern short distdata[64][64];
+extern short taxidata[64][64];
+
+#define taxicab(a,b) taxidata[a][b]
+#define distance(a,b) distdata[a][b]
+
+extern void Initialize_dist();
+#endif
+  
+#if (NEWMOVE >= 2)
+struct sqdata {
+  short nextpos;
+  short nextdir;
+};
+extern struct sqdata posdata[3][8][64][64];
+
+extern void Initialize_moves();
+
+#define ataks(side,a)\
+{\
+  register short u,c,sq;\
+  register struct sqdata *p;\
+  short i,piece,*PL;\
+  \
+  for (u = 64; u; a[--u] = 0); \
+  PL = PieceList[side];\
+  for (i = 0; i <= PieceCnt[side]; i++)\
+    {\
+      sq = PL[i];\
+      piece = board[sq];\
+      c = control[piece];\
+      p = posdata[side][piece][sq];\
+      if (piece == pawn) {\
+       u = p[sq].nextdir; /* follow captures thread */\
+       while (u != sq) {\
+         a[u] = ++a[u] | c;\
+         u = p[u].nextdir;\
+       }\
+      }\
+      else {\
+       u = p[sq].nextpos;\
+       while (u != sq) {\
+          a[u] = ++a[u] | c;\
+         if (color[u] == neutral)\
+           u = p[u].nextpos;\
+         else\
+           u = p[u].nextdir;\
+       }\
+      }\
+    }\
+}
+#endif
+
+#if (NEWMOVE >= 3)
+extern short PieceList[2][16];
+
+extern int Sqatakd();
+#endif
+
+#if (NEWMOVE > 3)
+extern short Kfield[2][64],PINVAL,control[7],hung[2],XRAY;
+
+extern BRscan();
+#endif
+
+#if (NEWMOVE > 4)
+#define valueQ 1100
+
+extern short PieceCnt[2],value[7],svalue[64];
+
+extern CaptureList();
+#endif
+
+#if (NEWMOVE > 5)
+extern GenMoves();
+#endif
diff --git a/usr/othersrc/games/chess/nondsp.c b/usr/othersrc/games/chess/nondsp.c
new file mode 100644 (file)
index 0000000..0b29ad5
--- /dev/null
@@ -0,0 +1,791 @@
+/*
+  UNIX & MSDOS NON-DISPLAY, AND CHESSTOOL interface for Chess
+   
+  Revision: 4-25-88
+   
+  Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
+  Copyright (c) 1988  John Stanback
+
+  This file is part of CHESS.
+
+  CHESS is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY.  No author or distributor
+  accepts responsibility to anyone for the consequences of using it
+  or for whether it serves any particular purpose or works at all,
+  unless he says so in writing.  Refer to the CHESS General Public
+  License for full details.
+
+  Everyone is granted permission to copy, modify and redistribute
+  CHESS, but only under the conditions described in the
+  CHESS General Public License.   A copy of this license is
+  supposed to have been given to you along with CHESS so you
+  can know your rights and responsibilities.  It should be in a
+  file named COPYING.  Among other things, the copyright notice
+  and this notice must be preserved on all copies.
+*/
+
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef MSDOS
+#include <dos.h>
+#include <stdlib.h>
+#include <time.h>
+#else
+#include <sys/param.h>
+#include <sys/times.h>
+#include <sys/file.h>
+struct tms tmbuf1,tmbuf2;
+int TerminateSearch(),Die();
+#endif MSDOS
+
+#include "gnuchess.h"
+#ifdef NEWMOVE
+#include "move.h"
+#endif
+
+#define printz printf
+#define scanz scanf
+int mycnt1,mycnt2;
+
+
+Initialize()
+{
+  mycnt1 = mycnt2 = 0;
+#ifndef MSDOS
+#endif
+#ifdef CHESSTOOL
+  setlinebuf(stdout);
+/*
+  setvbuf(stdout,NULL,_IOLBF,BUFSIZ);
+*/
+  printf("Chess\n");
+  if (Level == 0 && !TCflag) Level = 15;
+#endif CHESSTOOL
+}
+
+ExitChess()
+{
+  ListGame();
+  exit(0);
+}
+
+#ifndef MSDOS
+Die()
+{
+char s[80];
+  printz("Abort? ");
+  scanz("%s",s);
+  if (strcmp(s,"yes") == 0) ExitChess();
+}
+
+TerminateSearch()
+{
+  timeout = true;
+  bothsides = false;
+}
+#endif MSDOS
+
+
+InputCommand()
+
+/*
+   Process the users command. If easy mode is OFF (the computer is 
+   thinking on opponents time) and the program is out of book, then make 
+   the 'hint' move on the board and call SelectMove() to find a response. 
+   The user terminates the search by entering ^C (quit siqnal) before 
+   entering a command. If the opponent does not make the hint move, then 
+   set Sdepth to zero. 
+*/
+
+{
+int i;
+short ok,tmp;
+long cnt,rate,t1,t2;
+unsigned short mv;
+char s[80];
+
+  ok = quit = false;
+  player = opponent;
+  ft = 0;
+  if (hint > 0 && !easy && Book == NULL)
+    {
+      fflush(stdout);
+      time0 = time((long *)0);
+      algbr(hint>>8,hint & 0xFF,false);
+      strcpy(s,mvstr1);
+      tmp = epsquare;
+      if (VerifyMove(s,1,&mv))
+        {
+          SelectMove(computer,2);
+          VerifyMove(mvstr1,2,&mv);
+          if (Sdepth > 0) Sdepth--;
+        }
+      ft = time((long *)0) - time0;
+      epsquare = tmp;
+    }
+  
+#ifndef MSDOS
+#endif
+  while (!(ok || quit))
+    {
+      PromptForMove();
+      i = scanz("%s",s);
+      if (i == EOF || s[0] == 0) ExitChess();
+      player = opponent;
+      ok = VerifyMove(s,0,&mv);
+      if (ok && mv != hint)
+        {
+          Sdepth = 0;
+          ft = 0;
+        }
+        
+      if (strcmp(s,"bd") == 0)
+        {
+          ClrScreen();
+          UpdateDisplay(0,0,1,0);
+        }
+      if (strcmp(s,"quit") == 0) quit = true;
+      if (strcmp(s,"post") == 0) post = !post;
+      if (strcmp(s,"set") == 0) EditBoard();
+      if (strcmp(s,"go") == 0) ok = true;
+      if (strcmp(s,"help") == 0) help();
+      if (strcmp(s,"force") == 0) force = !force;
+      if (strcmp(s,"book") == 0) Book = NULL;
+      if (strcmp(s,"new") == 0) NewGame();
+      if (strcmp(s,"list") == 0) ListGame();
+      if (strcmp(s,"level") == 0) SelectLevel();
+      if (strcmp(s,"hash") == 0) hashflag = !hashflag;
+      if (strcmp(s,"beep") == 0) beep = !beep;
+      if (strcmp(s,"Awindow") == 0) ChangeAlphaWindow();
+      if (strcmp(s,"Bwindow") == 0) ChangeBetaWindow();
+      if (strcmp(s,"rcptr") == 0) rcptr = !rcptr;
+      if (strcmp(s,"hint") == 0) GiveHint();
+      if (strcmp(s,"zero") == 0) ZeroTTable();
+      if (strcmp(s,"both") == 0)
+        {
+          bothsides = !bothsides;
+          Sdepth = 0;
+          SelectMove(opponent,1);
+          ok = true;
+        }
+      if (strcmp(s,"reverse") == 0)
+        {
+          reverse = !reverse;
+          ClrScreen();
+          UpdateDisplay(0,0,1,0);
+        }
+      if (strcmp(s,"switch") == 0)
+        {
+          computer = otherside[computer];
+          opponent = otherside[opponent];
+          force = false;
+          Sdepth = 0;
+          ok = true;
+        }
+      if (strcmp(s,"white") == 0)  
+        {
+          computer = white; opponent = black;
+          ok = true; force = false;
+          Sdepth = 0;
+        }
+      if (strcmp(s,"black") == 0)
+        {
+          computer = black; opponent = white;
+          ok = true; force = false;
+          Sdepth = 0;
+        }
+      if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo();
+      if (strcmp(s,"remove") == 0 && GameCnt >= 1) 
+        {
+          Undo(); Undo();
+        }
+      if (strcmp(s,"get") == 0) GetGame();
+      if (strcmp(s,"save") == 0) SaveGame();
+      if (strcmp(s,"depth") == 0) ChangeSearchDepth();
+      if (strcmp(s,"random") == 0) dither = 6;
+      if (strcmp(s,"easy") == 0) easy = !easy;
+      if (strcmp(s,"contempt") == 0) SetContempt();
+      if (strcmp(s,"xwndw") == 0) ChangeXwindow();
+      if (strcmp(s,"test") == 0)
+        {
+          t1 = time(0);
+          cnt = 0;
+          for (i = 0; i < 10000; i++)
+            {
+              MoveList(opponent,2);
+              cnt += TrPnt[3] - TrPnt[2];
+            }
+          t2 = time(0);
+          rate = cnt / (t2-t1);
+          printz("cnt= %ld  rate= %ld\n",cnt,rate);
+        }
+    }
+    
+  ElapsedTime(1);
+  if (force)
+    {
+      computer = opponent; opponent = otherside[computer];
+    }
+#ifndef MSDOS
+  (void) times(&tmbuf1);
+#ifdef CHESSTOOL
+  printf("%d. %s\n",++mycnt2,s);
+#endif CHESSTOOL
+#endif MSDOS
+}
+
+
+help()
+{
+  ClrScreen();
+  printz("CHESS command summary\n");
+  printz("g1f3      move from g1 to f3\n");
+  printz("nf3       move knight to f3\n");
+  printz("o-o       castle king side\n");
+  printz("o-o-o     castle queen side\n");
+  printz("set       edit board\n");
+  printz("switch    sides with computer\n");
+  printz("white     computer plays white\n");
+  printz("black     computer plays black\n");
+  printz("reverse   board display\n");
+  printz("both      computer match\n");
+  printz("random    randomize play\n");
+  printz("undo      undo last move\n");
+  printz("time      change level\n");
+  printz("depth     set search depth\n");
+  printz("post      principle variation\n");
+  printz("hint      suggest a move\n");
+  printz("bd        redraw board\n");
+  printz("clock     set time control\n");
+  printz("force     enter game moves\n");
+  printz("list      game to chess.lst\n");
+  printz("save      game to file\n");
+  printz("get       game from file\n");
+  printz("new       start new game\n");
+  printz("quit      exit CHESS\n");
+  printz("Computer: ");
+  if (computer == white) printz("WHITE\n"); else printz("BLACK\n");
+  printz("Opponent: ");
+  if (opponent == white) printz("WHITE\n"); else printz("BLACK\n");
+  printz("Response time: %ld",Level," sec.\n");
+  printz("Easy mode: ");
+  if (easy) printz("ON\n"); else printz("OFF\n");
+  printz("Depth: %d\n",MaxSearchDepth);
+  printz("Random: "); 
+  if (dither) printz("ON\n"); else printz("OFF\n");
+  printz("Transposition table: ");
+  if (hashflag) printz("ON\n"); else printz("OFF\n");
+  UpdateDisplay(0,0,1,0);
+}
+
+
+EditBoard()
+
+/* 
+   Set up a board position. Pieces are entered by typing the piece 
+   followed by the location. For example, Nf3 will place a knight on 
+   square f3. 
+*/
+
+{
+short a,r,c,sq;
+char s[80];
+
+  ClrScreen();
+  UpdateDisplay(0,0,1,0);
+  printz(".   exit to main\n");
+  printz("#   clear board\n");
+  printz("enter piece & location: \n");
+  
+  a = white;
+  do
+  {
+    scanz("%s",s);
+    if (s[0] == '#')
+      {
+        for (sq = 0; sq < 64; sq++)
+          {
+            board[sq] = no_piece; color[sq] = neutral;
+          }
+        UpdateDisplay(0,0,1,0);
+      }
+    if (s[0] == 'c' || s[0] == 'C') a = otherside[a];
+    c = s[1]-'a'; r = s[2]-'1';
+    if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
+      {
+        sq = locn[r][c];
+        color[sq] = a;
+        if (s[0] == 'p') board[sq] = pawn;
+        else if (s[0] == 'n') board[sq] = knight;
+        else if (s[0] == 'b') board[sq] = bishop;
+        else if (s[0] == 'r') board[sq] = rook;
+        else if (s[0] == 'q') board[sq] = queen;
+        else if (s[0] == 'k') board[sq] = king;
+        else { board[sq] = no_piece; color[sq] = neutral; }
+      }
+  }
+  while (s[0] != '.');
+  if (board[4] != king) kingmoved[white] = 10;
+  if (board[60] != king) kingmoved[black] = 10;
+  GameCnt = -1; Game50 = 0; Sdepth = 0;
+  InitializeStats();
+  ClrScreen();
+  UpdateDisplay(0,0,1,0);
+}
+
+
+ShowDepth(ch)
+char ch;
+{
+}
+
+ShowResults(score,bstline,ch)
+short score;
+unsigned short bstline[];
+char ch;
+{
+#ifndef CHESSTOOL
+register int i;
+  printz("%2d%c  %5d %4ld %7ld   ",Sdepth,ch,score,et,NodeCnt);
+  for (i = 1; bstline[i] > 0; i++)
+    {
+      algbr((short)(bstline[i] >> 8),(short)(bstline[i] & 0xFF),false);
+      if (i == 9 || i == 17) printz("\n                          ");
+      printz("%5s ",mvstr1);
+    }
+  printz("\n");
+#endif
+}
+
+
+SearchStartStuff(side)
+short side;
+{
+#ifndef MSDOS
+#endif
+#ifndef CHESSTOOL
+  printz("\nMove# %d    Target= %ld    Clock: %ld\n",
+          TCmoves-TimeControl.moves[side]+1,
+          ResponseTime,TimeControl.clock[side]);
+#endif
+}
+
+
+OutputMove()
+{
+#ifdef CHESSTOOL
+  printz("%d. ... %s\n",++mycnt1,mvstr1);
+  if (root->flags & draw)
+    {
+      printz("Draw\n");
+      ListGame();
+      exit(0);
+    }
+  if (root->score == -9999)
+    {
+      if (opponent == white) printz("White\n"); else printz("Black\n");
+      ListGame();
+      exit(0);
+    }
+  if (root->score == 9998)
+    {
+      if (computer == white) printz("White\n"); else printz("Black\n");
+      ListGame();
+      exit(0);
+    }
+#else
+  printz("Nodes= %ld  Eval= %ld  Hash= %ld  Rate= %ld  ",
+          NodeCnt,EvalNodes,HashCnt,evrate);
+  printz("CPU= %.2ld:%.2ld.%.2ld\n\n",
+          cputimer/6000,(cputimer % 6000)/100,cputimer % 100);
+          
+  if (root->flags & epmask) UpdateDisplay(0,0,1,0);
+  else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask);
+  printz("My move is: %s\n\n",mvstr1);
+  if (beep) printz("%c",7);
+  
+  if (root->flags & draw) printz("Draw game!\n");
+  else if (root->score == -9999) printz("opponent mates!\n");
+  else if (root->score == 9998) printz("computer mates!\n");
+  else if (root->score < -9000) printz("opponent will soon mate!\n");
+  else if (root->score > 9000)  printz("computer will soon mate!\n");
+#endif CHESSTOOL
+}
+
+
+ElapsedTime(iop)
+short iop;
+
+/* 
+   Determine the time that has passed since the search was started. If 
+   the elapsed time exceeds the target (ResponseTime+ExtraTime) then set 
+   timeout to true which will terminate the search. 
+*/
+
+{
+  et = time((long *)0) - time0;
+  if (et < 0) et = 0;
+  ETnodes += 50;
+  if (et > et0 || iop == 1)
+    {
+      if (et > ResponseTime+ExtraTime && Sdepth > 1) timeout = true;
+      et0 = et;
+      if (iop == 1)
+        {
+          time0 = time((long *)0); et0 = 0;
+        }
+#ifdef MSDOS
+      cputimer = 100*et;
+      if (et > 0) evrate = NodeCnt/(et+ft); else evrate = 0;
+      if (kbhit() && Sdepth > 1)
+        {
+          timeout = true;
+          bothsides = false;
+        }
+#else
+      (void) times(&tmbuf2);
+      cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ;
+      if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft);
+      else evrate = 0;
+#endif MSDOS
+      ETnodes = NodeCnt + 50;
+    }
+}
+
+
+SetTimeControl()
+{
+  if (TCflag)
+    {
+      TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
+      TimeControl.clock[white] = TimeControl.clock[black] = 60*(long)TCminutes;
+    }
+  else
+    {
+      TimeControl.moves[white] = TimeControl.moves[black] = 0;
+      TimeControl.clock[white] = TimeControl.clock[black] = 0;
+      Level = 60*(long)TCminutes;
+    }
+  et = 0;
+  ElapsedTime(1);
+}
+
+
+ClrScreen()
+{
+#ifndef CHESSTOOL
+  printz("\n");
+#endif
+}
+
+
+UpdateDisplay(f,t,flag,iscastle)
+short f,t,flag,iscastle;
+{
+#ifndef CHESSTOOL
+short r,c,l;
+  if (flag)
+    {
+      printz("\n");
+      for (r = 7; r >= 0; r--)
+        {
+          for (c = 0; c <= 7; c++)
+            {
+              if (reverse) l = locn[7-r][7-c]; else l = locn[r][c];
+              if (color[l] == neutral) printz(" -");
+              else if (color[l] == white) printz(" %c",qxx[board[l]]);
+              else printz(" %c",pxx[board[l]]);
+            }
+          printz("\n");
+        }
+      printz("\n");
+    }
+#endif CHESSTOOL
+}
+
+
+GetOpenings()
+
+/*
+   Read in the Opening Book file and parse the algebraic notation for a 
+   move into an unsigned integer format indicating the from and to 
+   square. Create a linked list of opening lines of play, with 
+   entry->next pointing to the next line and entry->move pointing to a 
+   chunk of memory containing the moves. More Opening lines of up to 256 
+   half moves may be added to gnuchess.book. 
+*/
+
+{
+FILE *fd;
+int c,i,j,side;
+char buffr[2048];
+struct BookEntry *entry;
+unsigned short mv,*mp,tmp[100];
+
+  if ((fd = fopen("gnuchess.book","r")) != NULL)
+    {
+/*
+      setvbuf(fd,buffr,_IOFBF,2048);
+*/
+      Book = NULL;
+      i = 0; side = white;
+      while ((c = parse(fd,&mv,side)) >= 0)
+        if (c == 1)
+          {
+            tmp[++i] = mv;
+            side = otherside[side];
+          }
+        else if (c == 0 && i > 0)
+          {
+            entry = (struct BookEntry *)malloc(sizeof(struct BookEntry));
+            mp = (unsigned short *)malloc((i+1)*sizeof(unsigned short));
+            entry->mv = mp;
+            entry->next = Book;
+            Book = entry; 
+            for (j = 1; j <= i; j++) *(mp++) = tmp[j];
+            *mp = 0;
+            i = 0; side = white;
+          }
+      fclose(fd);
+    }
+}
+
+
+int parse(fd,mv,side)
+FILE *fd;
+unsigned short *mv;
+short side;
+{
+int c,i,r1,r2,c1,c2;
+char s[100];
+  while ((c = getc(fd)) == ' ');
+  i = 0; s[0] = c;
+  while (c != ' ' && c != '\n' && c != EOF) s[++i] = c = getc(fd);
+  s[++i] = '\0';
+  if (c == EOF) return(-1);
+  if (s[0] == '!' || i < 3)
+    {
+      while (c != '\n' && c != EOF) c = getc(fd);
+      return(0);
+    }
+  if (s[4] == 'o')
+    if (side == black) *mv = 0x3C3A; else *mv = 0x0402;
+  else if (s[0] == 'o')
+    if (side == black) *mv = 0x3C3E; else *mv = 0x0406;
+  else
+    {
+      c1 = s[0] - 'a'; r1 = s[1] - '1';
+      c2 = s[2] - 'a'; r2 = s[3] - '1';
+      *mv = (locn[r1][c1]<<8) + locn[r2][c2];
+    }
+  return(1);
+}
+
+
+GetGame()
+{
+FILE *fd;
+char fname[40];
+int c;
+short sq;
+unsigned short m;
+
+  printz("Enter file name: ");
+  scanz("%s",fname);
+  if (fname[0] == '\0') strcpy(fname,"chess.000");
+  if ((fd = fopen(fname,"r")) != NULL)
+    {
+      fscanf(fd,"%hd%hd%hd",&computer,&opponent,&Game50);
+      fscanf(fd,"%hd%hd%hd%hd",
+             &castld[white],&castld[black],
+             &kingmoved[white],&kingmoved[black]);
+      fscanf(fd,"%hd%hd",&TCflag,&OperatorTime);
+      fscanf(fd,"%ld%ld%hd%hd",
+             &TimeControl.clock[white],&TimeControl.clock[black],
+             &TimeControl.moves[white],&TimeControl.moves[black]);
+      for (sq = 0; sq < 64; sq++)
+        {
+          fscanf(fd,"%hd",&m);
+          board[sq] = (m >> 8); color[sq] = (m & 0xFF);
+          if (color[sq] == 0) color[sq] = neutral; else --color[sq];
+        }
+      GameCnt = -1; c = '?';
+      while (c != EOF)
+        {
+          ++GameCnt;
+          c = fscanf(fd,"%hd%hd%hd%ld%hd%hd%hd",&GameList[GameCnt].gmove,
+                     &GameList[GameCnt].score,&GameList[GameCnt].depth,
+                     &GameList[GameCnt].nodes,&GameList[GameCnt].time,
+                     &GameList[GameCnt].piece,&GameList[GameCnt].color);
+          if (GameList[GameCnt].color == 0) GameList[GameCnt].color = neutral;
+          else --GameList[GameCnt].color;
+        }
+      GameCnt--;
+      if (TimeControl.clock[white] > 0) TCflag = true;
+      computer--; opponent--;
+    }
+  fclose(fd);
+  InitializeStats();
+  UpdateDisplay(0,0,1,0);
+  Sdepth = 0;
+}
+
+
+SaveGame()
+{
+FILE *fd;
+char fname[40];
+short sq,i,c;
+
+  printz("Enter file name: ");
+  scanz("%s",fname);
+  
+  if (fname[0] == '\0' || access(fname,W_OK) == -1) strcpy(fname,"chess.000");
+  fd = fopen(fname,"w");
+  fprintf(fd,"%d %d %d\n",computer+1,opponent+1,Game50);
+  fprintf(fd,"%d %d %d %d\n",
+          castld[white],castld[black],kingmoved[white],kingmoved[black]);
+  fprintf(fd,"%d %d\n",TCflag,OperatorTime);
+  fprintf(fd,"%ld %ld %d %d\n",
+          TimeControl.clock[white],TimeControl.clock[black],
+          TimeControl.moves[white],TimeControl.moves[black]);
+  for (sq = 0; sq < 64; sq++)
+    {
+      if (color[sq] == neutral) c = 0; else c = color[sq]+1;
+      fprintf(fd,"%d\n",256*board[sq] + c);
+    }
+  for (i = 0; i <= GameCnt; i++)
+    {
+      if (GameList[i].color == neutral) c = 0;
+      else c = GameList[i].color + 1;
+      fprintf(fd,"%d %d %d %ld %d %d %d\n",
+              GameList[i].gmove,GameList[i].score,GameList[i].depth,
+              GameList[i].nodes,GameList[i].time,
+              GameList[i].piece,c);
+    }
+  fclose(fd);
+}
+
+
+ListGame()
+{
+FILE *fd;
+short i,f,t;
+  fd = fopen("chess.lst","w");
+  fprintf(fd,"\n");
+  fprintf(fd,"       score  depth  nodes  time         ");
+  fprintf(fd,"       score  depth  nodes  time\n");
+  for (i = 0; i <= GameCnt; i++)
+    {
+      f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF);
+      algbr(f,t,false);
+      if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd,"         ");
+      fprintf(fd,"%5s  %5d     %2d %6ld %5d",mvstr1,
+              GameList[i].score,GameList[i].depth,
+              GameList[i].nodes,GameList[i].time);
+    }
+  fprintf(fd,"\n\n");
+  fclose(fd);
+} 
+
+
+Undo()
+
+/*
+   Undo the most recent half-move.
+*/
+
+{
+short f,t;
+  f = GameList[GameCnt].gmove>>8;
+  t = GameList[GameCnt].gmove & 0xFF;
+  if (board[t] == king && distance(t,f) > 1)
+    castle(GameList[GameCnt].color,f,t,2);
+  else
+    {
+      board[f] = board[t]; color[f] = color[t];
+      board[t] = GameList[GameCnt].piece;
+      color[t] = GameList[GameCnt].color;
+      if (board[f] == king) --kingmoved[color[f]];
+    }
+  if (TCflag) ++TimeControl.moves[color[f]];
+  GameCnt--; mate = false; Sdepth = 0;
+  UpdateDisplay(0,0,1,0);
+  InitializeStats();
+}
+
+
+ShowMessage(s)
+char *s;
+{
+#ifndef CHESSTOOL
+  printz("%s\n");
+#endif CHESSTOOL
+}
+
+ShowSidetomove()
+{
+}
+
+PromptForMove()
+{
+#ifndef CHESSTOOL
+  printz("\nYour move is? ");
+#endif CHESSTOOL
+}
+
+
+ShowCurrentMove(pnt,f,t)
+short pnt,f,t;
+{
+}
+
+ChangeAlphaWindow()
+{
+  printz("window: ");
+  scanz("%hd",&Awindow);
+}
+
+ChangeBetaWindow()
+{
+  printz("window: ");
+  scanz("%hd",&Bwindow);
+}
+
+GiveHint()
+{
+  algbr((short)(hint>>8),(short)(hint & 0xFF),false);
+  printz("try %s\n",mvstr1);
+}
+
+
+SelectLevel()
+{
+  OperatorTime = 30000;
+  printz("Enter #moves #minutes: ");
+  scanz("%hd %hd",&TCmoves,&TCminutes);
+  printz("Operator time= ");
+  scanz("%hd",&OperatorTime);
+  TCflag = (TCmoves > 1);
+  SetTimeControl();
+}
+
+
+ChangeSearchDepth()
+{
+  printz("depth= ");
+  scanz("%hd",&MaxSearchDepth);
+}
+
+SetContempt()
+{
+  printz("contempt= ");
+  scanz("%hd",&contempt);
+}
+
+ChangeXwindow()
+{
+  printz("xwndw= ");
+  scanz("%hd",&xwndw);
+}