Exemple #1
0
 /** Record move as a failure. */
 public void addFail(Position pos, Move m, int depth)
 {
     int p = pos.getPiece(m.from);
     int cnt = depth;
     countFail[p][m.to] += cnt;
     score[p][m.to] = -1;
 }
Exemple #2
0
 /**
  * Prints board to console
  */
 public static void DispBoard(Position pos)
 {
     string ll = "    +----+----+----+----+----+----+----+----+";
     SystemHelper.println(ll);
     for (int y = 7; y >= 0; y--) {
     string ret = "    |";
     for (int x = 0; x < 8; x++) {
         ret+=' ';
         int p = pos.getPiece(Position.getSquare(x, y));
         if (p == Piece.EMPTY) {
             bool dark = Position.darkSquare(x, y);
             ret+=(dark ? ".. |" : "   |");
         } else {
             ret+=(Piece.isWhite(p) ? ' ' : '*');
             string pieceName = pieceToChar(p);
             if (pieceName.Length == 0)
                 pieceName = "P";
             ret+=pieceName;
             ret+=" |";
         }
     }
     SystemHelper.println(ret);
     SystemHelper.println(ll);
     }
 }
Exemple #3
0
 /** Record move as a success. */
 public void addSuccess(Position pos, Move m, int depth)
 {
     int p = pos.getPiece(m.from);
     int cnt = depth;
     int val = countSuccess[p][m.to] + cnt;
     if (val > 1000) {
     val /= 2;
     countFail[p][m.to] /= 2;
     }
     countSuccess[p][m.to] = val;
     score[p][m.to] = -1;
 }
Exemple #4
0
 /** Get a score between 0 and 49, depending of the success/fail ratio of the move. */
 public int getHistScore(Position pos, Move m)
 {
     int p = pos.getPiece(m.from);
     int ret = score[p][m.to];
     if (ret >= 0)
     return ret;
     int succ = countSuccess[p][m.to];
     int fail = countFail[p][m.to];
     if (succ + fail > 0) {
     ret = succ * 49 / (succ + fail);
     } else {
     ret = 0;
     }
     score[p][m.to] = ret;
     return ret;
 }
