📄 move.c
字号:
/* 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 + -