📄 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 + -