X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/3fcd6cf0c38928a36ccc1b065f9dd253b9e980ea..c5aa0b02c19bfd6e717837c0ae0b912456e47622:/netslide.c diff --git a/netslide.c b/netslide.c index d19bdbb..12fabd7 100644 --- a/netslide.c +++ b/netslide.c @@ -82,11 +82,6 @@ struct game_params { int movetarget; }; -struct game_aux_info { - int width, height; - unsigned char *tiles; -}; - struct game_state { int width, height, cx, cy, wrapping, completed; int used_solve, just_used_solve; @@ -314,7 +309,7 @@ static game_params *custom_params(config_item *cfg) return ret; } -static char *validate_params(game_params *params) +static char *validate_params(game_params *params, int full) { if (params->width <= 1 || params->height <= 1) return "Width and height must both be greater than one"; @@ -330,7 +325,7 @@ static char *validate_params(game_params *params) */ static char *new_game_desc(game_params *params, random_state *rs, - game_aux_info **aux, int interactive) + char **aux, int interactive) { tree234 *possibilities, *barriertree; int w, h, x, y, cx, cy, nbarriers; @@ -535,19 +530,22 @@ static char *new_game_desc(game_params *params, random_state *rs, } /* - * Save the unshuffled grid. We do this using a separate - * reference-counted structure since it's a large chunk of - * memory which we don't want to have to replicate in every - * game state while playing. + * Save the unshuffled grid in aux. */ { - game_aux_info *solution; + char *solution; + int i; - solution = snew(game_aux_info); - solution->width = w; - solution->height = h; - solution->tiles = snewn(w * h, unsigned char); - memcpy(solution->tiles, tiles, w * h); + /* + * String format is exactly the same as a solve move, so we + * can just dupstr this in solve_game(). + */ + + solution = snewn(w * h + 2, char); + solution[0] = 'S'; + for (i = 0; i < w * h; i++) + solution[i+1] = "0123456789abcdef"[tiles[i] & 0xF]; + solution[w*h+1] = '\0'; *aux = solution; } @@ -698,12 +696,6 @@ static char *new_game_desc(game_params *params, random_state *rs, return desc; } -static void game_free_aux_info(game_aux_info *aux) -{ - sfree(aux->tiles); - sfree(aux); -} - static char *validate_desc(game_params *params, char *desc) { int w = params->width, h = params->height; @@ -893,24 +885,15 @@ static void free_game(game_state *state) sfree(state); } -static game_state *solve_game(game_state *state, game_aux_info *aux, - char **error) +static char *solve_game(game_state *state, game_state *currstate, + char *aux, char **error) { - game_state *ret; - if (!aux) { *error = "Solution not known for this puzzle"; return NULL; } - assert(aux->width == state->width); - assert(aux->height == state->height); - ret = dup_game(state); - memcpy(ret->tiles, aux->tiles, ret->width * ret->height); - ret->used_solve = ret->just_used_solve = TRUE; - ret->completed = ret->move_count = 1; - - return ret; + return dupstr(aux); } static char *game_text_format(game_state *state) @@ -1004,6 +987,15 @@ static void free_ui(game_ui *ui) sfree(ui); } +static char *encode_ui(game_ui *ui) +{ + return NULL; +} + +static void decode_ui(game_ui *ui, char *encoding) +{ +} + /* ---------------------------------------------------------------------- * Process a move. */ @@ -1058,12 +1050,12 @@ struct game_drawstate { unsigned char *visible; }; -static game_state *make_move(game_state *state, 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 cx, cy; int n, dx, dy; - game_state *ret; + char buf[80]; button &= ~MOD_MASK; @@ -1099,16 +1091,59 @@ static game_state *make_move(game_state *state, game_ui *ui, dy = -dy; } - ret = dup_game(state); + if (dx == 0) + sprintf(buf, "C%d,%d", cx, dy); + else + sprintf(buf, "R%d,%d", cy, dx); + return dupstr(buf); +} + +static game_state *execute_move(game_state *from, char *move) +{ + game_state *ret; + int c, d, col; + + if ((move[0] == 'C' || move[0] == 'R') && + sscanf(move+1, "%d,%d", &c, &d) == 2 && + c >= 0 && c < (move[0] == 'C' ? from->width : from->height)) { + col = (move[0] == 'C'); + } else if (move[0] == 'S' && + strlen(move) == from->width * from->height + 1) { + int i; + ret = dup_game(from); + ret->used_solve = ret->just_used_solve = TRUE; + ret->completed = ret->move_count = 1; + + for (i = 0; i < from->width * from->height; i++) { + c = move[i+1]; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + else { + free_game(ret); + return NULL; + } + ret->tiles[i] = c; + } + return ret; + } else + return NULL; /* can't parse move string */ + + ret = dup_game(from); ret->just_used_solve = FALSE; - if (dx == 0) slide_col(ret, dy, cx); - else slide_row(ret, dx, cy); + if (col) + slide_col(ret, d, c); + else + slide_row(ret, d, c); ret->move_count++; - ret->last_move_row = dx ? cy : -1; - ret->last_move_col = dx ? -1 : cx; - ret->last_move_dir = dx + dy; + ret->last_move_row = col ? -1 : c; + ret->last_move_col = col ? c : -1; + ret->last_move_dir = d; /* * See if the game has been completed. @@ -1159,29 +1194,23 @@ static void game_free_drawstate(game_drawstate *ds) sfree(ds); } -static void game_size(game_params *params, game_drawstate *ds, int *x, int *y, - int expand) +static void game_compute_size(game_params *params, int tilesize, + int *x, int *y) { - int tsx, tsy, ts; - /* - * Each window dimension equals the tile size times two more - * than the grid dimension (the border containing the arrows is - * the same width as the tiles), plus TILE_BORDER, plus twice - * WINDOW_OFFSET. - */ - tsx = (*x - 2*WINDOW_OFFSET - TILE_BORDER) / (params->width + 2); - tsy = (*y - 2*WINDOW_OFFSET - TILE_BORDER) / (params->height + 2); - ts = min(tsx, tsy); - - if (expand) - ds->tilesize = ts; - else - ds->tilesize = min(ts, PREFERRED_TILE_SIZE); + /* Ick: fake up `ds->tilesize' for macro expansion purposes */ + struct { int tilesize; } ads, *ds = &ads; + ads.tilesize = tilesize; *x = BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * params->width + TILE_BORDER; *y = BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * params->height + TILE_BORDER; } +static void game_set_size(game_drawstate *ds, game_params *params, + int tilesize) +{ + ds->tilesize = tilesize; +} + static float *game_colours(frontend *fe, game_state *state, int *ncolours) { float *ret; @@ -1401,8 +1430,7 @@ static void draw_tile(frontend *fe, game_drawstate *ds, game_state *state, points[i+1] = by+(int)(cy+ey); } - draw_polygon(fe, points, 4, TRUE, col); - draw_polygon(fe, points, 4, FALSE, COL_WIRE); + draw_polygon(fe, points, 4, col, COL_WIRE); } /* @@ -1498,8 +1526,7 @@ static void draw_arrow(frontend *fe, game_drawstate *ds, POINT(5, 3 * TILE_SIZE / 8, TILE_SIZE / 2); /* left concave */ POINT(6, TILE_SIZE / 4, TILE_SIZE / 2); /* left corner */ - draw_polygon(fe, coords, 7, TRUE, COL_LOWLIGHT); - draw_polygon(fe, coords, 7, FALSE, COL_TEXT); + draw_polygon(fe, coords, 7, COL_LOWLIGHT, COL_TEXT); } static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, @@ -1769,7 +1796,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, @@ -1778,9 +1804,12 @@ const struct game thegame = { FALSE, game_text_format, new_ui, free_ui, + encode_ui, + decode_ui, game_changed_state, - make_move, - game_size, + interpret_move, + execute_move, + PREFERRED_TILE_SIZE, game_compute_size, game_set_size, game_colours, game_new_drawstate, game_free_drawstate,