Visibility Functions#

In this section we describe the visibility function protocol, the visibility function registry, and how to write your own custom visibility functions.

The VisibilityFunction Protocol#

A visibility function is a generative function which represents a (stochastic) distribution over binary visibility grids. Using the typing standard library, the visibility function type is defined as a callable typing.Protocol which receives a Grid representing the agent’s restricted view, a Position representing the agent’s position in the grid, and an optional numpy.random.Generator, and returns a boolean numpy.ndarray indicating whether each tile is visible or not.

class VisibilityFunction(*args, **kwargs)[source]
__call__(grid, position, *, rng=None)[source]

Call self as a function.

Return type

ndarray

Note

A visibility function may accept additional arguments; this is possible so long as the extra arguments either have default values, or are binded to specific values later on, e.g., using functools.partial().

The Visibility Function Registry#

The visibility_functions module contains some pre-defined visibility functions and the visibility_function_registry, a dictionary-like object through which to register and retrieve visibility functions. Visibility functions are registered using the register() method, which can be used as a decorator (also see Custom Visibility Functions). As a dictionary, visibility_function_registry has a keys() method which returns the names of registered functions.

Custom Visibility Functions#

Custom visibility functions can be defined so long as they satisfy some basic rules; A custom visibility function:

Warning

The rng argument is used to control the source of randomness and allow for the environment to be seeded via set_seed(), which in turn guarantees the reproducibility of traces, runs, and experiments; if you wish to use external sources of randomness, you will have to manage them and their seeding yourself.

Practical Example 1#

Note

The examples shown here can be found in the examples/ folder.

In this example, we are going to write a rather questionable visibility function in which the visibility of every other tile is determined by a coin flip (ignoring tile transparency).

from typing import Optional

import numpy as np
import numpy.random as rnd

from gym_gridverse.envs.visibility_functions import visibility_function_registry
from gym_gridverse.geometry import Position
from gym_gridverse.grid import Grid
from gym_gridverse.rng import get_gv_rng_if_none


@visibility_function_registry.register
def coinflip(
    grid: Grid,
    position: Position,
    *,
    rng: Optional[rnd.Generator] = None,
) -> np.ndarray:
    """randomly determines tile visibility"""

    rng = get_gv_rng_if_none(rng)  # necessary to use rng object!

    # sample a random binary visibility matrix
    visibility = rng.integers(2, size=grid.shape.as_tuple).astype(bool)
    # the agent tile should always be visible regardless
    visibility[position.y, position.x] = True

    return visibility

Practical Example 2#

In this example, we are going to write a visibility function in which the agent’s field of view expands like a 90° angle cone (ignoring tile transparency).

from typing import Optional

import numpy as np
import numpy.random as rnd

from gym_gridverse.envs.visibility_functions import visibility_function_registry
from gym_gridverse.geometry import Position
from gym_gridverse.grid import Grid


@visibility_function_registry.register
def conic(
    grid: Grid,
    position: Position,
    *,
    rng: Optional[rnd.Generator] = None,
) -> np.ndarray:
    """cone-shaped visibility, passes through all objects"""

    # initialize visibility matrix to False
    visibility = np.zeros(grid.shape.as_tuple, dtype=bool)

    # for every y-coordinate in front of the agent
    for y in range(position.y, -1, -1):
        dy = position.y - y

        x_from = position.x - dy
        x_to = position.x + dy

        # for every x-coordinate within the cone range
        for x in range(x_from, x_to + 1):
            # tile in the cone is visible
            visibility[y, x] = True

    return visibility