diff options
| author | Jonas Kölker <jonaskoelker@yahoo.com> | 2015-10-01 21:29:42 +0200 |
|---|---|---|
| committer | Simon Tatham <anakin@pobox.com> | 2015-10-03 17:12:20 +0100 |
| commit | b9dfef7a12a6ce813f30f1cc755ed3bb21945dcc (patch) | |
| tree | 951eafad08911593093be1808821c1a704dd71ca /inertia.c | |
| parent | bda4a963f447e3395a160e57ab9498278ad2fde2 (diff) | |
| download | puzzles-b9dfef7a12a6ce813f30f1cc755ed3bb21945dcc.zip puzzles-b9dfef7a12a6ce813f30f1cc755ed3bb21945dcc.tar.gz puzzles-b9dfef7a12a6ce813f30f1cc755ed3bb21945dcc.tar.bz2 puzzles-b9dfef7a12a6ce813f30f1cc755ed3bb21945dcc.tar.xz | |
Recompute solutions in Inertia if the user strays from the path.
Diffstat (limited to 'inertia.c')
| -rw-r--r-- | inertia.c | 79 |
1 files changed, 45 insertions, 34 deletions
@@ -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); } } |