Jettison MAKEWD(), GETTXT(), vocab(), GETIN(), and the old db compiler.
[open-adventure.git] / main.c
diff --git a/main.c b/main.c
index 3f4140971fcc09d5d4134f28c7d0682e592b71bf..c5dc311d0e7cf7a6b4e32107ec482a3d57afdc4e 100644 (file)
--- a/main.c
+++ b/main.c
@@ -20,8 +20,8 @@
 #include <getopt.h>
 #include <signal.h>
 #include <time.h>
+#include <string.h>
 #include "advent.h"
-#include "database.h"
 #include "linenoise/linenoise.h"
 #include "newdb.h"
 
@@ -61,7 +61,7 @@ static void sig_handler(int signo)
  *          Revived 2017 as Open Adventure.
  */
 
-static bool do_command(FILE *);
+static bool do_command(void);
 
 int main(int argc, char *argv[])
 {
@@ -136,7 +136,7 @@ int main(int argc, char *argv[])
     initialise();
 
     /*  Start-up, dwarf stuff */
-    game.zzword = rndvoc(3, 0);
+    make_zzword(game.zzword);
     game.newloc = LOC_START;
     game.loc = LOC_START;
     game.limit = GAMELIMIT;
@@ -153,7 +153,7 @@ int main(int argc, char *argv[])
 
     /* interpret commands until EOF or interrupt */
     for (;;) {
-        if (!do_command(stdin))
+        if (!do_command())
             break;
     }
     /* show score and exit */
@@ -170,7 +170,7 @@ static bool fallback_handler(char *buf)
         // autogenerated, so don't charge user time for it.
         --game.turns;
         // here we reconfigure any global game state that uses random numbers
-        game.zzword = rndvoc(3, 0);
+       make_zzword(game.zzword);
         return true;
     }
     return false;
