X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/121aae4bb9c6afab9ca957d1c0185ab1b0bd435b..6ce42e60a5d04df7628254fae6490aa5a8124eb7:/loopy.c diff --git a/loopy.c b/loopy.c index 777e6f8..f0344fe 100644 --- a/loopy.c +++ b/loopy.c @@ -120,7 +120,7 @@ typedef struct solver_state { #define CONFIG(upper,title,lower,fn) ":" #title #define SOLVER_FN_DECL(upper,title,lower,fn) static int fn(solver_state *); #define SOLVER_FN(upper,title,lower,fn) &fn, -enum diff { DIFFLIST(ENUM) DIFF_MAX }; +enum { DIFFLIST(ENUM) DIFF_MAX }; static char const *const diffnames[] = { DIFFLIST(TITLE) }; static char const diffchars[] = DIFFLIST(ENCODE); #define DIFFCONFIG DIFFLIST(CONFIG) @@ -129,7 +129,7 @@ static int (*(solver_fns[]))(solver_state *) = { DIFFLIST(SOLVER_FN) }; struct game_params { int w, h; - enum diff diff; + int diff; int rec; }; @@ -159,7 +159,7 @@ static int get_line_status_from_point(const game_state *state, static int dot_order(const game_state* state, int i, int j, char line_type); static int square_order(const game_state* state, int i, int j, char line_type); static solver_state *solve_game_rec(const solver_state *sstate, - enum diff diff); + int diff); #ifdef DEBUG_CACHES static void check_caches(const solver_state* sstate); @@ -323,7 +323,7 @@ static void free_game(game_state *state) } } -static solver_state *new_solver_state(const game_state *state, enum diff diff) { +static solver_state *new_solver_state(const game_state *state, int diff) { int i, j; solver_state *ret = snew(solver_state); @@ -512,22 +512,25 @@ static const game_params presets[] = { { 15, 15, DIFF_EASY, 0 }, { 15, 15, DIFF_NORMAL, 0 }, { 15, 15, DIFF_HARD, 0 }, +#ifndef SMALL_SCREEN { 30, 20, DIFF_EASY, 0 }, { 30, 20, DIFF_NORMAL, 0 }, { 30, 20, DIFF_HARD, 0 } #endif +#endif }; static int game_fetch_preset(int i, char **name, game_params **params) { - const game_params *tmppar; + game_params *tmppar; char buf[80]; if (i < 0 || i >= lenof(presets)) return FALSE; - tmppar = &presets[i]; - *params = dup_params((game_params *)tmppar); + tmppar = snew(game_params); + *tmppar = presets[i]; + *params = tmppar; sprintf(buf, "%dx%d %s", tmppar->h, tmppar->w, diffnames[tmppar->diff]); *name = dupstr(buf); @@ -630,7 +633,7 @@ static char *validate_params(game_params *params, int full) * and custom_params will never generate anything that isn't * within range. */ - assert(params->diff >= 0 && params->diff < DIFF_MAX); + assert(params->diff < DIFF_MAX); return NULL; } @@ -656,12 +659,12 @@ static char *state_to_text(const game_state *state) dp += sprintf(dp, "%c", (int)(empty_count + 'a' - 1)); empty_count = 0; } - dp += sprintf(dp, "%c", CLUE2CHAR(CLUE_AT(state, i, j))); + dp += sprintf(dp, "%c", (int)CLUE2CHAR(CLUE_AT(state, i, j))); } } if (empty_count) - dp += sprintf(dp, "%c", (empty_count + 'a' - 1)); + dp += sprintf(dp, "%c", (int)(empty_count + 'a' - 1)); retval = dupstr(description); sfree(description); @@ -909,7 +912,7 @@ static char *game_text_format(game_state *state) rp += sprintf(rp, " \n"); for (i = 0; i < state->w; ++i) { DRAW_VL; - rp += sprintf(rp, "%c", CLUE2CHAR(CLUE_AT(state, i, j))); + rp += sprintf(rp, "%c", (int)CLUE2CHAR(CLUE_AT(state, i, j))); } DRAW_VL; rp += sprintf(rp, "\n"); @@ -1646,7 +1649,7 @@ static void add_full_clues(game_state *state, random_state *rs) sfree(board); } -static int game_has_unique_soln(const game_state *state, enum diff diff) +static int game_has_unique_soln(const game_state *state, int diff) { int ret; solver_state *sstate_new; @@ -1665,7 +1668,7 @@ static int game_has_unique_soln(const game_state *state, enum diff diff) /* Remove clues one at a time at random. */ static game_state *remove_clues(game_state *state, random_state *rs, - enum diff diff) + int diff) { int *square_list, squares; game_state *ret = dup_game(state), *saved_ret; @@ -1743,7 +1746,9 @@ newboard_please: state = state_new; if (params->diff > 0 && game_has_unique_soln(state, params->diff-1)) { +#ifdef SHOW_WORKING fprintf(stderr, "Rejecting board, it is too easy\n"); +#endif goto newboard_please; } @@ -1873,26 +1878,21 @@ const static struct dline dlines[] = { (d==DLINE_DR) ? "DLINE_DR": \ "oops") -static const struct dline *get_dline(enum dline_desc desc) -{ - return &dlines[desc]; -} +#define CHECK_DLINE_SENSIBLE(d) assert(dlines[(d)].dx != -1 && dlines[(d)].dy != -1) /* This will fail an assertion if the directions handed to it are the same, as * no dline corresponds to that */ static enum dline_desc dline_desc_from_dirs(enum direction dir1, enum direction dir2) { - const struct dline *dl; int i; assert (dir1 != dir2); for (i = 0; i < lenof(dlines); ++i) { - dl = &dlines[i]; - if ((dir1 == dl->dir1 && dir2 == dl->dir2) || - (dir1 == dl->dir2 && dir2 == dl->dir1)) { - return dl->desc; + if ((dir1 == dlines[i].dir1 && dir2 == dlines[i].dir2) || + (dir1 == dlines[i].dir2 && dir2 == dlines[i].dir1)) { + return dlines[i].desc; } } @@ -1904,7 +1904,7 @@ static enum dline_desc dline_desc_from_dirs(enum direction dir1, * dline corresponding to the dot or square at [i,j]. You'll get an assertion * failure if you talk about a dline that doesn't exist, ie if you ask about * non-touching lines around a square. */ -static inline int get_dot_dline(const game_state *state, const char *dline_array, +static int get_dot_dline(const game_state *state, const char *dline_array, int i, int j, enum dline_desc desc) { /* fprintf(stderr, "get_dot_dline %p [%d,%d] %s\n", dline_array, i, j, DL2STR(desc)); */ @@ -1931,10 +1931,9 @@ static int set_dot_dline(game_state *state, char *dline_array, static int get_square_dline(game_state *state, char *dline_array, int i, int j, enum dline_desc desc) { - const struct dline *dl = get_dline(desc); - assert(dl->dx != -1 && dl->dy != -1); + CHECK_DLINE_SENSIBLE(desc); /* fprintf(stderr, "get_square_dline %p [%d,%d] %s\n", dline_array, i, j, DL2STR(desc)); */ - return BIT_SET(dline_array[(i+dl->dx) + (state->w + 1) * (j+dl->dy)], + return BIT_SET(dline_array[(i+dlines[desc].dx) + (state->w + 1) * (j+dlines[desc].dy)], desc); } @@ -1945,10 +1944,9 @@ static int set_square_dline(game_state *state, char *dline_array, #endif ) { - const struct dline *dl = get_dline(desc); int ret; - assert(dl->dx != -1 && dl->dy != -1); - ret = SET_BIT(dline_array[(i+dl->dx) + (state->w + 1) * (j+dl->dy)], desc); + CHECK_DLINE_SENSIBLE(desc); + ret = SET_BIT(dline_array[(i+dlines[desc].dx) + (state->w + 1) * (j+dlines[desc].dy)], desc); #ifdef SHOW_WORKING if (ret) fprintf(stderr, "set_square_dline %p [%d,%d] %s (%s)\n", dline_array, i, j, DL2STR(desc), reason); @@ -1979,10 +1977,9 @@ static int set_square_opp_dline(game_state *state, char *dline_array, static int dline_both_unknown(const game_state *state, int i, int j, enum dline_desc desc) { - const struct dline *dl = get_dline(desc); return - (get_line_status_from_point(state, i, j, dl->dir1) == LINE_UNKNOWN) && - (get_line_status_from_point(state, i, j, dl->dir2) == LINE_UNKNOWN); + (get_line_status_from_point(state, i, j, dlines[desc].dir1) == LINE_UNKNOWN) && + (get_line_status_from_point(state, i, j, dlines[desc].dir2) == LINE_UNKNOWN); } #define SQUARE_DLINES \ @@ -2064,7 +2061,7 @@ static int square_setall_identical(solver_state *sstate, int x, int y, #define SQUARE_LINE(dx, dy, linedir, dir_dot, sqdir) \ can[sqdir] = \ edsf_canonify(sstate->hard->linedsf, \ - LINEDSF_INDEX(sstate->state, x+dx, y+dy, linedir), \ + LINEDSF_INDEX(sstate->state, x+(dx), y+(dy), linedir), \ &inv[sqdir]); SQUARE_LINES; @@ -2083,7 +2080,7 @@ static int square_setall_identical(solver_state *sstate, int x, int y, * consider {i,j} in the opposite order. */ #define SQUARE_LINE(dx, dy, dir, c, sqdir) \ if (j == sqdir) { \ - retval = set_line_bydot(sstate, x+dx, y+dy, dir, line_new); \ + retval = set_line_bydot(sstate, x+(dx), y+(dy), dir, line_new); \ if (retval) { \ break; \ } \ @@ -2142,14 +2139,14 @@ static int square_setboth_in_dline(solver_state *sstate, enum dline_desc dd, int i, int j, enum line_state line_new) { int retval = FALSE; - const struct dline *dl = get_dline(dd); + const struct dline dll = dlines[dd], *dl = &dll; #if 0 fprintf(stderr, "square_setboth_in_dline %s [%d,%d] to %d\n", DL2STR(dd), i, j, line_new); #endif - assert(dl->dx != -1 && dl->dy != -1); + CHECK_DLINE_SENSIBLE(dd); retval |= set_line_bydot(sstate, i+dl->dx, j+dl->dy, dl->dir1, line_new); @@ -2341,7 +2338,7 @@ static int easy_mode_deductions(solver_state *sstate) { int i, j, h, w, current_yes, current_no; game_state *state; - enum diff diff = DIFF_MAX; + int diff = DIFF_MAX; state = sstate->state; h = state->h; @@ -2461,7 +2458,7 @@ static int normal_mode_deductions(solver_state *sstate) int i, j; game_state *state = sstate->state; enum dline_desc dd; - enum diff diff = DIFF_MAX; + int diff = DIFF_MAX; FORALL_SQUARES(state, i, j) { if (sstate->square_solved[SQUARE_INDEX(state, i, j)]) @@ -2649,8 +2646,7 @@ static int hard_mode_deductions(solver_state *sstate) const int h=state->h, w=state->w; enum direction dir1, dir2; int can1, can2, inv1, inv2; - enum diff diff = DIFF_MAX; - const struct dline *dl; + int diff = DIFF_MAX; enum dline_desc dd; FORALL_SQUARES(state, i, j) { @@ -2773,7 +2769,7 @@ static int hard_mode_deductions(solver_state *sstate) continue; FORALL_DOT_DLINES(dd) { - dl = get_dline(dd); + const struct dline dll = dlines[dd], *dl = &dll; if (i == 0 && (dl->dir1 == LEFT || dl->dir2 == LEFT)) continue; if (i == w && (dl->dir1 == RIGHT || dl->dir2 == RIGHT)) @@ -3054,7 +3050,7 @@ finished_loop_deductionsing: /* This will return a dynamically allocated solver_state containing the (more) * solved grid */ static solver_state *solve_game_rec(const solver_state *sstate_start, - enum diff diff) + int diff) { int i, j; int w, h; @@ -3790,14 +3786,14 @@ static void game_print(drawing *dr, game_state *state, int tilesize) /* * Lines. (At the moment, I'm not bothering with crosses.) */ - FORALL_VL(state, x, y) { + FORALL_HL(state, x, y) { if (RIGHTOF_DOT(state, x, y) == LINE_YES) draw_rect(dr, BORDER + x * TILE_SIZE, BORDER + y * TILE_SIZE - LINEWIDTH/2, TILE_SIZE, (LINEWIDTH/2) * 2 + 1, ink); } - FORALL_HL(state, x, y) { + FORALL_VL(state, x, y) { if (BELOW_DOT(state, x, y) == LINE_YES) draw_rect(dr, BORDER + x * TILE_SIZE - LINEWIDTH/2, BORDER + y * TILE_SIZE, @@ -3810,7 +3806,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Loopy", "games.loopy", + "Loopy", "games.loopy", "loopy", default_params, game_fetch_preset, decode_params,