#include <stdlib.h>
#include <string.h>
-#include <editline/readline.h>
#include <time.h>
#include <inttypes.h>
#include "advent.h"
#include "dungeon.h"
-#define VRSION 28 /* bump on save format change */
+/*
+ * Bump on save format change.
+ *
+ * Note: Verify that the tests run clean before bumping this, then rebuild the check
+ * files afterwards. Otherwise you will get a spurious failure due to the old version
+ * having been generated into a check file.
+ */
+#define VRSION 29
/*
* If you change the first three members, the resume function may not properly
/* 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;
rspeak(SUSPEND_WARNING);
- if (!yes(arbitrary_messages[THIS_ACCEPTABLE], arbitrary_messages[OK_MAN], arbitrary_messages[OK_MAN]))
+ if (!yes_or_no(arbitrary_messages[THIS_ACCEPTABLE], arbitrary_messages[OK_MAN], arbitrary_messages[OK_MAN]))
return GO_CLEAROBJ;
game.saved = game.saved + 5;
while (fp == NULL) {
- char* name = readline("\nFile name: ");
+ char* name = myreadline("\nFile name: ");
if (name == NULL)
return GO_TOP;
fp = fopen(name, WRITE_MODE);
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;
if (game.loc != 1 ||
game.abbrev[1] != 1) {
rspeak(RESUME_ABANDON);
- if (!yes(arbitrary_messages[THIS_ACCEPTABLE], arbitrary_messages[OK_MAN], arbitrary_messages[OK_MAN]))
+ if (!yes_or_no(arbitrary_messages[THIS_ACCEPTABLE], arbitrary_messages[OK_MAN], arbitrary_messages[OK_MAN]))
return GO_CLEAROBJ;
}
while (fp == NULL) {
- char* name = readline("\nFile name: ");
+ char* name = myreadline("\nFile name: ");
+ // Autocomplete can leave the input with an extra trailing space.
+ if (name != NULL && strlen(name) > 0 && name[strlen(name) - 1] == ' ')
+ name[strlen(name) - 1] = '\0';
if (name == NULL)
return GO_TOP;
fp = fopen(name, READ_MODE);
{
/* 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));
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
*/
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)