@@ -613,42 +613,39 @@ 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. */
-    scratchloc = T_HIGH(travel[kk]);
-
     do {
-        /*
-         * (ESR) This conditional-skip loop may have to be repeated if
-         * it includes the plover passage.  Same deal for any future
-         * cases where we need to block travel and then redo it once
-         * the blocking condition has been removed.
-         */
         for (;;) { /* L12 loop */
             for (;;) {
-                game.newloc = scratchloc / 1000;
-                motion = MOD(game.newloc, 100);
-                if (!SPECIAL(game.newloc)) {
-                    if (game.newloc <= 100) {
-                        if (game.newloc == 0 || PCT(game.newloc))
+                long cond = T_CONDITION(travel[kk]);
+                long arg = MOD(cond, 100);
+                if (!SPECIAL(cond)) {
+                   /* YAML N and [pct N] conditionals */
+                    if (cond <= 100) {
+                        if (cond == 0 || PCT(cond))
                             break;
                         /* else fall through */
                     }
-                   /* handles the YAML "with" clause */
-                    if (TOTING(motion) || (game.newloc > 200 && AT(motion)))
+                   /* YAML [with OBJ] clause */
+                    if (TOTING(arg) || (cond > 200 && AT(arg)))
                         break;
-                    /* else fall through */
-                } else if (game.prop[motion] != game.newloc / 100 - 3)
+                    /* else fall through to check [not OBJ STATE] */
+                } else if (game.prop[arg] != cond / 100 - 3)
                     break;
-                do {
-                    if (travel[kk].stop)
+
+               /* We arrive here on conditional failure.
+                * Skip to next non-matching destination */
+               long k2 = kk;
+               do {
+                    if (travel[k2].stop)
                         BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION); // LCOV_EXCL_LINE
-                    ++kk;
-                    game.newloc = T_HIGH(travel[kk]);
+                    ++k2;
                 } while
-                (game.newloc == scratchloc);
-                scratchloc = game.newloc;
+                   (T_HIGH(travel[kk]) == T_HIGH(travel[k2]));
+               kk = k2;
             }
 
-            game.newloc = MOD(scratchloc, 1000);
+           /* Found an eligible rule, now execute it */
+            game.newloc = T_DESTINATION(travel[kk]);
             if (!SPECIAL(game.newloc))
                 return true;
 
@@ -679,14 +676,14 @@ static bool playermove(token_t verb, int motion)
                      * to get it out.  Having dropped it, go back and
                      * pretend he wasn't carrying it after all. */
                     drop(EMERALD, game.loc);
+                   k2 = kk;
                     do {
-                        if (travel[kk].stop)
+                        if (travel[k2].stop)
                             BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION); // LCOV_EXCL_LINE
-                        ++kk;
-                        game.newloc = T_HIGH(travel[kk]);
+                        ++k2;
                     } while
-                    (game.newloc == scratchloc);
-                    scratchloc = game.newloc;
+                       (T_HIGH(travel[kk]) == T_HIGH(travel[k2]));
+                    kk = k2;
                     continue; /* goto L12 */
                 case 3:
                     /* Travel 303.  Troll bridge.  Must be done only
@@ -717,7 +714,7 @@ static bool playermove(token_t verb, int motion)
                         game.prop[TROLL] = 2;
                         drop(BEAR, game.newloc);
                         game.fixed[BEAR] = -1;
-                        game.prop[BEAR] = 3;
+                        game.prop[BEAR] = BEAR_DEAD;
                         game.oldlc2 = game.newloc;
                         croak();
                         return true;
@@ -780,7 +777,8 @@ static bool closecheck(void)
         move(TROLL2, objects[TROLL].plac);
         move(TROLL2 + NOBJECTS, objects[TROLL].fixd);
         juggle(CHASM);
-        if (game.prop[BEAR] != 3)DESTROY(BEAR);
+        if (game.prop[BEAR] != BEAR_DEAD)
+           DESTROY(BEAR);
         game.prop[CHAIN] = 0;
         game.fixed[CHAIN] = 0;
         game.prop[AXE] = 0;
@@ -925,7 +923,7 @@ static void listobjects(void)
     }
 }
 
-static bool do_command(FILE *cmdin)
+static bool do_command()
 /* Get and execute a command */
 {
     long V1, V2;
@@ -1018,8 +1016,25 @@ L2600:
             game.knfloc = 0;
 
         /* This is where we get a new command from the user */
-        if (!GETIN(cmdin, &command.wd1, &command.wd1x, &command.wd2, &command.wd2x))
-            return false;
+       char* input;
+       for (;;) {
+         input = get_input();
+         if (input == NULL)
+           return(false);
+         if (word_count(input) > 2)
+         {
+           rspeak(TWO_WORDS);
+           continue;
+         }
+         if (strcmp(input, "") != 0)
+           break;
+       }
+       long tokens[4];
+       tokenize(input, tokens);
+       command.wd1 = tokens[0];
+        command.wd1x = tokens[1];
+        command.wd2 = tokens[2];
+        command.wd2x = tokens[3];
 
         /*  Every input, check "game.foobar" flag.  If zero, nothing's
          *  going on.  If pos, make neg.  If neg, he skipped a word,
@@ -1051,8 +1066,12 @@ L2607:
         } else
             lampcheck();
 
-        V1 = vocab(command.wd1, -1);
-        V2 = vocab(command.wd2, -1);
+       char word1[6];
+       char word2[6];
+       packed_to_token(command.wd1, word1);
+       packed_to_token(command.wd2, word2);
+       V1 = get_vocab_id(word1);
+       V2 = get_vocab_id(word2);
         if (V1 == ENTER && (V2 == STREAM || V2 == 1000 + WATER)) {
             if (LIQLOC(game.loc) == WATER) {
                 rspeak(FEET_WET);
@@ -1070,26 +1089,27 @@ L2607:
             if (!((V1 != 1000 + WATER && V1 != 1000 + OIL) ||
                   (V2 != 1000 + PLANT && V2 != 1000 + DOOR))) {
                 if (AT(V2 - 1000))
-                    command.wd2 = MAKEWD(WORD_POUR);
+                   command.wd2 = token_to_packed("POUR");
             }
             if (V1 == 1000 + CAGE && V2 == 1000 + BIRD && HERE(CAGE) && HERE(BIRD))
-                command.wd1 = MAKEWD(WORD_CATCH);
+               command.wd1 = token_to_packed("CATCH");
         }
 L2620:
-        if (wordeq(command.wd1, MAKEWD(WORD_WEST))) {
+        if (wordeq(command.wd1, token_to_packed("WEST"))) {
             ++game.iwest;
             if (game.iwest == 10)
                 rspeak(W_IS_WEST);
         }
-        if (wordeq(command.wd1, MAKEWD(WORD_GO)) && !wordempty(command.wd2)) {
+        if (wordeq(command.wd1, token_to_packed("GO")) && !wordempty(command.wd2)) {
             if (++igo == 10)
                 rspeak(GO_UNNEEDED);
         }
 Lookup:
-        defn = vocab(command.wd1, -1);
+       packed_to_token(command.wd1, word1);
+       defn = get_vocab_id(word1);
         if (defn == -1) {
             /* Gee, I don't understand. */
-            if (fallback_handler(rawbuf))
+            if (fallback_handler(input))
                 continue;
             rspeak(DONT_KNOW, command.wd1, command.wd1x);
             goto L2600;
@@ -1110,14 +1130,14 @@ Lookup:
             command.verb = kmod;
             break;
         case 3:
-            rspeak(kmod);
+            rspeak(specials[kmod].message);
             goto L2012;
         default:
             BUG(VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3); // LCOV_EXCL_LINE
         }
 
 Laction:
-        switch (action(cmdin, &command)) {
+        switch (action(&command)) {
         case GO_TERMINATE:
             return true;
         case GO_MOVE:
@@ -1152,6 +1172,7 @@ Laction:
         default:
             BUG(ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH); // LCOV_EXCL_LINE
         }
+       linenoiseFree(input);
     }
 }