Test message corrected
[open-adventure.git] / main.c
diff --git a/main.c b/main.c
index a0c986a5251749fa31b498d475ca79df5552f3e5..dbdaef9c9d081d900c7f579bab267e38056fee08 100644 (file)
--- a/main.c
+++ b/main.c
@@ -116,6 +116,10 @@ int main(int argc, char *argv[])
     } else {
         restore(rfp);
     }
+#else
+    game.novice = yes(arbitrary_messages[WELCOME_YOU], arbitrary_messages[CAVE_NEARBY], arbitrary_messages[NO_MESSAGE]);
+    if (game.novice)
+        game.limit = NOVICELIMIT;
 #endif
 
     if (settings.logfp)
@@ -178,9 +182,9 @@ static void checkhints(void)
                     game.hintlc[hint] = 0;
                     return;
                 case 3:        /* maze */
-                    if (game.atloc[game.loc] == 0 &&
-                        game.atloc[game.oldloc] == 0 &&
-                        game.atloc[game.oldlc2] == 0 &&
+                    if (game.atloc[game.loc] == NO_OBJECT &&
+                        game.atloc[game.oldloc] == NO_OBJECT &&
+                        game.atloc[game.oldlc2] == NO_OBJECT &&
                         game.holdng > 1)
                         break;
                     game.hintlc[hint] = 0;
@@ -198,9 +202,9 @@ static void checkhints(void)
                     game.hintlc[hint] = 0;
                     return;
                 case 7:        /* woods */
-                    if (game.atloc[game.loc] == 0 &&
-                        game.atloc[game.oldloc] == 0 &&
-                        game.atloc[game.oldlc2] == 0)
+                    if (game.atloc[game.loc] == NO_OBJECT &&
+                        game.atloc[game.oldloc] == NO_OBJECT &&
+                        game.atloc[game.oldlc2] == NO_OBJECT)
                         break;
                     return;
                 case 8:        /* ogre */
@@ -247,7 +251,7 @@ static bool spotted_by_pirate(int i)
      *  it to the troll, but in that case he's seen the chest
      *  (game.prop=0). */
     if (game.loc == game.chloc ||
-        game.prop[CHEST] >= 0)
+        game.prop[CHEST] != STATE_NOTFOUND)
         return true;
     int snarfed = 0;
     bool movechest = false, robplayer = false;
@@ -324,7 +328,7 @@ static bool dwarfmove(void)
      *  means dwarves won't follow him into dead end in maze, but
      *  c'est la vie.  They'll wait for him outside the dead
      *  end. */
-    if (game.loc == 0 ||
+    if (game.loc == LOC_NOWHERE ||
         FORCED(game.loc) ||
         CNDBIT(game.newloc, COND_NOARRR))
         return true;
@@ -380,9 +384,10 @@ static bool dwarfmove(void)
         kk = tkey[game.dloc[i]];
         if (kk != 0)
             do {
-                game.newloc = travel[kk].dest;
+                enum desttype_t desttype = travel[kk].desttype;
+                game.newloc = travel[kk].destval;
                 /* Have we avoided a dwarf encounter? */
-                if (SPECIAL(game.newloc))
+                if (desttype != dest_goto)
                     continue;
                 else if (!INDEEP(game.newloc))
                     continue;
@@ -428,9 +433,7 @@ static bool dwarfmove(void)
         }
     }
 
-    /*  Now we know what's happening.  Let's tell the poor sucker about it.
-     *  Note that various of the "knife" messages must have specific relative
-     *  positions in the rspeak database. */
+    /*  Now we know what's happening.  Let's tell the poor sucker about it. */
     if (game.dtotal == 0)
         return true;
     rspeak(game.dtotal == 1 ? DWARF_SINGLE : DWARF_PACK, game.dtotal);
@@ -496,16 +499,18 @@ static void croak(void)
                 drop(i, (i == LAMP) ? LOC_START : game.oldlc2);
             }
         }
