[comp.sources.games] v07i068: NetHack3 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/24/89)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 68
Archive-name: NetHack3/Part13



#! /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 13 (of 38)."
# Contents:  src/alloc.c src/mon.c src/polyself.c
# Wrapped by billr@saab on Sun Jul 23 21:32:56 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/alloc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/alloc.c'\"
else
echo shar: Extracting \"'src/alloc.c'\" \(853 characters\)
sed "s/^X//" >'src/alloc.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)alloc.c	3.0	88/07/21
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X/* since this file is also used in auxiliary programs, don't include all the 
X * function declarations for all of nethack
X */
X#define EXTERN_H
X#include "config.h"
X
X#ifdef LINT
X/*
X   a ridiculous definition, suppressing
X	"possible pointer alignment problem" for (long *) malloc()
X   from lint
X*/
Xlong *
Xalloc(n) unsigned int n; {
Xlong dummy = ftell(stderr);
X	if(n) dummy = 0;	/* make sure arg is used */
X	return(&dummy);
X}
X
X#else
X#ifndef __TURBOC__
Xextern void panic P((char *,...));
X
Xlong *
Xalloc(lth)
Xregister unsigned int lth;
X{
X	register genericptr_t ptr;
X
X	if(!(ptr = malloc(lth)))
X		panic("Cannot get %d bytes", lth);
X	return((long *) ptr);
X}
X#endif
X
X
X#endif /* LINT /**/
END_OF_FILE
if test 853 -ne `wc -c <'src/alloc.c'`; then
    echo shar: \"'src/alloc.c'\" unpacked with wrong size!
