[net.sources] Hack sources for PDP11/44 and PDP11/45

huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)

#!/bin/sh
#
# 
# 
# This is a shell archive. These archives are packed by the program 
# packmail(1). If you have the program unshar(1), I suggest you use it.
# If you don't remove anything before the cut line and then feed to
# sh(1)
# 
# =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE===
#
echo 'Start of Hack, part 01 of 05:'
echo 'x - hack.debug.c'
sed 's/^X//' > hack.debug.c << '/'
X/*
X * Hack.debug.c
X *
X * Debug function, only exists when DEBUG  if defined
X * Michiel and Fred
X */
X
X#include "hack.h"
X
X#ifdef DEBUG
Xdebug () {
X	nomove ();
X	pline( "You're in the debug function!" );
X}
X#endif DEBUG
/
echo 'x - hack.do.c'
sed 's/^X//' > hack.do.c << '/'
X/*
X * Hack.do.c
X */
X
X#include "hack.h"
X
Xextern char     NOTHIN[], WCLEV[], *nomvmsg;
X
Xchar    WELDED[] = "The %s is welded into your hand!";
X
X#define LETTER(ch)      ((ch >= '@' && ch <= 'Z' ) || \
X						       (ch >= 'a' && ch <= 'z'))
X#define CURSED		1
X#define NOTCURSED       0
X#define MAXLEVEL       40
X
X#define SIZE( x ) 	sizeof( x )/sizeof( x[0] )
X
X/* Routines to do various user commands */
X
Xdoglow (num)
Xregister        num;
X{
X	pline ("Your %s glows %s for a %s.", (flags.dac) ?
X		armors[uarm -> otyp].armnam : weapons[uwep -> otyp].wepnam,
X		(num < 0) ?
X		"black" : "green",
X		(num * num == 1) ?
X		"moment" : "while");
X}
X
Xdoread () {
X	register        OBJECT otmp;
X	register        MONSTER mtmp, mtmp2;
X	register        GOLD_TRAP gtmp;
X	OBJECT otmp2, otmp3;
X	int     num, zx, zy, xtmp, ytmp;
X
X	if (!(otmp = getobj ("?", "read"))) {
X		nomove ();
X		return;
X	}
X	pline ("As you read the scroll, it disappears.");
X
X /* 
X  Sometimes a scroll doesn't do anything
X  */
X	if (!rn2 (20)) {
X		pline ("You can't read the dialect!");
X		useup (otmp);
X		return;
X	}
X
X	switch (otmp -> otyp) {
X
X		case S_ENCH_ARMOR: 
X			if (!uarm) {
X				nothin (otmp);
X				return;
X			}
X			uarm -> cursed = 0;
X			uarm -> spe++;
X			u.uac--;
X			flags.dac = 1;
X			doglow (1);
X			break;
X
X		case S_DROP: 
X/*
X * New scroll instead of scroll of monster confusion. This scroll
X * drops everything you have on you. And put it somewhere on the level
X * Michiel and Fred
X */
X			pline ("Bloody hell, what's going on?");
X			do {
X				xtmp = rn2 (80);
X				ytmp = rn2 (22);
X			} while (levl[xtmp][ytmp].typ != ROOM);
X			useup (otmp);
X			oiden[S_DROP] |= SCRN;
X			doring (uleft, OFF);
X		/* Checked on existence in routine */
X			doring (uright, OFF);
X			for (otmp2 = invent; otmp2; otmp2 = otmp3) {
X				otmp3 = otmp2 -> nobj;
X				if (otmp2 == uarm || otmp2 == uarm2) {
X					u.uac += otmp2 -> spe;
X					flags.dac = 1;
X				}
X				otmp2 -> ox = xtmp;
X				otmp2 -> oy = ytmp;
X				subfrombill (otmp2);
X				otmp -> unpaid = 0;
X				otmp2 -> nobj = fobj;
X				fobj = otmp2;
X			}
X			if (u.ugold) {
X				gtmp = newgen ();
X				gtmp -> gx = xtmp;
X				gtmp -> gy = ytmp;
X				gtmp -> gflag = (unsigned) u.ugold;
X				gtmp -> ngen = fgold;
X				fgold = gtmp;
X				u.ugold = 0L;
X				flags.dgold = 1;
X			}
X			uright = NULL;
X			uleft = NULL;
X			uwep = NULL;
X			invent = NULL;
X			uarm = NULL;
X			uarm2 = NULL;
X			levl[xtmp][ytmp].scrsym = fobj -> olet;
X			levl[xtmp][ytmp].new = 0;
X			return;
X
X		case S_CURSE_LEV: /* Michiel */
X			pline ("Your body begins to glow black.");
X			docurse ();
X			u.uhcursed = 1;
X			break;
X
X		case S_REM_CURSE: 
X			pline ("You feel like someone is helping you.");
X			if (uleft)
X				uleft -> cursed = 0;
X			if (uright)
X				uright -> cursed = 0;
X			if (uarm)
X				uarm -> cursed = 0;
X			if (uarm2)
X				uarm2 -> cursed = 0;
X			if (uwep)
X				uwep -> cursed = 0;
X			break;
X
X		case S_ENCH_WEP: 
X		case S_DAM_WEP: 
X			if (!uwep) {
X				nothin (otmp);
X				return;
X			}
X			num = 5 - otmp -> otyp;/* 4 or 6 */
X			if (!rn2 (6))
X				num <<= 1;
X			uwep -> spe += num;
X			if (num > 0)
X				uwep -> cursed = 0;
X			doglow (num);
X			break;
X
X		case S_CREAT_MON: 
X			makemon (0);
X			mnexto (fmon);
X			break;
X
X		case S_GENOCIDE: 
X			pline ("You have found a scroll of genocide!");
X			do {
X				pline ("What monster do you want to genocide (Type the letter)? ");
X				flags.topl = 0;
X				getlin (buf);
X			} while (strlen (buf) != 1 || !LETTER (*buf) ||
X					 /* a3 */ index (genocided, *buf));
X			strcat (genocided, buf);
X			for (mtmp = fmon; mtmp; mtmp = mtmp2) {
X				mtmp2 = mtmp -> nmon;
X				if (mtmp -> data -> mlet == *buf)
X					cmdel (mtmp);
X			}
X			if (*buf == '@') {
X				killer = "scroll of genocide";
X				u.uhp = 0;
X			}
X			break;
X
X		case S_DESTR_ARMOR: 
X			if (!uarm) {
X				nothin (otmp);
X				return;
X			}
X			pline ("Your armor turns to dust and falls to the floor!");
X			u.uac += uarm -> spe;
X			flags.dac = 1;
X			useup (uarm);
X			uarm = uarm2;
X			uarm2 = 0;
X			break;
X
X		case S_LIGHT: 
X			litroom ();
X			break;
X
X		case S_TELEPORT: 
X/* 
X * Extended by Michiel and Fred:
X * One can jump between levels
X */
X			pline ("The scroll turns into an elevator.");
X			do {
X				pline ("Which stock please? ");
X				getlin (buf);
X				num = atoi (buf);
X			} while (num > MAXLEVEL - 3 && num != dlevel);
X			if (!*buf)
X				break;
X			if (num <= 0)
X				pline ("Don't fool around");
X			else if (num == dlevel)
X				tele ();
X			else if (u.ufloat || u.ustuck || getinventory ("\"")) {
X				nothin (otmp);
X				pline ("The elevator vanishes");
X				return;
X			}
X			else {
X				home ();
X				flush ();
X				keepdogs (1);
X				unCoff (COFF, 1);
X				dosavelev ();
X				if (num > dlevel) {
X					dlevel = (num > maxdlevel) ?
X						maxdlevel : num - 1;
X					while (dlevel < num) {
X						dodown ();
X						levl[u.ux][u.uy].scrsym = '<';
X					}
X				}
X				else {
X					dlevel = num + 1;
X					doup ();
X					levl[u.ux][u.uy].scrsym = '>';
X				}
X				land ();
X				losedogs ();
X				setCon (CON);
X				inshop ();/* a3: zie tele */
X			}
X			pline ("The elevator vanishes");
X			break;
X
X		case S_GOLD_DETEC: 
X			if (!fgold) {
X				nothin (otmp);
X				return;
X			}
X			cls ();
X			for (gtmp = fgold; gtmp; gtmp = gtmp -> ngen)
X				at (gtmp -> gx, gtmp -> gy, '$');
X			prme ();
X			pline ("You feel very greedy, and sense gold!");
X			more ();
X			docrt ();
X			break;
X
X		case S_IDENTIFY: 
X			pline ("This is an identify scroll.");
X			useup (otmp);
X			oiden[S_IDENTIFY] |= SCRN;
X			otmp = getobj (0, "identify");
X			if (otmp) {
X				switch (otmp -> olet) {
X					case '!': 
X						oiden[otmp -> otyp] |= POTN;
X						break;
X					case '?': 
X						oiden[otmp -> otyp] |= SCRN;
X						break;
X					case '/': 
X						oiden[otmp -> otyp] |= WANN;
X					case '[': 
X					case ')': 
X						otmp -> known = 1;
X						break;
X					case '=': 
X						oiden[otmp -> otyp] |= RINN;
X						if (otmp -> otyp >= R_GAIN_STR)
X							otmp -> known = 1;
X						break;
X				}
X				prinv (otmp);
X			}
X			return;
X
X		case S_MAG_MAP: 
X			pline ("On this scroll is a map!");
X			for (zy = 0; zy < 22; zy++)
X				for (zx = 0; zx < 80; zx++) {
X					if ((num = levl[zx][zy].typ) == SDOOR) {
X						levl[zx][zy].typ = DOOR;
X						atl (zx, zy, '+');
X					}
X					else if ((num >= WALL && num <= CORR) &&
X					/* or DOOR; no SDOOR */
X							!levl[zx][zy].seen)
X						newunseen (zx, zy);
X					else if (num >= 30 && num <= 41)
X						newunseen (zx, zy);
X				}
X			newunseen (xupstair, yupstair);
X			if (xdnstair)/* maze */
X				newunseen (xdnstair, ydnstair);
X			break;
X
X		case S_FIRE: 
X			pline ("The scroll erupts in a tower of flame!");
X			if (u.ufireres)
X				pline ("You are uninjured.");
X			else {
X				num = rnd (6);
X				losehp (num, "scroll of fire");
X				u.uhpmax -= num;
X				flags.dhpmax = 1;
X			}
X			break;
X
X		default: 
X			pline ("Bad(%d)scroll", otmp -> otyp);
X			impossible ();
X
X	}
X	if (!(oiden[otmp -> otyp] & SCRN)) {
X		if (otmp -> otyp > S_CREAT_MON && (otmp -> otyp != S_LIGHT
X					|| !u.ublind)) {
X			oiden[otmp -> otyp] |= SCRN;
X			u.urexp += 10;
X		}
X		else if (!scrcall[otmp -> otyp])
X			docall (otmp);
X	}
X	if (u.uhcursed && otmp -> otyp == S_REM_CURSE) {
X		u.uhcursed = 0;
X		pline ("Your body stops glowing black.");
X	}
X	useup (otmp);
X}
X
Xlitroom () {
X	register        zx, zy;
X
X	if (!xdnstair || !dlevel) {
X		pline (NOTHIN);
X		return;
X	}
X	if (levl[u.ux][u.uy].typ == CORR) {
X		if (!u.ublind)
X			pline ("The corridor lights up around you, then fades.");
X		return;
X	}
X	else if (!u.ublind)
X		if (levl[u.ux][u.uy].lit)
X			pline ("The room lights up around you.");
X		else
X			pline ("The room is lit.");
X	if (levl[u.ux][u.uy].lit)
X		return;
X	if (levl[u.ux][u.uy].typ == DOOR) {
X		if (levl[u.ux][u.uy + 1].typ == ROOM)
X			zy = u.uy + 1;
X		else if (levl[u.ux][u.uy - 1].typ == ROOM)
X			zy = u.uy - 1;
X		else
X			zy = u.uy;
X		if (levl[u.ux + 1][u.uy].typ == ROOM)
X			zx = u.ux + 1;
X		else if (levl[u.ux - 1][u.uy].typ == ROOM)
X			zx = u.ux - 1;
X		else
X			zx = u.ux;
X	}
X	else {
X		zx = u.ux;
X		zy = u.uy;
X	}
X	for (seelx = u.ux; levl[seelx - 1][zy].typ % 2; seelx--);
X /* ROOM or WALL or DOOR */
X	for (seehx = u.ux; levl[seehx + 1][zy].typ % 2; seehx++);
X	for (seely = u.uy; levl[zx][seely - 1].typ % 2; seely--);
X	for (seehy = u.uy; levl[zx][seehy + 1].typ % 2; seehy++);
X	for (zy = seely; zy <= seehy; zy++)
X		for (zx = seelx; zx <= seehx; zx++) {
X			levl[zx][zy].lit = 1;
X			if (!u.ublind && dist (zx, zy) > 2)
X				prl (zx, zy);
X		}
X}
X
Xdodrink () {
X	register        OBJECT otmp, objs;
X	register        MONSTER mtmp;
X	register        num;
X
X	if (!(otmp = getobj ("!", "drink"))) {
X		nomove ();
X		return;
X	}
X	switch (otmp -> otyp) {
X
X		case P_REST_STR: 
X			pline ("Wow!  This makes you feel great!");
X			if (u.ustr < u.ustrmax) {
X				u.ustr = u.ustrmax;
X				flags.dstr = 1;
X			}
X			break;
X
X		case P_BOOZE: 
X			pline ("Ooph!  This tastes like liquid fire!");
X			u.uconfused += d (3, 8);
X			if (u.uhp < u.uhpmax)
X				losehp (-1, "");
X			if (!rn2 (4)) {
X				pline ("You pass out.");
X				multi = -rnd (15);
X				nomvmsg = "You awake with a headache.";
X			}
X			break;
X
X		case P_INVIS: 
X			pline ("Gee!  All of a sudden, you can't see yourself.");
X			newsym (u.ux, u.uy);
X			u.uinvis += rn1 (15, 31);
X			break;
X
X		case P_JUICE: 
X			pline ("This tastes like fruit juice.");
X			lesshungry (20);
X			break;
X
X		case P_HEALING: 
X			pline ("You begin to feel better.");
X			num = rnd (10);
X	H: 
X			if (u.uhp + num > u.uhpmax) {
X				u.uhp = ++u.uhpmax;
X				if (otmp -> otyp == P_EXTRA_HEALING)
X					u.uhp = ++u.uhpmax;
X				flags.dhpmax = 1;
X			}
X			else
X				u.uhp += num;
X			flags.dhp = 1;
X			if (u.ublind)
X				u.ublind = 1;
X			break;
X
X		case P_FROZEN: 
X			pline ("Your feet are frozen to the floor!");
X			nomul (-rn1 (10, 25));
X			break;
X
X		case P_MONDETEC: 
X			if (!fmon) {
X				nothin (otmp);
X				return;
X			}
X			cls ();
X			for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon)
X				at (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet);
X			killer = "monster";
X	P: 
X			prme ();
X			pline ("You sense the presence of %ss.", killer);
X			more ();
X			docrt ();
X			break;
X
X		case P_OBJDETEC: 
X			if (!fobj) {
X				nothin (otmp);
X				return;
X			}
X			cls ();
X			for (objs = fobj; objs; objs = objs -> nobj)
X				at (objs -> ox, objs -> oy, objs -> olet);
X			killer = "object";
X			goto P;
X
X		case P_POISON: 
X			pline ("Yech! This stuff tastes like poison.");
X			losestr (rn1 (4, 3));
X			losehp (rnd (10), "poison potion");
X			break;
X
X		case P_CONF: 
X			pline ("Huh, What?  Where am I?");
X			u.uconfused += rn1 (7, 16);
X			break;
X
X		case P_GAIN_STR: 
X			if (u.ustr == 118) {
X				pline ("You've had enough of it!");
X				break;/* Michiel */
X			}
X			pline ("Wow do you feel strong!");
X			if (u.ustr > 17)
X				u.ustr += rnd (118 - u.ustr);
X			else
X				u.ustr++;
X			if (u.ustr > u.ustrmax)
X				u.ustrmax = u.ustr;
X			flags.dstr = 1;
X			break;
X
X		case P_SPEED: 
X			pline ("You are suddenly moving much faster.");
X			u.ufast += rn1 (10, 100);
X			break;
X
X		case P_BLIND: 
X			pline ("A cloud of darkness falls upon you.");
X			u.ublind += rn1 (100, 250);
X			unCoff (COFF, 0);
X			break;
X
X		case P_GAIN_LEV: 
X			num = rnd (10);
X			u.uhpmax += num;
X			u.uhp += num;
X			if (u.ulevel < 14) {/* a3 */
X				pline ("You feel more experienced.");
X				u.uexp = (10 * pow (u.ulevel - 1)) + 1;
X				pline (WCLEV, ++u.ulevel);
X				flags.dulev = 1;
X				flags.dexp = 1;
X			}
X			else
X				pline ("You feel more capable.");
X			flags.dhpmax = 1;
X			flags.dhp = 1;
X			break;
X
X		case P_EXTRA_HEALING: 
X			pline ("You feel much better.");
X			num = d (2, 20) + 1;
X			goto H; /* a3 */
X
X		default: 
X			pline ("Bad(%d)potion", otmp -> otyp);
X			impossible ();
X	}
X
X	if (!(oiden[otmp -> otyp] & POTN)) {
X		if (otmp -> otyp > P_BOOZE) {
X			oiden[otmp -> otyp] |= POTN;
X			u.urexp += 10;
X		}
X		else if (!potcall[otmp -> otyp])
X			docall (otmp);
X	}
X	useup (otmp);
X}
X
Xnothin (obj)
Xregister        OBJECT obj;
X{
X	pline ("You have a strange feeling for a moment, then it passes.");
X	if (obj -> olet == '?') {
X		if ((!(oiden[obj -> otyp] & SCRN)) &&
X				(!scrcall[obj -> otyp]))
X			docall (obj);
X	}
X	else if ((!(oiden[obj -> otyp] & POTN)) &&
X			(!potcall[obj -> otyp]))
X		docall (obj);
X	useup (obj);
X}
X
Xdodrop () {
X	register        OBJECT obj, otmp;
X	register int    num;
X
X	if (!(obj = getobj (0, "drop"))) {
X		nomove ();
X		return;
X	}
X	if (obj -> quan > 1 && !obj -> unpaid) {
X		pline ("How many do you want to drop (%d max) ?",
X				obj -> quan);
X		getlin (buf);
X		num = atoi (buf);
X
X		if (num > obj -> quan || (num <= 0 && *buf) ||
X				*buf == 0) {
X			if (num != 0)
X				pline ("You can't drop that %s!",
X						(num > 0) ? "many" : "few");
X			nomove ();
X			return;
X		}
X		if (num != obj -> quan) {
X			otmp = newobj ();
X			*otmp = *obj;/* Copies whole structure */
X			obj -> quan = num;
X			otmp -> quan -= num;
X			obj -> nobj = otmp;
X		}
X	}
X	if (obj == uarm || obj == uarm2 ||
X			obj == uright || obj == uleft) {
X		pline ("You cannot drop something you are wearing.");
X		nomove ();
X		return;
X	}
X /* (a3) i.p.v. `if( obj==uwep) uwep=0;':  */
X	if (obj == uwep && uwepcursed ())
X		return;
X	dropit (obj);
X	doname (fobj, buf);
X	pline ("You dropped %s.", buf);
X	subfrombill (obj);
X}
X
Xgemsdrop () {
X	register        OBJECT obj;
X	register        counting = 0;
X
X	for (obj = invent; obj;) {
X		if (obj -> olet == '*') {
X			counting += obj -> quan;
X			dropit (obj);
X			subfrombill (obj);
X			obj = invent;
X		}
X		else
X			obj = obj -> nobj;
X	}
X	if (!counting) {
X		nomove ();
X		pline ("You ain't got no gems, Hacker!");
X	}
X	else
X		pline ("You dropped %d gem%s.", counting,
X				counting == 1 ? "" : "s");
X}
X
Xuwepcursed () {			/* a3,drop or throw uwep */
X	if (uwep -> cursed) {
X		multi = 0;	/* Dowield() */
X		pline (WELDED, weapons[uwep -> otyp].wepnam);
X		return CURSED;
X	}
X	uwep = 0;
X	return NOTCURSED;
X}
X
Xgetinventory (string)
Xchar   *string;
X{
X	register        OBJECT otmp;
X
X	for (otmp = invent; otmp && !index (string, otmp -> olet); otmp =
X			otmp -> nobj);
X	return (otmp ? 1 : 0);
X}
X
Xdropit (obj)
Xregister        OBJECT obj;
X{
X	register        OBJECT otmp;
X
X	if (obj == invent)
X		invent = invent -> nobj;
X	else {
X		for (otmp = invent; otmp -> nobj != obj;
X				otmp = otmp -> nobj);
X		otmp -> nobj = obj -> nobj;
X	}
X	obj -> ox = u.ux;
X	obj -> oy = u.uy;
X	obj -> nobj = fobj;
X	fobj = obj;
X	if (u.uinvis)
X		newsym (u.ux, u.uy);
X}
/
echo 'x - hack.h'
sed 's/^X//' > hack.h << '/'
X/*
X * Hack.h
X */
X
X#define NORMAL_IO
X#ifdef NORMAL_IO
X
X#include <stdio.h>
X#define flush()		fflush( stdout )
X
X#else
X
X#undef putchar
X#undef getchar
X#define NULL	0
X#define STDOUT  0		/* Defines print in I/O packet */
X
X#endif NORMAL_IO
X
X#include "envir.h"
X#include "hack.name.h"
X
Xchar   *index ();
X
Xlong    pow ();
X
X#define BUFSZ   256
X
X
X/* Arguments for panic to give just an error message or a core dump */
X#define NOCORE	0
X#define CORE	1
X
X#define ON      1
X#define OFF     0
X
X#define WALL    1
X#define SDOOR   2
X#define DOOR    3
X#define CORR    4
X#define ROOM    5
X#define POOL    7
X#define VAULT   9
X
X#define TRAPNUM 9
X
X#define MSLOW   1
X#define MFAST   2
X
X#define BEAR    0
X#define ARROW   1
X#define DART    2
X#define TDOOR   3
X#define TELE    4
X#define PIT     5
X#define SLPTRP  6
X#define PIERC   7
X#define MIMIC   8
X#define SEEN    32
X
X#define UWEP	0
X#define UARM    1
X#define UARM2   2
X#define ULEFT   3
X#define URIGHT  4
X
X#define POTN    1
X#define SCRN    2
X#define WANN    4
X#define RINN    8
X
X#define UNC     1		/* unCoff(): */
X#define COFF    0
X
X#define SETC    1		/* setCon(): */
X#define CON     0
X
X#define IT1     1
X#define THEIT2  2		/* kluns */
X
X#define CHOKED  0
X#define DIED    1
X#define STARVED 2
X#define DROWNED 3
X#define QUIT    4		/* Michiel args how you died */
X#define ESCAPED 5
X
X#define NOMOVE  0
X#define MOVE    1
X#define DEAD    2
X
X#define MISS    0
X#define HIT     1
X#define KILL    2
X
X
X
Xtypedef struct func_tab {
X	char    f_char;
X	int     (*f_funct) ();
X} FUNCTIONS;
Xextern  FUNCTIONS list[];
X
X
X
Xstruct rm {
X	unsigned        scrsym:	7;
X	unsigned        typ:	6;
X	unsigned        new:	1;
X	unsigned        seen:	1;
X	unsigned        lit:	1;
X};
Xtypedef struct rm       PART;
Xextern  PART levl[80][22];
X
X
X
X
Xstruct mkroom {
X	char    lx, hx, ly, hy, rtype, rlit, doorct, fdoor;
X};
Xtypedef struct mkroom   MKROOM;
Xextern  MKROOM rooms[15];
X
X
X
X#define DOORMAX 100
Xstruct coord {
X	char    x, y;
X};
Xtypedef struct coord    COORDINATES;
Xextern  COORDINATES doors[DOORMAX];
X
X
X
Xstruct food {
X	char   *foodnam, prob, delay;
X	int     nutrition;
X};
Xtypedef struct food    *FOOD;
Xextern struct food      foods[];
X
X
X
Xstruct armor {
X	char   *armnam, prob, delay, a_ac, a_can;
X};
Xtypedef struct armor   *ARMOR;
Xextern struct armor     armors[];
X
X
X
X
X
Xstruct weapon {
X	char   *wepnam, prob, wsdam, wldam;
X};
Xtypedef struct weapon  *WEAPON;
Xextern struct weapon    weapons[];
X
X
X
X
Xstruct permonst {
X	char   *mname, mlet, mhd, mmove, ac, damn, damd;
X	unsigned        pxlth;
X};
Xtypedef struct permonst *MONSTDATA;
Xextern struct permonst  mon[8][7];
X#define PM_MIMIC        &mon[5][2]
X#define PM_PIERC        &mon[2][3]
X#define PM_DEMON        &mon[7][6]
X#define PM_CHAM         &mon[6][6]
X
X
X
X
Xstruct obj {
X	struct obj     *nobj;
X	char    otyp;
X	int     spe;
X	unsigned        ox:	7;
X	unsigned        oy:	5;
X	unsigned        olet:	7;
X	unsigned        quan:	5;
X	unsigned        known:	1;
X	unsigned        cursed: 1;
X	unsigned        unpaid:	1;
X};
Xtypedef struct obj     *OBJECT;
Xextern  OBJECT fobj, invent, uwep, uarm, uarm2, uleft, uright;
X
X
X
Xstruct stole {
X	OBJECT sobj;
X	unsigned        sgold;
X};
Xtypedef struct stole   *STOLE;
X
X
Xstruct monst {
X	struct monst   *nmon;
X	MONSTDATA	data;
X	STOLE		mstole;
X	char    mx, my;
X	int     mhp, orig_hp;
X	unsigned        invis:	1;
X	unsigned        cham:	1;
X	unsigned        angry:	1;	/* Michiel: only for shopkeeper */
X	unsigned        ale:	1;	/* Michiel: is it an ale?? */
X	unsigned        mspeed:	2;
X	unsigned        msleep: 1;
X	unsigned        mfroz:	1;
X	unsigned        mconf:	1;
X	unsigned        mflee:	1;
X	unsigned        mcan:	1;
X	unsigned        mtame:	1;
X	unsigned        wormno: 5;
X	unsigned        mxlth;
X	char    mextra[1];
X};
Xtypedef struct monst   *MONSTER;
Xextern  MONSTER fmon, shopkeeper, vaultkeeper;
Xextern struct permonst  treasurer;
X
XMONSTER m_at ();
X
X
X
Xstruct wseg {
X	struct wseg    *nseg;
X	char    wx, wy;
X};
X
Xtypedef struct wseg    *WORMSEGMENT;
X
X#define newseg()        (alloc( sizeof(struct wseg) )->Wseg)
X
X
Xstruct gen {
X	struct gen     *ngen;
X	char    	gx, gy;
X	unsigned        gflag;
X};
Xtypedef struct gen     *GOLD_TRAP;
Xextern  GOLD_TRAP fgold, ftrap;
X
XGOLD_TRAP g_at ();
XOBJECT o_at (), getobj ();
X
X
Xstruct flag {
X	unsigned        topl:		1;
X	unsigned        botl:		1;
X /* faint:1, screen:1, */
X	unsigned        oneline:	1;
X	unsigned        next:		1;
X	unsigned        move:		1;
X	unsigned        mv:		1;
X	unsigned        run:		2;
X	unsigned        dgold:		1;
X	unsigned        dhp:		1;
X	unsigned        dhpmax:		1;
X	unsigned        dstr:		1;
X	unsigned        dac:		1;
X	unsigned        dulev:		1;
X	unsigned        dexp:		1;
X	unsigned        dhs:		1;
X	unsigned        dscr:		1;
X};
Xtypedef struct flag     FLAG;
Xextern  FLAG flags;
X
Xstruct you {
X	char    ux, uy, ustr, ustrmax, udaminc, uac;
X	int     uhunger;
X	unsigned        ufast:		7;
X	unsigned        uconfused:	6;
X	unsigned        uinvis:		6;
X	unsigned        ulevel:		5;
X	unsigned        utrap:		3;
X	unsigned        upit:		1;
X	unsigned        uinshop:	1;
X	unsigned        uinzoo:		1;
X	unsigned        uinyard:	1;
X	unsigned        uinswamp:	1;
X	unsigned        uinknox:	1;
X	unsigned        umconf:		1;
X	unsigned        uhcursed:	1;
X	unsigned        ufireres:	1;
X	unsigned        ucoldres:	1;
X	unsigned        utel:		1;
X	unsigned        upres:		1;
X	unsigned        ustelth:	1;
X	unsigned        uagmon:		1;
X	unsigned        ufeed:		1;
X	unsigned        usearch:	1;
X	unsigned        ucinvis:	1;
X	unsigned        uregen:		1;
X	unsigned        ufloat:		1;
X	unsigned        uswallow:	1;
X	unsigned        uswldtim:	4;
X	unsigned        ucham:		1;
X	unsigned        uhs:		2;
X	unsigned        ublind;
X	short   uhp, uhpmax;
X	long    ugold, uexp, urexp;
X	MONSTER ustuck;
X};
Xtypedef struct you      YOU;
Xextern  YOU u;
X
X
X
Xextern char    *wepnam[], *pottyp[], *scrtyp[], *traps[],
X               *wantyp[], *ringtyp[], *potcol[], *scrnam[],
X               *wannam[], *rinnam[], wdam[], oiden[],
X               *potcall[], *scrcall[], *wandcall[], *ringcall[],
X                curx, cury, savx,
X                xdnstair, ydnstair, xupstair, yupstair,
X                seehx, seelx, seehy, seely,
X               *save_cm, *killer, dlevel, maxdlevel,
X                dx, dy, buf[], lock[],
X                genocided[60], oldux, olduy, wizard;
X
Xextern unsigned moves;
X
Xextern  multi;
X
X#define newmonst(xl)    (alloc( xl + sizeof(struct monst) )->Mtmp )
X#define newobj()        (alloc( sizeof(struct obj) )->Otmp )
X#define newgen()        (alloc( sizeof(struct gen) )->Gtmp )
X#define newstole()      (alloc( sizeof(struct stole) )->Stmp )
X
X
X#define CHAR_NULL	(char *)NULL
X#define OBJ_NULL	(struct obj *)NULL
X#define TRAP_NULL	(struct gen *)NULL
X#define MON_NULL	(struct monst *)NULL
X#define STOLE_NULL	(struct stole *)NULL
X
X#ifndef SHOW
Xunion PTRS {
X	GOLD_TRAP Gtmp;
X	MONSTER Mtmp;
X	OBJECT Otmp;
X	STOLE Stmp;
X	WORMSEGMENT Wseg;
X	char   *Val;
X};
X
Xextern  union PTRS * alloc ();
X#endif SHOW
/
echo 'x - hack.mon.do.c'
sed 's/^X//' > hack.mon.do.c << '/'
X/*
X * Hack.mon.do.c
X */
X
X/* Contains monster control routines */
X
X#include "hack.h"
X
Xextern  MONSTER bhit ();
X
Xmovemon () {
X	register        MONSTER mtmp, mtmp2;
X
X	for (mtmp = fmon; mtmp; mtmp = mtmp2) {
X		mtmp2 = mtmp -> nmon;
X		if (mtmp -> mspeed != MSLOW || moves % 2 == 0)
X			if (dochug (mtmp))
X				continue;/* Monster died */
X		if (mtmp -> mspeed == MFAST)
X			if (dochug (mtmp))
X				continue;
X
X/* If we left the room: make monsters invis, even if they didn't move */
X
X		if (!cansee (mtmp -> mx, mtmp -> my))
X			levlsym (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet);
X		if (mtmp -> wormno && mtmp -> data -> mlet == 'w')
X			wormsee (mtmp -> wormno);
X	}
X}
X
Xjustswld (mtmp)
Xregister        MONSTER mtmp;
X{
X	newsym (mtmp -> mx, mtmp -> my);
X	mtmp -> mx = u.ux;
X	mtmp -> my = u.uy;
X	u.ustuck = mtmp;
X	at (u.ux, u.uy, mtmp -> data -> mlet);
X	pseebl ("%s swallows you!", mtmp -> data -> mname);
X	more ();
X	u.uswallow = 1;
X	docrt ();
X}
X
Xyouswld (mtmp, dam, die)
Xregister        MONSTER mtmp;
Xregister        dam, die;
X{
X	pseebl ("%s digests you!", killer = mtmp -> data -> mname);
X	if (dam > 0) {
X		u.uhp -= dam;
X		flags.dhp = 1;
X	}
X	if (u.uswldtim++ == die) {
X		pline ("It totally digests you!");
X		u.uhp = 0;
X	}
X}
X
Xx2hitu (mlev, x, name)
Xregister        mlev, x;
Xregister char  *name;		/* a3 */
X{
X	register        i;
X
X	for (i = 0; i < 2; i++)
X		hitu (mlev, (x < 0) ? d (2, x) : (x == 0) ? d (3, 4) :
X				rnd (x), name);
X}
X
Xdochug (mtmp)
Xregister        MONSTER mtmp;
X{
X	register        MONSTDATA mdat;
X	register        tmp = 0, ctmp;
X
X	if (mtmp -> mhp <= 0 && !mtmp -> mtame)
X		return 1;	/* Killed by dog or ? */
X	if (mtmp -> cham && !rn2 (6))
X		newcham (mtmp, &mon[rn1 (6, 2)][rn2 (7)]);
X	mdat = mtmp -> data;
X /* 
X  if( mdat->mhd < 0 )
X  panic( CORE, "Bad(%d)monster %c", mdat->mhd,
X  mdat->mlet );
X  */
X	if ((moves % 20 == 0 || index ("ViT", mdat -> mlet)) &&
X			mtmp -> mhp < mtmp -> orig_hp)
X		mtmp -> mhp++;	/* Regenerate monsters */
X	if (mtmp -> mfroz)
X		return 0;	/* Frozen monsters don't do anything */
X	if (mtmp -> msleep) {
X	/* Wake up a monster, or get out of here */
X		if (cansee (mtmp -> mx, mtmp -> my) && !u.ustelth &&
X				(!rn2 (7) || u.uagmon))
X			mtmp -> msleep = 0;
X		else
X			return 0;
X	}
X
X/* Confused monsters get unconfused with small probability */
X
X	if (mtmp -> mconf && !rn2 (50))
X		mtmp -> mconf = 0;
X	if (mdat -> mmove >= rnd (12) && (mtmp -> mflee || mtmp -> mconf ||
X				dist (mtmp -> mx, mtmp -> my) > 2 || mtmp -> mtame ||
X				mtmp == shopkeeper) && (tmp = m_move (mtmp, 0)) &&
X			mdat -> mmove <= 12)
X		return (tmp == 2);
X /* Move monsters and exit if rate<=12 */
X	if (tmp == 2)
X		return 1;	/* Monster died moving */
X
X	if (!index ("Ea", mdat -> mlet) && dist (mtmp -> mx, mtmp -> my) < 3
X			&& !mtmp -> mtame && mtmp != shopkeeper && u.uhp > 0) {
X		nomul (tmp = 0);
X		if (u.uswallow) {
X			if (mtmp != u.ustuck)
X				if (mdat -> mmove - 12 > rnd (12))
X					tmp = m_move (mtmp, 1);
X		}
X		else if (!index ("&DyF", mdat -> mlet)) {
X			if (mtmp -> ale && cansee (mtmp -> mx, mtmp -> my)) {
X				mtmp -> invis = 0;
X				pmon (mtmp);
X			}
X			tmp = hitu (mdat -> mhd, d (mdat -> damn, mdat -> damd),
X					mdat -> mname);
X		}
X
X/* Increase chance of hitting (no damage) for L and R */
X		if (index ("LR", mdat -> mlet) && hitu (5, 0, mdat -> mname))
X			tmp++;
X
X		ctmp = (tmp && !mtmp -> mcan && (!uarm ||
X					armors[uarm -> otyp].a_can < rnd (3)));
X
X		switch (mdat -> mlet) {
X
X			case ';': 
X				if (mtmp -> mcan)
X					break;
X				if (!u.ustuck && !rn2 (20)) {
X					p2xthe ("%s swings itself around you!",
X							mdat -> mname);
X					u.ustuck = mtmp;
X				}
X				else if (u.ustuck == mtmp && ctmp) {
X					p2xthe ("%s drowns you...", mdat -> mname);
X					more ();
X					done (DROWNED);
X				}
X				break;
X
X			case '&': 
X				if (!mtmp -> mcan && !rn2 (15)) {
X					makemon (PM_DEMON);
X					mnexto (fmon);
X				}
X				else {
X					x2hitu (10, -6, mdat -> mname);
X					x2hitu (10, 3, mdat -> mname);
X					hitu (10, rn1 (4, 2), mdat -> mname);
X				}
X				break;
X
X			case ',': 
X			case '\'': 
X				if (u.uswallow)
X					if (mdat -> mlet == ',')
X						youswld (mtmp, 4 + u.uac, 5);
X					else
X						youswld (mtmp, rnd (6), 7);
X				else if (tmp)
X					justswld (mtmp);
X				break;
X
X			case 'A': 
X				if (ctmp && rn2 (2)) {
X					pline ("You feel weaker!");
X					losestr (1);
X				}
X				break;
X
X			case 'C': 
X			case 'Y': 
X				hitu (4, rnd (6), mdat -> mname);
X				break;
X
X			case 'c': 
X				if (ctmp && !rn2 (5)) {
X					pline ("You get turned to stone!");
X					u.uhp = 0;
X				}
X				break;
X
X			case 'D': 
X				if (rn2 (6) || mtmp -> mcan) {
X					hitu (10, d (3, 10), mdat -> mname);
X					x2hitu (10, 8, mdat -> mname);
X					break;
X				}
X				pseebl ("%s breathes fire!", mdat -> mname);
X				buzz (Z_FIRE, mtmp -> mx, mtmp -> my,
X						u.ux - mtmp -> mx,
X						u.uy - mtmp -> my);
X				break;
X
X			case 'd': 
X				hitu (6, d (2, 4), mdat -> mname);
X				break;
X
X			case 'e': 
X				hitu (10, d (3, 6), mdat -> mname);
X				break;
X
X			case 'F': 
X				if (mtmp -> mcan)
X					break;
X				pseebl ("%s explodes!", mdat -> mname);
X				if (u.ucoldres)
X					pline ("You don't seem affected by it.");
X				else {
X					if (17 - (u.ulevel >> 1) > rnd (20)) {
X						pline ("You get blasted!");
X						tmp = 6;
X					}
X					else {
X						pline ("You duck the blast...");
X						tmp = 3;
X					}
X					losehp (d (tmp, 6), mdat -> mname);
X				}
X				cmdel (mtmp);
X				return 1;
X
X			case 'g': 
X				if (!ctmp || multi < 0 || rn2 (6))
X					break;
X				pseebl ("You are frozen by %ss juices", "cube'");
X				nomul (-rnd (10));
X				break;
X
X			case 'h': 
X				if (!ctmp || multi < 0 || rn2 (5))
X					break;
X				pseebl ("You are put to sleep by %ss bite!",
X						"homunculus'");
X				nomul (-rnd (10));
X				break;
X
X			case 'j': 
X				tmp = hitu (4, rnd (3), mdat -> mname);
X				tmp &= hitu (4, rnd (3), mdat -> mname);
X				if (tmp)
X					x2hitu (4, 4, mdat -> mname);
X				break;
X
X			case 'k': 
X				if ((hitu (4, rnd (4), mdat -> mname) || !rn2 (3))
X						&& ctmp)
X					poisoned ("bee's sting", mdat -> mname);
X				break;
X
X			case 'L': 
X				if (ctmp && u.ugold && rn2 (2)) {
X					u.ugold -= (ctmp = somegold ());
X					pline ("Your purse feels lighter.");
X					flags.dgold = 1;
X
X				/* Michiel save stolen gold */
X					if (mtmp -> mstole)
X						mtmp -> mstole -> sgold += ctmp;
X					else {
X						mtmp -> mstole = newstole ();
X						mtmp -> mstole -> sobj = 0;
X						mtmp -> mstole -> sgold = ctmp;
X					}
X					mtmp -> mflee = 1;
X					rloc (mtmp);
X				}
X				break;
X
X			case 'N': 
X				if (ctmp && invent && rn2 (2)) {
X					steal (mtmp);
X					rloc (mtmp);
X					mtmp -> mflee = 1;
X				}
X				break;
X
X			case 'n': 
X				x2hitu (11, -6, mdat -> mname);
X				break;
X
X			case 'o': 
X				hitu (5, rnd (6), mdat -> mname);
X				/*  tmp= ??  */
X				if (hitu (5, rnd (6), mdat -> mname) && ctmp &&
X						!u.ustuck && rn2 (2)) {
X					u.ustuck = mtmp;
X					pseebl ("%s has grabbed you!",
X							mdat -> mname);
X					u.uhp -= d (2, 8);
X					break;
X				}
X				if (u.ustuck == mtmp) {
X					pline ("You are being crushed.");
X					u.uhp -= d (2, 8);
X				}
X				break;
X
X			case 'P': 
X				if (u.uswallow)
X					youswld (mtmp, d (2, 4), 12);
X				else if (ctmp && !rn2 (4))
X					justswld (mtmp);
X				else
X					hitu (15, d (2, 4), mdat -> mname);
X				break;
X
X			case 'Q': 
X				x2hitu (3, 2, mdat -> mname);
X				break;
X
X			case 'R': 
X				if (ctmp && uarm && uarm -> otyp < A_STD_LEATHER
X						&& uarm -> spe > -2) {
X					pline ("Your armor rusts!");
X					--uarm -> spe;
X					u.uac++;
X					flags.dac = 1;
X				}
X				break;
X
X			case 'S': 
X				if (ctmp && !rn2 (8))
X					poisoned ("snake's bite", mdat -> mname);
X				break;
X
X			case 's': 
X				if (tmp && !rn2 (8))
X					poisoned ("scorpion's sting",
X							mdat -> mname);
X				x2hitu (5, 8, mdat -> mname);
X				break;
X
X			case 'T': 
X				x2hitu (6, 6, mdat -> mname);
X				break;
X
X			case 'U': 
X				x2hitu (9, 0, mdat -> mname);/* 0: d(3,4) */
X				break;
X
X			case 'v': 
X				if (ctmp && !u.ustuck)
X					u.ustuck = mtmp;
X				break;
X
X			case 'V': 
X				if (tmp)
X					u.uhp -= 4;
X				if (rn2 (3))
X					break;
X		V: 
X				if (ctmp) {/* hit by V or W */
X					if (u.ulevel > 1)
X						pline ("Goodbye level %d.",
X								u.ulevel--);
X					else
X						u.uhp = 0;
X					ctmp = rnd (10);
X					u.uhp -= ctmp;
X					u.uhpmax -= ctmp;
X					u.uexp = 10L * pow (u.ulevel - 1) - 1L;
X					flags.dhp = 1;
X					flags.dhpmax = 1;
X					flags.dulev = 1;
X					flags.dexp = 1;
X				}
X				break;
X
X			case 'W': 
X				if (rn2 (5))
X					break;
X				goto V;
X			case 'w': 
X				if (tmp)
X					wormhit (mtmp);
X				break;
X			case 'X': 
X				for (tmp = 0; tmp < 3; tmp++)
X					hitu (8, rnd (3), mdat -> mname);
X				break;
X
X			case 'y': 
X				if (mtmp -> mcan)
X					break;
X				cmdel (mtmp);
X				if (!u.ublind) {
X					pline ("You are blinded by a blast of light!");
X					u.ublind = d (4, 12);
X					unCoff (COFF, 0);
X				}
X				return 1;
X		}		/* switch */
X
X		if (u.uhp <= 0)
X			killer = mdat -> mname;
X	}
X	else if (mtmp -> ale && cansee (mtmp -> mx, mtmp -> my)) {
X		mtmp -> invis = 1;
X		newsym (mtmp -> mx, mtmp -> my);
X	}
X/* Extra movement for fast monsters */
X	if (mdat -> mmove - 12 > rnd (12))
X		tmp = m_move (mtmp, 1);
X	return (tmp == 2);
X}
X
Xcmdel (mtmp)
Xregister        MONSTER mtmp;
X{
X	register char   mx = mtmp -> mx, my = mtmp -> my;
X
X	delmon (mtmp);
X	if (cansee (mx, my))
X		newsym (mx, my);
X}
X
Xinrange (mtmp)
Xregister        MONSTER mtmp;
X{
X	int     zx, zy;
X	register char   tx = u.ux - mtmp -> mx, ty = u.uy - mtmp -> my;
X
X/* This mess figures out if the person is within 8 */
X	if ((!tx && abs (ty) < 8) || (!ty && abs (tx) < 8) ||
X			(abs (tx) == abs (ty) && abs (tx) < 8)) {
X		if (tx == 0)
X			zx = 0;
X		else
X			zx = tx / abs (tx);
X		if (ty == 0)
X			zy = 0;
X		else
X			zy = ty / abs (ty);
X/* If we don't save dx and dy a capital move may screw up: */
X		tx = dx;
X		ty = dy;
X		if (bhit (zx, zy, 8) == mtmp)
X			buzz (Z_FIRE, mtmp -> mx, mtmp -> my, dx, dy);
X		dx = zx;
X		dy = zy;
X	}
X}
X
Xm_move (mtmp, after)
Xregister        MONSTER mtmp;
X{
X	register        MONSTER mtmp2;
X	register        nix, niy, omx, omy, appr, nearer, cnt, zx, zy;
X	char    ddx, ddy, mmoved = 0;
X
X/* My dog gets a special treatment */
X	if (mtmp -> mtame)
X		return dog_move (mtmp, after);
X
X	if (u.uswallow)
X		return (1);	/* a3 */
X/* Likewise for shopkeeper */
X	if (mtmp == shopkeeper)
X		return shk_move ();
X	if (mtmp == vaultkeeper && !mtmp -> angry)
X		return (0);
X
X	if (mtmp -> data -> mlet == 't' && !rn2 (19)) {
X		if (rn2 (2)) {
X			ddx = mtmp -> mx;
X			ddy = mtmp -> my;
X			mnexto (mtmp);/* Doesn't change old position */
X			levlsym (ddx, ddy, 't');
X		}
X		else
X			rloc (mtmp);/* Rloc does */
X		return 1;
X	}
X	if (!mtmp -> mcan)
X		switch (mtmp -> data -> mlet) {
X			case 'D': 
X				inrange (mtmp);
X				break;
X			case 'U': 
X				if (!rn2 (10) && !u.uconfused &&
X						cansee (mtmp -> mx, mtmp -> my)) {
X					pline ("You are confused!");
X					u.uconfused = d (3, 4);
X				}
X				if (!mtmp -> mflee && u.uswallow &&
X						u.ustuck != mtmp)
X					return 1;
X		}
X	appr = 1;
X	if (mtmp -> mflee)
X		appr = -1;
X	if (mtmp -> mconf || u.uinvis || (index ("BI", mtmp -> data -> mlet) &&
X				!rn2 (3)))
X		appr = 0;
X	omx = mtmp -> mx;
X	omy = mtmp -> my;
X	nix = omx;
X	niy = omy;
X	cnt = 0;
X	for (ddx = -1; ddx <= 1; ddx++)
X		for (ddy = -1; ddy <= 1; ddy++)
X			if (r_free (zx = omx + ddx, zy = omy + ddy, mtmp)
X					&& (ddx || ddy)
X					&& !(ddx && ddy && (levl[omx][omy].typ == DOOR ||
X							levl[zx][zy].typ == DOOR))) {
X				if (!mtmp -> mconf && m_at (zx, zy))
X					continue;
X				nearer = (dist (zx, zy) < dist (nix, niy));
X				if ((appr > 0 && nearer) || (appr < 0 &&
X							!nearer) ||
X						(!mmoved && mtmp -> wormno) ||
X						(!appr && !rn2 (++cnt))) {
X					nix = zx;
X					niy = zy;
X					mmoved++;
X				}
X			}
X	if (mmoved) {
X		if (mtmp -> mconf && (mtmp2 = m_at (nix, niy))) {
X			if (hitmm (mtmp, mtmp2) == 1 && rn2 (4) &&
X					hitmm (mtmp2, mtmp) == 2)
X				return 2;
X			return 0;
X		}
X		if (!mtmp -> ale) {
X			mtmp -> mx = nix;
X			mtmp -> my = niy;
X		}
X		else if (levl[nix][niy].typ == POOL) {
X			mtmp -> mx = nix;
X			mtmp -> my = niy;
X		}
X
X		if (mtmp -> wormno && mtmp -> data -> mlet == 'w')
X			worm_move (mtmp);
X	}
X	else {
X		if (!rn2 (10) && index ("tNL", mtmp -> data -> mlet)) {
X			rloc (mtmp);
X			return 0;
X		}
X		if (mtmp -> wormno)
X			worm_nomove (mtmp);
X	}
X	if (mmoved || !cansee (omx, omy))
X		levlsym (omx, omy, mtmp -> data -> mlet);
X	pmon (mtmp);
X	return (mmoved);
X}
/
echo 'x - mklev.make.c'
sed 's/^X//' > mklev.make.c << '/'
X/*
X * Mklev.make.c
X */
X
X#define ZOO		1
X#define GRAVEYARD	2
X#define SWAMP		3
X#define FORT_KNOX	4
X#define MAZE		6
X
X#define NORMAL_IO
X#include "hack.h"
X
Xextern char     mmon[8][8];
X
X#define MAZX ((rnd(37) << 1) + 1)
X#define MAZY ((rnd(8) << 1) + 1)
X
X#define somex() rn1( croom->hx - croom->lx + 1, croom->lx )
X#define somey() rn1( croom->hy - croom->ly + 1, croom->ly )
X
Xextern  PART levl[80][22];
X
Xextern  MONSTER fmon;
Xextern  OBJECT fobj;
Xextern  GOLD_TRAP fgold, ftrap;
X
Xextern  MKROOM rooms[15], *croom;
X
Xextern  COORDINATES doors[DOORMAX];
X
Xextern int      doorindex, nroom, comp ();
X
Xextern char     dlevel, *geno, goldseen,
X                xdnstair, xupstair, ydnstair, yupstair,
X                wizard, nxcor, x, y,
X                dx, dy, tx, ty;
X /* For corridors and other things... */
X
Xmakemaz () {
X
X/* This is all Kenny's fault.  He seems to have his x and y reversed */
X
X	int     xx, yy, a, q, sp, dir, dirs[5], stack[200];
X	register int    zx, zy;
X	register        OBJECT otmp;
X
X	for (xx = 2; xx < 19; xx++)
X		for (yy = 2; yy < 77; yy++) {
X			if (xx % 2 == 0 || yy % 2 == 0)
X				levl[yy][xx].typ++;/* WALL==1 */
X		}
X	zx = MAZY;
X	zy = MAZX;
X	sp = 1;
X	stack[1] = 100 * zx + zy;
X	while (sp) {
X		xx = stack[sp] / 100;
X		yy = stack[sp] % 100;
X		levl[yy][xx].typ = 2;
X		q = 0;
X		for (a = 0; a < 4; a++)
X			if (okay (xx, yy, a))
X				dirs[q++] = a;
X		if (q) {
X			dir = dirs[rn2 (q)];
X			move (&xx, &yy, dir);
X			levl[yy][xx].typ = 0;
X			move (&xx, &yy, dir);
X			stack[++sp] = 100 * xx + yy;
X		}
X		else
X			sp--;
X	}
X	for (xx = 2; xx < 77; xx++)
X		for (yy = 2; yy < 19; yy++) {/* This was mine */
X			if (levl[xx][yy].typ == WALL)
X				levl[xx][yy].scrsym = '-';
X			else {
X				levl[xx][yy].typ = ROOM;
X				levl[xx][yy].scrsym = '.';
X			}
X		}
X	for (xx = rn1 (8, 11); xx; xx--) {
X		mkobj (0);
X		levl[(fobj -> ox = MAZX)][(fobj -> oy = MAZY)].scrsym = fobj -> olet;
X	}
X	for (xx = rn1 (5, 7); xx; xx--)
X		makemon (1, MAZX, MAZY);
X	for (xx = rn1 (6, 7); xx; xx--)
X		mkgold (0, MAZX, MAZY);
X	for (xx = rn1 (6, 7); xx; xx--)
X		mktrap (0, 1);
X	levl[(xupstair = MAZX)][(yupstair = MAZY)].scrsym = '<';
X	levl[zy][zx].scrsym = '"';
X	otmp = newobj ();
X	otmp -> nobj = fobj;
X	fobj = otmp;
X	otmp -> ox = zy;
X	otmp -> oy = zx;
X	otmp -> olet = '"';
X	xdnstair = 0;
X	ydnstair = 0;
X}
X
X/* Make a trap somewhere (in croom if mazeflag=0) */
Xmktrap (num, mazeflag)
Xregister int    num, mazeflag;
X{
X	register        GOLD_TRAP gtmp;
X	register int    nopierc;
X	int     nomimic, fakedoor, fakegold, tryct = 0;
X
X	gtmp = newgen ();
X	if (!num || num >= TRAPNUM) {
X		nopierc = (dlevel < 4);
X		nomimic = (dlevel < 9 || goldseen);
X		gtmp -> gflag = rn2 (TRAPNUM - nopierc - nomimic);
X/* Note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */
X	}
X	else
X		gtmp -> gflag = num;
X	fakedoor = (gtmp -> gflag == MIMIC && rn2 (2) && !mazeflag);
X	fakegold = (gtmp -> gflag == MIMIC && !fakedoor);
X	do {
X		if (++tryct > 200) {
X			printf ("tryct overflow7\n");
X			free (gtmp);
X			return;
X		}
X		if (mazeflag) {
X			gtmp -> gx = MAZX;
X			gtmp -> gy = MAZY;
X		}
X		else if (!fakedoor) {
X			gtmp -> gx = somex ();
X			gtmp -> gy = somey ();
X		}
X		else {
X			if (rn2 (2)) {
X				if (rn2 (2))
X					gtmp -> gx = croom -> hx + 1;
X				else
X					gtmp -> gx = croom -> lx - 1;
X				gtmp -> gy = somey ();
X			}
X			else {
X				if (rn2 (2))
X					gtmp -> gy = croom -> hy + 1;
X				else
X					gtmp -> gy = croom -> ly - 1;
X				gtmp -> gx = somex ();
X			}
X		}
X	} while (g_at (gtmp -> gx, gtmp -> gy, (fakegold) ? fgold : ftrap));
X	if (!fakegold) {
X		gtmp -> ngen = ftrap;
X		ftrap = gtmp;
X	}
X	else {
X		gtmp -> gflag = 0;
X		gtmp -> ngen = fgold;
X		fgold = gtmp;
X		goldseen++;
X	}
X	if (mazeflag && !rn2 (10) && gtmp -> gflag < PIERC)
X		gtmp -> gflag |= SEEN;
X	if (fakedoor)
X		num = '+';
X	else if (fakegold)
X		num = '$';
X	else
X		return;
X	levl[gtmp -> gx][gtmp -> gy].scrsym = num;
X}
X
Xmkgold (num, goldx, goldy)
Xregister int    num;
X{
X	register        GOLD_TRAP gtmp;
X
X	gtmp = newgen ();
X	gtmp -> ngen = fgold;
X	levl[gtmp -> gx = goldx][gtmp -> gy = goldy].scrsym = '$';
X	gtmp -> gflag = (num) ? num : 1 + rnd (dlevel + 2) * rnd (30);
X	fgold = gtmp;
X}
X
X/*VARARGS*/
Xpanic (str, arg1, arg2)
Xregister char  *str;
X{
X	fprintf (stderr, "\nMKLEV ERROR: ");
X	fprintf (stderr, str, arg1, arg2);
X	abort ();
X}
X
Xmakemon (sl, monx, mony)
Xregister int    sl, monx, mony;
X{
X	register        MONSTER mtmp;
X	register int    tryct = 0;
X
X	mtmp = newmonst (0);
X	mtmp -> mstole = STOLE_NULL;
X	mtmp -> msleep = sl;
X	mtmp -> mx = monx;
X	mtmp -> my = mony;
X	mtmp -> mfroz = 0;
X	mtmp -> mconf = 0;
X	mtmp -> mflee = 0;
X	mtmp -> mspeed = 0;
X	mtmp -> mtame = 0;
X	mtmp -> angry = 0;
X	mtmp -> mxlth = 0;
X	mtmp -> wormno = 0;
X	mtmp -> ale = 0;
X	if (levl[monx][mony].typ == POOL) {
X		mtmp -> ale = 1;
X		mtmp -> invis = 1;
X	}
X	else {
X		do {
X			if (++tryct > 100) {
X				printf ("tryct overflow8\n");
X				free (mtmp);
X				return;
X			}
X			mtmp -> mhp = rn2 (dlevel / 3 + 1) % 8;
X			mtmp -> orig_hp = rn2 (7);
X		} while (index (geno, mmon[mtmp -> mhp][mtmp -> orig_hp]));
X	}
X	mtmp -> nmon = fmon;
X	fmon = mtmp;
X}
X
X
Xchar    shtypes[] = "=/)%?![";	/* 8 shoptypes: 7 specialised, 1 mixed */
Xchar    shprobs[] = {
X	3, 3, 5, 5, 10, 10, 14, 50
X};				/* Their probabilities */
X
Xmkshop () {
X	register        MKROOM * sroom;
X	register int    sh, sx, sy, i;
X	register char   let;
X
X	for (sroom = &rooms[0];; sroom++) {
X		if (sroom -> hx < 0)
X			return;
X		if (ch_upstairs (sroom) || ch_dnstairs (sroom))
X			continue;
X		if (sroom -> doorct == 1)
X			break;
X	}
X	for (i = rn2 (100), let = 0; (i -= shprobs[let]) >= 0; let++)
X		if (!shtypes[let])
X			break;	/* Superfluous */
X	sroom -> rtype = 8 + let;
X	let = shtypes[let];
X	sh = sroom -> fdoor;
X	for (sx = sroom -> lx; sx <= sroom -> hx; sx++)
X		for (sy = sroom -> ly; sy <= sroom -> hy; sy++) {
X			if (sx == sroom -> lx && doors[sh].x == sx - 1 ||
X					sx == sroom -> hx && doors[sh].x == sx + 1 ||
X					sy == sroom -> ly && doors[sh].y == sy - 1 ||
X					sy == sroom -> hy && doors[sh].y == sy + 1)
X				continue;
X			mkobj (let);
X			levl[fobj -> ox = sx][fobj -> oy = sy].scrsym =
X				fobj -> olet;
X		}
X}
X
Xmkzoo () {
X	register        MKROOM * zroom;
X	register int    zx, zy;
X
X	for (;;) {
X		zroom = &rooms[rn2 (nroom)];
X		if (zroom -> hx < 0 || zroom -> rtype >= 8 ||
X				ch_upstairs (zroom))
X			continue;/* Niet in kamer met terugweg */
X		break;		/* Kamer gevonden */
X	}
X	zroom -> rtype = ZOO;
X	for (zx = zroom -> lx; zx <= zroom -> hx; zx++)
X		for (zy = zroom -> ly; zy <= zroom -> hy; zy++) {
X			if (!m_at (zx, zy)) {
X				mkgold (0, zx, zy);
X				makemon (1, zx, zy);
X			}
X		}
X}
X
X
Xmkyard () {
X	register        MKROOM * yroom;
X	register int    yx, yy;
X
X	for (;;) {
X		yroom = &rooms[rn2 (nroom)];
X		if (yroom -> hx < 0 || yroom -> rtype >= 8 ||
X				ch_upstairs (yroom))
X			continue;/* Niet in kamer met terugweg */
X		break;		/* Kamer gevonden */
X	}
X	yroom -> rtype = GRAVEYARD;
X	for (yx = yroom -> lx; yx <= yroom -> hx; yx++)
X		for (yy = yroom -> ly; yy <= yroom -> hy; yy++) {
X			if (!mymakemon (yx, yy)) {
X				if (fmon -> mhp == 7)
X					mymakemon (yx, yy);
X			/* Not so many demons */
X				mkgold (0, yx, yy);
X				if (fmon -> mhp != 1) {
X					mkobj (0);
X					if (rn2 (8))
X						fobj -> cursed = 1;
X					levl[fobj -> ox = yx][fobj -> oy = yy].scrsym = fobj -> olet;
X				}
X			}
X		}
X}
X
X#define NOMON	1
X#define MON	0
X
Xmymakemon (monx, mony) {
X	register        MONSTER mtmp;
X	register int    tryct = 0;
X	register int    tmp = 0;
X
X	if (m_at (monx, mony))
X		return NOMON;
X	mtmp = newmonst (0);
X	mtmp -> mstole = STOLE_NULL;
X	mtmp -> msleep = 1;
X	mtmp -> mx = monx;
X	mtmp -> my = mony;
X	mtmp -> mfroz = 0;
X	mtmp -> mconf = 0;
X	mtmp -> mflee = 0;
X	mtmp -> mspeed = 0;
X	mtmp -> mtame = 0;
X	mtmp -> angry = 0;
X	mtmp -> mxlth = 0;
X	mtmp -> wormno = 0;
X	do {
X		if (++tryct > 1000) {
X			printf ("tryct overflow yard\n");
X			free (mtmp);
X			return NOMON;
X		}
X		tmp = putyard (mtmp);
X	} while (index (geno, mmon[mtmp -> mhp][mtmp -> orig_hp]) || tmp);
X	mtmp -> nmon = fmon;
X	fmon = mtmp;
X	return 0;
X}
X
Xputyard (mtmp)
XMONSTER mtmp;
X{
X	switch (rn2 (5)) {
X		case 0: 
X			mtmp -> mhp = 1;/* level 3 */
X			mtmp -> orig_hp = 6;/* ZOMBIE */
X			break;
X		case 1: 
X			if (dlevel < 18)
X				return NOMON;
X			mtmp -> mhp = 6;/* level 18 */
X			mtmp -> orig_hp = 2;/* VAMPIRE */
X			break;
X		case 2: 
X			mtmp -> mhp = 4;/* level 12 */
X			mtmp -> orig_hp = 5;/* Wraith */
X			break;
X		case 3: 
X			if (dlevel < 21)
X				return NOMON;
X			mtmp -> mhp = 7;/* level 21 */
X			mtmp -> orig_hp = 6;/* DEMON */
X			break;
X		case 4: 
X			mtmp -> mhp = 10;/* altijd */
X			mtmp -> orig_hp = 10;/* GHOST */
X			break;
X		default: 
X			mtmp -> mhp = rn2 (dlevel / 3 + 1) % 8;
X			mtmp -> orig_hp = rn2 (7);
X	}
X	return MON;
X}
X
Xmkswamp () {
X	register        MKROOM * zroom;
X	register int    zx, zy;
X	register int    first = 0;
X
X	for (;;) {
X		zroom = &rooms[rn2 (nroom)];
X		if (zroom -> hx < 0)
X			return;
X		if (ch_upstairs (zroom) || ch_dnstairs (zroom))
X			continue;
X		if (zroom -> hx < 0 || zroom -> rtype >= 8)
X			continue;
X	/* Niet in kamer met terugweg of weg naar beneden */
X		break;		/* Kamer gevonden */
X	}
X	zroom -> rtype = SWAMP;
X	for (zx = zroom -> lx; zx <= zroom -> hx; zx++)
X		for (zy = zroom -> ly; zy <= zroom -> hy; zy++) {
X			if ((zx + zy) % 2 && !o_at (zx, zy) &&
X					!g_at (zx, zy, fgold) && !m_at (zx, zy) &&
X					ch_doors (zx, zy)) {
X				levl[zx][zy].typ = POOL;
X				levl[zx][zy].scrsym = '}';
X				if (!first) {
X					makemon (0, zx, zy);
X					++first;
X				}
X				else if (!rn2 (4))
X					makemon (0, zx, zy);
X			}
X		}
X}
X
Xch_doors (zx, zy)
Xregister int    zx, zy;
X{
X	register int    xx, yy;
X	register int    status = 1;
X
X	for (xx = zx - 1; xx <= zx + 1; xx++)
X		for (yy = zy - 1; yy <= zy + 1; yy++) {
X			if (levl[xx][yy].typ == DOOR)
X				status = 0;
X			else if (levl[xx][yy].typ == SDOOR) {
X				levl[xx][yy].typ = DOOR;
X				levl[xx][yy].scrsym = '+';
X				status = 0;
X			}
X		}
X	return status;
X}
X
Xmk_knox () {
X	register        MKROOM * kroom;
X	register int    kx, ky;
X	register int    tmp = 10000;
X	OBJECT otmp;
X	MONSTER mtmp;
X	GOLD_TRAP gtmp;
X
X	for (kroom = &rooms[0];; ++kroom) {
X		if (kroom -> hx < 0)
X			return;
X		if (ch_upstairs (kroom) || ch_dnstairs (kroom))
X			continue;
X		if ((kroom -> rtype >= 8 || kroom -> rtype <= SWAMP)
X				&& kroom -> rtype)
X				/* Shop or Zoo or Graveyard or Swamp */
X			continue;
X		if (kroom -> hx - kroom -> lx <= 3 || kroom -> hy - kroom -> ly <= 3)
X			continue;
X		break;
X	}
X	kroom -> rtype = FORT_KNOX;
X	kx = ((kroom -> hx - kroom -> lx) / 2) + kroom -> lx;
X	ky = ((kroom -> hy - kroom -> ly) / 2) + kroom -> ly;
X	for (tx = kx - 1; tx <= kx + 1; ++tx)
X		for (ty = ky - 1; ty <= ky + 1; ++ty) {
X			if (tx == kx && ty == ky)
X				continue;
X			if ((otmp = o_at (tx, ty))) {
X				otmp -> ox = kx;
X				otmp -> oy = ky;
X			}
X			if ((mtmp = m_at (tx, ty)))
X				delmon (mtmp);
X			if ((gtmp = g_at (tx, ty, fgold))) {
X				tmp += gtmp -> gflag;
X				delgen (gtmp, fgold);
X			}
X			if ((gtmp = g_at (tx, ty, ftrap)))
X				delgen (gtmp, ftrap);
X			levl[tx][ty].typ = VAULT;
X			levl[tx][ty].scrsym = (ty == ky) ? '|' : '-';
X		}
X	mkgold (tmp, kx, ky);
X}
X
Xch_upstairs (mroom)
Xregister        MKROOM * mroom;
X{
X	return (mroom -> lx <= xupstair && xupstair <= mroom -> hx &&
X			mroom -> ly <= yupstair && yupstair <= mroom -> hy);
X}
X
Xch_dnstairs (mroom)
Xregister        MKROOM * mroom;
X{
X	return (mroom -> lx <= xdnstair && xdnstair <= mroom -> hx &&
X			mroom -> ly <= ydnstair && ydnstair <= mroom -> hy);
X}
X
Xdelmon (mtmp)
Xregister        MONSTER mtmp;
X{
X	register        MONSTER mtmp2;
X
X	if (mtmp == fmon)
X		fmon = fmon -> nmon;
X	else {
X		for (mtmp2 = fmon; mtmp2 -> nmon != mtmp;
X				mtmp2 = mtmp2 -> nmon);
X		mtmp2 -> nmon = mtmp -> nmon;
X	}
X}
X
Xdelgen (gtmp, key)
Xregister        GOLD_TRAP gtmp, key;
X{
X	register        GOLD_TRAP gtmp2;
X
X	if (gtmp == key)
X		key = key -> ngen;
X	else {
X		for (gtmp2 = key; gtmp2 -> ngen != gtmp;
X				gtmp2 = gtmp2 -> ngen);
X		gtmp2 -> ngen = gtmp -> ngen;
X	}
X}
/
echo 'Part 01 of Hack complete.'
exit
-- 

			Michiel Huisjes.
			{seismo|decvax|philabs}!mcvax!vu44!ark!huisjes

huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)

#!/bin/sh
#
# 
# 
# This is a shell archive. These archives are packed by the program 
# packmail(1). If you have the program unshar(1), I suggest you use it.
# If you don't remove anything before the cut line and then feed to
# sh(1)
# 
# =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE===
#
echo 'Start of Hack, part 02 of 05:'
echo 'x - hack.do1.c'
sed 's/^X//' > hack.do1.c << '/'
X/*
X * Hack.do1.c
X */
X
X#include "hack.h"
X
Xextern char     NOTHIN[], WAND[];
X
Xextern  MONSTER shopkeeper;
XMONSTER vaultkeeper;
X
Xchar   *wandeffect[] = {
X	"magic missile",
X	"bolt of fire",
X	"sleep ray",
X	"bolt of cold",
X	"death ray",
X	"bolt of confusion"
X};
X
X#define MAXLEVEL	40
X
Xchar    vaultflag[MAXLEVEL];
X
XMONSTER bhit ();
X
X
X
X/* More various user do commands */
X
X
X
X
Xdozap () {
X	register        OBJECT obj;
X	register        MONSTER mtmp;
X	char    zx, zy;
X	register        num;
X
X	if (!(obj = getobj ("/", "zap"))) {
X		nomove ();
X		return;
X	}
X	if (!obj -> spe) {
X		pline (NOTHIN);
X		return;
X	}
X	obj -> spe--;
X	if (obj -> otyp <= Z_CREATE_MON) {
X		switch (obj -> otyp) {
X
X			case Z_LIGHT: 
X				if (dlevel)
X					litroom ();
X				else
X					pline (NOTHIN);
X				break;
X
X			case Z_DETEC: 
X				if (!findit ())
X					return;
X				break;
X
X			case Z_CREATE_MON: 
X				makemon (0);
X				mnexto (fmon);
X				break;
X		}
X
X		if (oiden[obj -> otyp] & WANN)
X			return;
X		u.urexp += 10;
X		oiden[obj -> otyp] |= WANN;
X		return;
X	}
X	if (!getdir ()) {
X		obj -> spe++;
X		nomove ();
X		return;
X	}
X	if (obj -> otyp <= Z_TELEPORT) {
X		if (mtmp = bhit (dx, dy, rn1 (8, 6))) {
X			switch (obj -> otyp) {
X
X				case Z_EXHAUST: 
X					pline ("You fight and fight and fight......");
X					home ();
X					flush ();
X					sleep (2);
X					flags.topl = 0;
X					u.uhp -= mtmp -> mhp;
X					if (u.uhp <= 0) {
X						pseebl ("You cannot beat %s",
X								mtmp -> data -> mname);
X						pline ("You die....");
X						done (DIED);
X					}
X					else {
X						mtmp -> mhp = 0;
X						flags.dhp = 1;
X						killed (mtmp);
X					}
X					oiden[obj -> otyp] |= WANN;
X					break;
X
X				case Z_SLOW_MON: 
X					mtmp -> mspeed = MSLOW;
X					break;
X
X				case Z_SPEED_MON: 
X					mtmp -> mspeed = MFAST;
X					break;
X
X				case Z_UND_TUR: 
X					if (index (" WVZ&", mtmp -> data -> mlet)) {
X						mtmp -> mhp -= rnd (8);
X						if (alive (mtmp))
X							mtmp -> mflee = 1;
X					}
X					break;
X
X				case Z_POLYMORF: 
X					if (mtmp -> ale && !cansee (mtmp -> mx, mtmp -> my))
X						break;
X					if (mtmp == shopkeeper)
X						shkdead ();/* Michiel */
X					unstuck (mtmp);
X					newcham (mtmp, &mon[rn2 (8)][rn2 (7)]);
X					oiden[obj -> otyp] |= WANN;
X					return;
X
X				case Z_CAN: 
X					mtmp -> mcan = 1;
X					break;
X
X				case Z_TELEPORT: 
X					unstuck (u.ustuck);
X					oiden[obj -> otyp] |= WANN;
X					if (mtmp == shopkeeper)
X						setangry ();/* FRED */
X					else if (mtmp == vaultkeeper)
X						mtmp -> angry = 1;
X					rloc (mtmp);
X					break;
X
X			}
X		}
X		return;
X	}
X	if (obj -> otyp == Z_CLOSING) {
X		PART * room;
X
X		zx = u.ux + dx;
X		zy = u.uy + dy;
X		room = &levl[zx][zy];
X		while (room -> typ >= CORR) {
X			zx += dx;
X			zy += dy;
X			room = &levl[zx][zy];
X		}
X		if (room -> typ == DOOR || room -> typ == SDOOR) {
X			pline ("The %sdoor closes forever.",
X					room -> typ == SDOOR ? "secret " : "");
X			oiden[obj -> otyp] |= WANN;
X			room -> typ = WALL;
X			newsym (zx, zy);
X		}
X		return;
X	}
X	if (obj -> otyp == Z_DIGGING) {
X	/* This is further improved by Michiel and Fred */
X		PART * room;
X		int     range = 1;
X
X		zx = u.ux + dx;
X		zy = u.uy + dy;
X		num = ROOM;
X		for (;;) {
X			if (zx < 1 || zx > 78 || zy < 1 || zy > 21) {
X				zx -= dx;
X				zy -= dy;
X				break;
X			}
X			atl (zx, zy, '*');
X			at (zx, zy, '*');
X			++range;
X			room = &levl[zx][zy];
X			if (!xdnstair) {
X				if (zx < 3 || zx > 76 || zy < 3 ||
X						zy > 18)
X					break;
X				if (room -> typ == WALL) {
X					room -> typ = ROOM;
X					break;
X				}
X			}
X			else if (room -> typ == POOL)
X				goto check;
X			else if (num == ROOM || num == 10) {
X				if (room -> typ) {
X					if (room -> typ == VAULT)
X						vaultinit ();
X					if (room -> typ != ROOM) {
X						if (room -> typ == VAULT)
X							room -> typ = ROOM;
X						else
X						if (room -> typ != CORR)
X							room -> typ = DOOR;
X						if (num == 10)
X							break;
X						num = 10;
X					}
X				}
X				else
X					room -> typ = CORR;
X			}
X			else {
X				if (room -> typ == VAULT)
X					vaultinit ();
X				if (room -> typ % 4) {
X				/* WALL,(S)DOOR,ROOM */
X					room -> typ = DOOR;
X					break;
X				}
X				else
X					room -> typ = CORR;
X			}
X	check: 
X			newsym (zx, zy);
X			zx += dx;
X			zy += dy;
X		}
X		while (--range) {
X			newsym (zx, zy);
X			if (mtmp = m_at (zx, zy))
X				pmon (mtmp);
X			zx -= dx;
X			zy -= dy;
X		}
X	}
X	else
X		buzz (obj -> otyp, u.ux, u.uy, dx, dy);
X	oiden[obj -> otyp] |= WANN;
X}
X
Xhit (str, mtmp)
Xregister char  *str;
Xregister        MONSTER mtmp;
X{
X	psee (THEIT2, mtmp -> mx, mtmp -> my, "%s hits %s", str,
X			mtmp -> data -> mname);
X}
X
Xmiss (str, mtmp)
Xregister char  *str;
Xregister        MONSTER mtmp;
X{
X	psee (THEIT2, mtmp -> mx, mtmp -> my, "%s misses %s", str,
X			mtmp -> data -> mname);
X}
X
Xfindit () {
X	char    num, lx, hx, ly, hy;
X	register char   zx, zy;
X	register        GOLD_TRAP gtmp, gt1;
X
X	for (lx = u.ux; levl[lx - 1][u.uy].typ % CORR; lx--);/* typ!=0 */
X /* WALL, SDOOR, DOOR, or ROOM (see hack.h) */
X
X	for (hx = u.ux; levl[hx + 1][u.uy].typ % 4; hx++);
X	for (ly = u.uy; levl[u.ux][ly - 1].typ % 4; ly--);
X	for (hy = u.uy; levl[u.ux][hy + 1].typ % 4; hy++);
X	num = 0;
X	for (zy = ly; zy <= hy; zy++)
X		for (zx = lx; zx <= hx; zx++) {
X			if (levl[zx][zy].typ == SDOOR) {
X				levl[zx][zy].typ = DOOR;
X				atl (zx, zy, '+');
X				num++;
X			}
X			else if (gtmp = g_at (zx, zy, ftrap)) {
X				if (gtmp -> gflag == PIERC) {
X					mkmonat (PM_PIERC, zx, zy);
X					num++;
X					deltrap (gtmp);
X				}
X				else if (gtmp -> gflag == MIMIC) {
X					deltrap (gtmp);
X			M: 
X					mkmonat (PM_MIMIC, zx, zy);
X					num++;
X				}
X				else if (!gtmp -> gflag & SEEN) {
X					gtmp -> gflag |= SEEN;
X					atl (zx, zy, '^');
X					num++;
X				}
X			}
X			else if ((gtmp = g_at (zx, zy, fgold)) &&
X					!gtmp -> gflag) {
X				if (gtmp == fgold)
X					fgold = gtmp -> ngen;
X				else {
X					for (gt1 = fgold; gt1 -> ngen !=
X							gtmp; gt1 = gt1 -> ngen);
X					gt1 -> ngen = gtmp -> ngen;
X				}
X				free (gtmp);
X				goto M;
X			}
X		}
X	return (num);
X}
X
X/* Sets dx,dy to the final position of the weapon thrown */
XMONSTER bhit (ddx, ddy, range) {
X	register        MONSTER mtmp;
X
X	dx = u.ux;
X	dy = u.uy;
X	if (u.uswallow)
X		return u.ustuck;/* a3 */
X	while (range-- > 0) {
X		dx += ddx;
X		dy += ddy;
X		if (mtmp = m_at (dx, dy))
X			return (mtmp);
X		if (levl[dx][dy].typ < CORR) {
X			dx -= ddx;
X			dy -= ddy;
X			return (0);
X		}
X	}
X	return (0);
X}
X
Xbuzz (type, sx, sy, ddx, ddy)
Xregister        sx, sy;
X{
X	PART * lev;
X	register char   range, let;
X	register        MONSTER mtmp;
X	register        wandeftype = type - 11;
X
X	if (u.uswallow) {
X		pline ("The %s rips into the %s.",
X				wandeffect[wandeftype],
X				u.ustuck -> data -> mname);
X		zhit (u.ustuck, type);
X		alive (u.ustuck);/* a3 */
X		return;
X	}
X	range = rn1 (7, 7);
X	if (ddx == ddy)
X		let = '\\';
X	else if (ddx && ddy)
X		let = '/';
X	else if (ddx)
X		let = '-';
X	else
X		let = '|';
X	while (range-- > 0) {
X		sx += ddx;
X		sy += ddy;
X		if ((lev = &levl[sx][sy]) -> typ) {
X			at (sx, sy, let);
X			on (sx, sy);
X			lev -> new = 1;
X		}
X		if (mtmp = m_at (sx, sy)) {
X			if (mtmp == vaultkeeper)
X				mtmp -> angry = 1;
X			if (rnd (20) < 18 + mtmp -> data -> ac) {
X				zhit (mtmp, type);
X				if (alive (mtmp))
X					hit (wandeffect[wandeftype],
X							mtmp);
X				range -= 2;
X			}
X			else
X				miss (wandeffect[wandeftype], mtmp);
X		}
X		else if (sx == u.ux && sy == u.uy) {
X			if (rnd (20) < 18 + u.uac) {
X				range -= 2;
X				flags.dhp = 1;/* Michiel */
X				pline ("The %s hits you!",
X						wandeffect[wandeftype]);
X				switch (type) {
X					case Z_MAG_MISSILE: 
X						u.uhp -= d (2, 6);
X						break;
X					case Z_FIRE: 
X						if (u.ufireres) {
X							pline ("You don't feel hot!");
X							break;
X						}
X						u.uhp -= d (6, 6);
X						break;
X					case Z_SLEEP: 
X						nomul (-rnd (25));
X						break;
X					case Z_COLD: 
X						if (u.ucoldres) {
X							pline ("You don't feel cold!");
X							break;
X						}
X						u.uhp -= d (6, 6);
X						break;
X					case Z_DEATH: 
X						u.uhp = 0;
X						break;
X					case Z_CONF_MON: 
X						u.uconfused = d (4, 6);
X				}
X				if (u.uhp <= 0)
X					killer = wandeffect[wandeftype];
X			}
X			else
X				pline ("The %s wizzes by you!",
X						wandeffect[wandeftype]);
X		}
X		if (lev -> typ <= DOOR || lev -> typ == VAULT) {
X			psee (0, sx, sy, "%s bounces!",
X					wandeffect[wandeftype], NULL);
X			ddx = -ddx;
X			ddy = -ddy;
X			range--;
X		}
X	}
X}
X
Xzhit (mtmp, type)
Xregister        MONSTER mtmp;
Xregister        type;
X{
X	if (mtmp == shopkeeper)
X		setangry ();
X	switch (type) {
X		case Z_MAG_MISSILE: 
X			mtmp -> mhp -= d (2, 6);
X			break;
X		case Z_FIRE: 
X			if (index ("Dg", mtmp -> data -> mlet))
X				return;
X			mtmp -> mhp -= d (6, 6);
X			if (mtmp -> data -> mlet == 'Y')
X				mtmp -> mhp -= 7;
X			break;
X		case Z_SLEEP: 
X			mtmp -> mfroz = 1;
X			break;
X		case Z_COLD: 
X			if (index ("Ygf", mtmp -> data -> mlet))
X				return;
X			if (mtmp -> data -> mlet == 'D')
X				mtmp -> mhp -= 7;
X			mtmp -> mhp -= d (6, 6);
X			break;
X		case Z_DEATH: 
X			if (index ("WVZ ", mtmp -> data -> mlet))
X				return;
X			mtmp -> mhp = 0;
X			break;
X		case Z_CONF_MON: 
X			if (mtmp == u.ustuck)
X				return;
X			mtmp -> mconf = 1;
X			break;
X
X	}
X}
X
Xdowhatis () {
X	register        fd;
X	register char  *str;
X
X
X	pline ("Specify what? ");
X	flags.topl = 0;
X	getlin (buf);
X	str = buf;
X	while (*str == ' ')
X		str++;
X	nomove ();
X	buf[52] = '\0';
X	if (*(str + 1))
X		pline ("One character please.");
X	else if ((fd = open (DATA, 0)) < 0)
X		pline ("Cannot open data file!");
X	else {
X		lseek (fd, (long) (*str * 51), 0);
X		if (read (fd, buf, 51) > 0 && *buf != '\\')
X			pline (buf);
X		else
X			pline ("Unknown symbol.");
X		close (fd);
X	}
X}
X
Xdoshow () {			/* Michiel: Show everything you're wearing */
X	nomove ();
X	show (uarm2);
X	show (uarm);
X	show (uwep);
X	show (uleft);
X	show (uright);
X}
X
Xshow (otmp)
Xregister        OBJECT otmp;
X{
X	if (otmp)
X		prinv (otmp);
X}
X
Xdosearch () {
X	register char   x, y;
X	register        GOLD_TRAP tgen;
X
X	for (x = u.ux - 1; x < u.ux + 2; x++)
X		for (y = u.uy - 1; y < u.uy + 2; y++)
X			if (levl[x][y].typ == SDOOR && !rn2 (7)) {
X				levl[x][y].typ = DOOR;
X				atl (x, y, '+');
X				nomul (0);
X			}
X			else {
X				for (tgen = ftrap; tgen; tgen = tgen -> ngen)
X					if (tgen -> gx == x && tgen -> gy == y &&
X							(!rn2 (8) || ((!u.usearch) &&
X									tgen -> gflag & SEEN))) {
X						nomul (0);
X						pline ("You find a%s", traps[tgen -> gflag & 037]);
X						if ((tgen -> gflag & 037) ==
X								PIERC) {
X							deltrap (tgen);
X							mkmonat (PM_PIERC, x, y);
X							return;
X						}
X						if ((tgen -> gflag & 037) ==
X								MIMIC) {
X							deltrap (tgen);
X							mkmonat (PM_MIMIC, x, y);
X							return;
X						}
X						if (!(tgen -> gflag & SEEN)) {
X							tgen -> gflag |= SEEN;
X							atl (x, y, '^');
X						}
X					}
X			}
X}
X
Xdoset () {
X	pline ("Give one inventory per line? ");
X	flush ();
X	flags.oneline = (getchar () == 'y');
X	nomove ();
X}
X
X
X
X/*
X * The whole vault was implemented by Fred and Michiel 
X *
X */
X
X
Xstruct permonst treasurer = {
X	"treasurer", '@', 15, 12, -1, 4, 8, 0
X};
X
Xvaultinit () {
X	GOLD_TRAP gtmp;
X
X	if (vaultflag[dlevel])
X		return;
X	vaultflag[dlevel] = 1;;
X	makemon (&treasurer);
X	vaultkeeper = fmon;
X	for (gtmp = fgold; gtmp -> gflag < 10000; gtmp = gtmp -> ngen);
X	fmon -> mx = gtmp -> gx;
X	fmon -> my = gtmp -> gy;
X	if (!u.ublind)
X		pmon (fmon);
X}
/
echo 'x - hack.mon.c'
sed 's/^X//' > hack.mon.c << '/'
X/*
X * Hack.mon.c
X */
X
X/* Contains various monster routines */
X
X#include "hack.h"
X
Xextern char     WCLEV[], STOPGLOW[];
X
Xdist (x, y)
Xregister        x, y;
X{
X	x -= u.ux;
X	y -= u.uy;
X	return (x * x + y * y);
X}
X
Xr_free (x, y, mtmp)
Xregister        x, y;
Xregister        MONSTER mtmp;
X{
X	if (mtmp -> ale)
X		return (levl[x][y].typ == POOL);
X	else
X		return (levl[x][y].typ > SDOOR &&
X				(x != u.ux || y != u.uy) && levl[x][y].typ < POOL);
X /* DOOR,CORR,ROOM */
X}
X
X
X/* Puts m next to u, or anywhere if there isn't room there */
Xmnexto (mtmp)
XMONSTER mtmp;
X{
X	register        x, y, z;
X	struct {
X		char    zx, zy;
X	}       foo[15], *tfoo;
X	int     range;
X
X	tfoo = foo;
X	range = 1;
X	do {			/* Full kludge action */
X		for (y = 0; y < 2; y++)
X			for (x = u.ux - range; x <= u.ux + range; x++) {
X				z = range;
X				if (!y)
X					z = -z;
X				if (test (x, z += u.uy)) {
X					tfoo -> zx = x;
X					tfoo++ -> zy = z;
X					if (tfoo == &foo[15])
X						goto foofull;
X				}
X			}
X		for (x = 0; x < 2; x++)
X			for (y = u.uy + 1 - range; y < u.uy + range;
X					y++) {
X				z = range;
X				if (!x)
X					z = -z;
X				if (test (z += u.ux, y)) {
X					tfoo -> zx = z;
X					tfoo++ -> zy = y;
X					if (tfoo == &foo[15])
X						goto foofull;
X				}
X			}
X		range++;
X	} while (tfoo == foo);
Xfoofull: 
X	tfoo = &foo[rn2 (tfoo - foo)];
X	mtmp -> mx = tfoo -> zx;
X	mtmp -> my = tfoo -> zy;
X	pmon (mtmp);
X	if (mtmp -> data -> mlet == 'w')
X		initworm (mtmp);
X}
X
Xrloc (mtmp)
XMONSTER mtmp;
X{
X	register        tx, ty;
X	register char   ch = mtmp -> data -> mlet;
X
X	if (ch == 'w' && mtmp -> mx)
X		return;		/* Do not relocate worms */
X	levlsym (mtmp -> mx, mtmp -> my, ch);
X	if (mtmp -> ale) {
X		do {
X			tx = rn1 (77, 2);
X			ty = rn2 (22);
X		/* until CORR,DORR,or ROOM; or... */
X		} while (levl[tx][ty].typ != POOL || m_at (tx, ty) ||
X				(tx == u.ux && ty == u.uy));
X	}
X	else {
X		do {
X			tx = rn1 (77, 2);
X			ty = rn2 (22);
X		/* until CORR,DORR,or ROOM; or... */
X		} while (levl[tx][ty].typ < DOOR || m_at (tx, ty) ||
X				(tx == u.ux && ty == u.uy)
X				|| levl[tx][ty].typ >= 7);
X	}
X	mtmp -> mx = tx;
X	mtmp -> my = ty;
X	pmon (mtmp);
X	if (ch == 'w')
X		initworm (mtmp);
X}
X
Xtest (x, y) {
X	if (x <= 0 || x > 78 || y <= 0 || y > 20)
X		return 0;
X	if (m_at (x, y) || levl[x][y].typ < DOOR || levl[x][y].typ >= 7)
X		return 0;
X	return 1;
X}
X
Xpoisoned (string, pname)
Xregister char  *string, *pname;
X{
X	pseebl ("%s was poisoned!", string);
X	if (u.upres) {
X		pline ("The poison doesn't seem to affect you.");
X		return;
X	}
X
X	switch (rn2 (6)) {
X		case 0: 
X			u.uhp = 0;
X			break;
X		case 1: 
X		case 2: 
X		case 3: 
X			losestr (rn1 (3, 3));
X			break;
X		case 4: 
X		case 5: 
X			losehp (rn1 (10, 6), pname);
X			return;
X	}
X
X	if (u.uhp <= 0)
X		killer = pname;
X}
X
Xsteal (mtmp)
XMONSTER mtmp;
X{
X	register        OBJECT otmp, ot1;
X	register        tmp;
X
X	for (otmp = invent, tmp = 0; otmp -> nobj; otmp = otmp -> nobj, tmp++);
X
X	tmp = rn2 (tmp);
X	otmp = invent;
X	if (!tmp)
X		invent = invent -> nobj;
X	else {
X		for (; otmp && tmp; tmp--, otmp = otmp -> nobj);
X		ot1 = otmp -> nobj;
X		otmp -> nobj = ot1 -> nobj;/* rm obj from invent */
X		otmp = ot1;
X	}
X	if (otmp == uarm || otmp == uarm2) {
X		u.uac += otmp -> spe;
X		if (otmp == uarm)
X			uarm = uarm2;
X		uarm2 = 0;
X		flags.dac = 1;
X	}
X	else if (otmp == uwep)
X		uwep = 0;
X	else if (otmp == uleft) {
X		uleft = 0;
X		doring (otmp, OFF);
X	}
X	else if (otmp == uright) {
X		uright = 0;
X		doring (otmp, OFF);
X	}
X	doname (otmp, buf);
X	pline ("She stole %s.", buf);
X	stlobj (mtmp, otmp);
X}
X
Xstlobj (mtmp, otmp)
Xregister        MONSTER mtmp;
Xregister        OBJECT otmp;
X{
X	otmp -> nobj = 0;	/* Michiel: dog and two objects? */
X	if (mtmp -> mstole) {
X		otmp -> nobj = mtmp -> mstole -> sobj;
X		mtmp -> mstole -> sobj = otmp;
X		return;
X	}			/* Michiel save stolen object */
X	else {
X		mtmp -> mstole = newstole ();
X		mtmp -> mstole -> sobj = otmp;
X		mtmp -> mstole -> sgold = 0;
X	}
X}
X
Xdelmon (mtmp)
Xregister        MONSTER mtmp;
X{
X	unstuck (mtmp);		/* a3 */
X	relmon (mtmp);
X	if (mtmp == shopkeeper)
X		shkdead ();
X	if (mtmp == vaultkeeper) {
X		mtmp -> data -> mmove = -1;
X		vaultkeeper = 0;
X	}
X	if (mtmp -> wormno)
X		wormdead (mtmp);
X	free (mtmp);
X}
X
Xrelmon (mtmp)
Xregister        MONSTER mtmp;
X{
X	register        MONSTER mtmp2;
X
X	if (mtmp == fmon)
X		fmon = fmon -> nmon;
X	else {
X		for (mtmp2 = fmon; mtmp2 -> nmon != mtmp; mtmp2 = mtmp2 -> nmon);
X		mtmp2 -> nmon = mtmp -> nmon;
X	}
X}
X
X/* Release the objects the killed animal has stolen */
Xrelobj (mtmp)
Xregister        MONSTER mtmp;
X{
X	register        GOLD_TRAP gtmp;
X	register        tmp = 0;
X	OBJECT otmp, otmp2;
X
X	if (mtmp -> mstole) {	/* Michiel drop stolen obj or gold */
X		if (mtmp -> mstole -> sgold)
X			tmp = mtmp -> mstole -> sgold;
X		else {
X			otmp = mtmp -> mstole -> sobj;
X			do {
X				otmp -> ox = mtmp -> mx;
X				otmp -> oy = mtmp -> my;
X				otmp2 = otmp;
X				otmp = otmp -> nobj;
X			} while (otmp);
X			otmp2 -> nobj = fobj;
X			fobj = mtmp -> mstole -> sobj;
X			if (mtmp -> data -> mlet != 'd')
X				seeatl (otmp -> ox, otmp -> oy, otmp -> olet);
X		}
X		free (mtmp -> mstole);
X		mtmp -> mstole = NULL;
X	}
X	if (mtmp -> data -> mlet == 'L') {
X		gtmp = newgen ();
X		gtmp -> ngen = fgold;
X		gtmp -> gx = mtmp -> mx;
X		gtmp -> gy = mtmp -> my;
X		if (dlevel)
X			gtmp -> gflag = tmp + d (dlevel, 30);
X		else
X			gtmp -> gflag = tmp + d (maxdlevel, 30);
X		fgold = gtmp;
X		seeatl (mtmp -> mx, mtmp -> my, '$');
X	}
X}
X
X/* a3 */
Xunstuck (mtmp)
Xregister        MONSTER mtmp;
X{
X	if (mtmp == u.ustuck) {
X		if (u.uswallow) {
X			u.uswallow = 0;
X			u.uswldtim = 0;
X			docrt ();
X			setCon (SETC);/* Try a3 */
X		}
X		u.ustuck = 0;
X	}
X}
X
Xkilled (mtmp)
Xregister        MONSTER mtmp;
X{
X	register        tmp;
X
X	unstuck (mtmp);
X	levlsym (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet);
X	if (mtmp -> cham)
X		mtmp -> data = (PM_CHAM);
X	pseebl ("You destroy %s!", mtmp -> data -> mname);
X	if (!u.ublind && u.umconf) {
X		pline (STOPGLOW);
X		u.umconf = 0;
X	}
X	tmp = mtmp -> data -> mhd;
X	tmp *= tmp;
X	++tmp;
X	if (mtmp -> data -> ac < 3)
X		tmp += (7 - mtmp -> data -> ac) << 1;
X	if (index ("AcsSDXaeRTVWU&In:P", mtmp -> data -> mlet))
X		tmp += mtmp -> data -> mhd << 1;
X	if (index ("DeV&P", mtmp -> data -> mlet))
X		tmp += 7 * mtmp -> data -> mhd;
X	if (mtmp -> data -> mhd > 6)
X		tmp += 50;
X	if (mtmp -> ale)
X		tmp += 1000;
X	relobj (mtmp);
X	if ((index ("NTV&", mtmp -> data -> mlet) || !rn2 (5)) && !mtmp -> ale
X			&& levl[mtmp -> mx][mtmp -> my].typ > SDOOR) {
X	/* Mimic in wall? */
X		mkobj (0);
X		fobj -> ox = mtmp -> mx;
X		fobj -> oy = mtmp -> my;
X		if (!u.ublind)
X			atl (mtmp -> mx, mtmp -> my, fobj -> olet);
X	}
X	delmon (mtmp);
X	u.urexp += tmp << 2;
X	u.uexp += tmp;
X	flags.dexp = 1;
X	while (u.uexp >= 10L * pow (u.ulevel - 1)) {
X		pline (WCLEV, ++u.ulevel);
X		tmp = rnd (10);
X		if (tmp < 3)
X			tmp = rnd (10);
X		u.uhpmax += tmp;
X		u.uhp += tmp;
X		flags.dhp = 1;
X		flags.dhpmax = 1;
X		flags.dulev = 1;
X	}
X}
X
X#define TBLIND	5
X#define NOTEST	6
X
X/*VARARGS*/
Xpsee (mode, x, y, str, name, arg)/* Str bevat %s */
Xregister char  *str, *name, *arg;
X{
X	char   *a1, *a2;
X
X	a1 = "the %s";
X	a2 = "the %s";
X	if (mode == TBLIND) {
X		if (u.ublind)
X			a1 = "it";
X	}
X	else if (mode != NOTEST && !cansee (x, y))
X		switch (mode) {
X			case IT1: 
X				a1 = "it";
X				break;
X			case THEIT2: 
X				a2 = "it";
X				break;
X			case 0: 
X				return 0;
X			default: 
X				pline ("Bad(%d) mode in psee", mode);
X		}
X	sprintf (buf, str, a1, a2);
X	if (*buf >= 'a' && *buf <= 'z')
X		*buf += 'A' - 'a';
X	pline (buf, name, arg);
X	return 1;
X}
X
X/*VARARGS*/
Xp2xthe (str, name, arg)
Xregister char  *str, *name, *arg;
X{
X	psee (NOTEST, 0, 0, str, name, arg);
X}
X
Xpseebl (str, name)
Xregister char  *str, *name;
X{
X	psee (TBLIND, 0, 0, str, name, NULL);
X}
X
Xrescham () {			/* Force all chameleons to become normal */
X	register        MONSTER mtmp;
X
X	for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon)
X		if (mtmp -> cham) {
X			mtmp -> cham = 0;
X			if (u.uswallow && u.ustuck == mtmp) {
X				unstuck (mtmp);
X				mnexto (mtmp);
X			}
X			newcham (mtmp, PM_CHAM);
X		}
X}
X
X/* Make a chameleon look like a new monster */
Xnewcham (mtmp, mdat)
Xregister        MONSTER mtmp;
Xregister        MONSTDATA mdat;
X{
X	register        mhp, hpn, hpd;
X
X	if (mdat == mtmp -> data)
X		return;		/* Still the same monster */
X	if (u.uswallow && mdat -> mlet == 'w')
X		return;
X	if (mtmp -> wormno)
X		wormdead (mtmp);/* Throw tail away */
X	hpn = mtmp -> mhp;
X	hpd = mtmp -> data -> mhd << 3;
X	mtmp -> data = mdat;
X	mtmp -> invis = 0;
X	mtmp -> mtame = 0;
X	mhp = mdat -> mhd << 3;
X/* New hp: same fraction of max as before */
X	mtmp -> mhp = 2 + (hpn * mhp) / hpd;
X	hpn = mtmp -> orig_hp;
X	mtmp -> orig_hp = 2 + (hpn * mhp) / hpd;
X	if (mdat -> mlet == 'I') {
X		++mtmp -> invis;
X		if (cansee (mtmp -> mx, mtmp -> my))
X			prl (mtmp -> mx, mtmp -> my);
X	}
X	if (mdat -> mlet == 'w' && getwn (mtmp))
X		initworm (mtmp);
X	if (u.uswallow && mtmp == u.ustuck &&
X			!index (",'P", mdat -> mlet)) {
X		unstuck (mtmp);
X		mnexto (mtmp);
X	}
X	pmon (mtmp);
X}
X
Xmakemon (ptr)
Xregister        MONSTDATA ptr;
X{
X	register        MONSTER mtmp;
X
X	if (!ptr) {
X		do
X			ptr = &mon[rn2 (dlevel / 3 + 1) % 8][rn2 (7)];
X		while (index (genocided, ptr -> mlet));
X	}
X	else {
X		if (index (genocided, ptr -> mlet)) {
X			if (!u.ublind)
X				p2xthe ("%s vanishes!", ptr -> mname);
X			return 1;
X		}
X	}
X	mtmp = newmonst (ptr -> pxlth);
X	mtmp -> nmon = fmon;
X	fmon = mtmp;
X	mtmp -> mstole = 0;
X	mtmp -> invis = 0;
X	mtmp -> cham = 0;
X	mtmp -> msleep = 0;
X	mtmp -> mfroz = 0;
X	mtmp -> mconf = 0;
X	mtmp -> mflee = 0;
X	mtmp -> mtame = 0;
X	mtmp -> mspeed = 0;
X	mtmp -> mcan = 0;
X	mtmp -> angry = 0;
X	mtmp -> mxlth = 0;
X	mtmp -> ale = 0;
X	mtmp -> data = ptr;
X	switch (ptr -> mlet) {
X		case 'I': 
X			++mtmp -> invis;
X			break;
X		case 'L': 
X			mtmp -> msleep = u.uhcursed;
X			break;
X		case ':': 
X			++mtmp -> cham;
X			if (!u.ucham)
X				newcham (mtmp, &mon[rn1 (6, 2)][rn2 (7)]);
X			break;
X		case ';': 
X			mtmp -> ale = 1;
X			break;
X	}
X	if (ptr -> mlet != 'w' || !getwn (mtmp))
X		mtmp -> wormno = 0;
X	mtmp -> mhp = rnd (4);
X	if (ptr -> mhd)
X		mtmp -> mhp = d (ptr -> mhd, 8);
X	mtmp -> orig_hp = mtmp -> mhp;
X	return 0;
X}
X
Xsomegold () {
X	return ((u.ugold < 100L) ? u.ugold :
X			(u.ugold > 10000L) ? rnd (10000) : rnd ((int) u.ugold));
X}
X
Xmkmonat (ptr, x, y)
Xregister        MONSTDATA ptr;
Xregister        x, y;
X{
X	if (makemon (ptr))
X		return;
X	if (x == u.ux && y == u.uy)
X		mnexto (fmon);
X	else {
X		atl (x, y, ptr -> mlet);
X		fmon -> mx = x;
X		fmon -> my = y;
X	}
X}
/
echo 'x - hack.move.c'
sed 's/^X//' > hack.move.c << '/'
X/*
X * Hack.move.c
X */
X
X#include "hack.h"
X
Xextern char     STOPGLOW[], UMISS[], *setan ();
X
X
Xextern  OBJECT addinv ();
X
Xchar    seelx, seehx, seely, seehy;/* Corners of lit room */
X /* l for Low, h for High */
X
X#define ZOO		1
X#define GRAVEYARD	2
X#define SWAMP		3
X#define FORT_KNOX	4
X
X
X/* Contains move commands */
X
Xchar    sdir[] = "hjklyubn";
Xshort   xdir[8] = {
X	-1, 0, 0, 1, -1, 1, -1, 1
X}      ,
X        ydir[8] = {
X	0, 1, -1, 0, -1, -1, 1, 1
X};
X
Xmovecm (cmd)
Xregister char  *cmd;
X{
X	register char  *dp;
X
X	if (!(dp = index (sdir, *cmd)))
X		return 0;
X	dx = xdir[dp - sdir];
X	dy = ydir[dp - sdir];
X	return 1;
X}
X
X
Xdomove () {
X	char    nx, ny, tmpx, tmpy, let;
X	register        MONSTER mtmp;
X	register        PART * tmpr, *ust;
X	GOLD_TRAP gold, trap, gtm1;
X	OBJECT otmp, obj;
X
X	if (u.uswallow) {
X		nx = u.ux;
X		ny = u.uy;
X		goto M;
X	}
X /*  n<letter> is used for u.u<letter> + d<letter>  */
X	if (u.uconfused) {
X		do {
X			dx = rn2 (3);
X			dy = rn2 (3);
X			dx--;
X			dy--;
X			tmpr = &levl[u.ux + dx][u.uy + dy];
X		}
X		while ((!dx && !dy) || tmpr -> typ < DOOR);
X	}
X	else
X		tmpr = &levl[u.ux + dx][u.uy + dy];
X	ust = &levl[u.ux][u.uy];
X	tmpx = u.ux;
X	tmpy = u.uy;
X	nx = u.ux + dx;
X	ny = u.uy + dy;
X	if (trap = g_at (nx, ny, ftrap)) {
X		if (trap -> gflag == MIMIC) {
X			nomul (0);
X			pline ("The door is actually a mimic.");
X			deltrap (trap);
X			if (makemon (PM_MIMIC)) {
X				newsym (nx, ny);
X				return;
X			}
X			if (m_at (nx, ny))
X				mnexto (fmon);
X			else {
X				fmon -> mx = nx;
X				fmon -> my = ny;
X			}
X			if (!u.ustuck)
X				u.ustuck = fmon;
X			pmon (fmon);
X			return;
X		}
X		if (trap -> gflag & SEEN)
X			nomul (0);
X	}
X	if (u.ustuck && (nx != u.ustuck -> mx || ny != u.ustuck -> my)) {
X		pseebl ("You cannot escape from %s!",
X				u.ustuck -> data -> mname);
X		nomul (0);
X		return;
X	}
XM: 
X	if (mtmp = m_at (nx, ny)) {
X/* Attack monster */
X		char    tmp;
X		register        MONSTDATA mdat = mtmp -> data;
X
X		tmp = u.ulevel - 1 + mdat -> ac + abon ();
X		if (uwep) {
X			tmp += uwep -> spe;
X			if (uwep -> otyp == W_TWOH_SWORD)
X				tmp--;
X			else if (uwep -> otyp == W_DAGGER)
X				tmp += 2;
X			else if (uwep -> otyp == W_SPEAR && index ("XDne",
X						mdat -> mlet))
X				tmp += 2;
X		}
X		if (mtmp -> msleep) {
X			mtmp -> msleep = 0;
X			tmp += 2;
X		}
X		if (mtmp -> mfroz) {
X			tmp += 4;
X			if (!rn2 (10))
X				mtmp -> mfroz = 0;
X		}
X		if (mtmp -> mflee)
X			tmp += 2;
X		if (u.utrap)
X			tmp -= 3;
X		if (mtmp == shopkeeper)
X			setangry ();
X		if (tmp < rnd (20) && !u.uswallow)
X			pseebl (UMISS, mdat -> mname);
X		else {
X/* We hit the monster; but: it might die! */
X
X			if (hmon (mtmp, uwep)) {
X			/* 0-destroy,1-hit */
X				if (!u.uswallow && !rn2 (25) &&
X						mtmp -> mhp < mtmp -> orig_hp >> 1) {
X/* You might be stucked at this point ! { FRED } */
X					if (mtmp == u.ustuck)
X						unstuck (mtmp);
X					mtmp -> mflee = 1;
X				}
X				pseebl ("You hit %s!", mdat -> mname);
X				if (u.umconf && !u.uswallow) {/* a3 */
X					if (!u.ublind) {
X						pline (STOPGLOW);
X						pseebl ("The %s appears confused.", mdat -> mname);
X					}
X					mtmp -> mconf = 1;
X					u.umconf = 0;
X				}
X				if (mtmp -> wormno)
X					cutworm (mtmp, nx, ny,
X							uwep -> otyp);
X				switch (mdat -> mlet) {
X
X					case 'a': 
X						if (rn2 (2)) {
X							pline ("You are splashed by the blob's acid!");
X							losehp (rnd (6), mdat -> mname);
X						}
X						if (!rn2 (6) && uwep) {
X							pline ("Your %s corrodes!",
X									weapons[uwep -> otyp].wepnam);
X							--uwep -> spe;
X						}
X						break;
X
X					case 'E': 
X						if (!u.ublind && rn2 (2)) {
X							pline ("You are frozen by the floating eye's gaze!");
X							nomul (rn1 (20, -20));
X							return;
X						}
X						break;
X				}
X			}
X		}
X		nomul (0);
X		return;
X	}
X
X/* Not attacking an animal, so we try to move  */
X	if (u.utrap) {
X		pline ((u.upit) ? "You are still in a pit." :
X				"You are caught in a beartrap.");
X		if (u.upit || (dx && dy) || !rn2 (5))
X			u.utrap--;
X		return;
X	}
X	if ((dx && dy && (tmpr -> typ == DOOR || ust -> typ == DOOR)) ||
X			tmpr -> typ < DOOR || tmpr -> typ == VAULT) {
X	/* 0, WALL, or SDOOR */
X		flags.move = 0;
X		nomul (0);
X		return;
X	}
X	u.ux = nx;		/* u.ux+=dx; u.uy+=dy; */
X	u.uy = ny;
X	nx += dx;
X	ny += dy;
X	if (flags.run)
X		if (tmpr -> typ == DOOR ||
X				(xupstair == u.ux && yupstair == u.uy) ||
X				(xdnstair == u.ux && ydnstair == u.uy))
X			nomul (0);
X	if (tmpr -> typ >= 30 && tmpr -> typ <= 41) {
X		for (otmp = invent; otmp; otmp = otmp -> nobj) {
X			if (otmp -> otyp == tmpr -> typ && otmp -> olet == '_') {
X				pline ("The door opens.");
X				doname (otmp, buf);
X				pline ("The %s vanishes.", buf);
X				useup (otmp);
X				tmpr -> typ = DOOR;
X				break;
X			}
X		}
X		if (!otmp) {
X			if (rn2 (2))
X				pline ("The door is locked!");
X			else
X				pline ("You cannot unlock the door!");
X			u.ux -= dx;
X			u.uy -= dy;
X			return;
X		}
X	}
X	if (ust -> scrsym == '@') {
X		newsym (tmpx, tmpy);
X		oldux = tmpx;
X		olduy = tmpy;
X	}
X	if (!u.ublind) {
X		if (ust -> lit) {
X			if (tmpr -> lit) {
X				if (tmpr -> typ == DOOR)
X					prl1 (nx, ny);
X				if (ust -> typ == DOOR)
X					nose1 (tmpx - dx, tmpy - dy);
X			}
X			else {
X				unCoff (UNC, 1);
X				prl1 (nx, ny);
X			}
X		}
X		else {
X			if (tmpr -> lit)
X				setCon (SETC);
X			else {
X				prl1 (nx, ny);
X				if (tmpr -> typ == DOOR) {
X					if (dy) {
X						prl (u.ux - 1, u.uy);
X						prl (u.ux + 1, u.uy);
X					}
X					else {
X						prl (u.ux, u.uy - 1);
X						prl (u.ux, u.uy + 1);
X					}
X				}
X			}
X			nose1 (tmpx - dx, tmpy - dy);
X		}
X	}
X	else
X		newunseen (tmpx, tmpy);
X	if (!multi)
X		pru ();
X	while (gold = g_at (u.ux, u.uy, fgold)) {
X		if (!gold -> gflag) {
X			pline ("The chest was a mimic!");
X			if (!makemon (PM_MIMIC)) {
X				mnexto (fmon);
X				u.ustuck = fmon;
X			}
X			nomul (0);
X		}
X		else {
X			if (u.uhcursed) {
X				pline ("You cannot pick up the gold!");
X				break;
X			}
X			if (gold -> gflag == 1)
X				gold -> gflag++;/* a3 */
X			pline ("%u gold pieces", gold -> gflag);
X			u.ugold += gold -> gflag;
X			flags.dgold = 1;
X		}
X		if (gold == fgold)
X			fgold = fgold -> ngen;
X		else {
X			for (gtm1 = fgold; gtm1 -> ngen != gold;
X					gtm1 = gtm1 -> ngen);
X			gtm1 -> ngen = gold -> ngen;
X		}
X		free (gold);
X		if (flags.run)
X			nomul (0);
X		if (u.uinvis)
X			newsym (u.ux, u.uy);
X	}
X	while (obj = o_at (u.ux, u.uy)) {
X		for (otmp = invent, let = 0; otmp; otmp = otmp -> nobj)
X			let += weight (otmp);
X		let += weight (obj);
X		if (let > 85) {
X			pline ("You can't carry anything more.");
X			if (flags.run)
X				nomul (0);
X			break;
X		}
X		if (let > 80)
X			pline ("You have a little trouble lifting");
X		if (!(obj -> cursed))
X			obj -> cursed = u.uhcursed;
X		freeobj (obj);
X		addtobill (obj);/* Sets obj->unpaid if necessary */
X		prinv (addinv (obj));
X	/* Might merge it with other objects */
X		if (u.uinvis)
X			newsym (u.ux, u.uy);
X		if (flags.run)
X			nomul (0);
X	}
X	if (trap) {
X		nomul (0);
X		if (trap -> gflag & SEEN && !rn2 (5))
X			pline ("You escape a%s.",
X					traps[trap -> gflag & 037]);
X		else {
X			trap -> gflag |= SEEN;
X			switch (((trap -> gflag) & 037)) {
X
X				case SLPTRP: 
X					pline ("A cloud of gas puts you to sleep!");
X					nomul (-rnd (25));
X					break;
X
X				case BEAR: 
X					u.utrap = rn1 (4, 4);
X					u.upit = 0;
X					pline ("A bear trap closes on your foot!");
X					break;
X
X				case PIERC: 
X					pline ("A piercer suddenly drops from the ceiling!");
X					deltrap (trap);
X					if (!makemon (PM_PIERC)) {
X						mnexto (fmon);
X						hitu (3, d (4, 6),
X								"falling piercer");
X					}
X					break;
X
X				case ARROW: 
X					pline ("An arrow shoots out at you!");
X					hitu (8, rnd (6), "arrow");
X					break;
X
X				case TDOOR: 
X					if (!xdnstair) {
X						pline ("A trap door in the ceiling opens and a rock falls on your head!");
X						losehp (d (2, 10),
X								"falling rock");
X						break;
X					}
X					pline ("A trap door opens up under you!");
X					if (u.ufloat || u.ustuck) {
X						pline ("For some reason you don't fall in.");
X						break;
X					}
X					more ();
X					keepdogs (1);
X					unCoff (COFF, 1);
X					do {
X						dosavelev ();
X						dodown ();
X						levl[u.ux][u.uy].scrsym = '<';
X					} while (!rn2 (4) && xdnstair);
X					land ();
X					losedogs ();
X					setCon (CON);
X					inshop ();/* a3:zie tele */
X					break;
X
X				case DART: 
X					pline ("A little dart shoots out at you!");
X					if (hitu (7, rnd (3), "little dart") &&
X							!rn2 (6))
X						poisoned ("dart", "poison dart");
X					break;
X
X				case TELE: 
X					newsym (u.ux, u.uy);
X					tele ();
X					break;
X
X				case PIT: 
X					if (u.ufloat) {
X						pline ("A pit opens up under you!");
X						pline ("You don't fall in!");
X						break;
X					}
X					pline ("You fall into a pit!");
X					u.utrap = rn1 (6, 2);
X					u.upit = 1;
X					losehp (rnd (6), "pit");
X					break;
X
X				default: 
X					pline ("Bad(%d)trap", trap -> gflag);
X					impossible ();
X			}
X		}
X	}
X	if (tmpr -> typ == DOOR && dlevel) {
X		inshop ();
X		switch (rooms[inroom (u.ux, u.uy)].rtype) {
X			case ZOO: 
X				if (!u.uinzoo) {
X					pline ("Welcome to the Zoo!");
X					u.uinzoo++;
X				}
X				break;
X			case GRAVEYARD: 
X				if (!u.uinyard) {
X					pline ("Welcome to the Graveyard!");
X					u.uinyard++;
X				}
X				break;
X			case SWAMP: 
X				if (!u.uinswamp) {
X					pline ("Welcome to the Swamp!");
X					u.uinswamp++;
X				}
X				break;
X			case FORT_KNOX: 
X				if (!u.uinknox) {
X					pline ("Welcome to Fort Knox!");
X					u.uinknox++;
X				}
X				break;
X			default: 
X				break;/* Who knows what more may come */
X		}
X	}
X	if (tmpr -> typ == CORR) {
X		if (u.uinshop)
X			inshop ();/* Outside shop now */
X		u.uinzoo = 0;	/* You left the Zoo ?? */
X		u.uinyard = 0;	/* You left the Graveyard ?? */
X		u.uinswamp = 0;	/* You left the Swamp ?? */
X		u.uinknox = 0;	/* You left Fort Knox ?? */
X	}
X	if (tmpr -> typ == POOL)
X		if (!u.ufloat) {
X			pline ("You fall into a pool!");
X			pline ("You can't swim!");
X			pline ("You drown...");
X			more ();
X			killer = "Pool of water";
X			done (DROWNED);
X		}
X}
X
X/* Stop running if we see something interesting */
Xlookaround () {
X	register        x, y, corrct = 0;
X	register        MONSTER mtmp;
X
X	if (u.ublind || flags.run < 2)
X		return;
X	for (x = u.ux - 1; x <= u.ux + 1; x++)
X		for (y = u.uy - 1; y <= u.uy + 1; y++) {
X			if (x == u.ux && y == u.uy)
X				continue;
X/* Note: we cannot call r_free: perhaps a M is hidden in the wall */
X			if (!levl[x][y].typ)
X				continue;
X			if (mtmp = m_at (x, y))
X				if (!mtmp -> mtame || (x == u.ux + dx &&
X							y == u.uy + dy)) {
X					nomul (0);
X					return;
X				}
X			if (x == u.ux - dx && y == u.uy - dy)
X				continue;
X			if (mtmp)
X				corrct++;
X			else
X				switch (levl[x][y].scrsym) {
X					case '+': 
X						if (x == u.ux || y == u.uy) {
X							nomul (0);
X							return;
X						}
X					case '0': 
X						multi = 0;
X						flags.run = 0;
X						return;
X					case '.': 
X					case '|': 
X					case '-': 
X						break;
X					case '#': 
X						corrct++;
X						break;
X					default: 
X						nomul (0);
X						return;
X				}
X		}
X	if (corrct > 1 && flags.run == 2)
X		nomul (0);
X}
X
Xnomul (nval)
Xregister        nval;
X{
X	if (multi < 0)
X		return;
X	if (flags.mv)
X		pru ();
X	multi = nval;
X	flags.mv = 0;
X	flags.run = 0;
X}
X
Xchar   *
X        parse () {
X	static char     inline[80];
X	register        foo;
X
X	oldux = 0;
X	olduy = 0;
X	flags.move = 1;
X	if (!u.uinvis)
X		curs (u.ux, u.uy + 2);
X	else
X		home ();
X	flush ();
X	while ((foo = getchar ()) >= '0' && foo <= '9')
X		multi += 10 * multi + foo - '0';
X	if (multi) {
X		multi--;
X		save_cm = inline;
X	}
X	inline[0] = foo;
X	inline[1] = 0;
X	if (foo == 'f' || foo == 'F') {
X		inline[1] = getchar ();
X		inline[2] = 0;
X	}
X	if (flags.topl) {
X		home ();
X		cl_end ();
X		flags.topl = 0;
X	}
X	return (inline);
X}
X
Xnomove () {
X	multi = 0;
X	flags.move = 0;
X}
/
echo 'x - hack.shk.c'
sed 's/^X//' > hack.shk.c << '/'
X/*
X * Hack.shk.c
X */
X
X#include "hack.h"
X
X#define BILLSZ  200
X#define ONBILL    1
X#define NOTONBILL 0
X#define GDIST(x, y)     ((x - gx)*(x - gx) + (y - gy)*(y - gy) )
X
Xstruct {
X	OBJECT op;
Xunsigned        useup:                 1;
Xunsigned        bquan:                 5;
X	unsigned        price;
X}       bill[BILLSZ];
X
XMONSTER shopkeeper;
X
Xstruct permonst shk_pm = {
X	"shopkeeper", '@', 10, 12, 0, 4, 8, 0
X};
X
Xlong    robbed = 0, total;
X
X/*
X * shoproom = index in rooms; set by inshop()
X * shlevel  = last level we initialized shopkeeper
X */
X
Xchar    billct = 0, shoproom, shlevel;
Xchar   *shopnam[] = {
X	"engagement ring", "walking cane", "antique weapon",
X	"delicatessen", "second hand book", "liquor",
X	"used armor", "assorted antiques"
X};
X
XCOORDINATES shk, shd;
X /* Usual position shopkeeper;position shop door */
X
X#define SHOP_NAME               shopnam[rooms[shoproom].rtype - 8]
X
Xshkdead () {
X	shopkeeper = 0;
X	rooms[shoproom].rtype = 0;
X	setpaid ();
X}
X
Xsetpaid () {
X	register        tmp;
X	register        OBJECT obj;
X
X	for (obj = invent; obj; obj = obj -> nobj)
X		obj -> unpaid = 0;
X	for (tmp = 0; tmp < billct; tmp++)
X		if (bill[tmp].useup)
X			ofree (bill[tmp].op);
X	billct = 0;
X}
X
Xaddupbill () {			/* Delivers result in total */
X	register        ct = billct;
X
X	total = 0;
X	while (ct--)
X		total += bill[ct].price;
X}
X
Xinshproom (x, y)
Xregister        x, y;		/* a3 */
X{
X	return (inroom (x, y) == shoproom);
X}
X
Xinshop () {
X	register        tmp = inroom (u.ux, u.uy);
X
X	if (tmp < 0 || rooms[tmp].rtype < 8) {
X		u.uinshop = 0;
X		if (billct) {
X			pline ("Somehow you escaped the shop without paying!");
X			addupbill ();
X			pline ("You stole for a total worth of %U zorkmids.", total);
X			robbed += total;
X			setpaid ();
X		}
X	}
X	else {
X		shoproom = tmp;
X		if (shlevel != dlevel)
X			shopinit ();
X		if (!u.uinshop) {
X			pline ("%s to Dirk's %s shop!",
X					(shopkeeper -> angry) ?
X					"You're not that welcome" : "Welcome",
X					SHOP_NAME);
X			++u.uinshop;
X		}
X	}
X	return (u.uinshop);
X}
X
X/* Called by useup and dothrow only */
Xonbill (obj)
Xregister        OBJECT obj;
X{
X	register        tmp;
X
X	for (tmp = 0; tmp < billct; tmp++)
X		if (bill[tmp].op == obj) {
X			bill[tmp].useup = 1;
X			obj -> unpaid = 0;/* only for doinvbill */
X			return (ONBILL);
X		}
X	return (NOTONBILL);
X}
X
Xdopay () {
X	register unsigned       tmp;
X	char    buffer[BUFSZ];
X
X	multi = 0;
X	if (!inshop ()) {
X		flags.move = 0;
X		pline ("You are not in a shop.");
X		return;
X	}
X
X	if (!shopkeeper || !inshproom (shopkeeper -> mx,
X				shopkeeper -> my)) {
X		pline ("There is nobody here to receive your payment.");
X		return;
X	}
X	if (!billct) {
X		pline ("You do not owe the shopkeeper anything.");
X		if (!u.ugold) {
X			pline ("Moreover, you have no money.");
X			return;
X		}
X		if (robbed) {
X			pline ("But since the shop has been robbed recently");
X			pline ("You %srepay the shopkeeper's expenses.", (u.ugold < robbed) ?
X					"partially " : "");
X			u.ugold -= robbed;
X			if (u.ugold < 0)
X				u.ugold = 0;
X			flags.dgold = 1;
X			robbed = 0;
X			return;
X		}
X		if (shopkeeper -> angry) {
X			pline ("But in order to appease the angry shopkeeper,");
X			if (u.ugold >= 1000L) {
X				tmp = 1000;
X				pline ("You give him 1000 gold pieces.");
X			}
X			else {
X				tmp = (int) u.ugold;
X				pline ("You give him all your money.");
X			}
X			u.ugold -= (long) tmp;
X			flags.dgold = 1;
X			if (rn2 (3)) {
X				pline ("The shopkeeper calms down.");
X				shopkeeper -> angry = 0;
X			}
X			else
X				pline ("The shopkeeper is as angry as ever.");
X		}
X		return;
X	}
X
X	while (billct) {
X		billct--;
X		bill[billct].op -> unpaid = 0;
X		doname (bill[billct].op, buffer);
X		tmp = bill[billct].price;
X		if (shopkeeper -> angry)
X			tmp += tmp / 3;
X		if (u.ugold < tmp) {
X			++bill[billct].op -> unpaid;
X			billct++;
X			pline ("You don't have gold enough to pay %s.",
X					buffer);
X			return;
X		}
X		u.ugold -= tmp;
X		flags.dgold = 1;
X		pline ("You bought %s for %d gold pieces.", buffer, tmp);
X		if (bill[billct].useup)
X			ofree (bill[billct].op);
X	}
X	pline ("Thank you for shopping in Dirk's %s store!",
X			SHOP_NAME);
X	shopkeeper -> angry = 0;
X}
X
Xpaybill () {			/* Called after dying (or quitting) with
X				   nonempty bill */
X	if (shopkeeper) {
X		addupbill ();
X		if (total > u.ugold) {
X			u.ugold = 0;
X			if (invent)
X				pline ("The shopkeeper comes and takes all your possessions.");
X		}
X		else {
X			u.ugold -= total;
X			pline ("The shopkeeper comes and takes the %D zorkmids you owed him.",
X					total);
X		}
X	}
X	more ();
X}
X
Xaddtobill (obj)
Xregister        OBJECT obj;
X{
X	if (!inshop ())
X		return;
X	if (billct == BILLSZ) {
X		pline ("You got that for free!");
X		return;
X	}
X	bill[billct].op = obj;
X	bill[billct].bquan = obj -> quan;
X	bill[billct].useup = 0;
X	bill[billct++].price = getprice (obj);
X	obj -> unpaid = 1;
X}
X
Xsubfrombill (obj)
Xregister        OBJECT obj;
X{
X	register        tmp;
X	register        OBJECT otmp;
X
X	if (!inshop ())
X		return;
X	for (tmp = 0; tmp < billct; tmp++)
X		if (bill[tmp].op == obj) {
X			obj -> unpaid = 0;
X			if (bill[tmp].bquan != obj -> quan) {
X				bill[tmp].op = otmp = newobj ();
X				*otmp = *obj;
X				otmp -> quan = (bill[tmp].bquan -=
X						obj -> quan);
X				bill[tmp].price *= otmp -> quan;
X				bill[tmp].price /= (otmp -> quan +
X						obj -> quan);
X				bill[tmp].useup = 1;
X				return;
X			}
X			billct--;
X			bill[tmp] = bill[billct];
X			return;
X		}
X/* I dropped something of my own, wanting to sell it */
X	if (shopkeeper -> msleep || shopkeeper -> mfroz ||
X			!inshproom (shopkeeper -> mx, shopkeeper -> my) ||
X			robbed || u.ux == shk.x && u.uy == shk.y ||
X			u.ux == shd.x && u.uy == shd.y)
X		return;
X	tmp = getprice (obj);
X	if (shopkeeper -> angry) {
X		tmp /= 3;
X		shopkeeper -> angry = 0;
X	}
X	else
X		tmp >>= 1;
X	if (tmp < 2)
X		tmp = 2;
X	u.ugold += tmp;
X	flags.dgold = 1;
X	doname (obj, buf);
X	pline ("You sold %s and got %d gold pieces.", buf, tmp);
X}
X
Xdoinvbill () {
X	register unsigned       tmp, cnt = 0;
X
X	for (tmp = 0; tmp < billct; tmp++)
X		if (bill[tmp].useup) {
X			if (!cnt && !flags.oneline) {
X				getret ();
X				cls ();
X				printf ("\n\nUnpaid articles already used up:\n\n");
X			}
X			strcpy (buf, "* -  ");
X			doname (bill[tmp].op, &buf[5]);
X			for (cnt = 0; buf[cnt]; cnt++);
X			while (cnt < 50)
X				buf[cnt++] = ' ';
X			sprintf (&buf[cnt], " %5d zorkmids",
X					bill[tmp].price);
X			if (flags.oneline)
X				pline (buf);
X			else
X				printf ("%s\n", buf);
X			if (!cnt % 20)
X				getret ();
X		}
X}
X
Xgetprice (obj)
Xregister        OBJECT obj;
X{
X	register        tmp, ac;
X
X	switch (obj -> olet) {
X		case '"': 
X			tmp = rnd (500);
X			break;
X		case '=': 
X		case '/': 
X			tmp = rnd (100);
X			break;
X		case '?': 
X		case '!': 
X			tmp = rnd (50);
X			break;
X		case '*': 
X			tmp = rnd (6);
X			break;
X		case '%': 
X			tmp = rnd (5 + 2000 / realhunger ());
X			break;
X		case '[': 
X			ac = obj -> spe;
X			tmp = (100 + ac * ac * rnd (10 + ac)) / 10;
X			break;
X		case ')': 
X			if (obj -> otyp <= W_AMMUNITION)
X				tmp = rnd (10);
X			else if (obj -> otyp == W_LONG_SWORD || obj -> otyp ==
X					W_TWOH_SWORD)
X				tmp = rnd (150);
X			else
X				tmp = rnd (75);
X			break;
X		case '_': 
X		default: 
X			tmp = 1000;
X	}
X	return (10 * obj -> quan * tmp);
X}
X
Xrealhunger () {			/* not completely foolproof (??) */
X	register        tmp = u.uhunger;
X	register        OBJECT otmp = invent;
X
X	while (otmp) {
X		if (otmp -> olet == '%' && !otmp -> unpaid)
X			tmp += foods[otmp -> otyp].nutrition;
X		otmp = otmp -> nobj;
X	}
X	return tmp;
X}
X
Xshopinit () {
X	register        MKROOM * sroom = &rooms[shoproom];
X	register        i, j, x, y;
X
X	shlevel = dlevel;
X	shd = doors[sroom -> fdoor];
X	shk.x = shd.x;
X	shk.y = shd.y;
X	if (shk.x == sroom -> lx - 1)
X		shk.x++;
X	else if (shk.x == sroom -> hx + 1)
X		shk.x--;
X	else if (shk.y == sroom -> ly - 1)
X		shk.y++;
X	else if (shk.y == sroom -> hy + 1)
X		shk.y--;
X	else {
X		sroom -> rtype = 0;
X		pline ("Where is shopdoor?");
X		impossible ();
X		return;
X	}
X	if (shopkeeper)
X		return;		/* We have been on this level before */
X	if (makemon (&shk_pm))
X		panic (CORE, "Cannot create shopkeeper?");
X	shopkeeper = fmon;
X	shopkeeper -> angry = u.uhcursed;
X	if (m_at (shk.x, shk.y) || (shk.x == u.ux && shk.y == u.uy)) {
X	/* (a3)`mnexto(shopkeeper)' is fout gaan */
X		prl (shk.x, shk.y);
X		for (i = -1; i < 2; i++)
X			for (j = -1; j < 2; j++)
X				if (levl[x = shk.x + i][y = shk.y + j].typ ==
X						ROOM)
X					if (!m_at (x, y)) {
X						fmon -> mx = x;
X						fmon -> my = y;
X						pmon (shopkeeper);
X						return;
X					}
X		fmon -> mx = shk.x;
X		fmon -> my = shk.y;
X		return;		/* bovenop een ander monster */
X	}
X	else {
X		fmon -> mx = shk.x;
X		fmon -> my = shk.y;
X	}
X	pmon (shopkeeper);
X}
X
Xsetangry () {
X	if (shopkeeper -> data -> mlet == '@' && !shopkeeper -> angry) {
X		pline ("The shopkeeper gets angry.");
X		++shopkeeper -> angry;
X	}
X}
X
Xshk_move () {
X	register        MONSTER mtmp;
X	char    gx, gy, omx, omy, cnt, appr,
X	        nix, niy, ddx, ddy, zx, zy, num;
X
X	omx = shopkeeper -> mx;
X	omy = shopkeeper -> my;
X	if (!u.uinshop && inshproom (omx, omy) &&
X			levl[omx][omy].typ == ROOM)
X		return NOMOVE;
X	if (shopkeeper -> angry && dist (omx, omy) < 3) {
X		hitu (shk_pm.mhd, d (shk_pm.damn, shk_pm.damd),
X				shk_pm.mname);
X		return NOMOVE;
X	}
X	appr = 1;
X	if ((shopkeeper -> angry) && !u.uinvis) {
X		gx = u.ux;	/* Fred */
X		gy = u.uy;
X	}
X	else if (shk.x == omx && shk.y == omy && !billct &&
X				!shopkeeper -> angry &&
X				(!robbed || (u.ux == shd.x && u.uy == shd.y)) &&
X			dist (omx, omy) < 3) {
X		appr = 0;
X		gx = 0;
X		gy = 0;
X	}
X	else {
X		gx = shk.x;
X		gy = shk.y;
X	}
X	cnt = 0;
X	if (omx == gx && omy == gy)
X		return NOMOVE;
X	if (shopkeeper -> mconf)
X		appr = 0;
X	nix = omx;
X	niy = omy;
X	for (ddx = -1; ddx <= 1; ddx++)
X		for (ddy = -1; ddy <= 1; ddy++) {
X			zx = omx + ddx;
X			zy = omy + ddy;
X			num = levl[zx][zy].typ;/* a3 */
X			if ((ddx || ddy) && (num == ROOM || !inshproom (omx, omy)
X						&& (num == CORR || num == DOOR)) &&
X					(shopkeeper -> mconf ||
X						((zx != u.ux || zy != u.uy) && !m_at (zx, zy))) &&
X					(!appr && !rn2 (++cnt) || appr && GDIST (zx, zy) <
X						GDIST (nix, niy))) {
X				nix = zx;
X				niy = zy;
X			}
X		}
X	if (nix != omx || niy != omy) {
X		if (shopkeeper -> mconf && (mtmp = m_at (nix, niy))) {
X			if (hitmm (shopkeeper, mtmp) == 1 && rn2 (3)
X					&& hitmm (mtmp, shopkeeper) == DEAD)
X				return DEAD;
X			return NOMOVE;
X		}
X		shopkeeper -> mx = nix;
X		shopkeeper -> my = niy;
X/* The shopkeeper might have been turned into an X */
X		levlsym (omx, omy, shopkeeper -> data -> mlet);
X		pmon (shopkeeper);
X		return MOVE;
X	}
X	return NOMOVE;
X}
/
echo 'x - mklev.svlev.c'
sed 's/^X//' > mklev.svlev.c << '/'
X/*
X * Mklev.savelev.c
X */
X
Xsavelev () {
X	register int    fd;
X	register        MONSTER mtmp, mtmp2;
X	register        GOLD_TRAP gtmp, gtmp2;
X	register        OBJECT otmp, otmp2;
X	int     minusone = -1;
X
X	if ((fd = creat (tfile, 0644)) < 0)
X		panic ("Cannot create %s\n", tfile);
X	bwrite (fd, levl, sizeof (levl));
X	bwrite (fd, nul, sizeof (unsigned));
X	bwrite (fd, (char *) & xupstair, 1);
X	bwrite (fd, (char *) & yupstair, 1);
X	bwrite (fd, (char *) & xdnstair, 1);
X	bwrite (fd, (char *) & ydnstair, 1);
X	for (mtmp = fmon; mtmp; mtmp = mtmp2) {
X		mtmp2 = mtmp -> nmon;
X		bwrite (fd, &mtmp -> mxlth, sizeof (int));
X		bwrite (fd, mtmp, mtmp -> mxlth + sizeof (struct monst));
X
X/* Michiel save stolen objects */
X		bwrite (fd, nul, sizeof (struct stole));
X	}
X	bwrite (fd, &minusone, sizeof (int));
X	for (gtmp = fgold; gtmp; gtmp = gtmp2) {
X		gtmp2 = gtmp -> ngen;
X		bwrite (fd, gtmp, sizeof (struct gen));
X		free (gtmp);
X	}
X	bwrite (fd, nul, sizeof (struct gen));
X	for (gtmp = ftrap; gtmp; gtmp = gtmp2) {
X		gtmp2 = gtmp -> ngen;
X		bwrite (fd, gtmp, sizeof (struct gen));
X		free (gtmp);
X	}
X	bwrite (fd, nul, sizeof (struct gen));
X	for (otmp = fobj; otmp; otmp = otmp2) {
X		otmp2 = otmp -> nobj;
X		bwrite (fd, otmp, sizeof (struct obj));
X		free (otmp);
X	}
X	bwrite (fd, nul, sizeof (struct obj));
X	bwrite (fd, rooms, sizeof (rooms));
X	bwrite (fd, doors, sizeof (doors));
X	fgold = TRAP_NULL;
X	ftrap = TRAP_NULL;
X	fmon = MON_NULL;
X	fobj = OBJ_NULL;
X}
X
X/*NOSTRICT*/
Xbwrite (fd, loc, num)
Xregister int    fd, num;
Xregister char  *loc;
X{
X	if (write (fd, loc, num) != num)
X		panic ("Cannot write %d bytes to file #%d", num, fd);
X}
/
echo 'Part 02 of Hack complete.'
exit
-- 

			Michiel Huisjes.
			{seismo|decvax|philabs}!mcvax!vu44!ark!huisjes

huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)

#!/bin/sh
#
# 
# 
# This is a shell archive. These archives are packed by the program 
# packmail(1). If you have the program unshar(1), I suggest you use it.
# If you don't remove anything before the cut line and then feed to
# sh(1)
# 
# =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE===
#
echo 'Start of Hack, part 03 of 05:'
echo 'x - hack.c'
sed 's/^X//' > hack.c << '/'
X/*
X * Hack.c
X */
X
X#include "hack.h"
X
Xextern char     news0 (), *setan ();
X
Xextern char     seelx, seehx, seely, seehy;/* Corners of lit room */
X /* l for Low, h for High */
X
X#define CANSEE 		1
X#define CANNOTSEE 	0
X#define HITYOU		1
X#define MISSYOU		0
X#define MONALIVE	1
X#define MONDEAD		0
X
X
Xchar   *
X        lowc (str)
Xregister char  *str;
X{
X	if (*str >= 'A' && *str <= 'Z')
X		*buf = *str + 'a' - 'A';
X	else
X		*buf = *str++;
X	buf[1] = 0;
X	return (buf);
X}
X
X/* (a3) mix van setsee() en seeon() */
XsetCon (setc) {			/* setc: 1-setsee, 0-seeon (we just went to a
X				   new level) */
X	register        x, y;
X	register        MONSTER mtmp;
X	int     lx, hx, ly, hy;
X
X	if (u.ublind) {
X		if (setc)
X			pru ();
X		else
X			docrt ();
X		return;
X	}
X	if (levl[u.ux][u.uy].lit) {
X		for (seelx = u.ux; levl[seelx - 1][u.uy].lit; seelx--);
X		for (seehx = u.ux; levl[seehx + 1][u.uy].lit; seehx++);
X		for (seely = u.uy; levl[u.ux][seely - 1].lit; seely--);
X		for (seehy = u.uy; levl[u.ux][seehy + 1].lit; seehy++);
X		lx = seelx;
X		hx = seehx;
X		ly = seely;
X		hy = seehy;
X	}
X	else {
X		seehx = 0;
X		lx = u.ux - 1;
X		hx = u.ux + 1;
X		ly = u.uy - 1;
X		hy = u.uy + 1;
X		if (setc) {
X			seelx = lx;
X			seehx = hx;
X			seely = ly;
X			seehy = hy;
X		}
X	}
X	for (x = lx; x <= hx; x++)
X		for (y = ly; y <= hy; y++) {
X			if (setc)
X				prl (x, y);
X			else {
X				if (!levl[u.ux][u.uy].lit &&
X						!levl[x][y].typ)
X					continue;
X				levl[x][y].seen = 1;
X				if (mtmp = m_at (x, y))
X					pmon (mtmp);
X			}
X		}
X	if (!setc) {
X		docrt ();
X		return;
X	}
X	if (!levl[u.ux][u.uy].lit)
X		seehx = 0;	/* Seems necessary elsewhere */
X	else {
X		if (seely == u.uy)
X			for (x = u.ux - 1; x <= u.ux + 1; x++)
X				prl (x, seely - 1);
X		if (seehy == u.uy)
X			for (x = u.ux - 1; x <= u.ux + 1; x++)
X				prl (x, seehy + 1);
X		if (seelx == u.ux)
X			for (y = u.uy - 1; y <= u.uy + 1; y++)
X				prl (seelx - 1, y);
X		if (seehx == u.ux)
X			for (y = u.uy - 1; y <= u.uy + 1; y++)
X				prl (seehx - 1, y);
X	}
X}
X
XunCoff (unc, mode) {
X /* 
X  * (a3) mix van unsee() en seeoff()
X  * unc: 1-unsee, 0-seeoff
X  * mode: 1-redo @ (misc movement),
X  * 0-leave them (blindness (Usually))
X  */
X
X	register        x, y;
X	register        PART * lev;
X	int     lx, hx, ly, hy;
X
X	if (seehx) {
X		lx = seelx;
X		hx = seehx;
X		ly = seely;
X		hy = seehy;
X	}
X	else {
X		lx = u.ux - 1;
X		hx = u.ux + 1;
X		ly = u.uy - 1;
X		hy = u.uy + 1;
X	}
X	for (x = lx; x <= hx; x++)
X		for (y = ly; y <= hy; y++) {
X			lev = &levl[x][y];
X			if (lev -> scrsym == '@' && mode) {
X				if (unc)
X					newsym (x, y);
X				else
X					lev -> scrsym = news0 (x, y);
X			}
X			else if (!seehx && lev -> scrsym == '.') {
X				if (mode) {
X					if (unc) {
X						lev -> scrsym = ' ';
X						lev -> new = 1;
X						on (x, y);
X					}
X				}
X				else
X					lev -> seen = 0;
X			}
X		}
X	seehx = 0;
X}
X
Xhitu (mlev, dam, name)
Xregister        mlev, dam;
Xregister char  *name;
X{
X	mlev += (u.uac - 1);
X	if (multi < 0)
X		mlev += 4;
X	if (u.uinvis)
X		mlev -= 2;
X	if (mlev < rnd (20)) {
X		pseebl ("%s misses", name);
X		return (MISSYOU);
X	}
X	pseebl ("%s hits!", name);
X	if (name == NULL)
X		impossible ();
X	losehp (dam, name);
X	return (HITYOU);
X}
X
Xcansee (x, y)
Xchar    x, y;
X{
X	if (u.ublind || u.uswallow)
X		return (CANNOTSEE);
X	if (dist (x, y) < 3)
X		return (CANSEE);
X	if (levl[x][y].lit && seelx <= x && x <= seehx && seely <= y &&
X			y <= seehy)
X		return (CANSEE);
X	return (CANNOTSEE);
X}
X
Xlong
X        pow (num)
Xregister        num;		/* Returns 2^num */
X{
X	return (1 << num);
X}
X
Xland () {			/* a3 */
X	do {
X		u.ux = rn2 (80);
X		u.uy = rn2 (22);
X	} while (levl[u.ux][u.uy].typ != ROOM || m_at (u.ux, u.uy));
X}
X
Xtele () {
X	unCoff (UNC, 0);	/* Dat was een 1 (a3) */
X	unstuck (u.ustuck);	/* a3 */
X	u.utrap = 0;
X	do
X		land ();
X	while (o_at (u.ux, u.uy) || g_at (u.ux, u.uy, ftrap) ||
X			g_at (u.ux, u.uy, fgold));
X	setCon (SETC);
X	inshop ();
X}
X
Xchar   *
X        sitoa (a)
Xregister int    a;
X{
X	static char     buffer[8];
X
X	sprintf (buffer, "+%d", a);
X	return ((a < 0) ? buffer + 1 : buffer);
X}
X
Xdoname (obj, buffer)
Xregister        OBJECT obj;
Xregister char  *buffer;
X{
X	switch (obj -> olet) {
X
X		case '"': 
X			strcpy (buffer, "The amulet of Frobozz");
X			break;
X
X		case '%': 
X			if (obj -> quan > 1)
X				sprintf (buffer, "%d %ss", obj -> quan,
X						foods[obj -> otyp].foodnam);
X			else
X				strcpy (buffer, setan (foods[obj -> otyp].foodnam));
X			break;
X
X		case ')': 
X			killer = weapons[obj -> otyp].wepnam;/* a3 */
X			if (obj -> known) {
X				if (obj -> quan > 1)
X					sprintf (buffer, "%d %s %ss", obj -> quan,
X							sitoa (obj -> spe), killer);
X				else
X					sprintf (buffer, "a %s %s", sitoa (obj -> spe),
X							killer);
X			}
X			else {
X				if (obj -> quan > 1)
X					sprintf (buffer, "%d %ss", obj -> quan,
X							killer);
X				else
X					strcpy (buffer, setan (killer));
X			}
X			if (obj == uwep)
X				strcat (buffer, " (weapon in hand)");
X			break;
X
X		case '[': 
X			if (obj -> known)
X				sprintf (buffer, "%s %s",
X						sitoa (obj -> spe - 10 + armors[obj -> otyp].a_ac),
X						armors[obj -> otyp].armnam);
X			else
X				strcpy (buffer, armors[obj -> otyp].armnam);
X			if (obj == uarm || obj == uarm2)
X				strcat (buffer, " (being worn)");
X			break;
X
X		case '!': 
X			if (oiden[obj -> otyp] & POTN || potcall[obj -> otyp]) {
X				if (obj -> quan > 1)
X					sprintf (buffer, "%d potions ", obj -> quan);
X				else
X					strcpy (buffer, "a potion ");
X				while (*buffer)
X					buffer++;
X				if (potcall[obj -> otyp])
X					sprintf (buffer, "called %s",
X							potcall[obj -> otyp]);
X				else
X					sprintf (buffer, "of %s",
X							pottyp[obj -> otyp]);
X			}
X			else {
X				killer = " potion";
X		P: 
X				if (obj -> quan > 1)
X					sprintf (buffer, "%d %s%ss", obj -> quan,
X							potcol[obj -> otyp], killer);
X				else
X					sprintf (buffer, "%s%s",
X							setan (potcol[obj -> otyp]),
X							killer);
X			}
X			break;
X
X		case '?': 
X			if (obj -> quan > 1)
X				sprintf (buffer, "%d scrolls ", obj -> quan);
X			else
X				strcpy (buffer, "a scroll ");
X			while (*buffer)
X				buffer++;
X			if (oiden[obj -> otyp] & SCRN)
X				sprintf (buffer, "of %s", scrtyp[obj -> otyp]);
X			else if (scrcall[obj -> otyp])
X				sprintf (buffer, "called %s", scrcall[obj -> otyp]);
X			else
X				sprintf (buffer, "labeled %s", scrnam[obj -> otyp]);
X			break;
X
X		case '/': 
X			if (oiden[obj -> otyp] & WANN)
X				sprintf (buffer, "a wand of %s", wantyp[obj -> otyp]);
X			else if (wandcall[obj -> otyp])
X				sprintf (buffer, "a wand called %s",
X						wandcall[obj -> otyp]);
X			else
X				sprintf (buffer, "%s wand",
X						setan (wannam[obj -> otyp]));
X			if (obj -> known) {
X				while (*buffer)
X					buffer++;
X				sprintf (buffer, " (%d)", obj -> spe);
X			}
X			break;
X
X		case '=': 
X			if (oiden[obj -> otyp] & RINN) {
X				if (obj -> known)
X					sprintf (buffer, "a %s ring of %s",
X							sitoa (obj -> spe),
X							ringtyp[obj -> otyp]);
X				else
X					sprintf (buffer, "a ring of %s",
X							ringtyp[obj -> otyp]);
X			}
X			else if (ringcall[obj -> otyp])
X				sprintf (buffer, "a ring called %s",
X						ringcall[obj -> otyp]);
X			else
X				sprintf (buffer, "%s ring",
X						setan (rinnam[obj -> otyp]));
X			if (obj == uright)
X				strcat (buffer, " (on right hand)");
X			if (obj == uleft)
X				strcat (buffer, " (on left hand)");
X			break;
X
X		case '*': 
X			killer = " gem";
X			goto P;
X
X		case '_': 
X			sprintf (buffer, "%s key",
X					setan (potcol[obj -> otyp - 30]));
X			break;
X
X		default: 
X			sprintf (buffer, "a%dglorkum %c(0%o)%d", obj -> otyp,
X					obj -> olet, obj -> olet, obj -> spe);
X	}
X	if (obj -> unpaid)
X		strcat (buffer, " (unpaid)");
X}
X
Xabon () {
X	if (u.ustr == 3)
X		return - 3;
X	if (u.ustr < 6)
X		return - 2;
X	if (u.ustr < 8)
X		return - 1;
X	if (u.ustr < 17)
X		return 0;
X	if (u.ustr < 69)
X		return 1;	/* up to 18/50 */
X	if (u.ustr < 118)
X		return 2;
X	return 3;
X}
X
Xdbon () {
X	if (u.ustr < 6)
X		return - 1;
X	if (u.ustr < 16)
X		return 0;
X	if (u.ustr < 18)
X		return 1;
X	if (u.ustr == 18)
X		return 2;	/* up to 18 */
X	if (u.ustr < 94)
X		return 3;	/* up to 18/75 */
X	if (u.ustr < 109)
X		return 4;	/* up to 18/90 */
X	if (u.ustr < 118)
X		return 5;	/* up to 18/99 */
X	return 6;		/* 18/00 */
X}
X
Xlosestr (num)
Xregister        num;
X{
X	u.ustr -= num;
X	while (u.ustr < 3) {
X		u.ustr++;
X		u.uhp -= 6;
X		u.uhpmax -= 6;
X		flags.dhp = flags.dhpmax = 1;
X	}
X	flags.dstr = 1;
X}
X
Xlosehp (n, knam)
Xregister        n;
Xchar   *knam;
X{
X	u.uhp -= n;
X	flags.dhp = 1;
X	if (u.uhp <= 0)
X		killer = knam;
X}
X
Xchar   *
X        setan (str)
Xregister char  *str;		/* a3 */
X{
X	static char     buffer[BUFSZ];
X
X	sprintf (buffer, "a%s %s", index ("aeiou", *str) ? "n" : "", str);
X	return buffer;
X}
X
Xweight (obj)
Xregister        OBJECT obj;
X{
X	switch (obj -> olet) {
X		case '"': 
X			return 2;
X		case '[': 
X			return 8;
X		case '%': 
X			if (obj -> otyp)/* Not a food ration */
X		case '*': 
X				return obj -> quan;
X		case '?': 
X			return (obj -> quan * 3);
X		case '!': 
X			return (obj -> quan << 1);
X		case ')': 
X			if (obj -> otyp == W_TWOH_SWORD)
X				return 4;
X			if (obj -> otyp <= W_AMMUNITION)/* darst arrows etc */
X				return (obj -> quan >> 1);
X		case '/': 
X			return 3;
X		case '_': 
X		case '=': 
X			return 1;
X		default: 
X			pline ("Weight: bad(%d) object 0%o.", obj -> otyp,
X					obj -> olet);
X			return 0;
X	}
X}
X
Xchar    mlarge[] = "bCDdegIlmnoPSsTUwY',&";
X
Xhmon (monst, obj)
Xregister        MONSTER monst;
Xregister        OBJECT obj;
X{
X	register        tmp;
X
X	if (!obj || obj == uwep && (obj -> otyp >= W_USE_AMMO ||
X				obj -> otyp <= W_AMMUNITION))
X		tmp = rnd (2);
X	else {
X		if (index (mlarge, monst -> data -> mlet)) {
X			tmp = rnd (weapons[obj -> otyp].wldam);
X			if (obj -> otyp == W_TWOH_SWORD)
X				tmp += d (2, 6);
X			else if (obj -> otyp == W_LONG_SWORD)
X				tmp += rnd (4);
X		}
X		else {
X			tmp = rnd (weapons[obj -> otyp].wsdam);
X			if (obj -> otyp == W_FLAIL || obj -> otyp == W_MACE)
X				tmp++;
X		}
X		tmp += obj -> spe;
X	}
X	tmp += u.udaminc + dbon ();
X	if (u.uswallow) {
X		if (monst -> data -> mlet == 'P')
X			tmp++;
X	}
X	else if (tmp <= 0)
X		tmp = 1;
X	monst -> mhp -= tmp;
X	return alive (monst);
X}
X
Xalive (monst)
Xregister        MONSTER monst;
X{
X	if (monst -> mhp > 0)
X		return (MONALIVE);
X	killed (monst);
X	return (MONDEAD);
X}
/
echo 'x - hack.dog.c'
sed 's/^X//' > hack.dog.c << '/'
X/*
X * Hack.dog.c
X */
X
X#include        "hack.h"
X#include        "hack.dog.h"
X
X#define UNDEF   127		/* Some large number */
X#define EDOG(mp)        ( (struct edog *)(&(mp->mextra[0])) )
X
Xextern struct permonst  li_dog, dog, la_dog;
X
Xchar    SADFEEL[] = "You have a sad feeling for a moment, then it passes";
X
Xmakedog () {
X	if (makemon (&li_dog))
X		return;		/* Dogs were genocided */
X	mnexto (fmon);
X	initedog (fmon);
X}
X
Xinitedog (mtmp)
Xregister        MONSTER mtmp;
X{
X	mtmp -> mtame = 1;
X	EDOG (mtmp) -> hungrytime = 1000 + moves;
X	EDOG (mtmp) -> eattime = 0;
X	EDOG (mtmp) -> droptime = 0;
X	EDOG (mtmp) -> dropdist = 10000;
X	EDOG (mtmp) -> apport = 10;
X	EDOG (mtmp) -> carry = 0;
X}
X
X/* Attach the monsters that went down (or up) together with @ */
X
XMONSTER mydogs = 0;
X
Xlosedogs () {
X	register        MONSTER mtmp;
X
X	while (mtmp = mydogs) {
X		mydogs = mtmp -> nmon;
X		mtmp -> nmon = fmon;
X		fmon = mtmp;
X		mnexto (mtmp);
X	}
X}
X
Xkeepdogs (checkdist)
Xint     checkdist;
X{
X	register        MONSTER mtmp;
X	register        PART * dr;
X
X	for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon)
X		if (mtmp -> mtame) {
X			if (checkdist && dist (mtmp -> mx, mtmp -> my) > 2) {
X				mtmp -> mtame = 0;/* Dog becomes wild */
X				mtmp -> mxlth = 0;
X				continue;
X			}
X			relmon (mtmp);
X			mtmp -> nmon = mydogs;
X			mydogs = mtmp;
X			dr = &levl[mtmp -> mx][mtmp -> my];
X			if (dr -> scrsym == mtmp -> data -> mlet)
X				dr -> scrsym = news0 (mtmp -> mx, mtmp -> my);
X		/* We destroyed the link, so use recursion */
X			keepdogs (checkdist);
X			return;	/* (admittedly somewhat primitive) */
X		}
X}
X
X#define GDIST(x, y) ((x - gx)*(x - gx) + (y - gy)*(y - gy) )
X#define DDIST(x, y) ((x - omx)*(x - omx) + (y - omy)*(y - omy) )
X
Xdog_move (mtmp, after)
Xregister        MONSTER mtmp;
X{
X	register        MONSTER mtmp2;
X	register struct edog   *edog = EDOG (mtmp);
X	int     nix, niy, omx, omy, appr, nearer, cnt, udist, zx, zy;
X	register        OBJECT obj;
X	register        GOLD_TRAP trap;
X	char    ddx, ddy, dogroom, uroom,
X	        gx = 0, gy = 0, gtyp;/* Current goal */
X
X	if (moves <= edog -> eattime)
X		return NOMOVE;	/* Dog is still eating */
X	omx = mtmp -> mx;
X	omy = mtmp -> my;
X	if (moves > edog -> hungrytime + 500 && !mtmp -> mconf) {
X		mtmp -> mconf = 1;
X		mtmp -> orig_hp /= 3;
X		if (mtmp -> mhp > mtmp -> orig_hp)
X			mtmp -> mhp = mtmp -> orig_hp;
X		psee (0, omx, omy, "%s is confused from hunger",
X				mtmp -> data -> mname);
X	}
X	else if (moves > edog -> hungrytime + 750 || mtmp -> mhp <= 0) {
X		if (!psee (0, omx, omy, "%s dies from hunger",
X					mtmp -> data -> mname))
X			pline (SADFEEL);
X		levlsym (omx, omy, mtmp -> data -> mlet);
X		delmon (mtmp);
X		return DEAD;
X	}
X	dogroom = inroom (omx, omy);
X	uroom = inroom (u.ux, u.uy);
X	udist = dist (omx, omy);
X
X/*
X * if we are carrying stg then we drop it (perhaps near @ )
X * Note: if apport == 1 then our behaviour is independent of udist
X */
X	if (edog -> carry) {
X		if (!rn2 (udist) || !rn2 (edog -> apport))
X			if (rn2 (10) < edog -> apport) {
X				relobj (mtmp);
X				if (edog -> apport > 1)
X					edog -> apport--;
X				edog -> carry = 0;
X			}
X	}
X	else {
X		if (obj = o_at (omx, omy))
X			if (rn2 (20) < edog -> apport + 3)
X				if (rn2 (udist) || !rn2 (edog -> apport)) {
X					edog -> carry = 1;
X					freeobj (obj);
X					levlsym (omx, omy, obj -> olet);
X					stlobj (mtmp, obj);
X				}
X	}
X
X/* First we look for food */
X	gtyp = UNDEF;		/* No goal as yet */
X	obj = fobj;
X	while (obj) {
X		if (obj -> olet == '%'
X				&& inroom (obj -> ox, obj -> oy) == dogroom
X				&& (gtyp == UNDEF || (gtyp != 1 && obj -> otyp == 1)
X					|| (((gtyp != 1 && obj -> otyp < 5)
X							|| (gtyp == 1 && obj -> otyp == 1))
X						&& DDIST (obj -> ox, obj -> oy) < DDIST (gx, gy)))) {
X			gx = obj -> ox;
X			gy = obj -> oy;
X			gtyp = obj -> otyp;
X		}
X		else if ((gtyp == UNDEF || gtyp == 67) && dogroom >= 0
X					&& inroom (obj -> ox, obj -> oy) == dogroom
X					&& uroom == dogroom
X				&& !edog -> carry && edog -> apport > rn2 (8)) {
X			gx = obj -> ox;
X			gy = obj -> oy;
X			gtyp = 66 + obj -> cursed;/* Random */
X		}
X		obj = obj -> nobj;
X	}
X	if (gtyp == UNDEF
X			|| (gtyp != 1 && gtyp != 66 && moves < edog -> hungrytime)) {
X		if (dogroom < 0 || dogroom == uroom) {
X			gx = u.ux;
X			gy = u.uy;
X		}
X		else {
X			int     tmp = rooms[dogroom].fdoor;
X
X			cnt = rooms[dogroom].doorct;
X			gx = gy = 100;/* Random, far away */
X			while (cnt--) {
X				if (dist (gx, gy) > dist (doors[tmp].x,
X							doors[tmp].y)) {
X					gx = doors[tmp].x;
X					gy = doors[tmp].y;
X				}
X				tmp++;
X
X			}
X			if (gy == 100)
X				panic (CORE, "No doors nearby?");
X			if (gx == omx && gy == omy) {
X				gx = u.ux;
X				gy = u.uy;
X			}
X		}
X		appr = 0;
X		if (udist >= 9)
X			appr++;
X		else if (mtmp -> mflee)
X			appr--;
X		if (after && udist <= 4 && gx == u.ux && gy == u.uy)
X			return NOMOVE;
X		if (udist > 1) {
X			if (levl[u.ux][u.uy].typ < ROOM || !rn2 (4) ||
X					(edog -> carry && rn2 (edog -> apport)))
X				appr = 1;
X		}
X/* If you have dog food he'll follow you more closely */
X		if (appr == 0) {
X			obj = invent;
X			while (obj) {
X				if (obj -> olet == '%' && obj -> otyp == 1) {
X					appr = 1;
X					break;
X				}
X				obj = obj -> nobj;
X			}
X		}
X	}
X	else
X		appr = 1;
X	if (mtmp -> mconf)
X		appr = 0;
X	nix = omx;
X	niy = omy;
X	cnt = 0;
X	for (ddx = -1; ddx <= 1; ddx++)
X		for (ddy = -1; ddy <= 1; ddy++) {
X			if (!ddx && !ddy)
X				continue;
X			zx = omx + ddx;
X			zy = omy + ddy;
X			if (mtmp2 = m_at (zx, zy)) {
X				if (mtmp2 -> data -> mhd >= mtmp -> data -> mhd + 2)
X					continue;
X				if (mtmp2 -> mtame)
X					continue;
X				if (after)
X					return NOMOVE;
X			/* Hit only once each move */
X				if (hitmm (mtmp, mtmp2) == HIT && rn2 (4) &&
X						hitmm (mtmp2, mtmp) == DEAD)
X					return DEAD;
X				return NOMOVE;
X			}
X			if (r_free (zx, zy, mtmp) && !(ddx && ddy
X						&& (levl[omx][omy].typ == DOOR
X							|| levl[zx][zy].typ == DOOR))) {
X/* M_at(zx,zy) is impossible here */
X
X/* Dog avoids unseen traps */
X				if ((trap = g_at (zx, zy, ftrap))
X						&& !(trap -> gflag & SEEN) && rn2 (10))
X					continue;
X
X/* Dog eschewes cursed objects but likes dog food */
X				obj = fobj;
X				while (obj) {
X					if (obj -> ox != zx || obj -> oy != zy)
X						goto nextobj;
X					if (obj -> cursed)
X						goto newdxy;
X					if (obj -> olet == '%' &&
X							(obj -> otyp == 1 || (obj -> otyp < 5 &&
X									edog -> hungrytime <= moves))) {
X						nix = zx;
X						niy = zy;
X						edog -> eattime = moves +
X							foods[obj -> otyp].delay;
X						edog -> hungrytime = moves + 5 *
X							foods[obj -> otyp].nutrition;
X						if (cansee (nix, niy)) {
X
X							char    buffer[BUFSZ];
X
X							doname (obj, buffer);
X							pline ("The %s ate %s.", mtmp -> data -> mname, buffer);
X						}
X						delobj (obj);
X/* perhaps this was a reward */
X						edog -> apport += 200 / (edog -> dropdist + moves - edog -> droptime);
X						goto newdogpos;
X					}
X			nextobj: 
X					obj = obj -> nobj;
X				}
X
X				nearer = GDIST (zx, zy) - GDIST (nix, niy);
X				nearer *= appr;
X				if (!nearer && !rn2 (++cnt) || nearer < 0
X						|| nearer > 0 && (omx == nix && omy ==
X							niy && !rn2 (3) || !rn2 (12))) {
X					nix = zx;
X					niy = zy;
X					if (nearer < 0)
X						cnt = 0;
X				}
X			}
X	newdxy: 	;
X		}
Xnewdogpos: 
X	if (nix != omx || niy != omy) {
X		mtmp -> mx = nix;
X		mtmp -> my = niy;
X	}
X	levlsym (omx, omy, mtmp -> data -> mlet);
X	pmon (mtmp);
X	return MOVE;
X}
X
Xhitmm (magr, mdef)
Xregister        MONSTER magr, mdef;
X{
X	register        MONSTDATA pa = magr -> data;
X	register        MONSTDATA pd = mdef -> data;
X	int     hit;
X	char    tmp, vis;
X
X	if (index ("Eay", magr -> data -> mlet))
X		return NOMOVE;
X	tmp = pd -> ac + pa -> mhd - 1;
X	if (mdef -> mconf || mdef -> mfroz || mdef -> msleep) {
X		tmp += 4;
X		mdef -> msleep = 0;
X	}
X	hit = (tmp >= rnd (20));
X	vis = (cansee (magr -> mx, magr -> my) &&
X			cansee (mdef -> mx, mdef -> my));
X	if (vis)
X		pline ("The %s %s the %s.", pa -> mname,
X				(hit) ? "hits" : "misses", pd -> mname);
X	else
X		pline ("You hear some noises %s.",
X				(dist (magr -> mx, magr -> my) > 15) ? "in the distance"
X				: "");
X	if (hit) {
X		if ((mdef -> mhp -= d (pa -> damn, pa -> damd)) <= 0) {
X			if (vis)
X				p2xthe ("%s is killed!", pd -> mname);
X			else
X			if (mdef -> mtame)
X				pline (SADFEEL);
X			unstuck (mdef);/* a3 */
X			relobj (mdef);
X			levlsym (mdef -> mx, mdef -> my, pd -> mlet);
X			magr -> orig_hp += rnd (pd -> mhd + 1);
X			if (magr -> mtame && magr -> orig_hp >
X					pa -> mhd << 3) {
X				if (pa == &li_dog)
X					magr -> data = pa = &dog;
X				else if (pa == &dog)
X					magr -> data = pa = &la_dog;
X			}
X			delmon (mdef);
X			hit = DEAD;
X		}
X	}
X	return hit;
X}
X
X/* Return roomnumber or -1 */
Xinroom (x, y)
Xchar    x, y;
X{
X	register        MKROOM * croom = &rooms[0];
X
X	if (xdnstair && dlevel)	/* a3 */
X		while (croom -> hx >= 0) {
X			if (croom -> hx >= x - 1 && croom -> lx <= x + 1
X					&& croom -> hy >= y - 1 && croom -> ly <= y + 1)
X				return (croom - rooms);
X			croom++;
X		}
X	return - 1;		/* In corridor or in maze */
X}
X
X#define NOTTAME 0
X#define TAME    1
X
Xtamedog (mtmp, obj)
Xregister        MONSTER mtmp;
Xregister        OBJECT obj;
X{
X	register        MONSTER mtmp2;
X
X	if (obj -> otyp >= 5 || mtmp -> mtame)
X		return NOTTAME;
X	psee (0, mtmp -> mx, mtmp -> my, "%s devours %s.",
X			mtmp -> data -> mname, foods[obj -> otyp].foodnam);
X	delobj (obj);
X	mtmp2 = newmonst (sizeof (struct edog));
X	*mtmp2 = *mtmp;
X	mtmp2 -> mxlth = sizeof (struct edog);
X	initedog (mtmp2);
X	mtmp2 -> nmon = fmon;
X	fmon = mtmp2;
X	delmon (mtmp);		/* %% */
X	return TAME;
X}
/
echo 'x - hack.invinit.c'
sed 's/^X//' > hack.invinit.c << '/'
X/*
X * Hack.invinit.c
X */
X
X#include "hack.h"
X
X/*
X * struct obj {
X *     struct obj *nobj;
X *     char otyp, spe;
X *     ox, oy, olet, quan, known, cursed, unpaid
X * };
X */
X
Xstruct obj arrows0 = {
X	(struct obj *)0,
X	W_ARROW, 0, 0, 0, ')', 25, 1, 0, 0	/* 25 +0 arrows */
X};
X
Xstruct obj bow0 = {
X	&arrows0,
X 	W_BOW, 1, 0, 0, ')', 1, 1, 0, 0		/* +1 bow */
X};
X
Xstruct obj mace0 = {
X	&bow0,
X 	W_MACE, 1, 0, 0, ')', 1, 1, 0, 0	/* +1 mace */
X};
X
Xstruct obj uarm0 = {
X	&mace0,
X 	A_RING, 4, 0, 0, '[', 1, 1, 0, 0	/* +1 ring mail */
X};
X
Xstruct obj food0 = {
X	&uarm0,
X 	F_FOOD, 0, 0, 0, '%', 2, 1, 0, 0	/* 2 food rations */
X};
X
Xstruct obj *yourinvent0 = &food0;
/
echo 'x - hack.pri.c'
sed 's/^X//' > hack.pri.c << '/'
X/*
X * Hack.pri.c
X */
X
X#include "hack.h"
X
Xchar    scrlx, scrhx, scrly, scrhy;
X
Xextern short    ospeed;
Xchar    xcurses[200];		/* Contain's curser stuff */
Xchar   *HO, *CL, *CE, *CM, *UP, *BC;
Xchar    PC;
Xextern char    *tgetstr (), *getenv (), *tgoto (), *malloc ();
Xint     putch ();
X /* Corners of new area on screen */
Xextern char     SAVEFILE[];
X
XCOORDINATES ou = {
X	-1, 0
X};				/* Coordinates of @ on screen (if ou.x>=0) */
X
Xextern char    *getenv (), *hu_stat[4];/* In eat.c */
X#ifdef NORMAL_IO
Xchar    obuf[BUFSIZ];
X#endif NORMAL_IO
X
Xstartup () {
X	char   *bp = malloc (1024);
X	char   *atcurs = xcurses;
X
X	if (tgetent (bp, getenv ("TERM")) <= 0)
X		panic (NOCORE, "I know about many terminals but alas, not this one\n");
X	PC = tgetflag ("pc");
X	HO = tgetstr ("ho", &atcurs);
X	CL = tgetstr ("cl", &atcurs);
X	CE = tgetstr ("ce", &atcurs);
X	UP = tgetstr ("up", &atcurs);
X	if (!(BC = tgetstr ("bc", &atcurs))) {
X		if (!tgetflag ("bs"))
X			panic (NOCORE,
X					"You don't have a backspaced terminal\n");
X		BC = (char *) NULL;
X	}
X	if (!(CM = tgetstr ("cm", &atcurs)))
X		panic (NOCORE, "Hack needs cursor addressible terminals\n");
X	else if (!UP || !CL || tgetflag ("os"))
X		panic (NOCORE, "Hack needs `up' and `cl' and no `os'\n");
X	free (bp);
X#ifdef NORMAL_IO
X	setbuf (stdout, obuf);
X#endif NORMAL_IO
X}
X
X/*VARARGS*/
Xpanic (coredump, str, a1, a2, a3, a4, a5, a6)
Xregister char  *str;
X{
X	home ();
X#ifdef NORMAL_IO
X	printf ("ERROR:  ", 10);
X#else
X	WRITE ("ERROR:  ", 10);
X#endif NORMAL_IO
X	printf (str, a1, a2, a3, a4, a5, a6);
X	hackmode (OFF);
X	if (!unlink (SAVEFILE))
X		printf ("Savefile removed.\n");
X	flush ();
X	if (coredump)
X		abort ();
X	exit (2);
X}
X
Xseeatl (x, y, c)
Xregister        x, y, c;
X{
X	if (cansee (x, y))
X		atl (x, y, c);
X}
X
Xcls () {
X	tputs (CL, 0, putch);
X	curx = 1;
X	cury = 1;
X	ou.x = -1;
X	flags.topl = 0;
X}
X
Xhome () {
X	if (HO)
X		tputs (HO, 0, putch);
X	else
X		tgoto (CM, 0, 0);
X	curx = 1;
X	cury = 1;
X}
X
Xatl (x, y, ch)
Xregister        x, y;
X{
X	register        PART * crm = &levl[x][y];
X
X	if (crm -> scrsym == ch)
X		return;
X	if (x < 0 || x > 79 || y < 0 || y > 21)
X		panic (CORE, "atl(%d,%d,%c_%d_)", x, y, ch, ch);
X	crm -> scrsym = ch;
X	crm -> new = 1;
X	on (x, y);
X}
X
Xon (x, y)
Xregister        x, y;
X{
X	if (flags.dscr) {
X		if (x < scrlx)
X			scrlx = x;
X		else if (x > scrhx)
X			scrhx = x;
X		if (y < scrly)
X			scrly = y;
X		else if (y > scrhy)
X			scrhy = y;
X	}
X	else {
X		flags.dscr = 1;
X		scrlx = scrhx = x;
X		scrly = scrhy = y;
X	}
X}
X
Xat (x, y, ch)
Xregister        x, y;
Xregister char   ch;
X{
X	if (!ch || x < 0 || x > 79 || y < 0 || y > 21)
X		panic (CORE, "at(%d %d,%d) at %d %d", x, y, ch,
X				u.ux, u.uy);
X	y += 2;
X	curs (x, y);
X	putchar (ch == '\t' ? ' ' : ch);
X	curx++;
X}
X
Xprme () {
X	if (!u.uinvis)
X		at (u.ux, u.uy, '@');
X}
X
Xpru () {
X	prl (u.ux, u.uy);
X}
X
Xprl (x, y) {
X	register        PART * room;
X	register        MONSTER mtmp;
X
X	room = &levl[x][y];
X	if (!room -> typ || (room -> typ < DOOR &&
X				levl[u.ux][u.uy].typ == CORR))
X		return;
X	if ((mtmp = m_at (x, y)) && (!mtmp -> invis || u.ucinvis))
X		atl (x, y,
X				(mtmp -> wormno && (mtmp -> mx != x || mtmp -> my != y)) ?
X				'~' :
X				mtmp -> data -> mlet);
X	else
X		newunseen (x, y);
X}
X
Xnewunseen (x, y)
Xregister        x, y;
X{
X	if (!levl[x][y].seen) {
X		levl[x][y].new = 1;
X		on (x, y);
X	}
X}
X
Xchar
X        news0 (x, y)
Xregister        x, y;
X{
X	register        OBJECT otmp;
X	register        GOLD_TRAP gtmp;
X	PART * room;
X	register char   tmp;
X
X	room = &levl[x][y];
X	if (!u.ublind && (otmp = o_at (x, y)))
X		tmp = otmp -> olet;
X	else if (!u.ublind && g_at (x, y, fgold))
X		tmp = '$';
X	else if (gtmp = g_at (x, y, ftrap)) {
X		if (gtmp -> gflag == MIMIC)
X			tmp = '+';
X		else if (gtmp -> gflag & SEEN)
X			tmp = '^';
X		else
X			tmp = '.';
X	}
X	else if (room -> typ >= 30 && room -> typ <= 41)
X		tmp = '0';
X	else
X		switch (room -> typ) {
X
X			case SDOOR: 
X			case WALL: 
X				if ((room - 1) -> typ == WALL && (room + 1) -> typ
X						== WALL)
X					tmp = '|';
X				else
X					tmp = '-';
X				break;
X
X			case DOOR: 
X				tmp = '+';
X				break;
X
X			case ROOM: 
X				if (x == xupstair && y == yupstair)
X					tmp = '<';
X				else if (x == xdnstair && y == ydnstair)
X					tmp = '>';
X				else if (room -> lit || cansee (x, y) || u.ublind)
X					tmp = '.';
X				else
X					tmp = ' ';
X				break;
X
X			case CORR: 
X				tmp = '#';
X				break;
X
X			case POOL: 
X				tmp = '}';
X				break;
X			case VAULT: 
X				tmp = '-';
X				break;
X
X			default: 
X				tmp = '`';
X				impossible ();
X		}
X	return tmp;
X}
X
Xnewsym (x, y)
Xregister        x, y;
X{
X	atl (x, y, news0 (x, y));
X}
X
Xlevlsym (x, y, c)
Xregister        x, y, c;
X{
X	if (levl[x][y].scrsym == c)
X		newsym (x, y);
X}
X
Xnosee (x, y)
Xregister        x, y;
X{
X	register        PART * room;
X
X	room = &levl[x][y];
X	if (room -> scrsym == '.' && !room -> lit && !u.ublind) {
X		if (room -> new && (x != oldux || y != olduy))
X			room -> new = 0;
X		else {
X			room -> scrsym = ' ';
X			room -> new = 1;
X			on (x, y);
X		}
X	}
X}
X
Xprl1 (x, y)
Xregister        x, y;
X{
X	register        count;
X
X	if (dx) {
X		if (dy) {
X			prl (x - (dx << 1), y);
X			prl (x - dx, y);
X			prl (x, y);
X			prl (x, y - dy);
X			prl (x, y - (dy << 1));
X		}
X		else
X			for (count = -1; count <= 1; ++count)
X				prl (x, y + count);
X	}
X	else
X		for (count = -1; count <= 1; ++count)
X			prl (x + count, y);
X}
X
Xnose1 (x, y)
Xregister        x, y;
X{
X	register        count;
X
X	if (dx)
X		if (dy) {
X			nosee (x, u.uy);
X			nosee (x, u.uy - dy);
X			nosee (x, y);
X			nosee (u.ux - dx, y);
X			nosee (u.ux, y);
X		}
X		else
X			for (count = -1; count <= 1; ++count)
X				nosee (x, y + count);
X	else
X		for (count = -1; count <= 1; ++count)
X			nosee (x + count, y);
X}
X
Xdoreprint () {
X	nomove ();
X	pline ("\200");		/* Michiel: Code for repeating last message */
X}
X
X/* VARARGS1 */
Xpline (line, arg1, arg2, arg3, arg4)
Xregister char  *line;
X{
X	char    pbuf[BUFSZ];
X	static char     prevbuf[BUFSZ];
X
X	if (index (line, '\200'))
X		strcpy (pbuf, prevbuf);
X	else {
X		if (!index (line, '%'))
X			strcpy (pbuf, line);
X		else
X			sprintf (pbuf, line, arg1, arg2, arg3, arg4);
X		if (multi && !strcmp (pbuf, prevbuf))
X			return;
X		strcpy (prevbuf, pbuf);
X	}
X	if (flags.dscr)
X		nscr ();
X	if (flags.topl) {
X		curs (savx, 1);
X		more ();
X	}
X	flags.topl = 1;
X	home ();
X	cl_end ();
X	printf (pbuf);
X	savx = strlen (pbuf);
X	curx = ++savx;
X}
X
Xprustr () {
X	if (u.ustr > 18) {
X		if (u.ustr > 117)
X			printf ("18/00");
X		else
X			printf ("18/%02d", u.ustr - 18);
X	}
X	else
X		printf ("%-5d", u.ustr);
X	curx += 5;
X}
X
Xpmon (mtmp)
Xregister        MONSTER mtmp;
X{
X	if (!mtmp -> invis || u.ucinvis)
X		seeatl (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet);
X}
X
Xdocrt () {
X	cls ();
X	if (u.uswallow) {
X		curs (u.ux - 1, u.uy - 1);
X		printf ("/-\\");
X		curs (u.ux - 1, u.uy);
X		printf ("|@|");
X		curs (u.ux - 1, u.uy + 1);
X		printf ("\\-/");
X		curx = u.ux + 2;
X	}
X	else
X		donscrt (0, 0);	/* a3 */
X	bot ();
X}
X
Xnscr () {
X	register        umv;
X
X	umv = ((ou.x < 0 && !u.uinvis) || (ou.x >= 0 &&
X				(u.uinvis || ou.x != u.ux || ou.y != u.uy)));
X	if (ou.x >= 0 && umv && !levl[ou.x][ou.y].new)
X		newsym (ou.x, ou.y);
X	donscrt (1, umv);
X}
X
Xdonscrt (mode, umv) {		/* mode: 0- docrt(), 1- nscr()  */
X	register        PART * room;
X	register        x, y, ly, hy, lx, hx;
X
X	if (u.uinvis) {
X		if (mode)
X			ou.x = -1;
X	}
X	else {
X		ou.x = u.ux;
X		ou.y = u.uy;
X		if (mode && umv)
X			atl (ou.x, ou.y, '@');
X		else {
X			(room = &levl[ou.x][ou.y]) -> scrsym = '@';
X			if (!mode)
X				room -> seen = 1;
X			else
X				room -> new = 0;
X		}
X	}
X	if (mode) {
X		ly = scrly;
X		hy = scrhy;
X		lx = scrlx;
X		hx = scrhx;
X	}
X	else {
X		ly = 0;
X		hy = 21;
X		lx = 0;
X		hx = 79;
X	}
X	for (y = ly; y <= hy; y++)
X		for (x = lx; x <= hx; x++)
X			if ((room = &levl[x][y]) -> new) {
X				room -> new = 0;
X				at (x, y, room -> scrsym);
X				if (room -> scrsym == ' ') {
X					room -> seen = 0;
X					room -> scrsym = '.';
X				}
X				else
X					room -> seen = 1;
X			}
X			else if (!mode)
X				if (room -> seen)
X					at (x, y, room -> scrsym);
X	flags.dscr = 0;
X	scrhx = 0;
X	scrhy = 0;
X	scrlx = 80;
X	scrly = 22;
X}
X
Xbot () {
X	flags.botl = 0;
X	flags.dhp = 0;
X	flags.dhpmax = 0;
X	flags.dac = 0;
X	flags.dstr = 0;
X	flags.dgold = 0;
X	flags.dhs = 0;
X	curs (1, 24);
X	printf ("Level %-4dGold %-7UHp%4d(%d)",
X			dlevel, u.ugold, u.uhp, u.uhpmax);
X	if (u.uhpmax < 10)
X		printf ("  ");
X	else if (u.uhpmax < 100)
X		putchar (' ');
X	printf ("Ac %-5dStr ", u.uac);
X	prustr ();
X	printf ("  Exp%3d/", u.ulevel);
X	if (u.ulevel < 14)
X		printf ("%-11U", u.uexp);
X	else
X		printf ("%-11s", "MAX++");
X	printf ("%s", hu_stat[u.uhs]);
X	curx = 78;
X}
X
Xcurs (x, y)
Xregister        x, y;
X{
X	if (y == cury && x == curx)
X		return;		/* Do nothing, gracefully */
X	tputs (tgoto (CM, x - 1, y - 1), 0, putch);
X	flush ();
X	cury = y;
X	curx = x;
X}
X
Xcl_end () {
X	if (CE)
X		tputs (CE, 0, putch);
X	else {
X		printf ("%80s", "");
X		home ();
X	}
X}
X
Xputch (c)
Xchar    c;
X{
X#ifdef NORMAL_IO
X	putchar (c);
X#else
X	WRITE (&c, 1);
X#endif NORMAL_IO
X}
/
echo 'x - mklev.c'
sed 's/^X//' > mklev.c << '/'
X/*
X * Mklev.c
X */
X
X#define NORMAL_IO
X#include "hack.h"
X
Xchar   *tfile, *tspe, **args, nul[20];
X
X#include "mklev.svlev.c"
X
Xchar    mmon[8][8] = {
X	"BGHJKLr",
X	"aEhiOyZ",
X	"AfNpQqv",
X	"bCcgjkS",
X	"FoRstWw",
X	"dlMmTuY",
X	"IUVXxz:",
X	"De'n,P&"
X};
X
X#define MAZX ((rnd(37) << 1) + 1)
X#define MAZY ((rnd(8) << 1) + 1)
X
X#define somex() rn1( croom->hx - croom->lx + 1, croom->lx )
X#define somey() rn1( croom->hy - croom->ly + 1, croom->ly )
X
X#define NOT_HERE	0
X
XPART levl[80][22];
X
XMONSTER fmon;
XOBJECT fobj;
XGOLD_TRAP fgold, ftrap;
X
XMKROOM rooms[15], *croom, *troom;
X
XCOORDINATES doors[DOORMAX];
X
Xint     doorindex = 0, nroom, comp ();
X
Xchar    dlevel, *geno, goldseen,
X        xdnstair, xupstair, ydnstair, yupstair,
X        wizard, nxcor, x, y,
X        dx, dy, tx, ty;
X /* For corridors and other things... */
X
X#define RUIN	5
X#define MAZE	6
X
Xmain (argc, argv)
Xchar   *argv[];
X{
X	char    lowy, lowx;
X	register unsigned       tryct;
X
X	if (argc < 6)
X		panic ("Too few arguments!!");
X	args = argv;
X	tfile = argv[1];
X	tspe = argv[2];
X	dlevel = atoi (argv[3]);
X	if (dlevel >= 30)
X		dlevel = 30;
X	geno = argv[4];
X	wizard = (*argv[5] == 'w');
X	srand (getpid ());
X/* for( lowy=2;lowy<19;lowy++) for( lowx=2;lowx<77;lowx++ )
X	 				levl[lowx][lowy].typ = 0; * /
X
X/*
X * a: normal;
X * b: maze;
X * n: next level will be maze
X */
X	if (*tspe == 'b') {
X		makemaz ();
X		savelev ();
X		exit (1);
X	}
X
X/* Construct the rooms */
X	croom = rooms;
X	tryct = 0;
X	while (nroom < 7) {
X		for (lowy = rn1 (3, 3); lowy < 15; lowy += rn1 (2, 4))
X			for (lowx = rn1 (3, 4); lowx < 70; lowx +=
X					rn1 (2, 7)) {
X				if (++tryct > 10000) {
X					printf ("tryct overflow\n");
X					goto jumpout;
X				}
X				if ((lowy += rn1 (5, -2)) < 3)
X					lowy = 3;
X				else if (lowy > 16)
X					lowy = 16;
X				if (levl[lowx][lowy].typ)
X					continue;
X				if (maker (lowx, rn1 (9, lowx + 2), lowy,
X							rn1 (4, lowy + 2)) && nroom > 13)
X					goto jumpout;
X			}
X	}
Xjumpout: 
X	croom -> hx = -1;
X
X/* For each room: put things inside */
X	for (croom = rooms; croom -> hx > 0; croom++) {
X
X/* Put a sleeping monster inside */
X		if (!rn2 (3))
X			makemon (1, somex (), somey ());
X
X/* Put traps and mimics inside */
X		goldseen = 0;
X		while (!rn2 (8 - (dlevel / 6)))
X			mktrap (0, 0);
X		if (!goldseen && !rn2 (3))
X			mkgold (0, somex (), somey ());
X		tryct = 0;
X		if (!rn2 (3))
X			do {
X				mkobj (0);
X				levl[fobj -> ox = somex ()][fobj -> oy = somey ()].scrsym = fobj -> olet;
X				if (tryct++ > 100) {
X					printf ("tryct overflow4\n");
X					break;
X				}
X			} while (!rn2 (5));
X	}
X	tryct = 0;
X	do {
X		if (++tryct > 1000)
X			panic ("Cannot make dnstairs\n");
X		croom = &rooms[rn2 (nroom)];
X		xdnstair = somex ();
X		ydnstair = somey ();
X	} while ((*tspe == 'n' &&
X				(xdnstair % 2 == 0 || ydnstair % 2 == 0)) ||
X			g_at (xdnstair, ydnstair, ftrap));
X	levl[xdnstair][ydnstair].scrsym = '>';
X	troom = croom;
X	do {
X		if (++tryct > 2000)
X			panic ("Cannot make upstairs\n");
X		croom = &rooms[rn2 (nroom)];
X		xupstair = somex ();
X		yupstair = somey ();
X	} while (croom == troom || m_at (xupstair, yupstair) ||
X			o_at (xupstair, yupstair) ||
X			g_at (xupstair, yupstair, ftrap));
X	levl[xupstair][yupstair].scrsym = '<';
X	qsort (rooms, nroom, sizeof (MKROOM), comp);
X	croom = rooms;
X	troom = croom + 1;
X	nxcor = 0;
X	mkpos ();
X	do
X		makecor (x + dx, y + dy);
X	while (croom -> hx > 0 && troom -> hx > 0);
X	if ((dlevel < 10 && rn2 (2)) || (dlevel > 9 && !rn2 (3)) ||
X			wizard)
X		mkshop ();
X	if (dlevel > 7 && !rn2 (6))
X		mkzoo ();
X	else if (dlevel > 11 && !rn2 (6) || wizard)
X		mkyard ();
X	else if ((dlevel > 18 && !rn2 (6)))
X		mkswamp ();
X	else if ((dlevel > 8 && !rn2 (8)) || wizard)
X		mk_knox ();
X	savelev ();
X}
X
Xcomp (xcoord, ycoord)
Xregister        MKROOM * xcoord, *ycoord;
X{
X	if (xcoord -> lx < ycoord -> lx)
X		return - 1;
X	return (xcoord -> lx > ycoord -> lx);
X}
X
Xmkpos () {
X	if (troom -> hx < 0 || croom -> hx < 0)
X		return;
X	if (troom -> lx > croom -> hx) {
X		x = croom -> hx + 1;
X		dx = 1;
X		tx = troom -> lx - 1;
X	}
X	else if (troom -> hy < croom -> ly) {
X		y = croom -> ly - 1;
X		dy = -1;
X		dx = 0;
X		ty = troom -> hy + 1;
X	}
X	else if (troom -> hx < croom -> lx) {
X		x = croom -> lx - 1;
X		dx = -1;
X		tx = troom -> hx + 1;
X	}
X	else {
X		y = croom -> hy + 1;
X		dy = 1;
X		dx = 0;
X		ty = troom -> ly - 1;
X	}
X	if (dx) {
X		dy = 0;
X		y = croom -> ly + rn2 (croom -> hy - croom -> ly + 1);
X		ty = troom -> ly + rn2 (troom -> hy - troom -> ly + 1);
X	}
X	else {
X		x = croom -> lx + rn2 (croom -> hx - croom -> lx + 1);
X		tx = troom -> lx + rn2 (troom -> hx - troom -> lx + 1);
X	}
X	if (levl[x + dx][y + dy].typ) {
X		if (nxcor)
X			newloc ();
X		else {
X			dodoor (x, y, croom);
X			x += dx;
X			y += dy;
X		}
X		return;
X	}
X	dodoor (x, y, croom);
X}
X
Xdodoor (doorx, doory, aroom)
Xregister int    doorx, doory;
Xregister        MKROOM * aroom;
X{
X	register        MKROOM * broom;
X	register int    tmp;
X
X	if ((tmp = levl[doorx - 1][doory].typ) == DOOR || tmp == SDOOR)
X		return;
X	if ((tmp = levl[doorx + 1][doory].typ) == DOOR || tmp == SDOOR)
X		return;
X	if ((tmp = levl[doorx][doory - 1].typ) == DOOR || tmp == SDOOR)
X		return;
X	if ((tmp = levl[doorx][doory + 1].typ) == DOOR || tmp == SDOOR)
X		return;
X	if (levl[doorx][doory].typ != WALL || doorindex >= DOORMAX)
X		return;
X	if (!rn2 (8))
X		levl[doorx][doory].typ = SDOOR;
X	else {
X		levl[doorx][doory].scrsym = '+';
X		levl[doorx][doory].typ = DOOR;
X	}
X	aroom -> doorct++;
X	broom = aroom + 1;
X	if (broom -> hx < 0)
X		tmp = doorindex;
X	else
X		for (tmp = doorindex; tmp > broom -> fdoor; tmp--) {
X			doors[tmp].x = doors[tmp - 1].x;
X			doors[tmp].y = doors[tmp - 1].y;
X		}
X	doorindex++;
X	doors[tmp].x = doorx;
X	doors[tmp].y = doory;
X	for (; broom -> hx >= 0; broom++)
X		broom -> fdoor++;
X}
X
Xnewloc () {
X	register int    tryct = 0;
X
X	++croom;
X	++troom;
X	if (nxcor || croom -> hx < 0 || troom -> hx < 0) {
X		if (nxcor++ > rn1 (nroom, 4)) {
X			croom = &rooms[nroom];
X			return;
X		}
X		do {
X			if (++tryct > 100) {
X				printf ("tryct overflow5\n");
X				croom = &rooms[nroom];
X				return;
X			}
X			croom = &rooms[rn2 (nroom)];
X			troom = &rooms[rn2 (nroom)];
X		}
X		while (croom == troom || (troom == croom + 1 &&
X					!rn2 (3)));
X	}
X	mkpos ();
X}
X
Xmove (xdir, ydir, dir)
Xregister int   *xdir, *ydir, dir;
X{
X	switch (dir) {
X		case 0: 
X			--(*xdir);
X			break;
X		case 1: 
X			(*ydir)++;
X			break;
X		case 2: 
X			(*xdir)++;
X			break;
X		case 3: 
X			--(*ydir);
X			break;
X	}
X}
X
Xokay (xx, yy, dir)
Xint     xx, yy;
Xregister int    dir;
X{
X	move (&xx, &yy, dir);
X	move (&xx, &yy, dir);
X	if (xx < 3 || yy < 3 || xx > 17 || yy > 75 || levl[yy][xx].typ != 0)
X		return 0;
X	return 1;
X}
X
Xmaker (lowx, hix, lowy, hiy)
Xchar    lowx, hix, lowy, hiy;
X{
X	register        PART * ltmp, *lmax;
X	register int    tmpx;
X
X	if (hix > 75)
X		hix = 75;
X	if (hiy > 18)
X		hiy = 18;
X	for (tmpx = lowx - 4; tmpx < hix + 5; tmpx++)
X		for (ltmp = &levl[tmpx][lowy - 3],
X				lmax = &levl[tmpx][hiy + 4];
X				ltmp != lmax; ltmp++)
X			if (ltmp -> typ)
X				return 0;
X	if (10 > rnd (dlevel)) {
X		for (tmpx = lowx - 1; tmpx < hix + 2; tmpx++)
X			for (ltmp = &levl[tmpx][lowy - 1],
X					lmax = &levl[tmpx][hiy + 2];
X					ltmp != lmax; ltmp++)
X				ltmp -> lit = 1;
X	}
X	croom -> lx = lowx;
X	croom -> hx = hix;
X	croom -> ly = lowy;
X	croom -> hy = hiy;
X	croom -> rtype = 0;
X	croom -> doorct = 0;
X	croom -> fdoor = 0;
X	croom++;
X	for (tmpx = lowx - 1; tmpx <= hix + 1; tmpx++) {
X		ltmp = &levl[tmpx][lowy - 1];
X		lmax = &levl[tmpx][hiy + 1];
X		ltmp -> scrsym = '-';
X		ltmp -> typ = WALL;
X		while (++ltmp != lmax) {
X			if (tmpx >= lowx && tmpx <= hix) {
X				ltmp -> scrsym = '.';
X				ltmp -> typ = ROOM;
X			}
X			else {
X				ltmp -> scrsym = '|';
X				ltmp -> typ = WALL;
X			}
X		}
X		ltmp -> scrsym = '-';
X		ltmp -> typ = WALL;
X	}
X /* 
X  -------
X  |.....|
X  |.....|		(This sort of room is made) (a3)
X  |.....|
X  -------
X  */
X	++nroom;
X	return 1;
X}
X
Xmakecor (nx, ny)
Xregister int    nx, ny;
X{
X	register        PART * crm;
X	register int    dix, diy;
X
X	if (nxcor && !rn2 (35)) {
X		newloc ();
X		return;
X	}
X	dix = abs (nx - tx);
X	diy = abs (ny - ty);
X	if (nx == 79 || !nx || !ny || ny == 21) {
X		if (nxcor) {
X			newloc ();
X			return;
X		}
X		printf ("something went wrong. we try again...\n");
X		execl ("./mklev", args[0], tfile, tspe, args[3],
X				args[4], 0);
X		panic ("cannot execute ./mklev\n");
X	}
X	if (dy && dix > diy) {
X		dy = 0;
X		dx = (nx > tx) ? -1 : 1;
X	}
X	else if (dx && diy > dix) {
X		dx = 0;
X		dy = (ny > ty) ? -1 : 1;
X	}
X	crm = &levl[nx][ny];
X	if (!crm -> typ) {
X		crm -> typ = CORR;
X		crm -> scrsym = '#';
X		x = nx;
X		y = ny;
X		return;
X	}
X	if (crm -> typ == CORR) {
X		x = nx;
X		y = ny;
X		return;
X	}
X	if (nx == tx && ny == ty) {
X		dodoor (nx, ny, troom);
X		newloc ();
X		return;
X	}
X	if (x + dx != nx || y + dy != ny)
X		return;
X	if (dx) {
X		dy = 1;
X		if (ty < ny || levl[nx + dx][ny - 1].typ != ROOM)
X			dy = -1;
X		dx = 0;
X	}
X	else {
X		dx = 1;
X		if (tx < nx || levl[nx - 1][ny + dy].typ != ROOM)
X			dx = -1;
X		dy = 0;
X	}
X}
X
XMONSTER m_at (monx, mony)
Xregister int    monx, mony;
X{
X	register        MONSTER mtmp;
X
X	for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon)
X		if (mtmp -> mx == monx && mtmp -> my == mony)
X			return (mtmp);
X	return (NOT_HERE);
X}
X
XOBJECT o_at (objx, objy)
Xregister int    objx, objy;
X{
X	register        OBJECT obj;
X
X	for (obj = fobj; obj; obj = obj -> nobj)
X		if (obj -> ox == objx && obj -> oy == objy)
X			return (obj);
X	return (NOT_HERE);
X}
X
XGOLD_TRAP g_at (gtx, gty, ptr)
Xregister int    gtx, gty;
Xregister        GOLD_TRAP ptr;
X{
X	while (ptr) {
X		if (ptr -> gx == gtx && ptr -> gy == gty)
X			return (ptr);
X		ptr = ptr -> ngen;
X	}
X	return NOT_HERE;
X}
/
echo 'x - show.c'
sed 's/^X//' > show.c << '/'
X/*
X * Showlevel.c
X */
X
X#define NORMAL_IO
X#define SHOW
X#include "hack.h"
X
XPART levl[80][22];
X
Xchar    mmon[8][8] = {
X	"BGHJKLr",
X	"aEhiOyZ",
X	"AfNpQqv",
X	"bCcgjkS",
X	"FoRstWw",
X	"dlMmTuY",
X	"IUVXxz:",
X	"De'n,P&"
X};
X
Xchar    stairs[4], mbuf[1000], obuf[BUFSIZ];
X
Xunsigned        omoves;
Xextern char    *setan ();
X
Xmain (argc, argv)
Xint     argc;
Xchar  **argv;
X{
X	register        fd;
X	register        MONSTER mtmp = (MONSTER) mbuf;
X	char    buffer[100];
X	struct stole    stmp;
X	struct obj      otmp;
X	char    buf[BUFSZ];
X	int     xl;
X
X	setbuf (stdout, obuf);
X	if (!strcmp (argv[1], "-r")) {
X		showrecord ();
X		exit (0);
X	}
X	if (!strcmp (argv[1], "-d")) {
X		delrecord ();
X		exit (0);
X	}
X	while (--argc) {
X		printf ("Next file is %s\n", argv[argc]);
X		if ((fd = open (argv[argc], 0)) < 0) {
X			printf ("Cannot open %s\n", argv[argc]);
X			getret ();
X			continue;
X		}
X		if (read (fd, levl, sizeof levl) != sizeof levl) {
X			printf ("Error reading level\n");
X			getret ();
X			continue;
X		}
X		show ();
X		mread (fd, &omoves, sizeof (unsigned));
X		mread (fd, stairs, 4);
X		mread (fd, &xl, sizeof (int));
X		printf ("Show Monsters? (%sSpecified) ", omoves ? "Not " : "");
X		fflush (stdout);
X		gets (buffer);
X		if (strcmp (buffer, "y"))
X			continue;
X		while (xl != -1) {
X			mread (fd, mtmp, xl + sizeof (struct monst));
X			mread (fd, &stmp, sizeof (struct stole));
X			if (!omoves) {
X				if (mtmp -> mhp == 10 && mtmp -> orig_hp == 10)
X					printf ("\' \'");
X				else if (mtmp -> mhp == 9 && mtmp -> orig_hp == 9)
X					printf ("Ale");
X				else
X					printf ("%c",
X							mmon[mtmp -> mhp][mtmp -> orig_hp]);
X				printf (" at [%d,%d]", mtmp -> mx, mtmp -> my);
X			}
X			else {
X				printf ("monster at [%d,%d]", mtmp -> mx, mtmp -> my);
X				if (stmp.sgold || stmp.sobj) {
X					printf (" stole ");
X					if (stmp.sgold)
X						printf ("%u goldpieces", stmp.sgold);
X					for (;;) {
X						mread (fd, &otmp,
X								sizeof (struct obj));
X						if (!otmp.olet)
X							break;
X						doname (otmp.olet, buf);
X						printf (" %s", buf);
X					}
X				}
X			}
X			if (mtmp -> msleep)
X				printf (" SLEEP");
X			if (mtmp -> invis)
X				printf (" INVIS");
X			if (mtmp -> cham)
X				printf (" CHAM");
X			if (mtmp -> mspeed)
X				printf (" MSPEED");
X			if (mtmp -> mconf)
X				printf (" MCONF");
X			if (mtmp -> mflee)
X				printf (" MFLEE");
X			if (mtmp -> mcan)
X				printf (" MCAN");
X			if (mtmp -> mtame)
X				printf (" TAME");
X			if (mtmp -> angry)
X				printf (" MANGRY");
X			if (mtmp -> wormno)
X				printf (" WORM[%d]", mtmp -> wormno);
X			if (mtmp -> mxlth)
X				printf (" +%d extra", mtmp -> mxlth);
X			if (mtmp -> mfroz)
X				printf (" FROZ");
X			putchar ('\n');
X			mread (fd, &xl, sizeof (int));
X		}
X		getret ();
X	}
X}
X
Xmread (fd, buf, n) {
X	register        nn;
X
X	if ((nn = read (fd, buf, n)) != n) {
X		printf ("error: read %d instead of %d bytes\n", nn, n);
X		exit (2);
X	}
X}
X
Xshow () {
X	register        i, j;
X
X	for (j = 0; j < 22; j++)
X		for (i = 0; i < 80; i++)
X			pch (levl[i][j].scrsym);
X	printf ("***     ");
X}
X
Xpch (ch)
Xchar    ch;
X{
X	putchar (ch ? ch : '_');
X}
X
Xextern char    *malloc ();
X
Xchar   *
X        alloc (num)
Xregister        num;
X{
X	register char  *val;
X
X	if (!(val = malloc (num)))
X		error ("Cannot get %d bytes", num);
X	return val;
X}
X
Xerror (s) {
X	printf (s);
X	putchar ('\n');
X	fflush (stdout);
X	exit (1);
X}
X
Xextern char    *itoa ();
X
X#define	NAMESIZE	 8
X#define	DEATHSIZE	40
X
Xstruct recitem {
X	long    points;
X	int     level, maxlvl, hp, maxhp;
X	char    str[NAMESIZE + 1], death[DEATHSIZE + 1];
X}               record;
X
Xshowrecord () {
X	register        killed;
X	register        place = 0;
X	register        rfile;
X
X	if ((rfile = open (RECORD, 0)) < 0)
X		error ("Cannot open %s", RECORD);
X	printf ("Number Points Name\n");
X	while (read (rfile, &record, sizeof (struct recitem)) > 0) {
X		printf ("%2d  %6D %8s ", ++place, record.points,
X			record.str);
X		killed = 0;
X		if (*record.death == 'e')
X			printf ("escaped the dungeon [max level %d]",
X				record.maxlvl);
X		else {
X			switch (record.death[1]) {
X				case 'u': 
X					printf ("quit");
X					break;
X				case 'h': 
X					printf ("choked in his/her food");
X					break;
X				case 't': 
X					printf ("starved");
X					break;
X				case 'r': 
X					printf ("drowned");
X					break;
X				default: 
X					printf ("was killed");
X					killed++;
X			}
X			                                                        printf (" on%s level %d", killed ? "" :
X				                                                        " dungeon", record.level);
X			if (record.maxlvl != record.level)
X				printf (" [%d]", record.maxlvl);
X		}
X		if (killed)
X			printf (" by %s", record.death);
X		putchar ('.');
X		if (record.maxhp)
X			printf (" Hp: %s [%d]", (record.hp > 0) ?
X					itoa (record.hp) : "-", record.maxhp);
X		putchar ('\n');
X	}
X	close (rfile);
X}
X
Xint     deleted[45];
X
Xdelrecord () {
X	register int    fd, fd2;
X	int     count = 0;
X
X	printf ("Delete (Terminate with a zero): ");
X	fflush (stdout);
X	fd = open (RECORD, 0);
X	fd2 = creat (".Temp", 0777);
X	if (fd < 0 || fd2 < 0) {
X		printf ("Cannot open files!\n");
X		exit (2);
X	}
X	do {
X		scanf ("%d", &count);
X		++deleted[count];
X	} while (count);
X	fprintf (stderr, "Deleted nr");
X	count = 1;
X	while (read (fd, &record, sizeof (struct recitem)) >    0) {
X		if (!deleted[count])
X			write (fd2, &record, sizeof (struct recitem));
X		else
X			                                                fprintf (stderr, " %d", count);
X		                                              ++count;
X	}
X	                                                        putc ('\n', stderr);
X	close (fd);
X	close (fd2);
X	execl ("/bin/mv", "mv", ".Temp", RECORD, NULL);
X}
X
Xchar   *
X        itoa (a)
Xregister int    a;
X{
X	static char     buf[8];
X
X	sprintf (buf, "%d", a);
X	return (buf);
X}
X
Xdoname (let, buf)
Xregister char   let;
Xregister char  *buf;
X{
X	switch (let) {
X
X		case '"': 
X			strcpy (buf, "The amulet of Frobozz");
X			break;
X
X		case '%': 
X			strcpy (buf, "some food");
X			break;
X
X		case ')': 
X			strcpy (buf, "a weapon");
X			break;
X
X		case '[': 
X			strcpy (buf, "armor");
X			break;
X
X		case '!': 
X			strcpy (buf, "a potion");
X			break;
X
X		case '?': 
X			strcpy (buf, "a scroll");
X			break;
X
X		case '/': 
X			strcpy (buf, "a wand");
X			break;
X
X		case '=': 
X			strcpy (buf, "a ring");
X			break;
X
X		case '*': 
X			strcpy (buf, "a gem");
X			break;
X
X		default: 
X			sprintf (buf, "a glorkum %c(0%o)", let, let);
X	}
X}
X
Xgetret () {
X	printf ("AHit j<return>k to continue");
X	fflush (stdout);
X	while (getchar () != '\n');
X}
/
echo 'Part 03 of Hack complete.'
exit
-- 

			Michiel Huisjes.
			{seismo|decvax|philabs}!mcvax!vu44!ark!huisjes

huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)

#!/bin/sh
#
# 
# 
# This is a shell archive. These archives are packed by the program 
# packmail(1). If you have the program unshar(1), I suggest you use it.
# If you don't remove anything before the cut line and then feed to
# sh(1)
# 
# =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE===
#
echo 'Start of Hack, part 04 of 05:'
echo 'x - data'
sed 's/^X//' > data << '/'
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X!       a potion                                 
X"       The amulet of Frobozz                    
X#       a corridor                               
X$       a pile, pot or chest of gold             
X%       a piece of food                          
X&       a demon                                  
X'       a lurker above                           
X\                                                
X)       a weapon                                 
X*       a gem                                    
X+       a door                                   
X,       a trapper                                
X-       a wall                                   
X.       the floor of a room                      
X/       a wand                                   
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X\                                                
X:       a chameleon                              
X;       a giant ale                              
X<       the staircase to the previous level      
X=       a ring                                   
X>       the staircase to the next level          
X?       a scroll                                 
X@       a human (or you)                         
XA       a giant ant                              
XB       a giant bat                              
XC       a centaur                                
XD       a dragon                                 
XE       a floating eye                           
XF       a freezing sphere                        
XG       a gnome                                  
XH       a hobgoblin                              
XI       an invisible stalker                     
XJ       a jackal                                 
XK       a kobold                                 
XL       a leprechaun                             
XM       a mimic                                  
XN       a nymph                                  
XO       an orc                                   
XP       a purple worm                            
XQ       a quasit                                 
XR       a rust monster                           
XS       a snake                                  
XT       a troll                                  
XU       an umber hulk                            
XV       a vampire                                
XW       a wraith                                 
XX       a xorn                                   
XY       a yeti                                   
XZ       a zombie                                 
X[       a suit of armor                          
X\                                                
X\                                                
X^       a trap                                   
X\                                                
X\                                                
Xa       an acid blob                             
Xb       a giant beetle                           
Xc       a cockatrice                             
Xd       a dog                                    
Xe       an ettin                                 
Xf       a fog cloud                              
Xg       a gelatinous cube                        
Xh       a homunculus                             
Xi       an imp                                   
Xj       a jaguar                                 
Xk       a killer bee                             
Xl       a leocrotta                              
Xm       a minouter                               
Xn       a neo-otyugh                             
Xo       an owlbear                               
Xp       a piercer                                
Xq       a quivering blob                         
Xr       a giant rat                              
Xs       a giant scorpion                         
Xt       a teleporter                             
Xu       a ugod                                   
Xv       a violet fungi                           
Xw       a long worm                              
Xx       a xerp                                   
Xy       a yellow light                           
Xz       a zelomp                                 
X\                                                
X|       a wall                                   
X}       a water filled area                      
X~       a wormsegment                            
X\                                                
/
echo 'x - hack.do.misc.c'
sed 's/^X//' > hack.do.misc.c << '/'
X/*
X * Hack.do.misc.c
X */
X
X/* Routines to do various user commands */
X
X#include <signal.h>
X#include "hack.h"
X#include "hack.do.vars.h"
X /* (MT) has 'do' structures and lists */
X
Xextern char    *getenv (), UMISS[], WELDED[];
X
X#define MAXLEVEL       40
X
XOBJECT loseone ();
X
Xint     done1 ();
X
Xchar    upxstairs[MAXLEVEL], upystairs[MAXLEVEL];
X
Xrhack (cmd)
Xregister char  *cmd;
X{
X	register        FUNCTIONS * tlist = list;
X
X	if (!cmd) {
X		pline ("Rhack: 0");
X		impossible ();
X		return;
X	}
X	if (!*cmd || *cmd == -1)
X		return;		/* Probably interrupt? */
X	if (movecm (cmd)) {
X		if (multi)
X			flags.mv = 1;
X		domove ();
X		return;
X	}
X	if (movecm (lowc (cmd))) {
X		flags.run = 1;
X		multi = 80;
X		flags.mv = 1;
X		domove ();
X		return;
X	}
X	if (*cmd == 'f' && movecm (cmd + 1)) {
X		flags.run = 2;
X		multi = 80;
X		flags.mv = 1;
X		domove ();
X		return;
X	}
X	if (*cmd == 'F' && movecm (lowc (cmd + 1))) {
X		flags.run = 3;
X		multi = 80;
X		flags.mv = 1;
X		domove ();
X		return;
X	}
X	while (tlist -> f_char) {
X		if (*cmd == tlist -> f_char) {
X			(*(tlist -> f_funct)) ();
X			return;
X		}
X		tlist++;
X	}
X	pline ("Unknown command '%s'", cmd);
X	nomove ();
X}
X
Xdoredraw () {
X	docrt ();
X	nomove ();
X}
X
X/*
X * VARIABELE ARGUMENTS, but if not given the last argument will always
X * be a NULL.		(Michiel)
X */
X/*VARARGS*/
Xhackexec (num, file, arg1, arg2, arg3, arg4, arg5, arg6)
Xregister int    num;
Xregister char  *file, *arg1;
Xchar   *arg2, *arg3, *arg4, *arg5, *arg6;
X{
X	nomove ();
X	switch (fork ()) {
X		case -1: 
X			pline ("Fork failed. Will try again.");
X			hackexec (num, file, arg1, arg2, arg3, arg4,
X					arg5, arg6);
X			break;
X		case 0: 
X			if (num) {
X				signal (SIGINT, SIG_DFL);
X				setuid (getuid ());
X				hackmode (OFF);
X				cls ();
X				flush ();
X				if (num == 2)
X					chdir (getenv ("HOME"));
X			}
X			else
X				signal (SIGINT, SIG_IGN);
X			execl (file, file, arg1, arg2, arg3, arg4, arg5, arg6);
X			panic (NOCORE, "%s: cannot execute.", file);
X			break;
X		default: 
X			signal (SIGINT, SIG_IGN);
X			signal (SIGQUIT, SIG_IGN);
X			wait (0);
X			if (num) {
X				hackmode (ON);
X				docrt ();
X			}
X			signal (SIGINT, done1);
X			signal (SIGQUIT, SIG_DFL);
X			break;
X	}
X}
X
Xdohelp () {
X	hackexec (1, MORE, HELP, NULL);
X}
X
Xdosh () {
X	register char  *str;
X
X	if (str = getenv ("SHELL"))
X		hackexec (2, str, NULL);
X	else
X		hackexec (2, "/bin/sh", "-i", NULL);
X}
X
Xdowield () {
X	register        OBJECT wep;
X
X	multi = 0;
X	if (!(wep = getobj (")", "wield")))
X		flags.move = 0;
X	else if (uwep && uwep -> cursed)
X		pline (WELDED, weapons[uwep -> otyp].wepnam);
X	else {
X		uwep = wep;
X		if (uwep -> cursed)
X			pline ("The %s welds itself to your hand!",
X					weapons[uwep -> otyp].wepnam);
X		else
X			prinv (uwep);
X	}
X}
X
Xddodown () {
X	dostairs ("down");
X}
X
Xddoup () {
X	dostairs ("up");
X}
X
Xdostairs (dir)
Xregister char  *dir;
X{
X	if (u.ustuck ||
X			(*dir == 'd' && (u.ux != xdnstair || u.uy != ydnstair)) ||
X			(*dir == 'u' && (u.ux != xupstair || u.uy != yupstair))) {
X		pline ("You can't go %s here", dir);
X		nomove ();
X		return;
X	}
X	keepdogs (1);
X	unCoff (COFF, 1);
X	dosavelev ();
X	if (*dir == 'd')
X		dodown ();
X	else
X		doup ();
X	losedogs ();
X	if (u.ucham)
X		rescham ();
X	setCon (CON);
X	if (u.uhcursed)
X		docurse ();
X}
X
Xdosavelev () {
X	register        fd;
X
X	glo (dlevel);
X	fd = creat (lock, 0644);
X	savelev (fd);
X	close (fd);
X}
X
Xextern int      uid;
X
Xchecklev (dir)			/* Michiel: Geen geknoei */
Xregister char  *dir;
X{
X	if ((upxstairs[dlevel] != xupstair ||
X				upystairs[dlevel] != yupstair) && !wizard) {
X		clearlocks ();
X		panic (NOCORE, "Way %s has been changed...", dir);
X	}
X}
X
Xdodown () {
X	register        fd;
X
X	glo (++dlevel);
X	if ((fd = open (lock, 0)) < 0)
X		mklev ();
X	else {
X		if (maxdlevel < dlevel)
X			mklev ();/* Bad file  */
X		else
X			getlev (fd);
X		close (fd);
X		checklev ("down");
X	}
X	if (maxdlevel < dlevel)
X		maxdlevel = dlevel;/* Trapdoor/stairs */
X	u.ux = xupstair;
X	u.uy = yupstair;
X	inshop ();
X}
X
Xdoup () {
X	register        fd;
X
X	if (dlevel == 1)
X		done (ESCAPED);
X	glo (--dlevel);
X	if ((fd = open (lock, 0)) < 0)
X		panic (CORE, "Cannot open %s\n", lock);
X	getlev (fd);
X	close (fd);
X	checklev ("up");
X	u.ux = xdnstair;
X	u.uy = ydnstair;
X}
X
Xm_call () {
X	register        OBJECT obj;
X
X	obj = getobj ("?!=/", "call");
X	if (obj)
X		docall (obj);
X	flags.move = 0;
X}
X
Xdocall (obj)
Xregister        OBJECT obj;
X{
X	register char  *str, **str1;
X
X	pline ("Call it:");
X	getlin (buf);
X	flags.topl = 0;
X	if (!*buf)
X		return;
X	str = alloc (strlen (buf) + 1) -> Val;
X	strcpy (str, buf);
X	switch (obj -> olet) {
X		case '_': 
X			free (str);
X			return;
X		case '?': 
X			str1 = &scrcall[obj -> otyp];
X			break;
X		case '!': 
X			str1 = &potcall[obj -> otyp];
X			break;
X		case '/': 
X			str1 = &wandcall[obj -> otyp];
X			break;
X		case '=': 
X			str1 = &ringcall[obj -> otyp];
X			break;
X		default: 
X			pline ("What a weird(%c %d)thing to call", obj -> olet, obj -> otyp);
X
X	}
X	if (*str1)
X		free (*str1);
X	*str1 = str;
X}
X
Xdonull () {
X}
X
XMONSTER bhit ();
X
Xdothrow () {
X	register        OBJECT obj;
X	register        MONSTER monst;
X	register        tmp;
X	char    x, y;
X
X	obj = getobj ("#%)", "throw");
X /* One can also throw food */
X	if (!obj || !getdir ()) {
X		nomove ();
X		return;		/* Sets dx and dy to direction */
X	}
X	if (obj == uarm || obj == uarm2 || obj == uleft ||
X			obj == uright) {
X		pline ("You can't throw something you are wearing");
X		return;
X	}
X	if (obj == uwep && uwepcursed ())
X		return;
X	monst = bhit (dx, dy, 8);
X	x = dx;
X	y = dy;
X	obj = loseone (obj);	/* Separate one out from list */
X	if (monst) {
X		if (obj -> olet == ')') {
X			tmp = u.ulevel - 1 + monst -> data -> ac + abon ();
X			if (obj -> otyp <= W_AMMUNITION) {
X				if (!uwep || uwep -> otyp != obj -> otyp +
X						11)
X					tmp -= 4;
X				else {
X					if (uwep -> cursed)
X						tmp -= uwep -> spe;
X					else
X						tmp += uwep -> spe;
X				}
X			}
X			else {
X				if (obj -> cursed)
X					tmp -= obj -> spe;
X				else
X					tmp += obj -> spe;
X			}
X			if (tmp >= rnd (20)) {
X				if (hmon (monst, obj)) {
X					hit (weapons[obj -> otyp].wepnam,
X							monst);
X					cutworm (monst, x, y, obj -> otyp);
X				}
X				else
X					monst = 0;
X				if (obj -> otyp <= W_AMMUNITION &&
X						rn2 (2)) {
X					freeobj (obj);
X					if (!onbill (obj))
X						ofree (obj);
X					return;
X				}
X			}
X			else
X				miss (weapons[obj -> otyp].wepnam, monst);
X		}
X		else {
X			psee (IT1, x, y, UMISS, monst -> data -> mname, NULL);
X			if (obj -> olet == '%' && monst -> data -> mlet == 'd')
X				if (tamedog (monst, obj))
X					return;
X		}
X/* Awake monster if sleeping */
X		if (monst) {
X			monst -> msleep = 0;
X			if (monst == shopkeeper)
X				setangry ();
X		}
X	}
X	obj -> ox = x;
X	obj -> oy = y;
X	if (obj -> unpaid && inshproom (x, y))
X		subfrombill (obj);
X	if (!m_at (x, y))
X		newsym (x, y);
X}
X
X/* Create a new object (at fobj) of multiplicity 1
X				  remove obj from invent if necessary */
XOBJECT loseone (obj)
Xregister        OBJECT obj;
X{
X	register        OBJECT otmp;
X
X	if (!index ("/=", obj -> olet) && obj -> quan > 1) {
X		obj -> quan--;
X		otmp = newobj ();
X		*otmp = *obj;
X		otmp -> quan = 1;
X		otmp -> unpaid = 0;/* Obj is still on the bill */
X		otmp -> nobj = fobj;
X		fobj = otmp;
X	}
X	else {
X		if (obj == invent)
X			invent = invent -> nobj;
X		else {
X			for (otmp = invent; otmp -> nobj != obj;
X					otmp = otmp -> nobj);
X			otmp -> nobj = obj -> nobj;
X		}
X		obj -> nobj = fobj;
X		fobj = obj;
X	}
X	return (fobj);
X}
X
Xgetdir () {
X	pline ("What direction?");
X	flush ();
X	*buf = getchar ();
X	flags.topl = 0;
X	return (movecm (buf));
X}
X
Xdocurse () {
X	register        MONSTER mtmp;
X
X	for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) {
X		mtmp -> msleep = 0;
X		mtmp -> mtame = 0;
X	}
X	if (shopkeeper)
X		shopkeeper -> angry = 1;
X	if (vaultkeeper)
X		vaultkeeper -> angry = 1;
X}
/
echo 'x - hack.end.c'
sed 's/^X//' > hack.end.c << '/'
X/*
X * Hack.end.c
X */
X
X#include "hack.h"
X#include <signal.h>
X
X#define MAXLEVEL	40
X
Xextern char     plname[], *itoa (), *setan ();
X
Xextern int      billct, rfile;
X
Xchar    maxdlevel = 0, *strcat ();
X
Xchar   *statxx[] = {
X	"choked",
X	"died",
X	"starved",
X	"drowned",
X	"quit",
X	"escaped"
X};
X
Xdone1 () {
X	register char   c;
X
X	nomove ();
X	signal (SIGINT, done1);
X	pline ("Really quit?");
X	flush ();
X	if ((c = getchar ()) == 'y')
X		done (QUIT);
X	else if (c == 'S')
X		hangup ();
X}
X
Xdone (status)
Xregister int    status;
X{
X	if (wizard && status != QUIT && status != ESCAPED) {
X		u.ustr = (u.ustrmax += 2);
X		u.uhp = (u.uhpmax += 10);
X		u.uac--;
X		if (uwep)
X			uwep -> spe++;
X		pline ("For some reason you are still alive.");
X		nomove ();
X		flags.botl = 1;
X		return;
X	}
X	if (status == QUIT && u.uhp <= 0)
X		status = DIED;
X	if (billct)
X		paybill ();
X	clearlocks ();
X	if (status < QUIT) {	/* Not when quit or escaped */
X#ifndef DEBUG
X		savebones ();
X#endif DEBUG
X		outrip ();
X	}
X	hackmode (OFF);
X	cls ();
X	printf ("Goodbye %s...\n\n", plname);
X	u.urexp += u.ugold;
X	if (status == DIED) {
X		strcpy (killer, setan (killer));
X		u.urexp -= u.ugold / 10;
X	}
X	else
X		killer = statxx[status];
X	if (status == ESCAPED) {
X		OBJECT otmp;
X
X		u.urexp += 150;
X		for (otmp = invent; otmp; otmp = otmp -> nobj) {
X			if (otmp -> olet == '*')
X				u.urexp += otmp -> quan * 10 * rnd (250);
X			else if (otmp -> olet == '"')
X				u.urexp += 25000;
X		}
X		printf ("You escaped from the dungeon");
X	}
X	else
X		printf ("You %s on dungeon level %d,", statxx[status],
X				dlevel);
X	printf (" with %U points\n", u.urexp);
X	printf ("and %U pieces of gold, after %u moves.\n",
X			u.ugold, moves);
X	printf ("You were level %d with a maximum of %d hit points when you %s.\n\n", u.ulevel, u.uhpmax, statxx[status]);
X	topten ();
X	flush ();
X	exit (0);
X}
X
X#define	NAMESIZE	 8
X#define	DEATHSIZE	40
X#define TOPPRINT	15	/* Aantal scores dat wordt afgedrukt */
X#define	TOPLIST		25	/* Length of 'top ten' list */
X
Xtopten () {
X	int     tmp;
X	struct recitem {
X		long    points;
X		int     level, maxlvl, hp, maxhp;
X		char    str[NAMESIZE + 1], death[DEATHSIZE + 1];
X	}               rec[TOPLIST + 1], *t1;
X	register        flg;
X
X	for (t1 = rec; t1 < &rec[TOPLIST]; t1++)
X		if (read (rfile, t1, sizeof (struct recitem)) <= 0)
X			                                                t1 -> points = 0;
X	flg = 0;
X	if (u.urexp > rec[TOPLIST - 1].points && !wizard) {
X		signal (SIGINT, SIG_IGN);
X		if (u.urexp > rec[TOPPRINT - 1].points)
X			printf ("You made the top %d list!\n", TOPPRINT);
X		if (lseek (rfile, 0L, 0) < 0)
X			panic (CORE, "Cannot lseek on record file");
X
X/* Stick in new entry. NB: we save the last few
X			entries that disappeared from the list */
X
X		for (tmp = TOPLIST - 2; tmp >= 0 && rec[tmp].points <
X				u.urexp; tmp--)
X			rec[tmp + 1] = rec[tmp];
X		tmp++;		/* Point to right place */
X		rec[tmp].points = u.urexp;
X		rec[tmp].level = dlevel;
X		rec[tmp].maxlvl = maxdlevel;
X		rec[tmp].hp = u.uhp;
X		rec[tmp].maxhp = u.uhpmax;
X		strncpy (rec[tmp].str, plname, NAMESIZE);
X		rec[tmp].str[NAMESIZE] = 0;
X		strncpy (rec[tmp].death, killer, DEATHSIZE);
X		rec[tmp].death[DEATHSIZE] = 0;
X		flg++;
X	}
X	printf ("Number Points Name\n");
X	for (t1 = rec, tmp = 1; t1 < &rec[TOPLIST]; tmp++, t1++) {
X		char    killed = 0;
X
X		if (flg && t1 -> points)
X			write (rfile, t1, sizeof (struct recitem));
X		if (t1 >= &rec[TOPPRINT] || t1 -> points == 0)
X			continue;
X		printf ("%2d  %6D %8s ", tmp, t1 -> points,
X				t1 -> str);
X		if (*t1 -> death == 'e')
X			printf ("escaped the dungeon [max level %d]", t1 -> maxlvl);
X		else {
X			switch (t1 -> death[1]) {
X				case 'u': 
X					printf ("quit");
X					break;
X				case 'h': 
X					printf ("choked on his food");
X					break;
X				case 't': 
X					printf ("starved");
X					break;
X				case 'r': 
X					printf ("drowned");
X					break;
X				default: 
X					printf ("was killed");
X					killed++;
X			}
X			printf (" on%s level %d",
X					killed ? "" : " dungeon", t1 -> level);
X			if (t1 -> maxlvl != t1 -> level)
X				printf (" [%d]", t1 -> maxlvl);
X		}
X		if (killed)
X			printf (" by %s", t1 -> death);
X		putchar ('.');
X		if (t1 -> maxhp)
X			printf (" Hp: %s [%d]", (t1 -> hp > 0) ?
X					itoa (t1 -> hp) : "-", t1 -> maxhp);
X		putchar ('\n');
X	}
X	close (rfile);
X}
X
Xchar   *
X        itoa (a)
Xregister int    a;
X{
X	static char     buffer[8];
X
X	sprintf (buffer, "%d", a);
X	return (buffer);
X}
X
Xclearlocks () {
X	register        x;
X
X	signal (SIGINT, SIG_IGN);
X	for (x = 1; x <= MAXLEVEL; x++) {
X		glo (x);
X		if (unlink (lock))
X			break;
X	}
X#ifdef DEBUG
X	glo (0);
X	unlink (lock);
X#endif DEBUG
X}
X
Xhangup () {
X	save ();
X	clearlocks ();
X	exit (1);
X}
/
echo 'x - hack.invent.c'
sed 's/^X//' > hack.invent.c << '/'
X/*
X * Hack.invent.c
X */
X
X#include	"hack.h"
X
X#define NOT_AT	0
X#define NO_OBJ	0
X
Xextern  WORMSEGMENT wsegs[32];
X
Xextern  OBJECT yourinvent0;
X
XOBJECT addinv (obj)
Xregister        OBJECT obj;
X{
X	register        OBJECT otmp;
X
X	for (otmp = invent; otmp; otmp = otmp -> nobj) {
X		if (otmp -> otyp == obj -> otyp && otmp -> olet == obj -> olet
X				&& !obj -> unpaid && !otmp -> unpaid &&
X				((obj -> otyp < F_COOKIE &&
X						obj -> olet == ')' &&
X						obj -> quan + otmp -> quan < 32 &&
X						obj -> spe == otmp -> spe) ||
X					index ("%?!*", otmp -> olet))) {
X			otmp -> quan += obj -> quan;
X			ofree (obj);
X			return otmp;
X		}
X		if (!otmp -> nobj) {
X			otmp -> nobj = obj;
X			obj -> nobj = 0;
X			return obj;
X		}
X	}
X	invent = obj;
X	obj -> nobj = 0;
X	return obj;
X}
X
Xuseup (obj)
Xregister        OBJECT obj;
X{
X	register        OBJECT otmp;
X
X	if (obj -> quan > 1) {
X		obj -> quan--;
X		return;
X	}
X	if (obj == invent)
X		invent = invent -> nobj;
X	else {
X		for (otmp = invent; otmp -> nobj != obj;
X				otmp = otmp -> nobj);
X		otmp -> nobj = obj -> nobj;
X	}
X	if (!onbill (obj))
X		ofree (obj);
X}
X
Xdelobj (obj)
Xregister        OBJECT obj;
X{
X	freeobj (obj);
X	ofree (obj);
X}
X
Xofree (obj)
Xregister        OBJECT obj;
X{
X	if (obj > yourinvent0)
X		free (obj);
X}
X
X/*  Unlink obj from chain starting with fobj  */
X
Xfreeobj (obj)
Xregister        OBJECT obj;
X{
X	register        OBJECT otmp;
X
X	if (obj == fobj)
X		fobj = fobj -> nobj;
X	else {
X		for (otmp = fobj; otmp -> nobj != obj; otmp = otmp -> nobj)
X			if (!otmp)
X				panic (CORE, "Try to free non-existing object");
X		otmp -> nobj = obj -> nobj;
X	}
X}
X
Xdeltrap (trap)
Xregister        GOLD_TRAP trap;
X{
X	register        GOLD_TRAP gtmp;
X
X	if (trap == ftrap)
X		ftrap = ftrap -> ngen;
X	else {
X		for (gtmp = ftrap; gtmp -> ngen != trap;
X				gtmp = gtmp -> ngen);
X		gtmp -> ngen = trap -> ngen;
X	}
X	free (trap);
X}
X
XMONSTER m_at (x, y)
Xregister        x, y;
X{
X	register        MONSTER mtmp;
X	register        WORMSEGMENT wtmp;
X
X	for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon) {
X		if (mtmp -> mx == x && mtmp -> my == y)
X			return (mtmp);
X		if (mtmp -> wormno)
X			for (wtmp = wsegs[mtmp -> wormno]; wtmp;
X					wtmp = wtmp -> nseg)
X				if (wtmp -> wx == x && wtmp -> wy == y)
X					return (mtmp);
X	}
X	return (NOT_AT);
X}
X
XOBJECT o_at (x, y)
Xregister        x, y;
X{
X	register        OBJECT otmp;
X
X	for (otmp = fobj; otmp; otmp = otmp -> nobj)
X		if (otmp -> ox == x && otmp -> oy == y)
X			return (otmp);
X	return (NOT_AT);
X}
X
XGOLD_TRAP g_at (x, y, ptr)
Xregister        x, y;
Xregister        GOLD_TRAP ptr;
X{
X	while (ptr) {
X		if (ptr -> gx == x && ptr -> gy == y)
X			return (ptr);
X		ptr = ptr -> ngen;
X	}
X	return (NOT_AT);
X}
X
XOBJECT getobj (let, word)
Xregister char  *let, *word;
X{
X	register        OBJECT otmp;
X	register char   ilet, ilet1, ilet2;
X	char    buffer[BUFSZ], allowall = 0;
X	register        foo = 0, foo2;
X
X	if (*let == '#') {
X		let++;
X		allowall++;
X	}
X	ilet = 'a';
X	for (otmp = invent; otmp; otmp = otmp -> nobj) {
X		if (!let || index (let, otmp -> olet))
X			buffer[foo++] = ilet;
X		if (ilet == 'z')
X			ilet = 'A';
X		else
X			ilet++;
X	}
X	buffer[foo] = 0;
X	if (foo > 5) {		/* Compactify string */
X		foo = foo2 = 1;
X		ilet2 = buffer[0];
X		ilet1 = buffer[1];
X		while (ilet = buffer[++foo2] = buffer[++foo]) {
X			if (ilet == ilet1 + 1) {
X				if (ilet1 == ilet2 + 1)
X					buffer[foo2 - 1] = ilet1 = '-';
X				else if (ilet2 == '-') {
X					buffer[--foo2] = ++ilet1;
X					continue;
X				}
X			}
X			ilet2 = ilet1;
X			ilet1 = ilet;
X		}
X	}
X	if (!foo && !allowall) {
X		pline ("You don't have anything to %s.", word);
X		return (NO_OBJ);
X	}
X	for (;;) {
X		pline ((foo) ? "What do you want to %s [%s or ?]? " :
X				"What do you want to %s? ", word, buffer);
X		flags.topl = 0;
X		flush ();
X		ilet = getchar ();
X		if (ilet == '\33' || ilet == ' ' || ilet == '\n')
X			if (strcmp (word, "identify"))
X				return (NO_OBJ);
X			else
X				continue;/* sukkel */
X		if (ilet == '?')
X			doinv (foo ? let : 0, 0);
X		else {
X			if (ilet >= 'A' && ilet <= 'Z')
X				ilet += 26 - 'A';
X			else
X				ilet -= 'a';
X			for (otmp = invent; otmp && ilet; ilet--,
X					otmp = otmp -> nobj);
X			if (!otmp) {
X				pline ("You don't have that object.");
X				continue;
X			}
X			break;
X		}
X	}
X	if (!allowall && let && !index (let, otmp -> olet)) {
X		pline ("That is a silly thing to %s.", word);
X		return (NO_OBJ);
X	}
X	return (otmp);
X}
X
Xprinv (obj)
Xregister        OBJECT obj;
X{
X	register        OBJECT otmp;
X	register char   ilet = 'a';
X
X	for (otmp = invent; otmp != obj; otmp = otmp -> nobj)
X		if (++ilet > 'z')
X			ilet = 'A';
X	prname (obj, ilet, 1);
X}
X
Xprname (obj, let, onelin)
Xregister        OBJECT obj;
Xregister char   let;
X{
X	char    li[BUFSZ];
X
X	doname (obj, buf);
X	sprintf (li, "%c - %s.", let, buf);
X	if (onelin)
X		pline (li);
X	else
X		printf ("%s\n", li);
X}
X
Xddoinv () {
X	nomove ();
X	if (!invent)
X		pline ("You are empty handed.");
X	else
X		doinv (0, 1);
X}
X
X/*
X * Page inventory done by Fred
X *
X */
X
Xdoinv (str, opt)
Xregister char  *str;
Xint     opt;
X{
X	register        OBJECT otmp;
X	register char   ilet = 'a';
X	register int    count = 1;
X	int     ct = 0;
X
X	if (!flags.oneline)
X		for (otmp = invent; otmp; otmp = otmp -> nobj)
X			if (!str || index (str, otmp -> olet))
X				ct++;
X	if (ct > 1)
X		cls ();
X	for (otmp = invent; otmp; otmp = otmp -> nobj) {
X		if (!str || index (str, otmp -> olet)) {
X			prname (otmp, ilet, ct <= 1);
X			count++;
X		}
X		if (++ilet > 'z')
X			ilet = 'A';
X		if (!(count % 22) && otmp -> nobj) {
X			getret ();
X			cls ();	/* M. F. Page listing */
X		}
X	}
X	if (!str && opt)
X		doinvbill ();
X	if (ct > 1) {
X		getret ();
X		docrt ();
X	}
X}
/
echo 'x - hack.lev.c'
sed 's/^X//' > hack.lev.c << '/'
X/*
X * Hack.lev.c
X */
X
X#include "hack.h"
X#include <signal.h>
X
X#define MAXLEVEL	40
X#define ERROR		 1
X#define OK		 0
X
Xextern char    *itoa (), nul[], upxstairs[MAXLEVEL], upystairs[MAXLEVEL];
X
Xextern  WORMSEGMENT wsegs[32], wheads[32];
Xextern unsigned wgrowtime[32];
Xextern struct permonst  pm_ghost;
X
X#include "hack.savelev.c"
X
Xstruct permonst pm_ale = {
X	"giant eel", ';', 15, 6, -3, 3, 6, 0
X};
X
Xgetlev (fd) {
X	register        MONSTER mtmp;
X	register        GOLD_TRAP gtmp;
X	register        OBJECT otmp;
X	register        WORMSEGMENT wtmp;
X	int     tmp, xl;
X	unsigned        tmoves, omoves;
X	STOLE stmp;
X
X	if (fd < 0 || read (fd, levl, sizeof (levl)) != sizeof (levl))
X		return ERROR;
X	fmon = 0;
X	fobj = 0;
X	fgold = 0;
X	ftrap = 0;
X	shopkeeper = 0;
X	vaultkeeper = 0;
X	mread (fd, &omoves, sizeof (unsigned));
X	mread (fd, &xupstair, 1);
X	mread (fd, &yupstair, 1);
X	mread (fd, &xdnstair, 1);
X	mread (fd, &ydnstair, 1);
X	if (omoves)
X		tmoves = (moves > omoves) ? moves - omoves : 0;
X	for (;;) {
X		mread (fd, &xl, sizeof (int));
X		if (xl == -1)
X			break;
X		mtmp = newmonst (xl);
X		mread (fd, mtmp, xl + sizeof (struct monst));
X
X/* Michiel restore stolen objects */
X		stmp = newstole ();
X		mread (fd, stmp, sizeof (struct stole));
X		if (stmp -> sgold || stmp -> sobj) {
X			mtmp -> mstole = stmp;
X			mtmp -> mstole -> sobj = 0;
X			for (;;) {
X				otmp = newobj ();
X				mread (fd, otmp, sizeof (struct obj));
X				if (!otmp -> olet)
X					break;
X				otmp -> nobj = mtmp -> mstole -> sobj;
X				mtmp -> mstole -> sobj = otmp;
X			}
X			ofree (otmp);
X		}
X		else
X			free (stmp);
X/* Regenerate animals if you've been on another level */
X		if (omoves) {
X			if (!index (genocided, mtmp -> data -> mlet)) {
X				if (index ("ViT", mtmp -> data -> mlet))
X					mtmp -> mhp += mtmp -> mhp + tmoves;
X				else
X					mtmp -> mhp += tmoves / 20;
X				if (mtmp -> mhp > mtmp -> orig_hp)
X					mtmp -> mhp = mtmp -> orig_hp;
X				if (mtmp -> data -> mlet == '@') {
X					if (*mtmp -> data -> mname == 's')
X						shopkeeper = mtmp;
X					else if (*mtmp -> data -> mname == 'v')
X						vaultkeeper = mtmp;
X				}
X				mtmp -> nmon = fmon;
X				fmon = mtmp;
X			}
X		}
X		else {		/* Convert code from MKLEV */
X			if (mtmp -> mhp == 10)
X				mtmp -> data = &pm_ghost;
X			else if (mtmp -> ale)
X				mtmp -> data = &pm_ale;
X			else
X				mtmp -> data = &mon[mtmp -> mhp][mtmp -> orig_hp];
X			if (mtmp -> data -> mlet == 'D')
X				mtmp -> mhp = 80;
X			else
X				mtmp -> mhp = mtmp -> data -> mhd ?
X					d (mtmp -> data -> mhd, 8) : rnd (4);
X			mtmp -> orig_hp = mtmp -> mhp;
X			mtmp -> cham = (mtmp -> data -> mlet == ':');
X			mtmp -> invis = (mtmp -> data -> mlet == 'I');
X			if (mtmp -> data -> mlet == 'w' &&
X					getwn (mtmp))
X				initworm (mtmp);
X			mtmp -> nmon = fmon;
X			fmon = mtmp;
X		}
X	}
X	for (;;) {
X		gtmp = newgen ();
X		mread (fd, gtmp, sizeof (struct gen));
X		if (!gtmp -> gx)
X			break;
X		gtmp -> ngen = fgold;
X		fgold = gtmp;
X	}
X	for (;;) {
X		mread (fd, gtmp, sizeof (struct gen));
X		if (!gtmp -> gx)
X			break;
X		gtmp -> ngen = ftrap;
X		ftrap = gtmp;
X		gtmp = newgen ();
X	}
X	free (gtmp);
X	for (;;) {
X		otmp = newobj ();
X		mread (fd, otmp, sizeof (struct obj));
X		if (!otmp -> olet)
X			break;
X		otmp -> nobj = fobj;
X		fobj = otmp;
X	}
X	ofree (otmp);
X	mread (fd, rooms, sizeof (rooms));
X	mread (fd, doors, sizeof (doors));
X	if (!omoves)
X		return OK;	/* From MKLEV */
X	mread (fd, wsegs, sizeof (wsegs));
X	for (tmp = 1; tmp < 32; tmp++)
X		if (wsegs[tmp]) {
X			wheads[tmp] = wsegs[tmp] = wtmp = newseg ();
X			for (;;) {
X				mread (fd, wtmp, sizeof (struct wseg));
X				if (!wtmp -> nseg)
X					break;
X				wheads[tmp] -> nseg = wtmp = newseg ();
X				wheads[tmp] = wtmp;
X			}
X		}
X	mread (fd, wgrowtime, sizeof (wgrowtime));
X	return OK;
X}
X
Xmread (fd, buffer, len)
Xregister        fd, len;
Xregister char  *buffer;
X{
X	register        rlen;
X
X	if ((rlen = read (fd, buffer, len)) != len)
X		panic (CORE, "Read %d instead of %d bytes from file #%d\n",
X				rlen, len, fd);
X}
X
Xmklev () {
X	register        fd;
X	char    type[2];
X
X#ifndef DEBUG
X	if (getbones ()) {
X		sleep (2);
X		goto Z;
X	}
X#endif DEBUG
X	if (flags.next) {
X		flags.next = 0;
X		type[0] = 'b';
X	}
X	else if (dlevel < rn1 (3, MAXLEVEL - 3))
X		type[0] = 'a';
X	else {
X		type[0] = 'n';
X		flags.next = 1;
X	}
X	type[1] = '\0';
X	hackexec (0, "./mklev", lock, type, itoa (dlevel), genocided,
X			wizard ? "w" : "", NULL);
X	if ((fd = open (lock, 0)) < 0) {
X		pline ("Can't open %s! Second try.", lock);
X		flush ();
X		hackexec (0, "./mklev", lock, type, itoa (dlevel), genocided,
X				wizard ? "w" : "", NULL);
X		if ((fd = open (lock, 0)) < 0)
X			panic (NOCORE, "Mklev error no level");
X	}
X	getlev (fd);
X	close (fd);
XZ: 
X	if (!upxstairs[dlevel] && !upystairs[dlevel]) {
X		upxstairs[dlevel] = xupstair;
X		upystairs[dlevel] = yupstair;
X	}
X}
/
echo 'x - hack.main.c'
sed 's/^X//' > hack.main.c << '/'
X/*
X * Hack.main.c
X */
X
X#include <signal.h>
X#include "hack.h"
X
X#define exception( id )	( id == uid )
X#define HUISJES	2201
X#define WILDE	2216
X
Xextern char    *hu_stat[4], *getenv (), *malloc (), *parse ();
X
Xint     rfile;
X
XCOORDINATES doors[DOORMAX];
X
XPART levl[80][22];
XMKROOM rooms[15];
XMONSTER fmon = 0;
XGOLD_TRAP fgold = 0, ftrap = 0;
XFLAG flags;
XYOU u;
XOBJECT fobj = 0, invent, uwep, uarm,
Xuarm2 = 0, uright = 0, uleft = 0;
X
Xextern  OBJECT yourinvent0;
Xextern struct obj       mace0, uarm0;
X
Xchar    nul[20];		/* Contains zeros */
X/* Lock contains 'pid'.dlevel */
Xchar    plname[10], lock[16], wizard,
X        curx, cury, savx,
X        xupstair, yupstair, xdnstair, ydnstair,
X       *save_cm = 0, *killer, *nomvmsg, dlevel = 0,
X        dx, dy, buf[BUFSZ], genocided[60],
X        SAVEFILE[37] = SAVEDIR;
X
Xunsigned        moves = 1;
X
Xint     multi = 0, done1 (), hangup (), hackpid;
Xint     uid;
X
Xmain (argc, argv)
Xchar   *argv[];
X{
X	int     fd;
X	char *getlogin();
X	register char  *yourname = getlogin ();
X
X	uid = getuid ();
X	/*
X	 * Check on UID's
X	 */
X
X	if (kantoor () && !exception (HUISJES) && !exception (WILDE)) {
X		printf ("Sorry, You can't play hack now\n" );
X		flush ();
X		exit (0);
X	}
X	if (!access (LOCK, 0) && strcmp (WIZARD, yourname)) {
X		printf ("Sorry, I'm busy with debugging.\nTry again later.\n");
X		flush ();
X		exit (0);
X	}
X
X	strncpy (plname, yourname, sizeof (plname) - 1);
X#ifdef WIZARD
X	while (argc > 1 && **++argv == '-') {
X		switch (argv[0][1]) {
X			case 'w': 
X				if (!exception (HUISJES) && !exception (WILDE) && strcmp (yourname, WIZARD))
X					printf ("Sorry\n");
X				else {
X					strcpy (plname, "wizard");
X					wizard++;
X				}
X				break;
X			default: 
X				printf ("Unknown option: %s\n", *argv);
X		}
X		flush ();
X	}
X#endif WIZARD
X
X	if (chdir (PLAYGROUND) < 0)
X		panic (NOCORE, "Cannot chdir to %s!", PLAYGROUND);
X	if ((rfile = open (RECORD, 2)) < 0)
X		panic (NOCORE, "Can't open %s!", RECORD);
X	setuid (getuid ());
X	umask (0);
X	srand (hackpid = getpid ());
X	startup ();
X	signal (SIGHUP, hangup);
X	signal (SIGINT, done1);
X	hackmode (ON);
X	if (!wizard) {
X		cls ();
X		flush ();
X	}
X	strcat (SAVEFILE, plname);
X	fd = open (SAVEFILE, 0);
X	if (fd >= 0) {
X		if (dorecover (fd) < 0)
X			goto normalplay;
X		flags.move = 0;
X	}
X	else {
Xnormalplay: 
X		shuffle ();
X		invent = yourinvent0;
X		uwep = &mace0;
X		uarm = &uarm0;
X		u.uac = 6;	/* 10 - uarm->spe */
X		u.ulevel = 1;
X		u.uhunger = 900;
X		u.uhpmax = u.uhp = 12;
X		u.ustrmax = u.ustr = rn2 (20) ? 16 : rn1 (7, 14);
X		flags.move = 1;
X		dodown ();	/* a3 */
X		cls ();
X		setCon (SETC);
X		flags.botl = 1;
X		makedog ();
X	}
X	for (;;) {
X		if (flags.move) {
X			if (!u.ufast || moves % 2 == 0) {
X				if (fmon)
X					movemon ();
X				if (!rn2 (70)) {
X					makemon (0);
X					fmon -> mx = 0;
X					fmon -> my = 0;
X					rloc (fmon);
X					seeatl (fmon -> mx, fmon -> my,
X							fmon -> data -> mlet);
X				}
X			}
X			if (u.ufast && !--u.ufast)
X				pline ("You feel yourself slowing down");
X			if (u.uconfused && !--u.uconfused)
X				pline ("You feel less confused now");
X			if (u.ublind && !--u.ublind) {
X				pline ("You can see again");
X				if (!u.uswallow)
X					setCon (SETC);
X			}
X			if (u.uinvis && !--u.uinvis) {
X				if (!u.uswallow)
X					on (u.ux, u.uy);
X				pline ("You are no longer invisible");
X			}
X			++moves;
X			if (u.uhp <= 0) {
X				pline ("You die...");
X				more ();
X				done (DIED);
X			}
X			if (u.uhp < u.uhpmax) {
X				if (u.ulevel > 9) {
X					if (u.uregen || moves % 3 == 0) {
X						flags.dhp = 1;
X						u.uhp +=
X							rnd (u.ulevel - 9);
X						if (u.uhp > u.uhpmax)
X							u.uhp = u.uhpmax;
X					}
X				}
X				else if (u.uregen || moves %
X						(22 - (u.ulevel << 1)) == 0) {
X					flags.dhp = 1;
X					u.uhp++;
X				}
X			}
X			if (u.utel && !rn2 (85))
X				tele ();
X			if (u.usearch)
X				dosearch ();
X			gethungry ();
X		}
X		flags.move = 1;
X		if (flags.dscr && !flags.mv)
X			nscr ();
X		if (flags.botl)
X			bot ();
X		else if (flags.dgold) {
X			flags.dgold = 0;
X			curs (16, 24);
X			curx = 21;
X			printf ("%-5U", u.ugold);
X		}
X		if (flags.dhp) {
X			flags.dhp = 0;
X			curs (26, 24);
X			curx = 29;
X			printf ("%3d", u.uhp);
X		}
X		if (flags.dhpmax) {
X			flags.dhpmax = 0;
X			curs (30, 24);
X			printf ("%d)", u.uhpmax);
X			if (u.uhpmax < 100)
X				putchar (' ');
X			curx = (u.uhpmax < 10) ? 33 : 34;
X		}
X		if (flags.dac) {
X			flags.dac = 0;
X			curs (37, 24);
X			printf ("%-3d", u.uac);
X			curx = 40;
X		}
X		if (flags.dstr) {
X			flags.dstr = 0;
X			curs (46, 24);
X			prustr ();
X			curx = 51;
X		}
X		if (flags.dulev) {
X			flags.dulev = 0;
X			curs (57, 24);
X			printf ("%2d", u.ulevel);
X			curx = 59;
X		}
X		if (flags.dexp) {
X			flags.dexp = 0;
X			curs (60, 24);
X			if (u.ulevel < 14)
X				printf ("%-5U", u.uexp);
X			else
X				printf ("MAX++");
X			curx = 65;
X		}
X		if (flags.dhs) {
X			flags.dhs = 0;
X			curs (71, 24);
X			printf (hu_stat[u.uhs]);
X			curx = 79;
X		}
X		if (multi < 0) {
X			if (!++multi) {
X				pline (nomvmsg ? nomvmsg :
X						"You can move again.");
X				nomvmsg = 0;
X			}
X		}
X		else {
X			if (multi) {
X				lookaround ();
X				if (!multi) {
X					flags.move = 0;
X					continue;
X				}
X				if (flags.mv) {
X					if (multi < 80 && !--multi) {
X						flags.mv = 0;
X						flags.run = 0;
X					}
X					domove ();
X				}
X				else {
X					--multi;
X					rhack (save_cm);
X				}
X			}
X			else
X				rhack (parse ());
X		}
X	}
X}
X
Xglo (n)
Xregister        n;		/* Construct the string `hackpid.n' */
X{
X/*
X	register char *tf = lock;
X
X	while( *tf && *tf != '.' )
X		tf++;
X	*tf++ = '.';
X	sprintf( tf, "%d", n );
X*/
X	sprintf (lock, "%d.%d", hackpid, n);
X}
X
Ximpossible () {
X	pline ("Program in disorder - perhaps you'd better Quit");
X}
/
echo 'x - hack.mkobj.c'
sed 's/^X//' > hack.mkobj.c << '/'
X/*
X * Hack.mkobj.c
X */
X
X#include "hack.h"
X#include "hack.vars.h"
X
Xmkfood () {
X	register        FOOD fp;
X	register        i = rn2 (100);
X
X	fp = &foods[0];
X	while ((i -= fp -> prob) >= 0)
X		fp++;
X	return (fp - foods);
X}
X
Xmkarm () {
X	register        ARMOR ap;
X	register        i = rn2 (100);
X
X	ap = &armors[0];
X	while ((i -= ap -> prob) >= 0)
X		ap++;
X	return (ap - armors);
X}
X
Xmkwep () {
X	register        WEAPON wp;
X	register        i = rn2 (100);
X
X	wp = &weapons[0];
X	while ((i -= wp -> prob) >= 0)
X		wp++;
X	return (wp - weapons);
X}
X
Xchar    mkobjstr[] = "))[[!!!!????%%%%//=**";
X
Xmkobj (let)
Xregister        let;
X{
X	register        OBJECT otmp;
X
X	otmp = newobj ();
X	otmp -> nobj = fobj;
X	fobj = otmp;
X	otmp -> known = 0;
X	otmp -> cursed = 0;
X	otmp -> spe = 0;
X	otmp -> unpaid = 0;
X	otmp -> quan = 1;
X	if (!let)
X		let = mkobjstr[rn2 (sizeof (mkobjstr) - 1)];
X	otmp -> olet = let;
X	switch (let) {
X
X		case ')': 
X			otmp -> otyp = mkwep ();
X			if (otmp -> otyp <= W_AMMUNITION)
X				otmp -> quan = rn1 (6, 6);
X			if (!rn2 (11))
X				otmp -> spe = rnd (3);
X			else if (!rn2 (10)) {
X				otmp -> cursed = 1;
X				otmp -> spe = -rnd (3);
X			}
X			break;
X
X		case '*': 
X			otmp -> otyp = rn2 (SIZE (potcol));
X			otmp -> quan = rn2 (6) ? 1 : 2;
X			break;
X
X		case '[': 
X			otmp -> otyp = mkarm ();
X			if (!rn2 (8))
X				otmp -> cursed = 1;
X			if (!rn2 (10))
X				otmp -> spe = rnd (3);
X			else if (!rn2 (9)) {
X				otmp -> spe = -rnd (3);
X				otmp -> cursed = 1;
X			}
X			otmp -> spe += 10 - armors[otmp -> otyp].a_ac;
X			break;
X
X		case '!': 
X			otmp -> otyp = rn2 (SIZE (pottyp));
X			break;
X
X		case '?': 
X			otmp -> otyp = rn2 (SIZE (scrtyp));
X			break;
X
X		case '%': 
X			otmp -> otyp = mkfood ();
X			otmp -> quan = rn2 (6) ? 1 : 2;
X			break;
X
X		case '/': 
X			otmp -> otyp = rn2 (SIZE (wantyp));
X			if (otmp -> otyp == Z_DEATH)
X				otmp -> otyp = rn2 (SIZE (wantyp));
X			otmp -> spe = rn1 (5, (otmp -> otyp <= Z_CREATE_MON) ?
X					11 : 4);
X		/* detection and light and create monster */
X			break;
X
X		case '=': 
X			otmp -> otyp = rn2 (SIZE (ringtyp));
X			if (otmp -> otyp >= R_GAIN_STR) {
X				if (!rn2 (3)) {
X					otmp -> spe = -rnd (2);
X					otmp -> cursed = 1;
X					break;
X				}
X				else
X					otmp -> spe = rnd (2);
X			}
X			else if (otmp -> otyp == R_TELE ||
X						otmp -> otyp == R_AGGRAV_MON ||
X					otmp -> otyp == R_HUNGER)
X				otmp -> cursed = 1;
X			break;
X
X		default: 
X			panic (CORE, "Impossible mkobj");
X	}
X}
X
Xshufl (base, num)
Xregister char  *base[];
Xregister        num;
X{
X	char  **tmp, *tmp1;
X	int     curnum;
X
X	for (curnum = num - 1; curnum > 0; curnum--) {
X		tmp = &base[rn2 (curnum)];
X		tmp1 = *tmp;
X		*tmp = base[curnum];
X		base[curnum] = tmp1;
X	}
X}
X
Xshuffle () {
X	shufl (wannam, SIZE (wantyp));
X	shufl (potcol, SIZE (potcol));
X	shufl (rinnam, SIZE (ringtyp));
X	shufl (scrnam, SIZE (scrtyp));
X}
X
Xsavenames (fd)
Xregister        fd;
X{
X	bwrite (fd, oiden, sizeof oiden);
X	bwrite (fd, potcol, sizeof potcol);
X	bwrite (fd, scrnam, sizeof scrnam);
X	bwrite (fd, wannam, sizeof wannam);
X	bwrite (fd, rinnam, sizeof rinnam);
X}
X
Xrestnames (fd)
Xregister        fd;
X{
X	mread (fd, oiden, sizeof oiden);
X	mread (fd, potcol, sizeof potcol);
X	mread (fd, scrnam, sizeof scrnam);
X	mread (fd, wannam, sizeof wannam);
X	mread (fd, rinnam, sizeof rinnam);
X}
X
X/* Restore the names we have given to things */
Xcallsrestore (fd)
Xregister        fd;
X{
X	restcalls (fd, potcall, SIZE (pottyp));
X	restcalls (fd, wandcall, SIZE (wantyp));
X	restcalls (fd, ringcall, SIZE (ringtyp));
X	restcalls (fd, scrcall, SIZE (scrtyp));
X}
X
X/* Save things we have given names to */
Xcallssave (fd)
Xregister        fd;
X{
X	savecalls (fd, potcall, SIZE (pottyp));
X	savecalls (fd, wandcall, SIZE (wantyp));
X	savecalls (fd, ringcall, SIZE (ringtyp));
X	savecalls (fd, scrcall, SIZE (scrtyp));
X}
X
Xsavecalls (fd, strings, max)
Xchar   *strings[];
Xregister int    max, fd;
X{
X	register        teller;
X
X	for (teller = 0; teller < max; ++teller) {
X		if (strings[teller])
X			bwrite (fd, strings[teller],
X					strlen (strings[teller]) + 1);
X		else
X			bwrite (fd, "\0", 1);
X	}
X}
X
Xrestcalls (fd, strings, max)
Xregister int    fd, max;
Xchar   *strings[];
X{
X	register        teller;
X	char   *str;
X	int     cnt;
X	char    buffer[BUFSZ];
X
X	str = NULL;
X	for (teller = 0; teller < max; ++teller) {
X		cnt = -1;
X		do {
X			++cnt;
X			mread (fd, str, 1);
X			buffer[cnt] = *str;
X		} while (*str != '\0');
X		if (cnt) {
X			strings[teller] = alloc (strlen (buffer) + 1) -> Val;
X			strcpy (strings[teller], buffer);
X		}
X	}
X}
/
echo 'x - hack.save.c'
sed 's/^X//' > hack.save.c << '/'
X/*
X * Hack.save.c
X */
X
X/*
X * The old version of save () didn't work at all. Many things are changed,
X * but some things are not implemented yet, like saving in a shop, or saving
X * while swallowed or stuck
X */
X
X#include "hack.h"
X#include "hack.dog.h"
X#include <signal.h>
X
X#define MAXLEVEL	40
X
Xextern char     SAVEFILE[], nul[], upxstairs[MAXLEVEL],
X                upystairs[MAXLEVEL], shlevel, vaultflag[MAXLEVEL];
Xextern long     robbed;
Xextern unsigned starved;
Xextern  COORDINATES shk, shd;
Xextern  MONSTER shopkeeper;
Xextern  MONSTER mydogs;
X
Xsave () {
X	register        fd, ofd, tmp;
X	register        OBJECT otmp, otmp2;
X	MONSTER mtmp;
X	int     version = VERSION;
X
X	nomove ();
X	if (shopkeeper && inshproom (u.ux, u.uy)) {
X		pline ("You are not allowed to save in a shop. (Continue or Quit)");
X		return;
X	}
X	else if (u.ustuck || u.uswallow) {
X		pline ("Not implemented when you're stuck or swallowed. (Continue or Quit)");
X		return;
X	}
X	if ((fd = creat (SAVEFILE, 0644)) < 0) {
X		pline ("Cannot creat save file. (Continue or Quit)");
X		return;
X	}
X	signal (SIGINT, SIG_IGN);
X	signal (SIGQUIT, SIG_IGN);
X
X	bwrite (fd, &version, sizeof (version));
X	keepdogs (0);
X	savelev (fd);
X	for (otmp = invent; otmp; otmp = otmp2) {
X		bwrite (fd, otmp, sizeof (struct obj));
X		if (otmp == uarm)
X			bwrite (fd, "a", 1);
X		else if (otmp == uarm2)
X			bwrite (fd, "b", 1);
X		else if (otmp == uwep)
X			bwrite (fd, "w", 1);
X		else if (otmp == uleft)
X			bwrite (fd, "l", 1);
X		else if (otmp == uright)
X			bwrite (fd, "r", 1);
X		else
X			bwrite (fd, "n", 1);
X		otmp2 = otmp -> nobj;
X		ofree (otmp);
X	}
X	bwrite (fd, nul, sizeof (struct obj));
X	bwrite (fd, &flags, sizeof (struct flag));
X	bwrite (fd, &dlevel, sizeof dlevel);
X	bwrite (fd, &moves, sizeof moves);
X	bwrite (fd, &u, sizeof (struct you));
X	bwrite (fd, genocided, sizeof genocided);
X	bwrite (fd, upxstairs, sizeof upxstairs);
X	bwrite (fd, upystairs, sizeof upystairs);
X	bwrite (fd, vaultflag, sizeof vaultflag);
X
X	savenames (fd);
X
X/* SHOP part */
X	bwrite (fd, &shd, sizeof (struct coord));
X	bwrite (fd, &shk, sizeof (struct coord));
X	bwrite (fd, &shlevel, sizeof shlevel);
X	bwrite (fd, &robbed, sizeof robbed);
X
X/* Various globals */
X	bwrite (fd, &starved, sizeof starved);
X	bwrite (fd, &seehx, sizeof seehx);
X	bwrite (fd, &seelx, sizeof seelx);
X	bwrite (fd, &seehy, sizeof seehy);
X	bwrite (fd, &seely, sizeof seely);
X	bwrite (fd, &dx, sizeof dx);
X	bwrite (fd, &dy, sizeof dy);
X	bwrite (fd, &maxdlevel, sizeof maxdlevel);
X
X/* And the dog(s) if any */
X	for (mtmp = mydogs; mtmp; mtmp = mtmp -> nmon)
X		bwrite (fd, mtmp, sizeof (struct monst) +
X			                                        sizeof (struct edog));
X	bwrite (fd, nul, sizeof (struct monst) + sizeof (struct edog));
X
X	callssave (fd);
X
X	cls ();
X	printf ("Saving level ");
X	flush ();
X	for (tmp = 1;; tmp++) {
X		glo (tmp);
X		if ((ofd = open (lock, 0)) < 0)
X			break;
X		getlev (ofd);
X		close (ofd);
X		savelev (fd);
X		printf ("%2d - %s", tmp,
X				(tmp % 10) ? "" : "\n             ");
X		flush ();
X		unlink (lock);
X	}
X
X	close (fd);
X	(*index (lock, '.')) = '\0';/* Remove main lock */
X	unlink (lock);
X	printf ("\n\nSee you around...\n");
X	flush ();
X	hackmode (OFF);
X	exit (0);
X}
X
Xdorecover (fd)
Xregister        fd;
X{
X	register        nfd, tmp;
X	register        OBJECT otmp, olast;
X	MONSTER mtmp;
X	int     version;
X
X	cls ();
X	printf ("Starting up a suspended game....\n");
X	flush ();
X	mread (fd, &version, sizeof (version));
X	if (version != VERSION) {
X		printf ("Sorry, you're savefile is out of date.\n");
X		printf ("I will have to remove it.\n");
X		printf ("Type <space> to continue.");
X		close (fd);
X		unlink (SAVEFILE);
X		flush ();
X		while (getchar () != ' ');
X		return - 1;
X	}
X
X	getlev (fd);
X
X	invent = otmp = newobj ();
X	while (1) {
X		mread (fd, otmp, sizeof (struct obj));
X		if (!otmp -> olet) {
X			if (otmp == invent)
X				invent = 0;
X			else
X				olast -> nobj = 0;
X			ofree (otmp);
X			break;
X		}
X		olast = otmp;
X		olast -> nobj = otmp = newobj ();
X		mread (fd, buf, 1);
X		switch (*buf) {
X			case 'w': 
X				uwep = olast;
X				break;
X			case 'r': 
X				uright = olast;
X				break;
X			case 'l': 
X				uleft = olast;
X				break;
X			case 'a': 
X				uarm = olast;
X				break;
X			case 'b': 
X				uarm2 = olast;
X			case 'n': 
X				break;
X			default: 
X				panic (CORE, "Error reading save file");
X		}
X	}
X	mread (fd, &flags, sizeof (struct flag));
X	mread (fd, &dlevel, sizeof dlevel);
X	mread (fd, &moves, sizeof moves);
X	mread (fd, &u, sizeof (struct you));
X	mread (fd, genocided, sizeof genocided);
X	mread (fd, upxstairs, sizeof upxstairs);
X	mread (fd, upystairs, sizeof upystairs);
X	mread (fd, vaultflag, sizeof vaultflag);
X
X	restnames (fd);
X
X/* Restore shop part */
X	mread (fd, &shd, sizeof (struct coord));
X	mread (fd, &shk, sizeof (shk));
X	mread (fd, &shlevel, sizeof shlevel);
X	mread (fd, &robbed, sizeof robbed);
X
X/* Restore various globals */
X	mread (fd, &starved, sizeof starved);
X	mread (fd, &seehx, sizeof seehx);
X	mread (fd, &seelx, sizeof seelx);
X	mread (fd, &seehy, sizeof seehy);
X	mread (fd, &seely, sizeof seely);
X	mread (fd, &dx, sizeof dx);
X	mread (fd, &dy, sizeof dy);
X	mread (fd, &maxdlevel, sizeof maxdlevel);
X
X/* Let's try the dog again */
X	while (1) {
X		mtmp = newmonst (sizeof (struct edog));
X		mread (fd, mtmp, sizeof (struct monst) +
X			                                        sizeof (struct edog));
X		if (mtmp -> data == 0)
X			break;
X		else {
X			mtmp -> nmon = mydogs;
X			mydogs = mtmp;
X		}
X	}
X	free (mtmp);
X
X	callsrestore (fd);
X
X	printf ("Restoring level ");
X	flush ();
X	for (tmp = 1;; tmp++) {
X		if (getlev (fd))
X			break;
X		glo (tmp);
X		if ((nfd = creat (lock, 0644)) < 0)
X			panic (CORE, "Cannot open temp file %s!\n",
X					lock);
X		savelev (nfd);
X		printf ("%2d - %s", tmp,
X				(tmp % 10) ? "" : "\n                ");
X		flush ();
X		close (nfd);
X	}
X
X	lseek (fd, (long) (sizeof (version)), 0);
X	getlev (fd);
X	close (fd);
X	losedogs ();
X	unlink (SAVEFILE);
X	docrt ();
X	return 1;
X}
/
echo 'Part 04 of Hack complete.'
exit
-- 

			Michiel Huisjes.
			{seismo|decvax|philabs}!mcvax!vu44!ark!huisjes

huisjes@ark.UUCP (Michiel B. Huisjes) (02/06/85)

#!/bin/sh
#
# 
# 
# This is a shell archive. These archives are packed by the program 
# packmail(1). If you have the program unshar(1), I suggest you use it.
# If you don't remove anything before the cut line and then feed to
# sh(1)
# 
# =====CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE=======CUT HERE===
#
echo 'Start of Hack, part 05 of 05:'
echo 'x - Makefile'
sed 's/^X//' > Makefile << '/'
X# hack makefile.
X# layout en verdere verbeteringen Michiel en Fred
X
XPLAYDIR = /usr/games/playdir
XSAVEDIR = /usr/games/playdir/save
X
XCFLAGS = -O -i
XLIB = -ltermlib
X
XTARGET = hack
X
XHFILES = hack.c hack.lev.c hack.pri.c hack.do.c hack.do1.c hack.main.c\
Xhack.mon.c hack.dog.c hack.invent.c hack.eat.c hack.save.c\
Xhack.do_wear.c hack.shk.c hack.io.c hack.end.c hack.rip.c\
Xhack.bones.c hack.mkobj.c hack.monst.c hack.invinit.c hack.worm.c\
Xhack.debug.c hack.move.c hack.do.misc.c hack.mon.do.c hack.str.c\
Xhack.office.c
X
XMFILES = mklev.c mklev.make.c mklev.mkobj.c mklev.svlev.c 
X
XGFILES = rnd.c alloc.c
X
XHOBJ = hack.o hack.lev.o hack.pri.o hack.do.o hack.do1.o hack.main.o\
Xhack.mon.o hack.dog.o hack.invent.o hack.eat.o hack.save.o\
Xhack.do_wear.o hack.shk.o hack.io.o hack.end.o hack.rip.o\
Xhack.bones.o hack.mkobj.o hack.monst.o hack.invinit.o hack.worm.o\
Xhack.debug.o hack.move.o hack.do.misc.o hack.mon.do.o hack.str.o\
Xhack.office.o
X
XGOBJ = rnd.o alloc.o
X
XMKOBJ = mklev.o mklev.make.o mklev.mkobj.o
X
Xall: hack mklev show
X
X$(TARGET)   : $(HOBJ) $(GOBJ)
X	@echo Loading...
X	@$(CC) $(CFLAGS) -o $(TARGET) $(GOBJ) $(HOBJ) $(LIB)
X	@size $(TARGET)
X	@echo 'Done Hack'
X
X$(HOBJ) $(MKOBJ) :	hack.h
Xhack.do.misc.o:		hack.do.vars.h envir.h
Xhack.vars.h:		hack.foods.h hack.armors.h hack.weapons.h
Xhack.lev.o:		hack.savelev.c
Xhack.dog.o hack.monst.o:        hack.dog.h
Xhack.mkobj.o mklev.mkobj.o: 	hack.vars.h
Xhack.main.o hack.lev.o hack.debug.o \
Xhack.do.misc.o hack.end.o hack.invinit.o: envir.h
X
Xhack.invinit.o:
X	cc $(CFLAGS) -c hack.invinit.c
X
Xmklev.o: hack.h envir.h
X	cc $(CFLAGS) -c mklev.c
X
Xmklev:  $(MKOBJ) $(GOBJ) mklev.svlev.c
X	cc $(CFLAGS) $(MKOBJ) $(GOBJ) -o mklev
X	@echo 'Done mklev'
X
Xshow: show.c hack.h envir.h
X	cc -O show.c -o show
X	@echo 'Done show'
X
Xcleanup:
X	rm -f $(HOBJ) $(GOBJ) $(PLAYDIR)/show $(PLAYDIR)/makelev \
X	   $(PLAYDIR)/bones_* mklev.mkobj.o mklev.o
X
Xinstall: all 
X	rm -f $(PLAYDIR)/bones_*
X	install -c -m 4711 $(TARGET) $(PLAYDIR)/$(TARGET)
X	install -c -m 711 mklev $(PLAYDIR)/mklev
X	install -c -m 700 show $(PLAYDIR)/show
X
Xnew: dirs install
X
Xdirs:
X	mkdir $(PLAYDIR)
X	mkdir $(SAVEDIR)
X	mv help $(PLAYDIR)
X	cp /dev/null $(PLAYDIR)/record
X	chmod 700 $(PLAYDIR)/record
X
Xlint:
X	lint -phbxac mk*.c rnd.c alloc.c -lc
/
echo 'x - READ_ME'
sed 's/^X//' > READ_ME << '/'
X
XWell, here they are, the sources of Hack for pdp11/44 and pdp11/45.
X
XHow to install these on your machine.
XThis is actually quite simple. Edit the file ``envir.h'' to define the
Xlocal parameters. Edit the Makefile to define the playdir directory
X(default /usr/games). Determine who will be the owner of the game, since
Xit has the setuid bits on. 
XAfter you unshared the shar-files (in a new directory),
Xyou should have the following files:
X	1) - help data Makefile show.c rnd.c alloc.c
X
X	2) - envir.h hack.armors.h hack.do.vars.h hack.dog.h hack.foods.h 
X	   - hack.h hack.name.h hack.vars.h hack.weapons.h 
X
X	3) - hack.bones.c hack.c hack.debug.c hack.do.c hack.do.misc.c 
X	   - hack.do1.c hack.do_wear.c hack.dog.c hack.eat.c hack.end.c 
X	   - hack.invent.c hack.invinit.c hack.io.c hack.lev.c hack.main.c 
X	   - hack.mkobj.c hack.mon.c hack.mon.do.c hack.monst.c hack.move.c 
X	   - hack.office.c hack.pri.c hack.rip.c hack.save.c hack.savelev.c 
X	   - hack.shk.c hack.str.c hack.worm.c
X
X	4) - mklev.c mklev.make.c mklev.mkobj.c mklev.svlev.c 
X
XNow type ``make'' and the file ``hack'', ``mklev'' and ``show'' will be created.
XNow type make new and the program will be installed in the right place.
X
XOne of the main problems of Hack is its size. If you add about 1000 bytes of
Xtext more, your text segment will be to big. Therefore we saved text wherever 
Xthis was possible. We removed the function fscanf(), and made the record file
Xbinary. To show the contents, use the program show (with flag -r).
X
XSome additions we (Fred de Wilde and Michiel Huisjes) made are
X	- The Vault
X	- The Swamp
X	- The Zoo
X	- The Graveyard
X	- Maxlevel = 40
X	- Proper Saving
X	- Several bugs
X	- And many, many more...
XA great bug that still exists is the display of the screen when you're blind.
XSome more bugs are still existing, but you'll find those out while playing.
X
XThere is not a manual included with these sources. I suggest you use the
Xmanual of the distributed version of hack (1.0.1) of CWI. 
X
XHave fun, and good hacking!
X
X				Michiel Huisjes and Fred de Wilde
X				{seismo|decvax|philabs}!mcvac!vu44!ark!huisjes
X								   ...!wilde
/
echo 'x - alloc.c'
sed 's/^X//' > alloc.c << '/'
X/*
X * Alloc.c
X *
X * Added new return values Michiel and Fred
X *
X */
X
X/*
X * The strange return value of alloc is implemented to shut lint up
X */
X
X#include "hack.h"
X
Xextern char    *malloc ();
X
Xunion PTRS ptrs;
X
Xunion PTRS *
Xalloc (num)
Xregister        num;
X{
X	register char  *val;
X
X	if (!(val = malloc (num)))
X		panic (CORE, "Cannot get %d bytes", num);
X	ptrs.Val = val;
X	return (&ptrs);
X}
/
echo 'x - envir.h'
sed 's/^X//' > envir.h << '/'
X/*
X * Envir.h
X */
X
X#define	PLAYGROUND	"/usr/games/playdir"
X#define HELP 		"/usr/games/playdir/help"
X#define HELP 		"/usr/games/playdir/data"
X#define RECORD		"/usr/games/playdir/record"
X#define LOCK		"/usr/games/playdir/hack.lock"
X#define	WIZARD		"huisjes"
X/*
X#define DEBUG
X*/
X
X#define SAVEDIR		"save/"
X#define	MORE		"/usr/ucb/more"
X#define VERSION		1
/
echo 'x - hack.armors.h'
sed 's/^X//' > hack.armors.h << '/'
X/*
X * Hack.armors.h
X */
X
Xstruct armor armors[] = {
X	{ "plate mail",	 	    5,	5, 3, 2 },
X	{ "splint mail",	   10,	5, 4, 1 },
X	{ "banded mail",	   10,	5, 4, 0 },
X	{ "chain mail",		   10,	5, 5, 1 },
X	{ "scale mail",		   10,	5, 6, 0 },
X	{ "ring mail",		   15,	5, 7, 0 },
X	{ "studded leather armor", 15,	3, 7, 1 },
X	{ "leather armor",   	   20,	3, 8, 0 },
X	{ "elven cloak",	    5,	0, 9, 3 },
X	{ "PROG ERROR",	   	  100,	0, 0, 0 }
X };
/
echo 'x - hack.bones.c'
sed 's/^X//' > hack.bones.c << '/'
X/*
X * Hack.bones.c
X *
X * Added increased chances on bones files.
X * Fixed bug with mad shopkeeper.
X *
X */
X
X#include "hack.h"
X
X#define NOBONES	0
X#define BONES	1
X
Xextern char     plname[10];
Xextern  MONSTER shopkeeper;
X
Xstruct permonst pm_ghost = {
X	"ghost", '\t', 10, 3, -5, 1, 1, sizeof (plname)
X};
X
X/* (a3)#define	GHMAX	10 */
X
Xchar    bones[] = "bones_xx";
X
X/* Save bones and possessions of a deceased adventurer */
Xsavebones () {
X	register        fd;
X	register        OBJECT otmp;
X	register        GOLD_TRAP gtmp;
X	register        MONSTER mtmp;
X
X	if (!rn2 (1 + dlevel/2))
X		return;	/* not so many ghosts on low levels */
X	sprintf (&bones[6], "%d", dlevel);
X	if ((fd = open (bones, 0)) >= 0 ) {
X		close (fd);
X		return;
X	}
X
X /* Drop everything; the corpse's possessions are usually cursed */
X	otmp = invent;
X	while (otmp) {
X		otmp -> ox = u.ux;
X		otmp -> oy = u.uy;
X		otmp -> unpaid = 0;
X		otmp -> known = 0;
X		if (rn2 (5))
X			otmp -> cursed = 1;
X		if (!otmp -> nobj) {
X			otmp -> nobj = fobj;
X			fobj = invent;
X			invent = 0;/* Superfluous */
X			break;
X		}
X		otmp = otmp -> nobj;
X	}
X	if (makemon (&pm_ghost))
X		return;
X	fmon -> mx = u.ux;
X	fmon -> my = u.uy;
X	fmon -> msleep = 1;
X/* Added: sizeof fmon->extra */
X/* This is actually nonsens. Ghosts do not have names in this version */
X	strncpy (fmon -> mextra, plname, sizeof fmon -> mextra);
X	if (shopkeeper &&
X			inshproom (shopkeeper -> mx, shopkeeper -> my))
X		shopkeeper -> angry = 0;
X	gtmp = newgen ();
X	gtmp -> ngen = fgold;
X	fgold = gtmp;
X	gtmp -> gx = u.ux;
X	gtmp -> gy = u.uy;
X	gtmp -> gflag = somegold () + d (dlevel, 30);
X	u.ux = u.uy = 100;	/* Random outside map */
X	keepdogs (1);		/* All tame animals become wild again */
X	for (mtmp = fmon; mtmp; mtmp = mtmp -> nmon)
X		levlsym (mtmp -> mx, mtmp -> my, mtmp -> data -> mlet);
X	if ((fd = creat (bones, 0644)) < 0)
X		return;
X	savelev (fd);
X	close (fd);
X}
X
Xgetbones () {
X	register        fd, x, y;
X
X	sprintf (&bones[6], "%d", dlevel);
X	if ((fd = open (bones, 0)) < 0 || rn2 (3)) {
X		close (fd);	/* Sometimes we find bones */
X		return NOBONES;
X	}
X	getlev (fd);
X	close (fd);
X	if (unlink (bones) < 0) {
X		pline ("Cannot unlink %s", bones);
X		return NOBONES;
X	}
X	for (x = 0; x < 80; x++)
X		for (y = 0; y < 22; y++) {
X			levl[x][y].seen = 0;
X			levl[x][y].new = 0;
X		}
X	return BONES;
X}
/
echo 'x - hack.do.vars.h'
sed 's/^X//' > hack.do.vars.h << '/'
X/*
X * Hack.do.vars.h
X */
X
Xint 	doredraw(),  dodrop(),    dodrink(),    doread(),
X	dosearch(),  armwear(),   dowearring(), doremarm(),
X	doremring(), dopay(),     save(),       dowield(),
X	ddoinv(),    dozap(),     m_call(),     doset(),
X	dowhatis(),  dohelp(),    doeat(),      ddoup(),
X	ddodown(),   done1(),     donull(),     dothrow(),
X	doshow(),    dosh(),	  doreprint(),  gemsdrop();
X
X#ifdef DEBUG
Xint debug();
X#endif DEBUG
X
XFUNCTIONS list[] = {
X	'\020', doredraw, 	 /* was  '\014' */
X	'A', doreprint,	 /* Michiel: Repeat last message printed */
X#ifdef DEBUG
X	'D', debug,
X#endif DEBUG
X	'P', dowearring,
X	'Q', done1,
X	'R', doremring,
X	'G', gemsdrop,
X	'S', save,
X	'T', doremarm,
X	'W', armwear,
X	'a', doshow,	/* Michiel: show everything you're wearing */
X	'c', m_call,
X	'd', dodrop,
X	'e', doeat,
X	'i', ddoinv,
X	'o', doset,
X	'p', dopay,
X	'q', dodrink,
X	'r', doread,
X	's', dosearch,
X	't', dothrow,
X	'w', dowield,
X	'z', dozap,
X	'<', ddoup,
X	'>', ddodown,
X	'/', dowhatis,
X	'?', dohelp,
X	'!', dosh,
X	'\n', donull,
X	' ', donull,
X	0, 0
X};
/
echo 'x - hack.do_wear.c'
sed 's/^X//' > hack.do_wear.c << '/'
X/*
X * Hack.do_wear.c
X */
X
X#include "hack.h"
X
X#define CURSED		1
X#define NOTCURSED	0
X
Xoff_msg (otmp)
Xregister        OBJECT otmp;
X{
X	doname (otmp, buf);
X	pline ("You were wearing %s.", buf);
X}
X
Xdoremarm () {
X	register        OBJECT oldarm = uarm;
X
X	nomove ();
X	if (!uarm) {
X		pline ("Not wearing any armor.");
X		return;
X	}
X	flags.move = 1;
X	if (cursed (uarm))
X		return;
X	nomul (-armors[uarm -> otyp].delay);
X	u.uac += uarm -> spe;
X	uarm = uarm2;
X	uarm2 = 0;
X	off_msg (oldarm);
X	flags.dac = 1;
X}
X
Xdoremring () {
X
X	nomove ();
X	if (!uleft && !uright) {
X		pline ("Not wearing any ring.");
X		return;
X	}
X	if (!uleft)
X		dorr (&uright);
X	else if (!uright)
X		dorr (&uleft);
X	else
X		for (;;) {
X			pline ("What ring, Right or Left? ");
X			flush ();
X			*buf = getchar ();
X			flags.topl = 0;
X			if (*buf == '\n' || *buf == '\033')
X				return;
X			if (*buf == 'l' || *buf == 'L') {
X				dorr (&uleft);
X				return;
X			}
X			if (*buf == 'r' || *buf == 'R') {
X				dorr (&uright);
X				return;
X			}
X			if (*buf == '?')
X				doinv ("=", 0);
X		}
X}
X
Xdorr (ring)
Xregister        OBJECT * ring;
X{
X	register        OBJECT otmp = *ring;
X
X	if (cursed (otmp))
X		return;
X	*ring = 0;
X	doring (otmp, OFF);
X	off_msg (otmp);
X}
X
Xcursed (otmp)
Xregister        OBJECT otmp;
X{
X	if (otmp -> cursed) {
X		pline ("You can't. It appears to be cursed.");
X		return (CURSED);
X	}
X	return (NOTCURSED);
X}
X
Xarmwear () {
X	register        OBJECT otmp;
X
X	otmp = getobj ("[", "wear");
X	if (!otmp) {
X		nomove ();
X		return;
X	}
X	if (uarm) {
X		if (otmp -> otyp == A_ELVEN_CLOAK && !uarm2)
X			uarm2 = uarm;
X		else {
X			pline ("You are already wearing some armor.");
X			flags.move = 0;
X			return;
X		}
X	}
X	uarm = otmp;
X	nomul (-armors[otmp -> otyp].delay);
X	uarm -> known = 1;
X	u.uac -= uarm -> spe;
X	flags.dac = 1;
X}
X
Xdowearring () {
X	register        OBJECT otmp;
X
X	otmp = getobj ("=", "wear");
X	if (!otmp) {
XR: 
X		nomove ();
X		return;
X	}
X	if (uleft && uright) {
X		pline ("There are no more fingers to fill.");
X		goto R;
X	}
X	if (otmp == uleft || otmp == uright) {
X		pline ("You are already wearing that.");
X		goto R;
X	}
X	if (uleft)
X		uright = otmp;
X	else if (uright)
X		uleft = otmp;
X	else
X		while (!uright && !uleft) {
X			pline ("What finger, Right or Left? ");
X			flush ();
X			*buf = getchar ();
X			flags.topl = 0;
X			if (*buf == 'l' || *buf == 'L')
X				uleft = otmp;
X			else if (*buf == 'r' || *buf == 'R')
X				uright = otmp;
X		}
X	doring (otmp, ON);
X	prinv (otmp);
X}
X
Xdoring (obj, eff)
Xregister        OBJECT obj;
Xregister        eff;
X{
X	register        tmp;
X
X	if (!obj)
X		return;
X	tmp = obj -> spe;
X	if (eff == OFF)
X		tmp = -tmp;
X	if (uleft && uright && uleft == uright &&
X			obj -> otyp <= R_GAIN_STR)
X		return;
X /* If wearing the same ring sometimes the flag must remain actif. */
X	switch (obj -> otyp) {
X		case R_TELE: 
X			u.utel = eff;
X		case R_ADORNMENT: 
X			break;
X		case R_REGEN: 
X			u.uregen = eff;
X			break;
X		case R_SEARCH: 
X			u.usearch = eff;
X			break;
X		case R_SEE_INV: 
X			u.ucinvis = eff;
X			break;
X		case R_STEALTH: 
X			u.ustelth = eff;
X			break;
X		case R_FLOAT: 
X			u.ufloat = eff;
X			break;
X		case R_POISON_RES: 
X			u.upres = eff;
X			break;
X		case R_AGGRAV_MON: 
X			u.uagmon = eff;
X			break;
X		case R_HUNGER: 
X			u.ufeed = eff;
X			break;
X		case R_FIRE_RES: 
X			u.ufireres = eff;
X			break;
X		case R_COLD_RES: 
X			u.ucoldres = eff;
X			break;
X		case R_SHAPE: 
X			u.ucham = eff;
X			if (eff != OFF)
X				rescham ();
X			break;
X		case R_GAIN_STR: 
X			u.ustr += tmp;
X			u.ustrmax += tmp;
X			flags.dstr = 1;
X			break;
X		case R_DAM_INC: 
X			u.udaminc += tmp;
X			break;
X		case R_PROTECTION: 
X			u.uac -= tmp;
X			flags.dac = 1;
X			break;
X		default: 
X			pline ("Bad(%d)ring", obj -> otyp);
X			impossible ();
X	}
X}
/
echo 'x - hack.dog.h'
sed 's/^X//' > hack.dog.h << '/'
X/*
X * Hack.dog.h
X */
X
Xstruct edog {
X	unsigned        hungrytime;	/* At this time dog gets hungry */
X	unsigned        eattime;	/* Dog is eating */
X	unsigned        droptime;	/* Moment dog dropped object */
X	unsigned        dropdist;	/* Dist of drpped obj from @ */
X	unsigned        apport;		/* Amount of training */
X	unsigned        carry:	1;	/* The dog is carrying sth */
X};
/
echo 'x - hack.eat.c'
sed 's/^X//' > hack.eat.c << '/'
X/*
X * hack.eat.c
X */
X
X#include "hack.h"
X
Xextern char    *nomvmsg;
X
Xunsigned        starved = 0;	/* Michiel: after 30 times fainting you starve
X				   to death */
X
Xchar   *hu_stat[4] = {
X	"        ",
X	"Hungry  ",		/* Hunger texts used in main (each 8 chars
X				   long) */
X	"Weak    ",
X	"Fainting"
X};
X
Xdoeat () {
X	register        OBJECT otmp;
X	register        FOOD ftmp;
X
X	if (!(otmp = getobj ("%", "eat"))) {
X		nomove ();
X		return;
X	}
X	starved = 0;
X	ftmp = &foods[otmp -> otyp];
X	if (!rn2 (7)) {
X		pline ("Blecch!  Rotten food!");
X		if (!rn2 (4)) {
X			pline ("You feel rather light headed.");
X			u.uconfused += d (2, 4);
X		}
X		else if (!rn2 (4) && !u.ublind) {
X			pline ("Everything suddenly goes dark.");
X			u.ublind = d (2, 10);
X			unCoff (COFF, 0);
X		}
X		else if (!rn2 (3)) {
X			pline ("The world spins and goes dark.");
X			nomul (-rnd (10));
X			nomvmsg = "You are conscious again";
X		}
X		lesshungry (ftmp -> nutrition >> 2);
X	}
X	else {
X		multi = -ftmp -> delay;
X		switch (otmp -> otyp) {
X
X			case F_FOOD: 
X				if (u.uhunger < 500)
X					pline ("That food really hit the spot!");
X				else if (u.uhunger < 1000)
X					pline ("That satiated your stomach!");
X				else if (u.uhunger < 1500) {
X					pline ("You're having a hard time getting all that food down.");
X					multi -= 2;
X				}
X				else {
X					pline ("You choke over your food.");
X					more ();
X					killer = ftmp -> foodnam;
X					done (CHOKED);
X				}
X				lesshungry (ftmp -> nutrition);
X				if (multi < 0)
X					nomvmsg = "You finished your meal.";
X				break;
X
X			case F_TRIPE: 
X				pline ("Yak - dog food!");
X				if (rn2 (2)) {
X					pline ("You vomit.");
X					lesshungry (-20);
X				}
X				else
X					lesshungry (ftmp -> nutrition);
X				break;
X
X			default: 
X				pline ("That %s was delicious!", ftmp -> foodnam);
X				lesshungry (ftmp -> nutrition);
X				break;
X		}
X	}
X	if (multi < 0 && !nomvmsg) {
X		static char     msgbuf[40];
X
X		sprintf (msgbuf, "You finished eating your %s.",
X				ftmp -> foodnam);
X		nomvmsg = msgbuf;
X	}
X	useup (otmp);
X}
X
Xlesshungry (num)		/* Eat stg or drink fruit juice */
Xregister        num;
X{
X	register        newhunger;
X
X	newhunger = u.uhunger + num;
X	if (u.uhunger < 151 && newhunger > 150) {
X		if (u.uhunger < 51 && u.ustr < u.ustrmax)
X			losestr (-1);
X		u.uhs = 0;
X		goto Ldohs;
X	}
X	if (u.uhunger < 51 && newhunger > 50) {
X		pline ("You only feel hungry now.");
X		if (u.ustr < u.ustrmax)
X			losestr (-1);
X		u.uhs = 1;
X		goto Ldohs;
X	}
X	if (u.uhunger <= 0 && newhunger < 50) {
X		pline ("You feel weak now.");
X		u.uhs = 2;
XLdohs: 
X		flags.dhs = 1;
X	}
X	u.uhunger = newhunger;
X}
X
Xgethungry () {			/* Called in main */
X	--u.uhunger;
X	if ((u.uregen || u.ufeed) && moves % 2)
X		u.uhunger--;
X	if (u.uhunger <= 150 && !u.uhs) {
X		pline ("You are beginning to feel hungry.");
X		u.uhs = 1;
X		goto Ldohs;
X	}
X	if (u.uhunger <= 50 && u.uhs == 1) {
X		pline ("You are beginning to feel weak.");
X		losestr (1);
X		u.uhs = 2;
X		goto Ldohs;
X	}
X	if (u.uhunger <= 0) {
X		pline ("You faint from lack of food.");
X		if (starved++ == 100) {
X			pline ("You starve!");
X			more ();
X			done (STARVED);
X		}
X		nomul (-20);
X		u.uhunger = rn1 (4, 22);
X		if (u.uhs != 3) {
X			u.uhs = 3;
X	Ldohs: 
X			flags.dhs = 1;
X		}
X	}
X}
/
echo 'x - hack.foods.h'
sed 's/^X//' > hack.foods.h << '/'
X/*
X * Hack.foods.h
X */
X
X/* Dog eats foods 0-4 but prefers 1 above 0, 2, 3, 4 */
X
Xstruct food foods[] = {
X	{ "food ration",  50, 5, 800 },
X	{ "tripe ration", 20, 1, 200 },
X	{ "pancake",  	   3, 1, 200 },
X	{ "dead lizard",   3, 0,  40 },
X	{ "cookie",	   7, 0,  40 },
X	{ "orange",	   3, 0,  80 },
X	{ "apple",	   3, 0,  50 },
X	{ "pear",	   3, 0,  50 },
X	{ "melon",	   1, 0, 100 },
X	{ "banana",	   3, 0,  80 },
X	{ "candy bar",	   3, 0, 100 },
X	{ "egg",	   1, 0,  80 },
X	{ "PROG ERROR",  100, 0,   0 }
X};
/
echo 'x - hack.io.c'
sed 's/^X//' > hack.io.c << '/'
X/*
X * Hack.io.c
X */
X
X#include "hack.h"
X#include <sgtty.h>
X
Xshort   ospeed;			/* Used by tputs */
X
Xgetlin (str)
Xregister char  *str;
X{
X	register char  *ostr = str;
X
X	flags.topl = 0;
X	flush ();
X	for (;;) {
X		*str = getchar ();
X		if (*str == '\b') {
X			if (str != ostr) {
X				str--;
X				write (1, "\b \b", 3);
X			}
X			else
X				write (1, "\7", 1);
X		}
X		else if (*str == '\n') {
X			*str = 0;
X			return;
X		}
X		else if (*str >= ' ') {
X			write (1, str, 1);
X			str++;
X		}
X	}
X}
X
Xgetret () {
X	printf ("\nHit space to continue: ");
X	flush ();
X	while (getchar () != ' ');
X}
X/*
X * Put together cbreak-mode and echo --- Michiel
X */
X
Xhackmode (x)
Xregister        x;
X{
X	struct sgttyb   ttyp;
X
X	ioctl (1, TIOCGETP, &ttyp);/* Use of basic functions */
X	ospeed = ttyp.sg_ospeed;
X	if (x) {
X		ttyp.sg_flags &= ~ECHO;
X		ttyp.sg_flags |= CBREAK;
X	}
X	else {
X		ttyp.sg_flags |= ECHO;
X		ttyp.sg_flags &= ~CBREAK;
X	}
X	if (ioctl (1, TIOCSETP, &ttyp) < 0) {
X		printf ("ERROR: Cannot change tty");
X		exit (1);
X	}
X}
X
Xmore () {
X	printf (" --More--");
X	flush ();
X	while (getchar () != ' ');
X	flags.topl = 0;
X}
X
X#ifndef NORMAL_IO
Xgetchar () {
X	char    c;
X
X	read (0, &c, 1);
X	return (c);
X}
X#endif NORMAL_IO
/
echo 'x - hack.monst.c'
sed 's/^X//' > hack.monst.c << '/'
X/*
X * Hack.monst.c
X */
X
X#include "hack.h"
X#include "hack.dog.h"
X
X/*
X * Unfortunately the syntax for structure initialization is
X * different on VAX and 11/45. Define VAX to get the VAX syntax
X */
X
X#define VAX
X
X#ifdef VAX
X
X#define	SOSEP	{
X#define	SCSEP	}
X#define GOSEP
X#define	GMSEP
X#define	GCSEP
X
X#else
X
X#define	SOSEP
X#define	SCSEP
X#define	GOSEP	{
X#define	GMSEP	},{
X#define	GCSEP	}
X
X#endif VAX
X
Xstruct permonst mon[8][7]={
X	GOSEP
X	SOSEP "bat",		'B',1,22,8,1,4,0 SCSEP,
X	SOSEP "gnome",		'G',1,6,5,1,6,0 SCSEP,
X	SOSEP "hobgoblin",	'H',1,9,5,1,8,0 SCSEP,
X	SOSEP "jackal",		'J',0,12,7,1,2,0 SCSEP,
X	SOSEP "kobold",		'K',1,6,7,1,4,0 SCSEP,
X	SOSEP "leprechaun",	'L',1,15,8,1,5,0 SCSEP,
X	SOSEP "giant rat",	'r',0,12,7,1,3,0 SCSEP,
X	GMSEP
X	SOSEP "acid blob",	'a',2,3,8,0,0,0 SCSEP,
X	SOSEP "floating eye",	'E',2,1,9,0,0,0 SCSEP,
X	SOSEP "homunculus",	'h',2,6,6,1,3,0 SCSEP,
X	SOSEP "imp",		'i',2,6,2,1,4,0 SCSEP,
X	SOSEP "orc",		'O',2,9,6,1,8,0 SCSEP,
X	SOSEP "yellow light",	'y',3,15,0,0,0,0 SCSEP,
X	SOSEP "zombie",		'Z',2,6,8,1,8,0 SCSEP,
X	GMSEP
X	SOSEP "giant ant",	'A',3,18,3,1,6,0 SCSEP,
X	SOSEP "fog cloud",	'f',3,1,0,1,6,0 SCSEP,
X	SOSEP "nymph",		'N',3,12,9,1,4,0 SCSEP,
X	SOSEP "piercer",	'p',3,1,3,2,6,0 SCSEP,
X	SOSEP "quasit",		'Q',3,15,3,1,4,0 SCSEP,
X	SOSEP "quivering blob",	'q',3,1,8,1,8,0 SCSEP,
X	SOSEP "violet fungi",	'v',3,1,7,1,4,0 SCSEP,
X	GMSEP
X	SOSEP "giant beetle",	'b',4,6,4,3,4,0 SCSEP,
X	SOSEP "centaur",	'C',4,18,4,1,6,0 SCSEP,
X	SOSEP "cockatrice",	'c',4,6,6,1,3,0 SCSEP,
X	SOSEP "gelatinous cube",'g',4,6,8,2,4,0 SCSEP,
X	SOSEP "jaguar",		'j',4,15,6,1,8,0 SCSEP,
X	SOSEP "killer bee",	'k',4,6,4,2,4,0 SCSEP,
X	SOSEP "snake",		'S',4,15,3,1,6,0 SCSEP,
X	GMSEP
X	SOSEP "freezing sphere",'F',2,13,4,0,0,0 SCSEP,
X	SOSEP "owlbear",	'o',5,12,5,2,6,0 SCSEP,
X	SOSEP "rust monster",	'R',5,18,3,0,0,0 SCSEP,
X	SOSEP "giant scorpion",	's',5,15,3,1,4,0 SCSEP,
X	SOSEP "teleporter",	't',5,3,5,1,7,0 SCSEP,
X	SOSEP "wraith",		'W',5,12,5,1,6,0 SCSEP,
X	SOSEP "long worm",	'w',6,3,5,2,5,0 SCSEP,
X	GMSEP
X	SOSEP "large dog",	'd',6,15,4,2,4,0 SCSEP,
X	SOSEP "leocrotta",	'l',6,18,4,3,6,0 SCSEP,
X	SOSEP "mimic",		'M',7,3,7,3,4,0 SCSEP,
X	SOSEP "minotaur",	'm',6,12,6,2,8,0 SCSEP,
X	SOSEP "troll",		'T',7,12,4,2,6,0 SCSEP,
X	SOSEP "ugod",		'u',6,11,5,1,10,0 SCSEP,
X	SOSEP "yeti",		'Y',5,15,6,1,6,0 SCSEP,
X	GMSEP
X	SOSEP "invisible stalker",'I',8,12,3,4,4,0 SCSEP,
X	SOSEP "umber hulk",	'U',9,6,2,2,14,0 SCSEP,
X	SOSEP "vampire",	'V',8,12,1,1,6,0 SCSEP,
X	SOSEP "xorn",		'X',8,9,-2,4,6,0 SCSEP,
X	SOSEP "xerp",		'x',7,6,3,2,4,0 SCSEP,
X	SOSEP "zelomp",		'z',9,8,3,3,6,0 SCSEP,
X	SOSEP "chameleon",	':',6,5,6,4,2,0 SCSEP,
X	GMSEP
X	SOSEP "dragon",		'D',20,9,-1,3,8,0 SCSEP,
X	SOSEP "ettin",		'e',10,12,3,2,8,0 SCSEP,
X	SOSEP "lurker above",	'\'',10,3,3,0,0,0 SCSEP,
X	SOSEP "neo-otyugh",	'n',11,6,0,1,3,0 SCSEP,
X	SOSEP "trapper",	',',12,3,3,0,0,0 SCSEP,
X	SOSEP "purple worm",	'P',20,9,-1,2,8,0 SCSEP,
X	SOSEP "demon",		'&',14,9,-4,1,6,0 SCSEP
X	GCSEP
X};
Xstruct permonst /* _mon={0,0,0,0,0,0,0,0},*/
X	li_dog={"little dog",	'd',2,18,6,1,6,sizeof(struct edog)},
X		dog={"dog",	'd',4,16,5,1,6,sizeof(struct edog)},
X	la_dog={"large dog",	'd',6,15,4,2,4,sizeof(struct edog)};
/
echo 'x - hack.name.h'
sed 's/^X//' > hack.name.h << '/'
X/*
X * Hack.name.h
X */
X
X#define S_ENCH_ARMOR	0
X#define S_DROP		1
X#define S_CURSE_LEV	2
X#define S_REM_CURSE	3
X#define S_ENCH_WEP	4
X#define S_CREAT_MON	5
X#define S_DAM_WEP	6
X#define S_GENOCIDE	7
X#define S_DESTR_ARMOR	8
X#define S_LIGHT		9
X#define S_TELEPORT	10
X#define S_GOLD_DETEC	11
X#define S_IDENTIFY	12
X#define S_MAG_MAP	13
X#define S_FIRE		14
X
X#define P_REST_STR	0
X#define P_BOOZE		1
X#define P_INVIS		2
X#define P_JUICE		3
X#define P_HEALING	4
X#define P_FROZEN	5
X#define P_MONDETEC	6
X#define P_OBJDETEC	7
X#define P_POISON	8
X#define P_CONF		9
X#define P_GAIN_STR	10
X#define P_SPEED		11
X#define P_BLIND		12
X#define P_GAIN_LEV	13
X#define P_EXTRA_HEALING	14
X
X#define Z_LIGHT		0
X#define Z_DETEC		1
X#define Z_CREATE_MON	2
X#define Z_EXHAUST	3
X#define Z_SLOW_MON	4
X#define Z_SPEED_MON	5
X#define Z_UND_TUR	6
X#define Z_POLYMORF	7
X#define Z_CAN		8
X#define Z_TELEPORT	9
X#define Z_DIGGING	10
X#define Z_MAG_MISSILE	11
X#define Z_FIRE		12
X#define Z_SLEEP		13
X#define Z_COLD		14
X#define Z_DEATH		15
X#define Z_CONF_MON	16
X#define Z_CLOSING	17
X
X#define R_ADORNMENT	0
X#define R_TELE		1
X#define R_REGEN		2
X#define R_SEARCH	3
X#define R_SEE_INV	4
X#define R_STEALTH	5
X#define R_FLOAT		6
X#define R_POISON_RES	7
X#define R_AGGRAV_MON	8
X#define R_HUNGER	9
X#define R_FIRE_RES	10
X#define R_COLD_RES	11
X#define R_SHAPE		12
X#define R_GAIN_STR	13
X#define R_DAM_INC	14
X#define R_PROTECTION	15
X
X#define W_ARROW		0
X#define W_SL_BULLET	1
X#define W_CROSS_BOLT	2
X#define W_DART		3
X#define W_MACE		4
X#define W_AXE		5
X#define W_FLAIL		6
X#define W_LONG_SWORD	7
X#define W_TWOH_SWORD	8
X#define W_DAGGER	9
X#define W_SPEAR		10
X#define W_BOW		11
X#define W_SLING		12
X#define W_CROSSBOW	13
X
X#define W_USE_AMMO	11
X#define W_AMMUNITION	3
X
X#define A_PLATE		0
X#define A_SPLINT	1
X#define A_BANDED	2
X#define A_CHAIN		3
X#define A_SCALE		4
X#define A_RING		5
X#define A_STD_LEATHER	6
X#define A_LEATHER	7
X#define A_ELVEN_CLOAK	8
X
X#define F_FOOD		0
X#define F_TRIPE		1
X#define F_PANCAKE	2
X#define F_LIZARD	3
X#define F_COOKIE	4
X#define F_ORANGE	5
X#define F_APPLE		6
X#define F_PEAR		7
X#define F_MELON		8
X#define F_BANANA	9
X#define F_CANDY		10
X#define F_EGG		11
/
echo 'x - hack.office.c'
sed 's/^X//' > hack.office.c << '/'
X/*
X * Hack.office.c
X */
X
Xstruct tm {			/* see ctime(3) */
X	int     tm_sec;
X	int     tm_min;
X	int     tm_hour;
X	int     tm_mday;
X	int     tm_mon;
X	int     tm_year;
X	int     tm_wday;
X	int     tm_yday;
X	int     tm_isdst;
X};
X
X
X#define SUNDAY 0
X#define SATURDAY 6
X
Xextern struct tm       *localtime ();
X
Xkantoor () {
X	struct tm      *s;
X	long    clock;
X
X	time (&clock);
X	s = localtime (&clock);
X	return (s -> tm_wday != SUNDAY && s -> tm_wday != SATURDAY &&
X			s -> tm_hour <= 17 && s -> tm_hour > 9);
X}
/
echo 'x - hack.rip.c'
sed 's/^X//' > hack.rip.c << '/'
X/*
X * Hack.rip.c
X */
X
X#include <time.h>
X#include "hack.h"
X
Xextern char     plname[];
X
Xstatic char    *rip[] = {
X	"                       ----------",
X	"                      /          \\",
X	"                     /    REST    \\",
X	"                    /      IN      \\",
X	"                   /     PEACE      \\",
X	"                  /                  \\",
X	"                  |                  |",
X	"                  |                  |",
X	"                  |   killed by a    |",
X	"                  |                  |",
X	"                  |       1001       |",
X	"                 *|     *  *  *      | *",
X	"        _________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
X	0
X};
X
Xoutrip () {
X	register char **dp = rip;
X	register struct tm     *lt;
X	long    date;
X	char    buffer[BUFSZ];
X	struct tm      *localtime ();
X
X	time (&date);
X	lt = localtime (&date);
X	cls ();
X	strcpy (buffer, plname);
X	center (6, buffer);
X	sprintf (buffer, "%D Au", u.ugold);
X	center (7, buffer);
X	strcpy (buffer, killer);
X	center (9, buffer);
X	sprintf (buffer, "19%2d", lt -> tm_year);
X	center (10, buffer);
X	curs (1, 8);
X	while (*dp)
X		printf ("%s\n", *dp++);
X	getret ();
X}
X
Xcenter (line, text)
Xregister int    line;
Xregister char  *text;
X{
X	register char  *ip, *op;
X
X	ip = text;
X	op = &rip[line][28 - ((strlen (text) + 1) >> 1)];
X	while (*ip)
X		*op++ = *ip++;
X}
/
echo 'x - hack.savelev.c'
sed 's/^X//' > hack.savelev.c << '/'
X/*
X * Hack.savelev.c
X */
X
Xsavelev (fd) {
X	register        MONSTER mtmp, mtmp2;
X	register        GOLD_TRAP gtmp, gtmp2;
X	register        OBJECT otmp, otmp2;
X	register        WORMSEGMENT wtmp, wtmp2;
X	register        tmp;
X	int     minusone = -1;
X
X	if (fd < 0)
X		panic (CORE, "Save on bad file!");
X	bwrite (fd, levl, sizeof (levl));
X	bwrite (fd, &moves, sizeof (unsigned));
X	bwrite (fd, &xupstair, 1);
X	bwrite (fd, &yupstair, 1);
X	bwrite (fd, &xdnstair, 1);
X	bwrite (fd, &ydnstair, 1);
X	for (mtmp = fmon; mtmp; mtmp = mtmp2) {
X		mtmp2 = mtmp -> nmon;
X		bwrite (fd, &mtmp -> mxlth, sizeof (int));
X		bwrite (fd, mtmp, mtmp -> mxlth + sizeof (struct monst));
X
X/* Michiel save stolen objects */
X		if (mtmp -> mstole) {
X			bwrite (fd, mtmp -> mstole, sizeof (struct stole));
X			for (otmp = mtmp -> mstole -> sobj; otmp;
X					otmp = otmp -> nobj)
X				bwrite (fd, otmp, sizeof (struct obj));
X			bwrite (fd, nul, sizeof (struct obj));
X			free (mtmp -> mstole);
X		}
X		else
X			bwrite (fd, nul, sizeof (struct stole));
X		free (mtmp);
X	}
X	bwrite (fd, &minusone, sizeof (int));
X	for (gtmp = fgold; gtmp; gtmp = gtmp2) {
X		gtmp2 = gtmp -> ngen;
X		bwrite (fd, gtmp, sizeof (struct gen));
X		free (gtmp);
X	}
X	bwrite (fd, nul, sizeof (struct gen));
X	for (gtmp = ftrap; gtmp; gtmp = gtmp2) {
X		gtmp2 = gtmp -> ngen;
X		bwrite (fd, gtmp, sizeof (struct gen));
X		free (gtmp);
X	}
X	bwrite (fd, nul, sizeof (struct gen));
X	for (otmp = fobj; otmp; otmp = otmp2) {
X		otmp2 = otmp -> nobj;
X		bwrite (fd, otmp, sizeof (struct obj));
X		ofree (otmp);
X	}
X	bwrite (fd, nul, sizeof (struct obj));
X	bwrite (fd, rooms, sizeof (rooms));
X	bwrite (fd, doors, sizeof (doors));
X	fgold = 0;
X	ftrap = 0;
X	fmon = 0;
X	fobj = 0;
X	bwrite (fd, wsegs, sizeof (wsegs));
X	for (tmp = 1; tmp < 32; tmp++) {
X		for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
X			wtmp2 = wtmp -> nseg;
X			bwrite (fd, wtmp, sizeof (struct wseg));
X		}
X		wsegs[tmp] = 0;
X	}
X	bwrite (fd, wgrowtime, sizeof (wgrowtime));
X	shopkeeper = 0;
X}
X
Xbwrite (fd, loc, num)
Xregister        fd, num;
Xregister char  *loc;
X{
X	if (write (fd, loc, num) != num)
X		panic (CORE, "Cannot write %d bytes to file #%d", num,
X				fd);
X}
/
echo 'x - hack.str.c'
sed 's/^X//' > hack.str.c << '/'
X/*
X * Hack.str.c
X */
X
X/*
X * strprint() : Cheap alternative for sprintf() and printf(), by
X * Fred and Michiel. If you want the normal io just define NORMAL_IO
X */
X
X
X#include "hack.h"
X
X#ifndef NORMAL_IO
X
X#define ARINDEX		512
Xstatic char output_buffer[ARINDEX];
Xstatic arcount = 0;
X
Xchar *litoa();
X
X/*VARARGS10*/
Xstrprint( dest, src, argptr )
Xregister char *dest, *src;
Xregister int *argptr;
X{
X	register kar;
X	register char *string;
X	register field;
X	int negated;
X	int printflag = 0;
X	static char extra[512];
X
X	if ( dest == STDOUT ) {
X		dest = extra;
X		printflag++;
X	}
X
X	while( *src ) {
X		if ( *src == '%' ) {
X			field = 0;
X			negated = 0;
X			if ( *++src == '-' )
X				++negated;
X			else
X				--src;
X			while( *++src & 060 && *src <= '9' )
X				field = 10*field + ( *src & 017 );
X			if ( (kar = *src) == '%' )
X				*dest++ = '%';
X			else if ( kar == 'c' )
X				*dest++ = (char)*argptr++;
X			else {
X				switch ( kar ) {
X					
X				case 'd' :
X					string = litoa( (long)(*argptr));
X					break;
X				case 'U' :
X				case 'D' :
X					string = litoa( *((long *)argptr++) );
X					break;
X				case 'u' :
X					string =
X					litoa( (long)( *((unsigned *)argptr)) );
X					break;
X				case 's' :
X					string = (char *)(*argptr);
X					break;
X				default :
X					strcpy( string, "%'" );
X				}
X				if ( field )
X					field -= strlen( string );
X				if ( field > 0 && !negated )
X					while( --field >= 0 )
X						*dest++ = ' ';
X				while( *dest++ = *string++ )
X					;
X				dest--;  /* Remove '\0' character */
X				if ( field > 0 && negated )
X					while( --field >= 0 )
X						*dest++ = ' ';
X				argptr++;
X			}
X			src++;
X		}	
X		else
X			*dest++ = *src++;
X	}
X	*dest = 0;
X	if ( printflag ) {
X		WRITE( extra, strlen(extra) );
X	}
X}
X
Xchar *
Xlitoa( l_arg )
Xlong l_arg;
X{
X	static char string[20];
X	register int i = 0;
X	register char *str2 = string;
X	char pipo[20];
X
X	if ( !l_arg )
X		return( "0" );
X	if ( l_arg < 0L ) {
X		*str2++ = '-';
X		l_arg = -l_arg;
X	}
X
X	while( l_arg ) {
X		pipo[i++] = (int)( l_arg % 10L + '0');
X		l_arg /= 10L;
X	}
X	while( --i >= 0 ) /* Michiel */
X		*str2++ = pipo[i];
X	*str2 = '\0';
X	return( string );
X}
X
XWRITE( string , length )
Xregister char *string;
Xregister length;
X{
X	if ( arcount + length >= ARINDEX )
X		flush();
X	strcat( output_buffer, string );
X	arcount += length;
X}
X
Xflush()
X{
X	write( 1, output_buffer, arcount );
X	arcount = 0;
X	output_buffer[0] = 0;
X}
X
Xputchar ( c )
X{
X	WRITE( &c, 1 );
X}
X
Xprintf( fmt, args )
X{
X	strprint( STDOUT, fmt, &args );
X}
X
Xsprintf( buffer, fmt, args )
X{
X	strprint( buffer, fmt, &args );
X}
X#endif NORMAL_IO
/
echo 'x - hack.vars.h'
sed 's/^X//' > hack.vars.h << '/'
X/*
X * Hack.vars.h
X */
X
X#define	SIZE(x)	(sizeof x)/(sizeof x[0])
X
Xchar    NOTHIN[]   = "Nothing Happens",
X        WCLEV[]    = "Welcome to level %d.",
X        STOPGLOW[] = "Your hands stop glowing blue.",
X        UMISS[]    = "You miss %s.";
X
X
Xchar   *traps[] = {
X	" bear trap",
X	"n arrow trap",
X	" dart trap",
X	" trapdoor",
X	" teleportation trap",
X	" pit",
X	" sleeping gas trap",
X	" piercer",
X	" mimic"
X};
X
X#include "hack.foods.h"
X#include "hack.armors.h"
X#include "hack.weapons.h"
X
Xchar   *pottyp[] = {
X	"restore strength",
X	"booze",
X	"invisibility",
X	"fruit juice",
X	"healing",
X	"paralysis",
X	"monster detection",
X	"object detection",
X	"sickness",
X	"confusion",
X	"gain strength",
X	"speed",
X	"blindness",
X	"gain level",
X	"extra healing"
X};
X
X
X
Xchar   *potcol[] = {
X	"ebony",
X	"magenta",
X	"clear",
X	"brilliant blue",
X	"sky blue",
X	"emerald",
X	"dark green",
X	"ruby",
X	"purple-red",
X	"swirly",
X	"white",
X	"yellow",
X	"purple",
X	"puce",
X	"pink",
X	"smokey",
X	"glowing",
X	"bubbly",
X	"orange"
X};
X
Xchar   *potcall[SIZE (pottyp)];
X
X /* SCROLLS */
X
Xchar   *scrtyp[] = {
X	"enchant armor",
X	"losing",
X	"curse levels",
X	"remove curse",
X	"enchant weapon",
X	"create monster",
X	"damage weapon",
X	"genocide",
X	"destroy armor",
X	"light",
X	"transportation",
X	"gold detection",
X	"identify",
X	"magic mapping",
X	"fire"
X};
X
X
Xchar   *scrnam[] = {
X	"VELOX NEB",
X	"FOOBIE BLETCH",
X	"TEMOV",
X	"GARVEN DEH",
X	"ZELGO MER",
X	"ANDOVA BEGARIN",
X	"ELAM EBOW",
X	"KERNOD WEL",
X	"THARR",
X	"VENZAR BORGAVVE",
X /* "ELBIB YLOH", */
X	"VERR YED HORRE",
X	"JUYED AWK YACC",
X	"HACKEM MUCHE",
X	"LEP GEX VEN ZEA",
X	"DAIYEN FOOELS"
X};
Xchar   *scrcall[SIZE (scrtyp)];
X
X
X /* WANDS */
X
Xchar   *wantyp[] = {
X	"light",
X	"secret door + trap detection",
X	"create monster",
X	"exhaustion",
X	"slow monster",
X	"speed monster",
X	"undead turning",
X	"polymorph",
X	"cancellation",
X	"teleport monster",
X	"digging",
X	"magic missile",
X	"fire",
X	"sleep",
X	"cold",
X	"death",
X	"confusion",
X	"door closing"
X};
X
X
Xchar   *wannam[] = {
X	"oak",
X	"ebony",
X	"runed",
X	"long",
X	"short",
X	"curved",
X	"steel",
X	"aluminium",
X	"iron",
X	"marble",
X	"pine",
X	"maple",
X	"brass",
X	"silver",
X	"copper",
X	"balsa",
X	"zinc",
X	"platinum"
X};
Xchar   *wandcall[SIZE (wantyp)];
X
X
X /* RINGS */
X
Xchar   *ringtyp[] = {
X	"adornment",
X	"teleportation",
X	"regeneration",
X	"searching",
X	"see invisible",
X	"stealth",
X	"floating",
X	"poison resistance",
X	"aggravate monster",
X	"hunger",
X	"fire resistance",
X	"cold resistance",
X	"protection from shape-changers",
X	"gain strength",
X	"increase damage",
X	"protection"
X};
X
X
Xchar   *rinnam[] = {
X	"blackened",
X /* "ivory", */
X	"granite",
X	"silver",
X	"ruby",
X	"jade",
X	"diamond",
X	"copper",
X	"gold",
X	"shining",
X	"tiger eye",
X	"agate",
X	"moonstone",
X	"sapphire",
X	"pearl",
X	"topaz",
X /* "black onix", */
X	"wired"
X};
X
Xchar   *ringcall[SIZE (ringtyp)], oiden[40], oldux, olduy;
/
echo 'x - hack.weapons.h'
sed 's/^X//' > hack.weapons.h << '/'
X/*
X * Hack.weapons.h
X */
X
X/*
X * weapons 0-4 come several at a time
X * weapons 0-2 are shot using 11-13
X */
X
Xstruct weapon weapons[] = {
X	{ "arrow",		7, 6, 6 },
X	{ "sling bullet",	7, 4, 6 },
X	{ "crossbow bolt",	7, 4, 6 },
X	{ "dart",		7, 3, 2 },
X	{ "mace",		7, 6, 6 },
X	{ "axe",		7, 6, 4 },
X	{ "flail",		7, 6, 4 },
X	{ "long sword",		9, 8,12 },
X	{ "two handed sword",	7,10, 6 },
X	{ "dagger",		7, 4, 3 },
X	{ "spear",		7, 6, 8 },
X	{ "bow",		7, 4, 6 },
X	{ "sling",		7, 6, 6 },
X	{ "crossbow",		7, 4, 6 },
X	{ "PROG ERROR",	      100, 0, 0 }
X };
/
echo 'x - hack.worm.c'
sed 's/^X//' > hack.worm.c << '/'
X/*
X * Hack.worm.c
X */
X
X#include "hack.h"
X
X/* Linked list, tail first */
XWORMSEGMENT wsegs[32], wheads[32];
X
Xunsigned        wgrowtime[32];
X
Xgetwn (mtmp)
XMONSTER mtmp;
X{
X	register        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
Xinitworm (mtmp)
XMONSTER mtmp;
X{
X	register        WORMSEGMENT wtmp;
X	register        tmp = mtmp -> wormno;
X
X	if (!tmp)
X		return;
X	wheads[tmp] = wsegs[tmp] = wtmp = newseg ();
X	wgrowtime[tmp] = 0;
X	wtmp -> wx = mtmp -> mx;
X	wtmp -> wy = mtmp -> my;
X	wtmp -> nseg = 0;
X}
X
Xworm_move (mtmp)
XMONSTER mtmp;
X{
X	register        WORMSEGMENT wtmp, whd;
X	register        tmp = mtmp -> wormno;
X
X	wtmp = newseg ();
X	wtmp -> wx = mtmp -> mx;
X	wtmp -> wy = mtmp -> my;
X	wtmp -> nseg = 0;
X	whd = wheads[tmp];
X	whd -> nseg = wtmp;
X	wheads[tmp] = wtmp;
X	seeatl (whd -> wx, whd -> wy, '~');
X	if (wgrowtime[tmp] <= moves) {
X		if (!wgrowtime[tmp])
X			wgrowtime[tmp] = moves + rnd (5);
X		else
X			wgrowtime[tmp] += 2 + rnd (15);
X		mtmp -> orig_hp++;
X		mtmp -> mhp++;
X		return;
X	}
X	whd = wsegs[tmp];
X	wsegs[tmp] = whd -> nseg;
X	remseg (whd);
X}
X
Xworm_nomove (mtmp)
Xregister        MONSTER mtmp;
X{
X	register        tmp;
X	register        WORMSEGMENT wtmp;
X
X	tmp = mtmp -> wormno;
X	wtmp = wsegs[tmp];
X	if (wtmp == wheads[tmp])
X		return;
X	wsegs[tmp] = wtmp -> nseg;
X	remseg (wtmp);
X	mtmp -> mhp--;		/* Orig_hp not changed! */
X}
X
Xwormdead (mtmp)
Xregister        MONSTER mtmp;
X{
X	register        tmp = mtmp -> wormno;
X	register        WORMSEGMENT wtmp, wtmp2;
X
X	if (!tmp)
X		return;
X	for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
X		wtmp2 = wtmp -> nseg;
X		remseg (wtmp);
X	}
X	wsegs[tmp] = 0;
X}
X
Xwormhit (mtmp)
Xregister        MONSTER mtmp;
X{
X	register        tmp = mtmp -> wormno;
X	register        MONSTDATA mdat = mtmp -> data;
X	register        WORMSEGMENT wtmp;
X
X	if (!tmp)
X		return;		/* Worm without tail */
X	for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp -> nseg)
X		hitu (mdat -> mhd, 1, mdat -> mname);
X}
X
Xwormsee (tmp)
Xregister        tmp;
X{
X	register        WORMSEGMENT wtmp;
X
X	for (wtmp = wsegs[tmp]; wtmp -> nseg; wtmp = wtmp -> nseg)
X		if (!cansee (wtmp -> wx, wtmp -> wy))
X			levlsym (wtmp -> wx, wtmp -> wy, '~');
X}
X
Xcutworm (mtmp, x, y, weptyp)
Xregister        MONSTER mtmp;
Xregister char   x, y;
Xregister unsigned       weptyp;
X{
X	register        WORMSEGMENT wtmp, wtmp2;
X	register        MONSTER mtmp2;
X	register        tmp, tmp2;
X
X	if (mtmp -> mx == x && mtmp -> my == y)
X		return;		/* Hit headon */
X
X/* Cutting goes best with axe or sword */
X	tmp = rnd (20);
X	if (weptyp == 7 || weptyp == 8 || weptyp == 5)
X		tmp += 5;
X	if (tmp < 16)
X		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 (wtmp);
X		return;
X	}
X
X/* Cut the worm in two halves */
X	mtmp2 = newmonst (0);
X	*mtmp2 = *mtmp;
X
X/* Sometimes the tail end dies */
X	if (rn2 (8) || !getwn (mtmp2)) {/* Michiel was rn2(3) */
X		free (mtmp2);
X		tmp2 = 0;
X	}
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)
X				wheads[tmp2] = wtmp;
X			wsegs[tmp] = wtmp -> nseg -> nseg;
X			remseg (wtmp -> nseg);
X			wtmp -> nseg = 0;
X			if (tmp2) {
X				pline ("You cut the worm in half.");
X				mtmp2 -> orig_hp = mtmp2 -> mhp =
X					d (mtmp2 -> data -> mhd, 8);
X				mtmp2 -> mx = wtmp -> wx;
X				mtmp2 -> my = wtmp -> wy;
X				mtmp2 -> nmon = fmon;
X				fmon = mtmp2;
X				pmon (mtmp2);
X			}
X			else {
X				pline ("You cut off part of the worm's tail.");
X				remseg (wtmp);
X			}
X			mtmp -> mhp >>= 1;
X			return;
X		}
X		wtmp2 = wtmp -> nseg;
X		if (!tmp2)
X			remseg (wtmp);
X		wtmp = wtmp2;
X	} while (wtmp -> nseg);
X	panic (CORE, "Cannot find worm segment");
X}
X
Xremseg (wtmp)
Xregister        WORMSEGMENT wtmp;
X{
X	levlsym (wtmp -> wx, wtmp -> wy, '~');
X	free (wtmp);
X}
/
echo 'x - help'
sed 's/^X//' > help << '/'
X	Welcome to HACK!
X
X	Hack is a Dungeons and Dragons like game where you (the adventurer)
Xdescend into the depths of the dungeon in search of the Amulet of Guyver
X(reputed to be hidden on the twentieth level).  On the way you will find
Xuseful (or useless) magic items, and assorted monsters.  You attack a monster
Xby trying to move into the space a monster is in.
X
X	Unlike most adventure games, which give you a verbal description of
Xyour location, hack gives you a visual image of the dungeon level you are on.
X
X	Hack uses the following symbols:
X		A to Z and a to z:  monsters.  You can find out what a letter
Xrepresents by saying "whatis (letter)", as in "whatis A", which will tell you
Xthat 'A' is a giant ant.
X		- and |  These form the walls of a room.
X		.  this is the floor of a room.
X		#  this is a corridor.
X		}  this is a water filled area.
X		>  this is the staircase to the next level.
X		<  the staircase to the previous level.
X		@  You (usually).
X		^  A trap.
X		)  A weapon of some sort.
X		[  A suit of armor.
X		%  A piece of food.
X		/  A wand.
X		=  A ring.
X		?  A scroll.
X		!  A magic potion.
X		$  A pile or pot of gold.
X
XCommands:
X	Hack knows the following commands:
X		help		print this list. (Hack mode: ?)
X		quit		quit the game. (Hack mode: Q)
X		up		go up the staircase. (if you are standing on it)
X				(Hack mode: <)
X		down		go down (just like up).
X				(Hack mode: >)
X		n,s,ne,etc.	go one space in the direction indicated.
X				North is toward the top of the screen.
X		N,S,NE, etc.	Go in that direction until you hit a wall or
X				run into something.
X		invent		Print your inventory.
X				(Hack mode: i)
X		search		search for secret doors and traps in the 
X				locations next to you.
X				(hack mode: s)
X		(return)	rest, do nothing.
X		redraw		redraws the screen, useful if you type too fast
X				or your terminal is too slow.
X				(Hack mode: ^z (control/z))
X		whatis ~	(~ is any symbol printed on your screen)
X				Tell what ~ is.  (For instance 'whatis A'
X				will tell you that A is a giant ant.
X				(Hack mode: /)
X		eat		Eat food.  It will then ask what object you
X				want to eat.
X				(Hack mode: e)
X		wield		Change the weapon you use to attack with.
X				It will ask what you want to wield.
X				(Hack mode: w)
X		drink		Drink a potion.  (Hack mode: q quaff)
X		read		Read a scroll.   (Hack mode: r)
X		remove		Remove your armor or ring.
X				(Hack mode: T takeoff armor; R remove ring)
X		wear		Wear a suit of armor or a ring.
X				(Hack mode: W wear armor; P put on ring)
X		pay		Pay your shopping bill.
X				(Hack mode: p)
X		show            Show all you are wearing on armor and rings.
X				(Hack mode: a)
X		repeat          Repeat last message printed.
X				(Hack mode: A)
X		drop gems       Drop all your gems that you are currently 
X				holding.
X				(Hack mode: G)
X		oneline		Give inventories one line at a time
X				(at the top of your screen).
X				(Hack mode: o)
X
X	You can put a number before a command to repeat it that many times,
X	as in "20 search" or "40" (40 rest).
X	You can also put more than one command on a line by putting commas
X	between them, as in "20 search,2 e,20 search", or 
X	"n,e,n,e,n".
X
X	In hack mode you have the commands h (left), j (down), k (up),
X	l (right), y (nw), u (ne), b (sw), n(se); these move you one step.
X	Also HJKLYUBN - these move you as far as possible in the indicated
X	direction.
X	Also fh, fj etc. - these move you repeatedly in the indicated
X	direction until something interesting happens.
X	Finally FH, FJ etc. - these work like the previous, but branching
X	in a corridor is not considered interesting.
X
X
X	Have Fun, and Good Hacking!
/
echo 'x - mklev.mkobj.c'
sed 's/^X//' > mklev.mkobj.c << '/'
X/*
X * Mklev.mkobj.c
X */
X
X#define NORMAL_IO
X#include "hack.h"
X#include "hack.vars.h"
X
Xmkfood () {
X	register        FOOD fp;
X	register        i = rn2 (100);
X
X	fp = &foods[0];
X	while ((i -= fp -> prob) >= 0)
X		fp++;
X	return (fp - foods);
X}
X
Xmkarm () {
X	register        ARMOR ap;
X	register        i = rn2 (100);
X
X	ap = &armors[0];
X	while ((i -= ap -> prob) >= 0)
X		ap++;
X	return (ap - armors);
X}
X
Xmkwep () {
X	register        WEAPON wp;
X	register        i = rn2 (100);
X	wp = &weapons[0];
X	while ((i -= wp -> prob) >= 0)
X		wp++;
X	return (wp - weapons);
X}
X
Xchar    mkobjstr[] = "))[[!!!!????%%%%//=**";
X
Xmkobj (let)
Xregister        let;
X{
X	register        OBJECT otmp;
X
X	otmp = newobj ();
X	otmp -> nobj = fobj;
X	fobj = otmp;
X	otmp -> known = 0;
X	otmp -> cursed = 0;
X	otmp -> spe = 0;
X	otmp -> unpaid = 0;
X	otmp -> quan = 1;
X	if (!let)
X		let = mkobjstr[rn2 (sizeof (mkobjstr) - 1)];
X	otmp -> olet = let;
X	switch (let) {
X
X		case ')': 
X			otmp -> otyp = mkwep ();
X			if (otmp -> otyp <= W_AMMUNITION)
X				otmp -> quan = rn1 (6, 6);
X			if (!rn2 (11))
X				otmp -> spe = rnd (3);
X			else if (!rn2 (10)) {
X				otmp -> cursed = 1;
X				otmp -> spe = -rnd (3);
X			}
X			break;
X
X		case '*': 
X			otmp -> otyp = rn2 (SIZE (potcol));
X			otmp -> quan = rn2 (6) ? 1 : 2;
X			break;
X
X		case '[': 
X			otmp -> otyp = mkarm ();
X			if (!rn2 (8))
X				otmp -> cursed = 1;
X			if (!rn2 (10))
X				otmp -> spe = rnd (3);
X			else if (!rn2 (9)) {
X				otmp -> spe = -rnd (3);
X				otmp -> cursed = 1;
X			}
X			otmp -> spe += 10 - armors[otmp -> otyp].a_ac;
X			break;
X
X		case '!': 
X			otmp -> otyp = rn2 (SIZE (pottyp));
X			break;
X
X		case '?': 
X			otmp -> otyp = rn2 (SIZE (scrtyp));
X			break;
X
X		case '%': 
X			otmp -> otyp = mkfood ();
X			otmp -> quan = rn2 (6) ? 1 : 2;
X			break;
X
X		case '/': 
X			otmp -> otyp = rn2 (SIZE (wantyp));
X			if (otmp -> otyp == Z_DEATH)
X				otmp -> otyp = rn2 (SIZE (wantyp));
X			otmp -> spe = rn1 (5, (otmp -> otyp <= Z_CREATE_MON) ?
X					11 : 4);
X			break;
X
X		case '=': 
X			otmp -> otyp = rn2 (SIZE (ringtyp));
X			if (otmp -> otyp >= R_GAIN_STR) {
X				if (!rn2 (3)) {
X					otmp -> spe = -rnd (2);
X					otmp -> cursed = 1;
X				}
X				else
X					otmp -> spe = rnd (2);
X			}
X			else if (otmp -> otyp == R_TELE ||
X						otmp -> otyp == R_AGGRAV_MON ||
X					otmp -> otyp == R_HUNGER)
X				otmp -> cursed = 1;
X			break;
X
X		default: 
X			panic ("impossible mkobj");
X	}
X}
/
echo 'x - rnd.c'
sed 's/^X//' > rnd.c << '/'
X/*
X * Rnd.c
X */
X
X#define RND(x)	((rand() >> 3) % x)
X
Xrn1 (x, y)
Xregister        x, y;
X{
X	return (RND (x) + y);
X}
X
Xrn2 (x)
Xregister        x;
X{
X	return (RND (x));
X}
X
Xrnd (x)
Xregister        x;
X{
X	return (RND (x) + 1);
X}
X
Xd (n, x)
Xregister        n, x;
X{
X	register        tmp = n;
X
X	while (n--)
X		tmp += RND (x);
X	return tmp;
X}
/
echo 'Part 05 of Hack complete.'
exit
-- 

			Michiel Huisjes.
			{seismo|decvax|philabs}!mcvax!vu44!ark!huisjes