DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T c

⟦bb04ffc03⟧ TextFile

    Length: 23773 (0x5cdd)
    Types: TextFile
    Names: »cvmain.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Crystal/cvmain.c« 

TextFile

/* cvmain.c
 ************************************************************************/

#define	SHORT	50

#include	<stdio.h>
#include	<string.h>
#include	<fcntl.h>
#include	"cvobj.h"
#include	"cvlocs.h"
#include	"cvocab.h"
#include	"cvmsg.h"
#include	"random.h"
#include	"cvorcs.h"
#include	"cvmisc.h"
#include	"cvcode.h"

extern char etext;
extern char edata;
extern char end;
extern char _etext;
extern char _edata;
extern char _end;

extern char *rmsg[] ;
extern int actspk[] ;
extern struct cmsg ctext[] ;
extern struct cvocab vtab [] ;
extern int maxloc ;
extern void exit();
extern void carry();
extern void move();
extern void move2();
extern void destry();
extern void getin();
extern void juggle();
extern void juggl2();
extern void checkobj();
extern void checkloc();
extern void fixrmsg();
extern void motd();
extern void rspeak();
extern void pspeak();
extern void mspeak();
extern void putcode();
extern int yes();
extern struct cvloc *moveme();

int saved = 0;	/* this defines the un-initialized state */

char *word1, *word2;
char *vword, *oword;

struct cvobj *lastobj ;
struct cvloc *loc = NULL;
struct cvloc *newloc, *oldloc, *knfloc, *oldlc2;
int	dflag = 0,
	demo = 0,
	score = 0,
	mxscore = 0,
	limit = 0,			/* how long his lamp will last on current power */
	setup = 0,			/* state of setup */
	tally = 0,			/* count of treasures yet to see */
	tally2 = 0,			/* count of treasures you'll never see */
	inorth = 0,		/* # of times he said NORTH instead of N */
	detail = 0,		/* # of times we said "not allowed . .  */
	numdie = 0,		/* # of times he died so far */
	maxdie = 0,		/* # of ways to resurrect him */
	holding = 0,		/* # objects he's carrying */
	dkill = 0,			/* # of dwarves killed */
	turns = 0,
	nxtchr = 0,
	abbnum = 0,		/* how often he gets long description */
	clock1 = 0,		/* time from last treasure to closing */
	clock2 = 0,		/* time from closing to closed */
		/* LOGICALS FOLLOW */
	bonus = FALSE,			/* gets bonus for correct finish */
	closing = FALSE,		/* are we closing? */
	panic = FALSE,			/* has he panicked */
	wzdark = FALSE,
	closed = FALSE,
	gaveup = FALSE,
	scoring = FALSE,
	mltcmd = FALSE,
	blklin = FALSE,
	samvrb = FALSE,
	finish = FALSE,
	lmwarn = FALSE;

\f


struct monster orcs[] = {
	{0},	/* spider */	/* monsters first */
	{0},	/* dragon */
	{0},	/* king */
	{0},	/* djinni */
	{0},	/* kobold */
	{0},	/* bugbear */
	{0},	/* unicorn */
	{0},	/* giant orc */
	{0},	/* balrog */
	{62,1},	/* dwarf in pool hall */	/* dwarves next */
	{78,1},	/* dwarf in privy chamber */
	{85,1},	/* dwarf at window in secret passage */
	{100,1},	/* dwarf in the time maze */
	{126,1},	/* dwarf in the harem */
	{130,1},	/* dwarf at the shelf */
	{87},	/* pirate at where he hides his chest */	/* then these */
	{0},	/* *YOU* */
	{-1}};

\f


void
locchg()
{
		if (dodwarf()) die();
}

