Here's the full set of kitemaps and metamaps for all the tile
+ types:
+
+
+
Tile name
+
Original tile
+
First-order expansion
+
Kitemap
+
Metamap
+
+
H
+
+
+
+
+
+
+
T
+
+
+
+
+
+
+
P
+
+
+
+
+
+
+
F
+
+
+
+
+
+
+
+
diff --git a/aux/doc/hats-single-F.svg b/aux/doc/hats-single-F.svg
new file mode 100644
index 0000000..bac6010
--- /dev/null
+++ b/aux/doc/hats-single-F.svg
@@ -0,0 +1,35 @@
+
+
diff --git a/aux/doc/hats-single-H.svg b/aux/doc/hats-single-H.svg
new file mode 100644
index 0000000..f7017ea
--- /dev/null
+++ b/aux/doc/hats-single-H.svg
@@ -0,0 +1,67 @@
+
+
diff --git a/aux/doc/hats-single-P.svg b/aux/doc/hats-single-P.svg
new file mode 100644
index 0000000..83b147e
--- /dev/null
+++ b/aux/doc/hats-single-P.svg
@@ -0,0 +1,35 @@
+
+
diff --git a/aux/doc/hats-single-T.svg b/aux/doc/hats-single-T.svg
new file mode 100644
index 0000000..146788e
--- /dev/null
+++ b/aux/doc/hats-single-T.svg
@@ -0,0 +1,19 @@
+
+
diff --git a/aux/doc/hats.html b/aux/doc/hats.html
new file mode 100644
index 0000000..ab73ccc
--- /dev/null
+++ b/aux/doc/hats.html
@@ -0,0 +1,258 @@
+
+
+
+Generating hat tilings for Loopy
+
+
+
+
Generating hat tilings for Loopy
+
The original paper
+ describes a method for generating hat tilings from a system of four
+ 'metatiles'. You can start with any one of the four tiles, and then
+ recursively apply a set of expansion rules that turn each tile into
+ a collection of smaller tiles from the same set.
+
This table shows the four tiles, with their one-letter names as
+ given in the paper, and how each one is expanded.
+
All the tiles have a significant orientation. The H, T and P
+ tiles are marked with arrows to indicate the orientation. The F tile
+ is asymmetric, so no arrow is needed.
+
I've assigned each tile in each expansion a number, which Loopy
+ will use for its coordinate system.
+
+
+
Tile name
+
Single tile
+
Expansion
+
+
H
+
+
+
+
+
T
+
+
+
+
+
P
+
+
+
+
+
F
+
+
+
+
+
Note that these expansions overlap. When two
+ adjacent metatiles are expanded, the outer layer of P and F tiles in
+ their expansions must be placed so that they overlap each other. The
+ original paper suggests a set of tiles to remove from these
+ expansions so that each metatile expands to a disjoint set
+ of smaller tiles. In our implementation, however, we prefer to keep
+ the overlap, because our coordinate system will use it.
+
Once you've generated a large enough patch of metatiles for your
+ needs, the final step is to convert it into the actual hat tiles.
+ The expansion of each metatile into hats is shown here. Again, I've
+ assigned numbers to each hat for coordinate-system purposes:
+
+
+
Tile name
+
Conversion into hats
+
+
H
+
+
+
+
+
T
+
+
+
+
+
P
+
+
+
+
+
F
+
+
+
+
+
(The hat in the middle of the H is shaded to indicate that it's
+ one of the rare reflected ones. All the other hats are rotations of
+ each other.)
+
Given all of this, an obvious approach to generating a random
+ patch of hat tiling would be to start with a single metatile,
+ iterate the expansion process a few times until you have a tiled
+ area much larger than you need, and then pick a subrectangle of
+ it at random.
+
Loopy's algorithm for generating Penrose tilings (which admit a
+ similar, though less complicated, expansion system) works in exactly
+ this way.
+
One problem with that algorithm is that it spends a lot of effort
+ on generating huge areas of tiles that aren't actually needed. So
+ you'd prefer to adjust the algorithm so that at every stage of
+ expansion it spots tiles completely outside the target rectangle,
+ and throws them away before spending 5 iterations on
+ exponentially expanding them into huge amounts of detail that will
+ only be thrown away anyway later.
+
That works well for Penrose tilings, because there, the expansion
+ procedure is geometrically precise: coordinates in the expanded
+ tiling are scaled up by an exact factor from coordinates in the
+ original tiling. So at every stage it's easy to know exactly where
+ your target rectangle is, and discard things that don't
+ overlap it.
+
But the metatiles shown here don't have that property. The tiles
+ distort slightly as they expand. The topological properties
+ of the expanded tiling match the original (which expanded tiles
+ connect to each other), but the geometry (precise distances) is
+ different. So it would be harder to implement the pruning for this
+ tiling. The target rectangle might not even be rectangular in every
+ iteration!
+
Instead, I came up with a completely different mechanism, by
+ devising a coordinate system to track our position within multiple
+ layers of tile expansion. This allows us to generate precisely the
+ area of tiling we need, and waste no effort at all on anything
+ outside the target region.
+
We begin by assigning an integer index to each kite making up an
+ individual hat:
+
+
(For a reflected hat, these indices work in mirror image, so that
+ for example 5 is still the kite in the middle.)
+
Together with the indices we've assigned to hats within each
+ metatile, and to metatiles in the expansion of another metatile,
+ this gives us a coordinate system that can identify an individual
+ kite in an n-times-expanded metatile. For each large metatile
+ expansion, you can give the index of the smaller metatile selected
+ from its expansion; when we reach the last layer of metatiles and
+ expand them into hats, we can give the index of the hat in that
+ metatile; finally we can index the kite in that hat.
+
But note that a kite can have multiple
+ coordinates, because of the overlap between the expansions
+ of adjacent metatiles. This will be useful!
+
Our next step is to unambiguously name the four directions in
+ which you can move from one kite to an adjacent kite. The directions
+ should be independent of the orientation of the kite. I've chosen to
+ name them from the viewpoint of someone standing at the pointy end
+ of the kite and looking towards the blunt end:
+
+
Left
+
Rotate 60° anticlockwise about the pointy end of the kite. For
+ example, in the above hat, going 'left' from kite 5 takes you to
+ kite 4.
+
Right
+
Rotate 60° clockwise about the pointy end. From kite 5, this
+ would take you to kite 6.
+
Forward left
+
Head forwards and slightly left, to the kite sharing the
+ left-hand one of this kite's short edges (as seen from the
+ centre). Equivalently, rotate 120° clockwise about the
+ blunt end. From kite 5, this takes you to kite 2.
+
Forward right
+
Head forwards and slightly right. Or rotate 120° anticlockwise
+ about the blunt end, if you prefer to think of it that way. From
+ kite 5, this takes you to kite 1.
+
+
The idea is that if we know how to transform the coordinates of a
+ single kite into the coordinates of each of those four adjacent
+ kites, then we can iterate that over a whole area and determine the
+ coordinates of every kite in the whole tiling.
+
Having done that, it's easy to identify each individual kite, by
+ several different methods. For example, you could iterate over edges
+ of the tiling to see whether the kites on each side have coordinates
+ differing only in the kite index; if so, they're part of the same
+ hat, and if not, not. Or a completely different approach (in fact
+ the one Loopy actually uses) would be to trace round the boundary of
+ each hat by starting from its kite #0 and just knowing what shape a
+ hat is.
+
So now we have to come up with an algorithm that lets us
+ transform a kite coordinate by making one of the four permitted
+ moves. To do this, we use two multilevel types of map.
+
The kitemap for a given metatile type is made by
+ expanding the metatile once into more metatiles, and then into hats.
+ For example, the T tile:
+
+
+
+
+
+
+
+
+
+
In each kite, we show a three-part coordinate, in little-endian
+ fashion (because that matches the order the coordinates are stored
+ in an array in the code that actually generates the tilings). For
+ example, 7.3.0 means kite 7 in hat 3 of metatile 0 of the
+ expansion.
+
This map can be converted into a lookup table, indexed by those
+ three-part coordinates and also the four move directions, which
+ allows you to look up that (for example) going Left from kite 7.3.0
+ goes to 0.0.0, or going Forward Left from 7.3.0 goes to 3.1.3.
+
But if you're at the very edge of the kitemap, this isn't enough.
+ For example, kite 0.0.4 right at the top can go Left to 1.0.4, but
+ if it wants to go in any of the other three directions, this map
+ doesn't help at all.
+
This is where the overlap between the metatile expansions comes
+ in. If you're in kite 0.0.4, then in particular, you're in the F
+ tile numbered 4 in the expansion of a larger T metatile. And that F
+ tile is also part of the expansion of at least one other
+ second-order metatile – maybe two of them – which means that there
+ are other equivalent coordinates describing the same kite, which
+ will place it in a different kitemap where it isn't right
+ on the edge,
+
In order to find those equivalent coordinates, we create a second
+ map for each metatile type, called the metamap.
+ This one arises from expanding the metatile twice into other
+ metatiles, instead of into hats:
+
+
+
+
+
+
+
+
+
+
Again, the coordinates are little-end first, so that 7.4 means
+ the 7th smallest-size tile expanded from the 4th medium-sized tile
+ expanded from the original single large tile.
+
Unlike the kitemap, the metamap is not used for moving
+ around the tiling to a different kite. It's used for rewriting
+ the coordinates of the current kite into equivalent forms. So each
+ the small tile in the metamap that's part of the expansion
+ of more than one medium-sized tile has more than one
+ coordinate pair. For example, tile 5.2 is also tile 5.4, and tile
+ 7.0 is also 8.3 and also 4.5 (because it's where three
+ medium-tile expansions meet).
+
Using both of these maps (converted into appropriate lookup
+ tables in the code), you can always eventually find a valid
+ coordinate representation of whichever kite you like adjacent to
+ your current one. If the kitemap corresponding to the current
+ coordinates doesn't tell you the coordinates of the next kite, then
+ you can try rewriting the two least-significant metatile indices
+ (using the metamap corresponding to the type of the next-larger
+ metatile still) and then see if that gives you a new kitemap that
+ works. If even that doesn't work, you can move another level up, and
+ try a metamap rewrite on the 2nd and 3rd smallest metatile levels,
+ or the 3rd and 4th, etc. And eventually, you find something you can
+ do.
+
The full set of kitemaps and metamaps for all the tile
+ types is in hatmaps.html.
+
+
diff --git a/aux/doc/kitemap-F.svg b/aux/doc/kitemap-F.svg
new file mode 100644
index 0000000..5b448ab
--- /dev/null
+++ b/aux/doc/kitemap-F.svg
@@ -0,0 +1,783 @@
+
+
diff --git a/aux/doc/kitemap-H.svg b/aux/doc/kitemap-H.svg
new file mode 100644
index 0000000..16750fb
--- /dev/null
+++ b/aux/doc/kitemap-H.svg
@@ -0,0 +1,933 @@
+
+
diff --git a/aux/doc/kitemap-P.svg b/aux/doc/kitemap-P.svg
new file mode 100644
index 0000000..bd3fffb
--- /dev/null
+++ b/aux/doc/kitemap-P.svg
@@ -0,0 +1,783 @@
+
+
diff --git a/aux/doc/kitemap-T.svg b/aux/doc/kitemap-T.svg
new file mode 100644
index 0000000..6be1ddc
--- /dev/null
+++ b/aux/doc/kitemap-T.svg
@@ -0,0 +1,483 @@
+
+
diff --git a/aux/doc/metamap-F.svg b/aux/doc/metamap-F.svg
new file mode 100644
index 0000000..4b2805c
--- /dev/null
+++ b/aux/doc/metamap-F.svg
@@ -0,0 +1,714 @@
+
+
diff --git a/aux/doc/metamap-H.svg b/aux/doc/metamap-H.svg
new file mode 100644
index 0000000..127df3d
--- /dev/null
+++ b/aux/doc/metamap-H.svg
@@ -0,0 +1,819 @@
+
+
diff --git a/aux/doc/metamap-P.svg b/aux/doc/metamap-P.svg
new file mode 100644
index 0000000..d5a6f4f
--- /dev/null
+++ b/aux/doc/metamap-P.svg
@@ -0,0 +1,708 @@
+
+
diff --git a/aux/doc/metamap-T.svg b/aux/doc/metamap-T.svg
new file mode 100644
index 0000000..c65fc83
--- /dev/null
+++ b/aux/doc/metamap-T.svg
@@ -0,0 +1,459 @@
+
+
diff --git a/aux/doc/single-F.svg b/aux/doc/single-F.svg
new file mode 100644
index 0000000..1e3c4d3
--- /dev/null
+++ b/aux/doc/single-F.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/aux/doc/single-H.svg b/aux/doc/single-H.svg
new file mode 100644
index 0000000..e3919dc
--- /dev/null
+++ b/aux/doc/single-H.svg
@@ -0,0 +1,11 @@
+
+
diff --git a/aux/doc/single-P.svg b/aux/doc/single-P.svg
new file mode 100644
index 0000000..2b7159a
--- /dev/null
+++ b/aux/doc/single-P.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/aux/doc/single-T.svg b/aux/doc/single-T.svg
new file mode 100644
index 0000000..68919bb
--- /dev/null
+++ b/aux/doc/single-T.svg
@@ -0,0 +1,8 @@
+
+
diff --git a/aux/hatgen-images.sh b/aux/hatgen-images.sh
new file mode 100755
index 0000000..f3cec4b
--- /dev/null
+++ b/aux/hatgen-images.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# Regenerate all the SVG images in the aux/doc directory for hats.html
+# and hatmap.html.
+
+set -e
+
+hatgen=$1
+
+if ! test -x "$hatgen"; then
+ echo "Provide pathname to hatgen as an argument" >&2
+ exit 1
+fi
+
+for tile in H T P F; do
+ "$hatgen" "$tile" > single-"$tile".svg
+ "$hatgen" c"$tile" > expanded-"$tile".svg
+ "$hatgen" h"$tile" > hats-single-"$tile".svg
+ "$hatgen" H"$tile" > kitemap-"$tile".svg
+ "$hatgen" C"$tile" > metamap-"$tile".svg
+done
+
+"$hatgen" --hat > hat-kites.svg
diff --git a/aux/hatgen.c b/aux/hatgen.c
new file mode 100644
index 0000000..11fb262
--- /dev/null
+++ b/aux/hatgen.c
@@ -0,0 +1,1713 @@
+/*
+ * Generate patches of tiling by the 'hat' aperiodic monotile
+ * discovered in 2023.
+ *
+ * This implementation of hat-tiling generation was intended to be the
+ * basis for generating hat grids for Loopy. However, it turned out
+ * that I found a better strategy, so this source file isn't used by
+ * the main puzzle system. I've kept it anyway because I ended up
+ * adapting it to generate the file hat-tables.h containing the lookup
+ * tables for the algorithm I _did_ end up using. It also generates
+ * diagrams that are useful for understanding that algorithm, and for
+ * debugging it if anything still turns out to be wrong with it.
+ *
+ * Discoverers' website: https://cs.uwaterloo.ca/~csk/hat/
+ * Preprint of paper: https://arxiv.org/abs/2303.10798
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "puzzles.h"
+#include "tree234.h"
+#include "hat.h"
+
+/*
+ * General strategy:
+ *
+ * We construct the hat tiling by means of a substitution system of
+ * 'metatiles' which come in four types, called H,T,P,F. A (valid)
+ * tiling of these metatiles can be expanded to a larger one by a set
+ * of recursive subdivision rules. Once we have a large enough patch
+ * of metatiles, we apply a final transformation that converts each
+ * metatile into 1, 2 or 4 instances of the aperiodically tiling
+ * 'hat'.
+ *
+ * Unlike the similar substitution system for Penrose tilings, the
+ * expansion rules are not geometrically precise: the larger versions
+ * of each metatile fit together combinatorially in the same way, but
+ * their shapes are distorted slightly. So we must construct our
+ * expanded meta-tiling by breadth-first search out from a starting
+ * metatile, because we won't quite know the coordinates of the
+ * expanded version of each metatile until we know one of the ones
+ * next to it.
+ */
+
+/*
+ * Coordinate system:
+ *
+ * Everything in this code lives on the tiling known to grid.c as
+ * 'Kites', which can be viewed as a tiling of hexagons each of which
+ * is subdivided into six kites sharing their pointy vertex, or
+ * (equivalently) a tiling of equilateral triangles each subdivided
+ * into three kits sharing their blunt vertex.
+ *
+ * We express coordinates in this system relative to the basis (1, r)
+ * where r = (1 + sqrt(3)i) / 2 is a primitive 6th root of unity. This
+ * gives us a system in which two integer coordinates can address any
+ * grid point, provided we scale up so that the side length of the
+ * equilateral triangles in the tiling is 6.
+ */
+
+typedef struct Point {
+ int x, y; /* represents x + yr */
+} Point;
+
+static inline Point left6(Point p)
+{
+ /* r satisfies the equation r^2 = r-1. Hence, multiplying by r
+ * (achieving a rotation anticlockwise by 1/6 turn) transforms
+ * x+yr into xr+yr^2 = xr+y(r-1) = (-y) + (x+y)r.
+ *
+ * It's easy to check that iterating this transformation six times
+ * gives you back the same coordinates you started with. */
+ Point q = { -p.y, p.x + p.y };
+ return q;
+}
+
+static inline Point right6(Point p)
+{
+ /* Conversely, 1/r = 1 - r, so dividing by r turns x+yr into x/r+y
+ * = x(1-r) + y = (x+y) + (-x)r. */
+ Point q = { p.x + p.y, -p.x };
+ return q;
+}
+
+typedef enum MetatileType { MT_H, MT_T, MT_P, MT_F } MetatileType;
+typedef struct Metatile Metatile;
+typedef struct MetaCoord {
+ Metatile *parent;
+ int index;
+} MetaCoord;
+
+struct Metatile {
+ /* Data fields describing the metatile and its position. */
+ MetatileType type;
+ Point start, orientation;
+
+ MetaCoord coords[4];
+ size_t ncoords;
+
+ /* Auxiliary fields used to store the progress of the expansion
+ * algorithm. */
+ bool queued;
+ Metatile *qnext;
+};
+
+#define MT_MAXVERT 6 /* largest number of vertices of any metatile */
+#define MT_MAXVDEGREE 3 /* largest degree of any vertex of a meta-tiling */
+#define MT_MAXEXPAND 13 /* largest number of metatiles in any expansion */
+#define MT_MAXHAT 4 /* largest number of hats in a metatile */
+#define HAT_NVERT 14 /* vertices of a single hat (counting the straight one) */
+#define HAT_NKITE 8 /* kites in a single hat */
+
+static int metatile_cmp(void *av, void *bv)
+{
+ Metatile *a = (Metatile *)av, *b = (Metatile *)bv;
+ if (a->type < b->type) return -1;
+ if (a->type > b->type) return +1;
+ if (a->start.x < b->start.x) return -1;
+ if (a->start.x > b->start.x) return +1;
+ if (a->start.y < b->start.y) return -1;
+ if (a->start.y > b->start.y) return +1;
+ if (a->orientation.x < b->orientation.x) return -1;
+ if (a->orientation.x > b->orientation.x) return +1;
+ if (a->orientation.y < b->orientation.y) return -1;
+ if (a->orientation.y > b->orientation.y) return +1;
+ return 0;
+}
+
+/*
+ * Return the coordinates of the vertices of a metatile, given the
+ * coordinates of the vertex we deem to be distinguished, and a vector
+ * of Euclidean length 1 showing its direction.
+ *
+ * If 'expanded' is true, we instead return the coordinates of the
+ * corresponding vertices of the expanded version of the same
+ * metatile.
+ */
+static size_t metatile_vertices(Metatile m, Point *out, bool expanded)
+{
+ static const Point vertices_H[] = {
+ {0, 0}, {4, -2}, {12, 6}, {10, 10}, {-6, 18}, {-8, 16},
+ };
+ static const Point vertices_T[] = {
+ {0, 0}, {6, 6}, {-6, 12},
+ };
+ static const Point vertices_P[] = {
+ {0, 0}, {4, 4}, {-4, 20}, {-8, 16},
+ };
+ static const Point vertices_F[] = {
+ {0, 0}, {4, -2}, {6, 0}, {-2, 16}, {-6, 12},
+ };
+
+ static const Point expanded_H[] = {
+ {0, 0}, {12, -6}, {30, 12}, {24, 24}, {-12, 42}, {-18, 36},
+ };
+ static const Point expanded_T[] = {
+ {0, 0}, {12, 12}, {-12, 24},
+ };
+ static const Point expanded_P[] = {
+ {0, 0}, {14, 8}, {-4, 44}, {-18, 36},
+ };
+ static const Point expanded_F[] = {
+ {0, 0}, {14, -4}, {18, 6}, {0, 42}, {-14, 34},
+ };
+
+ const Point *vertices;
+ size_t nvertices;
+ size_t i;
+
+ switch (m.type) {
+ case MT_H:
+ vertices = expanded ? expanded_H : vertices_H;
+ nvertices = lenof(vertices_H);
+ break;
+ case MT_T:
+ vertices = expanded ? expanded_T : vertices_T;
+ nvertices = lenof(vertices_T);
+ break;
+ case MT_P:
+ vertices = expanded ? expanded_P : vertices_P;
+ nvertices = lenof(vertices_P);
+ break;
+ default /* case MT_F */:
+ vertices = expanded ? expanded_F : vertices_F;
+ nvertices = lenof(vertices_F);
+ break;
+ }
+ assert(nvertices <= MT_MAXVERT);
+
+ Point orientation_r = left6(m.orientation);
+ for (i = 0; i < nvertices; i++) {
+ Point v = vertices[i];
+ out[i].x = m.start.x + v.x * m.orientation.x + v.y * orientation_r.x;
+ out[i].y = m.start.y + v.x * m.orientation.y + v.y * orientation_r.y;
+ }
+ return nvertices;
+}
+
+/*
+ * Return a list of metatiles that arise from expanding a given tile.
+ */
+static size_t metatile_expand(Metatile m, Metatile *out)
+{
+ static const Metatile tiles_H[] = {
+ {MT_H, {-4, 20}, {1, 0}},
+ {MT_H, {2, 2}, {1, 0}},
+ {MT_H, {8, 26}, {0, -1}},
+ {MT_T, {6, 24}, {-1, 0}},
+ {MT_P, {-8, 16}, {1, 0}},
+ {MT_P, {4, 34}, {0, -1}},
+ {MT_P, {6, 0}, {1, -1}},
+ {MT_F, {-10, 38}, {-1, 1}},
+ {MT_F, {-10, 44}, {0, -1}},
+ {MT_F, {-4, 2}, {1, 0}},
+ {MT_F, {2, 2}, {0, -1}},
+ {MT_F, {26, 14}, {1, 0}},
+ {MT_F, {32, 8}, {-1, 1}},
+ };
+ static const Metatile tiles_T[] = {
+ {MT_H, {10, 10}, {-1, 1}},
+ {MT_P, {-6, 0}, {1, 0}},
+ {MT_P, {8, 14}, {0, 1}},
+ {MT_P, {18, 6}, {-1, 1}},
+ {MT_F, {-14, 34}, {-1, 0}},
+ {MT_F, {-8, -2}, {1, -1}},
+ {MT_F, {22, 4}, {0, 1}},
+ };
+ static const Metatile tiles_P[] = {
+ {MT_H, {4, 22}, {0, 1}},
+ {MT_H, {10, 10}, {-1, 1}},
+ {MT_P, {-6, 0}, {1, 0}},
+ {MT_P, {6, 24}, {1, 0}},
+ {MT_P, {8, 14}, {0, 1}},
+ {MT_F, {-20, 40}, {1, -1}},
+ {MT_F, {-14, 34}, {-1, 0}},
+ {MT_F, {-8, -2}, {1, -1}},
+ {MT_F, {4, 46}, {-1, 1}},
+ {MT_F, {10, 10}, {1, 0}},
+ {MT_F, {16, 4}, {-1, 1}},
+ };
+ static const Metatile tiles_F[] = {
+ {MT_H, {8, 20}, {0, 1}},
+ {MT_H, {14, 8}, {-1, 1}},
+ {MT_P, {10, 22}, {1, 0}},
+ {MT_P, {12, 12}, {0, 1}},
+ {MT_F, {-16, 38}, {1, -1}},
+ {MT_F, {-10, 32}, {-1, 0}},
+ {MT_F, {-4, 2}, {1, 0}},
+ {MT_F, {2, 2}, {0, -1}},
+ {MT_F, {8, 44}, {-1, 1}},
+ {MT_F, {14, 8}, {1, 0}},
+ {MT_F, {20, 2}, {-1, 1}},
+ };
+
+ const Metatile *tiles;
+ size_t ntiles;
+ size_t i;
+
+ switch (m.type) {
+ case MT_H:
+ tiles = tiles_H;
+ ntiles = lenof(tiles_H);
+ break;
+ case MT_T:
+ tiles = tiles_T;
+ ntiles = lenof(tiles_T);
+ break;
+ case MT_P:
+ tiles = tiles_P;
+ ntiles = lenof(tiles_P);
+ break;
+ default /* case MT_F */:
+ tiles = tiles_F;
+ ntiles = lenof(tiles_F);
+ break;
+ }
+ assert(ntiles <= MT_MAXEXPAND);
+
+ Point orientation_r = left6(m.orientation);
+ for (i = 0; i < ntiles; i++) {
+ Metatile t = tiles[i];
+ out[i].type = t.type;
+ out[i].start.x = (m.start.x + t.start.x * m.orientation.x +
+ t.start.y * orientation_r.x);
+ out[i].start.y = (m.start.y + t.start.x * m.orientation.y +
+ t.start.y * orientation_r.y);
+ out[i].orientation.x = (t.orientation.x * m.orientation.x +
+ t.orientation.y * orientation_r.x);
+ out[i].orientation.y = (t.orientation.x * m.orientation.y +
+ t.orientation.y * orientation_r.y);
+ }
+ return ntiles;
+}
+
+/* Store data about each vertex during an expansion. */
+typedef struct VertexMapping {
+ Point in;
+
+ /* Metatiles sharing this vertex */
+ Metatile *tiles[MT_MAXVDEGREE];
+ size_t ntiles;
+
+ /* The expanded coordinates of this vertex, if known */
+ bool mapped;
+ Point out;
+} VertexMapping;
+
+static int vertexmapping_cmp(void *av, void *bv)
+{
+ VertexMapping *a = (VertexMapping *)av, *b = (VertexMapping *)bv;
+ if (a->in.x < b->in.x) return -1;
+ if (a->in.x > b->in.x) return +1;
+ if (a->in.y < b->in.y) return -1;
+ if (a->in.y > b->in.y) return +1;
+ return 0;
+}
+
+static int vertexmapping_find(void *av, void *bv)
+{
+ Point *a = (Point *)av;
+ VertexMapping *b = (VertexMapping *)bv;
+ if (a->x < b->in.x) return -1;
+ if (a->x > b->in.x) return +1;
+ if (a->y < b->in.y) return -1;
+ if (a->y > b->in.y) return +1;
+ return 0;
+}
+
+typedef struct MetatileSet {
+ /* The tiles in the set */
+ tree234 *tiles;
+
+ /*
+ * Bounding box of a rectangular region within the original single
+ * tile this set was expanded from. We need this in order to pick
+ * a random chunk out of the tiling to return to our client: this
+ * box is the limit of where we might select our chunk from.
+ *
+ * The box is obtained by starting from the two obtuse vertices of
+ * the starting P metatile, and then mapping those two vertices
+ * through each expansion pass. This wouldn't work for the _other_
+ * two vertices of the P metatile, which end up in the middle of
+ * another metatile after the first expansion, so that the next
+ * expansion wouldn't find that point in its VertexMapping. But
+ * luckily the two inner P vertices do continue working: they
+ * alternate in subsequent expansions between vertex 1 and vertex
+ * 4 of an F metatile. And those are the ones we need to define a
+ * reliable bounding box - phew!
+ */
+ Point vertices[2];
+ size_t nvertices;
+} MetatileSet;
+
+static MetatileSet *metatile_initial_set(MetatileType type)
+{
+ MetatileSet *s;
+ Metatile *m;
+ Point vertices[MT_MAXVERT];
+ size_t nv;
+
+ s = snew(MetatileSet);
+ s->tiles = newtree234(metatile_cmp);
+
+ m = snew(Metatile);
+ m->type = type;
+ m->start.x = 0;
+ m->start.y = 0;
+ m->orientation.x = 1;
+ m->orientation.y = 0;
+ m->ncoords = 0;
+ add234(s->tiles, m);
+
+ if (type == MT_P) {
+ nv = metatile_vertices(*m, vertices, false);
+ assert(nv == 4);
+ s->vertices[0] = vertices[1];
+ s->vertices[1] = vertices[3];
+ s->nvertices = 2;
+ } else {
+ s->nvertices = 0;
+ }
+
+ return s;
+}
+
+static void metatile_free_set(MetatileSet *s)
+{
+ Metatile *m;
+
+ while ((m = delpos234(s->tiles, 0)) != NULL)
+ sfree(m);
+ freetree234(s->tiles);
+ sfree(s);
+}
+
+typedef struct Queue {
+ Metatile *head, *tail;
+} Queue;
+
+static void map_vertex(VertexMapping *vm, Point out, Queue *queue)
+{
+ size_t i;
+
+ debug(("map_vertex %d,%d -> %d,%d", vm->in.x, vm->in.y, out.x, out.y));
+ if (vm->mapped) {
+ debug((" (already done)\n"));
+ return;
+ }
+ debug(("\n"));
+
+ vm->mapped = true;
+ vm->out = out;
+
+ for (i = 0; i < vm->ntiles; i++) {
+ Metatile *t = vm->tiles[i];
+ if (!t->queued) {
+ t->queued = true;
+ t->qnext = NULL;
+ if (queue->tail)
+ queue->tail->qnext = t;
+ else
+ queue->head = t;
+ queue->tail = t;
+ debug(("queued %c @ %d,%d d=%d,%d\n", "HTPF"[t->type], t->start.x,
+ t->start.y, t->orientation.x, t->orientation.y));
+ }
+ }
+}
+
+/*
+ * Expand a set of metatiles into its next-generation set. Returns the
+ * new set. The old set is not freed, but the auxiliary fields of its
+ * Metatile structures will be used as intermediate storage.
+ */
+static MetatileSet *metatile_set_expand(MetatileSet *si)
+{
+ tree234 *vmap;
+ VertexMapping *vm;
+ Metatile *m;
+ Queue queue = { NULL, NULL };
+ size_t i, j;
+ MetatileSet *so = snew(MetatileSet);
+
+ so->tiles = newtree234(metatile_cmp);
+
+ /*
+ * Enumerate all the vertices in our tiling, and store the set of
+ * tiles they belong to.
+ */
+ vmap = newtree234(vertexmapping_cmp);
+ for (i = 0; (m = index234(si->tiles, i)) != NULL; i++) {
+ Point vertices[MT_MAXVERT];
+ size_t nv = metatile_vertices(*m, vertices, false);
+
+ for (j = 0; j < nv; j++) {
+ VertexMapping *newvm = snew(VertexMapping);
+ newvm->in = vertices[j];
+ newvm->ntiles = 0;
+ newvm->mapped = false;
+
+ vm = add234(vmap, newvm);
+ if (vm != newvm)
+ sfree(newvm);
+
+ assert(vm->ntiles < MT_MAXVDEGREE);
+ vm->tiles[vm->ntiles++] = m;
+ }
+
+ m->queued = false;
+ }
+
+ for (i = 0; (vm = index234(vmap, i)) != NULL; i++) {
+ debug(("vertex @ %d,%d {", vm->in.x, vm->in.y));
+ for (j = 0; j < vm->ntiles; j++) {
+ m = vm->tiles[j];
+ debug(("%s%c @ %d,%d d=%d,%d", j?", ":"", "HTPF"[m->type],
+ m->start.x, m->start.y, m->orientation.x,
+ m->orientation.y));
+ }
+ debug(("}\n"));
+ }
+
+ /*
+ * Initialise an arbitrary vertex to a known location.
+ */
+ {
+ Point p = {0, 0};
+ m = index234(si->tiles, 0);
+ vm = find234(vmap, &m->start, vertexmapping_find);
+ map_vertex(vm, p, &queue);
+ }
+
+ /*
+ * Now process the queue of tiles to be expanded.
+ */
+ debug(("-- start\n"));
+ while (queue.head) {
+ Metatile *m, m_moved;
+ Metatile t[MT_MAXEXPAND];
+ Point vi[MT_MAXVERT], vo[MT_MAXVERT];
+ size_t nv, nt;
+
+ m = queue.head;
+ queue.head = queue.head->qnext;
+ if (!queue.head)
+ queue.tail = NULL;
+
+ debug(("unqueued %c @ %d,%d d=%d,%d\n", "HTPF"[m->type],
+ m->start.x, m->start.y, m->orientation.x, m->orientation.y));
+
+ nv = metatile_vertices(*m, vi, false);
+ metatile_vertices(*m, vo, true);
+
+ /* Find a vertex of this tile that's already mapped, and use
+ * it to determine the placement. */
+ int dx, dy;
+ for (i = 0; i < nv; i++) {
+ vm = find234(vmap, &vi[i], vertexmapping_find);
+ assert(vm);
+ if (vm->mapped) {
+ dx = vm->out.x - vo[i].x;
+ dy = vm->out.y - vo[i].y;
+ debug(("found mapped vertex %d,%d -> %d,%d: "
+ "offset=%d,%d\n",
+ vm->in.x, vm->in.y, vm->out.x, vm->out.y, dx, dy));
+ break;
+ }
+ }
+ assert(i < nv && "Why was this tile queued without a mapped vertex?");
+
+ /* Now map all the rest of the vertices of the tile. */
+ for (i = 0; i < nv; i++) {
+ vm = find234(vmap, &vi[i], vertexmapping_find);
+ vo[i].x += dx;
+ vo[i].y += dy;
+ map_vertex(vm, vo[i], &queue);
+ }
+
+ /* And expand it, substituting in its new starting coordinate. */
+ m_moved = *m; /* structure copy */
+ m_moved.start = vo[0];
+ nt = metatile_expand(m_moved, t);
+ for (i = 0; i < nt; i++) {
+ Metatile *newmt = snew(Metatile);
+ *newmt = t[i]; /* structure copy */
+ newmt->ncoords = 0;
+ debug(("expanded %c @ %d,%d d=%d,%d\n", "HTPF"[newmt->type],
+ newmt->start.x, newmt->start.y, newmt->orientation.x,
+ newmt->orientation.y));
+
+ Metatile *added = add234(so->tiles, newmt);
+ if (added != newmt)
+ sfree(newmt);
+ assert(added->ncoords < lenof(added->coords));
+ added->coords[added->ncoords].parent = m;
+ added->coords[added->ncoords].index = i;
+ added->ncoords++;
+ }
+ }
+
+ for (i = 0; (m = index234(si->tiles, i)) != NULL; i++) {
+ if (!m->queued)
+ debug(("OMITTED %c @ %d,%d d=%d,%d\n", "HTPF"[m->type],
+ m->start.x, m->start.y, m->orientation.x,
+ m->orientation.y));
+ }
+
+ /*
+ * Write out the remapped versions of the tile set's bounding
+ * vertices.
+ */
+ for (i = 0; i < si->nvertices; i++) {
+ vm = find234(vmap, &si->vertices[i], vertexmapping_find);
+ so->vertices[i] = vm->out;
+ }
+ so->nvertices = si->nvertices;
+
+ while ((vm = delpos234(vmap, 0)) != NULL)
+ sfree(vm);
+ freetree234(vmap);
+
+ return so;
+}
+
+typedef struct Hat {
+ Point start, orientation;
+ bool reversed;
+ const Metatile *parent;
+ int index;
+} Hat;
+
+static size_t metatile_hats(const Metatile *m, Hat *out)
+{
+ static const Hat hats_H[] = {
+ {{6, 0}, {1, 0}, false},
+ {{6, 6}, {0, -1}, false},
+ {{0, 12}, {1, 0}, false},
+ {{0, 6}, {-1, 0}, true},
+ };
+ static const Hat hats_T[] = {
+ {{-2, 10}, {-1, 1}, false},
+ };
+ static const Hat hats_P[] = {
+ {{-2, 10}, {-1, 1}, false},
+ {{-2, 16}, {0, 1}, false},
+ };
+ static const Hat hats_F[] = {
+ {{0, 6}, {-1, 1}, false},
+ {{0, 12}, {0, 1}, false},
+ };
+
+ const Hat *hats;
+ size_t nhats;
+ size_t i;
+
+ switch (m->type) {
+ case MT_H:
+ hats = hats_H;
+ nhats = lenof(hats_H);
+ break;
+ case MT_T:
+ hats = hats_T;
+ nhats = lenof(hats_T);
+ break;
+ case MT_P:
+ hats = hats_P;
+ nhats = lenof(hats_P);
+ break;
+ default /* case MT_F */:
+ hats = hats_F;
+ nhats = lenof(hats_F);
+ break;
+ }
+ assert(nhats <= MT_MAXHAT);
+
+ Point orientation_r = left6(m->orientation);
+ for (i = 0; i < nhats; i++) {
+ Hat h = hats[i];
+ out[i].parent = m;
+ out[i].index = i;
+ out[i].start.x = (m->start.x + h.start.x * m->orientation.x +
+ h.start.y * orientation_r.x);
+ out[i].start.y = (m->start.y + h.start.x * m->orientation.y +
+ h.start.y * orientation_r.y);
+ out[i].orientation.x = (h.orientation.x * m->orientation.x +
+ h.orientation.y * orientation_r.x);
+ out[i].orientation.y = (h.orientation.x * m->orientation.y +
+ h.orientation.y * orientation_r.y);
+ out[i].reversed = h.reversed;
+ }
+ return nhats;
+}
+
+static size_t hat_vertices(Hat h, Point *out)
+{
+ static const Point reference_hat[] = {
+ {0, 0}, {3, 0}, {2, 2}, {0, 3}, {-2, 4}, {-3, 3}, {-6, 6}, {-9, 6},
+ {-8, 4}, {-6, 3}, {-6, 0}, {-3, -3}, {-2, -2}, {0, -3},
+ };
+
+ size_t i;
+
+ Point orientation_r;
+ if (h.reversed)
+ orientation_r = right6(h.orientation);
+ else
+ orientation_r = left6(h.orientation);
+ assert(lenof(reference_hat) == HAT_NVERT);
+
+ for (i = 0; i < lenof(reference_hat); i++) {
+ Point v = reference_hat[h.reversed ? HAT_NVERT-1-i : i];
+ out[i].x = h.start.x + v.x * h.orientation.x + v.y * orientation_r.x;
+ out[i].y = h.start.y + v.x * h.orientation.y + v.y * orientation_r.y;
+ }
+ return lenof(reference_hat);
+}
+
+typedef struct BoundingBox {
+ Point bl, tr;
+} BoundingBox;
+
+static bool point_in_bbox(Point p, const BoundingBox *bbox)
+{
+ int xl, xr, x;
+
+ if (!bbox)
+ return true;
+
+ /*
+ * Bounding boxes have vertical edges, not aligned with our basis
+ * vector r. So the 'true' x coordinate of (x,y) is proportional
+ * to 2x+y.
+ */
+ if (p.y < bbox->bl.y || p.y > bbox->tr.y)
+ return false;
+
+ xl = 2*bbox->bl.x + bbox->bl.y;
+ xr = 2*bbox->tr.x + bbox->tr.y;
+ x = 2*p.x + p.y;
+
+ if (x < xl || x > xr)
+ return false;
+
+ return true;
+}
+
+static bool hat_in_bbox(Hat h, const BoundingBox *bbox)
+{
+ Point p[HAT_NVERT];
+ size_t i, np;
+
+ if (!bbox)
+ return true;
+
+ np = hat_vertices(h, p);
+ for (i = 0; i < np; i++)
+ if (!point_in_bbox(p[i], bbox))
+ return false;
+
+ return true;
+}
+
+static Hat *metatile_set_to_hats(MetatileSet *s, size_t *nhats,
+ const BoundingBox *bbox)
+{
+ Metatile *m;
+ size_t i, j, k, n;
+ Hat *h;
+
+ n = 0;
+ for (i = 0; (m = index234(s->tiles, i)) != NULL; i++) {
+ Hat htmp[MT_MAXHAT];
+ size_t nthis = metatile_hats(m, htmp);
+ for (k = 0; k < nthis; k++)
+ if (hat_in_bbox(htmp[k], bbox))
+ n++;
+ }
+
+ *nhats = n;
+ h = snewn(n, Hat);
+
+ j = 0;
+ for (i = 0; (m = index234(s->tiles, i)) != NULL; i++) {
+ Hat htmp[MT_MAXHAT];
+ size_t nthis = metatile_hats(m, htmp);
+ for (k = 0; k < nthis; k++) {
+ if (hat_in_bbox(htmp[k], bbox)) {
+ assert(j < n);
+ h[j++] = htmp[k]; /* structure copy */
+ }
+ }
+ }
+
+ assert(j == n);
+ return h;
+}
+
+#if 0
+void hat_tiling_randomise(struct HatPatchParams *params, random_state *rs)
+{
+ MetatileSet *s, *s2;
+ int x0, x1, y0, y1;
+
+ /*
+ * Iterate until we have a good-sized patch to select a rectangle
+ * from.
+ */
+ s = metatile_initial_set(MT_P);
+ params->iterations = 0;
+
+ while (true) {
+ x0 = 2 * s->vertices[0].x + s->vertices[0].y;
+ x1 = 2 * s->vertices[1].x + s->vertices[1].y;
+ if (x1 < x0) {
+ int t = x1;
+ x1 = x0;
+ x0 = t;
+ }
+ y0 = s->vertices[0].y;
+ y1 = s->vertices[1].y;
+ if (y1 < y0) {
+ int t = y1;
+ y1 = y0;
+ y0 = t;
+ }
+
+ if (50*params->w <= x1-x0 && 50*params->h <= y1-y0)
+ break;
+
+ params->iterations++;
+ s2 = metatile_set_expand(s);
+ metatile_free_set(s);
+ s = s2;
+ }
+
+ /*
+ * Now select that rectangle.
+ */
+ params->x = x0 + random_upto(rs, x1 - x0 - params->w + 1);
+ params->y = y0 + random_upto(rs, y1 - y0 - params->h + 1);
+}
+
+void hat_tiling_generate(struct HatPatchParams *params,
+ hat_tile_callback_fn cb, void *cbctx)
+{
+ MetatileSet *s, *s2;
+ unsigned i;
+ size_t j, nh;
+ BoundingBox bbox;
+ Hat *hats;
+
+ s = metatile_initial_set(MT_P);
+ for (i = 0; i < params->iterations; i++) {
+ s2 = metatile_set_expand(s);
+ metatile_free_set(s);
+ s = s2;
+ }
+
+ bbox.bl.x = (params->x - params->y) / 2;
+ bbox.tr.x = ((params->x + params->w) - (params->y + params->h)) / 2;
+ bbox.bl.y = params->y;
+ bbox.tr.y = params->y + params->h;
+ hats = metatile_set_to_hats(s, &nh, &bbox);
+ for (j = 0; j < nh; j++) {
+ Point vertices[HAT_NVERT];
+ size_t nv = hat_vertices(hats[j], vertices);
+ int out[2 * HAT_NVERT];
+ size_t k;
+
+ for (k = 0; k < nv; k++) {
+ out[2*k] = 2 * vertices[k].x + vertices[k].y;
+ out[2*k+1] = vertices[k].y;
+ }
+
+ cb(cbctx, nv, out);
+ }
+ sfree(hats);
+
+ metatile_free_set(s);
+}
+
+#endif
+
+#ifdef TEST_HAT
+
+/*
+ * Assortment of test modes that output Postscript diagrams.
+ */
+
+static size_t hat_kite_centres(Hat h, Point *out)
+{
+ static const Point reference_hat[] = {
+ {-7,5},{-5,4},{-5,1},{-4,-1},{-1,-1},{-2,1},{-1,2},{1,1},
+ };
+
+ size_t i;
+
+ Point orientation_r;
+ if (h.reversed)
+ orientation_r = right6(h.orientation);
+ else
+ orientation_r = left6(h.orientation);
+ assert(lenof(reference_hat) == HAT_NKITE);
+
+ for (i = 0; i < lenof(reference_hat); i++) {
+ Point v = reference_hat[i];
+ out[i].x = h.start.x + v.x * h.orientation.x + v.y * orientation_r.x;
+ out[i].y = h.start.y + v.x * h.orientation.y + v.y * orientation_r.y;
+ }
+ return lenof(reference_hat);
+}
+
+static inline int round6(int x)
+{
+ int sign = x<0 ? -1 : +1;
+ x *= sign;
+ x += 3;
+ x /= 6;
+ x *= 6;
+ x *= sign;
+ return x;
+}
+
+static inline Point kite_left(Point k)
+{
+ Point centre = { round6(k.x), round6(k.y) };
+ Point offset = { k.x - centre.x, k.y - centre.y };
+ offset = left6(offset);
+ Point r = { centre.x + offset.x, centre.y + offset.y };
+ return r;
+}
+
+static inline Point kite_right(Point k)
+{
+ Point centre = { round6(k.x), round6(k.y) };
+ Point offset = { k.x - centre.x, k.y - centre.y };
+ offset = right6(offset);
+ Point r = { centre.x + offset.x, centre.y + offset.y };
+ return r;
+}
+
+static inline Point kite_forward_left(Point k)
+{
+ Point centre = { round6(k.x), round6(k.y) };
+ Point offset = { k.x - centre.x, k.y - centre.y };
+ Point rotate = left6(offset);
+ Point r = { k.x + rotate.x + offset.x, k.y + rotate.y + offset.y };
+ return r;
+}
+
+static inline Point kite_forward_right(Point k)
+{
+ Point centre = { round6(k.x), round6(k.y) };
+ Point offset = { k.x - centre.x, k.y - centre.y };
+ Point rotate = right6(offset);
+ Point r = { k.x + rotate.x + offset.x, k.y + rotate.y + offset.y };
+ return r;
+}
+
+typedef struct pspoint {
+ float x, y;
+} pspoint;
+
+static inline pspoint pscoords(Point p)
+{
+ pspoint q = { p.x + p.y / 2.0F, p.y * sqrt(0.75) };
+ return q;
+}
+
+typedef struct psbbox {
+ bool started;
+ pspoint bl, tr;
+} psbbox;
+
+static inline void psbbox_add(psbbox *bbox, pspoint p)
+{
+ if (!bbox->started || bbox->bl.x > p.x)
+ bbox->bl.x = p.x;
+ if (!bbox->started || bbox->tr.x < p.x)
+ bbox->tr.x = p.x;
+ if (!bbox->started || bbox->bl.y > p.y)
+ bbox->bl.y = p.y;
+ if (!bbox->started || bbox->tr.y < p.y)
+ bbox->tr.y = p.y;
+ bbox->started = true;
+}
+
+static void draw_metatiles_svg(const Metatile *tiles, size_t n,
+ const Point *bounds, bool coords)
+{
+ size_t i, j;
+ psbbox bbox = { false };
+
+ for (i = 0; i < n; i++) {
+ Point vertices[MT_MAXVERT];
+ size_t nv = metatile_vertices(tiles[i], vertices, false);
+ for (j = 0; j < nv; j++)
+ psbbox_add(&bbox, pscoords(vertices[j]));
+ }
+
+ float ascale = 10, xscale = ascale, yscale = -ascale;
+ float border = 0.2 * ascale; /* leave room for strokes at the edges */
+ float ox = -xscale * bbox.bl.x + border;
+ float oy = -yscale * bbox.tr.y + border;
+
+ printf("\n");
+ printf("\n");
+}
+
+static void draw_metatile_set_svg(
+ MetatileSet *tiles, const Point *bounds, bool coords)
+{
+ /*
+ * Slurp the tree234 of tiles into an array for display.
+ * Tedious, but this test code doesn't have to be particularly
+ * efficient.
+ */
+ size_t nt = count234(tiles->tiles);
+ Metatile *t = snewn(nt, Metatile);
+ size_t i;
+ for (i = 0; i < nt; i++) {
+ Metatile *m = index234(tiles->tiles, i);
+ t[i] = *m; /* structure copy */
+ }
+ draw_metatiles_svg(t, nt, bounds, coords);
+ sfree(t);
+}
+
+static void draw_hats_svg(const Hat *hats, size_t n,
+ const Point *bounds, bool kites, char coordtype)
+{
+ size_t i, j;
+ psbbox bbox = { false };
+
+ for (i = 0; i < n; i++) {
+ Point vertices[HAT_NVERT];
+ size_t nv = hat_vertices(hats[i], vertices);
+ for (j = 0; j < nv; j++)
+ psbbox_add(&bbox, pscoords(vertices[j]));
+ }
+
+ float ascale = (coordtype == 'k' || coordtype == 'K' ? 20 : 10);
+ float xscale = ascale, yscale = -ascale;
+ float border = 0.2 * ascale; /* leave room for strokes at the edges */
+ float ox = -xscale * bbox.bl.x + border;
+ float oy = -yscale * bbox.tr.y + border;
+
+ printf("\n");
+ printf("\n");
+}
+
+typedef enum KiteStep { KS_LEFT, KS_RIGHT, KS_F_LEFT, KS_F_RIGHT } KiteStep;
+
+static inline Point kite_step(Point k, KiteStep step)
+{
+ switch (step) {
+ case KS_LEFT: return kite_left(k);
+ case KS_RIGHT: return kite_right(k);
+ case KS_F_LEFT: return kite_forward_left(k);
+ default /* case KS_F_RIGHT */: return kite_forward_right(k);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc <= 1) {
+ printf("usage: hat-test \n");
+ printf("modes: H,T,P,F display a single unexpanded tile\n");
+ printf(" xH,xT,xP,xF display the expansion of one tile\n");
+ printf(" cH,cT,cP,cF display expansion with tile coords\n");
+ printf(" CH,CT,CP,CF display double expansion with coords\n");
+ printf(" hH,hT,hP,hF display the hats from one tile\n");
+ printf(" HH,HT,HP,HF hats from an expansion, with coords\n");
+ printf(" m1, m2, ... nth expansion of one H metatile\n");
+ printf(" M1, M2, ... nth expansion turned into real hats\n");
+ printf(" --hat show the kites in a single hat\n");
+ printf(" --tables generate hat-tables.h for hat.c\n");
+ return 0;
+ }
+
+ if (!strcmp(argv[1], "H") || !strcmp(argv[1], "T") ||
+ !strcmp(argv[1], "P") || !strcmp(argv[1], "F")) {
+ MetatileType type = (argv[1][0] == 'H' ? MT_H :
+ argv[1][0] == 'T' ? MT_T :
+ argv[1][0] == 'P' ? MT_P : MT_F);
+ Metatile m = {type, {0, 0}, {1, 0}};
+ draw_metatiles_svg(&m, 1, NULL, false);
+ return 0;
+ }
+
+ if (!strcmp(argv[1], "xH") || !strcmp(argv[1], "xT") ||
+ !strcmp(argv[1], "xP") || !strcmp(argv[1], "xF")) {
+ MetatileType type = (argv[1][1] == 'H' ? MT_H :
+ argv[1][1] == 'T' ? MT_T :
+ argv[1][1] == 'P' ? MT_P : MT_F);
+ Metatile m = {type, {0, 0}, {1, 0}};
+ Metatile t[MT_MAXEXPAND];
+ size_t nt = metatile_expand(m, t);
+ draw_metatiles_svg(t, nt, NULL, false);
+ return 0;
+ }
+
+ if (argv[1][0] && argv[1][1] &&
+ strchr("cC", argv[1][0]) && strchr("HTPF", argv[1][1])) {
+ MetatileType type = (argv[1][1] == 'H' ? MT_H :
+ argv[1][1] == 'T' ? MT_T :
+ argv[1][1] == 'P' ? MT_P : MT_F);
+ MetatileSet *t[3];
+ int nsets = (argv[1][0] == 'c' ? 2 : 3);
+ int i;
+
+ t[0] = metatile_initial_set(type);
+ for (i = 1; i < nsets; i++)
+ t[i] = metatile_set_expand(t[i-1]);
+ draw_metatile_set_svg(t[nsets-1], NULL, true);
+ for (i = 0; i < nsets; i++)
+ metatile_free_set(t[i]);
+ return 0;
+ }
+
+ if (!strcmp(argv[1], "hH") || !strcmp(argv[1], "hT") ||
+ !strcmp(argv[1], "hP") || !strcmp(argv[1], "hF")) {
+ MetatileType type = (
+ !strcmp(argv[1], "hH") ? MT_H :
+ !strcmp(argv[1], "hT") ? MT_T :
+ !strcmp(argv[1], "hP") ? MT_P : MT_F);
+ Metatile m = {type, {0, 0}, {1, 0}};
+ Hat h[MT_MAXHAT];
+ size_t nh = metatile_hats(&m, h);
+ draw_hats_svg(h, nh, NULL, false, 'h');
+ return 0;
+ }
+
+ if (!strcmp(argv[1], "--hat")) {
+ Hat h = { { 0, 0 }, { 1, 0 }, false, NULL, 0 };
+ draw_hats_svg(&h, 1, NULL, true, 'K');
+ return 0;
+ }
+
+ if (argv[1][0] == 'H' && argv[1][1] && strchr("HTPF", argv[1][1])) {
+ MetatileType type = (argv[1][1] == 'H' ? MT_H :
+ argv[1][1] == 'T' ? MT_T :
+ argv[1][1] == 'P' ? MT_P : MT_F);
+ MetatileSet *t[2];
+ size_t i, nh;
+
+ t[0] = metatile_initial_set(type);
+ t[1] = metatile_set_expand(t[0]);
+ Hat *h = metatile_set_to_hats(t[1], &nh, NULL);
+ draw_hats_svg(h, nh, NULL, true, 'k');
+ sfree(h);
+ for (i = 0; i < 2; i++)
+ metatile_free_set(t[i]);
+ return 0;
+ }
+
+ if (argv[1][0] == 'm' || argv[1][0] == 'M') {
+ int niter = atoi(argv[1] + 1);
+ MetatileSet *tiles = metatile_initial_set(MT_P);
+
+ while (niter-- > 0) {
+ MetatileSet *t2 = metatile_set_expand(tiles);
+ metatile_free_set(tiles);
+ tiles = t2;
+ }
+
+ if (argv[1][0] == 'M') {
+ size_t nh;
+ Hat *h = metatile_set_to_hats(tiles, &nh, NULL);
+ draw_hats_svg(h, nh, tiles->vertices, false, 0);
+ sfree(h);
+ } else {
+ draw_metatile_set_svg(tiles, tiles->vertices, false);
+ }
+
+ metatile_free_set(tiles);
+
+ return 0;
+ }
+
+ if (!strcmp(argv[1], "--tables")) {
+ size_t i, j, k;
+
+ printf("/*\n"
+ " * Header file autogenerated by aux/hatgen.c\n"
+ " *\n"
+ " * To regenerate, run 'hatgen --tables > hat-tables.h'\n"
+ " */\n\n");
+
+ static const char HTPF[] = "HTPF";
+
+ printf("static const unsigned hats_in_metatile[] = {");
+ for (i = 0; i < 4; i++) {
+ Metatile m = {i, {0, 0}, {1, 0}};
+ Hat h[MT_MAXHAT];
+ size_t nh = metatile_hats(&m, h);
+ printf(" %zu,", nh);
+ }
+ printf(" };\n\n");
+
+ {
+ struct Parent {
+ MetatileType t;
+ unsigned index;
+ } parents[4][4*MT_MAXEXPAND];
+ size_t psizes[4] = {0, 0, 0, 0};
+ size_t csizes[4] = {0, 0, 0, 0};
+
+ for (i = 0; i < 4; i++) {
+ Metatile m = {i, {0, 0}, {1, 0}};
+ Metatile t[MT_MAXEXPAND];
+ size_t nt = metatile_expand(m, t);
+
+ printf("static const TileType children_%c[] = {\n"
+ " ", HTPF[i]);
+ for (j = 0; j < nt; j++) {
+ MetatileType c = t[j].type;
+ parents[c][psizes[c]].t = i;
+ parents[c][psizes[c]].index = j;
+ psizes[c]++;
+ csizes[i]++;
+ printf(" TT_%c,", HTPF[c]);
+ }
+ printf("\n};\n");
+ }
+
+ printf("static const TileType *const children[] = {\n");
+ for (i = 0; i < 4; i++)
+ printf(" children_%c,\n", HTPF[i]);
+ printf("};\n");
+ printf("static const size_t nchildren[] = {\n");
+ for (i = 0; i < 4; i++)
+ printf(" %u,\n", (unsigned)csizes[i]);
+ printf("};\n\n");
+
+ for (i = 0; i < 4; i++) {
+ printf("static const MetatilePossibleParent "
+ "permitted_parents_%c[] = {\n", HTPF[i]);
+ for (j = 0; j < psizes[i]; j++)
+ printf(" { TT_%c, %u },\n", HTPF[parents[i][j].t],
+ parents[i][j].index);
+ printf("};\n");
+ }
+
+ printf("static const MetatilePossibleParent *const "
+ "permitted_parents[] = {\n");
+ for (i = 0; i < 4; i++)
+ printf(" permitted_parents_%c,\n", HTPF[i]);
+ printf("};\n");
+
+ printf("static const size_t n_permitted_parents[] = {\n");
+ for (i = 0; i < 4; i++)
+ printf(" %u,\n", (unsigned)psizes[i]);
+ printf("};\n\n");
+ }
+
+ {
+ for (i = 0; i < 4; i++) {
+ MetatileSet *t[2];
+ size_t j, k, nh, nmeta, ti;
+ struct list {
+ Point kite;
+ unsigned ik, ih, im;
+ } list[8*MT_MAXHAT*MT_MAXEXPAND];
+ size_t len = 0;
+
+ t[0] = metatile_initial_set(i);
+ t[1] = metatile_set_expand(t[0]);
+ Hat *h = metatile_set_to_hats(t[1], &nh, NULL);
+
+ printf("static const KitemapEntry kitemap_%c[] = {\n",
+ HTPF[i]);
+
+ Point origin = h[0].start;
+ for (j = 0; j < nh; j++) {
+ Point kites[HAT_NKITE];
+ size_t nk = hat_kite_centres(h[j], kites);
+ for (k = 0; k < nk; k++) {
+ struct list *le = &list[len++];
+ le->kite.x = kites[k].x - origin.x;
+ le->kite.y = kites[k].y - origin.y;
+ le->ik = k;
+ le->ih = h[j].index;
+ le->im = h[j].parent->coords[0].index;
+#if 0
+ printf("// %d,%d = %u.%u.%u\n", le->kite.x, le->kite.y, le->ik, le->ih, le->im);
+#endif
+ }
+ }
+
+ nmeta = count234(t[1]->tiles);
+ for (ti = 0; ti < 8 * 4 * nmeta; ti++) {
+ unsigned ik = ti % 8;
+ unsigned ih = ti / 8 % 4;
+ unsigned im = ti / (8*4);
+ struct list *src = NULL, *dst = NULL;
+ int istep;
+
+ for (j = 0; j < len; j++) {
+ struct list *tmp = &list[j];
+ if (tmp->ik == ik && tmp->ih == ih && tmp->im == im) {
+ src = tmp;
+ break;
+ }
+ }
+ if (ik == 0) {
+ printf(" /* hat #%u in metatile #%u (type %c)",
+ ih, im, HTPF[((Metatile *)index234(
+ t[1]->tiles, im))->type]);
+ if (!src)
+ printf(" does not exist");
+ printf(" */\n");
+ }
+#if 0
+ if (src)
+ printf(" // src=%d,%d\n", src->kite.x, src->kite.y);
+#endif
+ printf(" ");
+
+ for (istep = 0; istep < 4; istep++) {
+ KiteStep step = istep;
+ dst = NULL;
+ if (src) {
+ Point pdst = kite_step(src->kite, step);
+#if 0
+ printf(" /* dst=%d,%d */", pdst.x, pdst.y);
+#endif
+ for (k = 0; k < len; k++) {
+ struct list *tmp = &list[k];
+ if (tmp->kite.x == pdst.x &&
+ tmp->kite.y == pdst.y) {
+ dst = tmp;
+ break;
+ }
+ }
+ }
+ if (!dst) {
+ printf(" {-1,-1,-1},");
+ } else {
+ printf(" {%u,%u,%u},", dst->ik, dst->ih, dst->im);
+ }
+ }
+ printf("\n");
+ }
+ printf("};\n");
+
+ sfree(h);
+ for (j = 0; j < 2; j++)
+ metatile_free_set(t[j]);
+ }
+
+ printf("static const KitemapEntry *const "
+ "kitemap[] = {\n");
+ for (i = 0; i < 4; i++)
+ printf(" kitemap_%c,\n", HTPF[i]);
+ printf("};\n\n");
+
+ }
+
+ {
+ for (i = 0; i < 4; i++) {
+ MetatileSet *t[3];
+ Metatile *m;
+ int map[MT_MAXEXPAND * MT_MAXEXPAND];
+ size_t maplen;
+
+ for (j = 0; j < lenof(map); j++)
+ map[j] = -1;
+
+ t[0] = metatile_initial_set(i);
+ for (j = 1; j < 3; j++)
+ t[j] = metatile_set_expand(t[j-1]);
+
+ for (j = 0; (m = index234(t[2]->tiles, j)) != NULL; j++) {
+ unsigned coords[4];
+ size_t ncoords = 0;
+ int cindex;
+
+#if 0
+ printf("// ***\n");
+#endif
+ for (cindex = 0; cindex < m->ncoords; cindex++) {
+#if 0
+ printf("// %d.%d\n", (int)m->coords[cindex].index,
+ (int)m->coords[cindex].parent->coords[0].index);
+#endif
+ coords[ncoords++] = (
+ m->coords[cindex].index + MT_MAXEXPAND *
+ m->coords[cindex].parent->coords[0].index);
+ }
+
+ unsigned prev = ncoords-1;
+ for (k = 0; k < ncoords; k++) {
+ map[coords[prev]] = coords[k];
+ prev = k;
+ }
+ }
+
+ printf("static const MetamapEntry metamap_%c[] = {\n",
+ HTPF[i]);
+ maplen = MT_MAXEXPAND * count234(t[1]->tiles);
+ for (j = 0; j < maplen; j++) {
+ printf(" /* %u, %u -> */ ",
+ (unsigned)(j % MT_MAXEXPAND),
+ (unsigned)(j / MT_MAXEXPAND));
+ if (map[j] == -1) {
+ printf("{-1,-1}, /* does not exist */\n");
+ } else {
+ printf("{%u, %u},",
+ (unsigned)(map[j] % MT_MAXEXPAND),
+ (unsigned)(map[j] / MT_MAXEXPAND));
+ if (map[j] == j)
+ printf(" /* no alternatives */");
+ printf("\n");
+ }
+ }
+ printf("};\n");
+
+ for (j = 0; j < 3; j++)
+ metatile_free_set(t[j]);
+ }
+
+ printf("static const MetamapEntry *const "
+ "metamap[] = {\n");
+ for (i = 0; i < 4; i++)
+ printf(" metamap_%c,\n", HTPF[i]);
+ printf("};\n");
+ }
+
+ return 0;
+ }
+
+ fprintf(stderr, "unknown test mode '%s'\n", argv[1]);
+ return 1;
+}
+#endif
diff --git a/grid.c b/grid.c
index 21353ba..bac8be8 100644
--- a/grid.c
+++ b/grid.c
@@ -19,6 +19,7 @@
#include "tree234.h"
#include "grid.h"
#include "penrose.h"
+#include "hat.h"
/* Debugging options */
@@ -3401,6 +3402,159 @@ static grid *grid_new_penrose_p3_thick(int width, int height, const char *desc)
return grid_new_penrose(width, height, PENROSE_P3, desc);
}
+#define HATS_TILESIZE 32
+#define HATS_XSQUARELEN 4
+#define HATS_YSQUARELEN 6
+#define HATS_XUNIT 14
+#define HATS_YUNIT 8
+
+static const char *grid_validate_params_hats(
+ int width, int height)
+{
+ int l = HATS_TILESIZE;
+
+ if (width > INT_MAX / l || /* xextent */
+ height > INT_MAX / l || /* yextent */
+ width > INT_MAX / (6 * height)) /* max_dots */
+ return "Grid must not be unreasonably large";
+ return NULL;
+}
+
+static void grid_size_hats(int width, int height,
+ int *tilesize, int *xextent, int *yextent)
+{
+ *tilesize = HATS_TILESIZE;
+ *xextent = width * HATS_XUNIT * HATS_XSQUARELEN;
+ *yextent = height * HATS_YUNIT * HATS_YSQUARELEN;
+}
+
+static char *grid_new_desc_hats(
+ grid_type type, int width, int height, random_state *rs)
+{
+ char *buf, *p;
+ size_t bufmax, i;
+ struct HatPatchParams hp;
+
+ hat_tiling_randomise(&hp, width, height, rs);
+
+ bufmax = 3 * hp.ncoords + 2;
+ buf = snewn(bufmax, char);
+ p = buf;
+ for (i = 0; i < hp.ncoords; i++) {
+ assert(hp.coords[i] < 100); /* at most 2 digits */
+ assert(p - buf <= bufmax-4); /* room for 2 digits, comma and NUL */
+ p += sprintf(p, "%d,", (int)hp.coords[i]);
+ }
+ assert(p - buf <= bufmax-2); /* room for final letter and NUL */
+ p[0] = hp.final_metatile;
+ p[1] = '\0';
+
+ sfree(hp.coords);
+ return buf;
+}
+
+/* Shared code between validating and reading grid descs.
+ * Always allocates hp->coords, whether or not it returns an error. */
+static const char *grid_desc_to_hat_params(
+ const char *desc, struct HatPatchParams *hp)
+{
+ size_t maxcoords;
+ const char *p = desc;
+
+ maxcoords = (strlen(desc) + 1) / 2;
+ hp->coords = snewn(maxcoords, unsigned char);
+ hp->ncoords = 0;
+
+ while (isdigit((unsigned char)*p)) {
+ const char *p_orig = p;
+ int n = atoi(p);
+ while (*p && isdigit((unsigned char)*p)) p++;
+ if (*p != ',')
+ return "expected ',' in grid description";
+ if (p - p_orig > 2 || n > 0xFF)
+ return "too-large coordinate in grid description";
+ p++; /* eat the comma */
+
+ /* This assert should be guaranteed by the way we calculated
+ * maxcoords, so a failure of this check is a bug in this
+ * function, not an indication of an invalid input string */
+ assert(hp->ncoords < maxcoords);
+ hp->coords[hp->ncoords++] = n;
+ }
+
+ if (*p == 'H' || *p == 'T' || *p == 'P' || *p == 'F')
+ hp->final_metatile = *p;
+ else
+ return "invalid character in grid description";
+
+ return NULL;
+}
+
+static const char *grid_validate_desc_hats(
+ grid_type type, int width, int height, const char *desc)
+{
+ struct HatPatchParams hp;
+ const char *error = NULL;
+
+ error = grid_desc_to_hat_params(desc, &hp);
+ if (!error)
+ error = hat_tiling_params_invalid(&hp);
+
+ sfree(hp.coords);
+ return error;
+}
+
+struct hatcontext {
+ grid *g;
+ tree234 *points;
+};
+
+static void grid_hats_callback(void *vctx, size_t nvertices, int *coords)
+{
+ struct hatcontext *ctx = (struct hatcontext *)vctx;
+ size_t i;
+
+ grid_face_add_new(ctx->g, nvertices);
+ for (i = 0; i < nvertices; i++) {
+ grid_dot *d = grid_get_dot(
+ ctx->g, ctx->points,
+ coords[2*i] * HATS_XUNIT,
+ coords[2*i+1] * HATS_YUNIT);
+ grid_face_set_dot(ctx->g, d, i);
+ }
+}
+
+static grid *grid_new_hats(int width, int height, const char *desc)
+{
+ struct HatPatchParams hp;
+ const char *error = NULL;
+
+ error = grid_desc_to_hat_params(desc, &hp);
+ assert(error == NULL && "grid_validate_desc_hats should have failed");
+
+ /* Upper bounds - don't have to be exact */
+ int max_faces = (width * height * 6 + 7) / 8;
+ int max_dots = width * height * 6 + width * 2 + height * 2 + 1;
+
+ struct hatcontext ctx[1];
+
+ ctx->g = grid_empty();
+ ctx->g->tilesize = HATS_TILESIZE;
+ ctx->g->faces = snewn(max_faces, grid_face);
+ ctx->g->dots = snewn(max_dots, grid_dot);
+
+ ctx->points = newtree234(grid_point_cmp_fn);
+
+ hat_tiling_generate(&hp, width, height, grid_hats_callback, ctx);
+
+ freetree234(ctx->points);
+ sfree(hp.coords);
+
+ grid_trim_vigorously(ctx->g);
+ grid_make_consistent(ctx->g);
+ return ctx->g;
+}
+
/* ----------- End of grid generators ------------- */
#define FNVAL(upper,lower) &grid_validate_params_ ## lower,
@@ -3425,6 +3579,8 @@ char *grid_new_desc(grid_type type, int width, int height, random_state *rs)
{
if (type == GRID_PENROSE_P2 || type == GRID_PENROSE_P3) {
return grid_new_desc_penrose(type, width, height, rs);
+ } else if (type == GRID_HATS) {
+ return grid_new_desc_hats(type, width, height, rs);
} else if (type == GRID_TRIANGULAR) {
return dupstr("0"); /* up-to-date version of triangular grid */
} else {
@@ -3437,6 +3593,8 @@ const char *grid_validate_desc(grid_type type, int width, int height,
{
if (type == GRID_PENROSE_P2 || type == GRID_PENROSE_P3) {
return grid_validate_desc_penrose(type, width, height, desc);
+ } else if (type == GRID_HATS) {
+ return grid_validate_desc_hats(type, width, height, desc);
} else if (type == GRID_TRIANGULAR) {
return grid_validate_desc_triangular(type, width, height, desc);
} else {
diff --git a/grid.h b/grid.h
index 69108d4..c0246c1 100644
--- a/grid.h
+++ b/grid.h
@@ -109,7 +109,9 @@ typedef struct grid {
A(GREATGREATDODECAGONAL,greatgreatdodecagonal) \
A(COMPASSDODECAGONAL,compassdodecagonal) \
A(PENROSE_P2,penrose_p2_kite) \
- A(PENROSE_P3,penrose_p3_thick)
+ A(PENROSE_P3,penrose_p3_thick) \
+ A(HATS,hats) \
+ /* end of list */
#define ENUM(upper,lower) GRID_ ## upper,
typedef enum grid_type { GRIDGEN_LIST(ENUM) GRID_TYPE_MAX } grid_type;
diff --git a/hat-tables.h b/hat-tables.h
new file mode 100644
index 0000000..5b3b0ed
--- /dev/null
+++ b/hat-tables.h
@@ -0,0 +1,2183 @@
+/*
+ * Header file autogenerated by aux/hatgen.c
+ *
+ * To regenerate, run 'hatgen --tables > hat-tables.h'
+ */
+
+static const unsigned hats_in_metatile[] = { 4, 1, 2, 2, };
+
+static const TileType children_H[] = {
+ TT_H, TT_H, TT_H, TT_T, TT_P, TT_P, TT_P, TT_F, TT_F, TT_F, TT_F, TT_F, TT_F,
+};
+static const TileType children_T[] = {
+ TT_H, TT_P, TT_P, TT_P, TT_F, TT_F, TT_F,
+};
+static const TileType children_P[] = {
+ TT_H, TT_H, TT_P, TT_P, TT_P, TT_F, TT_F, TT_F, TT_F, TT_F, TT_F,
+};
+static const TileType children_F[] = {
+ TT_H, TT_H, TT_P, TT_P, TT_F, TT_F, TT_F, TT_F, TT_F, TT_F, TT_F,
+};
+static const TileType *const children[] = {
+ children_H,
+ children_T,
+ children_P,
+ children_F,
+};
+static const size_t nchildren[] = {
+ 13,
+ 7,
+ 11,
+ 11,
+};
+
+static const MetatilePossibleParent permitted_parents_H[] = {
+ { TT_H, 0 },
+ { TT_H, 1 },
+ { TT_H, 2 },
+ { TT_T, 0 },
+ { TT_P, 0 },
+ { TT_P, 1 },
+ { TT_F, 0 },
+ { TT_F, 1 },
+};
+static const MetatilePossibleParent permitted_parents_T[] = {
+ { TT_H, 3 },
+};
+static const MetatilePossibleParent permitted_parents_P[] = {
+ { TT_H, 4 },
+ { TT_H, 5 },
+ { TT_H, 6 },
+ { TT_T, 1 },
+ { TT_T, 2 },
+ { TT_T, 3 },
+ { TT_P, 2 },
+ { TT_P, 3 },
+ { TT_P, 4 },
+ { TT_F, 2 },
+ { TT_F, 3 },
+};
+static const MetatilePossibleParent permitted_parents_F[] = {
+ { TT_H, 7 },
+ { TT_H, 8 },
+ { TT_H, 9 },
+ { TT_H, 10 },
+ { TT_H, 11 },
+ { TT_H, 12 },
+ { TT_T, 4 },
+ { TT_T, 5 },
+ { TT_T, 6 },
+ { TT_P, 5 },
+ { TT_P, 6 },
+ { TT_P, 7 },
+ { TT_P, 8 },
+ { TT_P, 9 },
+ { TT_P, 10 },
+ { TT_F, 4 },
+ { TT_F, 5 },
+ { TT_F, 6 },
+ { TT_F, 7 },
+ { TT_F, 8 },
+ { TT_F, 9 },
+ { TT_F, 10 },
+};
+static const MetatilePossibleParent *const permitted_parents[] = {
+ permitted_parents_H,
+ permitted_parents_T,
+ permitted_parents_P,
+ permitted_parents_F,
+};
+static const size_t n_permitted_parents[] = {
+ 8,
+ 1,
+ 11,
+ 22,
+};
+
+static const KitemapEntry kitemap_H[] = {
+ /* hat #0 in metatile #0 (type H) */
+ {1,0,0}, {7,3,0}, {3,0,4}, {4,0,4},
+ {4,3,0}, {0,0,0}, {5,0,0}, {2,0,0},
+ {3,0,4}, {3,0,0}, {1,0,0}, {5,0,0},
+ {2,0,0}, {1,2,1}, {4,0,0}, {6,2,1},
+ {3,0,3}, {5,0,0}, {6,2,1}, {3,0,0},
+ {4,0,0}, {6,0,0}, {2,0,0}, {1,0,0},
+ {5,0,0}, {7,0,0}, {4,3,0}, {3,3,0},
+ {6,0,0}, {2,0,3}, {7,1,0}, {0,0,3},
+ /* hat #1 in metatile #0 (type H) */
+ {1,1,0}, {2,0,5}, {7,1,8}, {0,0,5},
+ {3,0,2}, {0,1,0}, {5,1,0}, {2,1,0},
+ {7,1,8}, {3,1,0}, {1,1,0}, {5,1,0},
+ {2,1,0}, {4,1,8}, {4,1,0}, {0,3,0},
+ {2,3,0}, {5,1,0}, {0,3,0}, {3,1,0},
+ {4,1,0}, {6,1,0}, {2,1,0}, {1,1,0},
+ {5,1,0}, {7,1,0}, {3,0,2}, {4,0,2},
+ {6,1,0}, {3,3,0}, {0,0,3}, {7,0,0},
+ /* hat #2 in metatile #0 (type H) */
+ {1,2,0}, {1,0,7}, {7,1,4}, {6,0,7},
+ {3,0,8}, {0,2,0}, {5,2,0}, {2,2,0},
+ {7,1,4}, {3,2,0}, {1,2,0}, {5,2,0},
+ {2,2,0}, {4,1,4}, {4,2,0}, {6,3,0},
+ {1,3,0}, {5,2,0}, {6,3,0}, {3,2,0},
+ {4,2,0}, {6,2,0}, {2,2,0}, {1,2,0},
+ {5,2,0}, {7,2,0}, {3,0,8}, {4,0,8},
+ {6,2,0}, {0,3,0}, {3,1,8}, {4,1,8},
+ /* hat #3 in metatile #0 (type H) */
+ {7,2,0}, {1,3,0}, {3,1,0}, {4,1,0},
+ {0,3,0}, {4,2,0}, {2,3,0}, {5,3,0},
+ {3,3,0}, {4,1,0}, {5,3,0}, {1,3,0},
+ {7,1,0}, {2,3,0}, {6,0,0}, {4,3,0},
+ {5,3,0}, {1,0,0}, {3,3,0}, {6,0,0},
+ {6,3,0}, {4,3,0}, {1,3,0}, {2,3,0},
+ {7,3,0}, {5,3,0}, {3,2,0}, {4,2,0},
+ {0,0,0}, {6,3,0}, {3,1,4}, {4,1,4},
+ /* hat #0 in metatile #1 (type H) */
+ {1,0,1}, {7,3,1}, {3,0,9}, {4,0,9},
+ {4,3,1}, {0,0,1}, {5,0,1}, {2,0,1},
+ {3,0,9}, {3,0,1}, {1,0,1}, {5,0,1},
+ {2,0,1}, {1,0,10}, {4,0,1}, {6,0,10},
+ {0,0,6}, {5,0,1}, {6,0,10}, {3,0,1},
+ {4,0,1}, {6,0,1}, {2,0,1}, {1,0,1},
+ {5,0,1}, {7,0,1}, {4,3,1}, {3,3,1},
+ {6,0,1}, {1,0,6}, {7,1,1}, {6,0,6},
+ /* hat #1 in metatile #1 (type H) */
+ {1,1,1}, {1,1,2}, {7,0,3}, {6,1,2},
+ {0,1,6}, {0,1,1}, {5,1,1}, {2,1,1},
+ {7,0,3}, {3,1,1}, {1,1,1}, {5,1,1},
+ {2,1,1}, {4,0,3}, {4,1,1}, {0,3,1},
+ {2,3,1}, {5,1,1}, {0,3,1}, {3,1,1},
+ {4,1,1}, {6,1,1}, {2,1,1}, {1,1,1},
+ {5,1,1}, {7,1,1}, {0,1,6}, {7,0,6},
+ {6,1,1}, {3,3,1}, {6,0,6}, {7,0,1},
+ /* hat #2 in metatile #1 (type H) */
+ {1,2,1}, {2,0,4}, {7,1,9}, {0,0,4},
+ {3,0,0}, {0,2,1}, {5,2,1}, {2,2,1},
+ {7,1,9}, {3,2,1}, {1,2,1}, {5,2,1},
+ {2,2,1}, {4,1,9}, {4,2,1}, {6,3,1},
+ {1,3,1}, {5,2,1}, {6,3,1}, {3,2,1},
+ {4,2,1}, {6,2,1}, {2,2,1}, {1,2,1},
+ {5,2,1}, {7,2,1}, {3,0,0}, {4,0,0},
+ {6,2,1}, {0,3,1}, {3,0,3}, {4,0,3},
+ /* hat #3 in metatile #1 (type H) */
+ {7,2,1}, {1,3,1}, {3,1,1}, {4,1,1},
+ {0,3,1}, {4,2,1}, {2,3,1}, {5,3,1},
+ {3,3,1}, {4,1,1}, {5,3,1}, {1,3,1},
+ {7,1,1}, {2,3,1}, {6,0,1}, {4,3,1},
+ {5,3,1}, {1,0,1}, {3,3,1}, {6,0,1},
+ {6,3,1}, {4,3,1}, {1,3,1}, {2,3,1},
+ {7,3,1}, {5,3,1}, {3,2,1}, {4,2,1},
+ {0,0,1}, {6,3,1}, {3,1,9}, {4,1,9},
+ /* hat #0 in metatile #2 (type H) */
+ {1,0,2}, {7,3,2}, {3,0,5}, {4,0,5},
+ {4,3,2}, {0,0,2}, {5,0,2}, {2,0,2},
+ {3,0,5}, {3,0,2}, {1,0,2}, {5,0,2},
+ {2,0,2}, {1,1,0}, {4,0,2}, {6,1,0},
+ {0,0,3}, {5,0,2}, {6,1,0}, {3,0,2},
+ {4,0,2}, {6,0,2}, {2,0,2}, {1,0,2},
+ {5,0,2}, {7,0,2}, {4,3,2}, {3,3,2},
+ {6,0,2}, {1,0,3}, {7,1,2}, {6,0,3},
+ /* hat #1 in metatile #2 (type H) */
+ {1,1,2}, {1,1,6}, {7,1,12}, {6,1,6},
+ {0,1,1}, {0,1,2}, {5,1,2}, {2,1,2},
+ {7,1,12}, {3,1,2}, {1,1,2}, {5,1,2},
+ {2,1,2}, {4,1,12}, {4,1,2}, {0,3,2},
+ {2,3,2}, {5,1,2}, {0,3,2}, {3,1,2},
+ {4,1,2}, {6,1,2}, {2,1,2}, {1,1,2},
+ {5,1,2}, {7,1,2}, {0,1,1}, {7,0,3},
+ {6,1,2}, {3,3,2}, {6,0,3}, {7,0,2},
+ /* hat #2 in metatile #2 (type H) */
+ {1,2,2}, {1,0,11}, {7,1,5}, {6,0,11},
+ {3,0,12}, {0,2,2}, {5,2,2}, {2,2,2},
+ {7,1,5}, {3,2,2}, {1,2,2}, {5,2,2},
+ {2,2,2}, {4,1,5}, {4,2,2}, {6,3,2},
+ {1,3,2}, {5,2,2}, {6,3,2}, {3,2,2},
+ {4,2,2}, {6,2,2}, {2,2,2}, {1,2,2},
+ {5,2,2}, {7,2,2}, {3,0,12}, {4,0,12},
+ {6,2,2}, {0,3,2}, {3,1,12}, {4,1,12},
+ /* hat #3 in metatile #2 (type H) */
+ {7,2,2}, {1,3,2}, {3,1,2}, {4,1,2},
+ {0,3,2}, {4,2,2}, {2,3,2}, {5,3,2},
+ {3,3,2}, {4,1,2}, {5,3,2}, {1,3,2},
+ {7,1,2}, {2,3,2}, {6,0,2}, {4,3,2},
+ {5,3,2}, {1,0,2}, {3,3,2}, {6,0,2},
+ {6,3,2}, {4,3,2}, {1,3,2}, {2,3,2},
+ {7,3,2}, {5,3,2}, {3,2,2}, {4,2,2},
+ {0,0,2}, {6,3,2}, {3,1,5}, {4,1,5},
+ /* hat #0 in metatile #3 (type T) */
+ {1,0,3}, {4,0,2}, {7,0,0}, {7,1,0},
+ {7,0,2}, {0,0,3}, {5,0,3}, {2,0,3},
+ {7,0,0}, {3,0,3}, {1,0,3}, {5,0,3},
+ {2,0,3}, {4,0,0}, {4,0,3}, {7,2,1},
+ {3,1,1}, {5,0,3}, {7,2,1}, {3,0,3},
+ {4,0,3}, {6,0,3}, {2,0,3}, {1,0,3},
+ {5,0,3}, {7,0,3}, {7,0,2}, {7,1,2},
+ {6,0,3}, {2,1,1}, {6,1,2}, {0,1,1},
+ /* hat #1 in metatile #3 (type T) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #2 in metatile #3 (type T) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #3 (type T) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #4 (type P) */
+ {1,0,4}, {-1,-1,-1}, {0,2,1}, {7,1,9},
+ {-1,-1,-1}, {0,0,4}, {5,0,4}, {2,0,4},
+ {0,2,1}, {3,0,4}, {1,0,4}, {5,0,4},
+ {2,0,4}, {2,0,0}, {4,0,4}, {0,0,0},
+ {3,1,4}, {5,0,4}, {0,0,0}, {3,0,4},
+ {4,0,4}, {6,0,4}, {2,0,4}, {1,0,4},
+ {5,0,4}, {7,0,4}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,4}, {2,1,4}, {-1,-1,-1}, {0,1,4},
+ /* hat #1 in metatile #4 (type P) */
+ {1,1,4}, {-1,-1,-1}, {7,0,4}, {-1,-1,-1},
+ {0,1,7}, {0,1,4}, {5,1,4}, {2,1,4},
+ {7,0,4}, {3,1,4}, {1,1,4}, {5,1,4},
+ {2,1,4}, {4,0,4}, {4,1,4}, {7,3,0},
+ {3,2,0}, {5,1,4}, {7,3,0}, {3,1,4},
+ {4,1,4}, {6,1,4}, {2,1,4}, {1,1,4},
+ {5,1,4}, {7,1,4}, {0,1,7}, {7,0,7},
+ {6,1,4}, {2,2,0}, {6,0,7}, {0,2,0},
+ /* hat #2 in metatile #4 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #4 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #5 (type P) */
+ {1,0,5}, {-1,-1,-1}, {0,1,0}, {7,1,8},
+ {-1,-1,-1}, {0,0,5}, {5,0,5}, {2,0,5},
+ {0,1,0}, {3,0,5}, {1,0,5}, {5,0,5},
+ {2,0,5}, {2,0,2}, {4,0,5}, {0,0,2},
+ {3,1,5}, {5,0,5}, {0,0,2}, {3,0,5},
+ {4,0,5}, {6,0,5}, {2,0,5}, {1,0,5},
+ {5,0,5}, {7,0,5}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,5}, {2,1,5}, {-1,-1,-1}, {0,1,5},
+ /* hat #1 in metatile #5 (type P) */
+ {1,1,5}, {-1,-1,-1}, {7,0,5}, {-1,-1,-1},
+ {0,1,11}, {0,1,5}, {5,1,5}, {2,1,5},
+ {7,0,5}, {3,1,5}, {1,1,5}, {5,1,5},
+ {2,1,5}, {4,0,5}, {4,1,5}, {7,3,2},
+ {3,2,2}, {5,1,5}, {7,3,2}, {3,1,5},
+ {4,1,5}, {6,1,5}, {2,1,5}, {1,1,5},
+ {5,1,5}, {7,1,5}, {0,1,11}, {7,0,11},
+ {6,1,5}, {2,2,2}, {6,0,11}, {0,2,2},
+ /* hat #2 in metatile #5 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #5 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #6 (type P) */
+ {1,0,6}, {4,0,1}, {0,1,10}, {7,0,10},
+ {7,0,1}, {0,0,6}, {5,0,6}, {2,0,6},
+ {0,1,10}, {3,0,6}, {1,0,6}, {5,0,6},
+ {2,0,6}, {-1,-1,-1}, {4,0,6}, {-1,-1,-1},
+ {3,1,6}, {5,0,6}, {-1,-1,-1}, {3,0,6},
+ {4,0,6}, {6,0,6}, {2,0,6}, {1,0,6},
+ {5,0,6}, {7,0,6}, {7,0,1}, {7,1,1},
+ {6,0,6}, {2,1,6}, {6,1,1}, {0,1,6},
+ /* hat #1 in metatile #6 (type P) */
+ {1,1,6}, {1,1,1}, {7,0,6}, {6,1,1},
+ {0,1,2}, {0,1,6}, {5,1,6}, {2,1,6},
+ {7,0,6}, {3,1,6}, {1,1,6}, {5,1,6},
+ {2,1,6}, {4,0,6}, {4,1,6}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,6}, {-1,-1,-1}, {3,1,6},
+ {4,1,6}, {6,1,6}, {2,1,6}, {1,1,6},
+ {5,1,6}, {7,1,6}, {0,1,2}, {7,1,12},
+ {6,1,6}, {-1,-1,-1}, {6,1,12}, {-1,-1,-1},
+ /* hat #2 in metatile #6 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #6 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #7 (type F) */
+ {1,0,7}, {2,0,8}, {-1,-1,-1}, {0,0,8},
+ {0,2,0}, {0,0,7}, {5,0,7}, {2,0,7},
+ {-1,-1,-1}, {3,0,7}, {1,0,7}, {5,0,7},
+ {2,0,7}, {-1,-1,-1}, {4,0,7}, {-1,-1,-1},
+ {3,1,7}, {5,0,7}, {-1,-1,-1}, {3,0,7},
+ {4,0,7}, {6,0,7}, {2,0,7}, {1,0,7},
+ {5,0,7}, {7,0,7}, {0,2,0}, {7,1,4},
+ {6,0,7}, {2,1,7}, {6,1,4}, {0,1,7},
+ /* hat #1 in metatile #7 (type F) */
+ {1,1,7}, {1,1,4}, {7,0,7}, {6,1,4},
+ {-1,-1,-1}, {0,1,7}, {5,1,7}, {2,1,7},
+ {7,0,7}, {3,1,7}, {1,1,7}, {5,1,7},
+ {2,1,7}, {4,0,7}, {4,1,7}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,7}, {-1,-1,-1}, {3,1,7},
+ {4,1,7}, {6,1,7}, {2,1,7}, {1,1,7},
+ {5,1,7}, {7,1,7}, {-1,-1,-1}, {-1,-1,-1},
+ {6,1,7}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #2 in metatile #7 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #7 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #8 (type F) */
+ {1,0,8}, {-1,-1,-1}, {0,0,7}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,8}, {5,0,8}, {2,0,8},
+ {0,0,7}, {3,0,8}, {1,0,8}, {5,0,8},
+ {2,0,8}, {1,2,0}, {4,0,8}, {6,2,0},
+ {3,1,8}, {5,0,8}, {6,2,0}, {3,0,8},
+ {4,0,8}, {6,0,8}, {2,0,8}, {1,0,8},
+ {5,0,8}, {7,0,8}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,8}, {2,1,8}, {-1,-1,-1}, {0,1,8},
+ /* hat #1 in metatile #8 (type F) */
+ {1,1,8}, {-1,-1,-1}, {7,0,8}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,8}, {5,1,8}, {2,1,8},
+ {7,0,8}, {3,1,8}, {1,1,8}, {5,1,8},
+ {2,1,8}, {4,0,8}, {4,1,8}, {7,2,0},
+ {3,1,0}, {5,1,8}, {7,2,0}, {3,1,8},
+ {4,1,8}, {6,1,8}, {2,1,8}, {1,1,8},
+ {5,1,8}, {7,1,8}, {-1,-1,-1}, {-1,-1,-1},
+ {6,1,8}, {2,1,0}, {0,0,5}, {0,1,0},
+ /* hat #2 in metatile #8 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #8 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #9 (type F) */
+ {1,0,9}, {-1,-1,-1}, {0,0,10}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,9}, {5,0,9}, {2,0,9},
+ {0,0,10}, {3,0,9}, {1,0,9}, {5,0,9},
+ {2,0,9}, {2,0,1}, {4,0,9}, {0,0,1},
+ {3,1,9}, {5,0,9}, {0,0,1}, {3,0,9},
+ {4,0,9}, {6,0,9}, {2,0,9}, {1,0,9},
+ {5,0,9}, {7,0,9}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,9}, {2,1,9}, {-1,-1,-1}, {0,1,9},
+ /* hat #1 in metatile #9 (type F) */
+ {1,1,9}, {-1,-1,-1}, {7,0,9}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,9}, {5,1,9}, {2,1,9},
+ {7,0,9}, {3,1,9}, {1,1,9}, {5,1,9},
+ {2,1,9}, {4,0,9}, {4,1,9}, {7,3,1},
+ {3,2,1}, {5,1,9}, {7,3,1}, {3,1,9},
+ {4,1,9}, {6,1,9}, {2,1,9}, {1,1,9},
+ {5,1,9}, {7,1,9}, {-1,-1,-1}, {-1,-1,-1},
+ {6,1,9}, {2,2,1}, {0,0,4}, {0,2,1},
+ /* hat #2 in metatile #9 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #9 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #10 (type F) */
+ {1,0,10}, {2,0,9}, {-1,-1,-1}, {0,0,9},
+ {3,0,1}, {0,0,10}, {5,0,10}, {2,0,10},
+ {-1,-1,-1}, {3,0,10}, {1,0,10}, {5,0,10},
+ {2,0,10}, {-1,-1,-1}, {4,0,10}, {-1,-1,-1},
+ {3,1,10}, {5,0,10}, {-1,-1,-1}, {3,0,10},
+ {4,0,10}, {6,0,10}, {2,0,10}, {1,0,10},
+ {5,0,10}, {7,0,10}, {3,0,1}, {4,0,1},
+ {6,0,10}, {2,1,10}, {0,0,6}, {0,1,10},
+ /* hat #1 in metatile #10 (type F) */
+ {1,1,10}, {2,0,6}, {7,0,10}, {0,0,6},
+ {-1,-1,-1}, {0,1,10}, {5,1,10}, {2,1,10},
+ {7,0,10}, {3,1,10}, {1,1,10}, {5,1,10},
+ {2,1,10}, {4,0,10}, {4,1,10}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,10}, {-1,-1,-1}, {3,1,10},
+ {4,1,10}, {6,1,10}, {2,1,10}, {1,1,10},
+ {5,1,10}, {7,1,10}, {-1,-1,-1}, {-1,-1,-1},
+ {6,1,10}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #2 in metatile #10 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #10 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #11 (type F) */
+ {1,0,11}, {2,0,12}, {-1,-1,-1}, {0,0,12},
+ {0,2,2}, {0,0,11}, {5,0,11}, {2,0,11},
+ {-1,-1,-1}, {3,0,11}, {1,0,11}, {5,0,11},
+ {2,0,11}, {-1,-1,-1}, {4,0,11}, {-1,-1,-1},
+ {3,1,11}, {5,0,11}, {-1,-1,-1}, {3,0,11},
+ {4,0,11}, {6,0,11}, {2,0,11}, {1,0,11},
+ {5,0,11}, {7,0,11}, {0,2,2}, {7,1,5},
+ {6,0,11}, {2,1,11}, {6,1,5}, {0,1,11},
+ /* hat #1 in metatile #11 (type F) */
+ {1,1,11}, {1,1,5}, {7,0,11}, {6,1,5},
+ {-1,-1,-1}, {0,1,11}, {5,1,11}, {2,1,11},
+ {7,0,11}, {3,1,11}, {1,1,11}, {5,1,11},
+ {2,1,11}, {4,0,11}, {4,1,11}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,11}, {-1,-1,-1}, {3,1,11},
+ {4,1,11}, {6,1,11}, {2,1,11}, {1,1,11},
+ {5,1,11}, {7,1,11}, {-1,-1,-1}, {-1,-1,-1},
+ {6,1,11}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #2 in metatile #11 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #11 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #12 (type F) */
+ {1,0,12}, {-1,-1,-1}, {0,0,11}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,12}, {5,0,12}, {2,0,12},
+ {0,0,11}, {3,0,12}, {1,0,12}, {5,0,12},
+ {2,0,12}, {1,2,2}, {4,0,12}, {6,2,2},
+ {3,1,12}, {5,0,12}, {6,2,2}, {3,0,12},
+ {4,0,12}, {6,0,12}, {2,0,12}, {1,0,12},
+ {5,0,12}, {7,0,12}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,12}, {2,1,12}, {-1,-1,-1}, {0,1,12},
+ /* hat #1 in metatile #12 (type F) */
+ {1,1,12}, {-1,-1,-1}, {7,0,12}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,12}, {5,1,12}, {2,1,12},
+ {7,0,12}, {3,1,12}, {1,1,12}, {5,1,12},
+ {2,1,12}, {4,0,12}, {4,1,12}, {7,2,2},
+ {3,1,2}, {5,1,12}, {7,2,2}, {3,1,12},
+ {4,1,12}, {6,1,12}, {2,1,12}, {1,1,12},
+ {5,1,12}, {7,1,12}, {-1,-1,-1}, {7,1,6},
+ {6,1,12}, {2,1,2}, {6,1,6}, {0,1,2},
+ /* hat #2 in metatile #12 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #12 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+};
+static const KitemapEntry kitemap_T[] = {
+ /* hat #0 in metatile #0 (type H) */
+ {1,0,0}, {7,3,0}, {3,0,3}, {4,0,3},
+ {4,3,0}, {0,0,0}, {5,0,0}, {2,0,0},
+ {3,0,3}, {3,0,0}, {1,0,0}, {5,0,0},
+ {2,0,0}, {1,1,6}, {4,0,0}, {6,1,6},
+ {0,0,2}, {5,0,0}, {6,1,6}, {3,0,0},
+ {4,0,0}, {6,0,0}, {2,0,0}, {1,0,0},
+ {5,0,0}, {7,0,0}, {4,3,0}, {3,3,0},
+ {6,0,0}, {1,0,2}, {7,1,0}, {6,0,2},
+ /* hat #1 in metatile #0 (type H) */
+ {1,1,0}, {1,1,4}, {7,1,1}, {6,1,4},
+ {0,1,2}, {0,1,0}, {5,1,0}, {2,1,0},
+ {7,1,1}, {3,1,0}, {1,1,0}, {5,1,0},
+ {2,1,0}, {4,1,1}, {4,1,0}, {0,3,0},
+ {2,3,0}, {5,1,0}, {0,3,0}, {3,1,0},
+ {4,1,0}, {6,1,0}, {2,1,0}, {1,1,0},
+ {5,1,0}, {7,1,0}, {0,1,2}, {7,0,2},
+ {6,1,0}, {3,3,0}, {6,0,2}, {7,0,0},
+ /* hat #2 in metatile #0 (type H) */
+ {1,2,0}, {1,1,5}, {7,1,3}, {6,1,5},
+ {3,0,1}, {0,2,0}, {5,2,0}, {2,2,0},
+ {7,1,3}, {3,2,0}, {1,2,0}, {5,2,0},
+ {2,2,0}, {4,1,3}, {4,2,0}, {6,3,0},
+ {1,3,0}, {5,2,0}, {6,3,0}, {3,2,0},
+ {4,2,0}, {6,2,0}, {2,2,0}, {1,2,0},
+ {5,2,0}, {7,2,0}, {3,0,1}, {4,0,1},
+ {6,2,0}, {0,3,0}, {3,1,1}, {4,1,1},
+ /* hat #3 in metatile #0 (type H) */
+ {7,2,0}, {1,3,0}, {3,1,0}, {4,1,0},
+ {0,3,0}, {4,2,0}, {2,3,0}, {5,3,0},
+ {3,3,0}, {4,1,0}, {5,3,0}, {1,3,0},
+ {7,1,0}, {2,3,0}, {6,0,0}, {4,3,0},
+ {5,3,0}, {1,0,0}, {3,3,0}, {6,0,0},
+ {6,3,0}, {4,3,0}, {1,3,0}, {2,3,0},
+ {7,3,0}, {5,3,0}, {3,2,0}, {4,2,0},
+ {0,0,0}, {6,3,0}, {3,1,3}, {4,1,3},
+ /* hat #0 in metatile #1 (type P) */
+ {1,0,1}, {-1,-1,-1}, {0,1,5}, {7,0,5},
+ {-1,-1,-1}, {0,0,1}, {5,0,1}, {2,0,1},
+ {0,1,5}, {3,0,1}, {1,0,1}, {5,0,1},
+ {2,0,1}, {1,2,0}, {4,0,1}, {6,2,0},
+ {3,1,1}, {5,0,1}, {6,2,0}, {3,0,1},
+ {4,0,1}, {6,0,1}, {2,0,1}, {1,0,1},
+ {5,0,1}, {7,0,1}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,1}, {2,1,1}, {-1,-1,-1}, {0,1,1},
+ /* hat #1 in metatile #1 (type P) */
+ {1,1,1}, {-1,-1,-1}, {7,0,1}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,1}, {5,1,1}, {2,1,1},
+ {7,0,1}, {3,1,1}, {1,1,1}, {5,1,1},
+ {2,1,1}, {4,0,1}, {4,1,1}, {7,2,0},
+ {3,1,0}, {5,1,1}, {7,2,0}, {3,1,1},
+ {4,1,1}, {6,1,1}, {2,1,1}, {1,1,1},
+ {5,1,1}, {7,1,1}, {-1,-1,-1}, {7,1,4},
+ {6,1,1}, {2,1,0}, {6,1,4}, {0,1,0},
+ /* hat #2 in metatile #1 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #1 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #2 (type P) */
+ {1,0,2}, {4,0,0}, {-1,-1,-1}, {7,1,6},
+ {7,0,0}, {0,0,2}, {5,0,2}, {2,0,2},
+ {-1,-1,-1}, {3,0,2}, {1,0,2}, {5,0,2},
+ {2,0,2}, {-1,-1,-1}, {4,0,2}, {-1,-1,-1},
+ {3,1,2}, {5,0,2}, {-1,-1,-1}, {3,0,2},
+ {4,0,2}, {6,0,2}, {2,0,2}, {1,0,2},
+ {5,0,2}, {7,0,2}, {7,0,0}, {7,1,0},
+ {6,0,2}, {2,1,2}, {6,1,0}, {0,1,2},
+ /* hat #1 in metatile #2 (type P) */
+ {1,1,2}, {1,1,0}, {7,0,2}, {6,1,0},
+ {0,1,4}, {0,1,2}, {5,1,2}, {2,1,2},
+ {7,0,2}, {3,1,2}, {1,1,2}, {5,1,2},
+ {2,1,2}, {4,0,2}, {4,1,2}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,2}, {-1,-1,-1}, {3,1,2},
+ {4,1,2}, {6,1,2}, {2,1,2}, {1,1,2},
+ {5,1,2}, {7,1,2}, {0,1,4}, {7,0,4},
+ {6,1,2}, {-1,-1,-1}, {6,0,4}, {-1,-1,-1},
+ /* hat #2 in metatile #2 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #2 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #3 (type P) */
+ {1,0,3}, {-1,-1,-1}, {0,1,6}, {7,0,6},
+ {-1,-1,-1}, {0,0,3}, {5,0,3}, {2,0,3},
+ {0,1,6}, {3,0,3}, {1,0,3}, {5,0,3},
+ {2,0,3}, {2,0,0}, {4,0,3}, {0,0,0},
+ {3,1,3}, {5,0,3}, {0,0,0}, {3,0,3},
+ {4,0,3}, {6,0,3}, {2,0,3}, {1,0,3},
+ {5,0,3}, {7,0,3}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,3}, {2,1,3}, {-1,-1,-1}, {0,1,3},
+ /* hat #1 in metatile #3 (type P) */
+ {1,1,3}, {-1,-1,-1}, {7,0,3}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,3}, {5,1,3}, {2,1,3},
+ {7,0,3}, {3,1,3}, {1,1,3}, {5,1,3},
+ {2,1,3}, {4,0,3}, {4,1,3}, {7,3,0},
+ {3,2,0}, {5,1,3}, {7,3,0}, {3,1,3},
+ {4,1,3}, {6,1,3}, {2,1,3}, {1,1,3},
+ {5,1,3}, {7,1,3}, {-1,-1,-1}, {7,1,5},
+ {6,1,3}, {2,2,0}, {6,1,5}, {0,2,0},
+ /* hat #2 in metatile #3 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #3 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #4 (type F) */
+ {1,0,4}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,4}, {5,0,4}, {2,0,4},
+ {-1,-1,-1}, {3,0,4}, {1,0,4}, {5,0,4},
+ {2,0,4}, {-1,-1,-1}, {4,0,4}, {-1,-1,-1},
+ {3,1,4}, {5,0,4}, {-1,-1,-1}, {3,0,4},
+ {4,0,4}, {6,0,4}, {2,0,4}, {1,0,4},
+ {5,0,4}, {7,0,4}, {-1,-1,-1}, {7,1,2},
+ {6,0,4}, {2,1,4}, {6,1,2}, {0,1,4},
+ /* hat #1 in metatile #4 (type F) */
+ {1,1,4}, {1,1,2}, {7,0,4}, {6,1,2},
+ {0,1,0}, {0,1,4}, {5,1,4}, {2,1,4},
+ {7,0,4}, {3,1,4}, {1,1,4}, {5,1,4},
+ {2,1,4}, {4,0,4}, {4,1,4}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,4}, {-1,-1,-1}, {3,1,4},
+ {4,1,4}, {6,1,4}, {2,1,4}, {1,1,4},
+ {5,1,4}, {7,1,4}, {0,1,0}, {7,1,1},
+ {6,1,4}, {-1,-1,-1}, {6,1,1}, {-1,-1,-1},
+ /* hat #2 in metatile #4 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #4 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #5 (type F) */
+ {1,0,5}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,5}, {5,0,5}, {2,0,5},
+ {-1,-1,-1}, {3,0,5}, {1,0,5}, {5,0,5},
+ {2,0,5}, {-1,-1,-1}, {4,0,5}, {-1,-1,-1},
+ {3,1,5}, {5,0,5}, {-1,-1,-1}, {3,0,5},
+ {4,0,5}, {6,0,5}, {2,0,5}, {1,0,5},
+ {5,0,5}, {7,0,5}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,5}, {2,1,5}, {0,0,1}, {0,1,5},
+ /* hat #1 in metatile #5 (type F) */
+ {1,1,5}, {2,0,1}, {7,0,5}, {0,0,1},
+ {0,2,0}, {0,1,5}, {5,1,5}, {2,1,5},
+ {7,0,5}, {3,1,5}, {1,1,5}, {5,1,5},
+ {2,1,5}, {4,0,5}, {4,1,5}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,5}, {-1,-1,-1}, {3,1,5},
+ {4,1,5}, {6,1,5}, {2,1,5}, {1,1,5},
+ {5,1,5}, {7,1,5}, {0,2,0}, {7,1,3},
+ {6,1,5}, {-1,-1,-1}, {6,1,3}, {-1,-1,-1},
+ /* hat #2 in metatile #5 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #5 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #6 (type F) */
+ {1,0,6}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,6}, {5,0,6}, {2,0,6},
+ {-1,-1,-1}, {3,0,6}, {1,0,6}, {5,0,6},
+ {2,0,6}, {-1,-1,-1}, {4,0,6}, {-1,-1,-1},
+ {3,1,6}, {5,0,6}, {-1,-1,-1}, {3,0,6},
+ {4,0,6}, {6,0,6}, {2,0,6}, {1,0,6},
+ {5,0,6}, {7,0,6}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,6}, {2,1,6}, {0,0,3}, {0,1,6},
+ /* hat #1 in metatile #6 (type F) */
+ {1,1,6}, {2,0,3}, {7,0,6}, {0,0,3},
+ {3,0,0}, {0,1,6}, {5,1,6}, {2,1,6},
+ {7,0,6}, {3,1,6}, {1,1,6}, {5,1,6},
+ {2,1,6}, {4,0,6}, {4,1,6}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,6}, {-1,-1,-1}, {3,1,6},
+ {4,1,6}, {6,1,6}, {2,1,6}, {1,1,6},
+ {5,1,6}, {7,1,6}, {3,0,0}, {4,0,0},
+ {6,1,6}, {-1,-1,-1}, {0,0,2}, {-1,-1,-1},
+ /* hat #2 in metatile #6 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #6 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+};
+static const KitemapEntry kitemap_P[] = {
+ /* hat #0 in metatile #0 (type H) */
+ {1,0,0}, {7,3,0}, {3,0,4}, {4,0,4},
+ {4,3,0}, {0,0,0}, {5,0,0}, {2,0,0},
+ {3,0,4}, {3,0,0}, {1,0,0}, {5,0,0},
+ {2,0,0}, {1,1,9}, {4,0,0}, {6,1,9},
+ {0,0,3}, {5,0,0}, {6,1,9}, {3,0,0},
+ {4,0,0}, {6,0,0}, {2,0,0}, {1,0,0},
+ {5,0,0}, {7,0,0}, {4,3,0}, {3,3,0},
+ {6,0,0}, {1,0,3}, {7,1,0}, {6,0,3},
+ /* hat #1 in metatile #0 (type H) */
+ {1,1,0}, {1,1,8}, {7,1,5}, {6,1,8},
+ {0,1,3}, {0,1,0}, {5,1,0}, {2,1,0},
+ {7,1,5}, {3,1,0}, {1,1,0}, {5,1,0},
+ {2,1,0}, {4,1,5}, {4,1,0}, {0,3,0},
+ {2,3,0}, {5,1,0}, {0,3,0}, {3,1,0},
+ {4,1,0}, {6,1,0}, {2,1,0}, {1,1,0},
+ {5,1,0}, {7,1,0}, {0,1,3}, {7,0,3},
+ {6,1,0}, {3,3,0}, {6,0,3}, {7,0,0},
+ /* hat #2 in metatile #0 (type H) */
+ {1,2,0}, {1,0,6}, {7,1,4}, {6,0,6},
+ {3,0,5}, {0,2,0}, {5,2,0}, {2,2,0},
+ {7,1,4}, {3,2,0}, {1,2,0}, {5,2,0},
+ {2,2,0}, {4,1,4}, {4,2,0}, {6,3,0},
+ {1,3,0}, {5,2,0}, {6,3,0}, {3,2,0},
+ {4,2,0}, {6,2,0}, {2,2,0}, {1,2,0},
+ {5,2,0}, {7,2,0}, {3,0,5}, {4,0,5},
+ {6,2,0}, {0,3,0}, {3,1,5}, {4,1,5},
+ /* hat #3 in metatile #0 (type H) */
+ {7,2,0}, {1,3,0}, {3,1,0}, {4,1,0},
+ {0,3,0}, {4,2,0}, {2,3,0}, {5,3,0},
+ {3,3,0}, {4,1,0}, {5,3,0}, {1,3,0},
+ {7,1,0}, {2,3,0}, {6,0,0}, {4,3,0},
+ {5,3,0}, {1,0,0}, {3,3,0}, {6,0,0},
+ {6,3,0}, {4,3,0}, {1,3,0}, {2,3,0},
+ {7,3,0}, {5,3,0}, {3,2,0}, {4,2,0},
+ {0,0,0}, {6,3,0}, {3,1,4}, {4,1,4},
+ /* hat #0 in metatile #1 (type H) */
+ {1,0,1}, {7,3,1}, {3,0,10}, {4,0,10},
+ {4,3,1}, {0,0,1}, {5,0,1}, {2,0,1},
+ {3,0,10}, {3,0,1}, {1,0,1}, {5,0,1},
+ {2,0,1}, {1,0,9}, {4,0,1}, {6,0,9},
+ {0,0,4}, {5,0,1}, {6,0,9}, {3,0,1},
+ {4,0,1}, {6,0,1}, {2,0,1}, {1,0,1},
+ {5,0,1}, {7,0,1}, {4,3,1}, {3,3,1},
+ {6,0,1}, {1,0,4}, {7,1,1}, {6,0,4},
+ /* hat #1 in metatile #1 (type H) */
+ {1,1,1}, {1,1,6}, {7,1,2}, {6,1,6},
+ {0,1,4}, {0,1,1}, {5,1,1}, {2,1,1},
+ {7,1,2}, {3,1,1}, {1,1,1}, {5,1,1},
+ {2,1,1}, {4,1,2}, {4,1,1}, {0,3,1},
+ {2,3,1}, {5,1,1}, {0,3,1}, {3,1,1},
+ {4,1,1}, {6,1,1}, {2,1,1}, {1,1,1},
+ {5,1,1}, {7,1,1}, {0,1,4}, {7,0,4},
+ {6,1,1}, {3,3,1}, {6,0,4}, {7,0,1},
+ /* hat #2 in metatile #1 (type H) */
+ {1,2,1}, {1,1,7}, {7,1,10}, {6,1,7},
+ {3,0,2}, {0,2,1}, {5,2,1}, {2,2,1},
+ {7,1,10}, {3,2,1}, {1,2,1}, {5,2,1},
+ {2,2,1}, {4,1,10}, {4,2,1}, {6,3,1},
+ {1,3,1}, {5,2,1}, {6,3,1}, {3,2,1},
+ {4,2,1}, {6,2,1}, {2,2,1}, {1,2,1},
+ {5,2,1}, {7,2,1}, {3,0,2}, {4,0,2},
+ {6,2,1}, {0,3,1}, {3,1,2}, {4,1,2},
+ /* hat #3 in metatile #1 (type H) */
+ {7,2,1}, {1,3,1}, {3,1,1}, {4,1,1},
+ {0,3,1}, {4,2,1}, {2,3,1}, {5,3,1},
+ {3,3,1}, {4,1,1}, {5,3,1}, {1,3,1},
+ {7,1,1}, {2,3,1}, {6,0,1}, {4,3,1},
+ {5,3,1}, {1,0,1}, {3,3,1}, {6,0,1},
+ {6,3,1}, {4,3,1}, {1,3,1}, {2,3,1},
+ {7,3,1}, {5,3,1}, {3,2,1}, {4,2,1},
+ {0,0,1}, {6,3,1}, {3,1,10}, {4,1,10},
+ /* hat #0 in metatile #2 (type P) */
+ {1,0,2}, {-1,-1,-1}, {0,1,7}, {7,0,7},
+ {-1,-1,-1}, {0,0,2}, {5,0,2}, {2,0,2},
+ {0,1,7}, {3,0,2}, {1,0,2}, {5,0,2},
+ {2,0,2}, {1,2,1}, {4,0,2}, {6,2,1},
+ {3,1,2}, {5,0,2}, {6,2,1}, {3,0,2},
+ {4,0,2}, {6,0,2}, {2,0,2}, {1,0,2},
+ {5,0,2}, {7,0,2}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,2}, {2,1,2}, {-1,-1,-1}, {0,1,2},
+ /* hat #1 in metatile #2 (type P) */
+ {1,1,2}, {-1,-1,-1}, {7,0,2}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,2}, {5,1,2}, {2,1,2},
+ {7,0,2}, {3,1,2}, {1,1,2}, {5,1,2},
+ {2,1,2}, {4,0,2}, {4,1,2}, {7,2,1},
+ {3,1,1}, {5,1,2}, {7,2,1}, {3,1,2},
+ {4,1,2}, {6,1,2}, {2,1,2}, {1,1,2},
+ {5,1,2}, {7,1,2}, {-1,-1,-1}, {7,1,6},
+ {6,1,2}, {2,1,1}, {6,1,6}, {0,1,1},
+ /* hat #2 in metatile #2 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #2 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #3 (type P) */
+ {1,0,3}, {4,0,0}, {-1,-1,-1}, {7,1,9},
+ {7,0,0}, {0,0,3}, {5,0,3}, {2,0,3},
+ {-1,-1,-1}, {3,0,3}, {1,0,3}, {5,0,3},
+ {2,0,3}, {-1,-1,-1}, {4,0,3}, {-1,-1,-1},
+ {3,1,3}, {5,0,3}, {-1,-1,-1}, {3,0,3},
+ {4,0,3}, {6,0,3}, {2,0,3}, {1,0,3},
+ {5,0,3}, {7,0,3}, {7,0,0}, {7,1,0},
+ {6,0,3}, {2,1,3}, {6,1,0}, {0,1,3},
+ /* hat #1 in metatile #3 (type P) */
+ {1,1,3}, {1,1,0}, {7,0,3}, {6,1,0},
+ {0,1,8}, {0,1,3}, {5,1,3}, {2,1,3},
+ {7,0,3}, {3,1,3}, {1,1,3}, {5,1,3},
+ {2,1,3}, {4,0,3}, {4,1,3}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,3}, {-1,-1,-1}, {3,1,3},
+ {4,1,3}, {6,1,3}, {2,1,3}, {1,1,3},
+ {5,1,3}, {7,1,3}, {0,1,8}, {7,0,8},
+ {6,1,3}, {-1,-1,-1}, {6,0,8}, {-1,-1,-1},
+ /* hat #2 in metatile #3 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #3 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #4 (type P) */
+ {1,0,4}, {4,0,1}, {0,1,9}, {7,0,9},
+ {7,0,1}, {0,0,4}, {5,0,4}, {2,0,4},
+ {0,1,9}, {3,0,4}, {1,0,4}, {5,0,4},
+ {2,0,4}, {2,0,0}, {4,0,4}, {0,0,0},
+ {3,1,4}, {5,0,4}, {0,0,0}, {3,0,4},
+ {4,0,4}, {6,0,4}, {2,0,4}, {1,0,4},
+ {5,0,4}, {7,0,4}, {7,0,1}, {7,1,1},
+ {6,0,4}, {2,1,4}, {6,1,1}, {0,1,4},
+ /* hat #1 in metatile #4 (type P) */
+ {1,1,4}, {1,1,1}, {7,0,4}, {6,1,1},
+ {0,1,6}, {0,1,4}, {5,1,4}, {2,1,4},
+ {7,0,4}, {3,1,4}, {1,1,4}, {5,1,4},
+ {2,1,4}, {4,0,4}, {4,1,4}, {7,3,0},
+ {3,2,0}, {5,1,4}, {7,3,0}, {3,1,4},
+ {4,1,4}, {6,1,4}, {2,1,4}, {1,1,4},
+ {5,1,4}, {7,1,4}, {0,1,6}, {7,0,6},
+ {6,1,4}, {2,2,0}, {6,0,6}, {0,2,0},
+ /* hat #2 in metatile #4 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #4 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #5 (type F) */
+ {1,0,5}, {-1,-1,-1}, {0,0,6}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,5}, {5,0,5}, {2,0,5},
+ {0,0,6}, {3,0,5}, {1,0,5}, {5,0,5},
+ {2,0,5}, {1,2,0}, {4,0,5}, {6,2,0},
+ {3,1,5}, {5,0,5}, {6,2,0}, {3,0,5},
+ {4,0,5}, {6,0,5}, {2,0,5}, {1,0,5},
+ {5,0,5}, {7,0,5}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,5}, {2,1,5}, {-1,-1,-1}, {0,1,5},
+ /* hat #1 in metatile #5 (type F) */
+ {1,1,5}, {-1,-1,-1}, {7,0,5}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,5}, {5,1,5}, {2,1,5},
+ {7,0,5}, {3,1,5}, {1,1,5}, {5,1,5},
+ {2,1,5}, {4,0,5}, {4,1,5}, {7,2,0},
+ {3,1,0}, {5,1,5}, {7,2,0}, {3,1,5},
+ {4,1,5}, {6,1,5}, {2,1,5}, {1,1,5},
+ {5,1,5}, {7,1,5}, {-1,-1,-1}, {7,1,8},
+ {6,1,5}, {2,1,0}, {6,1,8}, {0,1,0},
+ /* hat #2 in metatile #5 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #5 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #6 (type F) */
+ {1,0,6}, {2,0,5}, {-1,-1,-1}, {0,0,5},
+ {0,2,0}, {0,0,6}, {5,0,6}, {2,0,6},
+ {-1,-1,-1}, {3,0,6}, {1,0,6}, {5,0,6},
+ {2,0,6}, {-1,-1,-1}, {4,0,6}, {-1,-1,-1},
+ {3,1,6}, {5,0,6}, {-1,-1,-1}, {3,0,6},
+ {4,0,6}, {6,0,6}, {2,0,6}, {1,0,6},
+ {5,0,6}, {7,0,6}, {0,2,0}, {7,1,4},
+ {6,0,6}, {2,1,6}, {6,1,4}, {0,1,6},
+ /* hat #1 in metatile #6 (type F) */
+ {1,1,6}, {1,1,4}, {7,0,6}, {6,1,4},
+ {0,1,1}, {0,1,6}, {5,1,6}, {2,1,6},
+ {7,0,6}, {3,1,6}, {1,1,6}, {5,1,6},
+ {2,1,6}, {4,0,6}, {4,1,6}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,6}, {-1,-1,-1}, {3,1,6},
+ {4,1,6}, {6,1,6}, {2,1,6}, {1,1,6},
+ {5,1,6}, {7,1,6}, {0,1,1}, {7,1,2},
+ {6,1,6}, {-1,-1,-1}, {6,1,2}, {-1,-1,-1},
+ /* hat #2 in metatile #6 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #6 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #7 (type F) */
+ {1,0,7}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,7}, {5,0,7}, {2,0,7},
+ {-1,-1,-1}, {3,0,7}, {1,0,7}, {5,0,7},
+ {2,0,7}, {-1,-1,-1}, {4,0,7}, {-1,-1,-1},
+ {3,1,7}, {5,0,7}, {-1,-1,-1}, {3,0,7},
+ {4,0,7}, {6,0,7}, {2,0,7}, {1,0,7},
+ {5,0,7}, {7,0,7}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,7}, {2,1,7}, {0,0,2}, {0,1,7},
+ /* hat #1 in metatile #7 (type F) */
+ {1,1,7}, {2,0,2}, {7,0,7}, {0,0,2},
+ {0,2,1}, {0,1,7}, {5,1,7}, {2,1,7},
+ {7,0,7}, {3,1,7}, {1,1,7}, {5,1,7},
+ {2,1,7}, {4,0,7}, {4,1,7}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,7}, {-1,-1,-1}, {3,1,7},
+ {4,1,7}, {6,1,7}, {2,1,7}, {1,1,7},
+ {5,1,7}, {7,1,7}, {0,2,1}, {7,1,10},
+ {6,1,7}, {-1,-1,-1}, {6,1,10}, {-1,-1,-1},
+ /* hat #2 in metatile #7 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #7 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #8 (type F) */
+ {1,0,8}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,8}, {5,0,8}, {2,0,8},
+ {-1,-1,-1}, {3,0,8}, {1,0,8}, {5,0,8},
+ {2,0,8}, {-1,-1,-1}, {4,0,8}, {-1,-1,-1},
+ {3,1,8}, {5,0,8}, {-1,-1,-1}, {3,0,8},
+ {4,0,8}, {6,0,8}, {2,0,8}, {1,0,8},
+ {5,0,8}, {7,0,8}, {-1,-1,-1}, {7,1,3},
+ {6,0,8}, {2,1,8}, {6,1,3}, {0,1,8},
+ /* hat #1 in metatile #8 (type F) */
+ {1,1,8}, {1,1,3}, {7,0,8}, {6,1,3},
+ {0,1,0}, {0,1,8}, {5,1,8}, {2,1,8},
+ {7,0,8}, {3,1,8}, {1,1,8}, {5,1,8},
+ {2,1,8}, {4,0,8}, {4,1,8}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,8}, {-1,-1,-1}, {3,1,8},
+ {4,1,8}, {6,1,8}, {2,1,8}, {1,1,8},
+ {5,1,8}, {7,1,8}, {0,1,0}, {7,1,5},
+ {6,1,8}, {-1,-1,-1}, {6,1,5}, {-1,-1,-1},
+ /* hat #2 in metatile #8 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #8 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #9 (type F) */
+ {1,0,9}, {2,0,10}, {-1,-1,-1}, {0,0,10},
+ {3,0,1}, {0,0,9}, {5,0,9}, {2,0,9},
+ {-1,-1,-1}, {3,0,9}, {1,0,9}, {5,0,9},
+ {2,0,9}, {-1,-1,-1}, {4,0,9}, {-1,-1,-1},
+ {3,1,9}, {5,0,9}, {-1,-1,-1}, {3,0,9},
+ {4,0,9}, {6,0,9}, {2,0,9}, {1,0,9},
+ {5,0,9}, {7,0,9}, {3,0,1}, {4,0,1},
+ {6,0,9}, {2,1,9}, {0,0,4}, {0,1,9},
+ /* hat #1 in metatile #9 (type F) */
+ {1,1,9}, {2,0,4}, {7,0,9}, {0,0,4},
+ {3,0,0}, {0,1,9}, {5,1,9}, {2,1,9},
+ {7,0,9}, {3,1,9}, {1,1,9}, {5,1,9},
+ {2,1,9}, {4,0,9}, {4,1,9}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,9}, {-1,-1,-1}, {3,1,9},
+ {4,1,9}, {6,1,9}, {2,1,9}, {1,1,9},
+ {5,1,9}, {7,1,9}, {3,0,0}, {4,0,0},
+ {6,1,9}, {-1,-1,-1}, {0,0,3}, {-1,-1,-1},
+ /* hat #2 in metatile #9 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #9 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #10 (type F) */
+ {1,0,10}, {-1,-1,-1}, {0,0,9}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,10}, {5,0,10}, {2,0,10},
+ {0,0,9}, {3,0,10}, {1,0,10}, {5,0,10},
+ {2,0,10}, {2,0,1}, {4,0,10}, {0,0,1},
+ {3,1,10}, {5,0,10}, {0,0,1}, {3,0,10},
+ {4,0,10}, {6,0,10}, {2,0,10}, {1,0,10},
+ {5,0,10}, {7,0,10}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,10}, {2,1,10}, {-1,-1,-1}, {0,1,10},
+ /* hat #1 in metatile #10 (type F) */
+ {1,1,10}, {-1,-1,-1}, {7,0,10}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,10}, {5,1,10}, {2,1,10},
+ {7,0,10}, {3,1,10}, {1,1,10}, {5,1,10},
+ {2,1,10}, {4,0,10}, {4,1,10}, {7,3,1},
+ {3,2,1}, {5,1,10}, {7,3,1}, {3,1,10},
+ {4,1,10}, {6,1,10}, {2,1,10}, {1,1,10},
+ {5,1,10}, {7,1,10}, {-1,-1,-1}, {7,1,7},
+ {6,1,10}, {2,2,1}, {6,1,7}, {0,2,1},
+ /* hat #2 in metatile #10 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #10 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+};
+static const KitemapEntry kitemap_F[] = {
+ /* hat #0 in metatile #0 (type H) */
+ {1,0,0}, {7,3,0}, {3,0,3}, {4,0,3},
+ {4,3,0}, {0,0,0}, {5,0,0}, {2,0,0},
+ {3,0,3}, {3,0,0}, {1,0,0}, {5,0,0},
+ {2,0,0}, {1,1,9}, {4,0,0}, {6,1,9},
+ {0,0,2}, {5,0,0}, {6,1,9}, {3,0,0},
+ {4,0,0}, {6,0,0}, {2,0,0}, {1,0,0},
+ {5,0,0}, {7,0,0}, {4,3,0}, {3,3,0},
+ {6,0,0}, {1,0,2}, {7,1,0}, {6,0,2},
+ /* hat #1 in metatile #0 (type H) */
+ {1,1,0}, {1,1,8}, {7,1,4}, {6,1,8},
+ {0,1,2}, {0,1,0}, {5,1,0}, {2,1,0},
+ {7,1,4}, {3,1,0}, {1,1,0}, {5,1,0},
+ {2,1,0}, {4,1,4}, {4,1,0}, {0,3,0},
+ {2,3,0}, {5,1,0}, {0,3,0}, {3,1,0},
+ {4,1,0}, {6,1,0}, {2,1,0}, {1,1,0},
+ {5,1,0}, {7,1,0}, {0,1,2}, {7,0,2},
+ {6,1,0}, {3,3,0}, {6,0,2}, {7,0,0},
+ /* hat #2 in metatile #0 (type H) */
+ {1,2,0}, {1,0,5}, {7,1,3}, {6,0,5},
+ {3,0,4}, {0,2,0}, {5,2,0}, {2,2,0},
+ {7,1,3}, {3,2,0}, {1,2,0}, {5,2,0},
+ {2,2,0}, {4,1,3}, {4,2,0}, {6,3,0},
+ {1,3,0}, {5,2,0}, {6,3,0}, {3,2,0},
+ {4,2,0}, {6,2,0}, {2,2,0}, {1,2,0},
+ {5,2,0}, {7,2,0}, {3,0,4}, {4,0,4},
+ {6,2,0}, {0,3,0}, {3,1,4}, {4,1,4},
+ /* hat #3 in metatile #0 (type H) */
+ {7,2,0}, {1,3,0}, {3,1,0}, {4,1,0},
+ {0,3,0}, {4,2,0}, {2,3,0}, {5,3,0},
+ {3,3,0}, {4,1,0}, {5,3,0}, {1,3,0},
+ {7,1,0}, {2,3,0}, {6,0,0}, {4,3,0},
+ {5,3,0}, {1,0,0}, {3,3,0}, {6,0,0},
+ {6,3,0}, {4,3,0}, {1,3,0}, {2,3,0},
+ {7,3,0}, {5,3,0}, {3,2,0}, {4,2,0},
+ {0,0,0}, {6,3,0}, {3,1,3}, {4,1,3},
+ /* hat #0 in metatile #1 (type H) */
+ {1,0,1}, {7,3,1}, {3,0,10}, {4,0,10},
+ {4,3,1}, {0,0,1}, {5,0,1}, {2,0,1},
+ {3,0,10}, {3,0,1}, {1,0,1}, {5,0,1},
+ {2,0,1}, {1,0,9}, {4,0,1}, {6,0,9},
+ {0,0,3}, {5,0,1}, {6,0,9}, {3,0,1},
+ {4,0,1}, {6,0,1}, {2,0,1}, {1,0,1},
+ {5,0,1}, {7,0,1}, {4,3,1}, {3,3,1},
+ {6,0,1}, {1,0,3}, {7,1,1}, {6,0,3},
+ /* hat #1 in metatile #1 (type H) */
+ {1,1,1}, {1,1,5}, {7,1,6}, {6,1,5},
+ {0,1,3}, {0,1,1}, {5,1,1}, {2,1,1},
+ {7,1,6}, {3,1,1}, {1,1,1}, {5,1,1},
+ {2,1,1}, {4,1,6}, {4,1,1}, {0,3,1},
+ {2,3,1}, {5,1,1}, {0,3,1}, {3,1,1},
+ {4,1,1}, {6,1,1}, {2,1,1}, {1,1,1},
+ {5,1,1}, {7,1,1}, {0,1,3}, {7,0,3},
+ {6,1,1}, {3,3,1}, {6,0,3}, {7,0,1},
+ /* hat #2 in metatile #1 (type H) */
+ {1,2,1}, {1,0,7}, {7,1,10}, {6,0,7},
+ {3,0,6}, {0,2,1}, {5,2,1}, {2,2,1},
+ {7,1,10}, {3,2,1}, {1,2,1}, {5,2,1},
+ {2,2,1}, {4,1,10}, {4,2,1}, {6,3,1},
+ {1,3,1}, {5,2,1}, {6,3,1}, {3,2,1},
+ {4,2,1}, {6,2,1}, {2,2,1}, {1,2,1},
+ {5,2,1}, {7,2,1}, {3,0,6}, {4,0,6},
+ {6,2,1}, {0,3,1}, {3,1,6}, {4,1,6},
+ /* hat #3 in metatile #1 (type H) */
+ {7,2,1}, {1,3,1}, {3,1,1}, {4,1,1},
+ {0,3,1}, {4,2,1}, {2,3,1}, {5,3,1},
+ {3,3,1}, {4,1,1}, {5,3,1}, {1,3,1},
+ {7,1,1}, {2,3,1}, {6,0,1}, {4,3,1},
+ {5,3,1}, {1,0,1}, {3,3,1}, {6,0,1},
+ {6,3,1}, {4,3,1}, {1,3,1}, {2,3,1},
+ {7,3,1}, {5,3,1}, {3,2,1}, {4,2,1},
+ {0,0,1}, {6,3,1}, {3,1,10}, {4,1,10},
+ /* hat #0 in metatile #2 (type P) */
+ {1,0,2}, {4,0,0}, {-1,-1,-1}, {7,1,9},
+ {7,0,0}, {0,0,2}, {5,0,2}, {2,0,2},
+ {-1,-1,-1}, {3,0,2}, {1,0,2}, {5,0,2},
+ {2,0,2}, {-1,-1,-1}, {4,0,2}, {-1,-1,-1},
+ {3,1,2}, {5,0,2}, {-1,-1,-1}, {3,0,2},
+ {4,0,2}, {6,0,2}, {2,0,2}, {1,0,2},
+ {5,0,2}, {7,0,2}, {7,0,0}, {7,1,0},
+ {6,0,2}, {2,1,2}, {6,1,0}, {0,1,2},
+ /* hat #1 in metatile #2 (type P) */
+ {1,1,2}, {1,1,0}, {7,0,2}, {6,1,0},
+ {0,1,8}, {0,1,2}, {5,1,2}, {2,1,2},
+ {7,0,2}, {3,1,2}, {1,1,2}, {5,1,2},
+ {2,1,2}, {4,0,2}, {4,1,2}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,2}, {-1,-1,-1}, {3,1,2},
+ {4,1,2}, {6,1,2}, {2,1,2}, {1,1,2},
+ {5,1,2}, {7,1,2}, {0,1,8}, {7,0,8},
+ {6,1,2}, {-1,-1,-1}, {6,0,8}, {-1,-1,-1},
+ /* hat #2 in metatile #2 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #2 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #3 (type P) */
+ {1,0,3}, {4,0,1}, {0,1,9}, {7,0,9},
+ {7,0,1}, {0,0,3}, {5,0,3}, {2,0,3},
+ {0,1,9}, {3,0,3}, {1,0,3}, {5,0,3},
+ {2,0,3}, {2,0,0}, {4,0,3}, {0,0,0},
+ {3,1,3}, {5,0,3}, {0,0,0}, {3,0,3},
+ {4,0,3}, {6,0,3}, {2,0,3}, {1,0,3},
+ {5,0,3}, {7,0,3}, {7,0,1}, {7,1,1},
+ {6,0,3}, {2,1,3}, {6,1,1}, {0,1,3},
+ /* hat #1 in metatile #3 (type P) */
+ {1,1,3}, {1,1,1}, {7,0,3}, {6,1,1},
+ {0,1,5}, {0,1,3}, {5,1,3}, {2,1,3},
+ {7,0,3}, {3,1,3}, {1,1,3}, {5,1,3},
+ {2,1,3}, {4,0,3}, {4,1,3}, {7,3,0},
+ {3,2,0}, {5,1,3}, {7,3,0}, {3,1,3},
+ {4,1,3}, {6,1,3}, {2,1,3}, {1,1,3},
+ {5,1,3}, {7,1,3}, {0,1,5}, {7,0,5},
+ {6,1,3}, {2,2,0}, {6,0,5}, {0,2,0},
+ /* hat #2 in metatile #3 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #3 (type P) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #4 (type F) */
+ {1,0,4}, {-1,-1,-1}, {0,0,5}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,4}, {5,0,4}, {2,0,4},
+ {0,0,5}, {3,0,4}, {1,0,4}, {5,0,4},
+ {2,0,4}, {1,2,0}, {4,0,4}, {6,2,0},
+ {3,1,4}, {5,0,4}, {6,2,0}, {3,0,4},
+ {4,0,4}, {6,0,4}, {2,0,4}, {1,0,4},
+ {5,0,4}, {7,0,4}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,4}, {2,1,4}, {-1,-1,-1}, {0,1,4},
+ /* hat #1 in metatile #4 (type F) */
+ {1,1,4}, {-1,-1,-1}, {7,0,4}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,4}, {5,1,4}, {2,1,4},
+ {7,0,4}, {3,1,4}, {1,1,4}, {5,1,4},
+ {2,1,4}, {4,0,4}, {4,1,4}, {7,2,0},
+ {3,1,0}, {5,1,4}, {7,2,0}, {3,1,4},
+ {4,1,4}, {6,1,4}, {2,1,4}, {1,1,4},
+ {5,1,4}, {7,1,4}, {-1,-1,-1}, {7,1,8},
+ {6,1,4}, {2,1,0}, {6,1,8}, {0,1,0},
+ /* hat #2 in metatile #4 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #4 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #5 (type F) */
+ {1,0,5}, {2,0,4}, {-1,-1,-1}, {0,0,4},
+ {0,2,0}, {0,0,5}, {5,0,5}, {2,0,5},
+ {-1,-1,-1}, {3,0,5}, {1,0,5}, {5,0,5},
+ {2,0,5}, {-1,-1,-1}, {4,0,5}, {-1,-1,-1},
+ {3,1,5}, {5,0,5}, {-1,-1,-1}, {3,0,5},
+ {4,0,5}, {6,0,5}, {2,0,5}, {1,0,5},
+ {5,0,5}, {7,0,5}, {0,2,0}, {7,1,3},
+ {6,0,5}, {2,1,5}, {6,1,3}, {0,1,5},
+ /* hat #1 in metatile #5 (type F) */
+ {1,1,5}, {1,1,3}, {7,0,5}, {6,1,3},
+ {0,1,1}, {0,1,5}, {5,1,5}, {2,1,5},
+ {7,0,5}, {3,1,5}, {1,1,5}, {5,1,5},
+ {2,1,5}, {4,0,5}, {4,1,5}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,5}, {-1,-1,-1}, {3,1,5},
+ {4,1,5}, {6,1,5}, {2,1,5}, {1,1,5},
+ {5,1,5}, {7,1,5}, {0,1,1}, {7,1,6},
+ {6,1,5}, {-1,-1,-1}, {6,1,6}, {-1,-1,-1},
+ /* hat #2 in metatile #5 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #5 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #6 (type F) */
+ {1,0,6}, {-1,-1,-1}, {0,0,7}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,6}, {5,0,6}, {2,0,6},
+ {0,0,7}, {3,0,6}, {1,0,6}, {5,0,6},
+ {2,0,6}, {1,2,1}, {4,0,6}, {6,2,1},
+ {3,1,6}, {5,0,6}, {6,2,1}, {3,0,6},
+ {4,0,6}, {6,0,6}, {2,0,6}, {1,0,6},
+ {5,0,6}, {7,0,6}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,6}, {2,1,6}, {-1,-1,-1}, {0,1,6},
+ /* hat #1 in metatile #6 (type F) */
+ {1,1,6}, {-1,-1,-1}, {7,0,6}, {-1,-1,-1},
+ {-1,-1,-1}, {0,1,6}, {5,1,6}, {2,1,6},
+ {7,0,6}, {3,1,6}, {1,1,6}, {5,1,6},
+ {2,1,6}, {4,0,6}, {4,1,6}, {7,2,1},
+ {3,1,1}, {5,1,6}, {7,2,1}, {3,1,6},
+ {4,1,6}, {6,1,6}, {2,1,6}, {1,1,6},
+ {5,1,6}, {7,1,6}, {-1,-1,-1}, {7,1,5},
+ {6,1,6}, {2,1,1}, {6,1,5}, {0,1,1},
+ /* hat #2 in metatile #6 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #6 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #7 (type F) */
+ {1,0,7}, {2,0,6}, {-1,-1,-1}, {0,0,6},
+ {0,2,1}, {0,0,7}, {5,0,7}, {2,0,7},
+ {-1,-1,-1}, {3,0,7}, {1,0,7}, {5,0,7},
+ {2,0,7}, {-1,-1,-1}, {4,0,7}, {-1,-1,-1},
+ {3,1,7}, {5,0,7}, {-1,-1,-1}, {3,0,7},
+ {4,0,7}, {6,0,7}, {2,0,7}, {1,0,7},
+ {5,0,7}, {7,0,7}, {0,2,1}, {7,1,10},
+ {6,0,7}, {2,1,7}, {6,1,10}, {0,1,7},
+ /* hat #1 in metatile #7 (type F) */
+ {1,1,7}, {1,1,10}, {7,0,7}, {6,1,10},
+ {-1,-1,-1}, {0,1,7}, {5,1,7}, {2,1,7},
+ {7,0,7}, {3,1,7}, {1,1,7}, {5,1,7},
+ {2,1,7}, {4,0,7}, {4,1,7}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,7}, {-1,-1,-1}, {3,1,7},
+ {4,1,7}, {6,1,7}, {2,1,7}, {1,1,7},
+ {5,1,7}, {7,1,7}, {-1,-1,-1}, {-1,-1,-1},
+ {6,1,7}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #2 in metatile #7 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #7 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #8 (type F) */
+ {1,0,8}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,8}, {5,0,8}, {2,0,8},
+ {-1,-1,-1}, {3,0,8}, {1,0,8}, {5,0,8},
+ {2,0,8}, {-1,-1,-1}, {4,0,8}, {-1,-1,-1},
+ {3,1,8}, {5,0,8}, {-1,-1,-1}, {3,0,8},
+ {4,0,8}, {6,0,8}, {2,0,8}, {1,0,8},
+ {5,0,8}, {7,0,8}, {-1,-1,-1}, {7,1,2},
+ {6,0,8}, {2,1,8}, {6,1,2}, {0,1,8},
+ /* hat #1 in metatile #8 (type F) */
+ {1,1,8}, {1,1,2}, {7,0,8}, {6,1,2},
+ {0,1,0}, {0,1,8}, {5,1,8}, {2,1,8},
+ {7,0,8}, {3,1,8}, {1,1,8}, {5,1,8},
+ {2,1,8}, {4,0,8}, {4,1,8}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,8}, {-1,-1,-1}, {3,1,8},
+ {4,1,8}, {6,1,8}, {2,1,8}, {1,1,8},
+ {5,1,8}, {7,1,8}, {0,1,0}, {7,1,4},
+ {6,1,8}, {-1,-1,-1}, {6,1,4}, {-1,-1,-1},
+ /* hat #2 in metatile #8 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #8 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #9 (type F) */
+ {1,0,9}, {2,0,10}, {-1,-1,-1}, {0,0,10},
+ {3,0,1}, {0,0,9}, {5,0,9}, {2,0,9},
+ {-1,-1,-1}, {3,0,9}, {1,0,9}, {5,0,9},
+ {2,0,9}, {-1,-1,-1}, {4,0,9}, {-1,-1,-1},
+ {3,1,9}, {5,0,9}, {-1,-1,-1}, {3,0,9},
+ {4,0,9}, {6,0,9}, {2,0,9}, {1,0,9},
+ {5,0,9}, {7,0,9}, {3,0,1}, {4,0,1},
+ {6,0,9}, {2,1,9}, {0,0,3}, {0,1,9},
+ /* hat #1 in metatile #9 (type F) */
+ {1,1,9}, {2,0,3}, {7,0,9}, {0,0,3},
+ {3,0,0}, {0,1,9}, {5,1,9}, {2,1,9},
+ {7,0,9}, {3,1,9}, {1,1,9}, {5,1,9},
+ {2,1,9}, {4,0,9}, {4,1,9}, {-1,-1,-1},
+ {-1,-1,-1}, {5,1,9}, {-1,-1,-1}, {3,1,9},
+ {4,1,9}, {6,1,9}, {2,1,9}, {1,1,9},
+ {5,1,9}, {7,1,9}, {3,0,0}, {4,0,0},
+ {6,1,9}, {-1,-1,-1}, {0,0,2}, {-1,-1,-1},
+ /* hat #2 in metatile #9 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #9 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #0 in metatile #10 (type F) */
+ {1,0,10}, {-1,-1,-1}, {0,0,9}, {-1,-1,-1},
+ {-1,-1,-1}, {0,0,10}, {5,0,10}, {2,0,10},
+ {0,0,9}, {3,0,10}, {1,0,10}, {5,0,10},
+ {2,0,10}, {2,0,1}, {4,0,10}, {0,0,1},
+ {3,1,10}, {5,0,10}, {0,0,1}, {3,0,10},
+ {4,0,10}, {6,0,10}, {2,0,10}, {1,0,10},
+ {5,0,10}, {7,0,10}, {-1,-1,-1}, {-1,-1,-1},
+ {6,0,10}, {2,1,10}, {-1,-1,-1}, {0,1,10},
+ /* hat #1 in metatile #10 (type F) */
+ {1,1,10}, {-1,-1,-1}, {7,0,10}, {-1,-1,-1},
+ {0,1,7}, {0,1,10}, {5,1,10}, {2,1,10},
+ {7,0,10}, {3,1,10}, {1,1,10}, {5,1,10},
+ {2,1,10}, {4,0,10}, {4,1,10}, {7,3,1},
+ {3,2,1}, {5,1,10}, {7,3,1}, {3,1,10},
+ {4,1,10}, {6,1,10}, {2,1,10}, {1,1,10},
+ {5,1,10}, {7,1,10}, {0,1,7}, {7,0,7},
+ {6,1,10}, {2,2,1}, {6,0,7}, {0,2,1},
+ /* hat #2 in metatile #10 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ /* hat #3 in metatile #10 (type F) does not exist */
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+ {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1}, {-1,-1,-1},
+};
+static const KitemapEntry *const kitemap[] = {
+ kitemap_H,
+ kitemap_T,
+ kitemap_P,
+ kitemap_F,
+};
+
+static const MetamapEntry metamap_H[] = {
+ /* 0, 0 -> */ {0, 0}, /* no alternatives */
+ /* 1, 0 -> */ {1, 0}, /* no alternatives */
+ /* 2, 0 -> */ {2, 0}, /* no alternatives */
+ /* 3, 0 -> */ {3, 0}, /* no alternatives */
+ /* 4, 0 -> */ {3, 4},
+ /* 5, 0 -> */ {2, 8},
+ /* 6, 0 -> */ {3, 3},
+ /* 7, 0 -> */ {8, 4},
+ /* 8, 0 -> */ {9, 8},
+ /* 9, 0 -> */ {9, 4},
+ /* 10, 0 -> */ {8, 1},
+ /* 11, 0 -> */ {10, 5},
+ /* 12, 0 -> */ {5, 3},
+ /* 0, 1 -> */ {0, 1}, /* no alternatives */
+ /* 1, 1 -> */ {1, 1}, /* no alternatives */
+ /* 2, 1 -> */ {2, 1}, /* no alternatives */
+ /* 3, 1 -> */ {3, 1}, /* no alternatives */
+ /* 4, 1 -> */ {2, 9},
+ /* 5, 1 -> */ {2, 3},
+ /* 6, 1 -> */ {2, 6},
+ /* 7, 1 -> */ {10, 4},
+ /* 8, 1 -> */ {6, 3},
+ /* 9, 1 -> */ {9, 9},
+ /* 10, 1 -> */ {6, 10},
+ /* 11, 1 -> */ {4, 3},
+ /* 12, 1 -> */ {6, 6},
+ /* 0, 2 -> */ {0, 2}, /* no alternatives */
+ /* 1, 2 -> */ {1, 2}, /* no alternatives */
+ /* 2, 2 -> */ {2, 2}, /* no alternatives */
+ /* 3, 2 -> */ {3, 2}, /* no alternatives */
+ /* 4, 2 -> */ {3, 5},
+ /* 5, 2 -> */ {2, 12},
+ /* 6, 2 -> */ {1, 3},
+ /* 7, 2 -> */ {8, 5},
+ /* 8, 2 -> */ {9, 12},
+ /* 9, 2 -> */ {9, 5},
+ /* 10, 2 -> */ {12, 0},
+ /* 11, 2 -> */ {5, 6},
+ /* 12, 2 -> */ {11, 1},
+ /* 0, 3 -> */ {0, 3}, /* no alternatives */
+ /* 1, 3 -> */ {6, 2},
+ /* 2, 3 -> */ {5, 1},
+ /* 3, 3 -> */ {6, 0},
+ /* 4, 3 -> */ {12, 2},
+ /* 5, 3 -> */ {10, 2},
+ /* 6, 3 -> */ {10, 0},
+ /* 7, 3 -> */ {-1,-1}, /* does not exist */
+ /* 8, 3 -> */ {-1,-1}, /* does not exist */
+ /* 9, 3 -> */ {-1,-1}, /* does not exist */
+ /* 10, 3 -> */ {-1,-1}, /* does not exist */
+ /* 11, 3 -> */ {-1,-1}, /* does not exist */
+ /* 12, 3 -> */ {-1,-1}, /* does not exist */
+ /* 0, 4 -> */ {0, 4}, /* no alternatives */
+ /* 1, 4 -> */ {1, 4}, /* no alternatives */
+ /* 2, 4 -> */ {2, 4}, /* no alternatives */
+ /* 3, 4 -> */ {4, 0},
+ /* 4, 4 -> */ {4, 4}, /* no alternatives */
+ /* 5, 4 -> */ {5, 7},
+ /* 6, 4 -> */ {6, 4}, /* no alternatives */
+ /* 7, 4 -> */ {4, 9},
+ /* 8, 4 -> */ {6, 7},
+ /* 9, 4 -> */ {9, 0},
+ /* 10, 4 -> */ {8, 9},
+ /* 11, 4 -> */ {-1,-1}, /* does not exist */
+ /* 12, 4 -> */ {-1,-1}, /* does not exist */
+ /* 0, 5 -> */ {0, 5}, /* no alternatives */
+ /* 1, 5 -> */ {1, 5}, /* no alternatives */
+ /* 2, 5 -> */ {2, 5}, /* no alternatives */
+ /* 3, 5 -> */ {4, 2},
+ /* 4, 5 -> */ {4, 5}, /* no alternatives */
+ /* 5, 5 -> */ {5, 11},
+ /* 6, 5 -> */ {6, 5}, /* no alternatives */
+ /* 7, 5 -> */ {4, 8},
+ /* 8, 5 -> */ {6, 11},
+ /* 9, 5 -> */ {9, 2},
+ /* 10, 5 -> */ {8, 8},
+ /* 11, 5 -> */ {-1,-1}, /* does not exist */
+ /* 12, 5 -> */ {-1,-1}, /* does not exist */
+ /* 0, 6 -> */ {0, 6}, /* no alternatives */
+ /* 1, 6 -> */ {1, 6}, /* no alternatives */
+ /* 2, 6 -> */ {6, 1},
+ /* 3, 6 -> */ {3, 6}, /* no alternatives */
+ /* 4, 6 -> */ {4, 6}, /* no alternatives */
+ /* 5, 6 -> */ {8, 12},
+ /* 6, 6 -> */ {12, 1},
+ /* 7, 6 -> */ {10, 1},
+ /* 8, 6 -> */ {4, 12},
+ /* 9, 6 -> */ {9, 6}, /* no alternatives */
+ /* 10, 6 -> */ {5, 10},
+ /* 11, 6 -> */ {-1,-1}, /* does not exist */
+ /* 12, 6 -> */ {-1,-1}, /* does not exist */
+ /* 0, 7 -> */ {0, 7}, /* no alternatives */
+ /* 1, 7 -> */ {1, 7}, /* no alternatives */
+ /* 2, 7 -> */ {2, 7}, /* no alternatives */
+ /* 3, 7 -> */ {3, 7}, /* no alternatives */
+ /* 4, 7 -> */ {4, 7}, /* no alternatives */
+ /* 5, 7 -> */ {5, 4},
+ /* 6, 7 -> */ {7, 0},
+ /* 7, 7 -> */ {10, 8},
+ /* 8, 7 -> */ {8, 7}, /* no alternatives */
+ /* 9, 7 -> */ {9, 7}, /* no alternatives */
+ /* 10, 7 -> */ {10, 7}, /* no alternatives */
+ /* 11, 7 -> */ {-1,-1}, /* does not exist */
+ /* 12, 7 -> */ {-1,-1}, /* does not exist */
+ /* 0, 8 -> */ {0, 8}, /* no alternatives */
+ /* 1, 8 -> */ {1, 8}, /* no alternatives */
+ /* 2, 8 -> */ {5, 0},
+ /* 3, 8 -> */ {3, 8}, /* no alternatives */
+ /* 4, 8 -> */ {7, 5},
+ /* 5, 8 -> */ {5, 8}, /* no alternatives */
+ /* 6, 8 -> */ {6, 8}, /* no alternatives */
+ /* 7, 8 -> */ {7, 8}, /* no alternatives */
+ /* 8, 8 -> */ {11, 0},
+ /* 9, 8 -> */ {8, 0},
+ /* 10, 8 -> */ {7, 7},
+ /* 11, 8 -> */ {-1,-1}, /* does not exist */
+ /* 12, 8 -> */ {-1,-1}, /* does not exist */
+ /* 0, 9 -> */ {0, 9}, /* no alternatives */
+ /* 1, 9 -> */ {1, 9}, /* no alternatives */
+ /* 2, 9 -> */ {4, 1},
+ /* 3, 9 -> */ {3, 9}, /* no alternatives */
+ /* 4, 9 -> */ {7, 4},
+ /* 5, 9 -> */ {5, 9}, /* no alternatives */
+ /* 6, 9 -> */ {6, 9}, /* no alternatives */
+ /* 7, 9 -> */ {7, 9}, /* no alternatives */
+ /* 8, 9 -> */ {7, 1},
+ /* 9, 9 -> */ {9, 1},
+ /* 10, 9 -> */ {7, 10},
+ /* 11, 9 -> */ {-1,-1}, /* does not exist */
+ /* 12, 9 -> */ {-1,-1}, /* does not exist */
+ /* 0, 10 -> */ {0, 10}, /* no alternatives */
+ /* 1, 10 -> */ {1, 10}, /* no alternatives */
+ /* 2, 10 -> */ {2, 10}, /* no alternatives */
+ /* 3, 10 -> */ {3, 10}, /* no alternatives */
+ /* 4, 10 -> */ {4, 10}, /* no alternatives */
+ /* 5, 10 -> */ {10, 6},
+ /* 6, 10 -> */ {7, 6},
+ /* 7, 10 -> */ {10, 9},
+ /* 8, 10 -> */ {8, 10}, /* no alternatives */
+ /* 9, 10 -> */ {9, 10}, /* no alternatives */
+ /* 10, 10 -> */ {10, 10}, /* no alternatives */
+ /* 11, 10 -> */ {-1,-1}, /* does not exist */
+ /* 12, 10 -> */ {-1,-1}, /* does not exist */
+ /* 0, 11 -> */ {0, 11}, /* no alternatives */
+ /* 1, 11 -> */ {1, 11}, /* no alternatives */
+ /* 2, 11 -> */ {2, 11}, /* no alternatives */
+ /* 3, 11 -> */ {3, 11}, /* no alternatives */
+ /* 4, 11 -> */ {4, 11}, /* no alternatives */
+ /* 5, 11 -> */ {5, 5},
+ /* 6, 11 -> */ {7, 2},
+ /* 7, 11 -> */ {10, 12},
+ /* 8, 11 -> */ {8, 11}, /* no alternatives */
+ /* 9, 11 -> */ {9, 11}, /* no alternatives */
+ /* 10, 11 -> */ {10, 11}, /* no alternatives */
+ /* 11, 11 -> */ {-1,-1}, /* does not exist */
+ /* 12, 11 -> */ {-1,-1}, /* does not exist */
+ /* 0, 12 -> */ {0, 12}, /* no alternatives */
+ /* 1, 12 -> */ {1, 12}, /* no alternatives */
+ /* 2, 12 -> */ {5, 2},
+ /* 3, 12 -> */ {3, 12}, /* no alternatives */
+ /* 4, 12 -> */ {8, 6},
+ /* 5, 12 -> */ {5, 12}, /* no alternatives */
+ /* 6, 12 -> */ {6, 12}, /* no alternatives */
+ /* 7, 12 -> */ {7, 12}, /* no alternatives */
+ /* 8, 12 -> */ {11, 2},
+ /* 9, 12 -> */ {8, 2},
+ /* 10, 12 -> */ {7, 11},
+ /* 11, 12 -> */ {-1,-1}, /* does not exist */
+ /* 12, 12 -> */ {-1,-1}, /* does not exist */
+};
+static const MetamapEntry metamap_T[] = {
+ /* 0, 0 -> */ {0, 0}, /* no alternatives */
+ /* 1, 0 -> */ {1, 0}, /* no alternatives */
+ /* 2, 0 -> */ {2, 0}, /* no alternatives */
+ /* 3, 0 -> */ {3, 0}, /* no alternatives */
+ /* 4, 0 -> */ {3, 3},
+ /* 5, 0 -> */ {3, 1},
+ /* 6, 0 -> */ {2, 2},
+ /* 7, 0 -> */ {8, 3},
+ /* 8, 0 -> */ {9, 1},
+ /* 9, 0 -> */ {9, 3},
+ /* 10, 0 -> */ {4, 6},
+ /* 11, 0 -> */ {4, 4},
+ /* 12, 0 -> */ {6, 2},
+ /* 0, 1 -> */ {0, 1}, /* no alternatives */
+ /* 1, 1 -> */ {1, 1}, /* no alternatives */
+ /* 2, 1 -> */ {2, 1}, /* no alternatives */
+ /* 3, 1 -> */ {5, 0},
+ /* 4, 1 -> */ {4, 1}, /* no alternatives */
+ /* 5, 1 -> */ {8, 4},
+ /* 6, 1 -> */ {6, 1}, /* no alternatives */
+ /* 7, 1 -> */ {6, 5},
+ /* 8, 1 -> */ {11, 0},
+ /* 9, 1 -> */ {8, 0},
+ /* 10, 1 -> */ {5, 5},
+ /* 11, 1 -> */ {-1,-1}, /* does not exist */
+ /* 12, 1 -> */ {-1,-1}, /* does not exist */
+ /* 0, 2 -> */ {0, 2}, /* no alternatives */
+ /* 1, 2 -> */ {1, 2}, /* no alternatives */
+ /* 2, 2 -> */ {6, 0},
+ /* 3, 2 -> */ {3, 2}, /* no alternatives */
+ /* 4, 2 -> */ {4, 2}, /* no alternatives */
+ /* 5, 2 -> */ {5, 4},
+ /* 6, 2 -> */ {12, 0},
+ /* 7, 2 -> */ {10, 0},
+ /* 8, 2 -> */ {6, 4},
+ /* 9, 2 -> */ {9, 2}, /* no alternatives */
+ /* 10, 2 -> */ {8, 6},
+ /* 11, 2 -> */ {-1,-1}, /* does not exist */
+ /* 12, 2 -> */ {-1,-1}, /* does not exist */
+ /* 0, 3 -> */ {0, 3}, /* no alternatives */
+ /* 1, 3 -> */ {1, 3}, /* no alternatives */
+ /* 2, 3 -> */ {2, 3}, /* no alternatives */
+ /* 3, 3 -> */ {4, 0},
+ /* 4, 3 -> */ {4, 3}, /* no alternatives */
+ /* 5, 3 -> */ {8, 5},
+ /* 6, 3 -> */ {6, 3}, /* no alternatives */
+ /* 7, 3 -> */ {6, 6},
+ /* 8, 3 -> */ {4, 5},
+ /* 9, 3 -> */ {9, 0},
+ /* 10, 3 -> */ {5, 6},
+ /* 11, 3 -> */ {-1,-1}, /* does not exist */
+ /* 12, 3 -> */ {-1,-1}, /* does not exist */
+ /* 0, 4 -> */ {0, 4}, /* no alternatives */
+ /* 1, 4 -> */ {1, 4}, /* no alternatives */
+ /* 2, 4 -> */ {2, 4}, /* no alternatives */
+ /* 3, 4 -> */ {3, 4}, /* no alternatives */
+ /* 4, 4 -> */ {8, 1},
+ /* 5, 4 -> */ {5, 2},
+ /* 6, 4 -> */ {8, 2},
+ /* 7, 4 -> */ {7, 4}, /* no alternatives */
+ /* 8, 4 -> */ {5, 1},
+ /* 9, 4 -> */ {9, 4}, /* no alternatives */
+ /* 10, 4 -> */ {10, 4}, /* no alternatives */
+ /* 11, 4 -> */ {-1,-1}, /* does not exist */
+ /* 12, 4 -> */ {-1,-1}, /* does not exist */
+ /* 0, 5 -> */ {0, 5}, /* no alternatives */
+ /* 1, 5 -> */ {1, 5}, /* no alternatives */
+ /* 2, 5 -> */ {2, 5}, /* no alternatives */
+ /* 3, 5 -> */ {3, 5}, /* no alternatives */
+ /* 4, 5 -> */ {7, 0},
+ /* 5, 5 -> */ {10, 1},
+ /* 6, 5 -> */ {7, 1},
+ /* 7, 5 -> */ {7, 5}, /* no alternatives */
+ /* 8, 5 -> */ {5, 3},
+ /* 9, 5 -> */ {9, 5}, /* no alternatives */
+ /* 10, 5 -> */ {10, 5}, /* no alternatives */
+ /* 11, 5 -> */ {-1,-1}, /* does not exist */
+ /* 12, 5 -> */ {-1,-1}, /* does not exist */
+ /* 0, 6 -> */ {0, 6}, /* no alternatives */
+ /* 1, 6 -> */ {1, 6}, /* no alternatives */
+ /* 2, 6 -> */ {2, 6}, /* no alternatives */
+ /* 3, 6 -> */ {3, 6}, /* no alternatives */
+ /* 4, 6 -> */ {7, 2},
+ /* 5, 6 -> */ {10, 3},
+ /* 6, 6 -> */ {7, 3},
+ /* 7, 6 -> */ {7, 6}, /* no alternatives */
+ /* 8, 6 -> */ {10, 2},
+ /* 9, 6 -> */ {9, 6}, /* no alternatives */
+ /* 10, 6 -> */ {10, 6}, /* no alternatives */
+ /* 11, 6 -> */ {-1,-1}, /* does not exist */
+ /* 12, 6 -> */ {-1,-1}, /* does not exist */
+};
+static const MetamapEntry metamap_P[] = {
+ /* 0, 0 -> */ {0, 0}, /* no alternatives */
+ /* 1, 0 -> */ {1, 0}, /* no alternatives */
+ /* 2, 0 -> */ {2, 0}, /* no alternatives */
+ /* 3, 0 -> */ {3, 0}, /* no alternatives */
+ /* 4, 0 -> */ {3, 4},
+ /* 5, 0 -> */ {2, 5},
+ /* 6, 0 -> */ {2, 3},
+ /* 7, 0 -> */ {8, 4},
+ /* 8, 0 -> */ {9, 5},
+ /* 9, 0 -> */ {9, 4},
+ /* 10, 0 -> */ {4, 9},
+ /* 11, 0 -> */ {4, 8},
+ /* 12, 0 -> */ {6, 3},
+ /* 0, 1 -> */ {0, 1}, /* no alternatives */
+ /* 1, 1 -> */ {1, 1}, /* no alternatives */
+ /* 2, 1 -> */ {2, 1}, /* no alternatives */
+ /* 3, 1 -> */ {3, 1}, /* no alternatives */
+ /* 4, 1 -> */ {2, 10},
+ /* 5, 1 -> */ {3, 2},
+ /* 6, 1 -> */ {2, 4},
+ /* 7, 1 -> */ {8, 10},
+ /* 8, 1 -> */ {9, 2},
+ /* 9, 1 -> */ {9, 10},
+ /* 10, 1 -> */ {7, 4},
+ /* 11, 1 -> */ {8, 2},
+ /* 12, 1 -> */ {6, 4},
+ /* 0, 2 -> */ {0, 2}, /* no alternatives */
+ /* 1, 2 -> */ {1, 2}, /* no alternatives */
+ /* 2, 2 -> */ {2, 2}, /* no alternatives */
+ /* 3, 2 -> */ {5, 1},
+ /* 4, 2 -> */ {4, 2}, /* no alternatives */
+ /* 5, 2 -> */ {8, 6},
+ /* 6, 2 -> */ {6, 2}, /* no alternatives */
+ /* 7, 2 -> */ {6, 7},
+ /* 8, 2 -> */ {4, 6},
+ /* 9, 2 -> */ {8, 1},
+ /* 10, 2 -> */ {5, 7},
+ /* 11, 2 -> */ {-1,-1}, /* does not exist */
+ /* 12, 2 -> */ {-1,-1}, /* does not exist */
+ /* 0, 3 -> */ {0, 3}, /* no alternatives */
+ /* 1, 3 -> */ {1, 3}, /* no alternatives */
+ /* 2, 3 -> */ {6, 0},
+ /* 3, 3 -> */ {3, 3}, /* no alternatives */
+ /* 4, 3 -> */ {4, 3}, /* no alternatives */
+ /* 5, 3 -> */ {5, 8},
+ /* 6, 3 -> */ {12, 0},
+ /* 7, 3 -> */ {10, 0},
+ /* 8, 3 -> */ {6, 8},
+ /* 9, 3 -> */ {9, 3}, /* no alternatives */
+ /* 10, 3 -> */ {8, 9},
+ /* 11, 3 -> */ {-1,-1}, /* does not exist */
+ /* 12, 3 -> */ {-1,-1}, /* does not exist */
+ /* 0, 4 -> */ {0, 4}, /* no alternatives */
+ /* 1, 4 -> */ {1, 4}, /* no alternatives */
+ /* 2, 4 -> */ {6, 1},
+ /* 3, 4 -> */ {4, 0},
+ /* 4, 4 -> */ {4, 4}, /* no alternatives */
+ /* 5, 4 -> */ {5, 6},
+ /* 6, 4 -> */ {12, 1},
+ /* 7, 4 -> */ {6, 9},
+ /* 8, 4 -> */ {6, 6},
+ /* 9, 4 -> */ {9, 0},
+ /* 10, 4 -> */ {5, 9},
+ /* 11, 4 -> */ {-1,-1}, /* does not exist */
+ /* 12, 4 -> */ {-1,-1}, /* does not exist */
+ /* 0, 5 -> */ {0, 5}, /* no alternatives */
+ /* 1, 5 -> */ {1, 5}, /* no alternatives */
+ /* 2, 5 -> */ {5, 0},
+ /* 3, 5 -> */ {3, 5}, /* no alternatives */
+ /* 4, 5 -> */ {8, 8},
+ /* 5, 5 -> */ {5, 5}, /* no alternatives */
+ /* 6, 5 -> */ {6, 5}, /* no alternatives */
+ /* 7, 5 -> */ {7, 5}, /* no alternatives */
+ /* 8, 5 -> */ {11, 0},
+ /* 9, 5 -> */ {8, 0},
+ /* 10, 5 -> */ {7, 6},
+ /* 11, 5 -> */ {-1,-1}, /* does not exist */
+ /* 12, 5 -> */ {-1,-1}, /* does not exist */
+ /* 0, 6 -> */ {0, 6}, /* no alternatives */
+ /* 1, 6 -> */ {1, 6}, /* no alternatives */
+ /* 2, 6 -> */ {2, 6}, /* no alternatives */
+ /* 3, 6 -> */ {3, 6}, /* no alternatives */
+ /* 4, 6 -> */ {11, 1},
+ /* 5, 6 -> */ {5, 4},
+ /* 6, 6 -> */ {7, 0},
+ /* 7, 6 -> */ {10, 5},
+ /* 8, 6 -> */ {5, 2},
+ /* 9, 6 -> */ {9, 6}, /* no alternatives */
+ /* 10, 6 -> */ {10, 6}, /* no alternatives */
+ /* 11, 6 -> */ {-1,-1}, /* does not exist */
+ /* 12, 6 -> */ {-1,-1}, /* does not exist */
+ /* 0, 7 -> */ {0, 7}, /* no alternatives */
+ /* 1, 7 -> */ {1, 7}, /* no alternatives */
+ /* 2, 7 -> */ {2, 7}, /* no alternatives */
+ /* 3, 7 -> */ {3, 7}, /* no alternatives */
+ /* 4, 7 -> */ {7, 1},
+ /* 5, 7 -> */ {10, 2},
+ /* 6, 7 -> */ {7, 2},
+ /* 7, 7 -> */ {7, 7}, /* no alternatives */
+ /* 8, 7 -> */ {4, 10},
+ /* 9, 7 -> */ {9, 7}, /* no alternatives */
+ /* 10, 7 -> */ {10, 7}, /* no alternatives */
+ /* 11, 7 -> */ {-1,-1}, /* does not exist */
+ /* 12, 7 -> */ {-1,-1}, /* does not exist */
+ /* 0, 8 -> */ {0, 8}, /* no alternatives */
+ /* 1, 8 -> */ {1, 8}, /* no alternatives */
+ /* 2, 8 -> */ {2, 8}, /* no alternatives */
+ /* 3, 8 -> */ {3, 8}, /* no alternatives */
+ /* 4, 8 -> */ {8, 5},
+ /* 5, 8 -> */ {5, 3},
+ /* 6, 8 -> */ {8, 3},
+ /* 7, 8 -> */ {7, 8}, /* no alternatives */
+ /* 8, 8 -> */ {4, 5},
+ /* 9, 8 -> */ {9, 8}, /* no alternatives */
+ /* 10, 8 -> */ {10, 8}, /* no alternatives */
+ /* 11, 8 -> */ {-1,-1}, /* does not exist */
+ /* 12, 8 -> */ {-1,-1}, /* does not exist */
+ /* 0, 9 -> */ {0, 9}, /* no alternatives */
+ /* 1, 9 -> */ {1, 9}, /* no alternatives */
+ /* 2, 9 -> */ {2, 9}, /* no alternatives */
+ /* 3, 9 -> */ {3, 9}, /* no alternatives */
+ /* 4, 9 -> */ {7, 3},
+ /* 5, 9 -> */ {10, 4},
+ /* 6, 9 -> */ {10, 1},
+ /* 7, 9 -> */ {10, 10},
+ /* 8, 9 -> */ {10, 3},
+ /* 9, 9 -> */ {9, 9}, /* no alternatives */
+ /* 10, 9 -> */ {10, 9}, /* no alternatives */
+ /* 11, 9 -> */ {-1,-1}, /* does not exist */
+ /* 12, 9 -> */ {-1,-1}, /* does not exist */
+ /* 0, 10 -> */ {0, 10}, /* no alternatives */
+ /* 1, 10 -> */ {1, 10}, /* no alternatives */
+ /* 2, 10 -> */ {4, 1},
+ /* 3, 10 -> */ {3, 10}, /* no alternatives */
+ /* 4, 10 -> */ {8, 7},
+ /* 5, 10 -> */ {5, 10}, /* no alternatives */
+ /* 6, 10 -> */ {6, 10}, /* no alternatives */
+ /* 7, 10 -> */ {7, 10}, /* no alternatives */
+ /* 8, 10 -> */ {4, 7},
+ /* 9, 10 -> */ {9, 1},
+ /* 10, 10 -> */ {7, 9},
+ /* 11, 10 -> */ {-1,-1}, /* does not exist */
+ /* 12, 10 -> */ {-1,-1}, /* does not exist */
+};
+static const MetamapEntry metamap_F[] = {
+ /* 0, 0 -> */ {0, 0}, /* no alternatives */
+ /* 1, 0 -> */ {1, 0}, /* no alternatives */
+ /* 2, 0 -> */ {2, 0}, /* no alternatives */
+ /* 3, 0 -> */ {3, 0}, /* no alternatives */
+ /* 4, 0 -> */ {3, 3},
+ /* 5, 0 -> */ {2, 4},
+ /* 6, 0 -> */ {2, 2},
+ /* 7, 0 -> */ {8, 3},
+ /* 8, 0 -> */ {9, 4},
+ /* 9, 0 -> */ {9, 3},
+ /* 10, 0 -> */ {4, 9},
+ /* 11, 0 -> */ {4, 8},
+ /* 12, 0 -> */ {6, 2},
+ /* 0, 1 -> */ {0, 1}, /* no alternatives */
+ /* 1, 1 -> */ {1, 1}, /* no alternatives */
+ /* 2, 1 -> */ {2, 1}, /* no alternatives */
+ /* 3, 1 -> */ {3, 1}, /* no alternatives */
+ /* 4, 1 -> */ {2, 10},
+ /* 5, 1 -> */ {2, 6},
+ /* 6, 1 -> */ {2, 3},
+ /* 7, 1 -> */ {8, 10},
+ /* 8, 1 -> */ {9, 6},
+ /* 9, 1 -> */ {9, 10},
+ /* 10, 1 -> */ {7, 3},
+ /* 11, 1 -> */ {8, 6},
+ /* 12, 1 -> */ {6, 3},
+ /* 0, 2 -> */ {0, 2}, /* no alternatives */
+ /* 1, 2 -> */ {1, 2}, /* no alternatives */
+ /* 2, 2 -> */ {6, 0},
+ /* 3, 2 -> */ {3, 2}, /* no alternatives */
+ /* 4, 2 -> */ {4, 2}, /* no alternatives */
+ /* 5, 2 -> */ {5, 8},
+ /* 6, 2 -> */ {12, 0},
+ /* 7, 2 -> */ {10, 0},
+ /* 8, 2 -> */ {6, 8},
+ /* 9, 2 -> */ {9, 2}, /* no alternatives */
+ /* 10, 2 -> */ {8, 9},
+ /* 11, 2 -> */ {-1,-1}, /* does not exist */
+ /* 12, 2 -> */ {-1,-1}, /* does not exist */
+ /* 0, 3 -> */ {0, 3}, /* no alternatives */
+ /* 1, 3 -> */ {1, 3}, /* no alternatives */
+ /* 2, 3 -> */ {6, 1},
+ /* 3, 3 -> */ {4, 0},
+ /* 4, 3 -> */ {4, 3}, /* no alternatives */
+ /* 5, 3 -> */ {5, 5},
+ /* 6, 3 -> */ {12, 1},
+ /* 7, 3 -> */ {6, 9},
+ /* 8, 3 -> */ {6, 5},
+ /* 9, 3 -> */ {9, 0},
+ /* 10, 3 -> */ {5, 9},
+ /* 11, 3 -> */ {-1,-1}, /* does not exist */
+ /* 12, 3 -> */ {-1,-1}, /* does not exist */
+ /* 0, 4 -> */ {0, 4}, /* no alternatives */
+ /* 1, 4 -> */ {1, 4}, /* no alternatives */
+ /* 2, 4 -> */ {5, 0},
+ /* 3, 4 -> */ {3, 4}, /* no alternatives */
+ /* 4, 4 -> */ {8, 8},
+ /* 5, 4 -> */ {5, 4}, /* no alternatives */
+ /* 6, 4 -> */ {6, 4}, /* no alternatives */
+ /* 7, 4 -> */ {7, 4}, /* no alternatives */
+ /* 8, 4 -> */ {11, 0},
+ /* 9, 4 -> */ {8, 0},
+ /* 10, 4 -> */ {7, 5},
+ /* 11, 4 -> */ {-1,-1}, /* does not exist */
+ /* 12, 4 -> */ {-1,-1}, /* does not exist */
+ /* 0, 5 -> */ {0, 5}, /* no alternatives */
+ /* 1, 5 -> */ {1, 5}, /* no alternatives */
+ /* 2, 5 -> */ {2, 5}, /* no alternatives */
+ /* 3, 5 -> */ {3, 5}, /* no alternatives */
+ /* 4, 5 -> */ {11, 1},
+ /* 5, 5 -> */ {5, 3},
+ /* 6, 5 -> */ {7, 0},
+ /* 7, 5 -> */ {10, 4},
+ /* 8, 5 -> */ {4, 6},
+ /* 9, 5 -> */ {9, 5}, /* no alternatives */
+ /* 10, 5 -> */ {10, 5}, /* no alternatives */
+ /* 11, 5 -> */ {-1,-1}, /* does not exist */
+ /* 12, 5 -> */ {-1,-1}, /* does not exist */
+ /* 0, 6 -> */ {0, 6}, /* no alternatives */
+ /* 1, 6 -> */ {1, 6}, /* no alternatives */
+ /* 2, 6 -> */ {5, 1},
+ /* 3, 6 -> */ {3, 6}, /* no alternatives */
+ /* 4, 6 -> */ {8, 5},
+ /* 5, 6 -> */ {5, 6}, /* no alternatives */
+ /* 6, 6 -> */ {6, 6}, /* no alternatives */
+ /* 7, 6 -> */ {7, 6}, /* no alternatives */
+ /* 8, 6 -> */ {4, 5},
+ /* 9, 6 -> */ {8, 1},
+ /* 10, 6 -> */ {7, 7},
+ /* 11, 6 -> */ {-1,-1}, /* does not exist */
+ /* 12, 6 -> */ {-1,-1}, /* does not exist */
+ /* 0, 7 -> */ {0, 7}, /* no alternatives */
+ /* 1, 7 -> */ {1, 7}, /* no alternatives */
+ /* 2, 7 -> */ {2, 7}, /* no alternatives */
+ /* 3, 7 -> */ {3, 7}, /* no alternatives */
+ /* 4, 7 -> */ {4, 7}, /* no alternatives */
+ /* 5, 7 -> */ {4, 10},
+ /* 6, 7 -> */ {7, 1},
+ /* 7, 7 -> */ {10, 6},
+ /* 8, 7 -> */ {8, 7}, /* no alternatives */
+ /* 9, 7 -> */ {9, 7}, /* no alternatives */
+ /* 10, 7 -> */ {10, 7}, /* no alternatives */
+ /* 11, 7 -> */ {-1,-1}, /* does not exist */
+ /* 12, 7 -> */ {-1,-1}, /* does not exist */
+ /* 0, 8 -> */ {0, 8}, /* no alternatives */
+ /* 1, 8 -> */ {1, 8}, /* no alternatives */
+ /* 2, 8 -> */ {2, 8}, /* no alternatives */
+ /* 3, 8 -> */ {3, 8}, /* no alternatives */
+ /* 4, 8 -> */ {8, 4},
+ /* 5, 8 -> */ {5, 2},
+ /* 6, 8 -> */ {8, 2},
+ /* 7, 8 -> */ {7, 8}, /* no alternatives */
+ /* 8, 8 -> */ {4, 4},
+ /* 9, 8 -> */ {9, 8}, /* no alternatives */
+ /* 10, 8 -> */ {10, 8}, /* no alternatives */
+ /* 11, 8 -> */ {-1,-1}, /* does not exist */
+ /* 12, 8 -> */ {-1,-1}, /* does not exist */
+ /* 0, 9 -> */ {0, 9}, /* no alternatives */
+ /* 1, 9 -> */ {1, 9}, /* no alternatives */
+ /* 2, 9 -> */ {2, 9}, /* no alternatives */
+ /* 3, 9 -> */ {3, 9}, /* no alternatives */
+ /* 4, 9 -> */ {7, 2},
+ /* 5, 9 -> */ {10, 3},
+ /* 6, 9 -> */ {10, 1},
+ /* 7, 9 -> */ {10, 10},
+ /* 8, 9 -> */ {10, 2},
+ /* 9, 9 -> */ {9, 9}, /* no alternatives */
+ /* 10, 9 -> */ {10, 9}, /* no alternatives */
+ /* 11, 9 -> */ {-1,-1}, /* does not exist */
+ /* 12, 9 -> */ {-1,-1}, /* does not exist */
+ /* 0, 10 -> */ {0, 10}, /* no alternatives */
+ /* 1, 10 -> */ {1, 10}, /* no alternatives */
+ /* 2, 10 -> */ {4, 1},
+ /* 3, 10 -> */ {3, 10}, /* no alternatives */
+ /* 4, 10 -> */ {5, 7},
+ /* 5, 10 -> */ {5, 10}, /* no alternatives */
+ /* 6, 10 -> */ {6, 10}, /* no alternatives */
+ /* 7, 10 -> */ {7, 10}, /* no alternatives */
+ /* 8, 10 -> */ {6, 7},
+ /* 9, 10 -> */ {9, 1},
+ /* 10, 10 -> */ {7, 9},
+ /* 11, 10 -> */ {-1,-1}, /* does not exist */
+ /* 12, 10 -> */ {-1,-1}, /* does not exist */
+};
+static const MetamapEntry *const metamap[] = {
+ metamap_H,
+ metamap_T,
+ metamap_P,
+ metamap_F,
+};
diff --git a/hat.c b/hat.c
new file mode 100644
index 0000000..d59f81e
--- /dev/null
+++ b/hat.c
@@ -0,0 +1,1248 @@
+/*
+ * Code to generate patches of the aperiodic 'hat' tiling discovered
+ * in 2023.
+ *
+ * aux/doc/hats.html contains an explanation of the basic ideas of
+ * this algorithm, which can't really be put in a source file because
+ * it just has too many complicated diagrams. So read that first,
+ * because the comments in here will refer to it.
+ *
+ * Discoverers' website: https://cs.uwaterloo.ca/~csk/hat/
+ * Preprint of paper: https://arxiv.org/abs/2303.10798
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "puzzles.h"
+#include "hat.h"
+
+/*
+ * Coordinate system:
+ *
+ * The output of this code lives on the tiling known to grid.c as
+ * 'Kites', which can be viewed as a tiling of hexagons each of which
+ * is subdivided into six kites sharing their pointy vertex, or
+ * (equivalently) a tiling of equilateral triangles each subdivided
+ * into three kits sharing their blunt vertex.
+ *
+ * We express coordinates in this system relative to the basis (1, r)
+ * where r = (1 + sqrt(3)i) / 2 is a primitive 6th root of unity. This
+ * gives us a system in which two integer coordinates can address any
+ * grid point, provided we scale up so that the side length of the
+ * equilateral triangles in the tiling is 6.
+ */
+
+typedef struct Point {
+ int x, y; /* represents x + yr */
+} Point;
+
+static inline Point pointscale(int scale, Point a)
+{
+ Point r = { scale * a.x, scale * a.y };
+ return r;
+}
+
+static inline Point pointadd(Point a, Point b)
+{
+ Point r = { a.x + b.x, a.y + b.y };
+ return r;
+}
+
+/*
+ * We identify a single kite by the coordinates of its four vertices.
+ * This allows us to construct the coordinates of an adjacent kite by
+ * taking affine transformations of the original kite's vertices.
+ *
+ * This is a useful way to do it because it means that if you reflect
+ * the kite (by swapping its left and right vertices) then these
+ * transformations also perform in a reflected way. This will be
+ * useful in the code below that outputs the coordinates of each hat,
+ * because this way it can work by walking around its 8 kites using a
+ * fixed set of steps, and if the hat is reflected, then we just
+ * reflect the starting kite before doing that, and everything still
+ * works.
+ */
+
+typedef struct Kite {
+ Point centre, left, right, outer;
+} Kite;
+
+static inline Kite kite_left(Kite k)
+{
+ Kite r;
+ r.centre = k.centre;
+ r.right = k.left;
+ r.outer = pointadd(pointscale(2, k.left), pointscale(-1, k.outer));
+ r.left = pointadd(pointadd(k.centre, k.left), pointscale(-1, k.right));
+ return r;
+}
+
+static inline Kite kite_right(Kite k)
+{
+ Kite r;
+ r.centre = k.centre;
+ r.left = k.right;
+ r.outer = pointadd(pointscale(2, k.right), pointscale(-1, k.outer));
+ r.right = pointadd(pointadd(k.centre, k.right), pointscale(-1, k.left));
+ return r;
+}
+
+static inline Kite kite_forward_left(Kite k)
+{
+ Kite r;
+ r.outer = k.outer;
+ r.right = k.left;
+ r.centre = pointadd(pointscale(2, k.left), pointscale(-1, k.centre));
+ r.left = pointadd(pointadd(k.right, k.left), pointscale(-1, k.centre));
+ return r;
+}
+
+static inline Kite kite_forward_right(Kite k)
+{
+ Kite r;
+ r.outer = k.outer;
+ r.left = k.right;
+ r.centre = pointadd(pointscale(2, k.right), pointscale(-1, k.centre));
+ r.right = pointadd(pointadd(k.left, k.right), pointscale(-1, k.centre));
+ return r;
+}
+
+typedef enum KiteStep { KS_LEFT, KS_RIGHT, KS_F_LEFT, KS_F_RIGHT } KiteStep;
+
+static inline Kite kite_step(Kite k, KiteStep step)
+{
+ switch (step) {
+ case KS_LEFT: return kite_left(k);
+ case KS_RIGHT: return kite_right(k);
+ case KS_F_LEFT: return kite_forward_left(k);
+ default /* case KS_F_RIGHT */: return kite_forward_right(k);
+ }
+}
+
+/*
+ * Function to enumerate the kites in a rectangular region, in a
+ * serpentine-raster fashion so that every kite delivered shares an
+ * edge with a recent previous one.
+ */
+#define KE_NKEEP 3
+typedef struct KiteEnum {
+ /* Fields private to the enumerator */
+ int state;
+ int x, y, w, h;
+ unsigned curr_index;
+
+ /* Fields the client can legitimately read out */
+ Kite *curr;
+ Kite recent[KE_NKEEP];
+ unsigned last_index;
+ KiteStep last_step; /* step that got curr from recent[last_index] */
+} KiteEnum;
+
+static void first_kite(KiteEnum *s, int w, int h)
+{
+ Kite start = { {0,0}, {0, 3}, {3, 0}, {2, 2} };
+ size_t i;
+
+ for (i = 0; i < KE_NKEEP; i++)
+ s->recent[i] = start; /* initialise to *something* */
+ s->curr_index = 0;
+ s->curr = &s->recent[s->curr_index];
+ s->state = 1;
+ s->w = w;
+ s->h = h;
+ s->x = 0;
+ s->y = 0;
+}
+static bool next_kite(KiteEnum *s)
+{
+ unsigned lastbut1 = s->last_index;
+ s->last_index = s->curr_index;
+ s->curr_index = (s->curr_index + 1) % KE_NKEEP;
+ s->curr = &s->recent[s->curr_index];
+
+ switch (s->state) {
+ /* States 1,2,3 walk rightwards along the upper side of a
+ * horizontal grid line with a pointy kite end at the start
+ * point */
+ case 1:
+ s->last_step = KS_F_RIGHT;
+ s->state = 2;
+ break;
+
+ case 2:
+ if (s->x+1 >= s->w) {
+ s->last_step = KS_F_RIGHT;
+ s->state = 4;
+ break;
+ }
+ s->last_step = KS_RIGHT;
+ s->state = 3;
+ s->x++;
+ break;
+
+ case 3:
+ s->last_step = KS_RIGHT;
+ s->state = 1;
+ break;
+
+ /* State 4 is special: we've just moved up into a row below a
+ * grid line, but we can't produce the rightmost tile of that
+ * row because it's not adjacent any tile so far emitted. So
+ * instead, emit the second-rightmost tile, and next time,
+ * we'll emit the rightmost. */
+ case 4:
+ s->last_step = KS_LEFT;
+ s->state = 5;
+ break;
+
+ /* And now we have to emit the third-rightmost tile relative
+ * to the last but one tile we emitted (the one from state 2,
+ * not state 4). */
+ case 5:
+ s->last_step = KS_RIGHT;
+ s->last_index = lastbut1;
+ s->state = 6;
+ break;
+
+ /* Now states 6-8 handle the general case of walking leftwards
+ * along the lower side of a line, starting from a
+ * right-angled kite end. */
+ case 6:
+ if (s->x <= 0) {
+ if (s->y+1 >= s->h) {
+ s->state = 0;
+ return false;
+ }
+ s->last_step = KS_RIGHT;
+ s->state = 9;
+ s->y++;
+ break;
+ }
+ s->last_step = KS_F_RIGHT;
+ s->state = 7;
+ s->x--;
+ break;
+
+ case 7:
+ s->last_step = KS_RIGHT;
+ s->state = 8;
+ break;
+
+ case 8:
+ s->last_step = KS_RIGHT;
+ s->state = 6;
+ break;
+
+ /* States 9,10,11 walk rightwards along the upper side of a
+ * horizontal grid line with a right-angled kite end at the
+ * start point. This time there's no awkward transition from
+ * the previous row. */
+ case 9:
+ s->last_step = KS_RIGHT;
+ s->state = 10;
+ break;
+
+ case 10:
+ s->last_step = KS_RIGHT;
+ s->state = 11;
+ break;
+
+ case 11:
+ if (s->x+1 >= s->w) {
+ /* Another awkward transition to the next row, where we
+ * have to generate it based on the previous state-9 tile.
+ * But this time at least we generate the rightmost tile
+ * of the new row, so the next states will be simple. */
+ s->last_step = KS_F_RIGHT;
+ s->last_index = lastbut1;
+ s->state = 12;
+ break;
+ }
+ s->last_step = KS_F_RIGHT;
+ s->state = 9;
+ s->x++;
+ break;
+
+ /* States 12,13,14 walk leftwards along the upper edge of a
+ * horizontal grid line with a pointy kite end at the start
+ * point */
+ case 12:
+ s->last_step = KS_F_RIGHT;
+ s->state = 13;
+ break;
+
+ case 13:
+ if (s->x <= 0) {
+ if (s->y+1 >= s->h) {
+ s->state = 0;
+ return false;
+ }
+ s->last_step = KS_LEFT;
+ s->state = 1;
+ s->y++;
+ break;
+ }
+ s->last_step = KS_RIGHT;
+ s->state = 14;
+ s->x--;
+ break;
+
+ case 14:
+ s->last_step = KS_RIGHT;
+ s->state = 12;
+ break;
+
+ default:
+ return false;
+ }
+
+ *s->curr = kite_step(s->recent[s->last_index], s->last_step);
+ return true;
+}
+
+/*
+ * Assorted useful definitions.
+ */
+typedef enum TileType { TT_H, TT_T, TT_P, TT_F, TT_KITE, TT_HAT } TileType;
+static const char tilechars[] = "HTPF";
+
+#define HAT_KITES 8 /* number of kites in a hat */
+#define MT_MAXEXPAND 13 /* largest number of metatiles in any expansion */
+
+/*
+ * Definitions for the autogenerated hat-tables.h header file that
+ * defines all the lookup tables.
+ */
+typedef struct MetatilePossibleParent {
+ TileType type;
+ unsigned index;
+} MetatilePossibleParent;
+
+typedef struct KitemapEntry {
+ int kite, hat, meta; /* all -1 if impossible */
+} KitemapEntry;
+
+typedef struct MetamapEntry {
+ int meta, meta2;
+} MetamapEntry;
+
+static inline size_t kitemap_index(KiteStep step, unsigned kite,
+ unsigned hat, unsigned meta)
+{
+ return step + 4 * (kite + 8 * (hat + 4 * meta));
+}
+
+static inline size_t metamap_index(unsigned meta, unsigned meta2)
+{
+ return meta2 * MT_MAXEXPAND + meta;
+}
+
+/*
+ * The actual tables.
+ */
+#include "hat-tables.h"
+
+/*
+ * Coordinate system for tracking kites within a randomly selected
+ * part of the recursively expanded hat tiling.
+ *
+ * HatCoords will store an array of HatCoord, in little-endian
+ * arrangement. So hc->c[0] will always have type TT_KITE and index a
+ * single kite within a hat; hc->c[1] will have type TT_HAT and index
+ * a hat within a first-order metatile; hc->c[2] will be the smallest
+ * metatile containing this hat, and hc->c[3, 4, 5, ...] will be
+ * higher-order metatiles as needed.
+ *
+ * The last coordinate stored, hc->c[hc->nc-1], will have a tile type
+ * but no index (represented by index==-1). This means "we haven't
+ * decided yet what this level of metatile needs to be". If we need to
+ * refer to this level during the step_coords algorithm, we make it up
+ * at random, based on a table of what metatiles each type can
+ * possibly be part of, at what index.
+ */
+typedef struct HatCoord {
+ int index; /* index within that tile, or -1 if not yet known */
+ TileType type; /* type of this tile */
+} HatCoord;
+
+typedef struct HatCoords {
+ HatCoord *c;
+ size_t nc, csize;
+} HatCoords;
+
+static HatCoords *hc_new(void)
+{
+ HatCoords *hc = snew(HatCoords);
+ hc->nc = hc->csize = 0;
+ hc->c = NULL;
+ return hc;
+}
+
+static void hc_free(HatCoords *hc)
+{
+ if (hc) {
+ sfree(hc->c);
+ sfree(hc);
+ }
+}
+
+static void hc_make_space(HatCoords *hc, size_t size)
+{
+ if (hc->csize < size) {
+ hc->csize = hc->csize * 5 / 4 + 16;
+ if (hc->csize < size)
+ hc->csize = size;
+ hc->c = sresize(hc->c, hc->csize, HatCoord);
+ }
+}
+
+static HatCoords *hc_copy(HatCoords *hc_in)
+{
+ HatCoords *hc_out = hc_new();
+ hc_make_space(hc_out, hc_in->nc);
+ memcpy(hc_out->c, hc_in->c, hc_in->nc * sizeof(*hc_out->c));
+ hc_out->nc = hc_in->nc;
+ return hc_out;
+}
+
+/*
+ * HatCoordContext is the shared context of a whole run of the
+ * algorithm. Its 'prototype' HatCoords object represents the
+ * coordinates of the starting kite, and is extended as necessary; any
+ * other HatCoord that needs extending will copy the higher-order
+ * values from ctx->prototype as needed, so that once each choice has
+ * been made, it remains consistent.
+ *
+ * When we're inventing a random piece of tiling in the first place,
+ * we append to ctx->prototype by choosing a random (but legal)
+ * higher-level metatile for the current topmost one to turn out to be
+ * part of. When we're replaying a generation whose parameters are
+ * already stored, we don't have a random_state, and we make fixed
+ * decisions if not enough coordinates were provided.
+ *
+ * (Of course another approach would be to reject grid descriptions
+ * that didn't define enough coordinates! But that would involve a
+ * whole extra iteration over the whole grid region just for
+ * validation, and that seems like more timewasting than really
+ * needed. So we tolerate short descriptions, and do something
+ * deterministic with them.)
+ */
+
+typedef struct HatCoordContext {
+ random_state *rs;
+ HatCoords *prototype;
+} HatCoordContext;
+
+static void init_coords_random(HatCoordContext *ctx, random_state *rs)
+{
+ ctx->rs = rs;
+ ctx->prototype = hc_new();
+ hc_make_space(ctx->prototype, 3);
+ ctx->prototype->c[0].type = TT_KITE;
+ ctx->prototype->c[1].type = TT_HAT;
+ ctx->prototype->c[2].type = random_upto(rs, 4);
+ ctx->prototype->c[2].index = -1;
+ ctx->prototype->c[1].index = random_upto(
+ rs, hats_in_metatile[ctx->prototype->c[2].type]);
+ ctx->prototype->c[0].index = random_upto(rs, HAT_KITES);
+ ctx->prototype->nc = 3;
+}
+
+static inline int metatile_char_to_enum(char metatile)
+{
+ return (metatile == 'H' ? TT_H :
+ metatile == 'T' ? TT_T :
+ metatile == 'P' ? TT_P :
+ metatile == 'F' ? TT_F : -1);
+}
+
+static void init_coords_params(HatCoordContext *ctx,
+ const struct HatPatchParams *hp)
+{
+ size_t i;
+
+ ctx->rs = NULL;
+ ctx->prototype = hc_new();
+
+ assert(hp->ncoords >= 3);
+
+ hc_make_space(ctx->prototype, hp->ncoords + 1);
+ ctx->prototype->nc = hp->ncoords + 1;
+
+ for (i = 0; i < hp->ncoords; i++)
+ ctx->prototype->c[i].index = hp->coords[i];
+
+ ctx->prototype->c[hp->ncoords].type =
+ metatile_char_to_enum(hp->final_metatile);
+ ctx->prototype->c[hp->ncoords].index = -1;
+
+ ctx->prototype->c[0].type = TT_KITE;
+ ctx->prototype->c[1].type = TT_HAT;
+
+ for (i = hp->ncoords - 1; i > 1; i--) {
+ TileType metatile = ctx->prototype->c[i+1].type;
+ assert(hp->coords[i] < nchildren[metatile]);
+ ctx->prototype->c[i].type = children[metatile][hp->coords[i]];
+ }
+
+ assert(hp->coords[0] < 8);
+}
+
+static HatCoords *initial_coords(HatCoordContext *ctx)
+{
+ return hc_copy(ctx->prototype);
+}
+
+/*
+ * Extend hc until it has at least n coordinates in, by copying from
+ * ctx->prototype if needed, and extending ctx->prototype if needed in
+ * order to do that.
+ */
+static void ensure_coords(HatCoordContext *ctx, HatCoords *hc, size_t n)
+{
+ if (ctx->prototype->nc < n) {
+ hc_make_space(ctx->prototype, n);
+ while (ctx->prototype->nc < n) {
+ TileType type = ctx->prototype->c[ctx->prototype->nc - 1].type;
+ assert(ctx->prototype->c[ctx->prototype->nc - 1].index == -1);
+ const MetatilePossibleParent *parents = permitted_parents[type];
+ size_t parent_index;
+ if (ctx->rs) {
+ parent_index = random_upto(ctx->rs, n_permitted_parents[type]);
+ } else {
+ parent_index = 0;
+ }
+ ctx->prototype->c[ctx->prototype->nc - 1].index =
+ parents[parent_index].index;
+ ctx->prototype->c[ctx->prototype->nc].index = -1;
+ ctx->prototype->c[ctx->prototype->nc].type =
+ parents[parent_index].type;
+ ctx->prototype->nc++;
+ }
+ }
+
+ hc_make_space(hc, n);
+ while (hc->nc < n) {
+ assert(hc->c[hc->nc - 1].index == -1);
+ assert(hc->c[hc->nc - 1].type == ctx->prototype->c[hc->nc - 1].type);
+ hc->c[hc->nc - 1].index = ctx->prototype->c[hc->nc - 1].index;
+ hc->c[hc->nc].index = -1;
+ hc->c[hc->nc].type = ctx->prototype->c[hc->nc].type;
+ hc->nc++;
+ }
+}
+
+static void cleanup_coords(HatCoordContext *ctx)
+{
+ hc_free(ctx->prototype);
+}
+
+#ifdef DEBUG_COORDS
+static inline void debug_coords(const char *prefix, HatCoords *hc,
+ const char *suffix)
+{
+ const char *sep = "";
+ static const char *const types[] = {"H","T","P","F","kite","hat"};
+
+ fputs(prefix, stderr);
+ for (size_t i = 0; i < hc->nc; i++) {
+ fprintf(stderr, "%s %s ", sep, types[hc->c[i].type]);
+ sep = " .";
+ if (hc->c[i].index == -1)
+ fputs("?", stderr);
+ else
+ fprintf(stderr, "%d", hc->c[i].index);
+ }
+ fputs(suffix, stderr);
+}
+#else
+#define debug_coords(p,c,s) ((void)0)
+#endif
+
+/*
+ * The actual system for finding the coordinates of an adjacent kite.
+ */
+
+/*
+ * Kitemap step: ensure we have enough coordinates to know two levels
+ * of meta-tiling, and use the kite map for the outer layer to move
+ * around the individual kites. If this fails, return NULL.
+ */
+static HatCoords *try_step_coords_kitemap(
+ HatCoordContext *ctx, HatCoords *hc_in, KiteStep step)
+{
+ ensure_coords(ctx, hc_in, 4);
+ debug_coords(" try kitemap ", hc_in, "\n");
+ unsigned kite = hc_in->c[0].index;
+ unsigned hat = hc_in->c[1].index;
+ unsigned meta = hc_in->c[2].index;
+ TileType meta2type = hc_in->c[3].type;
+ const KitemapEntry *ke = &kitemap[meta2type][
+ kitemap_index(step, kite, hat, meta)];
+ if (ke->kite >= 0) {
+ /*
+ * Success! We've got coordinates for the next kite in this
+ * direction.
+ */
+ HatCoords *hc_out = hc_copy(hc_in);
+
+ hc_out->c[2].index = ke->meta;
+ hc_out->c[2].type = children[meta2type][ke->meta];
+ hc_out->c[1].index = ke->hat;
+ hc_out->c[1].type = TT_HAT;
+ hc_out->c[0].index = ke->kite;
+ hc_out->c[0].type = TT_KITE;
+
+ debug_coords(" success! ", hc_out, "\n");
+ return hc_out;
+ }
+
+ return NULL;
+}
+
+/*
+ * Recursive metamap step. Try using the metamap to rewrite the
+ * coordinates at hc->c[depth] and hc->c[depth+1] (using the metamap
+ * for the tile type described in hc->c[depth+2]). If successful,
+ * recurse back down to see if this led to a successful step via the
+ * kitemap. If even that fails (so that we need to try a higher-order
+ * metamap rewrite), return NULL.
+ */
+static HatCoords *try_step_coords_metamap(
+ HatCoordContext *ctx, HatCoords *hc_in, KiteStep step, size_t depth)
+{
+ HatCoords *hc_tmp = NULL, *hc_out;
+
+ ensure_coords(ctx, hc_in, depth+3);
+#ifdef DEBUG_COORDS
+ fprintf(stderr, " try meta %-4d", (int)depth);
+ debug_coords("", hc_in, "\n");
+#endif
+ unsigned meta_orig = hc_in->c[depth].index;
+ unsigned meta2_orig = hc_in->c[depth+1].index;
+ TileType meta3type = hc_in->c[depth+2].type;
+
+ unsigned meta = meta_orig, meta2 = meta2_orig;
+
+ while (true) {
+ const MetamapEntry *me;
+ HatCoords *hc_curr = hc_tmp ? hc_tmp : hc_in;
+
+ if (depth > 2)
+ hc_out = try_step_coords_metamap(ctx, hc_curr, step, depth - 1);
+ else
+ hc_out = try_step_coords_kitemap(ctx, hc_curr, step);
+ if (hc_out) {
+ hc_free(hc_tmp);
+ return hc_out;
+ }
+
+ me = &metamap[meta3type][metamap_index(meta, meta2)];
+ assert(me->meta != -1);
+ if (me->meta == meta_orig && me->meta2 == meta2_orig) {
+ hc_free(hc_tmp);
+ return NULL;
+ }
+
+ meta = me->meta;
+ meta2 = me->meta2;
+
+ /*
+ * We must do the rewrite in a copy of hc_in. It's not
+ * _necessarily_ obvious that that's the case (any successful
+ * rewrite leaves the coordinates still valid and still
+ * referring to the same kite, right?). But the problem is
+ * that we might do a rewrite at this level more than once,
+ * and in between, a metamap rewrite at the next level down
+ * might have modified _one_ of the two coordinates we're
+ * messing about with. So it's easiest to let the recursion
+ * just use a separate copy.
+ */
+ if (!hc_tmp)
+ hc_tmp = hc_copy(hc_in);
+
+ hc_tmp->c[depth+1].index = meta2;
+ hc_tmp->c[depth+1].type = children[meta3type][meta2];
+ hc_tmp->c[depth].index = meta;
+ hc_tmp->c[depth].type = children[hc_tmp->c[depth+1].type][meta];
+
+ debug_coords(" rewritten -> ", hc_tmp, "\n");
+ }
+}
+
+/*
+ * The top-level algorithm for finding the next tile.
+ */
+static HatCoords *step_coords(HatCoordContext *ctx, HatCoords *hc_in,
+ KiteStep step)
+{
+ HatCoords *hc_out;
+ size_t depth;
+
+#ifdef DEBUG_COORDS
+ static const char *const directions[] = {
+ " left\n", " right\n", " forward left\n", " forward right\n" };
+ debug_coords("step start ", hc_in, directions[step]);
+#endif
+
+ /*
+ * First, just try a kitemap step immediately. If that succeeds,
+ * we're done.
+ */
+ if ((hc_out = try_step_coords_kitemap(ctx, hc_in, step)) != NULL)
+ return hc_out;
+
+ /*
+ * Otherwise, try metamap rewrites at successively higher layers
+ * until one works. Each one will recurse back down to the
+ * kitemap, as described above.
+ */
+ for (depth = 2;; depth++) {
+ if ((hc_out = try_step_coords_metamap(
+ ctx, hc_in, step, depth)) != NULL)
+ return hc_out;
+ }
+}
+
+/*
+ * Generate a random set of parameters for a tiling of a given size.
+ * To do this, we iterate over the whole tiling via first_kite and
+ * next_kite, and for each kite, calculate its coordinates. But then
+ * we throw the coordinates away and don't do anything with them!
+ *
+ * But the side effect of _calculating_ all those coordinates is that
+ * we found out how far ctx->prototype needed to be extended, and did
+ * so, pulling random choices out of our random_state. So after this
+ * iteration, ctx->prototype contains everything we need to replicate
+ * the same piece of tiling next time.
+ */
+void hat_tiling_randomise(struct HatPatchParams *hp, int w, int h,
+ random_state *rs)
+{
+ HatCoordContext ctx[1];
+ HatCoords *coords[KE_NKEEP];
+ KiteEnum s[1];
+ size_t i;
+
+ init_coords_random(ctx, rs);
+ for (i = 0; i < lenof(coords); i++)
+ coords[i] = NULL;
+
+ first_kite(s, w, h);
+ coords[s->curr_index] = initial_coords(ctx);
+
+ while (next_kite(s)) {
+ hc_free(coords[s->curr_index]);
+ coords[s->curr_index] = step_coords(
+ ctx, coords[s->last_index], s->last_step);
+ }
+
+ hp->ncoords = ctx->prototype->nc - 1;
+ hp->coords = snewn(hp->ncoords, unsigned char);
+ for (i = 0; i < hp->ncoords; i++)
+ hp->coords[i] = ctx->prototype->c[i].index;
+ hp->final_metatile = tilechars[ctx->prototype->c[hp->ncoords].type];
+
+ cleanup_coords(ctx);
+ for (i = 0; i < lenof(coords); i++)
+ hc_free(coords[i]);
+}
+
+const char *hat_tiling_params_invalid(const struct HatPatchParams *hp)
+{
+ TileType metatile;
+ size_t i;
+
+ if (hp->ncoords < 3)
+ return "Grid parameters require at least three coordinates";
+ if (metatile_char_to_enum(hp->final_metatile) < 0)
+ return "Grid parameters contain an invalid final metatile";
+ if (hp->coords[0] >= 8)
+ return "Grid parameters contain an invalid kite index";
+
+ metatile = metatile_char_to_enum(hp->final_metatile);
+ for (i = hp->ncoords - 1; i > 1; i--) {
+ if (hp->coords[i] >= nchildren[metatile])
+ return "Grid parameters contain an invalid metatile index";
+ metatile = children[metatile][hp->coords[i]];
+ }
+
+ if (hp->coords[1] >= hats_in_metatile[metatile])
+ return "Grid parameters contain an invalid hat index";
+
+ return NULL;
+}
+
+/*
+ * For each kite generated by hat_tiling_generate, potentially
+ * generate an output hat and give it to our caller.
+ *
+ * We do this by starting from kite #0 of each hat, and tracing round
+ * the boundary. If the whole boundary is within the caller's bounding
+ * region, we return it; if it goes off the edge, we don't.
+ *
+ * (Of course, every hat we _do_ want to return will have all its
+ * kites inside the rectangle, so its kite #0 will certainly be caught
+ * by this iteration.)
+ */
+static void maybe_report_hat(int w, int h, Kite kite, HatCoords *hc,
+ hat_tile_callback_fn cb, void *cbctx)
+{
+ Point vertices[14];
+ size_t i, j;
+ bool reversed = false;
+ int coords[28];
+
+ /* Only iterate from kite #0 of a hat */
+ if (hc->c[0].index != 0)
+ return;
+
+ /*
+ * Identify reflected hats: they are always hat #3 of an H
+ * metatile. If we find one, reflect the starting kite so that the
+ * kite_step operations below will go in the other direction.
+ */
+ if (hc->c[2].type == TT_H && hc->c[1].index == 3) {
+ reversed = true;
+ Point tmp = kite.left;
+ kite.left = kite.right;
+ kite.right = tmp;
+ }
+
+ vertices[0] = kite.centre;
+ vertices[1] = kite.right;
+ vertices[2] = kite.outer;
+ vertices[3] = kite.left;
+ kite = kite_left(kite); /* now on kite #1 */
+ kite = kite_forward_right(kite); /* now on kite #2 */
+ vertices[4] = kite.centre;
+ kite = kite_right(kite); /* now on kite #3 */
+ vertices[5] = kite.right;
+ vertices[6] = kite.outer;
+ kite = kite_forward_left(kite); /* now on kite #4 */
+ vertices[7] = kite.left;
+ vertices[8] = kite.centre;
+ kite = kite_right(kite); /* now on kite #5 */
+ kite = kite_right(kite); /* now on kite #6 */
+ kite = kite_right(kite); /* now on kite #7 */
+ vertices[9] = kite.right;
+ vertices[10] = kite.outer;
+ vertices[11] = kite.left;
+ kite = kite_left(kite); /* now on kite #6 again */
+ vertices[12] = kite.outer;
+ vertices[13] = kite.left;
+
+ if (reversed) {
+ /* For a reversed kite, also reverse the vertex order, so that
+ * we report every polygon in a consistent orientation */
+ for (i = 0, j = 13; i < j; i++, j--) {
+ Point tmp = vertices[i];
+ vertices[i] = vertices[j];
+ vertices[j] = tmp;
+ }
+ }
+
+ /*
+ * Convert from our internal coordinate system into the orthogonal
+ * one used in this module's external API. In the same loop, we
+ * might as well do the bounds check.
+ */
+ for (i = 0; i < 14; i++) {
+ Point v = vertices[i];
+ int x = (v.x * 2 + v.y) / 3, y = v.y;
+
+ if (x < 0 || x > 4*w || y < 0 || y > 6*h)
+ return; /* a vertex of this kite is out of bounds */
+
+ coords[2*i] = x;
+ coords[2*i+1] = y;
+ }
+
+ cb(cbctx, 14, coords);
+}
+
+/*
+ * Generate a hat tiling from a previously generated set of parameters.
+ */
+void hat_tiling_generate(const struct HatPatchParams *hp, int w, int h,
+ hat_tile_callback_fn cb, void *cbctx)
+{
+ HatCoordContext ctx[1];
+ HatCoords *coords[KE_NKEEP];
+ KiteEnum s[1];
+ size_t i;
+
+ init_coords_params(ctx, hp);
+ for (i = 0; i < lenof(coords); i++)
+ coords[i] = NULL;
+
+ first_kite(s, w, h);
+ coords[s->curr_index] = initial_coords(ctx);
+ maybe_report_hat(w, h, *s->curr, coords[s->curr_index], cb, cbctx);
+
+ while (next_kite(s)) {
+ hc_free(coords[s->curr_index]);
+ coords[s->curr_index] = step_coords(
+ ctx, coords[s->last_index], s->last_step);
+ maybe_report_hat(w, h, *s->curr, coords[s->curr_index], cb, cbctx);
+ }
+
+ cleanup_coords(ctx);
+ for (i = 0; i < lenof(coords); i++)
+ hc_free(coords[i]);
+}
+
+#ifdef TEST_HAT
+
+#include
+
+static HatCoords *hc_construct_v(TileType type, va_list ap)
+{
+ HatCoords *hc = hc_new();
+ while (true) {
+ int index = va_arg(ap, int);
+
+ hc_make_space(hc, hc->nc + 1);
+ hc->c[hc->nc].type = type;
+ hc->c[hc->nc].index = index;
+ hc->nc++;
+
+ if (index < 0)
+ return hc;
+
+ type = va_arg(ap, TileType);
+ }
+}
+
+static HatCoords *hc_construct(TileType type, ...)
+{
+ HatCoords *hc;
+ va_list ap;
+
+ va_start(ap, type);
+ hc = hc_construct_v(type, ap);
+ va_end(ap);
+
+ return hc;
+}
+
+static bool hc_equal(HatCoords *hc1, HatCoords *hc2)
+{
+ size_t i;
+
+ if (hc1->nc != hc2->nc)
+ return false;
+
+ for (i = 0; i < hc1->nc; i++) {
+ if (hc1->c[i].type != hc2->c[i].type ||
+ hc1->c[i].index != hc2->c[i].index)
+ return false;
+ }
+
+ return true;
+}
+
+static bool hc_expect(const char *file, int line, HatCoords *hc,
+ TileType type, ...)
+{
+ bool equal;
+ va_list ap;
+ HatCoords *hce;
+
+ va_start(ap, type);
+ hce = hc_construct_v(type, ap);
+ va_end(ap);
+
+ equal = hc_equal(hc, hce);
+
+ if (!equal) {
+ fprintf(stderr, "%s:%d: coordinate mismatch\n", file, line);
+ debug_coords(" expected: ", hce, "\n");
+ debug_coords(" actual: ", hc, "\n");
+ }
+
+ hc_free(hce);
+ return equal;
+}
+
+#define EXPECT(hc, ...) do { \
+ if (!hc_expect(__FILE__, __LINE__, hc, __VA_ARGS__)) \
+ fails++; \
+ } while (0)
+
+static bool unit_tests(void)
+{
+ int fails = 0;
+ HatCoordContext ctx[1];
+ HatCoords *hc_in, *hc_out;
+
+ ctx->rs = NULL;
+ ctx->prototype = hc_construct(TT_KITE, 0, TT_HAT, 0, TT_H, -1);
+
+ /* Simple steps within a hat */
+
+ hc_in = hc_construct(TT_KITE, 6, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_out = step_coords(ctx, hc_in, KS_LEFT);
+ EXPECT(hc_out, TT_KITE, 5, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_free(hc_in);
+ hc_free(hc_out);
+
+ hc_in = hc_construct(TT_KITE, 6, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_out = step_coords(ctx, hc_in, KS_RIGHT);
+ EXPECT(hc_out, TT_KITE, 7, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_free(hc_in);
+ hc_free(hc_out);
+
+ hc_in = hc_construct(TT_KITE, 5, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_out = step_coords(ctx, hc_in, KS_F_LEFT);
+ EXPECT(hc_out, TT_KITE, 2, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_free(hc_in);
+ hc_free(hc_out);
+
+ hc_in = hc_construct(TT_KITE, 5, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_out = step_coords(ctx, hc_in, KS_F_RIGHT);
+ EXPECT(hc_out, TT_KITE, 1, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_free(hc_in);
+ hc_free(hc_out);
+
+ /* Step between hats in the same kitemap, which can change the
+ * metatile type at layer 2 */
+
+ hc_in = hc_construct(TT_KITE, 6, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_out = step_coords(ctx, hc_in, KS_F_LEFT);
+ EXPECT(hc_out, TT_KITE, 3, TT_HAT, 0, TT_H, 0, TT_H, -1);
+ hc_free(hc_in);
+ hc_free(hc_out);
+
+ hc_in = hc_construct(TT_KITE, 7, TT_HAT, 2, TT_H, 1, TT_H, -1);
+ hc_out = step_coords(ctx, hc_in, KS_F_RIGHT);
+ EXPECT(hc_out, TT_KITE, 4, TT_HAT, 0, TT_T, 3, TT_H, -1);
+ hc_free(hc_in);
+ hc_free(hc_out);
+
+ /* Step off the edge of one kitemap, necessitating a metamap
+ * rewrite of layers 2,3 to get into a different kitemap where
+ * that step can be made */
+
+ hc_in = hc_construct(TT_KITE, 6, TT_HAT, 0, TT_P, 2, TT_P, 3, TT_P, -1);
+ hc_out = step_coords(ctx, hc_in, KS_F_RIGHT);
+ /* Working:
+ * kite 6 . hat 0 . P 2 . P 3 . P ?
+ * -> kite 6 . hat 0 . P 6 . H 0 . P ? (P metamap says 2.3 = 6.0)
+ */
+ EXPECT(hc_out, TT_KITE, 7, TT_HAT, 1, TT_H, 1, TT_H, 0, TT_P, -1);
+ hc_free(hc_in);
+ hc_free(hc_out);
+
+ cleanup_coords(ctx);
+ return fails == 0;
+}
+
+typedef struct pspoint {
+ float x, y;
+} pspoint;
+
+static inline pspoint pscoords(Point p)
+{
+ pspoint q = { p.x + p.y / 2.0F, p.y * sqrt(0.75) };
+ return q;
+}
+
+typedef struct psbbox {
+ bool started;
+ pspoint bl, tr;
+} psbbox;
+
+static inline void psbbox_add(psbbox *bbox, pspoint p)
+{
+ if (!bbox->started || bbox->bl.x > p.x)
+ bbox->bl.x = p.x;
+ if (!bbox->started || bbox->tr.x < p.x)
+ bbox->tr.x = p.x;
+ if (!bbox->started || bbox->bl.y > p.y)
+ bbox->bl.y = p.y;
+ if (!bbox->started || bbox->tr.y < p.y)
+ bbox->tr.y = p.y;
+ bbox->started = true;
+}
+
+static void header(psbbox *bbox)
+{
+ float xext = bbox->tr.x - bbox->bl.x, yext = bbox->tr.y - bbox->bl.y;
+ float ext = (xext > yext ? xext : yext);
+ float scale = 500 / ext;
+ float ox = 287 - scale * (bbox->bl.x + bbox->tr.x) / 2;
+ float oy = 421 - scale * (bbox->bl.y + bbox->tr.y) / 2;
+
+ printf("%%!PS-Adobe-2.0\n%%%%Creator: hat-test from Simon Tatham's "
+ "Portable Puzzle Collection\n%%%%Pages: 1\n"
+ "%%%%BoundingBox: %f %f %f %f\n"
+ "%%%%EndComments\n%%%%Page: 1 1\n",
+ ox + scale * bbox->bl.x - 20, oy + scale * bbox->bl.y - 20,
+ ox + scale * bbox->tr.x + 20, oy + scale * bbox->tr.y + 20);
+
+ printf("%f %f translate %f dup scale\n", ox, oy, scale);
+ printf("%f setlinewidth\n", 0.1);
+ printf("/thick { %f setlinewidth } def\n", 0.7);
+ printf("0 setgray 1 setlinejoin 1 setlinecap\n");
+}
+
+static void bbox_add_kite(Kite k, psbbox *bbox)
+{
+ pspoint p[4];
+ size_t i;
+
+ p[0] = pscoords(k.centre);
+ p[1] = pscoords(k.left);
+ p[2] = pscoords(k.outer);
+ p[3] = pscoords(k.right);
+
+ for (i = 0; i < 4; i++)
+ psbbox_add(bbox, p[i]);
+}
+
+static void fill_kite(Kite k, HatCoords *hc)
+{
+ pspoint p[4];
+ size_t i;
+
+ p[0] = pscoords(k.centre);
+ p[1] = pscoords(k.left);
+ p[2] = pscoords(k.outer);
+ p[3] = pscoords(k.right);
+
+ printf("newpath");
+ for (i = 0; i < 4; i++)
+ printf(" %f %f %s", p[i].x, p[i].y, i ? "lineto" : "moveto");
+ printf(" closepath gsave");
+ if (hc) {
+ const char *colour = "0 setgray";
+ if (hc->c[2].type == TT_H) {
+ colour = (hc->c[1].index == 3 ? "0 0.5 0.8 setrgbcolor" :
+ "0.6 0.8 1 setrgbcolor");
+ } else if (hc->c[2].type == TT_F) {
+ colour = "0.7 setgray";
+ } else {
+ colour = "1 setgray";
+ }
+ printf(" %s fill grestore\n", colour);
+ }
+}
+
+static void stroke_kite(Kite k, HatCoords *hc)
+{
+ pspoint p[4];
+ size_t i;
+
+ p[0] = pscoords(k.centre);
+ p[1] = pscoords(k.left);
+ p[2] = pscoords(k.outer);
+ p[3] = pscoords(k.right);
+
+ printf("newpath");
+ for (i = 0; i < 4; i++)
+ printf(" %f %f %s", p[i].x, p[i].y, i ? "lineto" : "moveto");
+ printf(" closepath");
+ printf(" stroke\n");
+
+ if (hc->c[2].type == TT_H && hc->c[1].index == 3) {
+ pspoint t = p[1]; p[1] = p[3]; p[3] = t;
+ }
+ #define LINE(a,b) printf("gsave newpath %f %f moveto %f %f lineto thick " \
+ "stroke grestore\n", p[a].x, p[a].y, p[b].x, p[b].y)
+ switch (hc->c[0].index) {
+ case 0: LINE(1, 2); LINE(2, 3); LINE(3, 0); break;
+ case 1: LINE(0, 1); break;
+ case 2: LINE(0, 1); break;
+ case 3: LINE(2, 3); LINE(3, 0); break;
+ case 4: LINE(0, 1); LINE(1, 2); break;
+ case 6: LINE(1, 2); LINE(2, 3); break;
+ case 7: LINE(1, 2); LINE(2, 3); LINE(3, 0); break;
+ }
+ #undef LINE
+}
+
+static void trailer(void)
+{
+ printf("showpage\n");
+ printf("%%%%Trailer\n");
+ printf("%%%%EOF\n");
+}
+
+int main(int argc, char **argv)
+{
+ psbbox bbox[1];
+ KiteEnum s[1];
+ HatCoordContext ctx[1];
+ HatCoords *coords[KE_NKEEP];
+ random_state *rs = random_new("12345", 5);
+ int w = 10, h = 10;
+ size_t i;
+
+ if (argc > 1 && !strcmp(argv[1], "--test")) {
+ return unit_tests() ? 0 : 1;
+ }
+
+ for (i = 0; i < lenof(coords); i++)
+ coords[i] = NULL;
+
+ init_coords_random(ctx, rs);
+
+ bbox->started = false;
+
+ first_kite(s, w, h);
+ coords[s->curr_index] = initial_coords(ctx);
+ bbox_add_kite(*s->curr, bbox);
+ while (next_kite(s)) {
+ hc_free(coords[s->curr_index]);
+ coords[s->curr_index] = step_coords(
+ ctx, coords[s->last_index], s->last_step);
+ bbox_add_kite(*s->curr, bbox);
+ }
+ for (i = 0; i < lenof(coords); i++) {
+ hc_free(coords[i]);
+ coords[i] = NULL;
+ }
+
+ header(bbox);
+
+ first_kite(s, w, h);
+ coords[s->curr_index] = initial_coords(ctx);
+ fill_kite(*s->curr, coords[s->curr_index]);
+ while (next_kite(s)) {
+ hc_free(coords[s->curr_index]);
+ coords[s->curr_index] = step_coords(
+ ctx, coords[s->last_index], s->last_step);
+ fill_kite(*s->curr, coords[s->curr_index]);
+ }
+ for (i = 0; i < lenof(coords); i++) {
+ hc_free(coords[i]);
+ coords[i] = NULL;
+ }
+
+ first_kite(s, w, h);
+ coords[s->curr_index] = initial_coords(ctx);
+ stroke_kite(*s->curr, coords[s->curr_index]);
+ while (next_kite(s)) {
+ hc_free(coords[s->curr_index]);
+ coords[s->curr_index] = step_coords(
+ ctx, coords[s->last_index], s->last_step);
+ stroke_kite(*s->curr, coords[s->curr_index]);
+ }
+ for (i = 0; i < lenof(coords); i++) {
+ hc_free(coords[i]);
+ coords[i] = NULL;
+ }
+
+ trailer();
+
+ cleanup_coords(ctx);
+
+ return 0;
+}
+#endif
diff --git a/hat.h b/hat.h
new file mode 100644
index 0000000..39e2d31
--- /dev/null
+++ b/hat.h
@@ -0,0 +1,67 @@
+#ifndef PUZZLES_HAT_H
+#define PUZZLES_HAT_H
+
+struct HatPatchParams {
+ /*
+ * A patch of hat tiling is identified by giving the coordinates
+ * of the kite in one corner, using a multi-level coordinate
+ * system based on metatile expansions. Coordinates are a sequence
+ * of small non-negative integers. The valid range for each
+ * coordinate depends on the next coordinate, or on final_metatile
+ * if it's the last one in the list. The largest valid range is
+ * {0,...,12}.
+ *
+ * 'final_metatile' is one of the characters 'H', 'T', 'P' or 'F'.
+ */
+ size_t ncoords;
+ unsigned char *coords;
+ char final_metatile;
+};
+
+/*
+ * Fill in HatPatchParams with a randomly selected set of coordinates,
+ * in enough detail to generate a patch of tiling covering an area of
+ * w x h 'squares' of a kite tiling.
+ *
+ * The kites grid is considered to be oriented so that it includes
+ * horizontal lines and not vertical ones. So each of the smallest
+ * equilateral triangles in the grid has a bounding rectangle whose
+ * height is sqrt(3)/2 times its width, and either the top or the
+ * bottom of that bounding rectangle is the horizontal edge of the
+ * triangle. A 'square' of a kite tiling (for convenience of choosing
+ * grid dimensions) counts as one of those bounding rectangles.
+ *
+ * The 'coords' field of the structure will be filled in with a new
+ * dynamically allocated array. Any previous pointer in that field
+ * will be overwritten.
+ */
+void hat_tiling_randomise(struct HatPatchParams *params, int w, int h,
+ random_state *rs);
+
+/*
+ * Validate a HatPatchParams to ensure it contains no illegal
+ * coordinates. Returns NULL if it's acceptable, or an error string if
+ * not.
+ */
+const char *hat_tiling_params_invalid(const struct HatPatchParams *params);
+
+/*
+ * Generate the actual set of hat tiles from a HatPatchParams, passing
+ * each one to a callback. The callback receives the vertices of each
+ * point, as a sequence of 2*nvertices integers, with x,y coordinates
+ * interleaved.
+ *
+ * The x coordinates are measured in units of 1/4 of the side length
+ * of the smallest equilateral triangle, or equivalently, 1/2 the
+ * length of one of the long edges of a single kite. The y coordinates
+ * are measured in units of 1/6 the height of the triangle, which is
+ * also 1/2 the length of the short edge of a kite. Therefore, you can
+ * expect x to go up to 4*w and y up to 6*h.
+ */
+typedef void (*hat_tile_callback_fn)(void *ctx, size_t nvertices,
+ int *coords);
+
+void hat_tiling_generate(const struct HatPatchParams *params, int w, int h,
+ hat_tile_callback_fn cb, void *cbctx);
+
+#endif
diff --git a/loopy.c b/loopy.c
index c627f2b..86f6d5e 100644
--- a/loopy.c
+++ b/loopy.c
@@ -280,6 +280,7 @@ static void check_caches(const solver_state* sstate);
A("Great-Great-Dodecagonal",GREATGREATDODECAGONAL,2,2) \
A("Kagome",KAGOME,3,3) \
A("Compass-Dodecagonal",COMPASSDODECAGONAL,2,2) \
+ A("Hats",HATS,6,6) \
/* end of list */
#define GRID_NAME(title,type,amin,omin) title,
@@ -564,6 +565,7 @@ static const game_params loopy_presets_more[] = {
{ 5, 4, DIFF_HARD, LOOPY_GRID_GREATDODECAGONAL },
{ 5, 3, DIFF_HARD, LOOPY_GRID_GREATGREATDODECAGONAL },
{ 5, 4, DIFF_HARD, LOOPY_GRID_COMPASSDODECAGONAL },
+ { 10, 10, DIFF_HARD, LOOPY_GRID_HATS },
#endif
};
@@ -2299,7 +2301,7 @@ static int dline_deductions(solver_state *sstate)
* on that. We check this with an assertion, in case someone decides to
* make a grid which has larger faces than this. Note, this algorithm
* could get quite expensive if there are many large faces. */
-#define MAX_FACE_SIZE 12
+#define MAX_FACE_SIZE 14
for (i = 0; i < g->num_faces; i++) {
int maxs[MAX_FACE_SIZE][MAX_FACE_SIZE];