HamiltonianGenerator
Static public entry point. Namespace SimpleHamiltonian.
| Member | Returns | Notes |
|---|---|---|
Generate(settings) | PuzzleData | Instant, always solvable. Solution count stays Unknown. |
GenerateVerified(settings) | PuzzleData | Solvable + uniqueness-checked; hunts for a unique board in Fixed + RequireUnique. Stamps a 1–5 Difficulty, and rolls toward settings.TargetDifficulty when it's set. |
GenerateVerifiedAsync(settings) | Task<PuzzleData> | Background thread; await resumes on the main thread. |
GenerateBatch(settings, count) | List<PuzzleData> | A pack of count verified puzzles, deterministic seeds. |
GenerateBatchAsync(settings, count, progress) | Task<List<PuzzleData>> | Background batch; IProgress<int> reports 1..count. |
HamiltonianRules
Static, stateless play rules. Feed your path; it tells you what's legal and whether you've won.
| Member | Returns | Notes |
|---|---|---|
IsLegalStep(puzzle, path, next, out reason) | bool | Walkable, no revisit, adjacent (topology-aware), Fixed-mode start rule. |
IsSolved(puzzle, path, out reason) | bool | Covers every cell; Fixed also checks start/end + checkpoint order. |
CheckpointsInOrder(puzzle, path) | bool | Checkpoints visited so far are in numbered order. |
Validate(puzzle) | ValidationResult | Is the puzzle data well-formed (importers / editors). |
Each predicate has a no-reason overload.
Solver
SolutionVerdict v = Solver.Verify(puzzle, nodeBudget: 400_000, budgetSeconds: 2.5);
// v.Count -> SolutionCount.One / Multiple / Unknown
// v.Verified -> proven (not cut off by a budget)
// v.IsUnique -> Count == One && Verified
// v.Found -> lower bound on solutions found (capped)
// v.Nodes -> solver search nodes expanded (the difficulty signal)
Topology-aware (square & hex), bounded by node and wall-clock budgets — a call can never hang.
Difficulty
Rate a verdict 1 (easiest) .. 5 (hardest) from the solver's search effort. Only verified-unique boards are rated; anything else returns 0.
int stars = Difficulty.Stars(v); // 1..5, or 0 if not verified-unique
Bigger, more open boards score higher; heavy constraints (many checkpoints, sparse
coverage) shrink the search and score lower. GenerateVerified stamps this on
PuzzleData.Difficulty for you.
PuzzleData
The serializable puzzle unit.
| Field | Type | Meaning |
|---|---|---|
Width / Height | int | Grid size. |
Mode / Shape | enum | Free/Fixed · Square/Hex. |
Seed | string | The seed that produced it. |
Start / End | Cell | Endpoints (Fixed). |
Walkable / Obstacles | List<Cell> | Cells the path may enter / blocked cells. |
Checkpoints | List<Cell> | Ordered; index 0 is checkpoint "1". |
Solution | List<Cell> | The intended cover-all path. |
IsUnique / SolutionCount | bool / enum | The solver's verdict. |
Difficulty | int | Rating 1–5 from the solver's search effort; 0 = unrated (not verified-unique). |
Plus computed helpers: CellCount, WalkableCount, ObstacleCount, SolutionLength, CheckpointCount, HasCheckpoints.
Enums & structs
| Type | Values / shape |
|---|---|
GridShape | Square · Hex |
PuzzleMode | Free · Fixed |
SolutionCount | Unknown · One · Multiple |
Cell | int X, Y grid coordinate |
SolutionVerdict | Count, Verified, Found, Nodes, IsUnique |
ValidationResult | IsValid, Errors, Warnings |
ScriptableObjects
| Type | Purpose |
|---|---|
HamiltonianPuzzle | One PuzzleData as an asset. .Puzzle reads it. |
HamiltonianPuzzlePack | Many puzzles (a level set). .Puzzles reads them. |
IPuzzleProvider | Implemented by both — AppendTo(list); a single list can mix packs and puzzles. |
Create assets via the Puzzle Generator (Save ▾ — current / pack / pack unique only), or in code with
PuzzleAssets.CreatePuzzle / CreatePack.
Using them in your own game
Assign a pack or puzzle in the inspector, then read the PuzzleData in code:
using SimpleHamiltonian;
public sealed class MyGame : MonoBehaviour
{
[SerializeField] HamiltonianPuzzlePack pack; // drag a pack asset here
[SerializeField] HamiltonianPuzzle single; // or a single puzzle
void Start()
{
// every puzzle in the pack
foreach (PuzzleData p in pack.Puzzles)
LoadLevel(p);
// by index / count
PuzzleData first = pack.Get(0);
int total = pack.Count;
// a single puzzle asset
PuzzleData one = single.Puzzle;
}
void LoadLevel(PuzzleData p) { /* render it, drive moves via HamiltonianRules */ }
}
Helpers & advanced
Cell
| Member | Notes |
|---|---|
ManhattanTo(other) | Grid (Manhattan) distance between two cells. |
IsAdjacentTo(other) | Orthogonal (square) adjacency. For hex, use a topology (below). |
Topology — for custom hex movement / layout
Building your own hex input or renderer? Use the topology instead of hard-coding neighbors — it's square/hex correct:
| Member | Notes |
|---|---|
Topology.For(shape) | An IGridTopology for Square or Hex. |
Topology.MaxNeighbors | 6 — size your neighbor buffer with this constant. |
IGridTopology.Neighbors(cell, w, h, buffer) | Fills buffer with in-bounds neighbors; returns the count. |
IGridTopology.AreAdjacent(a, b) | Adjacency under that topology. |
Other convenience
| Member | Notes |
|---|---|
GenerationSettings.Clone() / Clamp() | Field-for-field copy / coerce to valid ranges (returns this). |
ValidationResult.Summary | "N error(s), M warning(s)". |
HamiltonianPuzzle.Label / Mode / Width / Height / IsUnique / SolutionCount / Difficulty / Seed | Read puzzle facts without touching .Puzzle (handy for list UI). |
HamiltonianPuzzlePack.PackName | The pack's display name. |
Generator.Generate (unverified — prefer HamiltonianGenerator),
Solver.CountSolutions (the raw counter behind Verify),
Rng (deterministic RNG: NextInt / NextDouble / Shuffle),
and Grid / ObstacleMetrics (internal generation helpers). The square-only
Grid.Neighbors is legacy — use IGridTopology.Neighbors so hex works too.