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

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

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



#! /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 28 (of 38)."
# Contents:  src/attrib.c src/dothrow.c src/end.c src/termcap.c
#   src/worm.c
# Wrapped by billr@saab on Sun Jul 23 21:33:11 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/attrib.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/attrib.c'\"
else
echo shar: Extracting \"'src/attrib.c'\" \(11413 characters\)
sed "s/^X//" >'src/attrib.c' <<'END_OF_FILE'
X/*
X *	attrib.c	- attribute modification routines.
X *
X *	Copyright 1988, M. Stephenson
X */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include	"hack.h"
X
Xconst char	*plusattr[] = {	/* part of the output on gain of attribute */
X
X	"strong", "smart", "wise", "agile", "tough", "charismatic"
X};
X
Xconst char	*minusattr[] = { /* part of the output on loss of attribute */
X
X	"weak", "stupid", "foolish", "clumsy", "vulnerable", "ugly"
X};
X
Xstruct attribs	attrmax = {	/* max values for the attributes */
X
X	118, 18, 18, 18, 18, 18
X},
X		attrmin = {	/* min values for the attributes */
X
X	3, 3, 3, 3, 3, 3
X};
X
Xconst struct innate {
X
X	schar	ulevel;
X	long	*ability;
X	char	*gainstr, *losestr;
X}	a_abil[] = { {	 0, &(Stealth), "", "" },
X		     {   0, &(Fast), "", "" },
X		     {  10, &(Searching), "perceptive", "" },
X		     {	 0, 0, 0, 0 } },
X
X	b_abil[] = { {	 0, &(HPoison_resistance), "", "" },
X		     {   7, &(Fast), "quick", "slow" },
X		     {  15, &(Stealth), "stealthy", "" },
X		     {	 0, 0, 0, 0 } },
X
X	c_abil[] = { {	 7, &(Fast), "quick", "slow" },
X		     {	15, &(Warning), "sensitive", "" },
X		     {	 0, 0, 0, 0 } },
X
X	e_abil[] = { {   0, &(Fast), "", "" },
X		     {	 0, &(HSee_invisible), "", "" },
X		     {	 0, &(Searching), "", "" },
X		     {	 0, &(HSleep_resistance), "", "" },
X		     {	 0, 0, 0, 0 } },
X
X	h_abil[] = { {	 0, &(HPoison_resistance), "", "" },
X		     {	15, &(Warning), "sensitive", "" },
X		     {	 0, 0, 0, 0 } },
X
X	k_abil[] = { {	 7, &(Fast), "quick", "slow" },
X		     {	 0, 0, 0, 0 } },
X
X	p_abil[] = { {	15, &(Warning), "sensitive", "" },
X		     {  20, &(HFire_resistance), "cool", "warmer" },
X		     {	 0, 0, 0, 0 } },
X
X	r_abil[] = { {	 0, &(Stealth), "", ""  },
X		     {  10, &(Searching), "perceptive", "" },
X		     {	 0, 0, 0, 0 } },
X
X	s_abil[] = { {	 0, &(Fast), "", "" },
X		     {  15, &(Stealth), "stealthy", "" },
X		     {	 0, 0, 0, 0 } },
X
X	t_abil[] = { {	10, &(Searching), "perceptive", "" },
X		     {	20, &(HPoison_resistance), "hardy", "" },
X		     {	 0, 0, 0, 0 } },
X
X	v_abil[] = { {	 0, &(HCold_resistance), "", "" },
X		     {	 0, &(Stealth), "", "" },
X		     {   7, &(Fast), "quick", "slow" },
X		     {	 0, 0, 0, 0 } },
X
X	w_abil[] = { {	15, &(Warning), "sensitive", "" },
X		     {  17, &(HTeleport_control), "controlled","uncontrolled" },
X		     {	 0, 0, 0, 0 } };
X
Xconst struct clattr {
X
X	struct	attribs	base, dist;
X 	schar	align, aligntyp;
X	schar	shp, hd, xlev, ndx;
X/* According to AD&D, HD for some classes (i.e. Wizard) should be smaller
X * (4-sided for wizards).  But this is not AD&D, and using the AD&D
X * rule here produces an unplayable character.  This I have used a minimum
X * of an 10-sided hit die for everything.  Another AD&D change: wizards get
X * a minimum strength of 6 since without one you can't teleport or cast
X * spells. --KAA
X */
X	struct	innate *abil;
X}	a_attr = { {	 6,  9,  9,  6,  6,  6 },  /* Archeologist */
X		   {	20, 20, 20, 10, 20, 10 },
X		    10,  1, 13, 10, 14,  2, a_abil },
X
X	b_attr = { {	15,  6,  6, 14, 15,  5 },  /* Barbarian */
X		   {	30,  6,  7, 20, 30,  7 },
X		    10, -1, 16, 12, 10,  3, b_abil },
X
X	c_attr = { {	 9,  6,  6,  6,  7,  5 },  /* Caveman (fighter) */
X		   {	30,  6,  7, 20, 30,  7 },
X		     0,  1, 16, 10, 10,  3, c_abil },
X
X/*
X	e_attr = { {	13, 13, 14,  6, 14,  6 },
X */
X	e_attr = { {	12, 12, 12,  8, 12,  6 },  /* Elf (ranger) */
X		   {	30, 10, 10, 20, 20, 10 },
X		    10,  1, 15, 10, 11,  2, e_abil },
X
X	h_attr = { {	 6,  6, 12,  6, 10, 15 },  /* Healer (druid) */
X		   {	15, 20, 20, 15, 25, 10 },
X		    10,  1, 13, 10, 20,  2, h_abil },
X
X	k_attr = { {	12,  6, 13,  6,  9, 17 },  /* Knight (paladin) */
X		   {	20, 15, 15, 10, 20, 10 },
X		    10,  1, 16, 10, 10,  3, k_abil },
X
X	p_attr = { {	 6,  6,  9,  6,  6,  6 },  /* Priest (cleric) */
X		   {	15, 10, 30, 15, 20, 10 },
X		     0,  0, 14, 10, 10,  2, p_abil },
X
X	r_attr = { {	 6,  6,  6,  9,  6,  5 },  /* Rogue (thief) */
X		   {	20, 10, 10, 30, 20, 10 },
X		    10, -1, 12, 10, 11,  2, r_abil },
X
X	s_attr = { {	 9,  6,  6,  9, 17,  5 },  /* Samurai (fighter/thief) */
X		   {	30, 10, 10, 30, 14, 10 },
X		    10,  1, 15, 10, 11,  2, s_abil },
X
X	t_attr = { {	 6,  9,  5,  6,  6,  9 },  /* Tourist */
X		   {	15, 10, 10, 15, 30, 20 },
X		     0,  0, 10, 10, 14,  1, t_abil },
X
X	v_attr = { {	 9,  6,  6,  6,  9,  6 },  /* Valkyrie (fighter) */
X		   {	30,  6,  7, 20, 30,  7 },
X		     0, -1, 16, 10, 10,  3, v_abil },
X
X	w_attr = { {	 6,  9,  6,  6,  6,  6 },  /* Wizard (magic-user) */
X		   {	10, 30, 10, 20, 20, 10 },
X		     0,  0, 12, 10, 12,  1, w_abil },
X
X	X_attr = { {	 3,  3,  3,  3,  3,  3 },
X		   {	20, 15, 15, 15, 20, 15 },
X		     0,  0, 12, 10, 14,  1,  0 };
X
Xvoid
Xadjattrib(ndx, incr, silent)
X
X	int	ndx, incr;
X	boolean	silent;
X{
X	if(!incr) return;
X
X	if(incr > 0) {
X	    if((AMAX(ndx) >= attrmax.a[ndx]) && (ACURR(ndx) == AMAX(ndx))) {
X
X		if(!silent && flags.verbose)
X		    pline("You're already as %s as you can get.",
X			  plusattr[ndx]);
X		ABASE(ndx) = AMAX(ndx) = attrmax.a[ndx]; /* just in case */
X		return;
X	    }
X
X	    ABASE(ndx) += incr;
X	    if(ABASE(ndx) > AMAX(ndx)) {
X		incr = ABASE(ndx) - AMAX(ndx);
X		AMAX(ndx) += incr;
X		if(AMAX(ndx) > attrmax.a[ndx])
X		    AMAX(ndx) = attrmax.a[ndx];
X		ABASE(ndx) = AMAX(ndx);
X	    }
X	} else {
X	    if((AMAX(ndx) <= attrmin.a[ndx]) && (ABASE(ndx) == AMAX(ndx))) {
X		if(!silent && flags.verbose)
X		    pline("You're already as %s as you can get.",
X			  minusattr[ndx]);
X		ABASE(ndx) = AMAX(ndx) = attrmin.a[ndx]; /* just in case */
X		return;
X	    }
X
X	    ABASE(ndx) += incr;
X	    if(ABASE(ndx) < attrmin.a[ndx]) {
X		incr = ABASE(ndx) - attrmin.a[ndx];
X		ABASE(ndx) = attrmin.a[ndx];
X		AMAX(ndx) += incr;
X		if(AMAX(ndx) < attrmin.a[ndx])
X		    AMAX(ndx) = attrmin.a[ndx];
X	    }
X	}
X	if(!silent)
X	    You("feel %s%s!",
X		  (incr > 1) ? "very ": "",
X		  (incr > 0) ? plusattr[ndx] : minusattr[ndx]);
X	flags.botl = 1;
X	return;
X}
X
Xvoid
Xgainstr(otmp, incr)
X	register struct obj *otmp;
X	register int incr;
X{
X	int num = 1;
X
X	if(incr) num = incr;
X	else {
X	    if(ABASE(A_STR) < 18) num = (rn2(4) ? 1 : rnd(6) );
X	    else if (ABASE(A_STR) < 103) num = rnd(10);
X	}
X	adjattrib(A_STR, (otmp && otmp->cursed) ? -num : num, TRUE);
X}
X
Xvoid
Xlosestr(num)	/* may kill you; cause may be poison or monster like 'a' */
X	register int num;
X{
X	int ustr = ABASE(A_STR) - num;
X
X	while(ustr < 3) {
X		ustr++;
X		num--;
X		u.uhp -= 6;
X		u.uhpmax -= 6;
X	}
X	adjattrib(A_STR, -num, TRUE);
X}
X
Xvoid
Xchange_luck(n)
X	register schar n;
X{
X	u.uluck += n;
X	if (u.uluck < 0 && u.uluck < LUCKMIN)	u.uluck = LUCKMIN;
X	if (u.uluck > 0 && u.uluck > LUCKMAX)	u.uluck = LUCKMAX;
X}
X
Xint
Xstone_luck(parameter)
Xboolean parameter; /* So I can't think up of a good name.  So sue me. --KAA */
X{
X	register struct obj *otmp;
X	register int bonchance = 0;
X
X	for(otmp = invent; otmp; otmp=otmp->nobj)
X	    if(otmp->otyp == LUCKSTONE) {
X		if (otmp->cursed) bonchance -= otmp->quan;
X		else if (otmp->blessed) bonchance += otmp->quan;
X		else if (parameter) bonchance += otmp->quan;
X	    }
X
X	return sgn(bonchance);
X}
X
Xvoid
Xrestore_attrib() {
X
X	int	i;
X
X	for(i = 0; i < A_MAX; i++) {	/* all temporary losses/gains */
X
X	   if(ATEMP(i) && ATIME(i)) {
X		if(!(--(ATIME(i)))) { /* countdown for change */
X		    ATEMP(i) += ATEMP(i) > 0 ? -1 : 1;
X
X		    if(ATEMP(i)) /* reset timer */
X			ATIME(i) = 100 / ACURR(A_CON);
X		}
X	    }
X	}
X}
X
Xstatic struct	clattr *
Xclx()  {
X
X	register struct	clattr	*attr;
X
X	switch	(pl_character[0]) {
X
X	    case 'A':	attr = &a_attr;
X			break;
X	    case 'B':	attr = &b_attr;
X			break;
X	    case 'C':	attr = &c_attr;
X			break;
X	    case 'E':	attr = &e_attr;
X			break;
X	    case 'H':	attr = &h_attr;
X			break;
X	    case 'K':	attr = &k_attr;
X			break;
X	    case 'P':	attr = &p_attr;
X			break;
X	    case 'R':	attr = &r_attr;
X			break;
X	    case 'S':	attr = &s_attr;
X			break;
X	    case 'T':	attr = &t_attr;
X			break;
X	    case 'V':	attr = &v_attr;
X			break;
X	    case 'W':	attr = &w_attr;
X			break;
X	    default:	/* unknown type */
X			attr = &X_attr;
X			break;
X	}
X	return(attr);
X}
X
Xstatic void
Xinit_align() {	/* called from newhp if u.ulevel is 0 */
X
X	register struct	clattr	*attr = clx();
X
X	u.ualign = (int)attr->align;
X	u.ualigntyp = attr->aligntyp;
X}
X
Xvoid
Xinit_attr(np)
X	register int	np;
X{
X	register int	i, x, tryct;
X	register struct	clattr	*attr = clx();
X
X	for(i = 0; i < A_MAX; i++) {
X
X	    ABASE(i) = AMAX(i) = attr->base.a[i];
X	    ATEMP(i) = ATIME(i) = 0;
X	    np -= attr->base.a[i];
X	}
X
X	tryct = 0;
X	while(np > 0 && tryct < 100) {
X
X	    x = rn2(100);
X	    for(i = 0; (i < A_MAX) && ((x -= attr->dist.a[i]) > 0); i++);
X	    if(i >= A_MAX) continue; /* impossible */
X
X	    if(ABASE(i) >= attrmax.a[i]) {
X
X		tryct++;
X		continue;
X	    }
X	    tryct = 0;
X	    ABASE(i)++;
X	    AMAX(i)++;
X	    np--;
X	}
X
X	tryct = 0;
X	while(np < 0 && tryct < 100) {		/* for redistribution */
X
X	    x = rn2(100);
X	    for(i = 0; (i < A_MAX) && ((x -= attr->dist.a[i]) > 0); i++);
X	    if(i >= A_MAX) continue; /* impossible */
X
X	    if(ABASE(i) <= attrmin.a[i]) {
X
X		tryct++;
X		continue;
X	    }
X	    tryct = 0;
X	    ABASE(i)--;
X	    AMAX(i)--;
X	    np++;
X	}
X}
X
X#ifdef POLYSELF
Xvoid
Xredist_attr() {
X
X	register int i, tmp;
X
X	for(i = 0; i < A_MAX; i++) {
X	    if (i==A_INT || i==A_WIS) continue;
X		/* Polymorphing doesn't change your mind */
X	    tmp = AMAX(i);
X	    AMAX(i) += (rn2(5)-2);
X	    if (AMAX(i) > attrmax.a[i]) AMAX(i) = attrmax.a[i];
X	    if (AMAX(i) < attrmin.a[i]) AMAX(i) = attrmin.a[i];
X	    ABASE(i) = ABASE(i) * AMAX(i) / tmp;
X	    /* ABASE(i) > attrmax.a[i] is impossible */
X	    if (ABASE(i) < attrmin.a[i]) ABASE(i) = attrmin.a[i];
X	}
X}
X#endif
X
Xvoid
Xadjabil(flag)
X
X	int	flag;		/* +ve/-ve  = gain/lose */
X{
X	register struct	clattr	*attr = clx();
X	register struct innate	*abil = attr->abil;
X
X	if(abil) {
X
X	    for(; abil->ability; abil++) {
X		if ((flag>0 && u.ulevel >= abil->ulevel) ||
X					(flag<0 && u.ulevel < abil->ulevel)) {
X		    if(flag > 0) {
X			if(!(*(abil->ability) & INTRINSIC)) {
X			    *(abil->ability) |= INTRINSIC;
X			    if(strlen(abil->gainstr))
X				You("feel %s!", abil->gainstr);
X			}
X		    } else {
X			if((*(abil->ability) & INTRINSIC)) {
X			    *(abil->ability) &= ~INTRINSIC;
X			    if(strlen(abil->losestr))
X				You("feel %s!", abil->losestr);
X			    else if(strlen(abil->gainstr))
X				You("feel less %s!", abil->gainstr);
X			}
X		    }
X		} 
X	    }
X	}
X}
X
Xint
Xnewhp() {
X	register struct	clattr	*attr = clx();
X	int	hp, conplus;
X
X	if(u.ulevel == 0) {
X
X		hp = attr->shp;
X		init_align();	/* initialize alignment stuff */
X		return hp;
X	} else {
X
X	    if(u.ulevel < attr->xlev)
X		hp = rnd(attr->hd);
X	    else
X		hp = attr->ndx;
X	}
X
X	switch(ACURR(A_CON)) {
X		case	3:	conplus = -2; break;
X		case	4:
X		case	5:
X		case	6:	conplus = -1; break;
X		case	15:
X		case	16:	conplus = 1; break;
X		case	17:	conplus = 2; break;
X		case	18:	conplus = 3; break;
X		default:	conplus = 0;
X	}
X	hp += conplus;
X	return((hp <= 0) ? 1 : hp);
X}
X
Xschar
Xacurr(x) { 
X	register int tmp = (u.abon.a[x] + u.atemp.a[x] + u.acurr.a[x]);
X
X	if (x == A_STR) {
X		if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER) return(125);
X		else return((tmp >= 125) ? 125 : (tmp <= 3) ? 3 : tmp);
X	} 
X	else return((tmp >= 25) ? 25 : (tmp <= 3) ? 3 : tmp);
X}
X
X/* avoid possible problems with alignment overflow, and provide a centralized
X * location for any future alignment limits
X */
Xvoid
Xadjalign(n)
Xregister int n;
X{
X	register int newalign = u.ualign + n;
X
X	if(n < 0) {
X		if(newalign < u.ualign)
X			u.ualign = newalign;
X	} else
X		if(newalign > u.ualign)
X			u.ualign = newalign;
X}
END_OF_FILE
if test 11413 -ne `wc -c <'src/attrib.c'`; then
    echo shar: \"'src/attrib.c'\" unpacked with wrong size!
