Move PRNG initialization to simplify cheat.c
[open-adventure.git] / main.c
diff --git a/main.c b/main.c
index 6ad7c3669289b77ced08c8efae7f07e41c676071..077e3a996d200dde709fda3215035b194f5c9c99 100644 (file)
--- a/main.c
+++ b/main.c
  * and for the offensive globals.  Applying the Structured Program
  * Theorem can be hard.
  */
-#define DEFINE_GLOBALS_FROM_INCLUDES
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <getopt.h>
 #include <signal.h>
-#include <time.h>
 #include <string.h>
 #include "advent.h"
 #include "linenoise/linenoise.h"
 
 #define DIM(a) (sizeof(a)/sizeof(a[0]))
 
-struct game_t game;
-
-long LNLENG, LNPOSN;
-char rawbuf[LINESIZE], INLINE[LINESIZE + 1];
+struct game_t game = {
+    .dloc[1] = LOC_KINGHALL,
+    .dloc[2] = LOC_WESTBANK,
+    .dloc[3] = LOC_Y2,
+    .dloc[4] = LOC_ALIKE3,
+    .dloc[5] = LOC_COMPLEX,
+
+    /*  Sixth dwarf is special (the pirate).  He always starts at his
+     *  chest's eventual location inside the maze. This loc is saved
+     *  in chloc for ref. The dead end in the other maze has its
+     *  loc stored in chloc2. */
+    .dloc[6] = LOC_DEADEND12,
+    .chloc   = LOC_DEADEND12,
+    .chloc2  = LOC_DEADEND13,
+    .abbnum  = 5,
+    .clock1  = WARNTIME,
+    .clock2  = FLASHTIME,
+    .blklin  = true
+};
 
 FILE  *logfp = NULL, *rfp = NULL;
 bool oldstyle = false;
@@ -45,7 +59,7 @@ static void sig_handler(int signo)
         if (logfp != NULL)
             fflush(logfp);
     }
-    exit(0);
+    exit(EXIT_FAILURE);
 }
 // LCOV_EXCL_STOP
 
@@ -116,24 +130,15 @@ int main(int argc, char *argv[])
 #endif
             fprintf(stderr,
                     "        -s suppress command editing\n");
-            exit(-1);
+            exit(EXIT_FAILURE);
             break;
         }
     }
 
     linenoiseHistorySetMaxLen(350);
 
-    /* Initialize our LCG PRNG with parameters tested against
-     * Knuth vol. 2. by the original authors */
-    game.lcg_a = 1093;
-    game.lcg_c = 221587;
-    game.lcg_m = 1048576;
-    srand(time(NULL));
-    long seedval = (long)rand();
-    set_seed(seedval);
-
     /*  Initialize game variables */
-    initialise();
+    long seedval = initialise();
 
     /*  Start-up, dwarf stuff */
     make_zzword(game.zzword);
@@ -374,9 +379,12 @@ static bool dwarfmove(void)
             if (PCT(50))
                 game.dloc[j] = 0;
         }
+
+        /* Alternate initial loc for dwarf, in case one of them
+        *  starts out on top of the adventurer. */
         for (int i = 1; i <= NDWARVES - 1; i++) {
             if (game.dloc[i] == game.loc)
-                game.dloc[i] = DALTLC;
+                game.dloc[i] = DALTLC; //
             game.odloc[i] = game.dloc[i];
         }
         rspeak(DWARF_RAN);
@@ -425,7 +433,8 @@ static bool dwarfmove(void)
         game.odloc[i] = game.dloc[i];
         game.dloc[i] = tk[j];
         game.dseen[i] = (game.dseen[i] && INDEEP(game.loc)) || (game.dloc[i] == game.loc || game.odloc[i] == game.loc);
-        if (!game.dseen[i]) continue;
+        if (!game.dseen[i])
+            continue;
         game.dloc[i] = game.loc;
         if (spotted_by_pirate(i))
             continue;
@@ -448,7 +457,8 @@ static bool dwarfmove(void)
     rspeak(game.dtotal == 1 ? DWARF_SINGLE : DWARF_PACK, game.dtotal);
     if (attack == 0)
         return true;
-    if (game.dflag == 2)game.dflag = 3;
+    if (game.dflag == 2)
+        game.dflag = 3;
     if (attack > 1) {
         rspeak(THROWN_KNIVES, attack);
         rspeak(stick > 1 ? MULTIPLE_HITS : (stick == 1 ? ONE_HIT : NONE_HIT), stick);
@@ -519,7 +529,7 @@ static void croak(void)
  *  him, so we need game.oldlc2, which is the last place he was
  *  safe.) */
 
-static bool playermove(token_t verb, int motion)
+static bool playermove( int motion)
 {
     int scratchloc, travel_entry = tkey[game.loc];
     game.newloc = game.loc;
@@ -596,17 +606,21 @@ static bool playermove(token_t verb, int motion)
         if (T_TERMINATE(travel[travel_entry]) || travel[travel_entry].motion == motion)
             break;
         if (travel[travel_entry].stop) {
-            /* FIXME: Magic numbers! */
             /*  Couldn't find an entry matching the motion word passed
              *  in.  Various messages depending on word given. */
             int spk = CANT_APPLY;
-            if (motion >= 43 && motion <= 50)spk = BAD_DIRECTION;
-            if (motion == 29 || motion == 30)spk = BAD_DIRECTION;
-            if (motion == 7 || motion == 36 || motion == 37)spk = UNSURE_FACING;
-            if (motion == 11 || motion == 19)spk = NO_INOUT_HERE;
-            if (verb == FIND || verb == INVENTORY)spk = NEARBY;
-            if (motion == 62 || motion == 65)spk = NOTHING_HAPPENS;
-            if (motion == 17)spk = WHICH_WAY;
+            if (motion >= EAST && motion <= NW)
+                spk = BAD_DIRECTION;
+            if (motion == UP || motion == DOWN)
+                spk = BAD_DIRECTION;
+            if (motion == FORWARD || motion == LEFT || motion == RIGHT)
+                spk = UNSURE_FACING;
+            if (motion == OUTSIDE || motion == INSIDE)
+                spk = NO_INOUT_HERE;
+            if (motion == XYZZY || motion == PLUGH)
+                spk = NOTHING_HAPPENS;
+            if (motion == CRAWL)
+                spk = WHICH_WAY;
             rspeak(spk);
             return true;
         }
@@ -616,6 +630,7 @@ static bool playermove(token_t verb, int motion)
     /* (ESR) We've found a destination that goes with the motion verb.
      * Next we need to check any conditional(s) on this destination, and
      * possibly on following entries. */
+    /* FIXME: Magic numbers related to move opcodes */
     do {
         for (;;) { /* L12 loop */
             for (;;) {
@@ -698,8 +713,8 @@ static bool playermove(token_t verb, int motion)
                      * so step out and block him.  (standard travel
                      * entries check for game.prop(TROLL)=0.)  Special
                      * stuff for bear. */
-                    if (game.prop[TROLL] == 1) {
-                        pspeak(TROLL, look, 1);
+                    if (game.prop[TROLL] == TROLL_PAIDONCE) {
+                        pspeak(TROLL, look, TROLL_PAIDONCE);
                         game.prop[TROLL] = 0;
                         move(TROLL2, 0);
                         move(TROLL2 + NOBJECTS, 0);
@@ -710,11 +725,13 @@ static bool playermove(token_t verb, int motion)
                         return true;
                     } else {
                         game.newloc = objects[TROLL].plac + objects[TROLL].fixd - game.loc;
-                        if (game.prop[TROLL] == 0)game.prop[TROLL] = 1;
-                        if (!TOTING(BEAR)) return true;
+                        if (game.prop[TROLL] == TROLL_UNPAID)
+                            game.prop[TROLL] = TROLL_PAIDONCE;
+                        if (!TOTING(BEAR))
+                            return true;
                         rspeak(BRIDGE_COLLAPSE);
-                        game.prop[CHASM] = 1;
-                        game.prop[TROLL] = 2;
+                        game.prop[CHASM] = BRIDGE_WRECKED;
+                        game.prop[TROLL] = TROLL_GONE;
                         drop(BEAR, game.newloc);
                         game.fixed[BEAR] = -1;
                         game.prop[BEAR] = BEAR_DEAD;
@@ -770,7 +787,7 @@ static bool closecheck(void)
      *  have been activated, since we've found chest. */
     if (game.clock1 == 0) {
         game.prop[GRATE] = GRATE_CLOSED;
-        game.prop[FISSURE] = 0;
+        game.prop[FISSURE] = UNBRIDGED;
         for (int i = 1; i <= NDWARVES; i++) {
             game.dseen[i] = false;
             game.dloc[i] = 0;
@@ -872,7 +889,8 @@ static void lampcheck(void)
         if (!game.lmwarn && HERE(LAMP)) {
             game.lmwarn = true;
             int spk = GET_BATTERIES;
-            if (game.place[BATTERY] == LOC_NOWHERE)spk = LAMP_DIM;
+            if (game.place[BATTERY] == LOC_NOWHERE)
+                spk = LAMP_DIM;
             if (game.prop[BATTERY] == DEAD_BATTERIES)
                 spk = MISSING_BATTERIES;
             rspeak(spk);
@@ -893,7 +911,8 @@ static void listobjects(void)
         ++game.abbrev[game.loc];
         for (int i = game.atloc[game.loc]; i != 0; i = game.link[i]) {
             long obj = i;
-            if (obj > NOBJECTS)obj = obj - NOBJECTS;
+            if (obj > NOBJECTS)
+                obj = obj - NOBJECTS;
             if (obj == STEPS && TOTING(NUGGET))
                 continue;
             if (game.prop[obj] < 0) {
@@ -939,7 +958,8 @@ static bool do_command()
     if (OUTSID(game.newloc) && game.newloc != 0 && game.closng) {
         rspeak(EXIT_CLOSED);
         game.newloc = game.loc;
-        if (!game.panic)game.clock2 = PANICTIME;
+        if (!game.panic)
+            game.clock2 = PANICTIME;
         game.panic = true;
     }
 
@@ -980,10 +1000,11 @@ static bool do_command()
             }
             msg = arbitrary_messages[PITCH_DARK];
         }
-        if (TOTING(BEAR))rspeak(TAME_BEAR);
+        if (TOTING(BEAR))
+            rspeak(TAME_BEAR);
         speak(msg);
         if (FORCED(game.loc)) {
-            if (playermove(command.verb, 1))
+            if (playermove(HERE))
                 return true;
             else
                 continue;      /* back to top of main interpreter loop */
@@ -1020,6 +1041,8 @@ L2600:
 
         /* This is where we get a new command from the user */
         char* input;
+        char inputbuf[LINESIZE];
+
         for (;;) {
             input = get_input();
             if (input == NULL)
@@ -1031,8 +1054,12 @@ L2600:
             if (strcmp(input, "") != 0)
                 break;
         }
+
+        strncpy(inputbuf, input, LINESIZE - 1);
+        linenoiseFree(input);
+
         long tokens[4];
-        tokenize(input, tokens);
+        tokenize(inputbuf, tokens);
         command.wd1 = tokens[0];
         command.wd1x = tokens[1];
         command.wd2 = tokens[2];
@@ -1085,7 +1112,7 @@ L2607:
             command.wd1x = command.wd2x;
             wordclear(&command.wd2);
         } else {
-            /* FIXME: Magic numbers */
+            /* FIXME: Magic numbers related to vocabulary */
             if (!((V1 != 1000 + WATER && V1 != 1000 + OIL) ||
                   (V2 != 1000 + PLANT && V2 != 1000 + DOOR))) {
                 if (AT(V2 - 1000))
@@ -1109,15 +1136,16 @@ Lookup:
         defn = get_vocab_id(word1);
         if (defn == -1) {
             /* Gee, I don't understand. */
-            if (fallback_handler(input))
+            if (fallback_handler(inputbuf))
                 continue;
             rspeak(DONT_KNOW, command.wd1, command.wd1x);
             goto L2600;
         }
+        /* FIXME: magic numbers related to vocabulary */
         kmod = MOD(defn, 1000);
         switch (defn / 1000) {
         case 0:
-            if (playermove(command.verb, kmod))
+            if (playermove(kmod))
                 return true;
             else
                 continue;      /* back to top of main interpreter loop */
@@ -1141,7 +1169,7 @@ Laction:
         case GO_TERMINATE:
             return true;
         case GO_MOVE:
-            playermove(command.verb, NUL);
+            playermove(NUL);
             return true;
         case GO_TOP:
             continue;  /* back to top of main interpreter loop */
@@ -1172,7 +1200,6 @@ Laction:
         default:
             BUG(ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH); // LCOV_EXCL_LINE
         }
-        linenoiseFree(input);
     }
 }