games-request@tekred.TEK.COM (01/13/88)
Submitted by: nrcvax!kosman!kevin
Comp.sources.games: Volume 3, Issue 35
Archive-name: crystal/Part03
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 5)."
# Contents: cvact.c cvend.c cvmain.c cvocab.h
# Wrapped by billr@tekred on Tue Jan 12 10:11:32 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f cvact.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"cvact.c\"
else
echo shar: Extracting \"cvact.c\" \(20904 characters\)
sed "s/^X//" >cvact.c <<'END_OF_cvact.c'
X/* cvact.c
X * perform actions
X *************************************************************************/
X
X#include <stdio.h>
X#include "cvobj.h"
X#include "cvocab.h"
X#include "cvlocs.h"
X#include "cvmisc.h"
X#include "cvorcs.h"
X#include "cvcode.h"
X#include "random.h"
X
Xextern int actspk[]; /* cvocab.c */
Xextern char *oword;
Xextern void cvsave();
Xextern void putcode();
Xextern int mutilate();
Xextern void juggle();
X
X#define OKAY(msg) {rspeak(msg); return S_okay;}
X#define DEFMSG OKAY(actspk[verb%1000])
X#define BREAKIT {register int i; if (i = mutilate(object)) {\
X newloc = &(cvloc[i]); return S_move;\
X } else return S_okay; }
X#define FILLIT(object,liquid) {(object)->prop = (liquid) - _WATER + 1;}
X#define INTRANS
X#define TRANS 10000 +
X
Xint
Xsuicide()
X{
X pspeak(SELF,1);
X die();
X return S_show;
X}
X
Xstatic void
Xdolight(object,state)
Xregister struct cvobj *object;
Xregister int state;
X{
X if (object != LAMP) {
X rspeak(180);
X } else if (limit < 0) {
X rspeak(184);
X } else if (object->prop == state) {
X rspeak(182-state); /* already in that state */
X } else {
X rspeak(40 - state);
X object->prop = state;
X if (DARK) {
X rspeak(16);
X }
X }
X return;
X}
X
Xint
Xdrownch()
X{
X if (loc->flags & DROWN)
X { rspeak(120); /* You can't swim */
X oldlc2 = loc; /* and all your stuff gets lost in the water */
X die(); /* you guessed it! */
X return TRUE;
X } else {
X return FALSE;
X }
X}
X
Xvoid
Xdidorc()
X{ pspeak(ORCS,3); /* the orcs agree */
X ORCS->prop = 0; /* now kill THEM off */
X pspeak(IDOL,2); /* idol explodes (which is what kills the orcs) */
X IDOL->prop = 0; /* make idol toteable */
X destr2(IDOL); /* unfix the idol */
X pspeak(IDOL,0); /* report the new state of the (now small) idol */
X GIANT->prop = 1; /* Now for the BAD NEWS */
X pspeak(GIANT,1); /* He's after you for sure */
X
X /* Now start giant (as the priest) and the balrog */
X PRIEST->dloc = PRIEST->oloc = loc; /* he's right with you */
X PRIEST->dseen = TRUE; /* of course */
X
X BALLY->dloc = BALLY->oloc = &(cvloc[141]); /* anchor ledge */
X BALLY->dseen = FALSE; /* he'll get you later */
X return;
X}
X
Xvoid
Xnewcon(object,p,liquid)
Xregister struct cvobj *object;
Xregister int p, liquid;
X{ pspeak(object,p); /* tell what the new contents are */
X if (HERE(ORCS) && (ORCS->prop == 1) && (liquid == _COLA)) didorc();
X}
X
Xint
Xdrunkbear(object)
Xregister struct cvobj *object;
X{
X BEAR->prop = 0;
X object->prop = (object == KEG) ? 1 : 0;
X move(object,loc);
X juggle(BEAR);
X move2(object,FIXED);
X YOGI->dseen = FALSE;
X YOGI->dloc = DEAD;
X if (AXE->prop == 1 && AXE->conn2.where == FIXED) {
X AXE->prop = 0;
X destr2(AXE);
X }
X return S_show;
X}
X
Xint
Xwakeking()
X{ HELM->prop = 0;
X destry(HELM);
X ARTHUR->dseen = TRUE;
X ARTHUR->dloc = loc;
X pspeak(HELM, 2); /* oops, he's after you */
X return S_okay;
X}
X
Xint
Xunicorn()
X{ pspeak(UNICRN,UNICRN->prop + 2);
X if (UNICRN->prop == 1) {
X destr2(UNICRN);
X UNICRN->prop = 0;
X EINHORN->dseen = FALSE;
X EINHORN->dloc = EINHORN->oloc = DEAD;
X pspeak(UNICRN,0);
X }
X return S_okay;
X}
X
Xint
Xcvact(verb,obj,object) register int verb, obj;
Xregister struct cvobj *object;
X{
X register int k;
X
X switch ((!!obj*10000) + verb)
X {
X case TRANS DROP:
X case TRANS THROW: /* a few cases handled elsewhere */
X case INTRANS FEED:
X case TRANS FEED:
X case INTRANS POUR:
X case TRANS POUR:
X case INTRANS FILL:
X case TRANS FILL:
X return cvatt(verb,obj,object);
X
X case INTRANS SAVE:
X cvsave();
X OKAY(54);
X
X case INTRANS RESTOR:
X cvrest();
X rspeak(54);
X return S_show;
X
X case INTRANS TAKE:
X /* take what? I can figure it out if there's only one thing here,
X but otherwise, I complain. */
X if ((loc->atloc.link == NULL) || (loc->atloc.link->link != NULL))
X { return S_what; }
X
X /* if there's liquid here, too, I get confused, which may just
X confuse the adventurer, or may give him the hint he needs */
X if (LIQLOC(loc)) { return S_what; }
X
X /* if the one object is the skeleton in attack mode, there's a
X cutlass too, so we treat it as confusing, too */
X if (HERE(SKELTN) && (SKELTN->prop == 1)) { return S_what; }
X
X /* if any creatures are here, they confuse things, too */
X { register struct monster *cre;
X
X for (cre = orcs; cre->iloc != -1; ++cre)
X { if (cre->dloc == loc) { return S_what; } }
X }
X
X object = loc->atloc.link->who ;
X obj = (object - cvobj) + 1000 ;
X
X case TRANS TAKE:
X /* taking something
X * artifacts get destroyed (this should annoy the usual greedy
X players
X * liquids are treated specially, since they are shown as
X properties of places and vessels.
X * there are some other interesting side-effects, too!
X */
X
X if ((object >= MINART) && (object <= MAXART)) BREAKIT ;
X
X if (HERE(DRAGON) && DRAGON->prop ) OKAY(203);
X
X if (object == SHOWER)
X { pspeak(SHOWER,1);
X CRAP->prop = 0 ;
X return S_okay;
X }
X
X if ((object == ROPE)
X && (TOTING(ROPE) || (ROPE->prop % 2) )
X && HERE(ROPE2))
X { obj = _ROPE2; object = ROPE2; }
X
X if (TOTING(object)) DEFMSG ;
X
X if (DARK) OKAY(202);
X
X if ((object == WINE) || (object == COLA) || (object == WATER))
X { register int k;
X k = obj; obj = 0;
X if (AT(BOTTLE) && (LIQ(BOTTLE) == k )) obj = _BOTTLE ;
X if (AT(CUP) && (LIQ(CUP) == k)) obj = obj*100 + _CUP ;
X if (obj > 4000) { return S_what; }
X if (LIQLOC(loc) == k)
X { if (obj) { return S_what; } /* quibble about ambiguity */
X if (TOTING(BOTTLE) && !(BOTTLE->prop)) obj = _BOTTLE ;
X if (TOTING(CUP) && !(CUP->prop)) obj = obj*100 + _CUP ;
X if (obj > 4000)
X { fputs("Into what?\n",stdout) ;
X mltcmd = FALSE ;
X return S_obj;
X }
X if (obj)
X { object = OBJ(obj);
X FILLIT(object,k);
X newcon(object, object->prop + 7, k);
X } else {
X rspeak(104) ; /* nothing to put it in */
X }
X return S_okay ;
X }
X
X if (!obj) OKAY(24);
X object = OBJ(obj);
X }
X
X if (holding >= 9) OKAY(92); /* too many */
X
X if (object == TOAD)
X { pspeak(TOAD,1); /* all this for fun and games! */
X destry(TOAD); /* he oughtta get points just for reading this*/
X return S_okay;
X }
X
X if (object == HANG) {
X pspeak(HANG,HANG->prop + 1);
X if (HANG->prop == 0) {
X HANG->prop = 2;
X juggle(HANG);
X }
X return S_show;
X }
X
X if ((object == UNICRN) && UNICRN->prop)
X { pspeak(UNICRN,UNICRN->prop + 2);
X if (UNICRN->prop != 1) return S_okay;
X destr2(UNICRN); /* make it not fixed any more */
X EINHORN->dseen = FALSE ;
X EINHORN->dloc = EINHORN->oloc = DEAD;
X pspeak(UNICRN, (UNICRN->prop = 0)); /* make it just a collar */
X return S_okay;
X }
X
X if (object == BOAT) object->prop += 2;
X
X /* if the object has a second location, you can't touch it! */
X /* the reason given is it's beyond your power or just ridiculous */
X if (object->conn2.where != LOST) OKAY(IFTREAS(object) ? 146 : 25);
X
X if ((object == RING) && (JEANNIE->dloc != DEAD))
X { if (JEANNIE->dloc != loc)
X OKAY(146); /* beyond YOUR power (need jinni) */
X carry(object);
X JEANNIE->oloc = JEANNIE->dloc = DEAD;
X JEANNIE->dseen = FALSE;
X OKAY(209); /* explain what happened to jinni */
X }
X
X carry(object);
X
X if ((object == CROWN) && (HELM->prop)) return wakeking();
X
X if ((object == CHEST) && (SKELTN->prop))
X { rspeak(54); /* okay, but ... */
X rspeak(96); /* it DOES have a side effect! */
X SKELTN->prop = 1;
X rspeak(101); /* he always misses the first swing */
X return S_miss; /* of course, everything else is just FINE! */
X }
X
X OKAY(54);
X
X case INTRANS UNLOC:
X obj = 0;
X if (HERE(HELM) & HELM->prop) obj = _HELM;
X if (AT(DOOR)) {
X if (obj) return S_what;
X else obj = _DOOR;
X }
X if (HERE(CHAIN) && CHAIN->prop) {
X if (obj) return S_what;
X else obj = _CHAIN;
X }
X if (!obj) return S_what;
X object = OBJ(obj);
X case TRANS UNLOC:
X if (object == HELM) return wakeking();
X if (object == BEAR && HERE(CHAIN) && CHAIN->prop == 2) {
X obj = _CHAIN;
X object = OBJ(obj);
X }
X if (object == CHAIN) {
X if (!HERE(KEY)) OKAY(31);
X if (CHAIN->prop == 0) OKAY(37);
X CHAIN->prop = 0;
X destr2(CHAIN);
X if (!HERE(BEAR) || BEAR->prop <= 2) OKAY(54);
X BEAR->prop -= 2;
X YOGI->dseen = TRUE;
X YOGI->dloc = loc;
X return S_show;
X }
X goto Leave;
X
X case INTRANS LOCK:
X if (AT(DOOR)) obj = _DOOR;
X if (HERE(CHAIN)) {
X if (obj) return S_what;
X else obj = _CHAIN;
X }
X if (!obj) return S_what;
X object = OBJ(obj);
X case TRANS LOCK:
X if (object == CHAIN) {
X if (!HERE(KEY)) OKAY(31);
X if (TOTING(CHAIN)) move(CHAIN,loc);
X CHAIN->prop = 1;
X move2(CHAIN,FIXED);
X return S_okay;
X }
XLeave:
X if (object == NULL) DEFMSG;
X if (object == DOOR && HERE(KEY)) {
X if (closing) {
X if (!panic) clock2 = 15;
X panic = TRUE;
X OKAY(130);
X } else {
X k = 34 + DOOR->prop;
X DOOR->prop = (verb == LOCK) ? 0 : 1;
X OKAY(k + 2*(DOOR->prop));
X }
X } else {
X if (object == DOOR) OKAY(31);
X if (object == KEY) OKAY(55);
X OKAY(33);
X }
X
X case INTRANS PAY:
X if (loc == O_GATE->conn1.where)
X object = O_GATE;
X else OKAY(8);
X case TRANS PAY:
X if (object != O_GATE) OKAY(8);
X if (TOTING(RUG) && RUG->prop == 1) OKAY(117);
X if (!HERE(WALLET)) OKAY(20);
X if (WALLET->prop > 3) OKAY(21);
X if (O_GATE->prop == 2) OKAY(46);
X if (CRAP->prop) OKAY(113);
X (WALLET->prop)++;
X loc++;
X return S_show;
X
X case TRANS BREAK:
X if (object <= MINART && object >= MAXART) BREAKIT;
X if (object == MIRROR) {
X pspeak(object,object->prop + 3);
X bonus = !(object->prop);
X finish = TRUE;
X return S_show;
X } else if (object == DAM) {
X if (DAM->prop) return S_what;
X BRIDGE->prop = DAM->prop = 1;
X O_GATE->prop = 2;
X rspeak(41);
X if (BOAT->prop % 2) {
X move(BOAT,BOATPLC);
X k = BOAT->prop;
X BOAT->prop = 4;
X move2(BOAT,FIXED);
X rspeak(32);
X if (k == 3) {
X rspeak(45);
X die();
X }
X }
X return S_show;
X } else DEFMSG;
X
X case INTRANS TEST:
X case TRANS TEST:
X if (object == ROPE) {
X if (HERE(ROPE) && (ROPE->prop == 4 || ROPE->prop == 6)) {
X ROPE->prop = 6;
X OKAY(54);
X } else OKAY(29);
X }
X if (!HERE(LAMP)) DEFMSG;
X printf("%d turns of life left in your lamp batteries.",limit);
X return S_okay;
X
X case INTRANS CUT:
X object = ROPE;
X if (!HERE(ROPE) && HERE(ROPE2))
X object = ROPE2;
X else if (!HERE(ROPE) && HERE(EROPE))
X object = EROPE;
X else if (!HERE(ROPE))
X return S_what;
X case TRANS CUT:
X if (!HERE(AXE) && !HERE(SWORD)) DEFMSG;
X if (object != ROPE && object != ROPE2 && object != EROPE)
X return S_what;
X k = ROPE->prop > 3 ? 167 : 54; /* untie it sometimes */
X if (object == EROPE) {
X if (object->prop <3) OKAY(108); /* It's gotta be long */
X ROPE->prop = 3; /* anchored 60-foot rope */
X EROPE->prop = 0; /* end of 60-foot rope */
X ROPE2->prop = 2; /* loose 60-foot rope */
X move(ROPE2,loc); /* bring it here */
X destry(EROPE2);
X } else {
X if (object->prop % 2) OKAY(168); /* not at anchor */
X if (object->prop == 2) OKAY(108); /* too short */
X ROPE->prop = ROPE2->prop = 2;
X move(ROPE2,loc);
X }
X rspeak(k);
X return S_show;
X
X case INTRANS TIE:
X if (HERE(ROPE)) object = ROPE;
X if (HERE(ROPE2)) object = ROPE2;
X if (HERE(BOAT)) {
X if (object != NULL) return S_what;
X object = BOAT;
X }
X case TRANS TIE:
X if (object == BOAT) {
X if (object->prop == 4) OKAY(30);
X if (!(object->prop % 2)) OKAY(27);
X object->prop--;
X OKAY(54);
X }
X if (HERE(ROPE) && HERE(ROPE2) && ROPE->prop == 2) {
X ROPE->prop = 4;
X destry(ROPE2);
X destry(EROPE2); /* just in case it was rigged */
X OKAY(54);
X }
X /* NOTE: fall through to RIG when tying complete rope */
X case INTRANS RIG:
X case TRANS RIG:
X object = NULL;
X if (HERE(ROPE) && !(ROPE->prop % 2)) object = ROPE;
X else if (HERE(ROPE2) && ROPE2->prop == 2) object = ROPE2;
X else OKAY(205); /* You have no rope */
X { register struct rtr *rtr;
X register struct cvobj *obj2;
X
X obj2 = object + 2; /* EROPE object */
X k = loc - cvloc;
X for (rtr = rtrav; rtr->top != -1; rtr++)
X if (k == rtr->top) break;
X if (rtr->top == -1)
X OKAY(204); /* nothing to tie it to */
X if (rtr->mid == 0 && object->prop == 2)
X rspeak(206); /* It won't reach */
X object->prop ++; /* tie it */
X if (TOTING(object)) move(object,loc); /* drop it */
X move2(object,FIXED); /* fix it */
X move(obj2, &(cvloc[rtr->mid])); /* move the end */
X move2(obj2,FIXED); /* fix the end */
X obj2->prop = 0; /* assume the bottom */
X if (object==ROPE && !(rtr->bot) && ROPE->prop!=3) {
X if (rtr->mid == DUNGEON) {
X obj2->prop = 3; /* show the rest of the rope */
X }
X else {
X obj2->prop = 4; /* show the rest of the rope */
X }
X }
X if (rtr->bot && object == ROPE && object->prop != 3) {
X if (rtr->mid) {
X obj2 = EROPE2;
X EROPE->prop = (int)(ROPE->prop/4) +1;
X } else obj2 = EROPE;
X move(obj2,&(cvloc[rtr->bot]));
X move2(obj2,FIXED);
X }
X return S_show;
X }
X
X case INTRANS UNTIE:
X if (HERE(BOAT)) {
X if (HERE(ROPE) || HERE(ROPE2)) return S_what;
X object = BOAT;
X } else if (HERE(ROPE)) object = ROPE;
X else if (HERE(ROPE2)) object = ROPE2;
X case TRANS UNTIE:
X if (object == BOAT) {
X if (object->prop == 4) OKAY(30);
X if (object->prop % 2) OKAY(26);
X object->prop ++ ;
X OKAY(54);
X }
X if (HERE(ROPE) && (ROPE->prop == 4 || ROPE->prop == 6)) {
X ROPE->prop = ROPE2->prop = 2;
X move(ROPE2,loc);
X rspeak(54);
X return S_show;
X }
X if (HERE(EROPE) && (ROPE->prop > 3) && (EROPE->prop > 2)) {
X /* dividing a long rope while it's rigged */
X ROPE->prop = 3; /* make it short */
X EROPE->prop = 0; /* make the end short, too */
X ROPE2->prop = 2; /* create a short coil */
X destry(EROPE2); /* with no end */
X move(ROPE2,loc); /* bring it here */
X rspeak(54);
X return S_show;
X }
X /* now try this as an "unrig" */
X if (HERE(ROPE) && (ROPE->prop % 2)) object = ROPE;
X else if (HERE(ROPE2) && ROPE2->prop == 3) object = ROPE2;
X else DEFMSG;
X object->prop--;
X destr2(object);
X if (object == ROPE && EROPE->prop) destry(EROPE2);
X destry(object+2); /* destroy the end */
X return S_show;
X
X /* rubbing the helm gets you in trouble (but you gotta do it),
X rubbing the lamp gives you a ribbing, rubbing anything else is
X just useless */
X case TRANS RUB:
X if (object == LAMP) DEFMSG;
X if (object == HELM && HELM->prop) return wakeking();
X OKAY(76);
X
X case TRANS INVENT:
X case TRANS FIND:
X if (object == UNICRN && UNICRN->prop && HERE(UNICRN))
X return unicorn();
X if (TOTING(object)) OKAY(24);
X if (closed) OKAY(138);
X if (obj == _DWARF) {
X register struct monster *cre;
X for (cre = MINDWR; cre <= MAXDWR; ++cre) {
X if (cre->dloc == loc && dflag >= 2) {
X OKAY(94);
X }
X }
X }
X if (AT(object)
X || (LIQ(BOTTLE) == obj && AT(BOTTLE))
X || (LIQLOC(loc) == obj)) {
X OKAY(94);
X }
X
X case INTRANS INVENT:
X k = FALSE;
X for (object = cvobj; object->desc != NULL; object++) {
X if (strlen(object->desc) && TOTING(object)) {
X if (!k) {rspeak(99); k = TRUE; }
X blklin = FALSE;
X fputs(" ",stdout);
X putcode(object->desc);
X putchar('\n');
X if ((object == CUP || object == BOTTLE)
X && object->prop) {
X pspeak(object, object->prop + 3);
X }
X blklin = TRUE;
X }
X }
X if (!k) rspeak(98);
X return S_okay;
X
X case TRANS CALM:
X if (object == UNICRN && UNICRN->prop) return unicorn();
X DEFMSG;
X
X case INTRANS KILL:
X obj = 0;
X if (ME->dloc == loc) obj = _SELF;
X if (YOGI->dloc == loc) {
X if (obj) return S_what;
X else obj = _BEAR;
X }
X if (!obj) {
X register struct monster *cre;
X for (cre = orcs; cre->iloc != -1; ++cre) {
X if (cre->dloc == loc) OKAY(49);
X }
X OKAY(44);
X }
X object = OBJ(obj);
X case TRANS KILL:
X if (object >= MINART && object <= MAXART) BREAKIT;
X if (object == SELF) return suicide();
X if (object == BEAR) OKAY(165);
X OKAY(49);
X
X case INTRANS EAT:
X if (HERE(FOOD)) {
X destry(FOOD);
X OKAY(72);
X } else {
X return S_what;
X }
X
X case TRANS EAT:
X if (object == FOOD) {
X destry(FOOD);
X OKAY(72);
X }
X
X if (object == BEAR
X || object == SPIDER
X || object == SELF
X || object == DRAGON
X || object == SKELTN
X || object == BALROG
X || object == DWARF) OKAY(71);
X DEFMSG;
X
X case INTRANS DRINK:
X obj = LIQLOC(loc);
X if (HERE(CUP)) {
X if (obj) return S_what;
X else obj = LIQ(CUP);
X }
X if (HERE(BOTTLE)) {
X if (obj) return S_what;
X else obj = LIQ(BOTTLE);
X }
X if (!obj) return S_what;
X object = OBJ(obj);
X case TRANS DRINK:
X if (object != BOTTLE && object != CUP) {
X k = obj;
X obj = 0;
X if (HERE(CUP) && OBJ(LIQ(CUP)) == object) obj = _CUP;
X if (HERE(BOTTLE) && OBJ(LIQ(BOTTLE)) == object) {
X if (obj) OKAY(143); /* From what? (2 possibilities) */
X obj = _BOTTLE;
X }
X if (OBJ(LIQLOC(loc)) == object) {
X if (obj) OKAY(143); /* From what? (2 possibilities) */
X OKAY(object == WATER ? 73 : 72);
X }
X if (!obj) OKAY(143); /* from what? no possibilities */
X }
X object = OBJ(obj); /* object is now the container */
X if ((k=LIQ(object)) == 0) {pspeak(object,11); return S_okay; }
X rspeak(object == WATER ? 73 : 72); /* take the drink */
X object->prop = 0;
X newcon(object, 7, k);
X return S_okay;
X
X case INTRANS SIT:
X if (!HERE(THRONE) || THRONE->prop == 0) {
X if ((HERE(BOAT) && BOAT->prop/2 == 1)
X || (TOTING(RUG) && RUG->prop == 1))
X rspeak(192);
X else DEFMSG;
X return S_okay;
X }
X k = 0;
X if (HERE(SCEPT)) k++;
X if (HERE(CROWN)) k++;
X if (HERE(CAPE)) k++;
X if (HERE(ORB)) k++;
X pspeak(THRONE,2);
X pspeak(THRONE,k+3);
X oldlc2 = loc;
X if (k == 0) die();
X if (k != 4) return S_show;
X /* He got it right -- cast him into new universe of adventures */
X THRONE->prop = 0;
X destr2(THRONE); /* throne is now a treasure */
X newloc = &(cvloc[124]);
X /* start some new monsters */
X JEANNIE->dloc = RING->conn1.where;
X SLASHER->dloc = JEWLRY->conn1.where;
X EINHORN->dloc = RUG->conn1.where;
X return S_move;
X
X case INTRANS FLY:
X if (!TOTING(RUG)) DEFMSG;
X if (RUG->prop) OKAY(154);
X if (loc > &(cvloc[137])) OKAY(136);
X if (loc < &(cvloc[63])) OKAY(136);
X RUG->prop = 1;
X OKAY(54);
X
X case TRANS WAVE:
X if (!TOTING(object)) OKAY(29);
X if (closing) DEFMSG;
X if (object != SCEPT) OKAY(42);
X if (HERE(HELM) && HELM->prop) return wakeking();
X if (ARTHUR->dloc != loc) OKAY(76);
X ARTHUR->dloc = DEAD;
X ARTHUR->dseen = FALSE;
X move(HELM,loc); /* bring helm here (was destroyed while Arthur
X was walking around */
X destr2(HELM); /* make it takeable */
X pspeak(HELM,6); /* crumble Arthur to dust */
X newloc = loc;
X return S_move;
X
X case INTRANS BRIEF:
X abbnum = 10000;
X detail = 99;
X OKAY(156);
X
X case INTRANS READ:
X if (DARK) return S_what;
X if (HERE(SCROLL)) object = SCROLL;
X else return S_what;
X case TRANS READ:
X if (DARK) return S_dark;
X if (object != SCROLL) DEFMSG;
X OKAY(126);
X
X case INTRANS SCORE:
X getscore();
X printf("\nIf you were to quit now (after %d moves), you would \
Xscore %d\nout of a possible %d points.\n",turns,score,mxscore);
X return S_okay;
X
X case TRANS BLAST:
X case INTRANS BLAST:
X if (!closed) DEFMSG;
X finish = TRUE;
X return S_show;
X
X case INTRANS ON:
X if (!HERE(LAMP)) DEFMSG;
X object = LAMP;
X case TRANS ON:
X dolight(object,1);
X return S_light;
X
X case INTRANS OFF:
X if (!HERE(LAMP)) DEFMSG;
X object = LAMP;
X case TRANS OFF:
X dolight(object,0);
X return S_light;
X
X case INTRANS DESCRB:
X case INTRANS TOUCH:
X if (detail++<3) rspeak(15);
X wzdark = FALSE;
X loc->abb = 0;
X newloc = loc;
X return S_move;
X
X case TRANS TOUCH:
X if (object == TOAD) {
X pspeak(TOAD,1);
X destry(TOAD);
X return S_okay;
X }
X if (object >= MINART && object <= MAXART) BREAKIT;
X if (object == UNICRN && HERE(object) && object->prop)
X return unicorn();
X /* fall through to describe */
X case TRANS DESCRB:
X k = vocab(oword,3);
X if (k > 0) OKAY(k%1000);
X rspeak(15);
X wzdark = FALSE;
X loc->abb = 0;
X newloc = loc;
X return S_move;
X
X case INTRANS PLAY:
X if (!HERE(HARP)) return S_what;
X object = HARP;
X case TRANS PLAY:
X if (object != HARP) DEFMSG;
X pspeak(object,1);
X if (UNICRN->prop == 2 && HERE(UNICRN)) {
X UNICRN->prop = 1;
X OKAY(222);
X }
X if (UNICRN->prop != -1 && UNICRN->prop != 2)
X return S_okay;
X if ((loc >= &(cvloc[62]))
X && (dflag >= 2)
X && (EINHORN->dloc != DEAD)
X && (!(EINHORN->dseen))
X && (!(BADPLC(loc)))) {
X move(UNICRN,loc);
X EINHORN->dloc = EINHORN->oloc = loc;
X EINHORN->dseen = TRUE;
X rspeak(222);
X }
X return S_okay;
X
X case INTRANS DROP:
X case INTRANS SAY:
X case INTRANS RUB:
X case INTRANS FIND:
X case INTRANS BREAK:
X case INTRANS THROW:
X case INTRANS WAVE:
X case INTRANS CALM:
X case INTRANS WAKE:
X case TRANS SIT:
X return S_what;
X
X case INTRANS HELP:
X rspeak(157);
X while (getchar() != '\n') ;
X rspeak(158);
X return S_okay;
X
X case INTRANS QUIT:
X if (!(gaveup = yes(22,54,54))) return S_okay;
X finish = TRUE;
X return S_show;
X
X case TRANS QUIT:
X case TRANS SCORE:
X case TRANS SAVE:
X case TRANS RESTOR:
X case TRANS BRIEF:
X case TRANS WALK:
X case TRANS FLY:
X case TRANS WAKE:
X case TRANS HELP:
X DEFMSG;
X
X case INTRANS NOTHI:
X case TRANS NOTHI:
X OKAY(54);
X
X default:
X fputs("Unknown verb.\n",stdout);
X return S_okay;
X } /* end of verb switch */
X}
END_OF_cvact.c
if test 20904 -ne `wc -c <cvact.c`; then
echo shar: \"cvact.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cvend.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"cvend.c\"
else
echo shar: Extracting \"cvend.c\" \(1628 characters\)
sed "s/^X//" >cvend.c <<'END_OF_cvend.c'
X/* cvend.c
X * do stuff about the end of the game.
X *************************************************************************/
X
X#include <stdio.h>
X#include "cvmisc.h"
X#include "cvobj.h"
X#include "cvlocs.h"
X#include "cvocab.h"
X
Xvoid
Xgetscore()
X{ register struct cvobj *object;
X register struct hint *hint;
X
X score = 0;
X /* get a first impression of how far the adventurer went */
X if (RICK->prop > 0) score = 10;
X if (DAM->prop > 0) score = 25;
X if (dflag != 0) score = 30;
X if (THRONE->prop == 0) score = 35;
X mxscore = 35;
X
X /* tally treasures. Full points if in barn and not broken.
X 2 points each for treasures seen. */
X for (object = MINTRS; object < ENDTRS; ++object) {
X register int value;
X mxscore +=
X (value = (object < RUG) ? 12 : ((object == RUG) ? 14 : 16));
X if (object->prop >= 0) {
X if (INBARN(object)
X && (object->prop == 0 || object == CUP))
X score += value;
X else score += 2;
X }
X }
X
X /* Now look at how he finished, and how far he got.
X * "maxdie" and "numdie" tell us how well he survived.
X * "gaveup" says whether he is using "QUIT".
X * "dflag" will tell us if he ever got suitably deep into the cave.
X * "closing" still indicates whether he reached the endgame.
X * if he got as far as "CAVE CLOSED" then bonus will be false for
X * mundane exits.
X */
X score += (maxdie - numdie)*10; mxscore += maxdie * 10;
X if (!scoring && !gaveup) score += 10; mxscore += 10;
X if (closing) score += 30; mxscore += 30;
X if (closed) {
X score += 5;
X if (bonus) score += 15;
X }
X mxscore += 20;
X
X for (hint = hints; hint->turns >= 0; ++hint) {
X if (hint->hinted) score -= hint->points;
X }
X return;
X}
END_OF_cvend.c
if test 1628 -ne `wc -c <cvend.c`; then
echo shar: \"cvend.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cvmain.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"cvmain.c\"
else
echo shar: Extracting \"cvmain.c\" \(23773 characters\)
sed "s/^X//" >cvmain.c <<'END_OF_cvmain.c'
X/* cvmain.c
X ************************************************************************/
X
X#define SHORT 50
X
X#include <stdio.h>
X#include <string.h>
X#include <fcntl.h>
X#include "cvobj.h"
X#include "cvlocs.h"
X#include "cvocab.h"
X#include "cvmsg.h"
X#include "random.h"
X#include "cvorcs.h"
X#include "cvmisc.h"
X#include "cvcode.h"
X
Xextern char etext;
Xextern char edata;
Xextern char end;
Xextern char _etext;
Xextern char _edata;
Xextern char _end;
X
Xextern char *rmsg[] ;
Xextern int actspk[] ;
Xextern struct cmsg ctext[] ;
Xextern struct cvocab vtab [] ;
Xextern int maxloc ;
Xextern void exit();
Xextern void carry();
Xextern void move();
Xextern void move2();
Xextern void destry();
Xextern void getin();
Xextern void juggle();
Xextern void juggl2();
Xextern void checkobj();
Xextern void checkloc();
Xextern void fixrmsg();
Xextern void motd();
Xextern void rspeak();
Xextern void pspeak();
Xextern void mspeak();
Xextern void putcode();
Xextern int yes();
Xextern struct cvloc *moveme();
X
Xint saved = 0; /* this defines the un-initialized state */
X
Xchar *word1, *word2;
Xchar *vword, *oword;
X
Xstruct cvobj *lastobj ;
Xstruct cvloc *loc = NULL;
Xstruct cvloc *newloc, *oldloc, *knfloc, *oldlc2;
Xint dflag = 0,
X demo = 0,
X score = 0,
X mxscore = 0,
X limit = 0, /* how long his lamp will last on current power */
X setup = 0, /* state of setup */
X tally = 0, /* count of treasures yet to see */
X tally2 = 0, /* count of treasures you'll never see */
X inorth = 0, /* # of times he said NORTH instead of N */
X detail = 0, /* # of times we said "not allowed . . */
X numdie = 0, /* # of times he died so far */
X maxdie = 0, /* # of ways to resurrect him */
X holding = 0, /* # objects he's carrying */
X dkill = 0, /* # of dwarves killed */
X turns = 0,
X nxtchr = 0,
X abbnum = 0, /* how often he gets long description */
X clock1 = 0, /* time from last treasure to closing */
X clock2 = 0, /* time from closing to closed */
X /* LOGICALS FOLLOW */
X bonus = FALSE, /* gets bonus for correct finish */
X closing = FALSE, /* are we closing? */
X panic = FALSE, /* has he panicked */
X wzdark = FALSE,
X closed = FALSE,
X gaveup = FALSE,
X scoring = FALSE,
X mltcmd = FALSE,
X blklin = FALSE,
X samvrb = FALSE,
X finish = FALSE,
X lmwarn = FALSE;
X
X
Xstruct monster orcs[] = {
X {0}, /* spider */ /* monsters first */
X {0}, /* dragon */
X {0}, /* king */
X {0}, /* djinni */
X {0}, /* kobold */
X {0}, /* bugbear */
X {0}, /* unicorn */
X {0}, /* giant orc */
X {0}, /* balrog */
X {62,1}, /* dwarf in pool hall */ /* dwarves next */
X {78,1}, /* dwarf in privy chamber */
X {85,1}, /* dwarf at window in secret passage */
X {100,1}, /* dwarf in the time maze */
X {126,1}, /* dwarf in the harem */
X {130,1}, /* dwarf at the shelf */
X {87}, /* pirate at where he hides his chest */ /* then these */
X {0}, /* *YOU* */
X {-1}};
X
X
Xvoid
Xlocchg()
X{
X if (dodwarf()) die();
X}
X
Xstatic void
Xdohint(hint) register struct hint *hint;
X{
X switch (hint-hints) {
X case 4: if (O_GATE->prop != 0 || HERE(WALLET)) hint->lc = 0;
X break;
X case 5: if (DAM->prop != 0) hint->lc = 0;
X break;
X case 6: if (holding <= 1 || loc->atloc.link != NULL ||
X oldlc2->atloc.link != NULL || oldloc->atloc.link != NULL)
X hint->lc = 0;
X break;
X } /* end of switch for special tests */
X if (hint->lc == 0) return;
X hint->lc = 0;
X if (!yes(hint->quest,0,54)) return;
X printf("I am prepared to give you a hint, but it will cost you %d \
Xpoints.",hint->points);
X hint->hinted = yes(175,hint->hmsg,54);
X if (hint->hinted && limit>30) limit += 30*hint->points;
X return;
X}
Xvoid
Xbug(num) int num;
X{ register long a;
X (void) printf("\nFatal error number %d, see source code for\n\
Xinterpretation.\n",num);
X a = *((long *) 1);
X exit(1);
X}
X
Xvoid
Xmkill(monster,object) register struct monster *monster;
X register struct cvobj *object;
X{
X object->prop = 0;
X move(object,loc);
X object->conn2.where = FIXED ;
X monster->dseen = FALSE ;
X monster->dloc = DEAD ;
X}
X
Xvoid
Xshowroom() {
X putcode(( !(loc->abb++ % abbnum) || (loc->sdesc == NULL))
X ? loc->ldesc : loc->sdesc);
X}
X
Xvoid
Xwhat(word) register int word;
X{ if (word && PCT(60)) {rspeak(60); return;}
X if (PCT(20)) {rspeak(61); return;}
X rspeak(13); return;
X}
X
Xstatic void
Xcapchk(word) register char *word;
X{
X if (!strcmp(word,"indian")
X || !strcmp(word,"persian")
X || !strcmp(word,"coke")
X || !strcmp(word,"kobold")
X || !strcmp(word,"balrog")
X || !strcmp(word,"sears")
X || !strcmp(word,"rick") )
X { *word = toupper(*word);
X }
X}
X
Xmain(argc, argv)
Xint argc;
Xchar * argv[];
X{
X { register int r;
X if (!saved && argc == 2) {
X cvinit(argc,argv);
X exit(0);
X } else if (argc != 1 || saved != 1) {
X exit(1);
X }
X }
X/**********
X * do initialization (some of it just in case):
X * set all objects
X * nowhere (both ways)
X * to their initial properties
X * not linked to any location
X * set all locations
X * to get long message next
X * to have flags = C_FORCED if there's a forced motion
X ***********/
X { register struct cvobj *object;
X for (object = &(cvobj[1]); object->desc != NULL ; object++ )
X { object->conn1.where = object->conn2.where = LOST ;
X object->prop = object->iprop ;
X object->conn1.link = object->conn2.link = NULL ;
X object->conn1.who = object->conn2.who = object ;
X object->conn1.where = object->conn2.where = LOST ;
X }
X lastobj = object - 1 ;
X }
X
X { register struct cvloc *curloc;
X
X for (curloc = &cvloc[1]; curloc->travel != NULL; curloc++ )
X { register struct cvtrav *curtrv;
X curloc->abb = 0;
X curloc->atloc.link = NULL ;
X curtrv = curloc->travel ;
X if (curtrv->word == 1)
X curloc->flags = C_FORCED ;
X }
X }
X
X/************
X * set up the location arrays to that objects are at their indicated
X * places. We use drop, which puts things on the head of the list, so
X * we run this backwards. Things with two locations are dropped twice,
X * and since these are normally best described last, we do them first.
X ************/
X { register struct cvobj *object;
X#define ILOC(obj) (((obj)->iloc) ? (&(cvloc[(obj)->iloc])) : LOST )
X for (object = lastobj; ONUM(object); object--)
X { if (object->iloc2 > 0 )
X { move2(object,&(cvloc[object->iloc2]));
X move(object, ILOC(object) );
X }
X }
X
X for (object = lastobj; ONUM(object); object-- )
X { if (object->iloc2 <= 0 )
X { move(object, ILOC(object) );
X object->conn2.where = object->iloc2 ? FIXED : LOST;
X }
X }
X }
X
X/*************************************************************************
X * clear the hint stuff. loc is how long he's been at a loc with the
X * cond bit set. hinted is true if the hint has already been given.
X *************************************************************************/
X { register struct hint *hint;
X
X for (hint = hints; hint->turns >= 0; ++hint)
X { hint->lc = 0;
X hint->hinted = FALSE ;
X }
X }
X
X/*************************************************************************
X * initialize the monsters.
X * they are all known generically as dwarves because they all move like
X * dwarves, though the adventurer never really knows this.
X *
X * dloc is current location
X * oloc is old location
X * dseen is a flag. If on, this dwarf has the adventurer in sight and
X * is in hot pursuit.
X * dflag indicates the level of activity:
X * 0 no monster stuff yet (wait until pool hall is reached)
X * 1 no monsters met yet (thus, no axe)
X * 2 have axe, but no knives yet. most dwarves moving.
X * 3 first knives thrown (first set always miss)
X * 3+ dwarves are mad (and thus more accurate)
X * some dwarves don't look much like dwarves
X * 1 is grendl the spider
X * 2 is the dragon
X * 3 is the king
X * 4 is the djinni
X * 5 is the kobold
X * 6 is the bugbear
X * 7 is the unicorn
X * 8 is the giant orc
X * 9 is the balrog
X * 10-15 are just dwarves
X * 16 is the pirate.
X * 17 is *you*
X * no two of the initial locations for 10-16 are adjacent. The others
X * only start as part of a pre-set encounter.
X *************************************************************************/
X
X dflag = 0;
X
X { register struct monster *cre;
X
X for (cre = orcs ; (cre->iloc) != -1; cre++) {
X cre->dloc = &cvloc[cre->iloc] ;
X cre->dseen = FALSE ;
X }
X }
X
X/*************************************************************************
X * 'tally' keeps track of how many treasures are yet to be found so we
X * know when to close the cave. 'tally2' keeps track of how many can
X * never be found because the adventurer klutzed out (e.g. lost the
X * scroll in the maze).
X * ***** tally2 is not yet implemented *****
X * the objects must be assigned numbers in the following order
X * treasures
X * end-game weapons
X * artifacts in outer cave
X * other objects
X *************************************************************************/
X tally = tally2 = 0 ;
X
X { register struct cvobj *object;
X for (object = MINTRS ; object != ENDTRS ; ++object ) {
X object->prop = -1 ;
X ++tally ;
X }
X }
X
X BATTER->prop = -1 ;
X oldlc2 =
X knfloc = LOST ;
X
X inorth = /* # of times he said NORTH instead of N */
X detail = /* # of times we said "not allowed . . */
X numdie = /* # of times he died so far */
X holding = /* # objects he's carrying */
X dkill = /* # of dwarves killed */
X turns =
X nxtchr = 0;
X
X abbnum = 5 ; /* how often he gets long description */
X
X clock1 = 30 ; /* time from last treasure to closing */
X clock2 = 50 ; /* time from closing to closed */
X
X bonus = /* gets bonus for correct finish */
X closing = /* are we closing? */
X panic = /* has he panicked */
X closed =
X gaveup =
X scoring =
X mltcmd =
X samvrb =
X finish =
X lmwarn = FALSE ;
X
X { register int i;
X for (i=0 ; i<=4; ++i)
X if ( rmsg[2*i+81] != NULL ) maxdie = i+1 ;
X }
X
X saved = saved == 1 ? -1 : 2 ;
X/*************************************************************************
X * OK, we're close now. Get a couple more things set.
X *************************************************************************/
X demo = FALSE; /* everyone's a class 1 user here */
X motd(FALSE); /* message of the day? */
X hints[3].hinted = yes(65,1,0); /* instructions? */
X newloc = &(cvloc[1]) ; /* start here */
X oldloc = DEAD ; /* make lint happy */
X wzdark = FALSE ;
X setup = 3 ; /* in full swing */
X limit = hints[3].hinted ? 1000 : 330 ;
X juggl2(O_GATE);
X juggle(BEAR);
X juggle(HANG);
X
X/*************************************************************************
X * begin the real stuff
X *************************************************************************/
X
X dodwarf();
X while (!finish) /* motion loop */
X { register struct cvobj *object;
X int verb, oldvrb, obj ;
X
X blklin = TRUE ;
X if (loc == DEAD) {die(); continue; } ;
X if (FORCED(loc)) {
X showroom();
X verb = 1; /* for the benefit of a later switch */
X } else { /* motion not forced */
X if (DARK) {
X if (wzdark && PCT(35)) {
X rspeak(23);
X oldlc2 = loc;
X {die(); continue; };
X } else rspeak(16);
X } else { /* not dark: describe objects found here */
X register struct conn *curcon, *lastcon;
X if (DARKRM)
X pspeak(UNICRN,6); /* that must be the light */
X showroom();
X if (TOTING(BOAT)) pspeak(BOAT,BOAT->prop);
X if (TOTING(RUG) && (RUG->prop == 1)) pspeak(RUG,1);
X curcon = &(loc->atloc);
X while (curcon->link != NULL) {
X register struct cvobj *adobj;
X register int i;
X lastcon = curcon;
X curcon = curcon->link ;
X adobj = curcon->who ;
X if (curcon->where != loc) bug(32);
X if (adobj->prop < 0) {
X adobj->prop = adobj->iprop;
X if (IFTREAS(adobj)) --tally;
X if ((tally == tally2) && tally)
X limit = MIN(limit,35);
X }
X i = adobj->prop ;
X/* handle special cases */
X/* tell about the inside of the gate, if the dummy's there */
X if ((adobj == O_GATE)
X && (O_GATE->conn2.where == loc))
X i = 1;
X/* funny way to tell what happened to the container */
X if (((adobj == CUP) || (adobj == BOTTLE))
X && (adobj->conn2.where == FIXED)
X && (BEAR->prop == 0)
X && (HERE(BEAR)) ) i = 13 ;
X pspeak(adobj,i) ;
X blklin = FALSE ;
X/* seeing the poo close up means there are footprints in it */
X if (adobj == CRAP) adobj->prop = 1 ;
X/* remove ranger from gate after the first time he's seen */
X if (adobj == RICK) {
X RICK->prop++ ;
X destry(RICK);
X curcon = lastcon;
X }
X } /* end showing adobjs */
X } /* end describing objects here */
X goto okay;
X
X/* stuff for when you can't find the indicated object (it may be too dark)
X*/
Xdark: ;
X capchk(word1); /* capitalize some proper nouns */
X (void) printf("I see no %s here.\n",word1);
X mltcmd = FALSE ;
X/* loop here when you say "okay" and such -- less dangerous place than
X * most, but still must watch the skeleton, the lamp, etc.
X */
Xokay: ;
X blklin = TRUE ;
X/* if the skeleton's active, it can kill you */
X if (SKELTN->prop == 1) {
X if (PCT(25)) {
X rspeak(102);
X oldlc2 = loc ;
X {die(); continue; };
X }
X rspeak(101);
X }
X
Xmiss: if (TOTING(MEDAL) && (loc->flags & SECRET)) rspeak(112);
X
X if ((loc->flags & RANGER)
X && (RICK->prop == 0)
X && (DAM->prop == 0)
X && (PCT(25) || (loc->atloc.link != NULL))
X ) {
X pspeak(RICK,6);
X RICK->prop = 3;
X destry(RICK);
X loc = &(cvloc[O_GATE->iloc]);
X break;
X }
X
X/* finds you hanging in there? */
X if ((LNUM(loc) == 144) && PCT(25)) {
X rspeak(217) ;
X if (PCT(50)) rspeak(218);
X }
X
X/* when we don't understand, we come back here for a relatively safe retry.
X */
Xhuh: oldvrb = verb ;
X verb = 0;
Xnewobj: obj = 0;
X object = NULL ;
X/* if he left off the verb, we let him come back here to say it.
X */
Xgetvrb: ;
X/* check if this place is eligible for any hints. If the sucker has been
X * here long enough, perform the help section.
X */
X { register struct hint *hint;
X for (hint = hints+4; hint->turns != -1; ++hint) {
X if (!(hint->hinted)) {
X if (!(loc->flags & hint->bit)) hint->lc = -1 ;
X ++(hint->lc);
X if (hint->lc >= hint->turns) dohint(hint);
X }
X }
X } /* end of hint block */
X
X/* if closing this turn, check for any objects being toted with prop<0.
X * set the prop to -1-prop. This way objects won't be described until
X * they've been picked up and put down separate from their respective
X * piles. Don't let any of this happen unless well into the cave.
X */
X if (closed) {
X register struct cvobj *adobj;
X for (adobj=cvobj;adobj->desc != NULL; ++adobj)
X if (TOTING(adobj) && (adobj->prop < 0))
X adobj->prop = -adobj->prop - 1;
X }
X
X wzdark = DARK ;
X
X if ((knfloc != LOST) & (knfloc != loc)) knfloc = FIXED;
X
X/* get input */
X getin() ; /* set word1, word2 */
X
X if (!(turns++)
X && !strcmp("magic",word1)
X && !strcmp("mode",word2) )
X { maint(argv[0]); }
X
X/* demo games are ended by the wizard */
X if (demo && (turns >= SHORT))
X { mspeak(1);
X {finish = TRUE; continue; };
X }
X
X if (samvrb) verb = oldvrb ;
X
X if ((verb == SAY) && (word2 != NULL)) verb = 0 ;
X if (verb == SAY) goto process ;
X
X/* detect closing, closed, etc */
X if ((LNUM(loc) >= 31) && !tally && !(--clock1))
X { register struct monster *cre;
X
X DOOR->prop = 0;
X if (O_GATE->prop != 2) O_GATE->prop = 3;
X for (cre = orcs; cre->iloc != -1; ++cre)
X { cre->dloc = DEAD ;
X cre->dseen = FALSE ;
X }
X if (BEAR->prop) destry(BEAR);
X if (CHAIN->prop == 2) CHAIN->prop = 1;
X AXE->prop = 0 ;
X AXE->conn2.where = DEAD;
X rspeak(129);
X clock1 = -1;
X closing = TRUE ;
X }
X
X if (clock1 < 0 && !(--clock2))
X { register struct cvobj *curobj;
X loc = oldloc = newloc = OFFICE ;
X /* Put him there "naked" except for compass */
X for (curobj=cvobj; curobj->desc != NULL; ++curobj) {
X if (TOTING(curobj) && curobj != COMPASS)
X destry(curobj);
X }
X move(AXE,REPOS);
X rspeak(132);
X closed = TRUE;
X {locchg(); continue; };
X }
X
X/* one way to get to the end of the game is for the lamp to give out.
X * When it gets close, we warn him. If the lamp and fresh batteries are
X * handy, we replace the batteries for him. Otherwise, he may be in
X * trouble, depending on where he is.
X */
X if ((LAMP->prop == 1)
X && (--limit <= 30)
X && HERE(BATTER)
X && !(BATTER->prop)
X && HERE(LAMP) )
X { rspeak(188);
X BATTER->prop = 1 ;
X if (TOTING(BATTER)) move(BATTER,loc) ;
X limit += 500 ;
X lmwarn = FALSE ;
X }
X
X/* if lamp runs out */
X if (!limit)
X { limit = -1;
X LAMP->prop = 0 ;
X if (HERE(LAMP)) rspeak(184) ;
X }
X
X/* if it's dark and he's outside the cave proper, he just gives up */
X if ((limit < 0) && (LNUM(loc) <= 30))
X { rspeak(185) ;
X gaveup = TRUE;
X {finish = TRUE; continue; } ;
X }
X
X/* give warning about dim lamp */
X if ((limit <= 30) && HERE(LAMP) && !lmwarn)
X { lmwarn = TRUE ;
X if ((BATTER->prop == 1) || (BATTER->conn1.where == LOST))
X rspeak(189);
X else if (BATTER->prop == 0)
X rspeak(183);
X else
X rspeak(187);
X }
X
X/* now for the real work: we have to figure out what he means by what
X * he just said.
X */
X for ( ; word1 != NULL; word1=word2, word2=NULL)
X { register int i;
X
X if (!strcmp(word1,"north"))
X if (++inorth == 10) rspeak(17);
X i = vocab(word1,-1);
X if (i == -1)
X { what(TRUE); /* some form of not understanding */
X goto huh;
X }
X/* if he says ENTER, he may not really go anywhere because of some special
X * cases. Going into the water just gets him wet. Going into the boat
X * is treated as "take boat", so we change his verb.
X */
X if ((i == ENTER)
X && (word2 != NULL))
X { if (!strcmp(word2,"stream")
X || !strcmp(word2,"water")
X || !strcmp(word2,"river") )
X { if (LIQLOC(loc) == _WATER)
X rspeak(70); /* wet feet! */
X else
X rspeak(43); /* Where? */
X goto okay ; /* maybe this should just be moved */
X }
X else if (!strcmp(word2,"boat"))
X { obj = _BOAT;
X object = OBJ(obj) ;
X i = TAKE;
X }
X }
X
X switch(i/1000)
X {
X/* this is one of the big holes in the parser here. Motion words are
X * hardly checked for syntax at all. The object is usually not even
X * looked at, if given. There are just a few special cases, and they
X * do not go through the normal vocabulary stuff.
X */
X case 0: /* motion word */
X if (obj || (verb && (verb != WALK)))
X {what(FALSE); goto huh; }
X if ((i == OUT) && (!strcmp(word2,"boat")))
X { i = DROP ; } /* deal with word ambiguity here */
X if (i == OUT
X && TOTING(BOAT)
X && (word2 == NULL || !strcmp(word2,""))
X && obj == 0) {
X i = DROP ;
X object = OBJ(obj = _BOAT);
X }
X verb = i ; /* this sets dispatch switch */
X break;
X
X/* for objects, we make sure that there are not two objects being named,
X * and that the object is here. Also, if there's another word, we clear
X * 'verb' which may have been set by the operation of 'samvrb'.
X */
X case 1: /* object */
X oword = word1;
X if (obj != i)
X { if (obj
X || (verb && (word2 != NULL)))
X { what(FALSE); /* don't understand */
X goto huh;
X }
X }
X object = OBJ(obj = i) ;
X if (word2 != NULL) verb = 0; /* defeat samvrb */
X
X if ((object->conn2.where != loc)
X && !HERE(object)) /* object maybe not here */
X { register int flag;
X flag = FALSE ;
X if ((obj == _DWARF) && (dflag > 1))
X { register struct monster *cre;
X for (cre = orcs; cre->iloc >= 0; ++cre)
X { if (cre->dloc == loc)
X { flag = TRUE ;
X break;
X }
X }
X }
X if (flag
X || (obj == LIQLOC(loc))
X || ((obj == LIQ(BOTTLE)) && HERE(BOTTLE))
X || ((obj == LIQ(CUP)) && HERE(CUP) )
X || ((object == SPIDER)
X && (GRENDL->dloc == loc))
X || ((object == DRAGON)
X && (PUFF->dloc == loc))
X || ((object == DJINN)
X && (JEANNIE->dloc == loc))
X || ((object == KOBOLD)
X && (SLASHER->dloc == loc))
X || ((object == BALROG)
X && (BALLY->dloc == loc))
X || ((object == SELF)
X && (ME->dloc == loc))
X )
X ; /* okay to keep going */
X else if ((object == KNIFE)
X && (knfloc == loc))
X { knfloc = LOST;
X rspeak(116); /* sorry about them knives */
X goto okay ;
X } else if ((object == ROPE)
X && (HERE(ROPE2)))
X { object = ROPE2 ;
X ; /* substitute the "other" rope */
X } else if ((object == ROPE)
X && (HERE(EROPE)))
X { object = EROPE ;
X } else if ((object == ROPE)
X && (HERE(EROPE2)))
X { object = EROPE2;
X } else if ( (word2 == NULL)
X && ((verb == FIND)
X || (verb == INVENT)
X || (verb == DESCRB)
X || (verb == TOUCH) ) )
X { ; /* allow questions about things not here */
X } else {
X if (!verb && (word2 == NULL))
X /* this test is sensitive to verb funnies */
X { register int k;
X if ((k=vocab(word1,3)) > 0)
X { rspeak(k%1000); /* word has msg num */
X goto okay ;
X }
X }
X goto dark;
X }
X } /* end of the case the object is not here */
X
X if ((object == TOMB) && (HELM->prop))
X object = HELM ; /* actually a synonym */
X if (word2 != NULL) break;
X if (verb) break ;
X { register int k;
X if ((k=vocab(word1,3)) >0)
X { rspeak(k%1000); /* word has msg num in it */
X goto okay;
X }
X }
X capchk(word1); /* capitialize some proper nouns */
X (void) printf(
X"What do you want to do with the %s?",word1);
X mltcmd = FALSE ;
X goto getvrb ;
X
X case 2: /* action (verb) */
X vword = word1;
X if ((verb == TAKE)
X && ((i == INVENT)
X || (i == verb)))
X { verb = 0; /* destroy old verb */
X }
X if (verb && !obj && (word2 == NULL))
X { what(FALSE); /* two verbs */
X goto huh;
X }
X if (word2 != NULL) {obj = 0 ; object = NULL ; }
X verb = i;
X if (word2 != NULL)
X if (verb == SAY)
X { obj = 1;
X goto process;
X }
X break;
X
X case 3: /* special (just gets message) */
X verb = i ; /* this sets dispatch switch */
X break;
X } /* end of word-type switch */
X } /* end of word analysis */
X
X } /* end of getting new instructions (motion not forced) */
Xprocess:
X switch (verb/1000)
X {
X case 0: /* motion verb */
X newloc = moveme(loc,verb) ;
X locchg();
X continue ;
X
X case 2: /* true verb */
X if (verb == SAY) {
X if (word2 != NULL) word1 = word2;
X obj = vocab(word1,-1); /* what would happen? */
X if (obj == HOPE || obj == BANIS || obj == MISFO) {
X verb = obj; obj = 0; object = NULL;
X } else {
X printf("Okay, \"%s\".\n",word1);
X goto okay;
X }
X }
X switch (cvact(verb,obj,object))
X {
X case S_okay: goto okay;
X case S_miss: goto miss;
X case S_move: break;
X case S_obj: goto newobj;
X case S_what: *vword = toupper(*vword);
X printf("%s what?\n",vword);
X mltcmd = FALSE;
X goto newobj;
X case S_light: if (!DARK && wzdark) continue;
X goto okay;
X case S_show: continue;
X case S_dark: goto dark;
X default: bug(40);
X }
X locchg();
X continue;
X
X case 3: /* magic word */
X rspeak(verb%1000);
X goto okay;
X
X default: /* how could this be? */
X bug(1);
X }
X } /* end of motion loop */
X
X getscore();
X (void) printf("\nYou scored %d out of a possible %d, using %d turns.\n",
X score,mxscore,turns);
X { register struct cmsg *cmsg;
X for (cmsg = ctext;cmsg->score != -1; ++cmsg) ;
X for (--cmsg; cmsg - ctext; --cmsg) {
X if (cmsg->score <= 0) cmsg->score += mxscore ;
X if (cmsg->score <= score) break;
X }
X (void) fputs(cmsg->msg,stdout);
X if ((cmsg+1)->score == -1) {
X (void) fputs("To achieve the next higher rating would be a\
X neat trick!\n\n Congratulations!\n",stdout);
X }else{
X (void) printf("To achieve the next higher rating, you need %d \
Xmore point%s.\n",(cmsg+1)->score - score, ((cmsg+1)->score - score > 1) ?
X "s" : "");
X }
X } /* end of figuring the appropriate message */
X
X puts("\nTouch ENTER to continue.\n");
X { auto char answer[5];
X fgets(answer,4,stdin);
X }
X}
END_OF_cvmain.c
if test 23773 -ne `wc -c <cvmain.c`; then
echo shar: \"cvmain.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cvocab.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"cvocab.h\"
else
echo shar: Extracting \"cvocab.h\" \(4846 characters\)
sed "s/^X//" >cvocab.h <<'END_OF_cvocab.h'
X/* cvocab.h
X * the crystal cave vocabulary
X ************************************************************************/
X
Xstruct cvocab {
X int cvcode ;
X char *cvword ; } ;
X
X#define NORTH 2
X#define NE 3
X#define EAST 4
X#define SE 5
X#define SOUTH 6
X#define SW 7
X#define WEST 8
X#define NW 9
X#define UP 10
X#define DOWN 11
X#define OUT 12
X#define IN 13
X#define ENTER 14
X#define JUMP 15
X#define BARN 16
X#define PRIVY 17
X#define SHAFT 18
X#define SINKH 19
X#define PIGPE 20
X#define BLUFF 21
X#define HEADQ 22
X#define M_GATE 23
X#define LAKE 24
X#define FIELD 25
X#define BACK 27
X#define WAIT 28
X#define CROSS 29
X#define HOPE 30
X#define UPSTR 31
X#define DOWNS 32
X#define CLIMB 33
X#define PATH 34
X#define PAST 35
X#define FUTUR 36
X#define BANIS 37
X#define MISFO 38
X
X/* some objects */
X
X#define MINTRS (&(cvobj[1]))
X#define _JEWLRY 1003
X#define _CHEST 1005
X#define _CAPE 1006
X#define _CROWN 1007
X#define _SCEPT 1008
X#define _ORB 1010
X#define _IDOL 1011
X#define _RUG 1012
X#define _UNICRN 1013
X#define _CHAIN 1014
X#define _RING 1015
X#define _HELM 1016
X#define _THRONE 1018
X#define _SWORD 1019
X#define _HAMMER 1020
X#define _CUP 1021
X#define _MEDAL 1022
X#define _SCROLL 1023
X#define _HARP 1024
X#define _STONE 1025
X#define _KEG 1026
X#define ENDTRS OBJ(1027)
X#define IFTREAS(o) ((o) < ENDTRS)
X
X#define MINWPN OBJ(1027)
X#define MAXWPN OBJ(1034)
X
X#define MINART OBJ(1040)
X#define _COLUMN 1040
X#define MAXART OBJ(1047)
X
X#define _COMPASS 1050
X#define _KEY 1051
X#define _LAMP 1052
X#define _RICK 1053
X#define _SEARS 1054
X#define _WALLET 1055
X#define _DOOR 1056
X#define _BRIDGE 1057
X#define _BOAT 1058
X#define _DAM 1059
X#define _O_GATE 1060
X#define _ROPE 1061
X#define _ROPE2 (_ROPE+1)
X#define _EROPE (_ROPE+2)
X#define _EROPE2 (_ROPE+3)
X#define _SPICE 1067
X#define _KNIFE 1068
X#define _FOOD 1069
X#define _BOTTLE 1070
X#define _WATER 1071
X#define _WINE 1072
X#define _COLA 1073
X#define _MIRROR 1074
X#define _GIANT 1075
X#define _ORCS 1076
X#define _TOMB 1077
X#define _AXE 1078
X#define _TOAD 1079
X#define _SAND 1080
X#define _SHELF 1081
X#define _HANG 1082
X#define _CRAP 1086
X#define _SHOWER 1087
X#define _VEND 1088
X#define _BATTER 1089
X#define _DWARF 1090
X#define _BEAR 1091
X#define _SKELTN 1092
X#define _SPIDER 1093
X#define _DRAGON 1094
X#define _DJINN 1095
X#define _KOBOLD 1096
X#define _BALROG 1097
X#define _SELF 1098
X
X/* verb section */
X
X#define TAKE 2001
X#define DROP 2002
X#define ON 2003
X#define OFF 2004
X#define UNLOC 2005
X#define LOCK 2006
X#define SAY 2007
X#define RUB 2008
X#define FIND 2009
X#define INVENT 2010
X#define QUIT 2011
X#define SCORE 2012
X#define NOTHI 2013
X#define SAVE 2014
X#define BRIEF 2015
X/* HOURS not implemented */
X#define THROW 2017
X#define WALK 2018
X#define PAY 2019
X#define BREAK 2020
X#define DRINK 2021
X#define EAT 2022
X#define READ 2023
X#define TIE 2024
X#define UNTIE 2025
X#define FEED 2026
X#define POUR 2027
X#define KILL 2028
X#define RIG 2029
X#define CUT 2030
X#define FILL 2031
X#define TEST 2032
X#define BLAST 2033
X#define WAVE 2034
X#define SIT 2035
X#define CALM 2036
X#define FLY 2037
X#define WAKE 2038
X#define DESCRB 2039
X#define TOUCH 2040
X#define PLAY 2041
X#define RESTOR 2042
X#define HELP 2043
X
X/* define object references */
X
X#define OBJ(o) (&(cvobj[(o) % 1000]))
X
X#define JEWLRY OBJ(_JEWLRY)
X#define CHEST OBJ(_CHEST)
X#define CAPE OBJ(_CAPE)
X#define CROWN OBJ(_CROWN)
X#define SCEPT OBJ(_SCEPT)
X#define ORB OBJ(_ORB)
X#define IDOL OBJ(_IDOL)
X#define RUG OBJ(_RUG)
X#define UNICRN OBJ(_UNICRN)
X#define CHAIN OBJ(_CHAIN)
X#define RING OBJ(_RING)
X#define HELM OBJ(_HELM)
X#define THRONE OBJ(_THRONE)
X#define SWORD OBJ(_SWORD)
X#define HAMMER OBJ(_HAMMER)
X#define CUP OBJ(_CUP)
X#define MEDAL OBJ(_MEDAL)
X#define SCROLL OBJ(_SCROLL)
X#define HARP OBJ(_HARP)
X#define STONE OBJ(_STONE)
X#define KEG OBJ(_KEG)
X#define COLUMN OBJ(_COLUMN)
X#define COMPASS OBJ(_COMPASS)
X#define KEY OBJ(_KEY)
X#define LAMP OBJ(_LAMP)
X#define RICK OBJ(_RICK)
X#define SEARS OBJ(_SEARS)
X#define WALLET OBJ(_WALLET)
X#define DOOR OBJ(_DOOR)
X#define BRIDGE OBJ(_BRIDGE)
X#define BOAT OBJ(_BOAT)
X#define DAM OBJ(_DAM)
X#define O_GATE OBJ(_O_GATE)
X#define ROPE OBJ(_ROPE)
X#define ROPE2 OBJ(_ROPE2)
X#define EROPE OBJ(_EROPE)
X#define EROPE2 OBJ(_EROPE2)
X#define SPICE OBJ(_SPICE)
X#define KNIFE OBJ(_KNIFE)
X#define FOOD OBJ(_FOOD)
X#define BOTTLE OBJ(_BOTTLE)
X#define WATER OBJ(_WATER)
X#define WINE OBJ(_WINE)
X#define COLA OBJ(_COLA)
X#define MIRROR OBJ(_MIRROR)
X#define GIANT OBJ(_GIANT)
X#define ORCS OBJ(_ORCS)
X#define TOMB OBJ(_TOMB)
X#define AXE OBJ(_AXE)
X#define TOAD OBJ(_TOAD)
X#define SAND OBJ(_SAND)
X#define SHELF OBJ(_SHELF)
X#define HANG OBJ(_HANG)
X#define CRAP OBJ(_CRAP)
X#define SHOWER OBJ(_SHOWER)
X#define VEND OBJ(_VEND)
X#define BATTER OBJ(_BATTER)
X#define DWARF OBJ(_DWARF)
X#define BEAR OBJ(_BEAR)
X#define SKELTN OBJ(_SKELTN)
X#define SPIDER OBJ(_SPIDER)
X#define DRAGON OBJ(_DRAGON)
X#define DJINN OBJ(_DJINN)
X#define KOBOLD OBJ(_KOBOLD)
X#define BALROG OBJ(_BALROG)
X#define SELF OBJ(_SELF)
END_OF_cvocab.h
if test 4846 -ne `wc -c <cvocab.h`; then
echo shar: \"cvocab.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 3 \(of 5\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 5 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0