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

📄 move.c

📁 gun C 环境下编写的
💻 C
📖 第 1 页 / 共 2 页
字号:
      if (cboard[t] != 0)		/* capture */
         *s++ = 'x'; 
      strcpy (s, algbr[t]);
      s += 2;
   }

   /* See if it is a checking or mating move */
   MakeMove (side, &move);
   if (SqAtakd (board.king[1^side], side))
   {
      TreePtr[ply+2] = TreePtr[ply+1];
      GenCheckEscapes (ply+1);
      if (TreePtr[ply+1] == TreePtr[ply+2])
         *s++ = '#';
      else
         *s++ = '+';
      GenCnt -= TreePtr[ply+2] - TreePtr[ply+1];
   }
   UnmakeMove (1^side, &move); 

   *s = '\0';
   return;
}


#define ASCIITOFILE(a) ((a) - 'a')
#define ASCIITORANK(a) ((a) - '1')
#define ASCIITOSQ(a,b) (ASCIITOFILE(a)) + (ASCIITORANK(b)) * 8
#define ATOH(a) ((a) >= 'a' && (a) <= 'h')
#define ITO8(a) ((a) >= '1' && (a) <= '8')

inline int piece_id(const char c)
{
/* Given c, what is the piece id.  This only takes one char, which
 * isn't enough to handle two-character names (common in Russian text
 * and old English notation that used Kt), but we're not supposed to
 * see such text here anyway.  This will
 * accept "P" for pawn, and many lowercase chars (but not "b" for Bishop). */
   switch (c)
   {
      case 'n':
      case 'N':
         return knight;
      case 'B':
         return bishop;
      case 'r':
      case 'R':
         return rook;
      case 'q':
      case 'Q':
         return queen;
      case 'k':
      case 'K':
         return king;
      case 'p':
      case 'P':
         return pawn;
   }
   return empty;
}



leaf * ValidateMove (char *s)
/*************************************************************************
 *
 *  This routine takes a string and check to see if it is a legal move.
 *  Note.  At the moment, we accept 2 types of moves notation.
 *  1.  e2e4 format.   2. SAN format. (e4)
 *
 **************************************************************************/
{
   short f, t, side, rank, file, fileto;
   short piece, piece2, kount;
   char promote;
   char mvstr[MAXSTR], *p;
   BitBoard b, b2;
   leaf *n1, *n2;

   TreePtr[2] = TreePtr[1];
   GenMoves (1);   
   FilterIllegalMoves (1);	
   side = board.side;

   /************************************************************************
    * The thing to do now is to clean up the move string.  This
    * gets rid of things like 'x', '+', '=' and so forth.
    ************************************************************************/
   p = mvstr;
   do
   {
      if (*s != 'x' && *s != '+' && *s != '=' && !isspace(*s))
         *p++ = *s; 
   } while (*s++ != '\0' );

   /* Flush castles that check */
   if (mvstr[strlen(mvstr)-1] == '+' || mvstr[strlen(mvstr)-1] == '#' ||
       mvstr[strlen(mvstr)-1] == '=') mvstr[strlen(mvstr)-1] = '\000'; 

   /* Check for castling */
   if (strcmp (mvstr, "O-O") == 0 || strcmp (mvstr, "o-o") == 0 || 
       strcmp (mvstr, "0-0") == 0)
   {
      if (side == white)
      {
         f = 4; t = 6;
      }
      else 
      {
	 f = 60; t = 62;
      }
      return (IsInMoveList (1, f, t, ' '));
   }

   if (strcmp (mvstr, "O-O-O") == 0 || strcmp (mvstr, "o-o-o") == 0 ||
       strcmp (mvstr, "0-0-0") == 0)
   {
      if (side == white)
      {
         f = 4; t = 2;
      }
      else
      {
         f = 60; t = 58;
      }
      return (IsInMoveList (1, f, t, ' '));
   }

   /*  Test to see if it is e2e4 type notation */
   if (ATOH (mvstr[0]) && ITO8 (mvstr[1]) && ATOH (mvstr[2]) &&
	ITO8 (mvstr[3]))
   {
      f = ASCIITOSQ (mvstr[0], mvstr[1]);
      t = ASCIITOSQ (mvstr[2], mvstr[3]);
      piece = (strlen (mvstr) == 5 ? mvstr[4] : ' ');
      return (IsInMoveList (1, f, t, piece));
   }


   /***********************************************************************
    *  Its a SAN notation move.  More headache!  
    *  We generate all the legal moves and start comparing them with
    *  the input move.
    ***********************************************************************/
   if (ATOH (mvstr[0]))	/* pawn move */
   {
      if (ITO8 (mvstr[1]))					/* e4 type */
      {
	 t = ASCIITOSQ (mvstr[0], mvstr[1]);
         f = t + (side == white ? -8 : 8);
         /* Add Sanity Check */
         if ( f > 0 && f < 64 ) {
	   if (BitPosArray[f] & board.b[side][pawn])
           {
              if (mvstr[2] != '\0') 
                 return (IsInMoveList (1, f, t, mvstr[2]));
              else
                 return (IsInMoveList (1, f, t, ' '));
           }
           f = t + (side == white ? -16 : 16);
           if ( f > 0 && f < 64 ) {
	     if (BitPosArray[f] & board.b[side][pawn])
                return (IsInMoveList (1, f, t, ' '));
	   } /* End bound check +/- 16 */
	 } /* End bound check +/- 8 */
        }
      else if (ATOH (mvstr[1]) && ITO8 (mvstr[2]))		/* ed4 type */
      {
	 t = ASCIITOSQ (mvstr[1], mvstr[2]);
	 rank = ASCIITORANK (mvstr[2]) + (side == white ? -1 : 1);
         f = rank * 8 + ASCIITOFILE (mvstr[0]);
         piece = (strlen (mvstr) == 4 ? mvstr[3] : ' ');
         return (IsInMoveList (1, f, t, piece));
      }
      else if (ATOH (mvstr[1]))					/* ed type */
      {
         file = ASCIITOFILE (mvstr[0]);
         fileto = ASCIITOFILE (mvstr[1]);
	 b = board.b[side][pawn] & FileBit[file];
	 if (side == white)
	    b = b >> (fileto < file ? 7 : 9);
         else
	    b = b << (fileto < file ? 9 : 7);
         if (board.ep > -1)
	    b = b & (board.friends[1^side] | BitPosArray[board.ep]);
         else
	    b = b & (board.friends[1^side]);
         switch (nbits (b))
	 {
	    case 0  : return ((leaf *) NULL);
	    case 1  : t = leadz (b);
	    	      f = t - (side == white ? 8 : -8) + (file - fileto);
         	      piece = (strlen (mvstr) == 3 ? mvstr[2] : ' ');
	    	      return (IsInMoveList (1, f, t, piece));
	    default : 
		      printf ("Ambiguous move: %s %s\n",s,mvstr);
		      ShowBoard();
/*
		      getchar();
*/
	    	      return ((leaf *) NULL);
	 }
      } 

   } 
   else	if ((piece = piece_id(mvstr[0])) != empty &&
            (piece_id(mvstr[1]) == empty))	/* Is a piece move */
   {
      /* Since piece_id accepts P as pawns, this will correctly
       * handle malformed commands like Pe4 */

      b = board.b[side][piece];
      t = -1;
      if (ITO8 (mvstr[1]))				/* N1d2 type move */
      {
         rank = ASCIITORANK (mvstr[1]);
	 b &= RankBit[rank];
	 t = ASCIITOSQ (mvstr[2], mvstr[3]);
      }
      else if (ATOH (mvstr[1]) && ATOH (mvstr[2]))	/* Nbd2 type move */
      {
         file = ASCIITOFILE (mvstr[1]);
	 b &= FileBit[file];
	 t = ASCIITOSQ (mvstr[2], mvstr[3]);
      }
      else if (ATOH (mvstr[1]) && ITO8 (mvstr[2]))	/* Nd2 type move */
      {
	 t = ASCIITOSQ (mvstr[1], mvstr[2]);
      }

      kount = 0;
      n1 = n2 = (leaf *) NULL;
      while (b)
      {
         f = leadz (b);
 	 CLEARBIT (b, f);
	 if ((n1 = IsInMoveList (1, f, t, ' ')) != (leaf *) NULL )
	 {
	    n2 = n1;
	    kount++;
	 }
      }
      if (kount > 1)
      {
	 printf ("Ambiguous move: %s %s\n",s,mvstr);
	 ShowBoard();
/*
	 getchar();
*/
   	 return ((leaf *) NULL);
      } 
      else if (kount == 0)
   	 return ((leaf *) NULL);
      else
         return (n2);
   }
   else	if (((piece = piece_id(mvstr[0])) != empty) &&
            ((piece2 = piece_id(mvstr[1])) != empty) &&
	    ( (mvstr[2] == '\0') ||
	      ((piece_id(mvstr[2]) != empty) && mvstr[3] == '\0')))
   { /* KxP format */
      promote = ' ';
      if (piece_id(mvstr[2] != empty)) {
          promote = mvstr[2];
      }
      kount = 0;
      n1 = n2 = (leaf *) NULL;
      b = board.b[side][piece];
      while (b)
      {
         f = leadz (b);
 	 CLEARBIT (b, f);
         b2 = board.b[1^side][piece2];
	 while (b2)
	 {
           t = leadz (b2);
 	   CLEARBIT (b2, t);
	   printf("Trying %s: ", AlgbrMove(MOVE(f,t)));
	   if ((n1 = IsInMoveList (1, f, t, promote)) != (leaf *) NULL)
	   {
	     n2 = n1;
	     kount++;
	     printf("Y  ");
	   }
	   else printf("N  ");
	 }
      }
      if (kount > 1)
      {
	 printf ("Ambiguous move: %s %s\n",s,mvstr);
	 ShowBoard();
/*
	 getchar();
*/
   	 return ((leaf *) NULL);
      } 
      else if (kount == 0)
   	 return ((leaf *) NULL);
      else
         return (n2);
      
   }

   /* Fall through.  Nothing worked, return that no move was performed. */
   return ((leaf *) NULL);
}


leaf * IsInMoveList (int ply, int f, int t, char piece)
/**************************************************************************
 *
 *  Checks to see if from and to square can be found in the movelist
 *  and is legal.
 *
 **************************************************************************/
{
   leaf *node;

   for (node = TreePtr[ply]; node < TreePtr[ply + 1]; node++)
   {
      if ((int) (node->move & 0x0FFF) == MOVE(f,t)  && 
	toupper(piece) == notation[PROMOTEPIECE (node->move)])
         return (node);
   }
   return ((leaf *) NULL);
}


int IsLegalMove (int move)
/*****************************************************************************
 *
 *  Check that a move is legal on the current board.  
 *  Perform some preliminary sanity checks.
 *  1.  If from square is emtpy, illegal.
 *  2.  Piece not of right color.
 *  3.  To square is friendly, illegal.
 *  4.  Promotion move or enpassant, so piece must be pawn.
 *  5.  Castling move, piece must be king.
 *  Note that IsLegalMove() no longer care about if a move will place the
 *  king in check.  This will be caught by the Search().
 *
 *****************************************************************************/
{
   int side;
   int f, t, piece;
   BitBoard blocker, enemy;

   f = FROMSQ(move); 
   t = TOSQ(move);

   /*  Empty from square  */
   if (cboard[f] == empty)
      return (false);

   /*  Piece is not right color  */
   side = board.side;
   if (!(BitPosArray[f] & board.friends[side]))
      return (false);

   /*  TO square is a friendly piece, so illegal move  */
   if (BitPosArray[t] & board.friends[side])
      return (false);

   piece = cboard[f];
   /*  If promotion move, piece must be pawn */
   if ((move & (PROMOTION | ENPASSANT)) && piece != pawn)
      return (false);

   /*  If enpassant, then the enpassant square must be correct */
   if ((move & ENPASSANT) && t != board.ep)
      return (false);

   /*  If castling, then make sure its the king */
   if ((move & CASTLING) && piece != king)
      return (false); 

   blocker = board.blocker;
   /*  Pawn moves need to be handle specially  */
   if (piece == pawn)
   {
      if ((move & ENPASSANT) && board.ep > -1)
         enemy = board.friends[1^side] | BitPosArray[board.ep];
      else
         enemy = board.friends[1^side];
      if (side == white)
      {
         if (!(MoveArray[pawn][f] & BitPosArray[t] & enemy) &&
             !(t - f == 8 && cboard[t] == empty) &&
             !(t - f == 16 && RANK(f) == 1 && !(FromToRay[f][t] & blocker)))
	    return (false);
      }
      else if (side == black)
      {
         if (!(MoveArray[bpawn][f] & BitPosArray[t] & enemy) &&
             !(t - f == -8 && cboard[t] == empty) &&
             !(t - f == -16 && RANK(f) == 6 && !(FromToRay[f][t] & blocker)))
	    return (false);
      }
   }
   /*  King moves are also special, especially castling  */
   else if (piece == king)
   {
      if (side == white)
      {
         if (!(MoveArray[piece][f] & BitPosArray[t]) &&
	     !(f == E1 && t == G1 && board.flag & WKINGCASTLE &&
	       !(FromToRay[E1][G1] & blocker) && !SqAtakd(E1,black) &&
		!SqAtakd(F1,black)) &&
	     !(f == E1 && t == C1 && board.flag & WQUEENCASTLE &&
	       !(FromToRay[E1][B1] & blocker) && !SqAtakd(E1,black) &&
		!SqAtakd(D1,black)))
            return (false);
      }
      if (side == black)
      {
         if (!(MoveArray[piece][f] & BitPosArray[t]) &&
	     !(f == E8 && t == G8 && board.flag & BKINGCASTLE &&
	       !(FromToRay[E8][G8] & blocker) && !SqAtakd(E8,white) &&
		!SqAtakd(F8,white)) &&
	     !(f == E8 && t == C8 && board.flag & BQUEENCASTLE &&
	       !(FromToRay[E8][B8] & blocker) && !SqAtakd(E8,white) &&
		!SqAtakd(D8,white)))
            return (false);
      }
   }
   else 
   {
      if (!(MoveArray[piece][f] & BitPosArray[t]))
         return (false);
   }

   /*  If there is a blocker on the path from f to t, illegal move  */
   if (slider[piece])
   {
      if (FromToRay[f][t] & NotBitPosArray[t] & blocker)
         return (false);
   }

   return (true);
}

char *AlgbrMove (int move)
/*****************************************************************************
 *
 *  Convert an int move format to algebraic format of g1f3.
 *
 *****************************************************************************/
{
   int f, t;
   static char s[6];

   f = FROMSQ(move);
   t = TOSQ(move);
   strcpy (s, algbr[f]);
   strcpy (s+2, algbr[t]);
   if (move & PROMOTION)
   {
      if (flags & XBOARD)
        s[4] = lnotation[PROMOTEPIECE (move)];
      else
        s[4] = notation[PROMOTEPIECE (move)];
      s[5] = '\0';
   }
   else
      s[4] = '\0';
   return (s);
}

⌨️ 快捷键说明

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