home *** CD-ROM | disk | FTP | other *** search
- 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
-