[comp.sources.games] v03i038: gnuchess - Technology Chess program for GNU Unix, Part01/03

games-request@tekred.TEK.COM (01/13/88)

Submitted by: Stuart Cracraft <cracraft@venera.isi.edu>
Comp.sources.games: Volume 3, Issue 38
Archive-name: gnuchess/Part01


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  README MANIFEST COPYING gnuchess.1 gnuchess.c1
# Wrapped by billr@tekred on Tue Jan 12 11:56:40 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(468 characters\)
sed "s/^X//" >README <<'END_OF_README'
XThis is the comp.sources.games distribution of Gnuchess.  The source
Xis the latest as of mid December 1987.  The C source is split into
Xtwo files in order to get the shar files into reasonable sizes for
Xnetwork transfer.  I hacked up the man page based on the "help"
Xscreen and a man page from an earlier release of gnuchess.  See the
Xfile COPYING for the standard GNU info.
X
X	-Bill Randle
X	Moderator, comp.sources.games
X	Tektronix, Inc.
X	games-request@tekred.TEK.COM
END_OF_README
if test 468 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MANIFEST -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(354 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X COPYING                   1	
X MANIFEST                  1	This shipping list
X Makefile                  2	
X README                    1	
X gnuchess.1                1	
X gnuchess.book             2	
X gnuchess.c1               1	
X gnuchess.c2               3	
END_OF_MANIFEST
if test 354 -ne `wc -c <MANIFEST`; then
    echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f COPYING -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"COPYING\"
else
echo shar: Extracting \"COPYING\" \(6439 characters\)
sed "s/^X//" >COPYING <<'END_OF_COPYING'
X
X		 GNU CHESS GENERAL PUBLIC LICENSE
X
X Copyright (C) 1986,1987 Free Software Foundation, Inc.
X Everyone is permitted to copy and distribute verbatim copies
X of this license, but changing it is not allowed.
X
X  The license agreements of most software companies keep you at the
Xmercy of those companies.  By contrast, our general public license is
Xintended to give everyone the right to share GNU Chess.  To make
Xsure that you get the rights we want you to have, we need to make
Xrestrictions that forbid anyone to deny you these rights or to ask you
Xto surrender the rights.  Hence this license agreement.
X
X  Specifically, we want to make sure that you have the right to give
Xaway copies of GNU Chess, that you receive source code or else can get it
Xif you want it, that you can change GNU Chess or use pieces of it in new
Xfree programs, and that you know you can do these things.
X
X  To make sure that everyone has such rights, we have to forbid you to
Xdeprive anyone else of these rights.  For example, if you distribute
Xcopies of GNU Chess, you must give the recipients all the rights that you
Xhave.  You must make sure that they, too, receive or can get the
Xsource code.  And you must tell them their rights.
X
X  Also, for our own protection, we must make certain that everyone
Xfinds out that there is no warranty for GNU Chess.  If GNU Chess is
Xmodified by someone else and passed on, we want its recipients to know
Xthat what they have is not what we distributed, so that any problems
Xintroduced by others will not reflect on our reputation.
X
X  Therefore the Free Software Foundation, Inc. makes the following
Xterms which say what you must do to be allowed to distribute or change
XGNU Chess.
X
X			COPYING POLICIES
X
X  1. You may copy and distribute verbatim copies of GNU Chess source
Xcode as you receive it, in any medium, provided that you conspicuously
Xand appropriately publish on each file a valid copyright notice
X"Copyright (C) 1986,1987 Free Software Foundation, Inc.", containing the
Xyear of last change for the file in question; keep intact the notices
Xon all files that refer to this License Agreement and to the absence
Xof any warranty; and give any other recipients of the GNU Chess
Xprogram a copy of this License Agreement along with the program.
X
X  2. You may modify your copy or copies of GNU Chess source code or
Xany portion of it, and copy and distribute such modifications under
Xthe terms of Paragraph 1 above, provided that you also do the following:
X
X    a) cause the modified files to carry prominent notices stating
X    who last changed such files and the date of any change; and
X
X    b) cause the whole of any work that you distribute or publish,
X    that in whole or in part contains or is a derivative of GNU Chess
X    or any part thereof, to be freely distributed
X    and licensed to all third parties on terms identical to those
X    contained in this License Agreement (except that you may choose
X    to grant more extensive warranty protection to third parties,
X    at your option).
X
X    c) if the modified program serves as a text editor, cause it
X    when started running in the simplest and usual way, to print
X    an announcement including a valid copyright notice ("Copyright
X    (C)", the year of authorship, and all copyright owners' names),
X    saying that there is no warranty (or else, saying that you provide
X    a warranty) and that users may redistribute the program under
X    these conditions, and telling the user how to view a copy of
X    this License Agreement.
X
X  3. You may copy and distribute GNU Chess or any portion of it in
Xcompiled, executable or object code form under the terms of Paragraphs
X1 and 2 above provided that you do the following:
X
X    a) cause each such copy of GNU Chess to be accompanied by the
X    corresponding machine-readable source code; or
X
X    b) cause each such copy of GNU Chess to be accompanied by a
X    written offer, with no time limit, to give any third party
X    free (except for a nominal shipping charge) machine readable
X    copy of the corresponding source code; or
X
X    c) in the case of a recipient of GNU Chess in compiled, executable
X    or object code form (without the corresponding source code) you
X    shall cause copies you distribute to be accompanied by a copy
X    of the written offer of source code which you received along
X    with the copy of GNU Chess.
X
X  4. You may not copy, sublicense, distribute or transfer GNU Chess
Xexcept as expressly provided under this License Agreement.  Any attempt
Xotherwise to copy, sublicense, distribute or transfer GNU Chess is void and
Xyour rights to use GNU Chess under this License agreement shall be
Xautomatically terminated.  However, parties who have received computer
Xsoftware programs from you with this License Agreement will not have
Xtheir licenses terminated so long as such parties remain in full compliance.
X
XYour comments and suggestions about our licensing policies and our
Xsoftware are welcome!  Please contact the Free Software Foundation, Inc.,
X1000 Mass Ave, Cambridge, MA 02138, or call (617) 876-3296.
X
X			   NO WARRANTY
X
X  BECAUSE GNU CHESS IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
XNO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.  EXCEPT
XWHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
XAND/OR OTHER PARTIES PROVIDE GNU CHESS "AS IS" WITHOUT WARRANTY OF ANY
XKIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
XIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
XPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
XPROGRAM IS WITH YOU.  SHOULD THE GNU CHESS PROGRAM PROVE DEFECTIVE,
XYOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
X
X IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE
XFOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND
XREDISTRIBUTE GNU CHESS AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
XDAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
XINCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
XINABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
XBEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
XFAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
XFREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN
XADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY
XOTHER PARTY.
X======================================================================
END_OF_COPYING
if test 6439 -ne `wc -c <COPYING`; then
    echo shar: \"COPYING\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gnuchess.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gnuchess.1\"
