X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=moves.c;h=12f9b63ddba1e383c96018323498365255557c75;hb=9a9bae3af89e8e0c983d963d1bfbff111adc117f;hp=59700b7cc3a11c050d8df47dd0fc7892c6d9e639;hpb=18c97517acda747ffe9d9177c61c9bf5b1195bb6;p=xboard.git diff --git a/moves.c b/moves.c index 59700b7..12f9b63 100644 --- a/moves.c +++ b/moves.c @@ -69,7 +69,7 @@ int BlackPiece P((ChessSquare)); int SameColor P((ChessSquare, ChessSquare)); int PosFlags(int index); -extern signed char initialRights[BOARD_SIZE]; /* [HGM] all rights enabled, set in InitPosition */ +extern signed char initialRights[BOARD_FILES]; /* [HGM] all rights enabled, set in InitPosition */ int WhitePiece(piece) @@ -227,6 +227,9 @@ void CopyBoard(to, from) for (i = 0; i < BOARD_HEIGHT; i++) for (j = 0; j < BOARD_WIDTH; j++) to[i][j] = from[i][j]; + for (j = 0; j < BOARD_FILES-1; j++) // [HGM] gamestate: copy castling rights and ep status + to[CASTLING][j] = from[CASTLING][j]; + to[HOLDINGS_SET] = 0; // flag used in ICS play } int CompareBoards(board1, board2) @@ -251,15 +254,15 @@ int CompareBoards(board1, board2) EP_UNKNOWN if we don't know and want to allow all e.p. captures. Promotion moves generated are to Queen only. */ -void GenPseudoLegal(board, flags, epfile, callback, closure) +void GenPseudoLegal(board, flags, callback, closure) Board board; int flags; - int epfile; MoveCallback callback; VOIDSTAR closure; { int rf, ff; int i, j, d, s, fs, rs, rt, ft, m; + int epfile = (signed char)board[EP_STATUS]; // [HGM] gamestate: extract ep status from board for (rf = 0; rf < BOARD_HEIGHT; rf++) for (ff = BOARD_LEFT; ff < BOARD_RGHT; ff++) { @@ -680,6 +683,14 @@ void GenPseudoLegal(board, flags, epfile, callback, closure) } } break; + case WhiteFalcon: // [HGM] wild: for wildcards, self-capture symbolizes move to anywhere + case BlackFalcon: + case WhiteCobra: + case BlackCobra: + case WhiteLance: + case BlackLance: + callback(board, flags, NormalMove, rf, ff, rf, ff, closure); + break; } } @@ -740,22 +751,20 @@ typedef struct { true if castling is not yet ruled out by a move of the king or rook. Return TRUE if the player on move is currently in check and F_IGNORE_CHECK is not set. [HGM] add castlingRights parameter */ -int GenLegal(board, flags, epfile, castlingRights, callback, closure) +int GenLegal(board, flags, callback, closure) Board board; int flags; - int epfile; - char castlingRights[]; MoveCallback callback; VOIDSTAR closure; { GenLegalClosure cl; int ff, ft, k, left, right; int ignoreCheck = (flags & F_IGNORE_CHECK) != 0; - ChessSquare wKing = WhiteKing, bKing = BlackKing; + ChessSquare wKing = WhiteKing, bKing = BlackKing, *castlingRights = board[CASTLING]; cl.cb = callback; cl.cl = closure; - GenPseudoLegal(board, flags, epfile, GenLegalCallback, (VOIDSTAR) &cl); + GenPseudoLegal(board, flags, GenLegalCallback, (VOIDSTAR) &cl); if (!ignoreCheck && CheckTest(board, flags, -1, -1, -1, -1, FALSE)) return TRUE; @@ -774,7 +783,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) board[0][BOARD_RGHT-3] == EmptySquare && board[0][BOARD_RGHT-2] == EmptySquare && board[0][BOARD_RGHT-1] == WhiteRook && - castlingRights[0] >= 0 && /* [HGM] check rights */ + castlingRights[0] != NoRights && /* [HGM] check rights */ ( castlingRights[2] == ff || castlingRights[6] == ff ) && (ignoreCheck || (!CheckTest(board, flags, 0, ff, 0, ff + 1, FALSE) && @@ -794,7 +803,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) board[0][BOARD_LEFT+2] == EmptySquare && board[0][BOARD_LEFT+1] == EmptySquare && board[0][BOARD_LEFT+0] == WhiteRook && - castlingRights[1] >= 0 && /* [HGM] check rights */ + castlingRights[1] != NoRights && /* [HGM] check rights */ ( castlingRights[2] == ff || castlingRights[6] == ff ) && (ignoreCheck || (!CheckTest(board, flags, 0, ff, 0, ff - 1, FALSE) && @@ -813,7 +822,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) board[BOARD_HEIGHT-1][BOARD_RGHT-3] == EmptySquare && board[BOARD_HEIGHT-1][BOARD_RGHT-2] == EmptySquare && board[BOARD_HEIGHT-1][BOARD_RGHT-1] == BlackRook && - castlingRights[3] >= 0 && /* [HGM] check rights */ + castlingRights[3] != NoRights && /* [HGM] check rights */ ( castlingRights[5] == ff || castlingRights[7] == ff ) && (ignoreCheck || (!CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff + 1, FALSE) && @@ -833,7 +842,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) board[BOARD_HEIGHT-1][BOARD_LEFT+2] == EmptySquare && board[BOARD_HEIGHT-1][BOARD_LEFT+1] == EmptySquare && board[BOARD_HEIGHT-1][BOARD_LEFT+0] == BlackRook && - castlingRights[4] >= 0 && /* [HGM] check rights */ + castlingRights[4] != NoRights && /* [HGM] check rights */ ( castlingRights[5] == ff || castlingRights[7] == ff ) && (ignoreCheck || (!CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ff - 1, FALSE) && @@ -854,7 +863,7 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) if ((flags & F_WHITE_ON_MOVE) != 0) { ff = castlingRights[2]; /* King file if we have any rights */ - if(ff > 0 && board[0][ff] == WhiteKing) { + if(ff != NoRights && board[0][ff] == WhiteKing) { if (appData.debugMode) { fprintf(debugFP, "FRC castling, %d %d %d %d %d %d\n", castlingRights[0],castlingRights[1],ff,castlingRights[3],castlingRights[4],castlingRights[5]); @@ -863,49 +872,49 @@ int GenLegal(board, flags, epfile, castlingRights, callback, closure) left = ff+1; right = BOARD_RGHT-2; if(ff == BOARD_RGHT-2) left = right = ff-1; /* special case */ - for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */ - if(k != ft && board[0][k] != EmptySquare) ft = -1; - for(k=left; k= 0; k++) /* then if not checked */ - if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = -1; - if(ft >= 0 && board[0][ft] == WhiteRook) + for(k=left; k<=right && ft != NoRights; k++) /* first test if blocked */ + if(k != ft && board[0][k] != EmptySquare) ft = NoRights; + for(k=left; k= 0; k++) /* first test if blocked */ - if(k != ft && board[0][k] != EmptySquare) ft = -1; + for(k=left; k<=right && ft != NoRights; k++) /* first test if blocked */ + if(k != ft && board[0][k] != EmptySquare) ft = NoRights; if(ff > BOARD_LEFT+2) - for(k=left+1; k<=right && ft >= 0; k++) /* then if not checked */ - if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = -1; - if(ft >= 0 && board[0][ft] == WhiteRook) + for(k=left+1; k<=right && ft != NoRights; k++) /* then if not checked */ + if(!ignoreCheck && CheckTest(board, flags, 0, ff, 0, k, FALSE)) ft = NoRights; + if(ft != NoRights && board[0][ft] == WhiteRook) callback(board, flags, WhiteASideCastleFR, 0, ff, 0, ft, closure); } } else { ff = castlingRights[5]; /* King file if we have any rights */ - if(ff > 0 && board[BOARD_HEIGHT-1][ff] == BlackKing) { + if(ff != NoRights && board[BOARD_HEIGHT-1][ff] == BlackKing) { ft = castlingRights[3]; /* Rook file if we have H-side rights */ left = ff+1; right = BOARD_RGHT-2; if(ff == BOARD_RGHT-2) left = right = ff-1; /* special case */ - for(k=left; k<=right && ft >= 0; k++) /* first test if blocked */ - if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = -1; - for(k=left; k= 0; k++) /* then if not checked */ - if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = -1; - if(ft >= 0 && board[BOARD_HEIGHT-1][ft] == BlackRook) + for(k=left; k<=right && ft != NoRights; k++) /* first test if blocked */ + if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = NoRights; + for(k=left; k= 0; k++) /* first test if blocked */ - if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = -1; + for(k=left; k<=right && ft != NoRights; k++) /* first test if blocked */ + if(k != ft && board[BOARD_HEIGHT-1][k] != EmptySquare) ft = NoRights; if(ff > BOARD_LEFT+2) - for(k=left+1; k<=right && ft >= 0; k++) /* then if not checked */ - if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = -1; - if(ft >= 0 && board[BOARD_HEIGHT-1][ft] == BlackRook) + for(k=left+1; k<=right && ft != NoRights; k++) /* then if not checked */ + if(!ignoreCheck && CheckTest(board, flags, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, k, FALSE)) ft = NoRights; + if(ft != NoRights && board[BOARD_HEIGHT-1][ft] == BlackRook) callback(board, flags, BlackASideCastleFR, BOARD_HEIGHT-1, ff, BOARD_HEIGHT-1, ft, closure); } } @@ -991,8 +1000,7 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant) cl.check++; } - GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, -1, - CheckTestCallback, (VOIDSTAR) &cl); + GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, CheckTestCallback, (VOIDSTAR) &cl); goto undo_move; /* 2-level break */ } } @@ -1035,13 +1043,12 @@ void LegalityTestCallback(board, flags, kind, rf, ff, rt, ft, closure) cl->kind = kind; } -ChessMove LegalityTest(board, flags, epfile, castlingRights, rf, ff, rt, ft, promoChar) +ChessMove LegalityTest(board, flags, rf, ff, rt, ft, promoChar) Board board; - int flags, epfile; + int flags; int rf, ff, rt, ft, promoChar; - char castlingRights[]; { - LegalityTestClosure cl; ChessSquare piece = board[rf][ff]; + LegalityTestClosure cl; ChessSquare piece = board[rf][ff], *castlingRights = board[CASTLING]; if (appData.debugMode) { int i; @@ -1053,7 +1060,7 @@ ChessMove LegalityTest(board, flags, epfile, castlingRights, rf, ff, rt, ft, pro if(piece == WhiteFalcon || piece == BlackFalcon || piece == WhiteCobra || piece == BlackCobra || piece == WhiteLance || piece == BlackLance) - return NormalMove; + return CheckTest(board, flags, rf, ff, rt, ft, FALSE) ? IllegalMove : NormalMove; cl.rf = rf; cl.ff = ff; @@ -1061,7 +1068,7 @@ ChessMove LegalityTest(board, flags, epfile, castlingRights, rf, ff, rt, ft, pro cl.ft = ft; cl.kind = IllegalMove; cl.captures = 0; // [HGM] losers: prepare to count legal captures. - GenLegal(board, flags, epfile, castlingRights, LegalityTestCallback, (VOIDSTAR) &cl); + GenLegal(board, flags, LegalityTestCallback, (VOIDSTAR) &cl); if((flags & F_MANDATORY_CAPTURE) && cl.captures && board[rt][ft] == EmptySquare && cl.kind != WhiteCapturesEnPassant && cl.kind != BlackCapturesEnPassant) return(IllegalMove); // [HGM] losers: if there are legal captures, non-capts are illegal @@ -1134,10 +1141,9 @@ void MateTestCallback(board, flags, kind, rf, ff, rt, ft, closure) } /* Return MT_NONE, MT_CHECK, MT_CHECKMATE, or MT_STALEMATE */ -int MateTest(board, flags, epfile, castlingRights) +int MateTest(board, flags) Board board; - int flags, epfile; - char castlingRights[]; + int flags; { MateTestClosure cl; int inCheck, r, f, myPieces=0, hisPieces=0, nrKing=0; @@ -1165,7 +1171,7 @@ int MateTest(board, flags, epfile, castlingRights) if(myPieces == 1) return MT_BARE; } cl.count = 0; - inCheck = GenLegal(board, flags, epfile, castlingRights, MateTestCallback, (VOIDSTAR) &cl); + inCheck = GenLegal(board, flags, MateTestCallback, (VOIDSTAR) &cl); // [HGM] 3check: yet to do! if (cl.count > 0) { return inCheck ? MT_CHECK : MT_NONE; @@ -1195,6 +1201,13 @@ void DisambiguateCallback(board, flags, kind, rf, ff, rt, ft, closure) VOIDSTAR closure; { register DisambiguateClosure *cl = (DisambiguateClosure *) closure; + int wildCard = FALSE; ChessSquare piece = board[rf][ff]; + + // [HGM] wild: for wild-card pieces rt and rf are dummies + if(piece == WhiteFalcon || piece == BlackFalcon || + piece == WhiteCobra || piece == BlackCobra || + piece == WhiteLance || piece == BlackLance) + wildCard = TRUE; if ((cl->pieceIn == EmptySquare || cl->pieceIn == board[rf][ff] || PieceToChar(board[rf][ff]) == '~' @@ -1202,25 +1215,26 @@ void DisambiguateCallback(board, flags, kind, rf, ff, rt, ft, closure) ) && (cl->rfIn == -1 || cl->rfIn == rf) && (cl->ffIn == -1 || cl->ffIn == ff) && - (cl->rtIn == -1 || cl->rtIn == rt) && - (cl->ftIn == -1 || cl->ftIn == ft)) { + (cl->rtIn == -1 || cl->rtIn == rt || wildCard) && + (cl->ftIn == -1 || cl->ftIn == ft || wildCard)) { cl->count++; cl->piece = board[rf][ff]; cl->rf = rf; cl->ff = ff; - cl->rt = rt; - cl->ft = ft; + cl->rt = wildCard ? cl->rtIn : rt; + cl->ft = wildCard ? cl->ftIn : ft; cl->kind = kind; } } -void Disambiguate(board, flags, epfile, closure) +void Disambiguate(board, flags, closure) Board board; - int flags, epfile; + int flags; DisambiguateClosure *closure; { int illegal = 0; char c = closure->promoCharIn; + closure->count = 0; closure->rf = closure->ff = closure->rt = closure->ft = 0; closure->kind = ImpossibleMove; @@ -1229,12 +1243,11 @@ void Disambiguate(board, flags, epfile, closure) closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn, closure->promoCharIn, closure->promoCharIn >= ' ' ? closure->promoCharIn : '-'); } - GenLegal(board, flags, epfile, initialRights, DisambiguateCallback, (VOIDSTAR) closure); + GenLegal(board, flags, DisambiguateCallback, (VOIDSTAR) closure); if (closure->count == 0) { /* See if it's an illegal move due to check */ illegal = 1; - GenLegal(board, flags|F_IGNORE_CHECK, epfile, initialRights, DisambiguateCallback, - (VOIDSTAR) closure); + GenLegal(board, flags|F_IGNORE_CHECK, DisambiguateCallback, (VOIDSTAR) closure); if (closure->count == 0) { /* No, it's not even that */ if (appData.debugMode) { int i, j; @@ -1364,10 +1377,9 @@ void CoordsToAlgebraicCallback(board, flags, kind, rf, ff, rt, ft, closure) /* Convert coordinates to normal algebraic notation. promoChar must be NULLCHAR or 'x' if not a promotion. */ -ChessMove CoordsToAlgebraic(board, flags, epfile, - rf, ff, rt, ft, promoChar, out) +ChessMove CoordsToAlgebraic(board, flags, rf, ff, rt, ft, promoChar, out) Board board; - int flags, epfile; + int flags; int rf, ff, rt, ft; int promoChar; char out[MOVE_LEN]; @@ -1398,12 +1410,11 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, switch (piece) { case WhitePawn: case BlackPawn: - kind = LegalityTest(board, flags, epfile, initialRights, rf, ff, rt, ft, promoChar); + kind = LegalityTest(board, flags, rf, ff, rt, ft, promoChar); if (kind == IllegalMove && !(flags&F_IGNORE_CHECK)) { /* Keep short notation if move is illegal only because it leaves the player in check, but still return IllegalMove */ - kind = LegalityTest(board, flags|F_IGNORE_CHECK, epfile, initialRights, - rf, ff, rt, ft, promoChar); + kind = LegalityTest(board, flags|F_IGNORE_CHECK, rf, ff, rt, ft, promoChar); if (kind == IllegalMove) break; kind = IllegalMove; } @@ -1447,8 +1458,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, if((piece == WhiteKing && board[rt][ft] == WhiteRook) || (piece == BlackKing && board[rt][ft] == BlackRook)) { if(ft > ff) strcpy(out, "O-O"); else strcpy(out, "O-O-O"); - return LegalityTest(board, flags, epfile, initialRights, - rf, ff, rt, ft, promoChar); + return LegalityTest(board, flags, rf, ff, rt, ft, promoChar); } /* End of code added by Tord */ /* Test for castling or ICS wild castling */ @@ -1470,8 +1480,7 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, this situation. So I am not going to worry about it; I'll just generate an ambiguous O-O in this case. */ - return LegalityTest(board, flags, epfile, initialRights, - rf, ff, rt, ft, promoChar); + return LegalityTest(board, flags, rf, ff, rt, ft, promoChar); } /* else fall through */ @@ -1484,15 +1493,13 @@ ChessMove CoordsToAlgebraic(board, flags, epfile, cl.piece = piece; cl.kind = IllegalMove; cl.rank = cl.file = cl.either = 0; - GenLegal(board, flags, epfile, initialRights, - CoordsToAlgebraicCallback, (VOIDSTAR) &cl); + GenLegal(board, flags, CoordsToAlgebraicCallback, (VOIDSTAR) &cl); if (cl.kind == IllegalMove && !(flags&F_IGNORE_CHECK)) { /* Generate pretty moves for moving into check, but still return IllegalMove. */ - GenLegal(board, flags|F_IGNORE_CHECK, epfile, initialRights, - CoordsToAlgebraicCallback, (VOIDSTAR) &cl); + GenLegal(board, flags|F_IGNORE_CHECK, CoordsToAlgebraicCallback, (VOIDSTAR) &cl); if (cl.kind == IllegalMove) break; cl.kind = IllegalMove; } @@ -1719,7 +1726,7 @@ int PerpetualChase(int first, int last) if(appData.debugMode) fprintf(debugFP, "judge position %i\n", i); chaseStackPointer = 0; // clear stack that is going to hold possible chases // determine all captures possible after the move, and put them on chaseStack - GenLegal(boards[i+1], PosFlags(i), EP_NONE, initialRights, AttacksCallback, &cl); + GenLegal(boards[i+1], PosFlags(i), AttacksCallback, &cl); if(appData.debugMode) { int n; for(n=0; n