centralize calls to make_zzword()
[open-adventure.git] / main.c
diff --git a/main.c b/main.c
index a6027f8136e06637db534a1a3df691a0e8384e3e..1cff0d1648db7fb827b29fb6f3859ada02bcf16e 100644 (file)
--- a/main.c
+++ b/main.c
 #include <stdbool.h>
 #include <getopt.h>
 #include <signal.h>
-#include <time.h>
 #include <string.h>
 #include "advent.h"
-#include "linenoise/linenoise.h"
 #include "dungeon.h"
 
 #define DIM(a) (sizeof(a)/sizeof(a[0]))
 
-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;
-bool editline = true;
 bool prompt = true;
 
 // LCOV_EXCL_START
@@ -68,7 +45,6 @@ static void sig_handler(int signo)
  * MAIN PROGRAM
  *
  *  Adventure (rev 2: 20 treasures)
-Here's what we think. *
  *  History: Original idea & 5-treasure version (adventures) by Willie Crowther
  *           15-treasure version (adventure) by Don Woods, April-June 1977
  *           20-treasure version (rev 2) by Don Woods, August 1978
@@ -85,11 +61,11 @@ int main(int argc, char *argv[])
     /*  Options. */
 
 #ifndef ADVENT_NOSAVE
-    const char* opts = "l:or:s";
-    const char* usage = "Usage: %s [-l logfilename] [-o] [-r restorefilename] [-s] \n";
+    const char* opts = "l:or:";
+    const char* usage = "Usage: %s [-l logfilename] [-o] [-r restorefilename]\n";
 #else
-    const char* opts = "l:os";
-    const char* usage = "Usage: %s [-l logfilename] [-o] [-s] \n";
+    const char* opts = "l:o";
+    const char* usage = "Usage: %s [-l logfilename] [-o]\n";
 #endif
     while ((ch = getopt(argc, argv, opts)) != EOF) {
         switch (ch) {
@@ -103,7 +79,7 @@ int main(int argc, char *argv[])
             break;
         case 'o':
             oldstyle = true;
-            editline = prompt = false;
+            prompt = false;
             break;
 #ifndef ADVENT_NOSAVE
         case 'r':
@@ -115,9 +91,6 @@ int main(int argc, char *argv[])
             signal(SIGINT, sig_handler);
             break;
 #endif
-        case 's':
-            editline = false;
-            break;
         default:
             fprintf(stderr,
                     usage, argv[0]);
@@ -129,32 +102,15 @@ int main(int argc, char *argv[])
             fprintf(stderr,
                     "        -r restore from specified saved game file\n");
 #endif
-            fprintf(stderr,
-                    "        -s suppress command editing\n");
             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);
-    game.newloc = LOC_START;
-    game.loc = LOC_START;
-    game.limit = GAMELIMIT;
+#ifndef ADVENT_NOSAVE
     if (!rfp) {
         game.novice = yes(arbitrary_messages[WELCOME_YOU], arbitrary_messages[CAVE_NEARBY], arbitrary_messages[NO_MESSAGE]);
         if (game.novice)
@@ -162,6 +118,7 @@ int main(int argc, char *argv[])
     } else {
         restore(rfp);
     }
+#endif
 
     if (logfp)
         fprintf(logfp, "seed %ld\n", seedval);
@@ -184,8 +141,6 @@ static bool fallback_handler(char *buf)
         printf("Seed set to %ld\n", sv);
         // autogenerated, so don't charge user time for it.
         --game.turns;
-        // here we reconfigure any global game state that uses random numbers
-        make_zzword(game.zzword);
         return true;
     }
     return false;
