TinyGames · how it works

Nonogram

Numbers down the side, numbers across the top, and one picture that satisfies both. Every puzzle is solvable by deduction alone — a generator that cannot prove it is never shipped.

Draft. It is built, compiled and tested like every other game, and it is not on the hub: "draft": true in build/games.json keeps it off the cards, out of the sitemap and without a readme page until the rules are real. Take the flag off when it is worth playing.

How it is put together

picross.ts is the rules and touches nothing - no canvas, no engine, no storage. nonogram.ts is everything that draws or listens. The split is what makes the hard half testable: node test-picross.js runs against the shipped, minified JavaScript rather than the source, which is how a minification fault gets caught.

Every screen except the run itself belongs to the shared shell, so this game has one scene of its own, play. The menu, the pause card, the game-over screen and the high-score table come from src/shared/scenes.ts and look and behave the same here as in the other twenty.

The promise, and what keeps it

Every puzzle can be finished by reasoning, and never by guessing. Keeping that needs two pieces, and the second is the one usually skipped.

The line solver is complete: given a row's clues and what is known of it, it finds every cell whose value is forced, not just the ones the familiar overlap trick catches. It does that by enumerating the arrangements still consistent with the line and keeping the cells they agree on - slow in theory, instant at ten wide, and correct by construction rather than by a list of named techniques that is incomplete in ways nobody notices.

The generator throws puzzles away. Deriving clues from a random picture is easy and most results need a guess somewhere, so every candidate goes to the solver and is discarded unless the solver finishes it by deduction alone. A puzzle it has not proved is never shipped.

Uniqueness comes free: a puzzle the deduction solver completes has exactly one answer, because at no point was there a choice to make.

test-picross.js checks this against an independent reference - a brute-force enumerator written in the test file, sharing no code with the solver - over four thousand random lines including impossible ones. Its negative control is the smallest ambiguous nonogram there is: two cells on a diagonal, clues of one everywhere, two valid answers. The solver must refuse it, because that refusal is the judgement the generator depends on.

Playing it

Tap to fill, and drag to fill a run - deduction produces cells in runs, and tapping fifteen of them individually turns reasoning into clerical work. The mode button (or X, or the right mouse button) switches to marking blanks, which is how you keep your reasoning on the board instead of in your head.

The score is the time taken, so lower is better. Filling a cell that turns out to be blank is counted and shown, never punished - the puzzle never required a guess, so a wrong cell is information, not a penalty.

Still to do