return g;
}
+#define KAGOME_TILESIZE 18
+/* Vector for side of triangle - ratio is close to sqrt(3) */
+#define KAGOME_A 15
+#define KAGOME_B 26
+
+static void grid_size_kagome(int width, int height,
+ int *tilesize, int *xextent, int *yextent)
+{
+ int a = KAGOME_A;
+ int b = KAGOME_B;
+
+ *tilesize = KAGOME_TILESIZE;
+ *xextent = (4*a) * (width-1) + 6*a;
+ *yextent = (2*b) * (height-1) + 2*b;
+}
+
+static grid *grid_new_kagome(int width, int height, const char *desc)
+{
+ int x, y;
+ int a = KAGOME_A;
+ int b = KAGOME_B;
+
+ /* Upper bounds - don't have to be exact */
+ int max_faces = 6 * (width + 1) * (height + 1);
+ int max_dots = 6 * width * height;
+
+ tree234 *points;
+
+ grid *g = grid_empty();
+ g->tilesize = KAGOME_TILESIZE;
+ g->faces = snewn(max_faces, grid_face);
+ g->dots = snewn(max_dots, grid_dot);
+
+ points = newtree234(grid_point_cmp_fn);
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ grid_dot *d;
+ /* centre of hexagon */
+ int px = (4*a) * x;
+ int py = (2*b) * y;
+ if (y % 2)
+ px += 2*a;
+
+ /* hexagon */
+ grid_face_add_new(g, 6);
+ d = grid_get_dot(g, points, px + a, py - b); grid_face_set_dot(g, d, 0);
+ d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 1);
+ d = grid_get_dot(g, points, px + a, py + b); grid_face_set_dot(g, d, 2);
+ d = grid_get_dot(g, points, px - a, py + b); grid_face_set_dot(g, d, 3);
+ d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 4);
+ d = grid_get_dot(g, points, px - a, py - b); grid_face_set_dot(g, d, 5);
+
+ /* Triangle above right */
+ if ((x < width - 1) || (!(y % 2) && y)) {
+ grid_face_add_new(g, 3);
+ d = grid_get_dot(g, points, px + 3*a, py - b); grid_face_set_dot(g, d, 0);
+ d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 1);
+ d = grid_get_dot(g, points, px + a, py - b); grid_face_set_dot(g, d, 2);
+ }
+
+ /* Triangle below right */
+ if ((x < width - 1) || (!(y % 2) && (y < height - 1))) {
+ grid_face_add_new(g, 3);
+ d = grid_get_dot(g, points, px + 3*a, py + b); grid_face_set_dot(g, d, 0);
+ d = grid_get_dot(g, points, px + a, py + b); grid_face_set_dot(g, d, 1);
+ d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 2);
+ }
+
+ /* Left triangles */
+ if (!x && (y % 2)) {
+ /* Triangle above left */
+ grid_face_add_new(g, 3);
+ d = grid_get_dot(g, points, px - a, py - b); grid_face_set_dot(g, d, 0);
+ d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 1);
+ d = grid_get_dot(g, points, px - 3*a, py - b); grid_face_set_dot(g, d, 2);
+
+ /* Triangle below left */
+ if (y < height - 1) {
+ grid_face_add_new(g, 3);
+ d = grid_get_dot(g, points, px - a, py + b); grid_face_set_dot(g, d, 0);
+ d = grid_get_dot(g, points, px - 3*a, py + b); grid_face_set_dot(g, d, 1);
+ d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 2);
+ }
+ }
+ }
+ }
+
+ freetree234(points);
+ assert(g->num_faces <= max_faces);
+ assert(g->num_dots <= max_dots);
+
+ grid_make_consistent(g);
+ return g;
+}
+
#define OCTAGONAL_TILESIZE 40
/* b/a approx sqrt(2) */
#define OCTAGONAL_A 29
A("Penrose (kite/dart)",PENROSE_P2,3,3) \
A("Penrose (rhombs)",PENROSE_P3,3,3) \
A("Great-Great-Dodecagonal",GREATGREATDODECAGONAL,2,2) \
+ A("Kagome",KAGOME,3,3) \
/* end of list */
#define GRID_NAME(title,type,amin,omin) title,
#ifdef SMALL_SCREEN
{ 7, 7, DIFF_HARD, LOOPY_GRID_HONEYCOMB },
{ 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL },
+ { 5, 4, DIFF_HARD, LOOPY_GRID_KAGOME },
{ 5, 5, DIFF_HARD, LOOPY_GRID_OCTAGONAL },
{ 3, 3, DIFF_HARD, LOOPY_GRID_FLORET },
{ 3, 3, DIFF_HARD, LOOPY_GRID_DODECAGONAL },
#else
{ 10, 10, DIFF_HARD, LOOPY_GRID_HONEYCOMB },
{ 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL },
+ { 5, 4, DIFF_HARD, LOOPY_GRID_KAGOME },
{ 7, 7, DIFF_HARD, LOOPY_GRID_OCTAGONAL },
{ 5, 5, DIFF_HARD, LOOPY_GRID_FLORET },
{ 5, 4, DIFF_HARD, LOOPY_GRID_DODECAGONAL },