示例#1
0
        public static int generate_promotions(ExtMove[] mlist, int mPos, Bitboard pawnsOn7, Bitboard target, CheckInfo ci, GenType Type, Square Delta)
        {
            Bitboard b = BitBoard.shift_bb(pawnsOn7, Delta) & target;

            while (b != 0)
            {
                Square to = BitBoard.pop_lsb(ref b);

                if (Type == GenTypeS.CAPTURES || Type == GenTypeS.EVASIONS || Type == GenTypeS.NON_EVASIONS)
                {
                    mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.QUEEN);
                }

                if (Type == GenTypeS.QUIETS || Type == GenTypeS.EVASIONS || Type == GenTypeS.NON_EVASIONS)
                {
                    mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.ROOK);
                    mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.BISHOP);
                    mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.KNIGHT);
                }

                // Knight promotion is the only promotion that can give a direct check
                // that's not already included in the queen promotion.
                if (Type == GenTypeS.QUIET_CHECKS && (BitBoard.StepAttacksBB[PieceS.W_KNIGHT][to] & BitBoard.SquareBB[ci.ksq]) != 0)
                {
                    mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.KNIGHT);
                }
            }

            return(mPos);
        }
示例#2
0
        public static int generate_castling(Position pos, ExtMove[] mlist, int mPos, Color us, CheckInfo ci, CastlingRight Cr, bool Checks, bool Chess960)
        {
            bool KingSide = (Cr == CastlingRightS.WHITE_OO || Cr == CastlingRightS.BLACK_OO);

            if (pos.castling_impeded(Cr) || 0 == pos.can_castle_castleright(Cr))
            {
                return(mPos);
            }

            // After castling, the rook and king final positions are the same in Chess960
            // as they would be in standard chess.
            Square   kfrom   = pos.king_square(us);
            Square   rfrom   = pos.castling_rook_square(Cr);
            Square   kto     = Types.relative_square(us, KingSide ? SquareS.SQ_G1 : SquareS.SQ_C1);
            Bitboard enemies = pos.pieces_color(Types.notColor(us));

            Debug.Assert(0 == pos.checkers());

            Square K = Chess960 ? kto > kfrom ? SquareS.DELTA_W : SquareS.DELTA_E
                              : KingSide ? SquareS.DELTA_W : SquareS.DELTA_E;

            for (Square s = kto; s != kfrom; s += K)
            {
                if ((pos.attackers_to(s) & enemies) != 0)
                {
                    return(mPos);
                }
            }

            // Because we generate only legal castling moves we need to verify that
            // when moving the castling rook we do not discover some hidden checker.
            // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
            if (Chess960 && (BitBoard.attacks_bb_SBBPT(kto, pos.pieces() ^ BitBoard.SquareBB[rfrom], PieceTypeS.ROOK) & pos.pieces_color_piecetype(Types.notColor(us), PieceTypeS.ROOK, PieceTypeS.QUEEN)) != 0)
            {
                return(mPos);
            }

            Move m = Types.make(kfrom, rfrom, MoveTypeS.CASTLING);

            if (Checks && !pos.gives_check(m, ci))
            {
                return(mPos);
            }

            mlist[mPos++].move = m;

            return(mPos);
        }
