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