fi
# end of 'src/attrib.c'
fi
if test -f 'src/dothrow.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/dothrow.c'\"
else
echo shar: Extracting \"'src/dothrow.c'\" \(11169 characters\)
sed "s/^X//" >'src/dothrow.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)dothrow.c	3.0	88/10/22
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X/* Contains code for 't' (throw) */
X
X#include "hack.h"
X
Xstatic void gem_accept P((struct monst *, struct obj *));
Xstatic int throw_gold P((struct obj *));
Xstatic const char toss_objs[] = { '0', GOLD_SYM, '#', WEAPON_SYM, 0 };
X#ifdef WORM
Xextern boolean notonhead;
X#endif
X
Xint
Xdothrow() {
X	register struct obj *obj;
X
X	obj = getobj(toss_objs, "throw");
X	/* it is also possible to throw food */
X	/* (or jewels, or iron balls... ) */
X
X	if(!obj || !getdir(1)) {       /* ask "in what direction?" */
X		if(obj && obj->olet == GOLD_SYM) u.ugold += OGOLD(obj);
X		return(0);
X	}
X
X	if(obj->olet == GOLD_SYM) return(throw_gold(obj));
X
X	if(!canletgo(obj,"throw"))
X		return(0);
X	if(obj->otyp == BOULDER
X#ifdef POLYSELF
X					&& !throws_rocks(uasmon)
X#endif
X								) {
X		pline("It's too heavy.");
X		return(1);
X	}
X	if(!u.dx && !u.dy && !u.dz) {
X		You("cannot throw an object at yourself.");
X		return(0);
X	}
X	u_wipe_engr(2);
X
X	if(obj == uwep) {
X	    if(welded(obj)) {
X		weldmsg(obj, FALSE);
X		return(1);
X	    }
X	    if(obj->quan > 1)
X		setuwep(splitobj(obj, 1));
X	    else {
X		setuwep((struct obj *)0);
X		if (uwep) return(1); /* unwielded, died, rewielded */
X	    }
X	}
X	else if(obj->quan > 1)
X		(void) splitobj(obj, 1);
X	freeinv(obj);
X	return(throwit(obj));
X}
X
Xstatic void
Xhitfloor(obj)
Xregister struct obj *obj;
X{
X#ifdef ALTARS
X	if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj);
X	else
X#endif
X		pline("%s hits the floor.", Doname2(obj));
X	if (breaks(obj, TRUE)) return;
X	else if(obj->olet == POTION_SYM) {
X		pline("The flask breaks, and you smell a peculiar odor...");
X		potionbreathe(obj);
X		obfree(obj, (struct obj *)0);
X	} else
X		dropy(obj);
X}
X
Xint
Xthrowit(obj)
Xregister struct obj *obj;
X{
X	register struct monst *mon;
X	register int range;
X
X	if(u.uswallow) {
X		mon = u.ustuck;
X		bhitpos.x = mon->mx;
X		bhitpos.y = mon->my;
X	} else if(u.dz) {
X	  if(u.dz < 0) {
X	    pline("%s hits the ceiling, then falls back on top of your %s.",
X		Doname2(obj),		/* note: obj->quan == 1 */
X		body_part(HEAD));
X	    if(obj->olet == POTION_SYM)
X		potionhit(&youmonst, obj);
X	    else {
X		if(uarmh) pline("Fortunately, you are wearing a helmet!");
X		losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object");
X		if (!breaks(obj, TRUE)) dropy(obj);
X	    }
X	  } else hitfloor(obj);
X	  return(1);
X
X	} else if(obj->otyp == BOOMERANG) {
X		mon = boomhit(u.dx, u.dy);
X		if(mon == &youmonst) {		/* the thing was caught */
X			(void) addinv(obj);
X			return(1);
X		}
X	} else {
X		if(obj->otyp == PICK_AXE && shkcatch(obj))
X		    return(1);
X
X		range = (int)((ACURR(A_STR) > 18 ? 20 : ACURR(A_STR))/2 - obj->owt/4);
X		if (obj == uball) {
X			if (u.ustuck) range = 1;
X			else if (range >= 5) range = 5;
X		}
X		if (range < 1) range = 1;
X
X		if ((obj->olet == WEAPON_SYM || obj->olet == GEM_SYM) &&
X		    uwep &&
X		    objects[obj->otyp].w_propellor ==
X			-objects[uwep->otyp].w_propellor)
X				range++;
X#ifdef POLYSELF
X		if (obj->otyp == BOULDER) range = 20;
X#endif
X
X		mon = bhit(u.dx, u.dy, range, obj->olet,
X			(int (*)()) 0, (int (*)()) 0, obj);
X	}
X	if(mon) {
X		/* awake monster if sleeping */
X		wakeup(mon);
X#ifdef WORM
X		if(bhitpos.x != mon->mx || bhitpos.y != mon->my)
X			notonhead = TRUE;
X#endif
X		if(thitmonst(mon, obj)) return(1);
X	}
X	if(!u.uswallow)  {
X		char let = obj->olet;
X
X		/* the code following might become part of dropy() */
X		if (breaks(obj, TRUE)) {
X			tmp_at(-1, let);
X			tmp_at(-3, (int)AT_OBJ);
X			tmp_at(bhitpos.x, bhitpos.y);
X			tmp_at(-1, -1);
X			return(1);
X		}
X		if(flooreffects(obj,bhitpos.x,bhitpos.y)) return(1);
X#ifdef WORM
X		if(obj->otyp == CRYSKNIFE)
X			obj->otyp = WORM_TOOTH;
X#endif
X		obj->ox = bhitpos.x;
X		obj->oy = bhitpos.y;
X		obj->nobj = fobj;
X		fobj = obj;
X		levl[bhitpos.x][bhitpos.y].omask = 1;
X		if(obj->unpaid && costly_spot(bhitpos.x, bhitpos.y))
X			subfrombill(obj);
X		stackobj(obj);
X		if(obj == uball &&
X			(bhitpos.x != u.ux || bhitpos.y != u.uy)){
X			if(u.utrap){
X				if(u.utraptype == TT_PIT)
X					pline("The ball pulls you out of the pit!");
X				else if(u.utraptype == TT_WEB)  {
X					pline("The ball pulls you out of the web!");
X					pline("The web is destroyed!");
X					deltrap(t_at(u.ux,u.uy));
X				} else {
X				register long side =
X					rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
X				pline("The ball pulls you out of the bear trap.");
X				Your("%s %s is severely damaged.",
X					(side == LEFT_SIDE) ? "left" : "right",
X					body_part(LEG));
X				set_wounded_legs(side, 500+rn2(1000));
X				losehp(2, "thrown ball");
X				}
X				u.utrap = 0;
X			}
X			unsee();
X			u.ux = bhitpos.x - u.dx;
X			u.uy = bhitpos.y - u.dy;
X			movobj(uchain,u.ux,u.uy);
X			setsee();
X			spoteffects();
X		}
X		if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
X	}  else
X		mpickobj(u.ustuck,obj);
X	return(1);
X}
X
Xint
Xthitmonst(mon, obj)
Xregister struct monst *mon;
Xregister struct obj   *obj;
X{
X	register int	tmp; /* Base chance to hit */
X
X	/* Differences from melee weapons:
X	 *
X	 * Dex still gives a bonus, but strength does not.
X	 * Polymorphed players lacking attacks may still throw.
X	 * There's a base -2 to hit.
X	 * No bonuses for fleeing or stunned targets (they don't dodge
X	 *    melee blows as readily, but dodging arrows is hard anyway).
X	 * Not affected by traps, etc...
X	 * Certain items which don't in themselves do damage ignore tmp.
X	 */
X	tmp = -2 + Luck + mon->data->ac;
X#ifdef POLYSELF
X	if (u.umonnum >= 0) tmp += uasmon->mlevel;
X	else
X#endif
X		tmp += u.ulevel;
X	if(ACURR(A_DEX) < 4) tmp -= 3;
X	else if(ACURR(A_DEX) < 6) tmp -= 2;
X	else if(ACURR(A_DEX) < 8) tmp -= 1;
X	else if(ACURR(A_DEX) > 15) tmp += (ACURR(A_DEX) - 15);
X
X	if(mon->msleep) {
X		mon->msleep = 0;
X		tmp += 2;
X	}
X	if(mon->mfroz) {
X		tmp += 4;
X		if(!rn2(10)) mon->mfroz = 0;
X	}
X	if (is_orc(mon->data) && pl_character[0]=='E') tmp++;
X	if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */
X
X	if(obj->olet == GEM_SYM && mon->data->mlet == S_UNICORN) {
X		if (mon->mtame)
X			kludge("%s catches and drops the %s.",
X				Monnam(mon), xname(obj));
X		else {
X			kludge("%s catches the %s.", Monnam(mon), xname(obj));
X			gem_accept(mon, obj);
X		}
X		return(1);
X	}
X	if(obj->olet == WEAPON_SYM || obj->otyp == ROCK || obj->olet == GEM_SYM) {
X		if(obj->otyp < DART || obj->otyp == ROCK || obj->olet == GEM_SYM) {
X		    if (!uwep ||
X			objects[obj->otyp].w_propellor !=
X			-objects[uwep->otyp].w_propellor)
X			    tmp -= 4;
X		    else    tmp += uwep->spe;
X		} else if(obj->otyp == BOOMERANG) tmp += 4;
X		tmp += obj->spe;
X		if(tmp >= rnd(20)) {
X			if(hmon(mon,obj,1) == TRUE){
X			  /* mon still alive */
X#ifdef WORM
X			  cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp);
X#endif
X			} else mon = 0;
X			/* projectiles thrown disappear sometimes */
X			if((obj->otyp < BOOMERANG || obj->olet == GEM_SYM)
X								&& rn2(3)) {
X				/* check bill; free */
X				obfree(obj, (struct obj *)0);
X				return(1);
X			}
X		} else miss(xname(obj), mon);
X	} else if(obj->otyp == HEAVY_IRON_BALL) {
X		if(obj != uball) tmp += 2;
X		if(tmp >= rnd(20)) {
X			if(hmon(mon,obj,1) == FALSE)
X				mon = 0;	/* he died */
X		} else miss(xname(obj), mon);
X	} else if (obj->otyp == BOULDER) {
X		tmp += 6;  /* Likely to hit! */
X		if(tmp >= rnd(20)) {
X			if(hmon(mon,obj,1) == FALSE)
X				mon = 0;	/* he died */
X		} else miss(xname(obj), mon);
X	} else if((obj->otyp == CREAM_PIE
X#ifdef POLYSELF
X			|| obj->otyp == BLINDING_VENOM
X#endif
X					) && ACURR(A_DEX) >= rnd(10)) {
X		(void) hmon(mon,obj,1); /* can't die from it */
X#ifdef POLYSELF
X	} else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) {
X		if(hmon(mon,obj,1) == FALSE)
X			mon = 0;
X#endif
X	} else if(obj->olet == POTION_SYM && ACURR(A_DEX) >= rnd(15)) {
X		potionhit(mon, obj);
X		return(1);
X	} else {
X		pline("The %s misses %s.", xname(obj),
X			cansee(bhitpos.x,bhitpos.y) ? mon_nam(mon) : "it");
X		if(obj->olet == FOOD_SYM &&
X		  (mon->data->mlet == S_DOG || mon->data->mlet == S_FELINE))
X			if(tamedog(mon,obj)) return(1);
X	}
X	return(0);
X}
X
Xstatic void
Xgem_accept(mon, obj)
Xregister struct monst *mon;
Xregister struct obj *obj;
X{
X	char buf[BUFSZ];
X	static const char nogood[] = " is not interested in your junk.";
X	static const char maybeluck[] = " hesitatingly accepts your gift.";
X	static const char addluck[] = " graciously accepts your gift.";
X
X	Strcpy(buf,Monnam(mon));
X
X	mon->mpeaceful = 1;
X	if(obj->dknown && objects[obj->otyp].oc_name_known)  {
X		if(objects[obj->otyp].g_val > 0)  {
X		    if(mon->data == &mons[
X				((u.ualigntyp== U_CHAOTIC) ? PM_BLACK_UNICORN :
X				 (u.ualigntyp == U_LAWFUL) ? PM_WHITE_UNICORN
X						  : PM_GREY_UNICORN)]) {
X			    Strcat(buf, addluck);
X			    change_luck(5);
X		    } else {
X			    Strcat(buf, maybeluck);
X			    change_luck(rn2(7)-3);
X		    }
X		} else {
X		    Strcat(buf,nogood);
X		    goto nopick;
X		}
X	}  else  {  /* value unknown to @ */
X		change_luck(1);
X		Strcat(buf,addluck);
X	}
X	mpickobj(mon, obj);
Xnopick:
X	if(!Blind) pline(buf);
X	rloc(mon);
X}
X
X/* returns 0 if object doesn't break	*/
X/* returns 1 if object broke 		*/
Xint
Xbreaks(obj, loose)
Xregister struct obj   *obj;
Xregister boolean loose;		/* if not loose, obj is in fobj chain */
X{
X	switch(obj->otyp) {
X#ifdef MEDUSA
X		case MIRROR:
X			change_luck(-2);	/* and fall through */
X#endif
X		case EXPENSIVE_CAMERA:
X		case CRYSTAL_BALL:
X			if(!Blind)
X			    pline("%s shatters into a thousand pieces!",
X				Doname2(obj));
X			else You("hear something shatter!");
X			break;
X		case EGG:
X			pline("Splat!");
X			break;
X		case CREAM_PIE:
X			pline("What a mess!");
X			break;
X		case ACID_VENOM:
X		case BLINDING_VENOM:
X			pline("Splash!");
X			break;
X		default:
X			return 0;
X	}
X
X	if(loose) {
X		unpobj(obj);
X		obfree(obj, (struct obj *)0);
X	} else {
X		addtobill(obj, FALSE);
X		delobj(obj);
X	}
X	return(1);
X}
X
Xstatic boolean 
Xmartial() 
X{
X	return((pl_character[0] == 'S' || pl_character[0] == 'P'));
X}
X
Xstatic int
Xthrow_gold(obj)
Xstruct obj *obj;
X{
X	int range = 0, odx, ody;
X	long zorks = OGOLD(obj);
X	register struct monst *mon;
X
X	free((genericptr_t) obj);
X	if(zorks < 0) {
X		/* watch negative overflows a la drop() */
X		u.ugold += zorks;
X	pline("The LRS would be very interested to know you have that much.");
X		return(0);
X	}
X
X	if(u.uswallow) {
X		pline("The gold disappears in the %s's entrails.", 
X					mon_nam(u.ustuck));
X		u.ustuck->mgold += zorks;
X		return(1);
X	}
X
X	if(u.dz) {
X	  	if(u.dz < 0) {
X	    pline("The gold hits the ceiling, then falls back on top of your %s.",
X		    body_part(HEAD));
X		    /* some self damage? */
X		    if(uarmh) pline("Fortunately, you are wearing a helmet!");
X		} else pline("The gold hits the floor.");
X		bhitpos.x = u.ux; /* a msg is needed here */
X		bhitpos.y = u.uy;
X		goto skip;
X	}
X
X	range = rnd((int)ACURR(A_STR));
X	if(martial()) range = range + rnd(3);
X
X	/* see if the gold has a place to move into */
X	odx = u.ux + u.dx;
X	ody = u.uy + u.dy;
X	if(bad_kick_throw_pos(odx,ody)) {
X		bhitpos.x = u.ux;
X		bhitpos.y = u.uy;
X	} else {
X		if (mon = ghit(u.dx, u.dy, range))
X		    if (ghitm(mon, zorks))	/* was it caught? */
X			zorks = 0;
X	}
Xskip:
X	if (zorks)	/* perhaps it was caught */
X	    mkgold(zorks, bhitpos.x, bhitpos.y);
X	if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
X	return(1);
X}
END_OF_FILE
if test 11169 -ne `wc -c <'src/dothrow.c'`; then
    echo shar: \"'src/dothrow.c'\" unpacked with wrong size!
