📄 eval.c
字号:
>= -1 && dist_ (bf, br, sgf, sgr) > wsg) return (1);
md = mbpf - mwpf;
if (!(pf != 1 || bf <= 3))
{
sdr = br + (bf - 3);
if (sdr > 8) sdr = 8;
if (wr > br + 1) sdr = br;
if (sdr > ppr)
{
wsd = dist_ (wf, wr, 3, sdr);
bsd = dist_ (bf, br, 3, sdr);
if (bsd - wsd < -1) return (0);
if (bsd <= wsd && md <= 0) return (0);
}
}
brpuuu = dist_ (bf, br, pf + 1, pr + 3);
if (brpu > wrpu && brpuuu > wrpu && pr - wr != pf - wf) return (1);
if (brpuuu == 0 && wrpu == 1) return (1);
blpuuu = dist_ (bf, br, pf - 1, pr + 3);
if (pf != 1)
{
if (blpu > wlpu && blpuuu > wlpu && pr - wr != wf - pf) return (1);
if (blpuuu == 0 && wlpu == 1) return (1);
}
wrpuu = dist_ (wf, wr, pf + 1, pr + 2);
if (brpuu > wrpuu) return(1);
wlpuu = dist_ (wf, wr, pf - 1, pr + 2);
if (pf > 1 && blpuu > wlpuu) return (1);
if (br == pr)
{
if (mwpf <= 2 && wr - pr == -1 && mbpf != 2) return (1);
if (dist_ (wf, wr, bf - 1, br + 2) <= 1 && bf - pf > 1) return (1);
if (dist_ (wf, wr, bf + 1, br + 2) <= 1 && bf - pf < -1) return (1);
}
if (pf != 1)
{
if (br == pr && mbpf > 1 && dist_ (wf, wr, pf, pr - 1) <= 1) return (1);
if (br - pr >= 3 && wbdd == 1) return (1);
if (wr - pr >= 2 && wr < br && md >= 0) return (1);
if (mwpf <= 2 && wr - pr >= 3 && bf != pf && wr - br <= 1) return (1);
if (wr >= pr && br - pr >= 5 && mbpf >= 3 && md >= -1 && ppr == 3) return (1);
if (md >= -1 && pr == 2 && br == 8) return (1);
}
tbf = bf - 1;
if (pf > bf) tbf = bf + 1;
if (mbpf > 1 && br == ppr && dist_ (wf, wr, tbf, wr + 2) <= 1) return (1);
if (br == pr && bf - pf == -2 && dist_ (wf, wr, pf + 2, pr - 1) <= 1) return (1);
if (pf > 2 && br == pr && bf - pf == 2 &&
dist_ (wf, wr, pf - 2, pr - 1) <= 1) return(1);
return (0);
} /* kpkwv_ */
static SHORT
kpkbv_ (SHORT pf, SHORT pr, SHORT wf, SHORT wr, SHORT bf, SHORT br)
{
static SHORT incf[8] =
{0, 1, 1, 1, 0, -1, -1, -1};
static SHORT incr[8] =
{1, 1, 0, -1, -1, -1, 0, 1};
static SHORT i, nm, nbf, nbr;
nm = 0;
for (i = 0; i < 8; ++i)
{
nbf = bf + incf[i];
if (nbf < 1 || nbf > 8) continue;
nbr = br + incr[i];
if (nbr < 1 || nbr > 8) continue;
if (dist_ (nbf, nbr, wf, wr) < 2) continue;
if (nbf == pf && nbr == pr) return (0);
if (nbr == pr + 1 && (nbf == pf - 1 || nbf == pf + 1)) continue;
++nm;
if (kpkwv_ (pf, pr, wf, wr, nbf, nbr) == 0) return(0);
}
if (nm > 0) return(-1);
return(0);
} /* kpkbv_ */
int
evaluate (register SHORT side,
register SHORT ply,
register SHORT depth,
register SHORT ext,
register SHORT alpha,
register SHORT beta,
SHORT *terminal,
SHORT *InChk) /* output Check flag */
/*
* Compute an estimate of the score by adding the positional score from the
* previous ply to the material difference. If this score falls inside a
* window which is 180 points wider than the alpha-beta window (or within a
* 50 point window during quiescence search) call ScorePosition() to
* determine a score, otherwise return the estimated score. If one side has
* only a king and the other either has no pawns or no pieces then the
* function ScoreLoneKing() is called.
*/
{
register SHORT xside, slk;
SHORT s;
xside = side ^ 1;
s = -Pscore[ply - 1] + mtl[side] - mtl[xside] - INCscore;
*terminal = false;
hung[white] = hung[black] = 0;
slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
(mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
/* should we use the estimate or score the position */
if ( !slk && (ply == 1 ||
#ifdef PRUNE
depth == 1 || depth == 2 ||
#endif
#ifdef CACHE
(CheckEETable (side)) ||
#endif
(flag.neweval ? ((
(ply==Sdepth || (!ext && depth == 0 && s>=alpha-30 && s<=beta+30)) ||
(ext && s >= alpha - 25 && s <= beta + 25)) )
:
((Sdepth == ply) ||
(ply > Sdepth && (s >= (alpha - 30) && s <= (beta + 30)) )) )
))
{
/* score the position */
ataks (side, atak[side]);
ataks (xside, atak[xside]);
if (Anyatak (side, PieceList[xside][0]))
return (10001 - ply);
ChkFlag[ply - 1] = *InChk =
(Anyatak (xside, PieceList[side][0])) ? Pindex[TOsquare]+1 : 0;
#ifndef BAREBONES
EvalNodes++;
#endif
if (ply>4) PUTVAR = true;
s = ScorePosition (side);
PUTVAR = false;
}
else
{
/* use the estimate but look at check and slk */
if (SqAtakd (PieceList[xside][0], side)) return (10001 - ply);
*InChk = SqAtakd (PieceList[side][0], xside);
ChkFlag[ply - 1] = (*InChk ? Pindex[TOsquare] + 1 : 0);
#ifdef DEBUG
if (debuglevel & 4096)
printf("%lx %lx %d %d\n",hashbd,hashkey,ply,s);
#endif
if (slk)
{
if (ply>4) PUTVAR=true;
s = ScoreLoneKing (side);
PUTVAR=false;
*terminal = (s == 0 ? true : false);
}
}
Pscore[ply] = s - mtl[side] + mtl[xside];
QueenCheck[ply - 1] = /* tom@izf.tno.nl */
((*InChk) && board[TOsquare] == queen) ? TOsquare : 0;
#ifdef DEBUG
if (debuglevel & 4096)
printf("%lx %lx %d %d\n",hashbd,hashkey,ply,s);
#endif
return (s);
}
inline
int
BRscan (register SHORT sq, SHORT *mob)
/*
* Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
* hung[] array if a pin is found.
*/
{
register UCHAR *ppos, *pdir;
register SHORT s, mobx;
register SHORT u, pin;
SHORT piece, *Kf;
mobx = s = 0;
Kf = Kfield[c1];
piece = board[sq];
ppos = nextpos[piece][sq];
pdir = nextdir[piece][sq];
u = ppos[sq];
pin = -1; /* start new direction */
do
{
s += Kf[u];
if (color[u] == neutral)
{
mobx++;
if (ppos[u] == pdir[u])
pin = -1; /* oops new direction */
u = ppos[u];
}
else if (pin < 0)
{
if (board[u] == pawn || board[u] == king)
u = pdir[u];
else
{
if (ppos[u] != pdir[u])
pin = u; /* not on the edge and on to find a pin */
u = ppos[u];
}
}
else
{
if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
{
if (color[pin] == c2)
{
s += PINVAL;
if (atk2[pin] == 0 || atk1[pin] > control[board[pin]] + 1)
++hung[c2];
}
else
s += XRAY;
}
pin = -1; /* new direction */
u = pdir[u];
}
}
while (u != sq);
*mob = mobx;
return s;
}
inline
SHORT
KingScan (register SHORT sq)
/*
* Assign penalties if king can be threatened by checks, if squares near the
* king are controlled by the enemy (especially the queen), or if there are
* no pawns near the king.
The following must be true:
board[sq] == king
c1 == color[sq]
c2 == otherside[c1]
*/
#define ScoreThreat \
if (color[u] != c2)\
if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
else s -= 3
{
register SHORT cnt;
register UCHAR *ppos, *pdir;
register SHORT s;
register SHORT u;
SHORT ok;
s = 0;
cnt = 0;
if (HasBishop[c2] || HasQueen[c2])
{
ppos = nextpos[bishop][sq];
pdir = nextdir[bishop][sq];
u = ppos[sq];
do
{
if (atk2[u] & ctlBQ)
ScoreThreat;
u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
}
while (u != sq);
}
if (HasRook[c2] || HasQueen[c2])
{
ppos = nextpos[rook][sq];
pdir = nextdir[rook][sq];
u = ppos[sq];
do
{
if (atk2[u] & ctlRQ)
ScoreThreat;
u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
}
while (u != sq);
}
if (HasKnight[c2])
{
pdir = nextdir[knight][sq];
u = pdir[sq];
do
{
if (atk2[u] & ctlNN)
ScoreThreat;
u = pdir[u];
}
while (u != sq);
}
s += (KSFTY * KTHRT[cnt]) / 16;
cnt = 0;
ok = false;
pdir = nextpos[king][sq];
u = pdir[sq];
do
{
if (board[u] == pawn)
ok = true;
if (atk2[u] > atk1[u])
{
++cnt;
if (atk2[u] & ctlQ)
if (atk2[u] > ctlQ + 1 && atk1[u] < ctlQ)
s -= 4 * KSFTY;
}
u = pdir[u];
}
while (u != sq);
if (!ok)
s -= KSFTY;
if (cnt > 1)
s -= (KSFTY);
return (s);
}
inline
int
trapped (register SHORT sq)
/*
* See if the attacked piece has unattacked squares to move to. The following
* must be true: c1 == color[sq] c2 == otherside[c1]
*/
{
register SHORT u;
register UCHAR *ppos, *pdir;
register SHORT piece;
piece = board[sq];
ppos = nextpos[ptype[c1][piece]][sq];
pdir = nextdir[ptype[c1][piece]][sq];
if (piece == pawn)
{
u = ppos[sq]; /* follow no captures thread */
if (color[u] == neutral)
{
if (atk1[u] >= atk2[u])
return (false);
if (atk2[u] < ctlP)
{
u = ppos[u];
if (color[u] == neutral && atk1[u] >= atk2[u])
return (false);
}
}
u = pdir[sq]; /* follow captures thread */
if (color[u] == c2)
return (false);
u = pdir[u];
if (color[u] == c2)
return (false);
}
else
{
u = ppos[sq];
do
{
if (color[u] != c1)
if (atk2[u] == 0 || board[u] >= piece)
return (false);
u = ((color[u] == neutral) ? ppos[u] : pdir[u]);
}
while (u != sq);
}
return (true);
}
static inline int
PawnValue (register SHORT sq, SHORT side)
/*
* Calculate the positional value for a pawn on 'sq'.
*/
{
register SHORT fyle, rank;
register SHORT j, s, a1, a2, in_square, r, e;
a1 = (atk1[sq] & 0x4FFF);
a2 = (atk2[sq] & 0x4FFF);
rank = row (sq);
fyle = column (sq);
s = 0;
/* Central pawns, double pawns and isolanis */
if (CentralPawn[sq])
s += PCENTER * 2;
if ((fyle == 0 || PC1[fyle - 1] == 0) && (fyle == 7 || PC1[fyle + 1] == 0))
{
s += ISOLANI[fyle];
if (PC2[fyle] == 0)
s += PWEAKH;
}
if (PC1[fyle] > 1)
s += PDOUBLED;
if (c1 == white)
{
s += Mwpawn[sq];
if ((sq == 11 || sq == 12) && color[sq + 8] != neutral)
s += PEDRNK2B;
if (a1 < ctlP && atk1[sq + 8] < ctlP && atk2[sq + 8] & ctlP)
{
s += BACKWARD[a2 & 0xFF] * 2;
if (PC2[fyle] == 0) s += PWEAKH;
if (color[sq + 8] != neutral) s += PBLOK;
}
if (c1 == computer && rank != 7 && color[sq+8] == black && board[sq+8] == pawn) s -= PCRASH;
if (PC2[fyle] == 0)
{
r = rank - ((side == black)?1:0);
in_square = (row (bking) >= r && distance (sq, bking) < 8 - r);
e = (a2 == 0 || side == white)? 0: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 (c1 == black)
{
s += Mbpawn[sq];
if ((sq == 51 || sq == 52) && color[sq - 8] != neutral)
s += PEDRNK2B;
if (a1 < ctlP && atk1[sq - 8] < ctlP && atk2[sq - 8] & ctlP)
{
s += BACKWARD[a2 & 0xFF] * 2;
if (PC2[fyle] == 0) s += PWEAKH;
if (color[sq - 8] != neutral) s += PBLOK;
}
if (c1 == computer && rank != 0 && color[sq-8] == white && board[sq-8] == pawn) s -= PCRASH;
if (PC2[fyle] == 0)
{
r = rank + ((side == white)?1:0);
in_square = (row (wking) <= r && distance (sq, wking) < r + 1);
e = (a2 == 0 || side == black)?0: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];
}
}
if ((rank > 2 && rank < 5) && (fyle > 2 && fyle < 5)) s += PCENTER;
#ifdef notdef
if (a2 > 0)
{
if (a1 == 0 || a2 > ctlP + 1)
{
s += HUNGP;
if (trapped (sq)) hung[c1] += 2;
hung[c1]++;
}
else if (a2 > a1) s += ATAKD;
}
#endif
return (s);
}
inline
int
KnightValue (register SHORT sq, register SHORT side)
/*
* Calculate the positional value for a knight on 'sq'.
*/
{
register SHORT s, a2, a1;
s = Mknight[c1][sq];
a2 = (atk2[sq] & 0x4FFF);
if (a2 > 0)
{
a1 = (atk1[sq] & 0x4FFF);
if (a1 == 0 || a2 > ctlBN + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlBN || a1 < ctlP)
s += ATAKD;
}
return (s);
}
inline
int
BishopValue (register SHORT sq, register SHORT side)
/*
* Calculate the positional value for a bishop on 'sq'.
*/
{
register SHORT s;
register SHORT a2, a1;
SHORT mob;
s = Mbishop[c1][sq];
s += BRscan (sq, &mob);
s += BMBLTY[mob] * 2;
a2 = (atk2[sq] & 0x4FFF);
if (a2 > 0)
{
a1 = (atk1[sq] & 0x4FFF);
if (a1 == 0 || a2 > ctlBN + 1)
{
s += HUNGP;
if (trapped (sq))
hung[c1] += 2;
hung[c1]++;
}
else if (a2 >= ctlBN || a1 < ctlP)
s += ATAKD;
}
return (s);
}
inline
int
RookValue (register SHORT sq, register SHORT side)
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -