X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/79cb09e95eb4303318afb13c55759e48bfd5c016..acc7c231cc4a80bd0d2e2e9bad66a4b2bf3e7f49:/flip.c diff --git a/flip.c b/flip.c index 0cd5348..4f78ec7 100644 --- a/flip.c +++ b/flip.c @@ -347,7 +347,7 @@ static void addneighbours(tree234 *t, int w, int h, int cx, int cy, } static char *new_game_desc(game_params *params, random_state *rs, - game_aux_info **aux, int interactive) + char **aux, int interactive) { int w = params->w, h = params->h, wh = w * h; int i, j; @@ -590,14 +590,11 @@ static char *new_game_desc(game_params *params, random_state *rs, sprintf(ret, "%s,%s", mbmp, gbmp); sfree(mbmp); sfree(gbmp); + sfree(matrix); + sfree(grid); return ret; } -static void game_free_aux_info(game_aux_info *aux) -{ - assert(!"Shouldn't happen"); -} - static char *validate_desc(game_params *params, char *desc) { int w = params->w, h = params->h, wh = w * h; @@ -673,15 +670,15 @@ static void rowxor(unsigned char *row1, unsigned char *row2, int len) row1[i] ^= row2[i]; } -static game_state *solve_game(game_state *state, game_state *currstate, - game_aux_info *aux, char **error) +static char *solve_game(game_state *state, game_state *currstate, + char *aux, char **error) { int w = state->w, h = state->h, wh = w * h; unsigned char *equations, *solution, *shortest; int *und, nund; int rowsdone, colsdone; int i, j, k, len, bestlen; - game_state *ret; + char *ret; /* * Set up a list of simultaneous equations. Each one is of @@ -731,6 +728,7 @@ static game_state *solve_game(game_state *state, game_state *currstate, if (equations[j * (wh+1) + wh]) { *error = "No solution exists for this position"; sfree(equations); + sfree(und); return NULL; } break; @@ -837,21 +835,19 @@ static game_state *solve_game(game_state *state, game_state *currstate, } /* - * We have a solution. Produce a game state with the solution - * marked in annotations. + * We have a solution. Produce a move string encoding the + * solution. */ - ret = dup_game(currstate); - ret->hints_active = TRUE; - ret->cheated = TRUE; - for (i = 0; i < wh; i++) { - ret->grid[i] &= ~2; - if (shortest[i]) - ret->grid[i] |= 2; - } + ret = snewn(wh + 2, char); + ret[0] = 'S'; + for (i = 0; i < wh; i++) + ret[i+1] = shortest[i] ? '1' : '0'; + ret[wh+1] = '\0'; sfree(shortest); sfree(solution); sfree(equations); + sfree(und); return ret; } @@ -870,6 +866,15 @@ static void free_ui(game_ui *ui) { } +static char *encode_ui(game_ui *ui) +{ + return NULL; +} + +static void decode_ui(game_ui *ui, char *encoding) +{ +} + static void game_changed_state(game_ui *ui, game_state *oldstate, game_state *newstate) { @@ -881,41 +886,68 @@ struct game_drawstate { int tilesize; }; -static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds, - int x, int y, int button) +static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, + int x, int y, int button) { - int w = from->w, h = from->h, wh = w * h; - game_state *ret; + int w = state->w, h = state->h /*, wh = w * h */; + char buf[80]; if (button == LEFT_BUTTON) { int tx = FROMCOORD(x), ty = FROMCOORD(y); if (tx >= 0 && tx < w && ty >= 0 && ty < h) { - int i, j, done; + sprintf(buf, "M%d,%d", tx, ty); + return dupstr(buf); + } + } - ret = dup_game(from); + return NULL; +} - if (!ret->completed) - ret->moves++; +static game_state *execute_move(game_state *from, char *move) +{ + int w = from->w, h = from->h, wh = w * h; + game_state *ret; + int x, y; + + if (move[0] == 'S' && strlen(move) == wh+1) { + int i; + + ret = dup_game(from); + ret->hints_active = TRUE; + ret->cheated = TRUE; + for (i = 0; i < wh; i++) { + ret->grid[i] &= ~2; + if (move[i+1] != '0') + ret->grid[i] |= 2; + } + return ret; + } else if (move[0] == 'M' && + sscanf(move+1, "%d,%d", &x, &y) == 2 && + x >= 0 && x < w && y >= 0 && y < h) { + int i, j, done; - i = ty * w + tx; + ret = dup_game(from); - done = TRUE; - for (j = 0; j < wh; j++) { - ret->grid[j] ^= ret->matrix->matrix[i*wh+j]; - if (ret->grid[j] & 1) - done = FALSE; - } - ret->grid[i] ^= 2; /* toggle hint */ - if (done) { - ret->completed = TRUE; - ret->hints_active = FALSE; - } + if (!ret->completed) + ret->moves++; - return ret; - } - } + i = y * w + x; - return NULL; + done = TRUE; + for (j = 0; j < wh; j++) { + ret->grid[j] ^= ret->matrix->matrix[i*wh+j]; + if (ret->grid[j] & 1) + done = FALSE; + } + ret->grid[i] ^= 2; /* toggle hint */ + if (done) { + ret->completed = TRUE; + ret->hints_active = FALSE; + } + + return ret; + } else + return NULL; /* can't parse move string */ } /* ---------------------------------------------------------------------- @@ -1053,11 +1085,19 @@ static void draw_tile(frontend *fe, game_drawstate *ds, } /* - * Draw a hint blob if required. + * Draw a hint rectangle if required. */ if (tile & 2) { - draw_rect(fe, bx + TILE_SIZE/20, by + TILE_SIZE / 20, - TILE_SIZE / 6, TILE_SIZE / 6, COL_HINT); + int x1 = bx + TILE_SIZE / 20, x2 = bx + TILE_SIZE - TILE_SIZE / 20; + int y1 = by + TILE_SIZE / 20, y2 = by + TILE_SIZE - TILE_SIZE / 20; + int i = 3; + while (i--) { + draw_line(fe, x1, y1, x2, y1, COL_HINT); + draw_line(fe, x1, y2, x2, y2, COL_HINT); + draw_line(fe, x1, y1, x1, y2, COL_HINT); + draw_line(fe, x2, y1, x2, y2, COL_HINT); + x1++, y1++, x2--, y2--; + } } unclip(fe); @@ -1174,7 +1214,7 @@ static int game_timing_state(game_state *state) #endif const struct game thegame = { - "Flip", NULL, + "Flip", "games.flip", default_params, game_fetch_preset, decode_params, @@ -1184,7 +1224,6 @@ const struct game thegame = { TRUE, game_configure, custom_params, validate_params, new_game_desc, - game_free_aux_info, validate_desc, new_game, dup_game, @@ -1193,8 +1232,11 @@ const struct game thegame = { FALSE, game_text_format, new_ui, free_ui, + encode_ui, + decode_ui, game_changed_state, - make_move, + interpret_move, + execute_move, game_size, game_colours, game_new_drawstate,