fi
# end of 'src/dothrow.c'
fi
if test -f 'src/end.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/end.c'\"
else
echo shar: Extracting \"'src/end.c'\" \(11591 characters\)
sed "s/^X//" >'src/end.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)end.c	3.0	88/05/03
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#ifndef TOS
X#include <signal.h>
X#endif
X
X/* block some unused #defines to avoid overloading some cpp's */
X#define MONATTK_H
X#include "hack.h"
X
X#include "eshk.h"
X
Xvoid end_box_display();
X
Xint
Xdone1()
X{
X#ifndef TOS
X	(void) signal(SIGINT,SIG_IGN);
X#endif
X	if(flags.ignintr) {
X#ifndef TOS
X		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#endif
X		clrlin();
X		curs_on_u();
X		(void) fflush(stdout);
X		if(multi > 0) nomul(0);
X		return 0;
X	}
X	return done2();
X} 
X
Xint
Xdone2()
X{
X	pline("Really quit? ");
X	if(yn() == 'n') {
X#ifndef TOS
X		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
X#endif
X		clrlin();
X		curs_on_u();
X		(void) fflush(stdout);
X		if(multi > 0) nomul(0);
X		return 0;
X	}
X#if defined(WIZARD) && defined(UNIX)
X	if(wizard) {
X	    pline("Dump core? ");
X	    if(yn() == 'y') {
X		(void) signal(SIGINT, (SIG_RET_TYPE) done1);
X		settty(NULL);
X#ifdef SYSV
X		(void)
X#endif
X		    abort();
X	    }
X	}
X#endif
X#ifndef LINT
X	done("quit");
X#endif
X	return 0;
X}
X
Xstatic
Xint
Xdone_intr(){
X	done_stopprint++;
X#ifndef TOS
X	(void) signal(SIGINT, SIG_IGN);
X#ifdef UNIX
X	(void) signal(SIGQUIT, SIG_IGN);
X#endif
X#endif /* TOS /* */
X	return 0;
X}
X
X#ifdef UNIX
Xstatic
Xint
Xdone_hangup(){
X	done_hup++;
X	(void)signal(SIGHUP, SIG_IGN);
X	(void)done_intr();
X	return 0;
X}
X#endif
X
Xvoid
Xdone_in_by(mtmp)
Xregister struct monst *mtmp;
X{
X	char buf[BUFSZ];
X
X	You("die...");
X	buf[0] = '\0';
X	if (mtmp->minvis)
X		Sprintf(eos(buf), "invisible ");
X	if (Hallucination)
X		Sprintf(eos(buf), "hallucinogen-distorted ");
X
X	if(mtmp->data->mlet == S_GHOST) {
X		register char *gn = (char *) mtmp->mextra;
X		if (!Hallucination && !mtmp->minvis && *gn)
X			Sprintf(eos(buf), "the ");
X		Sprintf(eos(buf), (*gn ? "ghost of %s" : "ghost%s"), gn);
X	} else if(mtmp->isshk) {
X		Sprintf(eos(buf), "%s %s, the shopkeeper",
X			(ESHK(mtmp)->ismale ? "Mr." : "Ms."), shkname(mtmp));
X	} else if (mtmp->iswiz)
X		Sprintf(eos(buf), "the %s", mons[PM_WIZARD_OF_YENDOR].mname);
X	else Sprintf(eos(buf), "%s", mtmp->data->mname);
X	if (mtmp->mnamelth) Sprintf(eos(buf), " called %s", NAME(mtmp));
X	killer = buf;
X	if (mtmp->data->mlet == S_WRAITH)
X		u.ugrave_arise = PM_WRAITH;
X	else if (mtmp->data->mlet == S_MUMMY)
X		u.ugrave_arise = (pl_character[0]=='E') ?
X						PM_ELF_MUMMY : PM_HUMAN_MUMMY;
X	else if (mtmp->data->mlet == S_VAMPIRE)
X		u.ugrave_arise = PM_VAMPIRE;
X	if (u.ugrave_arise > -1 && (mons[u.ugrave_arise].geno & G_GENOD))
X		u.ugrave_arise = -1;
X	if (mtmp->data->mlet == S_COCKATRICE)
X		done("stoned");
X	else
X		done("died");
X	return;
X}
X
X/*VARARGS1*/
Xboolean panicking;
Xextern boolean hu;	/* from save.c */
X
Xvoid
Xpanic(str,a1,a2,a3,a4,a5,a6)
Xchar *str;
X{
X	if(panicking++)
X#ifdef SYSV
X	    (void)
X#endif
X		abort();    /* avoid loops - this should never happen*/
X				    /* was exit(1) */
X	home(); cls();
X	(void) puts(" Suddenly, the dungeon collapses.");
X#ifdef WIZARD
X# ifndef MSDOS
X	if(!wizard) {
X	    pline("Report error to %s and it may be possible to rebuild.",WIZARD);
X	    more();
X	}
X	Sprintf (SAVEF, "%s.e", SAVEF);
X	hu = FALSE;
X	(void) dosave0();
X# endif
X#endif
X	(void) fputs(" ERROR:  ", stdout);
X	Printf(str,a1,a2,a3,a4,a5,a6);
X	more();				/* contains a fflush() */
X#ifdef WIZARD
X# ifdef UNIX
X	if (wizard)	
X#  ifdef SYSV
X		(void)
X#  endif
X		    abort();	/* generate core dump */
X# endif
X#endif
X	done("panicked");
X}
X
X/* called with arg "died", "drowned", "escaped", "quit", "choked", "panicked",
X   "burned", "starved", "stoned", or "tricked" */
X/* Be careful not to call panic from here! */
Xvoid
Xdone(st1)
Xregister char *st1;
X{
X	struct permonst *upmon;
X	char buf[BUFSZ], buf1[BUFSZ], buf2[BUFSZ];
X	char	c;
X	boolean taken;
X#ifdef WIZARD
X	if (wizard && *st1=='t') {
X		You("are a very tricky wizard, it seems.");
X		return;
X	}
X#endif
X	if(Lifesaved && index("bcds", *st1)){
X		u.uswldtim = 0;
X		if(u.uhpmax < 0) u.uhpmax = 10;	/* arbitrary */
X		u.uhp = u.uhpmax;
X		adjattrib(A_CON, -1, TRUE);
X		pline("But wait...");
X		makeknown(AMULET_OF_LIFE_SAVING);
X		Your("medallion %s!",
X		      !Blind ? "begins to glow" : "feels warm");
X		You("feel much better!");
X		pline("The medallion crumbles to dust!");
X		useup(uamul);
X		Lifesaved = 0;
X		if (u.uhunger < 500) u.uhunger = 500;
X		nomovemsg = "You survived that attempt on your life.";
X		curs_on_u();
X		flags.move = 0;
X		if(multi > 0) multi = 0; else multi = -1;
X		flags.botl = 1;
X		u.ugrave_arise = -1;
X		if (!strncmp(killer, "genocide", 8)) {
X			pline("Unfortunately you are still genocided...");
X			done("died");
X		}
X		return;
X	}
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X	if((wizard || discover) && index("bcds", *st1)){
X		pline("Die? ");
X		if(yn() == 'y') goto die;
X		u.uswldtim = 0;
X		if(u.uhpmax < 0) u.uhpmax = 100;	/* arbitrary */
X		u.uhp = u.uhpmax;
X		if (u.uhunger < 500) u.uhunger = 500;
X		pline("Ok, so you don't die.");
X		nomovemsg = "You survived that attempt on your life.";
X		curs_on_u();
X		flags.move = 0;
X		if(multi > 0) multi = 0; else multi = -1;
X		flags.botl = 1;
X		u.ugrave_arise = -1;
X		return;
X	}
X#endif /* WIZARD || EXPLORE_MODE */
Xdie:
X#ifndef TOS
X	(void) signal(SIGINT, (SIG_RET_TYPE) done_intr);
X#ifdef UNIX
X	(void) signal(SIGQUIT, (SIG_RET_TYPE) done_intr);
X	(void) signal(SIGHUP, (SIG_RET_TYPE) done_hangup);
X#endif
X#endif /* TOS /* */
X	upmon = player_mon();
X	if(u.ugrave_arise > -1) /* create no corpse */ ;
X	else if(*st1 == 's' && st1[2] == 'o') 
X		(mk_named_object(STATUE, upmon, u.ux, u.uy, plname,
X					strlen(plname)))->spe = 0;
X	else
X		(void) mk_named_object(CORPSE, upmon, u.ux, u.uy, plname,
X							strlen(plname));
X	if(*st1 == 'q' && u.uhp < 1){
X		st1 = "died";
X		killer = "quit while already on Charon's boat";
X	}
X	if(*st1 == 's' && st1[2] == 'a') killer = "starvation"; else
X	if(*st1 == 'd' && st1[1] == 'r') killer = "drowning"; else
X	if(*st1 == 'p') killer = "panic"; else
X	if(*st1 == 't') killer = "trickery"; else
X	if(!index("bcds", *st1)) killer = st1;
X	taken = paybill();
X	paygd();
X	clearlocks();
X	if(flags.toplin == 1) more();
X
X	if(invent) {
X	    if(taken)
X		pline("Do you want to see what you had when you %s? ",
X			(*st1=='q') ? "quit" : "died");
X	    else
X		pline("Do you want your possessions identified? ");
X	    /* New dump format by maartenj@cs.vu.nl */
X	    if ((c = yn_function(ynqchars,'y')) == 'y') {
X		struct obj *obj;
X
X		for(obj = invent; obj && !done_stopprint; obj = obj->nobj) {
X		    makeknown(obj->otyp);
X		    obj->known = obj->bknown = obj->dknown = 1;
X		}
X		doinv(NULL);
X		end_box_display();
X	    }
X	    if (c == 'q')  done_stopprint++;
X	    if (taken) {
X		/* paybill has already given the inventory locations in the shop
X		 * and put it on the main object list
X		 */
X		struct obj *obj;
X
X		for(obj = invent; obj; obj = obj->nobj) {
X		    obj->owornmask = 0;
X		    if(rn2(5)) curse(obj);
X		}
X	        invent = (struct obj *) 0;
X	    }
X	}
X
X	if(index("bcds", *st1)){
X#ifdef WIZARD
X	    if(wizard) {
X		pline("Save bones? ");
X		if(yn() == 'y') savebones();
X	    }  else
X#endif
X		savebones();
X	    if(!flags.notombstone) outrip();
X	}
X	if(*st1 == 'c') killer = st1;		/* after outrip() */
X	if(*st1 == 's' && st1[2] == 'o') {
X		Sprintf(buf, "turned to stone by %s",killer);
X		/* No a or an; topten.c will do that. */
X		killer = buf;
X		st1 = "turned to stone";
X	}
X	Strcpy(buf1, st1);
X	if(u.uhave_amulet) Strcat(killer," (with the Amulet)");
X	settty(NULL);	/* does a clear_screen() */
X	Strcpy(buf2, plname);
X	if('a' <= buf2[0] && buf2[0] <= 'z') buf2[0] += 'A'-'a';
X	if(!done_stopprint)
X	    Printf("Goodbye %s the %s...\n\n", buf2,
X#ifdef ENDGAME
X		   *st1 != 'a' ? pl_character : "Demigod");
X#else
X		   pl_character);
X#endif
X	{ long int tmp;
X	  tmp = u.ugold - u.ugold0;
X	  if(tmp < 0)
X		tmp = 0;
X	  if(*st1 == 'd' || *st1 == 'b')
X		tmp -= tmp/10;
X	  u.urexp += tmp;
X	  u.urexp += 50 * maxdlevel;
X	  if(maxdlevel > 20)
X		u.urexp += 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20);
X#ifdef ENDGAME
X	  if(*st1 == 'a') u.urexp *= 2;
X#endif
X	}
X	if(*st1 == 'e') {
X		register struct monst *mtmp;
X		register struct obj *otmp;
X		long i;
X		register unsigned int worthlessct = 0;
X
X		killer = st1;
X		keepdogs();
X		mtmp = mydogs;
X		if(mtmp) {
X			if(!done_stopprint) Printf("You");
X			while(mtmp) {
X				if(!done_stopprint)
X					Printf(" and %s", mon_nam(mtmp));
X				if(mtmp->mtame)
X					u.urexp += mtmp->mhp;
X				mtmp = mtmp->nmon;
X			}
X			if(!done_stopprint)
X		    Printf("\nescaped from the dungeon with %ld points,\n",
X			u.urexp);
X		} else
X		if(!done_stopprint)
X		  Printf("You escaped from the dungeon with %ld points,\n",
X		    u.urexp);
X		get_all_from_box(); /* don't forget things in boxes and bags */
X		for(otmp = invent; otmp; otmp = otmp->nobj) {
X			if(otmp->olet == GEM_SYM && otmp->otyp < LUCKSTONE) {
X				makeknown(otmp->otyp);
X				i = (long) otmp->quan *
X					objects[otmp->otyp].g_val;
X				if(i == 0) {
X					worthlessct += otmp->quan;
X					continue;
X				}
X				u.urexp += i;
X				Printf("        %s (worth %ld Zorkmids),\n",
X				    doname(otmp), i);
X			} else if(otmp->olet == AMULET_SYM) {
X				otmp->known = 1;
X				i = (otmp->spe < 0) ? 2 : 
X					otmp->otyp == AMULET_OF_YENDOR ?
X							5000 : 500;
X				u.urexp += i;
X				Printf("        %s (worth %ld Zorkmids),\n",
X				    doname(otmp), i);
X			}
X		}
X		if(worthlessct)
X		  Printf("        %u worthless piece%s of colored glass,\n",
X			worthlessct, plur((long)worthlessct));
X		if(u.uhave_amulet) killer = "escaped (with Amulet)";
X		else killer = "escaped";
X	} else
X		if(!done_stopprint) {
X		    Printf("You %s ", 
X			!strcmp(st1, "tricked") ? "were tricked" : st1);
X#ifdef ENDGAME
X		    if (*st1 != 'a') {
X			if(dlevel == ENDLEVEL)
X			     Printf("in the endgame ");
X		    	else Printf("on dungeon level %d ", dlevel);
X		    }
X#else
X		    Printf("on dungeon level %d ", dlevel);
X#endif
X		    Printf("with %ld points,\n", u.urexp);
X		}
X	if(!done_stopprint)
X	  Printf("and %ld piece%s of gold, after %ld move%s.\n",
X	    u.ugold, plur(u.ugold), moves, plur(moves));
X	if(!done_stopprint)
X  Printf("You were level %u with a maximum of %d hit points when you %s.\n",
X	    u.ulevel, u.uhpmax, buf1);
X	if(*st1 == 'e' && !done_stopprint){
X		getret();	/* all those pieces of coloured glass ... */
X		cls();
X	}
X#if defined(WIZARD) || defined(EXPLORE_MODE)
X	if(wizard || discover)
X		Printf("\nSince you were in %s mode, the score list \
Xwill not be checked.\n", wizard ? "wizard" : "discover");
X	else
X#endif
X		topten();
X/* "So when I die, the first thing I will see in Heaven is a score list?" */
X	if(done_stopprint) Printf("\n\n");
X#ifdef APOLLO
X	getret();
X#endif
X	exit(0);
X}
X
Xvoid
Xclearlocks(){
X#if defined(DGK) && !defined(TOS)
X	eraseall(levels, alllevels);
X	if (ramdisk)
X		eraseall(permbones, alllevels);
X#else
X#if defined(UNIX) || (defined(MSDOS) && !defined(TOS))
X	register int x;
X#ifdef UNIX
X	(void) signal(SIGHUP,SIG_IGN);
X#endif
X	for(x = maxdlevel; x >= 0; x--) {
X		glo(x);
X		(void) unlink(lock);	/* not all levels need be present */
X	}
X#endif
X#endif
X}
X
X#ifdef NOSAVEONHANGUP
Xint
Xhangup()
X{
X	(void) signal(SIGINT, SIG_IGN);
X	clearlocks();
X	exit(1);
X}
X#endif
X
Xvoid
Xend_box_display()
X{
X	register struct obj *box, *obj;
X	char buf[BUFSZ];
X
X	for(box=invent; box; box=box->nobj) {
X	    if (Is_container(box) && box->otyp != BAG_OF_TRICKS) {
X		int cnt=0;
X
X		for(obj=fcobj; obj; obj=obj->nobj) {
X		    if (obj->cobj == box) {
X			if (!cnt) {
X			    Sprintf(buf, "Contents of the %s:",xname(box));
X			    cornline(0, buf);
X			}
X			makeknown(obj->otyp);
X			obj->known = obj->bknown = obj->dknown = 1;
X			cornline(1,doname(obj));
X			cnt++;
X		    }
X		}
X		if (!cnt) pline("The %s is empty.", xname(box));
X		else cornline(2,"");
X	    }
X	}
X}
END_OF_FILE
if test 11591 -ne `wc -c <'src/end.c'`; then
    echo shar: \"'src/end.c'\" unpacked with wrong size!
