Beispiel #1
0
        private static void AddMove(this IPosition pos, MoveList moves, Piece piece, Square from, Square to, Piece promoted, Emgf flags, EMoveType type = EMoveType.Quiet)
        {
            Move move;

            if (type.HasFlagFast(EMoveType.Capture))
            {
                move = new Move(piece, pos.GetPiece(to), from, to, type, promoted);
            }
            else if (type.HasFlagFast(EMoveType.Epcapture))
            {
                move = new Move(piece, EPieceType.Pawn.MakePiece(~pos.State.SideToMove), from, to, type, promoted);
            }
            else
            {
                move = new Move(piece, from, to, type, promoted);
            }

            // check if move is actual a legal move if the flag is enabled
            if (flags.HasFlagFast(Emgf.Legalmoves) && !pos.IsLegal(move, piece, from, type))
            {
                return;
            }

            moves.Add(move);
        }
Beispiel #2
0
        private static void GenerateQuietMoves(this IPosition pos, MoveList moves, Emgf flags)
        {
            var currentSide = pos.State.SideToMove;
            var up          = currentSide == PlayerExtensions.White ? EDirection.North : EDirection.South;
            var notOccupied = ~pos.Pieces();
            var pushed      = (pos.Pieces(EPieceType.Pawn, currentSide) & ~currentSide.Rank7()).Shift(up) & notOccupied;

            pos.AddPawnMoves(moves, pushed, currentSide.PawnPushDistance(), EMoveType.Quiet, flags);

            pushed &= currentSide.Rank3();
            pos.AddPawnMoves(moves, pushed.Shift(up) & notOccupied, currentSide.PawnDoublePushDistance(), EMoveType.Doublepush, flags);

            pos.AddMoves(moves, notOccupied, flags);

            if (pos.InCheck)
            {
                return;
            }

            for (var castleType = ECastleling.Short; castleType < ECastleling.CastleNb; castleType++)
            {
                if (pos.CanCastle(castleType))
                {
                    pos.AddCastleMove(moves, pos.GetKingCastleFrom(currentSide, castleType), castleType.GetKingCastleTo(currentSide), flags);
                }
            }
        }
Beispiel #3
0
        private void GenerateQuietMoves(MoveList moves)
        {
            var currentSide = _position.State.SideToMove;
            var up          = currentSide == PlayerExtensions.White ? EDirection.North : EDirection.South;
            var notOccupied = ~_position.Pieces();
            var pushed      = (_position.Pieces(EPieceType.Pawn, currentSide) & ~currentSide.Rank7()).Shift(up) & notOccupied;

            AddPawnMoves(moves, pushed, currentSide.PawnPushDistance(), EMoveType.Quiet);

            pushed &= currentSide.Rank3();
            AddPawnMoves(moves, pushed.Shift(up) & notOccupied, currentSide.PawnDoublePushDistance(), EMoveType.Doublepush);

            AddMoves(moves, notOccupied);

            if (_position.InCheck)
            {
                return;
            }

            for (var castleType = ECastleling.Short; castleType < ECastleling.CastleNb; castleType++)
            {
                if (_position.CanCastle(castleType))
                {
                    AddCastleMove(moves, _position.GetKingCastleFrom(currentSide, castleType), castleType.GetKingCastleTo(currentSide));
                }
            }
        }
Beispiel #4
0
        public void GenerateMoves(bool force = false)
        {
            // Align current structure to position.
            Reset(MoveExtensions.EmptyMove);

            // this is only preparation for true engine integration (not used yet)
            //if (Flags.HasFlagFast(Emgf.Stages))
            //    return;

            if (Table.TryGetValue(_position.State.Key, out var moves) && !force)
            {
                Moves = moves;
            }
            else
            {
                moves = new MoveList();
                // relax the gc while generating moves.
                var old = GCSettings.LatencyMode;
                GCSettings.LatencyMode = GCLatencyMode.LowLatency;
                GenerateCapturesAndPromotions(moves);
                GenerateQuietMoves(moves);
                Table.TryAdd(_position.State.Key, moves);
                Moves = moves;
                GCSettings.LatencyMode = old;
            }
        }
Beispiel #5
0
        public static MoveList GenerateMoves(this IPosition pos, Emgf flags = Emgf.Legalmoves, bool useCache = true, bool force = false)
        {
            pos.State.Pinned = flags.HasFlagFast(Emgf.Legalmoves)
                ? pos.GetPinnedPieces(pos.GetPieceSquare(EPieceType.King, pos.State.SideToMove), pos.State.SideToMove)
                : BitBoards.EmptyBitBoard;

            var moves = new MoveList();

            pos.GenerateCapturesAndPromotions(moves, flags);
            pos.GenerateQuietMoves(moves, flags);

            return(moves);
        }
