📄 eval.c
字号:
/*
* eval.c - C source for GNU CHESS
*
* Copyright (c) 1988,1989,1990 John Stanback
* Copyright (c) 1992 Free Software Foundation
*
* This file is part of GNU CHESS.
*
* GNU Chess is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* GNU Chess is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Chess; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "gnuchess.h"
#include "ataks.h"
#include "ttable.h" /* uses hashbd, hashkey and eval cache */
/* Backward pawn bonus indexed by # of attackers on the square */
static const SHORT BACKWARD[16] =
{-6, -10, -15, -21, -28, -28, -28, -28, -28, -28, -28, -28, -28, -28, -28, -28};
/* Bishop mobility bonus indexed by # reachable squares */
static const SHORT BMBLTY[14] =
{-2, 0, 2, 4, 6, 8, 10, 12, 13, 14, 15, 16, 16, 16};
/* Rook mobility bonus indexed by # reachable squares */
static const SHORT RMBLTY[15] =
{0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14};
/* Positional values for a dying king */
static const SHORT DyingKing[64] =
{0, 8, 16, 24, 24, 16, 8, 0,
8, 32, 40, 48, 48, 40, 32, 8,
16, 40, 56, 64, 64, 56, 40, 16,
24, 48, 64, 72, 72, 64, 48, 24,
24, 48, 64, 72, 72, 64, 48, 24,
16, 40, 56, 64, 64, 56, 40, 16,
8, 32, 40, 48, 48, 40, 32, 8,
0, 8, 16, 24, 24, 16, 8, 0};
/* Isolated pawn penalty by rank */
static const SHORT ISOLANI[8] =
/*{-18, -20, -22, -24, -24, -22, -20, -18};*/
{-8, -10, -12, -14, -14, -12, -10, -8};
/* table for King Bishop Knight endings */
static const SHORT KBNK[64] =
{620, 560, 500, 440, 380, 320, 260, 240,
560, 520, 460, 400, 340, 280, 230, 260,
500, 460, 320, 280, 260, 220, 280, 320,
440, 400, 280, 200, 200, 260, 340, 380,
380, 340, 260, 200, 200, 280, 400, 440,
320, 280, 220, 260, 280, 320, 460, 500,
260, 230, 280, 340, 400, 460, 520, 560,
240, 260, 320, 380, 440, 500, 560, 620};
/* penalty for threats to king, indexed by number of such threats */
static const SHORT KTHRT[36] =
{0, -8, -20, -36, -52, -68, -80, -80, -80, -80, -80, -80,
-80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
-80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80};
/* King positional bonus inopening stage */
static const SHORT KingOpening[64] =
{0, 0, -4, -10, -10, -4, 0, 0,
-4, -4, -8, -12, -12, -8, -4, -4,
-12, -16, -20, -20, -20, -20, -16, -12,
-16, -20, -24, -24, -24, -24, -20, -16,
-16, -20, -24, -24, -24, -24, -20, -16,
-12, -16, -20, -20, -20, -20, -16, -12,
-4, -4, -8, -12, -12, -8, -4, -4,
0, 0, -4, -10, -10, -4, 0, 0};
/* King positional bonus in end stage */
static const SHORT KingEnding[64] =
{0, 6, 12, 18, 18, 12, 6, 0,
6, 12, 18, 24, 24, 18, 12, 6,
12, 18, 24, 30, 30, 24, 18, 12,
18, 24, 30, 36, 36, 30, 24, 18,
18, 24, 30, 36, 36, 30, 24, 18,
12, 18, 24, 30, 30, 24, 18, 12,
6, 12, 18, 24, 24, 18, 12, 6,
0, 6, 12, 18, 18, 12, 6, 0};
/* Passed pawn positional bonus */
static const SHORT PassedPawn0[8] =
{0, 60, 80, 120, 200, 360, 600, 800};
static const SHORT PassedPawn1[8] =
{0, 30, 40, 60, 100, 180, 300, 800};
static const SHORT PassedPawn2[8] =
{0, 15, 25, 35, 50, 90, 140, 800};
static const SHORT PassedPawn3[8] =
{0, 5, 10, 15, 20, 30, 140, 800};
/* Knight positional bonus */
static const SHORT pknight[64] =
{0, 4, 8, 10, 10, 8, 4, 0,
4, 8, 16, 20, 20, 16, 8, 4,
8, 16, 24, 28, 28, 24, 16, 8,
10, 20, 28, 32, 32, 28, 20, 10,
10, 20, 28, 32, 32, 28, 20, 10,
8, 16, 24, 28, 28, 24, 16, 8,
4, 8, 16, 20, 20, 16, 8, 4,
0, 4, 8, 10, 10, 8, 4, 0};
/* Bishop positional bonus */
static const SHORT pbishop[64] =
{14, 14, 14, 14, 14, 14, 14, 14,
14, 22, 18, 18, 18, 18, 22, 14,
14, 18, 22, 22, 22, 22, 18, 14,
14, 18, 22, 22, 22, 22, 18, 14,
14, 18, 22, 22, 22, 22, 18, 14,
14, 18, 22, 22, 22, 22, 18, 14,
14, 22, 18, 18, 18, 18, 22, 14,
14, 14, 14, 14, 14, 14, 14, 14};
/* Pawn positional bonus */
static const SHORT PawnAdvance[64] =
{0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 4, 0, 0, 4, 4, 4,
6, 8, 8, 10, 10, 8, 8, 6,
6, 8, 12, 16, 16, 12, 8, 6,
8, 12, 16, 24, 24, 16, 12, 8,
12, 16, 24, 32, 32, 24, 16, 12,
12, 16, 24, 32, 32, 24, 16, 12,
0, 0, 0, 0, 0, 0, 0, 0};
static const SHORT CentralPawn[64] =
{ 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0} ;
#define AHOPEN (-270)
static SHORT kpkwv_ (SHORT, SHORT, SHORT, SHORT, SHORT, SHORT);
static SHORT kpkbv_ (SHORT, SHORT, SHORT, SHORT, SHORT, SHORT);
inline static int ScoreKBNK (SHORT, SHORT, SHORT);
inline static int ScoreK1PK (SHORT, SHORT, SHORT, SHORT, SHORT, SHORT);
SHORT PUTVAR = false;
SHORT Mwpawn[64], Mbpawn[64], Mknight[2][64], Mbishop[2][64];
static SHORT Mking[2][64], Kfield[2][64];
static SHORT c1, c2, *atk1, *atk2, *PC1, *PC2;
SHORT atak[2][64];
SHORT emtl[2];
static SHORT PawnBonus, BishopBonus, RookBonus;
static SHORT KNIGHTPOST, KNIGHTSTRONG, BISHOPSTRONG, KATAK;
static SHORT PEDRNK2B, PWEAKH, PADVNCM, PADVNCI, PAWNSHIELD, PDOUBLED, PBLOK;
static SHORT RHOPN, RHOPNX, KHOPN, KHOPNX, KSFTY;
static SHORT ATAKD, HUNGP, HUNGX, KCASTLD, KMOVD, XRAY, PINVAL;
SHORT pscore[2];
/************************* Evaluation cache code ****************************/
/* NOTE: The static evaluation cache "EETable" belongs to eval.c and cannot */
/* be moved to ttable.c */
#ifdef CACHE
struct etable *etab[2];
inline void
PutInEETable (SHORT side,int score)
/*
* Store the current eval position in the static cache
*/
{
register struct etable *ptbl;
#ifdef DEBUG
if (flag.nocache) return;
#endif
ptbl = &((etab[side])[hashkey % (ETABLE)]);
ptbl->ehashbd = hashbd;
ptbl->escore[white] = pscore[white];
ptbl->escore[black] = pscore[black];
ptbl->hung[white] = hung[white];
ptbl->hung[black] = hung[black];
ptbl->score = score;
memcpy (ptbl->sscore, svalue, sizeof (svalue));
#if defined HASHSTATS
EADD++;
#endif
return;
}
inline int
CheckEETable (SHORT side)
/* Check the static cache for an entry */
{
register struct etable *ptbl;
#ifdef DEBUG
if (flag.nocache) return false;
#endif
ptbl = &((etab[side])[hashkey % (ETABLE)]);
if (hashbd == ptbl->ehashbd) return true;
return false;
}
inline int
ProbeEETable (SHORT side, SHORT *score)
/* Get an evaluation from the static cache */
{
register struct etable *ptbl;
#ifdef DEBUG
if (flag.nocache) return false;
#endif
ptbl = &((etab[side])[hashkey % (ETABLE)]);
if (hashbd == ptbl->ehashbd)
{
pscore[white] = ptbl->escore[white];
pscore[black] = ptbl->escore[black];
memcpy (svalue, ptbl->sscore, sizeof (svalue));
*score = ptbl->score;
hung[white] = ptbl->hung[white];
hung[black] = ptbl->hung[black];
#if defined HASHSTATS
EGET++;
#endif
return true;
}
return false;
}
#else /* Define null stubs for the above procedures */
#define PutInEETable(side, score)
#define ProbeEETable(side, score) (false)
#define CheckEETable(side) (false)
#endif /* CACHE */
/* ............ POSITIONAL EVALUATION ROUTINES ............ */
/*
* Inputs are:
* pmtl[side] - value of pawns
* mtl[side] - value of all material
* emtl[side] - vaule of all material - value of pawns - value of king
* hung[side] - count of hung pieces
* Tscore[ply] - search tree score for ply
* ply
* Pscore[ply] - positional score for ply ply
* INCscore - bonus score or penalty for certain positions
* slk - single lone king flag
* Sdepth - search goal depth
* ChkFlag[ply]- checking piece at level ply or 0 if no check
* PC1[column] - # of my pawns in this column
* PC2[column] - # of opponents pawns in column
* PieceCnt[side] - just what it says
*/
inline
int
ScoreKPK (SHORT side,
SHORT winner,
SHORT loser,
SHORT king1,
register SHORT king2,
register SHORT sq)
/*
* Score King and Pawns versus King endings.
*/
{
register SHORT s, r;
s = ((PieceCnt[winner] == 1) ? 50 : 120);
if (winner == white)
{
r = row (sq) - ((side == loser) ? 1 : 0);
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 if (row (sq) == 6)
sq += 8;
}
else
{
r = row (sq) + ((side == loser) ? 1 : 0);
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 if (row (sq) == 1)
sq -= 8;
}
s += 8 * (taxicab (king2, sq) - taxicab (king1, sq));
return (s);
}
inline
SHORT
ScoreLoneKing (SHORT side)
/*
* Static evaluation when loser has only a king and winner has no pawns or no
* pieces.
*/
{
register SHORT winner, loser, king1, king2, s, i;
if (mtl[white] == valueK && mtl[black] == valueK)
return 0;
UpdateWeights ();
winner = ((mtl[white] > mtl[black]) ? white : black);
loser = winner ^ 1;
king1 = PieceList[winner][0];
king2 = PieceList[loser][0];
s = 0;
if (pmtl[winner] == 0)
{
if (emtl[winner] == valueB + valueN)
s = ScoreKBNK (winner, king1, king2);
else if (emtl[winner] == valueN + valueN)
s = 0;
else if (emtl[winner] < valueR)
s = 0;
else
s = 500 + emtl[winner] - DyingKing[king2] - 10 * distance (king1, king2);
}
else
{
if (pmtl[winner] == valueP)
s = ScoreK1PK (side, winner, loser, king1, king2, PieceList[winner][1]);
else
for (i = 1; i <= PieceCnt[winner]; i++)
s += ScoreKPK (side, winner, loser, king1, king2, PieceList[winner][i]);
}
return ((side == winner) ? s : -s);
}
inline
int
ScoreKBNK (SHORT winner, SHORT king1, SHORT king2)
/*
* Score King+Bishop+Knight versus King endings. Works fine now.
*/
{
register SHORT s, Bsq, Nsq, KBNKsq = 0;
if (board[PieceList[winner][1]] == bishop)
{
Bsq = PieceList[winner][1];
Nsq = PieceList[winner][2];
}
else
{
Bsq = PieceList[winner][2];
Nsq = PieceList[winner][1];
}
KBNKsq = (((row (Bsq) % 2) == (column (Bsq) % 2)) ? 0 : 7);
s = emtl[winner] - 300;
s += ((KBNKsq == 0) ? KBNK[king2] : KBNK[locn (row (king2), 7 - column (king2))]);
s -= (8*taxicab(king1,king2) + 2*distance(Nsq,king2) + distance(Bsq,king2));
s += KingEnding[king1];
return (s);
}
SHORT dist_ (SHORT f1, SHORT r1, SHORT f2, SHORT r2)
{
return distdata [ f1-9+8*r1 ][ f2-9+8*r2 ];
}
inline
int
ScoreK1PK (SHORT side,
SHORT winner,
SHORT loser,
SHORT king1,
register SHORT king2,
register SHORT sq)
/*
* We call Don Beal's routine with the necessary parameters and determine
* win/draw/loss. Then we compute the real evaluation which is +-500 for
* a win/loss and 10 for a draw, plus some points to lead the computer to
* a decisive winning/drawing line.
*/
{
#ifdef WAY4PL64
SHORT s;
#endif
SHORT win, sqc, sqr, k1c, k1r, k2c, k2r;
const int drawn = 10, won = 500;
#ifdef WAY4PL64
#ifdef CACHE
if (ProbeEETable(side,&s)) return s;
#endif
#endif
sqc = column (sq) + 1;
sqr = row (sq) + 1;
k1c = column (king1) + 1;
k1r = row (king1) + 1;
k2c = column (king2) + 1;
k2r = row (king2) + 1;
if (winner == black)
{
sqr = 9 - sqr;
k1r = 9 - k1r;
k2r = 9 - k2r;
}
if (sqc > 4)
{
sqc = 9 - sqc;
k1c = 9 - k1c;
k2c = 9 - k2c;
}
if (side == winner)
win = kpkwv_ (sqc, sqr, k1c, k1r, k2c, k2r);
else
win = kpkbv_ (sqc, sqr, k1c, k1r, k2c, k2r);
#ifdef WAY4PL64
if (!win) s = drawn + 5 * distance (sq, king2) - 5*distance(king1,king2);
else s = won + 50 * (sqr - 2) + 10*distance(sq,king2);
#else
if (!win)
return drawn + 5 * distance (sq, king2);
else
return won + 50 * (sqr - 2);
#endif
#ifdef WAY4PL64
#ifdef CACHE
if (PUTVAR) PutInEETable (side, s);
#endif
return s;
#endif
}
static SHORT
kpkwv_ (SHORT pf, SHORT pr, SHORT wf, SHORT wr, SHORT bf, SHORT br)
{
/*
* Don Beal's routine, which was originally in Fortran. See AICC 2
*/
static SHORT wbdd, mbpf, nbpf, blpu;
static SHORT brpu, mwpf, wlpu, wrpu, blpuu, brpuu, wlpuu, wrpuu, md,
bq, blpuuu, brpuuu, bsd, tbf, sgf, bpp, sdr, sgr, wsd, wsg, ppr, wpp;
ppr = ((pr == 2) ? 3 : pr);
if (pf == 1)
{
if (bf == 3)
{
if (pr == 7 && wf == 1 && wr == 8 && br > 6) return (0);
if (pr == 6 && wf < 4 && wr == 6 && br == 8) return (1);
}
if (bf == 1 && br > pr) return (0);
if (pr == 7 && bf > 2) return (1);
if (bf <= 3 && br - ppr > 1) return (0);
if (wf == 1 && bf == 3 && wr - pr == 1 && br - pr == 1) return(0);
}
bq = dist_ (bf, br, pf, 8);
if (bq > 8 - ppr) return (1);
mbpf = bf - pf;
if (mbpf < 0) mbpf = -mbpf;
bpp = dist_ (bf, br, pf, ppr);
wpp = dist_ (wf, wr, pf, ppr);
if (bpp - wpp < -1 && br - pr != mbpf) return (0);
if (pf == 1 && pr <= 3 && wf <= 2 && wr == 8 && bf == 4 && br >= 7) return (1);
if (!(pf != 2 || pr != 6 || bf != 1 || br != 8))
{
if (wf <= 3 && wr == 6) return (0);
if (wf == 4 && wr == 8) return (0);
}
if (pr == 7)
{
if (wr < 8 && wpp == 2 && bq == 0) return (1);
if (wr == 6 && wf == pf && bq == 0) return (1);
if (wr >= 6 && wpp <= 2 && bq != 0) return (1);
}
blpuu = dist_ (bf, br, pf - 1, pr + 2);
wbdd = dist_ (wf, wr, bf, br - 2);
brpuu = dist_ (bf, br, pf + 1, pr + 2);
if (pr == 6)
{
if (dist_ (bf, br, pf + 1, pr) > 1 &&
brpuu > dist_ (wf, wr, pf + 1, pr)) return (1);
if (pf != 1)
{
if (blpuu > dist_ (wf, wr, pf - 1, pr)) return (1);
if (br == 8 && mbpf == 1 && wbdd == 1) return (1);
if (br > 6 && nbpf == 2 && dist_ (wf, wr, bf, 5) <= 1) return (1);
}
else
if (wf == 1 && wr == 8 && bf == 2 && br == 6) return (0);
}
mwpf = wf - pf;
if (mwpf < 0) mwpf = -mwpf;
if (pr >= 5 && mwpf == 2 && wr == pr && bf == wf && br - pr == 2) return (1);
brpu = dist_ (bf, br, pf + 1, pr + 1);
wrpu = dist_ (wf, wr, pf + 1, pr + 1);
blpu = dist_ (bf, br, pf - 1, pr + 1);
wlpu = dist_ (wf, wr, pf - 1, pr + 1);
if (!(pf == 1 || pr != 5))
{
if (mwpf <= 1 && wr - pr == 1) return (1);
if (wrpu == 1 && brpu > 1) return (1);
if (wr >= 4 && bf == wf && br - pr >= 2 && mbpf == 3) return (1);
if (wlpu == 1 && blpu > 1) return (1);
}
if (pr == 2 && br == 3 && mbpf > 1 && dist_ (wf, wr, bf, br + 2) <= 1) return (1);
if (wr - pr == 2 && br == pr && mbpf == 1 && mwpf > 1 &&
(wf - pf) * (bf - pf) > 0) return (0);
if (pf == 1 && wf == 1 && wr == br && bf > 3) return (1);
sgf = pf - 1;
if (wf >= pf) { sgf = pf + 1; }
sgr = wr - (mwpf - 1);
if (mwpf == 0 && wr > br) sgr = wr - 1;
wsg = dist_ (wf, wr, sgf, sgr);
if (wr - pr - mwpf > 0 && wr - br >= -1 && bpp - (wsg + (sgr - ppr))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -