
/*	program VERB.C						*\
\*	WARNING: "advent.c" allocates GLOBAL storage space by	*\
\*		including "advdef.h".				*\
\*		All other modules use "advdec.h".		*/


#include	<stdio.h>
#include	"advent.h"
#include	"advdec.h"


/*
	Routine to process a transitive verb
*/
trverb()
{
	switch(verb){
	case CALM:
	case WALK:
	case QUIT:
	case SCORE:
	case FOO:
	case BRIEF:
	case SUSPEND:
	case HOURS:
	case LOG:
		actspk();
		break;
	case TAKE:
		vtake();
		break;
	case DROP:
		vdrop();
		break;
	case OPEN:
	case LOCK:
		vopen();
		break;
	case SAY:
		vsay();
		break;
	case NOTHING:
		rspeak(54);
		break;
	case ON:
		von();
		break;
	case OFF:
		voff();
		break;
	case WAVE:
		vwave();
		break;
	case KILL:
		vkill();
		break;
	case POUR:
		vpour();
		break;
	case EAT:
		veat();
		break;
	case DRINK:
		vdrink();
		break;
	case RUB:
		if (object != LAMP)
			rspeak(76);
		else
			actspk();
		break;
	case THROW:
		vthrow();
		break;
	case FEED:
		vfeed();
		break;
	case FIND:
	case INVENTORY:
		vfind();
		break;
	case FILL:
		vfill();
		break;
	case READ:
		vread();
		break;
	case BLAST:
		vblast();
		break;
	case BREAK:
		vbreak();
		break;
	case WAKE:
		vwake();
		break;
	default:
		printf("This verb is not implemented yet.\n");
	}
}

/*
	CARRY TAKE etc.
*/
vtake()
{
	int	i, msg;

	if (toting(object)) {
		actspk();
		return;
	}
	/*
	   special case objects and fixed objects
	*/
	msg = 25;
	if (object == PLANT && prop[PLANT] <= 0)
		msg = 115;
	if (object == BEAR && prop[BEAR] == 1)
		msg = 169;
	if (object == CHAIN && prop[BEAR] != 0)
		msg = 170;
	if (fixed[object]) {
		rspeak(msg);
		return;
	}
	/*
	   special case for liquids
	*/
	if (object == WATER || object == OIL) {
		if (!here(BOTTLE) || liq() != object) {
			object = BOTTLE;
			if (toting(BOTTLE)&&prop[BOTTLE] == 1){
				vfill();
				return;
			}
			if (prop[BOTTLE] != 1)
				msg = 105;
			if (!toting(BOTTLE))
				msg = 104;
			rspeak(msg);
			return;
		}
		object = BOTTLE;
	}
	if (holding >= 7) {
		rspeak(92);
		return;
	}
	/*
	   special case for bird.
	*/
	if (object == BIRD && prop[BIRD] == 0) {
		if (toting(ROD)) {
			rspeak(26);
			return;
		}
		if (!toting(CAGE)) {
			rspeak(27);
			return;
		}
		prop[BIRD] = 1;
	}
	if ( (object == BIRD || object == CAGE) &&
		prop[BIRD] != 0)
		carry((BIRD+CAGE)-object);
	carry(object);
	/*
	   handle liquid in bottle
	*/
	i = liq();
	if (object == BOTTLE && i != 0)
		place[i] = -1;
	rspeak(54);
}

/*
	DROP etc.
*/
vdrop()
{
	int	i;

	/*
	   check for dynamite
	*/
	if (toting(ROD2) && object == ROD && !toting(ROD))
		object = ROD2;
	if (!toting(object)){
		actspk();
		return;
	}
	/*
	   snake and bird
	*/
	if (object == BIRD && here(SNAKE)) {
		rspeak(30);
		if (closed)
			dwarfend();
		dstroy(SNAKE);
		prop[SNAKE] = -1;
	}
	/*
	   coins and vending machine
	*/
	else if (object == COINS && here(VEND)) {
		dstroy(COINS);
		drop(BATTERIES,loc);
		pspeak(BATTERIES,0);
		return;
	}
	/*
	   bird and dragon (ouch!!)
	*/
	else if (object == BIRD && at(DRAGON) && prop[DRAGON] == 0){
		rspeak(154);
		dstroy(BIRD);
		prop[BIRD] = 0;
		if (place[SNAKE] != 0)
			++tally2;
		return;
	}
	/*
	   Bear and troll
	*/
	if (object == BEAR && at(TROLL)) {
		rspeak(163);
		move(TROLL,0);
		move((TROLL+MAXOBJ),0);
		move(TROLL2,117);
		move((TROLL2+MAXOBJ),122);
		prop[TROLL] = 2;
	}
	/*
	   vase
	*/
	else if (object == VASE) {
		if (loc == 96)
			rspeak(54);
		else {
			prop[VASE] = at(PILLOW) ? 0 : 2;
			pspeak(VASE,prop[VASE]+1);
			if (prop[VASE] != 0)
				fixed[VASE] = -1;
		}
	}
	/*
	   handle liquid and bottle
	*/
	i = liq();
	if (i == object)
		object = BOTTLE;
	if (object == BOTTLE && i != 0)
		place[i] = 0;
	/*
	   handle bird and cage
	*/
	if (object == CAGE && prop[BIRD] != 0)
		drop(BIRD,loc);
	if (object == BIRD)
		prop[BIRD] = 0;
	drop(object,loc);
}

