numberlink.viewer

Interactive pygame viewer for numberlink.env.NumberLinkRGBEnv.

Provide an interactive display and input handling for a running numberlink.env.NumberLinkRGBEnv instance. Open a pygame window that renders environment state and accepts keyboard input to manipulate the environment in either path editing mode or cell switching mode.

The primary entry point is numberlink.viewer.NumberLinkViewer.

Module Contents

Classes

NumberLinkViewer

Interactive viewer for a numberlink.env.NumberLinkRGBEnv instance.

Functions

_detect_notebook_environment

Return the active notebook environment identifier or "none" when not in a notebook.

_show_notebook_missing_message

Surface a user friendly notice when notebook dependencies are missing.

_try_launch_notebook_viewer

Launch the notebook viewer when running in a notebook environment.

Data

API

numberlink.viewer.GLYPH_CACHE_MAX: int = 512[source]
class numberlink.viewer.NumberLinkViewer(env: numberlink.env.NumberLinkRGBEnv | gymnasium.Env[numpy.typing.NDArray[numpy.uint8], numpy.int64], cell_size: int = 48)[source]

Interactive viewer for a numberlink.env.NumberLinkRGBEnv instance.

Forward keyboard input to the environment. Support two interaction modes. In path editing mode, arrow keys and optional diagonal keys extend or retract a selected path head by sending directional actions to numberlink.env.NumberLinkRGBEnv.step(). In cell switching mode, a cursor moves across the board and the highlighted cell can be painted using an action created by numberlink.env.NumberLinkRGBEnv.encode_cell_switching_action().

Controls

Path mode

  • Move the selected head with arrow or diagonal keys.

  • Switch selected head with the left and right bracket keys.

  • Cycle the active color with Tab and Shift+Tab.

  • Backtrack the active head by one step using _backtrack_selected().

Cell mode

Parameters:
Variables:
  • env (numberlink.env.NumberLinkRGBEnv) – The unwrapped numberlink.env.NumberLinkRGBEnv instance used for rendering and action dispatch.

  • cell (int) – Pixel size of each rendered cell.

  • sel_color (int) – Index of the currently selected color.

  • sel_head (int) – Index of the currently selected head for the active color.

  • switch_mode (bool) – Whether the viewer is operating in cell switching mode.

  • cursor (list[int]) – Row and column of the cursor when in cell switching mode.

  • window (pygame.Surface or None) – The active pygame window Surface or None if no window is open.

  • pygame (module or None) – Reference to the loaded pygame module after initialization.

See also

pygame for window and input primitives used by the viewer.

Note

The viewer accesses internal environment attributes, e.g., numberlink.env.NumberLinkRGBEnv._endpoint_mask and numberlink.env.NumberLinkRGBEnv._palette_stack for efficient rendering.

Initialization

Initialize the viewer and internal state for a given environment.

Unwrap env when it is a wrapped environment, initialize the selected color and head indices, and position the cursor when in cell-switching mode.

Parameters:
  • env (numberlink.env.NumberLinkRGBEnv or wrapper) – The environment to render and control. If env is wrapped, the underlying environment is obtained from env.unwrapped.

  • cell_size (int, optional) – Pixel size of each rendered cell. Defaults to 48.

Raises:

ValueError – If cell_size is less than or equal to zero.

_glyph_cache: collections.OrderedDict[tuple[str, int, int, RGBInt, RGBInt | None], pygame.Surface] = None[source]
HELP_AUTO_HIDE_MS: int = 4000[source]
_initialize_pygame() None[source]

Initialize pygame once per viewer instance and set the application icon.

_shutdown_pygame() None[source]

Shut down pygame when the viewer loop exits.

loop() None[source]

Run the interactive pygame event loop.

Load pygame on first use, create a window sized to the environment grid, and process input events until the user exits.

_handle_path_key(key: int) None[source]

Handle a single key event while in path-editing mode.

Map navigation and control keys to environment actions. Direction keys are translated to a direction index with _direction_index() and the resulting action is dispatched via _attempt_path_step() which calls numberlink.env.NumberLinkRGBEnv.step().

Parameters:

key (int) – Numeric key code from pygame.

_handle_cell_switch_key(key: int) None[source]

Handle a single key event while in cell-switching mode.

Update the cursor location, change the selected color, or paint the highlighted cell. Painting uses numberlink.env.NumberLinkRGBEnv.encode_cell_switching_action() to create an action which is forwarded to numberlink.env.NumberLinkRGBEnv.step().

Parameters:

key (int) – Numeric key code from pygame.

_toggle_help_overlay() None[source]

Toggle the help overlay and reset the auto-hide timer.

_reset_environment(seed: int | None = None) None[source]

Reset the environment and refresh viewer state.

_generate_new_level() None[source]

Generate a new level when a generator configuration is available.

_toggle_replay() None[source]

Start replay when idle and toggle play or pause when already initialized.

When the replay state is idle call _start_replay(). When the replay state is playing switch to paused. When the replay state is paused resume playback and update the timing cursor.

_start_replay() None[source]

Begin solution replay from the level’s start state if a solution is available.

_stop_replay(*, restore: bool) None[source]

Stop any active replay and optionally restore the pre-replay environment state.

_advance_replay_if_needed() None[source]

Advance the solution replay based on the configured interval.

_snapshot_state() numberlink.types.Snapshot[source]

Capture a deep copy of environment and viewer state for later restoration.

_restore_state(snap: numberlink.types.Snapshot) None[source]

Restore environment and viewer state from a snapshot obtained via _snapshot_state().

_reset_view_state() None[source]

Synchronize viewer selections and cursor with the environment.

