games@tekred.TEK.COM (06/11/88)
Submitted by: John Stanback <jhs@hpltbm.HP.COM> Comp.sources.games: Volume 4, Issue 40 Archive-name: gnuchess2/Part04 #! /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 4 (of 4)." # Contents: gnuchess.c2 # Wrapped by billr@saab on Fri Jun 10 17:01:32 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\" \(19818 characters\) sed "s/^X//" >gnuchess.c2 <<'END_OF_gnuchess.c2' X X/* ............ POSITIONAL EVALUATION ROUTINES ............ */ X XScorePosition(side,score) Xshort side,*score; X X/* X Perform normal static evaluation of board position. A score is X generated for each piece and these are summed to get a score for each X side. X*/ X X{ Xregister short sq,s,i,xside; Xshort 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 if (c1 == white) EnemyKing = bking; else EnemyKing = wking; X atk1 = atak[c1]; atk2 = atak[c2]; X PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2]; X for (i = 0; i <= PieceCnt[c1]; i++) X { X sq = PieceList[c1][i]; X s = SqValue(sq,side); X pscore[c1] += s; X svalue[sq] = s; X } X } X if (hung[side] > 1) pscore[side] += HUNGX; X if (hung[xside] > 1) pscore[xside] += HUNGX; X X *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10; X if (dither) *score += rand() % dither; X X if (*score > 0 && pmtl[side] == 0) X if (emtl[side] < valueR) *score = 0; X else if (*score < valueR) *score /= 2; X if (*score < 0 && pmtl[xside] == 0) X if (emtl[xside] < valueR) *score = 0; X else if (-*score < valueR) *score /= 2; X X if (mtl[xside] == valueK && emtl[side] > valueB) *score += 200; X if (mtl[side] == valueK && emtl[xside] > valueB) *score -= 200; X} X X XScoreLoneKing(side,score) Xshort side,*score; X X/* X Static evaluation when loser has only a king and winner has no pawns X or no pieces. X*/ X X{ Xregister short winner,loser,king1,king2,s,i; X X UpdateWeights(); X if (mtl[white] > mtl[black]) winner = white; else winner = black; X loser = otherside[winner]; X king1 = PieceList[winner][0]; 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] - 2*KingEnding[king2] - 2*distance(king1,king2); X X if (side == winner) *score = s; else *score = -s; X} X X Xint ScoreKPK(side,winner,loser,king1,king2,sq) Xshort side,winner,loser,king1,king2,sq; X X/* X Score King and Pawns versus King endings. X*/ X X{ Xregister short s,r; X X if (PieceCnt[winner] == 1) s = 50; else s = 120; X if (winner == white) X { X if (side == loser) r = row[sq]-1; else r = row[sq]; X if (row[king2] >= r && distance(sq,king2) < 8-r) s += 10*row[sq]; X else s = 500+50*row[sq]; X if (row[sq] < 6) sq += 16; else sq += 8; X } X else X { X if (side == loser) r = row[sq]+1; else r = row[sq]; X if (row[king2] <= r && distance(sq,king2) < r+1) s += 10*(7-row[sq]); X else s = 500+50*(7-row[sq]); X if (row[sq] > 1) sq -= 16; else sq -= 8; X } X s += 8*(taxicab(king2,sq) - taxicab(king1,sq)); X return(s); X} X X Xint ScoreKBNK(winner,king1,king2) Xshort winner,king1,king2; X X/* X Score King+Bishop+Knight versus King endings. X This doesn't work all that well but it's better than nothing. X*/ X X{ Xregister short s; X s = emtl[winner] - 300; X if (KBNKsq == 0) s += KBNK[king2]; X else s += KBNK[locn[row[king2]][7-column[king2]]]; X s -= taxicab(king1,king2); X s -= distance(PieceList[winner][1],king2); X s -= distance(PieceList[winner][2],king2); X return(s); X} X X XSqValue(sq,side) Xshort sq,side; X X/* X Calculate the positional value for the piece on 'sq'. X*/ X X{ Xregister short j,fyle,rank,a1,a2; Xshort s,piece,in_square,r,mob,e,c; X X piece = board[sq]; X a1 = (atk1[sq] & 0x4FFF); a2 = (atk2[sq] & 0x4FFF); X rank = row[sq]; fyle = column[sq]; X s = 0; X if (piece == pawn && c1 == white) X { X s = Mwpawn[sq]; X if (sq == 11 || sq == 12) X if (color[sq+8] != neutral) s += PEDRNK2B; X if ((fyle == 0 || PC1[fyle-1] == 0) && X (fyle == 7 || PC1[fyle+1] == 0)) X s += ISOLANI[fyle]; X else if (PC1[fyle] > 1) s += PDOUBLED; X if (a1 < ctlP && atk1[sq+8] < ctlP) X { X s += BACKWARD[a2 & 0xFF]; X if (PC2[fyle] == 0) s += PWEAKH; X if (color[sq+8] != neutral) s += PBLOK; X } X if (PC2[fyle] == 0) X { X if (side == black) r = rank-1; else r = rank; X in_square = (row[bking] >= r && distance(sq,bking) < 8-r); X if (a2 == 0 || side == white) e = 0; else e = 1; X for (j = sq+8; j < 64; j += 8) X if (atk2[j] >= ctlP) { e = 2; break; } X else if (atk2[j] > 0 || color[j] != neutral) e = 1; X if (e == 2) s += (stage*PassedPawn3[rank]) / 10; X else if (in_square || e == 1) s += (stage*PassedPawn2[rank]) / 10; X else if (emtl[black] > 0) s += (stage*PassedPawn1[rank]) / 10; X else s += PassedPawn0[rank]; X } X } X else if (piece == pawn && c1 == black) X { X s = Mbpawn[sq]; X if (sq == 51 || sq == 52) X if (color[sq-8] != neutral) s += PEDRNK2B; X if ((fyle == 0 || PC1[fyle-1] == 0) && X (fyle == 7 || PC1[fyle+1] == 0)) X s += ISOLANI[fyle]; X else if (PC1[fyle] > 1) s += PDOUBLED; X if (a1 < ctlP && atk1[sq-8] < ctlP) X { X s += BACKWARD[a2 & 0xFF]; X if (PC2[fyle] == 0) s += PWEAKH; X if (color[sq-8] != neutral) s += PBLOK; X } X if (PC2[fyle] == 0) X { X if (side == white) r = rank+1; else r = rank; X in_square = (row[wking] <= r && distance(sq,wking) < r+1); X if (a2 == 0 || side == black) e = 0; else e = 1; X for (j = sq-8; j >= 0; j -= 8) X if (atk2[j] >= ctlP) { e = 2; break; } X else if (atk2[j] > 0 || color[j] != neutral) e = 1; X if (e == 2) s += (stage*PassedPawn3[7-rank]) / 10; X else if (in_square || e == 1) s += (stage*PassedPawn2[7-rank]) / 10; X else if (emtl[white] > 0) s += (stage*PassedPawn1[7-rank]) / 10; X else s += PassedPawn0[7-rank]; X } X } X else if (piece == knight) X { X s = Mknight[c1][sq]; X } X else if (piece == bishop) X { X s = Mbishop[c1][sq]; X BRscan(sq,&s,&mob); X s += BMBLTY[mob]; X } X else if (piece == rook) X { X s += RookBonus; X BRscan(sq,&s,&mob); X s += RMBLTY[mob]; X if (PC1[fyle] == 0) s += RHOPN; X if (PC2[fyle] == 0) s += RHOPNX; X if (rank == rank7[c1] && pmtl[c2] > 100) s += 10; X if (stage > 2) s += 14 - taxicab(sq,EnemyKing); X } X else if (piece == queen) X { X if (stage > 2) s += 14 - taxicab(sq,EnemyKing); X if (distance(sq,EnemyKing) < 3) s += 12; X } X else if (piece == king) X { X s = Mking[c1][sq]; X if (KSFTY > 0) X if (Developed[c2] || stage > 0) KingScan(sq,&s); X if (castld[c1]) s += KCASTLD; X else if (kingmoved[c1]) s += KMOVD; X X if (PC1[fyle] == 0) s += KHOPN; X if (PC2[fyle] == 0) s += KHOPNX; X if (fyle == 1 || fyle == 2 || fyle == 3 || fyle == 7) X { X if (PC1[fyle-1] == 0) s += KHOPN; X if (PC2[fyle-1] == 0) s += KHOPNX; X } X if (fyle == 4 || fyle == 5 || fyle == 6 || fyle == 0) X { X if (PC1[fyle+1] == 0) s += KHOPN; X if (PC2[fyle+1] == 0) s += KHOPNX; X } X if (fyle == 2) X { X if (PC1[0] == 0) s += KHOPN; X if (PC2[0] == 0) s += KHOPNX; X } X if (fyle == 5) X { X if (PC1[7] == 0) s += KHOPN; X if (PC2[7] == 0) s += KHOPNX; X } X } X X if (a2 > 0) X { X c = (control[piece] & 0x4FFF); X if (a1 == 0 || a2 > c+1) X { X s += HUNGP; X ++hung[c1]; X if (piece != king && trapped(sq,piece)) ++hung[c1]; X } X else if (piece != pawn || a2 > a1) X if (a2 >= c || a1 < ctlP) s += ATAKD; X } X return(s); X} X X XKingScan(sq,s) Xshort sq,*s; X X/* X Assign penalties if king can be threatened by checks, if squares X near the king are controlled by the enemy (especially the queen), X or if there are no pawns near the king. 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{ Xregister short m,u,d,i,m0,cnt,ok; X X cnt = 0; X m0 = map[sq]; X if (HasBishop[c2] || HasQueen[c2]) X for (i = Dstart[bishop]; i <= Dstop[bishop]; i++) X { X d = Dir[i]; m = m0+d; X while (!(m & 0x88)) X { X u = unmap[m]; X if (atk2[u] & ctlBQ) ScoreThreat; X if (color[u] != neutral) break; X m += d; 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; X while (!(m & 0x88)) X { X u = unmap[m]; X if (atk2[u] & ctlRQ) ScoreThreat; X if (color[u] != neutral) break; X m += d; X } X } X if (HasKnight[c2]) X for (i = Dstart[knight]; i <= Dstop[knight]; i++) X if (!((m = m0+Dir[i]) & 0x88)) X { X u = unmap[m]; X if (atk2[u] & ctlNN) ScoreThreat; X } X *s += (KSFTY*Kthreat[cnt]) / 16; X X cnt = 0; ok = false; X m0 = map[sq]; X for (i = Dstart[king]; i <= Dstop[king]; i++) X if (!((m = m0+Dir[i]) & 0x88)) X { X u = unmap[m]; X if (board[u] == pawn) 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) *s -= 4*KSFTY; X } X } X if (!ok) *s -= KSFTY; X if (cnt > 1) *s -= KSFTY; X} X X XBRscan(sq,s,mob) Xshort sq,*s,*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{ Xregister short m,u,d,m0,j,piece,pin; Xshort *Kf; X X Kf = Kfield[c1]; X *mob = 0; X m0 = map[sq]; piece = board[sq]; X for (j = Dstart[piece]; j <= Dstop[piece]; j++) X { X pin = -1; X d = Dir[j]; m = m0+d; X while (!(m & 0x88)) X { X u = unmap[m]; *s += Kf[u]; X if (color[u] == neutral) X { X (*mob)++; X m += d; X } X else if (pin < 0) X { X if (board[u] == pawn || board[u] == king) break; X pin = u; X m += d; X } X else 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 || X atk1[pin] > control[board[pin]]+1) X ++hung[c2]; X } X else *s += XRAY; X break; X } X else break; X } X } X} X X Xint trapped(sq,piece) Xshort sq,piece; X X/* X See if the attacked piece has unattacked squares to move to. X*/ X X{ Xregister short u,m,d,i,m0; X X m0 = map[sq]; X if (sweep[piece]) X for (i = Dstart[piece]; i <= Dstop[piece]; i++) X { X d = Dir[i]; m = m0+d; X while (!(m & 0x88)) X { X u = unmap[m]; X if (color[u] == c1) break; X if (atk2[u] == 0 || board[u] >= piece) return(false); X if (color[u] == c2) break; X m += d; X } X } X else if (piece == pawn) X { X if (c1 == white) u = sq+8; else u = sq-8; X if (color[u] == neutral && atk1[u] >= atk2[u]) X return(false); X if (!((m = m0+Dir[Dpwn[c1]]) & 0x88)) X if (color[unmap[m]] == c2) return(false); X if (!((m = m0+Dir[Dpwn[c1]+1]) & 0x88)) X if (color[unmap[m]] == c2) return(false); X } X else X { X for (i = Dstart[piece]; i <= Dstop[piece]; i++) X if (!((m = m0+Dir[i]) & 0x88)) X { X u = unmap[m]; X if (color[u] != c1) X if (atk2[u] == 0 || board[u] >= piece) return(false); X } X } X return(true); X} X X XExaminePosition() X X/* X This is done one time before the search is started. Set up arrays X Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the X SqValue() function to determine the positional value of each piece. X*/ X X{ Xregister short i,sq; Xshort wpadv,bpadv,wstrong,bstrong,z,side,pp,j,val,Pd,fyle,rank; 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 HasPawn[white] = HasPawn[black] = 0; 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 = 0; i <= PieceCnt[side]; i++) X switch (board[PieceList[side][i]]) X { X case pawn : ++HasPawn[side]; break; X case knight : ++HasKnight[side]; break; X case bishop : ++HasBishop[side]; break; X case rook : ++HasRook[side]; break; X case queen : ++HasQueen[side]; 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]; rank = row[sq]; X wstrong = bstrong = true; X for (i = sq; i < 64; i += 8) X if (atak[black][i] >= ctlP) wstrong = false; X for (i = sq; i >= 0; i -= 8) X if (atak[white][i] >= ctlP) bstrong = false; X wpadv = bpadv = PADVNCM; X if ((fyle == 0 || PawnCnt[white][fyle-1] == 0) && X (fyle == 7 || PawnCnt[white][fyle+1] == 0)) wpadv = PADVNCI; X if ((fyle == 0 || PawnCnt[black][fyle-1] == 0) && X (fyle == 7 || PawnCnt[black][fyle+1] == 0)) bpadv = PADVNCI; X Mwpawn[sq] = (wpadv*PawnAdvance[sq]) / 10; X Mbpawn[sq] = (bpadv*PawnAdvance[63-sq]) / 10; X Mwpawn[sq] += PawnBonus; Mbpawn[sq] += PawnBonus; X if (castld[white] || kingmoved[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 (castld[black] || kingmoved[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) || X (column[wking] > 3 && fyle < 3)) Mwpawn[sq] += 3*rank - 21; X if ((column[bking] < 4 && fyle > 4) || X (column[bking] > 3 && fyle < 3)) Mbpawn[sq] -= 3*rank; X } 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 = 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 (wstrong) Mknight[white][sq] += KNIGHTSTRONG; X if (bstrong) Mknight[black][sq] += KNIGHTSTRONG; X if (wstrong) Mbishop[white][sq] += BISHOPSTRONG; X if (bstrong) Mbishop[black][sq] += BISHOPSTRONG; X X if (HasBishop[white] == 2) Mbishop[white][sq] += 8; X if (HasBishop[black] == 2) Mbishop[black][sq] += 8; X if (HasKnight[white] == 2) Mknight[white][sq] += 5; X if (HasKnight[black] == 2) Mknight[black][sq] += 5; X X if (board[sq] == bishop) X if (rank % 2 == fyle % 2) KBNKsq = 0; else KBNKsq = 7; X X Kfield[white][sq] = Kfield[black][sq] = 0; X if (distance(sq,wking) == 1) Kfield[black][sq] = KATAK; X if (distance(sq,bking) == 1) Kfield[white][sq] = KATAK; X X Pd = 0; X for (i = 0; i < 64; i++) X if (board[i] == pawn) X { X if (color[i] == white) X { X 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 (atak[black][j] > ctlP || board[j] == pawn) pp = false; X } X else X { X 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 (atak[white][j] > ctlP || board[j] == pawn) pp = false; X } X if (pp) Pd += 5*taxicab(sq,z); else Pd += taxicab(sq,z); 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 X XUpdateWeights() X X/* X If material balance has changed, determine the values for the X positional evaluation terms. X*/ X X{ Xregister short 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 > 6600) stage = 0; X else if (tmtl < 1400) stage = 10; X else stage = (6600-tmtl) / 520; X if (tmtl > 3600) stage2 = 0; X else if (tmtl < 1400) stage2 = 10; X else stage2 = (3600-tmtl) / 220; X 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 = 2*stage; X X RHOPN = 10; /* rook on half open file */ X RHOPNX = 4; X RookBonus = 6*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 if (stage < 8) KSFTY = 16-2*stage; else KSFTY = 0; X X ATAKD = -6; /* defender > attacker */ X HUNGP = -8; /* each hung piece */ X HUNGX = -12; /* extra for >1 hung piece */ X } X} X X Xint distance(a,b) Xshort a,b; X{ Xregister short d1,d2; X X d1 = abs(column[a]-column[b]); X d2 = abs(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} END_OF_gnuchess.c2 if test 19818 -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 4 \(of 4\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 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