home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume13
/
gnuchess4
/
part11
< prev
next >
Wrap
Internet Message Format
|
1992-08-03
|
57KB
Path: uunet!zephyr.ens.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v13i099: gnuchess4 - GNU Chess 4.0, Part11/12
Message-ID: <3066@master.CNA.TEK.COM>
Date: 19 Jun 92 15:55:30 GMT
Sender: news@master.CNA.TEK.COM
Lines: 1999
Approved: billr@saab.CNA.TEK.COM
Submitted-by: cracraft@rice-chex.ai.mit.edu (Stuart Cracraft)
Posting-number: Volume 13, Issue 99
Archive-name: gnuchess4/Part11
Supersedes: gnuchess2: Volume 4, Issue 37-40
Environment:
#! /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 11 (of 12)."
# Contents: doc/ARTICLE.2 doc/MOVE-GEN misc/gnuchess.lang src/book.c
# src/genmoves.c src/main.c src/util.c
# Wrapped by billr@saab on Fri Jun 19 08:36:02 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'doc/ARTICLE.2' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/ARTICLE.2'\"
else
echo shar: Extracting \"'doc/ARTICLE.2'\" \(6615 characters\)
sed "s/^X//" >'doc/ARTICLE.2' <<'END_OF_FILE'
X
X
X GNU Chess: Experiences Learned
X with Communal Sharing
X by Stuart Cracraft
X (and contributors to the GNU Project)
X
X
XLimited sharing has characterized the computer chess community
Xfor the past two decades. Occasional research articles give hints
Xand suggestions for useful features, but rarely reveal the real
Xdetails of the critically important advances. We will here
Xdescribe an effort underway (titled "GNU Chess") to create a more
Xopen and friendly environment of sharing.
X
XGNU Chess is part of Project GNU, a large-scale effort in which
Xthe philosophical goals are far-reaching. We will not go into any
Xgreat depth about these goals as they relate to the larger pro-
Xject, because these are described elsewhere [1]. However, we will
Xmention the basic issues and the changes we hope to encourage.
X
XThe start of the GNU Chess project was a natural result of the
Xexperiences gleaned in writing a chess program. While the author
Xwas at a progressive academic location [2], he was able to con-
Xceive the idea of a communal chess program only after much heart-
Xache. During the period of writing the initial version (which
Xhas since undergone many improvements and whole revisions), it
Xbecame clear that the best features and most useful hints, the
Xvery best of the heuristics, were hidden and difficult to find in
Xthe literature.
X
XSprinkled across many books, research papers, magazine articles,
Xaccumulated in the community, during the past 25 years, there was
Xliterally a void of true, empirical programs. Locating usable
Xprograms was difficult. Many programs were the result of academic
Xwork in "ivory towers", and hence were inaccessible to the common
Xman. Other programs were sequestered in research think-tanks. Na-
Xturally, developers of commercial programs carefully guarded
Xtheir source in order to protect their investment. On the other
Xhand, a few chess program source listings had actually been pub-
Xlished, but these were not really very strong, often written in a
Xnon-general language, and frequently more pedantic than practi-
Xcal.
X
XThe idea of a reasonably strong communal program solidified.
XWhen we refer to a communal program, we do not regard this as
Xpublic-domain software. Rather, we refer to a program which is
Xunder the shared authority of a number of individuals, the prin-
Xcipal contributors. These individuals have experienced and real-
Xized the positive results of a sharing community and the rapid
Ximprovements that come through contributing in such a community.
XFurther, these individuals devote time and energy to coordinating
Xthe contributions of other individuals. While they exercise a
Xcertain editorial right, this is usually not exercised arbitrari-
Xly; instead, a discussion is often undertaken.
X
XEventually, a working C program that played chess was available.
XThe coordinating institution for Project GNU, accepted our
Xsuggestion of inclusion of a chess program in the GNU distribu-
Xtion. Initial distribution of GNU Chess commenced in October of
X1986. Interest in the project increased rapidly.
X
XContributions came in from many places and people. Interfaces to
XX-windows and SUN-windows were donated, thus allowing very fancy
Xchess fonts on bit-mapped screens. Also, contributions involving
Xlarge portions of opening books such as MCO and collections of
Xmaster games were added to the distribution. Additionally,
Xtree-search modifications and heuristics were provided, and occa-
Xsionally even entire rewrites.
X
XThe program advanced in strength by several USCF class intervals
Xduring a period of less than one year. During this time, many
Xunusual features and enhancements were added to the program, usu-
Xally under the coordination of two or more people, with one work-
Xing in a distant-advisory capacity to the other. Frequently, gra-
Xduate students would give up significant time from their thesis
Xwork to devote energy to contributing. Their corporate counter-
Xparts would often give up project time to make their donation.
X
XContributors would often enter the project in a very forceful way
Xand then having made their contribution, learn the viability of
Xcommunal sharing once others had stepped in and contributed to
Xthem, thus providing considerable reinforcement. Frequently, con-
Xtributors would then go into "hibernation" for a long period of
Xtime, but most of them remained open to contributing and were
Xhelpful when asked to reprogram their particular contribution in
Xa more recent version.
X
XGNU Chess has made great strides in relatively little time. It
Xhas run on many different hardware architectures and has been
Xcompiled by a number of C compilers. A sampling of the com-
Xputers on which the program has run is: National 32032, Vax
X11/750, 8550, 8600, 8650, Motorola 68020, CCI 5/32, CCI 6/32
X(tahoe), Cray XMP, SUN Sparc-1.
X
XIt is our belief that GNU Chess will stimulate graduate research
Xin computer chess theory and practice. When students are able to
Xeasily obtain a state-of-the-art program in order to test out
Xtheir ideas, they will no longer need to reinvent the wheel. The
Xstudents will be able to investigate their research areas much
Xmore thoroughly, because they will spend more time on the specif-
Xic research areas they are concerned about. Basically, GNU Chess
X"frees up" time in order to get on to more fundamental issues.
X
XWe also feel that as other researchers gain trust in the GNU
XChess project, they will be more likely to release their results
Xdirectly and rapidly, through journal articles, or directly to
Xthe GNU project, and in fact become contributors and join the
Xpresent list. At the very least, a communal, ever-growing
Xprogram will encourage the few "closeted" researchers to be some-
Xwhat more open in their approach to disseminating advances.
X
XIn whatever form it takes, the progress toward elaboration of
Xmachine chess is ongoing, and we hope that GNU chess will be
Xhelpful to the community. Copies of GNU Chess source and "book",
Xas well as additional experimental code are available from the
XFree Software Foundation [3] or the author [6].
X
X
X[1] The GNU Manifesto, Richard Stallman, Free Software Foundation, Inc.
X
X[2] University of Southern California, Information Sciences Institute.
X
X[3] Free Software Foundation, Inc. 675 Massachusetts Ave.,
X Cambridge MA 02139.
X
X[4] Stuart Cracraft, P.O. Box 2841, Laguna Hills, California.
X 92654-2841., cracraft@wheaties.ai.mit.edu.
END_OF_FILE
if test 6615 -ne `wc -c <'doc/ARTICLE.2'`; then
echo shar: \"'doc/ARTICLE.2'\" unpacked with wrong size!
fi
# end of 'doc/ARTICLE.2'
fi
if test -f 'doc/MOVE-GEN' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'doc/MOVE-GEN'\"
else
echo shar: Extracting \"'doc/MOVE-GEN'\" \(3326 characters\)
sed "s/^X//" >'doc/MOVE-GEN' <<'END_OF_FILE'
XThis file contains a description of GNU's new move generation algoritm.
X Copyright (C) 1989 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
XNew move Generation algoritm:
X
XRevision: 1989-09-06
X
XAuthor: Hans Eric Sandstroem.
X
XThis algortim is the result of an attempt to make an hardware move
Xgenerator, but since I newer had the time and resources to build
Xthe hardware I wrote a software version and incorporated that one
Xinto gnuchess. This was the best way I could think of sharing this
Xalgorithm with the computer chess community.
X
XIf there is anybody out there with the time and rescources to build
Xa hardware move generator I will be glad to assist.
X
XThe general idea behind this algoritm is to pre calculate
Xa lot of data. The data that is pre calculated is every possible move
Xfor every piece from every square disregarding any other pieces on the
Xboard. This pre calculated data is stored in an array that looks like
Xthis:
X
Xstruct sqdata {
X short nextpos;
X short nextdir;
X};
Xstruct sqdata posdata[8][64][64];
X/* posdata[piecetype][fromsquare][destinationsquare] */
Xexample:
X the first move for a queen at e8 is stored at;
X posdata[queen][e8][e8].nextpos
X suppose this is e7 and e7 is occupied then the next move
X will be found in;
X posdata[queen][e8][e7].nextdir
X
XTo handle the differeces between white and black pawns (they move in
Xopposite directions) an array ptype has been introduced:
X
Xstatic const short ptype[2][8] = {
X no_piece,pawn,knight,bishop,rook,queen,king,no_piece,
X no_piece,bpawn,knight,bishop,rook,queen,king,no_piece};
X ^^^^^
XAnd it is used like this:
X piecetype = ptype[side][piece]
XWhen generating moves for pieces that are not black pawns, piece
Xcan be used directly in posdata. As in the example above.
X
XThus the only thing one has to do when generating the moves
Xis to check for collisions with other pieces.
Xthe move generation to do this looks like this: (for non pawns)
X p = posdata[piece][sq];
X u = p[sq].nextpos;
X do {
X if (color[u] == neutral) {
X LinkMove(ply,sq,u,xside);
X u = p[u].nextpos;
X }
X else {
X if (color[u] == xside) LinkMove(ply,sq,u,xside);
X u = p[u].nextdir;
X }
X } while (u != sq);
X
X - I`nt this just beautiful!
X
XThe array posdata is initialized in the routine Initialize_moves.
XThis routine is called just once and it works so no time has been spent
Xon the structure of this code. GenMoves and CaptureList generates the
Xmoves but the routines ataks, BRscan, Sqatakd, KingScan and trapped
Xalso relies on the move generation algoritm so they have also been
Xrewritten.
X
X
X
END_OF_FILE
if test 3326 -ne `wc -c <'doc/MOVE-GEN'`; then
echo shar: \"'doc/MOVE-GEN'\" unpacked with wrong size!
fi
# end of 'doc/MOVE-GEN'
fi
if test -f 'misc/gnuchess.lang' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'misc/gnuchess.lang'\"
else
echo shar: Extracting \"'misc/gnuchess.lang'\" \(6777 characters\)
sed "s/^X//" >'misc/gnuchess.lang' <<'END_OF_FILE'
X001:eng:{ pnbrqk}
X002:eng:{ PNBRQK}
X003:eng:{abcdefgh}
X004:eng:{12345678}
X005:eng:{o-o}
X006:eng:{o-o-o}
X007:eng:{0-0}
X008:eng:{0-0-0}
X009:eng:{wWbB}
X010:eng:{ score depth nodes time }
X011:eng:{ score depth nodes time\n}
X012:eng:{ }
X013:eng:{ }
X014:eng:{ %s\n}
X015:eng:{ a b c d e f g h}
X016:eng:{ h g f e d c b a}
X017:eng:{ -}
X018:eng:{ 1. 60 moves in 5 minutes}
X019:eng:{ 2. 60 moves in 15 minutes}
X020:eng:{ 3. 60 moves in 30 minutes}
X021:eng:{ 4. 40 moves in 30 minutes}
X022:eng:{ 5. 40 moves in 60 minutes}
X023:eng:{ 6. 40 moves in 120 minutes}
X024:eng:{ 7. 40 moves in 240 minutes}
X025:eng:{ 8. 1 move in 15 minutes}
X026:eng:{ 9. 1 move in 60 minutes}
X027:eng:{10. 1 move in 600 minutes}
X028:eng:{# Clear board\n}
X029:eng:{. Exit to main\n}
X030:eng:{/usr/games/lib/gnuchess.book}
X031:eng:{Abort? }
X032:eng:{Ambiguous Move!}
X033:eng:{Awindow}
X034:eng:{BAwindow= }
X035:eng:{BBwindow= }
X036:eng:{Beep: %-12s Transposition file: %s\n}
X037:eng:{Black %s White %s %d\n}
X038:eng:{Bwindow: }
X039:eng:{Bwindow}
X040:eng:{CHESS command summary\n}
X041:eng:{CHESS}
X042:eng:{Castled White %s Black %s\n}
X043:eng:{Chess\n}
X044:eng:{Computer mates!}
X045:eng:{Computer will soon mate!}
X046:eng:{Computer: %-12s Opponent: %s\n}
X047:eng:{Computer: %s}
X048:eng:{Could not open file}
X049:eng:{Counting transposition file entries, wait!\n}
X050:eng:{Create failed for %s\n}
X051:eng:{Depth: %-12d Response time: %d sec\n}
X052:eng:{Depth: %d}
X053:eng:{Depth= %d%c }
X054:eng:{Draw %s\n}
X055:eng:{DrawPiece: color[sq] err}
X056:eng:{Drawn game! %s}
X057:eng:{Drawn game!\n}
X058:eng:{Drawn game!}
X059:eng:{Easy mode: %s}
X060:eng:{Editing: %s}
X061:eng:{Enter #moves #minutes: }
X062:eng:{Enter Level: }
X063:eng:{Enter file name: }
X064:eng:{Enter piece & location: }
X065:eng:{Enter piece: }
X066:eng:{Filling transposition file, wait!\n}
X067:eng:{GNU Chess display (MS-DOS, Mar 90)}
X068:eng:{GNU Chess display (Nov 89)}
X069:eng:{GNU Chess}
X070:eng:{Game saved}
X071:eng:{Hin/Hout/Tcol/Coll/Fin/Fout = %ld/%ld/%ld/%ld/%ld/%ld\n}
X072:eng:{Hint: %s\n}
X073:eng:{Hit <RET> to return: }
X074:eng:{Human}
X075:eng:{Illegal move (no matching move)%s\n}
X076:eng:{Illegal move (no matching move)}
X077:eng:{Illegal move..(in check)}
X078:eng:{Illegal move\n}
X079:eng:{Level: %ld}
X080:eng:{Max Moves}
X081:eng:{Max Tree= %5d}
X082:eng:{MoveLimit= }
X083:eng:{My move is: %s\n}
X084:eng:{My move is: %s}
X085:eng:{Testing Eval Speed}
X086:eng:{Nf3 move knight to f3 beep turn %s\n}
X087:eng:{No moves}
X088:eng:{No pieces}
X089:eng:{Nodes %ld Tree %d Eval %ld Rate %ld RS hi %ld lo %ld \n}
X090:eng:{Nodes= %8ld, Nodes/Sec= %5ld}
X091:eng:{Nodes= %ld Nodes/sec= %ld\n}
X092:eng:{OFF}
X093:eng:{ON}
X094:eng:{Operator time(hundredths)= }
X095:eng:{Opponent mates!}
X096:eng:{Opponent will soon mate!}
X097:eng:{Opponent: %s}
X098:eng:{Playing without hashfile}
X099:eng:{Random: %-12s Easy mode: %s\n}
X100:eng:{Random: %s}
X101:eng:{Repetition}
X102:eng:{Gnuchess version %s patchlevel %s\n}
X103:eng:{S=%d m%d p%d ps%d ss%d m%d p%d ps%d ss%d}
X104:eng:{Score= %d}
X105:eng:{Score}
X106:eng:{Setup successful\n}
X107:eng:{Testing CaptureList Speed}
X108:eng:{Testing MoveList Speed}
X109:eng:{The file contains %d entries out of max %d\n}
X110:eng:{Time Control %s %d moves %d sec %d opr %d depth\n}
X111:eng:{TimeControl %d Operator Time %d\n}
X112:eng:{Transposition table: %s}
X113:eng:{Usage: Gnuchess [-a] [-t] [-c size] [-s savefile][-l listfile] [-x xwndw]\n}
X114:eng:{WAwindow= }
X115:eng:{WBwindow= }
X116:eng:{White %d:%02d Black %d:%02d\n}
X117:eng:{White Clock %ld Moves %ld\nBlack Clock %d Moves %d\n\n}
X118:eng:{White}
X119:eng:{Black}
X120:eng:{Wwindow: }
X121:eng:{Your move is? }
X122:eng:{\n }
X123:eng:{\nMove# %d Target= %ld Clock: %ld\n}
X124:eng:{\nYour move is? }
X125:eng:{\n\n}
X126:eng:{\nmove score depth nodes time flags capture color\n}
X127:eng:{\n}
X128:eng:{a7a8q promote pawn to queen material turn %s\n}
X129:eng:{alg}
X130:eng:{bd redraw board reverse board display\n}
X131:eng:{bd}
X132:eng:{beep}
X133:eng:{black}
X134:eng:{book}
X135:eng:{both}
X136:eng:{c Change sides\n}
X137:eng:{chess.000}
X138:eng:{chess.lst.%d}
X139:eng:{computer mates!\n}
X140:eng:{computer will soon mate!\n}
X141:eng:{computer}
X142:eng:{contempt= }
X143:eng:{contempt}
X144:eng:{coords show coords rv reverse video\n}
X145:eng:{coords}
X146:eng:{debuglevel= }
X147:eng:{debuglevel}
X148:eng:{debug}
X149:eng:{depth set search depth clock set time control\n}
X150:eng:{depth= }
X151:eng:{depth}
X152:eng:{easy}
X153:eng:{edit edit board force enter game moves\n}
X154:eng:{edit}
X155:eng:{enter piece & location: \n}
X156:eng:{first}
X157:eng:{force}
X158:eng:{g1f3 move from g1 to f3 quit Exit Chess\n}
X159:eng:{game file= }
X160:eng:{get}
X161:eng:{gnuchess 4p%s game\n}
X162:eng:{go}
X163:eng:{hashdepth= }
X164:eng:{hashdepth}
X165:eng:{hash}
X166:eng:{help}
X167:eng:{hint suggest a move post turn %s principle variation\n}
X168:eng:{hint}
X169:eng:{level}
X170:eng:{list game to chess.lst book turn %s used %d of %d\n}
X171:eng:{list}
X172:eng:{new}
X173:eng:{o-o castle king side easy turn %s\n}
X174:eng:{o-o-o castle queen side hash turn %s\n}
X175:eng:{opponent mates!\n}
X176:eng:{opponent will soon mate!\n}
X177:eng:{post principle variation hint suggest a move\n}
X178:eng:{post}
X179:eng:{p}
X180:eng:{quit}
X181:eng:{random randomize play new start new game\n}
X182:eng:{random}
X183:eng:{rcptr}
X184:eng:{remove}
X185:eng:{reverse}
X186:eng:{rv}
X187:eng:{r}
X188:eng:{save game to file get game from file\n}
X189:eng:{save}
X190:eng:{setup}
X191:eng:{set}
X192:eng:{shade toggle shade black stars toggle stars\n}
X193:eng:{stars}
X194:eng:{switch sides with computer both computer match\n}
X195:eng:{switch}
X196:eng:{test}
X197:eng:{time}
X198:eng:{try }
X199:eng:{ttable collision detected}
X200:eng:{undo undo last ply remove take back a move\n}
X201:eng:{undo}
X202:eng:{white computer plays white black computer plays black\n}
X203:eng:{white}
X204:eng:{w}
X205:eng:{xboard.position.read}
X206:eng:{xboard}
X207:eng:{xget}
X208:eng:{xwndw= }
X209:eng:{xwndw}
X210:eng:{yes}
X211:eng:{Illegal move in book %d %s %s}
X212:eng:{Warning can't find book.}
X213:eng:{Book used %d of %d entries.}
X214:eng:{true}
X215:eng:{false}
X216:eng:{exit}
X217:eng:{clock}
X218:eng:{Computer}
X219:eng:{Open failure for file: %s}
X220:eng:{Time Control Error}
X221:eng:{material}
X222:eng:{time %d %d}
X223:eng:{I have no idea}
X224:eng:{Not Enough Material}
END_OF_FILE
if test 6777 -ne `wc -c <'misc/gnuchess.lang'`; then
echo shar: \"'misc/gnuchess.lang'\" unpacked with wrong size!
fi
# end of 'misc/gnuchess.lang'
fi
if test -f 'src/book.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/book.c'\"
else
echo shar: Extracting \"'src/book.c'\" \(8155 characters\)
sed "s/^X//" >'src/book.c' <<'END_OF_FILE'
X/*
X * book.c - C source for GNU CHESS
X *
X * Copyright (c) 1988,1989,1990 John Stanback
X * Copyright (c) 1992 Free Software Foundation
X *
X * This file is part of GNU CHESS.
X *
X * GNU Chess is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2, or (at your option)
X * any later version.
X *
X * GNU Chess is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with GNU Chess; see the file COPYING. If not, write to
X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
X */
X
X#include "gnuchess.h"
Xextern char mvstr[4][6];
Xshort bookcount = 0;
Xstatic struct bookentry
X{
X unsigned long bookkey;
X unsigned long bookbd;
X unsigned short bmove;
X unsigned short hint;
X unsigned char count;
X unsigned char flags;
X} OpenBook[BOOKSIZE];
Xstatic struct bookentry *BookTable[BKTBLSIZE];
Xvoid
XGetOpenings (void)
X
X/*
X * Read in the Opening Book file and parse the algebraic notation for a move
X * into an unsigned integer format indicating the from and to square. Create
X * a linked list of opening lines of play, with entry->next pointing to the
X * next line and entry->move pointing to a chunk of memory containing the
X * moves. More Opening lines of up to 100 half moves may be added to
X * gnuchess.book.
X */
X#ifndef BOOK
X#define BOOK "/usr/games/lib/gnuchess.book"
X#endif /* BOOK */
X{
X FILE *fd;
X register struct bookentry *OB, *OC;
X register short int i, f, t;
X char opening[80];
X char msg[80];
X short int xside, doit, c, side;
X short int rf, rt;
X unsigned short mv;
X
X
X for (OB = OpenBook; OB < &OpenBook[BOOKSIZE]; OB++)
X OB->count = 0;
X for (i = 0; i < BKTBLSIZE; i++)
X {
X BookTable[i] = &OpenBook[BOOKSIZE / BKTBLSIZE * i];
X }
X if ((fd = fopen (BOOK, "r")) == NULL)
X fd = fopen ("gnuchess.book", "r");
X if (fd != NULL)
X {
X OC = NULL;
X /* setvbuf(fd,buffr,_IOFBF,2048); */
X side = white;
X xside = black;
X hashbd = hashkey = 0;
X for (i = 0; i < 64; i++)
X {
X board[i] = Stboard[i];
X color[i] = Stcolor[i];
X }
X i = 0;
X
X while ((c = parse (fd, &mv, side, opening)) >= 0)
X if (c == 1)
X {
X
X /*
X * if not first move of an opening and first time we have
X * seen it save next move as hint
X */
X if (i && OB->count == 1)
X OB->hint = mv & 0x3f3f;
X OC = OB; /* save for end marking */
X doit = true;
X
X /*
X * see if this position and move already exist from some
X * other opening
X */
X /* is this ethical, to offer the bad move as a hint????? */
X for (OB = BookTable[hashkey & BOOKMASK]; OB->count; OB++)
X {
X if (OB->bookkey == hashkey
X && OB->bookbd == hashbd
X && (OB->flags & SIDEMASK) == side
X && OB->bmove == mv)
X {
X
X /*
X * yes so just bump count - count is used to choose
X * opening move in proportion to its presence in the
X * book
X */
X doit = false;
X OB->count++;
X break;
X }
X /* Book is hashed into BKTBLSIZE chunks based on hashkey */
X if (OB == &OpenBook[BOOKSIZE - 1])
X OB = OpenBook;
X }
X /* doesn`t exist so add it to the book */
X if (doit)
X {
X bookcount++;
X OB->bookkey = hashkey;
X OB->bookbd = hashbd;
X OB->bmove = mv;
X OB->hint = 0;
X OB->count = 1;
X OB->flags = side;
X }
X /* now update the board and hash values */
X /* should really check the moves as we do this, but??? */
X f = mv >> 8 & 0x3F;
X t = mv & 0x3F;
X if (board[t] != no_piece)
X {
X if (color[t] != xside)
X {
X algbr (f, t, false);
X sprintf (msg, CP[211], i + 1, mvstr, opening);
X ShowMessage (msg);
X }
X UpdateHashbd (xside, board[t], -1, t);
X }
X if (board[f] == no_piece || color[f] != side)
X {
X algbr (f, t, false);
X sprintf (msg, CP[211], i + 1, mvstr, opening);
X ShowMessage (msg);
X }
X UpdateHashbd (side, board[f], f, t);
X board[t] = board[f];
X color[t] = color[f];
X color[f] = neutral;
X board[f] = no_piece;
X if ((board[t] == king) && ((mv == BLACKCASTLE) || (mv == WHITECASTLE) || (mv == LONGBLACKCASTLE) || (mv == LONGWHITECASTLE)))
X {
X
X if (t > f)
X {
X rf = f + 3;
X rt = t - 1;
X }
X else
X {
X rf = f - 4;
X rt = t + 1;
X }
X board[rt] = rook;
X color[rt] = side;
X board[rf] = no_piece;
X color[rf] = neutral;
X UpdateHashbd (side, rook, rf, rt);
X }
X i++;
X xside = side;
X side = side ^ 1;
X }
X else if (c == 0 && i > 0)
X {
X /* Mark last move as end of an opening */
X /* might want to terminate? */
X OB->flags |= BOOKEND;
X if (i > 1)
X OC->flags |= BOOKEND;
X /* reset for next opening */
X side = white;
X hashbd = hashkey = 0;
X for (i = 0; i < 64; i++)
X {
X board[i] = Stboard[i];
X color[i] = Stcolor[i];
X }
X i = 0;
X
X }
X fclose (fd);
X#if !defined CHESSTOOL && !defined XBOARD
X sprintf (msg, CP[213], bookcount, BOOKSIZE);
X ShowMessage (msg);
X#endif
X /* set every thing back to start game */
X Book = BOOKFAIL;
X for (i = 0; i < 64; i++)
X {
X board[i] = Stboard[i];
X color[i] = Stcolor[i];
X }
X }
X else
X {
X#if !defined CHESSTOOL && !defined XBOARD
X ShowMessage (CP[212]);
X#endif
X Book = 0;
X }
X}
X
X
Xint
XOpeningBook (unsigned short *hint, short int side)
X
X/*
X * Go thru each of the opening lines of play and check for a match with the
X * current game listing. If a match occurs, generate a random number. If this
X * number is the largest generated so far then the next move in this line
X * becomes the current "candidate". After all lines are checked, the
X * candidate move is put at the top of the Tree[] array and will be played by
X * the program. Note that the program does not handle book transpositions.
X */
X
X{
X short pnt;
X unsigned short m;
X unsigned r, cnt, tcnt, ccnt;
X register struct bookentry *OB, *OC;
X int possibles = TrPnt[2] - TrPnt[2];
X
X srand ((unsigned int) time ((long *) 0));
X m = 0;
X cnt = 0;
X tcnt = 0;
X ccnt = 0;
X OC = NULL;
X
X
X /*
X * find all the moves for this position - count them and get their total
X * count
X */
X for (OB = BookTable[hashkey & BOOKMASK]; OB->count; OB++)
X {
X if (OB->bookkey == hashkey
X && OB->bookbd == hashbd
X && ((OB->flags) & SIDEMASK) == side)
X {
X if (OB->bmove & BADMOVE)
X {
X m = OB->bmove ^ BADMOVE;
X /* is the move is in the MoveList */
X for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
X {
X if (((Tree[pnt].f << 8) | Tree[pnt].t) == m)
X {
X if (--possibles)
X {
X Tree[pnt].score = DONTUSE;
X break;
X }
X }
X }
X
X }
X else
X {
X OC = OB;
X cnt++;
X tcnt += OB->count;
X }
X }
X }
X /* if only one just do it */
X if (cnt == 1)
X {
X m = OC->bmove;
X }
X else
X /* more than one must choose one at random */
X if (cnt > 1)
X {
X /* pick a number */
X r = urand () % 1000;
X
X for (OC = BookTable[hashkey & BOOKMASK]; OC->count; OC++)
X {
X if (OC->bookkey == hashkey
X && OC->bookbd == hashbd
X && ((OC->flags) & SIDEMASK) == side
X && !(OC->bmove & BADMOVE))
X {
X ccnt += OC->count;
X if (((ccnt * BOOKRAND) / tcnt) >= r)
X {
X m = OC->bmove;
X break;
X }
X }
X }
X }
X else
X {
X /* none decrement count of no finds */
X Book--;
X return false;
X }
X /* make sure the move is in the MoveList */
X for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
X {
X if (((Tree[pnt].f << 8) | Tree[pnt].t) == m)
X {
X Tree[pnt].score = 0;
X break;
X }
X }
X /* Make sure its the best */
X
X pick (TrPnt[1], TrPnt[2] - 1);
X if (Tree[TrPnt[1]].score)
X {
X /* no! */
X Book--;
X return false;
X }
X /* ok pick up the hint and go */
X *hint = OC->hint;
X Book = ((OC->flags & BOOKEND) && ((urand () % 1000) > BOOKENDPCT)) ? 0 : BOOKFAIL;
X return true;
X}
END_OF_FILE
if test 8155 -ne `wc -c <'src/book.c'`; then
echo shar: \"'src/book.c'\" unpacked with wrong size!
fi
# end of 'src/book.c'
fi
if test -f 'src/genmoves.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/genmoves.c'\"
else
echo shar: Extracting \"'src/genmoves.c'\" \(7906 characters\)
sed "s/^X//" >'src/genmoves.c' <<'END_OF_FILE'
X/*
X * genmoves.c - C source for GNU CHESS
X *
X * Copyright (c) 1988,1989,1990 John Stanback
X * Copyright (c) 1992 Free Software Foundation
X *
X * This file is part of GNU CHESS.
X *
X * GNU Chess is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2, or (at your option)
X * any later version.
X *
X * GNU Chess is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with GNU Chess; see the file COPYING. If not, write to
X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
X */
X#include "gnuchess.h"
Xshort *TrP;
X
X#define Link(from,to,flag,s) \
X{\
X node->f = from; node->t = to;\
X node->reply = 0;\
X node->flags = flag;\
X node->score = s;\
X ++node;\
X *TrP += 1;\
X }
X
Xinline void
XLinkMove (short int ply, short int f,
X short int t,
X short int flag,
X short int xside)
X
X/*
X * Add a move to the tree. Assign a bonus to order the moves as follows: 1.
X * Principle variation 2. Capture of last moved piece 3. Other captures
X * (major pieces first) 4. Killer moves 5.
X */
X
X{
X register short s;
X#if !defined NOHISTORY
X register short z;
X#endif
X register unsigned short mv;
X register struct leaf *node;
X
X node = &Tree[*TrP];
X mv = (f << 8) | t;
X#if defined NOHISTORY
X s = killt[mv | sidebit];
X#else
X z = (f << 6) | t;
X if (xside == white)
X z |= 0x1000;
X s = history[z];
X#endif
X if (color[t] != neutral)
X {
X /* TOsquare is the square the last piece moved moved to */
X s += value[board[t]] - board[f] + ((t == TOsquare) ? 500 : 0);
X }
X if (board[f] == pawn)
X if (row (t) == 0 || row (t) == 7)
X {
X flag |= promote;
X s += 800;
X#if !defined OLDXBOARD && !defined GNU3 && !defined CHESSTOOL
X Link (f, t, flag | queen, s - 20000);
X s -= 200;
X Link (f, t, flag | knight, s - 20000);
X s -= 50;
X Link (f, t, flag | rook, s - 20000);
X flag |= bishop;
X s -= 50;
X#else
X flag |= queen;
X#endif
X }
X else if (row (t) == 1 || row (t) == 6)
X {
X flag |= pwnthrt;
X s += 600;
X }
X else if ((row (t) == 2 || row (t) == 5) && (ply > MINDEPTH) && (ply < Sdepth+3))
X {
X if ((mtl[white] - pmtl[white] + mtl[black] - pmtl[black]) < PTVALUE)
X {
X flag |= pwnthrt;
X s += 400;
X }
X }
X Link (f, t, flag, s - 20000);
X}
X
Xinline
Xvoid
XGenMoves (register short int ply, register short int sq, short int side, short int xside)
X
X/*
X * Generate moves for a piece. The moves are taken from the precalulated
X * array nextpos/nextdir. If the board is free, next move is choosen from
X * nextpos else from nextdir.
X */
X
X{
X register short u, piece;
X register unsigned char *ppos, *pdir;
X
X TrP = &TrPnt[ply + 1];
X piece = board[sq];
X ppos = nextpos[ptype[side][piece]][sq];
X pdir = nextdir[ptype[side][piece]][sq];
X if (piece == pawn)
X {
X u = ppos[sq]; /* follow no captures thread */
X if (color[u] == neutral)
X {
X LinkMove (ply, sq, u, 0, xside);
X u = ppos[u];
X if (color[u] == neutral)
X LinkMove (ply, sq, u, 0, xside);
X }
X u = pdir[sq]; /* follow captures thread */
X if (color[u] == xside)
X LinkMove (ply, sq, u, capture, xside);
X u = pdir[u];
X if (color[u] == xside)
X LinkMove (ply, sq, u, capture, xside);
X }
X else
X {
X u = ppos[sq];
X do
X {
X if (color[u] == neutral)
X {
X LinkMove (ply, sq, u, 0, xside);
X u = ppos[u];
X }
X else
X {
X if (color[u] == xside)
X LinkMove (ply, sq, u, capture, xside);
X u = pdir[u];
X }
X } while (u != sq);
X }
X}
X
Xvoid
XMoveList (short int side, register short int ply)
X
X/*
X * Fill the array Tree[] with all available moves for side to play. Array
X * TrPnt[ply] contains the index into Tree[] of the first move at a ply.
X */
X
X{
X register short i, xside, f;
X
X xside = side ^ 1;
X TrP = &TrPnt[ply + 1];
X *TrP = TrPnt[ply];
X if (!PV)
X Swag0 = killr0[ply];
X Swag1 = killr1[ply];
X Swag2 = killr2[ply];
X Swag3 = killr3[ply];
X if (ply > 2)
X Swag4 = killr1[ply - 2];
X sidebit = ((side == white) ? 0 : 0x80);
X killt[SwagHt | sidebit] += 5000;
X killt[Swag0 | sidebit] += 2000;
X killt[Swag1 | sidebit] += 60;
X killt[Swag2 | sidebit] += 50;
X killt[Swag3 | sidebit] += 40;
X killt[Swag4 | sidebit] += 30;
X for (i = PieceCnt[side]; i >= 0; i--)
X GenMoves (ply, PieceList[side][i], side, xside);
X if (!castld[side])
X {
X f = PieceList[side][0];
X if (castle (side, f, f + 2, 0))
X {
X LinkMove (ply, f, f + 2, cstlmask, xside);
X }
X if (castle (side, f, f - 2, 0))
X {
X LinkMove (ply, f, f - 2, cstlmask, xside);
X }
X }
X if (epsquare > 0)
X {
X f = epmove1[epsquare];
X if (color[f] == side && board[f] == pawn)
X LinkMove (ply, f, epsquare, capture | epmask, xside);
X f = epmove2[epsquare];
X if (color[f] == side && board[f] == pawn)
X LinkMove (ply, f, epsquare, capture | epmask, xside);
X }
X killt[SwagHt | sidebit] -= 5000;
X killt[Swag0 | sidebit] -= 2000;
X killt[Swag1 | sidebit] -= 60;
X killt[Swag2 | sidebit] -= 50;
X killt[Swag3 | sidebit] -= 40;
X killt[Swag4 | sidebit] -= 30;
X SwagHt = 0; /* SwagHt is only used once */
X}
X
Xvoid
XCaptureList (register short int side, short int ply)
X
X/*
X * Fill the array Tree[] with all available cature and promote moves for side
X * to play. Array TrPnt[ply] contains the index into Tree[] of the first move
X * at a ply.
X */
X
X{
X register short u, sq, xside;
X register struct leaf *node;
X register unsigned char *ppos, *pdir;
X short i, piece, *PL, r7;
X
X xside = side ^ 1;
X TrP = &TrPnt[ply + 1];
X *TrP = TrPnt[ply];
X node = &Tree[*TrP];
X r7 = rank7[side];
X PL = PieceList[side];
X sidebit = ((side == white) ? 0 : 0x80);
X killt[SwagHt | sidebit] += 5000;
X killt[Swag0 | sidebit] += 2000;
X killt[Swag1 | sidebit] += 60;
X killt[Swag2 | sidebit] += 50;
X killt[Swag3 | sidebit] += 40;
X killt[Swag4 | sidebit] += 30;
X for (i = 0; i <= PieceCnt[side]; i++)
X {
X sq = PL[i];
X piece = board[sq];
X if (sweep[piece])
X {
X ppos = nextpos[piece][sq];
X pdir = nextdir[piece][sq];
X u = ppos[sq];
X do
X {
X if (color[u] == neutral)
X u = ppos[u];
X else
X {
X if (color[u] == xside)
X Link (sq, u, capture, value[board[u]] + svalue[board[u]] - piece);
X u = pdir[u];
X }
X } while (u != sq);
X }
X else
X {
X pdir = nextdir[ptype[side][piece]][sq];
X if (piece == pawn && row (sq) == r7)
X {
X u = pdir[sq];
X if (color[u] == xside)
X Link (sq, u, capture | promote | queen, valueQ);
X u = pdir[u];
X if (color[u] == xside)
X {
X Link (sq, u, capture | promote | queen, valueQ);
X#if defined OLDXBOARD || defined GNU3 || defined CHESSTOO
X Link (sq, u, promote | knight, valueN);
X Link (sq, u, promote | rook, valueR);
X Link (sq, u, promote | bishop, valueB);
X#endif
X }
X ppos = nextpos[ptype[side][piece]][sq];
X u = ppos[sq]; /* also generate non capture promote */
X if (color[u] == neutral)
X {
X Link (sq, u, promote | queen, valueQ);
X#if defined OLDXBOARD || defined GNU3 || defined CHESSTOO
X Link (sq, u, promote | knight, valueN);
X Link (sq, u, promote | rook, valueR);
X Link (sq, u, promote | bishop, valueB);
X#endif
X }
X }
X else
X {
X u = pdir[sq];
X do
X {
X if (color[u] == xside)
X Link (sq, u, capture, value[board[u]] + svalue[board[u]] - piece);
X u = pdir[u];
X } while (u != sq);
X }
X }
X }
X killt[SwagHt | sidebit] -= 5000;
X killt[Swag0 | sidebit] -= 2000;
X killt[Swag1 | sidebit] -= 60;
X killt[Swag2 | sidebit] -= 50;
X killt[Swag3 | sidebit] -= 40;
X killt[Swag4 | sidebit] -= 30;
X SwagHt = 0; /* SwagHt is only used once */
X}
END_OF_FILE
if test 7906 -ne `wc -c <'src/genmoves.c'`; then
echo shar: \"'src/genmoves.c'\" unpacked with wrong size!
fi
# end of 'src/genmoves.c'
fi
if test -f 'src/main.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/main.c'\"
else
echo shar: Extracting \"'src/main.c'\" \(8946 characters\)
sed "s/^X//" >'src/main.c' <<'END_OF_FILE'
X/*
X * main.c - C source for GNU CHESS
X *
X * Copyright (c) 1988,1989,1990 John Stanback
X * Copyright (c) 1992 Free Software Foundation
X *
X * This file is part of GNU CHESS.
X *
X * GNU Chess is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2, or (at your option)
X * any later version.
X *
X * GNU Chess is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with GNU Chess; see the file COPYING. If not, write to
X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
X */
X
X#include "version.h"
X#include "gnuchess.h"
X#include <signal.h>
Xchar *ColorStr[2];
Xchar *CP[CPSIZE];
X/*
X * In a networked enviroment gnuchess might be compiled on different hosts
X * with different random number generators, that is not acceptable if they
X * are going to share the same transposition table.
X */
Xunsigned long int next = 1;
X
Xunsigned int
Xurand (void)
X{
X next *= 1103515245;
X next += 12345;
X return ((unsigned int) (next >> 16) & 0xFFFF);
X}
X
Xvoid
Xsrand (unsigned int seed)
X{
X next = seed;
X}
X
Xunsigned long hashkey, hashbd;
Xstruct hashval hashcode[2][7][64];
X
X#ifdef ttblsz
Xstruct hashentry huge ttable[2][vttblsz + MAXrehash];
Xunsigned int ttblsize;
X#endif
X
X
Xchar savefile[128] = "";
Xchar listfile[128] = "";
X#if !defined NOHISTORY
Xunsigned char history[8192];
X#endif
Xshort rpthash[2][256];
Xstruct leaf Tree[TREE], *root;
Xshort TrPnt[MAXDEPTH];
Xshort PieceList[2][64], PawnCnt[2][8];
Xshort castld[2], Mvboard[64];
Xshort svalue[64];
Xstruct flags flag;
Xshort opponent, computer, WAwindow, WBwindow, BAwindow, BBwindow, dither, INCscore;
Xlong ResponseTime, ExtraTime, Level, et, et0, time0, ft;
Xlong NodeCnt, ETnodes, EvalNodes, HashCnt, HashAdd, FHashCnt, FHashAdd, HashCol,
X THashCol, filesz;
Xlong replus, reminus;
Xshort HashDepth = HASHDEPTH, HashMoveLimit = HASHMOVELIMIT;
Xshort player, xwndw, rehash;
Xstruct GameRec GameList[MAXMOVES + MAXDEPTH];
Xshort Sdepth, GameCnt, Game50, MaxSearchDepth;
Xshort epsquare, contempt;
Xint Book;
Xstruct TimeControlRec TimeControl;
Xshort TCflag, TCmoves, TCminutes, TCseconds, OperatorTime;
Xshort XCmoves[3], XCminutes[3], XCseconds[3], XC, XCmore;
Xconst short otherside[3] =
X{black, white, neutral};
Xunsigned short hint;
Xshort int TOflag; /* force search re-init if we backup search */
X
Xshort mtl[2], pmtl[2], hung[2];
Xshort Pindex[64];
Xshort PieceCnt[2];
Xshort FROMsquare, TOsquare;
Xshort HasKnight[2], HasBishop[2], HasRook[2], HasQueen[2];
Xshort ChkFlag[MAXDEPTH], CptrFlag[MAXDEPTH], PawnThreat[MAXDEPTH];
Xshort Pscore[MAXDEPTH], Tscore[MAXDEPTH];
Xconst short qrook[3] =
X{0, 56, 0};
Xconst short krook[3] =
X{7, 63, 0};
Xconst short kingP[3] =
X{4, 60, 0};
Xconst short rank7[3] =
X{6, 1, 0};
Xconst short sweep[8] =
X{false, false, false, true, true, true, false, false};
Xunsigned short killr0[MAXDEPTH], killr1[MAXDEPTH];
Xunsigned short killr2[MAXDEPTH], killr3[MAXDEPTH];
Xunsigned short PV, SwagHt, Swag0, Swag1, Swag2, Swag3, Swag4, sidebit;
Xshort killt[0x4000];
Xconst short value[7] =
X{0, valueP, valueN, valueB, valueR, valueQ, valueK};
Xconst short control[7] =
X{0, ctlP, ctlN, ctlB, ctlR, ctlQ, ctlK};
Xshort stage, stage2, Developed[2];
XFILE *hashfile;
Xunsigned int starttime;
Xshort int ahead = true, hash = true;
X
X/* hmm.... shouldn`t main be moved to the interface routines */
Xint
Xmain (int argc, char **argv)
X{
X char *xwin = 0;
X char *Lang = NULL;
X srand (starttime = ((unsigned int) time ((long *) 0))); /* init urand */
X#ifdef ttblsz
X ttblsize = ttblsz;
X rehash = -1;
X#endif /* ttblsz */
X if (argc > 2)
X {
X if (argv[1][0] == '-' && argv[1][1] == 'L')
X {
X Lang = argv[2];
X argv += 2;
X argc -= 2;
X }
X }
X InitConst (Lang);
X ColorStr[0] = CP[118];
X ColorStr[1] = CP[119];
X
X while (argc > 1 && ((argv[1][0] == '-') || (argv[1][0] == '+')))
X {
X switch (argv[1][1])
X {
X case 'a':
X ahead = ((argv[1][0] == '-') ? false : true);
X break;
X case 'h':
X hash = ((argv[1][0] == '-') ? false : true);
X break;
X case 's':
X argc--;
X argv++;
X if (argc > 1)
X strcpy (savefile, argv[1]);
X break;
X case 'l':
X argc--;
X argv++;
X if (argc > 1)
X strcpy (listfile, argv[1]);
X break;
X
X#if ttblsz
X case 'r':
X if (argc > 2)
X rehash = atoi (argv[2]);
X argc--;
X argv++;
X if (rehash > MAXrehash)
X rehash = MAXrehash;
X break;
X case 'T':
X if (argc > 2)
X ttblsize = atoi (argv[2]);
X argc--;
X argv++;
X if (ttblsize > 0 && ttblsize < 24)
X ttblsize = (1 << ttblsize);
X else
X ttblsize = ttblsz;
X break;
X#ifdef HASHFILE
X case 't': /* create or test persistent transposition
X * table */
X hashfile = fopen (HASHFILE, RWA_ACC);
X if (hashfile)
X {
X fseek (hashfile, 0L, SEEK_END);
X filesz = (ftell (hashfile) / sizeof (struct fileentry)) - 1;
X }
X if (hashfile != NULL)
X {
X long i, j;
X int nr[MAXDEPTH];
X struct fileentry n;
X
X printf (CP[49]);
X for (i = 0; i < MAXDEPTH; i++)
X nr[i] = 0;
X fseek (hashfile, 0L, SEEK_END);
X i = ftell (hashfile) / sizeof (struct fileentry);
X fseek (hashfile, 0L, SEEK_SET);
X for (j = 0; j < i + 1; j++)
X {
X fread (&n, sizeof (struct fileentry), 1, hashfile);
X if (n.depth)
X {
X nr[n.depth]++;
X nr[0]++;
X }
X }
X printf (CP[109],
X nr[0], i);
X for (j = 1; j < MAXDEPTH; j++)
X printf ("%d ", nr[j]);
X printf ("\n");
X }
X return 0;
X case 'c': /* create or test persistent transposition
X * table */
X if (argc > 2)
X filesz = atoi (argv[2]);
X if (filesz > 0 && filesz < 24)
X filesz = (1 << filesz) - 1 + MAXrehash;
X else
X filesz = Deffilesz + MAXrehash;
X if ((hashfile = fopen (HASHFILE, RWA_ACC)) == NULL)
X hashfile = fopen (HASHFILE, WA_ACC);
X if (hashfile != NULL)
X {
X long j;
X struct fileentry n;
X
X printf (CP[66]);
X for (j = 0; j < 32; j++)
X n.bd[j] = 0;
X n.f = n.t = 0;
X n.flags = 0;
X n.depth = 0;
X n.sh = n.sl = 0;
X for (j = 0; j < filesz + 1; j++)
X fwrite (&n, sizeof (struct fileentry), 1, hashfile);
X fclose (hashfile);
X }
X else
X printf (CP[50], HASHFILE);
X return (0);
X#endif /* HASHFILE */
X#endif /* ttblsz */
X case 'x':
X xwin = &argv[1][2];
X break;
X case 'v':
X fprintf (stderr, CP[102], version, patchlevel);
X exit ();
X default:
X fprintf (stderr, CP[103]);
X exit ();
X }
X argv++;
X argc--;
X }
X XC = 0;
X Level = 0;
X#if defined CHESSTOOL || defined XBOARD
X signal (SIGTERM, ExitChess);
X TCflag = true;
X TCmoves = 40;
X TCminutes = 120;
X TCseconds = 0;
X OperatorTime = 0;
X#else
X TCflag = false;
X OperatorTime = 0;
X#endif
X if (argc == 2)
X {
X if (argv[1][0] == ':')
X {
X TCseconds = atoi (&argv[1][1]);
X if (TCseconds)
X {
X TCflag = true;
X TCmoves = 1;
X TCminutes = 0;
X }
X }
X else
X {
X Level = MaxSearchDepth = atoi (argv[1]);
X if (Level > MAXDEPTH)
X Level = MaxSearchDepth = MAXDEPTH;
X }
X }
X if (argc >= 3)
X {
X char *p;
X if (argc > 9)
X {
X printf ("%s\n", CP[220]);
X exit ();
X }
X TCmoves = atoi (argv[1]);
X TCminutes = strtol (argv[2], &p, 10);
X if (*p == ':')
X TCseconds = strtol (p + 1, (char **) NULL, 10);
X else
X TCseconds = 0;
X TCflag = true;
X argc -= 3;
X argv += 3;
X while (argc > 1)
X {
X XCmoves[XC] = atoi (argv[0]);
X XCminutes[XC] = strtol (argv[1], &p, 10);
X if (*p == ':')
X XCseconds[XC] = strtol (p + 1, (char **) NULL, 10);
X else
X XCseconds[XC] = 0;
X if (XCmoves[XC] && (XCminutes[XC] || XCseconds[XC]))
X XC++;
X else
X {
X printf (CP[220]);
X exit ();
X }
X argc -= 2;
X argv += 2;
X }
X if (argc)
X {
X printf ("%s\n", CP[220]);
X exit ();
X }
X }
X Initialize ();
X#ifdef ttblsz
X Initialize_ttable ();
X#endif /* ttblsz */
X Initialize_dist ();
X Initialize_moves ();
X NewGame ();
X
X flag.easy = ahead;
X flag.hash = hash;
X if (xwin)
X xwndw = atoi (xwin);
X
X hashfile = NULL;
X#if ttblsz
X#ifdef HASHFILE
X hashfile = fopen (HASHFILE, RWA_ACC);
X if (hashfile)
X {
X fseek (hashfile, 0L, SEEK_END);
X filesz = ftell (hashfile) / sizeof (struct fileentry) - 1;
X }
X#if !defined CHESSTOOL && !defined XBOARD
X else
X ShowMessage (CP[98]);
X#endif
X#endif /* HASHFILE */
X#endif /* ttblsz */
X while (!(flag.quit))
X {
X if (flag.bothsides && !flag.mate)
X SelectMove (opponent, 1);
X else
X InputCommand ();
X if (!(flag.quit || flag.mate || flag.force))
X {
X SelectMove (computer, 1);
X }
X }
X#if ttblsz
X#ifdef HASHFILE
X if (hashfile)
X fclose (hashfile);
X#endif /* HASHFILE */
X#endif /* ttblsz */
X
X ExitChess ();
X return (0);
X}
END_OF_FILE
if test 8946 -ne `wc -c <'src/main.c'`; then
echo shar: \"'src/main.c'\" unpacked with wrong size!
fi
# end of 'src/main.c'
fi
if test -f 'src/util.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/util.c'\"
else
echo shar: Extracting \"'src/util.c'\" \(8883 characters\)
sed "s/^X//" >'src/util.c' <<'END_OF_FILE'
X/*
X * util.c - C source for GNU CHESS
X *
X * Copyright (c) 1988,1989,1990 John Stanback
X * Copyright (c) 1992 Free Software Foundation
X *
X * This file is part of GNU CHESS.
X *
X * GNU Chess is free software; you can redistribute it and/or modify
X * it under the terms of the GNU General Public License as published by
X * the Free Software Foundation; either version 2, or (at your option)
X * any later version.
X *
X * GNU Chess is distributed in the hope that it will be useful,
X * but WITHOUT ANY WARRANTY; without even the implied warranty of
X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X * GNU General Public License for more details.
X *
X * You should have received a copy of the GNU General Public License
X * along with GNU Chess; see the file COPYING. If not, write to
X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
X */
X#include "gnuchess.h"
Xextern char mvstr[4][6];
Xint
Xparse (FILE * fd, short unsigned int *mv, short int side, char *opening)
X{
X register int c, i, r1, r2, c1, c2;
X char s[128];
X char *p;
X
X while ((c = getc (fd)) == ' ' || c == '\n') ;
X i = 0;
X s[0] = (char) c;
X if (c == '!')
X {
X p = opening;
X do
X {
X *p++ = c;
X c = getc (fd);
X if (c == '\n' || c == EOF)
X {
X *p = '\0';
X return 0;
X }
X } while (true);
X }
X while (c != '?' && c != ' ' && c != '\t' && c != '\n' && c != EOF)
X s[++i] = (char) (c = getc (fd));
X s[++i] = '\0';
X if (c == EOF)
X return (-1);
X if (s[0] == '!' || s[0] == ';' || i < 3)
X {
X while (c != '\n' && c != EOF)
X c = getc (fd);
X return (0);
X }
X if (s[4] == 'o')
X *mv = ((side == black) ? LONGBLACKCASTLE : LONGWHITECASTLE);
X else if (s[0] == 'o')
X *mv = ((side == black) ? BLACKCASTLE : WHITECASTLE);
X else
X {
X c1 = s[0] - 'a';
X r1 = s[1] - '1';
X c2 = s[2] - 'a';
X r2 = s[3] - '1';
X *mv = (locn (r1, c1) << 8) | locn (r2, c2);
X }
X if (c == '?')
X { /* Bad move, not for the program to play */
X *mv |= 0x8000; /* Flag it ! */
X c = getc (fd);
X }
X return (1);
X}
X
X
X#if ttblsz
X
X#define CB(i) (unsigned char) ((color[2 * (i)] ? 0x80 : 0)\
X | (board[2 * (i)] << 4)\
X | (color[2 * (i) + 1] ? 0x8 : 0)\
X | (board[2 * (i) + 1]))
X
Xint
XProbeTTable (short int side,
X short int depth,
X short int ply,
X short int *alpha,
X short int *beta,
X short int *score)
X
X/*
X * Look for the current board position in the transposition table.
X */
X
X{
X register struct hashentry *ptbl;
X register short i;
X
X ptbl = &ttable[side][hashkey & (ttblsize - 1)];
X
X /* rehash max rehash times */
X for (i = 1; (ptbl->depth) && (ptbl->hashbd != hashbd) && (i <= rehash); i++)
X ptbl++;
X if ((ptbl->depth) && (ptbl->hashbd == hashbd))
X {
X HashCnt++;
X#ifdef HASHTEST
X for (i = 0; i < 32; i++)
X {
X if (ptbl->bd[i] != CB (i))
X {
X HashCol++;
X ShowMessage (CP[199]); /*ttable collision detected*/
X break;
X }
X }
X#endif /* HASHTEST */
X
X
X SwagHt = ptbl->mv;
X if ((short) ptbl->depth >= depth)
X {
X PV = ptbl->mv;
X if (ptbl->flags & truescore)
X {
X *score = ptbl->score;
X /* adjust *score so moves to mate is from root */
X if (*score > 9000)
X *score -= ply;
X else if (*score < -9000)
X *score += ply;
X *beta = -20000;
X }
X#if 0 /* Never happens! see search */
X else if (ptbl->flags & upperbound)
X {
X if (ptbl->score < *beta)
X *beta = ptbl->score + 1;
X }
X#endif
X else if (ptbl->flags & lowerbound)
X {
X if (ptbl->score > *alpha)
X *alpha = *score - 1;
X }
X return (true);
X }
X }
X return (false);
X}
X
Xint
XPutInTTable (short int side,
X short int score,
X short int depth,
X short int ply,
X short int alpha,
X short int beta,
X short unsigned int mv)
X
X/*
X * Store the current board position in the transposition table.
X */
X
X{
X register struct hashentry *ptbl;
X register short i;
X
X ptbl = &ttable[side][hashkey & (ttblsize - 1)];
X
X /* rehash max rehash times */
X for (i = 1; ptbl->depth && ptbl->hashbd != hashbd && i <= rehash; i++)
X ptbl++;
X if (i > rehash)
X THashCol++;
X if (depth >= ptbl->depth || ptbl->hashbd != hashbd)
X {
X HashAdd++;
X ptbl->hashbd = hashbd;
X ptbl->depth = (unsigned char) depth;
X /* adjust score so moves to mate is from this ply */
X if (score > 9000)
X score += ply;
X else if (score < -9000)
X score -= ply;
X ptbl->score = score;
X ptbl->mv = mv;
X#ifdef DEBUG4
X if (debuglevel & 32)
X {
X algbr (mv >> 8, mv & 0xff, 0);
X printf ("-add-> d=%d s=%d p=%d a=%d b=%d %s\n", depth, score, ply, alpha, beta, mvstr);
X }
X#endif
X/*#ifdef notdef
X if (score < alpha)
X ptbl->flags = upperbound;
X else
X/*#endif /* 0 */
X if (score > beta)
X {
X ptbl->flags = lowerbound;
X score = beta + 1;
X }
X else
X ptbl->flags = truescore;
X
X#ifdef HASHTEST
X for (i = 0; i < 32; i++)
X {
X ptbl->bd[i] = CB (i);
X }
X#endif /* HASHTEST */
X return true;
X }
X return false;
X}
X
Xvoid
XZeroTTable (void)
X{
X register int a;
X for (a = 0; a < ttblsize + rehash; a++)
X {
X ttable[white][a].depth = 0;
X ttable[black][a].depth = 0;
X }
X#ifdef notdef
X register struct hashentry *ptbl;
X for (ptbl = &ttable[white][0]; ptbl < &ttable[white][ttblsize + rehash]; ptbl++)
X ptbl->depth = 0;
X for (ptbl = &ttable[black][0]; ptbl < &ttable[white][ttblsize + rehash]; ptbl++)
X ptbl->depth = 0;
X#endif
X}
X
X#ifdef HASHFILE
Xint
XProbeFTable (short int side,
X short int depth,
X short int ply,
X short int *alpha,
X short int *beta,
X short int *score)
X
X/*
X * Look for the current board position in the persistent transposition table.
X */
X
X{
X register short i, j;
X register unsigned long hashix;
X struct fileentry new, t;
X
X hashix = ((side == white) ? (hashkey & 0xFFFFFFFE) : (hashkey | 1)) & filesz;
X
X for (i = 0; i < 32; i++)
X new.bd[i] = CB (i);
X new.flags = 0;
X if (Mvboard[kingP[side]] == 0)
X {
X if (Mvboard[qrook[side]] == 0)
X new.flags |= queencastle;
X if (Mvboard[krook[side]] == 0)
X new.flags |= kingcastle;
X }
X for (i = 0; i < frehash; i++)
X {
X fseek (hashfile,
X sizeof (struct fileentry) * ((hashix + 2 * i) & (filesz)),
X SEEK_SET);
X fread (&t, sizeof (struct fileentry), 1, hashfile);
X if (!t.depth)
X break;
X for (j = 0; j < 32; j++)
X if (t.bd[j] != new.bd[j])
X break;
X if (((short) t.depth >= depth) && (j >= 32)
X && (new.flags == (t.flags & (kingcastle | queencastle))))
X {
X FHashCnt++;
X PV = (t.f << 8) | t.t;
X *score = (t.sh << 8) | t.sl;
X /* adjust *score so moves to mate is from root */
X if (*score > 9000)
X *score -= ply;
X else if (*score < -9000)
X *score += ply;
X if (t.flags & truescore)
X {
X *beta = -20000;
X }
X else if (t.flags & lowerbound)
X {
X if (*score > *alpha)
X *alpha = *score - 1;
X }
X else if (t.flags & upperbound)
X {
X if (*score < *beta)
X *beta = *score + 1;
X }
X return (true);
X }
X }
X return (false);
X}
X
Xvoid
XPutInFTable (short int side,
X short int score,
X short int depth,
X short int ply,
X short int alpha,
X short int beta,
X short unsigned int f,
X short unsigned int t)
X
X/*
X * Store the current board position in the persistent transposition table.
X */
X
X{
X register unsigned short i;
X register unsigned long hashix;
X struct fileentry new, tmp;
X
X FHashAdd++;
X hashix = ((side == white) ? (hashkey & 0xFFFFFFFE) : (hashkey | 1)) & filesz;
X for (i = 0; i < 32; i++)
X new.bd[i] = CB (i);
X new.f = (unsigned char) f;
X new.t = (unsigned char) t;
X if (score < alpha)
X new.flags = upperbound;
X else
X new.flags = ((score > beta) ? lowerbound : truescore);
X if (Mvboard[kingP[side]] == 0)
X {
X if (Mvboard[qrook[side]] == 0)
X new.flags |= queencastle;
X if (Mvboard[krook[side]] == 0)
X new.flags |= kingcastle;
X }
X new.depth = (unsigned char) depth;
X /* adjust *score so moves to mate is from root */
X if (score > 9000)
X score += ply;
X else if (score < -9000)
X score -= ply;
X
X
X new.sh = (unsigned char) (score >> 8);
X new.sl = (unsigned char) (score & 0xFF);
X
X for (i = 0; i < frehash; i++)
X {
X fseek (hashfile,
X sizeof (struct fileentry) * ((hashix + 2 * i) & (filesz)),
X SEEK_SET);
X fread (&tmp, sizeof (struct fileentry), 1, hashfile);
X if ((short) tmp.depth <= depth)
X {
X fseek (hashfile,
X sizeof (struct fileentry) * ((hashix + 2 * i) & (filesz)),
X SEEK_SET);
X fwrite (&new, sizeof (struct fileentry), 1, hashfile);
X break;
X }
X }
X}
X
X#endif /* HASHFILE */
X#endif /* ttblsz */
X
Xvoid
XZeroRPT (void)
X{
X#ifdef NOMEMSET
X register int side, i;
X for (side = white; side <= black; side++)
X for (i = 0; i < 256;)
X rpthash[side][i++] = 0;
X#else
X memset ((char *) rpthash, 0, sizeof (rpthash));
X#endif
X}
END_OF_FILE
if test 8883 -ne `wc -c <'src/util.c'`; then
echo shar: \"'src/util.c'\" unpacked with wrong size!
fi
# end of 'src/util.c'
fi
echo shar: End of archive 11 \(of 12\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 12 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
echo Building book file.
cat misc/book.xaa misc/book.xab > misc/gnuchess.nunn.book
rm misc/book.xaa misc/book.xab
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0