View: Multi-Page Single Page

Generators

Four static entry points, one shape. Namespace SimpleStates. Each clamps the settings, rolls candidates until one matches (or MaxAttempts runs out), analyzes it exactly, stamps the persisted summary, and attaches the transient Analysis + Report.

MemberReturnsNotes
ClassicGenerator.GenerateVerified(settings)StatesPuzzleClassic combination boards. Honors solution style, dummy policy, rule shape, size window.
OrderedGenerator.GenerateVerified(settings)StatesPuzzleGated sequence boards; decoys and traps per policy. Trapped boards pass the no-deadlock proof.
LightsOutGenerator.GenerateVerified(settings)StatesPuzzleGrid boards, scrambled from solved — always solvable; matched to the press window or exact target. Honors GoalMode/GoalPattern.
Mod3Generator.GenerateVerified(settings)StatesPuzzleTrilight (mod-3) grid boards — same recipe over three states; scramble presses hit cells once or twice. Honors pattern goals.
Fallback is honestIf nothing matched within MaxAttempts, you still get the best candidate found — puzzle.Report.Matched is false.

Solvers

Static, allocation-light, pure C#. Every generated board arrives pre-analyzed; call these to re-analyze saved or hand-built boards (the analysis is transient and never serialized).

MemberReturnsNotes
ClassicSolver.Analyze(puzzle)PuzzleAnalysisExhaustive subset enumeration up to ExhaustiveMaxSwitches (16); bigger boards auto-dispatch to Gf2Solver.
Gf2Solver.Analyze(puzzle)PuzzleAnalysisGaussian elimination over GF(2) — instant on 56 cells. Exact counts (2^nullity); full listing up to 2^MaxEnumeratedNullity (4,096) solutions, partial beyond (flagged in warnings).
Mod3Solver.Analyze(puzzle)PuzzleAnalysisGaussian elimination over ℤ₃ for Trilight. Exact counts (3^nullity); listing to 6,561. Solutions carry a cell twice when it needs two presses.
OrderedSolver.Analyze(puzzle)PuzzleAnalysisBFS over board states: every shortest sequence (listing capped at 5,000 — unreachable at ≤ 8 switches), plus the step-by-step breakdown (Steps) with availability and blocked-press reasons.
OrderedSolver.CountTraps(puzzle)intHow many switches can re-lock a state (Toggle or Set-off effects).

Both classic solvers produce identical analyses — they are cross-checked field-for-field in the test harness. Malformed rule data (arrays shorter than SwitchCount) is rejected with a warning instead of throwing.

StatesPuzzle

The serializable puzzle unit (stored inside the ScriptableObjects). Board state is a bitmask: bit d set = state d on. Start = all off (0), Goal = all on.

FieldTypeMeaning
SeedstringThe seed that produced it.
ModePuzzleModeClassic or Ordered (Lights Out boards are Classic + a grid).
StateCount / SwitchCountintStates to turn on / switches to press.
ClassicRuleslong[]ClassicRules[p] = bitmask of states switch p toggles. Read row by row, this IS the incidence matrix.
OrderedRulesOrderedRule[]OrderedRules[p] = switch p's gate + effects (Ordered mode).
GridWidth / GridHeightint> 0 = a grid board (Lights Out / Trilight).
CellStatesint0/2 = binary grid; 3 = Trilight (IsMod3).
CellStart / CellGoalint[]Trilight only: per-cell values 0..2 (index y*W+x). The bitmasks below are unused there.
Start / GoallongBoard-state bitmasks. On Lights Out, Goal carries the pattern (all-lit / 0 / painted).
Solvable · SolutionCount · ShortestSize · Difficulty · UniquesummaryPersisted verdict, stamped at generation/verify time — readable without re-solving.
Analysis / ReporttransientFull analysis + generation report; [NonSerialized], recomputed on demand.
SettingsGenerationSettingsThe recipe that made it (used by inspector Re-roll). Null for hand-built boards.

Plus: AllStatesMask, IsLightsOut, StampSummary(), factories StatesPuzzle.Classic(…) / Ordered(…), and label helpers StateTag/SwitchTag/StateName/SwitchName ("ST3", "Switch 1"). Two-letter tags because switch and state share an initial — ST3 is a state, SW3 is a switch.

Ordered rules

An OrderedRule is a gate plus effects. The switch fires only when every condition holds; then all effects apply.

TypeMembersMeaning
OrderedRuleConditions, EffectsLists of the below.
ConditionState, RequiredOnThe state named by State must be off or on as stated.
EffectType, State, SetOnToggle flips the state; Set forces it. Factories: Effect.Toggle(d), Effect.Set(d, on).

