Пример #1
0
    def compute_fov(self,
                    x,
                    y,
                    fov='PERMISSIVE',
                    radius=None,
                    light_walls=True,
                    sphere=True,
                    cumulative=False):
        """Compute the field-of-view of this Map and return an iterator of the
        points touched.

        @type x: int
        @type y: int

        @param x: x center of the field-of-view
        @param y: y center of the field-of-view
        @type fov: string
        @param fov: The type of field-of-view to be used.  Available types are:

                    'BASIC', 'DIAMOND', 'SHADOW', 'RESTRICTIVE', 'PERMISSIVE',
                    'PERMISSIVE0', 'PERMISSIVE1', ..., 'PERMISSIVE8'
        @type radius: int
        @param radius: Raduis of the field-of-view.
        @type light_walls: boolean
        @param light_walls: Include or exclude wall tiles in the field-of-view.
        @type sphere: boolean
        @param sphere: True for a spherical field-of-view.
                       False for a square one.
        @type cumulative: boolean
        @param cumulative:

        @rtype: iter((x, y), ...)
        @return: An iterator of (x, y) points of tiles touched by the
                 field-of-view.

                 Unexpected behaviour can happen if you modify the Map while
                 using the iterator.

                 You can use the Map's fov attribute as an alternative to this
                 iterator.
        """
        # refresh cdata
        _lib.TDL_map_data_from_buffer(self._map_cdata, self._array_cdata_flat)
        if radius is None:  # infinite radius
            radius = max(self.width, self.height)
        _lib.TCOD_map_compute_fov(self._map_cdata, x, y, radius, light_walls,
                                  _get_fov_type(fov))
        _lib.TDL_map_fov_to_buffer(self._map_cdata, self._array_cdata_flat,
                                   cumulative)

        def iterate_fov():
            _array_cdata = self._array_cdata
            for y in range(self.height):
                for x in range(self.width):
                    if (_array_cdata[y][x] & 4):
                        yield (x, y)

        return iterate_fov()
Пример #2
0
    def compute_fov(self,
                    x,
                    y,
                    fov='PERMISSIVE',
                    radius=None,
                    light_walls=True,
                    sphere=True,
                    cumulative=False):
        """Compute the field-of-view of this Map and return an iterator of the
        points touched.

        Args:
            x (int): Point of view, x-coordinate.
            y (int): Point of view, y-coordinate.
            fov (Text): The type of field-of-view to be used.

                Available types are:
                'BASIC', 'DIAMOND', 'SHADOW', 'RESTRICTIVE', 'PERMISSIVE',
                'PERMISSIVE0', 'PERMISSIVE1', ..., 'PERMISSIVE8'
            radius (Optional[int]): Maximum view distance from the point of
                view.

                A value of 0 will give an infinite distance.
            light_walls (bool): Light up walls, or only the floor.
            sphere (bool): If True the lit area will be round instead of
                square.
            cumulative (bool): If True the lit cells will accumulate instead
                of being cleared before the computation.

        Returns:
            Iterator[Tuple[int, int]]: An iterator of (x, y) points of tiles
                touched by the field-of-view.
        """
        # refresh cdata
        if radius is None:  # infinite radius
            radius = 0
        if cumulative:
            fov_copy = self.fov.copy()
        lib.TCOD_map_compute_fov(self.map_c, x, y, radius, light_walls,
                                 _get_fov_type(fov))
        if cumulative:
            self.fov[:] |= fov_copy
        return zip(*np.where(self.fov))
Пример #3
0
def quick_fov(x,
              y,
              callback,
              fov='PERMISSIVE',
              radius=7.5,
              lightWalls=True,
              sphere=True):
    """All field-of-view functionality in one call.

    Before using this call be sure to make a function, lambda, or method that takes 2
    positional parameters and returns True if light can pass through the tile or False
    for light-blocking tiles and for indexes that are out of bounds of the
    dungeon.

    This function is 'quick' as in no hassle but can quickly become a very slow
    function call if a large radius is used or the callback provided itself
    isn't optimized.

    Always check if the index is in bounds both in the callback and in the
    returned values.  These values can go into the negatives as well.

    Args:
        x (int): x center of the field-of-view
        y (int): y center of the field-of-view
        callback (Callable[[int, int], bool]):

            This should be a function that takes two positional arguments x,y
            and returns True if the tile at that position is transparent
            or False if the tile blocks light or is out of bounds.
        fov (Text): The type of field-of-view to be used.

            Available types are:
            'BASIC', 'DIAMOND', 'SHADOW', 'RESTRICTIVE', 'PERMISSIVE',
            'PERMISSIVE0', 'PERMISSIVE1', ..., 'PERMISSIVE8'
        radius (float) Radius of the field-of-view.

            When sphere is True a floating point can be used to fine-tune
            the range.  Otherwise the radius is just rounded up.

            Be careful as a large radius has an exponential affect on
            how long this function takes.
        lightWalls (bool): Include or exclude wall tiles in the field-of-view.
        sphere (bool): True for a spherical field-of-view.
            False for a square one.

    Returns:
        Set[Tuple[int, int]]: A set of (x, y) points that are within the
            field-of-view.
    """
    trueRadius = radius
    radius = int(_math.ceil(radius))
    mapSize = radius * 2 + 1
    fov = _get_fov_type(fov)

    setProp = _lib.TCOD_map_set_properties  # make local
    inFOV = _lib.TCOD_map_is_in_fov

    tcodMap = _lib.TCOD_map_new(mapSize, mapSize)
    try:
        # pass no.1, write callback data to the tcodMap
        for x_, y_ in _itertools.product(range(mapSize), range(mapSize)):
            pos = (x_ + x - radius, y_ + y - radius)
            transparent = bool(callback(*pos))
            setProp(tcodMap, x_, y_, transparent, False)

        # pass no.2, compute fov and build a list of points
        _lib.TCOD_map_compute_fov(tcodMap, radius, radius, radius, lightWalls,
                                  fov)
        touched = set()  # points touched by field of view
        for x_, y_ in _itertools.product(range(mapSize), range(mapSize)):
            if sphere and _math.hypot(x_ - radius, y_ - radius) > trueRadius:
                continue
            if inFOV(tcodMap, x_, y_):
                touched.add((x_ + x - radius, y_ + y - radius))
    finally:
        _lib.TCOD_map_delete(tcodMap)
    return touched