/*	$NetBSD: subr.c,v 1.14 2021/05/02 12:50:43 rillig Exp $	*/

/*-
 * Copyright (c) 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * The game adventure was originally written in Fortran by Will Crowther
 * and Don Woods.  It was later translated to C and enhanced by Jim
 * Gillogly.  This code is derived from software contributed to Berkeley
 * by Jim Gillogly at The Rand Corporation.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)subr.c	8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: subr.c,v 1.14 2021/05/02 12:50:43 rillig Exp $");
#endif
#endif				/* not lint */

/*      Re-coding of advent in C: subroutines from main                 */

#include <stdio.h>
#include <stdlib.h>
#include "hdr.h"
#include "extern.h"

static void badmove(void);
static int bitset(int, int);
static int dropper(void);
static int liq2(int);
static int mback(void);
static int specials(void);
static int trbridge(void);

/*              Statement functions     */
int
toting(int objj)
{
	if (place[objj] == -1)
		return (TRUE);
	else
		return (FALSE);
}

int
here(int objj)
{
	if (place[objj] == loc || toting(objj))
		return (TRUE);
	else
		return (FALSE);
}

int
at(int objj)
{
	if (place[objj] == loc || fixed[objj] == loc)
		return (TRUE);
	else
		return (FALSE);
}

static int
liq2(int pbotl)
{
	return ((1 - pbotl) * water + (pbotl / 2) * (water + oil));
}

int
liq(void)
{
	int     i;
	i = prop[bottle];
	if (i > -1 - i)
		return (liq2(i));
	else
		return (liq2(-1 - i));
}

/* may want to clean this one up a bit */
int
liqloc(int locc)
{
	int     i, j, l;
	i = cond[locc] / 2;
	j = ((i * 2) % 8) - 5;
	l = cond[locc] / 4;
	l = l % 2;
	return (liq2(j * l + 1));
}

static int
bitset(int l, int n)
{
	if (cond[l] & setbit[n])
		return (TRUE);
	return (FALSE);
}

int
forced(int locc)
{
	if (cond[locc] == 2)
		return (TRUE);
	return (FALSE);
}

int
dark(void)
{
	if ((cond[loc] % 2) == 0 && (prop[lamp] == 0 || !here(lamp)))
		return (TRUE);
	return (FALSE);
}

int
pct(int n)
{
	if (ran(100) < n)
		return (TRUE);
	return (FALSE);
}


int
fdwarf(void)
{				/* 71 */
	int     i, j;
	struct travlist *kk;

	if (newloc != loc && !forced(loc) && !bitset(loc, 3)) {
		for (i = 1; i <= 5; i++) {
			if (odloc[i] != newloc || !dseen[i])
				continue;
			newloc = loc;
			rspeak(2);
			break;
		}
	}
	loc = newloc;		/* 74 */
	if (loc == 0 || forced(loc) || bitset(newloc, 3))
		return (2000);
	if (dflag == 0) {
		if (loc >= 15)
			dflag = 1;
		return (2000);
	}
	if (dflag == 1) {	/* 6000 */
		if (loc < 15 || pct(95))
			return (2000);
		dflag = 2;
		for (i = 1; i <= 2; i++) {
			j = 1 + ran(5);
			if (pct(50) && saved == -1)
				dloc[j] = 0;	/* 6001 */
		}
		for (i = 1; i <= 5; i++) {
			if (dloc[i] == loc)
				dloc[i] = daltloc;
			odloc[i] = dloc[i];	/* 6002 */
		}
		rspeak(3);
		drop(axe, loc);
		return (2000);
	}
	dtotal = attack = stick = 0;	/* 6010 */
	for (i = 1; i <= 6; i++) {	/* loop to 6030 */
		if (dloc[i] == 0)
			continue;
		j = 1;
		for (kk = travel[dloc[i]]; kk != 0; kk = kk->next) {
			newloc = kk->tloc;
			if (newloc > 300 || newloc < 15 || newloc == odloc[i]
			    || (j > 1 && newloc == tk[j - 1]) || j >= 20
			    || newloc == dloc[i] || forced(newloc)
			    || (i == 6 && bitset(newloc, 3))
			    || kk->conditions == 100)
				continue;
			tk[j++] = newloc;
		}
		tk[j] = odloc[i];	/* 6016 */
		if (j >= 2)
			j--;
		j = 1 + ran(j);
		odloc[i] = dloc[i];
		dloc[i] = tk[j];
		dseen[i] = (dseen[i] && loc >= 15) ||
		    (dloc[i] == loc || odloc[i] == loc);
		if (!dseen[i])
			continue;	/* i.e. goto 6030 */
		dloc[i] = loc;
		if (i == 6) {	/* pirate's spotted him */
			if (loc == chloc || prop[chest] >= 0)
				continue;
			k = 0;
			for (j = 50; j <= maxtrs; j++) { /* loop to 6020 */
				if (j == pyramid && (loc == plac[pyramid]
					|| loc == plac[emerald]))
					goto l6020;
				if (toting(j))
					goto l6022;
		l6020:		if (here(j))
					k = 1;
			}	/* 6020 */
			if (tally == tally2 + 1 && k == 0 && place[chest] == 0
			    && here(lamp) && prop[lamp] == 1)
				goto l6025;
			if (odloc[6] != dloc[6] && pct(20))
				rspeak(127);
			continue;	/* to 6030 */
	l6022:		rspeak(128);
			if (place[message] == 0)
				move(chest, chloc);
			move(message, chloc2);
			for (j = 50; j <= maxtrs; j++) { /* loop to 6023 */
				if (j == pyramid && (loc == plac[pyramid]
					|| loc == plac[emerald]))
					continue;
				if (at(j) && fixed[j] == 0)
					carry(j, loc);
				if (toting(j))
					drop(j, chloc);
			}
	l6024:		dloc[6] = odloc[6] = chloc;
			dseen[6] = FALSE;
			continue;
	l6025:		rspeak(186);
			move(chest, chloc);
			move(message, chloc2);
			goto l6024;
		}
		dtotal++;	/* 6027 */
		if (odloc[i] != dloc[i])
			continue;
		attack++;
		if (knfloc >= 0)
			knfloc = loc;
		if (ran(1000) < 95 * (dflag - 2))
			stick++;
	}			/* 6030 */
	if (dtotal == 0)
		return (2000);
	if (dtotal != 1) {
		printf("There are %d threatening little dwarves ", dtotal);
		printf("in the room with you.\n");
	} else
		rspeak(4);
	if (attack == 0)
		return (2000);
	if (dflag == 2)
		dflag = 3;
	if (saved != -1)
		dflag = 20;
	if (attack != 1) {
		printf("%d of them throw knives at you!\n", attack);
		k = 6;
l82:		if (stick <= 1) {	/* 82 */
			rspeak(k + stick);
			if (stick == 0)
				return (2000);
		} else
			printf("%d of them get you!\n", stick);	/* 83 */
		oldloc2 = loc;
		return (99);
	}
	rspeak(5);
	k = 52;
	goto l82;
}


/* label 8              */
int
march(void)
{
	int     ll1, ll2;

	if ((tkk = travel[newloc = loc]) == 0)
		bug(26);
	if (k == null)
		return (2);
	if (k == cave) {	/* 40                   */
		if (loc < 8)
			rspeak(57);
		if (loc >= 8)
			rspeak(58);
		return (2);
	}
	if (k == look) {	/* 30                   */
		if (detail++ < 3)
			rspeak(15);
		wasdark = FALSE;
		abb[loc] = 0;
		return (2);
	}
	if (k == back) {	/* 20                   */
		switch (mback()) {
		case 2:
			return (2);
		case 9:
			goto l9;
		default:
			bug(100);
		}
	}
	oldloc2 = oldloc;
	oldloc = loc;
l9:
	for (; tkk != 0; tkk = tkk->next)
		if (tkk->tverb == 1 || tkk->tverb == k)
			break;
	if (tkk == 0) {
		badmove();
		return (2);
	}
l11:	ll1 = tkk->conditions;	/* 11                   */
	ll2 = tkk->tloc;
	newloc = ll1;		/* newloc=conditions    */
	k = newloc % 100;	/* k used for prob      */
	if (newloc <= 300) {
		if (newloc <= 100) {	/* 13                   */
			if (newloc != 0 && !pct(newloc))
				goto l12;	/* 14   */
	l16:		newloc = ll2;	/* newloc=location      */
			if (newloc <= 300)
				return (2);
			if (newloc <= 500)
				switch (specials()) {	/* to 30000           */
				case 2:
					return (2);
				case 12:
					goto l12;
				case 99:
					return (99);
				default:
					bug(101);
				}
			rspeak(newloc - 500);
			newloc = loc;
			return (2);
		}
		if (toting(k) || (newloc > 200 && at(k)))
			goto l16;
		goto l12;
	}
	if (prop[k] != (newloc / 100) - 3)
		goto l16;	/* newloc still conditions */
l12:				/* alternative to probability move      */
	for (; tkk != 0; tkk = tkk->next)
		if (tkk->tloc != ll2 || tkk->conditions != ll1)
			break;
	if (tkk == 0)
		bug(25);
	goto l11;
}

/* 20                   */
static int
mback(void)
{
	struct travlist *tk2, *j;
	int     ll;
	if (forced(k = oldloc))
		k = oldloc2;	/* k=location           */
	oldloc2 = oldloc;
	oldloc = loc;
	tk2 = 0;
	if (k == loc) {
		rspeak(91);
		return (2);
	}
	for (; tkk != 0; tkk = tkk->next) {	/* 21                   */
		ll = tkk->tloc;
		if (ll == k) {
			k = tkk->tverb;	/* k back to verb       */
			tkk = travel[loc];
			return (9);
		}
		if (ll <= 300) {
			j = travel[loc];
			if (forced(ll) && k == j->tloc)
				tk2 = tkk;
		}
	}
	tkk = tk2;		/* 23                   */
	if (tkk != 0) {
		k = tkk->tverb;
		tkk = travel[loc];
		return (9);
	}
	rspeak(140);
	return (2);
}

/* 30000                */
static int
specials(void)
{
	switch (newloc -= 300) {
		case 1:		/* 30100                */
		newloc = 99 + 100 - loc;
		if (holding == 0 || (holding == 1 && toting(emerald)))
			return (2);
		newloc = loc;
		rspeak(117);
		return (2);
	case 2:		/* 30200                */
		drop(emerald, loc);
		return (12);
	case 3:		/* to 30300             */
		return (trbridge());
	default:
		bug(29);
	}
}

/* 30300                */
static int
trbridge(void)
{
	if (prop[troll] == 1) {
		pspeak(troll, 1);
		prop[troll] = 0;
		move(troll2, 0);
		move(troll2 + 100, 0);
		move(troll, plac[troll]);
		move(troll + 100, fixd[troll]);
		juggle(chasm);
		newloc = loc;
		return (2);
	}
	newloc = plac[troll] + fixd[troll] - loc;	/* 30310    */
	if (prop[troll] == 0)
		prop[troll] = 1;
	if (!toting(bear))
		return (2);
	rspeak(162);
	prop[chasm] = 1;
	prop[troll] = 2;
	drop(bear, newloc);
	fixed[bear] = -1;
	prop[bear] = 3;
	if (prop[spices] < 0)
		tally2++;
	oldloc2 = newloc;
	return (99);
}

/* 20                   */
static void
badmove(void)
{
	spk = 12;
	if (k >= 43 && k <= 50)
		spk = 9;
	if (k == 29 || k == 30)
		spk = 9;
	if (k == 7 || k == 36 || k == 37)
		spk = 10;
	if (k == 11 || k == 19)
		spk = 11;
	if (verb == find || verb == invent)
		spk = 59;
	if (k == 62 || k == 65)
		spk = 42;
	if (k == 17)
		spk = 80;
	rspeak(spk);
}

void
bug(int n)
{
	printf("Please tell jim@rand.org that fatal bug %d happened.\n", n);
	exit(1);
}

/* 2600 &c              */
void
checkhints(void)
{
	int     hint;
	for (hint = 4; hint <= hintmax; hint++) {
		if (hinted[hint])
			continue;
		if (!bitset(loc, hint))
			hintlc[hint] = -1;
		hintlc[hint]++;
		if (hintlc[hint] < hints[hint][1])
			continue;
		switch (hint) {
		case 4:	/* 40400 */
			if (prop[grate] == 0 && !here(keys))
				goto l40010;
			goto l40020;
		case 5:	/* 40500 */
			if (here(bird) && toting(rod) && obj == bird)
				goto l40010;
			continue;	/* i.e. goto l40030 */
		case 6:	/* 40600 */
			if (here(snake) && !here(bird))
				goto l40010;
			goto l40020;
		case 7:	/* 40700 */
			if (atloc[loc] == 0 && atloc[oldloc] == 0
			    && atloc[oldloc2] == 0 && holding > 1)
				goto l40010;
			goto l40020;
		case 8:	/* 40800 */
			if (prop[emerald] != -1 && prop[pyramid] == -1)
				goto l40010;
			goto l40020;
		case 9:
			goto l40010;	/* 40900 */
		default:
			bug(27);
		}
l40010:	hintlc[hint] = 0;
		if (!yes(hints[hint][3], 0, 54))
			continue;
		printf("I am prepared to give you a hint, but it will ");
		printf("cost you %d points.\n", hints[hint][2]);
		hinted[hint] = yes(175, hints[hint][4], 54);
l40020:	hintlc[hint] = 0;
	}
}

