Use C idioms for increment/decrement.
[open-adventure.git] / actions.c
index 1031d8ef19ef1915a1ef7b828a17e3e83e35cc61..3ef9289474b0671ddb4331dbf34cc7d686c8f6ce 100644 (file)
--- a/actions.c
+++ b/actions.c
@@ -3,8 +3,6 @@
 #include "advent.h"
 #include "database.h"
 
-#define VRSION 25      /* bump on save format change */
-
 /*
  * Action handlers.  Eventually we'll do lookup through a method table
  * that calls these.  Absolutely nothing like the original FORTRAN.
@@ -754,7 +752,7 @@ static int rub(token_t obj)
     DSTROY(URN);
     DROP(AMBER,game.loc);
     game.prop[AMBER]=1;
-    game.tally=game.tally-1;
+    --game.tally;
     DROP(CAVITY,game.loc);
     SPK=216;
     return(2011);
@@ -776,88 +774,6 @@ static int say(void)
 
 }
 
-static int suspendresume(FILE *input, bool resume)
-/* Suspend and resume */
-{
-    int kk;
-    long i;
-    if (!resume) {
-       /*  Suspend.  Offer to save things in a file, but charging
-        *  some points (so can't win by using saved games to retry
-        *  battles or to start over after learning zzword). */
-       SPK=201;
-       RSPEAK(260);
-       if (!YES(input,200,54,54)) return(2012);
-       game.saved=game.saved+5;
-       kk= -1;
-    }
-    else
-    {
-       /*  Resume.  Read a suspended game back from a file. */
-       kk=1;
-       if (game.loc != 1 || game.abbrev[1] != 1) {
-           RSPEAK(268);
-           if (!YES(input,200,54,54)) return(2012);
-       }
-    }
-
-    /*  Suspend vs resume cases are distinguished by the value of kk
-     *  (-1 for suspend, +1 for resume). */
-
-    /* 
-     * FIXME: This is way more complicated than it needs to be in C.
-     * What we ought to do is define a save-block structure that
-     * includes a game state block and then use a single fread/fwrite
-     * for I/O. All the SAV* functions can be scrapped.
-     */
-
-    DATIME(&i,&K);
-    K=i+650*K;
-    SAVWRD(kk,K);
-    K=VRSION;
-    SAVWRD(0,K);
-    if (K != VRSION) {
-       SETPRM(1,K/10,MOD(K,10));
-       SETPRM(3,VRSION/10,MOD(VRSION,10));
-       RSPEAK(269);
-       return(2000);
-    }
-    /* Herewith are all the variables whose values can change during a game,
-     * omitting a few (such as I, J) whose values between turns are
-     * irrelevant and some whose values when a game is
-     * suspended or resumed are guaranteed to match.  If unsure whether a value
-     * needs to be saved, include it.  Overkill can't hurt.  Pad the last savwds
-     * with junk variables to bring it up to 7 values. */
-    SAVWDS(game.abbnum,game.blklin,game.bonus,game.clock1,game.clock2,game.closed,game.closng);
-    SAVWDS(game.detail,game.dflag,game.dkill,game.dtotal,game.foobar,game.holdng,game.iwest);
-    SAVWDS(game.knfloc,game.limit,K,game.lmwarn,game.loc,game.newloc,game.numdie);
-    SAVWDS(K,game.oldlc2,game.oldloc,game.oldobj,game.panic,game.saved,game.setup);
-    SAVWDS(SPK,game.tally,game.thresh,game.trndex,game.trnluz,game.turns,OBJTXT[OYSTER]);
-    SAVWDS(K,WD1,WD1X,WD2,game.wzdark,game.zzword,OBJSND[BIRD]);
-    SAVWDS(OBJTXT[SIGN],game.clshnt,game.novice,K,K,K,K);
-    SAVARR(game.abbrev,LOCSIZ);
-    SAVARR(game.atloc,LOCSIZ);
-    SAVARR(game.dloc,NDWARVES);
-    SAVARR(game.dseen,NDWARVES);
-    SAVARR(game.fixed,NOBJECTS);
-    SAVARR(game.hinted,HNTSIZ);
-    SAVARR(game.hintlc,HNTSIZ);
-    SAVARR(game.link,NOBJECTS*2);
-    SAVARR(game.odloc,NDWARVES);
-    SAVARR(game.place,NOBJECTS);
-    SAVARR(game.prop,NOBJECTS);
-    SAVWRD(kk,K);
-    if (K != 0) {
-       RSPEAK(270);
-       exit(0);
-    }
-    K=NUL;
-    game.zzword=RNDVOC(3,game.zzword);
-    if (kk > 0) return(8);
-    RSPEAK(266);
-    exit(0);
-}
-
 static int throw_support(long spk)
 {
     RSPEAK(spk);
@@ -926,7 +842,7 @@ static int throw(FILE *cmdin, long verb, long obj)
     game.dseen[i]=false;
     game.dloc[i]=0;
     SPK=47;
-    game.dkill=game.dkill+1;
+    ++game.dkill;
     if (game.dkill == 1)SPK=149;
 
     return throw_support(SPK);
@@ -959,7 +875,7 @@ static int wave(token_t obj)
     if (SPK == 206 && game.loc == game.place[STEPS] && game.prop[JADE] < 0) {
        DROP(JADE,game.loc);
        game.prop[JADE]=0;
-       game.tally=game.tally-1;
+       --game.tally;
        SPK=208;
        return(2011);
     } else {
@@ -977,161 +893,156 @@ static int wave(token_t obj)
  * "goto".
  */
 
-int action(FILE *input, long STARTAT, long verb, long obj)
+int action(FILE *input, enum speechpart part, long verb, long obj)
 /*  Analyse a verb.  Remember what it was, go back for object if second word
  *  unless verb is "say", which snarfs arbitrary second word.
  */
 {
     int kk;
-    switch(STARTAT) {
-    case 4000: goto L4000;
-    case 4090: goto L4090;
-    case 5000: goto L5000;
-    }
-    BUG(99);
-
-L4000: 
-    SPK=ACTSPK[verb];
-    if (WD2 > 0 && verb != SAY) return(2800);
-    if (verb == SAY)obj=WD2;
-    if (obj > 0) goto L4090;
-
-/*  Analyse an intransitive verb (ie, no object given yet). */
-
-    switch (verb-1) {
-    case  0: /* CARRY */ return carry(INTRANSITIVE);
-    case  1: /* DROP  */ return(8000); 
-    case  2: /* SAY   */ return(8000); 
-    case  3: /* UNLOC */ return lock(verb, INTRANSITIVE);    
-    case  4: /* NOTHI */ return(2009); 
-    case  5: /* LOCK  */ return lock(verb, INTRANSITIVE);    
-    case  6: /* LIGHT */ return light(INTRANSITIVE);    
-    case  7: /* EXTIN */ return extinguish(INTRANSITIVE);    
-    case  8: /* WAVE  */ return(8000); 
-    case  9: /* CALM  */ return(8000); 
-    case 10: /* WALK  */ return(2011); 
-    case 11: /* ATTAC */ return attack(input, verb, obj);   
-    case 12: /* POUR  */ return pour(obj);   
-    case 13: /* EAT   */ return eat(INTRANSITIVE);   
-    case 14: /* DRINK */ return drink(obj);   
-    case 15: /* RUB   */ return(8000); 
-    case 16: /* TOSS  */ return(8000); 
-    case 17: /* QUIT  */ return quit(input);   
-    case 18: /* FIND  */ return(8000); 
-    case 19: /* INVEN */ return inven(obj);   
-    case 20: /* FEED  */ return(8000); 
-    case 21: /* FILL  */ return fill(obj);   
-    case 22: /* BLAST */ return blast();   
-    case 23: /* SCOR  */ return vscore();   
-    case 24: /* FOO   */ return bigwords(WD1);   
-    case 25: /* BRIEF */ return brief();   
-    case 26: /* READ  */ return read(input, INTRANSITIVE);   
-    case 27: /* BREAK */ return(8000); 
-    case 28: /* WAKE  */ return(8000); 
-    case 29: /* SUSP  */ return suspendresume(input, false);   
-    case 30: /* RESU  */ return suspendresume(input, true);   
-    case 31: /* FLY   */ return fly(INTRANSITIVE);   
-    case 32: /* LISTE */ return listen();   
-    case 33: /* ZZZZ  */ return reservoir();   
-    }
-    BUG(23);
-
-/*  Analyse a transitive verb. */
-
-L4090: switch (verb-1) {
-    case  0: /* CARRY */ return carry(obj);    
-    case  1: /* DROP  */ return discard(obj, false);    
-    case  2: /* SAY   */ return say();    
-    case  3: /* UNLOC */ return lock(verb, obj);    
-    case  4: /* NOTHI */ return(2009); 
-    case  5: /* LOCK  */ return lock(verb, obj);    
-    case  6: /* LIGHT */ return light(obj);    
-    case  7: /* EXTI  */ return extinguish(obj);    
-    case  8: /* WAVE  */ return wave(obj);    
-    case  9: /* CALM  */ return(2011); 
-    case 10: /* WALK  */ return(2011); 
-    case 11: /* ATTAC */ return attack(input, verb, obj);   
-    case 12: /* POUR  */ return pour(obj);   
-    case 13: /* EAT   */ return eat(obj);   
-    case 14: /* DRINK */ return drink(obj);   
-    case 15: /* RUB   */ return rub(obj);   
-    case 16: /* TOSS  */ return throw(input, verb, obj);   
-    case 17: /* QUIT  */ return(2011); 
-    case 18: /* FIND  */ return find(obj);   
-    case 19: /* INVEN */ return find(obj);   
-    case 20: /* FEED  */ return feed(obj);   
-    case 21: /* FILL  */ return fill(obj);   
-    case 22: /* BLAST */ return blast();   
-    case 23: /* SCOR  */ return(2011); 
-    case 24: /* FOO   */ return(2011); 
-    case 25: /* BRIEF */ return(2011); 
-    case 26: /* READ  */ return read(input, obj);   
-    case 27: /* BREAK */ return vbreak(obj);   
-    case 28: /* WAKE  */ return wake(obj);   
-    case 29: /* SUSP  */ return(2011); 
-    case 30: /* RESU  */ return(2011); 
-    case 31: /* FLY   */ return fly(obj);   
-    case 32: /* LISTE */ return(2011); 
-    case 33: /* ZZZZ  */ return reservoir();   
-    }
-    BUG(24);
-
-/*  Analyse an object word.  See if the thing is here, whether we've got a verb
- *  yet, and so on.  Object must be here unless verb is "find" or "invent(ory)"
- *  (and no new verb yet to be analysed).  Water and oil are also funny, since
- *  they are never actually dropped at any location, but might be here inside
- *  the bottle or urn or as a feature of the location. */
-
-L5000:
-    if (!HERE(obj))
-       goto L5100;
-L5010:
-    if (WD2 > 0)
-       return(2800);
-    if (verb != 0)
-       goto L4090;
-    SETPRM(1,WD1,WD1X);
-    RSPEAK(255);
-    return(2600);
+    switch(part)
+    {
+       case intransitive:
+           SPK=ACTSPK[verb];
+           if (WD2 > 0 && verb != SAY) return(2800);
+           if (verb == SAY)obj=WD2;
+           if (obj == 0) {
+               /*  Analyse an intransitive verb (ie, no object given yet). */
+               switch (verb-1) {
+                   case  0: /* CARRY */ return carry(INTRANSITIVE);
+                   case  1: /* DROP  */ return(8000); 
+                   case  2: /* SAY   */ return(8000); 
+                   case  3: /* UNLOC */ return lock(verb, INTRANSITIVE);    
+                   case  4: /* NOTHI */ return(2009); 
+                   case  5: /* LOCK  */ return lock(verb, INTRANSITIVE);    
+                   case  6: /* LIGHT */ return light(INTRANSITIVE);    
+                   case  7: /* EXTIN */ return extinguish(INTRANSITIVE);    
+                   case  8: /* WAVE  */ return(8000); 
+                   case  9: /* CALM  */ return(8000); 
+                   case 10: /* WALK  */ return(2011); 
+                   case 11: /* ATTAC */ return attack(input, verb, obj);   
+                   case 12: /* POUR  */ return pour(obj);   
+                   case 13: /* EAT   */ return eat(INTRANSITIVE);   
+                   case 14: /* DRINK */ return drink(obj);   
+                   case 15: /* RUB   */ return(8000); 
+                   case 16: /* TOSS  */ return(8000); 
+                   case 17: /* QUIT  */ return quit(input);   
+                   case 18: /* FIND  */ return(8000); 
+                   case 19: /* INVEN */ return inven(obj);   
+                   case 20: /* FEED  */ return(8000); 
+                   case 21: /* FILL  */ return fill(obj);   
+                   case 22: /* BLAST */ return blast();   
+                   case 23: /* SCOR  */ return vscore();   
+                   case 24: /* FOO   */ return bigwords(WD1);   
+                   case 25: /* BRIEF */ return brief();   
+                   case 26: /* READ  */ return read(input, INTRANSITIVE);   
+                   case 27: /* BREAK */ return(8000); 
+                   case 28: /* WAKE  */ return(8000); 
+                   case 29: /* SUSP  */ return saveresume(input, false);   
+                   case 30: /* RESU  */ return saveresume(input, true);   
+                   case 31: /* FLY   */ return fly(INTRANSITIVE);   
+                   case 32: /* LISTE */ return listen();   
+                   case 33: /* ZZZZ  */ return reservoir();   
+               }
+               BUG(23);
+           }
+           /* FALLTHRU */
+       case transitive:
+       L4090:
+           /*  Analyse a transitive verb. */
+           switch (verb-1) {
+               case  0: /* CARRY */ return carry(obj);    
+               case  1: /* DROP  */ return discard(obj, false);    
+               case  2: /* SAY   */ return say();    
+               case  3: /* UNLOC */ return lock(verb, obj);    
+               case  4: /* NOTHI */ return(2009); 
+               case  5: /* LOCK  */ return lock(verb, obj);    
+               case  6: /* LIGHT */ return light(obj);    
+               case  7: /* EXTI  */ return extinguish(obj);    
+               case  8: /* WAVE  */ return wave(obj);    
+               case  9: /* CALM  */ return(2011); 
+               case 10: /* WALK  */ return(2011); 
+               case 11: /* ATTAC */ return attack(input, verb, obj);   
+               case 12: /* POUR  */ return pour(obj);   
+               case 13: /* EAT   */ return eat(obj);   
+               case 14: /* DRINK */ return drink(obj);   
+               case 15: /* RUB   */ return rub(obj);   
+               case 16: /* TOSS  */ return throw(input, verb, obj);   
+               case 17: /* QUIT  */ return(2011); 
+               case 18: /* FIND  */ return find(obj);   
+               case 19: /* INVEN */ return find(obj);   
+               case 20: /* FEED  */ return feed(obj);   
+               case 21: /* FILL  */ return fill(obj);   
+               case 22: /* BLAST */ return blast();   
+               case 23: /* SCOR  */ return(2011); 
+               case 24: /* FOO   */ return(2011); 
+               case 25: /* BRIEF */ return(2011); 
+               case 26: /* READ  */ return read(input, obj);   
+               case 27: /* BREAK */ return vbreak(obj);   
+               case 28: /* WAKE  */ return wake(obj);   
+               case 29: /* SUSP  */ return(2011); 
+               case 30: /* RESU  */ return(2011); 
+               case 31: /* FLY   */ return fly(obj);   
+               case 32: /* LISTE */ return(2011); 
+               case 33: /* ZZZZ  */ return reservoir();   
+           }
+           BUG(24);
+       case unknown:
+           /*  Analyse an object word.  See if the thing is here, whether
+            *  we've got a verb yet, and so on.  Object must be here
+            *  unless verb is "find" or "invent(ory)" (and no new verb
+            *  yet to be analysed).  Water and oil are also funny, since
+            *  they are never actually dropped at any location, but might
+            *  be here inside the bottle or urn or as a feature of the
+            *  location. */
+           if (!HERE(obj))
+               goto L5100;
+       L5010:
+           if (WD2 > 0)
+               return(2800);
+           if (verb != 0)
+               goto L4090;
+           SETPRM(1,WD1,WD1X);
+           RSPEAK(255);
+           return(2600);
+
+       L5100:
+           if (obj == GRATE) {
+               if (game.loc == 1 || game.loc == 4 || game.loc == 7)
+                   obj=DPRSSN;
+               if (game.loc > 9 && game.loc < 15)
+                   obj=ENTRNC;
+               if (obj != GRATE)
+                   return(8);
+           }
 
-L5100:
-    if (obj == GRATE) {
-       if (game.loc == 1 || game.loc == 4 || game.loc == 7)
-           obj=DPRSSN;
-       if (game.loc > 9 && game.loc < 15)
-           obj=ENTRNC;
-       if (obj != GRATE)
-           return(8);
+           if (obj == DWARF && ATDWRF(game.loc) > 0)
+               goto L5010;
+           if ((LIQ(0) == obj && HERE(BOTTLE)) || obj == LIQLOC(game.loc))
+               goto L5010;
+           if (obj == OIL && HERE(URN) && game.prop[URN] != 0) {
+               obj=URN;
+               goto L5010;
+           }
+           if (obj == PLANT && AT(PLANT2) && game.prop[PLANT2] != 0) {
+               obj=PLANT2;
+               goto L5010;
+           }
+           if (obj == KNIFE && game.knfloc == game.loc) {
+               game.knfloc= -1;
+               SPK=116;
+               return(2011);
+           }
+           if (obj == ROD && HERE(ROD2)) {
+               obj=ROD2;
+               goto L5010;
+           }
+           if ((verb == FIND || verb == INVENT) && WD2 <= 0)
+               goto L5010;
+
+           SETPRM(1,WD1,WD1X);
+           RSPEAK(256);
+           return(2012);
+       default:
+           BUG(99);
     }
-
-    if (obj == DWARF && ATDWRF(game.loc) > 0)
-       goto L5010;
-    if ((LIQ(0) == obj && HERE(BOTTLE)) || obj == LIQLOC(game.loc))
-       goto L5010;
-    if (obj != OIL || !HERE(URN) || game.prop[URN] == 0)
-       goto L5120;
-    obj=URN;
-    goto L5010;
-L5120:
-    if (obj != PLANT || !AT(PLANT2) || game.prop[PLANT2] == 0)
-       goto L5130;
-    obj=PLANT2;
-    goto L5010;
-L5130:
-    if (obj != KNIFE || game.knfloc != game.loc)
-       goto L5140;
-    game.knfloc= -1;
-    SPK=116;
-    return(2011);
-L5140:
-    if (obj != ROD || !HERE(ROD2))
-       goto L5190;
-    obj=ROD2;
-    goto L5010;
-L5190:
-    if ((verb == FIND || verb == INVENT) && WD2 <= 0)
-       goto L5010;
-    SETPRM(1,WD1,WD1X);
-    RSPEAK(256);
-    return(2012);
 }