@@ -419,23 +374,29 @@ static bool dwarfmove(void)
         kk = tkey[game.dloc[i]];
         if (kk != 0)
             do {
-                game.newloc = T_DESTINATION(travel[kk]);
+                game.newloc = travel[kk].dest;
                 /* Have we avoided a dwarf encounter? */
-                bool avoided = (SPECIAL(game.newloc) ||
-                                !INDEEP(game.newloc) ||
-                                game.newloc == game.odloc[i] ||
-                                (j > 1 && game.newloc == tk[j - 1]) ||
-                                j >= DIM(tk) - 1 ||
-                                game.newloc == game.dloc[i] ||
-                                FORCED(game.newloc) ||
-                                (i == PIRATE && CNDBIT(game.newloc, COND_NOARRR)) ||
-                                T_NODWARVES(travel[kk]));
-                if (!avoided) {
-                    tk[j++] = game.newloc;
-                }
-                ++kk;
+                if (SPECIAL(game.newloc))
+                   continue;
+                else if (!INDEEP(game.newloc))
+                   continue;
+               else if (game.newloc == game.odloc[i])
+                   continue;
+                else if (j > 1 && game.newloc == tk[j - 1])
+                   continue;
+               else if (j >= DIM(tk) - 1)
+                   continue;
+               else if (game.newloc == game.dloc[i])
+                   continue;
+               else if (FORCED(game.newloc))
+                   continue;
+               else if (i == PIRATE && CNDBIT(game.newloc, COND_NOARRR))
+                   continue;
+               else if (travel[kk].nodwarves)
+                   continue;
+               tk[j++] = game.newloc;
             } while
-            (!travel[kk - 1].stop);
+               (!travel[kk++].stop);
         tk[j] = game.odloc[i];
         if (j >= 2)
             --j;
@@ -531,6 +492,13 @@ static void croak(void)
     }
 }
 
+static bool traveleq(long a, long b)
+/* Are two travel entries equal for purposes of skip after failed condition? */
+{
+    return (travel[a].cond == travel[b].cond)
+       && (travel[a].dest == travel[b].dest);
+}
+
 /*  Given the current location in "game.loc", and a motion verb number in
  *  "motion", put the new location in "game.newloc".  The current loc is saved
  *  in "game.oldloc" in case he wants to retreat.  The current
@@ -564,10 +532,10 @@ static bool playermove( int motion)
         if (spk == 0) {
             int te_tmp = 0;
             for (;;) {
-                scratchloc = T_DESTINATION(travel[travel_entry]);
+                scratchloc = travel[travel_entry].dest;
                 if (scratchloc != motion) {
                     if (!SPECIAL(scratchloc)) {
-                        if (FORCED(scratchloc) && T_DESTINATION(travel[tkey[scratchloc]]) == motion)
+                        if (FORCED(scratchloc) && travel[tkey[scratchloc]].dest == motion)
                             te_tmp = travel_entry;
                     }
                     if (!travel[travel_entry].stop) {
@@ -644,7 +612,7 @@ static bool playermove( int motion)
     do {
         for (;;) { /* L12 loop */
             for (;;) {
-                long cond = T_CONDITION(travel[travel_entry]);
+                long cond = travel[travel_entry].cond;
                 long arg = MOD(cond, 100);
                 if (!SPECIAL(cond)) {
                     /* YAML N and [pct N] conditionals */
@@ -668,12 +636,12 @@ static bool playermove( int motion)
                         BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION); // LCOV_EXCL_LINE
                     ++te_tmp;
                 } while
-                (T_HIGH(travel[travel_entry]) == T_HIGH(travel[te_tmp]));
+                   (traveleq(travel_entry, te_tmp));
                 travel_entry = te_tmp;
             }
 
             /* Found an eligible rule, now execute it */
-            game.newloc = T_DESTINATION(travel[travel_entry]);
+            game.newloc = travel[travel_entry].dest;
             if (!SPECIAL(game.newloc))
                 return true;
 
@@ -710,7 +678,7 @@ static bool playermove( int motion)
                             BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION); // LCOV_EXCL_LINE
                         ++te_tmp;
                     } while
-                    (T_HIGH(travel[travel_entry]) == T_HIGH(travel[te_tmp]));
+                       (traveleq(travel_entry, te_tmp));
                     travel_entry = te_tmp;
                     continue; /* goto L12 */
                 case 3:
@@ -725,7 +693,7 @@ static bool playermove( int motion)
                      * stuff for bear. */
                     if (game.prop[TROLL] == TROLL_PAIDONCE) {
                         pspeak(TROLL, look, TROLL_PAIDONCE);
-                        game.prop[TROLL] = 0;
+                        game.prop[TROLL] = TROLL_UNPAID;
                         move(TROLL2, 0);
                         move(TROLL2 + NOBJECTS, 0);
                         move(TROLL, objects[TROLL].plac);
@@ -809,8 +777,8 @@ static bool closecheck(void)
         juggle(CHASM);
         if (game.prop[BEAR] != BEAR_DEAD)
             DESTROY(BEAR);
-        game.prop[CHAIN] = 0;
-        game.fixed[CHAIN] = 0;
+        game.prop[CHAIN] = CHAIN_HEAP;
+        game.fixed[CHAIN] = CHAIN_HEAP;
         game.prop[AXE] = 0;
         game.fixed[AXE] = 0;
         rspeak(CAVE_CLOSING);
@@ -912,8 +880,8 @@ static void listobjects(void)
 /*  Print out descriptions of objects at this location.  If
  *  not closing and property value is negative, tally off
  *  another treasure.  Rug is special case; once seen, its
- *  game.prop is 1 (dragon on it) till dragon is killed.
- *  Similarly for chain; game.prop is initially 1 (locked to
+ *  game.prop is RUG_DRAGON (dragon on it) till dragon is killed.
+ *  Similarly for chain; game.prop is initially CHAINING_BEAR (locked to
  *  bear).  These hacks are because game.prop=0 is needed to
  *  get full score. */
 {
@@ -929,8 +897,10 @@ static void listobjects(void)
                 if (game.closed)
                     continue;
                 game.prop[obj] = 0;
-                if (obj == RUG || obj == CHAIN)
-                    game.prop[obj] = 1;
+                if (obj == RUG)
+                    game.prop[RUG] = RUG_DRAGON;
+                if (obj == CHAIN)
+                    game.prop[CHAIN] = CHAINING_BEAR;
                 --game.tally;
                 /*  Note: There used to be a test here to see whether the
                  *  player had blown it so badly that he could never ever see
@@ -1066,7 +1036,7 @@ L2600:
         }
 
         strncpy(inputbuf, input, LINESIZE - 1);
-        linenoiseFree(input);
+        free(input);
 
         long tokens[4];
         tokenize(inputbuf, tokens);
@@ -1123,12 +1093,12 @@ L2607:
             wordclear(&command.wd2);
         } else {
             /* FIXME: Magic numbers related to vocabulary */
-            if (!((V1 != 1000 + WATER && V1 != 1000 + OIL) ||
-                  (V2 != 1000 + PLANT && V2 != 1000 + DOOR))) {
-                if (AT(V2 - 1000))
+            if (!((V1 != PROMOTE_WORD(WATER) && V1 != PROMOTE_WORD(OIL)) ||
+                  (V2 != PROMOTE_WORD(PLANT) && V2 != PROMOTE_WORD(DOOR)))) {
+                if (AT(DEMOTE_WORD(V2)))
                     command.wd2 = token_to_packed("POUR");
             }
-            if (V1 == 1000 + CAGE && V2 == 1000 + BIRD && HERE(CAGE) && HERE(BIRD))
+            if (V1 == PROMOTE_WORD(CAGE) && V2 == PROMOTE_WORD(BIRD) && HERE(CAGE) && HERE(BIRD))
                 command.wd1 = token_to_packed("CATCH");
         }
 L2620:
@@ -1168,7 +1138,7 @@ Lookup:
             command.verb = kmod;
             break;
         case 3:
-            rspeak(specials[kmod].message);
+            speak(specials[kmod].message);
             goto L2012;
         default:
             BUG(VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3); // LCOV_EXCL_LINE