static void
dohint(hint) register struct hint *hint;
{
	switch (hint-hints) {
	case 4:	if (O_GATE->prop != 0 || HERE(WALLET)) hint->lc = 0;
		break;
	case 5: if (DAM->prop != 0) hint->lc = 0;
		break;
	case 6: if (holding <= 1 || loc->atloc.link != NULL ||
				oldlc2->atloc.link != NULL || oldloc->atloc.link != NULL)
				hint->lc = 0;
		break;
	} /* end of switch for special tests */
	if (hint->lc == 0) return;
	hint->lc = 0;
	if (!yes(hint->quest,0,54)) return;
	printf("I am prepared to give you a hint, but it will cost you %d \
points.",hint->points);
	hint->hinted = yes(175,hint->hmsg,54);
	if (hint->hinted && limit>30) limit += 30*hint->points;
	return;
}
void
bug(num) int num;
{	register long a;
	(void) printf("\nFatal error number %d, see source code for\n\
interpretation.\n",num);
	a = *((long *) 1);
	exit(1);
}

void
mkill(monster,object) register struct monster *monster;
	register struct cvobj *object;
{
	object->prop = 0;
	move(object,loc);
	object->conn2.where = FIXED ;
	monster->dseen = FALSE ;
	monster->dloc = DEAD ;
}

void
showroom() {
	putcode(( !(loc->abb++ % abbnum) || (loc->sdesc == NULL))
				? loc->ldesc : loc->sdesc);
}

void
what(word) register int word;
{	if (word && PCT(60)) {rspeak(60); return;}
	if (PCT(20)) {rspeak(61); return;}
	rspeak(13); return;
}

static void
capchk(word) register char *word;
{
	if (!strcmp(word,"indian")
		|| !strcmp(word,"persian")
		|| !strcmp(word,"coke")
		|| !strcmp(word,"kobold")
		|| !strcmp(word,"balrog")
		|| !strcmp(word,"sears")
		|| !strcmp(word,"rick") )
	{	*word = toupper(*word);
	}
}
\f