/*
	LOCK, UNLOCK, OPEN, CLOSE etc.
*/
vopen()
{
	int	msg, oyclam;

	switch(object) {
	case CLAM:
	case OYSTER:
		oyclam = (object == OYSTER ? 1 : 0);
		if (verb == LOCK)
			msg = 61;
		else if (!toting(TRIDENT))
			msg = 122+oyclam;
		else if (toting(object))
			msg = 120+oyclam;
		else {
			msg = 124+oyclam;
			dstroy(CLAM);
			drop(OYSTER,loc);
			drop(PEARL,105);
		}
		break;
	case DOOR:
		msg = (prop[DOOR] == 1 ? 54 : 111);
		break;
	case CAGE:
		msg = 32;
		break;
	case KEYS:
		msg = 55;
		break;
	case CHAIN:
		if (!here(KEYS))
			msg = 31;
		else if (verb == LOCK) {
			if (prop[CHAIN] != 0)
				msg = 34;
			else if (loc != 130)
				msg = 173;
			else {
				prop[CHAIN] = 2;
				if (toting(CHAIN))
					drop(CHAIN,loc);
				fixed[CHAIN] =  -1;
				msg = 172;
			}
		}
		else {
			if (prop[BEAR] == 0)
				msg = 41;
			else if (prop[CHAIN] == 0)
				msg = 37;
			else {
				prop[CHAIN] = 0;
				fixed[CHAIN] = 0;
				if (prop[BEAR] != 3)
					prop[BEAR] = 2;
				fixed[BEAR] = 2-prop[BEAR];
				msg = 171;
			}
		}
		break;
	case GRATE:
		if (!here(KEYS))
			msg = 31;
		else if (closing) {
			if (!panic) {
				clock2 = 15;
				++panic;
			}
			msg = 130;
		}
		else {
			msg = 34+prop[GRATE];
			prop[GRATE] = (verb == LOCK ? 0 : 1);
			msg += 2*prop[GRATE];
		}
		break;
	default:
		msg = 33;
	}
	rspeak(msg);
}

/*
	SAY etc.
*/
vsay()
{
	int	wtype, wval;

	analyze(word1,&wtype,&wval);
	printf("Okay.\n%s\n",wval == SAY ? word2 : word1);
}

/*
	ON etc.
*/
von()
{
	if (!here(LAMP))
		actspk();
	else if (limit<0)
		rspeak(184);
	else {
		prop[LAMP] = 1;
		rspeak(39);
		if (wzdark) {
			wzdark = 0;
			describe();
		}
	}
}

/*
	OFF etc.
*/
voff()
{
	if (!here(LAMP))
		actspk();
	else {
		prop[LAMP] = 0;
		rspeak(40);
	}
}

/*
	WAVE etc.
*/
vwave()
{
	if (!toting(object) &&
	   (object != ROD || !toting(ROD2)))
		rspeak(29);
	else if (object != ROD || !at(FISSURE) ||
		!toting(object) || closing)
		actspk();
	else {
		prop[FISSURE] = 1-prop[FISSURE];
		pspeak(FISSURE,2-prop[FISSURE]);
	}
}

