pzprjs enables one to create or edit pencil puzzles like sudoku and yajilin which are solved with specific rules on boards. It is developed using HTML5 features and JavaScript.
This project is a fork of the original sabo2/pzprjs; it is live on puzz.link.
Please file issues using the issue tracker if you run into any issues with pzprjs.
Or write to feedback at puzz.link
, or join
puzzlink.zulipchat.com to discuss.
The core of the puzzle solving and editing applet lives in src/
.
The list of puzzle types is in src/pzpr/variety.js
, the implementation
of the various types within src/variety/
. Tests for these types are
found in test/script/
and test/variety/
. The test cases in
test/script/
are also used to generate instructions.
The web UI around the applet (buttons, options, background etc.) live
in src-ui/
.
Calling make
will build the project to dist/
. Depending on your browser's
security settings, you can interact with the result directly by opening
dist/p.html
or dist/list.html
in your browser. Otherwise, you may need
to run a web server, e.g. by running python -m http.server
within dist/
and visiting http://localhost:8000/list.html
.
Calling make test
will run the unit tests.
Adding a puzzle type involves the following:
-
Define a new type in
src/pzpr/variety.js
. This could be a new base typemytype
which will go in a new filesrc/variety/mytype.js
, or be based on an existing typeoldtype
, in which case you'll editsrc/variety/oldtype.js
. (E.g., the typeaho
is defined inshikaku.js
.) -
Implement the type in that file in
src/variety/
. The parts of a type implementation are- Input event handling, by customising
MouseEvent
andKeyEvent
. Every type has a number of "input modes", and typically one custom "auto" input mode. - Board customisation, by customising
Cell
,Board
etc. - Rendering, by customising
Graphic
. - URL and file encoding, by customising
Encode
andFileIO
.Encode
is used to deal with pzpr URLs, whileFileIO
is used when you save a board state to file (see tests below). - Answer checks, by collecting names of checks in
AnsCheck.checklist
, implementing checking methods inAnsCheck
, and defining failure codes and messages inFailCode
.
Have a look at existing types to see how multiple types within one file share code.
- Input event handling, by customising
-
Add a test file for the new type in
test/script/mytype.js
. This must include a full suite of example boards that trigger the various fail codes one by one. Ideally, this would be one example puzzle that shows various errors, but it's fine to deviate from that. The boards are stored as strings as generated by "File -> Save file as...", with newlines replaced by slashes.Furthermore, if your type does any tricky input handling, it's a good idea to add some input scripts in the
inputs
section of this test file. -
Add the new type to the web UI by adding it to each of
src-ui/js/v3index.js
andsrc-ui/list.html
. -
Add a background tile as
src-ui/img/mytype.png
and add the type insrc-ui/js/ui/Misc.js:toBGimage
. -
Add a line to
Changelog.md
.
Steps 1 and 2 should be enough to be able to interact with the
type by visiting p.html?mytype
. Feel free to skip steps 5 and 6
when submitting a pull request for a new type.
There are some Japanese terms in the source code that may not be obvious.
irowake: per-component coloring peke: cross mark