games-request@tekred.TEK.COM (01/13/88)
Submitted by: Stuart Cracraft <cracraft@venera.isi.edu>
Comp.sources.games: Volume 3, Issue 40
Archive-name: gnuchess/Part03
#! /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 3 (of 3)."
# Contents: gnuchess.c2
# Wrapped by billr@tekred on Tue Jan 12 11:56:43 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f gnuchess.c2 -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"gnuchess.c2\"
else
echo shar: Extracting \"gnuchess.c2\" \(39696 characters\)
sed "s/^X//" >gnuchess.c2 <<'END_OF_gnuchess.c2'
XInitializeStats()
X{
Xregister short i,loc;
X epsquare = -1;
X for (i = 0; i < 8; i++)
X PawnCnt[white][i] = PawnCnt[black][i] = 0;
X mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
X PieceCnt[white] = PieceCnt[black] = 0;
X hashbd = hashkey = 0;
X for (loc = 0; loc < 64; loc++)
X if (color[loc] != neutral)
X {
X mtl[color[loc]] += value[board[loc]];
X if (board[loc] == pawn)
X {
X pmtl[color[loc]] += valueP;
X ++PawnCnt[color[loc]][col[loc]];
X }
X if (board[loc] == king) Pindex[loc] = 0;
X else Pindex[loc] = ++PieceCnt[color[loc]];
X PieceList[color[loc]][Pindex[loc]] = loc;
X hashbd ^= hashcode[color[loc]][board[loc]][loc].bd;
X hashkey ^= hashcode[color[loc]][board[loc]][loc].key;
X }
X}
X
X
Xsort(p1,p2)
Xshort p1,p2;
X{
Xregister short p,p0,s;
Xstruct leaf temp;
X
X s = 32000;
X while (p1 < p2)
X if (Tree[p1].score >= s) p1++;
X else
X {
X s = Tree[p1].score; p0 = p1;
X for (p = p1+1; p <= p2; p++)
X if (Tree[p].score > s)
X {
X s = Tree[p].score; p0 = p;
X }
X if (p0 != p1)
X {
X temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp;
X }
X p1++;
X }
X}
X
X
Xrepetition(cnt)
Xshort *cnt;
X
X/*
X Check for draw by threefold repetition.
X*/
X
X{
Xregister short i,f,t;
Xshort c,b[64];
Xunsigned short m;
X *cnt = c = 0;
X for (i = 0; i < 64; b[i++] = 0);
X/*
X bzero((char *)b,sizeof(b));
X memset((char *)b,0,64*sizeof(short));
X*/
X for (i = GameCnt; i > Game50; i--)
X {
X m = GameList[i].gmove; f = m>>8; t = m & 0xFF;
X if (++b[f] == 0) c--; else c++;
X if (--b[t] == 0) c--; else c++;
X if (c == 0) (*cnt)++;
X }
X}
X
X
Xint SqAtakd(sq,side)
Xshort sq,side;
X
X/*
X Generate moves from 'sq' for each piece and see if the appropriate
X piece with color 'side' is encountered.
X*/
X
X{
Xregister short i,u,m,d;
Xshort m0;
X
X m0 = map[sq];
X
X if (HasPawn[side])
X {
X d = Dpwn[otherside[side]];
X for (i = d; i <= d+1; i++)
X if ((u = unmap[m0+Dir[i]]) >= 0)
X if (board[u] == pawn && color[u] == side) return(true);
X }
X
X if (HasKnight[side])
X for (i = 8; i <= 15; i++)
X if ((u = unmap[m0+Dir[i]]) >= 0)
X if (board[u] == knight && color[u] == side) return(true);
X
X if (HasRook[side] || HasQueen[side])
X for (i = 0; i <= 3; i++)
X {
X d = Dir[i]; m = m0+d; u = unmap[m];
X while (u >= 0)
X if (color[u] == neutral)
X {
X m += d; u = unmap[m];
X }
X else if (color[u] == side && sweep1[board[u]]) return(true);
X else break;
X }
X
X if (HasBishop[side] || HasQueen[side])
X for (i = 4; i <= 7; i++)
X {
X d = Dir[i]; m = m0+d; u = unmap[m];
X while (u >= 0)
X if (color[u] == neutral)
X {
X m += d; u = unmap[m];
X }
X else if (color[u] == side && sweep2[board[u]]) return(true);
X else break;
X }
X
X if (distance(sq,PieceList[side][0]) == 1) return(true);
X
X return(false);
X}
X
X
Xataks(side,a)
Xshort side,a[];
X
X/*
X Fill array atak[][] with info about ataks to a square. Bits 8-15
X are set if the piece (king..pawn) ataks the square. Bits 0-7
X contain a count of total ataks to the square.
X*/
X
X{
Xregister short u,m,d,c;
Xshort j,piece,i,m0,loc;
X
X for (u = 0; u < 64; a[u++] = 0);
X/*
X memset((char *)a,0,64*sizeof(short));
X bzero((char *)a,sizeof(a));
X*/
X Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
X for (i = 0; i <= PieceCnt[side]; i++)
X {
X loc = PieceList[side][i];
X piece = board[loc]; m0 = map[loc]; c = control[piece];
X if (sweep[piece])
X for (j = Dstart[piece]; j <= Dstop[piece]; j++)
X {
X d = Dir[j]; m = m0+d; u = unmap[m];
X while (u >= 0)
X {
X a[u] = ++a[u] | c;
X if (color[u] == neutral)
X {
X m += d; u = unmap[m];
X }
X else break;
X }
X }
X else
X for (j = Dstart[piece]; j <= Dstop[piece]; j++)
X if ((u = unmap[m0+Dir[j]]) >= 0)
X a[u] = ++a[u] | c;
X }
X}
X
X
Xint castle(side,kf,kt,iop)
Xshort side,kf,kt,iop;
X{
Xshort i,rf,rt,c1,c2,t0,xside;
X
X xside = otherside[side];
X if (kt > kf)
X {
X rf = kf+3; rt = kt-1; c1 = kf; c2 = rf;
X }
X else
X {
X rf = kf-4; rt = kt+1; c1 = rf; c2 = kf;
X }
X if (iop == 0)
X {
X if (board[kf] != king || board[rf] != rook || color[rf] != side)
X return(false);
X for (i = c1+1; i < c2; i++)
X if (color[i] != neutral) return(false);
X for (i = c1; i <= c2; i++)
X if (SqAtakd(i,xside)) return(false);
X }
X else
X {
X if (iop == 1) castld[side] = true; else castld[side] = false;
X if (iop == 2)
X {
X t0 = kt; kt = kf; kf = t0;
X t0 = rt; rt = rf; rf = t0;
X }
X board[kt] = king; color[kt] = side; Pindex[kt] = 0;
X board[kf] = no_piece; color[kf] = neutral;
X board[rt] = rook; color[rt] = side; Pindex[rt] = Pindex[rf];
X board[rf] = no_piece; color[rf] = neutral;
X PieceList[side][Pindex[kt]] = kt;
X PieceList[side][Pindex[rt]] = rt;
X UpdateHashbd(side,king,kf,kt);
X UpdateHashbd(side,rook,rf,rt);
X }
X return(true);
X}
X
X
Xen_passant(xside,f,t,iop)
Xshort xside,f,t,iop;
X{
Xshort l;
X if (t > f) l = t-8; else l = t+8;
X if (iop == 1)
X {
X board[l] = no_piece; color[l] = neutral;
X }
X else
X {
X board[l] = pawn; color[l] = xside;
X }
X InitializeStats();
X}
X
X
XLinkMove(ply,f,t,xside)
Xshort ply,f,t,xside;
X
X/*
X Add a move to the tree. Assign a bonus to order the moves
X as follows:
X 1. Principle variation
X 2. Capture of last moved piece
X 3. Other captures (major pieces first)
X 4. Killer moves
X 5. "history" killers
X*/
X
X{
Xregister short s;
Xregister unsigned short mv;
Xstruct leaf *node;
X
X node = &Tree[TrPnt[ply+1]];
X ++TrPnt[ply+1];
X node->flags = node->reply = 0;
X node->f = f; node->t = t; mv = (f<<8) + t;
X s = 0;
X if (mv == PV || mv == Swag0) s = 2000;
X else if (mv == Swag1) s = 80;
X else if (mv == Swag2) s = 70;
X else if (mv == Swag3) s = 60;
X else if (mv == Swag4) s = 40;
X else if (mv == Swag5) s = 30;
X if (color[t] != neutral)
X {
X node->flags |= capture;
X if (t == TOsquare) s += 800;
X s += value[board[t]] - board[f];
X }
X if (board[f] == pawn)
X {
X if (row[t] == 0 || row[t] == 7)
X {
X node->flags |= promote;
X s += 500;
X }
X else if (row[t] == 1 || row[t] == 6)
X {
X node->flags |= pwnthrt;
X s += 500;
X }
X else if (t == epsquare) node->flags |= epmask;
X }
X if (InChk)
X {
X if (board[f] == king)
X if (SqAtakd(t,xside)) s -= 200; else s += 400;
X if (mv == Qkillr[ply]) s += 200;
X }
X s += history[otherside[xside]-1][f][t];
X node->score = s-20000;
X}
X
X
XGenMoves(ply,loc,side,xside)
Xshort ply,loc,side,xside;
X
X/*
X Generate moves for a piece. The from square is mapped onto a 12 by
X 12 board and offsets (taken from array Dir[]) are added to the
X mapped location. Array unmap[] maps the move back onto array
X board[] (yielding a value of -1 if the to square is off the board).
X This process is repeated for bishops, rooks, and queens until a
X piece is encountered or the the move falls off the board. Legal
X moves are then linked into the tree.
X*/
X
X{
Xregister short m,u,d;
Xshort i,m0,piece;
X
X piece = board[loc]; m0 = map[loc];
X if (sweep[piece])
X for (i = Dstart[piece]; i <= Dstop[piece]; i++)
X {
X d = Dir[i]; m = m0+d; u = unmap[m];
X while (u >= 0)
X if (color[u] == neutral)
X {
X LinkMove(ply,loc,u,xside);
X m += d; u = unmap[m];
X }
X else if (color[u] == xside)
X {
X LinkMove(ply,loc,u,xside);
X break;
X }
X else break;
X }
X else if (piece == pawn)
X {
X if (side == white && color[loc+8] == neutral)
X {
X LinkMove(ply,loc,loc+8,xside);
X if (row[loc] == 1)
X if (color[loc+16] == neutral)
X LinkMove(ply,loc,loc+16,xside);
X }
X else if (side == black && color[loc-8] == neutral)
X {
X LinkMove(ply,loc,loc-8,xside);
X if (row[loc] == 6)
X if (color[loc-16] == neutral)
X LinkMove(ply,loc,loc-16,xside);
X }
X for (i = Dstart[piece]; i <= Dstop[piece]; i++)
X if ((u = unmap[m0+Dir[i]]) >= 0)
X if (color[u] == xside || u == epsquare)
X LinkMove(ply,loc,u,xside);
X }
X else
X {
X for (i = Dstart[piece]; i <= Dstop[piece]; i++)
X if ((u = unmap[m0+Dir[i]]) >= 0)
X if (color[u] != side)
X LinkMove(ply,loc,u,xside);
X }
X}
X
X
XMoveList(side,ply)
Xshort side,ply;
X
X/*
X Fill the array Tree[] with all available moves for side to
X play. Array TrPnt[ply] contains the index into Tree[]
X of the first move at a ply.
X*/
X
X{
Xregister short i;
Xshort xside,f;
X
X xside = otherside[side];
X Swag0 = killr0[ply]; Swag1 = killr1[ply]; Swag2 = killr2[ply];
X Swag3 = killr3[ply]; Swag4 = Swag5 = 0;
X if (ply > 2)
X {
X Swag4 = killr1[ply-2];
X Swag5 = killr3[ply-2];
X }
X TrPnt[ply+1] = TrPnt[ply];
X Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
X for (i = PieceCnt[side]; i >= 0; i--)
X GenMoves(ply,PieceList[side][i],side,xside);
X if (kingmoved[side] == 0)
X {
X f = PieceList[side][0];
X if (castle(side,f,f+2,0))
X {
X LinkMove(ply,f,f+2,xside);
X Tree[TrPnt[ply+1]-1].flags |= cstlmask;
X }
X if (castle(side,f,f-2,0))
X {
X LinkMove(ply,f,f-2,xside);
X Tree[TrPnt[ply+1]-1].flags |= cstlmask;
X }
X }
X sort(TrPnt[ply],TrPnt[ply+1]-1);
X}
X
X
X#define LinkCapture\
X{\
X node = &Tree[TrPnt[ply+1]];\
X ++TrPnt[ply+1];\
X node->f = loc; node->t = u;\
X node->reply = 0;\
X node->flags = capture;\
X node->score = value[board[u]] + svalue[board[u]] - piece;\
X if (piece == pawn && (u < 8 || u > 55))\
X {\
X node->flags |= promote;\
X node->score = valueQ;\
X }\
X}
X
X
XCaptureList(side,xside,ply)
Xshort side,xside,ply;
X
X/*
X Generate a list of captures similiarly to GenMoves.
X*/
X
X{
Xregister short m,u,d;
Xshort loc,i,j,m0,piece;
Xstruct leaf *node;
X
X TrPnt[ply+1] = TrPnt[ply];
X Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
X for (i = 0; i <= PieceCnt[side]; i++)
X {
X loc = PieceList[side][i];
X piece = board[loc]; m0 = map[loc];
X if (sweep[piece])
X for (j = Dstart[piece]; j <= Dstop[piece]; j++)
X {
X d = Dir[j]; m = m0+d; u = unmap[m];
X while (u >= 0)
X if (color[u] == neutral)
X {
X m += d; u = unmap[m];
X }
X else
X {
X if (color[u] == xside) LinkCapture;
X break;
X }
X }
X else
X {
X for (j = Dstart[piece]; j <= Dstop[piece]; j++)
X if ((u = unmap[m0+Dir[j]]) >= 0)
X if (color[u] == xside) LinkCapture;
X if (piece == pawn && row[loc] == rank7[side])
X {
X if (side == white) u = loc+8; else u = loc-8;
X if (color[u] == neutral) LinkCapture;
X }
X }
X }
X sort(TrPnt[ply],TrPnt[ply+1]-1);
X}
X
X
XMakeMove(side,node,tempb,tempc,temps)
Xshort side,*tempc,*tempb,*temps;
Xstruct leaf *node;
X
X/*
X Update Arrays board[], color[], and Pindex[] to reflect the new
X board position obtained after making the move pointed to by
X node. Also update miscellaneous stuff that changes when a move
X is made.
X*/
X
X{
Xregister short f,t;
Xshort xside;
X
X xside = otherside[side];
X f = node->f; t = node->t; epsquare = -1;
X TOsquare = t; cptrval = 0;
X GameList[++GameCnt].gmove = (f<<8) + t;
X if (node->flags & cstlmask)
X {
X GameList[GameCnt].piece = no_piece;
X GameList[GameCnt].color = side;
X castle(side,f,t,1);
X }
X else
X {
X *tempc = color[t]; *tempb = board[t]; *temps = svalue[t];
X GameList[GameCnt].piece = *tempb;
X GameList[GameCnt].color = *tempc;
X if (*tempc != neutral)
X {
X UpdatePieceList(*tempc,t,1);
X if (*tempb == pawn) --PawnCnt[*tempc][col[t]];
X if (board[f] == pawn)
X {
X --PawnCnt[side][col[f]];
X ++PawnCnt[side][col[t]];
X }
X mtl[xside] -= value[*tempb];
X if (*tempb == pawn) pmtl[xside] -= valueP;
X UpdateHashbd(xside,*tempb,-1,t);
X cptrval = *temps;
X }
X color[t] = color[f]; board[t] = board[f]; svalue[t] = svalue[f];
X Pindex[t] = Pindex[f]; PieceList[side][Pindex[t]] = t;
X color[f] = neutral; board[f] = no_piece;
X if (board[t] == pawn)
X if (t-f == 16) epsquare = f+8;
X else if (f-t == 16) epsquare = f-8;
X if (node->flags & promote)
X {
X board[t] = queen;
X --PawnCnt[side][col[t]];
X mtl[side] += valueQ - valueP;
X pmtl[side] -= valueP;
X HasQueen[side] = true;
X cptrval -= svalue[f];
X UpdateHashbd(side,pawn,f,-1);
X UpdateHashbd(side,queen,f,-1);
X }
X if (board[t] == king) ++kingmoved[side];
X if (node->flags & epmask) en_passant(xside,f,t,1);
X else UpdateHashbd(side,board[t],f,t);
X }
X}
X
X
XUnmakeMove(side,node,tempb,tempc,temps)
Xshort side,*tempc,*tempb,*temps;
Xstruct leaf *node;
X
X/*
X Take back the move pointed to by node.
X*/
X
X{
Xregister short f,t;
Xshort xside;
X
X xside = otherside[side];
X f = node->f; t = node->t; epsquare = -1;
X GameCnt--;
X if (node->flags & cstlmask) castle(side,f,t,2);
X else
X {
X color[f] = color[t]; board[f] = board[t]; svalue[f] = svalue[t];
X Pindex[f] = Pindex[t]; PieceList[side][Pindex[f]] = f;
X color[t] = *tempc; board[t] = *tempb; svalue[t] = *temps;
X if (node->flags & promote)
X {
X board[f] = pawn;
X ++PawnCnt[side][col[t]];
X mtl[side] += valueP - valueQ;
X pmtl[side] += valueP;
X UpdateHashbd(side,queen,-1,t);
X UpdateHashbd(side,pawn,-1,t);
X }
X if (*tempc != neutral)
X {
X UpdatePieceList(*tempc,t,2);
X if (*tempb == pawn) ++PawnCnt[*tempc][col[t]];
X if (board[f] == pawn)
X {
X --PawnCnt[side][col[t]];
X ++PawnCnt[side][col[f]];
X }
X mtl[xside] += value[*tempb];
X if (*tempb == pawn) pmtl[xside] += valueP;
X UpdateHashbd(xside,*tempb,-1,t);
X }
X if (board[f] == king) --kingmoved[side];
X if (node->flags & epmask) en_passant(xside,f,t,2);
X else UpdateHashbd(side,board[f],f,t);
X }
X}
X
X
Xdistance(a,b)
Xshort a,b;
X{
Xshort d1,d2;
X
X d1 = absv(col[a]-col[b]);
X d2 = absv(row[a]-row[b]);
X if (d1 > d2) return(d1); else return(d2);
X}
X
X
XBlendBoard(a,b,c)
Xshort a[64],b[64],c[64];
X{
Xregister int sq;
X for (sq = 0; sq < 64; sq++)
X c[sq] = (a[sq]*(10-stage) + b[sq]*stage) / 10;
X}
X
X
XCopyBoard(a,b)
Xshort a[64],b[64];
X{
Xregister int sq;
X for (sq = 0; sq < 64; sq++)
X b[sq] = a[sq];
X}
X
X
XUpdateWeights()
X{
Xshort tmtl;
X
X if (mtl[white] != Zwmtl || mtl[black] != Zbmtl)
X {
X Zwmtl = mtl[white]; Zbmtl = mtl[black];
X emtl[white] = Zwmtl - pmtl[white] - valueK;
X emtl[black] = Zbmtl - pmtl[black] - valueK;
X tmtl = emtl[white] + emtl[black];
X if (tmtl > 5700) stage = 0;
X else if (tmtl < 1300) stage = 10;
X else stage = (5700-tmtl) / 440;
X
X PEDRNK2B = -15; /* centre pawn on 2nd rank & blocked */
X PBKWRD = -6; /* backward pawns */
X PWEAKA = -3; /* each attack to weak pawn */
X PWEAKH = -3; /* weak pawn on half open file */
X PAWNSHIELD = 10-stage; /* pawn near friendly king */
X PADVNCM = (10+stage)/2; /* advanced pawn multiplier */
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
X RHOPN = 10; /* rook on half open file */
X RHOPNX = 4;
X
X XRAY = 8; /* Xray attack on major piece */
X
X KHOPN = (3*stage-30) / 2; /* king on half open file */
X KHOPNX = KHOPN / 2;
X KCASTLD = 10 / (stage+1); /* king castled */
X KMOVD = -40 / (stage+1); /* king moved before castling */
X KATAK = 5; /* B,R attacks near enemy king */
X if (stage < 8) KSFTY = 8-stage; else KSFTY = 0;
X
X ATAKD = -6; /* defender > attacker */
X HUNGP = -8; /* each hung piece */
X HUNGX = -10; /* extra for >1 hung piece */
X }
X}
X
X
XExaminePosition()
X/*
X This is done one time before the search is started.
X Set up arrays Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used
X in the SqValue() function to determine the positional value of each
X piece.
X*/
X{
Xregister short i,sq;
Xshort r,wpadv,bpadv,z,side,pp,j;
Xlong stage2,tpmtl,Pd,val;
X
X wking = PieceList[white][0]; bking = PieceList[black][0];
X ataks(white,atak[white]); ataks(black,atak[black]);
X Zwmtl = Zbmtl = 0;
X UpdateWeights();
X stage2 = stage*stage; tpmtl = pmtl[white] + pmtl[black];
X HasPawn[white] = HasPawn[black] = false;
X HasKnight[white] = HasKnight[black] = false;
X HasBishop[white] = HasBishop[black] = false;
X HasRook[white] = HasRook[black] = false;
X HasQueen[white] = HasQueen[black] = false;
X for (side = white; side <= black; side++)
X for (i = 0; i <= PieceCnt[side]; i++)
X switch (board[PieceList[side][i]])
X {
X case pawn : HasPawn[side] = true; break;
X case knight : HasKnight[side] = true; break;
X case bishop : HasBishop[side] = true; break;
X case rook : HasRook[side] = true; break;
X case queen : HasQueen[side] = true; 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
X for (sq = 0; sq < 64; sq++)
X {
X WeakSq[white][sq] = WeakSq[black][sq] = true;
X for (i = sq; i >= 0; i -= 8)
X if (atak[white][i] >= ctlP) WeakSq[white][sq] = false;
X for (i = sq; i < 64; i += 8)
X if (atak[black][i] >= ctlP) WeakSq[black][sq] = false;
X Kfield[white][sq] = Kfield[black][sq] = 0;
X }
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 if (!Developed[white])
X {
X Mknight[white][1] -= 5;
X Mbishop[white][2] -= 5;
X Mbishop[white][5] -= 5;
X Mknight[white][6] -= 5;
X }
X if (!Developed[black])
X {
X Mknight[black][57] -= 5;
X Mbishop[black][58] -= 5;
X Mbishop[black][61] -= 5;
X Mknight[black][62] -= 5;
X }
X
X for (sq = 0; sq < 64; sq++)
X {
X wpadv = bpadv = PADVNCM;
X Mwpawn[sq] = (wpadv*PawnAdvance[sq]) / 10;
X Mbpawn[sq] = (bpadv*PawnAdvance[63-sq]) / 10;
X if (distance(sq,wking) < 3 && (col[sq] < 3 || col[sq] > 4))
X Mwpawn[sq] += PAWNSHIELD;
X if (distance(sq,bking) < 3 && (col[sq] < 3 || col[sq] > 4))
X Mbpawn[sq] += PAWNSHIELD;
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] += stage;
X Mbishop[black][sq] += stage;
X for (i = 0; i <= PieceCnt[black]; i++)
X if (distance(sq,PieceList[black][i]) < 3)
X Mknight[white][sq] += KNIGHTPOST;
X for (i = 0; i <= PieceCnt[white]; i++)
X if (distance(sq,PieceList[white][i]) < 3)
X Mknight[black][sq] += KNIGHTPOST;
X if (WeakSq[black][sq]) Mknight[white][sq] += KNIGHTSTRONG;
X if (WeakSq[white][sq]) Mknight[black][sq] += KNIGHTSTRONG;
X if (WeakSq[black][sq]) Mbishop[white][sq] += BISHOPSTRONG;
X if (WeakSq[white][sq]) Mbishop[black][sq] += BISHOPSTRONG;
X
X Pd = 0;
X for (i = 0; i < 64; i++)
X if (board[i] == pawn)
X {
X if (color[i] == white)
X {
X r = row[i]+3; pp = true;
X if (row[i] == 6) z = i+8; else z = i+16;
X for (j = i+8; j < 64; j += 8)
X if (!WeakSq[black][j]) pp = false;
X }
X else
X {
X r = 10-row[i]; pp = true;
X if (row[i] == 1) z = i-8; else z = i-16;
X for (j = i-8; j >= 0; j -= 8)
X if (!WeakSq[white][j]) pp = false;
X }
X if (pp) r *= 4;
X Pd += r*distance(sq,z);
X }
X if (tpmtl > 0)
X {
X val = (Pd*stage2) / (2*tpmtl);
X Mking[white][sq] -= (short)val;
X Mking[black][sq] -= (short)val;
X }
X
X if (distance(sq,wking) == 1) Kfield[black][sq] += KATAK;
X if (distance(sq,bking) == 1) Kfield[white][sq] += KATAK;
X }
X}
X
X
Xint trapped(loc,piece)
Xshort loc,piece;
X/*
X See if the attacked piece has unattacked squares to move to.
X If it is trapped, increment the hung[] array so that the search
X will be extended.
X*/
X{
Xregister short u,m,d;
Xshort i,m0;
X
X m0 = map[loc];
X if (sweep[piece])
X for (i = Dstart[piece]; i <= Dstop[piece]; i++)
X {
X d = Dir[i]; m = m0+d; u = unmap[m];
X while (u >= 0)
X if (color[u] == c1) break;
X else if (atak[c2][u] == 0 || board[u] >= piece) return(false);
X else if (color[u] == c2) break;
X else
X {
X m += d; u = unmap[m];
X }
X }
X else if (piece == pawn)
X {
X if (c1 == white) u = loc+8; else u = loc-8;
X if (color[u] == neutral && atak[c1][u] >= atak[c2][u])
X return(false);
X for (i = 0; i <= 1; i++)
X if ((u = unmap[m0+Dir[Dpwn[c1]+i]]) >= 0)
X if (color[u] == c2) return(false);
X }
X else
X {
X for (i = Dstart[piece]; i <= Dstop[piece]; i++)
X if ((u = unmap[m0+Dir[i]]) >= 0)
X if (color[u] != c1)
X if (atak[c2][u] == 0 || board[u] >= piece) return(false);
X }
X return(true);
X}
X
X
X#define ScoreThreat\
X if (color[u] != c2)\
X if (atak[c1][u] == 0 || (atak[c2][u] & 0xFF) > 1) ++cnt;\
X else *s -= 3
X
X
XKingScan(loc,s)
Xshort loc,*s;
X/*
X Assign penalty if king can be threatened by checks or if
X squares adjacent to the king have a bad attack/defence balance.
X*/
X{
Xregister short m,u,d;
Xshort i,m0,cnt,z;
X
X cnt = z = 0;
X m0 = map[loc];
X if (HasBishop[c2] || HasQueen[c2])
X for (i = Dstart[bishop]; i <= Dstop[bishop]; i++)
X {
X d = Dir[i]; m = m0+d; u = unmap[m];
X if (u >= 0 && atak[c2][u] > atak[c1][u]) z++;
X while (u >= 0)
X {
X if (atak[c2][u] & ctlBQ) ScoreThreat;
X if (color[u] != neutral) break;
X m += d; u = unmap[m];
X }
X }
X if (HasRook[c2] || HasQueen[c2])
X for (i = Dstart[rook]; i <= Dstop[rook]; i++)
X {
X d = Dir[i]; m = m0+d; u = unmap[m];
X if (u >= 0 && atak[c2][u] > atak[c1][u]) z++;
X while (u >= 0)
X {
X if (atak[c2][u] & ctlRQ) ScoreThreat;
X if (color[u] != neutral) break;
X m += d; u = unmap[m];
X }
X }
X if (HasKnight[c2])
X for (i = Dstart[knight]; i <= Dstop[knight]; i++)
X if ((u = unmap[m0+Dir[i]]) >= 0)
X if (atak[c2][u] & ctlNN) ScoreThreat;
X
X if (z > 2) cnt++;
X *s += (KSFTY*Kthreat[cnt]) / 8;
X}
X
X
XBRscan(loc,s,mob)
Xshort loc,*s,*mob;
X/*
X Find B,R mobility, XRAY attacks, and pins.
X Increment the hung[] array if a pin is found.
X*/
X{
Xregister short m,u,d;
Xshort j,m0,s0,piece,pin;
X
X *mob = 0;
X piece = board[loc]; m0 = map[loc];
X for (j = Dstart[piece]; j <= Dstop[piece]; j++)
X {
X s0 = 2;
X d = Dir[j]; m = m0+d; u = unmap[m];
X while (u >= 0)
X {
X *s += Kfield[c1][u];
X if (color[u] == neutral)
X {
X *mob += s0;
X m += d; u = unmap[m];
X }
X else if (board[u] == pawn) break;
X else if (s0 == 2)
X {
X pin = u; s0 = 1;
X m += d; u = unmap[m];
X }
X else if (color[u] == c2 && (board[u] > piece || atak[c2][u] == 0))
X {
X *s += XRAY;
X if (color[pin] == c2)
X if (atak[c2][pin] == 0 ||
X atak[c1][pin] > control[board[pin]]+1)
X ++hung[c2];
X break;
X }
X else break;
X }
X }
X}
X
X
Xint SqValue(loc,side)
X
X/* Calculate the positional value for the piece on 'loc'. */
X
Xshort loc,side;
X{
Xregister short j,rank,column;
Xshort s,piece,a1,a2,e,m0,u,in_square,r,mob;
X
X piece = board[loc];
X a1 = (atak[c1][loc] & 0x4FFF); a2 = (atak[c2][loc] & 0x4FFF);
X rank = row[loc]; column = col[loc];
X s = 0;
X if (piece == pawn && c1 == white)
X {
X s = Mwpawn[loc];
X if (loc == 11 || loc == 12)
X if (color[loc+8] != neutral) s += PEDRNK2B;
X if ((column == 0 || PawnCnt[white][column-1] == 0) &&
X (column == 7 || PawnCnt[white][column+1] == 0))
X s += ISOLANI[column];
X else if (PawnCnt[white][column] > 1) s += DOUBLED[column];
X if (a1 < ctlP && atak[white][loc+8] < ctlP)
X {
X s += PBKWRD;
X s += PWEAKA * (a2 & 0xFF);
X if (PawnCnt[black][column] == 0) s += PWEAKH;
X if (color[loc+8] != neutral) s -= 3;
X }
X if (PawnCnt[black][column] == 0)
X {
X if (side == black) r = rank-1; else r = rank;
X in_square = (row[bking] >= r && distance(loc,bking) < 8-r);
X if (a2 == 0 || side == white) e = 0; else e = 1;
X for (j = loc+8; j < 64; j += 8)
X if (atak[black][j] >= ctlP) j = 99;
X else if (atak[black][j] > 0 || color[j] != neutral) e = 1;
X if (j == 99) s += (stage*passed_pawn3[rank]) / 10;
X else
X {
X if (in_square || e == 1) s += (stage*passed_pawn2[rank]) / 10;
X else s += (stage*passed_pawn1[rank]) / 10;
X if (color[loc+8] != neutral) s -= 8;
X }
X }
X }
X else if (piece == pawn && c1 == black)
X {
X s = Mbpawn[loc];
X if (loc == 51 || loc == 52)
X if (color[loc-8] != neutral) s += PEDRNK2B;
X if ((column == 0 || PawnCnt[black][column-1] == 0) &&
X (column == 7 || PawnCnt[black][column+1] == 0))
X s += ISOLANI[column];
X else if (PawnCnt[black][column] > 1) s += DOUBLED[column];
X if (a1 < ctlP && atak[black][loc-8] < ctlP)
X {
X s += PBKWRD;
X s += PWEAKA * (a2 & 0xFF);
X if (PawnCnt[white][column] == 0) s += PWEAKH;
X if (color[loc-8] != neutral) s -= 3;
X }
X if (PawnCnt[white][column] == 0)
X {
X if (side == white) r = rank+1; else r = rank;
X in_square = (row[wking] <= r && distance(loc,wking) < r+1);
X if (a2 == 0 || side == black) e = 0; else e = 1;
X for (j = loc-8; j >= 0; j -= 8)
X if (atak[white][j] >= ctlP) j = -99;
X else if (atak[white][j] > 0 || color[j] != neutral) e = 1;
X if (j == -99) s += (stage*passed_pawn3[7-rank]) / 10;
X else
X {
X if (in_square || e == 1) s += (stage*passed_pawn2[7-rank]) / 10;
X else s += (stage*passed_pawn1[7-rank]) / 10;
X if (color[loc-8] != neutral) s -= 8;
X }
X }
X }
X else if (piece == knight)
X {
X s = Mknight[c1][loc];
X }
X else if (piece == bishop)
X {
X s = Mbishop[c1][loc];
X BRscan(loc,&s,&mob);
X s += BMBLTY[mob];
X }
X else if (piece == rook)
X {
X if (PawnCnt[c1][column] == 0) s += RHOPN;
X if (PawnCnt[c2][column] == 0) s += RHOPNX;
X BRscan(loc,&s,&mob);
X if (stage < 3) s += RMBLTY[mob] / 2;
X else
X {
X s += RMBLTY[mob];
X if (c1 == white) s += 14 - taxicab(loc,bking);
X else s += 14 - taxicab(loc,wking);
X }
X }
X else if (piece == queen)
X {
X if (stage > 3)
X if (c1 == white) s += 14 - taxicab(loc,bking);
X else s += 14 - taxicab(loc,wking);
X }
X else if (piece == king)
X {
X if (Developed[c2] && KSFTY > 0) KingScan(loc,&s);
X if (castld[c1]) s += KCASTLD;
X else if (kingmoved[c1] > 0) s += KMOVD;
X
X if (PawnCnt[c1][column] == 0) s += KHOPN;
X if (PawnCnt[c2][column] == 0) s += KHOPNX;
X if (column == 1 || column == 2 || column == 3 || column == 7)
X {
X if (PawnCnt[c1][column-1] == 0) s += KHOPN;
X if (PawnCnt[c2][column-1] == 0) s += KHOPNX;
X }
X if (column == 4 || column == 5 || column == 6 || column == 0)
X {
X if (PawnCnt[c1][column+1] == 0) s += KHOPN;
X if (PawnCnt[c2][column+1] == 0) s += KHOPNX;
X }
X
X if (stage < 8) s += Mking[c1][loc];
X else
X {
X e = Mking[c1][loc];
X m0 = map[loc];
X for (j = Dstart[king]; j <= Dstop[king]; j++)
X if ((u = unmap[m0+Dir[j]]) >= 0)
X if (atak[c2][u] == 0)
X if (Mking[c1][u] > e) e = Mking[c1][u];
X s += (Mking[c1][loc] + e) / 2;
X }
X }
X if (a2 > 0)
X if (a1 == 0 || a2 > control[piece]+1)
X {
X s += HUNGP;
X ++hung[c1];
X if (piece != king && trapped(loc,piece)) ++hung[c1];
X }
X else if (a2 > a1) s += ATAKD;
X return(s);
X}
X
X
XScoreLoneKing(side,score)
Xshort side,*score;
X/*
X static evaluation when loser has only a king and winner has no pawns
X and mating material.
X*/
X{
Xshort winner,loser,s;
X
X UpdateWeights();
X if (mtl[white] > mtl[black]) winner = white; else winner = black;
X loser = otherside[winner];
X if (emtl[winner] <= valueB) *score = 0;
X else
X {
X s = 4995 + emtl[winner] -
X DyingKing[PieceList[loser][0]] -
X 2*distance(PieceList[winner][0],PieceList[loser][0]);
X if (side == winner) *score = s; else *score = -s;
X }
X}
X
X
XScorePosition(side,score)
Xshort side,*score;
X
X/* Perform static evaluation of board position. */
X
X{
Xregister short loc,i;
Xshort s,xside,pscore[3];
X
X wking = PieceList[white][0]; bking = PieceList[black][0];
X UpdateWeights();
X xside = otherside[side];
X pscore[white] = pscore[black] = 0;
X
X for (c1 = white; c1 <= black; c1++)
X {
X c2 = otherside[c1];
X for (i = 0; i <= PieceCnt[c1]; i++)
X {
X loc = PieceList[c1][i];
X s = SqValue(loc,side);
X pscore[c1] += s;
X svalue[loc] = s;
X }
X }
X if (hung[side] > 1) pscore[side] += HUNGX;
X if (hung[xside] > 1) pscore[xside] += HUNGX;
X *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
X if (randflag) *score += rand() % 5;
X if (*score > 0 && pmtl[side] == 0 && emtl[side] <= valueB)
X *score = 0;
X if (*score < 0 && pmtl[xside] == 0 && emtl[xside] <= valueB)
X *score = 0;
X if (mtl[xside] == valueK && emtl[side] > valueB) *score += 200;
X if (mtl[side] == valueK && emtl[xside] > valueB) *score -= 200;
X}
X
X
X#define UpdateSearchStatus\
X{\
X if (post)\
X {\
X algbr(node->f,node->t,false);\
X gotoXY(65,1); printz("%5s ",mvstr1);\
X }\
X if (pnt > TrPnt[1])\
X {\
X d = best-Zscore; e = best-node->score;\
X if (Sdepth == 1) ExtraTime = 10;\
X else if (best < alpha)\
X {\
X if (alpha - best > 800) ExtraTime = 5*ResponseTime;\
X else ExtraTime = 3*ResponseTime;\
X }\
X else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
X else if (d > -zwndw) ExtraTime = 0;\
X else if (d > -3*zwndw) ExtraTime = ResponseTime;\
X else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
X else ExtraTime = 5*ResponseTime;\
X }\
X}
X
X
Xint evaluate(side,xside,ply,depth,alpha,beta)
Xshort side,xside,ply,depth,alpha,beta;
X
X/*
X Compute an estimate of the score by adding the positional score
X from the previous ply to the material difference. If in the
X quiescence search return this estimate, otherwise call
X ScorePosition() to determine the score.
X*/
X
X{
Xshort s;
X
X hung[white] = hung[black] = 0;
X slk = ((mtl[white] == valueK && pmtl[black] == 0) ||
X (mtl[black] == valueK && pmtl[white] == 0));
X s = -Pscore[ply-1] - cptrval + mtl[side] - mtl[xside];
X if (ply == 1 || slk ||
X (ply == Sdepth+1 && s-250 < beta) ||
X (ply == Sdepth+2 && s-prune < beta) ||
X (ply == Sdepth+3 && board[TOsquare] == pawn && s-prune < beta))
X {
X EvalNodes++;
X ataks(side,atak[side]);
X ataks(xside,atak[xside]);
X if (atak[side][PieceList[xside][0]] > 0) s = 10001-ply;
X else if (slk) ScoreLoneKing(side,&s);
X else ScorePosition(side,&s);
X InChk = (atak[xside][PieceList[side][0]] > 0);
X }
X else
X {
X if (CptrFlag[ply-1] && board[TOsquare] == pawn) s += 10;
X if (SqAtakd(PieceList[xside][0],side)) s = 10001-ply;
X InChk = SqAtakd(PieceList[side][0],xside);
X }
X Pscore[ply] = s - mtl[side] + mtl[xside];
X if (InChk) ChkFlag[ply-1] = Pindex[TOsquare];
X else ChkFlag[ply-1] = 0;
X Threat[ply-1] = (hung[side] > 1 && ply == Sdepth+1);
X return(s);
X}
X
X
Xint FoundInTTable(side,depth,alpha,beta,score)
Xshort side,depth,*alpha,*beta,*score;
X{
Xshort hindx;
X if (!hashflag) return(false);
X if (side == white) hashkey |= 1; else hashkey &= 0xFFFE;
X hindx = (hashkey & (ttblsz-1));
X ptbl = (ttable+hindx);
X if (ptbl->depth >= depth && ptbl->hashbd == hashbd)
X {
X HashCnt++;
X PV = ptbl->reply;
X if (ptbl->flags & truescore)
X {
X *score = ptbl->score;
X return(true);
X }
X/*
X else if (ptbl->flags & upperbound)
X {
X if (ptbl->score < *alpha)
X {
X *score = ptbl->score;
X return(true);
X }
X }
X*/
X else if (ptbl->flags & lowerbound)
X {
X if (ptbl->score > *alpha) *alpha = ptbl->score;
X }
X }
X return(false);
X}
X
X
XPutInTTable(side,score,depth,alpha,beta,reply)
Xshort side,score,depth,alpha,beta;
Xunsigned short reply;
X{
Xshort hindx;
X if (side == white) hashkey |= 1; else hashkey &= 0xFFFE;
X hindx = (hashkey & (ttblsz-1));
X ptbl = (ttable+hindx);
X ptbl->hashbd = hashbd;
X ptbl->depth = depth;
X ptbl->score = score;
X ptbl->reply = reply;
X ptbl->flags = 0;
X if (score < alpha)
X ptbl->flags |= upperbound;
X else if (score > beta)
X ptbl->flags |= lowerbound;
X else ptbl->flags |= truescore;
X}
X
X
Xint search(side,ply,depth,alpha,beta,bstline,rpt)
Xshort side,ply,depth,alpha,beta,*rpt;
Xunsigned short bstline[];
X
X/*
X Perform an alpha-beta search to determine the score for the
X current board position. If depth <= 0 only capturing moves are
X generated and searched, otherwise all moves are processed. The
X search depth is modified for check evasions, some forcing checks
X and for certain threats. Extensions may continue for up to 11
X ply beyond the nominal search depth.
X*/
X
X{
X#define cut (cf && score+node->score < alpha)
X
Xregister short j;
Xshort best,tempb,tempc,temps,xside,pnt,pbst,d,e,cf,score,in_check,xdepth,rcnt;
Xunsigned short mv,nxtline[maxdepth];
Xstruct leaf *node,tmp;
X
X NodeCnt++;
X xside = otherside[side];
X xdepth = depth;
X
X if (ply <= Sdepth+1) repetition(rpt); else *rpt = 0;
X if (*rpt >= 2) return(0);
X
X score = evaluate(side,xside,ply,depth,alpha,beta);
X in_check = InChk;
X if (score > 9000) return(score);
X
X if (in_check && depth > 0) ++depth;
X else if (depth < 1 && score >= alpha &&
X (in_check || PawnThreat[ply-1] || Threat[ply-1]))
X depth = 1;
X else if (depth < 1 && score <= beta && ply < Sdepth+4 &&
X ply > 4 && ChkFlag[ply-2] && ChkFlag[ply-4] &&
X ChkFlag[ply-2] != ChkFlag[ply-4])
X depth = 1;
X if (depth > 0)
X {
X if (FoundInTTable(side,depth,&alpha,&beta,&score))
X return(score);
X if (alpha > beta) return(alpha);
X }
X
X if (Sdepth == 1) d = 7; else d = 11;
X if (ply > Sdepth+d || (depth < 1 && score > beta)) return(score);
X
X if (ply > 1)
X if (depth > 0) MoveList(side,ply);
X else CaptureList(side,xside,ply);
X
X if (TrPnt[ply] == TrPnt[ply+1]) return(score);
X
X cf = (depth < 1 && !ChkFlag[ply-2] && !slk);
X
X if (depth > 0) best = -12000; else best = score;
X if (best > alpha) alpha = best;
X
X for (pnt = pbst = TrPnt[ply];
X pnt < TrPnt[ply+1] && best <= beta && !timeout;
X pnt++)
X {
X node = &Tree[pnt];
X nxtline[ply+1] = 0;
X
X if (cut) continue;
X if (ply == 1) UpdateSearchStatus;
X
X if (!(node->flags & exact))
X {
X MakeMove(side,node,&tempb,&tempc,&temps);
X CptrFlag[ply] = (node->flags & capture);
X PawnThreat[ply] = (node->flags & pwnthrt);
X Tscore[ply] = node->score;
X PV = node->reply;
X node->score = -search(xside,ply+1,depth-1,-beta,-alpha,
X nxtline,&rcnt);
X if (absv(node->score) > 9000) node->flags |= exact;
X else if (rcnt == 1)
X if (node->score > contempt[side]+20) node->score -= 20;
X else if (node->score < contempt[side]-20) node->score += 20;
X if (rcnt >= 2 || GameCnt-Game50 > 99 ||
X (node->score == 9999-ply && !ChkFlag[ply]))
X {
X node->flags |= draw; node->flags |= exact;
X node->score = contempt[side];
X }
X node->reply = nxtline[ply+1];
X UnmakeMove(side,node,&tempb,&tempc,&temps);
X }
X if (node->score > best && !timeout)
X {
X if (depth > 0)
X if (node->score > alpha && !(node->flags & exact))
X node->score += depth;
X best = node->score; pbst = pnt;
X if (best > alpha) alpha = best;
X for (j = ply+1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
X bstline[j] = 0;
X bstline[ply] = (node->f<<8) + node->t;
X if (ply == 1)
X {
X if (post) post_move(node);
X if (best == alpha)
X {
X tmp = Tree[pnt];
X for (j = pnt-1; j >= 0; j--) Tree[j+1] = Tree[j];
X Tree[0] = tmp;
X }
X if (Sdepth > 2)
X if (best > beta) ShowResults('+');
X else if (best < alpha) ShowResults('-');
X else ShowResults('&');
X }
X }
X if (NodeCnt > ETnodes) ElapsedTime(0);
X }
X if (ply == 1) node = &Tree[0]; else node = &Tree[pbst];
X mv = (node->f<<8) + node->t;
X if (ply <= Sdepth && *rpt == 0 && !timeout && hashflag)
X PutInTTable(side,best,xdepth,alpha,beta,bstline[ply+1]);
X if (depth > 0)
X if (history[side-1][node->f][node->t] < 180)
X history[side-1][node->f][node->t] += depth;
X if (node->t != (GameList[GameCnt].gmove & 0xFF))
X if (best <= beta) killr3[ply] = mv;
X else if (mv != killr1[ply])
X {
X killr2[ply] = killr1[ply];
X killr1[ply] = mv;
X }
X if (in_check && best > -9000) Qkillr[ply] = mv;
X if (best > 9000) killr0[ply] = mv; else killr0[ply] = 0;
X if (timeout || (best < alpha && -Tscore[ply-1] < best))
X best = -Tscore[ply-1];
X return(best);
X}
X
END_OF_gnuchess.c2
if test 39696 -ne `wc -c <gnuchess.c2`; then
echo shar: \"gnuchess.c2\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 3 \(of 3\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0