main(argc, argv)
int argc;
char * argv[];
{
	{	register int r;
		if (!saved && argc == 2) {
			cvinit(argc,argv);
			exit(0);
		} else if (argc != 1 || saved != 1) {
			exit(1);
		}
	}
/**********
 * do initialization (some of it just in case):
 * set all objects
 *   nowhere (both ways)
 *   to their initial properties
 *   not linked to any location
 * set all locations
 *   to get long message next
 *   to have flags = C_FORCED if there's a forced motion
 ***********/
	{	register struct cvobj *object;
		for (object = &(cvobj[1]); object->desc != NULL ; object++ )
		{	object->conn1.where = object->conn2.where = LOST ;
			object->prop = object->iprop ;
			object->conn1.link  = object->conn2.link  = NULL ;
			object->conn1.who   = object->conn2.who   = object ;
			object->conn1.where = object->conn2.where = LOST ;
		}
		lastobj = object - 1 ;
	}

	{	register struct cvloc *curloc;

		for (curloc = &cvloc[1]; curloc->travel != NULL; curloc++ )
		{	register struct cvtrav *curtrv;
			curloc->abb = 0;
			curloc->atloc.link = NULL ;
			curtrv = curloc->travel ;
			if (curtrv->word == 1)
				curloc->flags = C_FORCED ;
		}
	}

/************
 * set up the location arrays to that objects are at their indicated
 * places.  We use drop, which puts things on the head of the list, so
 * we run this backwards.  Things with two locations are dropped twice,
 * and since these are normally best described last, we do them first.
 ************/
	{	register struct cvobj *object;
#define	ILOC(obj)	(((obj)->iloc) ? (&(cvloc[(obj)->iloc])) : LOST )
		for (object = lastobj; ONUM(object); object--)
		{	if (object->iloc2 > 0 )
			{	move2(object,&(cvloc[object->iloc2]));
				move(object, ILOC(object) );
			}
		}

		for (object = lastobj; ONUM(object); object-- )
		{	if (object->iloc2 <= 0 )
			{	move(object, ILOC(object) );
				object->conn2.where = object->iloc2 ? FIXED : LOST;
			}
		}
	}

/*************************************************************************
 * clear the hint stuff.  loc is how long he's been at a loc with the
 * cond bit set.  hinted is true if the hint has already been given.
 *************************************************************************/
	{	register struct hint *hint;

		for (hint = hints; hint->turns >= 0; ++hint)
		{	hint->lc = 0;
			hint->hinted = FALSE ;
		}
	}

/*************************************************************************
 * initialize the monsters.
 * they are all known generically as dwarves because they all move like
 * dwarves, though the adventurer never really knows this.
 *
 * dloc is current location
 * oloc is old location
 * dseen is a flag.  If on, this dwarf has the adventurer in sight and
 *    is in hot pursuit.
 * dflag indicates the level of activity:
 *	0	no monster stuff yet (wait until pool hall is reached)
 *	1	no monsters met yet (thus, no axe)
 *	2	have axe, but no knives yet.  most dwarves moving.
 *	3	first knives thrown (first set always miss)
 *	3+	dwarves are mad (and thus more accurate)
 * some dwarves don't look much like dwarves
 *	1	is grendl the spider
 *	2	is the dragon
 *	3	is the king
 * 	4	is the djinni
 * 	5	is the kobold
 *	6	is the bugbear
 *	7	is the unicorn
 *	8	is the giant orc
 *	9	is the balrog
 *	10-15	are just dwarves
 *	16	is the pirate.
 *	17	is *you*
 * no two of the initial locations for 10-16 are adjacent.  The others
 * only start as part of a pre-set encounter.
 *************************************************************************/

	dflag = 0;

	{	register struct monster *cre;

		for (cre = orcs ; (cre->iloc) != -1; cre++) {
			cre->dloc = &cvloc[cre->iloc] ;
			cre->dseen = FALSE ;
		}
	}

/*************************************************************************
 * 'tally' keeps track of how many treasures are yet to be found so we
 * know when to close the cave.  'tally2' keeps track of how many can
 * never be found because the adventurer klutzed out (e.g. lost the
 * scroll in the maze).
 * ***** tally2 is not yet implemented *****
 * the objects must be assigned numbers in the following order
 *	treasures
 *	end-game weapons
 *	artifacts in outer cave
 *	other objects
 *************************************************************************/
	tally = tally2 = 0 ;
	
	{	register struct cvobj *object;
		for (object = MINTRS ; object != ENDTRS ; ++object ) {
			object->prop = -1 ;
			++tally ;
		}
	}

	BATTER->prop = -1 ;
	oldlc2 =
	knfloc = LOST ;

	inorth =		/* # of times he said NORTH instead of N */
	detail =		/* # of times we said "not allowed . .  */
	numdie =		/* # of times he died so far */
	holding =		/* # objects he's carrying */
	dkill =			/* # of dwarves killed */
	turns =
	nxtchr = 0;

	abbnum = 5 ;		/* how often he gets long description */

	clock1 = 30 ;		/* time from last treasure to closing */
	clock2 = 50 ;		/* time from closing to closed */

	bonus =			/* gets bonus for correct finish */
	closing =		/* are we closing? */
	panic =			/* has he panicked */
	closed =
	gaveup =
	scoring =
	mltcmd =
	samvrb =
	finish =
	lmwarn = FALSE ;

	{	register int i;
		for (i=0 ; i<=4; ++i)
			if ( rmsg[2*i+81] != NULL ) maxdie = i+1 ;
	}

	saved = saved == 1 ? -1 : 2 ;
/*************************************************************************
 * OK, we're close now.  Get a couple more things set.
 *************************************************************************/
	demo = FALSE;		/* everyone's a class 1 user here */
	motd(FALSE);		/* message of the day? */
	hints[3].hinted = yes(65,1,0);	/* instructions? */
	newloc = &(cvloc[1]) ;		/* start here */
	oldloc = DEAD ;		/* make lint happy */
	wzdark = FALSE ;
	setup = 3 ;			/* in full swing */
	limit = hints[3].hinted ? 1000 : 330 ;
	juggl2(O_GATE);
	juggle(BEAR);
	juggle(HANG);

/*************************************************************************
 * begin the real stuff
 *************************************************************************/

	dodwarf();
	while (!finish)  /* motion loop */
	{	register struct cvobj *object;
		int verb, oldvrb, obj ;

		blklin = TRUE ;
		if (loc == DEAD) {die(); continue; } ;
		if (FORCED(loc)) {
			showroom();
			verb = 1; /* for the benefit of a later switch */
		} else { /* motion not forced */
			if (DARK) {
				if (wzdark && PCT(35)) {
					rspeak(23);
					oldlc2 = loc;
					{die(); continue; };
				} else rspeak(16);
			} else { /* not dark: describe objects found here */
				register struct conn *curcon, *lastcon;
				if (DARKRM)
					pspeak(UNICRN,6); /* that must be the light */
				showroom();
				if (TOTING(BOAT)) pspeak(BOAT,BOAT->prop);
				if (TOTING(RUG) && (RUG->prop == 1)) pspeak(RUG,1);
				curcon = &(loc->atloc);
				while (curcon->link != NULL) {
					register struct cvobj *adobj;
					register int i;
					lastcon = curcon;
					curcon = curcon->link ;
					adobj = curcon->who ;
					if (curcon->where != loc) bug(32);
					if (adobj->prop < 0) {
						adobj->prop = adobj->iprop;
						if (IFTREAS(adobj)) --tally;
						if ((tally == tally2) && tally)
							limit = MIN(limit,35);
					}
					i = adobj->prop ;
/* handle special cases */
/* tell about the inside of the gate, if the dummy's there */
					if ((adobj == O_GATE)
						&& (O_GATE->conn2.where == loc))
						i = 1;
/* funny way to tell what happened to the container */
					if (((adobj == CUP) || (adobj == BOTTLE))
						&& (adobj->conn2.where == FIXED)
						&& (BEAR->prop == 0)
						&& (HERE(BEAR)) ) i = 13 ;
					pspeak(adobj,i) ;
					blklin = FALSE ;
/* seeing the poo close up means there are footprints in it */
					if (adobj == CRAP) adobj->prop = 1 ;
/* remove ranger from gate after the first time he's seen */
					if (adobj == RICK) {
						RICK->prop++ ;
						destry(RICK);
						curcon = lastcon;
					}
				} /* end showing adobjs */	
			} /* end describing objects here */
			goto okay;

/* stuff for when you can't find the indicated object (it may be too dark)
*/
dark:		;
			capchk(word1);	/* capitalize some proper nouns */
			(void) printf("I see no %s here.\n",word1);
			mltcmd = FALSE ;
/* loop here when you say "okay" and such -- less dangerous place than
 * most, but still must watch the skeleton, the lamp, etc.
 */
okay:			;
			blklin = TRUE ;
/* if the skeleton's active, it can kill you */
			if (SKELTN->prop == 1) {
				if (PCT(25)) {
					rspeak(102);
					oldlc2 = loc ;
					{die(); continue; };
				}
				rspeak(101);
			}

miss:		if (TOTING(MEDAL) && (loc->flags & SECRET)) rspeak(112);

			if ((loc->flags & RANGER)
				&& (RICK->prop == 0)
				&& (DAM->prop == 0)
				&& (PCT(25) || (loc->atloc.link != NULL))
				) {
				pspeak(RICK,6);
				RICK->prop = 3;
				destry(RICK);
				loc = &(cvloc[O_GATE->iloc]);
				break;
			}

/* finds you hanging in there? */
			if ((LNUM(loc) == 144) && PCT(25)) {
				rspeak(217) ;
				if (PCT(50)) rspeak(218);
			}

/* when we don't understand, we come back here for a relatively safe retry.
 */
huh:		oldvrb = verb ;
			verb = 0;
newobj:		obj = 0;
			object = NULL ;
/* if he left off the verb, we let him come back here to say it.
 */
getvrb:			;
/* check if this place is eligible for any hints.  If the sucker has been
 * here long enough, perform the help section.
 */
			{	register struct hint *hint;
				for (hint = hints+4; hint->turns != -1; ++hint) {
					if (!(hint->hinted)) {
						if (!(loc->flags & hint->bit)) hint->lc = -1 ;
						++(hint->lc);
						if (hint->lc >= hint->turns) dohint(hint);
					}
				}
			} /* end of hint block */

/* if closing this turn, check for any objects being toted with prop<0.
 * set the prop to -1-prop.  This way objects won't be described until
 * they've been picked up and put down separate from their respective
 * piles.  Don't let any of this happen unless well into the cave.
 */
			if (closed) {
				register struct cvobj *adobj;
				for (adobj=cvobj;adobj->desc != NULL; ++adobj)
					if (TOTING(adobj) && (adobj->prop < 0))
						adobj->prop = -adobj->prop - 1;
			}

			wzdark = DARK ;

			if ((knfloc != LOST) & (knfloc != loc)) knfloc = FIXED;

/* get input */
			getin() ; /* set word1, word2 */

			if (!(turns++)
				&& !strcmp("magic",word1)
				&& !strcmp("mode",word2) )
			{	maint(argv[0]); }
			
/* demo games are ended by the wizard */
			if (demo && (turns >= SHORT))
			{	mspeak(1);
				{finish = TRUE; continue; };
			}

			if (samvrb) verb = oldvrb ;

			if ((verb == SAY) && (word2 != NULL)) verb = 0 ;
			if (verb == SAY) goto process ;

/* detect closing, closed, etc */
			if ((LNUM(loc) >= 31) && !tally && !(--clock1))
			{	register struct monster *cre;

				DOOR->prop = 0;
				if (O_GATE->prop != 2) O_GATE->prop = 3;
				for (cre = orcs; cre->iloc != -1; ++cre)
				{	cre->dloc = DEAD ;
					cre->dseen = FALSE ;
				}
				if (BEAR->prop) destry(BEAR);
				if (CHAIN->prop == 2) CHAIN->prop = 1;
				AXE->prop = 0 ;
				AXE->conn2.where = DEAD;
				rspeak(129);
				clock1 = -1;
				closing = TRUE ;
			}

			if (clock1 < 0 && !(--clock2))
			{	register struct cvobj *curobj;
				loc = oldloc = newloc = OFFICE ;
				/* Put him there "naked" except for compass */
				for (curobj=cvobj; curobj->desc != NULL; ++curobj) {
					if (TOTING(curobj) && curobj != COMPASS)
						destry(curobj);	
				}
				move(AXE,REPOS);
				rspeak(132);
				closed = TRUE;
				{locchg(); continue; };
			}

/* one way to get to the end of the game is for the lamp to give out.
 * When it gets close, we warn him.  If the lamp and fresh batteries are
 * handy, we replace the batteries for him.  Otherwise, he may be in
 * trouble, depending on where he is.
 */
			if ((LAMP->prop == 1)
				&& (--limit <= 30)
				&& HERE(BATTER)
				&& !(BATTER->prop)
				&& HERE(LAMP) )
			{	rspeak(188);
				BATTER->prop = 1 ;
				if (TOTING(BATTER)) move(BATTER,loc) ;
				limit += 500 ;
				lmwarn = FALSE ;
			}

/* if lamp runs out */
			if (!limit)
			{	limit = -1;
				LAMP->prop = 0 ;
				if (HERE(LAMP)) rspeak(184) ;
			}

/* if it's dark and he's outside the cave proper, he just gives up */
			if ((limit < 0) && (LNUM(loc) <= 30))
			{	rspeak(185) ;
				gaveup = TRUE;
				{finish = TRUE; continue; } ;
			}

/* give warning about dim lamp */
			if ((limit <= 30) && HERE(LAMP) && !lmwarn)
			{	lmwarn = TRUE ;
				if ((BATTER->prop == 1) || (BATTER->conn1.where == LOST))
					rspeak(189);
				else if (BATTER->prop == 0)
					rspeak(183);
				else
					rspeak(187);
			}

/* now for the real work: we have to figure out what he means by what
 * he just said.
 */
			for ( ; word1 != NULL; word1=word2, word2=NULL)
			{	register int i;

				if (!strcmp(word1,"north"))
					if (++inorth == 10) rspeak(17);
				i = vocab(word1,-1);
				if (i == -1)
				{	what(TRUE); /* some form of not understanding */
					goto huh;
				}
/* if he says ENTER, he may not really go anywhere because of some special
 * cases.  Going into the water just gets him wet.  Going into the boat
 * is treated as "take boat", so we change his verb.
 */
				if ((i == ENTER)
					&& (word2 != NULL))
				{	if (!strcmp(word2,"stream")
						|| !strcmp(word2,"water")
						|| !strcmp(word2,"river") )
					{	if (LIQLOC(loc) == _WATER)
							rspeak(70); /* wet feet! */
						else
							rspeak(43); /* Where? */
						goto okay ; /* maybe this should just be moved */
					}
					else if (!strcmp(word2,"boat"))
					{	obj = _BOAT;
						object = OBJ(obj) ;
						i = TAKE;
					}
				}

				switch(i/1000)
				{
/* this is one of the big holes in the parser here.  Motion words are
 * hardly checked for syntax at all.  The object is usually not even
 * looked at, if given.  There are just a few special cases, and they
 * do not go through the normal vocabulary stuff.
 */
				case 0: /* motion word */
					if (obj || (verb && (verb != WALK))) 
						{what(FALSE); goto huh; }
					if ((i == OUT) && (!strcmp(word2,"boat")))
					{	i = DROP ; } /* deal with word ambiguity here */
					if (i == OUT
						&& TOTING(BOAT)
						&& (word2 == NULL || !strcmp(word2,""))
						&& obj == 0) {
						i = DROP ;
						object = OBJ(obj = _BOAT);
					}
					verb = i ; /* this sets dispatch switch */
					break;

/* for objects, we make sure that there are not two objects being named,
 * and that the object is here.  Also, if there's another word, we clear
 * 'verb' which may have been set by the operation of 'samvrb'.
 */
				case 1: /* object */
					oword = word1;
					if (obj != i)
					{	if (obj
							|| (verb && (word2 != NULL)))
						{	what(FALSE); /* don't understand */
							goto huh;
						}
					}
					object = OBJ(obj = i) ;
					if (word2 != NULL) verb = 0; /* defeat samvrb */

					if ((object->conn2.where != loc)
						&& !HERE(object)) /* object maybe not here */
					{	register int flag;
						flag = FALSE ;
						if ((obj == _DWARF) && (dflag > 1))
						{	register struct monster *cre;
							for (cre = orcs; cre->iloc >= 0; ++cre)
							{	if (cre->dloc == loc)
								{	flag = TRUE ;
									break;
								}
							}
						}
						if (flag
							|| (obj == LIQLOC(loc))
							|| ((obj == LIQ(BOTTLE)) && HERE(BOTTLE))
							|| ((obj == LIQ(CUP))    && HERE(CUP)   )
							|| ((object == SPIDER)
								&& (GRENDL->dloc == loc))
							|| ((object == DRAGON)
								&& (PUFF->dloc == loc))
							|| ((object == DJINN)
								&& (JEANNIE->dloc == loc))
							|| ((object == KOBOLD)
								&& (SLASHER->dloc == loc))
							|| ((object == BALROG)
								&& (BALLY->dloc == loc))
							|| ((object == SELF)
								&& (ME->dloc == loc))
							)
							; /* okay to keep going */
						else if ((object == KNIFE)
							&& (knfloc == loc))
						{	knfloc = LOST;
							rspeak(116); /* sorry about them knives */
							goto okay ;
						} else if ((object == ROPE)
							&& (HERE(ROPE2)))
						{	object = ROPE2 ;
							; /* substitute the "other" rope */
						} else if ((object == ROPE)
							&& (HERE(EROPE)))
						{	object = EROPE ;
						} else if ((object == ROPE)
							&& (HERE(EROPE2)))
						{	object = EROPE2;
						} else if ( (word2 == NULL)
							&& ((verb == FIND)
								|| (verb == INVENT)
								|| (verb == DESCRB)
								|| (verb == TOUCH) ) )
						{	; /* allow questions about things not here */
						} else {
							if (!verb && (word2 == NULL))
							/* this test is sensitive to verb funnies */
							{	register int k;
								if ((k=vocab(word1,3)) > 0)
								{	rspeak(k%1000); /* word has msg num */
									goto okay ;
								}
							}
							goto dark;
						}
					} /* end of the case the object is not here */

					if ((object == TOMB) && (HELM->prop))
						object = HELM ; /* actually a synonym */
					if (word2 != NULL) break;
					if (verb) break ;
					{	register int k;
						if ((k=vocab(word1,3)) >0)
						{	rspeak(k%1000);	/* word has msg num in it */
							goto okay;
						}
					}
					capchk(word1);	/* capitialize some proper nouns */
					(void) printf(
"What do you want to do with the %s?",word1);
					mltcmd = FALSE ;
					goto getvrb ;

				case 2: /* action (verb) */
					vword = word1;
					if ((verb == TAKE)
						&& ((i == INVENT)
							|| (i == verb)))
					{	verb = 0; /* destroy old verb */
					}
					if (verb && !obj && (word2 == NULL))
					{	what(FALSE); /* two verbs */
						goto huh;
					}
					if (word2 != NULL) {obj = 0 ; object = NULL ; }
					verb = i;
					if (word2 != NULL)
						if (verb == SAY)
						{	obj = 1;
							goto process;
						}
					break;

				case 3: /* special (just gets message) */
					verb = i ; /* this sets dispatch switch */
					break;
				} /* end of word-type switch */
			} /* end of word analysis */

		} /* end of getting new instructions (motion not forced) */
process:
		switch (verb/1000)
		{
		case 0: /* motion verb */
			newloc = moveme(loc,verb) ;
			locchg();
			continue ;

		case 2: /* true verb */
			if (verb == SAY) {
				if (word2 != NULL) word1 = word2;
				obj = vocab(word1,-1); /* what would happen? */
				if (obj == HOPE || obj == BANIS || obj == MISFO) {
					verb = obj; obj = 0; object = NULL;
				} else {
					printf("Okay, \"%s\".\n",word1);
					goto okay;
				}
			}
			switch (cvact(verb,obj,object))
			{
			case S_okay: goto okay;
			case S_miss: goto miss;
			case S_move: break;
			case S_obj: goto newobj;
			case S_what: *vword = toupper(*vword);
				printf("%s what?\n",vword);
				mltcmd = FALSE;
				goto newobj;
			case S_light: if (!DARK && wzdark) continue;
				goto okay;
			case S_show: continue;
			case S_dark: goto dark;
			default: bug(40);
			}
			locchg();
			continue;

		case 3: /* magic word */
			rspeak(verb%1000);
			goto okay;

		default: /* how could this be? */
			bug(1);
		}
	} /* end of motion loop */

	getscore();
	(void) printf("\nYou scored %d out of a possible %d, using %d turns.\n",
		score,mxscore,turns);
	{	register struct cmsg *cmsg;
		for (cmsg = ctext;cmsg->score != -1; ++cmsg) ;
		for (--cmsg; cmsg - ctext; --cmsg) {
			if (cmsg->score <= 0) cmsg->score += mxscore ;
			if (cmsg->score <= score) break;
		}
		(void) fputs(cmsg->msg,stdout);
		if ((cmsg+1)->score == -1) {
			(void) fputs("To achieve the next higher rating would be a\
 neat trick!\n\n Congratulations!\n",stdout);
		}else{
			(void) printf("To achieve the next higher rating, you need %d \
more point%s.\n",(cmsg+1)->score - score, ((cmsg+1)->score - score > 1) ?
				"s" : "");
		}
	} /* end of figuring the appropriate message */

	puts("\nTouch ENTER to continue.\n");
	{	auto char answer[5];
		fgets(answer,4,stdin);
	}
}