#include "database.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 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.
* Attackable objects fall into two categories: enemies (snake,
* dwarf, etc.) and others (bird, clam, machine). Ambiguous if 2
* enemies, or no enemies but 2 others. */
{
+ vocab_t verb = command->verb;
+ vocab_t obj = command->obj;
int spk = ACTSPK[verb];
if (obj == 0 || obj == INTRANSITIVE) {
if (ATDWRF(game.loc) > 0)
* fixed), move rug there (not fixed), and move him there,
* too. Then do a null motion to get new description. */
RSPEAK(BARE_HANDS_QUERY);
- GETIN(input, &WD1, &WD1X, &WD2, &WD2X);
- if (WD1 != MAKEWD(WORD_YINIT) && WD1 != MAKEWD(WORD_YES))
+ GETIN(input, &command->wd1, &command->wd1x, &command->wd2, &command->wd2x);
+ if (command->wd1 != MAKEWD(WORD_YINIT) && command->wd1 != MAKEWD(WORD_YES))
return GO_CHECKFOO;
PSPEAK(DRAGON, 3);
game.prop[DRAGON] = 1;
static int bigwords(token_t foo)
/* 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). */
{
int k = VOCAB(foo, 3);
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. */
{
- if (obj == INTRANSITIVE) {
- obj = 0;
+ if (command->obj == INTRANSITIVE) {
+ command->obj = 0;
for (int i = 1; i <= NOBJECTS; i++) {
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)) {
- SETPRM(1, WD1, WD1X);
+ SETPRM(1, command->wd1, command->wd1x);
RSPEAK(NO_SEE);
return GO_CLEAROBJ;
}
- if (OBJTXT[obj] == 0 || game.prop[obj] < 0) {
- RSPEAK(ACTSPK[verb]);
+ if (OBJTXT[command->obj] == 0 || game.prop[command->obj] < 0) {
+ RSPEAK(ACTSPK[command->verb]);
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]);
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;
}
-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. */
{
/* FIXME: ugly use of globals */
- SETPRM(1, WD2, WD2X);
- if (WD2 <= 0)
- SETPRM(1, WD1, WD1X);
- if (WD2 > 0)
- WD1 = WD2;
- int wd = VOCAB(WD1, -1);
+ SETPRM(1, command->wd2, command->wd2x);
+ if (command->wd2 <= 0)
+ SETPRM(1, command->wd1, command->wd1x);
+ if (command->wd2 > 0)
+ command->wd1 = command->wd2;
+ int wd = VOCAB(command->wd1, -1);
/* FIXME: Magic numbers */
if (wd == 62 || wd == 65 || wd == 71 || wd == 2025 || wd == 2034) {
- WD2 = 0;
+ command->wd2 = 0;
return GO_LOOKUP;
}
RSPEAK(OKEY_DOKEY);
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
* ignore bird, and if dwarf is present then one might be killed.
* (Only way to do so!) Axe also special for dragon, bear, and
* troll. Treasures special for troll. */
{
- int spk = ACTSPK[verb];
- if (TOTING(ROD2) && obj == ROD && !TOTING(ROD))obj = ROD2;
- if (!TOTING(obj)) {
+ int spk = ACTSPK[command->verb];
+ if (TOTING(ROD2) && command->obj == ROD && !TOTING(ROD))command->obj = ROD2;
+ if (!TOTING(command->obj)) {
RSPEAK(spk);
return GO_CLEAROBJ;
}
- if (obj >= MINTRS && obj <= MAXTRS && AT(TROLL)) {
+ if (command->obj >= MINTRS && command->obj <= MAXTRS && AT(TROLL)) {
spk = TROLL_SATISFIED;
/* Snarf a treasure for the troll. */
- DROP(obj, 0);
+ DROP(command->obj, 0);
MOVE(TROLL, 0);
MOVE(TROLL + NOBJECTS, 0);
DROP(TROLL2, PLAC[TROLL]);
RSPEAK(spk);
return GO_CLEAROBJ;
}
- if (obj == FOOD && HERE(BEAR)) {
+ if (command->obj == FOOD && HERE(BEAR)) {
/* But throwing food is another story. */
- obj = BEAR;
- return (feed(verb, obj));
+ command->obj = BEAR;
+ return (feed(command->verb, command->obj));
}
- if (obj != AXE)
- return (discard(verb, obj, false));
+ if (command->obj != AXE)
+ return (discard(command->verb, command->obj, false));
else {
int i = ATDWRF(game.loc);
if (i <= 0) {
RSPEAK(AXE_LOST);
return GO_CLEAROBJ;
}
- return (attack(cmdin, verb, 0));
+ command->obj = 0;
+ return (attack(cmdin, command));
}
if (randrange(NDWARVES + 1) < game.dflag) {
}
}
-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
* 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
* we've got a verb yet, and so on. Object must be here
* unless verb is "find" or "invent(ory)" (and no new verb
* 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(command.obj))
+ if (HERE(command->obj))
/* 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)
- command.obj = DPRSSN;
+ command->obj = DPRSSN;
if (game.loc == LOC_COBBLE || game.loc == LOC_DEBRIS || game.loc == LOC_AWKWARD ||
game.loc == LOC_BIRD || game.loc == LOC_PITTOP)
- command.obj = ENTRNC;
- if (command.obj != GRATE)
+ command->obj = ENTRNC;
+ if (command->obj != GRATE)
return GO_MOVE;
- } else if (command.obj == DWARF && ATDWRF(game.loc) > 0)
+ } else if (command->obj == DWARF && ATDWRF(game.loc) > 0)
/* 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 */;
- else if (command.obj == OIL && HERE(URN) && game.prop[URN] != 0) {
- command.obj = URN;
+ else if (command->obj == OIL && HERE(URN) && game.prop[URN] != 0) {
+ command->obj = URN;
/* FALL THROUGH */;
- } else if (command.obj == PLANT && AT(PLANT2) && game.prop[PLANT2] != 0) {
- command.obj = PLANT2;
+ } else if (command->obj == PLANT && AT(PLANT2) && game.prop[PLANT2] != 0) {
+ command->obj = PLANT2;
/* FALL THROUGH */;
- } else if (command.obj == KNIFE && game.knfloc == game.loc) {
+ } else if (command->obj == KNIFE && game.knfloc == game.loc) {
game.knfloc = -1;
spk = KNIVES_VANISH;
RSPEAK(spk);
return GO_CLEAROBJ;
- } else if (command.obj == ROD && HERE(ROD2)) {
- command.obj = ROD2;
+ } else if (command->obj == ROD && HERE(ROD2)) {
+ command->obj = ROD2;
/* 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 */;
else {
- SETPRM(1, WD1, WD1X);
+ SETPRM(1, command->wd1, command->wd1x);
RSPEAK(NO_SEE);
return GO_CLEAROBJ;
}
- if (WD2 > 0)
+ if (command->wd2 > 0)
return GO_WORD2;
- if (command.verb != 0)
- command.part = transitive;
+ if (command->verb != 0)
+ command->part = transitive;
}
- switch (command.part) {
+ switch (command->part) {
case intransitive:
- if (WD2 > 0 && command.verb != SAY)
+ if (command->wd2 > 0 && command->verb != SAY)
return GO_WORD2;
- if (command.verb == SAY)command.obj = WD2;
- if (command.obj == 0 || command.obj == INTRANSITIVE) {
+ if (command->verb == SAY)command->obj = command->wd2;
+ if (command->obj == 0 || command->obj == INTRANSITIVE) {
/* Analyse an intransitive verb (ie, no object given yet). */
- switch (command.verb - 1) {
+ switch (command->verb - 1) {
case 0: /* CARRY */
- return carry(command.verb, INTRANSITIVE);
+ return carry(command->verb, INTRANSITIVE);
case 1: /* DROP */
return GO_UNKNOWN;
case 2: /* SAY */
return GO_UNKNOWN;
case 3: /* UNLOC */
- return lock(command.verb, INTRANSITIVE);
+ return lock(command->verb, INTRANSITIVE);
case 4: { /* NOTHI */
RSPEAK(OK_MAN);
return (GO_CLEAROBJ);
}
case 5: /* LOCK */
- return lock(command.verb, INTRANSITIVE);
+ return lock(command->verb, INTRANSITIVE);
case 6: /* LIGHT */
- return light(command.verb, INTRANSITIVE);
+ return light(command->verb, INTRANSITIVE);
case 7: /* EXTIN */
- return extinguish(command.verb, INTRANSITIVE);
+ return extinguish(command->verb, INTRANSITIVE);
case 8: /* WAVE */
return GO_UNKNOWN;
case 9: /* CALM */
return GO_CLEAROBJ;
}
case 11: /* ATTAC */
- return attack(input, command.verb, command.obj);
+ return attack(input, command);
case 12: /* POUR */
- return pour(command.verb, command.obj);
+ return pour(command->verb, command->obj);
case 13: /* EAT */
- return eat(command.verb, INTRANSITIVE);
+ return eat(command->verb, INTRANSITIVE);
case 14: /* DRINK */
- return drink(command.verb, command.obj);
+ return drink(command->verb, command->obj);
case 15: /* RUB */
return GO_UNKNOWN;
case 16: /* TOSS */
case 20: /* FEED */
return GO_UNKNOWN;
case 21: /* FILL */
- return fill(command.verb, command.obj);
+ return fill(command->verb, command->obj);
case 22: /* BLAST */
blast();
return GO_CLEAROBJ;
score(scoregame);
return GO_CLEAROBJ;
case 24: /* FOO */
- return bigwords(WD1);
+ return bigwords(command->wd1);
case 25: /* BRIEF */
return brief();
case 26: /* READ */
- return read(command.verb, INTRANSITIVE);
+ command->obj = INTRANSITIVE;
+ return read(command);
case 27: /* BREAK */
return GO_UNKNOWN;
case 28: /* WAKE */
case 30: /* RESU */
return resume();
case 31: /* FLY */
- return fly(command.verb, INTRANSITIVE);
+ return fly(command->verb, INTRANSITIVE);
case 32: /* LISTE */
return listen();
case 33: /* ZZZZ */
/* FALLTHRU */
case transitive:
/* Analyse a transitive verb. */
- switch (command.verb - 1) {
+ switch (command->verb - 1) {
case 0: /* CARRY */
- return carry(command.verb, command.obj);
+ return carry(command->verb, command->obj);
case 1: /* DROP */
- return discard(command.verb, command.obj, false);
+ return discard(command->verb, command->obj, false);
case 2: /* SAY */
- return say();
+ return say(command);
case 3: /* UNLOC */
- return lock(command.verb, command.obj);
+ return lock(command->verb, command->obj);
case 4: { /* NOTHI */
RSPEAK(OK_MAN);
return (GO_CLEAROBJ);
}
case 5: /* LOCK */
- return lock(command.verb, command.obj);
+ return lock(command->verb, command->obj);
case 6: /* LIGHT */
- return light(command.verb, command.obj);
+ return light(command->verb, command->obj);
case 7: /* EXTI */
- return extinguish(command.verb, command.obj);
+ return extinguish(command->verb, command->obj);
case 8: /* WAVE */
- return wave(command.verb, command.obj);
+ return wave(command->verb, command->obj);
case 9: { /* CALM */
RSPEAK(spk);
return GO_CLEAROBJ;
return GO_CLEAROBJ;
}
case 11: /* ATTAC */
- return attack(input, command.verb, command.obj);
+ return attack(input, command);
case 12: /* POUR */
- return pour(command.verb, command.obj);
+ return pour(command->verb, command->obj);
case 13: /* EAT */
- return eat(command.verb, command.obj);
+ return eat(command->verb, command->obj);
case 14: /* DRINK */
- return drink(command.verb, command.obj);
+ return drink(command->verb, command->obj);
case 15: /* RUB */
- return rub(command.verb, command.obj);
+ return rub(command->verb, command->obj);
case 16: /* TOSS */
- return throw (input, command.verb, command.obj);
+ return throw(input, command);
case 17: { /* QUIT */
RSPEAK(spk);
return GO_CLEAROBJ;
}
case 18: /* FIND */
- return find(command.verb, command.obj);
+ return find(command->verb, command->obj);
case 19: /* INVEN */
- return find(command.verb, command.obj);
+ return find(command->verb, command->obj);
case 20: /* FEED */
- return feed(command.verb, command.obj);
+ return feed(command->verb, command->obj);
case 21: /* FILL */
- return fill(command.verb, command.obj);
+ return fill(command->verb, command->obj);
case 22: /* BLAST */
blast();
return GO_CLEAROBJ;
return GO_CLEAROBJ;
}
case 26: /* READ */
- return read(command.verb, command.obj);
+ return read(command);
case 27: /* BREAK */
- return vbreak(command.verb, command.obj);
+ return vbreak(command->verb, command->obj);
case 28: /* WAKE */
- return wake(command.verb, command.obj);
+ return wake(command->verb, command->obj);
case 29: { /* SUSP */
RSPEAK(spk);
return GO_CLEAROBJ;
return GO_CLEAROBJ;
}
case 31: /* FLY */
- return fly(command.verb, command.obj);
+ return fly(command->verb, command->obj);
case 32: { /* LISTE */
RSPEAK(spk);
return GO_CLEAROBJ;
BUG(TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST);
case unknown:
/* Unknown verb, couldn't deduce object - might need hint */
- SETPRM(1, WD1, WD1X);
+ SETPRM(1, command->wd1, command->wd1x);
RSPEAK(WHAT_DO);
return GO_CHECKHINT;
default:
RUBY, RUG, SAPPH, SAY, SIGN, SNAKE,
STEPS, STREAM, THROW, TRIDENT, TROLL, TROLL2,
URN, VASE, VEND, VOLCANO, WATER;
-token_t WD1, WD1X, WD2, WD2X;
FILE *logfp = NULL, *rfp = NULL;
bool oldstyle = false;
game.knfloc = 0;
/* 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;
/* Every input, check "game.foobar" flag. If zero, nothing's
}
}
- if (command.verb == SAY && WD2 > 0)
+ if (command.verb == SAY && command.wd2 > 0)
command.verb = 0;
if (command.verb == SAY) {
command.part = transitive;
} else
lampcheck();
- V1 = VOCAB(WD1, -1);
- V2 = VOCAB(WD2, -1);
+ V1 = VOCAB(command.wd1, -1);
+ V2 = VOCAB(command.wd2, -1);
if (V1 == ENTER && (V2 == STREAM || V2 == 1000 + WATER)) {
if (LIQLOC(game.loc) == WATER) {
RSPEAK(FEET_WET);
}
goto L2012;
}
- if (V1 == ENTER && WD2 > 0) {
- WD1 = WD2;
- WD1X = WD2X;
- wordclear(&WD2);
+ if (V1 == ENTER && command.wd2 > 0) {
+ command.wd1 = command.wd2;
+ command.wd1x = command.wd2x;
+ wordclear(&command.wd2);
} else {
/* FIXME: Magic numbers */
if (!((V1 != 1000 + WATER && V1 != 1000 + OIL) ||
(V2 != 1000 + PLANT && V2 != 1000 + DOOR))) {
if (AT(V2 - 1000))
- WD2 = MAKEWD(WORD_POUR);
+ command.wd2 = MAKEWD(WORD_POUR);
}
if (V1 == 1000 + CAGE && V2 == 1000 + BIRD && HERE(CAGE) && HERE(BIRD))
- WD1 = MAKEWD(WORD_CATCH);
+ command.wd1 = MAKEWD(WORD_CATCH);
}
L2620:
- if (wordeq(WD1, MAKEWD(WORD_WEST))) {
+ if (wordeq(command.wd1, MAKEWD(WORD_WEST))) {
++game.iwest;
if (game.iwest == 10)
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)
RSPEAK(GO_UNNEEDED);
}
Lookup:
- defn = VOCAB(WD1, -1);
+ defn = VOCAB(command.wd1, -1);
if (defn == -1) {
/* Gee, I don't understand. */
if (fallback_handler(rawbuf))
continue;
- SETPRM(1, WD1, WD1X);
+ SETPRM(1, command.wd1, command.wd1x);
RSPEAK(DONT_KNOW);
goto L2600;
}
}
Laction:
- switch (action(cmdin, command)) {
+ switch (action(cmdin, &command)) {
case GO_TERMINATE:
return true;
case GO_MOVE:
goto Lookup;
case GO_WORD2:
/* Get second word for analysis. */
- WD1 = WD2;
- WD1X = WD2X;
- wordclear(&WD2);
+ command.wd1 = command.wd2;
+ command.wd1x = command.wd2x;
+ wordclear(&command.wd2);
goto L2620;
case GO_UNKNOWN:
/* Random intransitive verbs come here. Clear obj just in case
* (see attack()). */
- SETPRM(1, WD1, WD1X);
+ SETPRM(1, command.wd1, command.wd1x);
RSPEAK(DO_WHAT);
command.obj = 0;
goto L2600;