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

📄 move.c

📁 gun C 环境下编写的
💻 C
📖 第 1 页 / 共 2 页
字号:
/* GNU Chess 5.0 - move.c - make and unmake moves code
   Copyright (c) 1999-2002 Free Software Foundation, Inc.

   GNU Chess is based on the two research programs 
   Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.

   GNU Chess is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   GNU Chess is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GNU Chess; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Contact Info: 
     bug-gnu-chess@gnu.org
     cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
*/
/*
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "common.h"

void MakeMove (int side, int *move)
/**************************************************************************
 *
 *  To make a move on the board and update the various game information.
 *
 **************************************************************************/
{
   BitBoard *a;
   int f, t, fpiece, tpiece; 
   int rookf, rookt, epsq, sq;
   int xside;
   GameRec *g;

   xside = 1^side;
   f = FROMSQ(*move);
   t = TOSQ(*move);
   fpiece = cboard[f];
   tpiece = cboard[t];
   a = &board.b[side][fpiece];
   CLEARBIT (*a, f);
   SETBIT (*a, t);
   CLEARBIT (board.blockerr90, r90[f]);
   SETBIT (board.blockerr90, r90[t]);
   CLEARBIT (board.blockerr45, r45[f]);
   SETBIT (board.blockerr45, r45[t]);
   CLEARBIT (board.blockerr315, r315[f]);
   SETBIT (board.blockerr315, r315[t]);
   cboard[f] = empty;
   cboard[t] = fpiece;
   GameCnt++;
   g = &Game[GameCnt];
   g->epsq = board.ep; 
   g->bflag = board.flag;
   g->Game50 = Game50;
   g->hashkey = HashKey;
   g->phashkey = PawnHashKey;
   g->mvboard = Mvboard[t];
   g->comments = NULL;
   Mvboard[t] = Mvboard[f]+1; 
   Mvboard[f] = 0;
   if (board.ep > -1)
      HashKey ^= ephash[board.ep];
   HashKey ^= hashcode[side][fpiece][f];
   HashKey ^= hashcode[side][fpiece][t];
   if (fpiece == king)
      board.king[side] = t;
   if (fpiece == pawn)
   {
      PawnHashKey ^= hashcode[side][pawn][f];
      PawnHashKey ^= hashcode[side][pawn][t];
   }

   if (tpiece != 0)		/* Capture */
   {
      ExchCnt[side]++;
      CLEARBIT (board.b[xside][tpiece], t);
      *move |= (tpiece << 15);
      HashKey ^= hashcode[xside][tpiece][t];
      if (tpiece == pawn)
         PawnHashKey ^= hashcode[xside][pawn][t];
      board.material[xside] -= Value[tpiece];
      if (tpiece != pawn)
         board.pmaterial[xside] -= Value[tpiece];
   }

   if (*move & PROMOTION) 	/* Promotion */ 
   {
      SETBIT (board.b[side][PROMOTEPIECE (*move)], t);
      CLEARBIT (*a, t);
      cboard[t] = PROMOTEPIECE (*move);
      HashKey ^= hashcode[side][pawn][t];
      HashKey ^= hashcode[side][cboard[t]][t];
      PawnHashKey ^= hashcode[side][pawn][t];
      board.material[side] += (Value[cboard[t]] - ValueP);
      board.pmaterial[side] += Value[cboard[t]];
   }

   if (*move & ENPASSANT)	/* En passant */
   {
      ExchCnt[side]++;
      epsq = board.ep + (side == white ? - 8 : 8);
      CLEARBIT (board.b[xside][pawn], epsq);
      CLEARBIT (board.blockerr90, r90[epsq]);
      CLEARBIT (board.blockerr45, r45[epsq]);
      CLEARBIT (board.blockerr315, r315[epsq]);
      cboard[epsq] = empty;
      HashKey ^= hashcode[xside][pawn][epsq];
      PawnHashKey ^= hashcode[xside][pawn][epsq];
      board.material[xside] -= ValueP;
   }
   if (*move & (CAPTURE | CASTLING) || fpiece == pawn)
      Game50 = GameCnt;

   if (*move & CASTLING) 	/* Castling */
   {
      if (t & 0x04)		/* King side */
      {
         rookf = t + 1;
         rookt = t - 1;
      }
      else			/* Queen side */
      {
         rookf = t - 2;
         rookt = t + 1;
      }
      a = &board.b[side][rook];
      CLEARBIT (*a, rookf);
      SETBIT (*a, rookt);
      CLEARBIT (board.blockerr90, r90[rookf]);
      SETBIT (board.blockerr90, r90[rookt]);
      CLEARBIT (board.blockerr45, r45[rookf]);
      SETBIT (board.blockerr45, r45[rookt]);
      CLEARBIT (board.blockerr315, r315[rookf]);
      SETBIT (board.blockerr315, r315[rookt]);
      cboard[rookf] = empty;
      cboard[rookt] = rook;
      Mvboard[rookf] = 0;
      Mvboard[rookt] = 1;
      HashKey ^= hashcode[side][rook][rookf];
      HashKey ^= hashcode[side][rook][rookt];
      board.castled[side] = true;
   }

   /* If king or rook move, clear castle flag. */
   if (side == white)
   {
      if (fpiece == king && board.flag & WCASTLE)
      {
	 if (board.flag & WKINGCASTLE)
            HashKey ^= WKCastlehash;
	 if (board.flag & WQUEENCASTLE)
            HashKey ^= WQCastlehash;
         board.flag &= ~WCASTLE;
      }
      else if (fpiece == rook)
      {
         if (f == H1)
	 {
	    if (board.flag & WKINGCASTLE)
               HashKey ^= WKCastlehash;
	    board.flag &= ~WKINGCASTLE;
	 }
         else if (f == A1) 
	 {
	    if (board.flag & WQUEENCASTLE)
               HashKey ^= WQCastlehash;
	    board.flag &= ~WQUEENCASTLE;
	 }
      }
      if (tpiece == rook)
      {
         if (t == H8) 
	 {
	    if (board.flag & BKINGCASTLE)
	       HashKey ^= BKCastlehash;
	    board.flag &= ~BKINGCASTLE;
         }
         else if (t == A8) 
	 {
	    if (board.flag & BQUEENCASTLE)
	       HashKey ^= BQCastlehash;
	    board.flag &= ~BQUEENCASTLE;
	 }
      }
   }
   else
   {
      if (fpiece == king && board.flag & BCASTLE)
      {
	 if (board.flag & BKINGCASTLE)
	    HashKey ^= BKCastlehash;
	 if (board.flag & BQUEENCASTLE)
	    HashKey ^= BQCastlehash;
         board.flag &= ~BCASTLE;
      }
      else if (fpiece == rook)
      {
         if (f == H8) 
	 {
	    if (board.flag & BKINGCASTLE)
	       HashKey ^= BKCastlehash;
	    board.flag &= ~BKINGCASTLE;
         }
         else if (f == A8) 
	 {
	    if (board.flag & BQUEENCASTLE)
	       HashKey ^= BQCastlehash;
	    board.flag &= ~BQUEENCASTLE;
	 }
      }
      if (tpiece == rook)
      {
         if (t == H1) 
	 {
	    if (board.flag & WKINGCASTLE)
               HashKey ^= WKCastlehash;
	    board.flag &= ~WKINGCASTLE;
	 }
         else if (t == A1) 
	 {
	    if (board.flag & WQUEENCASTLE)
               HashKey ^= WQCastlehash;
	    board.flag &= ~WQUEENCASTLE;
	 }
      } 
   }


   /* If pawn move 2 squares, set ep passant square. */
   if (fpiece == pawn && abs(f-t) == 16)
   {
      sq = (f + t) / 2;
      board.ep = sq;
      HashKey ^= ephash[sq];
   }
   else
      board.ep = -1;

   board.side = xside;
   HashKey ^= Sidehash;
   UpdateFriends ();

   /* Update game record */
   g->move = *move;
   return;
}



void UnmakeMove (int side, int *move)
/****************************************************************************
 *
 *  To unmake a move on the board and update the various game information.
 *  Note that if side is black, then black is about to move, but we will be
 *  undoing a move by white, not black.
 *
 ****************************************************************************/
{
   BitBoard *a;
   int f, t, fpiece, cpiece;   
   int rookf, rookt, epsq;
   int xside;
   GameRec *g;

   side = 1^side;
   xside = 1^side;
   f = FROMSQ(*move);
   t = TOSQ(*move);
   fpiece = cboard[t];
   cpiece = CAPTUREPIECE (*move);
   a = &board.b[side][fpiece];
   CLEARBIT (*a, t);
   SETBIT (*a, f);   
   CLEARBIT (board.blockerr90, r90[t]); 
   SETBIT (board.blockerr90, r90[f]); 
   CLEARBIT (board.blockerr45, r45[t]); 
   SETBIT (board.blockerr45, r45[f]); 
   CLEARBIT (board.blockerr315, r315[t]); 
   SETBIT (board.blockerr315, r315[f]); 
   cboard[f] = cboard[t];
   cboard[t] = empty;
   g = &Game[GameCnt];
   Mvboard[f] = Mvboard[t]-1;
   Mvboard[t] = g->mvboard;
   if (fpiece == king)
      board.king[side] = f;
   
   /* if capture, put back the captured piece */
   if (*move & CAPTURE)
   {
      ExchCnt[side]--;
      SETBIT (board.b[xside][cpiece], t);  
      SETBIT (board.blockerr90, r90[t]);  
      SETBIT (board.blockerr45, r45[t]);  
      SETBIT (board.blockerr315, r315[t]);  
      cboard[t] = cpiece; 
      board.material[xside] += Value[cpiece];  
      if (cpiece != pawn)
         board.pmaterial[xside] += Value[cpiece];  
   }

   /* Undo promotion */
   if (*move & PROMOTION)
   {
      CLEARBIT (*a, f);
      SETBIT (board.b[side][pawn], f);  
      cboard[f] = pawn;
      board.material[side] += (ValueP - Value[PROMOTEPIECE (*move)]); 
      board.pmaterial[side] -= Value[PROMOTEPIECE (*move)];
   }

   /* Undo enpassant */
   if (*move & ENPASSANT)
   {
      ExchCnt[side]--;
      epsq = (side == white ? g->epsq - 8 : g->epsq + 8);
      SETBIT (board.b[xside][pawn], epsq); 
      SETBIT (board.blockerr90, r90[epsq]); 
      SETBIT (board.blockerr45, r45[epsq]); 
      SETBIT (board.blockerr315, r315[epsq]); 
      cboard[epsq] = pawn;
      board.material[xside] += ValueP;  
   }   

   /* if castling, undo rook move */
   if (*move & CASTLING)
   {
      if (t & 0x04)		/* King side */
      {
         rookf = t + 1;
         rookt = t - 1;
      }
      else			/* Queen side */
      {
         rookf = t - 2;
         rookt = t + 1;
      }
      a = &board.b[side][rook];
      CLEARBIT (*a, rookt);
      SETBIT (*a, rookf); 
      CLEARBIT (board.blockerr90, r90[rookt]);
      SETBIT (board.blockerr90, r90[rookf]);
      CLEARBIT (board.blockerr45, r45[rookt]);
      SETBIT (board.blockerr45, r45[rookf]);
      CLEARBIT (board.blockerr315, r315[rookt]);
      SETBIT (board.blockerr315, r315[rookf]);
      cboard[rookf] = rook;
      cboard[rookt] = empty;
      Mvboard[rookf] = 0;
      Mvboard[rookt] = 0;
      board.castled[side] = false;
   }

   UpdateFriends ();
   board.side = side;
   board.ep = g->epsq;
   board.flag = g->bflag;  
   HashKey = g->hashkey;
   PawnHashKey = g->phashkey;
   Game50 = g->Game50;
   GameCnt--;
   return;
}


void SANMove (int move, int ply)
/****************************************************************************
 *
 *  Convert the move to a SAN format.  GenMoves (ply) needs to be called
 *  by the calling routine for this to work.
 *
 ****************************************************************************/
{
   int side;
   int piece, ambiguous;
   int f, t;
   BitBoard b;
   leaf *node1;
   char *s;

   side = board.side;
   s = SANmv;
   f = FROMSQ(move);
   t = TOSQ(move);
   /* Check some special moves like castling */
   if (move & CASTLING)
   {
      if (t == 6 || t == 62)
         strcpy (s, "O-O");
      else
	 strcpy (s, "O-O-O");
      return;
   }
 
/****************************************************************************
 *
 *  Here split the code into 2 parts for clarity sake.  First part deals 
 *  with pawn moves only, 2nd part only piece moves.  However before doing 
 *  that, see if the move is ambiguous.
 *
 ****************************************************************************/

   /*  AMBIGUITY CHECK  */
   piece = cboard[f];
   side = board.side;
   b = board.b[side][piece];
   ambiguous = false;
   node1 = TreePtr[ply];
   if (nbits (b) > 1)
   {
      /* 
       *  Scan the movelist to see if another same-type piece is
       *  also moving to that particular to-square.
       */
      for (node1 = TreePtr[ply]; node1 < TreePtr[ply + 1]; node1++)
      {
         if (FROMSQ(node1->move) == f)
            continue;                   /* original piece, skip */
         if (TOSQ(node1->move) != t)
            continue;                   /* diff to-square, skip */
         if (cboard[FROMSQ(node1->move)] != piece)
            continue;                   /* diff piece   */
         ambiguous = true;
	 break;
      }
   }

   if (piece == pawn)
   {
      /* Capture or enpassant */
      if (cboard[t] != 0 || board.ep == t)
      {
         *s++ = algbrfile [ROW (f)];
	 *s++ = 'x';
      }
      strcpy (s, algbr[t]);
      s += 2;

      /* Promotion */
      if (move & PROMOTION)
      {
         *s++ = '=';
         *s++ = notation[PROMOTEPIECE (move)];
      }
   }
   else	/* its not pawn */
   {
      *s++ = notation[piece];
      if (ambiguous)
      {
         if (ROW (f) == ROW (FROMSQ(node1->move)))
            *s++ = algbrrank[RANK (f)];
	 else
	    *s++ = algbrfile[ROW (f)];
      }

⌨️ 快捷键说明

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