numberlink.level_setup

Shared level setup utilities for NumberLink environments.

This module provides helpers to resolve level sources, validate grids, build color palettes, and construct a LevelTemplate used by the environment creation code. Use build_level_template() as the entry point to produce reusable static data for a level before creating an environment with the numberlink package.

Note

Type information is provided in function signatures where available and is compatible with static analysis tools.

Module Contents

Classes

LevelTemplate

Precomputed static data for a NumberLink level configuration.

Functions

resolve_variant

Resolve the effective VariantConfig to use for level construction.

_metric

Compute grid distance between two coordinates.

_grid_ok

Validate that a grid contains valid endpoint pairs and path lengths.

_resolve_level_source

Determine the resolved grid, bridge coordinates, level identifier, and solution.

_validate_grid

Validate grid shape and return its height and width.

_generate_colors

Generate visually distinguishable RGB colors.

_build_palette

Build a mapping from letter identifiers to RGB colors and return numpy arrays for rendering.

build_level_template

Construct a LevelTemplate from configuration inputs.

API

class numberlink.level_setup.LevelTemplate[source]

Precomputed static data for a NumberLink level configuration.

Instances of this dataclass hold static, precomputed values required to create runtime environments. Fields are documented in the class body via type annotations. Construct instances using build_level_template() to ensure internal consistency.

variant: numberlink.config.VariantConfig = None[source]
reward_config: numberlink.config.RewardConfig = None[source]
render_config: numberlink.config.RenderConfig = None[source]
raw_grid: list[str] = None[source]
bridges_mask: numpy.typing.NDArray[bool] = None[source]
level_id: str | None = None[source]
letters: list[str] = None[source]
palette_map: dict[str, RGBInt] = None[source]
palette_arrays: list[numpy.typing.NDArray[numpy.uint8]] = None[source]
endpoints: numpy.typing.NDArray[numpy.int16] = None[source]
dirs: numpy.typing.NDArray[numpy.int8] = None[source]
num_dirs: int = None[source]
actions_per_color: int = None[source]
action_space_size: int = None[source]
cell_switch_action_space_size: int = None[source]
height: int = None[source]
width: int = None[source]
num_colors: int = None[source]
solution: list[list[Coord]] | None = None[source]
numberlink.level_setup.resolve_variant(variant: numberlink.config.VariantConfig | None, generator: numberlink.config.GeneratorConfig | None) numberlink.config.VariantConfig[source]

Resolve the effective VariantConfig to use for level construction.

If variant is provided, return it unchanged. If variant is None and generator is provided, derive values from the generator configuration while preserving explicit defaults from VariantConfig where applicable. The returned object is safe to use with build_level_template() and _resolve_level_source().

Parameters:
  • variant (VariantConfig or None) – Explicit variant configuration or None to derive one.

  • generator (GeneratorConfig or None) – Generator configuration used to derive variant fields when variant is None.

Returns:

Effective variant configuration.

Return type:

VariantConfig

numberlink.level_setup._metric(a: Coord, b: Coord, *, allow_diagonal: bool) int[source]

Compute grid distance between two coordinates.

Returns the Chebyshev distance when allow_diagonal is True and the Manhattan distance otherwise. This helper is internal and is used by _grid_ok() for validating path lengths between endpoints.

Parameters:
  • a (tuple[int, int]) – First coordinate given as a pair (row, col).

  • b (tuple[int, int]) – Second coordinate given as a pair (row, col).

  • allow_diagonal (bool) – Whether diagonal moves are allowed.

Returns:

Integer distance between the two coordinates.

Return type:

int

numberlink.level_setup._grid_ok(grid: collections.abc.Sequence[str], *, min_path_length: int, allow_diagonal: bool) bool[source]

Validate that a grid contains valid endpoint pairs and path lengths.

The function checks that every non-'.' character appears exactly twice. For each pair it verifies that the distance computed by _metric() meets or exceeds min_path_length. This routine is used by _resolve_level_source() when regenerating candidate levels from a GeneratorConfig.

Parameters:
  • grid (Sequence[str]) – Iterable of row strings representing the grid.

  • min_path_length (int) – Minimum allowed distance between matching endpoints.

  • allow_diagonal (bool) – Whether diagonal moves are counted by _metric().

Returns:

True when the grid is valid, otherwise False.

Return type:

bool

numberlink.level_setup._resolve_level_source(*, grid: collections.abc.Sequence[str] | None, level_id: str | None, variant: numberlink.config.VariantConfig, bridges: collections.abc.Iterable[Coord] | None, generator: numberlink.config.GeneratorConfig | None) tuple[list[str], set[Coord], str | None, list[list[Coord]] | None][source]

Determine the resolved grid, bridge coordinates, level identifier, and solution.

The resolution order is as follows:

  1. If generator is provided, attempt to generate candidate levels using generate_level() until a candidate satisfies _grid_ok() or a maximum number of attempts is reached.

  2. If level_id is provided, load the level from the LEVELS mapping.

  3. If grid is provided, use it directly.

  4. Fall back to the built-in level with id 'builtin_5x5_rw_4c'.

