# ipuz extensions

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*](#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:
```json
    "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 edited by libipuz adds three styles within the
puzzle to render the barriers.

```json
"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 set other styles to a cell (such as a
> shapebg) along with a bar it's possible to add a cell-specific style
> and not use the internal ones.

```json
{
  "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.

```json
{
  "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

```json
{
  "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:

```json
{
  "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*](http://www.ipuz.org/example/first) 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.

> **UPDATE:** We got further clarification from the original spec
> author that the upper left cell was always supposed to be (0,0). The
> examples in the spec are wrong, and it will be updated to indicate
> this. Thoughts on dealing with the fallout from this are listed in
> [this bug](https://gitlab.gnome.org/jrb/libipuz/-/issues/49).

### 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:
```json
  "org.libipuz:charset": [ ..., "E", "F", "G", "H", "I", "IJ", "K", "L", ... ]
  "org.libipuz:charset": [ ..., "M", "N", "O", "P", "Q", "QU", "R", "S", ... ]
```

### Acrostic Quote and Source

The `org.libipuz:quote` extension field contains the original quote
that was used for generating the puzzle. Similarly, `org.libipuz:source`
indicates the original source or author of the quote.
Both extension strings are stored in a form appropriate for presenting to
the user. The quote string can also be displayed to the user upon completing
the puzzle.

Examples:
```json
  "org.libipuz:quote" : "Carnegie visited Princeton and told Wilson what ..."
  "org.libipuz:source" : "David Halberstam, The Amateurs"
```

### 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**
```json
  "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**
```json
  "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*](https://docs.gtk.org/Pango/pango_markup.html#pango-markup). This
is a subset of the valid html and doesn't include all possible
entities.

See [Issue #16](https://gitlab.gnome.org/jrb/libipuz/-/issues/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:
```json
{"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](https://spdx.org/licenses/)
when applicable. Otherwise, a URL is recommended for a custom or
proprietary license.

Examples:
```json
  "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:
```json
  "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?