else
echo shar: Extracting \"gnuchess.1\" \(3459 characters\)
sed "s/^X//" >gnuchess.1 <<'END_OF_gnuchess.1'
X.TH GNU CHESS
X.SH NAME
Xgnuchess \- The Technology Chess Program for GNU Unix
X.SH SYNOPSIS
X.B gnuchess
X.br
X.B chesstool gnuchess
X[
X.I level
X]
X.SH DESCRIPTION
X.I Gnuchess
Xplays a game of chess against the user. Or it plays against
Xitself. Or it referees a game.
X.PP
X.I Gnuchess
Xhas two display modes. The first mode is simply a normal 
Xmode that you could use with a terminal. The second mode
Xis a fancy display mode you can use with a SUN workstation.
XTo use the former, simply type 'gnuchess'. To use the
Xlatter, simply type 'chesstool gnuchess' on a SUN
Xworkstation where 'chesstool' is installed. In the
Xlatter example, the argument should be the path
Xspecifying where to find the gnuchess binary.
X.PP
XThe
X.I level
Xoption when using 'chesstool' allows setting the search level
Xtime limit (in seconds).  The default is 30 seconds.  In other
Xdisplay modes, the user is prompted for a time limit.  The
Xsearch limit can be changed with the "time" command.
X.PP
XThe following documentation assumes you are in
Xthe first mode (e.g. normal mode using a regular
Xterminal). If not, then you should read the chesstool documentation.
X.PP
XFor help once in
X.I Gnuchess
Xtype "help". To type in your move, use the
Xnotation "e2e4" where the first letter-number pair
Xindicates the origination square and the second
Xletter-number pair indicates the destination square.
XThe letter indicates the column with the left-most
Xcolumn being "a" and the right-most column being "h".
XThe number indicates the row, the first row (White's
Xfirst rank) being "1" and the last row (Black's
Xfirst rank) being "8". To castle, type the origin
Xsquare of the king and the destination square of the
Xking, just as you would do for a regular move.
X.SH LIST OF COMMANDS
X.LP
X.nf
XAwindow		set Alpha window size
XBwindow		set Beta window size
Xbd		redraw board
Xbeep		toggle beep
Xblack		computer plays black
Xbook		force computer to ignore opening book (?)
Xboth		computer match
Xclock		set time control
Xcontempt	?
Xdebug		debug piece locations
Xdepth		set search depth
Xeasy		toggle easy mode
Xforce		enter game moves
Xg1f3		move from g1 to f3
Xget		game from file
Xgo		?
Xhash		toggle hashing
Xhelp		print help message
Xhint		suggest a move
Xlist		game to chess.lst
Xnew		start new game
Xnf3		move knight to f3
Xo-o		castle king side
Xo-o-o		castle queen side
Xpost		principle variation
Xprune		prune search tree
Xquit		exit CHESS
Xrandom		randomize play
Xremove		undo last two moves
Xreverse		board display
Xsave		game to file
Xset		edit board
Xswitch		sides with computer
Xtime		change search level
Xundo		undo last move
Xverify		verify move against the book (?)
Xwhite		computer plays white
X.fi
X.SH BUGS
X.PP
XThere are probably some bugs. Suggestions for improvements
Xand bug reports should be mailed to the author.
X.SH AUTHOR
X.nf
XStuart Cracraft     Stuart Cracraft
XP.O. Box 13123      UCLA, Dept. of Mathematics
XTorrance, Ca.       Los Angeles, Ca.
X90503               90024
X(213) 214-1136      (213) 825-9040
X
Xemail: cracraft@venera.isi.edu
X.fi
X.sp
XManpage created by Bill Randle (billr@tekred.tek.com), based on
Xthe man page for an earlier release of Gnuchess.
X.SH AUTHOR'S COMMENT
X.PP
XThis software is being made available by the Free Software
XFoundation under the restrictions described in its license
Xagreement which accompanies this distribution. This software,
Xits sources, binaries, documentation and all associated parts
Xare copyright (C) 1986 by the Free Software Foundation, Inc.
X.SH SEE ALSO
X.nf
Xchesstool(6)
Xdbm(3)
X.fi
END_OF_gnuchess.1
if test 3459 -ne `wc -c <gnuchess.1`; then
    echo shar: \"gnuchess.1\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gnuchess.c1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gnuchess.c1\"
