aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENCE3
-rw-r--r--grid.c96
-rw-r--r--grid.h1
-rw-r--r--loopy.c3
4 files changed, 102 insertions, 1 deletions
diff --git a/LICENCE b/LICENCE
index 4235005..dbcf1ac 100644
--- a/LICENCE
+++ b/LICENCE
@@ -2,7 +2,8 @@ This software is copyright (c) 2004-2014 Simon Tatham.
Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas
Kölker, Dariusz Olszewski, Michael Schierl, Lambros Lambrou, Bernd
-Schmidt, Steffen Bauer, Lennard Sprong and Rogier Goossens.
+Schmidt, Steffen Bauer, Lennard Sprong, Rogier Goossens and Michael
+Quevillon.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
diff --git a/grid.c b/grid.c
index 52648e5..b5e6bb0 100644
--- a/grid.c
+++ b/grid.c
@@ -2060,6 +2060,102 @@ static grid *grid_new_greathexagonal(int width, int height, const char *desc)
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
diff --git a/grid.h b/grid.h
index 19079a4..26d0b16 100644
--- a/grid.h
+++ b/grid.h
@@ -100,6 +100,7 @@ typedef struct grid {
A(SNUBSQUARE,snubsquare) \
A(CAIRO,cairo) \
A(GREATHEXAGONAL,greathexagonal) \
+ A(KAGOME,kagome) \
A(OCTAGONAL,octagonal) \
A(KITE,kites) \
A(FLORET,floret) \
diff --git a/loopy.c b/loopy.c
index 5f1940e..c14412d 100644
--- a/loopy.c
+++ b/loopy.c
@@ -278,6 +278,7 @@ static void check_caches(const solver_state* sstate);
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,
@@ -544,6 +545,7 @@ static const game_params loopy_presets_more[] = {
#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 },
@@ -552,6 +554,7 @@ static const game_params loopy_presets_more[] = {
#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 },