[comp.sources.games] v03i035: crystal - another adventure game, Part03/05

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