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

📄 eval.c

📁 GNU国际象棋C++源代码Windows版的
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Calculate the positional value for a rook on 'sq'.
 */

{
    register SHORT s;
    register SHORT fyle, a2, a1;
    SHORT mob;

    s = RookBonus;
    s += BRscan (sq, &mob);
    s += RMBLTY[mob]; 
    fyle = column (sq);
    if (PC1[fyle] == 0)
	{ s += RHOPN;
    		if (PC2[fyle] == 0)
			s += RHOPNX;
        }
    if (pmtl[c2] > 100 && row (sq) == rank7[c1])
	s += 25;
    s += 14 - taxicab (sq, EnemyKing);
    a2 = (atk2[sq] & 0x4FFF);
    if (a2 > 0)
      {
	  a1 = (atk1[sq] & 0x4FFF);
	  if (a1 == 0 || a2 > ctlR + 1)
	    {
		s += HUNGP;
		if (trapped (sq))
		    hung[c1] += 2;
		hung[c1]++;
	    }
	  else if (a2 >= ctlR || a1 < ctlP)
	      s += ATAKD;
      }
    return (s);
}

inline
int
QueenValue (register SHORT sq, register SHORT side)

/*
 * Calculate the positional value for a queen on 'sq'.
 */

{
    register SHORT s, a2, a1;

    s = ((distance (sq, EnemyKing) < 3) ? 12 : 0);
    if (stage > 2)
	s += 14 - taxicab (sq, EnemyKing);
    a2 = (atk2[sq] & 0x4FFF);
    if (a2 > 0)
      {
	  a1 = (atk1[sq] & 0x4FFF);
	  if (a1 == 0 || a2 > ctlQ + 1)
	    {
		s += HUNGP;
		if (trapped (sq))
		    hung[c1] += 2;
		hung[c1]++;
	    }
	  else if (a2 >= ctlQ || a1 < ctlP)
	      s += ATAKD;
      }
    return (s);
}

inline
int
KingValue (register SHORT sq, register SHORT side)

/*
 * Calculate the positional value for a king on 'sq'.
 */

{
    register SHORT s;
    register SHORT fyle;
    SHORT a2, a1;
    s = (emtl[c2] > KINGPOSLIMIT) ? Mking[c1][sq] : Mking[c1][sq] / 2;
    if (KSFTY > 0)
/*	if (Developed[c2] || stage > 0) */
	    s += KingScan (sq);
    if (castld[c1])
	s += KCASTLD;
    else if (Mvboard[kingP[c1]])
	s += KMOVD;

    fyle = column (sq);
    if (PC1[fyle] == 0)
	s += KHOPN;
    if (PC2[fyle] == 0)
	s += KHOPNX;
    switch (fyle)
      {
      case 5:
	  if (PC1[7] == 0)
	      s += KHOPN;
	  if (PC2[7] == 0)
	      s += KHOPNX;
	  /* Fall through */
      case 6:
      case 4:
      case 0:

	  if (PC1[fyle + 1] == 0)
	      s += KHOPN;
	  if (PC2[fyle + 1] == 0)
	      s += KHOPNX;
	  break;
      case 2:
	  if (PC1[0] == 0)
	      s += KHOPN;
	  if (PC2[0] == 0)
	      s += KHOPNX;
	  /* Fall through */
      case 1:
      case 3:
      case 7:
	  if (PC1[fyle - 1] == 0)
	      s += KHOPN;
	  if (PC2[fyle - 1] == 0)
	      s += KHOPNX;
	  break;
      default:
	  /* Impossible! */
	  break;
      }
    /*  Some extra code for Ng5 problem */
    if (computer==c1 && fyle >= 6 && HasQueen[c2] && PC1[7]==0)
      s += AHOPEN;
    if (computer==c1 && fyle <= 1 && HasQueen[c2] && PC1[0]==0)
      s += AHOPEN;

    a2 = (atk2[sq] & 0x4FFF);
    if (a2 > 0)
      {
	  a1 = (atk1[sq] & 0x4FFF);
	  if (a1 == 0 || a2 > ctlK + 1)
	    {
		s += HUNGP;
		++hung[c1];
	    }
	  else
	      s += ATAKD;
      }
    return (s);
}


static int (*PieceValue[7]) (SHORT, SHORT) =
{NULL, PawnValue, KnightValue, BishopValue, RookValue, QueenValue, KingValue};

SHORT
ScorePosition (register SHORT side)

/*
 * Perform normal static evaluation of board position. A score is generated
 * for each piece and these are summed to get a score for each side.
 */