fi
# end of 'src/end.c'
fi
if test -f 'src/termcap.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/termcap.c'\"
else
echo shar: Extracting \"'src/termcap.c'\" \(11334 characters\)
sed "s/^X//" >'src/termcap.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)termcap.c	3.0	88/11/20
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include <ctype.h>	/* for isdigit() */
X
X/* block some unused #defines to avoid overloading some cpp's */
X#define MONATTK_H
X#include "hack.h"	/* for ROWNO, COLNO, *HI, *HE, *AS, *AE */
X
X#if !defined(SYSV) || defined(TOS) || defined(UNIXPC)
X# ifndef LINT
Xextern			/* it is defined in libtermlib (libtermcap) */
X# endif
X	short ospeed;	/* terminal baudrate; used by tputs */
X#else
Xshort	ospeed = 0;	/* gets around "not defined" error message */
X#endif
X
Xstatic void nocmov();
X#ifdef MSDOSCOLOR
Xstatic void init_hilite();
X#endif /* MSDOSCOLOR */
X
Xstatic char tbuf[512];
Xstatic char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE;
Xstatic char *VS, *VE, *US, *UE;
Xstatic char *MR, *ME;
X#if 0
Xstatic char *MB, *MD, *MH;
X#endif
Xstatic int SG;
Xstatic char PC = '\0';
X
X#if defined(MSDOS) && !defined(TERMLIB)
Xstatic char tgotobuf[20];
X#ifdef TOS
X#define tgoto(fmt, x, y)	(Sprintf(tgotobuf, fmt, y+' ', x+' '), tgotobuf)
X#else
X#define tgoto(fmt, x, y)	(Sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
X#endif
X#endif /* MSDOS /**/
X
Xvoid
Xstartup()
X{
X#ifdef TOS
X	HO = "\033H";
X	CL = "\033E";		/* the VT52 termcap */
X	CE = "\033K";
X	UP = "\033A";
X	CM = "\033Y%c%c";	/* used with function tgoto() */
X	ND = "\033C";
X	XD = "\033B";
X	BC = "\033D";
X	SO = "\033p";
X	SE = "\033q";
X	HI = "\033p";
X	HE = "\033q";
X#else
X	register char *term;
X	register char *tptr;
X	char *tbufptr, *pc;
X	register int i;
X
X	tptr = (char *) alloc(1024);
X
X	tbufptr = tbuf;
X	if(!(term = getenv("TERM")))
X# ifdef ANSI_DEFAULT
X	{
X		HO = "\033[H";
X		CL = "\033[2J";		/* the ANSI termcap */
X/*		CD = "\033[J"; */
X		CE = "\033[K";
X		CM = "\033[%i%d;%dH";
X		UP = "\033[A";
X		ND = "\033[C";
X		XD = "\033[B";
X		BC = "\033[D";
X		HI = SO = "\033[1m";
X		US = "\033[4m";
X		TI = HE = SE = UE = "\033[0m";
X		/* strictly, SE should be 2, and UE should be 24,
X		   but we can't trust all ANSI emulators to be
X		   that complete.  -3. */
X		AS = "\016";
X		AE = "\017";
X		VS = VE = "";
X	} else {
X# else
X		error("Can't get TERM.");
X# endif
X	if(!strncmp(term, "5620", 4))
X		flags.nonull = 1;	/* this should be a termcap flag */
X	if(tgetent(tptr, term) < 1)
X		error("Unknown terminal type: %s.", term);
X	if(pc = tgetstr("pc", &tbufptr))
X		PC = *pc;
X#ifdef TERMINFO
X	if(!(BC = tgetstr("le", &tbufptr))) {	
X#else
X	if(!(BC = tgetstr("bc", &tbufptr))) {	
X#endif
X#if !defined(MINIMAL_TERM) && !defined(HISX)
X		if(!tgetflag("bs"))
X			error("Terminal must backspace.");
X#endif
X		BC = tbufptr;
X		tbufptr += 2;
X		*BC = '\b';
X	}
X#ifdef MINIMAL_TERM
X	HO = NULL;
X#else
X	HO = tgetstr("ho", &tbufptr);
X#endif
X	CO = tgetnum("co");
X	LI = tgetnum("li");
X	if(CO < COLNO || LI < ROWNO+2)
X		setclipped();
X	if(!(CL = tgetstr("cl", &tbufptr)))
X		error("Hack needs CL.");
X	ND = tgetstr("nd", &tbufptr);
X	if(tgetflag("os"))
X		error("Hack can't have OS.");
X	CE = tgetstr("ce", &tbufptr);
X	UP = tgetstr("up", &tbufptr);
X	/* It seems that xd is no longer supported, and we should use
X	   a linefeed instead; unfortunately this requires resetting
X	   CRMOD, and many output routines will have to be modified
X	   slightly. Let's leave that till the next release. */
X	XD = tgetstr("xd", &tbufptr);
X/* not: 		XD = tgetstr("do", &tbufptr); */
X	if(!(CM = tgetstr("cm", &tbufptr))) {
X		if(!UP && !HO)
X			error("Hack needs CM or UP or HO.");
X		Printf("Playing hack on terminals without cm is suspect...\n");
X		getret();
X	}
X	SO = tgetstr("so", &tbufptr);
X	SE = tgetstr("se", &tbufptr);
X	US = tgetstr("us", &tbufptr);
X	UE = tgetstr("ue", &tbufptr);
X	SG = tgetnum("sg");	/* -1: not fnd; else # of spaces left by so */
X	if(!SO || !SE || (SG > 0)) SO = SE = US = UE = "";
X	TI = tgetstr("ti", &tbufptr);
X	TE = tgetstr("te", &tbufptr);
X	VS = VE = "";
X#if 0
X	MB = tgetstr("mb", &tbufptr);	/* blink */
X	MD = tgetstr("md", &tbufptr);	/* boldface */
X	MH = tgetstr("mh", &tbufptr);	/* dim */
X#endif
X	MR = tgetstr("mr", &tbufptr);	/* reverse */
X	ME = tgetstr("me", &tbufptr);
X
X	/* Get rid of padding numbers for HI and HE.  Hope they
X	 * aren't really needed!!!  HI and HE are ouputted to the
X	 * pager as a string - so how can you send it NULLS???
X	 *  -jsb
X	 */
X	    HI = (char *) alloc((unsigned)(strlen(SO)+1));
X	    HE = (char *) alloc((unsigned)(strlen(SE)+1));
X	    i = 0;
X	    while(isdigit(SO[i])) i++;
X	    Strcpy(HI, &SO[i]);
X	    i = 0;
X	    while(isdigit(SE[i])) i++;
X	    Strcpy(HE, &SE[i]);
X	AS = tgetstr("as", &tbufptr);
X	AE = tgetstr("ae", &tbufptr);
X	CD = tgetstr("cd", &tbufptr);
X# ifdef ANSI_DEFAULT
X	}
X# endif
X	set_whole_screen();		/* uses LI and CD */
X	if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
X	free((genericptr_t)tptr);
X#ifdef MSDOSCOLOR
X	init_hilite();
X#endif
X#endif /* TOS /* */
X}
X
Xvoid
Xstart_screen()
X{
X	xputs(TI);
X	xputs(VS);
X#ifdef DECRAINBOW
X	/* Select normal ASCII and line drawing character sets.
X	 */
X	if (flags.DECRainbow) {
X		xputs("\033(B\033)0");
X		if (!AS) {
X			AS = "\016";
X			AE = "\017";
X		}
X	}
X#endif /* DECRAINBOW */
X}
X
Xvoid
Xend_screen()
X{
X	clear_screen();
X	xputs(VE);
X	xputs(TE);
X}
X
X/* Cursor movements */
X
Xvoid
Xcurs(x, y)
Xregister int x, y;	/* not xchar: perhaps xchar is unsigned and
X			   curx-x would be unsigned as well */
X{
X
X	if (y == cury && x == curx)
X		return;
X	if(!ND && (curx != x || x <= 3)) {	/* Extremely primitive */
X		cmov(x, y);			/* bunker!wtm */
X		return;
X	}
X	if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
X		nocmov(x, y);
X	else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
X		(void) putchar('\r');
X		curx = 1;
X		nocmov(x, y);
X	} else if(!CM) {
X		nocmov(x, y);
X	} else
X		cmov(x, y);
X}
X
Xstatic void
Xnocmov(x, y)
X{
X	if (cury > y) {
X		if(UP) {
X			while (cury > y) {	/* Go up. */
X				xputs(UP);
X				cury--;
X			}
X		} else if(CM) {
X			cmov(x, y);
X		} else if(HO) {
X			home();
X			curs(x, y);
X		} /* else impossible("..."); */
X	} else if (cury < y) {
X		if(XD) {
X			while(cury < y) {
X				xputs(XD);
X				cury++;
X			}
X		} else if(CM) {
X			cmov(x, y);
X		} else {
X			while(cury < y) {
X				xputc('\n');
X				curx = 1;
X				cury++;
X			}
X		}
X	}
X	if (curx < x) {		/* Go to the right. */
X		if(!ND) cmov(x, y); else	/* bah */
X			/* should instead print what is there already */
X		while (curx < x) {
X			xputs(ND);
X			curx++;
X		}
X	} else if (curx > x) {
X		while (curx > x) {	/* Go to the left. */
X			xputs(BC);
X			curx--;
X		}
X	}
X}
X
Xvoid
Xcmov(x, y)
Xregister int x, y;
X{
X	xputs(tgoto(CM, x-1, y-1));
X	cury = y;
X	curx = x;
X}
X
Xvoid
Xxputc(c)
Xchar c;
X{
X	(void) fputc(c, stdout);
X}
X
Xvoid
Xxputs(s)
Xchar *s;
X{
X#if defined(MSDOS) && !defined(TERMLIB)
X	(void) fputs(s, stdout);
X#else
X# ifdef __STDC__
X	tputs(s, 1, (int (*)())xputc);
X# else
X	tputs(s, 1, xputc);
X# endif
X#endif
X}
X
Xvoid
Xcl_end() {
X	if(CE)
X		xputs(CE);
X	else {	/* no-CE fix - free after Harold Rynes */
X		/* this looks terrible, especially on a slow terminal
X		   but is better than nothing */
X		register int cx = curx, cy = cury;
X
X		while(curx < COLNO) {
X			xputc(' ');
X			curx++;
X		}
X		curs(cx, cy);
X	}
X}
X
Xvoid
Xclear_screen() {
X	xputs(CL);
X	home();
X}
X
Xvoid
Xhome()
X{
X	if(HO)
X		xputs(HO);
X	else if(CM)
X		xputs(tgoto(CM, 0, 0));
X	else
X		curs(1, 1);	/* using UP ... */
X	curx = cury = 1;
X}
X
Xvoid
Xstandoutbeg()
X{
X	if(SO) xputs(SO);
X}
X
Xvoid
Xstandoutend()
X{
X	if(SE) xputs(SE);
X}
X
Xvoid
Xrevbeg()
X{
X	if(MR) xputs(MR);
X}
X
X#if 0	/* if you need one of these, uncomment it (here and in extern.h) */
Xvoid
Xboldbeg()
X{
X	if(MD) xputs(MD);
X}
X
Xvoid
Xblinkbeg()
X{
X	if(MB) xputs(MB);
X}
X
Xvoid
Xdimbeg()
X/* not in most termcap entries */
X{
X	if(MH) xputs(MH);
X}
X#endif
X
Xvoid
Xm_end()
X{
X	if(ME) xputs(ME);
X}
X
Xvoid
Xbacksp()
X{
X	xputs(BC);
X}
X
Xvoid
Xbell()
X{
X	if (flags.silent) return;
X	(void) putchar('\007');		/* curx does not change */
X	(void) fflush(stdout);
X}
X
Xvoid
Xgraph_on() {
X	if (AS) xputs(AS);
X}
X
Xvoid
Xgraph_off() {
X	if (AE) xputs(AE);
X}
X
X#ifndef MSDOS
Xstatic const short tmspc10[] = {		/* from termcap */
X	0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
X};
X#endif
X
Xvoid
Xdelay_output() {
X	/* delay 50 ms - could also use a 'nap'-system call */
X	/* BUG: if the padding character is visible, as it is on the 5620
X	   then this looks terrible. */
X#ifdef MSDOS
X	/* simulate the delay with "cursor here" */
X	register int i;
X	for (i = 0; i < 3; i++) {
X		cmov(curx, cury);
X		(void) fflush(stdout);
X	}
X#else /* MSDOS /**/
X	if(!flags.nonull)
X#ifdef TERMINFO
X		/* cbosgd!cbcephus!pds for SYS V R2 */
X# ifdef __STDC__
X		tputs("$<50>", 1, (int (*)())xputc);
X# else
X		tputs("$<50>", 1, xputc);
X# endif
X#else
X		tputs("50", 1, xputs);
X#endif
X
X	else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) {
X		/* delay by sending cm(here) an appropriate number of times */
X		register int cmlen = strlen(tgoto(CM, curx-1, cury-1));
X		register int i = 500 + tmspc10[ospeed]/2;
X
X		while(i > 0) {
X			cmov(curx, cury);
X			i -= cmlen*tmspc10[ospeed];
X		}
X	}
X#endif /* MSDOS /**/
X}
X
Xvoid
Xcl_eos()			/* free after Robert Viduya */
X{				/* must only be called with curx = 1 */
X
X	if(CD)
X		xputs(CD);
X	else {
X		register int cx = curx, cy = cury;
X		while(cury <= LI-2) {
X			cl_end();
X			xputc('\n');
X			curx = 1;
X			cury++;
X		}
X		cl_end();
X		curs(cx, cy);
X	}
X}
X
X#ifdef MSDOSCOLOR
X/* Sets up highlighting, using ANSI escape sequences, for monsters,
X * objects, and gold (highlight code found in pri.c).
X * The termcap entry for HI (from SO) is scanned to find the background 
X * color. If everything is OK, monsters are displayed in the color
X * used to define HILITE_MONSTER, objects are displayed in the color
X * used to define HILITE_OBJECT, and gold is displayed in the color
X * used to define HILITE_GOLD. -3. */
X
X#define ESC		0x1b
X#define NONE		0
X#define HIGH_INTENSITY	1
X#define BLACK		0
X#define RED		1
X#define GREEN		2
X#define YELLOW		3
X#define BLUE		4
X#define MAGENTA		5
X#define CYAN		6
X#define WHITE		7
X
X#define HILITE_ATTRIB	HIGH_INTENSITY
X
Xstatic void
Xinit_hilite()
X{
X	int backg = BLACK, foreg = WHITE, len;
X	register int c, color;
X
X	HI_RED = HI_YELLOW = HI_GREEN = HI_BLUE = HI_WHITE = HI;
X
X	/* find the background color, HI[len] == 'm' */
X	len = strlen(HI) - 1;
X
X	if (HI[len] != 'm' || len < 3) return;
X
X	c = 2;
X	while (c < len) {
X	    if ((color = atoi(&HI[c])) == 0) {
X		/* this also catches errors */
X		foreg = WHITE; backg = BLACK;
X	    } else if (color >= 30 && color <= 37) {
X		foreg = color - 30;
X	    } else if (color >= 40 && color <= 47) {
X		backg = color - 40;
X	    }
X	    while (isdigit(HI[++c]));
X	    c++;
X	}
X
X	/* avoid invisibility */
X	if (foreg != RED && backg != RED) {
X	    HI_RED = (char *) alloc(sizeof("E[0;33;44;54m"));
X	    Sprintf(HI_RED, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X		    RED, backg);
X	}
X
X	if (foreg != YELLOW && backg != YELLOW) {
X	    HI_YELLOW = (char *) alloc(sizeof("E[0;33;44;54m"));
X	    Sprintf(HI_YELLOW, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X		    YELLOW, backg);
X	}
X
X	if (foreg != GREEN && backg != GREEN) {
X	    HI_GREEN = (char *) alloc(sizeof("E[0;33;44;54m"));
X	    Sprintf(HI_GREEN, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X		    GREEN, backg);
X	}
X
X	if (foreg != BLUE && backg != BLUE) {
X	    HI_BLUE = (char *) alloc(sizeof("E[0;33;44;54m"));
X	    Sprintf(HI_BLUE, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X		    BLUE, backg);
X	}
X
X	if (foreg != WHITE && backg != WHITE) {
X	    HI_WHITE = (char *) alloc(sizeof("E[0;33;44;54m"));
X	    Sprintf(HI_WHITE, "%c[%d;3%d;4%dm", ESC, HILITE_ATTRIB,
X		    WHITE, backg);
X	}
X}
X
X#endif
END_OF_FILE
if test 11334 -ne `wc -c <'src/termcap.c'`; then
    echo shar: \"'src/termcap.c'\" unpacked with wrong size!
