/* Suspend. Offer to save things in a file, but charging
* some points (so can't win by using saved games to retry
* battles or to start over after learning zzword).
- * If ADVENT_NOSAVE is defined, do nothing instead. */
+ * If ADVENT_NOSAVE is defined, gripe instead. */
-#ifdef ADVENT_NOSAVE
- return GO_UNKNOWN;
+#if defined ADVENT_NOSAVE || defined ADVENT_AUTOSAVE
+ rspeak(SAVERESUME_DISABLED)
+ return GO_TOP;
#endif
FILE *fp = NULL;
int resume(void)
{
/* Resume. Read a suspended game back from a file.
- * If ADVENT_NOSAVE is defined, do nothing instead. */
+ * If ADVENT_NOSAVE is defined, gripe instead. */
-#ifdef ADVENT_NOSAVE
- return GO_UNKNOWN;
+#if defined ADVENT_NOSAVE || defined ADVENT_AUTOSAVE
+ rspeak(SAVERESUME_DISABLED)
+ return GO_TOP;
#endif
FILE *fp = NULL;
{
/* Read and restore game state from file, assuming
* sane initial state.
- * If ADVENT_NOSAVE is defined, do nothing instead. */
+ * If ADVENT_NOSAVE is defined, gripe instead. */
#ifdef ADVENT_NOSAVE
- return GO_UNKNOWN;
+ rspeak(SAVERESUME_DISABLED)
+ return GO_TOP;
#endif
IGNORE(fread(&save, sizeof(struct save_t), 1, fp));
fclose(fp);
if (save.version != VRSION) {
rspeak(VERSION_SKEW, save.version / 10, MOD(save.version, 10), VRSION / 10, MOD(VRSION, 10));
- } else if (is_valid(save.game)) {
+ } else if (!is_valid(save.game)) {
+ rspeak(SAVE_TAMPERING);
+ exit(EXIT_SUCCESS);
+ } else {
game = save.game;
}
return GO_TOP;
bool is_valid(struct game_t valgame)
{
/* Save files can be roughly grouped into three groups:
- * With valid, reaceable state, with valid, but unreachable
- * state and with invaild state. We check that state is
+ * With valid, reacheable state, with valid, but unreachable
+ * state and with invalid state. We check that state is
* valid: no states are outside minimal or maximal value
*/
/* Check that properties of objects aren't beyond expected */
for (obj_t obj = 0; obj <= NOBJECTS; obj++) {
- if (valgame.prop[obj] < STATE_NOTFOUND || valgame.prop[obj] > 1) {
+ /* Magic number -2 allows a STASHED version of state 1 */
+ if (valgame.prop[obj] < -2 || valgame.prop[obj] > 1) {
switch (obj) {
case RUG:
case DRAGON:
case VASE:
case CHAIN:
if (valgame.prop[obj] == 2) // There are multiple different states, but it's convenient to clump them together
- continue;
+ continue; // LCOV_EXCL_LINE
/* FALLTHRU */
case BEAR:
if (valgame.prop[BEAR] == CONTENTED_BEAR || valgame.prop[BEAR] == BEAR_DEAD)