WD* globals abolished. They're now members of the command block.

This commit is contained in:
Eric S. Raymond 2017-06-20 20:06:32 -04:00
parent 9714c9fc2a
commit 9437ccca36
4 changed files with 124 additions and 126 deletions

4
TODO
View file

@ -3,10 +3,6 @@
The FORTRANish mess that once was is now mostly idiomatic C. Some issues The FORTRANish mess that once was is now mostly idiomatic C. Some issues
remain to be cleaned up: remain to be cleaned up:
* The remaining shared globals: WD1, WD1X, WD2, WD2X. These are used
rather promiscuously to pass around information that ought to be function
arguments in a modern language.
* Remaining unstructured gotos in do_command(). * Remaining unstructured gotos in do_command().
* The program is still pretty much typeless - full of magic numbers being * The program is still pretty much typeless - full of magic numbers being

203
actions.c
View file

@ -4,17 +4,16 @@
#include "database.h" #include "database.h"
#include "newdb.h" #include "newdb.h"
/* Limit visibility of ugly globals. Eventually these should go away. */
extern token_t WD1, WD1X, WD2, WD2X;
static int fill(token_t, token_t); static int fill(token_t, token_t);
static int attack(FILE *input, token_t verb, token_t obj) static int attack(FILE *input, struct command_t *command)
/* Attack. Assume target if unambiguous. "Throw" also links here. /* Attack. Assume target if unambiguous. "Throw" also links here.
* Attackable objects fall into two categories: enemies (snake, * Attackable objects fall into two categories: enemies (snake,
* dwarf, etc.) and others (bird, clam, machine). Ambiguous if 2 * dwarf, etc.) and others (bird, clam, machine). Ambiguous if 2
* enemies, or no enemies but 2 others. */ * enemies, or no enemies but 2 others. */
{ {
vocab_t verb = command->verb;
vocab_t obj = command->obj;
int spk = ACTSPK[verb]; int spk = ACTSPK[verb];
if (obj == 0 || obj == INTRANSITIVE) { if (obj == 0 || obj == INTRANSITIVE) {
if (ATDWRF(game.loc) > 0) if (ATDWRF(game.loc) > 0)
@ -81,8 +80,8 @@ static int attack(FILE *input, token_t verb, token_t obj)
* fixed), move rug there (not fixed), and move him there, * fixed), move rug there (not fixed), and move him there,
* too. Then do a null motion to get new description. */ * too. Then do a null motion to get new description. */
RSPEAK(BARE_HANDS_QUERY); RSPEAK(BARE_HANDS_QUERY);
GETIN(input, &WD1, &WD1X, &WD2, &WD2X); GETIN(input, &command->wd1, &command->wd1x, &command->wd2, &command->wd2x);
if (WD1 != MAKEWD(WORD_YINIT) && WD1 != MAKEWD(WORD_YES)) if (command->wd1 != MAKEWD(WORD_YINIT) && command->wd1 != MAKEWD(WORD_YES))
return GO_CHECKFOO; return GO_CHECKFOO;
PSPEAK(DRAGON, 3); PSPEAK(DRAGON, 3);
game.prop[DRAGON] = 1; game.prop[DRAGON] = 1;
@ -107,7 +106,7 @@ static int attack(FILE *input, token_t verb, token_t obj)
static int bigwords(token_t foo) static int bigwords(token_t foo)
/* FEE FIE FOE FOO (AND FUM). Advance to next state if given in proper order. /* FEE FIE FOE FOO (AND FUM). Advance to next state if given in proper order.
* Look up WD1 in section 3 of vocab to determine which word we've got. Last * Look up foo in section 3 of vocab to determine which word we've got. Last
* word zips the eggs back to the giant room (unless already there). */ * word zips the eggs back to the giant room (unless already there). */
{ {
int k = VOCAB(foo, 3); int k = VOCAB(foo, 3);
@ -792,32 +791,32 @@ static int quit(void)
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
static int read(token_t verb, token_t obj) static int read(struct command_t *command)
/* Read. Print stuff based on objtxt. Oyster (?) is special case. */ /* Read. Print stuff based on objtxt. Oyster (?) is special case. */
{ {
if (obj == INTRANSITIVE) { if (command->obj == INTRANSITIVE) {
obj = 0; command->obj = 0;
for (int i = 1; i <= NOBJECTS; i++) { for (int i = 1; i <= NOBJECTS; i++) {
if (HERE(i) && OBJTXT[i] != 0 && game.prop[i] >= 0) if (HERE(i) && OBJTXT[i] != 0 && game.prop[i] >= 0)
obj = obj * NOBJECTS + i; command->obj = command->obj * NOBJECTS + i;
} }
if (obj > NOBJECTS || obj == 0 || DARK(game.loc)) return GO_UNKNOWN; if (command->obj > NOBJECTS || command->obj == 0 || DARK(game.loc)) return GO_UNKNOWN;
} }
if (DARK(game.loc)) { if (DARK(game.loc)) {
SETPRM(1, WD1, WD1X); SETPRM(1, command->wd1, command->wd1x);
RSPEAK(NO_SEE); RSPEAK(NO_SEE);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
if (OBJTXT[obj] == 0 || game.prop[obj] < 0) { if (OBJTXT[command->obj] == 0 || game.prop[command->obj] < 0) {
RSPEAK(ACTSPK[verb]); RSPEAK(ACTSPK[command->verb]);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
if (obj == OYSTER && !game.clshnt) { if (command->obj == OYSTER && !game.clshnt) {
game.clshnt = YES(arbitrary_messages[CLUE_QUERY], arbitrary_messages[WAYOUT_CLUE], arbitrary_messages[OK_MAN]); game.clshnt = YES(arbitrary_messages[CLUE_QUERY], arbitrary_messages[WAYOUT_CLUE], arbitrary_messages[OK_MAN]);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
PSPEAK(obj, OBJTXT[obj] + game.prop[obj]); PSPEAK(command->obj, OBJTXT[command->obj] + game.prop[command->obj]);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
@ -859,19 +858,19 @@ static int rub(token_t verb, token_t obj)
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
static int say(void) static int say(struct command_t *command)
/* Say. Echo WD2 (or WD1 if no WD2 (SAY WHAT?, etc.).) Magic words override. */ /* Say. Echo WD2 (or WD1 if no WD2 (SAY WHAT?, etc.).) Magic words override. */
{ {
/* FIXME: ugly use of globals */ /* FIXME: ugly use of globals */
SETPRM(1, WD2, WD2X); SETPRM(1, command->wd2, command->wd2x);
if (WD2 <= 0) if (command->wd2 <= 0)
SETPRM(1, WD1, WD1X); SETPRM(1, command->wd1, command->wd1x);
if (WD2 > 0) if (command->wd2 > 0)
WD1 = WD2; command->wd1 = command->wd2;
int wd = VOCAB(WD1, -1); int wd = VOCAB(command->wd1, -1);
/* FIXME: Magic numbers */ /* FIXME: Magic numbers */
if (wd == 62 || wd == 65 || wd == 71 || wd == 2025 || wd == 2034) { if (wd == 62 || wd == 65 || wd == 71 || wd == 2025 || wd == 2034) {
WD2 = 0; command->wd2 = 0;
return GO_LOOKUP; return GO_LOOKUP;
} }
RSPEAK(OKEY_DOKEY); RSPEAK(OKEY_DOKEY);
@ -885,22 +884,22 @@ static int throw_support(long spk)
return GO_MOVE; return GO_MOVE;
} }
static int throw (FILE *cmdin, long verb, token_t obj) static int throw (FILE *cmdin, struct command_t *command)
/* Throw. Same as discard unless axe. Then same as attack except /* Throw. Same as discard unless axe. Then same as attack except
* ignore bird, and if dwarf is present then one might be killed. * ignore bird, and if dwarf is present then one might be killed.
* (Only way to do so!) Axe also special for dragon, bear, and * (Only way to do so!) Axe also special for dragon, bear, and
* troll. Treasures special for troll. */ * troll. Treasures special for troll. */
{ {
int spk = ACTSPK[verb]; int spk = ACTSPK[command->verb];
if (TOTING(ROD2) && obj == ROD && !TOTING(ROD))obj = ROD2; if (TOTING(ROD2) && command->obj == ROD && !TOTING(ROD))command->obj = ROD2;
if (!TOTING(obj)) { if (!TOTING(command->obj)) {
RSPEAK(spk); RSPEAK(spk);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
if (obj >= MINTRS && obj <= MAXTRS && AT(TROLL)) { if (command->obj >= MINTRS && command->obj <= MAXTRS && AT(TROLL)) {
spk = TROLL_SATISFIED; spk = TROLL_SATISFIED;
/* Snarf a treasure for the troll. */ /* Snarf a treasure for the troll. */
DROP(obj, 0); DROP(command->obj, 0);
MOVE(TROLL, 0); MOVE(TROLL, 0);
MOVE(TROLL + NOBJECTS, 0); MOVE(TROLL + NOBJECTS, 0);
DROP(TROLL2, PLAC[TROLL]); DROP(TROLL2, PLAC[TROLL]);
@ -909,13 +908,13 @@ static int throw (FILE *cmdin, long verb, token_t obj)
RSPEAK(spk); RSPEAK(spk);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
if (obj == FOOD && HERE(BEAR)) { if (command->obj == FOOD && HERE(BEAR)) {
/* But throwing food is another story. */ /* But throwing food is another story. */
obj = BEAR; command->obj = BEAR;
return (feed(verb, obj)); return (feed(command->verb, command->obj));
} }
if (obj != AXE) if (command->obj != AXE)
return (discard(verb, obj, false)); return (discard(command->verb, command->obj, false));
else { else {
int i = ATDWRF(game.loc); int i = ATDWRF(game.loc);
if (i <= 0) { if (i <= 0) {
@ -934,7 +933,8 @@ static int throw (FILE *cmdin, long verb, token_t obj)
RSPEAK(AXE_LOST); RSPEAK(AXE_LOST);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
return (attack(cmdin, verb, 0)); command->obj = 0;
return (attack(cmdin, command));
} }
if (randrange(NDWARVES + 1) < game.dflag) { if (randrange(NDWARVES + 1) < game.dflag) {
@ -995,14 +995,14 @@ static int wave(token_t verb, token_t obj)
} }
} }
int action(FILE *input, struct command_t command) int action(FILE *input, struct command_t *command)
/* Analyse a verb. Remember what it was, go back for object if second word /* Analyse a verb. Remember what it was, go back for object if second word
* unless verb is "say", which snarfs arbitrary second word. * unless verb is "say", which snarfs arbitrary second word.
*/ */
{ {
token_t spk = ACTSPK[command.verb]; token_t spk = ACTSPK[command->verb];
if (command.part == unknown) { if (command->part == unknown) {
/* Analyse an object word. See if the thing is here, whether /* Analyse an object word. See if the thing is here, whether
* we've got a verb yet, and so on. Object must be here * we've got a verb yet, and so on. Object must be here
* unless verb is "find" or "invent(ory)" (and no new verb * unless verb is "find" or "invent(ory)" (and no new verb
@ -1010,74 +1010,74 @@ int action(FILE *input, struct command_t command)
* they are never actually dropped at any location, but might * they are never actually dropped at any location, but might
* be here inside the bottle or urn or as a feature of the * be here inside the bottle or urn or as a feature of the
* location. */ * location. */
if (HERE(command.obj)) if (HERE(command->obj))
/* FALL THROUGH */; /* FALL THROUGH */;
else if (command.obj == GRATE) { else if (command->obj == GRATE) {
if (game.loc == LOC_START || game.loc == LOC_VALLEY || game.loc == LOC_SLIT) if (game.loc == LOC_START || game.loc == LOC_VALLEY || game.loc == LOC_SLIT)
command.obj = DPRSSN; command->obj = DPRSSN;
if (game.loc == LOC_COBBLE || game.loc == LOC_DEBRIS || game.loc == LOC_AWKWARD || if (game.loc == LOC_COBBLE || game.loc == LOC_DEBRIS || game.loc == LOC_AWKWARD ||
game.loc == LOC_BIRD || game.loc == LOC_PITTOP) game.loc == LOC_BIRD || game.loc == LOC_PITTOP)
command.obj = ENTRNC; command->obj = ENTRNC;
if (command.obj != GRATE) if (command->obj != GRATE)
return GO_MOVE; return GO_MOVE;
} else if (command.obj == DWARF && ATDWRF(game.loc) > 0) } else if (command->obj == DWARF && ATDWRF(game.loc) > 0)
/* FALL THROUGH */; /* FALL THROUGH */;
else if ((LIQUID() == command.obj && HERE(BOTTLE)) || command.obj == LIQLOC(game.loc)) else if ((LIQUID() == command->obj && HERE(BOTTLE)) || command->obj == LIQLOC(game.loc))
/* FALL THROUGH */; /* FALL THROUGH */;
else if (command.obj == OIL && HERE(URN) && game.prop[URN] != 0) { else if (command->obj == OIL && HERE(URN) && game.prop[URN] != 0) {
command.obj = URN; command->obj = URN;
/* FALL THROUGH */; /* FALL THROUGH */;
} else if (command.obj == PLANT && AT(PLANT2) && game.prop[PLANT2] != 0) { } else if (command->obj == PLANT && AT(PLANT2) && game.prop[PLANT2] != 0) {
command.obj = PLANT2; command->obj = PLANT2;
/* FALL THROUGH */; /* FALL THROUGH */;
} else if (command.obj == KNIFE && game.knfloc == game.loc) { } else if (command->obj == KNIFE && game.knfloc == game.loc) {
game.knfloc = -1; game.knfloc = -1;
spk = KNIVES_VANISH; spk = KNIVES_VANISH;
RSPEAK(spk); RSPEAK(spk);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} else if (command.obj == ROD && HERE(ROD2)) { } else if (command->obj == ROD && HERE(ROD2)) {
command.obj = ROD2; command->obj = ROD2;
/* FALL THROUGH */; /* FALL THROUGH */;
} else if ((command.verb == FIND || command.verb == INVENT) && WD2 <= 0) } else if ((command->verb == FIND || command->verb == INVENT) && command->wd2 <= 0)
/* FALL THROUGH */; /* FALL THROUGH */;
else { else {
SETPRM(1, WD1, WD1X); SETPRM(1, command->wd1, command->wd1x);
RSPEAK(NO_SEE); RSPEAK(NO_SEE);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
if (WD2 > 0) if (command->wd2 > 0)
return GO_WORD2; return GO_WORD2;
if (command.verb != 0) if (command->verb != 0)
command.part = transitive; command->part = transitive;
} }
switch (command.part) { switch (command->part) {
case intransitive: case intransitive:
if (WD2 > 0 && command.verb != SAY) if (command->wd2 > 0 && command->verb != SAY)
return GO_WORD2; return GO_WORD2;
if (command.verb == SAY)command.obj = WD2; if (command->verb == SAY)command->obj = command->wd2;
if (command.obj == 0 || command.obj == INTRANSITIVE) { if (command->obj == 0 || command->obj == INTRANSITIVE) {
/* Analyse an intransitive verb (ie, no object given yet). */ /* Analyse an intransitive verb (ie, no object given yet). */
switch (command.verb - 1) { switch (command->verb - 1) {
case 0: /* CARRY */ case 0: /* CARRY */
return carry(command.verb, INTRANSITIVE); return carry(command->verb, INTRANSITIVE);
case 1: /* DROP */ case 1: /* DROP */
return GO_UNKNOWN; return GO_UNKNOWN;
case 2: /* SAY */ case 2: /* SAY */
return GO_UNKNOWN; return GO_UNKNOWN;
case 3: /* UNLOC */ case 3: /* UNLOC */
return lock(command.verb, INTRANSITIVE); return lock(command->verb, INTRANSITIVE);
case 4: { /* NOTHI */ case 4: { /* NOTHI */
RSPEAK(OK_MAN); RSPEAK(OK_MAN);
return (GO_CLEAROBJ); return (GO_CLEAROBJ);
} }
case 5: /* LOCK */ case 5: /* LOCK */
return lock(command.verb, INTRANSITIVE); return lock(command->verb, INTRANSITIVE);
case 6: /* LIGHT */ case 6: /* LIGHT */
return light(command.verb, INTRANSITIVE); return light(command->verb, INTRANSITIVE);
case 7: /* EXTIN */ case 7: /* EXTIN */
return extinguish(command.verb, INTRANSITIVE); return extinguish(command->verb, INTRANSITIVE);
case 8: /* WAVE */ case 8: /* WAVE */
return GO_UNKNOWN; return GO_UNKNOWN;
case 9: /* CALM */ case 9: /* CALM */
@ -1087,13 +1087,13 @@ int action(FILE *input, struct command_t command)
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
case 11: /* ATTAC */ case 11: /* ATTAC */
return attack(input, command.verb, command.obj); return attack(input, command);
case 12: /* POUR */ case 12: /* POUR */
return pour(command.verb, command.obj); return pour(command->verb, command->obj);
case 13: /* EAT */ case 13: /* EAT */
return eat(command.verb, INTRANSITIVE); return eat(command->verb, INTRANSITIVE);
case 14: /* DRINK */ case 14: /* DRINK */
return drink(command.verb, command.obj); return drink(command->verb, command->obj);
case 15: /* RUB */ case 15: /* RUB */
return GO_UNKNOWN; return GO_UNKNOWN;
case 16: /* TOSS */ case 16: /* TOSS */
@ -1107,7 +1107,7 @@ int action(FILE *input, struct command_t command)
case 20: /* FEED */ case 20: /* FEED */
return GO_UNKNOWN; return GO_UNKNOWN;
case 21: /* FILL */ case 21: /* FILL */
return fill(command.verb, command.obj); return fill(command->verb, command->obj);
case 22: /* BLAST */ case 22: /* BLAST */
blast(); blast();
return GO_CLEAROBJ; return GO_CLEAROBJ;
@ -1115,11 +1115,12 @@ int action(FILE *input, struct command_t command)
score(scoregame); score(scoregame);
return GO_CLEAROBJ; return GO_CLEAROBJ;
case 24: /* FOO */ case 24: /* FOO */
return bigwords(WD1); return bigwords(command->wd1);
case 25: /* BRIEF */ case 25: /* BRIEF */
return brief(); return brief();
case 26: /* READ */ case 26: /* READ */
return read(command.verb, INTRANSITIVE); command->obj = INTRANSITIVE;
return read(command);
case 27: /* BREAK */ case 27: /* BREAK */
return GO_UNKNOWN; return GO_UNKNOWN;
case 28: /* WAKE */ case 28: /* WAKE */
@ -1129,7 +1130,7 @@ int action(FILE *input, struct command_t command)
case 30: /* RESU */ case 30: /* RESU */
return resume(); return resume();
case 31: /* FLY */ case 31: /* FLY */
return fly(command.verb, INTRANSITIVE); return fly(command->verb, INTRANSITIVE);
case 32: /* LISTE */ case 32: /* LISTE */
return listen(); return listen();
case 33: /* ZZZZ */ case 33: /* ZZZZ */
@ -1140,27 +1141,27 @@ int action(FILE *input, struct command_t command)
/* FALLTHRU */ /* FALLTHRU */
case transitive: case transitive:
/* Analyse a transitive verb. */ /* Analyse a transitive verb. */
switch (command.verb - 1) { switch (command->verb - 1) {
case 0: /* CARRY */ case 0: /* CARRY */
return carry(command.verb, command.obj); return carry(command->verb, command->obj);
case 1: /* DROP */ case 1: /* DROP */
return discard(command.verb, command.obj, false); return discard(command->verb, command->obj, false);
case 2: /* SAY */ case 2: /* SAY */
return say(); return say(command);
case 3: /* UNLOC */ case 3: /* UNLOC */
return lock(command.verb, command.obj); return lock(command->verb, command->obj);
case 4: { /* NOTHI */ case 4: { /* NOTHI */
RSPEAK(OK_MAN); RSPEAK(OK_MAN);
return (GO_CLEAROBJ); return (GO_CLEAROBJ);
} }
case 5: /* LOCK */ case 5: /* LOCK */
return lock(command.verb, command.obj); return lock(command->verb, command->obj);
case 6: /* LIGHT */ case 6: /* LIGHT */
return light(command.verb, command.obj); return light(command->verb, command->obj);
case 7: /* EXTI */ case 7: /* EXTI */
return extinguish(command.verb, command.obj); return extinguish(command->verb, command->obj);
case 8: /* WAVE */ case 8: /* WAVE */
return wave(command.verb, command.obj); return wave(command->verb, command->obj);
case 9: { /* CALM */ case 9: { /* CALM */
RSPEAK(spk); RSPEAK(spk);
return GO_CLEAROBJ; return GO_CLEAROBJ;
@ -1170,29 +1171,29 @@ int action(FILE *input, struct command_t command)
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
case 11: /* ATTAC */ case 11: /* ATTAC */
return attack(input, command.verb, command.obj); return attack(input, command);
case 12: /* POUR */ case 12: /* POUR */
return pour(command.verb, command.obj); return pour(command->verb, command->obj);
case 13: /* EAT */ case 13: /* EAT */
return eat(command.verb, command.obj); return eat(command->verb, command->obj);
case 14: /* DRINK */ case 14: /* DRINK */
return drink(command.verb, command.obj); return drink(command->verb, command->obj);
case 15: /* RUB */ case 15: /* RUB */
return rub(command.verb, command.obj); return rub(command->verb, command->obj);
case 16: /* TOSS */ case 16: /* TOSS */
return throw (input, command.verb, command.obj); return throw(input, command);
case 17: { /* QUIT */ case 17: { /* QUIT */
RSPEAK(spk); RSPEAK(spk);
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
case 18: /* FIND */ case 18: /* FIND */
return find(command.verb, command.obj); return find(command->verb, command->obj);
case 19: /* INVEN */ case 19: /* INVEN */
return find(command.verb, command.obj); return find(command->verb, command->obj);
case 20: /* FEED */ case 20: /* FEED */
return feed(command.verb, command.obj); return feed(command->verb, command->obj);
case 21: /* FILL */ case 21: /* FILL */
return fill(command.verb, command.obj); return fill(command->verb, command->obj);
case 22: /* BLAST */ case 22: /* BLAST */
blast(); blast();
return GO_CLEAROBJ; return GO_CLEAROBJ;
@ -1209,11 +1210,11 @@ int action(FILE *input, struct command_t command)
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
case 26: /* READ */ case 26: /* READ */
return read(command.verb, command.obj); return read(command);
case 27: /* BREAK */ case 27: /* BREAK */
return vbreak(command.verb, command.obj); return vbreak(command->verb, command->obj);
case 28: /* WAKE */ case 28: /* WAKE */
return wake(command.verb, command.obj); return wake(command->verb, command->obj);
case 29: { /* SUSP */ case 29: { /* SUSP */
RSPEAK(spk); RSPEAK(spk);
return GO_CLEAROBJ; return GO_CLEAROBJ;
@ -1223,7 +1224,7 @@ int action(FILE *input, struct command_t command)
return GO_CLEAROBJ; return GO_CLEAROBJ;
} }
case 31: /* FLY */ case 31: /* FLY */
return fly(command.verb, command.obj); return fly(command->verb, command->obj);
case 32: { /* LISTE */ case 32: { /* LISTE */
RSPEAK(spk); RSPEAK(spk);
return GO_CLEAROBJ; return GO_CLEAROBJ;
@ -1234,7 +1235,7 @@ int action(FILE *input, struct command_t command)
BUG(TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST); BUG(TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST);
case unknown: case unknown:
/* Unknown verb, couldn't deduce object - might need hint */ /* Unknown verb, couldn't deduce object - might need hint */
SETPRM(1, WD1, WD1X); SETPRM(1, command->wd1, command->wd1x);
RSPEAK(WHAT_DO); RSPEAK(WHAT_DO);
return GO_CHECKHINT; return GO_CHECKHINT;
default: default:

View file

@ -185,10 +185,12 @@ struct command_t {
enum speechpart part; enum speechpart part;
vocab_t verb; vocab_t verb;
vocab_t obj; vocab_t obj;
token_t wd1, wd1x;
token_t wd2, wd2x;
}; };
void initialise(void); void initialise(void);
int action(FILE *input, struct command_t command); int action(FILE *input, struct command_t *command);
/* Phase codes for action returns. /* Phase codes for action returns.
* These were at one time FORTRAN line numbers. * These were at one time FORTRAN line numbers.

39
main.c
View file

@ -41,7 +41,6 @@ long AMBER, AXE, BACK, BATTERY, BEAR, BIRD, BLOOD,
RUBY, RUG, SAPPH, SAY, SIGN, SNAKE, RUBY, RUG, SAPPH, SAY, SIGN, SNAKE,
STEPS, STREAM, THROW, TRIDENT, TROLL, TROLL2, STEPS, STREAM, THROW, TRIDENT, TROLL, TROLL2,
URN, VASE, VEND, VOLCANO, WATER; URN, VASE, VEND, VOLCANO, WATER;
token_t WD1, WD1X, WD2, WD2X;
FILE *logfp = NULL, *rfp = NULL; FILE *logfp = NULL, *rfp = NULL;
bool oldstyle = false; bool oldstyle = false;
@ -1015,7 +1014,7 @@ L2600:
game.knfloc = 0; game.knfloc = 0;
/* This is where we get a new command from the user */ /* This is where we get a new command from the user */
if (!GETIN(cmdin, &WD1, &WD1X, &WD2, &WD2X)) if (!GETIN(cmdin, &command.wd1, &command.wd1x, &command.wd2, &command.wd2x))
return false; return false;
/* Every input, check "game.foobar" flag. If zero, nothing's /* Every input, check "game.foobar" flag. If zero, nothing's
@ -1036,7 +1035,7 @@ L2607:
} }
} }
if (command.verb == SAY && WD2 > 0) if (command.verb == SAY && command.wd2 > 0)
command.verb = 0; command.verb = 0;
if (command.verb == SAY) { if (command.verb == SAY) {
command.part = transitive; command.part = transitive;
@ -1048,8 +1047,8 @@ L2607:
} else } else
lampcheck(); lampcheck();
V1 = VOCAB(WD1, -1); V1 = VOCAB(command.wd1, -1);
V2 = VOCAB(WD2, -1); V2 = VOCAB(command.wd2, -1);
if (V1 == ENTER && (V2 == STREAM || V2 == 1000 + WATER)) { if (V1 == ENTER && (V2 == STREAM || V2 == 1000 + WATER)) {
if (LIQLOC(game.loc) == WATER) { if (LIQLOC(game.loc) == WATER) {
RSPEAK(FEET_WET); RSPEAK(FEET_WET);
@ -1058,37 +1057,37 @@ L2607:
} }
goto L2012; goto L2012;
} }
if (V1 == ENTER && WD2 > 0) { if (V1 == ENTER && command.wd2 > 0) {
WD1 = WD2; command.wd1 = command.wd2;
WD1X = WD2X; command.wd1x = command.wd2x;
wordclear(&WD2); wordclear(&command.wd2);
} else { } else {
/* FIXME: Magic numbers */ /* FIXME: Magic numbers */
if (!((V1 != 1000 + WATER && V1 != 1000 + OIL) || if (!((V1 != 1000 + WATER && V1 != 1000 + OIL) ||
(V2 != 1000 + PLANT && V2 != 1000 + DOOR))) { (V2 != 1000 + PLANT && V2 != 1000 + DOOR))) {
if (AT(V2 - 1000)) if (AT(V2 - 1000))
WD2 = MAKEWD(WORD_POUR); command.wd2 = MAKEWD(WORD_POUR);
} }
if (V1 == 1000 + CAGE && V2 == 1000 + BIRD && HERE(CAGE) && HERE(BIRD)) if (V1 == 1000 + CAGE && V2 == 1000 + BIRD && HERE(CAGE) && HERE(BIRD))
WD1 = MAKEWD(WORD_CATCH); command.wd1 = MAKEWD(WORD_CATCH);
} }
L2620: L2620:
if (wordeq(WD1, MAKEWD(WORD_WEST))) { if (wordeq(command.wd1, MAKEWD(WORD_WEST))) {
++game.iwest; ++game.iwest;
if (game.iwest == 10) if (game.iwest == 10)
RSPEAK(W_IS_WEST); RSPEAK(W_IS_WEST);
} }
if (wordeq(WD1, MAKEWD(WORD_GO)) && !wordempty(WD2)) { if (wordeq(command.wd1, MAKEWD(WORD_GO)) && !wordempty(command.wd2)) {
if (++igo == 10) if (++igo == 10)
RSPEAK(GO_UNNEEDED); RSPEAK(GO_UNNEEDED);
} }
Lookup: Lookup:
defn = VOCAB(WD1, -1); defn = VOCAB(command.wd1, -1);
if (defn == -1) { if (defn == -1) {
/* Gee, I don't understand. */ /* Gee, I don't understand. */
if (fallback_handler(rawbuf)) if (fallback_handler(rawbuf))
continue; continue;
SETPRM(1, WD1, WD1X); SETPRM(1, command.wd1, command.wd1x);
RSPEAK(DONT_KNOW); RSPEAK(DONT_KNOW);
goto L2600; goto L2600;
} }
@ -1115,7 +1114,7 @@ Lookup:
} }
Laction: Laction:
switch (action(cmdin, command)) { switch (action(cmdin, &command)) {
case GO_TERMINATE: case GO_TERMINATE:
return true; return true;
case GO_MOVE: case GO_MOVE:
@ -1133,14 +1132,14 @@ Laction:
goto Lookup; goto Lookup;
case GO_WORD2: case GO_WORD2:
/* Get second word for analysis. */ /* Get second word for analysis. */
WD1 = WD2; command.wd1 = command.wd2;
WD1X = WD2X; command.wd1x = command.wd2x;
wordclear(&WD2); wordclear(&command.wd2);
goto L2620; goto L2620;
case GO_UNKNOWN: case GO_UNKNOWN:
/* Random intransitive verbs come here. Clear obj just in case /* Random intransitive verbs come here. Clear obj just in case
* (see attack()). */ * (see attack()). */
SETPRM(1, WD1, WD1X); SETPRM(1, command.wd1, command.wd1x);
RSPEAK(DO_WHAT); RSPEAK(DO_WHAT);
command.obj = 0; command.obj = 0;
goto L2600; goto L2600;