Beispiel #6
0
        private void AddMoves(MoveList moves, Piece piece, Square from, BitBoard attacks)
        {
            var target = _position.Pieces(~_position.State.SideToMove) & attacks;

            foreach (var to in target)
            {
                AddMove(moves, piece, from, to, EPieces.NoPiece, EMoveType.Capture);
            }

            target = ~_position.Pieces() & attacks;
            foreach (var to in target)
            {
                AddMove(moves, piece, from, to, PieceExtensions.EmptyPiece);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Iterates through the piece types and generates moves based on their attacks.
        /// It does not contain any checks for moves that are invalid, as the leaf methods
        /// contains implicit denial of move generation if the target bitboard is empty.
        /// </summary>
        /// <param name="moves">The move list to add potential moves to.</param>
        /// <param name="targetSquares">The target squares to move to</param>
        private void AddMoves(MoveList moves, BitBoard targetSquares)
        {
            var c = _position.State.SideToMove;

            var occupied = _position.Pieces();

            for (var pt = EPieceType.King; pt >= EPieceType.Knight; --pt)
            {
                var pc     = pt.MakePiece(c);
                var pieces = _position.Pieces(pc);
                foreach (var from in pieces)
                {
                    AddMoves(moves, pc, from, from.GetAttacks(pt, occupied) & targetSquares);
                }
            }
        }
Beispiel #8
0
        private static void AddPawnMoves(this IPosition pos, MoveList moves, BitBoard targetSquares, Direction direction, EMoveType type, Emgf flags)
        {
            if (targetSquares.Empty())
            {
                return;
            }

            var stm   = pos.State.SideToMove;
            var piece = EPieceType.Pawn.MakePiece(stm);

            var promotionRank       = stm.PromotionRank();
            var promotionSquares    = targetSquares & promotionRank;
            var nonPromotionSquares = targetSquares & ~promotionRank;

            while (nonPromotionSquares)
            {
                var to   = nonPromotionSquares.Lsb();
                var from = to - direction;
                pos.AddMove(moves, piece, from, to, PieceExtensions.EmptyPiece, flags, type);
                BitBoards.ResetLsb(ref nonPromotionSquares);
            }

            type |= EMoveType.Promotion;

            if (flags.HasFlagFast(Emgf.Queenpromotion))
            {
                var sqTo   = promotionSquares.Lsb();
                var sqFrom = sqTo - direction;
                pos.AddMove(moves, piece, sqFrom, sqTo, EPieceType.Queen.MakePiece(stm), flags, type);
                BitBoards.ResetLsb(ref promotionSquares);
            }
            else
            {
                while (promotionSquares)
                {
                    var sqTo   = promotionSquares.Lsb();
                    var sqFrom = sqTo - direction;
                    for (var promotedPiece = EPieceType.Queen; promotedPiece >= EPieceType.Knight; promotedPiece--)
                    {
                        pos.AddMove(moves, piece, sqFrom, sqTo, promotedPiece.MakePiece(stm), flags, type);
                    }

                    BitBoards.ResetLsb(ref promotionSquares);
                }
            }
        }
Beispiel #9
0
        /// <summary>
        /// Iterates through the piece types and generates moves based on their attacks.
        /// It does not contain any checks for moves that are invalid, as the leaf methods
        /// contains implicit denial of move generation if the target bitboard is empty.
        /// </summary>
        /// <param name="moves">The move list to add potential moves to.</param>
        /// <param name="targetSquares">The target squares to move to</param>
        private static void AddMoves(this IPosition pos, MoveList moves, BitBoard targetSquares, Emgf flags)
        {
            var c        = pos.State.SideToMove;
            var occupied = pos.Pieces();

            for (var pt = EPieceType.Knight; pt <= EPieceType.King; ++pt)
            {
                var pc     = pt.MakePiece(c);
                var pieces = pos.Pieces(pc);
                while (pieces)
                {
                    var from = pieces.Lsb();
                    pos.AddMoves(moves, pc, from, from.GetAttacks(pt, occupied) & targetSquares, flags);
                    BitBoards.ResetLsb(ref pieces);
                }
            }
        }
Beispiel #10
0
        private static void AddMoves(this IPosition pos, MoveList moves, Piece piece, Square from, BitBoard attacks, Emgf flags)
        {
            var target = pos.Pieces(~pos.State.SideToMove) & attacks;

            while (target)
            {
                var to = target.Lsb();
                pos.AddMove(moves, piece, from, to, PieceExtensions.EmptyPiece, flags, EMoveType.Capture);
                BitBoards.ResetLsb(ref target);
            }

            target = ~pos.Pieces() & attacks;
            while (target)
            {
                var to = target.Lsb();
                pos.AddMove(moves, piece, from, to, PieceExtensions.EmptyPiece, flags);
                BitBoards.ResetLsb(ref target);
            }
        }
Beispiel #11
0
        private static void GenerateCapturesAndPromotions(this IPosition pos, MoveList moves, Emgf flags)
        {
            var currentSide    = pos.State.SideToMove;
            var them           = ~currentSide;
            var occupiedByThem = pos.OccupiedBySide[them.Side];

            var(northEast, northWest) = currentSide.GetPawnAttackDirections();

            var pawns = pos.Pieces(EPieceType.Pawn, currentSide);

            pos.AddPawnMoves(moves, currentSide.PawnPush(pawns & currentSide.Rank7()) & ~pos.Pieces(), currentSide.PawnPushDistance(), EMoveType.Quiet, flags);
            pos.AddPawnMoves(moves, pawns.Shift(northEast) & occupiedByThem, currentSide.PawnWestAttackDistance(), EMoveType.Capture, flags);
            pos.AddPawnMoves(moves, pawns.Shift(northWest) & occupiedByThem, currentSide.PawnEastAttackDistance(), EMoveType.Capture, flags);

            if (pos.State.EnPassantSquare != ESquare.none)
            {
                pos.AddPawnMoves(moves, pawns.Shift(northEast) & pos.State.EnPassantSquare, currentSide.PawnWestAttackDistance(), EMoveType.Epcapture, flags);
                pos.AddPawnMoves(moves, pawns.Shift(northWest) & pos.State.EnPassantSquare, currentSide.PawnEastAttackDistance(), EMoveType.Epcapture, flags);
            }

            pos.AddMoves(moves, occupiedByThem, flags);
        }
Beispiel #12
0
        private void AddPawnMoves(MoveList moves, BitBoard targetSquares, Direction direction, EMoveType type)
        {
            if (targetSquares.Empty())
            {
                return;
            }

            var piece = EPieceType.Pawn.MakePiece(_position.State.SideToMove);

            foreach (var squareTo in targetSquares)
            {
                var squareFrom = squareTo - direction;
                if (!squareTo.IsPromotionRank())
                {
                    AddMove(moves, piece, squareFrom, squareTo, PieceExtensions.EmptyPiece, type);
                }
                else
                {
                    if (Flags.HasFlagFast(Emgf.Queenpromotion))
                    {
                        AddMove(moves, piece, squareFrom, squareTo,
                                EPieceType.Queen.MakePiece(_position.State.SideToMove),
                                type | EMoveType.Promotion);
                    }
                    else
                    {
                        for (var promotedPiece = EPieceType.Queen; promotedPiece >= EPieceType.Knight; promotedPiece--)
                        {
                            AddMove(moves, piece, squareFrom, squareTo,
                                    promotedPiece.MakePiece(_position.State.SideToMove),
                                    type | EMoveType.Promotion);
                        }
                    }
                }
            }
        }
Beispiel #13
0
        private void GenerateCapturesAndPromotions(MoveList moves)
        {
            var currentSide    = _position.State.SideToMove;
            var them           = ~currentSide;
            var occupiedByThem = _position.OccupiedBySide[them.Side];

            var(northEast, northWest) = currentSide == PlayerExtensions.White ? (EDirection.NorthEast, EDirection.NorthWest) : (EDirection.SouthEast, EDirection.SouthWest);

            AddMoves(moves, occupiedByThem);

            var pawns = _position.Pieces(EPieceType.Pawn, currentSide);

            AddPawnMoves(moves, currentSide.PawnPush(pawns & currentSide.Rank7()) & ~_position.Pieces(), currentSide.PawnPushDistance(), EMoveType.Quiet);
            AddPawnMoves(moves, pawns.Shift(northEast) & occupiedByThem, currentSide.PawnWestAttackDistance(), EMoveType.Capture);
            AddPawnMoves(moves, pawns.Shift(northWest) & occupiedByThem, currentSide.PawnEastAttackDistance(), EMoveType.Capture);

            if (_position.State.EnPassantSquare == ESquare.none)
            {
                return;
            }

            AddPawnMoves(moves, pawns.Shift(northEast) & _position.State.EnPassantSquare, currentSide.PawnWestAttackDistance(), EMoveType.Epcapture);
            AddPawnMoves(moves, pawns.Shift(northWest) & _position.State.EnPassantSquare, currentSide.PawnEastAttackDistance(), EMoveType.Epcapture);
        }
Beispiel #14
0
 private static void AddCastleMove(this IPosition pos, MoveList moves, Square from, Square to, Emgf flags)
 => pos.AddMove(moves, EPieceType.King.MakePiece(pos.State.SideToMove), from, to, PieceExtensions.EmptyPiece, flags, EMoveType.Castle);
Beispiel #15
0
 private void AddCastleMove(MoveList moves, Square from, Square to) => AddMove(moves, EPieceType.King.MakePiece(_position.State.SideToMove), from, to, PieceExtensions.EmptyPiece, EMoveType.Castle);