/*
	ATTACK, KILL etc.
*/
vkill()
{
	int	i, msg;

	switch(object) {
	case BIRD:
		if (closed)
			msg = 137;
		else {
			dstroy(BIRD);
			prop[BIRD] = 0;
			if (place[SNAKE] == 19)
				++tally2;
			msg = 45;
		}
		break;
	case 0:
		msg = 44;
		break;
	case CLAM:
	case OYSTER:
		msg = 150;
		break;
	case SNAKE:
		msg = 46;
		break;
	case DWARF:
		if (closed)
			dwarfend();
		msg = 49;
		break;
	case TROLL:
		msg = 157;
		break;
	case BEAR:
		msg = 165+(prop[BEAR]+1)/2;
		break;
	case DRAGON:
		if (prop[DRAGON] != 0) {
			msg = 167;
			break;
		}
		if (!yes(49,0,0))
			break;
		pspeak(DRAGON,1);
		prop[DRAGON] = 2;
		prop[RUG] = 0;
		move((DRAGON+MAXOBJ),-1);
		move((RUG+MAXOBJ),0);
		move(DRAGON,120);
		move(RUG,120);
		for(i = 1;i<MAXOBJ;++i)
			if (place[i] == 119 || place[i] == 121)
				move(i,120);
		newloc = 120;
		return;
	default:
		actspk();
		return;
	}
	rspeak(msg);
}

/*
	POUR
*/
vpour()
{
	if (object == BOTTLE || object == 0)
		object = liq();
	if (object == 0) {
		needobj();
		return;
	}
	if (!toting(object)) {
		actspk();
		return;
	}
	if (object != OIL && object != WATER) {
		rspeak(78);
		return;
	}
	prop[BOTTLE] = 1;
	place[object] = 0;
	if (at(PLANT)) {
		if (object != WATER)
			rspeak(112);
		else {
			pspeak(PLANT,prop[PLANT]+1);
			prop[PLANT] = (prop[PLANT]+2)%6;
			prop[PLANT2] = prop[PLANT]/2;
			describe();
		}
	}
	else if (at(DOOR)) {
		prop[DOOR] = (object == OIL ? 1 : 0);
		rspeak(113+prop[DOOR]);
	}
	else
		rspeak(77);
}

/*
	EAT
*/
veat()
{
	int	msg;

	switch(object) {
	case FOOD:
		dstroy(FOOD);
		msg = 72;
		break;
	case BIRD: case SNAKE: case CLAM: case OYSTER:
	case DWARF: case DRAGON: case TROLL: case BEAR:
		msg = 71;
		break;
	default:
		actspk();
		return;
	}
	rspeak(msg);
}

/*
	DRINK
*/
vdrink()
{
	if (object != WATER)
		rspeak(110);
	else if (liq() != WATER || !here(BOTTLE))
		actspk();
	else {
		prop[BOTTLE] = 1;
		place[WATER] = 0;
		rspeak(74);
	}
}

/*
	THROW etc.
*/
vthrow()
{
	int	i, msg;

	if (toting(ROD2) && object == ROD && !toting(ROD))
		object = ROD2;
	if (!toting(object)) {
		actspk();
		return;
	}
	/*
	   treasure to troll
	*/
	if (at(TROLL) && object >= 50 && object<MAXOBJ) {
		rspeak(159);
		drop(object,0);
		move(TROLL,0);
		move((TROLL+MAXOBJ),0);
		drop(TROLL2,117);
		drop((TROLL2+MAXOBJ),122);
		return;
	}
	/*
	   feed the bears...
	*/
	if (object == FOOD && here(BEAR)) {
		object = BEAR;
		vfeed();
		return;
	}
	/*
	   if not axe, same as drop...
	*/
	if (object != AXE) {
		vdrop();
		return;
	}
	/*
	   AXE is THROWN
	*/
	/*
	   at a dwarf...
	*/
	if (i = dcheck()) {
		msg = 48;
		if (pct(33)) {
			dseen[i] = dloc[i] = 0;
			msg = 47;
			++dkill;
			if (dkill == 1)
				msg = 149;
		}
	}
	/*
	   at a dragon...
	*/
	else if (at(DRAGON) && prop[DRAGON] == 0) 
		msg = 152;
	/*
	   at the troll...
	*/
	else if (at(TROLL))
		msg = 158;
	/*
	   at the bear...
	*/
	else if (here(BEAR) && prop[BEAR] == 0) {
		rspeak(164);
		drop(AXE,loc);
		fixed[AXE] = -1;
		prop[AXE] = 1;
		return;
	}
	/*
	   otherwise it is an attack
	*/
	else {
		verb = KILL;
		object = 0;
		itverb();
		return;
	}
	/*
	   handle the left over axe...
	*/
	rspeak(msg);
	drop(AXE,loc);
	describe();
}

