chiark / gitweb /
Changed my mind about midend_is_solved: I've now reprototyped it as
authorSimon Tatham <anakin@pobox.com>
Sun, 19 Jun 2011 13:43:35 +0000 (13:43 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 19 Jun 2011 13:43:35 +0000 (13:43 +0000)
midend_status(), and given it three return codes for win, (permanent)
loss and game-still-in-play. Depending on what the front end wants to
use it for, it may find any or all of these three states worth
distinguishing from each other.

(I suppose a further enhancement might be to add _non_-permanent loss
as a fourth distinct status, to describe situations in which you can't
play further without pressing Undo but doing so is not completely
pointless. That might reasonably include dead-end situations in Same
Game and Pegs, and blown-self-up situations in Mines and Inertia.
However, I haven't done this at present.)

[originally from svn r9179]

42 files changed:
blackbox.c
bridges.c
cube.c
devel.but
dominosa.c
fifteen.c
filling.c
flip.c
galaxies.c
guess.c
inertia.c
keen.c
lightup.c
loopy.c
magnets.c
map.c
midend.c
mines.c
net.c
netslide.c
nullgame.c
pattern.c
pegs.c
puzzles.h
range.c
rect.c
samegame.c
signpost.c
singles.c
sixteen.c
slant.c
solo.c
tents.c
towers.c
twiddle.c
unequal.c
unfinished/group.c
unfinished/pearl.c
unfinished/separate.c
unfinished/slide.c
unfinished/sokoban.c
untangle.c

index 305feac09f2b0269658ea7135b472d909e3d513a..be7963426827921ec6ea354cb168b24f52577f89 100644 (file)
@@ -1462,13 +1462,21 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
         return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    /*
-     * We return true whenever the solution has been revealed, even
-     * (on spoiler grounds) if it wasn't guessed correctly.
-     */
-    return state->reveal;
+    if (state->reveal) {
+        /*
+         * We return nonzero whenever the solution has been revealed,
+         * even (on spoiler grounds) if it wasn't guessed correctly.
+         */
+        if (state->nwrong == 0 &&
+            state->nmissed == 0 &&
+            state->nright >= state->minballs)
+            return +1;
+        else
+            return -1;
+    }
+    return 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1519,7 +1527,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index 8e61400c5a279844ef92f473c18d43bda3b8222f..5860e0cb89498c5be4713661fd227557c67a8b0e 100644 (file)
--- a/bridges.c
+++ b/bridges.c
@@ -2713,9 +2713,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2821,7 +2821,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/cube.c b/cube.c
index 9b7048756e83574bb248f45150ab3e863ddcbfb5..cac464076e047069edfeecaf48427df03774fa37 100644 (file)
--- a/cube.c
+++ b/cube.c
@@ -1708,9 +1708,9 @@ static float game_flash_length(game_state *oldstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1761,7 +1761,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index 9438e0ea9ed21fa0cf06fc72918d33e1ffb8d870..806ac638d671ee14ba0f2e7277c05c049b8d6df2 100644 (file)
--- a/devel.but
+++ b/devel.but
@@ -1224,27 +1224,33 @@ a mine from the colour it uses when you complete the game. In order
 to achieve this, its \cw{flash_length()} function has to store a
 flag in the \c{game_ui} to indicate which flash type is required.)
 
-\S{backend-is-solved} \cw{is_solved()}
+\S{backend-status} \cw{status()}
 
-\c int (*is_solved)(game_state *state);
+\c int (*status)(game_state *state);
 
-This function returns \cw{TRUE} if the game represented by \cw{state}
-is currently in a solved state. The mid-end uses this to implement
-\cw{midend_is_solved()} (\k{midend-is-solved}).
+This function returns a status value indicating whether the current
+game is still in play, or has been won, or has been conclusively lost.
+The mid-end uses this to implement \cw{midend_status()}
+(\k{midend-status}).
 
-Front ends may wish to use this as a cue to proactively offer the
-option of starting a new game. Therefore, back ends should consider
-returning \cw{TRUE} in situations where the game is \e{lost} as well
-as won, if losing makes it unlikely that the player would play on.
+The return value should be +1 if the game has been successfully
+solved. If the game has been lost in a situation where further play is
+unlikely, the return value should be -1. If neither is true (so play
+is still ongoing), return zero.
+
+Front ends may wish to use a non-zero status as a cue to proactively
+offer the option of starting a new game. Therefore, back ends should
+not return -1 if the game has been \e{technically} lost but undoing
+and continuing is still a realistic possibility.
 
 (For instance, games with hidden information such as Guess or Mines
-might well set this flag whenever they reveal the solution, whether or
-not the player guessed it correctly, on the grounds that a player
-would be unlikely to hide the solution and continue playing after the
-answer was spoiled. On the other hand, games where you can merely get
-into a dead end such as Same Game or Inertia might choose not to, on
-the grounds that the player would quite likely press Undo and carry on
-playing.)
+might well return a non-zero status whenever they reveal the solution,
+whether or not the player guessed it correctly, on the grounds that a
+player would be unlikely to hide the solution and continue playing
+after the answer was spoiled. On the other hand, games where you can
+merely get into a dead end such as Same Game or Inertia might choose
+to return 0 in that situation, on the grounds that the player would
+quite likely press Undo and carry on playing.)
 
 \S{backend-redraw} \cw{redraw()}
 
@@ -3118,18 +3124,19 @@ The front end can expect its drawing API and/or
 \cw{activate_timer()} to be called from within a call to this
 function.
 
-\H{midend-is-solved} \cw{midend_is_solved()}
+\H{midend-status} \cw{midend_status()}
 
-\c int midend_is_solved(midend *me);
+\c int midend_status(midend *me);
 
-This function returns \cw{TRUE} if the midend is currently displaying
-a game in a solved state, according to the back end's \cw{is_solved()}
+This function returns +1 if the midend is currently displaying a game
+in a solved state, -1 if the game is in a permanently lost state, or 0
+otherwise. This function just calls the back end's \cw{status()}
 function. Front ends may wish to use this as a cue to proactively
 offer the option of starting a new game.
 
-(See \k{backend-is-solved} for more detail about the back end's
-\cw{is_solved()} function and discussion of what should count as
-\q{solved} anyway).
+(See \k{backend-status} for more detail about the back end's
+\cw{status()} function and discussion of what should count as which
+status code.)
 
 \H{midend-can-undo} \cw{midend_can_undo()}
 
index 21d4b67e04585c7113705d8c3d322402e7981a53..02e276c9d5cfc0465b2e51b0e1f84a538c35ce8a 100644 (file)
@@ -1535,9 +1535,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1628,7 +1628,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 338a993ae255722c703f104ba5f04de97946f716..5419f41c75265506cc17bd46eafebf7fb419bdbf 100644 (file)
--- a/fifteen.c
+++ b/fifteen.c
@@ -830,9 +830,9 @@ static float game_flash_length(game_state *oldstate,
         return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -883,7 +883,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index 8b4a7c35342b45deeff29e185ace3d5378ecd8ef..6a0abe9fdfdc13b9f090b27311453fb5f65cbde4 100644 (file)
--- a/filling.c
+++ b/filling.c
@@ -1617,9 +1617,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1720,7 +1720,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                                /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/flip.c b/flip.c
index f8b96aebc04b3012b8f46db868d32d8adb99b578..6ba683b4adacaca7c68bb4d26435cd43319f3cd1 100644 (file)
--- a/flip.c
+++ b/flip.c
@@ -1251,9 +1251,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1304,7 +1304,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index 77ef597a1b63ece6af0816f3fde0d19c1148d0f2..d8906b6841bba5abf7ff83d4e9c9f74b8662aba4 100644 (file)
@@ -3348,9 +3348,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
         return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -3573,7 +3573,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
 #ifdef EDITOR
     FALSE, FALSE, NULL, NULL,
     TRUE,                              /* wants_statusbar */
diff --git a/guess.c b/guess.c
index 8cab1a41fb1e18b0b7538fe3228fa06059469266..a9fc1346e87daf55de1e2b8cefe8121b01b0c856 100644 (file)
--- a/guess.c
+++ b/guess.c
@@ -43,7 +43,7 @@ struct game_state {
     pegrow solution;
     int next_go; /* from 0 to nguesses-1;
                     if next_go == nguesses then they've lost. */
-    int solved;
+    int solved;   /* +1 = win, -1 = lose, 0 = still playing */
 };
 
 static game_params *default_params(void)
@@ -790,7 +790,7 @@ static game_state *execute_move(game_state *from, char *move)
 
     if (!strcmp(move, "S")) {
        ret = dup_game(from);
-       ret->solved = 1;
+       ret->solved = -1;
        return ret;
     } else if (move[0] == 'G') {
        p = move+1;
@@ -817,11 +817,11 @@ static game_state *execute_move(game_state *from, char *move)
        nc_place = mark_pegs(ret->guesses[from->next_go], ret->solution, ret->params.ncolours);
 
        if (nc_place == ret->solution->npegs) {
-           ret->solved = 1; /* win! */
+           ret->solved = +1; /* win! */
        } else {
            ret->next_go = from->next_go + 1;
            if (ret->next_go >= ret->params.nguesses)
-               ret->solved = 1; /* 'lose' so we show the pegs. */
+               ret->solved = -1; /* lose, meaning we show the pegs. */
        }
 
        return ret;
@@ -1273,7 +1273,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
         currmove_redraw(dr, ds, state->next_go, COL_HOLD);
 
     /* draw the solution (or the big rectangle) */
-    if ((state->solved != ds->solved) || !ds->started) {
+    if ((!state->solved ^ !ds->solved) || !ds->started) {
         draw_rect(dr, SOLN_OX, SOLN_OY, SOLN_W, SOLN_H,
                   state->solved ? COL_BACKGROUND : COL_EMPTY);
         draw_update(dr, SOLN_OX, SOLN_OY, SOLN_W, SOLN_H);
@@ -1313,14 +1313,13 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
     /*
-     * We return true whenever the solution has been revealed, even
-     * (on spoiler grounds) if it wasn't guessed correctly.
-     *
-     * However, in that situation, 'solved' is still true, so we don't
-     * have to make any effort to arrange this.
+     * We return nonzero whenever the solution has been revealed, even
+     * (on spoiler grounds) if it wasn't guessed correctly. The
+     * correct return value from this function is already in
+     * state->solved.
      */
     return state->solved;
 }
@@ -1373,7 +1372,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index d29a67669d761baf52c3c9fd2340935c4acf8dc5..74fc3c1682597e3c43c54da95e45845957a76e0c 100644 (file)
--- a/inertia.c
+++ b/inertia.c
@@ -2135,14 +2135,14 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
     /*
-     * If the player has died, we don't list the game as solved,
-     * because they're more likely to undo and carry on than to give
-     * up and start a new game.
+     * We never report the game as lost, on the grounds that if the
+     * player has died they're quite likely to want to undo and carry
+     * on.
      */
-    return !state->gems;
+    return state->gems == 0 ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2193,7 +2193,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/keen.c b/keen.c
index 7984475c5715117e330d70b40d39e6618477fbd4..3776283d7f41008f97d2c2254918efced8491596 100644 (file)
--- a/keen.c
+++ b/keen.c
@@ -2005,9 +2005,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2286,7 +2286,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 5d27fde5ce75f56bd367843f4cb6dc4095a7213e..5fe95b063ecaf9764c01e4ace6fac3a9f75f9bca 100644 (file)
--- a/lightup.c
+++ b/lightup.c
@@ -2160,9 +2160,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2267,7 +2267,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/loopy.c b/loopy.c
index b84ca8241d62e0c753fd5b7f3dd2d782c4e57737..1f95f414b5eacdbaf950d4ad106c64d705073b57 100644 (file)
--- a/loopy.c
+++ b/loopy.c
@@ -3780,9 +3780,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->solved;
+    return state->solved ? +1 : 0;
 }
 
 static void game_print_size(game_params *params, float *x, float *y)
@@ -3918,7 +3918,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE /* wants_statusbar */,
     FALSE, game_timing_state,
index d932232e8a71d8c154faaa17c37718fb27eeda8b..e49b7a51216bd7a00a2ed850be0a050f0d4531a0 100644 (file)
--- a/magnets.c
+++ b/magnets.c
@@ -2233,9 +2233,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2373,7 +2373,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/map.c b/map.c
index 556a9ec03e77798ada5c3a1bd267a74c745de5bc..5d170d10d34fc82bbb36959d6c9e1a8edabda962 100644 (file)
--- a/map.c
+++ b/map.c
@@ -3025,9 +3025,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
        return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -3223,7 +3223,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, TRUE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 0c8b3c003226a71f916b20dd9ebe17c323a9fcf4..8f4e4c98bf5eb9c2a5abdf605b9b9704a4cd5b9a 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -1336,7 +1336,7 @@ char *midend_solve(midend *me)
     return NULL;
 }
 
-int midend_is_solved(midend *me)
+int midend_status(midend *me)
 {
     /*
      * We should probably never be called when the state stack has no
@@ -1347,8 +1347,10 @@ int midend_is_solved(midend *me)
      * practically, a user whose midend has been left in that state
      * probably _does_ want the 'new game' option to be prominent.
      */
-    return (me->statepos == 0 ||
-            me->ourgame->is_solved(me->states[me->statepos-1].state));
+    if (me->statepos == 0)
+        return +1;
+
+    return me->ourgame->status(me->states[me->statepos-1].state);
 }
 
 char *midend_rewrite_statusbar(midend *me, char *text)
diff --git a/mines.c b/mines.c
index 80d23372d5f19a427f97418c81038f00cc213723..13cdc0c59eba5dae51f1e0221f2f463e5e9c3c1e 100644 (file)
--- a/mines.c
+++ b/mines.c
@@ -3084,9 +3084,14 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->won;
+    /*
+     * We report the game as lost only if the player has used the
+     * Solve function to reveal all the mines. Otherwise, we assume
+     * they'll undo and continue play.
+     */
+    return state->won ? (state->used_solve ? -1 : +1) : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -3139,7 +3144,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     TRUE, game_timing_state,
diff --git a/net.c b/net.c
index b8fd7e66580d93e4d5c25b7ec53c6a8d836299b5..667f9396be9c516f1db99e65bac417b506a6a8ad 100644 (file)
--- a/net.c
+++ b/net.c
@@ -2864,9 +2864,9 @@ static float game_flash_length(game_state *oldstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -3044,7 +3044,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index 27a3934b43648c05e84f164f90845786ef96c1e7..076cad41b2fee1c1a814edc2f8a899c78ea8b606 100644 (file)
@@ -1826,9 +1826,9 @@ static float game_flash_length(game_state *oldstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1879,7 +1879,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index 1484587982f61bade8a52fe88054779633a75f50..9e9910939241e10627600fce79bbdf38b79ffa6f 100644 (file)
@@ -238,9 +238,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return FALSE;
+    return 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -291,7 +291,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 4a72acfc19dc1955307e83cf264604c09cff2a39..043c1de41652595faa031865af5d2d1bfc94a51f 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -1282,9 +1282,9 @@ static float game_flash_length(game_state *oldstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1391,7 +1391,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/pegs.c b/pegs.c
index 195bca1c3fbd62e41e48056d169c035990779125..4daa55f23a53615c7db1025308d68e9eba1a540f 100644 (file)
--- a/pegs.c
+++ b/pegs.c
@@ -1269,9 +1269,13 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
         return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    /*
+     * Dead-end situations are assumed to be rescuable by Undo, so we
+     * don't bother to identify them and return -1.
+     */
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1322,7 +1326,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 1561f4a81dea5de88ff215a626e635724cb0f8ec..593fd38ac54bba49f050abb86350192b9e7c01e5 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -253,7 +253,7 @@ char *midend_get_game_id(midend *me);
 int midend_can_format_as_text_now(midend *me);
 char *midend_text_format(midend *me);
 char *midend_solve(midend *me);
-int midend_is_solved(midend *me);
+int midend_status(midend *me);
 int midend_can_undo(midend *me);
 int midend_can_redo(midend *me);
 void midend_supersede_game_desc(midend *me, char *desc, char *privdesc);
@@ -479,7 +479,7 @@ struct game {
                         game_ui *ui);
     float (*flash_length)(game_state *oldstate, game_state *newstate, int dir,
                          game_ui *ui);
-    int (*is_solved)(game_state *state);
+    int (*status)(game_state *state);
     int can_print, can_print_in_colour;
     void (*print_size)(game_params *params, float *x, float *y);
     void (*print)(drawing *dr, game_state *state, int tilesize);
diff --git a/range.c b/range.c
index 6bdba76670579123547c7187e6f0ed44b4930017..afb2de63d5132977f74b67902f68ac2c11dd291f 100644 (file)
--- a/range.c
+++ b/range.c
@@ -1485,9 +1485,9 @@ static float game_flash_length(game_state *from, game_state *to,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->was_solved;
+    return state->was_solved ? +1 : 0;
 }
 
 /* ----------------------------------------------------------------------
@@ -1737,7 +1737,7 @@ struct game const thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE, /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/rect.c b/rect.c
index f9ab508eb428529c0e80a24261c6b2d4450603c2..0a936386917d04842f6cab68373f0635e501927c 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -2855,9 +2855,9 @@ static float game_flash_length(game_state *oldstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2965,7 +2965,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index dc1f380dcc7abe06d1a60fe8f8cfcde8cdff3215..49dd64eae9dc5e9e76ae901849caca3e9e053ff9 100644 (file)
@@ -1611,14 +1611,13 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
        return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
     /*
-     * If the player has run out of moves without winning, we don't
-     * list the game as solved, because they're more likely to undo
-     * and carry on than to give up and start a new game.
+     * Dead-end situations are assumed to be rescuable by Undo, so we
+     * don't bother to identify them and return -1.
      */
-    return state->complete;
+    return state->complete ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1669,7 +1668,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index fdeadbac872f6ef4c7b3825042bfe66bbadb0789..3f2a64562a98afc4593417b4b17f0b56f22f476e 100644 (file)
@@ -2122,9 +2122,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
         return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2208,7 +2208,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 2c33337106e2503e76b43d4ee691a20017ff18b4..ff75cfbad388813538055418ef4bbfb310a6de1d 100644 (file)
--- a/singles.c
+++ b/singles.c
@@ -1735,9 +1735,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1826,7 +1826,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 6f061cd84f15397f02c0c6dbcc3217eada282c91..8079facfcfc52ba3a441a87e07ad7a4d6e257c18 100644 (file)
--- a/sixteen.c
+++ b/sixteen.c
@@ -1073,9 +1073,9 @@ static float game_flash_length(game_state *oldstate,
         return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1126,7 +1126,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/slant.c b/slant.c
index f85644c98b8153021e789ba975091953760d6ec2..52f21d6b86e6db651096147649fa576d58c3d0ff 100644 (file)
--- a/slant.c
+++ b/slant.c
@@ -2079,9 +2079,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2195,7 +2195,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/solo.c b/solo.c
index 8e50c3b8cac984577b8e173b0708903dcdb67961..052ebefd78f39b58878831153f50cdb51d415516 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -5187,9 +5187,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -5511,7 +5511,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
diff --git a/tents.c b/tents.c
index 6cf406d796988dffe49154e99f2442218611586e..cfdcdc37786e2db8e4689fcc71a77ab07ad33019 100644 (file)
--- a/tents.c
+++ b/tents.c
@@ -2522,9 +2522,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2597,7 +2597,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 94ed1a7b11470bd1c2457d0941f6a659792b2f36..be0a7306d7a36abe9a507cadefb8e73f501f39fe 100644 (file)
--- a/towers.c
+++ b/towers.c
@@ -1808,9 +1808,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1932,7 +1932,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index c5f89f81db911fce4f0f294b88af5248245a9d75..51a21f04749bc305512fd15ecf040cf518c1bfe6 100644 (file)
--- a/twiddle.c
+++ b/twiddle.c
@@ -1069,9 +1069,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
         return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
@@ -1291,7 +1291,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index 29f052701b4aad1b308ba4ab922be24034c4b0d7..5dcca368061ecd1a9f9fd7b99818b5e735e13b84 100644 (file)
--- a/unequal.c
+++ b/unequal.c
@@ -1865,9 +1865,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1958,7 +1958,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 869ff04bde11d0a7e80063de459c17b6cb2ade0f..79bd3fa79139de4d56845f325244fe5cb585e16e 100644 (file)
@@ -1813,9 +1813,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1936,7 +1936,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 843d99ea35e8c799c41927a443d52de777814057..51b2ed2eb74fe17fca08ef0afc84420758fd424f 100644 (file)
@@ -1349,9 +1349,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return FALSE;
+    return 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1402,7 +1402,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index b11f604b5f3eec6af88f01ae48a05b2dd64e1a58..b20cb52b6feeed60ce9860a83d02397abbacf681 100644 (file)
@@ -795,9 +795,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return FALSE;
+    return 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -848,7 +848,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index fbaa630ce7a2db962cf5b2a1ceeb1261d6de17ae..6fac4697463490c37b929aa262466e9fbda59c79 100644 (file)
@@ -2292,9 +2292,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -2345,7 +2345,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
index b389eb5792c823f6af786dea721baaa631634e45..53bd3a5bc00bb9818d79321373ae6c3d45bff75a 100644 (file)
@@ -1415,9 +1415,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
         return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1468,7 +1468,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
index 7a34475ef9fffce061ea48fdd3574db1b939867f..c07c957e0ec736984705a190db75eaf5f339aa47 100644 (file)
@@ -1412,9 +1412,9 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_is_solved(game_state *state)
+static int game_status(game_state *state)
 {
-    return state->completed;
+    return state->completed ? +1 : 0;
 }
 
 static int game_timing_state(game_state *state, game_ui *ui)
@@ -1465,7 +1465,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
-    game_is_solved,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,