Exemple #5
0
 /** 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);
     }
     }
 }
Exemple #6
0
        private static string moveTostring(Position pos, Move move, bool ulongForm, MoveGen.MoveList moves)
        {
            string ret = "";
            int wKingOrigPos = Position.getSquare(4, 0);
            int bKingOrigPos = Position.getSquare(4, 7);
            if (move.from == wKingOrigPos && pos.getPiece(wKingOrigPos) == Piece.WKING) {
            // Check white castle
            if (move.to == Position.getSquare(6, 0)) {
                    ret += ("O-O");
            } else if (move.to == Position.getSquare(2, 0)) {
                ret += ("O-O-O");
            }
            } else if (move.from == bKingOrigPos && pos.getPiece(bKingOrigPos) == Piece.BKING) {
            // Check white castle
            if (move.to == Position.getSquare(6, 7)) {
                ret += ("O-O");
            } else if (move.to == Position.getSquare(2, 7)) {
                ret += ("O-O-O");
            }
            }
            if (ret.Length == 0) {
            int p = pos.getPiece(move.from);
            ret += pieceToChar(p);
            int x1 = Position.getX(move.from);
            int y1 = Position.getY(move.from);
            int x2 = Position.getX(move.to);
            int y2 = Position.getY(move.to);
            if (ulongForm) {
                ret += ((char)(x1 + 'a'));
                ret += ((char)(y1 + '1'));
                ret += (isCapture(pos, move) ? 'x' : '-');
            } else {
                if (p == (pos.whiteMove ? Piece.WPAWN : Piece.BPAWN)) {
                    if (isCapture(pos, move)) {
                        ret += ((char)(x1 + 'a'));
                    }
                } else {
                    int numSameTarget = 0;
                    int numSameFile = 0;
                    int numSameRow = 0;
                    for (int mi = 0; mi < moves.size; mi++) {
                        Move m = moves.m[mi];
                        if (m == null)
                            break;
                        if ((pos.getPiece(m.from) == p) && (m.to == move.to)) {
                            numSameTarget++;
                            if (Position.getX(m.from) == x1)
                                numSameFile++;
                            if (Position.getY(m.from) == y1)
                                numSameRow++;
                        }
                    }
                    if (numSameTarget < 2) {
                        // No file/row info needed
                    } else if (numSameFile < 2) {
                        ret += ((char)(x1 + 'a'));   // Only file info needed
                    } else if (numSameRow < 2) {
                        ret += ((char)(y1 + '1'));   // Only row info needed
                    } else {
                        ret += ((char)(x1 + 'a'));   // File and row info needed
                        ret += ((char)(y1 + '1'));
                    }
                }
                if (isCapture(pos, move)) {
                    ret += ('x');
                }
            }
            ret += ((char)(x2 + 'a'));
            ret += ((char)(y2 + '1'));
            if (move.promoteTo != Piece.EMPTY) {
                ret += (pieceToChar(move.promoteTo));
            }
            }
            UndoInfo ui = new UndoInfo();
            if (MoveGen.givesCheck(pos, move)) {
            pos.makeMove(move, ui);
            MoveGen MG = new MoveGen();
            MoveGen.MoveList nextMoves = MG.pseudoLegalMoves(pos);
            MoveGen.RemoveIllegal(pos, nextMoves);
            if (nextMoves.size == 0) {
                ret += ('#');
            } else {
                ret += ('+');
            }
            pos.unMakeMove(move, ui);
            }

            return ret;
        }
Exemple #7
0
 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;
     }
 }
Exemple #8
0
        /** 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;
        }
Exemple #9
0
        /*throws ChessParseError*/
        /** Parse a FEN string and return a chess Position object. */
        public static Position readFEN(string fen)
        {
            Position pos = new Position();
            string[] words = fen.Split(' ');
            if (words.Length < 2) {
            throw new ChessParseError(/* "Too few pieces " */);
            }

            // Piece placement
            int row = 7;
            int col = 0;
            for (int i = 0; i < words[0].Length; i++) {
            char c = words[0][i];
            switch (c) {
                case '1': col += 1; break;
                case '2': col += 2; break;
                case '3': col += 3; break;
                case '4': col += 4; break;
                case '5': col += 5; break;
                case '6': col += 6; break;
                case '7': col += 7; break;
                case '8': col += 8; break;
                case '/': row--; col = 0; break;
                case 'P': safeSetPiece(pos, col, row, Piece.WPAWN);   col++; break;
                case 'N': safeSetPiece(pos, col, row, Piece.WKNIGHT); col++; break;
            case 'B': safeSetPiece(pos, col, row, Piece.WBISHOP); col++; break;
            case 'R': safeSetPiece(pos, col, row, Piece.WROOK);   col++; break;
            case 'Q': safeSetPiece(pos, col, row, Piece.WQUEEN);  col++; break;
            case 'K': safeSetPiece(pos, col, row, Piece.WKING);   col++; break;
            case 'p': safeSetPiece(pos, col, row, Piece.BPAWN);   col++; break;
            case 'n': safeSetPiece(pos, col, row, Piece.BKNIGHT); col++; break;
            case 'b': safeSetPiece(pos, col, row, Piece.BBISHOP); col++; break;
            case 'r': safeSetPiece(pos, col, row, Piece.BROOK);   col++; break;
            case 'q': safeSetPiece(pos, col, row, Piece.BQUEEN);  col++; break;
            case 'k': safeSetPiece(pos, col, row, Piece.BKING);   col++; break;
                default: throw new ChessParseError(/* "Invalid piece" */);
            }
            }
            if (words[1].Length == 0) {
            throw new ChessParseError(/*"Invalid side"*/);
            }
            pos.setWhiteMove(words[1][0] == 'w');

            // Castling rights
            int castleMask = 0;
            if (words.Length > 2) {
            for (int i = 0; i < words[2].Length; i++) {
                char c = words[2][i];
                switch (c) {
                    case 'K':
                        castleMask |= (1 << Position.H1_CASTLE);
                        break;
                    case 'Q':
                        castleMask |= (1 << Position.A1_CASTLE);
                        break;
                    case 'k':
                        castleMask |= (1 << Position.H8_CASTLE);
                        break;
                    case 'q':
                        castleMask |= (1 << Position.A8_CASTLE);
                        break;
                    case '-':
                        break;
                    default:
                        throw new ChessParseError(/* "Invalid castling flags" */);
                }
            }
            }
            pos.setCastleMask(castleMask);

            if (words.Length > 3) {
            // En passant target square
            string epstring = words[3];
            if (epstring != "-") {
                if (epstring.Length < 2) {
                    throw new ChessParseError(/* "Invalid en passant square" */);
                }
                pos.setEpSquare(getSquare(epstring));
            }
            }

            try {
            if (words.Length > 4) {
                pos.halfMoveClock = int.Parse(words[4]);
            }
            if (words.Length > 5) {
                pos.fullMoveCounter = int.Parse(words[5]);
            }
            } catch (NumberFormatException nfe) {
            // Ignore errors here, since the fields are optional
            }

            // Each side must have exactly one king
            int wKings = 0;
            int bKings = 0;
            for (int x = 0; x < 8; x++) {
            for (int y = 0; y < 8; y++) {
                int p = pos.getPiece(Position.getSquare(x, y));
                if (p == Piece.WKING) {
                    wKings++;
                } else if (p == Piece.BKING) {
                    bKings++;
                }
            }
            }
            if (wKings != 1) {
            throw new ChessParseError(/* "White must have exactly one king" */);
            }
            if (bKings != 1) {
            throw new ChessParseError(/* "Black must have exactly one king" */);
            }

            // Make sure king can not be captured
            Position pos2 = new Position(pos);
            pos2.setWhiteMove(!pos.whiteMove);
            if (MoveGen.inCheck(pos2)) {
            throw new ChessParseError(/* "King capture possible" */);
            }

            fixupEPSquare(pos);

            return pos;
        }
