egui-numberlink 0.2.0

A Numberlink puzzle game library for egui
Documentation

egui-numberlink

crates.io docs.rs deps.rs CI Rust version License Changelog Live demo

A self-contained Numberlink puzzle game library for egui.

Numberlink is the classic puzzle of connecting matching pairs of numbered endpoints on a grid with a path each, such that no two paths cross and every non-blocked cell of the board ends up covered by exactly one path. Some cells may be permanently blocked (walls no path may ever enter), which is what makes lower-density procedural puzzles genuinely harder rather than merely bigger.

Features

  • Pure game logic struct (NumberlinkGame) with no egui dependency — usable headlessly or with any renderer
  • Ready-to-use egui Widget (NumberlinkWidget) that renders an interactive, numbered board, including any blocked (wall) cells
  • Two ways to build a puzzle: NumberlinkGame::from_endpoints/from_endpoints_with_blocked (supply your own endpoints and, optionally, blocked cells) and NumberlinkGame::random (procedural, seeded, always has a solution by construction and prefers one verified unique within a bounded search)
  • Endpoints are always labeled with numbers, like the original Numberlink — color is an optional, fully customizable skin on top, not a replacement
  • NumberlinkWidget::colors lets embedding apps supply their own per-number palette; defaults to a colorblind-safe built-in one
  • Paths are drawn through the interior of each cell (connecting cell centers, turning at a cell's center), never along a cell's border
  • Click-and-drag drawing: either endpoint always works to start/redraw a number's path; dragging back over a path's own previous cell retracts it by one; dragging onto a different number's path is rejected; a plain click (no drag needed) also clears/starts a path
  • Undo/redo history, one entry per completed drag
  • Win banner drawn over the board once solved

Usage

Add the dependency:

[dependencies]
egui-numberlink = "0.1"

Then use it in your egui app:

use egui_numberlink::{NumberlinkGame, NumberlinkWidget};

// A curated puzzle from explicit endpoint pairs (number 0's endpoints, then
// number 1's, ...):
let mut game = NumberlinkGame::from_endpoints(
    3,
    3,
    vec![((0, 0), (2, 2)), ((0, 2), (1, 2))],
);

// Or a procedural puzzle, reproducible via a seed: 5 pairs on a 6x6 board,
// with 70% of cells playable (the rest permanently blocked). The generator
// prefers a layout it can verify has exactly one solution, within a bounded
// search.
let mut game = NumberlinkGame::random(6, 6, 5, 0.7, 42);

// Inside your egui update/UI closure:
ui.add(egui_numberlink::NumberlinkWidget::new(&mut game));

// Customize the per-number palette (must be at least one color; cycles if
// shorter than the puzzle's pair count):
use egui::Color32;
let colors = [Color32::RED, Color32::GREEN, Color32::BLUE];
ui.add(egui_numberlink::NumberlinkWidget::new(&mut game).colors(&colors));

After each frame you can inspect game.status to check for a win:

use egui_numberlink::GameStatus;

match game.status {
    GameStatus::Playing => {}
    GameStatus::Won => println!("Solved!"),
}

To start over on the same puzzle:

game.reset();

egui version compatibility

egui-numberlink egui
0.1 0.35

License

Licensed under either of MIT or Apache-2.0 at your option.