X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=inertia.c;h=c22d2e17d4be879e3dc9a9c09ea0f806b0603354;hb=3aa4516a680f52e2e6c8a16234a7ecca0ec77233;hp=7bd73c17fea08f79cb714f02c61d4194482efb98;hpb=d0f88aafa4b641904735c3e20485e66be6c77cb4;p=sgt-puzzles.git diff --git a/inertia.c b/inertia.c index 7bd73c1..c22d2e1 100644 --- a/inertia.c +++ b/inertia.c @@ -735,7 +735,7 @@ static int compare_integers(const void *av, const void *bv) static char *solve_game(const game_state *state, const game_state *currstate, const char *aux, char **error) { - int w = state->p.w, h = state->p.h, wh = w*h; + int w = currstate->p.w, h = currstate->p.h, wh = w*h; int *nodes, *nodeindex, *edges, *backedges, *edgei, *backedgei, *circuit; int nedges; int *dist, *dist2, *list; @@ -1645,6 +1645,38 @@ static char *interpret_move(const game_state *state, game_ui *ui, return dupstr(buf); } +static void install_new_solution(game_state *ret, const char *move) +{ + int i; + soln *sol; + assert (*move == 'S'); + ++move; + + sol = snew(soln); + sol->len = strlen(move); + sol->list = snewn(sol->len, unsigned char); + for (i = 0; i < sol->len; ++i) sol->list[i] = move[i] - '0'; + + if (ret->soln && --ret->soln->refcount == 0) { + sfree(ret->soln->list); + sfree(ret->soln); + } + + ret->soln = sol; + sol->refcount = 1; + + ret->cheated = TRUE; + ret->solnpos = 0; +} + +static void discard_solution(game_state *ret) +{ + --ret->soln->refcount; + assert(ret->soln->refcount > 0); /* ret has a soln-pointing dup */ + ret->soln = NULL; + ret->solnpos = 0; +} + static game_state *execute_move(const game_state *state, const char *move) { int w = state->p.w, h = state->p.h /*, wh = w*h */; @@ -1652,29 +1684,12 @@ static game_state *execute_move(const game_state *state, const char *move) game_state *ret; if (*move == 'S') { - int len, i; - soln *sol; - /* * This is a solve move, so we don't actually _change_ the * grid but merely set up a stored solution path. */ - move++; - len = strlen(move); - sol = snew(soln); - sol->len = len; - sol->list = snewn(len, unsigned char); - for (i = 0; i < len; i++) - sol->list[i] = move[i] - '0'; ret = dup_game(state); - ret->cheated = TRUE; - if (ret->soln && --ret->soln->refcount == 0) { - sfree(ret->soln->list); - sfree(ret->soln); - } - ret->soln = sol; - ret->solnpos = 0; - sol->refcount = 1; + install_new_solution(ret, move); return ret; } @@ -1715,22 +1730,18 @@ static game_state *execute_move(const game_state *state, const char *move) } if (ret->soln) { - /* - * If this move is the correct next one in the stored - * solution path, advance solnpos. - */ - if (ret->soln->list[ret->solnpos] == dir && - ret->solnpos+1 < ret->soln->len) { - ret->solnpos++; + if (ret->dead || ret->gems == 0) + discard_solution(ret); + else if (ret->soln->list[ret->solnpos] == dir) { + ++ret->solnpos; + assert(ret->solnpos < ret->soln->len); /* or gems == 0 */ + assert(!ret->dead); /* or not a solution */ } else { - /* - * Otherwise, the user has strayed from the path, so - * the path is no longer valid. - */ - ret->soln->refcount--; - assert(ret->soln->refcount > 0);/* `state' at least still exists */ - ret->soln = NULL; - ret->solnpos = 0; + char *error = NULL, *soln = solve_game(NULL, ret, NULL, &error); + if (!error) { + install_new_solution(ret, soln); + sfree(soln); + } else discard_solution(ret); } } @@ -2202,7 +2213,7 @@ static void game_print(drawing *dr, const game_state *state, int tilesize) const struct game thegame = { "Inertia", "games.inertia", "inertia", default_params, - game_fetch_preset, + game_fetch_preset, NULL, decode_params, encode_params, free_params,