def add_ball(self, balls=1, source_name=None, source_device=None,
                 player_controlled=False, reset=False):
        """Adds live ball(s) to the playfield.

        Args:
            balls: Integer of the number of balls you'd like to add.
            source_name: Optional string name of the ball device you'd like to
                add the ball(s) from.
            source_device: Optional ball device object you'd like to add the
                ball(s) from.
            player_controlled: Boolean which specifies whether this event is
                player controlled. (See not below for details)
            reset: Boolean which controls whether the source device should
                reset its state to idle

        Returns:
            True if it's able to process the add_ball() request, False if it
            cannot.

        Both source_name and source_device args are included to give you two
        options for specifying the source of the ball(s) to be added. You don't
        need to supply both. (it's an "either/or" thing.) Both of these args are
        optional, so if you don't supply them then MPF will look for a device
        tagged with 'ball_add_live'. If you don't provide a source and you don't
        have a device with the 'ball_add_live' tag, MPF will quit.

        This method does *not* increase the game controller's count of the
        number of balls in play. So if you want to add balls (like in a
        multiball scenario), you need to call this method along with
        ``self.machine.game.add_balls_in_play()``.)

        MPF tracks the number of balls in play separately from the actual balls
        on the playfield because there are numerous situations where the two
        counts are not the same. For example, if a ball is in a VUK while some
        animation is playing, there are no balls on the playfield but still one
        ball in play, or if the player has a two-ball multiball and they shoot
        them both into locks, there are still two balls in play even though
        there are no balls on the playfield. The opposite can also be true,
        like when the player tilts then there are still balls on the playfield
        but no balls in play.

        Explanation of the player_controlled parameter:

        Set player_controlled to True to indicate that MPF should wait for the
        player to eject the ball from the source_device rather than firing a
        coil. The logic works like this:

        If the source_device does not have an eject_coil defined, then it's
        assumed that player_controlled is the only option. (e.g. this is a
        traditional plunger.) If the source_device does have an eject_coil
        defined, then there are two ways the eject could work. (1) there could
        be a "launch" button of some kind that's used to fire the eject coil,
        or (2) the device could be the auto/manual combo style where there's a
        mechanical plunger but also a coil which can eject the ball.

        If player_controlled is true and the device has an eject_coil, MPF will
        look for the player_controlled_eject_tag and eject the ball when a
        switch with that tag is activated.

        If there is no player_controlled_eject_tag, MPF assumes it's a manual
        plunger and will wait for the ball to disappear from the device based
        on the device's ball count decreasing.

        """
        if balls < 1:
            self.log.error("Received request to add %s balls, which doesn't "
                           "make sense. Not adding any balls...")
            return False

        # Figure out which device we'll get a ball from

        if source_device:
            pass
        elif source_name and source_name in self.machine.ball_devices:
            source_device = self.machine.ball_devices[source_name]
        else:
            for device in self.machine.ball_devices.items_tagged('ball_add_live'):
                if self in device.config['eject_targets']:
                    source_device = device
                    break

        if not source_device:
            self.log.critical("Received request to add a ball to the playfield"
                              ", but no source device was passed and no ball "
                              "devices are tagged with 'ball_add_live'. Cannot"
                              " add a ball.")
            return False

        if reset:
            source_device.stop()

        self.log.debug("Received request to add %s ball(s). Source device: %s."
                       " Player-controlled: %s", balls,
                       source_device.name, player_controlled)

        if player_controlled:
            source_device.setup_player_controlled_eject(balls=balls,
                                                        target=self)
        else:
            source_device.eject(balls=balls, target=self, get_ball=True)

        return True
dataset/ETHPy150Open missionpinball/mpf/mpf/devices/playfield.py/Playfield.add_ball/original