-        game.loc = LOC_BUILDING;
-        game.oldloc = game.loc;
+        game.oldloc = game.loc = game.newloc = LOC_BUILDING;
     }
 }
 
 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);
+    return (travel[a].condtype == travel[b].condtype)
+           && (travel[a].condarg1 == travel[b].condarg1)
+           && (travel[a].condarg2 == travel[b].condarg2)
+           && (travel[a].desttype == travel[b].desttype)
+           && (travel[a].destval == travel[b].destval);
 }
 
 /*  Given the current location in "game.loc", and a motion verb number in
@@ -541,10 +546,11 @@ static void playermove( int motion)
         if (spk == 0) {
             int te_tmp = 0;
             for (;;) {
-                scratchloc = travel[travel_entry].dest;
-                if (scratchloc != motion) {
-                    if (!SPECIAL(scratchloc)) {
-                        if (FORCED(scratchloc) && travel[tkey[scratchloc]].dest == motion)
+                enum desttype_t desttype = travel[travel_entry].desttype;
+                scratchloc = travel[travel_entry].destval;
+                if (desttype != dest_goto || scratchloc != motion) {
+                    if (desttype == dest_goto) {
+                        if (FORCED(scratchloc) && travel[tkey[scratchloc]].destval == motion)
                             te_tmp = travel_entry;
                     }
                     if (!travel[travel_entry].stop) {
@@ -596,25 +602,38 @@ static void playermove( int motion)
         if (travel[travel_entry].stop) {
             /*  Couldn't find an entry matching the motion word passed
              *  in.  Various messages depending on word given. */
-            int spk = CANT_APPLY;
-            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);
+            switch (motion) {
+            case EAST:
+            case WEST:
+            case SOUTH:
+            case NORTH:
+            case NE:
+            case NW:
+            case SW:
+            case SE:
+            case UP:
+            case DOWN:
+                rspeak(BAD_DIRECTION);
+                break;
+            case FORWARD:
+            case LEFT:
+            case RIGHT:
+                rspeak(UNSURE_FACING);
+                break;
+            case OUTSIDE:
+            case INSIDE:
+                rspeak(NO_INOUT_HERE);
+                break;
+            case XYZZY:
+            case PLUGH:
+                rspeak(NOTHING_HAPPENS);
+                break;
+            case CRAWL:
+                rspeak(WHICH_WAY);
+                break;
+            default:
+                rspeak(CANT_APPLY);
+            }
             return;
         }
         ++travel_entry;