Caller-specified bridges override any bridges from generated or lookup sources. This helper is private and intended for use by build_level_template().

Parameters:
  • grid (Sequence[str] or None) – Optional explicit grid to use.

  • level_id (str or None) – Optional level identifier to load from LEVELS.

  • variant (VariantConfig) – Effective VariantConfig used when validating generated candidates.

  • bridges (Iterable[Coord] or None) – Optional iterable of bridge coordinates to force.

  • generator (GeneratorConfig or None) – Optional GeneratorConfig used to generate candidate grids.

Returns:

Tuple (resolved_grid, resolved_bridges, resolved_level_id, resolved_solution) where resolved_grid is a list of row strings, resolved_bridges is a set of coordinate tuples, resolved_level_id is either the selected level id or None when the grid came from a generator or explicit grid argument, and resolved_solution is the solution paths or None if unavailable.

Return type:

tuple[list[str], set[Coord], str or None, list[list[Coord]] or None]

numberlink.level_setup._validate_grid(grid: collections.abc.Sequence[str]) Coord[source]

Validate grid shape and return its height and width.

The function ensures the grid has at least one row and that all rows are the same width. It returns a tuple (height, width) for convenience. This helper is used by build_level_template() to validate input grids.

Parameters:

grid (Sequence[str]) – Sequence of row strings representing the grid.

Returns:

Pair of integers (height, width) describing the grid size.

Return type:

tuple[int, int]

Raises:

ValueError – If the grid is empty or rows have inconsistent lengths.

numberlink.level_setup._generate_colors(num_colors: int) list[RGBInt][source]

Generate visually distinguishable RGB colors.

The function returns a list of RGB triples where each triple is an (R, G, B) tuple with values in the range 0 to 255. For small values of num_colors a curated palette of high-contrast colors is returned. For larger values additional colors are generated by sampling HSV space and converting values to RGB.

Parameters:

num_colors (int) – Number of distinct colors required.

Returns:

List of RGB color tuples suitable for use in rendering.

Return type:

list[RGBInt]

numberlink.level_setup._build_palette(letters: list[str], palette: dict[str, RGBInt] | None) tuple[dict[str, RGBInt], list[numpy.typing.NDArray[numpy.uint8]]][source]

Build a mapping from letter identifiers to RGB colors and return numpy arrays for rendering.

The function first applies any user-provided mappings from palette. For letters that remain unassigned it generates visually distinguishable colors using _generate_colors(). The function also returns a list of numpy arrays ordered to match letters which is convenient for rendering code.

Parameters:
  • letters (list[str]) – Ordered list of letter identifiers present in the grid.

  • palette (dict[str, RGBInt] or None) – Optional mapping of letters to RGB triples to use as a base palette.

Returns:

Tuple of (palette_map, palette_arrays) where palette_map is a mapping from letter to RGB tuple and palette_arrays is a list of numpy.uint8 arrays in the same order as letters.

Return type:

tuple[dict[str, RGBInt], list[NDArray[numpy.uint8]]]

numberlink.level_setup.build_level_template(*, grid: collections.abc.Sequence[str] | None, level_id: str | None, variant: numberlink.config.VariantConfig | None, bridges: collections.abc.Iterable[Coord] | None, generator: numberlink.config.GeneratorConfig | None, reward_config: numberlink.config.RewardConfig | None, render_config: numberlink.config.RenderConfig | None, palette: dict[str, RGBInt] | None, solution: list[list[Coord]] | None = None) numberlink.level_setup.LevelTemplate[source]

Construct a LevelTemplate from configuration inputs.

This function resolves the effective variant using resolve_variant() and chooses a grid using _resolve_level_source(). It validates the resolved grid with _validate_grid(), builds a color palette with _build_palette(), and prepares arrays and masks required by runtime environments.

The returned LevelTemplate contains precomputed values such as endpoint coordinates, direction vectors, action space sizes, and color palettes. Use the returned object to construct environment instances.

Parameters:
  • grid (Sequence[str] or None) – Optional explicit grid to use. If None and generator is provided then levels are generated until a valid candidate is found.

  • level_id (str or None) – Optional key into the LEVELS mapping to select a predefined level.

  • variant (VariantConfig or None) – Optional VariantConfig to apply. If None the value is derived using resolve_variant() when generator is present.

  • bridges (Iterable[Coord] or None) – Optional iterable of bridge coordinates to force. If provided these override any bridges from generated or predefined levels.

  • generator (GeneratorConfig or None) – Optional GeneratorConfig used to generate levels when a grid is not supplied.

  • reward_config (RewardConfig or None) – Optional RewardConfig to attach to the template. When None a default RewardConfig is used.

  • render_config (RenderConfig or None) – Optional RenderConfig that controls rendering parameters. When None a default RenderConfig is used.

  • palette (dict[str, RGBInt] or None) – Optional mapping from letters to RGB triples. Missing letters are assigned generated colors by _build_palette().

Returns:

A fully populated LevelTemplate suitable for environment construction.

Return type:

LevelTemplate

Raises:

ValueError – If the resolved grid contains fewer than one color pair or a letter doesn’t appear twice.