/*
	INVENTORY, FIND etc.
*/
vfind()
{
	int	msg;
	if (toting(object))
		msg = 24;
	else if (closed)
		msg = 138;
	else if (dcheck() && dflag >= 2 && object == DWARF)
		msg = 94;
	else if (at(object) ||
		(liq() == object && here(BOTTLE)) ||
		object == liqloc())
		msg = 94;
	else {
		actspk();
		return;
	}
	rspeak(msg);
}

/*
	FILL
*/
vfill()
{
	int	i, msg;

	switch(object) {
	case BOTTLE:
		if (liq() != 0)
			msg = 105;
		else if (liqloc() == 0)
			msg = 106;
		else {
			prop[BOTTLE] = cond[loc] & WATOIL;
			i = liq();
			if (toting(BOTTLE))
				place[i] = -1;
			msg = (i == OIL ? 108 : 107);
		}
		break;
	case VASE:
		if (liqloc() == 0) {
			msg = 144;
			break;
		}
		if (!toting(VASE)) {
			msg = 29;
			break;
		}
		rspeak(145);
		vdrop();
		return;
	default:
		msg = 29;
	}
	rspeak(msg);
}

/*
	FEED
*/
vfeed()
{
	int	msg;

	switch(object) {
	case BIRD:
		msg = 100;
		break;
	case DWARF:
		if (!here(FOOD)) {
			actspk();
			return;
		}
		++dflag;
		msg = 103;
		break;
	case BEAR:
		if (!here(FOOD)) {
			if (prop[BEAR] == 0)
				msg = 102;
			else if (prop[BEAR] == 3)
				msg = 110;
			else {
				actspk();
				return;
			}
		break;
		}
		dstroy(FOOD);
		prop[BEAR] = 1;
		fixed[AXE] = 0;
		prop[AXE] = 0;
		msg = 168;
		break;
	case DRAGON:
		msg = (prop[DRAGON] != 0 ? 110 : 102);
		break;
	case TROLL:
		msg = 182;
		break;
	case SNAKE:
		if (closed || !here(BIRD)) {
			msg = 102;
			break;
		}
		msg = 101;
		dstroy(BIRD);
		prop[BIRD] = 0;
		++tally2;
		break;
	default:
		msg = 14;
	}
	rspeak(msg);
}

/*
	READ etc.
*/
vread()
{
	int	msg;
	char *probj();

	msg = 0;
	if (dark()) {
		printf("I see no %s here.\n",probj(object));
		return;
	}
	switch(object) {
	case MAGAZINE:
		msg = 190;
		break;
	case TABLET:
		msg = 196;
		break;
	case MESSAGE:
		msg = 191;
		break;
	case OYSTER:
		if (!toting(OYSTER) || !closed)
			break;
		yes(192,193,54);
		return;
	default:
		;
	}
	if (msg)
		rspeak(msg);
	else
		actspk();
}

/*
	BLAST etc.
*/
vblast()
{
	if (prop[ROD2] < 0 || !closed)
		actspk();
	else {
		bonus = 133;
		if (loc == 115)
			bonus = 134;
		if (here(ROD2))
			bonus = 135;
		rspeak(bonus);
		normend();
	}
}

/*
	BREAK etc.
*/
vbreak()
{
	int	msg;
	if (object == MIRROR) {
		msg = 148;
		if (closed) {
			rspeak(197);
			dwarfend();
		}
	}
	else if (object == VASE && prop[VASE] == 0) {
		msg = 198;
		if (toting(VASE))
			drop(VASE,loc);
		prop[VASE] = 2;
		fixed[VASE] = -1;
	}
	else {
		actspk();
		return;
	}
	rspeak(msg);
}

/*
	WAKE etc.
*/
vwake()
{
	if (object != DWARF || !closed)
		actspk();
	else {
		rspeak(199);
		dwarfend();
	}
}

/*
	Routine to speak default verb message
*/
actspk()
{
	int	i;

	if (verb<1 || verb>32)
		bug(39);
	i = actmsg[verb];
	if (i)
		rspeak(i);
}

/*
	Routine to indicate no reasonable
	object for verb found.  Used mostly by
	intransitive verbs.
*/
needobj()
{
	int wtype, wval;

	analyze(word1,&wtype,&wval);
	printf("%s what?\n",wtype == 2 ? word1 : word2);
}

 

