/** Remove pseudo-legal EP square if it is not legal, ie would leave king in check. */ public static void fixupEPSquare(Position pos) { int epSquare = pos.getEpSquare(); if (epSquare >= 0) { MoveGen MG = new MoveGen(); MoveGen.MoveList moves = MG.pseudoLegalMoves(pos); MoveGen.RemoveIllegal(pos, moves); bool epValid = false; for (int mi = 0; mi < moves.size; mi++) { Move m = moves.m[mi]; if (m.to == epSquare) { if (pos.getPiece(m.from) == (pos.whiteMove ? Piece.WPAWN : Piece.BPAWN)) { epValid = true; break; } } } if (!epValid) { pos.setEpSquare(-1); } } }
private static bool isCapture(Position pos, Move move) { if (pos.getPiece(move.to) == Piece.EMPTY) { int p = pos.getPiece(move.from); if ((p == (pos.whiteMove ? Piece.WPAWN : Piece.BPAWN)) && (move.to == pos.getEpSquare())) { return true; } else { return false; } } else { return true; } }
/** Return a FEN string corresponding to a chess Position object. */ public static string toFEN(Position pos) { string ret = ""; // Piece placement for (int r = 7; r >=0; r--) { int numEmpty = 0; for (int c = 0; c < 8; c++) { int p = pos.getPiece(Position.getSquare(c, r)); if (p == Piece.EMPTY) { numEmpty++; } else { if (numEmpty > 0) { ret+=numEmpty.ToString(); numEmpty = 0; } switch (p) { case Piece.WKING: ret+=('K'); break; case Piece.WQUEEN: ret+=('Q'); break; case Piece.WROOK: ret+=('R'); break; case Piece.WBISHOP: ret+=('B'); break; case Piece.WKNIGHT: ret+=('N'); break; case Piece.WPAWN: ret+=('P'); break; case Piece.BKING: ret+=('k'); break; case Piece.BQUEEN: ret+=('q'); break; case Piece.BROOK: ret+=('r'); break; case Piece.BBISHOP: ret+=('b'); break; case Piece.BKNIGHT: ret+=('n'); break; case Piece.BPAWN: ret+=('p'); break; default: throw new RuntimeException(); } } } if (numEmpty > 0) { ret += numEmpty.ToString(); } if (r > 0) { ret += ('/'); } } ret += (pos.whiteMove ? " w " : " b "); // Castling rights bool anyCastle = false; if (pos.h1Castle()) { ret += ('K'); anyCastle = true; } if (pos.a1Castle()) { ret += ('Q'); anyCastle = true; } if (pos.h8Castle()) { ret += ('k'); anyCastle = true; } if (pos.a8Castle()) { ret += ('q'); anyCastle = true; } if (!anyCastle) { ret += ('-'); } // En passant target square { ret += (' '); if (pos.getEpSquare() >= 0) { int x = Position.getX(pos.getEpSquare()); int y = Position.getY(pos.getEpSquare()); ret += ((char)(x + 'a')); ret += ((char)(y + '1')); } else { ret += ('-'); } } // Move counters ret += " " + pos.halfMoveClock; ret += " " + pos.fullMoveCounter; return ret; }
/** * Generate and return a list of pseudo-legal moves. * Pseudo-legal means that the moves doesn't necessarily defend from check threats. */ public MoveList pseudoLegalMoves(Position pos) { MoveList moveList = getMoveListObj(); ulong occupied = pos.whiteBB | pos.blackBB; if (pos.whiteMove) { int sq = 0; ulong m = 0; // Queen moves ulong squares = pos.pieceTypeBB[Piece.WQUEEN]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = (BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied)) & ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Rook moves squares = pos.pieceTypeBB[Piece.WROOK]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.rookAttacks(sq, occupied) & ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Bishop moves squares = pos.pieceTypeBB[Piece.WBISHOP]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.bishopAttacks(sq, occupied) & ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // King moves { sq = pos.getKingSq(true); m = BitBoard.kingAttacks[sq] & ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; int k0 = 4; if (sq == k0) { ulong OO_SQ = 0x60L; ulong OOO_SQ = 0xEL; if (((pos.getCastleMask() & (1 << Position.H1_CASTLE)) != 0) && ((OO_SQ & (pos.whiteBB | pos.blackBB)) == 0) && (pos.getPiece(k0 + 3) == Piece.WROOK) && !sqAttacked(pos, k0) && !sqAttacked(pos, k0 + 1)) { setMove(moveList, k0, k0 + 2, Piece.EMPTY); } if (((pos.getCastleMask() & (1 << Position.A1_CASTLE)) != 0) && ((OOO_SQ & (pos.whiteBB | pos.blackBB)) == 0) && (pos.getPiece(k0 - 4) == Piece.WROOK) && !sqAttacked(pos, k0) && !sqAttacked(pos, k0 - 1)) { setMove(moveList, k0, k0 - 2, Piece.EMPTY); } } } // Knight moves ulong knights = pos.pieceTypeBB[Piece.WKNIGHT]; while (knights != 0) { sq = BitBoard.numberOfTrailingZeros(knights); m = BitBoard.knightAttacks[sq] & ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; knights &= knights-1; } // Pawn moves ulong pawns = pos.pieceTypeBB[Piece.WPAWN]; m = (pawns << 8) & ~occupied; if (addPawnMovesByMask(moveList, pos, m, -8, true)) return moveList; m = ((m & BitBoard.maskRow3) << 8) & ~occupied; addPawnDoubleMovesByMask(moveList, pos, m, -16); int epSquare = pos.getEpSquare(); ulong epMask = (epSquare >= 0) ? (1UL << epSquare) : 0L; m = (pawns << 7) & BitBoard.maskAToGFiles & (pos.blackBB | epMask); if (addPawnMovesByMask(moveList, pos, m, -7, true)) return moveList; m = (pawns << 9) & BitBoard.maskBToHFiles & (pos.blackBB | epMask); if (addPawnMovesByMask(moveList, pos, m, -9, true)) return moveList; } else { int sq = 0; ulong m = 0; // Queen moves ulong squares = pos.pieceTypeBB[Piece.BQUEEN]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = (BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied)) & ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Rook moves squares = pos.pieceTypeBB[Piece.BROOK]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.rookAttacks(sq, occupied) & ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Bishop moves squares = pos.pieceTypeBB[Piece.BBISHOP]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.bishopAttacks(sq, occupied) & ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // King moves { sq = pos.getKingSq(false); m = BitBoard.kingAttacks[sq] & ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; int k0 = 60; if (sq == k0) { ulong OO_SQ = 0x6000000000000000L; ulong OOO_SQ = 0xE00000000000000L; if (((pos.getCastleMask() & (1 << Position.H8_CASTLE)) != 0) && ((OO_SQ & (pos.whiteBB | pos.blackBB)) == 0) && (pos.getPiece(k0 + 3) == Piece.BROOK) && !sqAttacked(pos, k0) && !sqAttacked(pos, k0 + 1)) { setMove(moveList, k0, k0 + 2, Piece.EMPTY); } if (((pos.getCastleMask() & (1 << Position.A8_CASTLE)) != 0) && ((OOO_SQ & (pos.whiteBB | pos.blackBB)) == 0) && (pos.getPiece(k0 - 4) == Piece.BROOK) && !sqAttacked(pos, k0) && !sqAttacked(pos, k0 - 1)) { setMove(moveList, k0, k0 - 2, Piece.EMPTY); } } } // Knight moves ulong knights = pos.pieceTypeBB[Piece.BKNIGHT]; while (knights != 0) { sq = BitBoard.numberOfTrailingZeros(knights); m = BitBoard.knightAttacks[sq] & ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; knights &= knights-1; } // Pawn moves ulong pawns = pos.pieceTypeBB[Piece.BPAWN]; m = (pawns >> 8) & ~occupied; if (addPawnMovesByMask(moveList, pos, m, 8, true)) return moveList; m = ((m & BitBoard.maskRow6) >> 8) & ~occupied; addPawnDoubleMovesByMask(moveList, pos, m, 16); int epSquare = pos.getEpSquare(); ulong epMask = (epSquare >= 0) ? (1UL << epSquare) : 0L; m = (pawns >> 9) & BitBoard.maskAToGFiles & (pos.whiteBB | epMask); if (addPawnMovesByMask(moveList, pos, m, 9, true)) return moveList; m = (pawns >> 7) & BitBoard.maskBToHFiles & (pos.whiteBB | epMask); if (addPawnMovesByMask(moveList, pos, m, 7, true)) return moveList; } return moveList; }
/** Generate captures, checks, and possibly some other moves that are too hard to filter out. */ public MoveList pseudoLegalCapturesAndChecks(Position pos) { MoveList moveList = getMoveListObj(); ulong occupied = pos.whiteBB | pos.blackBB; if (pos.whiteMove) { int sq = 0; ulong m = 0; int bKingSq = pos.getKingSq(false); ulong discovered = 0; // Squares that could generate discovered checks ulong kRookAtk = BitBoard.rookAttacks(bKingSq, occupied); if ((BitBoard.rookAttacks(bKingSq, occupied & ~kRookAtk) & (pos.pieceTypeBB[Piece.WQUEEN] | pos.pieceTypeBB[Piece.WROOK])) != 0) discovered |= kRookAtk; ulong kBishAtk = BitBoard.bishopAttacks(bKingSq, occupied); if ((BitBoard.bishopAttacks(bKingSq, occupied & ~kBishAtk) & (pos.pieceTypeBB[Piece.WQUEEN] | pos.pieceTypeBB[Piece.WBISHOP])) != 0) discovered |= kBishAtk; // Queen moves ulong squares = pos.pieceTypeBB[Piece.WQUEEN]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = (BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied)); if ((discovered & (1UL<<sq)) == 0) m &= (pos.blackBB | kRookAtk | kBishAtk); m &= ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Rook moves squares = pos.pieceTypeBB[Piece.WROOK]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.rookAttacks(sq, occupied); if ((discovered & (1UL<<sq)) == 0) m &= (pos.blackBB | kRookAtk); m &= ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Bishop moves squares = pos.pieceTypeBB[Piece.WBISHOP]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.bishopAttacks(sq, occupied); if ((discovered & (1UL<<sq)) == 0) m &= (pos.blackBB | kBishAtk); m &= ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // King moves { sq = pos.getKingSq(true); m = BitBoard.kingAttacks[sq]; m &= ((discovered & (1UL<<sq)) == 0) ? pos.blackBB : ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; int k0 = 4; if (sq == k0) { ulong OO_SQ = 0x60L; ulong OOO_SQ = 0xEL; if (((pos.getCastleMask() & (1 << Position.H1_CASTLE)) != 0) && ((OO_SQ & (pos.whiteBB | pos.blackBB)) == 0) && (pos.getPiece(k0 + 3) == Piece.WROOK) && !sqAttacked(pos, k0) && !sqAttacked(pos, k0 + 1)) { setMove(moveList, k0, k0 + 2, Piece.EMPTY); } if (((pos.getCastleMask() & (1 << Position.A1_CASTLE)) != 0) && ((OOO_SQ & (pos.whiteBB | pos.blackBB)) == 0) && (pos.getPiece(k0 - 4) == Piece.WROOK) && !sqAttacked(pos, k0) && !sqAttacked(pos, k0 - 1)) { setMove(moveList, k0, k0 - 2, Piece.EMPTY); } } } // Knight moves ulong knights = pos.pieceTypeBB[Piece.WKNIGHT]; ulong kKnightAtk = BitBoard.knightAttacks[bKingSq]; while (knights != 0) { sq = BitBoard.numberOfTrailingZeros(knights); m = BitBoard.knightAttacks[sq] & ~pos.whiteBB; if ((discovered & (1UL<<sq)) == 0) m &= (pos.blackBB | kKnightAtk); m &= ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; knights &= knights-1; } // Pawn moves // Captures ulong pawns = pos.pieceTypeBB[Piece.WPAWN]; int epSquare = pos.getEpSquare(); ulong epMask = (epSquare >= 0) ? (1UL << epSquare) : 0L; m = (pawns << 7) & BitBoard.maskAToGFiles & (pos.blackBB | epMask); if (addPawnMovesByMask(moveList, pos, m, -7, false)) return moveList; m = (pawns << 9) & BitBoard.maskBToHFiles & (pos.blackBB | epMask); if (addPawnMovesByMask(moveList, pos, m, -9, false)) return moveList; // Discovered checks and promotions ulong pawnAll = discovered | BitBoard.maskRow7; m = ((pawns & pawnAll) << 8) & ~(pos.whiteBB | pos.blackBB); if (addPawnMovesByMask(moveList, pos, m, -8, false)) return moveList; m = ((m & BitBoard.maskRow3) << 8) & ~(pos.whiteBB | pos.blackBB); addPawnDoubleMovesByMask(moveList, pos, m, -16); // Normal checks m = ((pawns & ~pawnAll) << 8) & ~(pos.whiteBB | pos.blackBB); if (addPawnMovesByMask(moveList, pos, m & BitBoard.bPawnAttacks[bKingSq], -8, false)) return moveList; m = ((m & BitBoard.maskRow3) << 8) & ~(pos.whiteBB | pos.blackBB); addPawnDoubleMovesByMask(moveList, pos, m & BitBoard.bPawnAttacks[bKingSq], -16); } else { int sq = 0; ulong m = 0; int wKingSq = pos.getKingSq(true); ulong discovered = 0; // Squares that could generate discovered checks ulong kRookAtk = BitBoard.rookAttacks(wKingSq, occupied); if ((BitBoard.rookAttacks(wKingSq, occupied & ~kRookAtk) & (pos.pieceTypeBB[Piece.BQUEEN] | pos.pieceTypeBB[Piece.BROOK])) != 0) discovered |= kRookAtk; ulong kBishAtk = BitBoard.bishopAttacks(wKingSq, occupied); if ((BitBoard.bishopAttacks(wKingSq, occupied & ~kBishAtk) & (pos.pieceTypeBB[Piece.BQUEEN] | pos.pieceTypeBB[Piece.BBISHOP])) != 0) discovered |= kBishAtk; // Queen moves ulong squares = pos.pieceTypeBB[Piece.BQUEEN]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = (BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied)); if ((discovered & (1UL<<sq)) == 0) m &= pos.whiteBB | kRookAtk | kBishAtk; m &= ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Rook moves squares = pos.pieceTypeBB[Piece.BROOK]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.rookAttacks(sq, occupied); if ((discovered & (1UL<<sq)) == 0) m &= pos.whiteBB | kRookAtk; m &= ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Bishop moves squares = pos.pieceTypeBB[Piece.BBISHOP]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.bishopAttacks(sq, occupied); if ((discovered & (1UL<<sq)) == 0) m &= pos.whiteBB | kBishAtk; m &= ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // King moves { sq = pos.getKingSq(false); m = BitBoard.kingAttacks[sq]; m &= ((discovered & (1UL<<sq)) == 0) ? pos.whiteBB : ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; int k0 = 60; if (sq == k0) { ulong OO_SQ = 0x6000000000000000L; ulong OOO_SQ = 0xE00000000000000L; if (((pos.getCastleMask() & (1 << Position.H8_CASTLE)) != 0) && ((OO_SQ & (pos.whiteBB | pos.blackBB)) == 0) && (pos.getPiece(k0 + 3) == Piece.BROOK) && !sqAttacked(pos, k0) && !sqAttacked(pos, k0 + 1)) { setMove(moveList, k0, k0 + 2, Piece.EMPTY); } if (((pos.getCastleMask() & (1 << Position.A8_CASTLE)) != 0) && ((OOO_SQ & (pos.whiteBB | pos.blackBB)) == 0) && (pos.getPiece(k0 - 4) == Piece.BROOK) && !sqAttacked(pos, k0) && !sqAttacked(pos, k0 - 1)) { setMove(moveList, k0, k0 - 2, Piece.EMPTY); } } } // Knight moves ulong knights = pos.pieceTypeBB[Piece.BKNIGHT]; ulong kKnightAtk = BitBoard.knightAttacks[wKingSq]; while (knights != 0) { sq = BitBoard.numberOfTrailingZeros(knights); m = BitBoard.knightAttacks[sq] & ~pos.blackBB; if ((discovered & (1UL<<sq)) == 0) m &= pos.whiteBB | kKnightAtk; m &= ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; knights &= knights-1; } // Pawn moves // Captures ulong pawns = pos.pieceTypeBB[Piece.BPAWN]; int epSquare = pos.getEpSquare(); ulong epMask = (epSquare >= 0) ? (1UL << epSquare) : 0L; m = (pawns >> 9) & BitBoard.maskAToGFiles & (pos.whiteBB | epMask); if (addPawnMovesByMask(moveList, pos, m, 9, false)) return moveList; m = (pawns >> 7) & BitBoard.maskBToHFiles & (pos.whiteBB | epMask); if (addPawnMovesByMask(moveList, pos, m, 7, false)) return moveList; // Discovered checks and promotions ulong pawnAll = discovered | BitBoard.maskRow2; m = ((pawns & pawnAll) >> 8) & ~(pos.whiteBB | pos.blackBB); if (addPawnMovesByMask(moveList, pos, m, 8, false)) return moveList; m = ((m & BitBoard.maskRow6) >> 8) & ~(pos.whiteBB | pos.blackBB); addPawnDoubleMovesByMask(moveList, pos, m, 16); // Normal checks m = ((pawns & ~pawnAll) >> 8) & ~(pos.whiteBB | pos.blackBB); if (addPawnMovesByMask(moveList, pos, m & BitBoard.wPawnAttacks[wKingSq], 8, false)) return moveList; m = ((m & BitBoard.maskRow6) >> 8) & ~(pos.whiteBB | pos.blackBB); addPawnDoubleMovesByMask(moveList, pos, m & BitBoard.wPawnAttacks[wKingSq], 16); } return moveList; }
public MoveList pseudoLegalCaptures(Position pos) { MoveList moveList = getMoveListObj(); ulong occupied = pos.whiteBB | pos.blackBB; if (pos.whiteMove) { int sq = 0; ulong m = 0; // Queen moves ulong squares = pos.pieceTypeBB[Piece.WQUEEN]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = (BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied)) & pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Rook moves squares = pos.pieceTypeBB[Piece.WROOK]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.rookAttacks(sq, occupied) & pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Bishop moves squares = pos.pieceTypeBB[Piece.WBISHOP]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.bishopAttacks(sq, occupied) & pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Knight moves ulong knights = pos.pieceTypeBB[Piece.WKNIGHT]; while (knights != 0) { sq = BitBoard.numberOfTrailingZeros(knights); m = BitBoard.knightAttacks[sq] & pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; knights &= knights-1; } // King moves sq = pos.getKingSq(true); m = BitBoard.kingAttacks[sq] & pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; // Pawn moves ulong pawns = pos.pieceTypeBB[Piece.WPAWN]; m = (pawns << 8) & ~(pos.whiteBB | pos.blackBB); m &= BitBoard.maskRow8; if (addPawnMovesByMask(moveList, pos, m, -8, false)) return moveList; int epSquare = pos.getEpSquare(); ulong epMask = (epSquare >= 0) ? (1UL << epSquare) : 0L; m = (pawns << 7) & BitBoard.maskAToGFiles & (pos.blackBB | epMask); if (addPawnMovesByMask(moveList, pos, m, -7, false)) return moveList; m = (pawns << 9) & BitBoard.maskBToHFiles & (pos.blackBB | epMask); if (addPawnMovesByMask(moveList, pos, m, -9, false)) return moveList; } else { int sq = 0; ulong m = 0; // Queen moves ulong squares = pos.pieceTypeBB[Piece.BQUEEN]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = (BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied)) & pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Rook moves squares = pos.pieceTypeBB[Piece.BROOK]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.rookAttacks(sq, occupied) & pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Bishop moves squares = pos.pieceTypeBB[Piece.BBISHOP]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.bishopAttacks(sq, occupied) & pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Knight moves ulong knights = pos.pieceTypeBB[Piece.BKNIGHT]; while (knights != 0) { sq = BitBoard.numberOfTrailingZeros(knights); m = BitBoard.knightAttacks[sq] & pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; knights &= knights-1; } // King moves sq = pos.getKingSq(false); m = BitBoard.kingAttacks[sq] & pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; // Pawn moves ulong pawns = pos.pieceTypeBB[Piece.BPAWN]; m = (pawns >> 8) & ~(pos.whiteBB | pos.blackBB); m &= BitBoard.maskRow1; if (addPawnMovesByMask(moveList, pos, m, 8, false)) return moveList; int epSquare = pos.getEpSquare(); ulong epMask = (epSquare >= 0) ? (1UL << epSquare) : 0L; m = (pawns >> 9) & BitBoard.maskAToGFiles & (pos.whiteBB | epMask); if (addPawnMovesByMask(moveList, pos, m, 9, false)) return moveList; m = (pawns >> 7) & BitBoard.maskBToHFiles & (pos.whiteBB | epMask); if (addPawnMovesByMask(moveList, pos, m, 7, false)) return moveList; } return moveList; }
/** * Generate and return a list of pseudo-legal check evasion moves. * Pseudo-legal means that the moves doesn't necessarily defend from check threats. */ public MoveList checkEvasions(Position pos) { MoveList moveList = getMoveListObj(); ulong occupied = pos.whiteBB | pos.blackBB; if (pos.whiteMove) { int sq = 0; ulong m = 0; ulong kingThreats = pos.pieceTypeBB[Piece.BKNIGHT] & BitBoard.knightAttacks[pos.wKingSq]; ulong rookPieces = pos.pieceTypeBB[Piece.BROOK] | pos.pieceTypeBB[Piece.BQUEEN]; if (rookPieces != 0) kingThreats |= rookPieces & BitBoard.rookAttacks(pos.wKingSq, occupied); ulong bishPieces = pos.pieceTypeBB[Piece.BBISHOP] | pos.pieceTypeBB[Piece.BQUEEN]; if (bishPieces != 0) kingThreats |= bishPieces & BitBoard.bishopAttacks(pos.wKingSq, occupied); kingThreats |= pos.pieceTypeBB[Piece.BPAWN] & BitBoard.wPawnAttacks[pos.wKingSq]; ulong validTargets = 0; if ((kingThreats != 0) && ((kingThreats & (kingThreats-1)) == 0)) { // Exactly one attacking piece int threatSq = BitBoard.numberOfTrailingZeros(kingThreats); validTargets = kingThreats | BitBoard.squaresBetween[pos.wKingSq][threatSq]; } validTargets |= pos.pieceTypeBB[Piece.BKING]; // Queen moves ulong squares = pos.pieceTypeBB[Piece.WQUEEN]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = (BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied)) & ~pos.whiteBB & validTargets; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Rook moves squares = pos.pieceTypeBB[Piece.WROOK]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.rookAttacks(sq, occupied) & ~pos.whiteBB & validTargets; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Bishop moves squares = pos.pieceTypeBB[Piece.WBISHOP]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.bishopAttacks(sq, occupied) & ~pos.whiteBB & validTargets; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // King moves { sq = pos.getKingSq(true); m = BitBoard.kingAttacks[sq] & ~pos.whiteBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; } // Knight moves ulong knights = pos.pieceTypeBB[Piece.WKNIGHT]; while (knights != 0) { sq = BitBoard.numberOfTrailingZeros(knights); m = BitBoard.knightAttacks[sq] & ~pos.whiteBB & validTargets; if (addMovesByMask(moveList, pos, sq, m)) return moveList; knights &= knights-1; } // Pawn moves ulong pawns = pos.pieceTypeBB[Piece.WPAWN]; m = (pawns << 8) & ~occupied; if (addPawnMovesByMask(moveList, pos, m & validTargets, -8, true)) return moveList; m = ((m & BitBoard.maskRow3) << 8) & ~occupied; addPawnDoubleMovesByMask(moveList, pos, m & validTargets, -16); int epSquare = pos.getEpSquare(); ulong epMask = (epSquare >= 0) ? (1UL << epSquare) : 0L; m = (pawns << 7) & BitBoard.maskAToGFiles & ((pos.blackBB & validTargets) | epMask); if (addPawnMovesByMask(moveList, pos, m, -7, true)) return moveList; m = (pawns << 9) & BitBoard.maskBToHFiles & ((pos.blackBB & validTargets) | epMask); if (addPawnMovesByMask(moveList, pos, m, -9, true)) return moveList; } else { int sq = 0; ulong m = 0; ulong kingThreats = pos.pieceTypeBB[Piece.WKNIGHT] & BitBoard.knightAttacks[pos.bKingSq]; ulong rookPieces = pos.pieceTypeBB[Piece.WROOK] | pos.pieceTypeBB[Piece.WQUEEN]; if (rookPieces != 0) kingThreats |= rookPieces & BitBoard.rookAttacks(pos.bKingSq, occupied); ulong bishPieces = pos.pieceTypeBB[Piece.WBISHOP] | pos.pieceTypeBB[Piece.WQUEEN]; if (bishPieces != 0) kingThreats |= bishPieces & BitBoard.bishopAttacks(pos.bKingSq, occupied); kingThreats |= pos.pieceTypeBB[Piece.WPAWN] & BitBoard.bPawnAttacks[pos.bKingSq]; ulong validTargets = 0; if ((kingThreats != 0) && ((kingThreats & (kingThreats-1)) == 0)) { // Exactly one attacking piece int threatSq = BitBoard.numberOfTrailingZeros(kingThreats); validTargets = kingThreats | BitBoard.squaresBetween[pos.bKingSq][threatSq]; } validTargets |= pos.pieceTypeBB[Piece.WKING]; // Queen moves ulong squares = pos.pieceTypeBB[Piece.BQUEEN]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = (BitBoard.rookAttacks(sq, occupied) | BitBoard.bishopAttacks(sq, occupied)) & ~pos.blackBB & validTargets; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Rook moves squares = pos.pieceTypeBB[Piece.BROOK]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.rookAttacks(sq, occupied) & ~pos.blackBB & validTargets; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // Bishop moves squares = pos.pieceTypeBB[Piece.BBISHOP]; while (squares != 0) { sq = BitBoard.numberOfTrailingZeros(squares); m = BitBoard.bishopAttacks(sq, occupied) & ~pos.blackBB & validTargets; if (addMovesByMask(moveList, pos, sq, m)) return moveList; squares &= squares-1; } // King moves { sq = pos.getKingSq(false); m = BitBoard.kingAttacks[sq] & ~pos.blackBB; if (addMovesByMask(moveList, pos, sq, m)) return moveList; } // Knight moves ulong knights = pos.pieceTypeBB[Piece.BKNIGHT]; while (knights != 0) { sq = BitBoard.numberOfTrailingZeros(knights); m = BitBoard.knightAttacks[sq] & ~pos.blackBB & validTargets; if (addMovesByMask(moveList, pos, sq, m)) return moveList; knights &= knights-1; } // Pawn moves ulong pawns = pos.pieceTypeBB[Piece.BPAWN]; m = (pawns >> 8) & ~occupied; if (addPawnMovesByMask(moveList, pos, m & validTargets, 8, true)) return moveList; m = ((m & BitBoard.maskRow6) >> 8) & ~occupied; addPawnDoubleMovesByMask(moveList, pos, m & validTargets, 16); int epSquare = pos.getEpSquare(); ulong epMask = (epSquare >= 0) ? (1UL << epSquare) : 0L; m = (pawns >> 9) & BitBoard.maskAToGFiles & ((pos.whiteBB & validTargets) | epMask); if (addPawnMovesByMask(moveList, pos, m, 9, true)) return moveList; m = (pawns >> 7) & BitBoard.maskBToHFiles & ((pos.whiteBB & validTargets) | epMask); if (addPawnMovesByMask(moveList, pos, m, 7, true)) return moveList; } return moveList; }