{
    register SHORT score;
    register SHORT sq, i, xside;
    SHORT s;

    xside = side ^ 1;
    hung[white] = hung[black] = pscore[white] = pscore[black] = 0;
/* initialize Hasxxx */
    HasKnight[white] = HasKnight[black] = 0;
    HasBishop[white] = HasBishop[black] = 0;
    HasRook[white] = HasRook[black] = 0;
    HasQueen[white] = HasQueen[black] = 0;
    for (s = white; s <= black; s++)
	for (i = PieceCnt[s]; i >= 0; i--)
	    switch (board[PieceList[s][i]])
	      {
	      case knight:
		  ++HasKnight[s];
		  break;
	      case bishop:
		  ++HasBishop[s];
		  break;
	      case rook:
		  ++HasRook[s];
		  break;
	      case queen:
		  ++HasQueen[s];
		  break;
	      }
#ifdef CACHE
    if (!(hashkey+hashbd) || !ProbeEETable (side, &s))
      {
#endif
          UpdateWeights ();
	  for (c1 = white; c1 <= black; c1++)
	    {
		c2 = c1 ^ 1;
		/* atk1 is array of atacks on squares by my side */
		atk1 = atak[c1];
		/* atk2 is array of atacks on squares by other side */
		atk2 = atak[c2];
		/* same for PC1 and PC2 */
		PC1 = PawnCnt[c1];
		PC2 = PawnCnt[c2];
		for (i = PieceCnt[c1]; i >= 0; i--)
		  {
		      sq = PieceList[c1][i];
		      s = (*PieceValue[board[sq]]) (sq, side);	
/*		      switch (board[sq])
			{
			case pawn:
			    s = PawnValue (sq, side);
			    break;
			case knight:
			    s = KnightValue (sq);
			    break;
			case bishop:
			    s = BishopValue (sq);
			    break;
			case rook:
			    s = RookValue (sq);
			    break;
			case queen:
			    s = QueenValue (sq);
			    break;
			case king:
			    s = KingValue (sq);
			    break;
			default:
			    s = 0;
			    break;
			} */
		      pscore[c1] += s;
		      svalue[sq] = s;
		  }
	    }
    if (hung[side] > 1)
	pscore[side] += HUNGX;
    if (hung[xside] > 1)
	pscore[xside] += HUNGX;
    if (hung[computer] > 1)
	pscore[computer] += 8 * HUNGX; 

/*  Bonus for double bishops  */
    if (HasBishop[side] == 2)
	pscore[side] += 10 + 2 * stage;
    if (HasBishop[xside] == 2)
	pscore[xside] += 10 + 2 * stage;

    score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
#ifndef NODITHER
    if (dither)
      {
	  if (flag.hash)
	      gsrand (starttime + (unsigned int) hashbd);
	  score += urand () % dither;
      }
#endif
    if (score > 0 && pmtl[side] == 0)
	if (emtl[side] < valueR)
	    score = 0;
	else if (score < valueR)
	    score /= 2;
    if (score < 0 && pmtl[xside] == 0)
	if (emtl[xside] < valueR)
	    score = 0;
	else if (-score < valueR)
	    score /= 2;

    if (mtl[xside] == valueK && emtl[side] > valueB)
	score += 200;
    if (mtl[side] == valueK && emtl[xside] > valueB)
	score -= 200;
#ifdef CACHE
    if(PUTVAR)PutInEETable(side,score);
#endif
    return (score);
#ifdef CACHE
}
else {
return s;
}
#endif
}
static inline void
BlendBoard (const SHORT a[64], const SHORT b[64], SHORT c[64])
{
    register int sq, s;
    s = 10 - stage;
    for (sq = 0; sq < 64; sq++)
	c[sq] = ((a[sq] * s) + (b[sq] * stage)) / 10;
}


void
ExaminePosition (void)

/*
 * This is done one time before the search is started. Set up arrays Mwpawn,
 * Mbpawn, Mknight, Mbishop, Mking which are used in the SqValue() function
 * to determine the positional value of each piece.
 */

{
    register SHORT i, sq;
    register SHORT fyle;
    SHORT wpadv, bpadv, wstrong, bstrong, z, side, pp, j, k, val, Pd, rank;
    static SHORT PawnStorm = false;
/* update ataks arrays */
    ataks (white, atak[white]);
    ataks (black, atak[black]);
/*	*/
    UpdateWeights ();
/* initialize Hasxxx */
    HasKnight[white] = HasKnight[black] = 0;
    HasBishop[white] = HasBishop[black] = 0;
    HasRook[white] = HasRook[black] = 0;
    HasQueen[white] = HasQueen[black] = 0;
    for (side = white; side <= black; side++)
	for (i = PieceCnt[side]; i >= 0; i--)
	    switch (board[PieceList[side][i]])
	      {
	      case knight:
		  ++HasKnight[side];
		  break;
	      case bishop:
		  ++HasBishop[side];
		  break;
	      case rook:
		  ++HasRook[side];
		  break;
	      case queen:
		  ++HasQueen[side];
		  break;
	      }
/* Developed if has moved knights and bishops */
    if (!Developed[white])
	Developed[white] = (board[1] != knight && board[2] != bishop &&
			    board[5] != bishop && board[6] != knight);
    if (!Developed[black])
	Developed[black] = (board[57] != knight && board[58] != bishop &&
			    board[61] != bishop && board[62] != knight);
/* Pawn Storm */
/*    if (!PawnStorm && stage < 5)*/
    PawnStorm = (stage < 5) &&
	           ((column (wking) < 3 && column (bking) > 4) ||
		     (column (wking) > 4 && column (bking) < 3));
/* setup base tables */
    memcpy (Mknight[white],pknight,sizeof(pknight));
    memcpy (Mknight[black],pknight,sizeof(pknight));
    memcpy(Mbishop[white],pbishop,sizeof(pbishop));
    memcpy(Mbishop[black],pbishop,sizeof(pbishop));

/* linear interpolate on stage	*/
/* Mking = (KingOpening * (10 - stage) + KingEnding * srage) /10  */
    BlendBoard (KingOpening, KingEnding, Mking[white]);
    BlendBoard (KingOpening, KingEnding, Mking[black]);

    for (sq = 0; sq < 64; sq++)
      {
	  fyle = column (sq);
	  rank = row (sq);
	  wstrong = bstrong = true;
/* does a black pawn attack to squares in this col from sq to end */
	  for (i = sq; i < 64; i += 8)
	      if (Patak (black, i)) { wstrong = false; break; }
/* does a white pawn attack to squares in this col from sq to end */
	  for (i = sq; i >= 0; i -= 8)
	      if (Patak (white, i)) { bstrong = false; break; }
/* 	*/
	  wpadv = bpadv = PADVNCM;
	  if ((fyle == 0 || PawnCnt[white][fyle - 1] == 0) && (fyle == 7 || PawnCnt[white][fyle + 1] == 0)) wpadv = PADVNCI;
	  if ((fyle == 0 || PawnCnt[black][fyle - 1] == 0) && (fyle == 7 || PawnCnt[black][fyle + 1] == 0)) bpadv = PADVNCI;
	  Mwpawn[sq] = (wpadv * PawnAdvance[sq]) / 10;
	  Mbpawn[sq] = (bpadv * PawnAdvance[63 - sq]) / 10;
	  Mwpawn[sq] += PawnBonus;
	  Mbpawn[sq] += PawnBonus;
/* 	*/
	  if (Mvboard[kingP[white]])
	    {
		if ((fyle < 3 || fyle > 4) && distance (sq, wking) < 3)
		    Mwpawn[sq] += PAWNSHIELD;
	    }
	  else if (rank < 3 && (fyle < 2 || fyle > 5))
	      Mwpawn[sq] += PAWNSHIELD / 2;
/* 	*/
	  if (Mvboard[kingP[black]])
	    {
		if ((fyle < 3 || fyle > 4) && distance (sq, bking) < 3)
		    Mbpawn[sq] += PAWNSHIELD;
	    }
	  else if (rank > 4 && (fyle < 2 || fyle > 5))
	      Mbpawn[sq] += PAWNSHIELD / 2;
/* 	*/
	  if (PawnStorm)
	    {
		if ((column (wking) < 4 && fyle > 4) || (column (wking) > 3 && fyle < 3))
		    Mwpawn[sq] += 4 * rank;
		if ((column (bking) < 4 && fyle > 4) || (column (bking) > 3 && fyle < 3))
		    Mbpawn[sq] -= (4 * rank - 28);
	    }
/* 	*/
	  Mknight[white][sq] += 5 - distance (sq, bking);
	  Mknight[white][sq] += 5 - distance (sq, wking);
	  Mknight[black][sq] += 5 - distance (sq, wking);
	  Mknight[black][sq] += 5 - distance (sq, bking);
/* 	*/
	  Mbishop[white][sq] += BishopBonus;
	  Mbishop[black][sq] += BishopBonus;
/* 	*/
	  for (i = PieceCnt[black]; i >= 0; i--)
	      if (distance (sq, PieceList[black][i]) < 3)
		  Mknight[white][sq] += KNIGHTPOST;
	  for (i = PieceCnt[white]; i >= 0; i--)
	      if (distance (sq, PieceList[white][i]) < 3)
		  Mknight[black][sq] += KNIGHTPOST;
/* 	*/
	  if (wstrong)
	      Mknight[white][sq] += KNIGHTSTRONG;
	  if (bstrong)
	      Mknight[black][sq] += KNIGHTSTRONG;
	  if (wstrong)
	      Mbishop[white][sq] += BISHOPSTRONG;
	  if (bstrong)
	      Mbishop[black][sq] += BISHOPSTRONG;
/* 	*/
#ifdef notdef
	  if (HasBishop[white] == 2)
	      Mbishop[white][sq] += 8;
	  if (HasBishop[black] == 2)
	      Mbishop[black][sq] += 8;
	  if (HasKnight[white] == 2)
	      Mknight[white][sq] += 5;
	  if (HasKnight[black] == 2)
	      Mknight[black][sq] += 5;
#endif
/* 	*/

	  Kfield[white][sq] = Kfield[black][sq] = 0;
	  if (distance (sq, wking) == 1)
	      Kfield[black][sq] = KATAK;
	  if (distance (sq, bking) == 1)
	      Kfield[white][sq] = KATAK;
/* 	*/
	  Pd = 0;
	  for (k = 0; k <= PieceCnt[white]; k++)
	    {
		i = PieceList[white][k];
		if (board[i] == pawn)
		  {
		      pp = true;
		      for (j = i + 8; j < 64; j += 8)
			  if (Patak (black, j) || board[j] == pawn)
			    {
				pp = false;
				break;
			    }
		      z = (pp ? i + ((row (i) == 6) ? 8 : 16) : i);
		      Pd += ((pp) ? 5 * taxicab (sq, z) : taxicab (sq, z));
		  }
	    }
/* 	*/
	  for (k = 0; k <= PieceCnt[black]; k++)
	    {
		i = PieceList[black][k];
		if (board[i] == pawn)
		  {
		      pp = true;
		      for (j = i - 8; j >= 0; j -= 8)
			  if (Patak (white, j) || board[j] == pawn)
			    {
				pp = false;
				break;
			    }
		      z = (pp ? i - ((row (i) == 1) ? 8 : 16) : i);
		      Pd += ((pp) ? 5 * taxicab (sq, z) : taxicab (sq, z));
		  }
	    }
/* 	*/
	  if (Pd != 0)
	    {
		val = (Pd * stage2) / 4;
		Mking[white][sq] -= val;
		Mking[black][sq] -= val;
	    }
      }
}

void
UpdateWeights (void)

/*
 * If material balance has changed, determine the values for the positional
 * evaluation terms.
 */

{
    register SHORT s1, tmtl;

    emtl[white] = mtl[white] - pmtl[white] - valueK;
    emtl[black] = mtl[black] - pmtl[black] - valueK;
    tmtl = emtl[white] + emtl[black];
    s1 = ((tmtl > 6600) ? 0 : ((tmtl < 1400) ? 10 : (6600 - tmtl) / 520));
    if (s1 != stage)
      {
	stage = s1;
	stage2 = ((tmtl > 3600) ? 0 : ((tmtl < 1400) ? 10 : (3600 - tmtl) / 220));
	PEDRNK2B = -15;		/* centre pawn on 2nd rank & blocked */
	PBLOK = -4;		/* blocked backward pawn */
	PDOUBLED = -14;		/* doubled pawn */
	PWEAKH = -12;		/* weak pawn on half open file */
	PAWNSHIELD = 10-stage;	/* pawn near friendly king */
	PADVNCM = 12;		/* advanced pawn multiplier */
	PADVNCI = 7;		/* muliplier for isolated pawn */
	PawnBonus = stage;

	KNIGHTPOST = (stage + 2) / 3;	/* knight near enemy pieces */
	KNIGHTSTRONG = (stage + 6) / 2;	/* occupies pawn hole */

	BISHOPSTRONG = (stage + 6) / 2;	/* occupies pawn hole */
	BishopBonus = BBONUS * stage;

	RHOPN = 10;		/* rook on half open file */
	RHOPNX = 4;
	RookBonus = RBONUS * stage;

	XRAY = 8;		/* Xray attack on piece */
	PINVAL = 16;		/* Pin */

	KHOPN = (2 * stage - 20);	/* king on half open file */
	KHOPNX = KHOPN / 2;
	KCASTLD = 10 - stage;
	KMOVD = -40 / (stage + 1);	/* king moved before castling */
	KATAK = (10 - stage);		/* B,R attacks near enemy king */
	KSFTY = ((stage < 8) ? (KINGSAFETY - 4 * stage) : 0);

	ATAKD = -8;		/* defender > attacker */
	HUNGP = -12;		/* each hung piece */
	HUNGX = -18;		/* extra for >1 hung piece */
      }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -