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

📄 eval.c

📁 gun C 环境下编写的
💻 C
📖 第 1 页 / 共 3 页
字号:
 *  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 + -