📄 gnuchess.c
字号:
UpdateHashbd(side,piece,f,t)short side,piece,f,t;/* hashbd contains a 32 bit "signature" of the board position. hashkey contains a 16 bit code used to address the hash table. When a move is made, XOR'ing the hashcode of moved piece on the from and to squares with the hashbd and hashkey values keeps things current. */{ if (f >= 0) { hashbd ^= hashcode[side][piece][f].bd; hashkey ^= hashcode[side][piece][f].key; } if (t >= 0) { hashbd ^= hashcode[side][piece][t].bd; hashkey ^= hashcode[side][piece][t].key; }}UpdatePieceList(side,sq,iop)short side,sq,iop;/* Update the PieceList and Pindex arrays when a piece is captured or when a capture is unmade. */{register short i; if (iop == 1) { PieceCnt[side]--; for (i = Pindex[sq]; i <= PieceCnt[side]; i++) { PieceList[side][i] = PieceList[side][i+1]; Pindex[PieceList[side][i]] = i; } } else { PieceCnt[side]++; PieceList[side][PieceCnt[side]] = sq; Pindex[sq] = PieceCnt[side]; }}InitializeStats()/* Scan thru the board seeing what's on each square. If a piece is found, update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also determine the material for each side and set the hashkey and hashbd variables to represent the current board position. Array PieceList[side][indx] contains the location of all the pieces of either side. Array Pindex[sq] contains the indx into PieceList for a given square. */{register short i,sq; epsquare = -1; for (i = 0; i < 8; i++) PawnCnt[white][i] = PawnCnt[black][i] = 0; mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0; PieceCnt[white] = PieceCnt[black] = 0; hashbd = hashkey = 0; for (sq = 0; sq < 64; sq++) if (color[sq] != neutral) { mtl[color[sq]] += value[board[sq]]; if (board[sq] == pawn) { pmtl[color[sq]] += valueP; ++PawnCnt[color[sq]][column[sq]]; } if (board[sq] == king) Pindex[sq] = 0; else Pindex[sq] = ++PieceCnt[color[sq]]; PieceList[color[sq]][Pindex[sq]] = sq; hashbd ^= hashcode[color[sq]][board[sq]][sq].bd; hashkey ^= hashcode[color[sq]][board[sq]][sq].key; }}pick(p1,p2)short p1,p2;/* Find the best move in the tree between indexes p1 and p2. Swap the best move into the p1 element. */{register short p,s;short p0,s0;struct leaf temp; s0 = Tree[p1].score; p0 = p1; for (p = p1+1; p <= p2; p++) if ((s = Tree[p].score) > s0) { s0 = s; p0 = p; } if (p0 != p1) { temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp; }}repetition(cnt)short *cnt;/* Check for draw by threefold repetition.*/{register short i,c;short f,t,b[64];unsigned short m; *cnt = c = 0; if (GameCnt > Game50+3) {/* memset((char *)b,0,64*sizeof(short));*/ for (i = 0; i < 64; b[i++] = 0); for (i = GameCnt; i > Game50; i--) { m = GameList[i].gmove; f = m>>8; t = m & 0xFF; if (++b[f] == 0) c--; else c++; if (--b[t] == 0) c--; else c++; if (c == 0) (*cnt)++; } }}#if (NEWMOVE < 3)int SqAtakd(sq,side)short sq,side;/* See if any piece with color 'side' ataks sq. First check for pawns or king, then try other pieces. Array Dcode is used to check for knight attacks or R,B,Q co-linearity. */{register short m,d;short i,m0,m1,loc,piece,*PL; m1 = map[sq]; if (side == white) m = m1-0x0F; else m = m1+0x0F; if (!(m & 0x88)) if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true); if (side == white) m = m1-0x11; else m = m1+0x11; if (!(m & 0x88)) if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true); if (distance(sq,PieceList[side][0]) == 1) return(true); PL = PieceList[side]; for (i = 1; i <= PieceCnt[side]; i++) { loc = PL[i]; piece = board[loc]; if (piece == pawn) continue; m0 = map[loc]; d = Dcode[abs(m1-m0)]; if (d == 0 || (Pdir[d] & pbit[piece]) == 0) continue; if (piece == knight) return(true); else { if (m1 < m0) d = -d; for (m = m0+d; m != m1; m += d) if (color[unmap[m]] != neutral) break; if (m == m1) return(true); } } return(false);}#endif#if (NEWMOVE < 2)ataks(side,a)short side,*a;/* Fill array atak[][] with info about ataks to a square. Bits 8-15 are set if the piece (king..pawn) ataks the square. Bits 0-7 contain a count of total ataks to the square.*/{register short u,m;short d,c,j,j1,j2,piece,i,m0,sq,*PL; /* memset((char *)a,0,64*sizeof(short));*/ for (u = 0; u < 64; a[u++] = 0); Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1; PL = PieceList[side]; for (i = 0; i <= PieceCnt[side]; i++) { sq = PL[i]; m0 = map[sq]; piece = board[sq]; c = control[piece]; j1 = Dstart[piece]; j2 = Dstop[piece]; if (sweep[piece]) for (j = j1; j <= j2; j++) { d = Dir[j]; m = m0+d; while (!(m & 0x88)) { u = unmap[m]; a[u] = ++a[u] | c; if (color[u] == neutral) m += d; else break; } } else for (j = j1; j <= j2; j++) if (!((m = m0+Dir[j]) & 0x88)) { u = unmap[m]; a[u] = ++a[u] | c; } }}#endif/* ............ POSITIONAL EVALUATION ROUTINES ............ */ScorePosition(side,score)short side,*score;/* Perform normal static evaluation of board position. A score is generated for each piece and these are summed to get a score for each side. */{register short sq,s;short i,xside,pscore[3]; wking = PieceList[white][0]; bking = PieceList[black][0]; UpdateWeights(); xside = otherside[side]; pscore[white] = pscore[black] = 0; for (c1 = white; c1 <= black; c1++) { c2 = otherside[c1]; if (c1 == white) EnemyKing = bking; else EnemyKing = wking; atk1 = atak[c1]; atk2 = atak[c2]; PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2]; for (i = 0; i <= PieceCnt[c1]; i++) { sq = PieceList[c1][i]; s = SqValue(sq,side); pscore[c1] += s; svalue[sq] = s; } } if (hung[side] > 1) pscore[side] += HUNGX; if (hung[xside] > 1) pscore[xside] += HUNGX; *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10; if (dither) *score += rand() % dither; if (*score > 0 && pmtl[side] == 0) if (emtl[side] < valueR) *score = 0; else if (*score < valueR) *score /= 2; if (*score < 0 && pmtl[xside] == 0) if (emtl[xside] < valueR) *score = 0; else if (-*score < valueR) *score /= 2; if (mtl[xside] == valueK && emtl[side] > valueB) *score += 200; if (mtl[side] == valueK && emtl[xside] > valueB) *score -= 200;}ScoreLoneKing(side,score)short side,*score;/* Static evaluation when loser has only a king and winner has no pawns or no pieces.*/{short winner,loser,king1,king2,s,i; UpdateWeights(); if (mtl[white] > mtl[black]) winner = white; else winner = black; loser = otherside[winner]; king1 = PieceList[winner][0]; king2 = PieceList[loser][0]; s = 0; if (pmtl[winner] > 0) for (i = 1; i <= PieceCnt[winner]; i++) s += ScoreKPK(side,winner,loser,king1,king2,PieceList[winner][i]); else if (emtl[winner] == valueB+valueN) s = ScoreKBNK(winner,king1,king2); else if (emtl[winner] > valueB) s = 500 + emtl[winner] - DyingKing[king2] - 2*distance(king1,king2); if (side == winner) *score = s; else *score = -s;}int ScoreKPK(side,winner,loser,king1,king2,sq)short side,winner,loser,king1,king2,sq;/* Score King and Pawns versus King endings.*/{short s,r; if (PieceCnt[winner] == 1) s = 50; else s = 120; if (winner == white) { if (side == loser) r = row[sq]-1; else r = row[sq]; if (row[king2] >= r && distance(sq,king2) < 8-r) s += 10*row[sq]; else s = 500+50*row[sq]; if (row[sq] < 6) sq += 16; else sq += 8; } else { if (side == loser) r = row[sq]+1; else r = row[sq]; if (row[king2] <= r && distance(sq,king2) < r+1) s += 10*(7-row[sq]); else s = 500+50*(7-row[sq]); if (row[sq] > 1) sq -= 16; else sq -= 8; } s += 8*(taxicab(king2,sq) - taxicab(king1,sq)); return(s);}int ScoreKBNK(winner,king1,king2)short winner,king1,king2;/* Score King+Bishop+Knight versus King endings. This doesn't work all that well but it's better than nothing.*/{short s; s = emtl[winner] - 300; if (KBNKsq == 0) s += KBNK[king2]; else s += KBNK[locn[row[king2]][7-column[king2]]]; s -= taxicab(king1,king2); s -= distance(PieceList[winner][1],king2); s -= distance(PieceList[winner][2],king2); return(s);}SqValue(sq,side)short sq,side;/* Calculate the positional value for the piece on 'sq'.*/{register short j,fyle,rank;short s,piece,a1,a2,in_square,r,mob,e,c; piece = board[sq]; a1 = (atk1[sq] & 0x4FFF); a2 = (atk2[sq] & 0x4FFF); rank = row[sq]; fyle = column[sq]; s = 0; if (piece == pawn && c1 == white) { s = Mwpawn[sq]; if (sq == 11 || sq == 12) if (color[sq+8] != neutral) s += PEDRNK2B; if ((fyle == 0 || PC1[fyle-1] == 0) && (fyle == 7 || PC1[fyle+1] == 0)) s += ISOLANI[fyle]; else if (PC1[fyle] > 1) s += PDOUBLED; if (a1 < ctlP && atk1[sq+8] < ctlP) { s += BACKWARD[a2 & 0xFF]; if (PC2[fyle] == 0) s += PWEAKH; if (color[sq+8] != neutral) s += PBLOK; } if (PC2[fyle] == 0) { if (side == black) r = rank-1; else r = rank; in_square = (row[bking] >= r && distance(sq,bking) < 8-r); if (a2 == 0 || side == white) e = 0; else e = 1; for (j = sq+8; j < 64; j += 8) if (atk2[j] >= ctlP) { e = 2; break; } else if (atk2[j] > 0 || color[j] != neutral) e = 1; if (e == 2) s += (stage*PassedPawn3[rank]) / 10; else if (in_square || e == 1) s += (stage*PassedPawn2[rank]) / 10; else if (emtl[black] > 0) s += (stage*PassedPawn1[rank]) / 10; else s += PassedPawn0[rank]; } } else if (piece == pawn && c1 == black) { s = Mbpawn[sq]; if (sq == 51 || sq == 52) if (color[sq-8] != neutral) s += PEDRNK2B; if ((fyle == 0 || PC1[fyle-1] == 0) && (fyle == 7 || PC1[fyle+1] == 0)) s += ISOLANI[fyle]; else if (PC1[fyle] > 1) s += PDOUBLED; if (a1 < ctlP && atk1[sq-8] < ctlP) { s += BACKWARD[a2 & 0xFF]; if (PC2[fyle] == 0) s += PWEAKH; if (color[sq-8] != neutral) s += PBLOK; } if (PC2[fyle] == 0) { if (side == white) r = rank+1; else r = rank; in_square = (row[wking] <= r && distance(sq,wking) < r+1); if (a2 == 0 || side == black) e = 0; else e = 1; for (j = sq-8; j >= 0; j -= 8) if (atk2[j] >= ctlP) { e = 2; break; } else if (atk2[j] > 0 || color[j] != neutral) e = 1; if (e == 2) s += (stage*PassedPawn3[7-rank]) / 10; else if (in_square || e == 1) s += (stage*PassedPawn2[7-rank]) / 10; else if (emtl[white] > 0) s += (stage*PassedPawn1[7-rank]) / 10; else s += PassedPawn0[7-rank]; } } else if (piece == knight) { s = Mknight[c1][sq]; } else if (piece == bishop) { s = Mbishop[c1][sq]; BRscan(sq,&s,&mob); s += BMBLTY[mob]; } else if (piece == rook) { s += RookBonus; BRscan(sq,&s,&mob); s += RMBLTY[mob]; if (PC1[fyle] == 0) s += RHOPN; if (PC2[fyle] == 0) s += RHOPNX; if (rank == rank7[c1] && pmtl[c2] > 100) s += 10; if (stage > 2) s += 14 - taxicab(sq,EnemyKing);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -