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

📄 eval.c

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