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
+ for (j = 0; j < BOARD_FILES; j++) // [HGM] gamestate: copy castling rights and ep status
+ to[VIRGIN][j] = from[VIRGIN][j],
to[CASTLING][j] = from[CASTLING][j];
to[HOLDINGS_SET] = 0; // flag used in ICS play
}
if(appData.debugMode) fprintf(debugFP, "LegalDrop: %d @ %d,%d)\n", piece, ft, rt);
if(board[rt][ft] != EmptySquare) return ImpossibleMove; // must drop to empty square
n = PieceToNumber(piece);
- if(gameInfo.holdingsWidth == 0 || (flags & F_WHITE_ON_MOVE ? board[n][BOARD_WIDTH-1] : board[BOARD_HEIGHT-1-n][0]) != piece)
+ if((gameInfo.holdingsWidth == 0 || (flags & F_WHITE_ON_MOVE ? board[n][BOARD_WIDTH-1] : board[BOARD_HEIGHT-1-n][0]) != piece)
+ && gameInfo.variant != VariantBughouse) // in bughouse we don't check for availability, because ICS doesn't always tell us
return ImpossibleMove; // piece not available
if(gameInfo.variant == VariantShogi) { // in Shogi lots of drops are forbidden!
if((piece == WhitePawn || piece == WhiteQueen) && rt == BOARD_HEIGHT-1 ||
ChessMove
LegalityTest (Board board, int flags, int rf, int ff, int rt, int ft, int promoChar)
{
- LegalityTestClosure cl; ChessSquare piece, filterPiece, *castlingRights = board[CASTLING];
+ LegalityTestClosure cl; ChessSquare piece, filterPiece;
if(quickFlag) flags = flags & ~1 | quickFlag & 1; // [HGM] speed: in quick mode quickFlag specifies side-to-move.
if(rf == DROP_RANK) return LegalDrop(board, flags, ff, rt, ft);
if(gameInfo.variant == VariantSChess && promoChar && promoChar != '=' && board[rf][ff] != WhitePawn && board[rf][ff] != BlackPawn) {
if(board[rf][ff] < BlackPawn) { // white
if(rf != 0) return IllegalMove; // must be on back rank
+ if(!(board[VIRGIN][ff] & VIRGIN_W)) return IllegalMove; // non-virgin
if(board[PieceToNumber(CharToPiece(ToUpper(promoChar)))][BOARD_WIDTH-2] == 0) return ImpossibleMove;// must be in stock
} else {
if(rf != BOARD_HEIGHT-1) return IllegalMove;
+ if(!(board[VIRGIN][ff] & VIRGIN_B)) return IllegalMove; // non-virgin
if(board[BOARD_HEIGHT-1-PieceToNumber(CharToPiece(ToLower(promoChar)))][1] == 0) return ImpossibleMove;
}
} else
closure->count = closure->captures = 0;
closure->rf = closure->ff = closure->rt = closure->ft = 0;
closure->kind = ImpossibleMove;
- if (appData.debugMode) {
- fprintf(debugFP, "Disambiguate in: %d(%d,%d)-(%d,%d) = %d (%c)\n",
- closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,
- closure->promoCharIn, closure->promoCharIn >= ' ' ? closure->promoCharIn : '-');
- }
rFilter = closure->rtIn; // [HGM] speed: only consider moves to given to-square
fFilter = closure->ftIn;
if(quickFlag) { // [HGM] speed: try without check test first, because if that is not ambiguous, we are happy
GenLegal(board, flags|F_IGNORE_CHECK, DisambiguateCallback, (VOIDSTAR) closure, closure->pieceIn);
if (closure->count == 0) {
/* No, it's not even that */
- if (appData.debugMode) { int i, j;
- for(i=BOARD_HEIGHT-1; i>=0; i--) {
- for(j=0; j<BOARD_WIDTH; j++)
- fprintf(debugFP, "%3d", (int) board[i][j]);
- fprintf(debugFP, "\n");
- }
- }
+ if(!appData.testLegality && closure->pieceIn != EmptySquare) {
+ int f, r; // if there is only a single piece of the requested type on the board, use that
+ closure->rt = closure->rtIn, closure->ft = closure->ftIn;
+ for(r=0; r<BOARD_HEIGHT; r++) for(f=BOARD_LEFT; f<BOARD_RGHT; f++)
+ if(board[r][f] == closure->pieceIn) closure->count++, closure->rf = r, closure->ff = f;
+ if(closure->count > 1) illegal = 0; // ambiguous
+ }
+ if(closure->count == 0) {
+ if (appData.debugMode) { int i, j;
+ for(i=BOARD_HEIGHT-1; i>=0; i--) {
+ for(j=0; j<BOARD_WIDTH; j++)
+ fprintf(debugFP, "%3d", (int) board[i][j]);
+ fprintf(debugFP, "\n");
+ }
+ }
return;
+ }
}
}
if(gameInfo.variant == VariantSChess && c && c != '=' && closure->piece != WhitePawn && closure->piece != BlackPawn) {
if(closure->piece < BlackPawn) { // white
if(closure->rf != 0) closure->kind = IllegalMove; // must be on back rank
+ if(!(board[VIRGIN][closure->ff] & VIRGIN_W)) closure->kind = IllegalMove; // non-virgin
if(board[PieceToNumber(CharToPiece(ToUpper(c)))][BOARD_WIDTH-2] == 0) closure->kind = ImpossibleMove;// must be in stock
} else {
if(closure->rf != BOARD_HEIGHT-1) closure->kind = IllegalMove;
+ if(!(board[VIRGIN][closure->ff] & VIRGIN_B)) closure->kind = IllegalMove; // non-virgin
if(board[BOARD_HEIGHT-1-PieceToNumber(CharToPiece(ToLower(c)))][1] == 0) closure->kind = ImpossibleMove;
}
} else
*/
closure->kind = IllegalMove;
}
- if (appData.debugMode) {
- fprintf(debugFP, "Disambiguate out: %d(%d,%d)-(%d,%d) = %d (%c)\n",
- closure->piece,closure->ff,closure->rf,closure->ft,closure->rt,closure->promoChar,
- closure->promoChar >= ' ' ? closure->promoChar:'-');
- }
}