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, callback, closure)
+void GenPseudoLegal(board, flags, callback, closure, filter)
Board board;
int flags;
MoveCallback callback;
VOIDSTAR closure;
+ ChessSquare filter; // [HGM] speed: only do moves with this piece type
{
int rf, ff;
int i, j, d, s, fs, rs, rt, ft, m;
m = 0; piece = board[rf][ff];
if(PieceToChar(piece) == '~')
piece = (ChessSquare) ( DEMOTED piece );
+ if(filter != EmptySquare && piece != filter) continue;
if(gameInfo.variant == VariantShogi)
piece = (ChessSquare) ( SHOGI piece );
VOIDSTAR cl;
} GenLegalClosure;
+int rFilter, fFilter; // [HGM] speed: sorry, but I get a bit tired of this closure madness
+
extern void GenLegalCallback P((Board board, int flags, ChessMove kind,
int rf, int ff, int rt, int ft,
VOIDSTAR closure));
{
register GenLegalClosure *cl = (GenLegalClosure *) closure;
+ if(rFilter >= 0 && rFilter != rt || fFilter >= 0 && fFilter != ft) return; // [HGM] speed: ignore moves with wrong to-square
+
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
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, callback, closure)
+int GenLegal(board, flags, callback, closure, filter)
Board board;
int flags;
MoveCallback callback;
VOIDSTAR closure;
+ ChessSquare filter;
{
GenLegalClosure cl;
int ff, ft, k, left, right, swap;
cl.cb = callback;
cl.cl = closure;
- GenPseudoLegal(board, flags, GenLegalCallback, (VOIDSTAR) &cl);
+ 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;
board[i][cl.fking] == (dir>0 ? BlackWazir : WhiteWazir) )
cl.check++;
}
- GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, CheckTestCallback, (VOIDSTAR) &cl);
+ GenPseudoLegal(board, flags ^ F_WHITE_ON_MOVE, CheckTestCallback, (VOIDSTAR) &cl, EmptySquare);
if(gameInfo.variant != VariantSpartan || cl.check == 0) // in Spartan Chess go on to test if other King is checked too
goto undo_move; /* 2-level break */
}
int flags;
int rf, ff, rt, ft, promoChar;
{
- LegalityTestClosure cl; ChessSquare piece, *castlingRights = board[CASTLING];
+ LegalityTestClosure cl; ChessSquare piece, filterPiece, *castlingRights = board[CASTLING];
if(rf == DROP_RANK) return LegalDrop(board, flags, ff, rt, ft);
- piece = board[rf][ff];
+ piece = filterPiece = board[rf][ff];
+ if(PieceToChar(piece) == '~') filterPiece = DEMOTED piece;
if (appData.debugMode) {
int i;
cl.rf = rf;
cl.ff = ff;
- cl.rt = rt;
- cl.ft = ft;
+ cl.rt = rFilter = rt; // [HGM] speed: filter on to-square
+ cl.ft = fFilter = ft;
cl.kind = IllegalMove;
cl.captures = 0; // [HGM] losers: prepare to count legal captures.
- GenLegal(board, flags, LegalityTestCallback, (VOIDSTAR) &cl);
+ if(flags & F_MANDATORY_CAPTURE) filterPiece = EmptySquare; // [HGM] speed: do not filter in suicide, to find all captures
+ GenLegal(board, flags, LegalityTestCallback, (VOIDSTAR) &cl, filterPiece);
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
if(myPieces == 1) return MT_BARE;
}
cl.count = 0;
- inCheck = GenLegal(board, flags, MateTestCallback, (VOIDSTAR) &cl);
+ inCheck = GenLegal(board, flags, MateTestCallback, (VOIDSTAR) &cl, EmptySquare);
// [HGM] 3check: yet to do!
if (cl.count > 0) {
return inCheck ? MT_CHECK : MT_NONE;
closure->pieceIn,closure->ffIn,closure->rfIn,closure->ftIn,closure->rtIn,
closure->promoCharIn, closure->promoCharIn >= ' ' ? closure->promoCharIn : '-');
}
- GenLegal(board, flags, DisambiguateCallback, (VOIDSTAR) closure);
+ rFilter = closure->rtIn; // [HGM] speed: only consider moves to given to-square
+ fFilter = closure->ftIn;
+ 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 */
illegal = 1;
- GenLegal(board, flags|F_IGNORE_CHECK, DisambiguateCallback, (VOIDSTAR) closure);
+ 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;
/* Piece move */
cl.rf = rf;
cl.ff = ff;
- cl.rt = rt;
- cl.ft = ft;
+ cl.rt = rFilter = rt; // [HGM] speed: filter on to-square
+ cl.ft = fFilter = ft;
cl.piece = piece;
cl.kind = IllegalMove;
cl.rank = cl.file = cl.either = 0;
- GenLegal(board, flags, CoordsToAlgebraicCallback, (VOIDSTAR) &cl);
+ c = PieceToChar(piece) ;
+ GenLegal(board, flags, CoordsToAlgebraicCallback, (VOIDSTAR) &cl, c!='~' ? piece : (DEMOTED piece)); // [HGM] speed
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, CoordsToAlgebraicCallback, (VOIDSTAR) &cl);
+ GenLegal(board, flags|F_IGNORE_CHECK, CoordsToAlgebraicCallback, (VOIDSTAR) &cl, c!='~' ? piece : (DEMOTED piece));
if (cl.kind == IllegalMove) break;
cl.kind = IllegalMove;
}
else "N1f3" or "N5xf7",
else "Ng1f3" or "Ng5xf7".
*/
- c = PieceToChar(piece) ;
if( c == '~' || c == '+') {
/* [HGM] print nonexistent piece as its demoted version */
piece = (ChessSquare) (DEMOTED piece);
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), AttacksCallback, &cl);
+ GenLegal(boards[i+1], PosFlags(i), AttacksCallback, &cl, EmptySquare);
if(appData.debugMode) { int n;
for(n=0; n<chaseStackPointer; n++)
fprintf(debugFP, "%c%c%c%c ", chaseStack[n].ff+AAA, chaseStack[n].rf+ONE,
cl.ff = moveList[i][0]-AAA+BOARD_LEFT;
cl.rt = moveList[i][3]-ONE;
cl.ft = moveList[i][2]-AAA+BOARD_LEFT;
- GenLegal(boards[i], PosFlags(i), ExistingAttacksCallback, &cl);
+ GenLegal(boards[i], PosFlags(i), ExistingAttacksCallback, &cl, EmptySquare);
if(appData.debugMode) { int n;
for(n=0; n<chaseStackPointer; n++)
fprintf(debugFP, "%c%c%c%c ", chaseStack[n].ff+AAA, chaseStack[n].rf+ONE,
if(appData.debugMode) {
fprintf(debugFP, "test if we can recapture %c%c\n", cl.ft+AAA, cl.rt+ONE);
}
- GenLegal(boards[i+1], PosFlags(i+1), ProtectedCallback, &cl); // try all moves
+ GenLegal(boards[i+1], PosFlags(i+1), ProtectedCallback, &cl, EmptySquare); // try all moves
// unmake the capture
boards[i+1][chaseStack[j].rf][chaseStack[j].ff] = boards[i+1][chaseStack[j].rt][chaseStack[j].ft];
boards[i+1][chaseStack[j].rt][chaseStack[j].ft] = captured;