Exemple #10
0
 /** Like nextPiece(), but handles board edges. */
 private static int nextPieceSafe(Position pos, int sq, int delta)
 {
     int dx = 0, dy = 0;
     switch (delta) {
     case 1: dx=1; dy=0; break;
     case 9: dx=1; dy=1; break;
     case 8: dx=0; dy=1; break;
     case 7: dx=-1; dy=1; break;
     case -1: dx=-1; dy=0; break;
     case -9: dx=-1; dy=-1; break;
     case -8: dx=0; dy=-1; break;
     case -7: dx=1; dy=-1; break;
     }
     int x = Position.getX(sq);
     int y = Position.getY(sq);
     while (true) {
     x += dx;
     y += dy;
     if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) {
         return Piece.EMPTY;
     }
     int p = pos.getPiece(Position.getSquare(x, y));
     if (p != Piece.EMPTY)
         return p;
     }
 }
Exemple #11
0
 /**
  * Return the next piece in a given direction, starting from sq.
  */
 private static int nextPiece(Position pos, int sq, int delta)
 {
     while (true) {
     sq += delta;
     int p = pos.getPiece(sq);
     if (p != Piece.EMPTY)
         return p;
     }
 }
Exemple #12
0
        /**
         * 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;
        }
Exemple #13
0
        /** 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;
        }
Exemple #14
0
 /**
  * Return true if making a move delivers check to the opponent
  */
 public static bool givesCheck(Position pos, Move m)
 {
     bool wtm = pos.whiteMove;
     int oKingSq = pos.getKingSq(!wtm);
     int oKing = wtm ? Piece.BKING : Piece.WKING;
     int p = Piece.makeWhite(m.promoteTo == Piece.EMPTY ? pos.getPiece(m.from) : m.promoteTo);
     int d1 = BitBoard.getDirection(m.to, oKingSq);
     switch (d1) {
     case 8: case -8: case 1: case -1: // Rook direction
     if ((p == Piece.WQUEEN) || (p == Piece.WROOK))
         if ((d1 != 0) && (/*MoveGen.*/ nextPiece(pos, m.to, d1) == oKing))
             return true;
     break;
     case 9: case 7: case -9: case -7: // Bishop direction
     if ((p == Piece.WQUEEN) || (p == Piece.WBISHOP)) {
         if ((d1 != 0) && (/*MoveGen.*/ nextPiece(pos, m.to, d1) == oKing))
             return true;
     } else if (p == Piece.WPAWN) {
         if (((d1 > 0) == wtm) && (pos.getPiece(m.to + d1) == oKing))
             return true;
     }
     break;
     default:
     if (d1 != 0) { // Knight direction
         if (p == Piece.WKNIGHT)
             return true;
     }
     break;
     }
     int d2 = BitBoard.getDirection(m.from, oKingSq);
     if ((d2 != 0) && (d2 != d1) && (/*MoveGen.*/ nextPiece(pos, m.from, d2) == oKing)) {
     int p2 = /*MoveGen.*/ nextPieceSafe(pos, m.from, -d2);
     switch (d2) {
     case 8: case -8: case 1: case -1: // Rook direction
         if ((p2 == (wtm ? Piece.WQUEEN : Piece.BQUEEN)) ||
             (p2 == (wtm ? Piece.WROOK : Piece.BROOK)))
             return true;
         break;
     case 9: case 7: case -9: case -7: // Bishop direction
         if ((p2 == (wtm ? Piece.WQUEEN : Piece.BQUEEN)) ||
             (p2 == (wtm ? Piece.WBISHOP : Piece.BBISHOP)))
             return true;
         break;
     }
     }
     if ((m.promoteTo != Piece.EMPTY) && (d1 != 0) && (d1 == d2)) {
     switch (d1) {
     case 8: case -8: case 1: case -1: // Rook direction
         if ((p == Piece.WQUEEN) || (p == Piece.WROOK))
             if ((d1 != 0) && (/*MoveGen.*/ nextPiece(pos, m.from, d1) == oKing))
                 return true;
         break;
     case 9: case 7: case -9: case -7: // Bishop direction
         if ((p == Piece.WQUEEN) || (p == Piece.WBISHOP)) {
             if ((d1 != 0) && (/*MoveGen.*/ nextPiece(pos, m.from, d1) == oKing))
                 return true;
         }
         break;
     }
     }
     if (p == Piece.WKING) {
     if (m.to - m.from == 2) { // O-O
         if (/*MoveGen.*/ nextPieceSafe(pos, m.from, -1) == oKing)
             return true;
         if (/*MoveGen.*/ nextPieceSafe(pos, m.from + 1, wtm ? 8 : -8) == oKing)
             return true;
     } else if (m.to - m.from == -2) { // O-O-O
         if (/*MoveGen.*/ nextPieceSafe(pos, m.from, 1) == oKing)
             return true;
         if (/*MoveGen.*/ nextPieceSafe(pos, m.from - 1, wtm ? 8 : -8) == oKing)
             return true;
     }
     } else if (p == Piece.WPAWN) {
     if (pos.getPiece(m.to) == Piece.EMPTY) {
         int dx = Position.getX(m.to) - Position.getX(m.from);
         if (dx != 0) { // en passant
             int epSq = m.from + dx;
             int d3 = BitBoard.getDirection(epSq, oKingSq);
             switch (d3) {
             case 9: case 7: case -9: case -7:
                 if (/*MoveGen.*/ nextPiece(pos, epSq, d3) == oKing) {
                     int p2 = /*MoveGen.*/ nextPieceSafe(pos, epSq, -d3);
                     if ((p2 == (wtm ? Piece.WQUEEN : Piece.BQUEEN)) ||
                         (p2 == (wtm ? Piece.WBISHOP : Piece.BBISHOP)))
                         return true;
                 }
                 break;
             case 1:
                 if (/*MoveGen.*/ nextPiece(pos, Math.Max(epSq, m.from), d3) == oKing) {
                     int p2 = /*MoveGen.*/ nextPieceSafe(pos, Math.Min(epSq, m.from), -d3);
                     if ((p2 == (wtm ? Piece.WQUEEN : Piece.BQUEEN)) ||
                         (p2 == (wtm ? Piece.WROOK : Piece.BROOK)))
                         return true;
                 }
                 break;
             case -1:
                 if (/*MoveGen.*/ nextPiece(pos, Math.Min(epSq, m.from), d3) == oKing) {
                     int p2 = /*MoveGen.*/ nextPieceSafe(pos, Math.Max(epSq, m.from), -d3);
                     if ((p2 == (wtm ? Piece.WQUEEN : Piece.BQUEEN)) ||
                         (p2 == (wtm ? Piece.WROOK : Piece.BROOK)))
                         return true;
                 }
                 break;
             }
         }
     }
     }
     return false;
 }