fi
# end of 'src/termcap.c'
fi
if test -f 'src/worm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/worm.c'\"
else
echo shar: Extracting \"'src/worm.c'\" \(4990 characters\)
sed "s/^X//" >'src/worm.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)worm.c	3.0	88/11/11
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#ifdef WORM
X#include "wseg.h"
X
Xstruct wseg *wsegs[32] = DUMMY, *wheads[32] = DUMMY, *m_atseg = 0;
Xlong wgrowtime[32] = DUMMY;
X
Xint
Xgetwn(mtmp)
Xstruct monst *mtmp;
X{
X	register int tmp;
X
X	for(tmp = 1; tmp < 32; tmp++)
X	    if(!wsegs[tmp]) {
X		mtmp->wormno = tmp;
X		return(1);
X	    }
X	return(0);	/* level infested with worms */
X}
X
X/* called to initialize a worm unless cut in half */
Xvoid
Xinitworm(mtmp)
Xstruct monst *mtmp;
X{
X	register struct wseg *wtmp;
X	register int tmp = mtmp->wormno;
X
X	if(!tmp) return;
X	wheads[tmp] = wsegs[tmp] = wtmp = newseg();
X	wgrowtime[tmp] = 0;
X	wtmp->wx = mtmp->mx;
X	wtmp->wy = mtmp->my;
X/*	wtmp->wdispl = 0; */
X	wtmp->nseg = 0;
X}
X
Xstatic void
Xremseg(mtmp,wtmp)
Xstruct monst *mtmp;
Xregister struct wseg *wtmp;
X{
X	if (mtmp->mx != wtmp->wx || mtmp->my != wtmp->wy)
X		levl[wtmp->wx][wtmp->wy].mmask = 0;
X	if(wtmp->wdispl) newsym(wtmp->wx, wtmp->wy);
X	free((genericptr_t) wtmp);
X}
X
Xvoid
Xworm_move(mtmp)
Xstruct monst *mtmp;
X{
X	register struct wseg *wtmp, *whd;
X	register int tmp = mtmp->wormno;
X
X	wtmp = newseg();
X	wtmp->wx = mtmp->mx;
X	wtmp->wy = mtmp->my;
X	wtmp->nseg = 0;
X/*	wtmp->wdispl = 0; */
X	(whd = wheads[tmp])->nseg = wtmp;
X	wheads[tmp] = wtmp;
X	if(cansee(whd->wx,whd->wy)){
X		unpmon(mtmp);
X		atl(whd->wx, whd->wy, S_WORM_TAIL);
X		whd->wdispl = 1;
X	} else	whd->wdispl = 0;
X	if(wgrowtime[tmp] <= moves) {
X		if(!wgrowtime[tmp]) wgrowtime[tmp] = moves + rnd(5);
X		else wgrowtime[tmp] += 2+rnd(15);
X		mtmp->mhp += 3;
X		if (mtmp->mhp > MHPMAX) mtmp->mhp = MHPMAX;
X		if (mtmp->mhp > mtmp->mhpmax) mtmp->mhpmax = mtmp->mhp;
X		return;
X	}
X	whd = wsegs[tmp];
X	wsegs[tmp] = whd->nseg;
X	remseg(mtmp, whd);
X}
X
Xvoid
Xworm_nomove(mtmp)
Xregister struct monst *mtmp;
X{
X	register int tmp;
X	register struct wseg *wtmp;
X
X	tmp = mtmp->wormno;
X	wtmp = wsegs[tmp];
X	if(wtmp == wheads[tmp]) return;
X	if(wtmp == 0 || wtmp->nseg == 0) panic("worm_nomove?");
X	wsegs[tmp] = wtmp->nseg;
X	remseg(mtmp, wtmp);
X	if (mtmp->mhp > 3) mtmp->mhp -= 3;	/* mhpmax not changed ! */
X	else mtmp->mhp = 1;
X}
X
Xvoid
Xwormdead(mtmp)
Xregister struct monst *mtmp;
X{
X	register int tmp = mtmp->wormno;
X	register struct wseg *wtmp, *wtmp2;
X
X	if(!tmp) return;
X	mtmp->wormno = 0;
X	for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
X		wtmp2 = wtmp->nseg;
X		remseg(mtmp, wtmp);
X	}
X	wsegs[tmp] = 0;
X}
X
Xvoid
Xwormhit(mtmp)
Xregister struct monst *mtmp;
X{
X	register int tmp = mtmp->wormno;
X	register struct wseg *wtmp;
X
X	if(!tmp) return;	/* worm without tail */
X	for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
X		if (dist(wtmp->wx, wtmp->wy) < 3) (void) mattacku(mtmp);
X}
X
Xvoid
Xwormsee(tmp)
Xregister unsigned int tmp;
X{
X	register struct wseg *wtmp = wsegs[tmp];
X
X	if(!wtmp) panic("wormsee: wtmp==0");
X
X	for(; wtmp->nseg; wtmp = wtmp->nseg)
X		if(!cansee(wtmp->wx,wtmp->wy) && wtmp->wdispl) {
X			newsym(wtmp->wx, wtmp->wy);
X			wtmp->wdispl = 0;
X		}
X}
X
Xvoid
Xcutworm(mtmp, x, y, weptyp)
Xregister struct monst *mtmp;
Xregister xchar x,y;
Xregister unsigned weptyp;		/* uwep->otyp or 0 */
X{
X	register struct wseg *wtmp, *wtmp2;
X	register struct monst *mtmp2;
X	register int tmp, tmp2;
X
X	if(mtmp->mx == x && mtmp->my == y) return;	/* hit headon */
X
X	/* cutting goes best with axe or sword */
X	tmp = rnd(20);
X	if(weptyp >= SHORT_SWORD && weptyp <= KATANA ||
X	   weptyp == AXE)
X		tmp += 5;
X
X	if(tmp < 12) return;
X
X	/* if tail then worm just loses a tail segment */
X	tmp = mtmp->wormno;
X	wtmp = wsegs[tmp];
X	if(wtmp->wx == x && wtmp->wy == y){
X		wsegs[tmp] = wtmp->nseg;
X		remseg(mtmp, wtmp);
X		return;
X	}
X
X	/* cut the worm in two halves */
X	mtmp2 = newmonst(0);
X	*mtmp2 = *mtmp;
X	mtmp2->mxlth = mtmp2->mnamelth = 0;
X
X	/* sometimes the tail end dies */
X	if(rn2(3) || !getwn(mtmp2)){
X		monfree(mtmp2);
X		levl[mtmp2->mx][mtmp2->my].mmask = 1;
X			/* since mtmp is still on that spot */
X		tmp2 = 0;
X	} else {
X		tmp2 = mtmp2->wormno;
X		wsegs[tmp2] = wsegs[tmp];
X		wgrowtime[tmp2] = 0;
X	}
X	do {
X	    if(wtmp->nseg->wx == x && wtmp->nseg->wy == y){
X		if(tmp2) wheads[tmp2] = wtmp;
X		wsegs[tmp] = wtmp->nseg->nseg;
X		remseg(mtmp, wtmp->nseg);
X		wtmp->nseg = 0;
X		if(tmp2) {
X		    You("cut the worm in half.");
X		/* devalue the monster level of both halves of the worm */
X		    mtmp->m_lev = (mtmp->m_lev <= 2) ? 2 : mtmp->m_lev - 2;
X		    mtmp2->m_lev = mtmp->m_lev;
X		/* calculate the mhp on the new (lower) monster level */
X		    mtmp2->mhpmax = mtmp2->mhp = d((int)mtmp2->m_lev, 8);
X		    mtmp2->mx = wtmp->wx;
X		    mtmp2->my = wtmp->wy;
X		    levl[mtmp2->mx][mtmp2->my].mmask = 1;
X		    mtmp2->nmon = fmon;
X		    fmon = mtmp2;
X		    mtmp2->mdispl = 0;
X		    pmon(mtmp2);
X		} else {
X			You("cut off part of the worm's tail.");
X			remseg(mtmp, wtmp);
X		}
X		mtmp->mhp /= 2;
X		return;
X	    }
X	    wtmp2 = wtmp->nseg;
X	    if(!tmp2) remseg(mtmp, wtmp);
X	    wtmp = wtmp2;
X	} while(wtmp->nseg);
X	panic("Cannot find worm segment");
X}
X
X#endif /* WORM /**/
END_OF_FILE
if test 4990 -ne `wc -c <'src/worm.c'`; then
    echo shar: \"'src/worm.c'\" unpacked with wrong size!
fi
# end of 'src/worm.c'
fi
echo shar: End of archive 28 \(of 38\).
cp /dev/null ark28isdone
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