/* 9030                 */
int
trsay(void)
{
	int     i;
	if (*wd2 != 0)
		copystr(wd2, wd1);
	i = vocab(wd1, -1, 0);
	if (i == 62 || i == 65 || i == 71 || i == 2025) {
		*wd2 = 0;
		obj = 0;
		return (2630);
	}
	printf("\nOkay, \"%s\".\n", wd2);
	return (2012);
}

/* 9010                 */
int
trtake(void)
{
	if (toting(obj))
		return (2011);	/* 9010 */
	spk = 25;
	if (obj == plant && prop[plant] <= 0)
		spk = 115;
	if (obj == bear && prop[bear] == 1)
		spk = 169;
	if (obj == chain && prop[bear] != 0)
		spk = 170;
	if (fixed[obj] != 0)
		return (2011);
	if (obj == water || obj == oil) {
		if (here(bottle) && liq() == obj) {
			obj = bottle;
			goto l9017;
		}
		obj = bottle;
		if (toting(bottle) && prop[bottle] == 1)
			return (9220);
		if (prop[bottle] != 1)
			spk = 105;
		if (!toting(bottle))
			spk = 104;
		return (2011);
	}
l9017:	if (holding >= 7) {
		rspeak(92);
		return (2012);
	}
	if (obj == bird) {
		if (prop[bird] != 0)
			goto l9014;
		if (toting(rod)) {
			rspeak(26);
			return (2012);
		}
		if (!toting(cage)) {	/* 9013 */
			rspeak(27);
			return (2012);
		}
		prop[bird] = 1;	/* 9015 */
	}
l9014:	if ((obj == bird || obj == cage) && prop[bird] != 0)
		carry(bird + cage - obj, loc);
	carry(obj, loc);
	k = liq();
	if (obj == bottle && k != 0)
		place[k] = -1;
	return (2009);
}

/* 9021                 */
static int
dropper(void)
{
	k = liq();
	if (k == obj)
		obj = bottle;
	if (obj == bottle && k != 0)
		place[k] = 0;
	if (obj == cage && prop[bird] != 0)
		drop(bird, loc);
	if (obj == bird)
		prop[bird] = 0;
	drop(obj, loc);
	return (2012);
}

/* 9020                 */
int
trdrop(void)
{
	if (toting(rod2) && obj == rod && !toting(rod))
		obj = rod2;
	if (!toting(obj))
		return (2011);
	if (obj == bird && here(snake)) {
		rspeak(30);
		if (closed)
			return (19000);
		destroy(snake);
		prop[snake] = 1;
		return (dropper());
	}
	if (obj == coins && here(vend)) {	/* 9024                 */
		destroy(coins);
		drop(batter, loc);
		pspeak(batter, 0);
		return (2012);
	}
	if (obj == bird && at(dragon) && prop[dragon] == 0) {	/* 9025 */
		rspeak(154);
		destroy(bird);
		prop[bird] = 0;
		if (place[snake] == plac[snake])
			tally2--;
		return (2012);
	}
	if (obj == bear && at(troll)) {	/* 9026                 */
		rspeak(163);
		move(troll, 0);
		move(troll + 100, 0);
		move(troll2, plac[troll]);
		move(troll2 + 100, fixd[troll]);
		juggle(chasm);
		prop[troll] = 2;
		return (dropper());
	}
	if (obj != vase || loc == plac[pillow]) { /* 9027       */
		rspeak(54);
		return (dropper());
	}
	prop[vase] = 2;		/* 9028                 */
	if (at(pillow))
		prop[vase] = 0;
	pspeak(vase, prop[vase] + 1);
	if (prop[vase] != 0)
		fixed[vase] = -1;
	return (dropper());
}

