⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 GNU国际象棋C++源代码Windows版的
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -