From ac5deb9c728c31e6adeedc57fa2ed1b2565b1818 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 2 Feb 2012 07:13:14 +0000 Subject: [PATCH] Added "dual" option to grid generators It is now possible to produce duals of all grids. git-svn-id: svn://svn.tartarus.org/sgt/puzzles@9396 cda61777-01e9-0310-a592-d414129be87e --- grid.c | 57 +++++++++++++++-------------------- grid.h | 7 ++--- loopy.c | 103 +++++++++++++++++++++++++++++++++++++--------------------------- pearl.c | 2 +- 4 files changed, 87 insertions(+), 82 deletions(-) diff --git a/grid.c b/grid.c index 14f2dc8..24380d9 100644 --- a/grid.c +++ b/grid.c @@ -518,7 +518,7 @@ static void grid_make_consistent(grid *g) * We use "-1", not "-2" here, because Euler's formula includes the * infinite face, which we don't count. */ g->num_edges = g->num_faces + g->num_dots - 1; - assert(g->num_edges > 2); + debug(("allocating room for %d edges\n", g->num_edges)); g->edges = snewn(g->num_edges, grid_edge); next_new_edge = g->edges; @@ -533,6 +533,7 @@ static void grid_make_consistent(grid *g) for (i = 0; i < g->num_faces; i++) { grid_face *f = g->faces + i; int j; + assert(f->order > 2); for (j = 0; j < f->order; j++) { grid_edge e; /* fake edge for searching */ grid_edge *edge_found; @@ -1380,7 +1381,7 @@ void grid_find_incentre(grid_face *f) static grid *grid_dual(grid *g) { grid *new_g; - int i, j; + int i, j, k; tree234* points; new_g = grid_empty(); @@ -1411,16 +1412,17 @@ static grid *grid_dual(grid *g) if (order>2) { grid_face_add_new(new_g, order); - for (j=0;jorder;j++) + for (j=0,k=0;jorder;j++) { grid_dot *new_d; if (d->faces[j]) { new_d = grid_get_dot(new_g, points, d->faces[j]->ix, d->faces[j]->iy); - grid_face_set_dot(new_g, new_d, j); + grid_face_set_dot(new_g, new_d, k++); } } + assert(k==order); } } @@ -2104,30 +2106,6 @@ static grid *grid_new_octagonal(int width, int height, char *desc) return g; } -#define DUAL_OCTAGONAL_TILESIZE OCTAGONAL_TILESIZE -/* b/a approx sqrt(2) */ -#define DUAL_OCTAGONAL_A OCTAGONAL_A -#define DUAL_OCTAGONAL_B OCTAGONAL_B - -static void grid_size_dual_octagonal(int width, int height, - int *tilesize, int *xextent, int *yextent) -{ - grid_size_octagonal(width, height, tilesize, xextent, yextent); -} - -static grid *grid_new_dual_octagonal(int width, int height, char *desc) -{ - grid *orig; - grid *g; - - orig = grid_new_octagonal(width, height, desc); - - g = grid_dual(orig); - grid_free(orig); - - return g; -} - #define KITE_TILESIZE 40 /* b/a approx sqrt(3) */ #define KITE_A 15 @@ -2793,7 +2771,7 @@ static grid *grid_new_penrose_p3_thick(int width, int height, char *desc) static grid *(*(grid_news[]))(int, int, char*) = { GRIDGEN_LIST(FNNEW) }; static void(*(grid_sizes[]))(int, int, int*, int*, int*) = { GRIDGEN_LIST(FNSZ) }; -char *grid_new_desc(grid_type type, int width, int height, random_state *rs) +char *grid_new_desc(grid_type type, int width, int height, int dual, random_state *rs) { if (type != GRID_PENROSE_P2 && type != GRID_PENROSE_P3) return NULL; @@ -2801,7 +2779,7 @@ char *grid_new_desc(grid_type type, int width, int height, random_state *rs) return grid_new_desc_penrose(type, width, height, rs); } -char *grid_validate_desc(grid_type type, int width, int height, char *desc) +char *grid_validate_desc(grid_type type, int width, int height, int dual, char *desc) { if (type != GRID_PENROSE_P2 && type != GRID_PENROSE_P3) { if (desc != NULL) @@ -2812,12 +2790,25 @@ char *grid_validate_desc(grid_type type, int width, int height, char *desc) return grid_validate_desc_penrose(type, width, height, desc); } -grid *grid_new(grid_type type, int width, int height, char *desc) +grid *grid_new(grid_type type, int width, int height, int dual, char *desc) { - char *err = grid_validate_desc(type, width, height, desc); + char *err = grid_validate_desc(type, width, height, dual, desc); if (err) assert(!"Invalid grid description."); - return grid_news[type](width, height, desc); + if (!dual) + { + return grid_news[type](width, height, desc); + } + else + { + grid *temp; + grid *g; + + temp = grid_news[type](width, height, desc); + g = grid_dual(temp); + grid_free(temp); + return g; + } } void grid_compute_size(grid_type type, int width, int height, diff --git a/grid.h b/grid.h index 00cd7c5..7cf4f59 100644 --- a/grid.h +++ b/grid.h @@ -101,7 +101,6 @@ typedef struct grid { A(CAIRO,cairo) \ A(GREATHEXAGONAL,greathexagonal) \ A(OCTAGONAL,octagonal) \ - A(DUAL_OCTAGONAL,dual_octagonal) \ A(KITE,kites) \ A(FLORET,floret) \ A(DODECAGONAL,dodecagonal) \ @@ -115,10 +114,10 @@ typedef enum grid_type { GRIDGEN_LIST(ENUM) GRID_TYPE_MAX } grid_type; /* Free directly after use if non-NULL. Will never contain an underscore * (so clients can safely use that as a separator). */ -char *grid_new_desc(grid_type type, int width, int height, random_state *rs); -char *grid_validate_desc(grid_type type, int width, int height, char *desc); +char *grid_new_desc(grid_type type, int width, int height, int dual, random_state *rs); +char *grid_validate_desc(grid_type type, int width, int height, int dual, char *desc); -grid *grid_new(grid_type type, int width, int height, char *desc); +grid *grid_new(grid_type type, int width, int height, int dual, char *desc); void grid_free(grid *g); diff --git a/loopy.c b/loopy.c index 328a717..091b378 100644 --- a/loopy.c +++ b/loopy.c @@ -208,6 +208,7 @@ struct game_params { int w, h; int diff; int type; + int dual; }; /* line_drawstate is the same as line_state, but with the extra ERROR @@ -257,7 +258,6 @@ static void check_caches(const solver_state* sstate); A(Great-Dodecagonal,GRID_GREATDODECAGONAL,2,2) \ A(Penrose (kite/dart),GRID_PENROSE_P2,3,3) \ A(Penrose (rhombs),GRID_PENROSE_P3,3,3) \ - A(Octagonal (dual),GRID_DUAL_OCTAGONAL,3,3) #define GRID_NAME(title,type,amin,omin) #title, #define GRID_CONFIG(title,type,amin,omin) ":" #title @@ -267,6 +267,7 @@ static void check_caches(const solver_state* sstate); "Width and height for this grid type must both be at least " #amin, \ "At least one of width and height for this grid type must be at least " #omin,}, static char const *const gridnames[] = { GRIDLIST(GRID_NAME) }; +static char const *const dualnames[] = { "", "(dual) " }; #define GRID_CONFIGS GRIDLIST(GRID_CONFIG) static grid_type grid_types[] = { GRIDLIST(GRID_TYPE) }; #define NUM_GRID_TYPES (sizeof(grid_types) / sizeof(grid_types[0])) @@ -280,7 +281,7 @@ static const struct { * generated. */ static grid *loopy_generate_grid(game_params *params, char *grid_desc) { - return grid_new(grid_types[params->type], params->w, params->h, grid_desc); + return grid_new(grid_types[params->type], params->w, params->h, params->dual, grid_desc); } /* ---------------------------------------------------------------------- @@ -476,6 +477,7 @@ static game_params *default_params(void) #endif ret->diff = DIFF_EASY; ret->type = 0; + ret->dual = 0; return ret; } @@ -490,40 +492,40 @@ static game_params *dup_params(game_params *params) static const game_params presets[] = { #ifdef SMALL_SCREEN - { 7, 7, DIFF_EASY, 0 }, - { 7, 7, DIFF_NORMAL, 0 }, - { 7, 7, DIFF_HARD, 0 }, - { 7, 7, DIFF_HARD, 1 }, - { 7, 7, DIFF_HARD, 2 }, - { 5, 5, DIFF_HARD, 3 }, - { 7, 7, DIFF_HARD, 4 }, - { 5, 4, DIFF_HARD, 5 }, - { 5, 5, DIFF_HARD, 6 }, - { 5, 5, DIFF_HARD, 7 }, - { 3, 3, DIFF_HARD, 8 }, - { 3, 3, DIFF_HARD, 9 }, - { 3, 3, DIFF_HARD, 10 }, - { 6, 6, DIFF_HARD, 11 }, - { 6, 6, DIFF_HARD, 12 }, + { 7, 7, DIFF_EASY, 0, 0 }, + { 7, 7, DIFF_NORMAL, 0, 0 }, + { 7, 7, DIFF_HARD, 0, 0 }, + { 7, 7, DIFF_HARD, 1, 0 }, + { 7, 7, DIFF_HARD, 2, 0 }, + { 5, 5, DIFF_HARD, 3, 0 }, + { 7, 7, DIFF_HARD, 4, 0 }, + { 5, 4, DIFF_HARD, 5, 0 }, + { 5, 5, DIFF_HARD, 6, 0 }, + { 5, 5, DIFF_HARD, 7, 0 }, + { 3, 3, DIFF_HARD, 8, 0 }, + { 3, 3, DIFF_HARD, 9, 0 }, + { 3, 3, DIFF_HARD, 10, 0 }, + { 6, 6, DIFF_HARD, 11, 0 }, + { 6, 6, DIFF_HARD, 12, 0 }, #else - { 7, 7, DIFF_EASY, 0 }, - { 10, 10, DIFF_EASY, 0 }, - { 7, 7, DIFF_NORMAL, 0 }, - { 10, 10, DIFF_NORMAL, 0 }, - { 7, 7, DIFF_HARD, 0 }, - { 10, 10, DIFF_HARD, 0 }, - { 10, 10, DIFF_HARD, 1 }, - { 12, 10, DIFF_HARD, 2 }, - { 7, 7, DIFF_HARD, 3 }, - { 9, 9, DIFF_HARD, 4 }, - { 5, 4, DIFF_HARD, 5 }, - { 7, 7, DIFF_HARD, 6 }, - { 5, 5, DIFF_HARD, 7 }, - { 5, 5, DIFF_HARD, 8 }, - { 5, 4, DIFF_HARD, 9 }, - { 5, 4, DIFF_HARD, 10 }, - { 10, 10, DIFF_HARD, 11 }, - { 10, 10, DIFF_HARD, 12 } + { 7, 7, DIFF_EASY, 0, 0 }, + { 10, 10, DIFF_EASY, 0, 0 }, + { 7, 7, DIFF_NORMAL, 0, 0 }, + { 10, 10, DIFF_NORMAL, 0, 0 }, + { 7, 7, DIFF_HARD, 0, 0 }, + { 10, 10, DIFF_HARD, 0, 0 }, + { 10, 10, DIFF_HARD, 1, 0 }, + { 12, 10, DIFF_HARD, 2, 0 }, + { 7, 7, DIFF_HARD, 3, 0 }, + { 9, 9, DIFF_HARD, 4, 0 }, + { 5, 4, DIFF_HARD, 5, 0 }, + { 7, 7, DIFF_HARD, 6, 0 }, + { 5, 5, DIFF_HARD, 7, 0 }, + { 5, 5, DIFF_HARD, 8, 0 }, + { 5, 4, DIFF_HARD, 9, 0 }, + { 5, 4, DIFF_HARD, 10, 0 }, + { 10, 10, DIFF_HARD, 11, 0 }, + { 10, 10, DIFF_HARD, 12, 0 } #endif }; @@ -538,8 +540,9 @@ static int game_fetch_preset(int i, char **name, game_params **params) tmppar = snew(game_params); *tmppar = presets[i]; *params = tmppar; - sprintf(buf, "%dx%d %s - %s", tmppar->h, tmppar->w, - gridnames[tmppar->type], diffnames[tmppar->diff]); + sprintf(buf, "%dx%d %s %s- %s", tmppar->h, tmppar->w, + gridnames[tmppar->type], dualnames[tmppar->dual], + diffnames[tmppar->diff]); *name = dupstr(buf); return TRUE; @@ -554,12 +557,17 @@ static void decode_params(game_params *params, char const *string) { params->h = params->w = atoi(string); params->diff = DIFF_EASY; + params->dual = 0; while (*string && isdigit((unsigned char)*string)) string++; if (*string == 'x') { string++; params->h = atoi(string); while (*string && isdigit((unsigned char)*string)) string++; } + if (*string == 'l') { + string++; + params->dual = 1; + } if (*string == 't') { string++; params->type = atoi(string); @@ -578,7 +586,8 @@ static void decode_params(game_params *params, char const *string) static char *encode_params(game_params *params, int full) { char str[80]; - sprintf(str, "%dx%dt%d", params->w, params->h, params->type); + sprintf(str, "%dx%dt%d%s", params->w, params->h, params->type, + params->dual ? "l" : ""); if (full) sprintf(str + strlen(str), "d%c", diffchars[params->diff]); return dupstr(str); @@ -589,7 +598,7 @@ static config_item *game_configure(game_params *params) config_item *ret; char buf[80]; - ret = snewn(5, config_item); + ret = snewn(6, config_item); ret[0].name = "Width"; ret[0].type = C_STRING; @@ -613,10 +622,15 @@ static config_item *game_configure(game_params *params) ret[3].sval = DIFFCONFIG; ret[3].ival = params->diff; - ret[4].name = NULL; - ret[4].type = C_END; + ret[4].name = "Dual"; + ret[4].type = C_BOOLEAN; ret[4].sval = NULL; - ret[4].ival = 0; + ret[4].ival = params->dual; + + ret[5].name = NULL; + ret[5].type = C_END; + ret[5].sval = NULL; + ret[5].ival = 0; return ret; } @@ -629,6 +643,7 @@ static game_params *custom_params(config_item *cfg) ret->h = atoi(cfg[1].sval); ret->type = cfg[2].ival; ret->diff = cfg[3].ival; + ret->dual = cfg[4].ival; return ret; } @@ -723,7 +738,7 @@ static char *validate_desc(game_params *params, char *desc) /* It's pretty inefficient to do this just for validation. All we need to * know is the precise number of faces. */ grid_desc = extract_grid_desc(&desc); - ret = grid_validate_desc(grid_types[params->type], params->w, params->h, grid_desc); + ret = grid_validate_desc(grid_types[params->type], params->w, params->h, params->dual, grid_desc); if (ret) return ret; g = loopy_generate_grid(params, grid_desc); @@ -1374,7 +1389,7 @@ static char *new_game_desc(game_params *params, random_state *rs, game_state *state = snew(game_state); game_state *state_new; - grid_desc = grid_new_desc(grid_types[params->type], params->w, params->h, rs); + grid_desc = grid_new_desc(grid_types[params->type], params->w, params->h, params->dual, rs); state->game_grid = g = loopy_generate_grid(params, grid_desc); state->clues = snewn(g->num_faces, signed char); diff --git a/pearl.c b/pearl.c index 248d64e..ef9fdc9 100644 --- a/pearl.c +++ b/pearl.c @@ -1048,7 +1048,7 @@ int pearl_loopgen_bias(void *vctx, char *board, int face) void pearl_loopgen(int w, int h, char *lines, random_state *rs) { - grid *g = grid_new(GRID_SQUARE, w-1, h-1, NULL); + grid *g = grid_new(GRID_SQUARE, w-1, h-1, 0, NULL); char *board = snewn(g->num_faces, char); int i, s = g->tilesize; struct pearl_loopgen_bias_ctx biasctx; -- 2.11.0