minix/commands/advent/itverb.c

598 lines
11 KiB
C
Raw Normal View History

2005-04-21 16:53:53 +02:00
/* 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;
}