View: Multi-Page Single Page

Simple States

Switch & state logic puzzles — generated, verified, and fully analyzed.

Complete documentation, on one page.

v1.0 · by Living Failure

Overview

Simple States generates switch-and-state logic puzzles in four modes. Classic: every switch toggles (XORs) a set of states — press the right set, order never matters; the deduction lives in the states that several switches share. Ordered: switches are gated behind board states, so they only fire in sequence — with decoys, and optional traps that turn a state back off when pressed (wrong tries cost work; every trapped board is verified deadlock-free). Lights Out: grids up to 56 cells where every cell is a light and a button; pressing flips it plus its orthogonal neighbours, every board solvable by construction — with pattern goals: all lit, blackout, or a painted target shape. Trilight: the mod-3 grid — cells cycle off → dim → bright, a press bumps a cell and its neighbours one step, and a cell can need two presses.

Every board is solved exactly — solution count, the shortest solution (the board's par), all solutions, switch roles (required / optional / dummy), rule diagnostics, and a 1–5★ difficulty — then stored as a plain ScriptableObject. Deterministic from a seed. Pure C# core with no package dependencies; Built-in, URP, and HDRP.

Requirements

  • Unity 6000.3+ (developed on 6000.3.8f1).
  • Core (generation / solving / analysis / storage): no package dependencies, any render pipeline.
  • Demo & editor tooling: Input System and TextMeshPro (Unity prompts to import TMP essentials). The demo board is runtime primitives tinted via MaterialPropertyBlock — no material conversion on any pipeline.
  • Core, Demo, and Editor are separate assembly definitions.

Quick start

No code: Window ▸ Living Failure ▸ Simple States ▸ Puzzle Generator → pick a mode (Classic / Ordered / Lights Out / Trilight), set states/switches or the grid, pick a preset, GenerateSave ▸ Current or Save ▸ Pack. Open Scenes/DemoScene, assign packs on the StatesDemo component, press Play. The demo's pack slots take packs, not single-puzzle assets — a pack of one is fine.

using SimpleStates;

var settings = new GenerationSettings {
    Mode = PuzzleMode.Classic,
    StateCount = 6, SwitchCount = 6,
    SolutionStyle = SolutionStyle.Single,
    DummyPolicy = DummyPolicy.Allow,
    MinSolutionSize = 2, MaxSolutionSize = 4,
    Seed = "level-42",
};
StatesPuzzle puzzle = ClassicGenerator.GenerateVerified(settings);

// Ordered chains with traps (modes: Classic / Ordered / Lights Out / Trilight):
var ordered = new GenerationSettings {
    Mode = PuzzleMode.Ordered, StateCount = 8, SwitchCount = 8,
    SolutionStyle = SolutionStyle.Few, DummyPolicy = DummyPolicy.Require,
    TrapPolicy = TrapPolicy.Require, MinSolutionSize = 4, MaxSolutionSize = 6,
    MaxAttempts = 800,
};
StatesPuzzle chain = OrderedGenerator.GenerateVerified(ordered);

// Lights Out (a grid implies the mode; goals: AllLit / AllDark / Pattern):
var lights = new GenerationSettings {
    GridWidth = 5, GridHeight = 5, MinSolutionSize = 6, MaxSolutionSize = 14,
    GoalMode = LightsOutGoal.Pattern,
    GoalPattern = 0b00100_01110_11111_01110_00100,   // a diamond
};
StatesPuzzle grid = LightsOutGenerator.GenerateVerified(lights);

// Trilight (mod-3) - same recipe, three states:
StatesPuzzle tri = Mod3Generator.GenerateVerified(new GenerationSettings {
    GridWidth = 5, GridHeight = 5, MinSolutionSize = 6, MaxSolutionSize = 14,
});

Generating

The Generator window shows settings on the left (they adapt to the mode) and the result set with its full analysis on the right: verdict, best solution, per-press path preview, readable rules, switch roles, all solutions, diagnostics, the rule matrix (or the board grid for Lights Out), and the generation report. Batches accumulate behind a progress bar; Only unique filters the browser; presets, Auto tune, and guardrail warnings cover the common recipes.

On grid boards the Board section is interactive: click cells and they respond as they would in play, so you can watch a solution resolve instead of reading a list of marked cells. A solid dot is a cell still to press, a hollow ring one already pressed, and a badge (Trilight) the presses still needed. Cells are labelled by column letter + row number (B1, C4), matching headers drawn on the board. Where a board has several answers a picker steps through them, shortest first; the status reads SOLVED whenever the board matches the goal, including by a route of your own. Nothing here edits the asset.

Grid solution counts are fixed by the grid SIZE, not by the board — a 5×5 Lights Out always has 4 answers, a 4×4 always 16, most sizes exactly 1. The generator says which before you press Generate, and suggests sizes that give a unique board.

  • Classic — solution style (Single / Few / Many), dummy policy, rule shape (states per switch, required overlap), degenerate-rule filters, exact shortest-solution target.
  • Ordered — gated chains solved by BFS; decoys hide the chain; the trap policy adds decoys that turn states back off, verified deadlock-free (the goal stays reachable from every reachable state).
  • Lights Out — the start is scrambled backwards from the solved board (always solvable); the GF(2) solver finds the true shortest, matched to the window or an exact target.
  • Pattern goals (grid modes) — All Lit, All Dark (blackout), or a click-painted Pattern; any target is solvable by construction and stamped into the saved data.
  • Trilight — three states over the same recipe; exact ℤ₃ math (counts are 3^nullity), scramble presses hit cells once or twice, solutions list a cell twice when it needs two presses.

Saved assets re-check with inspector Verify (single / all) and regenerate with Re-roll (current / every multiple-solution entry) — all undoable. Every board gets a challenge score mapped to 1–5★ (Lights Out is rated on press count).

GuardrailsSingle solution + no dummies forces the solution to use every switch; requiring traps needs dummies allowed (traps are decoys). The window warns about both.

Settings (GenerationSettings)

FieldRangeMeaning
ModeClassic / OrderedThe puzzle type. A grid (below) implies Lights Out.
StateCount / SwitchCount3–8States to open / switches to press.
GridWidth / GridHeightup to 8 per side (≤ 56 cells)Grid size; both > 0 switches to a grid mode.
CellStates2 / 3Grid flavor: binary Lights Out / mod-3 Trilight.
GoalMode + GoalPatternAllLit / AllDark / Pattern · bitmaskThe grid target; Pattern = the painted bitmask.
SolutionStyleSingle / Few / ManyHow many valid solutions the board may have.
DummyPolicy / TrapPolicyNone / Allow / RequireDecoys · decoys that turn a state back off (Ordered).
MinSolutionSize / MaxSolutionSize1…switches / cellsWindow for the shortest solution.
MinStatesPerSwitch / MaxStatesPerSwitch1…statesClassic rule shape.
RequireOverlap + MinOverlapStatesbool · 0…statesStates shared by 2+ switches — the source of deduction.
ForbidSingleStateSwitches / ForbidAllStateSwitches / ForbidDuplicateRulesboolDegenerate-rule filters.
AutoRuleShape + TargetShortestSizebool · 0…Pin the shortest solution to an exact size (0 = off).
ScramblePresses0–56Lights Out scramble depth (0 = auto from the window).
MaxAttempts1–5000 (window slider 50+)Tries before keeping the best fallback (see the report).
SeedstringEmpty = random; any string reproduces the board.

Clamp() coerces every field into range. The report: AttemptsUsed, RuleRejects, QualityRejects, Matched.

API reference

TypeSurface
ClassicGenerator / OrderedGenerator / LightsOutGenerator / Mod3GeneratorGenerateVerified(settings) → analyzed, rated StatesPuzzle; honest fallback via Report.Matched.
ClassicSolverAnalyze(puzzle) — exhaustive ≤ 16 switches, auto-dispatch to GF(2) beyond.
Gf2SolverAnalyze(puzzle) — Gaussian elimination; exact counts (2^nullity), full listing to 4,096 solutions.
Mod3SolverAnalyze(puzzle) — the same over ℤ₃ for Trilight; counts are 3^nullity, twice-pressed cells listed twice.
OrderedSolverAnalyze(puzzle) — BFS: shortest sequences + step breakdown; CountTraps(puzzle).
StatesPuzzleMode, counts, ClassicRules (bitmask per switch — the incidence matrix), OrderedRules, grid, Start/Goal, persisted summary (Solvable/SolutionCount/ShortestSize/Difficulty/Unique), transient Analysis/Report, Settings, factories + label helpers.
OrderedRuleConditions (state must be off/on) + Effects (Effect.Toggle(d) / Effect.Set(d, on)).
PuzzleAnalysisSolvable, SolutionCount, ShortestSize, IsUnique, ShortestSolutions/AllSolutions, roles, Diagnostics, Steps (ordered, with blocked-press reasons), ChallengeScore, Difficulty, warnings, notes.
StatesPuzzleAsset / StatesPuzzlePackScriptableObject storage (single / ordered set), both IPuzzleProvider; PuzzleAssets.CreatePuzzle/CreatePack factories.
StatesGame (Demo)LoadLevel, PressSwitch, ResetLevel, StartAutoSolve/CancelAutoSolve, live state, events (LevelLoaded/Reset/Solved, Pressed, PressBlocked).

Reading a saved puzzle

StatesPuzzle p = pack.Get(0);
Debug.Log($"{p.Mode} · {p.StateCount} states · unique={p.Unique} · {p.Difficulty}★");

// Classic play is three lines of state:
long state = p.Start;
state ^= p.ClassicRules[2];              // press P3
bool won = state == p.Goal;

// Full picture on demand:
p.Analysis = p.IsMod3 ? Mod3Solver.Analyze(p)
    : p.Mode == PuzzleMode.Ordered ? OrderedSolver.Analyze(p)
    : ClassicSolver.Analyze(p);

Lights Out: cell (x, y) = index y * GridWidth + x, used as both state bit and switch index.

The demo

Open Scenes/DemoScene, press Play. A Canvas landing menu picks one of the four modes and endless-vs-pack; the HUD shows a goal-aware objective, live counter, presses vs par, difficulty pips, and Reset / Solve / Menu, with a par verdict on the Solved overlay. Click presses · R resets · F auto-solves step by step, exactly on par (input locks; R cancels). Ordered boards glow the switches that would change something right now — including trap recovery; pattern-goal boards dot their target cells on the board; Trilight cells rise a physical step per state. Assign one pack per mode on StatesDemo; skin via the renderer's prefab slots, palette, and layout dials; SFX are synthesized (an AudioListener is required). One-click builders: … ▸ Simple States ▸ Build Demo Scene (everything), plus standalone menu/HUD builders under … ▸ Demo Setup.

Troubleshooting

  • "Best-effort fallback" — nothing matched within Max attempts; raise it, widen the window, or loosen the strictest filter. The board is still analyzed honestly.
  • Can't assign a saved puzzle in the demo — the slots take packs; use Save ▸ Pack (a pack of one is fine).
  • Ordered too easy — enable traps (with dummies allowed); the glow marks actionable switches, including re-pressable trap recovery.
  • F does nothing — already solved or already auto-solving (both intentional).
  • "Malformed rule data" — incomplete/hand-edited asset; Re-roll or regenerate it.
  • Huge grid-mode counts — counts are exactly 2^nullity (Trilight: 3^nullity); listing caps at 4,096 / 6,561 and says so. The shortest solution stays exact.
  • Trilight lists a cell twice — intentional: that cell needs two presses (+1 mod 3 each).
  • Grid caps at 56 cells — 64-bit masks; sliders clamp automatically.
  • Missing text / TMP errors — import TMP Essentials (Examples & Extras not needed).
  • Compile errors — the demo needs Input System + TextMeshPro; the core has no dependencies.
  • No sound — add an AudioListener; SFX are synthesized, no clips to assign.

About

Simple States is made by Living Failure. Also available: Simple Connect (draw / pipe-rotate / network connection puzzles, square & hex) and Simple Hamiltonian (cover-all single-path puzzles) — the same verified, ScriptableObject-first workflow. Support: livingfailuregames@gmail.com — include the Unity version, and the seed + settings for board-specific issues. Distributed under the Unity Asset Store EULA.