@@ -627,22 +646,23 @@ static void playermove( int motion)
     do {
         for (;;) { /* L12 loop */
             for (;;) {
-                long cond = travel[travel_entry].cond;
-                long arg = MOD(cond, 100);
-                if (!SPECIAL(cond)) {
+                enum condtype_t condtype = travel[travel_entry].condtype;
+                long condarg1 = travel[travel_entry].condarg1;
+                long condarg2 = travel[travel_entry].condarg2;
+                if (condtype < cond_not) {
                     /* YAML N and [pct N] conditionals */
-                    if (cond <= 100) {
-                        if (cond == 0 ||
-                            PCT(cond))
+                    if (condtype == cond_goto || condtype == cond_pct) {
+                        if (condarg1 == 0 ||
+                            PCT(condarg1))
                             break;
                         /* else fall through */
                     }
                     /* YAML [with OBJ] clause */
-                    if (TOTING(arg) ||
-                        (cond > 200 && AT(arg)))
+                    else if (TOTING(condarg1) ||
+                             (condtype == cond_with && AT(condarg1)))
                         break;
                     /* else fall through to check [not OBJ STATE] */
-                } else if (game.prop[arg] != cond / 100 - 3)
+                } else if (game.prop[condarg1] != condarg2)
                     break;
 
                 /* We arrive here on conditional failure.
@@ -658,17 +678,17 @@ static void playermove( int motion)
             }
 
             /* Found an eligible rule, now execute it */
-            game.newloc = travel[travel_entry].dest;
-            if (!SPECIAL(game.newloc))
+            enum desttype_t desttype = travel[travel_entry].desttype;
+            game.newloc = travel[travel_entry].destval;
+            if (desttype == dest_goto)
                 return;
 
-            if (game.newloc > 500) {
+            if (desttype == dest_speak) {
                 /* Execute a speak rule */
-                rspeak(L_SPEAK(game.newloc));
+                rspeak(game.newloc);
                 game.newloc = game.loc;
                 return;
             } else {
-                game.newloc -= SPECIALBASE;
                 switch (game.newloc) {
                 case 1:
                     /* Special travel 1.  Plover-alcove passage.  Can carry only
@@ -713,8 +733,8 @@ static void playermove( int motion)
                     if (game.prop[TROLL] == TROLL_PAIDONCE) {
                         pspeak(TROLL, look, TROLL_PAIDONCE, true);
                         game.prop[TROLL] = TROLL_UNPAID;
-                        move(TROLL2, 0);
-                        move(TROLL2 + NOBJECTS, 0);
+                        move(TROLL2, LOC_NOWHERE);
+                        move(TROLL2 + NOBJECTS, IS_FREE);
                         move(TROLL, objects[TROLL].plac);
                         move(TROLL + NOBJECTS, objects[TROLL].fixd);
                         juggle(CHASM);
@@ -787,10 +807,10 @@ static bool closecheck(void)
         game.prop[FISSURE] = UNBRIDGED;
         for (int i = 1; i <= NDWARVES; i++) {
             game.dseen[i] = false;
-            game.dloc[i] = 0;
+            game.dloc[i] = LOC_NOWHERE;
         }
-        move(TROLL, 0);
-        move(TROLL + NOBJECTS, 0);
+        move(TROLL, LOC_NOWHERE);
+        move(TROLL + NOBJECTS, IS_FREE);
         move(TROLL2, objects[TROLL].plac);
         move(TROLL2 + NOBJECTS, objects[TROLL].fixd);
         juggle(CHASM);
@@ -823,10 +843,10 @@ static bool closecheck(void)
          *  could cause trouble, such as the keys).  We describe the
          *  flash of light and trundle back. */
         game.prop[BOTTLE] = put(BOTTLE, LOC_NE, EMPTY_BOTTLE);
-        game.prop[PLANT] = put(PLANT, LOC_NE, 0);
-        game.prop[OYSTER] = put(OYSTER, LOC_NE, 0);
-        game.prop[LAMP] = put(LAMP, LOC_NE, 0);
-        game.prop[ROD] = put(ROD, LOC_NE, 0);
+        game.prop[PLANT] = put(PLANT, LOC_NE, PLANT_THIRSTY);
+        game.prop[OYSTER] = put(OYSTER, LOC_NE, STATE_FOUND);
+        game.prop[LAMP] = put(LAMP, LOC_NE, LAMP_DARK);
+        game.prop[ROD] = put(ROD, LOC_NE, STATE_FOUND);
         game.prop[DWARF] = put(DWARF, LOC_NE, 0);
         game.loc = LOC_NE;
         game.oldloc = LOC_NE;
@@ -836,13 +856,13 @@ static bool closecheck(void)
         put(GRATE, LOC_SW, 0);
         put(SIGN, LOC_SW, 0);
         game.prop[SIGN] = ENDGAME_SIGN;
-        game.prop[SNAKE] = put(SNAKE, LOC_SW, 1);
-        game.prop[BIRD] = put(BIRD, LOC_SW, 1);
-        game.prop[CAGE] = put(CAGE, LOC_SW, 0);
-        game.prop[ROD2] = put(ROD2, LOC_SW, 0);
-        game.prop[PILLOW] = put(PILLOW, LOC_SW, 0);
+        game.prop[SNAKE] = put(SNAKE, LOC_SW, SNAKE_CHASED);
+        game.prop[BIRD] = put(BIRD, LOC_SW, BIRD_CAGED);
+        game.prop[CAGE] = put(CAGE, LOC_SW, STATE_FOUND);
+        game.prop[ROD2] = put(ROD2, LOC_SW, STATE_FOUND);
+        game.prop[PILLOW] = put(PILLOW, LOC_SW, STATE_FOUND);
 
-        game.prop[MIRROR] = put(MIRROR, LOC_NE, 0);
+        game.prop[MIRROR] = put(MIRROR, LOC_NE, STATE_FOUND);
         game.fixed[MIRROR] = LOC_SW;
 
         for (int i = 1; i <= NOBJECTS; i++) {
@@ -870,28 +890,29 @@ static void lampcheck(void)
      *  here, in which case we replace the batteries and continue.
      *  Second is for other cases of lamp dying.  Eve after it goes
      *  out, he can explore outside for a while if desired. */
-    if (game.limit <= WARNTIME && HERE(BATTERY) && game.prop[BATTERY] == FRESH_BATTERIES && HERE(LAMP)) {
-        rspeak(REPLACE_BATTERIES);
-        game.prop[BATTERY] = DEAD_BATTERIES;
-        if (TOTING(BATTERY))
-            drop(BATTERY, game.loc);
-        game.limit += BATTERYLIFE;
-        game.lmwarn = false;
-    } else if (game.limit == 0) {
+    if (game.limit <= WARNTIME) {
+        if (HERE(BATTERY) && game.prop[BATTERY] == FRESH_BATTERIES && HERE(LAMP)) {
+            rspeak(REPLACE_BATTERIES);
+            game.prop[BATTERY] = DEAD_BATTERIES;
+            if (TOTING(BATTERY))
+                drop(BATTERY, game.loc);
+            game.limit += BATTERYLIFE;
+            game.lmwarn = false;
+        } else if (!game.lmwarn && HERE(LAMP)) {
+            game.lmwarn = true;
+            if (game.prop[BATTERY] == DEAD_BATTERIES)
+                rspeak(MISSING_BATTERIES);
+            else if (game.place[BATTERY] == LOC_NOWHERE)
+                rspeak(LAMP_DIM);
+            else
+                rspeak(GET_BATTERIES);
+        }
+    }
+    if (game.limit == 0) {
         game.limit = -1;
         game.prop[LAMP] = LAMP_DARK;
         if (HERE(LAMP))
             rspeak(LAMP_OUT);
-    } else if (game.limit <= WARNTIME) {
-        if (!game.lmwarn && HERE(LAMP)) {
-            game.lmwarn = true;
-            int spk = GET_BATTERIES;
-            if (game.place[BATTERY] == LOC_NOWHERE)
-                spk = LAMP_DIM;
-            if (game.prop[BATTERY] == DEAD_BATTERIES)
-                spk = MISSING_BATTERIES;
-            rspeak(spk);
-        }
     }
 }
 
@@ -1014,9 +1035,7 @@ static bool do_command()
         listobjects();
 
 L2012:
-        command.verb = 0;
         game.oldobj = command.obj;
-        command.obj = 0;
 
 L2600:
         checkhints();
@@ -1047,10 +1066,12 @@ L2600:
                 return (false);
             if (word_count(input) > 2) {
                 rspeak(TWO_WORDS);
+                free(input);
                 continue;
             }
             if (strcmp(input, "") != 0)
                 break;
+            free(input);
         }
 
         strncpy(inputbuf, input, LINESIZE - 1);
@@ -1174,7 +1195,7 @@ Laction:
         case GO_WORD2:
             /* Get second word for analysis. */
             command.wd1 = command.wd2;
-            strcpy(command.raw1, command.raw2);
+            strncpy(command.raw1, command.raw2, LINESIZE - 1);
             wordclear(&command.wd2);
             command.raw2[0] = '\0';
             goto L2620;