X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=actions.c;h=3ef9289474b0671ddb4331dbf34cc7d686c8f6ce;hb=e6f183ba7f4e0d7e12d7cdc848d204e308840f9c;hp=1031d8ef19ef1915a1ef7b828a17e3e83e35cc61;hpb=64897f132e6651a5c52c822ff8452c9f3e9e032b;p=open-adventure.git diff --git a/actions.c b/actions.c index 1031d8e..3ef9289 100644 --- 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); }