else
echo shar: Extracting \"gnuchess.c1\" \(41541 characters\)
sed "s/^X//" >gnuchess.c1 <<'END_OF_gnuchess.c1'
X/* Compile via: cc gnuchess.c -o gnuchess. For display version,
X   add -DDISPLAY flag and -lcurses -ltermcap libraries to
X   command-line. For SUN Chesstool version, add -DCHESSTOOL
X   but don't include display options in last sentence.
X   For faster version, add -O flag to any of these flags.
X*/
X/* This file contains code for CHESS.
X   Copyright (C) 1986, 1987 Free Software Foundation, Inc.
X
XThis file is part of CHESS.
X
XCHESS is distributed in the hope that it will be useful,
Xbut WITHOUT ANY WARRANTY.  No author or distributor
Xaccepts responsibility to anyone for the consequences of using it
Xor for whether it serves any particular purpose or works at all,
Xunless he says so in writing.  Refer to the CHESS General Public
XLicense for full details.
X
XEveryone is granted permission to copy, modify and redistribute
XCHESS, but only under the conditions described in the
XCHESS General Public License.   A copy of this license is
Xsupposed to have been given to you along with CHESS so you
Xcan know your rights and responsibilities.  It should be in a
Xfile named COPYING.  Among other things, the copyright notice
Xand this notice must be preserved on all copies.  */
X
X/* Modified 12/18/87 by Bill Randle (billr@tekred.tek.com) to
X   remove a redundant #include and #ifdef section.
X*/
X
X#include <stdio.h>
X#include <ctype.h>
X#include <signal.h>
X
X#ifdef MSDOS
X#include <dos.h>
X#include <stdlib.h>
X#include <time.h>
X#include <alloc.h>
X#define printz printf
X#define scanz scanf
X#define refresh();   
X#define initscr();  
X#define crmode();   
X#define nocrmode();   
X#define endwin();   
X#define _stklen 8000
X#define ttblsz 4096
X#else
X#include <sys/param.h>
X#include <sys/times.h>
X#define ttblsz 16384
X#ifdef DISPLAY
X#include <curses.h>
X#define printz printw
X#define scanz fflush(stdout), scanw
X#else
X#define printz printf
X#define scanz fflush(stdout), scanf
X#define refresh();   
X#define initscr();  
X#define crmode();   
X#define nocrmode();   
X#define endwin();   
X#endif DISPLAY
X#endif MSDOS
X#ifndef HZ
X#define HZ 60
X#endif
X
X#define neutral 0
X#define white 1
X#define black 2 
X#define no_piece 0
X#define pawn 1
X#define knight 2
X#define bishop 3
X#define rook 4
X#define queen 5
X#define king 6
X#define valueP 100
X#define valueN 330
X#define valueB 330
X#define valueR 520
X#define valueQ 980
X#define valueK 999
X#define ctlP 0x4000
X#define ctlN 0x2800
X#define ctlB 0x1800
X#define ctlR 0x0400
X#define ctlQ 0x0200
X#define ctlK 0x0100
X#define ctlBQ 0x1200
X#define ctlRQ 0x0600
X#define ctlNN 0x2000
X#define px " PNBRQK"
X#define qx " pnbrqk"
X#define rx "12345678"
X#define cx "abcdefgh"
X#define check 0x0001
X#define capture 0x0002
X#define draw 0x0004
X#define promote 0x0008
X#define cstlmask 0x0010
X#define epmask 0x0020
X#define exact 0x0040
X#define pwnthrt 0x0080
X#define truescore 0x0001
X#define lowerbound 0x0002
X#define upperbound 0x0004
X#define maxdepth 30
X#define true 1
X#define false 0
X#define absv(x) ((x) < 0 ? -(x) : (x))
X#define taxicab(a,b) (absv(col[a]-col[b]) + absv(row[a]-row[b]))
X
Xstruct leaf
X  {
X    short f,t,score,reply;
X    unsigned short flags;
X  };
Xstruct GameRec
X  {
X    unsigned short gmove;
X    short score,depth,time,piece,color;
X    long nodes;
X  };
Xstruct TimeControlRec
X  {
X    short moves[3];
X    long clock[3];
X  };
Xstruct hashval
X  {
X    unsigned long bd;
X    unsigned short key;
X  };
Xstruct hashentry
X  {
X    unsigned long hashbd;
X    unsigned short reply,flags;
X    short score,depth;
X  };
X
Xchar mvstr1[5],mvstr2[5];
Xstruct leaf Tree[2000],*root;
Xshort TrPnt[maxdepth],board[64],color[64];
Xshort row[64],col[64],locn[8][8],Pindex[64],svalue[64];
Xshort PieceList[3][16],PieceCnt[3],atak[3][64],PawnCnt[3][8];
Xshort castld[3],kingmoved[3],mtl[3],pmtl[3],emtl[3],hung[3];
Xshort mate,post,opponent,computer,Sdepth,Awindow,Bwindow,randflag;
Xlong ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft;
Xlong NodeCnt,evrate,ETnodes,EvalNodes,HashCnt;
Xlong OperatorTime;
Xshort quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep;
Xshort wking,bking,TOsquare,timeout,Zscore,zwndw,cptrval,prune,slk;
Xshort HasPawn[3],HasKnight[3],HasBishop[3],HasRook[3],HasQueen[3];
Xshort ChkFlag[maxdepth],CptrFlag[maxdepth],PawnThreat[maxdepth];
Xshort Pscore[maxdepth],Tscore[maxdepth],Threat[maxdepth];
Xstruct GameRec GameList[240];
Xshort GameCnt,Game50,epsquare,lpost;
Xshort BookSize,BookDepth,MaxSearchDepth;
Xstruct TimeControlRec TimeControl;
Xshort TCflag,TCmoves,mycnt1,mycnt2;
X#ifdef MSDOS
Xunsigned short Book[80][24];
X#else
Xunsigned short Book[250][50];
Xstruct tms tmbuf1,tmbuf2;
X#endif
Xshort otherside[3]={0,2,1};
Xshort map[64]=
X   {26,27,28,29,30,31,32,33,38,39,40,41,42,43,44,45,
X    50,51,52,53,54,55,56,57,62,63,64,65,66,67,68,69,
X    74,75,76,77,78,79,80,81,86,87,88,89,90,91,92,93,
X    98,99,100,101,102,103,104,105,110,111,112,113,114,115,116,117};
Xshort unmap[144]=
X   {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
X    -1,-1,0,1,2,3,4,5,6,7,-1,-1,-1,-1,8,9,10,11,12,13,14,15,-1,-1,
X    -1,-1,16,17,18,19,20,21,22,23,-1,-1,-1,-1,24,25,26,27,28,29,30,31,-1,-1,
X    -1,-1,32,33,34,35,36,37,38,39,-1,-1,-1,-1,40,41,42,43,44,45,46,47,-1,-1,
X    -1,-1,48,49,50,51,52,53,54,55,-1,-1,-1,-1,56,57,58,59,60,61,62,63,-1,-1,
X    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
Xshort Stboard[64]=
X   {rook,knight,bishop,queen,king,bishop,knight,rook,
X    pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
X    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,
X    pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
X    rook,knight,bishop,queen,king,bishop,knight,rook};
Xshort Stcolor[64]=
X   {white,white,white,white,white,white,white,white,
X    white,white,white,white,white,white,white,white,
X    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,
X    black,black,black,black,black,black,black,black,
X    black,black,black,black,black,black,black,black};
Xshort sweep[7]= {false,false,false,true,true,true,false};
Xshort sweep1[7]= {false,false,false,false,true,true,false};
Xshort sweep2[7]= {false,false,false,true,false,true,false};
Xshort Dpwn[3]={0,4,6};
Xshort Dstart[7]={6,4,8,4,0,0,0};
Xshort Dstop[7]={7,5,15,7,3,7,7};
Xshort Dir[16]={1,12,-1,-12,11,13,-11,-13,10,-10,14,-14,23,-23,25,-25};
Xshort rank7[3] = {0,6,1};
Xunsigned short killr0[maxdepth],killr1[maxdepth],killr2[maxdepth];
Xunsigned short killr3[maxdepth],Qkillr[maxdepth],PrVar[maxdepth];
Xunsigned short PV,hint,Swag0,Swag1,Swag2,Swag3,Swag4,Swag5;
Xunsigned short hashkey;
Xunsigned long hashbd;
Xstruct hashval hashcode[3][7][64];
X#ifdef MSDOS
Xstruct hashentry far *ttable,*ptbl;
X#else
Xstruct hashentry *ttable,*ptbl;
Xint TerminateSearch(),Die();
X#endif MSDOS
Xunsigned char history[2][64][64];
X
Xshort Mwpawn[64],Mbpawn[64],Mknight[3][64],Mbishop[3][64],Mking[3][64];
Xshort WeakSq[3][64],Kfield[3][64],contempt[3];
Xshort value[7]={0,valueP,valueN,valueB,valueR,valueQ,valueK};
Xshort control[7]={0,ctlP,ctlN,ctlB,ctlR,ctlQ,ctlK};
Xshort passed_pawn1[8]={0,15,30,60,100,180,280,800};
Xshort passed_pawn2[8]={0,15,25,35,50,90,140,800};
Xshort passed_pawn3[8]={0,5,10,15,20,30,120,800};
Xshort ISOLANI[8] = {-12,-14,-16,-20,-20,-16,-14,-12};
Xshort DOUBLED[8] = {-12,-12,-12,-10,-10,-12,-12,-12};
Xshort BMBLTY[30] = {-4,-2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,13,14,14,
X                    15,15,16,16,17,17,18,18,18,18,18};
Xshort RMBLTY[30] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,14,15,15,
X                    16,16,17,17,18,18,19,19,20,20,20,20};
Xshort Kthreat[16] = {0,-6,-16,-32,-48,-64,-64,-64,-64,-64,-64,-64,
X                     -64,-64,-64,-64};
Xshort KNIGHTPOST,KNIGHTSTRONG,BISHOPSTRONG,KATAK;
Xshort PEDRNK2B,PBKWRD,PWEAKA,PWEAKH,PADVNCM,PAWNSHIELD;
Xshort RHOPN,RHOPNX,KHOPN,KHOPNX;
Xshort ATAKD,HUNGP,HUNGX,KCASTLD,KMOVD,XRAY;
Xshort stage,Zwmtl,Zbmtl,c1,c2,KSFTY,Developed[3];
Xshort KingOpening[64]=
X   {  0,  0, -4, -8, -8, -4,  0,  0,
X     -4, -4, -8,-12,-12, -8, -4, -4,
X    -12,-16,-20,-20,-20,-20,-16,-12,
X    -16,-20,-24,-24,-24,-24,-20,-16,
X    -16,-20,-24,-24,-24,-24,-20,-16,
X    -12,-16,-20,-20,-20,-20,-16,-12,
X     -4, -4, -8,-12,-12, -8, -4, -4,
X      0,  0, -4, -8, -8, -4,  0,  0};
Xshort KingEnding[64]=
X   { 0, 6,12,18,18,12, 6, 0,
X     6,12,18,24,24,18,12, 6,
X    12,18,24,30,30,24,18,12,
X    18,24,30,36,36,30,24,18,
X    18,24,30,36,36,30,24,18,
X    12,18,24,30,30,24,18,12,
X     6,12,18,24,24,18,12, 6,
X     0, 6,12,18,18,12, 6, 0};
Xshort DyingKing[64]=
X   { 0, 8,16,24,24,16, 8, 0,
X     8,32,40,48,48,40,32, 8,
X    16,40,56,64,64,56,40,16,
X    24,48,64,72,72,64,48,24,
X    24,48,64,72,72,64,48,24,
X    16,40,56,64,64,56,40,16,
X     8,32,40,48,48,40,32, 8,
X     0, 8,16,24,24,16, 8, 0};
Xshort pknight[64]=
X   { 0, 4, 8,10,10, 8, 4, 0,
X     4, 8,16,20,20,16, 8, 4,
X     8,16,24,28,28,24,16, 8,
X    10,20,28,32,32,28,20,10,
X    10,20,28,32,32,28,20,10,
X     8,16,24,28,28,24,16, 8,
X     4, 8,16,20,20,16, 8, 4,
X     0, 4, 8,10,10, 8, 4, 0};
Xshort pbishop[64]=
X   {14,14,14,14,14,14,14,14,
X    14,22,18,18,18,18,22,14,
X    14,18,22,22,22,22,18,14,
X    14,18,22,22,22,22,18,14,
X    14,18,22,22,22,22,18,14,
X    14,18,22,22,22,22,18,14,
X    14,22,18,18,18,18,22,14,
X    14,14,14,14,14,14,14,14};
Xshort PawnAdvance[64]=
X   { 0, 0, 0, 0, 0, 0, 0, 0,
X     0, 2, 4, 0, 0, 4, 2, 0,
X     6, 8,10,12,12,10, 8, 6,
X     8,12,20,32,32,20,12, 8,
X    12,20,28,40,40,28,20,12,
X    16,28,36,48,48,36,28,16,
X    16,28,36,48,48,36,28,16,
X     0, 0, 0, 0, 0, 0, 0, 0};
X
X
Xmain(argc,argv)
Xint argc; char *argv[];
X{
X#ifdef MSDOS
X  ttable = (struct hashentry far *)farmalloc(ttblsz *
X           (unsigned long)sizeof(struct hashentry));
X  printf("%lu bytes free\n",farcoreleft());
X#else
X  ttable = (struct hashentry *)malloc(ttblsz *
X           (unsigned long)sizeof(struct hashentry));
X  signal(SIGINT,Die); signal(SIGQUIT,Die);
X#endif MSDOS
X#ifdef CHESSTOOL
X  setlinebuf(stdout);
X  if (argc > 1) Level = atoi(argv[1]);
X  else Level = 30; /* Default to 30 seconds */
X#endif CHESSTOOL
X  initscr();
X  crmode();
X  NewGame();
X  while (!(quit))
X    {
X      if (bothsides && !mate) SelectMove(opponent,1); else input_command();
X      if (!(quit || mate || force)) SelectMove(computer,1);
X    }
X  nocrmode();
X  endwin();
X}
X
X
X#ifndef MSDOS
XDie()
X{
Xchar s[80];
X  signal(SIGINT,SIG_IGN);
X  signal(SIGQUIT,SIG_IGN);
X  gotoXY(50,24);
X  printz("Abort? ");
X  scanz("%s",s);
X  if (strcmp(s,"yes") == 0)
X    {
X#ifdef DISPLAY
X      gotoXY(1,24);
X      nocrmode();
X      endwin();
X#endif DISPLAY
X      exit(0);
X    }
X  signal(SIGINT,Die); signal(SIGQUIT,Die);
X}
X
XTerminateSearch()
X{
X  signal(SIGINT,SIG_IGN);
X  signal(SIGQUIT,SIG_IGN);
X  timeout = true;
X  bothsides = false;
X  signal(SIGINT,Die); signal(SIGQUIT,Die);
X}
X#endif
X
X
XOpeningBook()
X{
Xshort i,j,r0,pnt;
Xunsigned m,r;
X  srand((unsigned)time0);
X  r0 = m = 0;
X  for (i = 0; i < BookSize; i++)
X    {
X      for (j = 0; j <= GameCnt; j++)
X        if (GameList[j].gmove != Book[i][j]) break;
X      if (j > GameCnt)
X        if ((r=rand()) > r0)
X          {
X            r0 = r; m = Book[i][GameCnt+1];
X            hint = Book[i][GameCnt+2];
X          }
X    }
X  for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
X    if ((Tree[pnt].f<<8) + Tree[pnt].t == m) Tree[pnt].score = 0;
X  sort(TrPnt[1],TrPnt[2]-1);
X  if (Tree[TrPnt[1]].score < 0) BookDepth = -1;
X}
X
X
XShowDepth(ch)
Xchar ch;
X{
X#ifdef DISPLAY
X  gotoXY(75,1); printz("%2d%c",Sdepth,ch); ClrEoln();
X#endif DISPLAY
X}
X
XShowResults(ch)
Xchar ch;
X{
X#ifndef DISPLAY
X#ifndef CHESSTOOL
Xregister int i;
X  printz("%2d%c  %5d %4ld %7ld   ",Sdepth,ch,root->score,et,NodeCnt);
X  for (i = 1; PrVar[i] > 0; i++)
X    {
X      algbr((short)(PrVar[i] >> 8),(short)(PrVar[i] & 0xFF),false);
X      if (i == 9 || i == 17) printz("\n                          ");
X      printz("%5s ",mvstr1);
X    }
X  printz("\n");
X  fflush(stdout);
X#endif CHESSTOOL
X#endif DISPLAY
X}
X
X
Xint SelectMove(side,iop)
Xshort side,iop;
X
X/*
X    Select a move by calling function search() at progressively deeper 
X    ply until time is up or a mate or draw is reached. An alpha-beta 
X    window of -9000 to +90 points is set around the score returned from the 
X    previous iteration. 
X*/
X
X{
Xstatic short i,j,alpha,beta,score,tempb,tempc,temps,xside,rpt;
X
X#ifndef MSDOS
X  (void) times(&tmbuf1);
X  signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch);
X#endif MSDOS
X  timeout = false;
X  xside = otherside[side];
X  if (iop != 2) player = side;
X  if (TCflag)
X    {
X      ResponseTime = (TimeControl.clock[side]) /
X                     (TimeControl.moves[side] + 3) -
X                     OperatorTime;
X      ResponseTime += (ResponseTime*TimeControl.moves[side])/(2*TCmoves+1);
X    }
X  else ResponseTime = Level;
X  if (iop == 2) ResponseTime = 999;
X  if (Sdepth > 0 && root->score > Zscore-zwndw) ResponseTime -= ft;
X  else if (ResponseTime < 1) ResponseTime = 1;
X  ExtraTime = 0;
X  
X  if (Sdepth == 0)
X  {
X    ExaminePosition();
X    ptbl = ttable;
X    for (i = 0; i < ttblsz; i++,ptbl++) ptbl->depth = 0;
X    for (i = 0; i < 64; i++)
X      for (j = 0; j < 64; j++)
X        history[0][i][j] = history[1][i][j] = 0;
X    TOsquare = -1;
X    PV = 0;
X    if (iop != 2) hint = 0;
X    for (i = 0; i < maxdepth; i++)
X     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = Qkillr[i] = 0;
X#ifdef DISPLAY
X    for (i = 1; i < 17; i++)
X      {
X        gotoXY(50,i); ClrEoln();
X      }
X#else
X    post = false;
X#ifndef CHESSTOOL
X   printz("\nMove# %d    Target= %ld    Clock: %ld\n",TimeControl.moves[side],
X           ResponseTime,TimeControl.clock[side]);
X#endif CHESSTOOL
X#endif DISPLAY  
X    alpha = -9000; beta = 9000; rpt = 0;
X    TrPnt[1] = 0; root = &Tree[0];
X    MoveList(side,1);
X    if (GameCnt < BookDepth) OpeningBook(); else BookDepth = -1;
X    if (BookDepth > 0) timeout = true;
X    NodeCnt = ETnodes = EvalNodes = HashCnt = 0;
X    Zscore = 0; zwndw = 25;
X  }
X  
X  while (!timeout && Sdepth < MaxSearchDepth)
X    {
X      Sdepth++;
X      ShowDepth(' ');
X      score = search(side,1,Sdepth,alpha,beta,PrVar,&rpt);
X      for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
X      if (score < alpha)
X        {
X          ShowDepth('-');
X          ExtraTime = 5*ResponseTime;
X          score = search(side,1,Sdepth,-9000,beta,PrVar,&rpt);
X        }
X      if (score > beta && !(root->flags & exact))
X        {
X          ShowDepth('+');
X          ExtraTime = 0;
X          score = search(side,1,Sdepth,alpha,9000,PrVar,&rpt);
X        }
X      score = root->score;
X      ShowResults('.');
X      beta = score + Bwindow;
X      if (Awindow != 9000) alpha = score - Awindow;
X      for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
X      if (!timeout) sort(0,TrPnt[2]-1);
X      if (score > Zscore-zwndw && score > Tree[1].score+250) ExtraTime = 0;
X      else if (score > Zscore-3*zwndw) ExtraTime = ResponseTime;
X      else ExtraTime = 3*ResponseTime;
X      if (root->flags & exact) timeout = true;
X      if (Tree[1].score < -9000) timeout = true;
X      if (4*et > 2*ResponseTime + ExtraTime) timeout = true;
X      if (!timeout)
X        {
X          Tscore[0] = score;
X          if (Zscore == 0) Zscore = score;
X          else Zscore = (Zscore+score)/2;
X        }
X      zwndw = 25+absv(Zscore/12);
X    }
X
X  score = root->score;
X  if (rpt >= 2 || score < -12000) root->flags |= draw;
X  if (iop == 2) return(0);
X  if (BookDepth < 0) hint = PrVar[2];
X  ElapsedTime(1);
X#ifdef DISPLAY
X  gotoXY(50,22); printz("Nodes=   %6ld",NodeCnt); ClrEoln();
X  gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate); ClrEoln();
X#else
X#ifndef CHESSTOOL
Xprintz("Nodes= %ld  Eval= %ld  Hash= %ld  Rate= %ld  ",
X        NodeCnt,EvalNodes,HashCnt,evrate);
Xprintz("CPU= %.2ld:%.2ld.%.2ld\n",
X        cputimer/6000,(cputimer % 6000)/100,cputimer % 100);
X#endif CHESSTOOL
X#endif DISPLAY
X
X  if (score > -9999 && rpt <= 2)
X    {
X      MakeMove(side,root,&tempb,&tempc,&temps);
X      algbr(root->f,root->t,root->flags & cstlmask);
X    }
X  else algbr(PieceList[side][0],PieceList[side][0],false);
X  if (root->flags & epmask) UpdateDisplay(0,0,1,0);
X  else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask);
X#ifdef CHESSTOOL
X  gotoXY(50,17); printz("%d. ... %s",++mycnt1,mvstr1); ClrEoln();
X  if (root->flags & draw) printz("Draw\n");
X  if (score == -9999)
X    if (opponent == white) printz("White\n"); else printz("Black\n");
X  if (score == 9998)
X    if (computer == white) printz("White\n"); else printz("Black\n");
X#else
X  gotoXY(50,17); printz("My move is: %s",mvstr1);
X  if (beep) printz("%c",7);
X  ClrEoln();
X  gotoXY(50,24);
X  if (root->flags & draw) printz("Draw game!");
X  if (score == -9999) printz("opponent mates!");
X  else if (score == 9998) printz("computer mates!");
X  else if (score < -9000) printz("opponent will soon mate!");
X  else if (score > 9000)  printz("computer will soon mate!");
X  ClrEoln();
X#endif CHESSTOOL
X#ifndef DISPLAY
X  printz("\n");
X#endif DISPLAY
X  if (score == -9999 || score == 9998) mate = true;
X  if (mate) hint = 0;
X  if (post) post_move(root);
X  if (root->flags & cstlmask) Game50 = GameCnt;
X  else if (board[root->t] == pawn || (root->flags & capture)) 
X    Game50 = GameCnt;
X  GameList[GameCnt].score = score;
X  GameList[GameCnt].nodes = NodeCnt;
X  GameList[GameCnt].time = (short)et;
X  GameList[GameCnt].depth = Sdepth;
X  if (TCflag)
X    {
X      TimeControl.clock[side] -= (et + OperatorTime);
X      if (--TimeControl.moves[side] == 0)
X        SetTimeControl();
X    }
X#ifdef MSDOS
X  if (kbhit()) bothsides = false;
X#endif
X  if ((root->flags & draw) && bothsides) quit = true;
X  if (GameCnt > 238) quit = true;
X  player = xside;
X  Sdepth = 0;
X  fflush(stdin);
X  return(0);
X}
X
X
X#ifdef CHESSTOOL
X#define illegalmsg printz("illegal move\n")
X#else
X#define illegalmsg {gotoXY(50,24); printz("illegal move!"); ClrEoln();}
X#endif
X
Xint VerifyMove(s,iop,mv)
Xchar s[];
Xshort iop;
Xunsigned short *mv;
X{
Xstatic short pnt,tempb,tempc,temps,cnt;
Xstatic struct leaf xnode;
Xstruct leaf *node;
X
X  *mv = 0;
X  if (iop == 2)
X    {
X      UnmakeMove(opponent,&xnode,&tempb,&tempc,&temps);
X      return(false);
X    }
X  cnt = 0;
X  MoveList(opponent,2);
X  pnt = TrPnt[2];
X  while (pnt < TrPnt[3])
X    {
X      node = &Tree[pnt]; pnt++;
X      algbr(node->f,node->t,node->flags & cstlmask);
X      if (strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0)
X        {
X          cnt++; xnode = *node;
X        }
X    }
X  if (cnt == 0)
X    if (isdigit(s[1]) || isdigit(s[2])) illegalmsg;
X  if (cnt == 1)
X    {
X      MakeMove(opponent,&xnode,&tempb,&tempc,&temps);
X      if (SqAtakd(PieceList[opponent][0],computer))
X        {
X          UnmakeMove(opponent,&xnode,&tempb,&tempc,&temps);
X          illegalmsg;
X          return(false);
X        }
X      else
X        {
X          if (iop == 1) return(true);
X          if (xnode.flags & epmask) UpdateDisplay(0,0,1,0);
X          else UpdateDisplay(xnode.f,xnode.t,0,xnode.flags & cstlmask);
X          if (xnode.flags & cstlmask) Game50 = GameCnt;
X          else if (board[xnode.t] == pawn || (xnode.flags & capture)) 
X            Game50 = GameCnt;
X          GameList[GameCnt].depth = GameList[GameCnt].score = 0;
X          GameList[GameCnt].nodes = 0;
X          ElapsedTime(1);
X          GameList[GameCnt].time = (short)et;
X          TimeControl.clock[opponent] -= et;
X          --TimeControl.moves[opponent];
X          *mv = (xnode.f << 8) + xnode.t;
X          return(true);
X        } 
X    }
X  else if (cnt > 1)
X    {
X      gotoXY(50,24); printz("ambiguous move!"); ClrEoln();
X    }
X  return(false);
X}
X
X      
Xinput_command()
X{
Xshort ok,i,f,t,c,p,tc,tp;
Xunsigned short mv;
Xchar s[80],fname[20];
X
X  ok=quit=false;
X  player = opponent;
X  ataks(white,atak[white]); ataks(black,atak[black]);
X#ifdef DISPLAY
X  gotoXY(50,19); printz("Your move is? "); ClrEoln();
X#endif
X  ft = 0;
X  if (hint > 0 && !easy && BookDepth < 0)
X    {
X      fflush(stdout);
X      time0 = time((long *)0);
X      algbr(hint>>8,hint & 0xFF,false);
X      strcpy(s,mvstr1);
X      f = epsquare;
X      if (VerifyMove(s,1,&mv))
X        {
X          SelectMove(computer,2);
X          VerifyMove(mvstr1,2,&mv);
X          if (Sdepth > 0) Sdepth--;
X        }
X      ft = time((long *)0) - time0;
X      epsquare = f;
X    }
X  fflush(stdin);
X  
X  while (!(ok || quit))
X    {
X#ifndef CHESSTOOL
X      gotoXY(50,19); printz("Your move is? "); ClrEoln();
X#endif CHESSTOOL
X      scanz("%s",s);
X      player = opponent;
X      ok = VerifyMove(s,0,&mv);
X      if (ok && mv != hint)
X        {
X          Sdepth = 0;
X          ft = 0;
X        }
X      if (strcmp(s,"bd") == 0)
X        {
X#ifdef DISPLAY
X          ClrScreen();  UpdateDisplay(0,0,1,0);
X#else
X          PrintBoard();
X#endif DISPLAY
X        }
X      if (strcmp(s,"quit") == 0) quit = true;
X      if (strcmp(s,"post") == 0) post = !post;
X      if (strcmp(s,"set") == 0) SetBoard();
X      if (strcmp(s,"go") == 0) ok = true;
X      if (strcmp(s,"help") == 0) help();
X      if (strcmp(s,"force") == 0) force = !force;
X      if (strcmp(s,"random") == 0) randflag = !randflag; 
X      if (strcmp(s,"book") == 0) BookDepth = -1;
X      if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo();
X      if (strcmp(s,"new") == 0) NewGame();
X      if (strcmp(s,"list") == 0) ListGame();
X      if (strcmp(s,"clock") == 0) SetTimeControl();
X      if (strcmp(s,"hash") == 0) hashflag = !hashflag;
X      if (strcmp(s,"beep") == 0) beep = !beep;
X      if (strcmp(s,"Awindow") == 0)
X        {
X          gotoXY(50,24); printz("window: "); ClrEoln();
X          scanz("%hd",&Awindow);
X        }
X      if (strcmp(s,"Bwindow") == 0)
X        {
X          gotoXY(50,24); printz("window: "); ClrEoln();
X          scanz("%hd",&Bwindow);
X        }
X      if (strcmp(s,"hint") == 0)
X        {
X          algbr((short)(hint>>8),(short)(hint & 0xFF),false);
X          gotoXY(50,24); printz("try  %5s",mvstr1); ClrEoln();
X        }
X      if (strcmp(s,"both") == 0)
X        {
X          bothsides = !bothsides;
X          Sdepth = 0;
X          SelectMove(opponent,1);
X          ok = true;
X        }
X      if (strcmp(s,"reverse") == 0)
X        {
X          reverse = !reverse;
X          ClrScreen();
X          UpdateDisplay(0,0,1,0);
X        }
X      if (strcmp(s,"switch") == 0)
X        {
X          computer = otherside[computer];
X          opponent = otherside[opponent];
X          UpdateDisplay(0,0,1,0);
X          force = false;
X          ok = true;
X          Sdepth = 0;
X        }
X      if (strcmp(s,"white") == 0)
X        {
X          computer = white; opponent = black;
X          UpdateDisplay(0,0,1,0);
X          ok = true; force = false;
X          Sdepth = 0;
X        }
X      if (strcmp(s,"black") == 0)
X        {
X          computer = black; opponent = white;
X          UpdateDisplay(0,0,1,0);
X          ok = true; force = false;
X          Sdepth = 0;
X        }
X      if (strcmp(s,"time") == 0)
X        {
X          gotoXY(50,24); printz("enter time: "); ClrEoln();
X          scanz("%ld",&Level);
X          TCflag = false;
X        }
X      if (strcmp(s,"remove") == 0 && GameCnt >= 1) 
X        {
X          Undo(); Undo();
X        }
X      if (strcmp(s,"get") == 0)
X        {
X          gotoXY(50,24); printz("fname? "); ClrEoln(); scanz("%s",fname);
X          GetGame(fname);
X          InitializeStats();
X          UpdateDisplay(0,0,1,0);
X          Sdepth = 0;
X        }
X      if (strcmp(s,"save") == 0)
X        {
X          gotoXY(50,24); printz("fname? "); ClrEoln(); scanz("%s",fname);
X          SaveGame(fname);
X        }
X      if (strcmp(s,"depth") == 0)
X        {
X          gotoXY(50,24); printz("depth= "); ClrEoln();
X          scanz("%hd",&MaxSearchDepth);
X        }
X      if (strcmp(s,"verify") == 0) VerifyBook();
X      if (strcmp(s,"easy") == 0) easy = !easy;
X      if (strcmp(s,"contempt") == 0)
X        {
X          gotoXY(50,24); printz("contempt= "); ClrEoln();
X          scanz("%hd",&c);
X          contempt[computer] = c;
X          contempt[opponent] = -c;
X        }
X      if (strcmp(s,"prune") == 0)
X        {
X          gotoXY(50,24); printz("prune= "); ClrEoln();
X          scanz("%hd",&prune);
X        }
X      if (strcmp(s,"debug") == 0)
X        {
X          ExaminePosition();
X          gotoXY(50,24); printz("enter piece: "); ClrEoln();
X          scanz("%s",s);
X          if (s[0] == 'w') c = white; else c = black;
X          if (s[1] == 'p') p = pawn;
X          else if (s[1] == 'n') p = knight;
X          else if (s[1] == 'b') p = bishop;
X          else if (s[1] == 'r') p = rook;
X          else if (s[1] == 'q') p = queen;
X          else if (s[1] == 'k') p = king;
X          else p = no_piece;
X          for (i = 0; i < 64; i++)
X            {
X              gotoXY(4+5*col[i],5+2*(7-row[i]));
X              tp = board[i]; tc = color[i];
X              board[i] = p; color[i] = c;
X              c1 = c; c2 = otherside[c1];
X              printz("%3d ",SqValue(i,opponent));
X              board[i] = tp; color[i] = tc;
X            }
X          refresh();
X        }
X    }
X#ifdef CHESSTOOL
X  printf("%d. %s\n",++mycnt2,s);
X#endif CHESSTOOL
X  gotoXY(50,24); ClrEoln();
X  ElapsedTime(1);
X  if (force)
X    {
X      computer = opponent; opponent = otherside[computer];
X    }
X}
X
X
XgotoXY(x,y)
Xshort x,y;
X{
X#ifdef DISPLAY
X#ifdef MSDOS
Xunion REGS r1,r2;
X  r1.h.ah = 0x02; r1.h.bh = 0x00;
X  r1.h.dl = x-1; r1.h.dh = y-1;
X  int86(0x10,&r1,&r2);
X#else
X  move(y-1,x-1);
X#endif MSDOS
X#else
X#ifndef CHESSTOOL
X  printz("\n");
X#endif CHESSTOOL
X#endif DISPLAY
X}
X
X
XClrScreen()
X{
X#ifdef DISPLAY
X#ifdef MSDOS
Xunion REGS r1,r2;
X  gotoXY(1,1);
X  r1.h.ah = 0x08; r1.h.bh = 0x00;
X  int86(0x10,&r1,&r2);
X  r1.h.ah = 0x09; r1.h.al = 0x20;
X  r1.h.bh = 0x00; r1.h.bl = r2.h.ah; 
X  r1.h.ch = 0x07; r1.h.cl = 0xD0;
X  int86(0x10,&r1,&r2);
X  gotoXY(1,1);
X#else
X  clear(); refresh();
X#endif MSDOS
X#else
X  printz("\n\n");
X#endif DISPLAY
X}
X
X
XClrEoln()
X{
X#ifdef DISPLAY
X#ifdef MSDOS
Xunion REGS r1,r2;
Xchar x,y;
X  r1.h.ah = 0x03; r1.h.bh = 0x00;
X  int86(0x10,&r1,&r2);
X  x = r2.h.dl+1; y = r2.h.dh+1;
X  r1.h.ah = 0x08; r1.h.bh = 0x00;
X  int86(0x10,&r1,&r2);
X  r1.h.ah = 0x09; r1.h.al = 0x20;
X  r1.h.bh = 0x00; r1.h.bl = r2.h.ah; 
X  r1.h.ch = 0x00; r1.h.cl = 81-x;
X  int86(0x10,&r1,&r2);
X  gotoXY(x,y);
X#else
X  clrtoeol(); refresh();
X#endif MSDOS
X#endif DISPLAY
X}
X
X
Xalgbr(f,t,iscastle)
Xshort f,t,iscastle;
X{
X  mvstr1[0] = cx[col[f]]; mvstr1[1] = rx[row[f]];
X  mvstr1[2] = cx[col[t]]; mvstr1[3] = rx[row[t]];
X  mvstr2[0] = qx[board[f]];
X  mvstr2[1] = mvstr1[2]; mvstr2[2] = mvstr1[3];
X  mvstr1[4] = '\0'; mvstr2[3] = '\0';
X  if (iscastle)
X    if (t > f) strcpy(mvstr2,"o-o");
X    else strcpy(mvstr2,"o-o-o");
X}
X
X
XUndo()
X{
Xshort f,t;
X  f = GameList[GameCnt].gmove>>8;
X  t = GameList[GameCnt].gmove & 0xFF;
X  if (board[t] == king && distance(t,f) > 1)
X    castle(GameList[GameCnt].color,f,t,2);
X  else
X    {
X      board[f] = board[t]; color[f] = color[t];
X      board[t] = GameList[GameCnt].piece;
X      color[t] = GameList[GameCnt].color;
X      if (board[f] == king) --kingmoved[color[f]];
X    }
X  if (TCflag) ++TimeControl.moves[color[f]];
X  GameCnt--; mate = false; Sdepth = 0;
X  UpdateDisplay(0,0,1,0);
X  InitializeStats();
X}
X
X
Xparse(s,m,j)
Xunsigned short *m; char s[];
Xshort j;
X{
Xshort r1,r2,c1,c2;
X  if (s[4] == 'o')
X    if (j & 1) *m = 0x3C3A; else *m = 0x0402;
X  else if (s[0] == 'o')
X    if (j & 1) *m = 0x3C3E; else *m = 0x0406;
X  else
X    {
X      c1 = s[0] - 'a'; r1 = s[1] - '1';
X      c2 = s[2] - 'a'; r2 = s[3] - '1';
X      *m = (locn[r1][c1]<<8) + locn[r2][c2];
X    }
X}
X
X
XGetOpenings()
X{
XFILE *fd;
Xint c,j;
Xchar s[80],*p;
X  if ((fd = fopen("gnuchess.book","r")) != NULL)
X    {
X      BookSize = 0; j = 0; c = '?'; p = s;
X      while ((c = getc(fd)) != EOF)
X        if (c != '\n') *(p++) = c;
X        else
X          {
X            *p = '\0';
X            if (s[0] == '!')
X              {
X                if (j > 0)
X                  {
X                    while (j < BookDepth) Book[BookSize][j++] = 0; 
X                    BookSize++; j = 0;
X                  }
X              }
X            else
X              {
X                parse(&s[0],&Book[BookSize][j],j); j++;
X                parse(&s[6],&Book[BookSize][j],j); j++;
X              } 
X            p = s;
X          }
X      fclose(fd);
X    }
X}
X
X
XGetGame(fname)
Xchar fname[20];
X{
XFILE *fd;
Xint c;
Xshort loc;
Xunsigned short m;
X
X  if (fname[0] == '\0') strcpy(fname,"chess.000");
X  if ((fd = fopen(fname,"r")) != NULL)
X    {
X      fscanf(fd,"%hd%hd%hd",&computer,&opponent,&Game50);
X      fscanf(fd,"%hd%hd%hd%hd",
X             &castld[white],&castld[black],
X             &kingmoved[white],&kingmoved[black]);
X      fscanf(fd,"%hd%hd",&TCflag,&OperatorTime);
X      fscanf(fd,"%ld%ld%hd%ld",
X             &TimeControl.clock[white],&TimeControl.clock[black],
X             &TimeControl.moves[white],&TimeControl.moves[black]);
X      for (loc = 0; loc < 64; loc++)
X        {
X          fscanf(fd,"%hd",&m); board[loc] = (m >> 8); color[loc] = (m & 0xFF);
X        }
X      GameCnt = -1; c = '?';
X      while (c != EOF)
X        {
X          ++GameCnt;
X          c = fscanf(fd,"%hd%hd%hd%ld%hd%hd%hd",&GameList[GameCnt].gmove,
X                     &GameList[GameCnt].score,&GameList[GameCnt].depth,
X                     &GameList[GameCnt].nodes,&GameList[GameCnt].time,
X                     &GameList[GameCnt].piece,&GameList[GameCnt].color);
X        }
X      GameCnt--;
X    }
X  fclose(fd);
X}
X
X
XSaveGame(fname)
Xchar fname[20];
X{
XFILE *fd;
Xshort loc,i;
X
X  if (fname[0] == '\0') strcpy(fname,"chess.000");
X  fd = fopen(fname,"w");
X  fprintf(fd,"%d %d %d\n",computer,opponent,Game50);
X  fprintf(fd,"%d %d %d %d\n",
X          castld[white],castld[black],kingmoved[white],kingmoved[black]);
X  fprintf(fd,"%d %d\n",TCflag,OperatorTime);
X  fprintf(fd,"%ld %ld %d %ld\n",
X          TimeControl.clock[white],TimeControl.clock[black],
X          TimeControl.moves[white],TimeControl.moves[black]);
X  for (loc = 0; loc < 64; loc++)
X    fprintf(fd,"%d\n",256*board[loc] + color[loc]);
X  for (i = 0; i <= GameCnt; i++)
X    fprintf(fd,"%d %d %d %ld %d %d %d\n",
X            GameList[i].gmove,GameList[i].score,GameList[i].depth,
X            GameList[i].nodes,GameList[i].time,
X            GameList[i].piece,GameList[i].color);
X  fclose(fd);
X}
X
X
XListGame()
X{
XFILE *fd;
Xshort i,f,t;
X  fd = fopen("chess.lst","w");
X  fprintf(fd,"\n");
X  fprintf(fd,"       score  depth  nodes  time         ");
X  fprintf(fd,"       score  depth  nodes  time\n");
X  for (i = 0; i <= GameCnt; i++)
X    {
X      f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF);
X      algbr(f,t,false);
X      if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd,"         ");
X      fprintf(fd,"%5s  %5d     %2d %6ld %5d",mvstr1,
X              GameList[i].score,GameList[i].depth,
X              GameList[i].nodes,GameList[i].time);
X    }
X  fprintf(fd,"\n\n");
X  fclose(fd);
X} 
X
X
XVerifyBook()
X{
Xshort i,j,side,found,pnt,tempb,tempc,temps;
Xunsigned short mv;
Xstruct leaf *node;
X  ClrScreen();
X  for (i = 0; i < BookSize; i++)
X    {
X      CopyBoard(Stboard,board); CopyBoard(Stcolor,color);
X      InitializeStats(); GameCnt = 0;
X      kingmoved[white] = kingmoved[black] = false;
X      castld[white] = castld[black] = false;
X      side = white;
X      for (j = 0; Book[i][j] > 0; j++)
X        {
X          MoveList(side,1);
X          found = false;
X          for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
X            {
X              node = &Tree[pnt];
X              mv = (node->f << 8) + node->t;
X              if (mv == Book[i][j])
X                {
X                  found = true;
X                  MakeMove(side,node,&tempb,&tempc,&temps);
X                  break;
X                }
X            }
X          if (!found) break;
X          side = otherside[side];
X        }
X      if (found) printz("%d   ok\n",i);
X      else printz("%d   bad (%d)\n",i,j);
X    }
X}
X
X
XSetTimeControl()
X{
Xlong minutes;
X  
X  TCmoves = 0; OperatorTime = 30000;
X  while (TCmoves <= 0)
X    {
X      gotoXY(50,24); printz("Enter #moves #minutes: "); ClrEoln();
X      scanz("%hd %ld",&TCmoves,&minutes);
X    }
X  while (OperatorTime * TCmoves > 60*minutes + TCmoves)
X    {
X      gotoXY(50,24); printz("Operator time= "); ClrEoln();
X      scanz("%ld",&OperatorTime);
X    }
X  TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
X  TimeControl.clock[white] = TimeControl.clock[black] = 60*minutes;
X  TCflag = true;
X  et = 0;
X#ifndef MSDOS
X  (void) times(&tmbuf1);
X#endif MSDOS
X  ElapsedTime(1);
X}
X
X
XElapsedTime(iop)
Xshort iop;
X{
Xshort m,s;
X  et = time((long *)0) - time0;
X  if (et < 0) et = 0;
X  ETnodes += 50;
X  if (et > et0 || iop == 1)
X    {
X      if (et > ResponseTime+ExtraTime) timeout = true;
X#ifdef MSDOS
X      if (kbhit()) timeout = true;
X#endif MSDOS
X      et0 = et;
X      if (iop == 1)
X        {
X          time0 = time((long *)0); et0 = 0;
X        }
X#ifdef DISPLAY
X      m = et/60; s = (et - 60*m);
X      if (TCflag)
X        {
X          m = (TimeControl.clock[player] - et) / 60;
X          s = absv(TimeControl.clock[player]) - et - 60*m;
X        }
X      if (player == white)
X        if (reverse) gotoXY(20,2); else gotoXY(20,23);
X      else
X        if (reverse) gotoXY(20,23); else gotoXY(20,2);
X      printz("%d:%2d   ",m,s);
X#endif DISPLAY
X#ifdef MSDOS
X      cputimer = 100*et;
X      if (et > 0) evrate = NodeCnt/(et+ft); else evrate = 0;
X#else
X      (void) times(&tmbuf2);
X      cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ;
X      if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft);
X      else evrate = 0;
X#endif MSDOS
X      ETnodes = NodeCnt + 50;
X      if (post)
X        {
X          gotoXY(50,22); printz("Nodes=   %6ld",NodeCnt);
X          gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate);
X        }
X      refresh();
X    }
X}
X
X
Xpost_move(node)
Xstruct leaf *node;
X{
Xshort c,d,e,ply;
X  e = lpost; c = player;
X  gotoXY(50,3); printz("Score= %6d",node->score);
X  if (c == white) d = 4; else d = 5;
X  for (ply = 1; PrVar[ply] > 0; ply++)
X    {
X      algbr((short)(PrVar[ply]>>8),(short)(PrVar[ply] & 0x00FF),false);
X      if (c == white) gotoXY(50,++d); else gotoXY(60,d);
X      printz("%5s",mvstr1);
X      c = otherside[c];
X    }
X  ClrEoln();
X  lpost = d;
X  while (++d <= e)
X    {
X      gotoXY(50,d); ClrEoln();
X    }
X}
X
X
XDrawPiece(loc)
Xshort loc;
X{
X#ifdef DISPLAY
Xshort r,c; char x;
X  if (reverse) r = 7-row[loc]; else r = row[loc];
X  if (reverse) c = 7-col[loc]; else c = col[loc];
X  if (color[loc] == black) x = '*'; else x = ' ';
X  gotoXY(5+5*c,5+2*(7-r)); printz("%c%c ",x,px[board[loc]]);
X#endif DISPLAY
X}
X
X
XUpdateDisplay(f,t,flag,iscastle)
Xshort f,t,flag,iscastle;
X{
X#ifdef DISPLAY
Xshort i,l,c,z; 
X  if (flag)
X    {
X      i = 3;
X      gotoXY(3,++i);
X      printz("|----|----|----|----|----|----|----|----|");
X      while (i<19)
X        {
X          gotoXY(1,++i);
X          if (reverse) z = (i/2)-1; else z = 10-(i/2);
X          printz("%d |    |    |    |    |    |    |    |    |",z);
X          gotoXY(3,++i);
X          printz("|----|----|----|----|----|----|----|----|");
X        }
X      gotoXY(3,21);
X      if (reverse) printz("  h    g    f    e    d    c    b    a");
X              else printz("  a    b    c    d    e    f    g    h");
X      if (reverse) gotoXY(5,23); else gotoXY(5,2);
X      if (computer == black) printz("Computer"); else printz("Human   ");
X      if (reverse) gotoXY(5,2); else gotoXY(5,23);
X      if (computer == white) printz("Computer"); else printz("Human   ");
X      for (l = 0; l < 64; l++) DrawPiece(l);
X    }
X  else
X    {
X      DrawPiece(f); DrawPiece(t);
X      if (iscastle)
X        if (t > f)
X          { DrawPiece(f+3); DrawPiece(t-1); }
X        else
X          { DrawPiece(f-4); DrawPiece(t+1); }
X    }
X  refresh();
X#endif DISPLAY
X}
X
X
XPrintBoard()
X{
Xshort r,c,l;
X#ifndef DISPLAY
Xprintz("\n");
Xfor (r = 7; r >= 0; r--)
X  {
X    for (c = 0; c <= 7; c++)
X      {
X        if (reverse) l = locn[7-r][7-c]; else l = locn[r][c];
X        if (color[l] == neutral) printz(" -");
X        else if (color[l] == white) printz(" %c",qx[board[l]]);
X        else printz(" %c",px[board[l]]);
X      }
X    printz("\n");
X  }
X#endif DISPLAY
X}
X
X
XSetBoard()
X{
Xshort a,r,c,loc;
Xchar s[80];
X
X  ClrScreen(); UpdateDisplay(0,0,1,0);
X  gotoXY(50,2); printz(".   exit to main");
X  gotoXY(50,3); printz("#   clear board");
X  a = white;
X  do
X  {
X    gotoXY(49,5);
X    printz("enter piece & location: "); ClrEoln(); scanz("%s",s);
X    if (s[0] == '#')
X      {
X        for (loc = 0; loc < 64; loc++)
X          { board[loc] = no_piece; color[loc] = neutral; }
X        UpdateDisplay(0,0,1,0);
X      }
X    if (s[0] == 'c' || s[0] == 'C') a = otherside[a];
X    c = s[1]-'a'; r = s[2]-'1';
X    if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
X      {
X        loc = locn[r][c];
X        color[loc] = a;
X        if (s[0] == 'p') board[loc] = pawn;
X        else if (s[0] == 'n') board[loc] = knight;
X        else if (s[0] == 'b') board[loc] = bishop;
X        else if (s[0] == 'r') board[loc] = rook;
X        else if (s[0] == 'q') board[loc] = queen;
X        else if (s[0] == 'k') board[loc] = king;
X        else { board[loc] = no_piece; color[loc] = neutral; }
X        DrawPiece(loc);
X      }
X  }
X  while (s[0] != '.');
X  if (board[4] != king) kingmoved[white] = 10;
X  if (board[60] != king) kingmoved[black] = 10;
X  GameCnt = -1; Game50 = 0; BookDepth = -1; Sdepth = 0;
X  InitializeStats(); ClrScreen(); UpdateDisplay(0,0,1,0);
X}
X  
X
XNewGame()
X{
Xshort l,r,c,p;
X
X  mate = quit = reverse = bothsides = post = randflag = TCflag = false;
X  hashflag = force = easy = false;
X  beep = true;
X  mycnt1 = mycnt2 = 0;
X  lpost =  NodeCnt = epsquare = et0 = 0;
X  Awindow = 9000;
X  Bwindow = 90;
X  MaxSearchDepth = 30;
X  prune = 50;
X  contempt[white] = contempt[black] = 0;
X#ifdef MSDOS
X  BookDepth = 24;
X#else
X  BookDepth = 50;
X#endif MSDOS
X  GameCnt = -1; Game50 = 0;
X  Zwmtl = Zbmtl = 0;
X  Developed[white] = Developed[black] = false;
X  castld[white] = castld[black] = false;
X  kingmoved[white] = kingmoved[black] = 0;
X  PawnThreat[0] = CptrFlag[0] = Threat[0] = false;
X  Pscore[0] = 12000; Tscore[0] = 12000;
X  TimeControl.clock[white] = TimeControl.clock[black] = 0;
X  TimeControl.moves[white] = TimeControl.moves[black] = 0;
X  opponent = white; computer = black;
X  for (r = 0; r < 8; r++)
X    for (c = 0; c < 8; c++)
X      {
X        l = 8*r+c; locn[r][c] = l;
X        row[l] = r; col[l] = c;
X        board[l] = Stboard[l]; color[l] = Stcolor[l];
X      }
X  for (c = white; c <= black; c++)
X    for (p = pawn; p <= king; p++)
X      for (l = 0; l < 64; l++)
X        {
X          hashcode[c][p][l].key = (unsigned short)rand();
X          hashcode[c][p][l].bd = ((unsigned long)rand() << 16) +
X                                 (unsigned long)rand();
X        }
X#ifdef CHESSTOOL
X  printf("Chess\n");
X  easy = true;
X#else
X  ClrScreen(); gotoXY(1,20);
X  printz("enter response time: "); ClrEoln();
X  scanz("%ld",&Level);
X  ClrScreen();
X#endif CHESSTOOL
X  UpdateDisplay(0,0,1,0);
X  InitializeStats();
X  time0 = time((long *)0);
X  ElapsedTime(1);
X  GetOpenings();
X}
X
X
Xhelp()
X{
X  ClrScreen();
X  gotoXY(28,1); printz("CHESS command summary");
X  gotoXY(1,3); printz("g1f3      move from g1 to f3");
X  gotoXY(1,4); printz("nf3       move knight to f3");
X  gotoXY(1,5); printz("o-o       castle king side");
X  gotoXY(1,6); printz("o-o-o     castle queen side");
X  gotoXY(1,7); printz("set       edit board");
X  gotoXY(1,8); printz("switch    sides with computer");
X  gotoXY(1,9); printz("white     computer plays white");
X  gotoXY(1,10); printz("black     computer plays black");
X  gotoXY(1,11); printz("reverse   board display");
X  gotoXY(1,12); printz("both      computer match");
X  gotoXY(1,13); printz("random    randomize play");
X  gotoXY(1,14); printz("undo      undo last move");
X  gotoXY(42,3); printz("time      change level");
X  gotoXY(42,4); printz("depth     set search depth");
X  gotoXY(42,5); printz("post      principle variation");
X  gotoXY(42,6); printz("hint      suggest a move");
X  gotoXY(42,7); printz("bd        redraw board");
X  gotoXY(42,8); printz("clock     set time control");
X  gotoXY(42,9); printz("force     enter game moves");
X  gotoXY(42,10); printz("list      game to chess.lst");
X  gotoXY(42,11); printz("save      game to file");
X  gotoXY(42,12); printz("get       game from file");
X  gotoXY(42,13); printz("new       start new game");
X  gotoXY(42,14); printz("quit      exit CHESS");
X  gotoXY(10,21); printz("Computer: ");
X  if (computer == white) printz("WHITE"); else printz("BLACK");
X  gotoXY(10,22); printz("Opponent: ");
X  if (opponent == white) printz("WHITE"); else printz("BLACK");
X  gotoXY(10,23); printz("Response time: %ld",Level," sec.");
X  gotoXY(10,24); printz("Easy mode: ");
X  if (easy) printz("ON"); else printz("OFF");
X  gotoXY(40,21); printz("Depth: %d",MaxSearchDepth);
X  gotoXY(40,22); printz("Random: "); 
X  if (randflag) printz("ON"); else printz("OFF");
X  gotoXY(40,23); printz("Transposition table: ");
X  if (hashflag) printz("ON"); else printz("OFF");
X  refresh();
X  while (getchar() != '\n');
X  ClrScreen();
X  UpdateDisplay(0,0,1,0);
X}
X
X
XUpdateHashbd(side,piece,f,t)
Xshort side,piece,f,t;
X/*
X   hashbd contains a 32 bit "signature" of the board position.
X   hashkey contains a 16 bit code used to address the hash table.
X   When a move is made, XOR'ing the hashcode of moved piece on the from and
X   to squares with the hashbd and hashkey values keeps things current.
X*/
X{
X  if (f >= 0)
X    {
X      hashbd ^= hashcode[side][piece][f].bd;
X      hashkey ^= hashcode[side][piece][f].key;
X    }
X  if (t >= 0)
X    {
X      hashbd ^= hashcode[side][piece][t].bd;
X      hashkey ^= hashcode[side][piece][t].key;
X    }
X}
X
X
XUpdatePieceList(side,loc,iop)
Xshort side,loc,iop;
X
X/*
X    Array PieceList[side][Pindx] contains the location of all the pieces of
X    either side. Array Pindex[loc] contains the indx into PieceList for a
X    given square.
X*/
X
X{
Xregister short i;
X  if (iop == 1)
X    {
X      PieceCnt[side]--;
X      for (i = Pindex[loc]; i <= PieceCnt[side]; i++)
X        {
X          PieceList[side][i] = PieceList[side][i+1];
X          Pindex[PieceList[side][i]] = i;
X        }
X    }
X  else
X    {
X      PieceCnt[side]++;
X      PieceList[side][PieceCnt[side]] = loc;
X      Pindex[loc] = PieceCnt[side];
X    }
X}
X
X
END_OF_gnuchess.c1
if test 41541 -ne `wc -c <gnuchess.c1`; then
    echo shar: \"gnuchess.c1\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0