fi
# end of 'src/alloc.c'
fi
if test -f 'src/mon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/mon.c'\"
else
echo shar: Extracting \"'src/mon.c'\" \(31897 characters\)
sed "s/^X//" >'src/mon.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)mon.c	3.0	88/10/31
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X#include "mfndpos.h"
X#ifdef NAMED_ITEMS
X#  include "artifact.h"
X#endif
X
X#ifdef HARD
Xstatic boolean restrap();
X#endif
X
Xlong lastwarntime;
Xint lastwarnlev;
Xstatic const char *warnings[] = {
X	"white", "pink", "red", "ruby", "purple", "black" };
Xstruct monst *fdmon;	/* chain of dead monsters, need not to be saved */
X
X/* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
X * leave corpses.  Monsters which leave "special" corpses should have
X * G_NOCORPSE set in order to prevent wishing for one, finding tins of one,
X * etc....
X */
Xstatic struct obj *
Xmake_corpse(mtmp)
Xregister struct monst *mtmp;
X{
X	register struct permonst *mdat = mtmp->data;
X#ifdef GOLEMS
X	int pieces;
X#endif
X	struct obj *obj = 0;
X	int x = mtmp->mx, y = mtmp->my;
X
X	switch(monsndx(mdat)) {
X	    case PM_KOBOLD_MUMMY:
X		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
X	    case PM_KOBOLD_ZOMBIE:
X		obj = mksobj_at(CORPSE, x, y);
X		obj->corpsenm = PM_KOBOLD;
X		break;
X	    case PM_GNOME_MUMMY:
X		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
X	    case PM_GNOME_ZOMBIE:
X		obj = mksobj_at(CORPSE, x, y);
X		obj->corpsenm = PM_GNOME;
X		break;
X	    case PM_ORC_MUMMY:
X		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
X	    case PM_ORC_ZOMBIE:
X		obj = mksobj_at(CORPSE, x, y);
X		obj->corpsenm = PM_ORC;
X		break;
X	    case PM_ELF_MUMMY:
X		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
X	    case PM_ELF_ZOMBIE:
X		obj = mksobj_at(CORPSE, x, y);
X		obj->corpsenm = PM_ELF;
X		break;
X	    case PM_HUMAN_MUMMY:
X		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
X	    case PM_HUMAN_ZOMBIE:
X		obj = mksobj_at(CORPSE, x, y);
X		obj->corpsenm = PM_HUMAN;
X		break;
X	    case PM_GIANT_MUMMY:
X		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
X	    case PM_GIANT_ZOMBIE:
X		obj = mksobj_at(CORPSE, x, y);
X		obj->corpsenm = PM_GIANT;
X		break;
X	    case PM_ETTIN_MUMMY:
X		obj = mksobj_at(MUMMY_WRAPPING, x, y); /* and fall through */
X	    case PM_ETTIN_ZOMBIE:
X		obj = mksobj_at(CORPSE, x, y);
X		obj->corpsenm = PM_ETTIN;
X		break;
X#ifdef GOLEMS
X	    case PM_IRON_GOLEM:
X		pieces = d(2,6);
X		while (pieces--)
X			obj = mksobj_at(IRON_CHAIN, x, y);
X		break;
X	    case PM_CLAY_GOLEM:
X		obj = mksobj_at(ROCK, x, y);
X		obj->quan = rn2(20) + 100;
X		obj->owt = weight(obj);
X		break;
X	    case PM_STONE_GOLEM:
X		obj = mkstatue(mdat, x, y);
X		break;
X	    case PM_WOOD_GOLEM:
X		pieces = d(2,4);
X		while(pieces--)
X			obj = mksobj_at(QUARTERSTAFF, x, y);
X		break;
X	    case PM_LEATHER_GOLEM:
X		pieces = d(2,4);
X		while(pieces--)
X			obj = mksobj_at(LEATHER_ARMOR, x, y);
X		break;
X#endif
X	    default:
X		if (mdat->geno & G_NOCORPSE)
X			return (struct obj *)0;
X		else obj = mkcorpse_at(mdat, x, y);
X		break;
X	}
X	/* All special cases should precede the G_NOCORPSE check */
X
X	/* Note: oname() cannot be used generically for non-inventory objects
X	 * unless you fix the link from the previous object in the chain.
X	 * (Here we know it's the first one, so there was no link.)
X	 */
X	if (mtmp->mnamelth) {
X		obj = oname(obj, NAME(mtmp), 0);
X		fobj = obj;
X	}
X	stackobj(fobj);
X	newsym(x, y);
X	return obj;
X}
X
X
Xstatic void
Xdmonsfree(){
Xregister struct monst *mtmp;
X	while(mtmp = fdmon){
X		fdmon = mtmp->nmon;
X		free((genericptr_t) mtmp);
X	}
X}
X
Xvoid
Xmovemon()
X{
X	register struct monst *mtmp;
X	register int fr;
X
X	warnlevel = 0;
X
X	while(1) {
X		/*  Find a monster that we have not treated yet.
X		 *  Note that mtmp or mtmp->nmon might get killed
X		 *  while mtmp moves, so we cannot just walk down the
X		 *  chain (even new monsters might get created!)
X		 */
X		/* Do tame monsters first.  Necessary so that when the tame
X		 * monster attacks something, the something gets a chance to
X		 * attack the tame monster back (which it's permitted to do
X		 * only if it hasn't made its move yet).
X		 */
X		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X			if(mtmp->mlstmv < moves && mtmp->mtame) goto next_mon;
X		for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X			if(mtmp->mlstmv < moves && !mtmp->mtame) goto next_mon;
X		/* treated all monsters */
X		break;
X
X	next_mon:
X		mtmp->mlstmv = moves;
X
X		/* most monsters drown in pools */
X		{ boolean inpool,infountain,iseel,isgremlin;
X
X		  inpool = is_pool(mtmp->mx,mtmp->my);
X		  iseel = mtmp->data->mlet == S_EEL;
X		  isgremlin = mtmp->data->mlet == S_GREMLIN;
X		  infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
X		/* Gremlin multiplying won't go on forever since the hit points
X		 * keep going down, and when it gets to 1 hit point the clone
X		 * function will fail.
X		 */
X		  if((inpool || infountain) && isgremlin && rn2(3)) {
X			struct monst *mtmp2 = clone_mon(mtmp);
X
X			if (mtmp2) {
X			    mtmp2->mhpmax = (mtmp->mhpmax /= 2);
X			    if(cansee(mtmp->mx,mtmp->my))
X				pline("%s multiplies.", Monnam(mtmp));
X			}
X#ifdef FOUNTAINS
X			if (infountain) dryup();
X#endif
X		  } else
X		  if(inpool && !is_flyer(mtmp->data) && !is_swimmer(mtmp->data)) {
X			if(cansee(mtmp->mx,mtmp->my))
X			    pline("%s drowns.", Monnam(mtmp));
X			mondead(mtmp);
X			continue;
X		  } else
X		/* but eels have a difficult time outside */
X		  if(iseel && !inpool) {
X			if(mtmp->mhp > 1) mtmp->mhp--;
X			mtmp->mflee = 1;
X			mtmp->mfleetim += 2;
X		  }
X		}
X		if(mtmp->mblinded && !--mtmp->mblinded)
X			mtmp->mcansee = 1;
X		if(mtmp->mfleetim && !--mtmp->mfleetim)
X			mtmp->mflee = 0;
X#ifdef HARD
X		/* unwatched mimics and piercers may hide again  [MRS] */
X		if(is_hider(mtmp->data) && restrap(mtmp))   continue;
X#endif
X		if(mtmp->mimic) continue;
X		if(mtmp->mspeed != MSLOW || !(moves%2)){
X			/* continue if the monster died fighting */
X			fr = -1;
X/* TODO:	Handle the case of the agressor dying? */
X			if(Conflict && cansee(mtmp->mx,mtmp->my)
X				&& !mtmp->iswiz
X				&& (fr = fightm(mtmp)) == 2)
X				continue;
X  			if(fr<0 && dochugw(mtmp))
X				continue;
X		}
X		if(mtmp->mspeed == MFAST && dochugw(mtmp))
X			continue;
X	}
X#ifdef NAMED_ITEMS
X	if (warnlevel == 100) {
X		Your("%s %s!", aobjnam(uwep, "glow"),
X			Hallucination ? hcolor() : light_blue);
X		warnlevel = 0;
X	}
X#endif
X	warnlevel -= u.ulevel;
X	if(warnlevel >= SIZE(warnings))
X		warnlevel = SIZE(warnings)-1;
X	if(!Blind && warnlevel >= 0)
X	if(warnlevel > lastwarnlev || moves > lastwarntime + 5){
X	    register char *rr;
X	
X	    switch((int) (Warning & (LEFT_RING | RIGHT_RING))){
X	    case LEFT_RING:
X		rr = "Your left ring glows";
X		break;
X	    case RIGHT_RING:
X		rr = "Your right ring glows";
X		break;
X	    case LEFT_RING | RIGHT_RING:
X		rr = "Both your rings glow";
X		break;
X	    default:
X		{ char buf[33];
X		Sprintf(buf, "Your %s glow", makeplural(body_part(FINGERTIP)));
X		rr = buf;
X		}
X		break;
X	    }
X	    pline("%s %s!", rr, Hallucination ? hcolor() : warnings[warnlevel]);
X	    lastwarntime = moves;
X	    lastwarnlev = warnlevel;
X	}
X
X	dmonsfree();	/* remove all dead monsters */
X}
X
Xvoid
Xmeatgold(mtmp)
X	register struct monst *mtmp;
X{
X	register struct gold *gold;
X	register struct obj *otmp;
X
X	/* Eats gold if it is there */
X	while(gold = g_at(mtmp->mx, mtmp->my)){
X		if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
X			pline("%s eats some gold!", Monnam(mtmp));
X		mtmp->meating = (int)((gold->amount + 500L)/1000L);
X		freegold(gold);
X		/* Left behind a pile? */
X		if(rnd(25) < 3) (void) mksobj_at(ROCK, mtmp->mx, mtmp->my);
X		newsym(mtmp->mx, mtmp->my);
X	}
X	/* Eats topmost metal object if it is there */
X	for (otmp = fobj; otmp; otmp = otmp->nobj)
X	    if (otmp->ox == mtmp->mx && otmp->oy == mtmp->my &&
X		objects[otmp->otyp].oc_material == METAL) {
X		    if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
X			pline("%s eats %s!", Monnam(mtmp),
X				distant_name(otmp,doname));
X		    else if (flags.soundok && flags.verbose)
X			You("hear a crunching sound.");
X		    mtmp->meating = otmp->owt/2 - 1;
X		    /* Heal up to the object's weight in hp */
X		    if (mtmp->mhp < mtmp->mhpmax) {
X			mtmp->mhp += objects[otmp->otyp].oc_weight;
X			if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
X		    }
X		    freeobj(otmp);
X		    /* Left behind a pile? */
X		    if(rnd(25) < 3) (void) mksobj_at(ROCK, mtmp->mx, mtmp->my);
X		    newsym(mtmp->mx, mtmp->my);
X		    break;
X	    }
X	set_omask(mtmp->mx, mtmp->my);
X}
X
Xvoid
Xmeatobj(mtmp)		/* for gelatinous cubes */
X	register struct monst *mtmp;
X{
X	register struct obj *otmp, *otmp2;
X
X	/* Eats organic, glass, or wood objects if there */
X	/* Engulfs anything else, metal and rock */
X	for (otmp = fobj; otmp; otmp = otmp2) {
X	    otmp2 = otmp->nobj;
X	    if (otmp->ox == mtmp->mx && otmp->oy == mtmp->my) {
X		if(!objects[otmp->otyp].oc_material <= WOOD) {
X		    if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
X			pline("%s eats %s!", Monnam(mtmp),
X				distant_name(otmp, doname));
X		    else if (flags.soundok && flags.verbose)
X			You("hear a slurping sound.");
X                    /* Heal up to the object's weight in hp */
X		    if (mtmp->mhp < mtmp->mhpmax) {
X			mtmp->mhp += objects[otmp->otyp].oc_weight;
X			if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
X		    }
X		    delobj(otmp);		/* munch */
X		} else if (otmp->olet != ROCK_SYM && otmp->olet != BALL_SYM) {
X		    if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
X			pline("%s engulfs %s.", Monnam(mtmp),
X				distant_name(otmp,doname));
X		    freeobj(otmp);
X		    mpickobj(mtmp, otmp);	/* slurp */
X		}
X	    }
X	    /* Engulf & devour is instant, so don't set meating */
X	    newsym(mtmp->mx, mtmp->my);
X	}
X	set_omask(mtmp->mx, mtmp->my);
X}
X
Xvoid
Xmpickgold(mtmp)
X	register struct monst *mtmp;
X{
X	register struct gold *gold;
X
X	while(gold = g_at(mtmp->mx, mtmp->my)){
X		mtmp->mgold += gold->amount;
X		if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
X			pline("%s picks up some gold.", Monnam(mtmp));
X		freegold(gold);
X		if(levl[mtmp->mx][mtmp->my].scrsym == GOLD_SYM)
X			newsym(mtmp->mx, mtmp->my);
X	}
X	set_omask(mtmp->mx, mtmp->my);
X}
X
X/* Now includes giants which pick up enormous rocks.  KAA */
Xvoid
Xmpickgems(mtmp)
X	register struct monst *mtmp;
X{
X	register struct obj *otmp;
X
X	for(otmp = fobj; otmp; otmp = otmp->nobj)
X	  if(throws_rocks(mtmp->data) ? otmp->otyp == BOULDER :
X			(otmp->olet == GEM_SYM && otmp->otyp < LAST_GEM+5))
X	    if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my)
X	      if(mtmp->data->mlet != S_UNICORN
X		 || objects[otmp->otyp].g_val != 0){
X		if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
X			pline("%s picks up %s.", Monnam(mtmp),
X				distant_name(otmp, doname));
X		freeobj(otmp);
X		mpickobj(mtmp, otmp);
X		newsym(mtmp->mx, mtmp->my);
X		return;	/* pick only one object */
X	      }
X	set_omask(mtmp->mx, mtmp->my);
X}
X
Xint
Xcurr_mon_load(mtmp)
Xregister struct monst *mtmp;
X{
X	register int curload = 0;
X	register struct obj *obj;
X
X	for(obj = mtmp->minvent; obj; obj = obj->nobj) {
X		if(obj->otyp != BOULDER || !throws_rocks(mtmp->data))
X			curload += weight(obj);
X	}
X
X	return curload;
X}
X
Xint
Xmax_mon_load(mtmp)
Xregister struct monst *mtmp;
X{
X	register int maxload;
X
X	/* Base monster carrying capacity is equal to human maximum
X	 * carrying capacity, or half human maximum if not strong.
X	 * (for a polymorphed player, the value used would be the
X	 * non-polymorphed carrying capacity instead of max/half max).
X	 * This is then modified by the ratio between the monster weights
X	 * and human weights (weight of a human=45).  Limits for corpseless
X	 * monsters are arbitrary.
X	 */
X	maxload = (mtmp->data->cwt ? mtmp->data->cwt : mtmp->data->mlevel*6)
X		* MAX_CARR_CAP / 45;
X	if (!strongmonst(mtmp->data)) maxload /= 2;
X
X	return maxload;
X}
X
X/* for restricting monsters' object-pickup */
Xboolean
Xcan_carry(mtmp,otmp)
Xstruct monst *mtmp;
Xstruct obj *otmp;
X{
X	register int newload = weight(otmp);
X
X	if (mtmp->isshk) return(TRUE); /* no limit */
X	if (mtmp->mpeaceful && !mtmp->mtame) return(FALSE);
X	/* otherwise players might find themselves obligated to violate
X	 * their alignment if the monster takes something they need
X	 */
X	
X	/* special--boulder throwers carry unlimited amounts of boulders */
X	if (throws_rocks(mtmp->data) && otmp->otyp == BOULDER)
X		return(TRUE);
X	
X	/* nymphs deal in stolen merchandise, but not boulders or statues */
X	if (mtmp->data->mlet == S_NYMPH)
X		return !(otmp->olet == ROCK_SYM);
X
X	if(curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) return(FALSE);
X
X	return(TRUE);
X}
X
Xvoid
Xmpickstuff(mtmp, str)
X	register struct monst *mtmp;
X	register char *str;
X{
X	register struct obj *otmp;
X
X/*	prevent shopkeepers from leaving the door of their shop */
X	if(mtmp->isshk && inhishop(mtmp)) return;
X
X	for(otmp = fobj; otmp; otmp = otmp->nobj)
X	  if(index(str, otmp->olet))
X	    if(otmp->ox == mtmp->mx && otmp->oy == mtmp->my) {
X		if(!can_carry(mtmp,otmp)) return;
X		if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
X			pline("%s picks up %s.", Monnam(mtmp), doname(otmp));
X		freeobj(otmp);
X		mpickobj(mtmp, otmp);
X		if(index(str, (char) levl[mtmp->mx][mtmp->my].scrsym))
X			newsym(mtmp->mx, mtmp->my);
X		set_omask(mtmp->mx, mtmp->my);
X		return;			/* pick only one object */
X	    }
X}
X
X/* return number of acceptable neighbour positions */
Xint
Xmfndpos(mon, poss, info, flag)
X	register struct monst *mon;
X	coord *poss;	/* coord poss[9] */
X	long *info;	/* long info[9] */
X	long flag;
X{
X	register int x,y,nx,ny,cnt = 0,ntyp;
X	int nowtyp;
X	boolean wantpool,poolok;
X
X	x = mon->mx;
X	y = mon->my;
X	nowtyp = levl[x][y].typ;
X
X	wantpool = mon->data->mlet == S_EEL;
X	poolok = is_flyer(mon->data) || (is_swimmer(mon->data) && !wantpool);
Xnexttry:	/* eels prefer the water, but if there is no water nearby,
X		   they will crawl over land */
X	if(mon->mconf) {
X		flag |= ALLOW_ALL;
X		flag &= ~NOTONL;
X	}
X	if(!mon->mcansee)
X		flag |= ALLOW_SSM;
X	for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) {
X	    if((nx == x && ny == y) || !isok(nx,ny)) continue;
X	    if(IS_ROCK(ntyp = levl[nx][ny].typ) && !(flag & ALLOW_WALL) &&
X		!((flag & ALLOW_DIG) && may_dig(nx,ny))) continue;
X	    if(IS_DOOR(ntyp) && !amorphous(mon->data) &&
X	       ((levl[nx][ny].doormask & D_LOCKED &&
X		   !is_giant(mon->data) && !mon->isshk) ||
X		(levl[nx][ny].doormask & D_CLOSED &&
X		   (verysmall(mon->data) ||
X		    (!is_giant(mon->data) && nohands(mon->data))))
X	       ) && !(flag & (ALLOW_WALL|ALLOW_DIG))) continue;
X	    if(nx != x && ny != y && (IS_DOOR(nowtyp) || IS_DOOR(ntyp)))
X		continue;
X	    if(is_pool(nx,ny) == wantpool || poolok) {
X		/* Displacement also displaces the Elbereth/scare monster,
X		 * as long as you are visible.
X		 */
X		int dispx = (Displaced && (!Invis || perceives(mon->data)) &&
X			(mon->mux==nx)) ? u.ux : nx;
X		int dispy = (Displaced && (!Invis || perceives(mon->data)) &&
X			(mon->muy==ny)) ? u.uy : ny;
X
X		info[cnt] = 0;
X		if(sobj_at(SCR_SCARE_MONSTER, dispx, dispy)
X#ifdef ELBERETH
X		   || sengr_at("Elbereth", dispx, dispy)
X#endif
X		  ) {
X			if(!(flag & ALLOW_SSM)) continue;
X			info[cnt] |= ALLOW_SSM;
X		}
X		if((nx == u.ux && ny == u.uy) ||
X		   (nx == mon->mux && ny == mon->muy)) {
X			if(!(flag & ALLOW_U)) continue;
X			info[cnt] |= ALLOW_U;
X		} else {
X			if(levl[nx][ny].mmask) {
X				if(!(flag & ALLOW_M)) continue;
X				info[cnt] |= ALLOW_M;
X				if((m_at(nx,ny))->mtame) {
X					if(!(flag & ALLOW_TM)) continue;
X					info[cnt] |= ALLOW_TM;
X				}
X			}
X#if defined(ALTARS) && defined(THEOLOGY)
X			/* Note: ALLOW_SANCT only prevents movement, not */
X			/* attack, into a temple. */
X			if(!in_temple(x, y) && in_temple(nx, ny) &&
X					u_in_sanctuary(in_temple(nx, ny))) {
X				if(!(flag & ALLOW_SANCT)) continue;
X				info[cnt] |= ALLOW_SANCT;
X			}
X#endif
X		}
X		if(sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
X			if(flag & NOGARLIC) continue;
X			info[cnt] |= NOGARLIC;
X		}
X		if(sobj_at(BOULDER, nx, ny)) {
X			if(!(flag & ALLOW_ROCK)) continue;
X			info[cnt] |= ALLOW_ROCK;
X		}
X		if((!Invis || perceives(mon->data)) && online(nx,ny)){
X			if(flag & NOTONL) continue;
X			info[cnt] |= NOTONL;
X		}
X		/* we cannot avoid traps of an unknown kind */
X		{ register struct trap *ttmp = t_at(nx, ny);
X		  register long tt;
X			if(ttmp) {
X/*				tt = 1L << ttmp->ttyp;*/
X/* why don't we just have code look like what it's supposed to do? then it
X/* might start working for every case. try this instead: -sac */
X				tt = (ttmp->ttyp < TRAPNUM && ttmp->ttyp);
X				/* below if added by GAN 02/06/87 to avoid
X				 * traps out of range
X				 */
X				if(!(tt & ALLOW_TRAPS))  {
Ximpossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp);
X					continue;
X				}
X				if(mon->mtrapseen & tt) {
X
X					if(!(flag & tt)) continue;
X					info[cnt] |= tt;
X				}
X			}
X		}
X		poss[cnt].x = nx;
X		poss[cnt].y = ny;
X		cnt++;
X	    }
X	}
X	if(!cnt && wantpool && !is_pool(x,y)) {
X		wantpool = FALSE;
X		goto nexttry;
X	}
X	return(cnt);
X}
X
Xint
Xdist(x, y)
Xregister int x,y;
X{
X	register int dx = x - u.ux, dy = y - u.uy;
X	return dx*dx + dy*dy;
X}
X
Xstatic const char *poiseff[] = {
X
X	" feel very weak", "r brain is on fire",
X	" can't think straight", "r muscles won't obey you",
X	" feel very sick", " break out in hives"
X};
X
Xvoid
Xpoisontell(typ)
X
X	int	typ;
X{
X	pline("You%s.", poiseff[typ]);
X}
X
Xvoid
Xpoisoned(string, typ, pname)
Xregister char *string, *pname;
Xregister int  typ;
X{
X	register int i, plural;
X	boolean thrown_weapon = !strncmp(string, "poison", 6);
X		/* admittedly a kludge... */
X
X	if(strcmp(string, "blast") && !thrown_weapon) {
X	    /* 'blast' has already given a 'poison gas' message */
X	    /* so have "poison arrow", "poison dart", etc... */
X	    plural = (string[strlen(string) - 1] == 's')? 1 : 0;
X	    if(Blind)
X		pline("%s poisoned.", (plural) ? "They were" : "It was");
X	    else
X		pline("The %s %s poisoned!", string, (plural) ? "were" : "was");
X	}
X
X	if(Poison_resistance) {
X		if(!strcmp(string, "blast")) shieldeff(u.ux, u.uy);
X		pline("The poison doesn't seem to affect you.");
X		return;
X	}
X	i = rn2(10 + 20*thrown_weapon);
X	if(i == 0 && typ != A_CHA) {
X		u.uhp = -1;
X		pline("The poison was deadly...");
X	} else if(i <= 5) {
X		pline("You%s!", poiseff[typ]);
X		adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), TRUE);
X	} else {
X		losehp(thrown_weapon ? rnd(6) : rn1(10,6), pname);
X	}
X	if(u.uhp < 1) {
X		killer = pname;
X		done("died");
X	}
X}
X
Xstatic void
Xm_detach(mtmp)
Xregister struct monst *mtmp;
X{
X#ifdef WALKIES
X	if(mtmp->mleashed) m_unleash(mtmp);
X#endif
X	relobj(mtmp,1);
X	unpmon(mtmp);
X	relmon(mtmp);
X	unstuck(mtmp);
X}
X
Xvoid
Xmondead(mtmp)
Xregister struct monst *mtmp;
X{
X	m_detach(mtmp);	
X#ifdef KOPS
X	if(mtmp->data->mlet == S_KOP && allow_kops) {
X	    /* Dead Kops may come back. */
X	    switch(rnd(5)) {
X		case 1:	     /* returns near the stairs */
X			(void) mkmon_at(mtmp->data->mname,xdnstair,ydnstair);
X			break;
X		case 2:	     /* randomly */
X			(void) mkmon_at(mtmp->data->mname,0,0);
X			break;
X		default:
X			break;
X	    }
X	}
X#endif
X	if(mtmp->isshk) shkdead(mtmp);
X	if(mtmp->isgd) gddead();
X#ifdef WORM
X	if(mtmp->wormno) wormdead(mtmp);
X#endif
X#ifdef HARD
X	if(mtmp->iswiz) wizdead(mtmp);
X#endif
X#ifdef MEDUSA
X	if(mtmp->data == &mons[PM_MEDUSA]) u.ukilled_medusa = TRUE;
X#endif
X	monfree(mtmp);
X}
X
X/* called when monster is moved to larger structure */
Xvoid
Xreplmon(mtmp, mtmp2)
Xregister struct monst *mtmp, *mtmp2;
X{
X	relmon(mtmp);
X	monfree(mtmp);
X	levl[mtmp2->mx][mtmp2->my].mmask = 1;
X	mtmp2->nmon = fmon;
X	fmon = mtmp2;
X	if(u.ustuck == mtmp) u.ustuck = mtmp2;
X	if(mtmp2->isshk) replshk(mtmp,mtmp2);
X	if(mtmp2->isgd) replgd(mtmp,mtmp2);
X}
X
Xvoid
Xrelmon(mon)
Xregister struct monst *mon;
X{
X	register struct monst *mtmp;
X
X	if (fmon == 0)  panic ("relmon: no fmon available.");
X
X	levl[mon->mx][mon->my].mmask = 0;
X
X	if(mon == fmon) fmon = fmon->nmon;
X	else {
X		for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ;
X		if(mtmp)    mtmp->nmon = mon->nmon;
X		else	    panic("relmon: mon not in list.");
X	}
X}
X
X/* we do not free monsters immediately, in order to have their name
X   available shortly after their demise */
Xvoid
Xmonfree(mtmp) register struct monst *mtmp; {
X	mtmp->nmon = fdmon;
X	fdmon = mtmp;
X	levl[mtmp->mx][mtmp->my].mmask = 0;
X}
X
Xvoid
Xunstuck(mtmp)
Xregister struct monst *mtmp;
X{
X	if(u.ustuck == mtmp) {
X		if(u.uswallow){
X			u.ux = mtmp->mx;
X			u.uy = mtmp->my;
X			u.uswallow = 0;
X			setsee();
X			docrt();
X		}
X		u.ustuck = 0;
X	}
X}
X
Xvoid
Xkilled(mtmp)
Xregister struct monst *mtmp;
X{
X	xkilled(mtmp, 1);
X}
X
Xvoid
Xxkilled(mtmp, dest)
X	register struct monst *mtmp;
X/*
X * Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse
X * either; dest=3, message but no corpse
X */
X	int	dest;
X{
X	register int tmp, nk, x, y;
X	register struct permonst *mdat = mtmp->data;
X	register struct obj *otmp;
X	boolean chance;
X
X	if (dest & 1) {
X	    if(!cansee(mtmp->mx,mtmp->my)) You("destroy it!");
X	    else {
X		You("destroy %s!",
X			mtmp->mtame ? a_monnam(mtmp, "poor") : mon_nam(mtmp));
X	    }
X	}
X
X	/* restore chameleon, lycanthropes to true form at death */
X	/* cannot do this in make_corpse() since genociding monsters after
X	 * MAXMONNO were killed does the wrong type
X	 */
X	if(mtmp->cham) mtmp->data = mdat = &mons[PM_CHAMELEON];
X	if(mdat == &mons[PM_JACKALWERE])
X		mtmp->data = mdat = &mons[PM_WEREJACKAL];
X	if(mdat == &mons[PM_WOLFWERE])
X		mtmp->data = mdat = &mons[PM_WEREWOLF];
X	if(mdat == &mons[PM_RATWERE])
X		mtmp->data = mdat = &mons[PM_WERERAT];
X
X	if(u.umconf) {
X	    if(!Blind) {
X		Your("%s stop glowing %s.",
X		makeplural(body_part(HAND)),
X		Hallucination ? hcolor() : red);
X	    }
X	    u.umconf = 0;
X	}
X
X	/* if we have killed MAXMONNO monsters of a given type, and it
X	 * can be done, genocide that monster.
X	 */
X	tmp = monsndx(mdat);
X	u.nr_killed[tmp]++;
X	nk = u.nr_killed[tmp];
X#ifdef TOLKIEN
X	if(nk > (tmp==PM_NAZGUL ? 9 : MAXMONNO) &&
X				!(mons[tmp].geno & (G_NOGEN | G_GENOD))) {
X#else
X	if(nk > MAXMONNO && !(mons[tmp].geno & (G_NOGEN | G_GENOD))) {
X#endif
X#ifdef DEBUG
X		pline("Automatically genocided %s.", makeplural(mons[tmp].mname));
X#endif
X		mons[tmp].geno |= G_GENOD;
X	}
X#ifdef MAIL
X	/* If you kill the mail daemon, no more mail delivery.  -3. */
X	else if(tmp==PM_MAIL_DAEMON) mons[tmp].geno |= G_GENOD;
X#endif	
X
X	/* punish bad behaviour */
X	if(is_human(mdat) && !always_hostile(mdat) &&
X	   (monsndx(mdat) < PM_ARCHEOLOGIST || monsndx(mdat) > PM_WIZARD) &&
X	   u.ualigntyp != U_CHAOTIC) {
X		HTelepat &= ~INTRINSIC;
X		change_luck(-2);
X	}
X	if((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame)	change_luck(-1);
X	if ((mdat==&mons[PM_BLACK_UNICORN] && u.ualigntyp == U_CHAOTIC) ||
X	    (mdat==&mons[PM_GREY_UNICORN] && u.ualigntyp == U_NEUTRAL) ||
X	    (mdat==&mons[PM_WHITE_UNICORN] && u.ualigntyp == U_LAWFUL))
X		change_luck(-5);
X
X	/* give experience points */
X	tmp = experience(mtmp, nk);
X	more_experienced(tmp, 0);
X	newexplevel();		/* will decide if you go up */
X
X	/* adjust alignment points */
X	if(mtmp->mtame)
X		adjalign(-15);	/* bad!! */
X#if defined(ALTARS) && defined(THEOLOGY)
X	else if (mtmp->ispriest && !p_coaligned(mtmp))
X		adjalign(2);
X#endif
X	else if (mtmp->mpeaceful)
X		adjalign(-5);
X	/* malign was already adjusted for ualigntyp and randomization */
X	adjalign(mtmp->malign);
X
X	/* dispose of monster and make cadaver */
X	if(stoned) {
X		monstone(mtmp);
X		return;
X	}
X
X	x = mtmp->mx;   y = mtmp->my;
X
X	mondead(mtmp);
X
X	if((dest & 2)
X#ifdef REINCARNATION
X		 || dlevel == rogue_level
X#endif
X					) return;
X
X#ifdef WORM
X	if(mdat == &mons[PM_LONG_WORM]) {
X		(void) mksobj_at(WORM_TOOTH, x, y);
X		stackobj(fobj);
X		newsym(x,y);
X	}
X#endif
X#ifdef MAIL
X	if(mdat == &mons[PM_MAIL_DAEMON]) {
X		(void) mksobj_at(SCR_MAIL, x, y);
X		stackobj(fobj);
X		newsym(x,y);
X	}
X#endif
X	if(!ACCESSIBLE(levl[x][y].typ) ||
X	   (IS_DOOR(levl[x][y].typ) &&
X	    levl[x][y].doormask & (D_CLOSED | D_LOCKED))) {
X	    /* might be mimic in wall or dead eel*/
X 	    newsym(x,y);
X	} else if(x != u.ux || y != u.uy) {
X		/* might be here after swallowed */
X		if (!rn2(6) && !(mdat->geno & G_NOCORPSE)
X#ifdef KOPS
X					&& mdat->mlet != S_KOP
X#endif
X							) {
X			int typ;
X
X			otmp = mkobj_at(RANDOM_SYM, x, y);
X			/* Don't create large objects from small monsters */
X			typ = otmp->otyp;
X			if (!bigmonst(mdat) && typ != FOOD_RATION
X#ifdef WALKIES
X			    && typ != LEASH
X#endif
X			    && typ != FIGURINE
X			    && (otmp->owt > 3 ||
X				(typ >= SPEAR && typ <= LANCE) ||
X				(typ >= SCIMITAR && typ <= KATANA) ||
X				(typ == MORNING_STAR || typ == QUARTERSTAFF) ||
X				(typ >= BARDICHE && typ <= VOULGE) ||
X				(typ>=PLATE_MAIL && typ<=DRAGON_SCALE_MAIL) ||
X				(typ == LARGE_SHIELD))) {
X			    delobj(otmp);
X			} else newsym(x,y);
X		}
X		/* Whether or not it always makes a corpse is, in theory,
X		 * different from whether or not the corpse is "special";
X		 * if we want both, we have to specify it explicitly.
X		 */
X		if (bigmonst(mdat)
X#ifdef GOLEMS
X				   || is_golem(mdat)
X#endif
X		   ) chance = 1;
X		else chance = !rn2((int)
X			(2 + ((mdat->geno & G_FREQ)<2) + verysmall(mdat)));
X		if (chance)
X			(void) make_corpse(mtmp);
X	}
X}
X
X/*VARARGS2*/
Xvoid
Xkludge(str, arg, arg2, arg3)
X	register char *str,*arg,*arg2,*arg3;
X{
X	if(Blind || !flags.verbose) {
X		if(*str == '%') pline(str,"It",arg2,arg3);
X		else pline(str,"it",arg2,arg3);
X	} else pline(str,arg,arg2,arg3);
X}
X
Xvoid
Xrescham() {	/* force all chameleons to become normal */
X
X	register struct monst *mtmp;
X
X	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X		if(mtmp->cham) {
X			mtmp->cham = 0;
X			(void) newcham(mtmp, &mons[PM_CHAMELEON]);
X		}
X		if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
X			(void) new_were(mtmp);
X	}
X}
X
X/* Let the chameleons change again -dgk */
Xvoid
Xrestartcham() {
X
X	register struct monst *mtmp;
X
X	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X		if (mtmp->data->mlet == S_CHAMELEON)
X			mtmp->cham = 1;
X}
X
Xint
Xnewcham(mtmp, mdat)	/* make a chameleon look like a new monster */
X			/* returns 1 if the monster actually changed */
X	register struct monst *mtmp;
X	register struct permonst *mdat;
X{
X	register int mhp, hpn, hpd;
X	int tryct;
X
X	/* mdat = 0 -> caller wants a random monster shape */
X	tryct = 0;
X	if(mdat == 0) {
X		while (++tryct < 100) {
X			static int num;
X			mdat = &mons[num=rn2(NUMMONS)];
X			if ((!is_human(mdat) || num == PM_NURSE)
X				&& !type_is_pname(mdat)
X				&& !is_were(mdat)
X#ifdef MEDUSA
X				&& num != PM_MEDUSA
X#endif
X#ifdef MAIL
X				&& num != PM_MAIL_DAEMON
X#endif
X				)
X				break;
X		}
X		if (tryct >= 100) return(0); /* Should never happen */
X	}
X  	if(mdat == mtmp->data) return(0);	/* still the same monster */
X
X#ifdef WORM
X	if(mtmp->wormno) wormdead(mtmp);	/* throw tail away */
X#endif
X	mtmp->m_lev = adj_lev(mdat);		/* new monster level */
X
X	hpn = mtmp->mhp;
X 	hpd = (mtmp->m_lev < 50) ? (mtmp->m_lev)*8 : mdat->mlevel;
X 	if(!hpd) hpd = 4;
X 	mhp = (mtmp->m_lev < 50) ? (mtmp->m_lev)*8 : mdat->mlevel;
X 	if(!mhp) mhp = 4;
X
X	/* new hp: same fraction of max as before */
X#ifndef LINT
X 	mtmp->mhp = (int)(((long)hpn*(long)mhp)/(long)hpd);
X#endif
X 	if(mtmp->mhp < 0) mtmp->mhp = hpn;	/* overflow */
X/* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
X   0HD creature will require this statement */
X 	if (!mtmp->mhp) mtmp->mhp = 1;
X
X/* and the same for maximum hit points */
X	hpn = mtmp->mhpmax;
X#ifndef LINT
X 	mtmp->mhpmax = (int)(((long)hpn*(long)mhp)/(long)hpd);
X#endif
X 	if(mtmp->mhpmax < 0) mtmp->mhpmax = hpn;	/* overflow */
X 	if (!mtmp->mhpmax) mtmp->mhpmax = 1;
X
X 	mtmp->data = mdat;
X	mtmp->minvis = !!(mdat->mlet == S_STALKER);
X	mtmp->mhide = !!hides_under(mdat);
X	if (!mtmp->mhide) mtmp->mundetected = 0;
X	if (u.ustuck == mtmp
X#ifdef POLYSELF
X			&& !sticks(uasmon)
X#endif
X			&& !sticks(mdat))
X		u.ustuck = 0;
X#ifdef WORM
X	if(mdat == &mons[PM_LONG_WORM] && getwn(mtmp)) initworm(mtmp);
X			/* perhaps we should clear mtmp->mtame here? */
X#endif
X	unpmon(mtmp);	/* necessary for 'I' and to force pmon */
X	pmon(mtmp);
X	return(1);
X}
X
Xvoid
Xmnexto(mtmp)	/* Make monster mtmp next to you (if possible) */
X	struct monst *mtmp;
X{
X	coord mm;
X	enexto(&mm, u.ux, u.uy);
X	levl[mtmp->mx][mtmp->my].mmask = 0;
X	levl[mm.x][mm.y].mmask = 1;
X	mtmp->mx = mm.x;
X	mtmp->my = mm.y;
X	pmon(mtmp);
X	set_apparxy(mtmp);
X}
X
Xvoid
Xmnearto(mtmp,x,y,gz)	/* Make monster near (or at) location if possible */
X	register struct monst *mtmp;
X	xchar x, y;
X	boolean gz;     
X{
X	coord mm;
X	if(!gz || !goodpos(x,y)) {
X		enexto(&mm, x, y);
X		x = mm.x; y = mm.y;
X	}
X	if(x == mtmp->mx && y == mtmp->my) /* that was easy */
X		return;
X	levl[mtmp->mx][mtmp->my].mmask = 0;
X	levl[x][y].mmask = 1;
X	mtmp->mx = x;
X	mtmp->my = y;
X	pmon(mtmp);
X	set_apparxy(mtmp);
X}
X
Xvoid
Xsetmangry(mtmp)
X	register struct monst *mtmp;
X{
X	if(!mtmp->mpeaceful) return;
X	if(mtmp->mtame) return;
X	mtmp->mpeaceful = 0;
X#if defined(ALTARS) && defined(THEOLOGY)
X	if(mtmp->ispriest) {
X		if(p_coaligned(mtmp)) adjalign(-5); /* very bad */
X		else adjalign(2);
X	} else
X#endif
X	adjalign(-1);		/* attacking peaceful monsters is bad */
X	if(humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
X		pline("%s gets angry!", Monnam(mtmp));
X#ifdef SOUNDS
X	else if (flags.verbose && flags.soundok) growl(mtmp);
X#endif
X}
X
Xint
Xdisturb(mtmp)		/* awaken monsters while in the same room.
X			 * return a 1 if they have been woken.
X			 */
X	register struct monst *mtmp;
X{
X	/* wake up, or get out of here. */
X	/* ettins are hard to surprise */
X	/* Nymphs and Leprechauns do not easily wake up */
X	if(cansee(mtmp->mx,mtmp->my) &&
X		(!Stealth || (mtmp->data == &mons[PM_ETTIN] && rn2(10))) &&
X		(!(mtmp->data->mlet == S_NYMPH
X		   || mtmp->data->mlet == S_LEPRECHAUN) || !rn2(50)) &&
X		(Aggravate_monster ||
X		 (mtmp->data->mlet == S_DOG || mtmp->data->mlet == S_HUMAN) ||
X		(!rn2(7) && !mtmp->mimic))) {
X		mtmp->msleep = 0;
X		return(1);
X	}
X	if(Hallucination) pmon(mtmp);
X	return(0);
X}
X
X#ifdef HARD
Xstatic boolean
Xrestrap(mtmp)
X/* unwatched hiders may hide again,
X * if so, a 1 is returned.
X */
Xregister struct monst *mtmp;
X{
X	if(mtmp->cham || mtmp->mcan || mtmp->mimic ||
X	   cansee(mtmp->mx, mtmp->my) || rn2(3))
X		return(FALSE);
X
X	if(mtmp->data->mlet == S_MIMIC) {
X		set_mimic_sym(mtmp);
X		return(TRUE);
X	} else
X	    if(levl[mtmp->mx][mtmp->my].typ == ROOM)  {
X		(void) maketrap(mtmp->mx, mtmp->my, MONST_TRAP);
X		/* override type selection */
X		ftrap->pm = monsndx(mtmp->data);
X		mondead(mtmp);
X		return(TRUE);
X	    }
X
X	return(FALSE);
X}
X#endif
X
X/* drop (perhaps) a cadaver and remove monster */
Xvoid
Xmondied(mdef)
Xregister struct monst *mdef;
X{
X	mondead(mdef);
X	if(rn2(3)
X#ifdef REINCARNATION
X	   && dlevel != rogue_level
X#endif
X					)
X		(void) make_corpse(mdef);
X}
X
X/* monster disappears, not dies */
Xvoid
Xmongone(mdef)
Xregister struct monst *mdef;
X{
X	register struct obj *otmp, *otmp2;
X
X	/* release monster's inventory */
X	for (otmp = mdef->minvent; otmp; otmp = otmp2) {
X		otmp2 = otmp->nobj;
X		obfree(otmp, (struct obj *)0);
X	}
X	mdef->minvent = 0;
X	mdef->mgold = 0;
X	m_detach(mdef);
X	monfree(mdef);
X}
X
X/* drop a statue or rock and remove monster */
Xvoid
Xmonstone(mdef)
Xregister struct monst *mdef;
X{
X	struct obj *otmp;
X
X	if(!verysmall(mdef->data) ||
X	   !rn2(2 + ((mdef->data->geno & G_FREQ) > 2))) {
X		otmp = mk_named_object(STATUE, mdef->data, mdef->mx, mdef->my,
X			NAME(mdef), (int)mdef->mnamelth);
X		otmp->spe = 0; /* no book inside */
X	} else
X		(void) mksobj_at(ROCK, mdef->mx, mdef->my);
X
X	stackobj(fobj);
X
X	if(cansee(mdef->mx, mdef->my)){
X		unpmon(mdef);
X		atl(mdef->mx,mdef->my,Hallucination ? rndobjsym() : fobj->olet);
X	}
X	mondead(mdef);
X}
X
X#ifdef GOLEMS
Xvoid
Xgolemeffects(mon, damtype, dam)
Xregister struct monst *mon;
Xint damtype, dam;
X{
X	int heal=0, slow=0;
X
X	if (mon->data != &mons[PM_FLESH_GOLEM]
X					&& mon->data != &mons[PM_IRON_GOLEM])
X		return;
X
X	if (mon->data == &mons[PM_FLESH_GOLEM]) {
X		if (damtype == AD_ELEC) heal = dam / 6;
X		else if (damtype == AD_FIRE || damtype == AD_COLD) slow = 1;
X	} else {
X		if (damtype == AD_ELEC) slow = 1;
X		else if (damtype == AD_FIRE) heal = dam;
X	}
X	if (slow) {
X		if (mon->mspeed != MSLOW) {
X			if (mon->mspeed == MFAST) mon->mspeed = 0;
X			else mon->mspeed = MSLOW;
X			if (cansee(mon->mx, mon->my))
X				pline("%s seems to be moving slower.",
X					Monnam(mon));
X		}
X	}
X	if (heal) {
X		if (mon->mhp < mon->mhpmax) {
X			mon->mhp += dam;
X			if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
X			if (cansee(mon->mx, mon->my))
X				pline("%s seems healthier.", Monnam(mon));
X		}
X	}
X}
X#endif /* GOLEMS */
END_OF_FILE
if test 31897 -ne `wc -c <'src/mon.c'`; then
    echo shar: \"'src/mon.c'\" unpacked with wrong size!
fi
# end of 'src/mon.c'
fi
if test -f 'src/polyself.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/polyself.c'\"
else
echo shar: Extracting \"'src/polyself.c'\" \(18377 characters\)
sed "s/^X//" >'src/polyself.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)polyself.c	3.0	88/10/22
X/* Polymorph self routine.  Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X
X#ifdef POLYSELF
X
Xstatic void break_armor(), drop_weapon();
Xstatic void skinback();
Xstatic void uunstick();
X
Xvoid
Xpolyself()
X{
X	char buf[BUFSZ];
X	int tmp, tmp2, mntmp = -1;
X	int tries=0;
X	boolean draconian = (uarm && uarm->otyp==DRAGON_SCALE_MAIL &&
X		uarm->corpsenm >= PM_GREY_DRAGON &&
X		uarm->corpsenm <= PM_YELLOW_DRAGON);
X	/* We have to calculate sticky in multiple places since we might go
X	 * through any one of them without going through the others.
X	 */
X	boolean sticky = sticks(uasmon) && u.ustuck && !u.uswallow;
X
X	if(!Polymorph_control && !draconian) {
X	    if (rn2(20) > ACURR(A_CON)) {
X		You("shudder for a moment.");
X		losehp(rn2(30),"system shock");
X		return;
X	    }
X	}
X
X	if (Polymorph_control) {
X		do {
X			pline("Become what kind of monster? [type the name] ");
X			getlin(buf);
X			mntmp = name_to_mon(buf);
X			if (mntmp < 0)
X				pline("I've never heard of such monsters.");
X			else if (!polyok(&mons[mntmp]))
X				You("cannot polymorph into that.");
X			else break;
X		} while(++tries < 5);
X		if (tries==5) pline(thats_enough_tries);
X	} else if (draconian)
X		mntmp = uarm->corpsenm;
X
X	if (mntmp < 0) {
X		tries = 0;
X		do {
X			mntmp = rn2(PM_CHAMELEON);
X			/* All valid monsters are from 0 to PM_CHAMELEON-1 */
X		} while(!polyok(&mons[mntmp]) && tries++ < 200);
X	}
X
X	if (draconian && mntmp==uarm->corpsenm) {
X		if (!(mons[uarm->corpsenm].geno & G_GENOD)) {
X			You("merge with your scaly armor.");
X			uskin = uarm;
X			uarm = (struct obj *)0;
X		}
X	}
X	/* The below polyok() should never fail unless just about everything
X	 * was genocided...
X	 */
X	if (!polyok(&mons[mntmp]) || !rn2(5)) {
X		if (!rn2(10)) {
X			flags.female = !flags.female;
X			max_rank_sz();
X			if (pl_character[0]=='P')
X				Strcpy(pl_character+6, flags.female?"ess":"");
X			if (pl_character[0]=='C')
X				Strcpy(pl_character+5,
X				flags.female ? "woman" : "man");
X		}
X		if (u.umonnum != -1) {
X			u.acurr = u.macurr;	/* restore old attribs */
X			u.amax = u.mamax;
X		}
X	    tmp = u.uhpmax;
X	    tmp2 = u.ulevel;
X	    u.usym = S_HUMAN;
X	    u.umonnum = -1;
X	    if (u.uundetected) u.uundetected = 0;
X	    prme();
X	    u.mtimedone = u.mh = u.mhmax = 0;
X	    u.ulevel = u.ulevel-2+rn2(5);
X	    if (u.ulevel > 127 || u.ulevel == 0) u.ulevel = 1;
X	    if (u.ulevel > MAXULEV) u.ulevel = MAXULEV;
X
X	    for(tmp = u.ulevel; tmp != tmp2; tmp += (tmp2 < u.ulevel) ? -1 : 1)
X		adjabil((tmp2 > u.ulevel) ? -1 : 1);
X	    tmp = u.uhpmax;
X
X	    /* random experience points for the new experience level */
X	    u.uexp = rndexp();
X#ifndef LINT
X	    u.uhpmax = (u.uhpmax-10)*(long)u.ulevel/tmp2 + 19 - rn2(19);
X#endif
X/* If it was u.uhpmax*u.ulevel/tmp+9-rn2(19), then a 1st level character
X   with 16 hp who polymorphed into a 3rd level one would have an average
X   of 48 hp.  */
X#ifndef LINT
X	    u.uhp = u.uhp * (long)u.uhpmax/tmp;
X#endif
X#ifdef SPELLS
X	    tmp = u.uenmax;
X#ifndef LINT
X	    u.uenmax = u.uenmax * (long)u.ulevel/tmp2 + 9 - rn2(19);
X#endif
X	    if (u.uenmax < 0) u.uenmax = 0;
X#ifndef LINT
X	    u.uen = (tmp ? u.uen * (long)u.uenmax / tmp : u.uenmax);
X#endif
X#endif
X	    (void)redist_attr();
X	    u.uhunger = rn1(500,500);
X	    Sick = 0;
X	    Stoned = 0;
X	    if (u.uhp <= 0 || u.uhpmax <= 0) {
X
X		if(Polymorph_control) {
X		    if (u.uhp <= 0) u.uhp = 1;
X		    if (u.uhpmax <= 0) u.uhpmax = 1;
X		} else {
X		    Your("new form doesn't seem healthy enough to survive.");
X		    killer="unsuccessful polymorph";
X		    done("died");
X		}
X	    }
X	    set_uasmon();
X	    You("feel like a new %sman!", flags.female ? "wo" : "");
X#ifdef WIZARD
X	    if(!wizard) {
X#endif
Xnewname:	more();
X		do {
X		    pline("What is your new name? ");
X		    getlin(buf);
X		} while (buf[0]=='\033' || buf[0]==0);
X		if (!strcmp(plname,buf)) {
X		    pline("That is the same as your old name!");
X		    goto newname;
X		}
X		(void)strncpy(plname, buf, sizeof(plname)-1);
X		Sprintf(SAVEF, "save/%d%s", getuid(), plname);
X		regularize(SAVEF+5);		/* avoid . or / in name */
X#ifdef WIZARD
X	    }
X#endif
X	    flags.botl = 1;
X	    skinback();
X	    find_ac();
X	    if (sticky) uunstick();
X	} else if(!polymon(mntmp)) return;
X
X	if (!uarmg) selftouch("No longer petrify-resistant, you");
X	if (Inhell && !Fire_resistance) {
X	    You("burn to a crisp.");
X	    killer = "unwise polymorph";
X	    done("burned");
X	}
X}
X
Xint
Xpolymon(mntmp)	/* returns 1 if polymorph successful */
X	int	mntmp;
X{
X	int	tmp;
X	boolean sticky = sticks(uasmon) && u.ustuck && !u.uswallow;
X
X	if (mons[mntmp].geno & G_GENOD) {
X		You("feel rather %s-ish.",mons[mntmp].mname);
X		return(0);
X	}
X
X	if (u.umonnum == -1) {
X		/* Human to monster; save human stats */
X		u.macurr = u.acurr;
X		u.mamax = u.amax;
X	} else {
X		/* Monster to monster; restore human stats, to be
X		 * immediately changed to provide stats for the new monster
X		 */
X		u.acurr = u.macurr;
X		u.amax = u.mamax;
X	}
X	u.umonnum = mntmp;
X	set_uasmon();
X	u.usym = mons[mntmp].mlet;
X	/* New stats for monster, to last only as long as polymorphed.
X	 * Currently only strength gets changed.
X	 */
X	if(strongmonst(&mons[mntmp])) ABASE(A_STR) = AMAX(A_STR) = 118;
X
X	if (resists_ston(uasmon) && Stoned) { /* parnes@eniac.seas.upenn.edu */
X		Stoned = 0;
X		You("no longer seem to be petrifying.");
X	}
X	if (u.usym == S_FUNGUS && Sick) {
X		Sick = 0;
X		You("no longer feel sick.");
X	}
X	if (u.usym == S_DRAGON && mntmp >= PM_GREY_DRAGON) u.mhmax = 80;
X#ifdef GOLEMS
X	else if (is_golem(uasmon)) u.mhmax = golemhp(mntmp);
X#endif /* GOLEMS */
X	else {
X
X		/*
X		tmp = adj_lev(&mons[mntmp]);
X		 * We can't do this, since there's no such thing as an
X		 * "experience level of you as a monster" for a polymorphed
X		 * character.
X		 */
X		tmp = mons[mntmp].mlevel;
X		if (!tmp) u.mhmax = rnd(4);
X		else u.mhmax = d(tmp, 8);
X	}
X	u.mh = u.mhmax;
X	You("turn into a%s %s!",
X		index(vowels, *(mons[mntmp].mname)) ? "n" : "",
X		mons[mntmp].mname);
X	if (uskin && mntmp != uskin->corpsenm)
X		skinback();
X	break_armor();
X	drop_weapon(1);
X	if (u.uundetected && !hides_under(uasmon)) u.uundetected = 0;
X	else if (hides_under(uasmon) && (levl[u.ux][u.uy].omask ||
X			levl[u.ux][u.uy].gmask))
X		u.uundetected = 1;
X	prme();
X	if (!sticky && !u.uswallow && u.ustuck && sticks(uasmon)) u.ustuck = 0;
X	else if (sticky && !sticks(uasmon)) uunstick();
X	u.mtimedone = 500 + rn2(500);
X	if (u.ulevel < mons[mntmp].mlevel)
X	/* Low level characters can't become high level monsters for long */
X		u.mtimedone = u.mtimedone * u.ulevel / mons[mntmp].mlevel;
X	flags.botl = 1;
X	if (can_breathe(uasmon))
X		pline("Use the command #monster for breath weapon.");
X	if (attacktype(uasmon, AT_SPIT))
X		pline("Use the command #monster to spit venom.");
X	if (u.usym == S_NYMPH)
X		pline("Use the command #monster if you have to remove an iron ball.");
X	if (u.usym == S_UMBER)
X		pline("Use the command #monster to confuse monsters.");
X	if (is_hider(uasmon))
X		pline("Use the command #monster to hide.");
X	if (is_were(uasmon))
X		pline("Use the command #monster to summon help.");
X	if (webmaker(uasmon))
X		pline("Use the command #monster to spin a web.");
X	if (lays_eggs(uasmon) || u.umonnum == PM_QUEEN_BEE)
X		pline("Use the command #sit to lay an egg.");
X	find_ac();
X	return(1);
X}
X
Xstatic void
Xbreak_armor() {
X     struct obj *otmp;
X
X     if (breakarm(uasmon)) {
X	if (otmp = uarm) {
X		You("break out of your armor!");
X		(void) Armor_gone();
X		useup(otmp);
X	}
X	if (otmp = uarmc) {
X		Your("cloak tears apart!");
X		(void) Cloak_off();
X		useup(otmp);
X	}
X#ifdef SHIRT
X	if (uarmu) {
X		Your("shirt rips to shreds!");
X		useup(uarmu);
X	}
X#endif
X     } else if (sliparm(uasmon)) {
X	if (otmp = uarm) {
X		Your("armor falls around you!");
X		(void) Armor_gone();
X		dropx(otmp);
X	}
X	if (otmp = uarmc) {
X		You("shrink out of your cloak!");
X		(void) Cloak_off();
X		dropx(otmp);
X	}
X#ifdef SHIRT
X	if (otmp = uarmu) {
X		You("become much too small for your shirt!");
X		setworn((struct obj *)0, otmp->owornmask & W_ARMU);
X		dropx(otmp);
X	}
X#endif
X     }
X     if (nohands(uasmon) || verysmall(uasmon)) {
X	  if (otmp = uarmg) {
X	       /* Drop weapon along with gloves */
X	       You("drop your gloves%s!", uwep ? " and weapon" : "");
X	       (void) Gloves_off();
X	       dropx(otmp);
X	       drop_weapon(0);
X	  }
X	  if (otmp = uarms) {
X	       You("can no longer hold your shield!");
X	       (void) Shield_off();
X	       dropx(otmp);
X	  }
X	  if (otmp = uarmh) {
X	       Your("helmet falls to the floor!");
X	       (void) Helmet_off();
X	       dropx(otmp);
X	  }
X	  if (otmp = uarmf) {
X	       Your("boots %s off your feet!",
X			verysmall(uasmon) ? "slide" : "get pushed");
X	       (void) Boots_off();
X	       dropx(otmp);
X	  }
X     }
X}
X
Xstatic void
Xdrop_weapon(alone)
Xint alone;
X{
X     struct obj *otmp;
X     if (otmp = uwep) {
X	  /* !alone check below is currently superfluous but in the
X	   * future it might not be so if there are monsters which cannot
X	   * wear gloves but can wield weapons
X	   */
X	  if (!alone || cantwield(uasmon)) {
X	       if (alone) You("find you must drop your weapon!");
X	       uwepgone();
X	       dropx(otmp);
X	  }
X     }
X}
X
Xvoid
Xrehumanize()
X{
X	boolean sticky = sticks(uasmon) && u.ustuck && !u.uswallow;
X
X	u.mh = u.mhmax = u.mtimedone = 0;
X 	u.acurr = u.macurr;		/* restore old strength */
X 	u.amax = u.mamax;
X	u.usym = S_HUMAN;
X	u.umonnum = -1;
X	skinback();
X	set_uasmon();
X	You("return to %sn form!",(pl_character[0]=='E')?"elve":"huma");
X
X	if (u.uhp < 1)	done("died");
X	if (!Fire_resistance && Inhell) {
X	    You("burn to a crisp.");
X	    killer = "dissipating polymorph spell";
X	   done("burned");
X	}
X	if (!uarmg) selftouch("No longer petrify-resistant, you");
X	if (sticky) uunstick();
X	nomul(0);
X	if (u.uundetected) u.uundetected = 0;
X	prme();
X	flags.botl = 1;
X	find_ac();
X}
X
Xint
Xdobreathe() {
X	if(!getdir(1)) return(0);
X	if (rn2(4))
X	    You("produce a loud and noxious belch.");
X	else {
X	    register struct attack *mattk;
X	    register int i;
X
X	    for(i = 0; i < NATTK; i++) {
X		mattk = &(uasmon->mattk[i]);
X		if(mattk->aatyp == AT_BREA) break;
X	    }
X	    buzz((int) (20 + mattk->adtyp-1), (int)mattk->damn,
X		u.ux, u.uy, u.dx, u.dy);
X	}
X	return(1);
X}
X
Xint
Xdospit() {
X	struct obj *otmp;
X
X	if (!getdir(1)) return(0);
X	otmp = mksobj(u.umonnum==PM_COBRA ? BLINDING_VENOM : ACID_VENOM, FALSE);
X	(void) throwit(otmp);
X	return(1);
X}
X
Xint
Xdoremove() {
X     if (!Punished) {
X	  You("are not chained to anything!");
X	  return(0);
X     }
X     unpunish();
X     return(1);
X}
X
Xint
Xdospinweb() {
X	register struct trap *ttmp = t_at(u.ux,u.uy);
X
X	if (Levitation) {
X		You("must be on the ground to spin a web.");
X		return(0);
X	}
X	if (u.uswallow) {
X		You("release web fluid inside %s.", mon_nam(u.ustuck));
X		pline("%s regurgitates you!", Monnam(u.ustuck));
X		u.ux = u.ustuck->mx;
X		u.uy = u.ustuck->my;
X		mnexto(u.ustuck);
X		u.uswallow = 0;
X		u.ustuck = 0;
X		setsee();
X		docrt();
X		return(1);
X	}
X	if (u.utrap) {
X		You("cannot spin webs while stuck in a trap.");
X		return(0);
X	}
X	if (ttmp) switch (ttmp->ttyp) {
X		case SPIKED_PIT:
X		case PIT: You("spin a web, covering up the pit.");
X			deltrap(ttmp);
X			if (Invisible) newsym(u.ux, u.uy);
X			return(1);
X		case WEB: You("make the web thicker.");
X			return(1);
X		case SQBRD: pline("The squeaky board is muffled.");
X			deltrap(ttmp);
X			if (Invisible) newsym(u.ux, u.uy);
X			return(1);
X		case TELEP_TRAP:
X		case LEVEL_TELEP:
X			Your("webbing vanishes!");
X			return(0);
X		case TRAPDOOR: if (!is_maze_lev) {
X				You("web over the trapdoor.");
X				deltrap(ttmp);
X				if (Invisible) newsym(u.ux, u.uy);
X				return 1;
X			}
X			/* Fall through */
X		case MGTRP:
X		case POLY_TRAP:
X		case DART_TRAP:
X		case ARROW_TRAP:
X#ifdef SPELLS
X		case ANTI_MAGIC:
X#endif
X		case LANDMINE:
X		case SLP_GAS_TRAP:
X		case BEAR_TRAP:
X		case RUST_TRAP:
X			You("have triggered a trap!");
X			dotrap(ttmp);
X			return(1);
X		default:
X			impossible("Webbing over trap type %d?",ttmp->ttyp);
X			return(0);
X	}
X	ttmp = maketrap(u.ux, u.uy, WEB);
X	ttmp->tseen = 1;
X	if (Invisible) newsym(u.ux, u.uy);
X	return(1);
X}
X
Xint
Xdosummon()
X{
X	You("call upon your brethren for help!");
X	if (!were_summon(uasmon,TRUE))
X		pline("But none arrive.");
X	return(1);
X}
X
Xint
Xdoconfuse()
X{
X	register struct monst *mtmp;
X	int looked = 0;
X
X	if (Blind) {
X		You("can't see anything to gaze at.");
X		return 0;
X	}
X	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X	    if (canseemon(mtmp)) {
X		looked = 1;
X		if (Invis && !perceives(mtmp->data))
X		    pline("%s seems not to notice your gaze.", Monnam(mtmp));
X		else if (mtmp->minvis && !See_invisible)
X		    You("can't see where to gaze at %s.", Monnam(mtmp));
X		else if (mtmp->mimic)
X		    continue;
X		else if (flags.safe_dog && !Confusion && !Hallucination
X		  && (mtmp->data->mlet == S_DOG || mtmp->data->mlet == S_FELINE)
X		  && mtmp->mtame) {
X		    if (mtmp->mnamelth)
X			You("avoid gazing at %s.", NAME(mtmp));
X		    else
X			You("avoid gazing at your %s.",
X						mtmp->data->mname);
X		} else {
X		    if (flags.confirm && mtmp->mpeaceful && !Confusion
X							&& !Hallucination) {
X			pline("Really confuse %s? ", mon_nam(mtmp));
X			(void) fflush(stdout);
X			if (yn() != 'y') continue;
X			setmangry(mtmp);
X		    }
X		    if (mtmp->mfroz || mtmp->mstun || mtmp->msleep ||
X							mtmp->mblinded)
X			continue;
X		    if (!mtmp->mconf)
X			Your("gaze confuses %s!", mon_nam(mtmp));
X		    else
X			pline("%s is getting more and more confused.",
X							Monnam(mtmp));
X		    mtmp->mconf = 1;
X		    if ((mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) {
X			You("are frozen by %s's gaze!", mon_nam(mtmp));
X			nomul((u.ulevel > 6 || rn2(4)) ? 
X				-d((int)mtmp->m_lev+1,
X					(int)mtmp->data->mattk[0].damd)
X				: -200);
X			return 1;
X		    }
X#ifdef MEDUSA
X		    if ((mtmp->data==&mons[PM_MEDUSA]) && !mtmp->mcan) {
X			pline("Gazing at an awake medusa is not a very good idea...");
X			You("turn to stone...");
X			done("stoned");
X		    }
X#endif
X		}
X	    }
X	}
X	if (!looked) You("gaze at no place in particular.");
X	return 1;
X}
X
Xint
Xdohide()
X{
X	if (u.uundetected || u.usym == S_MIMIC_DEF) {
X		pline("You are already hiding.");
X		return(0);
X	}
X	if (u.usym == S_MIMIC) {
X		u.usym = S_MIMIC_DEF;
X		prme();
X	} else {
X		newsym(u.ux,u.uy);
X		u.uundetected = 1;
X	}
X	return(1);
X}
X
Xstatic void
Xuunstick()
X{
X	kludge("%s is no longer in your clutches...", Monnam(u.ustuck));
X	u.ustuck = 0;
X}
X
Xstatic void
Xskinback()
X{
X	if (uskin) {
X		Your("skin returns to its original form.");
X		uarm = uskin;
X		uskin = (struct obj *)0;
X	}	
X}
X#endif
X
Xchar *
Xbody_part(part)
X{
X	/* Note: it is assumed these will never be >22 characters long,
X	 * plus the trailing null, after pluralizing (since sometimes a
X	 * buffer is made a fixed size and must be able to hold it)
X	 */
X	static const char *humanoid_parts[] = { "arm", "eye", "face", "finger",
X		"fingertip", "foot", "hand", "handed", "head", "leg",
X		"light headed", "neck", "toe" };
X#ifdef POLYSELF
X	static const char *jelly_parts[] = { "pseudopod", "dark spot", "front",
X		"pseudopod extension", "pseudopod extremity",
X		"pseudopod root", "grasp", "grasped", "cerebral area",
X		"lower pseudopod", "viscous", "middle",
X		"pseudopod extremity" },
X	*animal_parts[] = { "forelimb", "eye", "face", "foreclaw", "claw tip",
X		"rear claw", "foreclaw", "clawed", "head", "rear limb",
X		"light headed", "neck", "rear claw tip" },
X	*horse_parts[] = { "forelimb", "eye", "face", "forehoof", "hoof tip",
X		"rear hoof", "foreclaw", "hooved", "head", "rear limb",
X		"light headed", "neck", "rear hoof tip" },
X	*sphere_parts[] = { "appendage", "optic nerve", "body", "tentacle",
X		"tentacle tip", "lower appendage", "tentacle", "tentacled",
X		"body", "lower tentacle", "rotational", "equator",
X		"lower tentacle tip" },
X	*fungus_parts[] = { "mycelium", "visual area", "front", "hypha",
X		"hypha", "root", "strand", "stranded", "cap area",
X		"rhizome", "sporulated", "stalk", "rhizome tip" },
X	*vortex_parts[] = { "region", "eye", "front", "minor current",
X		"minor current", "lower current", "swirl", "swirled",
X		"central core", "lower current", "addled", "center",
X		"edge" },
X	*snake_parts[] = { "vestigal limb", "eye", "face", "large scale",
X		"large scale tip", "rear region", "scale gap", "scale gapped",
X		"head", "rear region", "light headed", "neck", "rear scale" };
X	
X	if (humanoid(uasmon) || (u.usym==S_CENTAUR && 
X		(part==ARM || part==FINGER || part==FINGERTIP
X		|| part==HAND || part==HANDED))) return humanoid_parts[part];
X	if (u.usym==S_CENTAUR || u.usym==S_UNICORN) return horse_parts[part];
X	if (u.usym==S_SNAKE || u.usym==S_NAGA || u.usym==S_WORM)
X		return snake_parts[part];
X	if (u.usym==S_EYE) return sphere_parts[part];
X	if (u.usym==S_JELLY || u.usym==S_PUDDING) return jelly_parts[part];
X	if (u.usym==S_VORTEX || u.usym==S_ELEMENTAL) return vortex_parts[part];
X	if (u.usym==S_FUNGUS) return fungus_parts[part];
X	return animal_parts[part];
X#else
X	return humanoid_parts[part];
X#endif
X}
X
Xint
Xpoly_gender()
X{
X/* Returns gender of polymorphed player; 0/1=same meaning as flags.female,
X * 2=none.
X * Used in:
X *	- Seduction by succubus/incubus
X *	- Talking to nymphs (sounds.c)
X * Not used in:
X *	- Messages given by nymphs stealing armor (they can't steal from
X *	  incubi/succubi/nymphs, and nonhumanoids can't wear armor).
X *	- Amulet of change (must refer to real gender no matter what
X *	  polymorphed into).
X *	- Priest/Priestess, Caveman/Cavewoman (ditto)
X *	- Polymorph self (only happens when human)
X *	- Shopkeeper messages (since referred to as "creature" and not "sir"
X *	  or "lady" when polymorphed)
X */
X#ifdef POLYSELF
X	if (uasmon->mflags1 & M1_FEM) return 1;
X#ifdef HARD
X	if (u.umonnum==PM_INCUBUS) return 0;
X#endif
X	if (!humanoid(uasmon)) return 2;
X#endif
X	return flags.female;
X}
X
X#ifdef POLYSELF
X#ifdef GOLEMS
Xvoid
Xugolemeffects(damtype, dam)
Xint damtype;
X{
X	int heal = 0;
X	/* We won't bother with "slow"/"haste" since players do not
X	 * have a monster-specific slow/haste so there is no way to
X	 * restore the old velocity once they are back to human.
X	 */
X	if (u.umonnum != PM_FLESH_GOLEM && u.umonnum != PM_IRON_GOLEM)
X		return;
X	switch (damtype) {
X		case AD_ELEC: if (u.umonnum == PM_IRON_GOLEM)
X				heal = dam / 6; /* Approx 1 per die */
X			break;
X		case AD_FIRE: if (u.umonnum == PM_IRON_GOLEM)
X				heal = dam;
X			break;
X	}
X	if (heal && (u.mh < u.mhmax)) {
X		u.mh += heal;
X		if (u.mh > u.mhmax) u.mh = u.mhmax;
X		flags.botl = 1;
X		pline("Strangely, you feel better than before.");
X	}
X}
X#endif /* GOLEMS */
X#endif
END_OF_FILE
if test 18377 -ne `wc -c <'src/polyself.c'`; then
    echo shar: \"'src/polyself.c'\" unpacked with wrong size!
fi
# end of 'src/polyself.c'
fi
echo shar: End of archive 13 \(of 38\).
cp /dev/null ark13isdone
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 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 38 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