示例#3
0
        public static int generate_pawn_moves(Position pos, ExtMove[] mlist, int mPos, Bitboard target, CheckInfo ci, Color Us, GenType Type)
        {
            // Compute our parametrized parameters at compile time, named according to
            // the point of view of white side.
            Color    Them     = (Us == ColorS.WHITE ? ColorS.BLACK : ColorS.WHITE);
            Bitboard TRank8BB = (Us == ColorS.WHITE ? BitBoard.Rank8BB : BitBoard.Rank1BB);
            Bitboard TRank7BB = (Us == ColorS.WHITE ? BitBoard.Rank7BB : BitBoard.Rank2BB);
            Bitboard TRank3BB = (Us == ColorS.WHITE ? BitBoard.Rank3BB : BitBoard.Rank6BB);
            Square   Up       = (Us == ColorS.WHITE ? SquareS.DELTA_N : SquareS.DELTA_S);
            Square   Right    = (Us == ColorS.WHITE ? SquareS.DELTA_NE : SquareS.DELTA_SW);
            Square   Left     = (Us == ColorS.WHITE ? SquareS.DELTA_NW : SquareS.DELTA_SE);

            Bitboard b1, b2, dc1, dc2, emptySquares = 0;

            Bitboard pawnsOn7    = pos.pieces_color_piecetype(Us, PieceTypeS.PAWN) & TRank7BB;
            Bitboard pawnsNotOn7 = pos.pieces_color_piecetype(Us, PieceTypeS.PAWN) & ~TRank7BB;

            Bitboard enemies = (Type == GenTypeS.EVASIONS ? pos.pieces_color(Them) & target :
                                Type == GenTypeS.CAPTURES ? target : pos.pieces_color(Them));

            // Single and double pawn pushes, no promotions
            if (Type != GenTypeS.CAPTURES)
            {
                emptySquares = (Type == GenTypeS.QUIETS || Type == GenTypeS.QUIET_CHECKS ? target : ~pos.pieces());

                b1 = BitBoard.shift_bb(pawnsNotOn7, Up) & emptySquares;
                b2 = BitBoard.shift_bb(b1 & TRank3BB, Up) & emptySquares;

                if (Type == GenTypeS.EVASIONS) // Consider only blocking squares
                {
                    b1 &= target;
                    b2 &= target;
                }

                if (Type == GenTypeS.QUIET_CHECKS)
                {
                    b1 &= pos.attacks_from_pawn(ci.ksq, Them);
                    b2 &= pos.attacks_from_pawn(ci.ksq, Them);

                    // Add pawn pushes which give discovered check. This is possible only
                    // if the pawn is not on the same file as the enemy king, because we
                    // don't generate captures. Note that a possible discovery check
                    // promotion has been already generated among captures.
                    if ((pawnsNotOn7 & ci.dcCandidates) != 0)
                    {
                        dc1 = BitBoard.shift_bb(pawnsNotOn7 & ci.dcCandidates, Up) & emptySquares & ~BitBoard.file_bb_square(ci.ksq);
                        dc2 = BitBoard.shift_bb(dc1 & TRank3BB, Up) & emptySquares;

                        b1 |= dc1;
                        b2 |= dc2;
                    }
                }

                while (b1 != 0)
                {
                    Square to = BitBoard.pop_lsb(ref b1);
                    mlist[mPos++].move = Types.make_move(to - Up, to);
                }

                while (b2 != 0)
                {
                    Square to = BitBoard.pop_lsb(ref b2);
                    mlist[mPos++].move = Types.make_move(to - Up - Up, to);
                }
            }

            // Promotions and underpromotions
            if (pawnsOn7 != 0 && (Type != GenTypeS.EVASIONS || (target & TRank8BB) != 0))
            {
                if (Type == GenTypeS.CAPTURES)
                {
                    emptySquares = ~pos.pieces();
                }

                if (Type == GenTypeS.EVASIONS)
                {
                    emptySquares &= target;
                }

                mPos = generate_promotions(mlist, mPos, pawnsOn7, enemies, ci, Type, Right);
                mPos = generate_promotions(mlist, mPos, pawnsOn7, enemies, ci, Type, Left);
                mPos = generate_promotions(mlist, mPos, pawnsOn7, emptySquares, ci, Type, Up);
            }

            // Standard and en-passant captures
            if (Type == GenTypeS.CAPTURES || Type == GenTypeS.EVASIONS || Type == GenTypeS.NON_EVASIONS)
            {
                b1 = BitBoard.shift_bb(pawnsNotOn7, Right) & enemies;
                b2 = BitBoard.shift_bb(pawnsNotOn7, Left) & enemies;

                while (b1 != 0)
                {
                    Square to = BitBoard.pop_lsb(ref b1);
                    mlist[mPos++].move = Types.make_move(to - Right, to);
                }

                while (b2 != 0)
                {
                    Square to = BitBoard.pop_lsb(ref b2);
                    mlist[mPos++].move = Types.make_move(to - Left, to);
                }

                if (pos.ep_square() != SquareS.SQ_NONE)
                {
                    Debug.Assert(Types.rank_of(pos.ep_square()) == Types.relative_rank_rank(Us, RankS.RANK_6));

                    // An en passant capture can be an evasion only if the checking piece
                    // is the double pushed pawn and so is in the target. Otherwise this
                    // is a discovery check and we are forced to do otherwise.
                    if (Type == GenTypeS.EVASIONS && (target & BitBoard.SquareBB[(pos.ep_square() - Up)]) == 0)
                    {
                        return(mPos);
                    }

                    b1 = pawnsNotOn7 & pos.attacks_from_pawn(pos.ep_square(), Them);

                    Debug.Assert(b1 != 0);

                    while (b1 != 0)
                    {
                        mlist[mPos++].move = Types.make(BitBoard.pop_lsb(ref b1), pos.ep_square(), MoveTypeS.ENPASSANT);
                    }
                }
            }

            return(mPos);
        }
示例#4
0
        /// probe() tries to find a book move for the given position. If no move is
        /// found returns MOVE_NONE. If pickBest is true returns always the highest
        /// rated move, otherwise randomly chooses one, based on the move score.
        public Move probe(Position pos, string fName, bool pickBest)
        {
            if (fName == null || (fileName != fName && !open(fName)))
            {
                return(MoveS.MOVE_NONE);
            }

            PolyglotBook.Entry e    = new PolyglotBook.Entry();
            UInt16             best = 0;
            uint sum  = 0;
            Move move = MoveS.MOVE_NONE;
            Key  key  = polyglot_key(pos);

            stream.Seek(find_first(key) * SIZE_OF_BOOKENTRY, SeekOrigin.Begin);
            while (read(ref e) && e.key == key)
            {
                best = Math.Max(best, e.count);
                sum += e.count;

                // Choose book move according to its score. If a move has a very
                // high score it has higher probability to be choosen than a move
                // with lower score. Note that first entry is always chosen.
                if ((sum != 0 && ((((uint)RKiss.rand64()) % sum) < e.count)) ||
                    (pickBest && e.count == best))
                {
                    move = (e.move);
                }
            }

            if (move == 0)
            {
                return(MoveS.MOVE_NONE);
            }

            // A PolyGlot book move is encoded as follows:
            //
            // bit  0- 5: destination square (from 0 to 63)
            // bit  6-11: origin square (from 0 to 63)
            // bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4)
            //
            // Castling moves follow "king captures rook" representation. So in case book
            // move is a promotion we have to convert to our representation, in all the
            // other cases we can directly compare with a Move after having masked out
            // the special Move's flags (bit 14-15) that are not supported by PolyGlot.
            int pt = (move >> 12) & 7;

            if (pt != 0)
            {
                move = Types.make(Types.from_sq(move), Types.to_sq(move), MoveTypeS.PROMOTION, (pt + 1));
            }

            // Add 'special move' flags and verify it is legal
            for (MoveList ml = new MoveList(pos, GenTypeS.LEGAL); ml.mlist[ml.cur].move != MoveS.MOVE_NONE; ++ml)
            {
                if (move == (ml.move() ^ Types.type_of_move(ml.move())))
                {
                    return(ml.move());
                }
            }

            return(MoveS.MOVE_NONE);
        }