/* 9040                 */
int
tropen(void)
{
	if (obj == clam || obj == oyster) {
		k = 0;		/* 9046                 */
		if (obj == oyster)
			k = 1;
		spk = 124 + k;
		if (toting(obj))
			spk = 120 + k;
		if (!toting(trident))
			spk = 122 + k;
		if (verb == lock)
			spk = 61;
		if (spk != 124)
			return (2011);
		destroy(clam);
		drop(oyster, loc);
		drop(pearl, 105);
		return (2011);
	}
	if (obj == door)
		spk = 111;
	if (obj == door && prop[door] == 1)
		spk = 54;
	if (obj == cage)
		spk = 32;
	if (obj == keys)
		spk = 55;
	if (obj == grate || obj == chain)
		spk = 31;
	if (spk != 31 || !here(keys))
		return (2011);
	if (obj == chain) {
		if (verb == lock) {
			spk = 172;	/* 9049: lock           */
			if (prop[chain] != 0)
				spk = 34;
			if (loc != plac[chain])
				spk = 173;
			if (spk != 172)
				return (2011);
			prop[chain] = 2;
			if (toting(chain))
				drop(chain, loc);
			fixed[chain] = -1;
			return (2011);
		}
		spk = 171;
		if (prop[bear] == 0)
			spk = 41;
		if (prop[chain] == 0)
			spk = 37;
		if (spk != 171)
			return (2011);
		prop[chain] = 0;
		fixed[chain] = 0;
		if (prop[bear] != 3)
			prop[bear] = 2;
		fixed[bear] = 2 - prop[bear];
		return (2011);
	}
	if (isclosing) {
		k = 130;
		if (!panic)
			clock2 = 15;
		panic = TRUE;
		return (2010);
	}
	k = 34 + prop[grate];	/* 9043                 */
	prop[grate] = 1;
	if (verb == lock)
		prop[grate] = 0;
	k = k + 2 * prop[grate];
	return (2010);
}

/* 9120                         */
int
trkill(void)
{
	int     i;
	for (i = 1; i <= 5; i++)
		if (dloc[i] == loc && dflag >= 2)
			break;
	if (i == 6)
		i = 0;
	if (obj == 0) {		/* 9122                         */
		if (i != 0)
			obj = dwarf;
		if (here(snake))
			obj = obj * 100 + snake;
		if (at(dragon) && prop[dragon] == 0)
			obj = obj * 100 + dragon;
		if (at(troll))
			obj = obj * 100 + troll;
		if (here(bear) && prop[bear] == 0)
			obj = obj * 100 + bear;
		if (obj > 100)
			return (8000);
		if (obj == 0) {
			if (here(bird) && verb != throw)
				obj = bird;
			if (here(clam) || here(oyster))
				obj = 100 * obj + clam;
			if (obj > 100)
				return (8000);
		}
	}
	if (obj == bird) {	/* 9124                         */
		spk = 137;
		if (closed)
			return (2011);
		destroy(bird);
		prop[bird] = 0;
		if (place[snake] == plac[snake])
			tally2++;
		spk = 45;
	}
	if (obj == 0)
		spk = 44;	/* 9125                         */
	if (obj == clam || obj == oyster)
		spk = 150;
	if (obj == snake)
		spk = 46;
	if (obj == dwarf)
		spk = 49;
	if (obj == dwarf && closed)
		return (19000);
	if (obj == dragon)
		spk = 147;
	if (obj == troll)
		spk = 157;
	if (obj == bear)
		spk = 165 + (prop[bear] + 1) / 2;
	if (obj != dragon || prop[dragon] != 0)
		return (2011);
	rspeak(49);
	verb = 0;
	obj = 0;
	getin(&wd1, &wd2);
	if (!weq(wd1, "y") && !weq(wd1, "yes"))
		return (2608);
	pspeak(dragon, 1);
	prop[dragon] = 2;
	prop[rug] = 0;
	k = (plac[dragon] + fixd[dragon]) / 2;
	move(dragon + 100, -1);
	move(rug + 100, 0);
	move(dragon, k);
	move(rug, k);
	for (obj = 1; obj <= 100; obj++)
		if (place[obj] == plac[dragon] || place[obj] == fixd[dragon])
			move(obj, k);
	loc = k;
	k = null;
	return (8);
}

