X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=moves.c;h=3ea2ab0d9ad9627fea055eeece2f2a101009f5a3;hb=c6f53dd7c428bfe0e96418cb6892068afd1fc3dd;hp=2a8e187f8fb8cd5eb8659d784ac4d5c8bebd0653;hpb=681dfc03596526017b3b8f39caef7f8f7c032987;p=xboard.git diff --git a/moves.c b/moves.c index 2a8e187..3ea2ab0 100644 --- a/moves.c +++ b/moves.c @@ -70,7 +70,7 @@ int SameColor P((ChessSquare, ChessSquare)); int PosFlags(int index); extern signed char initialRights[BOARD_FILES]; /* [HGM] all rights enabled, set in InitPosition */ - +int quickFlag; int WhitePiece(piece) ChessSquare piece; @@ -84,6 +84,7 @@ int BlackPiece(piece) return (int) piece >= (int) BlackPawn && (int) piece < (int) EmptySquare; } +#if 0 int SameColor(piece1, piece2) ChessSquare piece1, piece2; { @@ -96,6 +97,9 @@ int SameColor(piece1, piece2) (int) piece2 >= (int) BlackPawn && (int) piece2 < (int) EmptySquare); } +#else +#define SameColor(piece1, piece2) (piece1 < EmptySquare && piece2 < EmptySquare && (piece1 < BlackPawn) == (piece2 < BlackPawn)) +#endif char pieceToChar[] = { 'P', 'N', 'B', 'R', 'Q', 'F', 'E', 'A', 'C', 'W', 'M', @@ -184,13 +188,11 @@ void GenPseudoLegal(board, flags, callback, closure, filter) for (rf = 0; rf < BOARD_HEIGHT; rf++) for (ff = BOARD_LEFT; ff < BOARD_RGHT; ff++) { ChessSquare piece; - int rookRange = 1000; + int rookRange; - if (flags & F_WHITE_ON_MOVE) { - if (!WhitePiece(board[rf][ff])) continue; - } else { - if (!BlackPiece(board[rf][ff])) continue; - } + if(board[rf][ff] == EmptySquare) continue; + if ((flags & F_WHITE_ON_MOVE) != (board[rf][ff] < BlackPawn)) continue; // [HGM] speed: wrong color + rookRange = 1000; m = 0; piece = board[rf][ff]; if(PieceToChar(piece) == '~') piece = (ChessSquare) ( DEMOTED piece ); @@ -715,6 +717,7 @@ typedef struct { } GenLegalClosure; int rFilter, fFilter; // [HGM] speed: sorry, but I get a bit tired of this closure madness +Board xqCheckers, nullBoard; extern void GenLegalCallback P((Board board, int flags, ChessMove kind, int rf, int ff, int rt, int ft, @@ -733,7 +736,15 @@ void GenLegalCallback(board, flags, kind, rf, ff, rt, ft, closure) if (!(flags & F_IGNORE_CHECK) ) { int check, promo = (gameInfo.variant == VariantSpartan && kind == BlackPromotion); - if(promo) board[rf][ff] = BlackKing; // [HGM] spartan: promote to King before check-test + if(promo) { + int r, f, kings=0; + for(r=0; r= 2) + promo = 0; + else + board[rf][ff] = BlackKing; // [HGM] spartan: promote to King before check-test + } check = CheckTest(board, flags, rf, ff, rt, ft, kind == WhiteCapturesEnPassant || kind == BlackCapturesEnPassant); @@ -783,14 +794,15 @@ int GenLegal(board, flags, callback, closure, filter) int ff, ft, k, left, right, swap; int ignoreCheck = (flags & F_IGNORE_CHECK) != 0; ChessSquare wKing = WhiteKing, bKing = BlackKing, *castlingRights = board[CASTLING]; + int inCheck = !ignoreCheck && CheckTest(board, flags, -1, -1, -1, -1, FALSE); // kludge alert: this would mark pre-existing checkers if status==1 cl.cb = callback; cl.cl = closure; + xqCheckers[EP_STATUS] *= 2; // quasi: if previous CheckTest has been marking, we now set flag for suspending same checkers if(filter == EmptySquare) rFilter = fFilter = -1; // [HGM] speed: do not filter on square if we do not filter on piece GenPseudoLegal(board, flags, GenLegalCallback, (VOIDSTAR) &cl, filter); - if (!ignoreCheck && - CheckTest(board, flags, -1, -1, -1, -1, FALSE)) return TRUE; + if (inCheck) return TRUE; /* Generate castling moves */ if(gameInfo.variant == VariantKnightmate) { /* [HGM] Knightmate */ @@ -969,7 +981,11 @@ void CheckTestCallback(board, flags, kind, rf, ff, rt, ft, closure) { register CheckTestClosure *cl = (CheckTestClosure *) closure; - if (rt == cl->rking && ft == cl->fking) cl->check++; + if (rt == cl->rking && ft == cl->fking) { + if(xqCheckers[EP_STATUS] >= 2 && xqCheckers[rf][ff]) return; // checker is piece with suspended checking power + cl->check++; + xqCheckers[rf][ff] = xqCheckers[EP_STATUS] & 1; // remember who is checking (if status == 1) + } } @@ -995,16 +1011,18 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant) if(gameInfo.variant == VariantKnightmate) king = flags & F_WHITE_ON_MOVE ? WhiteUnicorn : BlackUnicorn; - if (rf >= 0) { + if (rt >= 0) { if (enPassant) { captured = board[rf][ft]; board[rf][ft] = EmptySquare; } else { captured = board[rt][ft]; } - board[rt][ft] = board[rf][ff]; - board[rf][ff] = EmptySquare; - } else board[rt][ft] = ff; // [HGM] drop + if(rf == DROP_RANK) board[rt][ft] = ff; else { // [HGM] drop + board[rt][ft] = board[rf][ff]; + board[rf][ff] = EmptySquare; + } + } /* For compatibility with ICS wild 9, we scan the board in the order a1, a2, a3, ... b1, b2, ..., h8 to find the first king, @@ -1031,15 +1049,16 @@ int CheckTest(board, flags, rf, ff, rt, ft, enPassant) undo_move: - if (rf >= 0) { - board[rf][ff] = board[rt][ft]; + if (rt >= 0) { + if(rf != DROP_RANK) // [HGM] drop + board[rf][ff] = board[rt][ft]; if (enPassant) { board[rf][ft] = captured; board[rt][ft] = EmptySquare; } else { board[rt][ft] = captured; } - } else board[rt][ft] = EmptySquare; // [HGM] drop + } return cl.fking < BOARD_RGHT ? cl.check : 1000; // [HGM] atomic: return 1000 if we have no king } @@ -1109,6 +1128,7 @@ ChessMove LegalityTest(board, flags, rf, ff, rt, ft, promoChar) { LegalityTestClosure cl; ChessSquare piece, filterPiece, *castlingRights = board[CASTLING]; + 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); piece = filterPiece = board[rf][ff]; if(PieceToChar(piece) == '~') filterPiece = DEMOTED piece; @@ -1335,6 +1355,7 @@ void Disambiguate(board, flags, closure) { int illegal = 0; char c = closure->promoCharIn; + if(quickFlag) flags = flags & ~1 | quickFlag & 1; // [HGM] speed: in quick mode quickFlag specifies side-to-move. closure->count = closure->captures = 0; closure->rf = closure->ff = closure->rt = closure->ft = 0; closure->kind = ImpossibleMove; @@ -1345,6 +1366,15 @@ void Disambiguate(board, flags, closure) } 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 > 1) { // gamble did not pay off. retry with check test to resolve ambiguity + closure->count = closure->captures = 0; + closure->rf = closure->ff = closure->rt = closure->ft = 0; + closure->kind = ImpossibleMove; + GenLegal(board, flags, DisambiguateCallback, (VOIDSTAR) closure, closure->pieceIn); // [HGM] speed: only pieces of requested type + } + } else GenLegal(board, flags, DisambiguateCallback, (VOIDSTAR) closure, closure->pieceIn); // [HGM] speed: only pieces of requested type if (closure->count == 0) { /* See if it's an illegal move due to check */ @@ -1828,7 +1858,9 @@ int PerpetualChase(int first, int last) cl.ff = moveList[i][0]-AAA+BOARD_LEFT; cl.rt = moveList[i][3]-ONE; cl.ft = moveList[i][2]-AAA+BOARD_LEFT; + CopyBoard(xqCheckers, nullBoard); xqCheckers[EP_STATUS] = 1; // giant kludge to make GenLegal ignore pre-existing checks GenLegal(boards[i], PosFlags(i), ExistingAttacksCallback, &cl, EmptySquare); + xqCheckers[EP_STATUS] = 0; // disable the generation of quasi-legal moves again if(appData.debugMode) { int n; for(n=0; n