597 lines
11 KiB
C
Executable file
597 lines
11 KiB
C
Executable file
/* program ITVERB.C */
|
|
|
|
|
|
#include <stdio.h>
|
|
#include "advent.h"
|
|
#include "advdec.h"
|
|
|
|
_PROTOTYPE(void needobj, (void));
|
|
_PROTOTYPE(void ivtake, (void));
|
|
_PROTOTYPE(void ivopen, (void));
|
|
_PROTOTYPE(void ivkill, (void));
|
|
_PROTOTYPE(void ivdrink, (void));
|
|
_PROTOTYPE(void ivquit, (void));
|
|
_PROTOTYPE(void ivfoo, (void));
|
|
_PROTOTYPE(void inventory, (void));
|
|
_PROTOTYPE(void addobj, (int obj));
|
|
_PROTOTYPE(void ivpour, (void));
|
|
_PROTOTYPE(void ivfill, (void));
|
|
_PROTOTYPE(void ivbrief, (void));
|
|
_PROTOTYPE(void ivread, (void));
|
|
_PROTOTYPE(void ivcombo, (void));
|
|
_PROTOTYPE(void iveat, (void));
|
|
/*
|
|
Routines to process intransitive verbs
|
|
*/
|
|
void itverb()
|
|
{
|
|
int i;
|
|
|
|
newtravel = FALSE;
|
|
switch (verb) {
|
|
case DROP:
|
|
case SAY:
|
|
case WAVE:
|
|
case CALM:
|
|
case RUB:
|
|
case THROW:
|
|
case FIND:
|
|
case FEED:
|
|
case BREAK:
|
|
case WAKE:
|
|
case WEAR:
|
|
case HIT:
|
|
case DIAL:
|
|
case PLAY:
|
|
case PICK:
|
|
case PUT:
|
|
case TURN: needobj(); break;
|
|
case TAKE:
|
|
case YANK:
|
|
case GET:
|
|
case INSRT:
|
|
case REMOVE:
|
|
case BURN: ivtake(); break;
|
|
case OPEN:
|
|
case CLOSE:
|
|
case LOCK:
|
|
case UNLOCK: ivopen(); break;
|
|
case NOTHING: rspeak(54); break;
|
|
case ON:
|
|
case OFF: trverb(); break;
|
|
case WALK: actspk(verb); break;
|
|
case KILL: ivkill(); break;
|
|
case POUR: ivpour(); break;
|
|
case EAT: iveat(); break;
|
|
case DRINK: ivdrink(); break;
|
|
case QUIT: ivquit(); break;
|
|
case INVENTORY: inventory(); break;
|
|
case FILL: ivfill(); break;
|
|
case BLAST: ivblast(); break;
|
|
case SCORE: score(TRUE); break;
|
|
case FOO: ivfoo(); break;
|
|
case BRIEF: ivbrief(); break;
|
|
case READ: ivread(); break;
|
|
case SUSPEND:
|
|
if (g.closing)
|
|
rspeak(378);
|
|
else
|
|
saveadv("advent.sav");
|
|
break;
|
|
case RESTORE: restore("advent.sav"); break;
|
|
case ANSWER:
|
|
if ((g.loc != 189) || (g.prop[PHONE] != 0))
|
|
needobj();
|
|
else {
|
|
object = PHONE;
|
|
itverb();
|
|
}
|
|
break;
|
|
case BLOW: rspeak(268); break;
|
|
/* Action verb 'LEAVE' has no object */
|
|
case LEAVE: bug(29); break;
|
|
/* Call if no phone is handy, yell. */
|
|
case YELL:
|
|
if (!here(PHONE))
|
|
needobj();
|
|
else if (!g.closed)
|
|
rspeak(271);
|
|
else {
|
|
rspeak(283);
|
|
normend();
|
|
}
|
|
break;
|
|
/* Health. give him a diagnosis. */
|
|
case HEALTH:
|
|
if (g.numdie)
|
|
fprintf(stdout, "You have been killed %d times otherwise\n",
|
|
g.numdie);
|
|
if (g.health >= 95) {
|
|
if (pct(50))
|
|
rspeak(348);
|
|
else
|
|
rspeak(349);
|
|
} else {
|
|
fprintf(stdout,
|
|
"Your health rating is %2d out of a possible 100.\n",
|
|
g.health);
|
|
rspeak(381 + (100 - g.health) / 20);
|
|
}
|
|
break;
|
|
case LOOK: ivlook(); break;
|
|
case COMBO:
|
|
if (at(SAFE))
|
|
ivcombo();
|
|
break;
|
|
case SWEEP:
|
|
/* Dust/sweep */
|
|
if (!at(CARVNG) || !athand(BRUSH) || (g.prop[CARVNG] == 1))
|
|
rspeak(342);
|
|
else {
|
|
g.prop[CARVNG] = 1;
|
|
rspeak(363);
|
|
rspeak(372);
|
|
}
|
|
break;
|
|
case TERSE:
|
|
/* Terse/unterse. supress all long_form descriptions. */
|
|
g.terse = !g.terse;
|
|
g.detail = 3;
|
|
rspeak(54);
|
|
break;
|
|
case WIZ:
|
|
is_wiz = !is_wiz;
|
|
case MAP:
|
|
rspeak(54);
|
|
break;
|
|
case GATE:
|
|
if (is_wiz) {
|
|
static char buf[INPUTBUFLEN];
|
|
sscanf(ask("Location ? ", buf, sizeof(buf)), "%d", &g.loc);
|
|
}
|
|
rspeak(54);
|
|
break;
|
|
case PIRLOC:
|
|
if (is_wiz) {
|
|
fprintf(stdout, "The dwarfs are at locations:\n");
|
|
for (i = 1; i < DWARFMAX; i++)
|
|
fprintf(stdout, " %4d", g.dloc[i]);
|
|
fprintf(stdout, "\nThe pirate is at location %4d\n",
|
|
g.dloc[DWARFMAX]);
|
|
}
|
|
rspeak(54);
|
|
break;
|
|
default:
|
|
printf("This intransitive not implemented yet\n");
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
Routine to indicate no reasonable
|
|
object for verb found. Used mostly by
|
|
intransitive verbs.
|
|
*/
|
|
void needobj()
|
|
{
|
|
printf("%s what?\n", vtxt[vrbx]);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
CARRY, TAKE etc.
|
|
*/
|
|
void ivtake()
|
|
{
|
|
int anobj, item;
|
|
|
|
anobj = 0;
|
|
for (item = 1; item < MAXOBJ; ++item)
|
|
if (g.place[item] == g.loc)
|
|
if (anobj == 0)
|
|
anobj = item;
|
|
else {
|
|
needobj();
|
|
return;
|
|
}
|
|
|
|
if (anobj == 0 || (dcheck() && g.dflag >= 2) || blind())
|
|
needobj();
|
|
else {
|
|
object = anobj;
|
|
if (verb == YANK)
|
|
vyank();
|
|
else if (verb == WEAR)
|
|
vwear();
|
|
else
|
|
vtake();
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
OPEN, LOCK, UNLOCK
|
|
*/
|
|
void ivopen()
|
|
{
|
|
int obj_cnt, item;
|
|
|
|
for (item = 1, obj_cnt = 0; item < MAXOBJ; item++) {
|
|
if ((g.place[item] == g.loc) && (hinged(item))) {
|
|
object = item;
|
|
obj_cnt++;
|
|
}
|
|
}
|
|
if (obj_cnt != 1)
|
|
needobj();
|
|
else if (verb == LOCK)
|
|
vlock();
|
|
else if (verb == UNLOCK)
|
|
vunlock();
|
|
else if (verb == SHUT)
|
|
vclose();
|
|
else
|
|
vopen();
|
|
}
|
|
|
|
/*
|
|
ATTACK, KILL etc
|
|
*/
|
|
boolean previous_obj;
|
|
|
|
void ivkill()
|
|
{
|
|
previous_obj = FALSE;
|
|
if (dcheck() && g.dflag >= 2)
|
|
object = DWARF;
|
|
if (here(SNAKE))
|
|
addobj(SNAKE);
|
|
if (at(DRAGON) && g.prop[DRAGON] == 0)
|
|
addobj(DRAGON);
|
|
if (at(TROLL))
|
|
addobj(TROLL);
|
|
if (here(GNOME))
|
|
addobj(GNOME);
|
|
if (here(BEAR) && g.prop[BEAR] == 0)
|
|
addobj(BEAR);
|
|
if (here(WUMPUS) && g.prop[WUMPUS] == 0)
|
|
addobj(WUMPUS);
|
|
/* Can't attack bird by throwing axe */
|
|
if (here(BIRD) && verb != THROW)
|
|
addobj(BIRD);
|
|
/* Clam and oyster both treated as clam for intransitive case; no
|
|
harm done. */
|
|
if (here(CLAM) || here(OYSTER))
|
|
addobj(CLAM);
|
|
|
|
if ((previous_obj) || (object == 0))
|
|
rspeak(44);
|
|
else
|
|
vkill();
|
|
return;
|
|
}
|
|
|
|
/*
|
|
POUR if no object, assume liq in container, if holding one.
|
|
*/
|
|
void ivpour()
|
|
{
|
|
if ((holding(BOTTLE)) && (liq(BOTTLE) != 0) && !holding(CASK))
|
|
object = BOTTLE;
|
|
if ((holding(CASK)) && (liq(CASK) != 0) && !holding(BOTTLE))
|
|
object = CASK;
|
|
|
|
if (object == 0)
|
|
needobj();
|
|
else
|
|
trverb();
|
|
}
|
|
|
|
/*
|
|
EAT. intransitive: assume edible if present, else ask what.
|
|
If he as more than one edible, or none, 'EAT' is ambiguous
|
|
without an explicit object.
|
|
*/
|
|
void iveat()
|
|
{
|
|
int i;
|
|
|
|
previous_obj = FALSE;
|
|
for (i = 1; i < MAXOBJ; i++) {
|
|
if ((here(i)) && (edible(i)))
|
|
addobj(i);
|
|
}
|
|
if ((previous_obj) || (object == 0))
|
|
needobj();
|
|
else
|
|
trverb();
|
|
}
|
|
|
|
/*
|
|
DRINK. If no object, assume water or wine and look for them here.
|
|
If potable is in bottle or cask, drink that. If not, see if there
|
|
is something drinkable nearby (stream, lake, wine fountain, etc.),
|
|
and drink that. If he has stuff in both containers, ask which.
|
|
*/
|
|
void ivdrink()
|
|
{
|
|
int ll;
|
|
|
|
previous_obj = FALSE;
|
|
ll = liqloc(g.loc);
|
|
if ((ll == WATER) || (ll == WINE)) {
|
|
object = ll;
|
|
iobj = -1;
|
|
}
|
|
ll = liq(BOTTLE);
|
|
if ((athand(BOTTLE)) && ((ll == WATER) || (ll == WINE))) {
|
|
object = ll;
|
|
iobj = BOTTLE;
|
|
}
|
|
ll = liq(CASK);
|
|
if ((athand(CASK)) && ((ll == WATER) || (ll == WINE))
|
|
&& iobj != BOTTLE) {
|
|
object = ll;
|
|
iobj = CASK;
|
|
} else
|
|
object = 0;
|
|
|
|
if (object == 0)
|
|
needobj();
|
|
else
|
|
trverb();
|
|
}
|
|
|
|
/*
|
|
QUIT intransitive only. Verify intent and exit if that's what he wants
|
|
*/
|
|
void ivquit()
|
|
{
|
|
gaveup = yes(22, 54, 54);
|
|
if (gaveup)
|
|
normend();
|
|
return;
|
|
}
|
|
|
|
/*
|
|
INVENTORY
|
|
*/
|
|
void inventory()
|
|
{
|
|
int i, msg;
|
|
boolean init_msg;
|
|
|
|
init_msg = TRUE;
|
|
msg = 98;
|
|
for (i = 1; i < MAXOBJ; i++) {
|
|
if (!holding(i) || wearng(i) || i == BEAR || i == BOAT)
|
|
continue;
|
|
if (init_msg)
|
|
rspeak(99);
|
|
pspeak(i, -1);
|
|
init_msg = FALSE;
|
|
msg = 0;
|
|
lookin(i);
|
|
}
|
|
|
|
/* Tell him what he is wearing */
|
|
init_msg = TRUE;
|
|
for (i = 1; i < MAXOBJ; i++) {
|
|
if (wearng(i)) {
|
|
if (init_msg)
|
|
fprintf(stdout, "\nYou are wearing:\n");
|
|
fprintf(stdout, " ");
|
|
pspeak(i, -1);
|
|
msg = 0;
|
|
init_msg = FALSE;
|
|
}
|
|
}
|
|
|
|
if (holding(BOAT)) {
|
|
rspeak(221);
|
|
lookin(BOAT);
|
|
}
|
|
if (holding(BEAR))
|
|
msg = 141;
|
|
|
|
if (msg)
|
|
rspeak(msg);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
FILL bottle or cask must be empty, and some liquid avaible
|
|
*/
|
|
void ivfill()
|
|
{
|
|
if ((g.prop[CASK] == 1) && !here(CASK))
|
|
object = CASK;
|
|
if ((g.prop[BOTTLE] == 1) && !here(BOTTLE))
|
|
object = BOTTLE;
|
|
|
|
if ((here(BOTTLE) && here(CASK)) || (object == 0))
|
|
needobj();
|
|
else
|
|
trverb();
|
|
}
|
|
|
|
/*
|
|
BLAST etc.
|
|
*/
|
|
void ivblast()
|
|
{
|
|
if (!g.closed)
|
|
actspk(verb);
|
|
else {
|
|
g.bonus = 135;
|
|
if (g.place[ROD2] == 212 && g.loc == 116)
|
|
g.bonus = 133;
|
|
if (g.place[ROD2] == 116 && g.loc != 116)
|
|
g.bonus = 134;
|
|
rspeak(g.bonus);
|
|
normend();
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
Handle fee fie foe foo...
|
|
*/
|
|
void ivfoo()
|
|
{
|
|
int k;
|
|
int msg;
|
|
|
|
k = VAL(vocab(vtxt[vrbx], MISC));
|
|
if (g.foobar != 1 - k) {
|
|
if (g.foobar == 0)
|
|
msg = 42;
|
|
else
|
|
msg = 151;
|
|
rspeak(msg);
|
|
return;
|
|
}
|
|
g.foobar = k;
|
|
if (k != 4)
|
|
return;
|
|
g.foobar = 0;
|
|
if (g.place[EGGS] == plac[EGGS] ||
|
|
(toting(EGGS) && g.loc == plac[EGGS])) {
|
|
rspeak(42);
|
|
return;
|
|
}
|
|
/* Bring back troll if we steal the eggs back from him before
|
|
crossing */
|
|
if (g.place[EGGS] == 0 && g.place[TROLL] == 0 && g.prop[TROLL] == 0)
|
|
g.prop[TROLL] = 1;
|
|
|
|
if (here(EGGS))
|
|
k = 1;
|
|
else if (g.loc == plac[EGGS])
|
|
k = 0;
|
|
else
|
|
k = 2;
|
|
move(EGGS, plac[EGGS]);
|
|
pspeak(EGGS, k);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
brief/unbrief. intransitive only.
|
|
suppress long descriptions after first time.
|
|
*/
|
|
void ivbrief()
|
|
{
|
|
int msg;
|
|
|
|
g.detail = 3;
|
|
g.terse = FALSE;
|
|
if (g.abbnum != 10000) {
|
|
msg = 156;
|
|
g.abbnum = 10000;
|
|
} else {
|
|
msg = 374;
|
|
g.abbnum = 5;
|
|
}
|
|
rspeak(msg);
|
|
}
|
|
|
|
/*
|
|
read etc...
|
|
*/
|
|
void ivread()
|
|
{
|
|
previous_obj = FALSE;
|
|
if (here(BOOK))
|
|
object = BOOK;
|
|
if (here(BOOK2))
|
|
addobj(BOOK2);
|
|
if (here(BILLBD))
|
|
addobj(BILLBD);
|
|
if (here(CARVNG))
|
|
addobj(CARVNG);
|
|
if (here(MAGAZINE))
|
|
addobj(MAGAZINE);
|
|
if (here(MESSAGE))
|
|
addobj(MESSAGE);
|
|
if (here(OYSTER))
|
|
addobj(OYSTER);
|
|
if (here(POSTER))
|
|
addobj(POSTER);
|
|
if (here(TABLET))
|
|
addobj(TABLET);
|
|
|
|
if (previous_obj || object == 0 || dark())
|
|
needobj();
|
|
else
|
|
vread();
|
|
return;
|
|
}
|
|
|
|
/*
|
|
LOOK. can't give more detail. Pretend it wasn't dark (though it may "now"
|
|
be dark) so he won't fall into a pit staring into the gloom.
|
|
*/
|
|
void ivlook()
|
|
{
|
|
if (g.detail++ < 3)
|
|
rspeak(15);
|
|
g.wzdark = FALSE;
|
|
g.visited[g.loc] = 0;
|
|
g.newloc = g.loc;
|
|
newtravel = TRUE;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
COMBO: trying to open safe. (see comments for fee fie foe foo)
|
|
*/
|
|
void ivcombo()
|
|
{
|
|
int k, msg;
|
|
|
|
k = VAL(vocab(vtxt[vrbx], MISC)) - 10;
|
|
msg = 42;
|
|
if (g.combo != 1 - k) {
|
|
if (g.combo != 0)
|
|
msg = 366;
|
|
rspeak(msg);
|
|
return;
|
|
}
|
|
g.combo = k;
|
|
if (k != 3)
|
|
rspeak(371);
|
|
else {
|
|
g.combo = 0;
|
|
bitoff(SAFE, LOCKBT);
|
|
biton(SAFE, OPENBT);
|
|
g.prop[SAFE] = 1;
|
|
if (g.prop[BOOK] < 0) {
|
|
g.tally--;
|
|
g.prop[BOOK] = 0;
|
|
/* If remaining treasures too elusive, zap his lamp. this
|
|
duplicates some code, must be done here since book is
|
|
contained ins safe & tally stuff only works for thing
|
|
deposited at a location. */
|
|
if ((g.tally == g.tally2) && (g.tally != 0))
|
|
g.limit = (g.limit < 35) ? g.limit : 35;
|
|
}
|
|
rspeak(365);
|
|
}
|
|
}
|
|
|
|
/*
|
|
ensure uniqueness as objects are searched
|
|
out for an intransitive verb
|
|
*/
|
|
void addobj(obj)
|
|
int obj;
|
|
{
|
|
if (!previous_obj) {
|
|
if (object != 0)
|
|
previous_obj = TRUE;
|
|
else
|
|
object = obj;
|
|
}
|
|
return;
|
|
}
|