chiark / gitweb /
Recompute solutions in Inertia if the user strays from the path.
authorJonas Kölker <jonaskoelker@yahoo.com>
Thu, 1 Oct 2015 19:29:42 +0000 (21:29 +0200)
committerSimon Tatham <anakin@pobox.com>
Sat, 3 Oct 2015 16:12:20 +0000 (17:12 +0100)
inertia.c
puzzles.but

index 7bd73c17fea08f79cb714f02c61d4194482efb98..4cbdd5299b823359b48b6bad5d16c8eed1b0d92f 100644 (file)
--- 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);
        }
     }
 
index 113f46256be171778038453c9254e7bac7c8987f..b220ca29456e14ef1f34b2ac4001fb32df4da85a 100644 (file)
@@ -2032,9 +2032,7 @@ begin on this path. If you then move in that direction, the arrow
 will update to indicate the next direction on the path. You can also
 press Space to automatically move in the direction of the hint
 arrow. If you move in a different direction from the one shown by
-the arrow, the hint arrows will stop appearing because you have
-strayed from the provided path; you can then use \q{Solve} again to
-generate a new path if you want to.
+the arrow, arrows will be shown only if the puzzle is still solvable.
 
 All the actions described in \k{common-actions} are also available.
 In particular, if you do run into a mine and die, you can use the