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

📄 eval.c

📁 一款运行在linux上的象棋游戏。用GTK/GNOME环境下用GLADE开发。
💻 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 + -