예제 #1
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);
        }