?? eval.c
字號:
* winning side to attract the search to such positions.
*
**************************************************************************/
{
int s, winer, sq1, sq2;
winer = 1^loser;
if (board.material[winer] == ValueB+ValueN &&
nbits(board.b[winer][bishop]) == 1 &&
nbits(board.b[winer][knight]) == 1)
return (ScoreKBNK (side, loser));
sq1 = board.king[winer];
sq2 = board.king[loser];
s = 150 - 6 * taxicab[sq1][sq2] - EndingKing[sq2];
if (side == loser)
s = -s;
s += MATERIAL;
return (s);
}
int KPK (int side)
/**************************************************************************
*
* A KPK endgame evaluator. Side is the one on the move.
* This is not a perfect evaluator, it merely identifies SOME positions
* as wins or draw. Some WON positions could be seen as draws; the search
* will be able to use the knowledge here to identify more positions.
*
**************************************************************************/
{
int winer, loser, sq, sqw, sql;
int s;
winer = (board.b[white][pawn] ? white : black);
loser = 1 ^ winer;
sq = leadz (board.b[winer][pawn]);
sqw = board.king[winer];
sql = board.king[loser];
s = ValueP + (ValueQ * Passed[winer][RANK(sq)] / PFACTOR) +
4 * (winer == white ? RANK(sqw) : 7-RANK(sqw));
/**************************************************************************
*
* Pawn is outside the square of the king
*
**************************************************************************/
if (~SquarePawnMask[winer][sq] & board.b[loser][king])
{
if (!(MoveArray[king][sql] & SquarePawnMask[winer][sq]))
return (winer == side ? s : -s);
if (winer == side)
return (s);
}
/**************************************************************************
*
* Friendly king is on same or adjacent file to the pawn, and the pawn is
* on a file other than a rook file and ...
*
**************************************************************************/
if (ROW(sq) != 0 && ROW(sq) != 7 &&
((IsolaniMask[ROW(sq)] | FileBit[ROW(sq)]) & board.b[winer][king]))
{
/**************************************************************************
*
* a. friendly king is 2 ranks more advanced than the pawn
* b. friendly king is 1 rank more advanced than the pawn
* i. The friendly king is on the sixth rank.
* ii. The enemy king does not have direct opposition by being 2 ranks
* in front of the friendly king and on the same file.
* c. friendly king is same rank as pawn
* i. The enemy king is not 2-4 ranks more advanced that the pawn.
* ii. The pawn is on the sixth rank and the enemy king does not have
* direct opposition.
* d. pawn is on the 7th rank, friendly king is on sixth rank and
* i. The enemy king is not on the queening square.
* ii. The enemy is on the queening square but both kings are in the same
* file.
*
**************************************************************************/
if (winer == white)
{
if (RANK(sqw) == RANK(sq) + 2)
return (winer == side ? s : -s);
if (RANK(sqw) == RANK(sq) + 1)
{
if (RANK(sqw) == 5)
return (winer == side ? s : -s);
if (sqw < A6)
{
if (sqw+16 == sql && winer == side)
return (0);
else
return (winer == side ? s : -s);
}
}
if (RANK(sqw) == RANK(sq))
{
if ((RANK(sql) - RANK(sq) < 2 || RANK(sql) - RANK(sq) > 4) &&
winer == side)
return (s);
if ((RANK(sql) - RANK(sq) < 1 || RANK(sql) - RANK(sq) > 5) &&
loser == side)
return (-s);
if (RANK(sq) == 5 && sqw+16 != sql)
return (winer == side ? s : 0);
}
if (RANK(sq) == 6 && RANK(sqw) == 5)
{
if (sql != sq+8)
return (winer == side ? s : 0);
if (sql == sq+8 && sql == sqw+16)
return (winer == side ? s : 0);
}
}
else
{
if (RANK(sqw) == RANK(sq) - 2)
return (winer == side ? s : -s);
if (RANK(sqw) == RANK(sq) - 1)
{
if (RANK(sqw) == 2)
return (winer == side ? s : -s);
if (sqw > H3)
{
if (sqw-16 == sql && winer == side)
return (0);
else
return (winer == side ? s : -s);
}
}
if (RANK(sqw) == RANK(sq))
{
if ((RANK(sq) - RANK(sql) < 2 || RANK(sq) - RANK(sql) > 4) &&
winer == side)
return (s);
if ((RANK(sq) - RANK(sql) < 1 || RANK(sq) - RANK(sql) > 5) &&
loser == side)
return (-s);
if (RANK(sq) == 5 && sqw+16 != sql)
return (winer == side ? s : 0);
}
if (RANK(sq) == 1 && RANK(sqw) == 2)
{
if (sql != sq-8)
return (winer == side ? s : 0);
if (sql == sq-8 && sql == sqw-16)
return (winer == side ? s : 0);
}
}
}
return (0);
}
int KBNK[64] =
{
0, 10, 20, 30, 40, 50, 60, 70,
10, 20, 30, 40, 50, 60, 70, 60,
20, 30, 40, 50, 60, 70, 60, 50,
30, 40, 50, 60, 70, 60, 50, 40,
40, 50, 60, 70, 60, 50, 40, 30,
50, 60, 70, 60, 50, 40, 30, 20,
60, 70, 60, 50, 40, 30, 20, 10,
70, 60, 50, 40, 30, 20, 10, 0
};
int ScoreKBNK (int side, int loser)
/****************************************************************************
*
* My very own KBNK routine!
*
****************************************************************************/
{
int s, winer, sq1, sq2, sqB;
winer = 1^loser;
sqB = board.king[loser];
if (board.b[winer][bishop] & WHITESQUARES)
sqB = RANK(sqB)*8 + 7 - ROW(sqB);
sq1 = board.king[winer];
sq2 = board.king[loser];
s = 300 - 6 * taxicab[sq1][sq2];
s -= KBNK[sqB];
s -= EndingKing[sq2];
s -= taxicab[leadz(board.b[winer][knight])][sq2];
s -= taxicab[leadz(board.b[winer][bishop])][sq2];
/* King in the central 4x4 region is good! */
if (board.b[winer][king] & ULL(0x00003C3C3C3C0000))
s += 20;
if (side == loser)
s = -s;
s += MATERIAL;
return (s);
}
static const BitBoard nn[2] = { ULL(0x4200000000000000), ULL(0x0000000000000042) };
static const BitBoard bb[2] = { ULL(0x2400000000000000), ULL(0x0000000000000024) };
int ScoreDev (short side)
/***************************************************************************
*
* Calculate the development score for side (for opening only).
* Penalize the following.
* . Uncastled and cannot castled
* . Undeveloped knights and bishops
* . Early queen move.
*
***************************************************************************/
{
int s;
int sq;
BitBoard c;
/* Calculate whether we are developed */
c = (board.b[side][knight] & nn[side]) | (board.b[side][bishop] & bb[side]);
s = nbits(c) * -8;
/* If we are castled or beyond the 20th move, no more ScoreDev */
if (board.castled[side] || GameCnt >= 38)
return (s);
s += NOTCASTLED;
/* If the king is moved, nail it, otherwise check rooks */
if (Mvboard[board.king[side]] > 0)
s += KINGMOVED;
/* Discourage rook moves */
c = board.b[side][rook];
while (c) {
sq = leadz(c);
CLEARBIT(c, sq);
if (Mvboard[sq] > 0)
s += ROOKMOVED;
}
/* Penalize a queen that moves at all */
if (board.b[side][queen])
{
sq = leadz (board.b[side][queen]);
if (Mvboard[sq] > 0)
s += EARLYQUEENMOVE;
/* s += Mvboard[sq] * EARLYQUEENMOVE; */
}
/* Discourage repeat minor piece moves */
c = board.b[side][knight] | board.b[side][bishop];
while (c) {
sq = leadz(c);
CLEARBIT(c, sq);
if (Mvboard[sq] > 1)
s += EARLYMINORREPEAT;
/* s += Mvboard[sq] * EARLYMINORREPEAT; */
}
/* Discourage any wing pawn moves */
/* c = board.b[side][pawn] & (FileBit[0]|FileBit[1]|FileBit[6]|FileBit[7]); */
c = board.b[side][pawn] & ULL(0xc3c3c3c3c3c3c3c3);
while (c) {
sq = leadz(c);
CLEARBIT(c, sq);
if (Mvboard[sq] > 0)
s += EARLYWINGPAWNMOVE;
}
/* Discourage any repeat center pawn moves */
/* c = board.b[side][pawn] & (FileBit[2]|FileBit[3]|FileBit[4]|FileBit[5]); */
c = board.b[side][pawn] & ULL(0x3c3c3c3c3c3c3c3c);
while (c) {
sq = leadz(c);
CLEARBIT(c, sq);
if (Mvboard[sq] > 1)
s += EARLYCENTERPREPEAT;
}
return (s);
}
/* Array of pointer to functions */
static int (*ScorePiece[7]) (short) =
{ NULL, ScoreP, ScoreN, ScoreB, ScoreR, ScoreQ, ScoreK };
int Evaluate (int alpha, int beta)
/****************************************************************************
*
* First check to see if this position can be specially dealt with.
* E.g. if our bounds indicate that we are looking for a mate score,
* then just return the material score. Nothing else is important.
* If its a KPK endgame, call our KPK routine.
* If one side has a lone king & the winning side has no pawns then call
* the LoneKing() mating driver routine. Note that there is enough
* mating material as we have already check for insufficient mating material
* in the call to EvaluateDraw() in search()/quiesce().
*
****************************************************************************/
{
int side, xside;
int piece, s, s1, score;
int npiece[2];
BitBoard *b;
side = board.side;
xside = 1 ^ side;
/* If we are looking for a MATE, just return the material */
if (alpha > MATE-255 || beta < -MATE+255)
return (MATERIAL);
/* A KPK endgame. */
if (board.material[white]+board.material[black] == ValueP)
return (KPK (side));
/* One side has a lone king and other side has no pawns */
if (board.material[xside] == 0 && board.b[side][pawn] == NULLBITBOARD)
return LoneKing (side, xside);
if (board.material[side] == 0 && board.b[xside][pawn] == NULLBITBOARD)
return LoneKing (side, side);
/****************************************************************************
*
* Lets try a lazy evaluation. In this stage, we should evaluate all those
* features that gives big bonus/penalties. E.g. squares around king is
* attacked by enemy pieces, 2 rooks on 7th rank, runaway passed pawns etc.
* This will be the direction, so things will continue to change in this
* section.
*
****************************************************************************/
EvalCall++;
phase = PHASE;
b = board.b[white];
pieces[white] = b[knight] | b[bishop] | b[rook] | b[queen];
npiece[white] = nbits (pieces[white]);
b = board.b[black];
pieces[black] = b[knight] | b[bishop] | b[rook] | b[queen];
npiece[black] = nbits (pieces[black]);
s1 = MATERIAL;
if ((s1 + maxposnscore[side] < alpha || s1 - maxposnscore[xside] > beta) &&
phase <= 6)
{
score = s1;
goto next;
}
s = 0;
s += ScoreDev (side) - ScoreDev (xside);
s += ScoreP (side) - ScoreP (xside);
s += ScoreK (side) - ScoreK (xside);
s += BishopTrapped (side) - BishopTrapped (xside);
s += DoubleQR7 (side) - DoubleQR7 (xside);
s1 = s + MATERIAL;
/**************************************************************************
*
* See if we can have a lazy evaluation cut. Otherwise its a slow eval.
*
**************************************************************************/
if (s1 + lazyscore[side] < alpha || s1 - lazyscore[side] > beta)
{
score = s1;
}
else
{
EvalCnt++;
GenAtaks();
s1 = HUNGPENALTY * ( EvalHung(side) - EvalHung(xside) );
FindPins(&pinned);
for (piece = knight; piece < king; piece++)
{
s1 += (*ScorePiece[piece]) (side) - (*ScorePiece[piece]) (xside);
}
lazyscore[side] = MAX (s1, lazyscore[side]);
maxposnscore[side] = MAX (maxposnscore[side], s + s1);
score = s + s1 + MATERIAL;
}
/***************************************************************************
*
* Trade down bonus code. When ahead, trade pieces & not pawns;
*
***************************************************************************/
next:
if (MATERIAL >= 200)
{
score += (RootPieces - nbits(pieces[white] | pieces[black])) * TRADEPIECE;
score -= (RootPawns - nbits(board.b[white][pawn] | board.b[black][pawn]))
* TRADEPAWNS;
}
else if (MATERIAL <= -200)
{
score -= (RootPieces - nbits(pieces[white] | pieces[black])) * TRADEPIECE;
score += (RootPawns - nbits(board.b[white][pawn] | board.b[black][pawn]))
* TRADEPAWNS;
}
/***************************************************************************
*
* Opposite color bishops is drawish.
*
***************************************************************************/
if (ENDING && pieces[white] == board.b[white][bishop] &&
pieces[black] == board.b[black][bishop] &&
((pieces[white] & WHITESQUARES && pieces[black] & BLACKSQUARES) ||
(pieces[white] & BLACKSQUARES && pieces[black] & WHITESQUARES)))
{
score /= 2;
}
/***************************************************************************
*
* When one side has no mating material, then his score can never be > 0.
*
***************************************************************************/
if (score > 0 && !board.b[side][pawn] && (board.material[side] < ValueR
|| pieces[side] == board.b[side][knight]))
score = 0;
if (score < 0 && !board.b[xside][pawn] && (board.material[xside] < ValueR
|| pieces[xside] == board.b[xside][knight]))
score = 0;
return (score);
}
short EvaluateDraw (void)
/***************************************************************************
*
* This routine is called by search() and quiesce() before anything else
* is done. Its purpose it to check if the current position is a draw.
* 0. 50-move draw.
* 1. If there are any pawns, it is not.
* 2. If both sides has anything less than a rook, draw.
* 3. If both sides has <= 2 knights only, draw.
* 4. If its a KBBK and bishops of same color, draw.
*
***************************************************************************/
{
BitBoard *w, *b;
int wm, bm, wn, bn;
/*
* Exception - if we are close to a pawn move, promotion
* or capture it is possible a forced mate will follow.
* So we assume not drawn for 2 moves.
*/
if ( (GameCnt-Game50) < 5 )
return (false);
/* 50 move rule */
if ( (GameCnt-Game50) > 100 )
return (true);
w = board.b[white];
b = board.b[black];
if (w[pawn] != 0 || b[pawn] != 0)
return (false);
wm = board.material[white];
bm = board.material[black];
wn = nbits (w[knight]);
bn = nbits (b[knight]);
if ((wm<ValueR || (wm==2*ValueN && wn==2)) &&
(bm<ValueR || (bm==2*ValueN && bn==2)))
return (true);
if (wm < ValueR)
{
if (bm == 2*ValueB &&
( nbits(board.b[black][bishop] & WHITESQUARES) == 2 ||
nbits(board.b[black][bishop] & BLACKSQUARES) == 2 ))
return (true);
}
if (bm < ValueR)
{
if (wm == 2*ValueB &&
( nbits(board.b[white][bishop] & WHITESQUARES) == 2 ||
nbits(board.b[white][bishop] & BLACKSQUARES) == 2 ))
return (true);
}
return (false);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -