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