[comp.sources.games] v10i079: nethack3p9 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 79
Archive-name: nethack3p9/Part34
Supersedes: NetHack3: Volume 7, Issue 56-93



#! /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 34 (of 56)."
# Contents:  src/dbridge.c src/pager.c src/sit.c
# Wrapped by billr@saab on Wed Jul 11 17:11:42 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/dbridge.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/dbridge.c'\"
else
echo shar: Extracting \"'src/dbridge.c'\" \(20980 characters\)
sed "s/^X//" >'src/dbridge.c' <<'END_OF_FILE'
X/*     SCCS Id: @(#)dbridge.c  3.0     88/18/12
X/*     Copyright (c) 1989 by Jean-Christophe Collet */
X/* NetHack may be freely redistributed.  See license for details. */
X
X/*
X * This file contains the drawbridge manipulation (create, open, close,
X * destroy).
X *
X * Added comprehensive monster-handling, and the "entity" structure to 
X * deal with players as well. - 11/89
X */
X
X#include "hack.h"
X
X#ifdef STRONGHOLD
X# ifdef OVLB
Xstatic void FDECL(redosym, (int, int));
Xstatic void FDECL(get_wall_for_db, (int *, int *));
Xstatic struct entity *FDECL(e_at, (int, int));
Xstatic void FDECL(m_to_e, (struct monst *, struct entity *));
Xstatic void FDECL(u_to_e, (struct entity *));
Xstatic void FDECL(set_entity, (int, int, struct entity *));
Xstatic char *FDECL(e_nam, (struct entity *));
X/* static char *FDECL(Enam, (struct entity *)); */ /* unused */
Xstatic char *FDECL(E_phrase, (struct entity *, const char *));
Xstatic boolean FDECL(e_survives_at, (struct entity *, int, int));
Xstatic void FDECL(e_died, (struct entity *, int, int));
Xstatic boolean FDECL(automiss, (struct entity *));
Xstatic boolean FDECL(e_missed, (struct entity *, BOOLEAN_P));
Xstatic boolean FDECL(e_jumps, (struct entity *));
Xstatic void FDECL(do_entity, (struct entity *));
X# endif /* OVLB */
X#endif /* STRONGHOLD */
X
X#ifdef OVL0
X
Xboolean
Xis_pool(x,y)
Xint x,y;
X{
X       if(levl[x][y].typ == POOL || levl[x][y].typ == MOAT) return TRUE;
X#ifdef STRONGHOLD
X       if(levl[x][y].typ == DRAWBRIDGE_UP &&
X               (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
X#endif
X       return FALSE;
X}
X
X#endif /* OVL0 */
X
X#ifdef STRONGHOLD
X
X#ifdef OVL1
X
Xvoid
Xinitsym(x,y)
Xint x,y;
X{
X	char oldseen;
X	struct rm *crm = &levl[x][y];
X
X	oldseen = crm->seen;
X	crm->seen = 1;
X	crm->scrsym = news0(x,y);
X	crm->seen = oldseen;
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
Xstatic void
Xredosym(x,y)
Xint x,y;
X{
X	if(cansee(x,y)) {
X		levl[x][y].seen = 0;            /* force prl */
X		prl(x, y);
X	} else {
X		initsym(x,y);
X		levl[x][y].seen = 0;
X	}
X}
X
X#endif /* OVLB */
X#ifdef OVL1
X
X/* 
X * We want to know whether a wall (or a door) is the portcullis (passageway)
X * of an eventual drawbridge.
X *
X * Return value:  the direction of the drawbridge.
X */
X
Xint
Xis_drawbridge_wall(x,y)
Xint x,y;
X{
X	struct rm *lev;
X
X	lev = &levl[x][y];
X	if (lev->typ != DOOR && !(lev->diggable & W_GATEWAY))
X		return (-1);
X	switch (lev->typ) {
X	case DOOR:
X	case VWALL:
X		if (IS_DRAWBRIDGE(levl[x+1][y].typ) &&
X	 	    (levl[x+1][y].drawbridgemask & DB_DIR) == DB_WEST)
X			return (DB_WEST);
X		if (IS_DRAWBRIDGE(levl[x-1][y].typ) && 
X		    (levl[x-1][y].drawbridgemask & DB_DIR) == DB_EAST)
X			return (DB_EAST);
X		if (lev->typ == VWALL) break;
X	case HWALL:
X		if (IS_DRAWBRIDGE(levl[x][y-1].typ) && 
X		    (levl[x][y-1].drawbridgemask & DB_DIR) == DB_SOUTH)
X			return (DB_SOUTH);
X		if (IS_DRAWBRIDGE(levl[x][y+1].typ) && 
X		    (levl[x][y+1].drawbridgemask & DB_DIR) == DB_NORTH)
X			return (DB_NORTH);
X	}
X	return (-1);
X}
X
X/*
X * Use is_db_wall where you want to verify that a
X * drawbridge "wall" is UP in the location x, y
X * (instead of UP or DOWN, as with is_drawbridge_wall). 
X */ 
Xboolean
Xis_db_wall(x,y)
Xint x,y;
X{
X	return( (levl[x][y].typ == VWALL || levl[x][y].typ == HWALL) &&
X		levl[x][y].diggable & W_GATEWAY);
X}
X
X
X/*
X * Return true with x,y pointing to the drawbridge if x,y initially indicate
X * a drawbridge or drawbridge wall.
X */
Xboolean
Xfind_drawbridge(x,y)
Xint *x,*y;
X{
X	int dir;
X
X	if (IS_DRAWBRIDGE(levl[*x][*y].typ))
X		return TRUE;
X	dir = is_drawbridge_wall(*x,*y);
X	if (dir >= 0) {
X		switch(dir) {
X			case DB_NORTH: (*y)++; break;
X			case DB_SOUTH: (*y)--; break;
X			case DB_EAST:  (*x)--; break;
X			case DB_WEST:  (*x)++; break;
X		}
X		return TRUE;
X	}
X	return FALSE;
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
X/* 
X * Find the drawbridge wall associated with a drawbridge.
X */
Xstatic void
Xget_wall_for_db(x,y)
Xint *x,*y;
X{
X	switch (levl[*x][*y].drawbridgemask & DB_DIR) {
X		case DB_NORTH: (*y)--; break;
X		case DB_SOUTH: (*y)++; break;
X		case DB_EAST:  (*x)++; break;
X		case DB_WEST:  (*x)--; break;
X	}
X}
X
X/*
X * Creation of a drawbridge at pos x,y.
X *     dir is the direction.
X *     flag must be put to TRUE if we want the drawbridge to be opened.
X */
X
Xboolean
Xcreate_drawbridge(x,y,dir,flag)
Xint x,y,dir;
Xboolean flag;
X{
X	int x2,y2;
X	uchar wall;
X
X	x2 = x; y2 = y;
X	switch(dir) {
X		case DB_NORTH:
X			wall = HWALL;
X			y2--;
X			break;
X		case DB_SOUTH:
X			wall = HWALL;
X			y2++;
X			break;
X		case DB_EAST:
X			wall = VWALL;
X			x2++;
X			break;
X		default:
X			impossible("bad direction in create_drawbridge");
X			/* fall through */
X		case DB_WEST:
X			wall = VWALL;
X			x2--;
X			break;
X	}
X	if (!IS_WALL(levl[x2][y2].typ))
X		return(FALSE);
X	if (flag) {             /* We want the bridge open */
X		levl[x][y].typ = DRAWBRIDGE_DOWN;
X		levl[x2][y2].typ = DOOR;
X		levl[x2][y2].doormask = D_NODOOR;
X	} else {
X		levl[x][y].typ = DRAWBRIDGE_UP;
X		levl[x2][y2].typ = wall;
X		/* Beware, drawbridges are non-diggable. */
X		levl[x2][y2].diggable = (W_NONDIGGABLE | W_GATEWAY);
X	}
X	levl[x][y].drawbridgemask = dir;        /* always have DB_MOAT */
X	initsym(x,y);
X	initsym(x2,y2);
X	return(TRUE);           
X}
X
Xstruct entity {
X	struct monst *emon;	   /* youmonst for the player */
X	struct permonst *edata;    /* must be non-zero for record to be valid */
X	int ex, ey;
X};
X
X#define ENTITIES 2
X
Xstatic struct entity NEARDATA occupants[ENTITIES];
X
Xstatic
Xstruct entity *
Xe_at(x, y)
Xint x, y;
X{
X	int entitycnt;
X	
X	for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++)
X		if ((occupants[entitycnt].edata) && 
X		    (occupants[entitycnt].ex == x) &&
X		    (occupants[entitycnt].ey == y))
X			break;
X#ifdef D_DEBUG
X	pline("entitycnt = %d", entitycnt);
X	fflush(stdout);
X#endif
X	return((entitycnt == ENTITIES)? 
X	       (struct entity *)0 : &(occupants[entitycnt]));
X}
X
Xstatic void
Xm_to_e(mtmp, etmp)
Xstruct monst *mtmp;
Xstruct entity *etmp;
X{
X	etmp->emon = mtmp;
X	if (mtmp) {
X		etmp->ex = mtmp->mx;
X		etmp->ey = mtmp->my;
X		etmp->edata = mtmp->data;
X	} else
X		etmp->edata = (struct permonst *)0;
X}
X
Xstatic void
Xu_to_e(etmp)
Xstruct entity *etmp;
X{
X	etmp->emon = &youmonst;
X	etmp->ex = u.ux;
X	etmp->ey = u.uy;
X	etmp->edata = uasmon;
X}
X
Xstatic void
Xset_entity(x, y, etmp)
Xint x, y;
Xstruct entity *etmp;
X{
X	if ((x == u.ux) && (y == u.uy))
X		u_to_e(etmp);
X	else
X		if (MON_AT(x, y))
X			m_to_e(m_at(x, y), etmp);
X		else
X			etmp->edata = (struct permonst *)0;
X}
X
X#ifdef POLYSELF
X#define is_u(etmp) (etmp->emon == &youmonst)
X#else
X#define is_u(x) FALSE
X#endif
X
X/* 
X * WARNING! THE FOLLOWING IS ONLY USEFUL FOR CANSEEMON, OR OTHER FUNCS WHICH 
X * ALWAYS RETURN TRUE FOR U.
X */
X
X#define e_boolean(etmp, func) (is_u(etmp)? (boolean)TRUE : func(etmp->emon)) 
X
X/*
X * e_strg is a utility routine which is not actually in use anywhere, since 
X * the specialized routines below suffice for all current purposes. 
X */
X
X/* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
X
Xstatic char *
Xe_nam(etmp)
Xstruct entity *etmp;
X{
X	return(is_u(etmp)? "you" : mon_nam(etmp->emon));
X}
X
X/*
X * Enam is another unused utility routine:  E_phrase is preferable.
X */
X
X/*
Xstatic char *
XEnam(etmp)
Xstruct entity *etmp;
X{
X	return(is_u(etmp)? "You" : Monnam(etmp->emon));
X}
X*/
X
X/*
X * Generates capitalized entity name, makes 2nd -> 3rd person conversion on 
X * verb, where necessary.
X */
X
Xstatic char *
XE_phrase(etmp, verb)
Xstruct entity *etmp;
Xconst char *verb;
X{
X	char wholebuf[80], verbbuf[30];
X
X	if (is_u(etmp)) 
X		Strcpy(wholebuf, "You");
X	else
X		Strcpy(wholebuf, Monnam(etmp->emon));
X	if (!*verb)
X		return(wholebuf);
X	Strcat(wholebuf, " ");
X	verbbuf[0] = '\0';
X	if (is_u(etmp)) 
X		Strcpy(verbbuf, verb);
X	else {
X		if (!strcmp(verb, "are"))
X			Strcpy(verbbuf, "is");
X		if (!strcmp(verb, "have"))
X			Strcpy(verbbuf, "has");
X		if (!verbbuf[0]) {
X			Strcpy(verbbuf, verb);
X			switch (verbbuf[strlen(verbbuf) - 1]) {
X				case 'y':
X					verbbuf[strlen(verbbuf) - 1] = '\0';
X					Strcat(verbbuf, "ies");
X					break;
X				case 'h':
X				case 'o':
X				case 's':
X					Strcat(verbbuf, "es");
X					break;
X				default:
X					Strcat(verbbuf, "s");
X					break;
X			}
X		}
X	}
X	Strcat(wholebuf, verbbuf);
X	return(wholebuf);
X}
X
X/*
X * Simple-minded "can it be here?" routine
X */
X
Xstatic boolean
Xe_survives_at(etmp, x, y)
Xstruct entity *etmp;
Xint x, y;
X{
X	if (noncorporeal(etmp->edata))
X		return(TRUE);
X	if (is_pool(x, y))
X		return((is_u(etmp) && (Wwalking || Levitation)) ||
X		       is_swimmer(etmp->edata) || is_flyer(etmp->edata) ||
X		       is_floater(etmp->edata));
X	if (is_db_wall(x, y))
X		return(passes_walls(etmp->edata));
X	return(TRUE);
X}
X
Xstatic void
Xe_died(etmp, dest, how)
Xstruct entity *etmp;
Xint dest, how;
X{
X	if (is_u(etmp)) {
X		if (how == DROWNING)
X			drown();
X		else {
X			coord xy;
X
X			killer_format = KILLED_BY_AN;
X			killer = "falling drawbridge";
X			done(how);
X			/* So, you didn't die */
X			if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
X				pline("A %s force teleports you away...",
X		      		      Hallucination ? "normal" : "strange");
X				(void) enexto(&xy, etmp->ex, etmp->ey,
X								etmp->edata);
X				teleds(xy.x, xy.y);
X			}
X		}
X	} else {
X		xkilled(etmp->emon, dest);
X		etmp->edata = (struct permonst *)0;	
X	}
X}
X
X
X/*
X * These are never directly affected by a bridge or portcullis.
X */
X
Xstatic boolean
Xautomiss(etmp)
Xstruct entity *etmp;
X{
X	return(passes_walls(etmp->edata) || noncorporeal(etmp->edata));
X}
X
X/*
X * Does falling drawbridge or portcullis miss etmp?
X */
X
Xstatic boolean
Xe_missed(etmp, chunks)
Xstruct entity *etmp;
Xboolean chunks;
X{
X	int misses;
X
X#ifdef D_DEBUG
X	if (chunks)
X		pline("Do chunks miss?");
X#endif
X	if (automiss(etmp))
X		return(TRUE);	
X
X	if (is_flyer(etmp->edata) && 
X	    (is_u(etmp)? !Sleeping : 
X	     (etmp->emon->mcanmove && !etmp->emon->msleep)))
X						  /* flying requires mobility */
X		misses = 5;	/* out of 8 */	
X	else
X		if (is_floater(etmp->edata) ||
X		    (is_u(etmp) && Levitation))	  /* doesn't require mobility */
X			misses = 3;
X		else
X			if (chunks && is_pool(etmp->ex, etmp->ey))
X				misses = 2; 		     /* sitting ducks */
X			else
X				misses = 0;	  
X
X	if (is_db_wall(etmp->ex, etmp->ey))
X		misses -= 3;				     /* less airspace */
X
X#ifdef D_DEBUG
X	pline("Miss chance = %d (out of 8)", misses);
X#endif
X
X	return((misses >= rnd(8))? TRUE : FALSE);
X}
X
X/*
X * Can etmp jump from death?
X */ 
X
Xstatic boolean
Xe_jumps(etmp)
Xstruct entity *etmp;
X{
X	int tmp = 4; 		/* out of 10 */
X
X	if (is_u(etmp)? (Sleeping || Fumbling) : 
X		        (!etmp->emon->mcanmove || etmp->emon->msleep || 
X			 !etmp->edata->mmove))
X		return(FALSE);
X
X	if (is_u(etmp)? Confusion : etmp->emon->mconf)
X		tmp -= 2;
X
X	if (is_u(etmp)? Stunned : etmp->emon->mstun)
X		tmp -= 3;
X
X	if (is_db_wall(etmp->ex, etmp->ey))
X		tmp -= 2;			     /* less room to maneuver */
X	
X#ifdef D_DEBUG
X	pline("%s to jump (%d chances in 10)", E_phrase(etmp, "try"), tmp);
X#endif
X	return((tmp >= rnd(10))? TRUE : FALSE);
X}
X
Xstatic void
Xdo_entity(etmp)
Xstruct entity *etmp;
X{
X	int newx, newy, at_portcullis, oldx, oldy;
X	boolean must_jump = FALSE, relocates = FALSE, e_inview;
X	struct rm *crm;
X
X	if (!etmp->edata)
X		return;
X
X	e_inview = e_boolean(etmp, canseemon);
X
X	oldx = etmp->ex;
X	oldy = etmp->ey;
X
X	at_portcullis = is_db_wall(oldx, oldy);
X
X	crm = &levl[oldx][oldy];
X
X	if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
X		char edifice[20];
X
X		if (e_inview) {
X			*edifice = '\0';
X			if ((crm->typ == DRAWBRIDGE_DOWN) ||
X		    	    (crm->typ == DRAWBRIDGE_UP))
X				Strcpy(edifice, "drawbridge");
X			else
X     				if (at_portcullis) 
X					Strcpy(edifice, "portcullis");
X			if (*edifice)
X				pline("The %s passes through %s!", edifice, 
X			      	      e_nam(etmp));			
X		}
X		return;
X	}
X	if (e_missed(etmp, FALSE)) { 
X		if (at_portcullis)
X			pline("The portcullis misses %s!",
X			      e_nam(etmp));
X#ifdef D_DEBUG
X		else
X			pline("The drawbridge misses %s!", 
X			      e_nam(etmp));
X#endif
X		if (e_survives_at(etmp, oldx, oldy)) 
X			return;
X		else {
X#ifdef D_DEBUG
X			pline("Mon can't survive here");
X#endif
X			if (at_portcullis)
X				must_jump = TRUE;
X			else
X				relocates = TRUE;  /* just ride drawbridge in */
X		}
X	} else {
X		if (crm->typ == DRAWBRIDGE_DOWN) {
X			pline("%s crushed underneath the drawbridge.",
X		      	      E_phrase(etmp, "are"));	   	   /* no jump */
X			e_died(etmp, e_inview? 2 : 3, CRUSHING); /* no corpse */
X			return;   /* Note: Beyond this point, we know we're   */
X		}                 /* not at an opened drawbridge, since all   */
X		must_jump = TRUE; /* *missable* creatures survive on the      */
X	}			  /* square, and all the unmissed ones die.   */
X	if (must_jump) 
X		if (at_portcullis) {
X			if (e_jumps(etmp)) {
X				relocates = TRUE;
X#ifdef D_DEBUG
X				pline("Jump succeeds!");
X#endif
X			} else {
X				if (e_inview)
X			       pline("%s crushed by the falling portcullis!",
X	      	      		     E_phrase(etmp, "are"));
X				else
X					if (flags.soundok)
X						You("hear a crushing sound.");
X				e_died(etmp, e_inview? 1 : 0, CRUSHING);
X								    /* corpse */
X				return;
X			}
X		} else {       /* tries to jump off bridge to original square */
X			relocates = !e_jumps(etmp); 
X#ifdef D_DEBUG
X			pline("Jump %s!", (relocates)? "fails" : "succeeds");
X#endif
X		}
X
X/*
X * Here's where we try to do relocation.  Assumes that etmp is not arriving
X * at the portcullis square while the drawbridge is falling, since this square
X * would be inaccessible (i.e. etmp started on drawbridge square) or 
X * unnecessary (i.e. etmp started here) in such a situation.
X */
X#ifdef D_DEBUG
X	pline("Doing relocation");
X#endif
X	newx = oldx;
X	newy = oldy;
X	(void)find_drawbridge(&newx, &newy);
X	if ((newx == oldx) && (newy == oldy))
X		get_wall_for_db(&newx, &newy);
X#ifdef D_DEBUG
X	pline("Checking new square for occupancy");
X#endif
X	if (relocates && (e_at(newx, newy))) { 
X
X/* 
X * Standoff problem:  one or both entities must die, and/or both switch 
X * places.  Avoid infinite recursion by checking first whether the other 
X * entity is staying put.  Clean up if we happen to move/die in recursion.
X */
X		struct entity *other;
X
X		other = e_at(newx, newy);
X#ifdef D_DEBUG
X		pline("New square is occupied by %s", e_nam(other));
X#endif
X		if (e_survives_at(other, newx, newy) && automiss(other)) {
X			relocates = FALSE;     	       /* "other" won't budge */
X#ifdef D_DEBUG
X			pline("%s suicide.", E_phrase(etmp, "commit"));
X#endif
X		} else {
X
X#ifdef D_DEBUG
X			pline("Handling %s", e_nam(other));
X#endif
X			while ((e_at(newx, newy)) && 
X			       (e_at(newx, newy) != etmp))
X		       		do_entity(other);
X#ifdef D_DEBUG
X			pline("Checking existence of %s", 
X			      e_nam(etmp));
X			fflush(stdout);
X#endif
X			if (e_at(oldx, oldy) != etmp) {
X#ifdef D_DEBUG
X			        pline("%s moved or died in recursion somewhere",
X				      E_phrase(etmp, "have"));
X				fflush(stdout);
X#endif
X				return;
X			}
X		}
X	}
X	if (relocates) {
X#ifdef D_DEBUG
X		pline("Moving %s", e_nam(etmp));
X#endif
X		if (!is_u(etmp)) {
X			remove_monster(etmp->ex, etmp->ey);
X			place_monster(etmp->emon, newx, newy);
X		} else {
X			u.ux = newx;
X			u.uy = newy;
X		}
X		etmp->ex = newx;
X		etmp->ey = newy;
X		e_inview = e_boolean(etmp, canseemon);
X	}
X#ifdef D_DEBUG
X	pline("Final disposition of %s", e_nam(etmp));
X	fflush(stdout);
X#endif
X	if (is_db_wall(etmp->ex, etmp->ey)) {
X#ifdef D_DEBUG
X		pline("%s in portcullis chamber", E_phrase(etmp, "are"));
X		fflush(stdout);
X#endif
X		if (e_inview)
X			if (is_u(etmp)) {
X				You("tumble towards the closed portcullis!"); 
X				if (automiss(etmp))
X					You("pass through it!");
X				else
X					pline("The drawbridge closes in...");
X			} else
X				pline("%s behind the drawbridge.",
X		      	      	      E_phrase(etmp, "disappear"));
X		if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
X			killer_format = KILLED_BY_AN;
X			killer = "closing drawbridge";
X			e_died(etmp, 0, CRUSHING); 		/* no message */
X			return;
X		}
X#ifdef D_DEBUG
X		pline("%s in here", E_phrase(etmp, "survive"));
X#endif
X	} else {
X#ifdef D_DEBUG
X		pline("%s on drawbridge square", E_phrase(etmp, "are"));
X#endif
X		if (is_pool(etmp->ex, etmp->ey) && !e_inview)
X			if (flags.soundok)
X				You("hear a splash.");
X		if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
X			if (e_inview && !is_flyer(etmp->edata) &&
X			    !is_floater(etmp->edata))
X				pline("%s from the bridge.",
X		      	      	      E_phrase(etmp, "fall"));	
X			return;	
X		}
X#ifdef D_DEBUG
X		pline("%s cannot survive on the drawbridge square", Enam(etmp));
X#endif
X		if (is_pool(etmp->ex, etmp->ey))
X			if (e_inview && 
X			    !is_u(etmp))  /* drown() will supply msgs if nec. */
X				if (Hallucination)
X				      pline("%s the moat and disappears.",
X					    E_phrase(etmp, "drink"));
X				else
X				      pline("%s into the moat.",
X			      	            E_phrase(etmp, "fall"));
X		killer_format = NO_KILLER_PREFIX;
X		killer = "fell from a drawbridge";
X		e_died(etmp, e_inview? 1 : 0,        /* CRUSHING is arbitrary */
X		       (is_pool(etmp->ex, etmp->ey))? DROWNING : CRUSHING);
X		       						    /* corpse */
X		return;
X	}
X}
X
X/*
X * Close the drawbridge located at x,y
X */
X
Xvoid
Xclose_drawbridge(x,y)
Xint x,y;
X{
X	register struct rm *lev1, *lev2;
X	struct obj *otmp, *otmp2;
X	int x2, y2;
X
X	lev1 = &levl[x][y];
X	if (lev1->typ != DRAWBRIDGE_DOWN) return;
X	x2 = x; y2 = y;
X	get_wall_for_db(&x2,&y2);
X	if (cansee(x,y))   /* change msgs if you are a w-walker at portcullis */
X		You("see a drawbridge %s up!", 
X		    ((u.ux == x2) && (u.uy == y2))? "coming" : "going");
X	lev1->typ = DRAWBRIDGE_UP;
X	lev2 = &levl[x2][y2];
X	switch (lev1->drawbridgemask & DB_DIR) {
X		case DB_NORTH:
X		case DB_SOUTH:
X			lev2->typ = HWALL;
X			break;
X		case DB_WEST:
X		case DB_EAST:
X			lev2->typ = VWALL;
X			break;
X	}
X	lev2->diggable = (W_NONDIGGABLE | W_GATEWAY);
X	set_entity(x, y, &(occupants[0]));
X	set_entity(x2, y2, &(occupants[1]));
X	do_entity(&(occupants[0]));
X	do_entity(&(occupants[1]));
X	redosym(x, y);
X	for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
X		otmp2 = otmp->nexthere;
X		delobj(otmp);
X	}
X	for (otmp = level.objects[x2][y2]; otmp; otmp = otmp2) {
X		otmp2 = otmp->nexthere;
X		delobj(otmp);
X	}
X	redosym(x2, y2);
X}
X
X/* 
X * Open the drawbridge located at x,y
X */
X
Xvoid
Xopen_drawbridge(x,y)
Xint x,y;
X{
X	register struct rm *lev1, *lev2;
X	int x2, y2;
X
X	lev1 = &levl[x][y];
X	if (lev1->typ != DRAWBRIDGE_UP) return;
X	x2 = x; y2 = y;
X	get_wall_for_db(&x2,&y2);
X	if (cansee(x,y))   /* change msgs if you are a w-walker at portcullis */
X		You("see a drawbridge %s down!",
X		    ((x2 == u.ux) && (y2 == u.uy))? "going" : "coming");
X	lev1->typ = DRAWBRIDGE_DOWN;
X	lev2 = &levl[x2][y2];
X	lev2->typ = DOOR;
X	lev2->doormask = D_NODOOR;
X	set_entity(x, y, &(occupants[0]));
X	set_entity(x2, y2, &(occupants[1]));
X	do_entity(&(occupants[0]));
X	do_entity(&(occupants[1]));
X	redosym(x, y);
X	redosym(x2, y2);
X}
X
X/*
X * Let's destroy the drawbridge located at x,y
X */
X
Xvoid
Xdestroy_drawbridge(x,y)
Xint x,y;
X{
X	register struct rm *lev1, *lev2;
X	int x2, y2;
X	boolean e_inview;
X	struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);
X
X	lev1 = &levl[x][y];
X	if (!IS_DRAWBRIDGE(lev1->typ))
X		return;
X	x2 = x; y2 = y;
X	get_wall_for_db(&x2,&y2);
X	lev2 = &levl[x2][y2];
X	if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT) {
X		if (lev1->typ == DRAWBRIDGE_UP) {
X			if (cansee(x2,y2))
X		pline("The portcullis of the drawbridge falls into the moat!");
X			else if (flags.soundok)
X				You("hear a loud *SPLASH*!");
X		} else {
X			if (cansee(x,y))
X			    pline("The drawbridge collapses into the moat!");
X			else if (flags.soundok)
X				You("hear a loud *SPLASH*!");
X		}
X		lev1->typ = MOAT;
X		lev1->drawbridgemask = 0;
X	} else {
X		if (cansee(x,y))
X			pline("The drawbridge disintegrates!");
X		else
X			You("hear a loud *CRASH*!");
X		lev1->typ = ROOM;
X		lev1->icedpool =
X			((lev1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
X	}
X	set_entity(x2, y2, etmp2); /* currently, only automissers can be here */
X	if (etmp2->edata) {
X		e_inview = e_boolean(etmp2, canseemon);
X		if (!automiss(etmp2)) {			   /* i.e. no-one yet */
X			if (e_inview)
X				pline("%s blown apart by flying debris",
X			      	      E_phrase(etmp2, "are"));
X			killer_format = KILLED_BY_AN;
X			killer = "exploding drawbridge";
X			e_died(etmp2, e_inview? 2 : 3, CRUSHING);/* no corpse */
X		}	      /* nothing which is vulnerable can survive this */
X	}
X	lev2->typ = DOOR;
X	lev2->doormask = D_NODOOR;
X	set_entity(x, y, etmp1);
X	if (etmp1->edata) {
X		e_inview = e_boolean(etmp1, canseemon);
X		if (e_missed(etmp1, TRUE)) {
X#ifdef D_DEBUG
X			pline("%s spared!", E_phrase(etmp1, "are"));
X#endif
X		} else {
X			if (e_inview) 
X				if (!is_u(etmp1) && Hallucination)
X					pline("%s into some heavy metal",
X					      E_phrase(etmp1, "get"));
X				else
X				    pline("%s hit by a huge chunk of metal!",
X			      	          E_phrase(etmp1, "are"));
X			else 
X				if (flags.soundok && !is_u(etmp1) && 
X				    !is_pool(x, y))
X					You("hear a crushing sound");
X#ifdef D_DEBUG
X				else
X					pline("%s from shrapnel", 
X					      E_phrase(etmp1, "die"));
X#endif
X			killer_format = KILLED_BY_AN;
X			killer = "collapsing drawbridge";
X			e_died(etmp1, e_inview? 0 : 1, CRUSHING);   /* corpse */
X		}
X	}
X	redosym(x,y);
X	redosym(x2,y2);
X}
X
X
X#endif /* OVLB */
X
X#endif /* STRONGHOLD /**/
END_OF_FILE
if test 20980 -ne `wc -c <'src/dbridge.c'`; then
    echo shar: \"'src/dbridge.c'\" unpacked with wrong size!
fi
# end of 'src/dbridge.c'
fi
if test -f 'src/pager.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/pager.c'\"
else
echo shar: Extracting \"'src/pager.c'\" \(28788 characters\)
sed "s/^X//" >'src/pager.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)pager.c	3.0	89/11/19
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X/* This file contains the command routine dowhatis() and a pager. */
X/* Also readmail() and doshell(), and generally the things that
X   contact the outside world. */
X
X#define MONATTK_H	/* comment line for pre-compiled headers */
X/* block some unused #defines to avoid overloading some cpp's */
X#include	"hack.h"
X
X#include <ctype.h>
X#ifndef NO_SIGNAL
X#include <signal.h>
X#endif
X#if defined(BSD) || defined(ULTRIX)
X#include <sys/wait.h>
X#endif
X#ifdef MACOS
Xextern WindowPtr	HackWindow;
Xextern short macflags;
X#endif
X
X#ifndef SEEK_SET
X#define SEEK_SET 0
X#endif
X
XSTATIC_DCL boolean FDECL(clear_help, (CHAR_P));
XSTATIC_DCL boolean FDECL(valid_help, (CHAR_P));
X
X#ifndef OVLB
XSTATIC_DCL char hc;
X#else /* OVLB */
XSTATIC_OVL char NEARDATA hc = 0;
X
Xstatic void FDECL(page_more, (FILE *,int));
Xstatic boolean FDECL(is_swallow_sym, (UCHAR_P));
Xstatic boolean FDECL(pmatch,(const char *,const char *));
Xstatic boolean FDECL(outspec,(const char *,int));
Xstatic const char *FDECL(lookat,(int,int,UCHAR_P));
X#ifdef WIZARD
Xstatic void NDECL(wiz_help);
X#endif
Xstatic void NDECL(help_menu);
X
X/*
X * simple pattern matcher: '*' matches 0 or more characters
X * returns TRUE if strng matches patrn
X */
X
Xstatic boolean
Xpmatch(patrn, strng)
X	const char *patrn, *strng;
X{
X	char s, p;
X
X	s = *strng;
X	p = *patrn;
X
X	if (!p) {
X		return (s == 0);
X	}
X
X	if (p == '*') {
X		if (!patrn[1] || pmatch(patrn+1, strng)) {
X			return TRUE;
X		}
X		return (s ? pmatch(patrn, strng+1) : FALSE);
X	}
X
X	return (p == s) ? pmatch(patrn+1, strng+1) : FALSE;
X}
X
X/*
X * returns "true" for characters that could represent a monster's stomach
X */
X
Xstatic boolean
Xis_swallow_sym(c)
Xuchar c;
X{
X	return (index(" /-\\|", (char)c) != 0);
X}
X
X/*
X * print out another possibility for dowhatis. "new" is the possible new
X * string; "out_flag" indicates whether we really want output, and if
X * so what kind of output: 0 == no output, 1 == "(or %s)" output. 
X * Returns TRUE if this new string wasn't the last string printed.
X */
X
Xstatic boolean
Xoutspec(new, out_flag)
Xconst char *new;
Xint out_flag;
X{
X	static char NEARDATA old[50];
X
X	if (!strcmp(old, new))
X		return FALSE;		/* don't print the same thing twice */
X
X	if (out_flag)
X		pline("(or %s)", an(new));
X
X	Strcpy(old, new);
X	return 1;
X}
X
X/*
X * return the name of the character ch found at (x,y)
X */
X
Xstatic
Xconst char *
Xlookat(x, y, ch)
Xint x,y;
Xuchar ch;
X{
X	register struct monst *mtmp;
X	register struct obj *otmp;
X	struct trap *trap;
X	static char NEARDATA answer[50];
X	register char *s, *t;
X	uchar typ;
X
X	answer[0] = 0;
X
X	if(MON_AT(x,y)) {
X		mtmp = m_at(x,y);
X		if (!showmon(mtmp) || Hallucination)
X			mtmp = (struct monst *)0;
X	} else
X		mtmp = (struct monst *) 0;
X	typ = levl[x][y].typ;
X	if (!Invisible 
X#ifdef POLYSELF
X			&& !u.uundetected
X#endif
X			&& u.ux==x && u.uy==y) {
X		Sprintf(answer, "%s named %s",
X#ifdef POLYSELF
X			u.mtimedone ? mons[u.umonnum].mname :
X#endif
X			pl_character, plname);
X	} else if (u.uswallow && is_swallow_sym(ch)) {
X		Sprintf(answer, "interior of %s", defmonnam(u.ustuck));
X	} else if (mtmp && !mtmp->mimic)
X		Sprintf(answer, "%s%s",
X		   mtmp->mtame ? "tame " :
X		   mtmp->mpeaceful ? "peaceful " : "",
X		   strncmp(lmonnam(mtmp), "the ", 4)
X			  ? lmonnam(mtmp) : lmonnam(mtmp)+4);
X	else if (!levl[x][y].seen)
X		Strcpy(answer,"dark part of a room");
X	else if (mtmp && mtmp->mimic) {
X		if (mtmp->m_ap_type == M_AP_FURNITURE) {
X			if (mtmp->mappearance == S_altar)
X				Strcpy(answer, "neutral altar");
X			else
X				Strcpy(answer, explainsyms[mtmp->mappearance]);
X		}
X		else if (mtmp->m_ap_type == M_AP_OBJECT) {
X			if (mtmp->mappearance == STRANGE_OBJECT)
X				Strcpy(answer, "strange object");
X			else {
X				int oindx = mtmp->mappearance;
X				otmp = mksobj(oindx,FALSE );
X				if(oindx == STATUE || oindx == FIGURINE)
X				    otmp->corpsenm = PM_KOBOLD;
X				else if (oindx == DRAGON_SCALE_MAIL)
X				    otmp->corpsenm = PM_RED_DRAGON;
X				Strcpy(answer, distant_name(otmp, xname));
X				free((genericptr_t) otmp);
X			}
X		}
X		else if (mtmp->m_ap_type == M_AP_GOLD)
X			Strcpy(answer, "pile of gold");
X	}
X	else if (OBJ_AT(x, y)) {
X		otmp = level.objects[x][y];
X		Strcpy(answer, distant_name(otmp, xname));
X	}
X	else if (ch == GOLD_SYM) {
X		Strcpy(answer, "pile of gold");
X	}
X#ifdef ALTARS
X	else if (ch == ALTAR_SYM && IS_ALTAR(typ)) {
X		int kind = levl[x][y].altarmask & ~A_SHRINE;
X		Sprintf( answer, "%s altar",
X			(kind == A_CHAOS) ? "chaotic" :
X			(kind == A_NEUTRAL) ? "neutral" :
X			 "lawful" );
X	}
X#endif
X#ifdef STRONGHOLD
X	else if ((ch == DB_VWALL_SYM || ch == DB_HWALL_SYM) && is_db_wall(x,y))
X		Strcpy(answer,"raised drawbridge");
X#endif
X#ifdef THRONES
X	else if ((ch == THRONE_SYM) && IS_THRONE(typ))
X		Strcpy(answer, "throne");
X#endif
X	else if ( (ch==H_OPEN_DOOR_SYM ||
X		   ch==V_OPEN_DOOR_SYM ||
X		   ch==CLOSED_DOOR_SYM ||
X		   ch==NO_DOOR_SYM) &&
X		  IS_DOOR(typ) ) {
X		switch(levl[x][y].doormask & ~D_TRAPPED) {
X			case D_NODOOR: Strcpy(answer,"doorway"); break;
X			case D_BROKEN: Strcpy(answer,"broken door"); break;
X			case D_ISOPEN: Strcpy(answer,"open door"); break;
X			default:       Strcpy(answer,"closed door"); break;
X					   /* locked or not */
X		}
X	}
X#ifdef SINKS
X	else if (ch == SINK_SYM && IS_SINK(levl[x][y].typ))
X		Strcpy(answer,"sink");
X#endif
X	else if ((ch == TRAP_SYM || ch == WEB_SYM) && (trap = t_at(x, y))) {
X		if (trap->ttyp == WEB && ch == WEB_SYM)
X			Strcpy(answer, "web");
X		else if (trap->ttyp != MONST_TRAP && ch == TRAP_SYM) {
X			Strcpy(answer, traps[ Hallucination ?
X				rn2(TRAPNUM-3)+3 : trap->ttyp]);
X		/* strip leading garbage */
X			for (s = answer; *s && *s != ' '; s++) ;
X			if (*s) ++s;
X			for (t = answer; *t++ = *s++; ) ;
X		}
X	}
X	else if (ch == UP_SYM && x == xupstair && y == yupstair)
X		Strcpy(answer, "staircase up");
X	else if (ch == DN_SYM && x == xdnstair && y == ydnstair)
X		Strcpy(answer, "staircase down");
X#ifdef STRONGHOLD
X	else if (ch == UPLADDER_SYM && x && x == xupladder && y == ydnladder)
X		Strcpy(answer, "ladder up");
X	else if (ch == DNLADDER_SYM && x && x == xdnladder && y == ydnladder)
X		Strcpy(answer, "ladder down");
X#endif
X	else if (IS_ROOM(typ)) {
X		if (ch == ROOM_SYM) {
X			if (levl[x][y].icedpool)
X			    Strcpy(answer,"iced pool");
X			else
X			    Strcpy(answer,"floor of a room");
X		}
X		else if (ch == STONE_SYM || ch == ' ')
X			Strcpy(answer,"dark part of a room");
X	}
X	else if (ch == CORR_SYM && SPACE_POS(typ))
X		Strcpy(answer,"corridor");
X	else if (!ACCESSIBLE(typ)) {
X		if (ch == STONE_SYM || ch == ' ')
X			Strcpy(answer,"dark part of a room");
X		else
X			Strcpy(answer,"wall");
X	}
X	return answer;
X}
X
X	
Xint
Xdowhatis()
X{
X	FILE *fp;
X	char buf[BUFSZ], inpbuf[BUFSZ];
X	register char *ep, *inp = inpbuf;
X	char *alt = 0;		/* alternate description */
X#ifdef __GNULINT__
X	const char *firstmatch = 0;
X#else
X	const char *firstmatch;
X#endif
X	uchar q;
X	register int i;
X	coord	cc;
X	boolean oldverb = flags.verbose;
X	boolean found_in_file = FALSE, need_to_print = FALSE;
X	int	found = 0;
X	static const char *mon_interior = "the interior of a monster";
X
X#ifdef OS2_CODEVIEW
X	char tmp[PATHLEN];
X
X	Strcpy(tmp,hackdir);
X	append_slash(tmp);
X	Strcat(tmp,DATAFILE);
X	fp = fopen(tmp,"r"));
X#else
X	fp = fopen(DATAFILE, "r");
X#endif
X	if(!fp) {
X#ifdef MACOS
X		fp = openFile(DATAFILE, "r");
X	}
X	if (!fp) {
X#endif
X		pline("Cannot open data file!");
X		return 0;
X	}
X
X	pline ("Specify unknown object by cursor? ");
X	q = ynq();
X	if (q == 'q') {
X		(void) fclose(fp);
X		return 0;
X	} else if (q == 'n') {
X		cc.x = cc.y = -1;
X		pline("Specify what? (type the word) ");
X		getlin(inp);
X		if (inp[0] == '\033' || !inp[0]) {
X			(void)fclose(fp);
X			return 0;
X		}
X		if (!inp[1])
X			q = inp[0];
X		else
X			q = 0;
X	} else {
X		cc.x = u.ux;
X		cc.y = u.uy;
Xselobj:
X		need_to_print = found_in_file = FALSE;
X		found = 0;
X		inp = inpbuf;
X		alt = 0;
X		(void) outspec("", 0);		/* reset output */
X		if(flags.verbose)
X			pline("Please move the cursor to an unknown object.");
X		else
X			pline("Pick an object.");
X		getpos(&cc, FALSE, "an unknown object");
X		if (cc.x < 0) {
X			    (void) fclose(fp); /* sweet@scubed */
X			    flags.verbose = oldverb;
X			    return 0;
X		}
X		flags.verbose = FALSE;
X		if (!u.uswallow) {
X			q = levl[cc.x][cc.y].scrsym;
X			if (!q || (!levl[cc.x][cc.y].seen && !MON_AT(cc.x,cc.y)))
X				q = ' ';
X		}
X		else if (cc.x == u.ux && cc.y == u.uy)
X			q = u.usym;
X		else {
X			i = (u.uy - cc.y)+1;
X			if (i < 0 || i > 2)
X				q = ' ';
X			else {
X				firstmatch = (i == 0) ? "/-\\" :
X					(i == 1) ? "| |" : "\\-/";
X				i = (u.ux - cc.x)+1;
X				if (i < 0 || i > 2)
X					q = ' ';
X				else
X					q = firstmatch[i];
X			}
X		}
X	}
X
X	if (!q)
X		goto checkfile; /* user typed in a complete string */
X
X	if (q != ' ' && index(quitchars, (char)q)) {
X		(void) fclose(fp); /* sweet@scubed */
X		flags.verbose = oldverb;
X		return 0;
X	}
X/*
X * if the user just typed one letter, or we're identifying from the
X * screen, then we have to check all the possibilities and print them
X * out for him/her.
X */
X
X/* Check for monsters */
X	for (i = 0; monsyms[i]; i++) {
X		if (q == monsyms[i]) {
X			need_to_print = TRUE;
X			pline("%c       %s",q,an(monexplain[i]));
X			(void) outspec(firstmatch = monexplain[i], 0);
X			found++;
X			break;
X		}
X	}
X
X/* Special case: if identifying from the screen, and
X * we're swallowed, and looking at something other than our own symbol,
X * then just say "the interior of a monster".
X */
X	if (u.uswallow && is_swallow_sym(q)) {
X		if (!found) {
X			pline("%c       %s", q, mon_interior);
X			(void)outspec(firstmatch=mon_interior, 0);
X		}
X		else
X			(void)outspec(mon_interior, 1);
X		found++; need_to_print = TRUE;
X	}
X
X/* Now check for objects */
X	for (i = 0; objsyms[i]; i++) {
X		if (q == objsyms[i]) {
X			need_to_print = TRUE;
X			if (!found) {
X				pline("%c       %s",q,an(objexplain[i]));
X				(void)outspec(firstmatch = objexplain[i], 0);
X				found++;
X			}
X			else if (outspec(objexplain[i], 1))
X				found++;
X		}
X	}
X
X/* Now check for graphics symbols */
X	for (i = 0; i < MAXPCHARS; i++) {
X		if ( q == showsyms[i] && (*explainsyms[i])) {
X			if (!found) {
X				pline("%c       %s",q,an(explainsyms[i]));
X				(void)outspec(firstmatch = explainsyms[i], 0);
X				found++;
X			}
X			else if (outspec(explainsyms[i], 1))
X				found++;
X			if (i == S_altar || i == S_trap || i == S_web)
X				need_to_print = TRUE;
X		}
X	}
X
X	if (!found)
X		pline("I've never heard of such things.");
X	else if (cc.x != -1) {	/* a specific object on screen */
X		if (found > 1 || need_to_print) {
X			Strcpy(inp, lookat(cc.x, cc.y, q));
X			if (*inp)
X				pline("(%s)", inp);
X		}
X		else {
X			Strcpy(inp, firstmatch);
X		}
X	}
X	else if (found == 1) {
X		Strcpy(inp, firstmatch);
X	}
X	else
X		found = FALSE;	/* abort the 'More info?' stuff */
X
X/* check the data file for information about this thing */
X
Xcheckfile:
X
X	if (!strncmp(inp, "interior of ", 12))
X		inp += 12;
X	if (!strncmp(inp, "a ", 2))
X		inp += 2;
X	else if (!strncmp(inp, "an ", 3))
X		inp += 3;
X	else if (!strncmp(inp, "the ", 4))
X		inp += 4;
X	if (!strncmp(inp, "tame ", 5))
X		inp += 5;
X	else if (!strncmp(inp, "peaceful ", 9))
X		inp += 9;
X	if (!strncmp(inp, "invisible ", 10))
X		inp += 10;
X
X/*
X * look in the file for more info if:
X * the user typed in the whole name (!q)
X * OR we've found a possible match with the character q (found) and
X *    flags.help is TRUE
X * and, of course, the name to look for must be non-empty.
X */
X	if ((!q || (found && flags.help)) && *inp) {
X/* adjust the input to remove "named " and convert to lower case */
X 		for (ep = inp; *ep; ) {
X			if ((!strncmp(ep, " named ", 7) && (alt = ep + 7)) ||
X			    !strncmp(ep, " called ", 8))
X				*ep = 0;
X			else {
X				if(isupper(*ep)) *ep = tolower(*ep);
X				ep++;
X			}
X		}
X
X/*
X * If the object is named, then the name is the alternate search string;
X * otherwise, the result of makesingular() applied to the name is. This
X * isn't strictly optimal, but named objects of interest to the user
X * will usually be found under their name, rather than under their
X * object type, so looking for a singular form is pointless.
X */
X
X		if (!alt)
X			alt = makesingular(inp);
X		else
X			for (ep = alt; *ep; ep++) 
X				if(isupper(*ep)) *ep = tolower(*ep);
X
X		while(fgets(buf,BUFSZ,fp)) {
X			if(*buf != '\t') {
X			    ep = index(buf, '\n');
X			    if(ep) *ep = 0;
X			    else impossible("bad data file");
X			    if (pmatch(buf, inp)||(alt && pmatch(buf, alt))) {
X				found_in_file = TRUE;
X				break;
X			    }
X			}
X		}
X	}
X
X	if(found_in_file) {
X/* skip over other possible matches for the info */
X		for(;;) {
X			if ( (i = getc(fp)) == '\t' ) {
X				(void) ungetc(i, fp);
X				break;
X			}
X			if (!fgets(buf, BUFSZ, fp)) {
X				break;
X			}
X		}
X		if (q) {
X			pline("More info? ");
X			if(yn() == 'y') {
X				page_more(fp,1); /* does fclose() */
X				flags.verbose = oldverb;
X				return 0;
X			}
X		}
X		else {
X			page_more(fp, 1);
X			flags.verbose = oldverb;
X			return 0;
X		}
X	}
X	else if (!q)
X		pline("I don't have any information on those things.");
X
X/* if specified by cursor, keep going */
X	if(cc.x != -1) {
X		more();
X		rewind(fp);
X		goto selobj;
X	}
X	(void) fclose(fp); 	/* kopper@psuvax1 */
X	flags.verbose = oldverb;
X	return 0;
X}
X
Xint
Xdowhatdoes()
X{
X	FILE *fp;
X	char bufr[BUFSZ+6];
X	register char *buf = &bufr[6], *ep, q, ctrl, meta;
X#ifdef OS2_CODEVIEW
X	char tmp[PATHLEN];
X
X	Strcpy(tmp,hackdir);
X	append_slash(tmp);
X	Strcat(tmp,CMDHELPFILE);
X	if(!(fp = fopen(tmp,"r"))) {
X#else
X# ifdef MACOS
X	if(!(fp = fopen(CMDHELPFILE, "r")))
X		fp = openFile(CMDHELPFILE, "r");
X	if (!fp) {
X# else
X	if(!(fp = fopen(CMDHELPFILE, "r"))) {
X# endif
X#endif
X		pline("Cannot open data file!");
X		return 0;
X	}
X
X	pline("What command? ");
X#if defined(UNIX) || defined(VMS)
X	introff();
X#endif
X	q = readchar();
X#if defined(UNIX) || defined(VMS)
X	intron();
X#endif
X	ctrl = ((q <= '\033') ? (q - 1 + 'A') : 0);
X	meta = ((0x80 & q) ? (0x7f & q) : 0);
X	while(fgets(buf,BUFSZ,fp))
X	    if ((ctrl && *buf=='^' && *(buf+1)==ctrl) ||
X		(meta && *buf=='M' && *(buf+1)=='-' && *(buf+2)==meta) ||
X		*buf==q) {
X		ep = index(buf, '\n');
X		if(ep) *ep = 0;
X		if (ctrl && buf[2] == '\t'){
X			buf = bufr + 1;
X			(void) strncpy(buf, "^?      ", 8);
X			buf[1] = ctrl;
X		} else if (meta && buf[3] == '\t'){
X			buf = bufr + 2;
X			(void) strncpy(buf, "M-?     ", 8);
X			buf[2] = meta;
X		} else if(buf[1] == '\t'){
X			buf = bufr;
X			buf[0] = q;
X			(void) strncpy(buf+1, "       ", 7);
X		}
X		pline("%s", buf);
X		(void) fclose(fp);
X		return 0;
X	    }
X	pline("I've never heard of such commands.");
X	(void) fclose(fp);
X	return 0;
X}
X
X/* make the paging of a file interruptible */
Xstatic volatile int NEARDATA got_intrup;
X
X#if !defined(MSDOS) && !defined(TOS) && !defined(MACOS)
Xstatic int
Xintruph(){
X	(void) signal(SIGINT, (SIG_RET_TYPE) intruph);
X	got_intrup++;
X	return 0;
X}
X#endif
X
X/* simple pager, also used from dohelp() */
Xstatic void
Xpage_more(fp,strip)
XFILE *fp;
Xint strip;	/* nr of chars to be stripped from each line (0 or 1) */
X{
X#ifdef MACOS
X	short tmpflags;
X	
X	tmpflags = macflags;
X	macflags &= ~fDoUpdate;
X	if(!mac_more(fp, strip)) {
X		macflags |= (tmpflags & fDoUpdate);
X		return;
X	}
X	macflags |= (tmpflags & fDoUpdate);
X#else
X	register char *bufr;
X#if !defined(MSDOS) && !defined(MINIMAL_TERM)
X	register char *ep;
X#endif
X#if !defined(MSDOS) && !defined(TOS)
X	int (*prevsig)() = (int (*)())signal(SIGINT, (SIG_RET_TYPE) intruph);
X#endif
X#if defined(MSDOS) || defined(MINIMAL_TERM)
X	/* There seems to be a bug in ANSI.SYS  The first tab character
X	 * after a clear screen sequence is not expanded correctly.  Thus
X	 * expand the tabs by hand -dgk
X	 */
X	int tabstop = 8, spaces;
X	char buf[BUFSIZ], *bufp, *bufrp;
X
X	set_pager(0);
X	bufr = (char *) alloc((unsigned) COLNO);
X	while (fgets(buf, BUFSIZ, fp) && (!strip || *buf == '\t')){
X		bufp = buf;
X		bufrp = bufr;
X		if (strip && *bufp && *bufp != '\n')
X			*bufrp++ = *bufp++;
X		while (*bufp && *bufp != '\n') {
X			if (*bufp == '\t') {
X				spaces = tabstop - (bufrp - bufr) % tabstop;
X				while (spaces--)
X					*bufrp++ = ' ';
X				bufp++;
X			} else
X				*bufrp++ = *bufp++;
X		}
X		*bufrp = '\0';
X#else /* MSDOS /**/
X	set_pager(0);
X	bufr = (char *) alloc((unsigned) COLNO);
X	bufr[COLNO-1] = 0;
X	while(fgets(bufr,COLNO-1,fp) && (!strip || *bufr == '\t')){
X		ep = index(bufr, '\n');
X		if(ep)
X			*ep = 0;
X#endif /* MSDOS /**/
X		if(got_intrup || page_line(bufr+strip)) {
X			set_pager(2);
X			goto ret;
X		}
X	}
X	set_pager(1);
Xret:
X	free((genericptr_t) bufr);
X	(void) fclose(fp);
X#if !defined(MSDOS) && !defined(TOS)
X	(void) signal(SIGINT, (SIG_RET_TYPE) prevsig);
X	got_intrup = 0;
X#endif
X#endif /* MACOS */
X}
X
X#endif /* OVLB */
X
X#define	PAGMIN	12	/* minimum # of lines for page below level map */
X
X#ifndef OVLB
X
XSTATIC_DCL boolean whole_screen;
X
X#else /* OVLB */
X
XSTATIC_OVL boolean NEARDATA whole_screen = TRUE;
X
Xvoid
Xset_whole_screen() {	/* called in termcap as soon as LI is known */
X	whole_screen = (LI-ROWNO-2 <= PAGMIN || !CD);
X}
X
X#ifdef NEWS
Xint
Xreadnews() {
X	register int ret;
X
X	whole_screen = TRUE;	/* force a docrt(), our first */
X	ret = page_file(NEWS, TRUE);
X	set_whole_screen();
X	return(ret);		/* report whether we did docrt() */
X}
X#endif
X
Xvoid
Xset_pager(mode)
Xregister int mode;	/* 0: open  1: wait+close  2: close */
X{
X#ifdef LINT	/* lint may handle static decl poorly -- static boolean so; */
X	boolean so;
X#else
X	static boolean NEARDATA so;
X#endif
X	if(mode == 0) {
X		if(!whole_screen) {
X			/* clear topline */
X			clrlin();
X			/* use part of screen below level map */
X			curs(1, ROWNO+4);
X		} else {
X			cls();
X		}
X		so = flags.standout;
X		flags.standout = 1;
X	} else {
X		if(mode == 1) {
X			curs(1, LI);
X			more();
X		}
X		flags.standout = so;
X		if(whole_screen)
X			docrt();
X		else {
X			curs(1, ROWNO+4);
X			cl_eos();
X		}
X	}
X}
X
X#endif /* OVLB */
X#ifdef OVL0
X
Xint
Xpage_line(s)		/* returns 1 if we should quit */
Xregister const char *s;
X{
X#ifdef CLIPPING
X/* we assume here that no data files have more than 80 chars/line */
X	static char tmp[81], *t;
X#endif
X	if(cury == LI-1) {
X		if(!*s)
X			return(0);	/* suppress blank lines at top */
X		(void) putchar('\n');
X		cury++;
X		cmore("q\033");
X		if(morc) {
X			morc = 0;
X			return(1);
X		}
X		if(whole_screen)
X			cls();
X		else {
X			curs(1, ROWNO+4);
X			cl_eos();
X		}
X	}
X#ifdef CLIPPING
X/* if lines are too long for the screen, first try stripping leading blanks */
X	if (strlen(s) >= CO) {
X		while (*s == ' ' || *s == '\t') s++;
X	}
X
X/* if it's still too long, try compressing blanks */
X	if (strlen(s) >= CO) {
X		t = tmp;
X		while ( (*t = *s) != 0) {
X			if (*t == ' ') {
X				while (*s == ' ')
X					s++;
X			}
X			else
X				s++;
X			t++;
X		}
X		s = tmp;
X	}
X#endif /* CLIPPING */
X
X#ifdef TERMINFO
X	xputs(s); xputc('\n');
X#else
X	(void) puts(s);
X# ifdef MACOS
X	(void) putchar('\n');
X# endif
X#endif
X	cury++;
X	return(0);
X}
X
X/*
X * Flexible pager: feed it with a number of lines and it will decide
X * whether these should be fed to the pager above, or displayed in a
X * corner.
X * Call:
X *	cornline(0, title or 0)	: initialize
X *	cornline(1, text)	: add text to the chain of texts
X *	cornline(2, morcs)	: output everything and cleanup
X *	cornline(3, 0)		: cleanup
X *	cornline(-1,"")		: special, for help menu mode only
X */
X
Xvoid
Xcornline(mode, text)
Xint mode;
Xconst char *text;
X{
X	static struct line {
X		struct line *next_line;
X		char *line_text;
X	} NEARDATA *texthead, NEARDATA *texttail;
X	static int NEARDATA maxlen;
X	static int NEARDATA linect;
X	register struct line *tl;
X	register boolean hmenu = FALSE;
X
X	if(mode == -1) { /* help menu display only */
X		mode = 2;
X		hmenu = TRUE;
X	}
X	if(mode == 0) {
X		texthead = 0;
X		maxlen = 0;
X		linect = 0;
X		if(text) {
X			cornline(1, text);	/* title */
X			cornline(1, "");	/* blank line */
X		}
X		return;
X	}
X
X	if(mode == 1) {
X	    register int len;
X
X	    if(!text) return;	/* superfluous, just to be sure */
X	    linect++;
X	    len = strlen(text) + 1; /* allow for an extra leading space */
X	    if(len > maxlen)
X		maxlen = len;
X	    tl = (struct line *)
X		alloc((unsigned)(len + sizeof(struct line) + 1));
X	    tl->next_line = 0;
X	    tl->line_text = (char *)(tl + 1);
X	    tl->line_text[0] = ' ';
X	    tl->line_text[1] = '\0';
X	    Strcat(tl->line_text, text);
X	    if(!texthead)
X		texthead = tl;
X	    else
X		texttail->next_line = tl;
X	    texttail = tl;
X	    return;
X	}
X
X	/* --- now we really do it --- */
X	if(mode == 2 && linect == 1)			    /* topline only */
X		pline("%s", texthead->line_text);
X	else
X	if(mode == 2) {
X	    register int curline, lth;
X
X	    if(flags.toplin == 1) more();	/* ab@unido */
X	    remember_topl();
X
X	    lth = CO - maxlen - 2;		   /* Use full screen width */
X	    if (linect < LI && lth >= 10) {		     /* in a corner */
X		home ();
X		cl_end ();
X		flags.toplin = 0;
X		curline = 1;
X		for (tl = texthead; tl; tl = tl->next_line) {
X#if defined(MSDOS) && !defined(AMIGA)
X		    cmov (lth, curline);
X#else
X		    curs (lth, curline);
X#endif
X		    if(curline > 1)
X			cl_end ();
X		    xputs(tl->line_text);
X		    curx = curx + strlen(tl->line_text);
X		    curline++;
X		}
X		if(hmenu) {	/* help menu display */
X			do 
X				hc = lowc(readchar());
X			while (!valid_help(hc));
X		}
X#if defined(MSDOS) && !defined(AMIGA)
X		cmov (lth, curline);
X#else
X		curs (lth, curline);
X#endif
X		cl_end ();
X		if (!hmenu) {
X			cmore (text);
X		}
X		if (!hmenu || clear_help(hc)) {
X		    home ();
X		    cl_end ();
X		    docorner (lth, curline-1);
X		}
X	    } else {					/* feed to pager */
X#ifdef MACOS
X		short	tmpflags;
X		
X		tmpflags = macflags;
X		macflags &= ~fDoNonKeyEvt;
X#endif
X		set_pager(0);
X		for (tl = texthead; tl; tl = tl->next_line) {
X		    if (page_line (tl->line_text)) {
X			set_pager(2);
X#ifdef MACOS
X			macflags = tmpflags;
X#endif
X			while(tl = texthead) {
X			    texthead = tl->next_line;
X			    free((genericptr_t) tl);
X			}
X			return;
X		    }
X		}
X		if(text) {
X			cgetret(text);
X			set_pager(2);
X		} else
X			set_pager(1);
X#ifdef MACOS
X		macflags = tmpflags;
X#endif
X	    }
X	}
X
X	while(tl = texthead) {
X		texthead = tl->next_line;
X		free((genericptr_t) tl);
X	}
X}
X
X#endif /* OVL0 */
X#ifdef OVLB
X
X#ifdef WIZARD
Xstatic
Xvoid
Xwiz_help()
X{
X	cornline(0, "Wizard-Mode Quick Reference:");
X	cornline(1, "^E  ==  detect secret doors and traps.");
X	cornline(1, "^F  ==  do magic mapping.");
X	cornline(1, "^G  ==  create monster.");
X	cornline(1, "^I  ==  identify items in pack.");
X	cornline(1, "^O  ==  tell locations of special levels.");
X	cornline(1, "^T  ==  do intra-level teleport.");
X	cornline(1, "^V  ==  do trans-level teleport.");
X	cornline(1, "^W  ==  make wish.");
X	cornline(1, "^X  ==  show intrinsic attributes.");
X	cornline(1, "");
X	cornline(2, "");
X}
X#endif
X
Xstatic void
Xhelp_menu() {
X	cornline(0, "Information available:");
X	cornline(1, "a.  Long description of the game and commands.");
X	cornline(1, "b.  List of game commands.");
X	cornline(1, "c.  Concise history of NetHack.");
X	cornline(1, "d.  Info on a character in the game display.");
X	cornline(1, "e.  Info on what a given key does.");
X	cornline(1, "f.  List of game options.");
X	cornline(1, "g.  Longer explanation of game options.");
X	cornline(1, "h.  List of extended commands.");
X	cornline(1, "i.  The NetHack license.");
X#ifdef MACOS
X	cornline(1, "j.  Macintosh primer.");
X#endif
X#ifdef WIZARD
X	if (wizard)
X# ifdef MACOS
X		cornline(1, "k.  List of wizard-mode commands.");
X# else
X		cornline(1, "j.  List of wizard-mode commands.");
X# endif
X#endif
X	cornline(1, "");
X#ifdef WIZARD
X	if (wizard)
X# ifdef MACOS
X		cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j,k or ESC: ");
X# else
X		cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j or ESC: ");
X# endif
X	else
X#endif
X#ifdef MACOS
X		cornline(1, "Select one of a,b,c,d,e,f,g,h,i,j or ESC: ");
X#else
X		cornline(1, "Select one of a,b,c,d,e,f,g,h,i or ESC: ");
X#endif
X	cornline(-1,"");
X}
X
XSTATIC_OVL boolean
Xclear_help(c)
Xchar c;
X{
X	/* those valid_help characters which do not correspond to help routines
X	 * that redraw the whole screen on their own.  if we always clear the
X	 * help menu, we end up restoring the part of the maze underneath the
X	 * help menu when the last page of a long help file is displayed with
X	 * an external pager.
X	 *
X	 * When whole_screen is FALSE and the internal pager is used, the
X	 * screen is big enough so that the maze is left in place during paging
X	 * and the paging occurs in the lower part of the screen.  In this case
X	 * the pager clears out the part it wrote over when it exits but it
X	 * doesn't redraw the whole screen.  So all characters require that
X	 * the help menu be cleared.
X	 *
X	 * When an external pager is used, the screen is always cleared.
X	 * However, the "f" and "h" help options always use the internal
X	 * pager even if DEF_PAGER is defined.
X	 *                        - Bob Wilber  wilber@homxb.att.com  10/20/89
X	 */
X	return(index(quitchars,c) || c == 'd' || c == 'e'
X#ifdef DEF_PAGER
X	        || (!whole_screen && (c == 'f' || c == 'h'))
X#else
X	        || !whole_screen
X#endif
X#ifdef WIZARD
X# ifdef MACOS
X		|| c == 'k'
X# else
X		|| c == 'j'
X# endif
X#endif
X		);
X}
X
XSTATIC_OVL boolean
Xvalid_help(c)
Xchar c;
X{
X#ifdef WIZARD
X# ifdef MACOS
X	return ((c >= 'a' && c <= (wizard ? 'k' : 'j')) || index(quitchars,c));
X# else
X	return ((c >= 'a' && c <= (wizard ? 'j' : 'i')) || index(quitchars,c));
X# endif
X#else
X# ifdef MACOS
X	return ((c >= 'a' && c <= 'j') || index(quitchars,c));
X# else
X	return ((c >= 'a' && c <= 'i') || index(quitchars,c));
X# endif
X#endif
X}
X
Xint
Xdohelp()
X{
X#ifdef MACOS
X	term_info	*t;
X
X	macflags &= ~fDoNonKeyEvt;
X	t = (term_info *)GetWRefCon(HackWindow);
X	SetVol((StringPtr)NULL,
X		(t->auxFileVRefNum) ? t->auxFileVRefNum : t->recordVRefNum);
X#endif
X	help_menu();
X	if (!index(quitchars, hc)) {
X		switch(hc) {
X			case 'a':  (void) page_file(HELP, FALSE);  break;
X			case 'b':  (void) page_file(SHELP, FALSE);  break;
X			case 'c':  (void) dohistory();  break;
X			case 'd':  (void) dowhatis();  break;
X			case 'e':  (void) dowhatdoes();  break;
X			case 'f':  option_help();  break;
X			case 'g':  (void) page_file(OPTIONFILE, FALSE);  break;
X			case 'h':  (void) doextlist();  break;
X			case 'i':  (void) page_file(LICENSE, FALSE);  break;
X#ifdef WIZARD
X# ifdef MACOS
X			case 'j':  (void) page_file(MACHELP, FALSE);  break;
X			case 'k':  wiz_help();  break;
X# else
X			case 'j':  wiz_help();  break;
X# endif
X#endif
X		}
X	}
X#ifdef MACOS
X	SetVol((StringPtr)NULL, t->recordVRefNum);
X	macflags |= fDoNonKeyEvt;
X#endif
X	return 0;
X}
X
Xint
Xdohistory()
X{
X	(void) page_file(HISTORY, FALSE);
X	return 0;
X}
X
Xint
Xpage_file(fnam, silent)	/* return: 0 - cannot open fnam; 1 - otherwise */
Xregister const char *fnam;
Xboolean silent;
X{
X#ifdef DEF_PAGER			/* this implies that UNIX is defined */
X      {
X	/* use external pager; this may give security problems */
X
X	register int fd = open(fnam, 0);
X
X	if(fd < 0) {
X		if(!silent) pline("Cannot open %s.", fnam);
X		return(0);
X	}
X	if(child(1)){
X		/* Now that child() does a setuid(getuid()) and a chdir(),
X		   we may not be able to open file fnam anymore, so make
X		   it stdin. */
X		(void) close(0);
X		if(dup(fd)) {
X			if(!silent) Printf("Cannot open %s as stdin.\n", fnam);
X		} else {
X			(void) execl(catmore, "page", NULL);
X			if(!silent) Printf("Cannot exec %s.\n", catmore);
X		}
X		exit(1);
X	}
X	(void) close(fd);
X      }
X#else
X      {
X	FILE *f;			/* free after Robert Viduya */
X#ifdef OS2_CODEVIEW
X	char tmp[PATHLEN];
X
X	Strcpy(tmp,hackdir);
X	append_slash(tmp);
X	Strcat(tmp,fnam);
X	if ((f = fopen (tmp, "r")) == (FILE *) 0) {
X#else
X# ifdef MACOS
X	if ((f = fopen (fnam, "r")) == (FILE *) 0)
X		f = openFile(fnam, "r");
X	if (!f) {
X# else
X	if ((f = fopen (fnam, "r")) == (FILE *) 0) {
X# endif
X#endif
X		if(!silent) {
X			home(); perror (fnam); flags.toplin = 1;
X			pline ("Cannot open %s.", fnam);
X		}
X		return(0);
X	}
X	page_more(f, 0);
X      }
X#endif /* DEF_PAGER /**/
X
X	return(1);
X}
X
X#ifdef UNIX
X#ifdef SHELL
Xint
Xdosh(){
Xregister char *str;
X	if(child(0)) {
X		if(str = getenv("SHELL"))
X			(void) execl(str, str, NULL);
X		else
X			(void) execl("/bin/sh", "sh", NULL);
X		pline("sh: cannot execute.");
X		exit(1);
X	}
X	return 0;
X}
X#endif /* SHELL /**/
X
X#if defined(SHELL) || defined(DEF_PAGER) || defined(DEF_MAILREADER)
Xint
Xchild(wt)
Xint wt;
X{
Xregister int f = fork();
X	if(f == 0){		/* child */
X		settty(NULL);		/* also calls end_screen() */
X		(void) setgid(getgid());
X		(void) setuid(getuid());
X#ifdef CHDIR
X		(void) chdir(getenv("HOME"));
X#endif
X		return(1);
X	}
X	if(f == -1) {	/* cannot fork */
X		pline("Fork failed.  Try again.");
X		return(0);
X	}
X	/* fork succeeded; wait for child to exit */
X	(void) signal(SIGINT,SIG_IGN);
X	(void) signal(SIGQUIT,SIG_IGN);
X	(void) wait(
X#if defined(BSD) || defined(ULTRIX)
X		(union wait *)
X#else
X		(int *)
X#endif
X		0);
X	gettty();
X	setftty();
X	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#ifdef WIZARD
X	if(wizard) (void) signal(SIGQUIT,SIG_DFL);
X#endif
X	if(wt) {
X		boolean so;
X
X		cmov(1, LI);	/* get prompt in reasonable place */
X		so = flags.standout;
X		flags.standout = 1;
X		more();
X		flags.standout = so;
X	}
X	docrt();
X	return(0);
X}
X#endif
X#endif /* UNIX /**/
X
X#endif /* OVLB */
END_OF_FILE
if test 28788 -ne `wc -c <'src/pager.c'`; then
    echo shar: \"'src/pager.c'\" unpacked with wrong size!
fi
# end of 'src/pager.c'
fi
if test -f 'src/sit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/sit.c'\"
else
echo shar: Extracting \"'src/sit.c'\" \(5549 characters\)
sed "s/^X//" >'src/sit.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)sit.c	3.0	89/06/12
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X
X#if defined(THRONES) || defined(SPELLS)
Xvoid
Xtake_gold()
X{
X	if (u.ugold <= 0)  {
X		You("feel a strange sensation.");
X	} else {
X		You("notice you have no gold!");
X		u.ugold = 0;
X		flags.botl = 1;
X	}
X}
X#endif
X
Xint
Xdosit() {
X#ifdef THRONES
X	register int cnt;
X#endif
X
X	if(Levitation)  {
X	    pline("There's nothing to sit on up here.");
X#ifdef THRONES
X	} else  if(IS_THRONE(levl[u.ux][u.uy].typ)) {
X
X	    if (rnd(6) > 4)  {
X		switch (rnd(13))  {
X		    case 1:
X			adjattrib(rn2(A_MAX), -rn1(4,3), FALSE);
X			losehp(rnd(10), "cursed throne", KILLED_BY_AN);
X			break;
X		    case 2:
X			adjattrib(rn2(A_MAX), 1, FALSE);
X			break;
X		    case 3:
X		pline("A%s charge of electricity shoots through your body!",
X			      (Shock_resistance) ? "" : " massive");
X			if(Shock_resistance)
X				losehp(rnd(6), "electric chair", KILLED_BY_AN);
X			else	losehp(rnd(30), "electric chair", KILLED_BY_AN);
X			break;
X		    case 4:
X			You("feel much, much better!");
X			if(u.uhp >= (u.uhpmax - 5))  u.uhpmax += 4;
X			u.uhp = u.uhpmax;
X			make_blinded(0L,TRUE);
X			make_sick(0L,FALSE);
X			heal_legs();
X			flags.botl = 1;
X			break;
X		    case 5:
X			take_gold();
X			break;
X		    case 6:
X			if(u.uluck + rn2(5) < 0) {
X			    You("feel your luck is changing.");
X			    change_luck(1);
X			} else	    makewish();
X			break;
X		    case 7:
X			cnt = rnd(10);
X			You("hear a voice echo:");
X			pline("\"Thy audience hath been summoned, Sire!\"");
X			while(cnt--)
X			    (void) makemon(courtmon(), u.ux, u.uy);
X			break;
X		    case 8:
X			You("hear a voice echo:");
X			pline("\"By thy Imperious order, Sire...\"");
X			do_genocide(1);
X			break;
X		    case 9:
X			You("hear a voice echo:");
X	pline("\"A curse upon thee for sitting upon this most holy throne!\"");
X			if (Luck > 0)  {
X			    make_blinded(Blinded + rn1(100,250),TRUE);
X			} else	    rndcurse();
X			break;
X		    case 10:
X			if (Luck < 0 || (HSee_invisible & INTRINSIC))  {
X				pline("An image forms in your mind.");
X				do_mapping();
X			} else  {
X				Your("vision clarifies.");
X				HSee_invisible |= INTRINSIC;
X			}
X			break;
X		    case 11:
X			if (Luck < 0)  {
X			    You("feel threatened.");
X			    aggravate();
X			} else  {
X
X			    You("feel a wrenching sensation.");
X			    tele();		/* teleport him */
X			}
X			break;
X		    case 12:
X			You("are granted a gift of insight!");
X			while (!ggetobj("identify", identify, rn2(5))
X				&& invent);
X			break;
X		    case 13:
X			Your("mind turns into a pretzel!");
X			make_confused(HConfusion + rn1(7,16),FALSE);
X			break;
X		    default:	impossible("throne effect");
X				break;
X		}
X	    } else	You("feel somehow out of place...");
X
X	    if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ))	{
X		pline("The throne vanishes in a puff of logic.");
X/*		levl[u.ux][u.uy].scrsym = ROOM_SYM; */
X		levl[u.ux][u.uy].typ = ROOM;
X		if(Invisible) newsym(u.ux,u.uy);
X	    }
X#endif
X#ifdef POLYSELF
X	} else if (lays_eggs(uasmon) || u.umonnum == PM_QUEEN_BEE) {
X		struct obj *uegg;
X
X		if (u.uhunger < objects[EGG].nutrition) {
X			You("are too weak to lay an egg.");
X			return 0;
X		}
X
X		uegg = mksobj(EGG, 0);
X		uegg->spe = 1;
X		uegg->quan = 1;
X		uegg->owt = weight(uegg);
X		uegg->corpsenm =
X		    (u.umonnum==PM_QUEEN_BEE ? PM_KILLER_BEE : monsndx(uasmon));
X		uegg->known = uegg->dknown = 1;
X		You("lay an egg.");
X		dropy(uegg);
X		stackobj(uegg);
X		morehungry(objects[EGG].nutrition);
X#endif
X	} else
X		pline("Having fun sitting on the floor?");
X	return(1);
X}
X
Xvoid
Xrndcurse() {			/* curse a few inventory items at random! */
X
X	int	nobj = 0;
X	int	cnt, onum;
X	struct	obj	*otmp;
X
X	if(Antimagic) {
X	    shieldeff(u.ux, u.uy);
X	    You("feel a malignant aura surround you.");
X	}
X
X	for (otmp = invent; otmp; otmp = otmp->nobj)  nobj++;
X
X	if (nobj)
X	    for (cnt = rnd(6/((!!Antimagic) + 1)); cnt > 0; cnt--)  {
X		onum = rn2(nobj);
X		for(otmp = invent; onum != 0; onum--)
X		    otmp = otmp->nobj;
X		if(otmp->blessed)
X			otmp->blessed = 0;
X		else
X			otmp->cursed++;
X	    }
X}
X
Xvoid
Xattrcurse() {			/* remove a random INTRINSIC ability */
X	switch(rnd(10)) {
X	case 1 : if (HFire_resistance & INTRINSIC) {
X			HFire_resistance &= ~INTRINSIC;
X			if (Inhell && !Fire_resistance) {
X			    You("burn to a crisp.");
X			    killer_format = NO_KILLER_PREFIX;
X			    killer = self_pronoun("a gremlin stole %s fire resistance in hell", "his");
X			    done(BURNING);
X			} else You("feel warmer.");
X			break;
X		}
X	case 2 : if (HTeleportation & INTRINSIC) {
X			HTeleportation &= ~INTRINSIC;
X			You("feel less jumpy.");
X			break;
X		}
X	case 3 : if (HPoison_resistance & INTRINSIC) {
X			HPoison_resistance &= ~INTRINSIC;
X			You("feel a little sick!");
X			break;
X		}
X	case 4 : if (HTelepat & INTRINSIC) {
X			HTelepat &= ~INTRINSIC;
X			Your("senses fail!");
X			break;
X		}
X	case 5 : if (HCold_resistance & INTRINSIC) {
X			HCold_resistance &= ~INTRINSIC;
X			You("feel cooler.");
X			break;
X		}
X	case 6 : if (HInvis & INTRINSIC) {
X			HInvis &= ~INTRINSIC;
X			You("feel paranoid.");
X			break;
X		}
X	case 7 : if (HSee_invisible & INTRINSIC) {
X			HSee_invisible &= ~INTRINSIC;
X			You("thought you saw something!");
X			break;
X		}
X	case 8 : if (Fast & INTRINSIC) {
X			Fast &= ~INTRINSIC;
X			You("feel slower.");
X			break;
X		}
X	case 9 : if (Stealth & INTRINSIC) {
X			Stealth &= ~INTRINSIC;
X			You("feel clumsy.");
X			break;
X		}
X	case 10: if (Protection & INTRINSIC) {
X			Protection &= ~INTRINSIC;
X			You("feel vulnerable.");
X			break;
X		}
X	default: break;
X	}
X}
END_OF_FILE
if test 5549 -ne `wc -c <'src/sit.c'`; then
    echo shar: \"'src/sit.c'\" unpacked with wrong size!
fi
# end of 'src/sit.c'
fi
echo shar: End of archive 34 \(of 56\).
cp /dev/null ark34isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 56 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0