The generator emits set-on chains, decoys, and (per policy) traps — Effect.Set(state, false) gated on that state being on. The data model carries the full condition/effect vocabulary, so hand-built rules can use all of it; the BFS solver handles any combination.

PuzzleAnalysis

Everything the solver learns. Classic counts every valid switch set; Ordered counts shortest sequences.

MemberTypeMeaning
Solvable / IsUniqueboolAny solution / exactly one.
SolutionCount / ShortestSizeintHow many · switches in the smallest.
ShortestSolutions / AllSolutionsList<int[]>Switch indices — unordered sets (Classic) or sequences (Ordered).
RequiredSwitches / OptionalSwitches / DummySwitchesint[]Roles: in every / some / no solution.
DiagnosticsRuleDiagnosticsStates-per-switch spread, overlap count, single-state / all-state / dominant switches, isolated states, duplicate-rule groups.
StepsList<SequenceStep>Ordered only: the shortest solve step by step — PressedSwitch, StateMask (the whole board after that press), ChangedStates, AvailableSwitches, and BlockedSwitches with reasons.
ChallengeScore / DifficultyintRaw score · 1–5★ (0 = unrated).
Warnings / DesignNotesList<string>Human-readable observations ("Exactly one solution (unique).").

GenerationSettings & GenerationReport

Every settings field is documented in the Generating page's table. Clamp() coerces all fields into valid ranges; Clone() copies a recipe. The report:

FieldMeaning
AttemptsUsedCandidates rolled.
RuleRejectsFailed the rule-shape filters.
QualityRejectsFailed the solution-quality filters (style, window, roles, traps).
Matchedtrue = a board met every filter; false = best-effort fallback.

Enums

EnumValuesMeaning
PuzzleModeClassic · OrderedCombination vs sequence. Lights Out = Classic + grid.
EffectTypeToggle · SetOrdered effect kind.
SolutionStyleSingle · Few · ManyHow many valid solutions the generator accepts.
DummyPolicyNone · Allow · RequireDecoy switches in no solution.
TrapPolicyNone · Allow · RequireOrdered: re-locking decoys (deadlock-free verified).
LightsOutGoalAllLit · AllDark · PatternGrid-mode target; Pattern uses GenerationSettings.GoalPattern.

ScriptableObjects

Storage lives in Runtime/ScriptableObjects. Both types implement IPuzzleProvider (AppendTo(List<StatesPuzzle>)), so one list can mix singles and packs.

TypeMembersNotes
StatesPuzzleAssetPuzzle, Label, plus verdict pass-throughs (Solvable, IsUnique, SolutionCount, Difficulty, IsLightsOut, Seed…) and Set(data, label)One puzzle. What Save ▸ Current writes.
StatesPuzzlePackPackName, Puzzles, Count, Get(i), Set / Add / Replace / ClearAn ordered set. What the demo's four pack slots take.
PuzzleAssetsCreatePuzzle(data, label), CreatePack(puzzles, name)Factories for building the assets from code (editor tooling uses these too).

Reading a saved puzzle

using SimpleStates;

// Assigned in the inspector, or loaded any way you like:
[SerializeField] StatesPuzzlePack pack;

void Start()
{
    StatesPuzzle p = pack.Get(0);

    // The persisted verdict — no solving needed:
    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;

    // Need the full picture (all solutions, roles, steps)? Recompute:
    p.Analysis = p.IsMod3 ? Mod3Solver.Analyze(p)
        : p.Mode == PuzzleMode.Ordered ? OrderedSolver.Analyze(p)
        : ClassicSolver.Analyze(p);
}

For grid boards, cell (x, y) is index y * GridWidth + x — the same index is both the state bit and the switch index (and the CellStart/CellGoal slot on Trilight).

Demo runtime (SimpleStates.Demo)

The demo assembly's play loop is reusable as-is — StatesGame is a complete referee for any board:

MemberNotes
LoadLevel(puzzle)Builds the 3D board (via StatesLevelRenderer) and resets state.
PressSwitch(i) / ResetLevel()A press (classic toggles; ordered checks its gate first) / back to Start.
StartAutoSolve(stepDelay) / CancelAutoSolve()Play the best solution one press at a time; player input locks while AutoSolving.
Puzzle · IsSolved · AutoSolving · StatesOnCount · MatchedCount · StateCount · MoveCount · ParLive state for your UI — including presses vs the proven par and goal-matching counts on pattern boards.
events: LevelLoaded, LevelReset, LevelSolved, Pressed, PressBlockedHook SFX/UI — the demo's beeper and HUD are wired off exactly these.

Around it: StatesLevelRenderer (board + optional switch/state prefab slots), StatesInput (click / R / F), StatesDemo (flow), StatesMenu + StatesHud (Canvas UI), StatesBeeper (procedural SFX). See Demos.