📄 eval.c
字号:
* Calculate the positional value for a rook on 'sq'.
*/
{
register SHORT s;
register SHORT fyle, a2, a1;
SHORT mob;
s = RookBonus;
s += BRscan (sq, &mob);
s += RMBLTY[mob];
fyle = column (sq);
if (PC1[fyle] == 0)
{ s += RHOPN;
if (PC2[fyle] == 0)
s += RHOPNX;
}
if (pmtl[c2] > 100 && row (sq) == rank7[c1])
s += 25;
s += 14 - taxicab (sq, EnemyKing);
a2 = (atk2[sq] & 0x4FFF);
if (a2 > 0)
{
a1 = (atk1[sq] & 0x4FFF);
if (a1 == 0 || a2 > ctlR + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlR || a1 < ctlP)
s += ATAKD;
}
return (s);
}
inline
int
QueenValue (register SHORT sq, register SHORT side)
/*
* Calculate the positional value for a queen on 'sq'.
*/
{
register SHORT s, a2, a1;
s = ((distance (sq, EnemyKing) < 3) ? 12 : 0);
if (stage > 2)
s += 14 - taxicab (sq, EnemyKing);
a2 = (atk2[sq] & 0x4FFF);
if (a2 > 0)
{
a1 = (atk1[sq] & 0x4FFF);
if (a1 == 0 || a2 > ctlQ + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlQ || a1 < ctlP)
s += ATAKD;
}
return (s);
}
inline
int
KingValue (register SHORT sq, register SHORT side)
/*
* Calculate the positional value for a king on 'sq'.
*/
{
register SHORT s;
register SHORT fyle;
SHORT a2, a1;
s = (emtl[c2] > KINGPOSLIMIT) ? Mking[c1][sq] : Mking[c1][sq] / 2;
if (KSFTY > 0)
/* if (Developed[c2] || stage > 0) */
s += KingScan (sq);
if (castld[c1])
s += KCASTLD;
else if (Mvboard[kingP[c1]])
s += KMOVD;
fyle = column (sq);
if (PC1[fyle] == 0)
s += KHOPN;
if (PC2[fyle] == 0)
s += KHOPNX;
switch (fyle)
{
case 5:
if (PC1[7] == 0)
s += KHOPN;
if (PC2[7] == 0)
s += KHOPNX;
/* Fall through */
case 6:
case 4:
case 0:
if (PC1[fyle + 1] == 0)
s += KHOPN;
if (PC2[fyle + 1] == 0)
s += KHOPNX;
break;
case 2:
if (PC1[0] == 0)
s += KHOPN;
if (PC2[0] == 0)
s += KHOPNX;
/* Fall through */
case 1:
case 3:
case 7:
if (PC1[fyle - 1] == 0)
s += KHOPN;
if (PC2[fyle - 1] == 0)
s += KHOPNX;
break;
default:
/* Impossible! */
break;
}
/* Some extra code for Ng5 problem */
if (computer==c1 && fyle >= 6 && HasQueen[c2] && PC1[7]==0)
s += AHOPEN;
if (computer==c1 && fyle <= 1 && HasQueen[c2] && PC1[0]==0)
s += AHOPEN;
a2 = (atk2[sq] & 0x4FFF);
if (a2 > 0)
{
a1 = (atk1[sq] & 0x4FFF);
if (a1 == 0 || a2 > ctlK + 1)
{
s += HUNGP;
++hung[c1];
}
else
s += ATAKD;
}
return (s);
}
static int (*PieceValue[7]) (SHORT, SHORT) =
{NULL, PawnValue, KnightValue, BishopValue, RookValue, QueenValue, KingValue};
SHORT
ScorePosition (register SHORT side)
/*
* 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 score;
register SHORT sq, i, xside;
SHORT s;
xside = side ^ 1;
hung[white] = hung[black] = pscore[white] = pscore[black] = 0;
/* initialize Hasxxx */
HasKnight[white] = HasKnight[black] = 0;
HasBishop[white] = HasBishop[black] = 0;
HasRook[white] = HasRook[black] = 0;
HasQueen[white] = HasQueen[black] = 0;
for (s = white; s <= black; s++)
for (i = PieceCnt[s]; i >= 0; i--)
switch (board[PieceList[s][i]])
{
case knight:
++HasKnight[s];
break;
case bishop:
++HasBishop[s];
break;
case rook:
++HasRook[s];
break;
case queen:
++HasQueen[s];
break;
}
#ifdef CACHE
if (!(hashkey+hashbd) || !ProbeEETable (side, &s))
{
#endif
UpdateWeights ();
for (c1 = white; c1 <= black; c1++)
{
c2 = c1 ^ 1;
/* atk1 is array of atacks on squares by my side */
atk1 = atak[c1];
/* atk2 is array of atacks on squares by other side */
atk2 = atak[c2];
/* same for PC1 and PC2 */
PC1 = PawnCnt[c1];
PC2 = PawnCnt[c2];
for (i = PieceCnt[c1]; i >= 0; i--)
{
sq = PieceList[c1][i];
s = (*PieceValue[board[sq]]) (sq, side);
/* switch (board[sq])
{
case pawn:
s = PawnValue (sq, side);
break;
case knight:
s = KnightValue (sq);
break;
case bishop:
s = BishopValue (sq);
break;
case rook:
s = RookValue (sq);
break;
case queen:
s = QueenValue (sq);
break;
case king:
s = KingValue (sq);
break;
default:
s = 0;
break;
} */
pscore[c1] += s;
svalue[sq] = s;
}
}
if (hung[side] > 1)
pscore[side] += HUNGX;
if (hung[xside] > 1)
pscore[xside] += HUNGX;
if (hung[computer] > 1)
pscore[computer] += 8 * HUNGX;
/* Bonus for double bishops */
if (HasBishop[side] == 2)
pscore[side] += 10 + 2 * stage;
if (HasBishop[xside] == 2)
pscore[xside] += 10 + 2 * stage;
score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
#ifndef NODITHER
if (dither)
{
if (flag.hash)
gsrand (starttime + (unsigned int) hashbd);
score += urand () % dither;
}
#endif
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;
#ifdef CACHE
if(PUTVAR)PutInEETable(side,score);
#endif
return (score);
#ifdef CACHE
}
else {
return s;
}
#endif
}
static inline void
BlendBoard (const SHORT a[64], const SHORT b[64], SHORT c[64])
{
register int sq, s;
s = 10 - stage;
for (sq = 0; sq < 64; sq++)
c[sq] = ((a[sq] * s) + (b[sq] * stage)) / 10;
}
void
ExaminePosition (void)
/*
* This is done one time before the search is started. Set up arrays Mwpawn,
* Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue() function
* to determine the positional value of each piece.
*/
{
register SHORT i, sq;
register SHORT fyle;
SHORT wpadv, bpadv, wstrong, bstrong, z, side, pp, j, k, val, Pd, rank;
static SHORT PawnStorm = false;
/* update ataks arrays */
ataks (white, atak[white]);
ataks (black, atak[black]);
/* */
UpdateWeights ();
/* initialize Hasxxx */
HasKnight[white] = HasKnight[black] = 0;
HasBishop[white] = HasBishop[black] = 0;
HasRook[white] = HasRook[black] = 0;
HasQueen[white] = HasQueen[black] = 0;
for (side = white; side <= black; side++)
for (i = PieceCnt[side]; i >= 0; i--)
switch (board[PieceList[side][i]])
{
case knight:
++HasKnight[side];
break;
case bishop:
++HasBishop[side];
break;
case rook:
++HasRook[side];
break;
case queen:
++HasQueen[side];
break;
}
/* Developed if has moved knights and bishops */
if (!Developed[white])
Developed[white] = (board[1] != knight && board[2] != bishop &&
board[5] != bishop && board[6] != knight);
if (!Developed[black])
Developed[black] = (board[57] != knight && board[58] != bishop &&
board[61] != bishop && board[62] != knight);
/* Pawn Storm */
/* if (!PawnStorm && stage < 5)*/
PawnStorm = (stage < 5) &&
((column (wking) < 3 && column (bking) > 4) ||
(column (wking) > 4 && column (bking) < 3));
/* setup base tables */
memcpy (Mknight[white],pknight,sizeof(pknight));
memcpy (Mknight[black],pknight,sizeof(pknight));
memcpy(Mbishop[white],pbishop,sizeof(pbishop));
memcpy(Mbishop[black],pbishop,sizeof(pbishop));
/* linear interpolate on stage */
/* Mking = (KingOpening * (10 - stage) + KingEnding * srage) /10 */
BlendBoard (KingOpening, KingEnding, Mking[white]);
BlendBoard (KingOpening, KingEnding, Mking[black]);
for (sq = 0; sq < 64; sq++)
{
fyle = column (sq);
rank = row (sq);
wstrong = bstrong = true;
/* does a black pawn attack to squares in this col from sq to end */
for (i = sq; i < 64; i += 8)
if (Patak (black, i)) { wstrong = false; break; }
/* does a white pawn attack to squares in this col from sq to end */
for (i = sq; i >= 0; i -= 8)
if (Patak (white, i)) { bstrong = false; break; }
/* */
wpadv = bpadv = PADVNCM;
if ((fyle == 0 || PawnCnt[white][fyle - 1] == 0) && (fyle == 7 || PawnCnt[white][fyle + 1] == 0)) wpadv = PADVNCI;
if ((fyle == 0 || PawnCnt[black][fyle - 1] == 0) && (fyle == 7 || PawnCnt[black][fyle + 1] == 0)) bpadv = PADVNCI;
Mwpawn[sq] = (wpadv * PawnAdvance[sq]) / 10;
Mbpawn[sq] = (bpadv * PawnAdvance[63 - sq]) / 10;
Mwpawn[sq] += PawnBonus;
Mbpawn[sq] += PawnBonus;
/* */
if (Mvboard[kingP[white]])
{
if ((fyle < 3 || fyle > 4) && distance (sq, wking) < 3)
Mwpawn[sq] += PAWNSHIELD;
}
else if (rank < 3 && (fyle < 2 || fyle > 5))
Mwpawn[sq] += PAWNSHIELD / 2;
/* */
if (Mvboard[kingP[black]])
{
if ((fyle < 3 || fyle > 4) && distance (sq, bking) < 3)
Mbpawn[sq] += PAWNSHIELD;
}
else if (rank > 4 && (fyle < 2 || fyle > 5))
Mbpawn[sq] += PAWNSHIELD / 2;
/* */
if (PawnStorm)
{
if ((column (wking) < 4 && fyle > 4) || (column (wking) > 3 && fyle < 3))
Mwpawn[sq] += 4 * rank;
if ((column (bking) < 4 && fyle > 4) || (column (bking) > 3 && fyle < 3))
Mbpawn[sq] -= (4 * rank - 28);
}
/* */
Mknight[white][sq] += 5 - distance (sq, bking);
Mknight[white][sq] += 5 - distance (sq, wking);
Mknight[black][sq] += 5 - distance (sq, wking);
Mknight[black][sq] += 5 - distance (sq, bking);
/* */
Mbishop[white][sq] += BishopBonus;
Mbishop[black][sq] += BishopBonus;
/* */
for (i = PieceCnt[black]; i >= 0; i--)
if (distance (sq, PieceList[black][i]) < 3)
Mknight[white][sq] += KNIGHTPOST;
for (i = PieceCnt[white]; i >= 0; i--)
if (distance (sq, PieceList[white][i]) < 3)
Mknight[black][sq] += KNIGHTPOST;
/* */
if (wstrong)
Mknight[white][sq] += KNIGHTSTRONG;
if (bstrong)
Mknight[black][sq] += KNIGHTSTRONG;
if (wstrong)
Mbishop[white][sq] += BISHOPSTRONG;
if (bstrong)
Mbishop[black][sq] += BISHOPSTRONG;
/* */
#ifdef notdef
if (HasBishop[white] == 2)
Mbishop[white][sq] += 8;
if (HasBishop[black] == 2)
Mbishop[black][sq] += 8;
if (HasKnight[white] == 2)
Mknight[white][sq] += 5;
if (HasKnight[black] == 2)
Mknight[black][sq] += 5;
#endif
/* */
Kfield[white][sq] = Kfield[black][sq] = 0;
if (distance (sq, wking) == 1)
Kfield[black][sq] = KATAK;
if (distance (sq, bking) == 1)
Kfield[white][sq] = KATAK;
/* */
Pd = 0;
for (k = 0; k <= PieceCnt[white]; k++)
{
i = PieceList[white][k];
if (board[i] == pawn)
{
pp = true;
for (j = i + 8; j < 64; j += 8)
if (Patak (black, j) || board[j] == pawn)
{
pp = false;
break;
}
z = (pp ? i + ((row (i) == 6) ? 8 : 16) : i);
Pd += ((pp) ? 5 * taxicab (sq, z) : taxicab (sq, z));
}
}
/* */
for (k = 0; k <= PieceCnt[black]; k++)
{
i = PieceList[black][k];
if (board[i] == pawn)
{
pp = true;
for (j = i - 8; j >= 0; j -= 8)
if (Patak (white, j) || board[j] == pawn)
{
pp = false;
break;
}
z = (pp ? i - ((row (i) == 1) ? 8 : 16) : i);
Pd += ((pp) ? 5 * taxicab (sq, z) : taxicab (sq, z));
}
}
/* */
if (Pd != 0)
{
val = (Pd * stage2) / 4;
Mking[white][sq] -= val;
Mking[black][sq] -= val;
}
}
}
void
UpdateWeights (void)
/*
* If material balance has changed, determine the values for the positional
* evaluation terms.
*/
{
register SHORT s1, tmtl;
emtl[white] = mtl[white] - pmtl[white] - valueK;
emtl[black] = mtl[black] - pmtl[black] - valueK;
tmtl = emtl[white] + emtl[black];
s1 = ((tmtl > 6600) ? 0 : ((tmtl < 1400) ? 10 : (6600 - tmtl) / 520));
if (s1 != stage)
{
stage = s1;
stage2 = ((tmtl > 3600) ? 0 : ((tmtl < 1400) ? 10 : (3600 - tmtl) / 220));
PEDRNK2B = -15; /* centre pawn on 2nd rank & blocked */
PBLOK = -4; /* blocked backward pawn */
PDOUBLED = -14; /* doubled pawn */
PWEAKH = -12; /* weak pawn on half open file */
PAWNSHIELD = 10-stage; /* pawn near friendly king */
PADVNCM = 12; /* advanced pawn multiplier */
PADVNCI = 7; /* muliplier for isolated pawn */
PawnBonus = stage;
KNIGHTPOST = (stage + 2) / 3; /* knight near enemy pieces */
KNIGHTSTRONG = (stage + 6) / 2; /* occupies pawn hole */
BISHOPSTRONG = (stage + 6) / 2; /* occupies pawn hole */
BishopBonus = BBONUS * stage;
RHOPN = 10; /* rook on half open file */
RHOPNX = 4;
RookBonus = RBONUS * stage;
XRAY = 8; /* Xray attack on piece */
PINVAL = 16; /* Pin */
KHOPN = (2 * stage - 20); /* king on half open file */
KHOPNX = KHOPN / 2;
KCASTLD = 10 - stage;
KMOVD = -40 / (stage + 1); /* king moved before castling */
KATAK = (10 - stage); /* B,R attacks near enemy king */
KSFTY = ((stage < 8) ? (KINGSAFETY - 4 * stage) : 0);
ATAKD = -8; /* defender > attacker */
HUNGP = -12; /* each hung piece */
HUNGX = -18; /* extra for >1 hung piece */
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -