Extensions to the ipuz spec that we support

In general, we try to keep as close to the ipuz spec as possible. Unless listed below, we consider differences between our implementation and the spec as a bug.

However, in some areas the spec is unclear or allows for interpretation. In other areas we want to extend it to get additional functionality. This document captures those differences.

Puzzle Types

Acrostic puzzles

The description for http://ipuz.org/acrostic#1 type puzzles is minimal in the spec. We support the following conventions

  • There can be an (optional) clue with a clue of [QUOTE] who’s cells can be used to describe the main quote of the puzzle. This quote clue allows us to keep compatibility with apps that only render crosswords. This approach is used by .jpz files.

    • Acrostics with the [QUOTE] clue can have the http://ipuz.org/crossword#1 kind tag as as well. This will provide compatibility with existing players, and let a reasonably compliant player solve the puzzle.

  • The [QUOTE] clue can appear either in the main clues list (as seen in .jpz files) or a separate clue list.

    • See the section below on clue list directions for more information on how to handle multiple clue lists.

  • For acrostics, libipuz will either detect the [QUOTE] clue if it exists or calculate it based on the shape of the puzzle. It can be accessed through ipuz_acrostic_get_quote_clue (). Users of libipuz will have to handle that clue separately in their interface.

Example of optional [QUOTE] clue:

    "clues": {
        "Clues": [ {"label":"A", "clue":"Daughter to Brabantio", "cells":[ [9, 8], [4, 0], [10, 2], [19, 13], [10, 13], [18, 2], [8, 10], [8, 1], [6, 9] ] },
                   {"label":"B", "clue":"\"Tis an _______ thing to play with souls\" <i>(Browning)</i>", "cells":[ [4, 13], [1, 4], [18, 4], [9, 3], [14, 5], [18, 0], [11, 10] ] },
                   {"label":"C", "clue":"A gentleman of Verona", "cells":[ [9, 0], [7, 1], [8, 4], [19, 2], [1, 6], [11, 1], [11, 5], [4, 10], [17, 8] ] },
                   ... ]
        "Clues:Quote": [ {"clue":"[QUOTE]", "cells":[ [0, 0], [0, 1], [0, 2], [0, 4], ... ] } ]
    }

Barred puzzles

When saving, we tag barred puzzles as being a separate puzzle type through the https://libipuz.org/barred#1 kind tag. These are parseable as normal crosswords, and will also contain http://ipuz.org/crossword#1 in their kind tag for compatability. This is primarily so that we can differentiate the interface in editing mode.

Every barred puzzle is recommended to have three styles within the puzzle to render the barriers. If missing, libipuz will add the styles to the puzzle and use them when setting barriers:

"styles": {
    "L": {"barred": "L" },
    "T": {"barred": "T" },
    "TL": {"barred": "TL" }
}

These are used to render and define the bar, and to be used with the various _fix() functions to enforce symmetry.

Note: if you want to add other styles to a cell (such as a shapebg) it’s possible to add a cell-specific style. However, libipuz will currently only check the top and left barred setting when calculating clue extents, etc.

{
  "version" : "http://ipuz.org/v2",
  "kind" : [ "http://ipuz.org/crossword#1", "http://libipuz.org/barred#1" ],
  "styles" : {
    "T" : { "barred" : "T" },
    "L" : { "barred" : "L" },
    "TL" : { "barred" : "TL" }
  },
  "dimensions" : { "Dimension": n, ... },
  "puzzle" : [
    [ 1, 0, 0, 2, 0 ],
    [0, { "cell" : 3, "style" : "L" }, { "cell" : 0, "style" : "T" }, 0, { "cell" : 4, "style" : "TL" } ],
    [ LabeledCell, ... ], ... ],
  "solution": [ [ CrosswordValue, ... ], ... ],
  "clues": { "Across": [ Clue, ... ],
             "Down": [ Clue, ... ] },
}

Filippine puzzles

We tag dutch-style filippine puzzles as being a separate puzzle type through the https://libipuz.org/filippine#1 kind tag. These are parseable as normal crosswords, and will also contain https://ipuz.org/crossword#1 for compatability. This is primarily so that we can differentiate the interface in editing mode.

Nonograms

Nonograms are a type of picture puzzle game. The puzzle field is used represent the image, and has a slightly different cell type than other puzzles.

Nonograms require row clues to be provided for the user to play the game, but these clues are deterministic and can be calculated from the image. As a result, they are not included in file format.

{
  "version": "http://ipuz.org/v2",
  "kind": [ "https://libipuz.org/nonogram#1" ],
  "dimensions": { "Dimension": n, ... },
  "puzzle": [ [ NonogramCell, ... ] ... ]
}

NonogramCell

A NonogramCell is one of:

Field

Description

null

Omitted cell

empty value

Cell without a block (defaults to 0 and can be set by the empty field)

block value

A block (defaults to “#” and can be specified by the block field)

color block value

A string matching a style with an identical StyleName

Example Nonogram

{
  "version": "http://ipuz.org/v2",
  "kind": [ "https://libipuz.org/nonogram#1" ],
  "dimensions": { "Dimension": n, ... },
  "puzzle": [ [ 0 , "#",  0 ,  0 ,  0 ,  0 ,  0 ,  0 , "#",  0  ],
              ["#",  0 ,  0 ,  0 ,  0 ,  0 , "#",  0 ,  0 , "#" ],
              [ 0 ,  0 , "#",  0 , "#", "#", "#", "#",  0 ,  0  ],
              [ 0 ,  0 ,  0 , "#", "#", "#", "#", "#", "#",  0  ],
              [ 0 ,  0 , "#", "#", "#", "#", "#", "#", "#", "#" ],
              [ 0 , "#", "#", "#", "#", "#", "#", "#", "#",  0  ],
              ["#", "#", "#", "#", "#", "#", "#", "#", "#",  0  ],
              [ 0 , "#", "#", "#", "#", "#", "#", "#",  0 ,  0  ],
              [ 0 ,  0 , "#", "#", "#", "#", "#",  0 ,  0 , "#" ],
              [ 0 ,  0 ,  0 , "#", "#",  0 ,  0 ,  0 ,  0 ,  0  ] ]
}

Color Nonograms

Color Nonograms are a variant of Nonograms where blocks are different colors. In that instance, the cell value has the same value as StyleName.

As an example:

{
  "version": "http://ipuz.org/v2",
  "kind": [ "https://libipuz.org/nonogram#1", "https://libipuz.org/colornonogram#1" ], ],
  "dimensions": { "Dimension": n, ... },
  "styles": {
      "A": {"color": "#986a44" },
      "B": {"color": "#57e389" }
  },
  "puzzle": [ [ 0 , "A",  0 ,  0 ,  0 ,  0 ,  0 ,  0 , "A",  0  ],
              ["A",  0 ,  0 ,  0 ,  0 ,  0 , "A",  0 ,  0 , "A" ],
              [ 0 ,  0 , "A",  0 , "B", "B", "B", "A",  0 ,  0  ],
              [ 0 ,  0 ,  0 , "B", "B", "B", "B", "B", "A",  0  ],
              [ 0 ,  0 , "B", "B", "B", "B", "B", "B", "B", "A" ],
              [ 0 , "B", "B", "B", "B", "B", "B", "B", "A",  0  ],
              ["B", "B", "B", "B", "B", "B", "B", "B", "A",  0  ],
              [ 0 , "B", "B", "B", "B", "B", "B", "B",  0 ,  0  ],
              [ 0 ,  0 , "B", "B", "B", "B", "B",  0 ,  0 , "A" ],
              [ 0 ,  0 ,  0 , "A", "A",  0 ,  0 ,  0 ,  0 ,  0  ] ]
}

Extensions and Clarifications

We support a number of extensions to the ipuz spec. These all should be backwards compatible, and are likely to be safely ignored by other implementations. Please file a bug if any of these cause problems!

There are also areas where the spec is unclear. This section details all the libipuz decisions that were made.

Cell coordinates

The spec refers to COL1 and ROW1 as a coordinate for a row but doesn’t explicitly indicate if it is indexed at 0 or 1. The first crossword example implies it starts at zero, but the spec has examples (such as Calcudoku) that imply the coordinates start at 1:

  • We interpret it as starting at 0, which is what is used by some of the puzzles we’ve found in the wild.

  • puzzaz interprets puzzles as 0-based as well, which further indicates we should use that.

Charset List

The org.libipuz:charset list is a supplement for the charset variable. It’s supposed to be used to handle multi-character cell values. As an example, Dutch crosswords consider the “IJ” digraph as a single character.

Ideally, the ipuz spec would accept both a list as well as a string. Until the spec changes, we handle it as an extension.

Examples:

  "org.libipuz:charset": [ ..., "E", "F", "G", "H", "I", "IJ", "K", "L", ... ]
  "org.libipuz:charset": [ ..., "M", "N", "O", "P", "Q", "QU", "R", "S", ... ]

Clue list directions

We don’t support multiple unadorned Clue lists of the same direction. This is also invalid json.

We do plan to support having multiple clue lists with a label associated with them. This can be used by acrostics to have multiple Zones or Clues sections.

Examples:

Invalid

  "clues": {
      "Zones": [[1, "The first man"],
                [5, "Holds back progress"],
                [8, "Many armed sea creature"],
                ... ]
      "Zones": [[1, "Bow companion"],
                [2, "___ Leppard"],
                [3, "Without a warranty (hyphenated)"],
                ... ]
  }

Valid

  "clues": {
      "Zones": [[1, "The first man"],
                [5, "Holds back progress"],
                [8, "Many armed sea creature"],
                ... ]
      "Zones:Second Zone": [[1, "Bow companion"],
                           [2, "___ Leppard"],
                           [3, "Without a warranty (hyphenated)"],
                           ... ]
  }

HTML

The amount of HTML acceptable in a puzzle is loosely defined in the spec. As a practical matter, we convert the HTML strings into something that’s appropriate for Pango Markup. This is a subset of the valid html and doesn’t include all possible entities.

See Issue #16 for additional details of what is supported and not supported. Unsupported tags are ignored and stripped.

Style on BLOCKS

We support setting styles on BLOCK cells. While this is redundant to the solving of the puzzle, it can be a nice visual addition. Specifically it lets us set a BLOCK to be a specific color rather than just black. It is recommended that implementations texture the block differently from a straight colored cells when this happens.

Example:

{"cell": "#", "style": {"color":"#2d4ce5"}}

License

We add an org.libipuz:license tag to indicate the license of the puzzle. We expect these to be a recognized string description of a well-known license, and not the full license text. The description should come from the SPDX License List when applicable. Otherwise, a URL is recommended for a custom or proprietary license.

Examples:

  "org.libipuz:license": "CC-BY-SA-2.0"
  "org.libipuz:license": "https://www.example.com/licensing.html"

Locale

We add an org.libipuz:locale tag that indicates the locale the puzzle is written for. This can be useful for filtering out the language of the puzzle for users that don’t speak the language. It should not affect the parsing of the puzzle at all. It is assumed that if a puzzle doesn’t have a language tag, it’s of the “C” Locale.

Example:

  "org.libipuz:locale": "nl_NL"

Unclear/unhandled ipuz spec terms

  • What does clueplacement do?

  • What does annotation do?

  • How are answer/answers supposed to be rendered?