/* 9170: throw                  */
int
trtoss(void)
{
	int     i;
	if (toting(rod2) && obj == rod && !toting(rod))
		obj = rod2;
	if (!toting(obj))
		return (2011);
	if (obj >= 50 && obj <= maxtrs && at(troll)) {
		spk = 159;	/* 9178                 */
		drop(obj, 0);
		move(troll, 0);
		move(troll + 100, 0);
		drop(troll2, plac[troll]);
		drop(troll2 + 100, fixd[troll]);
		juggle(chasm);
		return (2011);
	}
	if (obj == food && here(bear)) {
		obj = bear;	/* 9177                 */
		return (9210);
	}
	if (obj != axe)
		return (9020);
	for (i = 1; i <= 5; i++) {
		if (dloc[i] == loc) {
			spk = 48;	/* 9172                 */
			if (ran(3) == 0 || saved != -1)
	l9175:		{
				rspeak(spk);
				drop(axe, loc);
				k = null;
				return (8);
			}
			dseen[i] = FALSE;
			dloc[i] = 0;
			spk = 47;
			dkill++;
			if (dkill == 1)
				spk = 149;
			goto l9175;
		}
	}
	spk = 152;
	if (at(dragon) && prop[dragon] == 0)
		goto l9175;
	spk = 158;
	if (at(troll))
		goto l9175;
	if (here(bear) && prop[bear] == 0) {
		spk = 164;
		drop(axe, loc);
		fixed[axe] = -1;
		prop[axe] = 1;
		juggle(bear);
		return (2011);
	}
	obj = 0;
	return (9120);
}

/* 9210                 */
int
trfeed(void)
{
	if (obj == bird) {
		spk = 100;
		return (2011);
	}
	if (obj == snake || obj == dragon || obj == troll) {
		spk = 102;
		if (obj == dragon && prop[dragon] != 0)
			spk = 110;
		if (obj == troll)
			spk = 182;
		if (obj != snake || closed || !here(bird))
			return (2011);
		spk = 101;
		destroy(bird);
		prop[bird] = 0;
		tally2++;
		return (2011);
	}
	if (obj == dwarf) {
		if (!here(food))
			return (2011);
		spk = 103;
		dflag++;
		return (2011);
	}
	if (obj == bear) {
		if (prop[bear] == 0)
			spk = 102;
		if (prop[bear] == 3)
			spk = 110;
		if (!here(food))
			return (2011);
		destroy(food);
		prop[bear] = 1;
		fixed[axe] = 0;
		prop[axe] = 0;
		spk = 168;
		return (2011);
	}
	spk = 14;
	return (2011);
}

/* 9220 */
int
trfill(void)
{
	if (obj == vase) {
		spk = 29;
		if (liqloc(loc) == 0)
			spk = 144;
		if (liqloc(loc) == 0 || !toting(vase))
			return (2011);
		rspeak(145);
		prop[vase] = 2;
		fixed[vase] = -1;
		return (9020);	/* advent/10 goes to 9024 */
	}
	if (obj != 0 && obj != bottle)
		return (2011);
	if (obj == 0 && !here(bottle))
		return (8000);
	spk = 107;
	if (liqloc(loc) == 0)
		spk = 106;
	if (liq() != 0)
		spk = 105;
	if (spk != 107)
		return (2011);
	prop[bottle] = ((cond[loc] % 4) / 2) * 2;
	k = liq();
	if (toting(bottle))
		place[k] = -1;
	if (k == oil)
		spk = 108;
	return (2011);
}

/* 10000 */
void
closing(void)
{
	int     i;

	prop[grate] = prop[fissure] = 0;
	for (i = 1; i <= 6; i++) {
		dseen[i] = FALSE;
		dloc[i] = 0;
	}
	move(troll, 0);
	move(troll + 100, 0);
	move(troll2, plac[troll]);
	move(troll2 + 100, fixd[troll]);
	juggle(chasm);
	if (prop[bear] != 3)
		destroy(bear);
	prop[chain] = 0;
	fixed[chain] = 0;
	prop[axe] = 0;
	fixed[axe] = 0;
	rspeak(129);
	clock1 = -1;
	isclosing = TRUE;
}

/* 11000 */
void
caveclose(void)
{
	int     i;
	prop[bottle] = put(bottle, 115, 1);
	prop[plant] = put(plant, 115, 0);
	prop[oyster] = put(oyster, 115, 0);
	prop[lamp] = put(lamp, 115, 0);
	prop[rod] = put(rod, 115, 0);
	prop[dwarf] = put(dwarf, 115, 0);
	loc = 115;
	oldloc = 115;
	newloc = 115;

	put(grate, 116, 0);
	prop[snake] = put(snake, 116, 1);
	prop[bird] = put(bird, 116, 1);
	prop[cage] = put(cage, 116, 0);
	prop[rod2] = put(rod2, 116, 0);
	prop[pillow] = put(pillow, 116, 0);

	prop[mirror] = put(mirror, 115, 0);
	fixed[mirror] = 116;

	for (i = 1; i <= 100; i++)
		if (toting(i))
			destroy(i);
	rspeak(132);
	closed = TRUE;
}
