state is in a solved position, and a midend function wrapping it.
(Or, at least, a situation in which further play is pointless. The
point is, given that game state, would it be a good idea for a front
end that does that sort of thing to proactively provide the option to
start a fresh game?)
[originally from svn r9140]
return 0.0F;
}
+static int game_is_solved(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;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
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()}
+
+\c int (*is_solved)(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}).
+
+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 TRUE in situations where the game is \e{lost} as well as
+won, if losing makes it unlikely that the player would play on.
+
+(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.)
+
\S{backend-redraw} \cw{redraw()}
\c void (*redraw)(drawing *dr, game_drawstate *ds,
\cw{activate_timer()} to be called from within a call to this
function.
+\S{midend-is-solved} \cw{midend_is_solved()}
+
+\c int midend_is_solved(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()}
+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).
+
\H{midend-can-undo} \cw{midend_can_undo()}
\c int midend_can_undo(midend *me);
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
#ifdef EDITOR
FALSE, FALSE, NULL, NULL,
TRUE, /* wants_statusbar */
return 0.0F;
}
+static int game_is_solved(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.
+ */
+ return state->solved;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(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.
+ */
+ return !state->gems;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
if (state->completed)
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->solved;
+}
+
static void game_print_size(game_params *params, float *x, float *y)
{
int pw, ph;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE /* wants_statusbar */,
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, TRUE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return NULL;
}
+int midend_is_solved(midend *me)
+{
+ /*
+ * We should probably never be called when the state stack has no
+ * states on it at all - ideally, midends should never be left in
+ * that state for long enough to get put down and forgotten about.
+ * But if we are, I think we return _true_ - pedantically speaking
+ * a midend in that state is 'vacuously solved', and more
+ * 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));
+}
+
char *midend_rewrite_statusbar(midend *me, char *text)
{
/*
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->won;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
if (state->dead || state->won || ui->completed || !state->layout->mines)
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
TRUE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return FALSE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return FALSE;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
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_can_undo(midend *me);
int midend_can_redo(midend *me);
void midend_supersede_game_desc(midend *me, char *desc, char *privdesc);
game_ui *ui);
float (*flash_length)(game_state *oldstate, game_state *newstate, int dir,
game_ui *ui);
+ int (*is_solved)(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);
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->was_solved;
+}
+
/* ----------------------------------------------------------------------
* Drawing routines.
*/
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(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.
+ */
+ return state->complete;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
if (state->completed)
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
if (state->completed)
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
game_state *state, int dir, game_ui *ui,
float animtime, float flashtime)
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
if (state->completed)
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return FALSE;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return FALSE;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,
return 0.0F;
}
+static int game_is_solved(game_state *state)
+{
+ return state->completed;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
game_redraw,
game_anim_length,
game_flash_length,
+ game_is_solved,
FALSE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,