Add optional auto-save/restore feature using -a <filename> option
[open-adventure.git] / main.c
diff --git a/main.c b/main.c
index 809574b6c35cc82e02208a05862133463aa26e2b..c53660081b3fa5abfc8444c03ce244cb7e76113c 100644 (file)
--- a/main.c
+++ b/main.c
 
 #define DIM(a) (sizeof(a)/sizeof(a[0]))
 
+#if defined ADVENT_AUTOSAVE
+static FILE* autosave_fp;
+void autosave(void)
+{
+    if (autosave_fp != NULL) {
+        rewind(autosave_fp);
+        savefile(autosave_fp, /* version (auto): */0);
+        fflush(autosave_fp);
+    }
+}
+#endif
+
 // LCOV_EXCL_START
 // exclude from coverage analysis because it requires interactivity to test
 static void sig_handler(int signo)
@@ -26,6 +38,11 @@ static void sig_handler(int signo)
         if (settings.logfp != NULL)
             fflush(settings.logfp);
     }
+
+#if defined ADVENT_AUTOSAVE
+    if (signo == SIGHUP || signo == SIGTERM)
+        autosave();
+#endif
     exit(EXIT_FAILURE);
 }
 // LCOV_EXCL_STOP
@@ -50,7 +67,12 @@ int main(int argc, char *argv[])
 
     /*  Options. */
 
-#ifndef ADVENT_NOSAVE
+#if defined ADVENT_AUTOSAVE
+    const char* opts = "l:oa:";
+    const char* usage = "Usage: %s [-l logfilename] [-o] [-a filename] [script...]\n";
+    FILE *rfp = NULL;
+    const char* autosave_filename = NULL;
+#elif !defined ADVENT_NOSAVE
     const char* opts = "l:or:";
     const char* usage = "Usage: %s [-l logfilename] [-o] [-r restorefilename] [script...]\n";
     FILE *rfp = NULL;
@@ -72,7 +94,14 @@ int main(int argc, char *argv[])
             settings.oldstyle = true;
             settings.prompt = false;
             break;
-#ifndef ADVENT_NOSAVE
+#ifdef ADVENT_AUTOSAVE
+        case 'a':
+            rfp = fopen(optarg, READ_MODE);
+            autosave_filename = optarg;
+            signal(SIGHUP, sig_handler);
+            signal(SIGTERM, sig_handler);
+            break;
+#elif !defined ADVENT_NOSAVE
         case 'r':
             rfp = fopen(optarg, "r");
             if (rfp == NULL)
@@ -88,7 +117,10 @@ int main(int argc, char *argv[])
                     "        -l create a log file of your game named as specified'\n");
             fprintf(stderr,
                     "        -o 'oldstyle' (no prompt, no command editing, displays 'Initialising...')\n");
-#ifndef ADVENT_NOSAVE
+#if defined ADVENT_AUTOSAVE
+            fprintf(stderr,
+                    "        -a automatic save/restore from specified saved game file\n");
+#elif !defined ADVENT_NOSAVE
             fprintf(stderr,
                     "        -r restore from specified saved game file\n");
 #endif
@@ -97,7 +129,7 @@ int main(int argc, char *argv[])
         }
     }
 
-    /* copy inncation line part after switches */
+    /* copy invocation line part after switches */
     settings.argc = argc - optind;
     settings.argv = argv + optind;
     settings.optind = 0;
@@ -105,14 +137,26 @@ int main(int argc, char *argv[])
     /*  Initialize game variables */
     int seedval = initialise();
 
-#ifndef ADVENT_NOSAVE
+#if !defined ADVENT_NOSAVE
     if (!rfp) {
         game.novice = yes_or_no(arbitrary_messages[WELCOME_YOU], arbitrary_messages[CAVE_NEARBY], arbitrary_messages[NO_MESSAGE]);
         if (game.novice)
             game.limit = NOVICELIMIT;
     } else {
         restore(rfp);
+#if defined ADVENT_AUTOSAVE
+        score(scoregame);
+#endif
     }
+#if defined ADVENT_AUTOSAVE
+    if (autosave_filename != NULL) {
+        if ((autosave_fp = fopen(autosave_filename, WRITE_MODE)) == NULL) {
+            perror(autosave_filename);
+            return EXIT_FAILURE;
+        }
+        autosave();
+    }
+#endif
 #else
     game.novice = yes_or_no(arbitrary_messages[WELCOME_YOU], arbitrary_messages[CAVE_NEARBY], arbitrary_messages[NO_MESSAGE]);
     if (game.novice)
@@ -139,8 +183,8 @@ int main(int argc, char *argv[])
 char *myreadline(const char *prompt)
 {
     /*
-     * This function isbn't required for gameplay, readline() straight
-     * up would suffice for tat.  It's where we interpret command-line
+     * This function isn't required for gameplay, readline() straight
+     * up would suffice for that.  It's where we interpret command-line
      * logfiles for testing purposes.
      */
     /* Normal case - no script arguments */
@@ -656,7 +700,7 @@ static void playermove(int motion)
     /* Look for a way to fulfil the motion verb passed in - travel_entry indexes
      * the beginning of the motion entries for here (game.loc). */
     for (;;) {
-        if (T_TERMINATE(travel[travel_entry]) ||
+        if ((travel[travel_entry].motion == HERE) ||
             travel[travel_entry].motion == motion)
             break;
         if (travel[travel_entry].stop) {
@@ -1048,10 +1092,10 @@ static void listobjects(void)
 static bool preprocess_command(command_t *command)
 /* Pre-processes a command input to see if we need to tease out a few specific cases:
  * - "enter water" or "enter stream":
- *   wierd specific case that gets the user wet, and then kicks us back to get another command
+ *   weird specific case that gets the user wet, and then kicks us back to get another command
  * - <object> <verb>:
  *   Irregular form of input, but should be allowed. We switch back to <verb> <object> form for
- *   furtherprocessing.
+ *   further processing.
  * - "grate":
  *   If in location with grate, we move to that grate. If we're in a number of other places,
  *   we move to the entrance.
@@ -1222,7 +1266,7 @@ static bool do_command()
             if (closecheck() )
                 return true;
 
-            /* loop until all words in command are procesed */
+            /* loop until all words in command are processed */
             while (command.state == PREPROCESSED ) {
                 command.state = PROCESSING;
 
@@ -1313,7 +1357,7 @@ static bool do_command()
                 default: // LCOV_EXCL_LINE
                     BUG(ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH); // LCOV_EXCL_LINE
                 }
-            } /* while command has nob been fully processed */
+            } /* while command has not been fully processed */
         } /* while command is not yet given */
     } /* while command is not executed */