home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume13
/
gnuchess4
/
part05
< prev
next >
Wrap
Internet Message Format
|
1992-08-03
|
56KB
Path: uunet!zephyr.ens.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v13i093: gnuchess4 - GNU Chess 4.0, Part05/12
Message-ID: <3060@master.CNA.TEK.COM>
Date: 19 Jun 92 15:54:13 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2302
Approved: billr@saab.CNA.TEK.COM
Submitted-by: cracraft@rice-chex.ai.mit.edu (Stuart Cracraft)
Posting-number: Volume 13, Issue 93
Archive-name: gnuchess4/Part05
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 5 (of 12)."
# Contents: src/eval.c src/uxdsp.c test/test-mchess
# Wrapped by billr@saab on Fri Jun 19 08:36:01 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/eval.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/eval.c'\"
else
echo shar: Extracting \"'src/eval.c'\" \(32715 characters\)
sed "s/^X//" >'src/eval.c' <<'END_OF_FILE'
X/*
X * eval.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"
X#include "ataks.h"
Xshort int sscore[2];
X/* Backward pawn bonus indexed by # of attackers on the square */
Xstatic const short BACKWARD[16] =
X{-6, -10, -15, -21, -28, -28, -28, -28, -28, -28, -28, -28, -28, -28, -28, -28};
X
X/* Bishop mobility bonus indexed by # reachable squares */
Xstatic const short BMBLTY[14] =
X{-2, 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 16, 16, 16};
X
X/* Rook mobility bonus indexed by # reachable squares */
Xstatic const short RMBLTY[15] =
X{0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14};
X
X/* Positional values for a dying king */
Xstatic const short DyingKing[64] =
X{0, 8, 16, 24, 24, 16, 8, 0,
X 8, 32, 40, 48, 48, 40, 32, 8,
X 16, 40, 56, 64, 64, 56, 40, 16,
X 24, 48, 64, 72, 72, 64, 48, 24,
X 24, 48, 64, 72, 72, 64, 48, 24,
X 16, 40, 56, 64, 64, 56, 40, 16,
X 8, 32, 40, 48, 48, 40, 32, 8,
X 0, 8, 16, 24, 24, 16, 8, 0};
X
X/* Isoloted pawn penalty by rank */
Xstatic const short ISOLANI[8] =
X{-12, -16, -20, -24, -24, -20, -16, -12};
X
X/* table for King Bishop Knight endings */
Xstatic const short KBNK[64] =
X{99, 90, 80, 70, 60, 50, 40, 40,
X 90, 80, 60, 50, 40, 30, 20, 40,
X 80, 60, 40, 30, 20, 10, 30, 50,
X 70, 50, 30, 10, 0, 20, 40, 60,
X 60, 40, 20, 0, 10, 30, 50, 70,
X 50, 30, 10, 20, 30, 40, 60, 80,
X 40, 20, 30, 40, 50, 60, 80, 90,
X 40, 40, 50, 60, 70, 80, 90, 99};
X
X/* penalty for threats to king, indexed by number of such threats */
Xstatic const short KTHRT[36] =
X{0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
X -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
X -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
X
X/* King positional bonus inopening stage */
Xstatic const short KingOpening[64] =
X{0, 0, -4, -10, -10, -4, 0, 0,
X -4, -4, -8, -12, -12, -8, -4, -4,
X -12, -16, -20, -20, -20, -20, -16, -12,
X -16, -20, -24, -24, -24, -24, -20, -16,
X -16, -20, -24, -24, -24, -24, -20, -16,
X -12, -16, -20, -20, -20, -20, -16, -12,
X -4, -4, -8, -12, -12, -8, -4, -4,
X 0, 0, -4, -10, -10, -4, 0, 0};
X
X/* King positional bonus in end stage */
Xstatic const short KingEnding[64] =
X{0, 6, 12, 18, 18, 12, 6, 0,
X 6, 12, 18, 24, 24, 18, 12, 6,
X 12, 18, 24, 30, 30, 24, 18, 12,
X 18, 24, 30, 36, 36, 30, 24, 18,
X 18, 24, 30, 36, 36, 30, 24, 18,
X 12, 18, 24, 30, 30, 24, 18, 12,
X 6, 12, 18, 24, 24, 18, 12, 6,
X 0, 6, 12, 18, 18, 12, 6, 0};
X
X/* Passed pawn positional bonus */
Xstatic const short PassedPawn0[8] =
X{0, 60, 80, 120, 200, 360, 600, 800};
Xstatic const short PassedPawn1[8] =
X{0, 30, 40, 60, 100, 180, 300, 800};
Xstatic const short PassedPawn2[8] =
X{0, 15, 25, 35, 50, 90, 140, 800};
Xstatic const short PassedPawn3[8] =
X{0, 5, 10, 15, 20, 30, 140, 800};
X
X/* Knight positional bonus */
Xstatic const short pknight[64] =
X{0, 4, 8, 10, 10, 8, 4, 0,
X 4, 8, 16, 20, 20, 16, 8, 4,
X 8, 16, 24, 28, 28, 24, 16, 8,
X 10, 20, 28, 32, 32, 28, 20, 10,
X 10, 20, 28, 32, 32, 28, 20, 10,
X 8, 16, 24, 28, 28, 24, 16, 8,
X 4, 8, 16, 20, 20, 16, 8, 4,
X 0, 4, 8, 10, 10, 8, 4, 0};
X
X/* Bishop positional bonus */
Xstatic const short pbishop[64] =
X{14, 14, 14, 14, 14, 14, 14, 14,
X 14, 22, 18, 18, 18, 18, 22, 14,
X 14, 18, 22, 22, 22, 22, 18, 14,
X 14, 18, 22, 22, 22, 22, 18, 14,
X 14, 18, 22, 22, 22, 22, 18, 14,
X 14, 18, 22, 22, 22, 22, 18, 14,
X 14, 22, 18, 18, 18, 18, 22, 14,
X 14, 14, 14, 14, 14, 14, 14, 14};
X
X/* Pawn positional bonus */
Xstatic const short PawnAdvance[64] =
X{0, 0, 0, 0, 0, 0, 0, 0,
X 4, 4, 4, 0, 0, 4, 4, 4,
X 6, 8, 2, 10, 10, 2, 8, 6,
X 6, 8, 12, 16, 16, 12, 8, 6,
X 8, 12, 16, 24, 24, 16, 12, 8,
X 12, 16, 24, 32, 32, 24, 16, 12,
X 12, 16, 24, 32, 32, 24, 16, 12,
X 0, 0, 0, 0, 0, 0, 0, 0};
X#if !defined NOSCORESPACE
X#ifdef BLACKAG0
X/* Space positional bonus */
Xstatic const short SpaceBonusB[64] =
X{0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 2, 2, 2, 2, 0, 0,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 0, 0, 3, 4, 4, 3, 0, 0,
X 0, 0, 5, 5, 5, 5, 0, 0,
X 0, 0, 4, 4, 7, 7, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0};
X#elif defined BLACKAG1
X/* Space positional bonus */
Xstatic const short SpaceBonusB[64] =
X{1, 1, 1, 1, 1, 1, 1, 1,
X 1, 1, 2, 2, 2, 2, 1, 1,
X 1, 1, 2, 3, 3, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 3, 5, 5, 3, 1, 1,
X 1, 1, 3, 6, 6, 3, 1, 1,
X 1, 1, 3, 7, 7, 3, 1, 1,
X 1, 1, 1, 1, 1, 1, 1, 1};
X#elif defined BLACKAG2
X/* Space positional bonus */
Xstatic const short SpaceBonusB[64] =
X{1, 1, 1, 1, 1, 1, 1, 1,
X 1, 1, 2, 2, 2, 2, 1, 1,
X 1, 1, 3, 3, 3, 3, 1, 1,
X 1, 1, 4, 4, 4, 4, 1, 1,
X 1, 1, 5, 6, 6, 5, 1, 1,
X 1, 1, 6, 7, 7, 6, 1, 1,
X 1, 1, 7, 8, 8, 7, 1, 1,
X 1, 1, 1, 1, 1, 1, 1, 1};
X#elif defined BLACKAG3
X/* Space positional bonus */
Xstatic const short SpaceBonusB[64] =
X{0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 2, 2, 2, 2, 0, 0,
X 0, 0, 3, 3, 3, 3, 0, 0,
X 0, 0, 4, 4, 4, 3, 0, 0,
X 0, 0, 6, 6, 4, 4, 0, 0,
X 0, 0, 7, 7, 5, 5, 0, 0,
X 0, 0, 8, 8, 7, 7, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0};
X#elif defined BLACKAG4
X/* Space positional bonus */
Xstatic const short SpaceBonusB[64] =
X{1, 1, 1, 1, 1, 1, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 1, 1, 1, 1, 1, 1};
X#endif
X
X#ifdef WHITEAG0
X/* Space positional bonus */
Xstatic const short SpaceBonusW[64] =
X{0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 5, 5, 5, 5, 0, 0,
X 0, 0, 3, 4, 4, 3, 0, 0,
X 0, 0, 2, 4, 4, 2, 0, 0,
X 0, 0, 1, 4, 4, 1, 0, 0,
X 0, 0, 1, 4, 4, 1, 0, 0,
X 0, 0, 1, 2, 2, 1, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0};
X#elif defined WHITEAG1
X/* Space positional bonus */
Xstatic const short SpaceBonusW[64] =
X{1, 1, 1, 1, 1, 1, 1, 1,
X 1, 1, 3, 7, 7, 3, 1, 1,
X 1, 1, 3, 6, 6, 3, 1, 1,
X 1, 1, 3, 5, 5, 3, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 3, 3, 2, 1, 1,
X 1, 1, 2, 2, 2, 2, 1, 1,
X 1, 1, 1, 1, 1, 1, 1, 1};
X#elif defined WHITEAG2
X/* Space positional bonus */
Xstatic const short SpaceBonusW[64] =
X{1, 1, 1, 1, 1, 1, 1, 1,
X 1, 1, 7, 8, 8, 7, 1, 1,
X 1, 1, 6, 7, 7, 6, 1, 1,
X 1, 1, 5, 6, 6, 5, 1, 1,
X 1, 1, 4, 4, 4, 4, 1, 1,
X 1, 1, 3, 3, 3, 3, 1, 1,
X 1, 1, 2, 2, 2, 2, 1, 1,
X 1, 1, 1, 1, 1, 1, 1, 1};
X#elif defined WHITEAG3
X/* Space positional bonus */
Xstatic const short SpaceBonusW[64] =
X{0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 8, 8, 7, 7, 0, 0,
X 0, 0, 7, 7, 5, 5, 0, 0,
X 0, 0, 6, 6, 4, 4, 0, 0,
X 0, 0, 4, 4, 4, 3, 0, 0,
X 0, 0, 3, 3, 3, 3, 0, 0,
X 0, 0, 2, 2, 2, 2, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0};
X#elif defined WHITEAG4
X/* Space positional bonus */
Xstatic const short SpaceBonusW[64] =
X{1, 1, 1, 1, 1, 1, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 2, 4, 4, 2, 1, 1,
X 1, 1, 1, 1, 1, 1, 1, 1};
X#endif
X#endif
X
Xstatic short Mwpawn[64], Mbpawn[64], Mknight[2][64], Mbishop[2][64];
Xstatic short Mking[2][64], Kfield[2][64];
Xstatic short c1, c2, *atk1, *atk2, *PC1, *PC2, atak[2][64];
Xshort emtl[2];
Xstatic short PawnBonus, BishopBonus, RookBonus;
Xstatic short KNIGHTPOST, KNIGHTSTRONG, BISHOPSTRONG, KATAK;
Xstatic short PEDRNK2B, PWEAKH, PADVNCM, PADVNCI, PAWNSHIELD, PDOUBLED,
X PBLOK;
Xstatic short RHOPN, RHOPNX, KHOPN, KHOPNX, KSFTY;
Xstatic short ATAKD, HUNGP, HUNGX, KCASTLD, KMOVD, XRAY, PINVAL;
Xshort pscore[2];
Xshort tmtl;
X
X/* ............ POSITIONAL EVALUATION ROUTINES ............ */
X
X/*
X * Inputs are:
X * pmtl[side] - value of pawns
X * mtl[side] - value of all material
X * emtl[side] - vaule of all material - value of pawns - value of king
X * hung[side] - count of hung pieces
X * Tscore[ply] - search tree score for ply
X * ply
X * Pscore[ply] - positional score for ply ply
X * INCscore - bonus score or penalty for certain positions
X * slk - single lone king flag
X * Sdepth - search goal depth
X * xwndw - evaluation window about alpha/beta
X * EWNDW - second evaluation window about alpha/beta
X * ChkFlag[ply]- checking piece at level ply or 0 if no check
X */
Xinline
Xint
XScoreKPK (short int side,
X short int winner,
X short int loser,
X short int king1,
X register short int king2,
X register short int sq)
X
X/*
X * Score King and Pawns versus King endings.
X */
X
X{
X register short s, r;
X
X s = ((PieceCnt[winner] == 1) ? 50 : 120);
X if (winner == white)
X {
X r = row (sq) - ((side == loser) ? 1 : 0);
X if (row (king2) >= r && distance (sq, king2) < 8 - r)
X s += 10 * row (sq);
X else
X s = 500 + 50 * row (sq);
X if (row (sq) < 6)
X sq += 16;
X else if (row (sq) == 6)
X sq += 8;
X }
X else
X {
X r = row (sq) + ((side == loser) ? 1 : 0);
X if (row (king2) <= r && distance (sq, king2) < r + 1)
X s += 10 * (7 - row (sq));
X else
X s = 500 + 50 * (7 - row (sq));
X if (row (sq) > 1)
X sq -= 16;
X else if (row (sq) == 1)
X sq -= 8;
X }
X s += 8 * (taxicab (king2, sq) - taxicab (king1, sq));
X return (s);
X}
X
X
Xinline
Xint
XScoreKBNK (short int winner, short int king1, short int king2)
X
X
X/*
X * Score King+Bishop+Knight versus King endings. This doesn't work all that
X * well but it's better than nothing.
X */
X
X{
X register short s, sq, KBNKsq = 0;
X
X for (sq = 0; sq < 64; sq++)
X if (board[sq] == bishop)
X KBNKsq = (((row (sq) % 2) == (column (sq) % 2)) ? 0 : 7);
X
X s = emtl[winner] - 300;
X s += ((KBNKsq == 0) ? KBNK[king2] : KBNK[locn (row (king2), 7 - column (king2))]);
X s -= ((taxicab (king1, king2) + distance (PieceList[winner][1], king2) + distance (PieceList[winner][2], king2)));
X return (s);
X}
X
Xinline
Xshort int
XScoreLoneKing (short int side)
X
X/*
X * Static evaluation when loser has only a king and winner has no pawns or no
X * pieces.
X */
X
X{
X register short winner, loser, king1, king2, s, i;
X
X UpdateWeights ();
X winner = ((mtl[white] > mtl[black]) ? white : black);
X loser = winner ^ 1;
X king1 = PieceList[winner][0];
X king2 = PieceList[loser][0];
X
X s = 0;
X
X if (pmtl[winner] > 0)
X for (i = 1; i <= PieceCnt[winner]; i++)
X s += ScoreKPK (side, winner, loser, king1, king2, PieceList[winner][i]);
X
X else if (emtl[winner] == valueB + valueN)
X s = ScoreKBNK (winner, king1, king2);
X
X else if (emtl[winner] > valueB)
X s = 500 + emtl[winner] - DyingKing[king2] - 2 * distance (king1, king2);
X
X return ((side == winner) ? s : -s);
X}
X
Xint
Xevaluate (register short int side,
X register short int ply,
X register short int alpha,
X register short int beta,
X short int INCscore,
X short int *slk, /* output single lone king */
X short int *InChk) /* output Check flag */
X
X/*
X * Compute an estimate of the score by adding the positional score from the
X * previous ply to the material difference. If this score falls inside a
X * window which is 180 points wider than the alpha-beta window (or within a
X * 50 point window during quiescence search) call ScorePosition() to
X * determine a score, otherwise return the estimated score. If one side has
X * only a king and the other either has no pawns or no pieces then the
X * function ScoreLoneKing() is called.
X */
X
X{
X register short evflag, xside;
X short s;
X
X xside = side ^ 1;
X s = -Pscore[ply - 1] + mtl[side] - mtl[xside] - INCscore;
X hung[white] = hung[black] = 0;
X *slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
X (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
X
X if (*slk)
X evflag = false;
X else
X /* should we use the estimete or score the position */
X evflag = (ply == 1 ||
X ((ply <= Sdepth)) ||
X ((ply == Sdepth + 1 || ply == (Sdepth + 2)) && (s > (alpha - xwndw) && s < (beta + xwndw))) ||
X (ply > (Sdepth + 2) && s >= (alpha - EWNDW) && s <= (beta + EWNDW)));
X#ifdef DEBUG4
X if (debuglevel & 1)
X evflag = true;
X#endif
X if (evflag)
X {
X /* score the position */
X ataks (side, atak[side]);
X if (Anyatak (side, PieceList[xside][0]))
X return (10001 - ply);
X ataks (xside, atak[xside]);
X *InChk = Anyatak (xside, PieceList[side][0]);
X EvalNodes++;
X s = ScorePosition (side);
X }
X else
X {
X /* use the estimate but look at check and slk */
X if (SqAtakd (PieceList[xside][0], side))
X return (10001 - ply);
X *InChk = SqAtakd (PieceList[side][0], xside);
X if (*slk)
X s = ScoreLoneKing (side);
X }
X
X Pscore[ply] = s - mtl[side] + mtl[xside];
X ChkFlag[ply - 1] = ((*InChk) ? Pindex[TOsquare] : 0);
X return (s);
X}
X
Xinline
Xvoid
XBRscan (short int sq, register short int *s, short int *mob)
X
X/*
X * Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
X * hung[] array if a pin is found.
X */
X{
X register short u, pin;
X register unsigned char *ppos, *pdir;
X short piece, *Kf;
X
X Kf = Kfield[c1];
X *mob = 0;
X piece = board[sq];
X ppos = nextpos[piece][sq];
X pdir = nextdir[piece][sq];
X u = ppos[sq];
X pin = -1; /* start new direction */
X do
X {
X *s += Kf[u];
X if (color[u] == neutral)
X {
X (*mob)++;
X if (ppos[u] == pdir[u])
X pin = -1; /* oops new direction */
X u = ppos[u];
X }
X else if (pin < 0)
X {
X if (board[u] == pawn || board[u] == king)
X u = pdir[u];
X else
X {
X if (ppos[u] != pdir[u])
X pin = u; /* not on the edge and on to find a pin */
X u = ppos[u];
X }
X }
X else
X {
X if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
X {
X if (color[pin] == c2)
X {
X *s += PINVAL;
X if (atk2[pin] == 0 || atk1[pin] > control[board[pin]] + 1)
X ++hung[c2];
X }
X else
X *s += XRAY;
X }
X pin = -1; /* new direction */
X u = pdir[u];
X }
X } while (u != sq);
X}
X
Xinline
Xshort int
XKingScan (register short int sq)
X
X/*
X * Assign penalties if king can be threatened by checks, if squares near the
X * king are controlled by the enemy (especially the queen), or if there are
X * no pawns near the king. The following must be true: board[sq] == king c1
X * == color[sq] c2 == otherside[c1]
X */
X
X#define ScoreThreat \
X if (color[u] != c2)\
X if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
X else s -= 3
X
X{
X register short int s;
X register short u;
X register unsigned char *ppos, *pdir;
X register short cnt, ok;
X
X s = 0;
X cnt = 0;
X if (HasBishop[c2] || HasQueen[c2])
X {
X ppos = nextpos[bishop][sq];
X pdir = nextdir[bishop][sq];
X u = ppos[sq];
X do
X {
X if (atk2[u] & ctlBQ)
X ScoreThreat;
X u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
X } while (u != sq);
X }
X if (HasRook[c2] || HasQueen[c2])
X {
X ppos = nextpos[rook][sq];
X pdir = nextdir[rook][sq];
X u = ppos[sq];
X do
X {
X if (atk2[u] & ctlRQ)
X ScoreThreat;
X u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
X } while (u != sq);
X }
X if (HasKnight[c2])
X {
X pdir = nextdir[knight][sq];
X u = pdir[sq];
X do
X {
X if (atk2[u] & ctlNN)
X ScoreThreat;
X u = pdir[u];
X } while (u != sq);
X }
X s += (KSFTY * KTHRT[cnt]) / 16;
X
X cnt = 0;
X ok = false;
X pdir = nextpos[king][sq];
X u = pdir[sq];
X do
X {
X if (board[u] == pawn)
X ok = true;
X if (atk2[u] > atk1[u])
X {
X ++cnt;
X if (atk2[u] & ctlQ)
X if (atk2[u] > ctlQ + 1 && atk1[u] < ctlQ)
X s -= 4 * KSFTY;
X }
X u = pdir[u];
X } while (u != sq);
X if (!ok)
X s -= KSFTY;
X if (cnt > 1)
X s -= (KSFTY);
X return (s);
X}
X
Xinline
Xint
Xtrapped (register short int sq)
X
X/*
X * See if the attacked piece has unattacked squares to move to. The following
X * must be true: c1 == color[sq] c2 == otherside[c1]
X */
X
X{
X register short u, piece;
X register unsigned char *ppos, *pdir;
X
X piece = board[sq];
X ppos = nextpos[ptype[c1][piece]][sq];
X pdir = nextdir[ptype[c1][piece]][sq];
X if (piece == pawn)
X {
X u = ppos[sq]; /* follow no captures thread */
X if (color[u] == neutral)
X {
X if (atk1[u] >= atk2[u])
X return (false);
X if (atk2[u] < ctlP)
X {
X u = ppos[u];
X if (color[u] == neutral && atk1[u] >= atk2[u])
X return (false);
X }
X }
X u = pdir[sq]; /* follow captures thread */
X if (color[u] == c2)
X return (false);
X u = pdir[u];
X if (color[u] == c2)
X return (false);
X }
X else
X {
X u = ppos[sq];
X do
X {
X if (color[u] != c1)
X if (atk2[u] == 0 || board[u] >= piece)
X return (false);
X u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
X } while (u != sq);
X }
X return (true);
X}
X
Xinline
Xint
XPawnValue (register short int sqx, short int side)
X
X/*
X * Calculate the positional value for a pawn on 'sq'.
X */
X
X{
X register short s, fyle, rank;
X register short j, a1, a2, in_square, r, e;
X
X a1 = (atk1[sqx] & 0x4FFF);
X a2 = (atk2[sqx] & 0x4FFF);
X rank = row (sqx);
X fyle = column (sqx);
X s = 0;
X if (c1 == white)
X {
X s = Mwpawn[sqx];
X if ((sqx == 11 && color[19] != neutral) || (sqx == 12 && color[20] != neutral))
X s += PEDRNK2B;
X if ((fyle == 0 || PC1[fyle - 1] == 0) && (fyle == 7 || PC1[fyle + 1] == 0))
X s += ISOLANI[fyle];
X else if (PC1[fyle] > 1)
X s += PDOUBLED;
X if (a1 < ctlP && atk1[sqx + 8] < ctlP)
X {
X s += BACKWARD[a2 & 0xFF];
X if (PC2[fyle] == 0)
X s += PWEAKH;
X if (color[sqx + 8] != neutral)
X s += PBLOK;
X }
X if (PC2[fyle] == 0)
X {
X r = rank - ((side == black) ? 1 : 0);
X in_square = (row (bking) >= r && distance (sqx, bking) < 8 - r);
X e = ((a2 == 0 || side == white) ? 0 : 1);
X for (j = sqx + 8; j < 64; j += 8)
X if (atk2[j] >= ctlP)
X {
X e = 2;
X break;
X }
X else if (atk2[j] > 0 || color[j] != neutral)
X e = 1;
X if (e == 2)
X s += (stage * PassedPawn3[rank]) / 10;
X else if (in_square || e == 1)
X s += (stage * PassedPawn2[rank]) / 10;
X else if (emtl[black] > 0)
X s += (stage * PassedPawn1[rank]) / 10;
X else
X s += PassedPawn0[rank];
X }
X }
X else if (c1 == black)
X {
X s = Mbpawn[sqx];
X if ((sqx == 51 && color[43] != neutral) || (sqx == 52 && color[44] != neutral))
X s += PEDRNK2B;
X if ((fyle == 0 || PC1[fyle - 1] == 0) && (fyle == 7 || PC1[fyle + 1] == 0))
X s += ISOLANI[fyle];
X else if (PC1[fyle] > 1)
X s += PDOUBLED;
X if (a1 < ctlP && atk1[sqx - 8] < ctlP)
X {
X s += BACKWARD[a2 & 0xFF];
X if (PC2[fyle] == 0)
X s += PWEAKH;
X if (color[sqx - 8] != neutral)
X s += PBLOK;
X }
X if (PC2[fyle] == 0)
X {
X r = rank + ((side == white) ? 1 : 0);
X in_square = (row (wking) <= r && distance (sqx, wking) < r + 1);
X e = ((a2 == 0 || side == black) ? 0 : 1);
X for (j = sqx - 8; j >= 0; j -= 8)
X if (atk2[j] >= ctlP)
X {
X e = 2;
X break;
X }
X else if (atk2[j] > 0 || color[j] != neutral)
X e = 1;
X if (e == 2)
X s += (stage * PassedPawn3[7 - rank]) / 10;
X else if (in_square || e == 1)
X s += (stage * PassedPawn2[7 - rank]) / 10;
X else if (emtl[white] > 0)
X s += (stage * PassedPawn1[7 - rank]) / 10;
X else
X s += PassedPawn0[7 - rank];
X }
X }
X if (a2 > 0)
X {
X if (a1 == 0 || a2 > ctlP + 1)
X {
X s += HUNGP;
X ++hung[c1];
X if (trapped (sqx))
X ++hung[c1];
X }
X else if (a2 > a1)
X s += ATAKD;
X }
X return (s);
X}
X
Xinline
Xint
XKnightValue (short int sq, short int side)
X
X/*
X * Calculate the positional value for a knight on 'sq'.
X */
X
X{
X register short s, a2, a1;
X
X s = Mknight[c1][sq];
X a2 = (atk2[sq] & 0x4FFF);
X if (a2 > 0)
X {
X a1 = (atk1[sq] & 0x4FFF);
X if (a1 == 0 || a2 > ctlBN + 1)
X {
X s += HUNGP;
X ++hung[c1];
X if (trapped (sq))
X ++hung[c1];
X }
X else if (a2 >= ctlBN || a1 < ctlP)
X s += ATAKD;
X }
X return (s);
X}
X
Xinline
Xint
XBishopValue (short int sq, short int side)
X
X/*
X * Calculate the positional value for a bishop on 'sq'.
X */
X
X{
X register short a2, a1;
X short s, mob;
X
X s = Mbishop[c1][sq];
X BRscan (sq, &s, &mob);
X s += BMBLTY[mob];
X a2 = (atk2[sq] & 0x4FFF);
X if (a2 > 0)
X {
X a1 = (atk1[sq] & 0x4FFF);
X if (a1 == 0 || a2 > ctlBN + 1)
X {
X s += HUNGP;
X ++hung[c1];
X if (trapped (sq))
X ++hung[c1];
X }
X else if (a2 >= ctlBN || a1 < ctlP)
X s += ATAKD;
X }
X return (s);
X}
X
Xinline
Xint
XRookValue (register short int sq, short int side)
X
X/*
X * Calculate the positional value for a rook on 'sq'.
X */
X
X{
X register short fyle, a2, a1;
X short s, mob;
X
X s = RookBonus;
X BRscan (sq, &s, &mob);
X s += RMBLTY[mob];
X fyle = column (sq);
X if (PC1[fyle] == 0)
X s += RHOPN;
X if (PC2[fyle] == 0)
X s += RHOPNX;
X if (pmtl[c2] > 100 && row (sq) == rank7[c1])
X s += 10;
X if (stage > 2)
X s += 14 - taxicab (sq, EnemyKing);
X a2 = (atk2[sq] & 0x4FFF);
X if (a2 > 0)
X {
X a1 = (atk1[sq] & 0x4FFF);
X if (a1 == 0 || a2 > ctlR + 1)
X {
X s += HUNGP;
X ++hung[c1];
X
X if (trapped (sq))
X ++hung[c1];
X }
X else if (a2 >= ctlR || a1 < ctlP)
X s += ATAKD;
X }
X return (s);
X}
X
Xinline
Xint
XQueenValue (register short int sq, short int side)
X
X/*
X * Calculate the positional value for a queen on 'sq'.
X */
X
X{
X register short s, a2, a1;
X
X s = ((distance (sq, EnemyKing) < 3) ? 12 : 0);
X if (stage > 2)
X s += 14 - taxicab (sq, EnemyKing);
X a2 = (atk2[sq] & 0x4FFF);
X if (a2 > 0)
X {
X a1 = (atk1[sq] & 0x4FFF);
X if (a1 == 0 || a2 > ctlQ + 1)
X {
X s += HUNGP;
X ++hung[c1];
X if (trapped (sq))
X ++hung[c1];
X }
X else if (a2 >= ctlQ || a1 < ctlP)
X s += ATAKD;
X }
X return (s);
X}
X
Xinline
Xint
XKingValue (short int sq, short int side)
X
X/*
X * Calculate the positional value for a king on 'sq'.
X */
X
X{
X register short fyle, a2, a1;
X short s;
X s = (emtl[side ^ 1] > KINGPOSLIMIT) ? Mking[c1][sq] : Mking[c1][sq] / 2;
X if (KSFTY > 0)
X if (Developed[c2] || stage > 0)
X s += KingScan (sq);
X if (castld[c1])
X s += KCASTLD;
X else if (Mvboard[kingP[c1]])
X s += KMOVD;
X
X fyle = column (sq);
X if (PC1[fyle] == 0)
X s += KHOPN;
X if (PC2[fyle] == 0)
X s += KHOPNX;
X switch (fyle)
X {
X case 5:
X if (PC1[7] == 0)
X s += KHOPN;
X if (PC2[7] == 0)
X s += KHOPNX;
X /* Fall through */
X case 4:
X case 6:
X case 0:
X if (PC1[fyle + 1] == 0)
X s += KHOPN;
X if (PC2[fyle + 1] == 0)
X s += KHOPNX;
X break;
X case 2:
X if (PC1[0] == 0)
X s += KHOPN;
X if (PC2[0] == 0)
X s += KHOPNX;
X /* Fall through */
X case 3:
X case 1:
X case 7:
X if (PC1[fyle - 1] == 0)
X s += KHOPN;
X if (PC2[fyle - 1] == 0)
X s += KHOPNX;
X break;
X default:
X /* Impossible! */
X break;
X }
X
X a2 = (atk2[sq] & 0x4FFF);
X if (a2 > 0)
X {
X a1 = (atk1[sq] & 0x4FFF);
X if (a1 == 0 || a2 > ctlK + 1)
X {
X s += HUNGP;
X ++hung[c1];
X }
X else
X s += ATAKD;
X }
X return (s);
X}
X
X#if !defined NOSCORESPACE
Xinline
Xvoid
XScoreSpace (void)
X{
X register short *b, *w, *sw, *sb;
X register short sBl, sWh;
X sBl = sWh = 0;
X for (b = &atak[black][63], w = &atak[white][63], sw = &SpaceBonusW[63], sb = &SpaceBonusB[63];
X sw > &SpaceBonusW[0];
X b--, w--, sw--, sb--)
X {
X if (*b > *w)
X {
X if (*b > ctlR)
X sBl += *sb;
X }
X else if (*b < *w)
X if (*w > ctlR)
X sWh += *sw;
X }
X pscore[white] += (sWh);
X pscore[black] += (sBl);
X sscore[white] = sWh;
X sscore[black] = sBl;
X}
X
X#endif
X
X
X
Xshort int
XScorePosition (register short int side)
X
X/*
X * Perform normal static evaluation of board position. A score is generated
X * for each piece and these are summed to get a score for each side.
X */
X
X{
X register short int score;
X register short sq, s, i, xside;
X
X UpdateWeights ();
X xside = side ^ 1;
X pscore[white] = pscore[black] = 0;
X#if !defined NOSCORESPACE
X if (stage < SCORESPLIM)
X ScoreSpace ();
X#endif
X for (c1 = white; c1 <= black; c1++)
X {
X c2 = c1 ^ 1;
X /* atk1 is array of atacks on squares by my side */
X atk1 = atak[c1];
X /* atk2 is array of atacks on squares by other side */
X atk2 = atak[c2];
X /* same for PC1 and PC2 */
X PC1 = PawnCnt[c1];
X PC2 = PawnCnt[c2];
X for (i = PieceCnt[c1]; i >= 0; i--)
X {
X sq = PieceList[c1][i];
X switch (board[sq])
X {
X case pawn:
X s = PawnValue (sq, side);
X break;
X case knight:
X s = KnightValue (sq, side);
X break;
X case bishop:
X s = BishopValue (sq, side);
X break;
X case rook:
X s = RookValue (sq, side);
X break;
X case queen:
X s = QueenValue (sq, side);
X break;
X case king:
X s = KingValue (sq, side);
X break;
X default:
X s = 0;
X break;
X }
X pscore[c1] += s;
X svalue[sq] = s;
X }
X }
X if (hung[side] > 1)
X pscore[side] += HUNGX;
X if (hung[xside] > 1)
X pscore[xside] += HUNGX;
X
X score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
X if (dither)
X {
X if (flag.hash)
X srand (starttime + (unsigned int) hashbd);
X score += urand () % dither;
X }
X
X if (score > 0 && pmtl[side] == 0)
X if (emtl[side] < valueR)
X score = 0;
X else if (score < valueR)
X score /= 2;
X if (score < 0 && pmtl[xside] == 0)
X if (emtl[xside] < valueR)
X score = 0;
X else if (-score < valueR)
X score /= 2;
X
X if (mtl[xside] == valueK && emtl[side] > valueB)
X score += 200;
X if (mtl[side] == valueK && emtl[xside] > valueB)
X score -= 200;
X return (score);
X}
Xstatic inline void
XBlendBoard (const short int a[64], const short int b[64], short int c[64])
X{
X register int sq, s;
X s = 10 - stage;
X for (sq = 0; sq < 64; sq++)
X c[sq] = ((a[sq] * s) + (b[sq] * stage)) / 10;
X}
X
X
Xstatic inline void
XCopyBoard (const short int a[64], short int b[64])
X{
X register short *sqa, *sqb;
X for (sqa = a, sqb = b; sqa < a + 64;)
X *sqb++ = *sqa++;
X}
X
X
Xvoid
XExaminePosition (void)
X
X/*
X * This is done one time before the search is started. Set up arrays Mwpawn,
X * Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue() function
X * to determine the positional value of each piece.
X */
X
X{
X register short i, sq;
X short wpadv, bpadv, wstrong, bstrong, z, side, pp, j, k, val, Pd, fyle,
X rank;
X static short PawnStorm = false;
X
X ataks (white, atak[white]);
X ataks (black, atak[black]);
X UpdateWeights ();
X HasKnight[white] = HasKnight[black] = 0;
X HasBishop[white] = HasBishop[black] = 0;
X HasRook[white] = HasRook[black] = 0;
X HasQueen[white] = HasQueen[black] = 0;
X for (side = white; side <= black; side++)
X for (i = PieceCnt[side]; i >= 0; i--)
X switch (board[PieceList[side][i]])
X {
X case knight:
X ++HasKnight[side];
X break;
X case bishop:
X ++HasBishop[side];
X break;
X case rook:
X ++HasRook[side];
X break;
X case queen:
X ++HasQueen[side];
X break;
X }
X if (!Developed[white])
X Developed[white] = (board[1] != knight && board[2] != bishop &&
X board[5] != bishop && board[6] != knight);
X if (!Developed[black])
X Developed[black] = (board[57] != knight && board[58] != bishop &&
X board[61] != bishop && board[62] != knight);
X if (!PawnStorm && stage < 5)
X PawnStorm = ((column (wking) < 3 && column (bking) > 4) ||
X (column (wking) > 4 && column (bking) < 3));
X
X CopyBoard (pknight, Mknight[white]);
X CopyBoard (pknight, Mknight[black]);
X CopyBoard (pbishop, Mbishop[white]);
X CopyBoard (pbishop, Mbishop[black]);
X BlendBoard (KingOpening, KingEnding, Mking[white]);
X BlendBoard (KingOpening, KingEnding, Mking[black]);
X
X for (sq = 0; sq < 64; sq++)
X {
X fyle = column (sq);
X rank = row (sq);
X wstrong = bstrong = true;
X for (i = sq; i < 64; i += 8)
X if (Patak (black, i))
X {
X wstrong = false;
X break;
X }
X for (i = sq; i >= 0; i -= 8)
X if (Patak (white, i))
X {
X bstrong = false;
X break;
X }
X wpadv = bpadv = PADVNCM;
X if ((fyle == 0 || PawnCnt[white][fyle - 1] == 0) && (fyle == 7 || PawnCnt[white][fyle + 1] == 0))
X wpadv = PADVNCI;
X if ((fyle == 0 || PawnCnt[black][fyle - 1] == 0) && (fyle == 7 || PawnCnt[black][fyle + 1] == 0))
X bpadv = PADVNCI;
X Mwpawn[sq] = (wpadv * PawnAdvance[sq]) / 10;
X Mbpawn[sq] = (bpadv * PawnAdvance[63 - sq]) / 10;
X Mwpawn[sq] += PawnBonus;
X Mbpawn[sq] += PawnBonus;
X if (Mvboard[kingP[white]])
X {
X if ((fyle < 3 || fyle > 4) && distance (sq, wking) < 3)
X Mwpawn[sq] += PAWNSHIELD;
X }
X else if (rank < 3 && (fyle < 2 || fyle > 5))
X Mwpawn[sq] += PAWNSHIELD / 2;
X if (Mvboard[kingP[black]])
X {
X if ((fyle < 3 || fyle > 4) && distance (sq, bking) < 3)
X Mbpawn[sq] += PAWNSHIELD;
X }
X else if (rank > 4 && (fyle < 2 || fyle > 5))
X Mbpawn[sq] += PAWNSHIELD / 2;
X if (PawnStorm)
X {
X if ((column (wking) < 4 && fyle > 4) || (column (wking) > 3 && fyle < 3))
X Mwpawn[sq] += 3 * rank - 21;
X if ((column (bking) < 4 && fyle > 4) || (column (bking) > 3 && fyle < 3))
X Mbpawn[sq] -= 3 * rank;
X }
X Mknight[white][sq] += 5 - distance (sq, bking);
X Mknight[white][sq] += 5 - distance (sq, wking);
X Mknight[black][sq] += 5 - distance (sq, wking);
X Mknight[black][sq] += 5 - distance (sq, bking);
X Mbishop[white][sq] += BishopBonus;
X Mbishop[black][sq] += BishopBonus;
X for (i = PieceCnt[black]; i >= 0; i--)
X if (distance (sq, PieceList[black][i]) < 3)
X Mknight[white][sq] += KNIGHTPOST;
X for (i = PieceCnt[white]; i >= 0; i--)
X if (distance (sq, PieceList[white][i]) < 3)
X Mknight[black][sq] += KNIGHTPOST;
X if (wstrong)
X Mknight[white][sq] += KNIGHTSTRONG;
X if (bstrong)
X Mknight[black][sq] += KNIGHTSTRONG;
X if (wstrong)
X Mbishop[white][sq] += BISHOPSTRONG;
X if (bstrong)
X Mbishop[black][sq] += BISHOPSTRONG;
X
X if (HasBishop[white] == 2)
X Mbishop[white][sq] += 8;
X if (HasBishop[black] == 2)
X Mbishop[black][sq] += 8;
X if (HasKnight[white] == 2)
X Mknight[white][sq] += 5;
X if (HasKnight[black] == 2)
X Mknight[black][sq] += 5;
X
X Kfield[white][sq] = Kfield[black][sq] = 0;
X if (distance (sq, wking) == 1)
X Kfield[black][sq] = KATAK;
X if (distance (sq, bking) == 1)
X Kfield[white][sq] = KATAK;
X Pd = 0;
X for (k = 0; k <= PieceCnt[white]; k++)
X {
X i = PieceList[white][k];
X if (board[i] == pawn)
X {
X pp = true;
X z = i + ((row (i) == 6) ? 8 : 16);
X for (j = i + 8; j < 64; j += 8)
X if (Patak (black, j) || board[j] == pawn)
X {
X pp = false;
X break;
X }
X Pd += ((pp) ? 5 * taxicab (sq, z) : taxicab (sq, z));
X }
X }
X for (k = 0; k <= PieceCnt[black]; k++)
X {
X i = PieceList[black][k];
X if (board[i] == pawn)
X {
X pp = true;
X z = i - ((row (i) == 1) ? 8 : 16);
X for (j = i - 8; j >= 0; j -= 8)
X if (Patak (white, j) || board[j] == pawn)
X {
X pp = false;
X break;
X }
X Pd += ((pp) ? 5 * taxicab (sq, z) : taxicab (sq, z));
X }
X }
X if (Pd != 0)
X {
X val = (Pd * stage2) / 10;
X Mking[white][sq] -= val;
X Mking[black][sq] -= val;
X }
X }
X}
X
Xvoid
XUpdateWeights (void)
X
X/*
X * If material balance has changed, determine the values for the positional
X * evaluation terms.
X */
X
X{
X register short s1;
X
X emtl[white] = mtl[white] - pmtl[white] - valueK;
X emtl[black] = mtl[black] - pmtl[black] - valueK;
X tmtl = emtl[white] + emtl[black];
X s1 = ((tmtl > 6600) ? 0 : ((tmtl < 1400) ? 10 : (6600 - tmtl) / 520));
X if (s1 != stage)
X {
X stage = s1;
X stage2 = ((tmtl > 3600) ? 0 : ((tmtl < 1400) ? 10 : (3600 - tmtl) / 220));
X PEDRNK2B = -15; /* centre pawn on 2nd rank & blocked */
X PBLOK = -4; /* blocked backward pawn */
X PDOUBLED = -14; /* doubled pawn */
X PWEAKH = -4; /* weak pawn on half open file */
X PAWNSHIELD = 10 - stage; /* pawn near friendly king */
X PADVNCM = 10; /* advanced pawn multiplier */
X PADVNCI = 7; /* muliplier for isolated pawn */
X PawnBonus = stage;
X
X KNIGHTPOST = (stage + 2) / 3; /* knight near enemy pieces */
X KNIGHTSTRONG = (stage + 6) / 2; /* occupies pawn hole */
X
X BISHOPSTRONG = (stage + 6) / 2; /* occupies pawn hole */
X BishopBonus = BBONUS * stage;
X
X RHOPN = 10; /* rook on half open file */
X RHOPNX = 4;
X RookBonus = RBONUS * stage;
X
X XRAY = 8; /* Xray attack on piece */
X PINVAL = 10; /* Pin */
X
X KHOPN = (3 * stage - 30) / 2; /* king on half open file */
X KHOPNX = KHOPN / 2;
X KCASTLD = 10 - stage;
X KMOVD = -40 / (stage + 1);/* king moved before castling */
X KATAK = (10 - stage) / 2; /* B,R attacks near enemy king */
X KSFTY = ((stage < 8) ? KINGSAFETY - 2 * stage : 0);
X
X ATAKD = -6; /* defender > attacker */
X HUNGP = -16; /* each hung piece */
X HUNGX = -22; /* extra for >1 hung piece */
X }
X}
END_OF_FILE
if test 32715 -ne `wc -c <'src/eval.c'`; then
echo shar: \"'src/eval.c'\" unpacked with wrong size!
fi
# end of 'src/eval.c'
fi
if test -f 'src/uxdsp.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/uxdsp.c'\"
else
echo shar: Extracting \"'src/uxdsp.c'\" \(17782 characters\)
sed "s/^X//" >'src/uxdsp.c' <<'END_OF_FILE'
X/*
X * uxdsp.c - ALPHA interface for 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 <ctype.h>
X#include <signal.h>
X#ifdef MSDOS
X#include <dos.h>
X#include <conio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <time.h>
X
X#define ESC 0x1B
X#define refresh() fflush(stdout)
X
Xint mycntl1, mycntl2;
Xstatic void param (short n);
X
X#else
X#include <sys/param.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <curses.h>
X
X
X/* <stdlib.h> */
Xextern void *malloc (size_t);
Xextern void exit (int);
X
X/* <string.h> */
Xextern char *strcat (char *, const char *);
Xextern int strcmp (const char *, const char *);
Xextern char *strcpy (char *, const char *);
X
X/* <time.h> */
Xextern long int time (long int *);
X
X#endif /* MSDOS */
X
X#include "gnuchess.h"
X
Xextern short int pscore[2];
X
X#define TAB (46)
X#define VIR_C(s) ((flag.reverse) ? 7-column(s) : column(s))
X#define VIR_R(s) ((flag.reverse) ? 7-row(s) : row(s))
X
Xunsigned short int MV[MAXDEPTH];
Xint MSCORE;
Xchar *DRAW;
Xchar mvstr[4][6];
X
Xextern char *getenv (const char *);
Xvoid TerminateSearch (int), Die (int);
X
Xvoid
XInitialize (void)
X{
X signal (SIGINT, Die);
X#ifndef MSDOS
X signal (SIGQUIT, Die);
X initscr ();
X crmode ();
X#else
X mycntl1 = mycntl2 = 0;
X#endif /* MSDOS */
X}
X
Xvoid
XExitChess (void)
X{
X ListGame ();
X gotoXY (1, 24);
X#ifndef MSDOS
X nocrmode ();
X endwin ();
X#endif /* MSDOS */
X exit (0);
X}
X
Xvoid
XDie (int Sig)
X{
X char s[80];
X
X signal (SIGINT, SIG_IGN);
X#ifdef MSDOS
X Sig++; /* shut up the compiler */
X#else
X signal (SIGQUIT, SIG_IGN);
X#endif /* MSDOS */
X ShowMessage (CP[31]); /*Abort?*/
X scanz ("%s", s);
X if (strcmp (s, CP[210]) == 0) /*yes*/
X ExitChess ();
X signal (SIGINT, Die);
X#ifndef MSDOS
X signal (SIGQUIT, Die);
X#endif /* MSDOS */
X}
X
Xvoid
XTerminateSearch (int Sig)
X{
X signal (SIGINT, SIG_IGN);
X#ifdef MSDOS
X Sig++; /* shut up the compiler */
X#else
X signal (SIGQUIT, SIG_IGN);
X#endif /* MSDOS */
X if (!flag.timeout)
X flag.musttimeout = true;
X flag.bothsides = false;
X signal (SIGINT, Die);
X#ifndef MSDOS
X signal (SIGQUIT, Die);
X#endif /* MSDOS */
X}
Xvoid
XShowLine (short unsigned int *bstline)
X{
X}
X
Xvoid
Xhelp (void)
X{
X ClrScreen ();
X /*printz ("CHESS command summary\n");*/
X printz (CP[40]);
X printz ("----------------------------------------------------------------\n");
X /*printz ("g1f3 move from g1 to f3 quit Exit Chess\n");*/
X printz (CP[158]);
X /*printz ("Nf3 move knight to f3 beep turn %s\n", (flag.beep) ? "off" : "on");*/
X printz (CP[86], (flag.beep) ? CP[92] : CP[93]);
X /*printz ("a7a8q promote pawn to queen\n");*/
X printz (CP[128], (flag.material) ? CP[92] : CP[93]);
X /*printz ("o-o castle king side easy turn %s\n", (flag.easy) ? "off" : "on");*/
X printz (CP[173], (flag.easy) ? CP[92] : CP[93]);
X /*printz ("o-o-o castle queen side hash turn %s\n", (flag.hash) ? "off" : "on");*/
X printz (CP[174], (flag.hash) ? CP[92] : CP[93]);
X /*printz ("bd redraw board reverse board display\n");*/
X printz (CP[130]);
X /*printz ("list game to chess.lst book turn %s used %d of %d\n", (Book) ? "off" : "on", book
Xcount, BOOKSIZE);*/
X printz (CP[170], (Book) ? CP[92] : CP[93], bookcount, BOOKSIZE);
X /*printz ("undo undo last ply remove take back a move\n");*/
X printz (CP[200]);
X /*printz ("edit edit board force enter game moves\n");*/
X printz (CP[153]);
X /*printz ("switch sides with computer both computer match\n");*/
X printz (CP[194]);
X /*printz ("white computer plays white black computer plays black\n");*/
X printz (CP[202]);
X /*printz ("depth set search depth clock set time control\n");*/
X printz (CP[149]);
X /*printz ("hint suggest a move post turn %s principle variation\n", (flag.post) ? "off" :
X"on");*/
X printz (CP[177], (flag.post) ? CP[92] : CP[93]);
X /*printz ("save game to file get game from file\n");*/
X printz (CP[188]);
X /*printz ("random randomize play new start new game\n");*/
X printz (CP[181]);
X gotoXY (10, 20);
X printz (CP[47], ColorStr[computer]);
X gotoXY (10, 21);
X printz (CP[97], ColorStr[opponent]);
X gotoXY (10, 22);
X printz (CP[79], Level);
X gotoXY (10, 23);
X printz (CP[59], (flag.easy) ? CP[93] : CP[92]);
X gotoXY (40, 20);
X printz (CP[52], MaxSearchDepth);
X gotoXY (40, 21);
X printz (CP[100], (dither) ? CP[93] : CP[92]);
X gotoXY (40, 22);
X printz (CP[112], (flag.hash) ? CP[93] : CP[92]);
X gotoXY (40, 23);
X printz (CP[73]);
X gotoXY (10, 24);
X printz (CP[110], (TCflag) ? CP[93] : CP[92],
X TimeControl.moves[white], TimeControl.clock[white] / 100, OperatorTime, MaxSearchDepth);
X refresh ();
X fflush (stdin);
X getchar ();
X ClrScreen ();
X UpdateDisplay (0, 0, 1, 0);
X}
X
X
Xvoid
XEditBoard (void)
X
X/*
X * Set up a board position. Pieces are entered by typing the piece followed
X * by the location. For example, Nf3 will place a knight on square f3.
X */
X
X{
X short a, r, c, sq, i;
X char s[80];
X
X flag.regularstart = false;
X Book = false;
X ClrScreen ();
X UpdateDisplay (0, 0, 1, 0);
X gotoXY (TAB, 3);
X printz (CP[29]);
X gotoXY (TAB, 4);
X printz (CP[28]);
X gotoXY (TAB, 5);
X printz (CP[136]);
X gotoXY (TAB, 7);
X printz (CP[64]);
X a = white;
X do
X {
X gotoXY (TAB, 6);
X printz (CP[60], ColorStr[a]); /*Editing %s*/
X gotoXY (TAB + 24, 7);
X ClrEoln ();
X scanz ("%s", s);
X if (s[0] == CP[28][0]) /*#*/
X {
X for (sq = 0; sq < 64; sq++)
X {
X board[sq] = no_piece;
X color[sq] = neutral;
X DrawPiece (sq);
X }
X }
X if (s[0] == CP[136][0]) /*c*/
X a = otherside[a];
X c = s[1] - 'a';
X r = s[2] - '1';
X if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
X {
X sq = locn (r, c);
X for (i = king; i > no_piece; i--)
X if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
X break;
X board[sq] = i;
X color[sq] = ((board[sq] == no_piece) ? neutral : a);
X DrawPiece (sq);
X }
X } while (s[0] != CP[29][0]); /*.*/
X
X for (sq = 0; sq < 64; sq++)
X Mvboard[sq] = ((board[sq] != Stboard[sq]) ? 10 : 0);
X GameCnt = 0;
X Game50 = 1;
X ZeroRPT ();
X Sdepth = 0;
X InitializeStats ();
X ClrScreen ();
X UpdateDisplay (0, 0, 1, 0);
X}
X
Xvoid
XShowPlayers (void)
X{
X gotoXY (5, ((flag.reverse) ? 23 : 2));
X printz ("%s", (computer == black) ? CP[218] : CP[74]);
X gotoXY (5, ((flag.reverse) ? 2 : 23));
X printz ("%s", (computer == white) ? CP[218] : CP[74]);
X}
X
Xvoid
XShowDepth (char ch)
X{
X gotoXY (TAB, 4);
X printz (CP[53], Sdepth, ch); /*Depth= %d%c*/
X ClrEoln ();
X}
X
Xvoid
XShowScore (short score)
X{
X gotoXY (TAB, 5);
X printz (CP[104], score);
X ClrEoln ();
X}
X
Xvoid
XShowMessage (char *s)
X{
X gotoXY (TAB, 6);
X printz ("%s", s);
X ClrEoln ();
X}
X
Xvoid
XClearMessage (void)
X{
X gotoXY (TAB, 6);
X ClrEoln ();
X}
X
Xvoid
XShowCurrentMove (short int pnt, short int f, short int t)
X{
X algbr (f, t, false);
X gotoXY (TAB, 7);
X printz ("(%2d) %4s", pnt, mvstr[0]);
X}
X
Xvoid
XShowHeader (void)
X{
X gotoXY (TAB, 2);
X printz (CP[69]);
X}
X
Xvoid
XShowSidetoMove (void)
X{
X gotoXY (TAB, 14);
X printz ("%2d: %s", 1 + GameCnt / 2, ColorStr[player]);
X ClrEoln ();
X}
X
Xvoid
XShowPrompt (void)
X{
X gotoXY (TAB, 19);
X printz (CP[121]); /*Your movwe is?*/
X ClrEoln ();
X}
X
Xvoid
XShowNodeCnt (long int NodeCnt)
X{
X gotoXY (TAB, 21);
X printz (CP[90], NodeCnt, (et > 100) ? NodeCnt / (et / 100) : 0);
X ClrEoln ();
X}
X
Xvoid
XShowResults (short int score, short unsigned int *bstline, char ch)
X{
X unsigned char d, ply;
X
X if (flag.post)
X {
X ShowDepth (ch);
X ShowScore (score);
X d = 7;
X for (ply = 1; bstline[ply] > 0; ply++)
X {
X if (ply % 4 == 1)
X {
X gotoXY (TAB, ++d);
X ClrEoln ();
X }
X algbr ((short) bstline[ply] >> 8, (short) bstline[ply] & 0xFF, false);
X printz ("%5s ", mvstr[0]);
X }
X ClrEoln ();
X while (d < 13)
X {
X gotoXY (TAB, ++d);
X ClrEoln ();
X }
X }
X}
X
Xvoid
XSearchStartStuff (short int side)
X{
X short i;
X
X signal (SIGINT, TerminateSearch);
X#ifdef MSDOS
X side++; /* shut up the compiler */
X#else
X signal (SIGQUIT, TerminateSearch);
X#endif /* MSDOS */
X for (i = 4; i < 14; i++)
X {
X gotoXY (TAB, i);
X ClrEoln ();
X }
X}
X
Xvoid
XOutputMove (void)
X{
X int i;
X
X UpdateDisplay (rootnode.f, rootnode.t, 0, (short) rootnode.flags);
X gotoXY (TAB, 17);
X printz (CP[84], mvstr[0]); /*My move is %s*/
X if (flag.beep)
X putchar (7);
X ClrEoln ();
X
X gotoXY (TAB, 24);
X if (rootnode.flags & draw)
X printz (CP[58]);
X else if (rootnode.score == -9999)
X printz (CP[95]);
X else if (rootnode.score == 9998)
X printz (CP[44]);
X#ifdef VERYBUGGY
X else if (rootnode.score < -9000)
X printz (CP[96]);
X else if (rootnode.score > 9000)
X printz (CP[45]);
X#endif VERYBUGGY
X ClrEoln ();
X if (flag.post)
X {
X register short h, l, t;
X
X h = TREE;
X l = 0;
X t = TREE >> 1;
X while (l != t)
X {
X if (Tree[t].f || Tree[t].t)
X l = t;
X else
X h = t;
X t = (l + h) >> 1;
X }
X
X ShowNodeCnt (NodeCnt);
X gotoXY (TAB, 22);
X printz (CP[81], t); /*Max Tree=*/
X ClrEoln ();
X }
X ShowSidetoMove ();
X}
X
Xvoid
XUpdateClocks (void)
X{
X short m, s;
X
X m = (short) (et / 6000);
X s = (short) (et - 6000 * (long) m) / 100;
X if (TCflag)
X {
X m = (short) ((TimeControl.clock[player] - et) / 6000);
X s = (short) ((TimeControl.clock[player] - et - 6000 * (long) m) / 100);
X }
X if (m < 0)
X m = 0;
X if (s < 0)
X s = 0;
X if (player == white)
X gotoXY (20, (flag.reverse) ? 2 : 23);
X else
X gotoXY (20, (flag.reverse) ? 23 : 2);
X printz ("%d:%02d ", m, s);
X if (flag.post)
X ShowNodeCnt (NodeCnt);
X refresh ();
X}
X
Xvoid
XgotoXY (short int x, short int y)
X{
X#ifdef MSDOS
X putchar (ESC);
X putchar ('[');
X param (y);
X putchar (';');
X param (x);
X putchar ('H');
X#else
X move (y - 1, x - 1);
X#endif /* MSDOS */
X}
X
Xvoid
XClrScreen (void)
X{
X#ifdef MSDOS
X putchar (ESC);
X putchar ('[');
X putchar ('2');
X putchar ('J');
X#else
X clear ();
X#endif /* MSDOS */
X refresh ();
X}
X
Xvoid
XClrEoln (void)
X{
X#ifdef MSDOS
X putchar (ESC);
X putchar ('[');
X putchar ('K');
X#else
X clrtoeol ();
X#endif /* MSDOS */
X refresh ();
X}
X
X#ifdef MSDOS
Xvoid
Xparam (short n)
X{
X if (n >= 10)
X {
X register short d, q;
X
X q = n / 10;
X d = n % 10;
X putchar (q + '0');
X putchar (d + '0');
X }
X else
X putchar (n + '0');
X}
X
X#endif /* MSDOS */
X
Xvoid
XDrawPiece (short int sq)
X{
X register char x;
X
X if (color[sq] == black)
X#if defined(MSDOS) && !defined(SEVENBIT)
X x = '7'; /* print WHITE boldface, */
X else
X x = '1'; /* print BLACK inverted */
X gotoXY (6 + 5 * VIR_C (sq), 5 + 2 * (7 - VIR_R (sq)));
X printz ("\033[%cm%c\033[0m", x, pxx[board[sq]]);
X#else
X x = '*';
X else
X x = ' ';
X gotoXY (5 + 5 * VIR_C (sq), 5 + 2 * (7 - VIR_R (sq)));
X printz ("%c%c ", x, pxx[board[sq]]);
X#endif /* MSDOS && !SEVENBIT */
X}
X
Xvoid
XShowPostnValue (short int sq)
X
X/*
X * must have called ExaminePosition() first
X */
X
X{
X short score;
X
X gotoXY (4 + 5 * VIR_C (sq), 5 + 2 * (7 - VIR_R (sq)));
X score = ScorePosition (color[sq]);
X if (color[sq] != neutral)
X printz ("%3d ", svalue[sq]);
X else
X printz (" ");
X}
X
Xvoid
XShowPostnValues (void)
X{
X short sq, score;
X
X ExaminePosition ();
X for (sq = 0; sq < 64; sq++)
X ShowPostnValue (sq);
X score = ScorePosition (opponent);
X gotoXY (TAB, 5);
X printz (CP[103], score, mtl[computer], pmtl[computer], pscore[computer], mtl[opponent], pmtl[opponent], pscore[opponent]);
X ClrEoln ();
X}
X
Xvoid
XUpdateDisplay (short int f, short int t, short int redraw, short int isspec)
X{
X short i, sq, z;
X
X if (redraw)
X {
X ShowHeader ();
X ShowPlayers ();
X
X i = 3;
X gotoXY (3, ++i);
X#if defined(MSDOS) && !defined(SEVENBIT)
X printz ("\332\304\304\304\304\302\304\304\304\304\302\304\304\304\304" \
X "\302\304\304\304\304\302\304\304\304\304\302\304\304\304\304" \
X "\302\304\304\304\304\302\304\304\304\304\277");
X#else
X printz ("+----+----+----+----+----+----+----+----+");
X#endif /* MSDOS && !SEVENBIT */
X while (i < 19)
X {
X gotoXY (1, ++i);
X if (flag.reverse)
X z = (i / 2) - 1;
X else
X z = 10 - (i / 2);
X#if defined(MSDOS) && !defined(SEVENBIT)
X printz ("%d \263 \263 \263 \263 \263 \263 " \
X "\263 \263 \263", z);
X#else
X printz ("%d | | | | | | | | |", z);
X#endif /* MSDOS && !SEVENBIT */
X gotoXY (3, ++i);
X if (i < 19)
X#if defined(MSDOS) && !defined(SEVENBIT)
X printz ("\303\304\304\304\304\305\304\304\304\304\305\304\304" \
X "\304\304\305\304\304\304\304\305\304\304\304\304\305" \
X "\304\304\304\304\305\304\304\304\304\305\304\304\304" \
X "\304\264");
X#else
X printz ("+----+----+----+----+----+----+----+----+");
X#endif /* MSDOS && !SEVENBIT */
X }
X#if defined(MSDOS) && !defined(SEVENBIT)
X printz ("\300\304\304\304\304\301\304\304\304\304\301\304\304\304\304" \
X "\301\304\304\304\304\301\304\304\304\304\301\304\304\304\304" \
X "\301\304\304\304\304\301\304\304\304\304\331");
X#else
X printz ("+----+----+----+----+----+----+----+----+");
X#endif /* MSDOS && !SEVENBIT */
X gotoXY (3, 21);
X if (flag.reverse)
X printz (CP[16]);
X else
X printz (CP[15]);
X for (sq = 0; sq < 64; sq++)
X DrawPiece (sq);
X }
X else
X {
X DrawPiece (f);
X DrawPiece (t);
X if (isspec & cstlmask)
X if (t > f)
X {
X DrawPiece (f + 3);
X DrawPiece (t - 1);
X }
X else
X {
X DrawPiece (f - 4);
X DrawPiece (t + 1);
X }
X else if (isspec & epmask)
X {
X DrawPiece (t - 8);
X DrawPiece (t + 8);
X }
X }
X refresh ();
X}
X
Xchar *InPtr;
Xvoid
Xskip ()
X{
X while (*InPtr != ' ')
X InPtr++;
X while (*InPtr == ' ')
X InPtr++;
X}
Xvoid
Xskipb ()
X{
X while (*InPtr == ' ')
X InPtr++;
X}
X
Xvoid
XChangeAlphaWindow (void)
X{
X ShowMessage (CP[114]);
X scanz ("%hd", &WAwindow);
X ShowMessage (CP[34]);
X scanz ("%hd", &BAwindow);
X}
X
Xvoid
XChangeBetaWindow (void)
X{
X ShowMessage (CP[115]);
X scanz ("%hd", &WBwindow);
X ShowMessage (CP[35]);
X scanz ("%hd", &BBwindow);
X}
X
Xvoid
XGiveHint (void)
X{
X char s[40];
X if (hint)
X {
X algbr ((short) (hint >> 8), (short) (hint & 0xFF), false);
X strcpy (s, CP[198]); /*try*/
X strcat (s, mvstr[0]);
X ShowMessage (s);
X }
X else
X ShowMessage (CP[223]);
X}
X
Xvoid
XChangeHashDepth (void)
X{
X ShowMessage (CP[163]);
X scanz ("%hd", &HashDepth);
X ShowMessage (CP[82]);
X scanz ("%hd", &HashMoveLimit);
X}
X
Xvoid
XChangeSearchDepth (void)
X{
X ShowMessage (CP[150]);
X scanz ("%hd", &MaxSearchDepth);
X TCflag = !(MaxSearchDepth > 0);
X}
X
Xvoid
XSetContempt (void)
X{
X ShowMessage (CP[142]);
X scanz ("%hd", &contempt);
X}
X
Xvoid
XChangeXwindow (void)
X{
X ShowMessage (CP[208]);
X scanz ("%hd", &xwndw);
X}
X
Xvoid
XSelectLevel (void)
X{
X ClrScreen ();
X gotoXY (32, 2);
X printz (CP[41]);
X gotoXY (20, 4);
X printz (CP[18]);
X gotoXY (20, 5);
X printz (CP[19]);
X gotoXY (20, 6);
X printz (CP[20]);
X gotoXY (20, 7);
X printz (CP[21]);
X gotoXY (20, 8);
X printz (CP[22]);
X gotoXY (20, 9);
X printz (CP[23]);
X gotoXY (20, 10);
X printz (CP[24]);
X gotoXY (20, 11);
X printz (CP[25]);
X gotoXY (20, 12);
X printz (CP[26]);
X gotoXY (20, 13);
X printz (CP[27]);
X
X OperatorTime = 0;
X TCmoves = 60;
X TCminutes = 5;
X TCseconds = 0;
X
X gotoXY (20, 17);
X printz (CP[62]);
X refresh ();
X scanz ("%ld", &Level);
X switch ((int) Level)
X {
X case 1:
X TCmoves = 60;
X TCminutes = 5;
X break;
X case 2:
X TCmoves = 60;
X TCminutes = 15;
X break;
X case 3:
X TCmoves = 60;
X TCminutes = 30;
X break;
X case 4:
X TCmoves = 40;
X TCminutes = 30;
X break;
X case 5:
X TCmoves = 40;
X TCminutes = 60;
X break;
X case 6:
X TCmoves = 40;
X TCminutes = 120;
X break;
X case 7:
X TCmoves = 40;
X TCminutes = 240;
X break;
X case 8:
X TCmoves = 1;
X TCminutes = 15;
X break;
X case 9:
X TCmoves = 1;
X TCminutes = 60;
X break;
X case 10:
X TCmoves = 1;
X TCminutes = 600;
X break;
X }
X
X TCflag = (TCmoves > 0);
X SetTimeControl ();
X ClrScreen ();
X UpdateDisplay (0, 0, 1, 0);
X}
X
Xvoid
XDoDebug (void)
X{
X short c, p, sq, tp, tc, tsq, score;
X char s[40];
X
X ExaminePosition ();
X ShowMessage (CP[65]);
X scanz ("%s", s);
X c = neutral;
X if (s[0] == CP[9][0] || s[0] == CP[9][1]) /* w W*/
X c = white;
X if (s[0] == CP[9][2] || s[0] == CP[9][3]) /*b B*/
X c = black;
X for (p = king; p > no_piece; p--)
X if ((s[1] == pxx[p]) || (s[1] == qxx[p]))
X break;
X for (sq = 0; sq < 64; sq++)
X {
X tp = board[sq];
X tc = color[sq];
X board[sq] = p;
X color[sq] = c;
X tsq = PieceList[c][1];
X PieceList[c][1] = sq;
X ShowPostnValue (sq);
X PieceList[c][1] = tsq;
X board[sq] = tp;
X color[sq] = tc;
X }
X score = ScorePosition (opponent);
X gotoXY (TAB, 5);
X printz (CP[103], score, mtl[computer], pmtl[computer], pscore[computer], mtl[opponent], pmtl[opponent], pscore[opponent]);
X ClrEoln ();
X}
END_OF_FILE
if test 17782 -ne `wc -c <'src/uxdsp.c'`; then
echo shar: \"'src/uxdsp.c'\" unpacked with wrong size!
fi
# end of 'src/uxdsp.c'
fi
if test -f 'test/test-mchess' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'test/test-mchess'\"
else
echo shar: Extracting \"'test/test-mchess'\" \(500 characters\)
sed "s/^X//" >'test/test-mchess' <<'END_OF_FILE'
XBlack comPuter White Human 1 #correct move d4d5
XCastled White false Black false
XTimeControl 0 OPerator Time 0
XWhite Clock 0000 Moves 0
XBlack Clock 0000 Moves 0
X
X8 R....RK. 10 10 10 10 10 10 10 10
X7 .PP...BP 10 10 10 10 10 10 10 10
X6 P..P.... 10 10 10 10 10 10 10 10
X5 ...QBb. 10 10 10 10 10 10 10 10
X4 ....P.P 10 10 10 10 10 10 10 10
X3 .n...N. 10 10 10 10 10 10 10 10
X2 p.q..p. 10 10 10 10 10 10 10 10
X1 .bkrr... 10 10 10 10 10 10 10 10
X abcdefgh
X
Xmove score dePth nodes time flags caPture color
END_OF_FILE
if test 500 -ne `wc -c <'test/test-mchess'`; then
echo shar: \"'test/test-mchess'\" unpacked with wrong size!
fi
# end of 'test/test-mchess'
fi
echo shar: End of archive 5 \(of 12\).
cp /dev/null ark5isdone
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