_can_generate_new_level() bool[source]

Return whether the viewer can request a new procedurally generated level.

_update_help_timer() None[source]

Hide the help overlay automatically after the configured timeout.

_cycle_color(delta: int) None[source]

Cycle the currently selected color by delta.

Wrap the selection using the environment’s num_colors attribute.

Parameters:

delta (int) – Signed amount to change the selected color index.

_direction_index(dr: int, dc: int) int | None[source]

Return the index of the direction matching the delta (dr, dc).

Search numberlink.env.NumberLinkRGBEnv._dirs for an entry whose row and column deltas match dr and dc. Return the matching index or None when no match exists.

Parameters:
  • dr (int) – Row delta.

  • dc (int) – Column delta.

Returns:

Direction index or None.

Return type:

int or None

_attempt_path_step(dr: int, dc: int) None[source]

Attempt to move the selected head in direction (dr, dc).

Convert the direction to an index using _direction_index(). If a valid index exists compute the action index for the selected color and head and dispatch it via numberlink.env.NumberLinkRGBEnv.step().

Parameters:
  • dr (int) – Row delta for the attempted step.

  • dc (int) – Column delta for the attempted step.

_backtrack_selected() None[source]

Backtrack the active head one step when possible.

If the active head has at least two entries on its stack, compute the reverse step to return the head to the previous cell and dispatch the corresponding action using numberlink.env.NumberLinkRGBEnv.step().

_move_cursor(dr: int, dc: int) None[source]

Move the cursor in cell-switching mode by (dr, dc).

Clamp the cursor coordinates to the valid grid range.

Parameters:
  • dr (int) – Row delta.

  • dc (int) – Column delta.

_paint_selected_cell() None[source]

Paint the highlighted cell with the currently selected color.

Do nothing for endpoint cells. For other cells, construct the action using numberlink.env.NumberLinkRGBEnv.encode_cell_switching_action() and dispatch it to numberlink.env.NumberLinkRGBEnv.step().

_handle_mouse_down(pos: Coord) None[source]

Handle mouse button down event.

Convert pixel position to grid coordinates and initiate dragging.

Parameters:

pos (Coord) – Mouse position in pixels as (x, y).

_handle_mouse_motion(pos: Coord) None[source]

Handle mouse motion during drag.

Convert pixel position to grid coordinates and perform action if cell changed.

Parameters:

pos (Coord) – Mouse position in pixels as (x, y).

_select_focus_for_cell(row: int, col: int) bool[source]

Adjust the selected color and head based on the cell at (row, col).

Prioritize exact matches against endpoints and current head positions. When the cell belongs to a path segment, pick the head whose stack approaches the cell most recently. Bridge cells prefer the lane that matches the currently selected color before falling back to any occupied lane.

Parameters:
  • row (int) – Cell row index.

  • col (int) – Cell column index.

Returns:

True when the selection changed, otherwise False.

Return type:

bool

_handle_mouse_cell(row: int, col: int) None[source]

Handle mouse interaction in path mode.

Determine the appropriate action based on current head position and target cell.

Parameters:
  • row (int) – Target row.

  • col (int) – Target column.

_ensure_color_ready_for_head() None[source]

Reset the currently selected color when switching starting endpoints mid-path.

_draw() None[source]

Render the environment state into the pygame surface.

Request an RGB image from numberlink.env.NumberLinkRGBEnv._render_rgb() and draw a grid of colored cells. Draw a highlighted border for the cursor when in cell mode or for the active head when in path mode. Optionally draw a help overlay with key bindings.

static _metrics_for_scale(scale: int, *, line_spacing: int) RGBInt[source]

Return character cell width, char height, and line spacing for a given scale.

This reproduces the simple metrics logic previously defined as nested helpers in the viewer methods. The return order matches the previous (cw, ch, ls).

static _wrap_lines(lines: list[str], cw: int, max_w: int, *, padding: int) list[str][source]

Wrap lines to fit within max_w using character cell width cw and panel padding.

This implements the same wrapping algorithm used in the nested helpers. The padding parameter is required to ensure identical max_chars computation.

_draw_help_overlay() None[source]

Draw a help overlay showing key bindings on the game window.

_draw_status_overlay(solved: bool, deadlocked: bool, truncated: bool) None[source]

Draw an end-of-game overlay summarizing the current status and available actions.

_draw_text(text: str, topleft: Coord, color: RGBInt, scale: int = 3, outline_color: RGBInt | None = (0, 0, 0), outline_thickness: int = 1) int[source]

Draw text at topleft (x,y) onto self.window using the bitmap font.

Returns the width in pixels of the rendered string.

_draw_text_centered(text: str, center: Coord, color: RGBInt, scale: int = 3, outline_color: RGBInt | None = (0, 0, 0), outline_thickness: int = 1) None[source]
_get_glyph_surface(ch: str, scale: int, outline_thickness: int, fg: RGBInt, outline: RGBInt | None) pygame.Surface[source]

Return a cached pygame Surface for a glyph rendered at the given parameters.

The surface is tightly sized to the glyph’s bounding box.

_draw_replay_overlay() None[source]

Draw a small overlay indicating replay status or transient info messages.

numberlink.viewer._detect_notebook_environment() str[source]

Return the active notebook environment identifier or "none" when not in a notebook.

numberlink.viewer._show_notebook_missing_message(env_label: str, detail: str | None = None) None[source]

Surface a user friendly notice when notebook dependencies are missing.

numberlink.viewer._try_launch_notebook_viewer(base_viewer: numberlink.viewer.NumberLinkViewer) bool[source]

Launch the notebook viewer when running in a notebook environment.