Engine mapping
How pencilmark builds its engine Puzzle from a sudoku-puzzle file (Puzzle format). This is for people
working on pencilmark or adding a rule; it is not part of the format.
The format is a transport layer: the engine Puzzle built from a file equals the one the site loaders build (groups
and their order, relations, constraints, domains, givens, coordinates), and each mechanic has one engine expansion
whatever its source.
Expansions
| Rule | Engine |
|---|---|
grid | row / col groups of its D × D area (rows, then columns; an already present house is skipped) |
box_grid | as grid, then the area's box groups |
box / row / column | box / row / col groups |
region | groups of kind diag (diagonal), window (window), region (the other kinds) |
cage | a cage group with its total |
line | {"type": "line", "kind": …} (whisper value → k; closed: the first cell repeated at the end); double_arrow → equal_sum [[ends], middle]; lockout → diffge on the ends plus a 3-cell table per middle cell |
arrow | one arrow constraint per shaft |
edge | relations diff 1 / ratio 2 (kropki), sum 10 / sum 5 (xv), lt of the reversed pair (greater); difference / sum / product / ratio: a 2-cell table of the allowed pairs (normalisation 8) |
corner | battenburg: a 4-cell table; mathrax: a 2-cell table per diagonal pair (TL–BR, then TR–BL), even / odd: a cell clue; exclude: a cell exclude clue |
sum | little_killer / sum constraints |
| outside clues | sandwich / xsum / skyscraper / first_seen constraints; rossini: lt relations and, with its negative, 3-cell tables |
neighbours | neq / nonconsec / the operator's relations per pair |
relation | one relation per pair |
negative | the complementary relation on every uncovered pair (nonconsec for white kropki, notratio, notsum, notdiff, allowed), tables for rossini / battenburg, domains for digits |
cell, candidates | domain masks (cell clues are also kept as cell clues) |
contains / appears / count / distinct_count / clone / isomorphic / global_entropy / equal_sum / vudoku | the engine constraints and named rules of the same mechanics |
Normalisations
Site loaders produce engine structures in several shapes; the writer maps each to one rule, so the same puzzle gives the same file and the same card whatever its source.
- Bare
setconsecutive constraints →linerenban. - Bare
betweenconstraints →linebetween. - Bare
equal_sumconstraints that are a zipper or a region-sum line → thatlinekind. increasing→linethermo;dutch_whisper→linewhisper with value 4;kropki_chainlines → kropki edges.- Jigsaw pieces stored as
regiongroups →boxgroups. - Disjoint groups of kind
extra→ kindregion; explicit-house boards (kindshouse/partial) →row/col/box/regionby shape. - "Not consecutive" relations of a white-kropki negative (
notdiff 1) →nonconsec(identical to the solver). - Numbered pair clues (edge
difference/sum/product/ratio) andcornermathraxclues expand to 2-cell tables of the allowed digit pairs (in digit order; equal digits allowed only when the two cells share no house). This is the form whose pricing fits players' times. A 2-cell table equal to a clue's digit pairs is written as that clue (first match in the order difference, sum, ratio, product: a 7:6 quotient and a ×42 product have the same pairs); kropki dots, XV and inequality signs stay pair relations. (exchange.NUMBERED_PAIR_FORM = "relation"switches to pair relations.) sumconstraints with distinct digits whose cells share no house →cagegroups.- A house listed twice is one house.
- Negative and neighbour rules expand in board order (cell by cell).
- Named multi-grid layouts (puzzle JSON
layout): cells are numbered in board reading order. - Houses are written grid by grid (
grid/box_grid, at the place of the grid's first house) whatever order a loader listed them in; reading the file back lists each grid's rows, columns, then boxes.
Mechanics without a named rule (same-parity lines, maximin, minimax, ten-eleven and similar) can be graded when a loader
builds them as engine tables, but cannot be written in format_version 1: table and the allowed operator are reserved
for the planned custom rule type (docs/formats/rules/other.mdx, 6.17), and to_export refuses such puzzles.
Adding a rule
Add a rule kind lists every place a new rule kind touches.