rogue

Ken Arnold's Rogue
git clone https://git.woozle.org/neale/rogue.git

commit
11cf2fc
parent
11cf2fc
author
Neale Pickett
date
2011-10-13 09:59:16 -0600 MDT
Import from SourceForge
37 files changed,  +12688, -0
A data.c
A edit.c
A find.c
A rmap.c
A Makefile
+113, -0
  1@@ -0,0 +1,113 @@
  2+#
  3+# Makefile for network
  4+# @(#)Makefile	4.21 (Berkeley) 02/04/99
  5+#
  6+HDRS=	netprot.h network.h netwait.h
  7+DOBJS=	terminal.o rmove.o network.o netprot.o rwrite.o rread.o \
  8+	sendit.o continue.o rinit.o control.o error.o rmap.o edit.o \
  9+	rexec.o master.o handle.o pipes.o packet.o socket.o ether.o \
 10+	netmap.o startup.o solve.o data.o signal.o rcopy.o \
 11+	system.o ctlmod.o
 12+OBJS=	$(DOBJS) find.o inter.o
 13+CFILES=	terminal.c rmove.c network.c netprot.c rwrite.c rread.c \
 14+	sendit.c continue.c rinit.c control.c error.c rmap.c edit.c \
 15+	rexec.c master.c handle.c pipes.c packet.c socket.c ether.c \
 16+	netmap.c inter.c startup.c solve.c data.c signal.c rcopy.c \
 17+	system.c ctlmod.c find.c
 18+MISC_C=	ropen.c netwait.c netmisc.c
 19+MISC=	Makefile $(MISC_C)
 20+
 21+DEFS=		-DMASTER -DDUMP -DALLSCORES -DUSE_OLD_TTY
 22+CFLAGS=		-g $(DEFS)
 23+#CFLAGS=		-Bcpp/ -tp -O $(DEFS)
 24+PROFLAGS=	-pg -O
 25+#LDFLAGS=	-i	# For PDP-11's
 26+LDFLAGS=	-g	# For VAXen
 27+CRLIB=		-lncurses
 28+#CRLIB=		-lcurses
 29+#CRLIB=		libcurses.a
 30+
 31+#SCOREFILE=	/usr/public/n_rogue_roll
 32+SCOREFILE=	/usr/games/rogue.scores
 33+#SCOREFILE=	./net_hist
 34+SF=		-DSCOREFILE='"$(SCOREFILE)"'
 35+NAMELIST=	/vmunix
 36+NL=		-DNAMELIST='"$(NAMELIST)"'
 37+#MACHDEP=	-DMAXLOAD=40 -DLOADAV -DCHECKTIME=4
 38+
 39+LD=	ld
 40+VGRIND=	/usr/ucb/vgrind
 41+# for sites without sccs front end, GET= get
 42+GET=	sccs get
 43+
 44+# Use ansi flag to gcc
 45+#CC = gcc -ansi
 46+CC = cc
 47+
 48+.DEFAULT:
 49+	$(GET) $@
 50+
 51+a.out: $(HDRS) $(OBJS)
 52+	-rm -f a.out
 53+	@rm -f x.c
 54+	-$(CC) $(LDFLAGS) $(OBJS) $(CRLIB)
 55+#	-$(CC) $(LDFLAGS) $(OBJS) $(CRLIB) -ltermlib
 56+#	-$(CC) $(LDFLAGS) $(OBJS) $(CRLIB) -lcrypt
 57+	size a.out
 58+#	@echo -n 'You still have to remove '		# 11/70's
 59+#	@size a.out | sed 's/+.*/ 1024 63 * - p/' | dc	# 11/70's
 60+
 61+terminal.o:
 62+	$(CC) -c $(CFLAGS) terminal.c
 63+
 64+find.o: find.c
 65+	$(CC) -c $(CFLAGS) $(SF) $(NL) $(MACHDEP) find.c
 66+
 67+inter.o: inter.c
 68+	$(CC) -c $(CFLAGS) $(SF) $(NL) $(MACHDEP) inter.c
 69+
 70+network: newvers a.out
 71+	cp a.out network
 72+	strip network
 73+
 74+ropen: ropen.c
 75+	$(CC) -s -o ropen ropen.c
 76+
 77+netwait: netwait.o netmisc.o terminal.o
 78+	$(CC) -s -o netwait terminal.o netwait.o netmisc.o -lcurses
 79+
 80+netmisc.o netwait.o:
 81+	$(CC) -O -c $(SF) $*.c
 82+
 83+newvers:
 84+	$(GET) -e terminal.c
 85+	sccs delta -y terminal.c
 86+
 87+flist: $(HDRS) $(CFILES) $(MISC_C)
 88+	-mv flist tags
 89+	ctags -u $?
 90+	ed - tags < :rofix
 91+	sort tags -o flist
 92+	rm -f tags
 93+
 94+lint:
 95+	/bin/csh -c "lint -hxbc $(DEFS) $(MACHDEP) $(SF) $(NL) $(CFILES) -lcurses > linterrs"
 96+
 97+clean:
 98+	rm -f $(OBJS) core a.out p.out network strings ? network.tar vgrind.* x.c x.o xs.c linterrs ropen
 99+
100+xtar: $(HDRS) $(CFILES) $(MISC)
101+	rm -f network.tar
102+	tar cf network.tar $? :rofix
103+	touch xtar
104+
105+vgrind:
106+	@csh $(VGRIND) -t -h "Rogue Version 3.7" $(HDRS) *.c > vgrind.out
107+	@ctags -v $(HDRS) *.c > index
108+	@csh $(VGRIND) -t -x index > vgrind.out.tbl
109+
110+wc:
111+	@echo "  bytes  words  lines  pages file"
112+	@wc -cwlp $(HDRS) $(CFILES)
113+
114+cfiles: $(CFILES)
A continue.c
+666, -0
  1@@ -0,0 +1,666 @@
  2+/*
  3+ * All the fighting gets done here
  4+ *
  5+ * @(#)continue.c	4.67 (Berkeley) 09/06/83
  6+ */
  7+
  8+#include <curses.h>
  9+#include <ctype.h>
 10+#include "netprot.h"
 11+
 12+#define	EQSTR(a, b)	(strcmp(a, b) == 0)
 13+
 14+char *H_names[] = {		/* strings for hitting */
 15+	" scored an excellent hit on ",
 16+	" hit ",
 17+	" have injured ",
 18+	" swing and hit ",
 19+	" scored an excellent hit on ",
 20+	" hit ",
 21+	" has injured ",
 22+	" swings and hits "
 23+};
 24+
 25+char *M_names[] = {		/* strings for missing */
 26+	" miss",
 27+	" swing and miss",
 28+	" barely miss",
 29+	" don't hit",
 30+	" misses",
 31+	" swings and misses",
 32+	" barely misses",
 33+	" doesn't hit",
 34+};
 35+
 36+/*
 37+ * adjustments to hit probabilities due to strength
 38+ */
 39+static int Str_plus[] = {
 40+    -7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
 41+    1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
 42+};
 43+
 44+/*
 45+ * adjustments to damage done due to strength
 46+ */
 47+static int Add_dam[] = {
 48+    -7, -6, -5, -4, -3, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3,
 49+    3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6
 50+};
 51+
 52+/*
 53+ * fight:
 54+ *	The player attacks the monster.
 55+ */
 56+bool
 57+fight(coord *mp, THING *weap, bool thrown)
 58+{
 59+    THING *tp;
 60+    bool did_hit = TRUE;
 61+    char *mname, ch;
 62+
 63+    /*
 64+     * Find the monster we want to fight
 65+     */
 66+#ifdef MASTER
 67+    if ((tp = moat(mp->y, mp->x)) == NULL)
 68+	debug("Fight what @ %d,%d", mp->y, mp->x);
 69+#else
 70+    tp = moat(mp->y, mp->x);
 71+#endif
 72+    /*
 73+     * Since we are fighting, things are not quiet so no healing takes
 74+     * place.
 75+     */
 76+    Count = 0;
 77+    Quiet = 0;
 78+    runto(mp);
 79+    /*
 80+     * Let him know it was really a xeroc (if it was one).
 81+     */
 82+    ch = '\0';
 83+    if (tp->t_type == 'X' && tp->t_disguise != 'X' && !on(Player, ISBLIND))
 84+    {
 85+	tp->t_disguise = 'X';
 86+	if (on(Player, ISHALU)) {
 87+	    ch = rnd(26) + 'A';
 88+	    mvaddch(tp->t_pos.y, tp->t_pos.x, ch);
 89+	}
 90+	msg(choose_str("heavy!  That's a nasty critter!",
 91+		       "wait!  That's a xeroc!"));
 92+	if (!thrown)
 93+	    return FALSE;
 94+    }
 95+    mname = set_mname(tp);
 96+    did_hit = FALSE;
 97+    Has_hit = (Terse && !To_death);
 98+    if (roll_em(&Player, tp, weap, thrown))
 99+    {
100+	did_hit = FALSE;
101+	if (thrown)
102+	    thunk(weap, mname, Terse);
103+	else
104+	    hit((char *) NULL, mname, Terse);
105+	if (on(Player, CANHUH))
106+	{
107+	    did_hit = TRUE;
108+	    tp->t_flags |= ISHUH;
109+	    Player.t_flags &= ~CANHUH;
110+	    endmsg();
111+	    Has_hit = FALSE;
112+	    msg("your hands stop glowing %s", pick_color("red"));
113+	}
114+	if (tp->t_stats.s_hpt <= 0)
115+	    killed(tp, TRUE);
116+	else if (did_hit && !on(Player, ISBLIND))
117+	    msg("%s appears confused", mname);
118+	did_hit = TRUE;
119+    }
120+    else
121+	if (thrown)
122+	    bounce(weap, mname, Terse);
123+	else
124+	    miss((char *) NULL, mname, Terse);
125+    return did_hit;
126+}
127+
128+/*
129+ * attack:
130+ *	The monster attacks the player
131+ */
132+void
133+attack(THING *mp)
134+{
135+    char *mname, ch;
136+    int oldhp;
137+
138+    /*
139+     * Since this is an attack, stop running and any healing that was
140+     * going on at the time.
141+     */
142+    Running = FALSE;
143+    Count = 0;
144+    Quiet = 0;
145+    if (To_death && !on(*mp, ISTARGET))
146+    {
147+	To_death = FALSE;
148+	Kamikaze = FALSE;
149+    }
150+    if (mp->t_type == 'X' && mp->t_disguise != 'X' && !on(Player, ISBLIND))
151+    {
152+	mp->t_disguise = 'X';
153+	if (on(Player, ISHALU))
154+	    mvaddch(mp->t_pos.y, mp->t_pos.x, rnd(26) + 'A');
155+    }
156+    mname = set_mname(mp);
157+    oldhp = Pstats.s_hpt;
158+    if (roll_em(mp, &Player, (THING *) NULL, FALSE))
159+    {
160+	if (mp->t_type != 'I')
161+	{
162+	    if (Has_hit)
163+		addmsg(".  ");
164+	    hit(mname, (char *) NULL, FALSE);
165+	}
166+	else
167+	    if (Has_hit)
168+		endmsg();
169+	Has_hit = FALSE;
170+	if (Pstats.s_hpt <= 0)
171+	    death(mp->t_type);	/* Bye bye life ... */
172+	else if (!Kamikaze)
173+	{
174+	    oldhp -= Pstats.s_hpt;
175+	    if (oldhp > Max_hit)
176+		Max_hit = oldhp;
177+	    if (Pstats.s_hpt <= Max_hit)
178+		To_death = FALSE;
179+	}
180+	if (!on(*mp, ISCANC))
181+	    switch (mp->t_type)
182+	    {
183+		when 'A':
184+		    /*
185+		     * If an aquator hits, you can lose armor class.
186+		     */
187+		    rust_armor(Cur_armor);
188+		when 'I':
189+		    /*
190+		     * The ice monster freezes you
191+		     */
192+		    Player.t_flags &= ~ISRUN;
193+		    if (!No_command)
194+		    {
195+			addmsg("you are frozen");
196+			if (!Terse)
197+			    addmsg(" by the %s", mname);
198+			endmsg();
199+		    }
200+		    No_command += rnd(2) + 2;
201+		    if (No_command > BORE_LEVEL)
202+			death('h');
203+		when 'R':
204+		    /*
205+		     * Rattlesnakes have poisonous bites
206+		     */
207+		    if (!save(VS_POISON))
208+			if (!ISWEARING(R_SUSTSTR))
209+			{
210+			    chg_str(-1);
211+			    if (!Terse)
212+				msg("you feel a bite in your leg and now feel weaker");
213+			    else
214+				msg("a bite has weakened you");
215+			}
216+			else if (!To_death)
217+			    if (!Terse)
218+				msg("a bite momentarily weakens you");
219+			    else
220+				msg("bite has no effect");
221+		when 'W':
222+		case 'V':
223+		    /*
224+		     * Wraiths might drain energy levels, and Vampires
225+		     * can steal Max_hp
226+		     */
227+		    if (rnd(100) < (mp->t_type == 'W' ? 15 : 30))
228+		    {
229+			int fewer;
230+
231+			if (mp->t_type == 'W')
232+			{
233+			    if (Pstats.s_exp == 0)
234+				death('W');		/* All levels gone */
235+			    if (--Pstats.s_lvl == 0)
236+			    {
237+				Pstats.s_exp = 0;
238+				Pstats.s_lvl = 1;
239+			    }
240+			    else
241+				Pstats.s_exp = E_levels[Pstats.s_lvl-1]+1;
242+			    fewer = roll(1, 10);
243+			}
244+			else
245+			    fewer = roll(1, 3);
246+			Pstats.s_hpt -= fewer;
247+			Max_hp -= fewer;
248+			if (Pstats.s_hpt <= 0)
249+			    Pstats.s_hpt = 1;
250+			if (Max_hp <= 0)
251+			    death(mp->t_type);
252+			msg("you suddenly feel weaker");
253+		    }
254+		when 'F':
255+		    /*
256+		     * Venus Flytrap stops the poor guy from moving
257+		     */
258+		    Player.t_flags |= ISHELD;
259+		    sprintf(Monsters['F'-'A'].m_stats.s_dmg,"%dx1", ++Vf_hit);
260+		    if (--Pstats.s_hpt <= 0)
261+			death('F');
262+		when 'L':
263+		{
264+		    /*
265+		     * Leperachaun steals some gold
266+		     */
267+		    long lastpurse;
268+
269+		    lastpurse = Purse;
270+		    Purse -= GOLDCALC;
271+		    if (!save(VS_MAGIC))
272+			Purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
273+		    if (Purse < 0)
274+			Purse = 0;
275+		    remove_mon(&mp->t_pos, mp, FALSE);
276+		    if (Purse != lastpurse)
277+			msg("your purse feels lighter");
278+		}
279+		when 'N':
280+		{
281+		    THING *obj, *steal;
282+		    int nobj;
283+
284+		    /*
285+		     * Nymph's steal a magic item, look through the pack
286+		     * and pick out one we like.
287+		     */
288+		    steal = NULL;
289+		    for (nobj = 0, obj = Pack; obj != NULL; obj = next(obj))
290+			if (obj != Cur_armor && obj != Cur_weapon
291+			    && obj != Cur_ring[LEFT] && obj != Cur_ring[RIGHT]
292+			    && is_magic(obj) && rnd(++nobj) == 0)
293+				steal = obj;
294+		    if (steal != NULL)
295+		    {
296+			remove_mon(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
297+			leave_pack(steal, FALSE, FALSE);
298+			msg("she stole %s!", inv_name(steal, TRUE));
299+			discard(steal);
300+		    }
301+		}
302+		otherwise:
303+		    break;
304+	    }
305+    }
306+    else if (mp->t_type != 'I')
307+    {
308+	if (Has_hit)
309+	{
310+	    addmsg(".  ");
311+	    Has_hit = FALSE;
312+	}
313+	if (mp->t_type == 'F')
314+	{
315+	    Pstats.s_hpt -= Vf_hit;
316+	    if (Pstats.s_hpt <= 0)
317+		death(mp->t_type);	/* Bye bye life ... */
318+	}
319+	miss(mname, (char *) NULL, FALSE);
320+    }
321+    if (Fight_flush && !To_death)
322+	flush_type();
323+    Count = 0;
324+    status();
325+}
326+
327+/*
328+ * set_mname:
329+ *	return the monster name for the given monster
330+ */
331+char *
332+set_mname(THING *tp)
333+{
334+    int ch;
335+    char *mname;
336+    static char tbuf[MAXSTR] = { 't', 'h', 'e', ' ' };
337+
338+    if (!see_monst(tp) && !on(Player, SEEMONST))
339+	return (Terse ? "it" : "something");
340+    else if (on(Player, ISHALU))
341+    {
342+	move(tp->t_pos.y, tp->t_pos.x);
343+	ch = toascii(inch());
344+	if (!isupper(ch))
345+	    ch = rnd(26);
346+	else
347+	    ch -= 'A';
348+	mname = Monsters[ch].m_name;
349+    }
350+    else
351+	mname = Monsters[tp->t_type - 'A'].m_name;
352+    strcpy(&tbuf[4], mname);
353+    return tbuf;
354+}
355+
356+/*
357+ * swing:
358+ *	Returns true if the swing hits
359+ */
360+bool
361+swing(int at_lvl, int op_arm, int wplus)
362+{
363+    int res = rnd(20);
364+    int need = (20 - at_lvl) - op_arm;
365+
366+    return (res + wplus >= need);
367+}
368+
369+/*
370+ * roll_em:
371+ *	Roll several attacks
372+ */
373+bool
374+roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl)
375+{
376+    struct stats *att, *def;
377+    char *cp;
378+    int ndice, nsides, def_arm;
379+    bool did_hit = FALSE;
380+    int hplus;
381+    int dplus;
382+    int damage;
383+    char *index();
384+
385+    att = &thatt->t_stats;
386+    def = &thdef->t_stats;
387+    if (weap == NULL)
388+    {
389+	cp = att->s_dmg;
390+	dplus = 0;
391+	hplus = 0;
392+    }
393+    else
394+    {
395+	hplus = (weap == NULL ? 0 : weap->o_hplus);
396+	dplus = (weap == NULL ? 0 : weap->o_dplus);
397+	if (weap == Cur_weapon)
398+	{
399+	    if (ISRING(LEFT, R_ADDDAM))
400+		dplus += Cur_ring[LEFT]->o_arm;
401+	    else if (ISRING(LEFT, R_ADDHIT))
402+		hplus += Cur_ring[LEFT]->o_arm;
403+	    if (ISRING(RIGHT, R_ADDDAM))
404+		dplus += Cur_ring[RIGHT]->o_arm;
405+	    else if (ISRING(RIGHT, R_ADDHIT))
406+		hplus += Cur_ring[RIGHT]->o_arm;
407+	}
408+	cp = weap->o_damage;
409+	if (hurl)
410+	    if ((weap->o_flags&ISMISL) && Cur_weapon != NULL &&
411+	      Cur_weapon->o_which == weap->o_launch)
412+	    {
413+		cp = weap->o_hurldmg;
414+		hplus += Cur_weapon->o_hplus;
415+		dplus += Cur_weapon->o_dplus;
416+	    }
417+	    else if (weap->o_launch < 0)
418+		cp = weap->o_hurldmg;
419+    }
420+    /*
421+     * If the creature being attacked is not running (alseep or held)
422+     * then the attacker gets a plus four bonus to hit.
423+     */
424+    if (!on(*thdef, ISRUN))
425+	hplus += 4;
426+    def_arm = def->s_arm;
427+    if (def == &Pstats)
428+    {
429+	if (Cur_armor != NULL)
430+	    def_arm = Cur_armor->o_arm;
431+	if (ISRING(LEFT, R_PROTECT))
432+	    def_arm -= Cur_ring[LEFT]->o_arm;
433+	if (ISRING(RIGHT, R_PROTECT))
434+	    def_arm -= Cur_ring[RIGHT]->o_arm;
435+    }
436+    while (cp != NULL && *cp != '\0')
437+    {
438+	ndice = atoi(cp);
439+	if ((cp = index(cp, 'x')) == NULL)
440+	    break;
441+	nsides = atoi(++cp);
442+	if (swing(att->s_lvl, def_arm, hplus + Str_plus[att->s_str]))
443+	{
444+	    int proll;
445+
446+	    proll = roll(ndice, nsides);
447+#ifdef MASTER
448+	    if (ndice + nsides > 0 && proll <= 0)
449+		debug("Damage for %dx%d came out %d, dplus = %d, Add_dam = %d, def_arm = %d", ndice, nsides, proll, dplus, Add_dam[att->s_str], def_arm);
450+#endif
451+	    damage = dplus + proll + Add_dam[att->s_str];
452+	    def->s_hpt -= max(0, damage);
453+	    did_hit = TRUE;
454+	}
455+	if ((cp = index(cp, '/')) == NULL)
456+	    break;
457+	cp++;
458+    }
459+    return did_hit;
460+}
461+
462+/*
463+ * prname:
464+ *	The print name of a combatant
465+ */
466+char *
467+prname(char *mname, bool upper)
468+{
469+    static char tbuf[MAXSTR];
470+
471+    *tbuf = '\0';
472+    if (mname == 0)
473+	strcpy(tbuf, "you"); 
474+    else
475+	strcpy(tbuf, mname);
476+    if (upper)
477+	*tbuf = toupper(*tbuf);
478+    return tbuf;
479+}
480+
481+/*
482+ * thunk:
483+ *	A missile hits a monster
484+ */
485+void
486+thunk(THING *weap, char *mname, bool noend)
487+{
488+    if (To_death)
489+	return;
490+    if (weap->o_type == WEAPON)
491+	addmsg("the %s hits ", Weap_info[weap->o_which].oi_name);
492+    else
493+	addmsg("you hit ");
494+    addmsg("%s", mname);
495+    if (!noend)
496+	endmsg();
497+}
498+
499+/*
500+ * hit:
501+ *	Print a message to indicate a succesful hit
502+ */
503+void
504+hit(char *er, char *ee, bool noend)
505+{
506+    int i;
507+    char *s;
508+    extern char *H_names[];
509+
510+    if (To_death)
511+	return;
512+    addmsg(prname(er, TRUE));
513+    if (Terse)
514+	s = " hit";
515+    else
516+    {
517+	i = rnd(4);
518+	if (er != NULL)
519+	    i += 4;
520+	s = H_names[i];
521+    }
522+    addmsg(s);
523+    if (!Terse)
524+	addmsg(prname(ee, FALSE));
525+    if (!noend)
526+	endmsg();
527+}
528+
529+/*
530+ * miss:
531+ *	Print a message to indicate a poor swing
532+ */
533+void
534+miss(char *er, char *ee, bool noend)
535+{
536+    int i;
537+    extern char *M_names[];
538+
539+    if (To_death)
540+	return;
541+    addmsg(prname(er, TRUE));
542+    if (Terse)
543+	i = 0;
544+    else
545+	i = rnd(4);
546+    if (er != NULL)
547+	i += 4;
548+    addmsg(M_names[i]);
549+    if (!Terse)
550+	addmsg(" %s", prname(ee, FALSE));
551+    if (!noend)
552+	endmsg();
553+}
554+
555+/*
556+ * bounce:
557+ *	A missile misses a monster
558+ */
559+void
560+bounce(THING *weap, char *mname, bool noend)
561+{
562+    if (To_death)
563+	return;
564+    if (weap->o_type == WEAPON)
565+	addmsg("the %s misses ", Weap_info[weap->o_which].oi_name);
566+    else
567+	addmsg("you missed ");
568+    addmsg(mname);
569+    if (!noend)
570+	endmsg();
571+}
572+
573+/*
574+ * remove_mon:
575+ *	Remove a monster from the screen
576+ */
577+void
578+remove_mon(coord *mp, THING *tp, bool waskill)
579+{
580+    THING *obj, *nexti;
581+
582+    for (obj = tp->t_pack; obj != NULL; obj = nexti)
583+    {
584+	nexti = next(obj);
585+	obj->o_pos = tp->t_pos;
586+	detach(tp->t_pack, obj);
587+	if (waskill)
588+	    fall(obj, FALSE);
589+	else
590+	    discard(obj);
591+    }
592+    moat(mp->y, mp->x) = NULL;
593+    mvaddch(mp->y, mp->x, tp->t_oldch);
594+    detach(Mlist, tp);
595+    if (on(*tp, ISTARGET))
596+    {
597+	Kamikaze = FALSE;
598+	To_death = FALSE;
599+	if (Fight_flush)
600+	    flush_type();
601+    }
602+    discard(tp);
603+}
604+
605+/*
606+ * killed:
607+ *	Called to put a monster to death
608+ */
609+void
610+killed(THING *tp, bool pr)
611+{
612+    char *mname;
613+
614+    Pstats.s_exp += tp->t_stats.s_exp;
615+
616+    /*
617+     * If the monster was a venus flytrap, un-hold him
618+     */
619+    switch (tp->t_type)
620+    {
621+	when 'F':
622+	    Player.t_flags &= ~ISHELD;
623+	    Vf_hit = 0;
624+	    strcpy(Monsters['F'-'A'].m_stats.s_dmg, "000x0");
625+	when 'L':
626+	{
627+	    THING *gold;
628+
629+	    if (fallpos(&tp->t_pos, &tp->t_room->r_gold) && Level >= Max_level)
630+	    {
631+		gold = new_item();
632+		gold->o_type = GOLD;
633+		gold->o_goldval = GOLDCALC;
634+		if (save(VS_MAGIC))
635+		    gold->o_goldval += GOLDCALC + GOLDCALC
636+				     + GOLDCALC + GOLDCALC;
637+		attach(tp->t_pack, gold);
638+	    }
639+	}
640+    }
641+    /*
642+     * Get rid of the monster.
643+     */
644+    mname = set_mname(tp);
645+    remove_mon(&tp->t_pos, tp, TRUE);
646+    if (pr)
647+    {
648+	if (Has_hit)
649+	{
650+	    addmsg(".  Defeated ");
651+	    Has_hit = FALSE;
652+	}
653+	else
654+	{
655+	    if (!Terse)
656+		addmsg("you have ");
657+	    addmsg("defeated ");
658+	}
659+	msg(mname);
660+    }
661+    /*
662+     * Do adjustments if he went up a level
663+     */
664+    check_level();
665+    if (Fight_flush)
666+	flush_type();
667+}
A control.c
+273, -0
  1@@ -0,0 +1,273 @@
  2+/*
  3+ * Various input/output functions
  4+ *
  5+ * @(#)control.c	4.32 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include <ctype.h>
 10+#include "netprot.h"
 11+
 12+/*
 13+ * msg:
 14+ *	Display a message at the top of the screen.
 15+ */
 16+#define MAXMSG	(NUMCOLS - sizeof "--More--")
 17+
 18+static char Msgbuf[MAXMSG+1];
 19+static int Newpos = 0;
 20+
 21+/* VARARGS1 */
 22+int
 23+msg(char *fmt, ...)
 24+{
 25+    va_list args;
 26+
 27+    /*
 28+     * if the string is "", just clear the line
 29+     */
 30+    if (*fmt == '\0')
 31+    {
 32+	move(0, 0);
 33+	clrtoeol();
 34+	Mpos = 0;
 35+	return ~ESCAPE;
 36+    }
 37+    /*
 38+     * otherwise add to the message and flush it out
 39+     */
 40+    va_start(args, fmt);
 41+    doadd(fmt, args);
 42+    va_end(args);
 43+    return endmsg();
 44+}
 45+
 46+/*
 47+ * addmsg:
 48+ *	Add things to the current message
 49+ */
 50+/* VARARGS1 */
 51+void
 52+addmsg(char *fmt, ...)
 53+{
 54+    va_list args;
 55+
 56+    va_start(args, fmt);
 57+    doadd(fmt, args);
 58+    va_end(args);
 59+}
 60+
 61+/*
 62+ * endmsg:
 63+ *	Display a new msg (giving him a chance to see the previous one
 64+ *	if it is up there with the --More--)
 65+ */
 66+int
 67+endmsg(void)
 68+{
 69+    char ch;
 70+
 71+    if (Save_msg)
 72+	strcpy(Huh, Msgbuf);
 73+    if (Mpos)
 74+    {
 75+	look(FALSE);
 76+	mvaddstr(0, Mpos, "--More--");
 77+	refresh();
 78+	if (!Msg_esc)
 79+	    wait_for(' ');
 80+	else
 81+	{
 82+	    while ((ch = readchar()) != ' ')
 83+		if (ch == ESCAPE)
 84+		{
 85+		    Msgbuf[0] = '\0';
 86+		    Mpos = 0;
 87+		    Newpos = 0;
 88+		    Msgbuf[0] = '\0';
 89+		    return ESCAPE;
 90+		}
 91+	}
 92+    }
 93+    /*
 94+     * All messages should start with uppercase, except ones that
 95+     * start with a pack addressing character
 96+     */
 97+    if (islower(Msgbuf[0]) && !Lower_msg && Msgbuf[1] != ')')
 98+	Msgbuf[0] = toupper(Msgbuf[0]);
 99+    mvaddstr(0, 0, Msgbuf);
100+    clrtoeol();
101+    Mpos = Newpos;
102+    Newpos = 0;
103+    Msgbuf[0] = '\0';
104+    refresh();
105+    return ~ESCAPE;
106+}
107+
108+/*
109+ * doadd:
110+ *	Perform an add onto the message buffer
111+ */
112+void
113+doadd(char *fmt, va_list args)
114+{
115+    static char buf[MAXSTR];
116+
117+    /*
118+     * Do the printf into buf
119+     */
120+    vsprintf(buf, fmt, args);
121+    if (strlen(buf) + Newpos >= MAXMSG)
122+	endmsg();
123+    strcat(Msgbuf, buf);
124+    Newpos = strlen(Msgbuf);
125+}
126+
127+/*
128+ * step_ok:
129+ *	Returns true if it is ok to step on ch
130+ */
131+bool
132+step_ok(char ch)
133+{
134+    switch (ch)
135+    {
136+	case ' ':
137+	case '|':
138+	case '-':
139+	    return FALSE;
140+	default:
141+	    return (!isalpha(ch));
142+    }
143+}
144+
145+/*
146+ * readchar:
147+ *	Reads and returns a character, checking for gross input errors
148+ */
149+int
150+readchar(void)
151+{
152+    int cnt;
153+    static char c;
154+
155+    cnt = 0;
156+    while (read(0, &c, 1) <= 0)
157+	if (cnt++ > 100)	/* if we are getting infinite EOFs */
158+	    auto_save(0);	/* save the game */
159+    return c;
160+}
161+
162+/*
163+ * status:
164+ *	Display the important stats line.  Keep the cursor where it was.
165+ */
166+void
167+status(void)
168+{
169+    int (*print_func)(char *fmt, ...);
170+# define	PRINT_FUNC	(*print_func)
171+    int oy, ox, temp;
172+    static int hpwidth = 0;
173+    static int s_hungry;
174+    static int s_lvl;
175+    static int s_pur = -1;
176+    static int s_hp;
177+    static int s_arm;
178+    static str_t s_str;
179+    static long s_exp = 0;
180+    static char *state_name[] =
181+    {
182+	"", "Hungry", "Weak", "Faint"
183+    };
184+
185+    /*
186+     * If nothing has changed since the last status, don't
187+     * bother.
188+     */
189+    temp = (Cur_armor != NULL ? Cur_armor->o_arm : Pstats.s_arm);
190+    if (s_hp == Pstats.s_hpt && s_exp == Pstats.s_exp && s_pur == Purse
191+	&& s_arm == temp && s_str == Pstats.s_str && s_lvl == Level
192+	&& s_hungry == Hungry_state
193+	&& !Stat_msg
194+	)
195+	    return;
196+
197+    s_arm = temp;
198+
199+    getyx(stdscr, oy, ox);
200+    if (s_hp != Max_hp)
201+    {
202+	temp = Max_hp;
203+	s_hp = Max_hp;
204+	for (hpwidth = 0; temp; hpwidth++)
205+	    temp /= 10;
206+    }
207+
208+    /*
209+     * Save current status
210+     */
211+    s_lvl = Level;
212+    s_pur = Purse;
213+    s_hp = Pstats.s_hpt;
214+    s_str = Pstats.s_str;
215+    s_exp = Pstats.s_exp; 
216+    s_hungry = Hungry_state;
217+
218+    if (Stat_msg)
219+    {
220+	print_func = msg;
221+	move(0, 0);
222+    }
223+    else
224+    {
225+	move(STATLINE, 0);
226+	print_func = printw;
227+    }
228+    PRINT_FUNC("Level: %d  Gold: %-5d  Hp: %*d(%*d)  Str: %2d(%d)  Arm: %-2d  Exp: %d/%ld  %s",
229+	    Level, Purse, hpwidth, Pstats.s_hpt, hpwidth, Max_hp, Pstats.s_str,
230+	    Max_stats.s_str, 10 - s_arm, Pstats.s_lvl, Pstats.s_exp,
231+	    state_name[Hungry_state]);
232+
233+    clrtoeol();
234+    move(oy, ox);
235+}
236+
237+/*
238+ * wait_for
239+ *	Sit around until the guy types the right key
240+ */
241+void
242+wait_for(char ch)
243+{
244+    char c;
245+
246+    if (ch == '\n')
247+        while ((c = readchar()) != '\n' && c != '\r')
248+	    continue;
249+    else
250+        while (readchar() != ch)
251+	    continue;
252+}
253+
254+/*
255+ * show_win:
256+ *	Function used to display a window and wait before returning
257+ */
258+void
259+show_win(char *message)
260+{
261+    WINDOW *win;
262+
263+    win = Hw;
264+    wmove(win, 0, 0);
265+    waddstr(win, message);
266+    touchwin(win);
267+    wmove(win, Hero.y, Hero.x);
268+    wrefresh(win);
269+    wait_for(' ');
270+    clearok(curscr, TRUE);
271+#ifdef	attron
272+    touchwin(stdscr);
273+#endif	attron
274+}
A ctlmod.c
+266, -0
  1@@ -0,0 +1,266 @@
  2+/*
  3+ * Special wizard commands (some of which are also non-wizard commands
  4+ * under strange circumstances)
  5+ *
  6+ * @(#)ctlmod.c	4.30 (Berkeley) 02/05/99
  7+ */
  8+
  9+#include <curses.h>
 10+#include <ctype.h>
 11+#include "netprot.h"
 12+
 13+/*
 14+ * whatis:
 15+ *	What a certin object is
 16+ */
 17+void
 18+whatis(bool insist, int type)
 19+{
 20+    THING *obj;
 21+
 22+    if (Pack == NULL)
 23+    {
 24+	msg("you don't have anything in your pack to identify");
 25+	return;
 26+    }
 27+
 28+    for (;;)
 29+    {
 30+	obj = get_item("identify", type);
 31+	if (insist)
 32+	{
 33+	    if (N_objs == 0)
 34+		return;
 35+	    else if (obj == NULL)
 36+		msg("you must identify something");
 37+	    else if (type && obj->o_type != type &&
 38+	       !(type == R_OR_S && obj->o_type == RING || obj->o_type == STICK))
 39+		    msg("you must identify a %s", type_name(type));
 40+	    else
 41+		break;
 42+	}
 43+	else
 44+	    break;
 45+    }
 46+
 47+    if (obj == NULL)
 48+	return;
 49+
 50+    switch (obj->o_type)
 51+    {
 52+        when SCROLL:
 53+	    set_know(obj, Scr_info);
 54+        when POTION:
 55+	    set_know(obj, Pot_info);
 56+	when STICK:
 57+	    set_know(obj, Ws_info);
 58+        when WEAPON:
 59+        case ARMOR:
 60+	    obj->o_flags |= ISKNOW;
 61+        when RING:
 62+	    set_know(obj, Ring_info);
 63+    }
 64+    msg(inv_name(obj, FALSE));
 65+}
 66+
 67+/*
 68+ * set_know:
 69+ *	Set things up when we really know what a thing is
 70+ */
 71+void
 72+set_know(THING *obj, struct obj_info *info)
 73+{
 74+    char **guess;
 75+
 76+    info[obj->o_which].oi_know = TRUE;
 77+    obj->o_flags |= ISKNOW;
 78+    guess = &info[obj->o_which].oi_guess;
 79+    if (*guess)
 80+    {
 81+	free(*guess);
 82+	*guess = NULL;
 83+    }
 84+}
 85+
 86+/*
 87+ * type_name:
 88+ *	Return a pointer to the name of the type
 89+ */
 90+char *
 91+type_name(int type)
 92+{
 93+    struct h_list *hp;
 94+    static struct h_list tlist[] = {
 95+	POTION,	 "potion",		FALSE,
 96+	SCROLL,	 "scroll",		FALSE,
 97+	FOOD,	 "food",		FALSE,
 98+	R_OR_S,	 "ring, wand or staff",	FALSE,
 99+	RING,	 "ring",		FALSE,
100+	STICK,	 "wand or staff",	FALSE,
101+	WEAPON,	 "weapon",		FALSE,
102+	ARMOR,	 "suit of armor",	FALSE,
103+    };
104+
105+    for (hp = tlist; hp->h_ch; hp++)
106+	if (type == hp->h_ch)
107+	    return hp->h_desc;
108+    /* NOTREACHED */
109+}
110+
111+#ifdef MASTER
112+/*
113+ * create_obj:
114+ *	Wizard command for getting anything he wants
115+ */
116+void
117+create_obj(void)
118+{
119+    THING *obj;
120+    char ch, bless;
121+
122+    obj = new_item();
123+    msg("type of item: ");
124+    obj->o_type = readchar();
125+    Mpos = 0;
126+    msg("which %c do you want? (0-f)", obj->o_type);
127+    obj->o_which = (isdigit((ch = readchar())) ? ch - '0' : ch - 'a' + 10);
128+    obj->o_group = 0;
129+    obj->o_count = 1;
130+    Mpos = 0;
131+    if (obj->o_type == WEAPON || obj->o_type == ARMOR)
132+    {
133+	msg("blessing? (+,-,n)");
134+	bless = readchar();
135+	Mpos = 0;
136+	if (bless == '-')
137+	    obj->o_flags |= ISCURSED;
138+	if (obj->o_type == WEAPON)
139+	{
140+	    init_weapon(obj, obj->o_which);
141+	    if (bless == '-')
142+		obj->o_hplus -= rnd(3)+1;
143+	    if (bless == '+')
144+		obj->o_hplus += rnd(3)+1;
145+	}
146+	else
147+	{
148+	    obj->o_arm = A_class[obj->o_which];
149+	    if (bless == '-')
150+		obj->o_arm += rnd(3)+1;
151+	    if (bless == '+')
152+		obj->o_arm -= rnd(3)+1;
153+	}
154+    }
155+    else if (obj->o_type == RING)
156+	switch (obj->o_which)
157+	{
158+	    case R_PROTECT:
159+	    case R_ADDSTR:
160+	    case R_ADDHIT:
161+	    case R_ADDDAM:
162+		msg("blessing? (+,-,n)");
163+		bless = readchar();
164+		Mpos = 0;
165+		if (bless == '-')
166+		    obj->o_flags |= ISCURSED;
167+		obj->o_arm = (bless == '-' ? -1 : rnd(2) + 1);
168+	    when R_AGGR:
169+	    case R_TELEPORT:
170+		obj->o_flags |= ISCURSED;
171+	}
172+    else if (obj->o_type == STICK)
173+	fix_stick(obj);
174+    else if (obj->o_type == GOLD)
175+    {
176+	msg("how much?");
177+	get_num(&obj->o_goldval, stdscr);
178+    }
179+    add_pack(obj, FALSE);
180+}
181+#endif
182+
183+/*
184+ * telport:
185+ *	Bamf the hero someplace else
186+ */
187+void
188+teleport(void)
189+{
190+    int rm;
191+    static coord c;
192+
193+    mvaddch(Hero.y, Hero.x, floor_at());
194+    find_floor((struct room *) NULL, &c, FALSE, TRUE);
195+    if (roomin(&c) != Proom)
196+    {
197+	leave_room(&Hero);
198+	Hero = c;
199+	enter_room(&Hero);
200+    }
201+    else
202+    {
203+	Hero = c;
204+	look(TRUE);
205+    }
206+    mvaddch(Hero.y, Hero.x, PLAYER);
207+    /*
208+     * turn off ISHELD in case teleportation was done while fighting
209+     * a Flytrap
210+     */
211+    if (on(Player, ISHELD)) {
212+	Player.t_flags &= ~ISHELD;
213+	Vf_hit = 0;
214+	strcpy(Monsters['F'-'A'].m_stats.s_dmg, "000x0");
215+    }
216+    No_move = 0;
217+    Count = 0;
218+    Running = FALSE;
219+    flush_type();
220+}
221+
222+#ifdef MASTER
223+/*
224+ * passwd:
225+ *	See if user knows password
226+ */
227+bool
228+passwd(void)
229+{
230+    char *sp, c;
231+    static char buf[MAXSTR];
232+    char *crypt();
233+
234+    msg("wizard's Password:");
235+    Mpos = 0;
236+    sp = buf;
237+    while ((c = getchar()) != '\n' && c != '\r' && c != ESCAPE)
238+	*sp++ = c;
239+    if (sp == buf)
240+	return FALSE;
241+    *sp = '\0';
242+    return (strcmp(PASSWD, crypt(buf, "mT")) == 0);
243+}
244+
245+/*
246+ * show_map:
247+ *	Print out the map for the wizard
248+ */
249+void
250+show_map(void)
251+{
252+    int y, x, real;
253+
254+    wclear(Hw);
255+    for (y = 1; y < NUMLINES - 1; y++)
256+	for (x = 0; x < NUMCOLS; x++)
257+	{
258+	    if (!(real = flat(y, x) & F_REAL))
259+		wstandout(Hw);
260+	    wmove(Hw, y, x);
261+	    waddch(Hw, chat(y, x));
262+	    if (!real)
263+		wstandend(Hw);
264+	}
265+    show_win("---More (level map)---");
266+}
267+#endif
A data.c
+319, -0
  1@@ -0,0 +1,319 @@
  2+/*
  3+ * Read a scroll and let it happen
  4+ *
  5+ * @(#)data.c	4.44 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include <ctype.h>
 10+#include "netprot.h"
 11+
 12+/*
 13+ * read_scroll:
 14+ *	Read a scroll from the pack and do the appropriate thing
 15+ */
 16+void
 17+read_scroll(void)
 18+{
 19+    THING *obj;
 20+    PLACE *pp;
 21+    int y, x;
 22+    char ch;
 23+    int i;
 24+    bool discardit = FALSE;
 25+    struct room *cur_room;
 26+    THING *orig_obj;
 27+    static coord mp;
 28+
 29+    obj = get_item("read", SCROLL);
 30+    if (obj == NULL)
 31+	return;
 32+    if (obj->o_type != SCROLL)
 33+    {
 34+	if (!Terse)
 35+	    msg("there is nothing on it to read");
 36+	else
 37+	    msg("nothing to read");
 38+	return;
 39+    }
 40+    /*
 41+     * Calculate the effect it has on the poor guy.
 42+     */
 43+    if (obj == Cur_weapon)
 44+	Cur_weapon = NULL;
 45+    /*
 46+     * Get rid of the thing
 47+     */
 48+    discardit = (obj->o_count == 1);
 49+    leave_pack(obj, FALSE, FALSE);
 50+    orig_obj = obj;
 51+
 52+    switch (obj->o_which)
 53+    {
 54+	when S_CONFUSE:
 55+	    /*
 56+	     * Scroll of monster confusion.  Give him that power.
 57+	     */
 58+	    Player.t_flags |= CANHUH;
 59+	    msg("your hands begin to glow %s", pick_color("red"));
 60+	when S_ARMOR:
 61+	    if (Cur_armor != NULL)
 62+	    {
 63+		Cur_armor->o_arm--;
 64+		Cur_armor->o_flags &= ~ISCURSED;
 65+		msg("your armor glows %s for a moment", pick_color("silver"));
 66+	    }
 67+	when S_HOLD:
 68+	    /*
 69+	     * Hold monster scroll.  Stop all monsters within two spaces
 70+	     * from chasing after the hero.
 71+	     */
 72+
 73+	    ch = 0;
 74+	    for (x = Hero.x - 2; x <= Hero.x + 2; x++)
 75+		if (x >= 0 && x < NUMCOLS)
 76+		    for (y = Hero.y - 2; y <= Hero.y + 2; y++)
 77+			if (y >= 0 && y <= NUMLINES - 1)
 78+			    if ((obj = moat(y, x)) != NULL && on(*obj, ISRUN))
 79+			    {
 80+				obj->t_flags &= ~ISRUN;
 81+				obj->t_flags |= ISHELD;
 82+				ch++;
 83+			    }
 84+	    if (ch)
 85+	    {
 86+		addmsg("the monster");
 87+		if (ch > 1)
 88+		    addmsg("s around you");
 89+		addmsg(" freeze");
 90+		if (ch == 1)
 91+		    addmsg("s");
 92+		endmsg();
 93+		Scr_info[S_HOLD].oi_know = TRUE;
 94+	    }
 95+	    else
 96+		msg("you feel a strange sense of loss");
 97+	when S_SLEEP:
 98+	    /*
 99+	     * Scroll which makes you fall asleep
100+	     */
101+	    Scr_info[S_SLEEP].oi_know = TRUE;
102+	    No_command += rnd(SLEEPTIME) + 4;
103+	    Player.t_flags &= ~ISRUN;
104+	    msg("you fall asleep");
105+	when S_CREATE:
106+	    /*
107+	     * Create a monster:
108+	     * First look in a circle around him, next try his room
109+	     * otherwise give up
110+	     */
111+	    i = 0;
112+	    for (y = Hero.y - 1; y <= Hero.y + 1; y++)
113+		for (x = Hero.x - 1; x <= Hero.x + 1; x++)
114+		    /*
115+		     * Don't put a monster in top of the player.
116+		     */
117+		    if (y == Hero.y && x == Hero.x)
118+			continue;
119+		    /*
120+		     * Or anything else nasty
121+		     */
122+		    else if (step_ok(ch = winat(y, x)))
123+			if (ch == SCROLL
124+			    && find_obj(y, x)->o_which == S_SCARE)
125+				continue;
126+			else if (rnd(++i) == 0)
127+			{
128+			    mp.y = y;
129+			    mp.x = x;
130+			}
131+	    if (i == 0)
132+		msg("you hear a faint cry of anguish in the distance");
133+	    else
134+	    {
135+		obj = new_item();
136+		new_monster(obj, randmonster(FALSE), &mp);
137+	    }
138+	when S_ID_POTION:
139+	case S_ID_SCROLL:
140+	case S_ID_WEAPON:
141+	case S_ID_ARMOR:
142+	case S_ID_R_OR_S:
143+	{
144+	    static char id_type[S_ID_R_OR_S + 1] =
145+		{ 0, 0, 0, 0, 0, POTION, SCROLL, WEAPON, ARMOR, R_OR_S };
146+	    /*
147+	     * Identify, let him figure something out
148+	     */
149+	    Scr_info[obj->o_which].oi_know = TRUE;
150+	    msg("this scroll is an %s scroll", Scr_info[obj->o_which].oi_name);
151+	    whatis(TRUE, id_type[obj->o_which]);
152+	}
153+	when S_MAP:
154+	    /*
155+	     * Scroll of magic mapping.
156+	     */
157+	    Scr_info[S_MAP].oi_know = TRUE;
158+	    msg("oh, now this scroll has a map on it");
159+	    /*
160+	     * Take all the things we want to keep hidden out of the window
161+	     */
162+	    for (y = 1; y < NUMLINES - 1; y++)
163+		for (x = 0; x < NUMCOLS; x++)
164+		{
165+		    pp = INDEX(y, x);
166+		    switch (ch = pp->p_ch)
167+		    {
168+			case DOOR:
169+			case STAIRS:
170+			    break;
171+
172+			case '-':
173+			case '|':
174+			    if (!(pp->p_flags & F_REAL))
175+			    {
176+				ch = pp->p_ch = DOOR;
177+				pp->p_flags |= F_REAL;
178+			    }
179+			    break;
180+
181+			case ' ':
182+			    if (pp->p_flags & F_REAL)
183+				goto def;
184+			    pp->p_flags |= F_REAL;
185+			    ch = pp->p_ch = PASSAGE;
186+			    /* FALLTHROUGH */
187+
188+			case PASSAGE:
189+pass:
190+			    if (!(pp->p_flags & F_REAL))
191+				pp->p_ch = PASSAGE;
192+			    pp->p_flags |= (F_SEEN|F_REAL);
193+			    ch = PASSAGE;
194+			    break;
195+
196+			case FLOOR:
197+			    if (pp->p_flags & F_REAL)
198+				ch = ' ';
199+			    else
200+			    {
201+				ch = TRAP;
202+				pp->p_ch = TRAP;
203+				pp->p_flags |= (F_SEEN|F_REAL);
204+			    }
205+			    break;
206+
207+			default:
208+def:
209+			    if (pp->p_flags & F_PASS)
210+				goto pass;
211+			    ch = ' ';
212+			    break;
213+		    }
214+		    if (ch != ' ')
215+		    {
216+			if ((obj = pp->p_monst) != NULL)
217+			    obj->t_oldch = ch;
218+			if (obj == NULL || !on(Player, SEEMONST))
219+			    mvaddch(y, x, ch);
220+		    }
221+		}
222+	when S_FDET:
223+	    /*
224+	     * Potion of gold detection
225+	     */
226+	    ch = FALSE;
227+	    wclear(Hw);
228+	    for (obj = Lvl_obj; obj != NULL; obj = next(obj))
229+		if (obj->o_type == FOOD)
230+		{
231+		    ch = TRUE;
232+		    wmove(Hw, obj->o_pos.y, obj->o_pos.x);
233+		    waddch(Hw, FOOD);
234+		}
235+	    if (ch)
236+	    {
237+		Scr_info[S_FDET].oi_know = TRUE;
238+		show_win("Your nose tingles and you smell food.--More--");
239+	    }
240+	    else
241+		msg("your nose tingles");
242+	when S_TELEP:
243+	    /*
244+	     * Scroll of teleportation:
245+	     * Make him dissapear and reappear
246+	     */
247+	    {
248+		cur_room = Proom;
249+		teleport();
250+		if (cur_room != Proom)
251+		    Scr_info[S_TELEP].oi_know = TRUE;
252+	    }
253+	when S_ENCH:
254+	    if (Cur_weapon == NULL || Cur_weapon->o_type != WEAPON)
255+		msg("you feel a strange sense of loss");
256+	    else
257+	    {
258+		Cur_weapon->o_flags &= ~ISCURSED;
259+		if (rnd(2) == 0)
260+		    Cur_weapon->o_hplus++;
261+		else
262+		    Cur_weapon->o_dplus++;
263+		msg("your %s glows %s for a moment",
264+		    Weap_info[Cur_weapon->o_which].oi_name, pick_color("blue"));
265+	    }
266+	when S_SCARE:
267+	    /*
268+	     * Reading it is a mistake and produces laughter at her
269+	     * poor boo boo.
270+	     */
271+	    msg("you hear maniacal laughter in the distance");
272+	when S_REMOVE:
273+	    uncurse(Cur_armor);
274+	    uncurse(Cur_weapon);
275+	    uncurse(Cur_ring[LEFT]);
276+	    uncurse(Cur_ring[RIGHT]);
277+	    msg(choose_str("you feel in touch with the Universal Onenes",
278+			   "you feel as if somebody is watching over you"));
279+	when S_AGGR:
280+	    /*
281+	     * This scroll aggravates all the monsters on the current
282+	     * level and sets them running towards the hero
283+	     */
284+	    aggravate();
285+	    msg("you hear a high pitched humming noise");
286+	when S_PROTECT:
287+	    if (Cur_armor != NULL)
288+	    {
289+		Cur_armor->o_flags |= ISPROT;
290+		msg("your armor is covered by a shimmering %s shield",
291+		    pick_color("gold"));
292+	    }
293+	    else
294+		msg("you feel a strange sense of loss");
295+#ifdef MASTER
296+	otherwise:
297+	    msg("what a puzzling scroll!");
298+	    return;
299+#endif
300+    }
301+    obj = orig_obj;
302+    look(TRUE);	/* put the result of the scroll on the screen */
303+    status();
304+
305+    call_it(&Scr_info[obj->o_which]);
306+
307+    if (discardit)
308+	discard(obj);
309+}
310+
311+/*
312+ * uncurse:
313+ *	Uncurse an item
314+ */
315+void
316+uncurse(THING *obj)
317+{
318+    if (obj != NULL)
319+	obj->o_flags &= ~ISCURSED;
320+}
A edit.c
+577, -0
  1@@ -0,0 +1,577 @@
  2+/*
  3+ * All sorts of miscellaneous routines
  4+ *
  5+ * @(#)edit.c	4.66 (Berkeley) 08/06/83
  6+ */
  7+
  8+#include <curses.h>
  9+#include "netprot.h"
 10+#include <ctype.h>
 11+
 12+/*
 13+ * look:
 14+ *	A quick glance all around the player
 15+ */
 16+# undef	DEBUG
 17+
 18+void
 19+look(bool wakeup)
 20+{
 21+    int x, y;
 22+    int ch;
 23+    THING *tp;
 24+    PLACE *pp;
 25+    struct room *rp;
 26+    int ey, ex;
 27+    int passcount;
 28+    char pfl, *fp, pch;
 29+    int sy, sx, sumhero, diffhero;
 30+# ifdef DEBUG
 31+    static bool done = FALSE;
 32+
 33+    if (done)
 34+	return;
 35+    done = TRUE;
 36+# endif DEBUG
 37+    passcount = 0;
 38+    rp = Proom;
 39+    if (!ce(Oldpos, Hero))
 40+    {
 41+	erase_lamp(&Oldpos, Oldrp);
 42+	Oldpos = Hero;
 43+	Oldrp = rp;
 44+    }
 45+    ey = Hero.y + 1;
 46+    ex = Hero.x + 1;
 47+    sx = Hero.x - 1;
 48+    sy = Hero.y - 1;
 49+    if (Door_stop && !Firstmove && Running)
 50+    {
 51+	sumhero = Hero.y + Hero.x;
 52+	diffhero = Hero.y - Hero.x;
 53+    }
 54+    pp = INDEX(Hero.y, Hero.x);
 55+    pch = pp->p_ch;
 56+    pfl = pp->p_flags;
 57+
 58+    for (y = sy; y <= ey; y++)
 59+	if (y > 0 && y < NUMLINES - 1) for (x = sx; x <= ex; x++)
 60+	{
 61+	    if (x < 0 || x >= NUMCOLS)
 62+		continue;
 63+	    if (!on(Player, ISBLIND))
 64+	    {
 65+		if (y == Hero.y && x == Hero.x)
 66+		    continue;
 67+	    }
 68+
 69+	    pp = INDEX(y, x);
 70+	    ch = pp->p_ch;
 71+	    if (ch == ' ')		/* nothing need be done with a ' ' */
 72+		    continue;
 73+	    fp = &pp->p_flags;
 74+	    if (pch != DOOR && ch != DOOR)
 75+		if ((pfl & F_PASS) != (*fp & F_PASS))
 76+		    continue;
 77+	    if (((*fp & F_PASS) || ch == DOOR) && 
 78+		 ((pfl & F_PASS) || pch == DOOR))
 79+	    {
 80+		if (Hero.x != x && Hero.y != y &&
 81+		    !step_ok(chat(y, Hero.x)) && !step_ok(chat(Hero.y, x)))
 82+			continue;
 83+	    }
 84+
 85+	    if ((tp = pp->p_monst) == NULL)
 86+		ch = trip_ch(y, x, ch);
 87+	    else
 88+		if (on(Player, SEEMONST) && on(*tp, ISINVIS))
 89+		{
 90+		    if (Door_stop && !Firstmove)
 91+			Running = FALSE;
 92+		    continue;
 93+		}
 94+		else
 95+		{
 96+		    if (wakeup)
 97+			wake_monster(y, x);
 98+		    if (see_monst(tp))
 99+			if (on(Player, ISHALU))
100+			    ch = rnd(26) + 'A';
101+			else
102+			    ch = tp->t_disguise;
103+		}
104+	    if (on(Player, ISBLIND) && (y != Hero.y || x != Hero.x))
105+		continue;
106+
107+	    move(y, x);
108+
109+	    if ((Proom->r_flags & ISDARK) && !See_floor && ch == FLOOR)
110+		ch = ' ';
111+
112+	    if (tp != NULL || ch != inch())
113+		addch(ch);
114+
115+	    if (Door_stop && !Firstmove && Running)
116+	    {
117+		switch (Runch)
118+		{
119+		    when 'h':
120+			if (x == ex)
121+			    continue;
122+		    when 'j':
123+			if (y == sy)
124+			    continue;
125+		    when 'k':
126+			if (y == ey)
127+			    continue;
128+		    when 'l':
129+			if (x == sx)
130+			    continue;
131+		    when 'y':
132+			if ((y + x) - sumhero >= 1)
133+			    continue;
134+		    when 'u':
135+			if ((y - x) - diffhero >= 1)
136+			    continue;
137+		    when 'n':
138+			if ((y + x) - sumhero <= -1)
139+			    continue;
140+		    when 'b':
141+			if ((y - x) - diffhero <= -1)
142+			    continue;
143+		}
144+		switch (ch)
145+		{
146+		    case DOOR:
147+			if (x == Hero.x || y == Hero.y)
148+			    Running = FALSE;
149+			break;
150+		    case PASSAGE:
151+			if (x == Hero.x || y == Hero.y)
152+			    passcount++;
153+			break;
154+		    case FLOOR:
155+		    case '|':
156+		    case '-':
157+		    case ' ':
158+			break;
159+		    default:
160+			Running = FALSE;
161+			break;
162+		}
163+	    }
164+	}
165+    if (Door_stop && !Firstmove && passcount > 1)
166+	Running = FALSE;
167+    if (!Running || !Jump)
168+	mvaddch(Hero.y, Hero.x, PLAYER);
169+# ifdef DEBUG
170+    done = FALSE;
171+# endif DEBUG
172+}
173+
174+/*
175+ * trip_ch:
176+ *	Return the character appropriate for this space, taking into
177+ *	account whether or not the player is tripping.
178+ */
179+int
180+trip_ch(int y, int x, char ch)
181+{
182+    if (on(Player, ISHALU) && After)
183+	switch (ch)
184+	{
185+	    case FLOOR:
186+	    case ' ':
187+	    case PASSAGE:
188+	    case '-':
189+	    case '|':
190+	    case DOOR:
191+	    case TRAP:
192+		break;
193+	    default:
194+		if (y != Stairs.y || x != Stairs.x || !Seenstairs)
195+		    ch = rnd_thing();
196+		break;
197+	}
198+    return ch;
199+}
200+
201+/*
202+ * erase_lamp:
203+ *	Erase the area shown by a lamp in a dark room.
204+ */
205+void
206+erase_lamp(coord *pos, struct room *rp)
207+{
208+    int y, x, ey, sy, ex;
209+
210+    if (!(See_floor && (rp->r_flags & (ISGONE|ISDARK)) == ISDARK
211+	&& !on(Player,ISBLIND)))
212+	    return;
213+
214+    ey = pos->y + 1;
215+    ex = pos->x + 1;
216+    sy = pos->y - 1;
217+    for (x = pos->x - 1; x <= ex; x++)
218+	for (y = sy; y <= ey; y++)
219+	{
220+	    if (y == Hero.y && x == Hero.x)
221+		continue;
222+	    move(y, x);
223+	    if (inch() == FLOOR)
224+		addch(' ');
225+	}
226+}
227+
228+/*
229+ * show_floor:
230+ *	Should we show the floor in her room at this time?
231+ */
232+bool
233+show_floor(void)
234+{
235+    if ((Proom->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(Player, ISBLIND))
236+	return See_floor;
237+    else
238+	return TRUE;
239+}
240+
241+/*
242+ * find_obj:
243+ *	Find the unclaimed object at y, x
244+ */
245+THING *
246+find_obj(int y, int x)
247+{
248+    THING *obj;
249+
250+    for (obj = Lvl_obj; obj != NULL; obj = next(obj))
251+    {
252+	if (obj->o_pos.y == y && obj->o_pos.x == x)
253+		return obj;
254+    }
255+#ifdef MASTER
256+    msg(sprintf(Prbuf, "Non-object %d,%d", y, x));
257+    return NULL;
258+#else
259+    /* NOTREACHED */
260+#endif
261+}
262+
263+/*
264+ * eat:
265+ *	She wants to eat something, so let her try
266+ */
267+void
268+eat(void)
269+{
270+    THING *obj;
271+
272+    if ((obj = get_item("eat", FOOD)) == NULL)
273+	return;
274+    if (obj->o_type != FOOD)
275+    {
276+	if (!Terse)
277+	    msg("ugh, you would get ill if you ate that");
278+	else
279+	    msg("that's Inedible!");
280+	return;
281+    }
282+    if (Food_left < 0)
283+	Food_left = 0;
284+    if ((Food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE)
285+	Food_left = STOMACHSIZE;
286+    Hungry_state = 0;
287+    if (obj == Cur_weapon)
288+	Cur_weapon = NULL;
289+    leave_pack(obj, FALSE, FALSE);
290+    if (obj->o_which == 1)
291+	msg("my, that was a yummy %s", Fruit);
292+    else
293+	if (rnd(100) > 70)
294+	{
295+	    Pstats.s_exp++;
296+	    msg("%s, this food tastes awful", choose_str("bummer", "yuk"));
297+	    check_level();
298+	}
299+	else
300+	    msg("%s, that tasted good", choose_str("oh, wow", "yum"));
301+}
302+
303+/*
304+ * check_level:
305+ *	Check to see if the guy has gone up a level.
306+ */
307+void
308+check_level(void)
309+{
310+    int i, add, olevel;
311+
312+    for (i = 0; E_levels[i] != 0; i++)
313+	if (E_levels[i] > Pstats.s_exp)
314+	    break;
315+    i++;
316+    olevel = Pstats.s_lvl;
317+    Pstats.s_lvl = i;
318+    if (i > olevel)
319+    {
320+	add = roll(i - olevel, 10);
321+	Max_hp += add;
322+	Pstats.s_hpt += add;
323+	msg("welcome to level %d", i);
324+    }
325+}
326+
327+/*
328+ * chg_str:
329+ *	Used to modify the playes strength.  It keeps track of the
330+ *	highest it has been, just in case
331+ */
332+void
333+chg_str(int amt)
334+{
335+    auto str_t comp;
336+
337+    if (amt == 0)
338+	return;
339+    add_str(&Pstats.s_str, amt);
340+    comp = Pstats.s_str;
341+    if (ISRING(LEFT, R_ADDSTR))
342+	add_str(&comp, -Cur_ring[LEFT]->o_arm);
343+    if (ISRING(RIGHT, R_ADDSTR))
344+	add_str(&comp, -Cur_ring[RIGHT]->o_arm);
345+    if (comp > Max_stats.s_str)
346+	Max_stats.s_str = comp;
347+}
348+
349+/*
350+ * add_str:
351+ *	Perform the actual add, checking upper and lower bound limits
352+ */
353+add_str(str_t *sp, int amt)
354+{
355+    if ((*sp += amt) < 3)
356+	*sp = 3;
357+    else if (*sp > 31)
358+	*sp = 31;
359+}
360+
361+/*
362+ * add_haste:
363+ *	Add a haste to the player
364+ */
365+bool
366+add_haste(bool potion)
367+{
368+    if (on(Player, ISHASTE))
369+    {
370+	No_command += rnd(8);
371+	Player.t_flags &= ~(ISRUN|ISHASTE);
372+	extinguish(nohaste);
373+	msg("you faint from exhaustion");
374+	return FALSE;
375+    }
376+    else
377+    {
378+	Player.t_flags |= ISHASTE;
379+	if (potion)
380+	    fuse(nohaste, 0, rnd(4)+4, AFTER);
381+	return TRUE;
382+    }
383+}
384+
385+/*
386+ * aggravate:
387+ *	Aggravate all the monsters on this level
388+ */
389+void
390+aggravate(void)
391+{
392+    THING *mp;
393+
394+    for (mp = Mlist; mp != NULL; mp = next(mp))
395+	runto(&mp->t_pos);
396+}
397+
398+/*
399+ * vowelstr:
400+ *      For printfs: if string starts with a vowel, return "n" for an
401+ *	"an".
402+ */
403+char *
404+vowelstr(char *str)
405+{
406+    switch (*str)
407+    {
408+	case 'a': case 'A':
409+	case 'e': case 'E':
410+	case 'i': case 'I':
411+	case 'o': case 'O':
412+	case 'u': case 'U':
413+	    return "n";
414+	default:
415+	    return "";
416+    }
417+}
418+
419+/* 
420+ * is_current:
421+ *	See if the object is one of the currently used items
422+ */
423+bool
424+is_current(THING *obj)
425+{
426+    if (obj == NULL)
427+	return FALSE;
428+    if (obj == Cur_armor || obj == Cur_weapon || obj == Cur_ring[LEFT]
429+	|| obj == Cur_ring[RIGHT])
430+    {
431+	if (!Terse)
432+	    addmsg("That's already ");
433+	msg("in use");
434+	return TRUE;
435+    }
436+    return FALSE;
437+}
438+
439+/*
440+ * get_dir:
441+ *      Set up the direction co_ordinate for use in varios "prefix"
442+ *	commands
443+ */
444+bool
445+get_dir(void)
446+{
447+    char *prompt;
448+    bool gotit;
449+    static coord last_delt;
450+
451+    if (Again && Last_dir != '\0')
452+    {
453+	Delta.y = last_delt.y;
454+	Delta.x = last_delt.x;
455+	Dir_ch = Last_dir;
456+    }
457+    else
458+    {
459+	if (!Terse)
460+	    msg(prompt = "which direction? ");
461+	else
462+	    prompt = "direction: ";
463+	do
464+	{
465+	    gotit = TRUE;
466+	    switch (Dir_ch = readchar())
467+	    {
468+		when 'h': case'H': Delta.y =  0; Delta.x = -1;
469+		when 'j': case'J': Delta.y =  1; Delta.x =  0;
470+		when 'k': case'K': Delta.y = -1; Delta.x =  0;
471+		when 'l': case'L': Delta.y =  0; Delta.x =  1;
472+		when 'y': case'Y': Delta.y = -1; Delta.x = -1;
473+		when 'u': case'U': Delta.y = -1; Delta.x =  1;
474+		when 'b': case'B': Delta.y =  1; Delta.x = -1;
475+		when 'n': case'N': Delta.y =  1; Delta.x =  1;
476+		when ESCAPE: Last_dir = '\0'; reset_last(); return FALSE;
477+		otherwise:
478+		    Mpos = 0;
479+		    msg(prompt);
480+		    gotit = FALSE;
481+	    }
482+	} until (gotit);
483+	if (isupper(Dir_ch))
484+	    Dir_ch = tolower(Dir_ch);
485+	Last_dir = Dir_ch;
486+	last_delt.y = Delta.y;
487+	last_delt.x = Delta.x;
488+    }
489+    if (on(Player, ISHUH) && rnd(5) == 0)
490+	do
491+	{
492+	    Delta.y = rnd(3) - 1;
493+	    Delta.x = rnd(3) - 1;
494+	} while (Delta.y == 0 && Delta.x == 0);
495+    Mpos = 0;
496+    return TRUE;
497+}
498+
499+/*
500+ * sign:
501+ *	Return the sign of the number
502+ */
503+int
504+sign(int nm)
505+{
506+    if (nm < 0)
507+	return -1;
508+    else
509+	return (nm > 0);
510+}
511+
512+/*
513+ * spread:
514+ *	Give a spread around a given number (+/- 20%)
515+ */
516+int
517+spread(int nm)
518+{
519+    return nm - nm / 20 + rnd(nm / 10);
520+}
521+
522+/*
523+ * call_it:
524+ *	Call an object something after use.
525+ */
526+void
527+call_it(struct obj_info *info)
528+{
529+    if (info->oi_know)
530+    {
531+	if (info->oi_guess)
532+	{
533+	    free(info->oi_guess);
534+	    info->oi_guess = NULL;
535+	}
536+    }
537+    else if (!info->oi_guess)
538+    {
539+	msg(Terse ? "call it: " : "what do you want to call it? ");
540+	if (get_str(Prbuf, stdscr) == NORM)
541+	{
542+	    if (info->oi_guess != NULL)
543+		free(info->oi_guess);
544+	    info->oi_guess = malloc((unsigned int) strlen(Prbuf) + 1);
545+	    strcpy(info->oi_guess, Prbuf);
546+	}
547+    }
548+}
549+
550+/*
551+ * rnd_thing:
552+ *	Pick a random thing appropriate for this level
553+ */
554+int
555+rnd_thing(void)
556+{
557+    int i;
558+    static char thing_list[] = {
559+	POTION, SCROLL, RING, STICK, FOOD, WEAPON, ARMOR, STAIRS, GOLD, AMULET
560+    };
561+
562+    if (Level >= AMULETLEVEL)
563+        i = rnd(sizeof thing_list / sizeof (char));
564+    else
565+        i = rnd(sizeof thing_list / sizeof (char) - 1);
566+    return thing_list[i];
567+}
568+
569+/*
570+ str str:
571+ *	Choose the first or second string depending on whether it the
572+ *	player is tripping
573+ */
574+char *
575+choose_str(char *ts, char *ns)
576+{
577+	return (on(Player, ISHALU) ? ts : ns);
578+}
A error.c
+102, -0
  1@@ -0,0 +1,102 @@
  2+/*
  3+ * Functions for dealing with linked lists of goodies
  4+ *
  5+ * @(#)error.c	4.12 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include "netprot.h"
 10+
 11+#ifdef MASTER
 12+static int Total = 0;			/* Total dynamic memory bytes */
 13+#endif
 14+
 15+/*
 16+ * detach:
 17+ *	Takes an item out of whatever linked list it might be in
 18+ */
 19+void
 20+_detach(THING **list, THING *item)
 21+{
 22+    if (*list == item)
 23+	*list = next(item);
 24+    if (prev(item) != NULL)
 25+	item->l_prev->l_next = next(item);
 26+    if (next(item) != NULL)
 27+	item->l_next->l_prev = prev(item);
 28+    item->l_next = NULL;
 29+    item->l_prev = NULL;
 30+}
 31+
 32+/*
 33+ * _attach:
 34+ *	add an item to the head of a list
 35+ */
 36+void
 37+_attach(THING **list, THING *item)
 38+{
 39+    if (*list != NULL)
 40+    {
 41+	item->l_next = *list;
 42+	(*list)->l_prev = item;
 43+	item->l_prev = NULL;
 44+    }
 45+    else
 46+    {
 47+	item->l_next = NULL;
 48+	item->l_prev = NULL;
 49+    }
 50+    *list = item;
 51+}
 52+
 53+/*
 54+ * _free_list:
 55+ *	Throw the whole blamed thing away
 56+ */
 57+void
 58+_free_list(THING **ptr)
 59+{
 60+    THING *item;
 61+
 62+    while (*ptr != NULL)
 63+    {
 64+	item = *ptr;
 65+	*ptr = next(item);
 66+	discard(item);
 67+    }
 68+}
 69+
 70+/*
 71+ * discard:
 72+ *	Free up an item
 73+ */
 74+void
 75+discard(THING *item)
 76+{
 77+#ifdef MASTER
 78+    Total--;
 79+#endif
 80+    free((char *) item);
 81+}
 82+
 83+/*
 84+ * new_item
 85+ *	Get a new item with a specified size
 86+ */
 87+THING *
 88+new_item(void)
 89+{
 90+    THING *item;
 91+
 92+#ifdef MASTER
 93+    if ((item = calloc(1, sizeof *item)) == NULL)
 94+	msg("ran out of memory after %d items", Total);
 95+    else
 96+	Total++;
 97+#else
 98+    item = calloc(1, sizeof *item);
 99+#endif
100+    item->l_next = NULL;
101+    item->l_prev = NULL;
102+    return item;
103+}
A ether.c
+365, -0
  1@@ -0,0 +1,365 @@
  2+/*
  3+ * Function(s) for dealing with potions
  4+ *
  5+ * @(#)ether.c	4.46 (Berkeley) 06/07/83
  6+ */
  7+
  8+#include <curses.h>
  9+#include <ctype.h>
 10+#include "netprot.h"
 11+
 12+typedef struct
 13+{
 14+    int pa_flags;
 15+    void (*pa_daemon)(void);
 16+    int pa_time;
 17+    char *pa_high, *pa_straight;
 18+} PACT;
 19+
 20+static PACT P_actions[] =
 21+{
 22+	{ ISHUH,	unconfuse,	HUHDURATION,	/* P_CONFUSE */
 23+		"what a tripy feeling!",
 24+		"wait, what's going on here. Huh? What? Who?" },
 25+	{ ISHALU,	come_down,	SEEDURATION,	/* P_LSD */
 26+		"Oh, wow!  Everything seems so cosmic!",
 27+		"Oh, wow!  Everything seems so cosmic!" },
 28+	{ 0,		NULL,	0 },			/* P_POISON */
 29+	{ 0,		NULL,	0 },			/* P_STRENGTH */
 30+	{ CANSEE,	unsee,	SEEDURATION,		/* P_SEEINVIS */
 31+		Prbuf,
 32+		Prbuf },
 33+	{ 0,		NULL,	0 },			/* P_HEALING */
 34+	{ 0,		NULL,	0 },			/* P_MFIND */
 35+	{ 0,		NULL,	0 },			/* P_TFIND  */
 36+	{ 0,		NULL,	0 },			/* P_RAISE */
 37+	{ 0,		NULL,	0 },			/* P_XHEAL */
 38+	{ 0,		NULL,	0 },			/* P_HASTE */
 39+	{ 0,		NULL,	0 },			/* P_RESTORE */
 40+	{ ISBLIND,	sight,	SEEDURATION,		/* P_BLIND */
 41+		"oh, bummer!  Everything is dark!  Help!",
 42+		"a cloak of darkness falls around you" },
 43+	{ ISLEVIT,	land,	HEALTIME,		/* P_LEVIT */
 44+		"oh, wow!  You're floating in the air!",
 45+		"you start to float in the air" }
 46+};
 47+
 48+/*
 49+ * quaff:
 50+ *	Quaff a potion from the pack
 51+ */
 52+void
 53+quaff(void)
 54+{
 55+    THING *obj, *tp, *mp;
 56+    bool discardit = FALSE;
 57+    bool show, trip;
 58+
 59+    obj = get_item("quaff", POTION);
 60+    /*
 61+     * Make certain that it is somethings that we want to drink
 62+     */
 63+    if (obj == NULL)
 64+	return;
 65+    if (obj->o_type != POTION)
 66+    {
 67+	if (!Terse)
 68+	    msg("yuk! Why would you want to drink that?");
 69+	else
 70+	    msg("that's undrinkable");
 71+	return;
 72+    }
 73+    if (obj == Cur_weapon)
 74+	Cur_weapon = NULL;
 75+
 76+    /*
 77+     * Calculate the effect it has on the poor guy.
 78+     */
 79+    trip = on(Player, ISHALU);
 80+    discardit = (obj->o_count == 1);
 81+    leave_pack(obj, FALSE, FALSE);
 82+    switch (obj->o_which)
 83+    {
 84+	when P_CONFUSE:
 85+	    do_pot(P_CONFUSE, !trip);
 86+	when P_POISON:
 87+	    Pot_info[P_POISON].oi_know = TRUE;
 88+	    if (ISWEARING(R_SUSTSTR))
 89+		msg("you feel momentarily sick");
 90+	    else
 91+	    {
 92+		chg_str(-(rnd(3) + 1));
 93+		msg("you feel very sick now");
 94+		come_down();
 95+	    }
 96+	when P_HEALING:
 97+	    Pot_info[P_HEALING].oi_know = TRUE;
 98+	    if ((Pstats.s_hpt += roll(Pstats.s_lvl, 4)) > Max_hp)
 99+		Pstats.s_hpt = ++Max_hp;
100+	    sight();
101+	    msg("you begin to feel better");
102+	when P_STRENGTH:
103+	    Pot_info[P_STRENGTH].oi_know = TRUE;
104+	    chg_str(1);
105+	    msg("you feel stronger, now.  What bulging muscles!");
106+	when P_MFIND:
107+	    Player.t_flags |= SEEMONST;
108+	    fuse(turn_see, TRUE, HUHDURATION, AFTER);
109+	    if (!turn_see(FALSE))
110+		msg("you have a %s feeling for a moment, then it passes",
111+		    choose_str("normal", "strange"));
112+	when P_TFIND:
113+	    /*
114+	     * Potion of magic detection.  Show the potions and scrolls
115+	     */
116+	    show = FALSE;
117+	    if (Lvl_obj != NULL)
118+	    {
119+		wclear(Hw);
120+		for (tp = Lvl_obj; tp != NULL; tp = next(tp))
121+		{
122+		    if (is_magic(tp))
123+		    {
124+			show = TRUE;
125+			wmove(Hw, tp->o_pos.y, tp->o_pos.x);
126+			waddch(Hw, MAGIC);
127+			Pot_info[P_TFIND].oi_know = TRUE;
128+		    }
129+		}
130+		for (mp = Mlist; mp != NULL; mp = next(mp))
131+		{
132+		    for (tp = mp->t_pack; tp != NULL; tp = next(tp))
133+		    {
134+			if (is_magic(tp))
135+			{
136+			    show = TRUE;
137+			    wmove(Hw, mp->t_pos.y, mp->t_pos.x);
138+			    waddch(Hw, MAGIC);
139+			}
140+		    }
141+		}
142+	    }
143+	    if (show)
144+	    {
145+		Pot_info[P_TFIND].oi_know = TRUE;
146+		show_win("You sense the presence of magic on this level.--More--");
147+	    }
148+	    else
149+		msg("you have a %s feeling for a moment, then it passes",
150+		    choose_str("normal", "strange"));
151+	when P_LSD:
152+	    if (!trip)
153+	    {
154+		if (on(Player, SEEMONST))
155+		    turn_see(FALSE);
156+		start_daemon(visuals, 0, BEFORE);
157+		Seenstairs = seen_stairs();
158+	    }
159+	    do_pot(P_LSD, TRUE);
160+	when P_SEEINVIS:
161+	    sprintf(Prbuf, "this potion tastes like %s juice", Fruit);
162+	    show = on(Player, CANSEE);
163+	    do_pot(P_SEEINVIS, FALSE);
164+	    if (!show)
165+		invis_on();
166+	    sight();
167+	when P_RAISE:
168+	    Pot_info[P_RAISE].oi_know = TRUE;
169+	    msg("you suddenly feel much more skillful");
170+	    raise_level();
171+	when P_XHEAL:
172+	    Pot_info[P_XHEAL].oi_know = TRUE;
173+	    if ((Pstats.s_hpt += roll(Pstats.s_lvl, 8)) > Max_hp)
174+	    {
175+		if (Pstats.s_hpt > Max_hp + Pstats.s_lvl + 1)
176+		    ++Max_hp;
177+		Pstats.s_hpt = ++Max_hp;
178+	    }
179+	    sight();
180+	    come_down();
181+	    msg("you begin to feel much better");
182+	when P_HASTE:
183+	    Pot_info[P_HASTE].oi_know = TRUE;
184+	    After = FALSE;
185+	    if (add_haste(TRUE))
186+		msg("you feel yourself moving much faster");
187+	when P_RESTORE:
188+	    if (ISRING(LEFT, R_ADDSTR))
189+		add_str(&Pstats.s_str, -Cur_ring[LEFT]->o_arm);
190+	    if (ISRING(RIGHT, R_ADDSTR))
191+		add_str(&Pstats.s_str, -Cur_ring[RIGHT]->o_arm);
192+	    if (Pstats.s_str < Max_stats.s_str)
193+		Pstats.s_str = Max_stats.s_str;
194+	    if (ISRING(LEFT, R_ADDSTR))
195+		add_str(&Pstats.s_str, Cur_ring[LEFT]->o_arm);
196+	    if (ISRING(RIGHT, R_ADDSTR))
197+		add_str(&Pstats.s_str, Cur_ring[RIGHT]->o_arm);
198+	    msg("hey, this tastes great.  It make you feel warm all over");
199+	when P_BLIND:
200+	    do_pot(P_BLIND, TRUE);
201+	when P_LEVIT:
202+	    do_pot(P_LEVIT, TRUE);
203+#ifdef MASTER
204+	otherwise:
205+	    msg("what an odd tasting potion!");
206+	    return;
207+#endif
208+    }
209+    status();
210+    /*
211+     * Throw the item away
212+     */
213+
214+    call_it(&Pot_info[obj->o_which]);
215+
216+    if (discardit)
217+	discard(obj);
218+    return;
219+}
220+
221+/*
222+ * is_magic:
223+ *	Returns true if an object radiates magic
224+ */
225+bool
226+is_magic(THING *obj)
227+{
228+    switch (obj->o_type)
229+    {
230+	case ARMOR:
231+	    return (obj->o_flags&ISPROT) || obj->o_arm != A_class[obj->o_which];
232+	case WEAPON:
233+	    return obj->o_hplus != 0 || obj->o_dplus != 0;
234+	case POTION:
235+	case SCROLL:
236+	case STICK:
237+	case RING:
238+	case AMULET:
239+	    return TRUE;
240+    }
241+    return FALSE;
242+}
243+
244+/*
245+ * invis_on:
246+ *	Turn on the ability to see invisible
247+ */
248+void
249+invis_on(void)
250+{
251+    THING *mp;
252+
253+    Player.t_flags |= CANSEE;
254+    for (mp = Mlist; mp != NULL; mp = next(mp))
255+	if (on(*mp, ISINVIS) && see_monst(mp) && !on(Player, ISHALU))
256+	    mvaddch(mp->t_pos.y, mp->t_pos.x, mp->t_disguise);
257+}
258+
259+/*
260+ * turn_see:
261+ *	Put on or off seeing monsters on this level
262+ */
263+bool
264+turn_see(bool turn_off)
265+{
266+    THING *mp;
267+    bool can_see, add_new;
268+
269+    add_new = FALSE;
270+    for (mp = Mlist; mp != NULL; mp = next(mp))
271+    {
272+	move(mp->t_pos.y, mp->t_pos.x);
273+	can_see = see_monst(mp);
274+	if (turn_off)
275+	{
276+	    if (!can_see)
277+		addch(mp->t_oldch);
278+	}
279+	else
280+	{
281+	    if (!can_see)
282+		standout();
283+	    if (!on(Player, ISHALU))
284+		addch(mp->t_type);
285+	    else
286+		addch(rnd(26) + 'A');
287+	    if (!can_see)
288+	    {
289+		standend();
290+		add_new++;
291+	    }
292+	}
293+    }
294+    if (turn_off)
295+	Player.t_flags &= ~SEEMONST;
296+    else
297+	Player.t_flags |= SEEMONST;
298+    return add_new;
299+}
300+
301+/*
302+ * seen_stairs:
303+ *	Return TRUE if the player has seen the stairs
304+ */
305+bool
306+seen_stairs(void)
307+{
308+    THING	*tp;
309+
310+    move(Stairs.y, Stairs.x);
311+    if (inch() == STAIRS)			/* it's on the map */
312+	return TRUE;
313+    if (ce(Hero, Stairs))			/* It's under him */
314+	return TRUE;
315+
316+    /*
317+     * if a monster is on the stairs, this gets hairy
318+     */
319+    if ((tp = moat(Stairs.y, Stairs.x)) != NULL)
320+    {
321+	if (see_monst(tp) && on(*tp, ISRUN))	/* if it's visible and awake */
322+	    return TRUE;			/* it must have moved there */
323+
324+	if (on(Player, SEEMONST)		/* if she can detect monster */
325+	    && tp->t_oldch == STAIRS)		/* and there once were stairs */
326+		return TRUE;			/* it must have moved there */
327+    }
328+    return FALSE;
329+}
330+
331+/*
332+ * raise_level:
333+ *	The guy just magically went up a level.
334+ */
335+void
336+raise_level(void)
337+{
338+    Pstats.s_exp = E_levels[Pstats.s_lvl-1] + 1L;
339+    check_level();
340+}
341+
342+/*
343+ * do_pot:
344+ *	Do a potion with standard setup.  This means it uses a fuse and
345+ *	turns on a flag
346+ */
347+void
348+do_pot(int type, bool knowit)
349+{
350+    PACT *pp;
351+    int t;
352+
353+    pp = &P_actions[type];
354+    if (!Pot_info[type].oi_know)
355+	Pot_info[type].oi_know = knowit;
356+    t = spread(pp->pa_time);
357+    if (!on(Player, pp->pa_flags))
358+    {
359+	Player.t_flags |= pp->pa_flags;
360+	fuse(pp->pa_daemon, 0, t, AFTER);
361+	look(FALSE);
362+    }
363+    else
364+	lengthen(pp->pa_daemon, t);
365+    msg(choose_str(pp->pa_high, pp->pa_straight));
366+}
A find.c
+480, -0
  1@@ -0,0 +1,480 @@
  2+/*
  3+ * Various installation dependent routines
  4+ *
  5+ * @(#)find.c	4.37 (Berkeley) 05/23/83
  6+ */
  7+
  8+/*
  9+ * The various tuneable defines are:
 10+ *
 11+ *	SCOREFILE	Where/if the score file should live.
 12+ *	ALLSCORES	Score file is top ten scores, not top ten
 13+ *			players.  This is only useful when only a few
 14+ *			people will be playing; otherwise the score file
 15+ *			gets hogged by just a few people.
 16+ *	NUMSCORES	Number of scores in the score file (default 10).
 17+ *	NUMNAME		String version of NUMSCORES (first character
 18+ *			should be capitalized) (default "Ten").
 19+ *	MAXLOAD		What (if any) the maximum load average should be
 20+ *			when people are playing.  Since it is divided
 21+ *			by 10, to specify a load limit of 4.0, MAXLOAD
 22+ *			should be "40".	 If defined, then
 23+ *		LOADAV		Should it use it's own routine to get
 24+ *				the load average?
 25+ *		NAMELIST	If so, where does the system namelist
 26+ *				hide?
 27+ *	MAXUSERS	What (if any) the maximum user count should be
 28+ *			when people are playing.  If defined, then
 29+ *		UCOUNT		Should it use it's own routine to count
 30+ *				users?
 31+ *		UTMP		If so, where does the user list hide?
 32+ *	CHECKTIME	How often/if it should check during the game
 33+ *			for high load average.
 34+ */
 35+
 36+#include <curses.h>
 37+#include "network.h"
 38+#include <signal.h>
 39+#include <sys/types.h>
 40+#include <sys/stat.h>
 41+#include <sys/ioctl.h>
 42+
 43+#include <fcntl.h>
 44+
 45+#ifdef SCOREFILE
 46+
 47+static char *Lockfile = "/tmp/.fredlock";
 48+
 49+# ifndef NUMSCORES
 50+#	define	NUMSCORES	10
 51+#	define	NUMNAME		"Ten"
 52+# endif
 53+
 54+unsigned int numscores = NUMSCORES;
 55+char *Numname = NUMNAME;
 56+
 57+# ifdef ALLSCORES
 58+bool Allscore = TRUE;
 59+# else  ALLSCORES
 60+bool Allscore = FALSE;
 61+# endif ALLSCORES
 62+
 63+#endif SCOREFILE
 64+
 65+#ifdef CHECKTIME
 66+static int Num_checks;		/* times we've gone over in checkout() */
 67+#endif CHECKTIME
 68+
 69+/*
 70+ * init_check:
 71+ *	Check out too see if it is proper to play the game now
 72+ */
 73+void
 74+init_check(void)
 75+{
 76+#if defined(MAXLOAD) || defined(MAXUSERS)
 77+    if (too_much())
 78+    {
 79+	printf("Sorry, %s, but the system is too loaded now.\n", Whoami);
 80+	printf("Try again later.  Meanwhile, why not enjoy a%s %s?\n",
 81+	    vowelstr(Fruit), Fruit);
 82+	if (author())
 83+	    printf("However, since you're a good guy, it's up to you\n");
 84+	else
 85+	    exit(1);
 86+    }
 87+#endif
 88+}
 89+
 90+/*
 91+ * open_score:
 92+ *	Open up the score file for future use, and then
 93+ *	setuid(getuid()) in case we are running setuid.
 94+ */
 95+void
 96+open_score(void)
 97+{
 98+#ifdef SCOREFILE
 99+    Fd = open(SCOREFILE, O_RDWR);
100+#else
101+    Fd = -1;
102+#endif
103+    setuid(getuid());
104+    setgid(getgid());
105+}
106+
107+/*
108+ * setup:
109+ *	Get starting setup for all games
110+ */
111+void
112+setup(void)
113+{
114+#ifdef CHECKTIME
115+    int  checkout();
116+#endif
117+
118+    signal(SIGHUP, auto_save);
119+#ifndef DUMP
120+    signal(SIGILL, auto_save);
121+    signal(SIGTRAP, auto_save);
122+    signal(SIGIOT, auto_save);
123+    signal(SIGEMT, auto_save);
124+    signal(SIGFPE, auto_save);
125+    signal(SIGBUS, auto_save);
126+    signal(SIGSEGV, auto_save);
127+    signal(SIGSYS, auto_save);
128+    signal(SIGTERM, auto_save);
129+#endif
130+
131+    signal(SIGINT, quit);
132+#ifndef DUMP
133+    signal(SIGQUIT, endit);
134+#endif
135+#ifdef CHECKTIME
136+    signal(SIGALRM, checkout);
137+    alarm(CHECKTIME * 60);
138+    Num_checks = 0;
139+#endif
140+    crmode();				/* Cbreak mode */
141+    noecho();				/* Echo off */
142+#ifdef TIOCGLTC
143+    getltchars();			/* get the local tty chars */
144+#endif
145+}
146+
147+/*
148+ * getltchars:
149+ *	Get the local tty chars for later use
150+ */
151+void
152+getltchars(void)
153+{
154+#ifdef TIOCGLTC
155+    ioctl(1, TIOCGLTC, &Ltc);
156+    Got_ltc = TRUE;
157+    Orig_dsusp = Ltc.t_dsuspc;
158+    Ltc.t_dsuspc = Ltc.t_suspc;
159+    ioctl(1, TIOCSLTC, &Ltc);
160+#endif
161+}
162+
163+/*
164+ * resetltchars:
165+ *	Reset the local tty chars to original values.
166+ */
167+void
168+resetltchars(void)
169+{
170+#ifdef TIOCGLTC
171+    if (Got_ltc) {
172+	Ltc.t_dsuspc = Orig_dsusp;
173+	ioctl(1, TIOCSLTC, &Ltc);
174+    }
175+#endif
176+}
177+
178+/*
179+ * playltchars:
180+ *	Set local tty chars to the values we use when playing.
181+ */
182+void
183+playltchars(void)
184+{
185+#ifdef TIOCGLTC
186+    if (Got_ltc) {
187+	Ltc.t_dsuspc = Ltc.t_suspc;
188+	ioctl(1, TIOCSLTC, &Ltc);
189+    }
190+#endif
191+}
192+
193+/*
194+ * start_score:
195+ *	Start the scoring sequence
196+ */
197+void
198+start_score(void)
199+{
200+#ifdef CHECKTIME
201+    signal(SIGALRM, SIG_IGN);
202+#endif
203+}
204+
205+/*
206+ * is_symlink:
207+ *	See if the file has a symbolic link
208+ */
209+bool
210+is_symlink(char *sp)
211+{
212+#ifdef S_IFLNK
213+    struct stat sbuf2;
214+
215+    if (lstat(sp, &sbuf2) < 0)
216+	return FALSE;
217+    else
218+	return ((sbuf2.st_mode & S_IFMT) != S_IFREG);
219+#else
220+    return FALSE;
221+#endif
222+}
223+
224+#if defined(MAXLOAD) || defined(MAXUSERS)
225+/*
226+ * too_much:
227+ *	See if the system is being used too much for this game
228+ */
229+bool
230+too_much(void)
231+{
232+#ifdef MAXLOAD
233+    double avec[3];
234+#else
235+    int cnt;
236+#endif
237+
238+#ifdef MAXLOAD
239+    loadav(avec);
240+    if (avec[1] > (MAXLOAD / 10.0))
241+	return TRUE;
242+#endif
243+#ifdef MAXUSERS
244+    if (ucount() > MAXUSERS)
245+	return TRUE;
246+#endif
247+    return FALSE;
248+}
249+
250+/*
251+ * author:
252+ *	See if a user is an author of the program
253+ */
254+bool
255+author(void)
256+{
257+#ifdef MASTER
258+    if (Wizard)
259+	return TRUE;
260+#endif
261+    switch (getuid())
262+    {
263+	case -1:
264+	    return TRUE;
265+	default:
266+	    return FALSE;
267+    }
268+}
269+#endif
270+
271+#ifdef CHECKTIME
272+/*
273+ * checkout:
274+ *	Check each CHECKTIME seconds to see if the load is too high
275+ */
276+void
277+checkout(int sig)
278+{
279+    static char *msgs[] = {
280+	"The load is too high to be playing.  Please leave in %0.1f minutes",
281+	"Please save your game.  You have %0.1f minutes",
282+	"Last warning.  You have %0.1f minutes to leave",
283+    };
284+    int checktime;
285+
286+    signal(SIGALRM, checkout);
287+    if (too_much())
288+    {
289+	if (author())
290+	{
291+	    Num_checks = 1;
292+	    chmsg("The load is rather high, O exaulted one");
293+	}
294+	else if (Num_checks++ == 3)
295+	    fatal("Sorry.  You took too long.  You are dead\n");
296+	checktime = (CHECKTIME * 60) / Num_checks;
297+	alarm(checktime);
298+	chmsg(msgs[Num_checks - 1], ((double) checktime / 60.0));
299+    }
300+    else
301+    {
302+	if (Num_checks)
303+	{
304+	    Num_checks = 0;
305+	    chmsg("The load has dropped back down.  You have a reprieve");
306+	}
307+	alarm(CHECKTIME * 60);
308+    }
309+}
310+
311+/*
312+ * chmsg:
313+ *	checkout()'s version of msg.  If we are in the middle of a
314+ *	shell, do a printf instead of a msg to avoid the refresh.
315+ */
316+/* VARARGS1 */
317+void
318+chmsg(char *fmt, int arg)
319+{
320+    if (!In_shell)
321+	msg(fmt, arg);
322+    else
323+    {
324+	printf(fmt, arg);
325+	putchar('\n');
326+	fflush(stdout);
327+    }
328+}
329+#endif
330+
331+#ifdef LOADAV
332+/*
333+ * loadav:
334+ *	Looking up load average in core (for system where the loadav()
335+ *	system call isn't defined
336+ */
337+
338+#include <nlist.h>
339+
340+struct nlist avenrun = {
341+    "_avenrun"
342+};
343+
344+void
345+loadav(double *avg)
346+{
347+    int kmem;
348+
349+    if ((kmem = open("/dev/kmem", 0)) < 0)
350+	goto bad;
351+    nlist(NAMELIST, &avenrun);
352+    if (avenrun.n_type == 0)
353+    {
354+	close(kmem);
355+bad:
356+	avg[0] = 0.0;
357+	avg[1] = 0.0;
358+	avg[2] = 0.0;
359+	return;
360+    }
361+
362+    lseek(kmem, (long) avenrun.n_value, 0);
363+    read(kmem, (char *) avg, 3 * sizeof (double));
364+    close(kmem);
365+}
366+#endif
367+
368+#ifdef UCOUNT
369+/*
370+ * ucount:
371+ *	Count number of users on the system
372+ */
373+#include <utmp.h>
374+
375+struct utmp buf;
376+
377+int
378+ucount(void)
379+{
380+    struct utmp *up;
381+    FILE *utmp;
382+    int count;
383+
384+    if ((utmp = fopen(UTMP, "r")) == NULL)
385+	return 0;
386+
387+    up = &buf;
388+    count = 0;
389+
390+    while (fread(up, 1, sizeof (*up), utmp) > 0)
391+	if (buf.ut_name[0] != '\0')
392+	    count++;
393+    fclose(utmp);
394+    return count;
395+}
396+#endif
397+
398+/*
399+ * lock_sc:
400+ *	lock the score file.  If it takes too long, ask the user if
401+ *	they care to wait.  Return TRUE if the lock is successful.
402+ */
403+bool
404+lock_sc(void)
405+{
406+#ifdef SCOREFILE
407+    int cnt;
408+    static struct stat sbuf;
409+    time_t time();
410+
411+over:
412+    close(8);	/* just in case there are no files left */
413+    if (creat(Lockfile, 0000) >= 0)
414+	return TRUE;
415+    for (cnt = 0; cnt < 5; cnt++)
416+    {
417+	sleep(1);
418+	if (creat(Lockfile, 0000) >= 0)
419+	    return TRUE;
420+    }
421+    if (stat(Lockfile, &sbuf) < 0)
422+    {
423+	creat(Lockfile, 0000);
424+	return TRUE;
425+    }
426+    if (time(NULL) - sbuf.st_mtime > 10)
427+    {
428+	if (unlink(Lockfile) < 0)
429+	    return FALSE;
430+	goto over;
431+    }
432+    else
433+    {
434+	printf("The score file is very busy.  Do you want to wait longer\n");
435+	printf("for it to become free so your score can get posted?\n");
436+	printf("If so, type \"y\"\n");
437+	fgets(Prbuf, MAXSTR, stdin);
438+	if (Prbuf[0] == 'y')
439+	    for (;;)
440+	    {
441+		if (creat(Lockfile, 0000) >= 0)
442+		    return TRUE;
443+		if (stat(Lockfile, &sbuf) < 0)
444+		{
445+		    creat(Lockfile, 0000);
446+		    return TRUE;
447+		}
448+		if (time(NULL) - sbuf.st_mtime > 10)
449+		{
450+		    if (unlink(Lockfile) < 0)
451+			return FALSE;
452+		}
453+		sleep(1);
454+	    }
455+	else
456+	    return FALSE;
457+    }
458+#endif
459+}
460+
461+/*
462+ * unlock_sc:
463+ *	Unlock the score file
464+ */
465+void
466+unlock_sc(void)
467+{
468+#ifdef SCOREFILE
469+    unlink(Lockfile);
470+#endif
471+}
472+
473+/*
474+ * flush_type:
475+ *	Flush typeahead for traps, etc.
476+ */
477+void
478+flush_type(void)
479+{
480+    crmode();
481+}
A handle.c
+220, -0
  1@@ -0,0 +1,220 @@
  2+#include <curses.h>
  3+#include "netprot.h"
  4+
  5+#define TREAS_ROOM 20	/* one chance in TREAS_ROOM for a treasure room */
  6+#define MAXTREAS 10	/* maximum number of treasures in a treasure room */
  7+#define MINTREAS 2	/* minimum number of treasures in a treasure room */
  8+
  9+/*
 10+ * new_level:
 11+ *	Dig and draw a new level
 12+ *
 13+ * @(#)handle.c	4.38 (Berkeley) 02/05/99
 14+ */
 15+void
 16+new_level(void)
 17+{
 18+    THING *tp;
 19+    PLACE *pp;
 20+    char *sp;
 21+    int i;
 22+
 23+    Player.t_flags &= ~ISHELD;	/* unhold when you go down just in case */
 24+    if (Level > Max_level)
 25+	Max_level = Level;
 26+    /*
 27+     * Clean things off from last level
 28+     */
 29+    for (pp = Places; pp < &Places[MAXCOLS*MAXLINES]; pp++)
 30+    {
 31+	pp->p_ch = ' ';
 32+	pp->p_flags = F_REAL;
 33+	pp->p_monst = NULL;
 34+    }
 35+    clear();
 36+    /*
 37+     * Free up the monsters on the last level
 38+     */
 39+    for (tp = Mlist; tp != NULL; tp = next(tp))
 40+	free_list(tp->t_pack);
 41+    free_list(Mlist);
 42+    /*
 43+     * Throw away stuff left on the previous level (if anything)
 44+     */
 45+    free_list(Lvl_obj);
 46+    do_rooms();				/* Draw rooms */
 47+    do_passages();			/* Draw passages */
 48+    No_food++;
 49+    put_things();			/* Place objects (if any) */
 50+    /*
 51+     * Place the traps
 52+     */
 53+    if (rnd(10) < Level)
 54+    {
 55+	Ntraps = rnd(Level / 4) + 1;
 56+	if (Ntraps > MAXTRAPS)
 57+	    Ntraps = MAXTRAPS;
 58+	i = Ntraps;
 59+	while (i--)
 60+	{
 61+	    /*
 62+	     * not only wouldn't it be NICE to have traps in mazes
 63+	     * (not that we care about being nice), since the trap
 64+	     * number is stored where the passage number is, we
 65+	     * can't actually do it.
 66+	     */
 67+	    do
 68+	    {
 69+		find_floor((struct room *) NULL, &Stairs, FALSE, FALSE);
 70+	    } while (chat(Stairs.y, Stairs.x) != FLOOR);
 71+	    sp = &flat(Stairs.y, Stairs.x);
 72+	    *sp &= ~F_REAL;
 73+	    *sp |= rnd(NTRAPS);
 74+	}
 75+    }
 76+    /*
 77+     * Place the staircase down.
 78+     */
 79+    find_floor((struct room *) NULL, &Stairs, FALSE, FALSE);
 80+    chat(Stairs.y, Stairs.x) = STAIRS;
 81+    Seenstairs = FALSE;
 82+
 83+    for (tp = Mlist; tp != NULL; tp = next(tp))
 84+	tp->t_room = roomin(&tp->t_pos);
 85+
 86+    find_floor((struct room *) NULL, &Hero, FALSE, TRUE);
 87+    enter_room(&Hero);
 88+    mvaddch(Hero.y, Hero.x, PLAYER);
 89+    if (on(Player, SEEMONST))
 90+	turn_see(FALSE);
 91+    if (on(Player, ISHALU))
 92+	visuals();
 93+}
 94+
 95+/*
 96+ * rnd_room:
 97+ *	Pick a room that is really there
 98+ */
 99+int
100+rnd_room(void)
101+{
102+    int rm;
103+
104+    do
105+    {
106+	rm = rnd(MAXROOMS);
107+    } while (Rooms[rm].r_flags & ISGONE);
108+    return rm;
109+}
110+
111+/*
112+ * put_things:
113+ *	Put potions and scrolls on this level
114+ */
115+void
116+put_things(void)
117+{
118+    int i;
119+    THING *obj;
120+
121+    /*
122+     * Once you have found the amulet, the only way to get new stuff is
123+     * go down into the dungeon.
124+     */
125+    if (Amulet && Level < Max_level)
126+	return;
127+    /*
128+     * check for treasure rooms, and if so, put it in.
129+     */
130+    if (rnd(TREAS_ROOM) == 0)
131+	treas_room();
132+    /*
133+     * Do MAXOBJ attempts to put things on a level
134+     */
135+    for (i = 0; i < MAXOBJ; i++)
136+	if (rnd(100) < 36)
137+	{
138+	    /*
139+	     * Pick a new object and link it in the list
140+	     */
141+	    obj = new_thing();
142+	    attach(Lvl_obj, obj);
143+	    /*
144+	     * Put it somewhere
145+	     */
146+	    find_floor((struct room *) NULL, &obj->o_pos, FALSE, FALSE);
147+	    chat(obj->o_pos.y, obj->o_pos.x) = obj->o_type;
148+	}
149+    /*
150+     * If he is really deep in the dungeon and he hasn't found the
151+     * amulet yet, put it somewhere on the ground
152+     */
153+    if (Level >= AMULETLEVEL && !Amulet)
154+    {
155+	obj = new_item();
156+	attach(Lvl_obj, obj);
157+	obj->o_hplus = 0;
158+	obj->o_dplus = 0;
159+	obj->o_damage = obj->o_hurldmg = "0x0";
160+	obj->o_arm = 11;
161+	obj->o_type = AMULET;
162+	/*
163+	 * Put it somewhere
164+	 */
165+	find_floor((struct room *) NULL, &obj->o_pos, FALSE, FALSE);
166+	chat(obj->o_pos.y, obj->o_pos.x) = AMULET;
167+    }
168+}
169+
170+/*
171+ * treas_room:
172+ *	Add a treasure room
173+ */
174+#define MAXTRIES 10	/* max number of tries to put down a monster */
175+
176+void
177+treas_room(void)
178+{
179+    int nm;
180+    THING *tp;
181+    struct room *rp;
182+    int spots, num_monst;
183+    static coord mp;
184+
185+    rp = &Rooms[rnd_room()];
186+    spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS;
187+    if (spots > (MAXTREAS - MINTREAS))
188+	spots = (MAXTREAS - MINTREAS);
189+    num_monst = nm = rnd(spots) + MINTREAS;
190+    while (nm--)
191+    {
192+	find_floor(rp, &mp, 2 * MAXTRIES, FALSE);
193+	tp = new_thing();
194+	tp->o_pos = mp;
195+	attach(Lvl_obj, tp);
196+	chat(mp.y, mp.x) = tp->o_type;
197+    }
198+
199+    /*
200+     * fill up room with monsters from the next level down
201+     */
202+
203+    if ((nm = rnd(spots) + MINTREAS) < num_monst + 2)
204+	nm = num_monst + 2;
205+    spots = (rp->r_max.y - 2) * (rp->r_max.x - 2);
206+    if (nm > spots)
207+	nm = spots;
208+    Level++;
209+    while (nm--)
210+    {
211+	spots = 0;
212+	if (find_floor(rp, &mp, MAXTRIES, TRUE))
213+	{
214+	    tp = new_item();
215+	    new_monster(tp, randmonster(FALSE), &mp);
216+	    tp->t_flags |= ISMEAN;	/* no sloughers in THIS room */
217+	    give_pack(tp);
218+	}
219+    }
220+    Level--;
221+}
A inter.c
+471, -0
  1@@ -0,0 +1,471 @@
  2+/*
  3+ * File for the fun ends
  4+ * Death or a total win
  5+ *
  6+ * @(#)inter.c	4.57 (Berkeley) 02/05/99
  7+ */
  8+
  9+#include <curses.h>
 10+#ifdef	attron
 11+#include <term.h>
 12+#endif	attron
 13+#include <time.h>
 14+#include <signal.h>
 15+#include <sys/types.h>
 16+#include <pwd.h>
 17+#include <ctype.h>
 18+#include "netprot.h"
 19+#include "netwait.h"
 20+
 21+#include <fcntl.h>
 22+
 23+#ifdef	attron
 24+int	_putchar(char c);
 25+# define	_puts(s)	tputs(s, 0, _putchar);
 26+# define	SO		enter_standout_mode
 27+# define	SE		exit_standout_mode
 28+#endif
 29+
 30+static char *Rip[] = {
 31+"                       __________\n",
 32+"                      /          \\\n",
 33+"                     /    REST    \\\n",
 34+"                    /      IN      \\\n",
 35+"                   /     PEACE      \\\n",
 36+"                  /                  \\\n",
 37+"                  |                  |\n",
 38+"                  |                  |\n",
 39+"                  |   killed by a    |\n",
 40+"                  |                  |\n",
 41+"                  |       1980       |\n",
 42+"                 *|     *  *  *      | *\n",
 43+"         ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______\n",
 44+    0
 45+};
 46+
 47+/*
 48+ * score:
 49+ *	Figure score and post it.
 50+ */
 51+/* VARARGS2 */
 52+void
 53+score(int amount, int flags, char monst)
 54+{
 55+    SCORE *scp;
 56+    int i;
 57+    SCORE *sc2;
 58+    SCORE *top_ten, *endp;
 59+    FILE *outf;
 60+# ifdef MASTER
 61+    int prflags = 0;
 62+# endif
 63+    void (*fp)(int);
 64+    int uid;
 65+    static char *reason[] = {
 66+	"killed",
 67+	"quit",
 68+	"A total winner",
 69+	"killed with Amulet"
 70+    };
 71+
 72+    start_score();
 73+
 74+    if (flags >= 0)
 75+    {
 76+	endwin();
 77+	resetltchars();
 78+	/*
 79+	 * free up space to "guarantee" there is space for the top_ten
 80+	 */
 81+	delwin(stdscr);
 82+	delwin(curscr);
 83+	if (Hw != NULL)
 84+	    delwin(Hw);
 85+    }
 86+
 87+    if (Fd >= 0)
 88+	outf = fdopen(Fd, "w");
 89+    else
 90+	return;
 91+
 92+    top_ten = (SCORE *) malloc(numscores * sizeof (SCORE));
 93+    endp = &top_ten[numscores];
 94+    for (scp = top_ten; scp < endp; scp++)
 95+    {
 96+	scp->sc_score = 0;
 97+	for (i = 0; i < MAXSTR; i++)
 98+	    scp->sc_name[i] = rnd(255);
 99+	scp->sc_flags = RN;
100+	scp->sc_level = RN;
101+	scp->sc_monster = RN;
102+	scp->sc_uid = RN;
103+    }
104+
105+    signal(SIGINT, SIG_DFL);
106+    if (flags >= 0
107+#ifdef MASTER
108+	    || Wizard
109+#endif
110+	)
111+    {
112+	printf("[Press return to continue]");
113+	fflush(stdout);
114+	fgets(Prbuf,10,stdin);
115+    }
116+#ifdef MASTER
117+    if (Wizard)
118+	if (strcmp(Prbuf, "names") == 0)
119+	    prflags = 1;
120+	else if (strcmp(Prbuf, "edit") == 0)
121+	    prflags = 2;
122+#endif
123+    rd_score(top_ten, Fd);
124+    fclose(outf);
125+    close(Fd);
126+    Fd = open(SCOREFILE, O_RDWR);
127+    outf = fdopen(Fd, "w");
128+    /*
129+     * Insert her in list if need be
130+     */
131+    sc2 = NULL;
132+    if (!Noscore)
133+    {
134+	uid = getuid();
135+	for (scp = top_ten; scp < endp; scp++)
136+	    if (amount > scp->sc_score)
137+		break;
138+	    else if (!Allscore &&	/* only one score per nowin uid */
139+		flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2)
140+		    scp = endp;
141+	if (scp < endp)
142+	{
143+	    if (flags != 2 && !Allscore)
144+	    {
145+		for (sc2 = scp; sc2 < endp; sc2++)
146+		{
147+		    if (sc2->sc_uid == uid && sc2->sc_flags != 2)
148+			break;
149+		}
150+		if (sc2 >= endp)
151+		    sc2 = endp - 1;
152+	    }
153+	    else
154+		sc2 = endp - 1;
155+	    while (sc2 > scp)
156+	    {
157+		*sc2 = sc2[-1];
158+		sc2--;
159+	    }
160+	    scp->sc_score = amount;
161+	    strncpy(scp->sc_name, Whoami, MAXSTR);
162+	    scp->sc_flags = flags;
163+	    if (flags == 2)
164+		scp->sc_level = Max_level;
165+	    else
166+		scp->sc_level = Level;
167+	    scp->sc_monster = monst;
168+	    scp->sc_uid = uid;
169+	    sc2 = scp;
170+	}
171+    }
172+    /*
173+     * Print the list
174+     */
175+    if (flags != -1)
176+	putchar('\n');
177+    printf("Top %s %s:\n", Numname, Allscore ? "Scores" : "Rogueists");
178+    printf("Rank\tScore\tName\n");
179+    for (scp = top_ten; scp < endp; scp++)
180+    {
181+	if (scp->sc_score) {
182+	    if (sc2 == scp && SO)
183+		_puts(SO);
184+	    printf("%d\t%d\t%s: %s on level %d", scp - top_ten + 1,
185+		scp->sc_score, scp->sc_name, reason[scp->sc_flags],
186+		scp->sc_level);
187+	    if (scp->sc_flags == 0 || scp->sc_flags == 3)
188+		printf(" by %s", killname((char) scp->sc_monster, TRUE));
189+# ifdef MASTER
190+	    if (prflags == 1)
191+	    {
192+		struct passwd *pp, *getpwuid();
193+
194+		if ((pp = getpwuid(scp->sc_uid)) == NULL)
195+		    printf(" (%d)", scp->sc_uid);
196+		else
197+		    printf(" (%s)", pp->pw_name);
198+		putchar('\n');
199+	    }
200+	    else if (prflags == 2)
201+	    {
202+		fflush(stdout);
203+		fgets(Prbuf,10,stdin);
204+		if (Prbuf[0] == 'd')
205+		{
206+		    for (sc2 = scp; sc2 < endp - 1; sc2++)
207+			*sc2 = *(sc2 + 1);
208+		    sc2 = endp - 1;
209+		    sc2->sc_score = 0;
210+		    for (i = 0; i < MAXSTR; i++)
211+			sc2->sc_name[i] = rnd(255);
212+		    sc2->sc_flags = RN;
213+		    sc2->sc_level = RN;
214+		    sc2->sc_monster = RN;
215+		    scp--;
216+		}
217+	    }
218+	    else
219+# endif MASTER
220+		printf(".\n");
221+	    if (sc2 == scp && SE)
222+		_puts(SE);
223+	}
224+	else
225+	    break;
226+    }
227+    fseek(outf, 0L, SEEK_SET);
228+    /*
229+     * Update the list file
230+     */
231+    if (sc2 != NULL)
232+    {
233+	if (lock_sc())
234+	{
235+	    fp = signal(SIGINT, SIG_IGN);
236+	    wr_score(top_ten, outf);
237+	    unlock_sc();
238+	    signal(SIGINT, fp);
239+	}
240+    }
241+    fclose(outf);
242+}
243+
244+/*
245+ * death:
246+ *	Do something really fun when he dies
247+ */
248+void
249+death(char monst)
250+{
251+    char **dp, *killer;
252+    struct tm *lt;
253+    static time_t date;
254+    struct tm *localtime();
255+
256+    signal(SIGINT, SIG_IGN);
257+    Purse -= Purse / 10;
258+    signal(SIGINT, leave);
259+    clear();
260+    killer = killname(monst, FALSE);
261+    if (!Tombstone)
262+    {
263+	mvprintw(LINES - 2, 0, "Killed by ");
264+	killer = killname(monst, FALSE);
265+	if (monst != 's' && monst != 'h')
266+	    printw("a%s ", vowelstr(killer));
267+	printw("%s with %d gold", killer, Purse);
268+    }
269+    else
270+    {
271+	time(&date);
272+	lt = localtime(&date);
273+	move(8, 0);
274+	dp = Rip;
275+	while (*dp)
276+	    addstr(*dp++);
277+	mvaddstr(17, center(killer), killer);
278+	if (monst == 's' || monst == 'h')
279+	    mvaddch(16, 32, ' ');
280+	else
281+	    mvaddstr(16, 33, vowelstr(killer));
282+	mvaddstr(14, center(Whoami), Whoami);
283+	sprintf(Prbuf, "%d Au", Purse);
284+	move(15, center(Prbuf));
285+	addstr(Prbuf);
286+	sprintf(Prbuf, "%2d", lt->tm_year);
287+	mvaddstr(18, 28, Prbuf);
288+    }
289+    move(LINES - 1, 0);
290+    refresh();
291+    score(Purse, Amulet ? 3 : 0, monst);
292+    my_exit(0);
293+}
294+
295+/*
296+ * center:
297+ *	Return the index to center the given string
298+ */
299+int
300+center(char *str)
301+{
302+    return 28 - ((strlen(str) + 1) / 2);
303+}
304+
305+/*
306+ * total_winner:
307+ *	Code for a winner
308+ */
309+void
310+total_winner(void)
311+{
312+    THING *obj;
313+    struct obj_info *op;
314+    int worth;
315+    int oldpurse;
316+
317+    clear();
318+    standout();
319+    addstr("                                                               \n");
320+    addstr("  @   @               @   @           @          @@@  @     @  \n");
321+    addstr("  @   @               @@ @@           @           @   @     @  \n");
322+    addstr("  @   @  @@@  @   @   @ @ @  @@@   @@@@  @@@      @  @@@    @  \n");
323+    addstr("   @@@@ @   @ @   @   @   @     @ @   @ @   @     @   @     @  \n");
324+    addstr("      @ @   @ @   @   @   @  @@@@ @   @ @@@@@     @   @     @  \n");
325+    addstr("  @   @ @   @ @  @@   @   @ @   @ @   @ @         @   @  @     \n");
326+    addstr("   @@@   @@@   @@ @   @   @  @@@@  @@@@  @@@     @@@   @@   @  \n");
327+    addstr("                                                               \n");
328+    addstr("     Congratulations, you have made it to the light of day!    \n");
329+    standend();
330+    addstr("\nYou have joined the elite ranks of those who have escaped the\n");
331+    addstr("Dungeons of Doom alive.  You journey home and sell all your loot at\n");
332+    addstr("a great profit and are admitted to the Fighters' Guild.\n");
333+    mvaddstr(LINES - 1, 0, "--Press space to continue--");
334+    refresh();
335+    wait_for(' ');
336+    clear();
337+    mvaddstr(0, 0, "   Worth  Item\n");
338+    oldpurse = Purse;
339+    for (obj = Pack; obj != NULL; obj = next(obj))
340+    {
341+	switch (obj->o_type)
342+	{
343+	    when FOOD:
344+		worth = 2 * obj->o_count;
345+	    when WEAPON:
346+		worth = Weap_info[obj->o_which].oi_worth;
347+		worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count;
348+		obj->o_flags |= ISKNOW;
349+	    when ARMOR:
350+		worth = Arm_info[obj->o_which].oi_worth;
351+		worth += (9 - obj->o_arm) * 100;
352+		worth += (10 * (A_class[obj->o_which] - obj->o_arm));
353+		obj->o_flags |= ISKNOW;
354+	    when SCROLL:
355+		worth = Scr_info[obj->o_which].oi_worth;
356+		worth *= obj->o_count;
357+		op = &Scr_info[obj->o_which];
358+		if (!op->oi_know)
359+		    worth /= 2;
360+		op->oi_know = TRUE;
361+	    when POTION:
362+		worth = Pot_info[obj->o_which].oi_worth;
363+		worth *= obj->o_count;
364+		op = &Pot_info[obj->o_which];
365+		if (!op->oi_know)
366+		    worth /= 2;
367+		op->oi_know = TRUE;
368+	    when RING:
369+		op = &Ring_info[obj->o_which];
370+		worth = op->oi_worth;
371+		if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||
372+		    obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)
373+			if (obj->o_arm > 0)
374+			    worth += obj->o_arm * 100;
375+			else
376+			    worth = 10;
377+		if (!(obj->o_flags & ISKNOW))
378+		    worth /= 2;
379+		obj->o_flags |= ISKNOW;
380+		op->oi_know = TRUE;
381+	    when STICK:
382+		op = &Ws_info[obj->o_which];
383+		worth = op->oi_worth;
384+		worth += 20 * obj->o_charges;
385+		if (!(obj->o_flags & ISKNOW))
386+		    worth /= 2;
387+		obj->o_flags |= ISKNOW;
388+		op->oi_know = TRUE;
389+	    when AMULET:
390+		worth = 1000;
391+	}
392+	if (worth < 0)
393+	    worth = 0;
394+	printw("%c) %5d  %s\n", obj->o_packch, worth, inv_name(obj, FALSE));
395+	Purse += worth;
396+    }
397+    printw("   %5d  Gold Pieces          ", oldpurse);
398+    refresh();
399+    score(Purse, 2, ' ');
400+    my_exit(0);
401+}
402+
403+/*
404+ * killname:
405+ *	Convert a code to a monster name
406+ */
407+char *
408+killname(char monst, bool doart)
409+{
410+    struct h_list *hp;
411+    char *sp;
412+    bool article;
413+    static struct h_list nlist[] = {
414+	'a',	"arrow",		TRUE,
415+	'b',	"bolt",			TRUE,
416+	'd',	"dart",			TRUE,
417+	'h',	"hypothermia",		FALSE,
418+	's',	"starvation",		FALSE,
419+	'\0'
420+    };
421+
422+    if (isupper(monst))
423+    {
424+	sp = Monsters[monst-'A'].m_name;
425+	article = TRUE;
426+    }
427+    else
428+    {
429+	sp = "Wally the Wonder Badger";
430+	article = FALSE;
431+	for (hp = nlist; hp->h_ch; hp++)
432+	    if (hp->h_ch == monst)
433+	    {
434+		sp = hp->h_desc;
435+		article = hp->h_print;
436+		break;
437+	    }
438+    }
439+    if (doart && article)
440+	sprintf(Prbuf, "a%s ", vowelstr(sp));
441+    else
442+	Prbuf[0] = '\0';
443+    strcat(Prbuf, sp);
444+    return Prbuf;
445+}
446+
447+/*
448+ * death_monst:
449+ *	Return a monster appropriate for a random death.
450+ */
451+char
452+death_monst(void)
453+{
454+    static char poss[] =
455+    {
456+	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
457+	'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
458+	'Y', 'Z', 'a', 'b', 'h', 'd', 's',
459+	' '	/* This is provided to generate the "Wally the Wonder Badger"
460+		   message for killer */
461+    };
462+
463+    return poss[rnd(sizeof poss / sizeof (char))];
464+}
465+
466+#ifdef	attron
467+int
468+_putchar(char c)
469+{
470+	putchar(c);
471+}
472+#endif	attron
A master.c
+400, -0
  1@@ -0,0 +1,400 @@
  2+/*
  3+ * Hero movement commands
  4+ *
  5+ * @(#)master.c	4.49 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include <ctype.h>
 10+#include "netprot.h"
 11+
 12+/*
 13+ * Used to hold the new Hero position
 14+ */
 15+
 16+coord nh;
 17+
 18+/*
 19+ * do_run:
 20+ *	Start the hero running
 21+ */
 22+void
 23+do_run(char ch)
 24+{
 25+    Running = TRUE;
 26+    After = FALSE;
 27+    Runch = ch;
 28+}
 29+
 30+/*
 31+ * do_move:
 32+ *	Check to see that a move is legal.  If it is handle the
 33+ * consequences (fighting, picking up, etc.)
 34+ */
 35+void
 36+do_move(int dy, int dx)
 37+{
 38+    char ch, fl;
 39+
 40+    Firstmove = FALSE;
 41+    if (No_move)
 42+    {
 43+	No_move--;
 44+	msg("you are still stuck in the bear trap");
 45+	return;
 46+    }
 47+    /*
 48+     * Do a confused move (maybe)
 49+     */
 50+    if (on(Player, ISHUH) && rnd(5) != 0)
 51+    {
 52+	nh = *rndmove(&Player);
 53+	if (ce(nh, Hero))
 54+	{
 55+	    After = FALSE;
 56+	    Running = FALSE;
 57+	    To_death = FALSE;
 58+	    return;
 59+	}
 60+    }
 61+    else
 62+    {
 63+over:
 64+	nh.y = Hero.y + dy;
 65+	nh.x = Hero.x + dx;
 66+    }
 67+
 68+    /*
 69+     * Check if he tried to move off the screen or make an illegal
 70+     * diagonal move, and stop him if he did.
 71+     */
 72+    if (nh.x < 0 || nh.x >= NUMCOLS || nh.y <= 0 || nh.y >= NUMLINES - 1)
 73+	goto hit_bound;
 74+    if (!diag_ok(&Hero, &nh))
 75+    {
 76+	After = FALSE;
 77+	Running = FALSE;
 78+	return;
 79+    }
 80+    if (Running && ce(Hero, nh))
 81+	After = Running = FALSE;
 82+    fl = flat(nh.y, nh.x);
 83+    ch = winat(nh.y, nh.x);
 84+    if (!(fl & F_REAL) && ch == FLOOR)
 85+    {
 86+	if (!on(Player, ISLEVIT))
 87+	{
 88+	    chat(nh.y, nh.x) = ch = TRAP;
 89+	    flat(nh.y, nh.x) |= F_REAL;
 90+	}
 91+    }
 92+    else if (on(Player, ISHELD) && ch != 'F')
 93+    {
 94+	msg("you are being held");
 95+	return;
 96+    }
 97+    switch (ch)
 98+    {
 99+	case ' ':
100+	case '|':
101+	case '-':
102+hit_bound:
103+	    if (Passgo && Running && (Proom->r_flags & ISGONE)
104+		&& !on(Player, ISBLIND))
105+	    {
106+		bool	b1, b2;
107+
108+		switch (Runch)
109+		{
110+		    case 'h':
111+		    case 'l':
112+			b1 = (Hero.y != 1 && turn_ok(Hero.y - 1, Hero.x));
113+			b2 = (Hero.y != NUMLINES - 2 && turn_ok(Hero.y + 1, Hero.x));
114+			if (!(b1 ^ b2))
115+			    break;
116+			if (b1)
117+			{
118+			    Runch = 'k';
119+			    dy = -1;
120+			}
121+			else
122+			{
123+			    Runch = 'j';
124+			    dy = 1;
125+			}
126+			dx = 0;
127+			turnref();
128+			goto over;
129+		    case 'j':
130+		    case 'k':
131+			b1 = (Hero.x != 0 && turn_ok(Hero.y, Hero.x - 1));
132+			b2 = (Hero.x != NUMCOLS - 1 && turn_ok(Hero.y, Hero.x + 1));
133+			if (!(b1 ^ b2))
134+			    break;
135+			if (b1)
136+			{
137+			    Runch = 'h';
138+			    dx = -1;
139+			}
140+			else
141+			{
142+			    Runch = 'l';
143+			    dx = 1;
144+			}
145+			dy = 0;
146+			turnref();
147+			goto over;
148+		}
149+	    }
150+	    Running = FALSE;
151+	    After = FALSE;
152+	    break;
153+	case DOOR:
154+	    Running = FALSE;
155+	    if (flat(Hero.y, Hero.x) & F_PASS)
156+		enter_room(&nh);
157+	    goto move_stuff;
158+	case TRAP:
159+	    ch = be_trapped(&nh);
160+	    if (ch == T_DOOR || ch == T_TELEP)
161+		return;
162+	    goto move_stuff;
163+	case PASSAGE:
164+	    /*
165+	     * when you're in a corridor, you don't know if you're in
166+	     * a maze room or not, and there ain't no way to find out
167+	     * if you're leaving a maze room, so it is necessary to
168+	     * always recalculate Proom.
169+	     */
170+	    Proom = roomin(&Hero);
171+	    goto move_stuff;
172+	case FLOOR:
173+	    if (!(fl & F_REAL))
174+		be_trapped(&Hero);
175+	    goto move_stuff;
176+	case STAIRS:
177+	    Seenstairs = TRUE;
178+	    /* FALLTHROUGH */
179+	default:
180+	    Running = FALSE;
181+	    if (isupper(ch) || moat(nh.y, nh.x))
182+		fight(&nh, Cur_weapon, FALSE);
183+	    else
184+	    {
185+		if (ch != STAIRS)
186+		    Take = ch;
187+move_stuff:
188+		mvaddch(Hero.y, Hero.x, floor_at());
189+		if ((fl & F_PASS) && chat(Oldpos.y, Oldpos.x) == DOOR)
190+		    leave_room(&nh);
191+		Hero = nh;
192+	    }
193+    }
194+}
195+
196+/*
197+ * turn_ok:
198+ *	Decide whether it is legal to turn onto the given space
199+ */
200+bool
201+turn_ok(int y, int x)
202+{
203+    PLACE *pp;
204+
205+    pp = INDEX(y, x);
206+    return (pp->p_ch == DOOR
207+	|| (pp->p_flags & (F_REAL|F_PASS)) == (F_REAL|F_PASS));
208+}
209+
210+/*
211+ * turnref:
212+ *	Decide whether to refresh at a passage turning or not
213+ */
214+void
215+turnref(void)
216+{
217+    PLACE *pp;
218+
219+    pp = INDEX(Hero.y, Hero.x);
220+    if (!(pp->p_flags & F_SEEN))
221+    {
222+	if (Jump)
223+	{
224+	    leaveok(stdscr, TRUE);
225+	    refresh();
226+	    leaveok(stdscr, FALSE);
227+	}
228+	pp->p_flags |= F_SEEN;
229+    }
230+}
231+
232+/*
233+ * door_open:
234+ *	Called to illuminate a room.  If it is dark, remove anything
235+ *	that might move.
236+ */
237+void
238+door_open(struct room *rp)
239+{
240+    THING *mp;
241+    int y, x;
242+
243+    if (!(rp->r_flags & ISGONE))
244+	for (y = rp->r_pos.y; y < rp->r_pos.y + rp->r_max.y; y++)
245+	    for (x = rp->r_pos.x; x < rp->r_pos.x + rp->r_max.x; x++)
246+		if (isupper(winat(y, x)))
247+		    wake_monster(y, x);
248+}
249+
250+/*
251+ * be_trapped:
252+ *	The guy stepped on a trap.... Make him pay.
253+ */
254+char
255+be_trapped(coord *tc)
256+{
257+    PLACE *pp;
258+    THING *arrow;
259+    char tr;
260+
261+    if (on(Player, ISLEVIT))
262+	return T_RUST;	/* anything that's not a door or teleport */
263+    Running = FALSE;
264+    Count = FALSE;
265+    pp = INDEX(tc->y, tc->x);
266+    pp->p_ch = TRAP;
267+    tr = pp->p_flags & F_TMASK;
268+    pp->p_flags |= F_SEEN;
269+    switch (tr)
270+    {
271+	when T_DOOR:
272+	    Level++;
273+	    new_level();
274+	    msg("you fell into a trap!");
275+	when T_BEAR:
276+	    No_move += BEARTIME;
277+	    msg("you are caught in a bear trap");
278+	when T_SLEEP:
279+	    No_command += SLEEPTIME;
280+	    Player.t_flags &= ~ISRUN;
281+	    msg("a strange white mist envelops you and you fall asleep");
282+	when T_ARROW:
283+	    if (swing(Pstats.s_lvl - 1, Pstats.s_arm, 1))
284+	    {
285+		Pstats.s_hpt -= roll(1, 6);
286+		if (Pstats.s_hpt <= 0)
287+		{
288+		    msg("an arrow killed you");
289+		    death('a');
290+		}
291+		else
292+		    msg("oh no! An arrow shot you");
293+	    }
294+	    else
295+	    {
296+		arrow = new_item();
297+		init_weapon(arrow, ARROW);
298+		arrow->o_count = 1;
299+		arrow->o_pos = Hero;
300+		fall(arrow, FALSE);
301+		msg("an arrow shoots past you");
302+	    }
303+	when T_TELEP:
304+	    /*
305+	     * since the hero's leaving, look() won't put a TRAP
306+	     * down for us, so we have to do it ourself
307+	     */
308+	    teleport();
309+	    mvaddch(tc->y, tc->x, TRAP);
310+	when T_DART:
311+	    if (!swing(Pstats.s_lvl+1, Pstats.s_arm, 1))
312+		msg("a small dart whizzes by your ear and vanishes");
313+	    else
314+	    {
315+		Pstats.s_hpt -= roll(1, 4);
316+		if (Pstats.s_hpt <= 0)
317+		{
318+		    msg("a poisoned dart killed you");
319+		    death('d');
320+		}
321+		if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON))
322+		    chg_str(-1);
323+		msg("a small dart just hit you in the shoulder");
324+	    }
325+	when T_RUST:
326+	    msg("a gush of water hits you on the head");
327+	    rust_armor(Cur_armor);
328+    }
329+    flush_type();
330+    return tr;
331+}
332+
333+/*
334+ * rndmove:
335+ *	Move in a random direction if the monster/person is confused
336+ */
337+coord *
338+rndmove(THING *who)
339+{
340+    THING *obj;
341+    int x, y;
342+    char ch;
343+    coord ret;  /* what we will be returning */
344+
345+    y = ret.y = who->t_pos.y + rnd(3) - 1;
346+    x = ret.x = who->t_pos.x + rnd(3) - 1;
347+    /*
348+     * Now check to see if that's a legal move.  If not, don't move.
349+     * (I.e., bump into the wall or whatever)
350+     */
351+    if (y == who->t_pos.y && x == who->t_pos.x)
352+	return &ret;
353+    if (!diag_ok(&who->t_pos, &ret))
354+	goto bad;
355+    else
356+    {
357+	ch = winat(y, x);
358+	if (!step_ok(ch))
359+	    goto bad;
360+	if (ch == SCROLL)
361+	{
362+	    for (obj = Lvl_obj; obj != NULL; obj = next(obj))
363+		if (y == obj->o_pos.y && x == obj->o_pos.x)
364+		    break;
365+	    if (obj != NULL && obj->o_which == S_SCARE)
366+		goto bad;
367+	}
368+    }
369+    return &ret;
370+
371+bad:
372+    ret = who->t_pos;
373+    return &ret;
374+}
375+
376+/*
377+ * rust_armor:
378+ *	Rust the given armor, if it is a legal kind to rust, and we
379+ *	aren't wearing a magic ring.
380+ */
381+void
382+rust_armor(THING *arm)
383+{
384+    if (arm == NULL || arm->o_type != ARMOR || arm->o_which == LEATHER ||
385+	arm->o_arm >= 9)
386+	    return;
387+
388+    if ((arm->o_flags & ISPROT) || ISWEARING(R_SUSTARM))
389+    {
390+	if (!To_death)
391+	    msg("the rust vanishes instantly");
392+    }
393+    else
394+    {
395+	arm->o_arm++;
396+	if (!Terse)
397+	    msg("your armor appears to be weaker now. Oh my!");
398+	else
399+	    msg("your armor weakens");
400+    }
401+}
A netmap.c
+196, -0
  1@@ -0,0 +1,196 @@
  2+#include <curses.h>
  3+#include "netprot.h"
  4+
  5+/*
  6+ * Routines dealing specifically with rings
  7+ *
  8+ * @(#)netmap.c	4.19 (Berkeley) 05/29/83
  9+ */
 10+
 11+/*
 12+ * ring_on:
 13+ *	Put a ring on a hand
 14+ */
 15+void
 16+ring_on(void)
 17+{
 18+    THING *obj;
 19+    int ring;
 20+
 21+    obj = get_item("put on", RING);
 22+    /*
 23+     * Make certain that it is somethings that we want to wear
 24+     */
 25+    if (obj == NULL)
 26+	return;
 27+    if (obj->o_type != RING)
 28+    {
 29+	if (!Terse)
 30+	    msg("it would be difficult to wrap that around a finger");
 31+	else
 32+	    msg("not a ring");
 33+	return;
 34+    }
 35+
 36+    /*
 37+     * find out which hand to put it on
 38+     */
 39+    if (is_current(obj))
 40+	return;
 41+
 42+    if (Cur_ring[LEFT] == NULL && Cur_ring[RIGHT] == NULL)
 43+    {
 44+	if ((ring = gethand()) < 0)
 45+	    return;
 46+    }
 47+    else if (Cur_ring[LEFT] == NULL)
 48+	ring = LEFT;
 49+    else if (Cur_ring[RIGHT] == NULL)
 50+	ring = RIGHT;
 51+    else
 52+    {
 53+	if (!Terse)
 54+	    msg("you already have a ring on each hand");
 55+	else
 56+	    msg("wearing two");
 57+	return;
 58+    }
 59+    Cur_ring[ring] = obj;
 60+
 61+    /*
 62+     * Calculate the effect it has on the poor guy.
 63+     */
 64+    switch (obj->o_which)
 65+    {
 66+	case R_ADDSTR:
 67+	    chg_str(obj->o_arm);
 68+	    break;
 69+	case R_SEEINVIS:
 70+	    invis_on();
 71+	    break;
 72+	case R_AGGR:
 73+	    aggravate();
 74+	    break;
 75+    }
 76+
 77+    if (!Terse)
 78+	addmsg("you are now wearing ");
 79+    msg("%s (%c)", inv_name(obj, TRUE), obj->o_packch);
 80+}
 81+
 82+/*
 83+ * ring_off:
 84+ *	Take off a ring
 85+ */
 86+void
 87+ring_off(void)
 88+{
 89+    int ring;
 90+    THING *obj;
 91+
 92+    if (Cur_ring[LEFT] == NULL && Cur_ring[RIGHT] == NULL)
 93+    {
 94+	if (Terse)
 95+	    msg("no rings");
 96+	else
 97+	    msg("you aren't wearing any rings");
 98+	return;
 99+    }
100+    else if (Cur_ring[LEFT] == NULL)
101+	ring = RIGHT;
102+    else if (Cur_ring[RIGHT] == NULL)
103+	ring = LEFT;
104+    else
105+	if ((ring = gethand()) < 0)
106+	    return;
107+    Mpos = 0;
108+    obj = Cur_ring[ring];
109+    if (obj == NULL)
110+    {
111+	msg("not wearing such a ring");
112+	return;
113+    }
114+    if (dropcheck(obj))
115+	msg("was wearing %s (%c)", inv_name(obj, TRUE), obj->o_packch);
116+}
117+
118+/*
119+ * gethand:
120+ *	Which hand is the hero interested in?
121+ */
122+int
123+gethand(void)
124+{
125+    int c;
126+
127+    for (;;)
128+    {
129+	if (Terse)
130+	    msg("left or right ring? ");
131+	else
132+	    msg("left hand or right hand? ");
133+	if ((c = readchar()) == ESCAPE)
134+	    return -1;
135+	Mpos = 0;
136+	if (c == 'l' || c == 'L')
137+	    return LEFT;
138+	else if (c == 'r' || c == 'R')
139+	    return RIGHT;
140+	if (Terse)
141+	    msg("L or R");
142+	else
143+	    msg("please type L or R");
144+    }
145+}
146+
147+/*
148+ * ring_eat:
149+ *	How much food does this ring use up?
150+ */
151+int
152+ring_eat(int hand)
153+{
154+    THING *ring;
155+    int eat;
156+    static int uses[] = {
157+	 1,	/* R_PROTECT */		 1,	/* R_ADDSTR */
158+	 1,	/* R_SUSTSTR */		-3,	/* R_SEARCH */
159+	-5,	/* R_SEEINVIS */	 0,	/* R_NOP */
160+	 0,	/* R_AGGR */		-3,	/* R_ADDHIT */
161+	-3,	/* R_ADDDAM */		 2,	/* R_REGEN */
162+	-2,	/* R_DIGEST */		 0,	/* R_TELEPORT */
163+	 1,	/* R_STEALTH */		 1	/* R_SUSTARM */
164+    };
165+
166+    if ((ring = Cur_ring[hand]) == NULL)
167+	return 0;
168+    if ((eat = uses[ring->o_which]) < 0)
169+	eat = (rnd(-eat) == 0);
170+    if (ring->o_which == R_DIGEST)
171+	eat = -eat;
172+    return eat;
173+}
174+
175+/*
176+ * ring_num:
177+ *	Print ring bonuses
178+ */
179+char *
180+ring_num(THING *obj)
181+{
182+    static char buf[10];
183+
184+    if (!(obj->o_flags & ISKNOW))
185+	return "";
186+    switch (obj->o_which)
187+    {
188+	when R_PROTECT:
189+	case R_ADDSTR:
190+	case R_ADDDAM:
191+	case R_ADDHIT:
192+	    sprintf(buf, " [%s]", num(obj->o_arm, 0, RING));
193+	otherwise:
194+	    return "";
195+    }
196+    return buf;
197+}
A netmisc.c
+231, -0
  1@@ -0,0 +1,231 @@
  2+/*
  3+ * copies of several routines needed for netwait
  4+ *
  5+ * @(#)netmisc.c	4.7 (Berkeley) 02/05/99
  6+ */
  7+
  8+# include	<stdio.h>
  9+# include	<sys/types.h>
 10+# include	<stat.h>
 11+# include	<ctype.h>
 12+
 13+# define	TRUE		1
 14+# define	FALSE		0
 15+# define	MAXSTR		80
 16+# define	bool		char
 17+# define	when		break;case
 18+# define	otherwise	break;default
 19+
 20+typedef struct {
 21+	char	*m_name;
 22+} MONST;
 23+
 24+char	*s_vowelstr();
 25+
 26+extern char	encstr[], frob;
 27+
 28+char *lockfile = "/tmp/.fredlock";
 29+
 30+char Prbuf[MAXSTR];			/* Buffer for sprintfs */
 31+
 32+MONST	Monsters[] = {
 33+	{ "aquator" }, { "bat" }, { "centaur" }, { "dragon" }, { "emu" },
 34+	{ "venus flytrap" }, { "griffin" }, { "hobgoblin" }, { "ice monster" },
 35+	{ "jabberwock" }, { "kobold" }, { "leprechaun" }, { "medusa" },
 36+	{ "nymph" }, { "orc" }, { "phantom" }, { "quasit" }, { "rattlesnake" },
 37+	{ "snake" }, { "troll" }, { "ur-vile" }, { "vampire" }, { "wraith" },
 38+	{ "xeroc" }, { "yeti" }, { "zombie" }
 39+};
 40+
 41+/*
 42+ * s_lock_sc:
 43+ *	lock the score file.  If it takes too long, ask the user if
 44+ *	they care to wait.  Return TRUE if the lock is successful.
 45+ */
 46+bool
 47+s_lock_sc(void)
 48+{
 49+    int cnt;
 50+    static struct stat sbuf;
 51+    time_t time();
 52+
 53+over:
 54+    close(8);	/* just in case there are no files left */
 55+    if (creat(lockfile, 0000) >= 0)
 56+	return TRUE;
 57+    for (cnt = 0; cnt < 5; cnt++)
 58+    {
 59+	sleep(1);
 60+	if (creat(lockfile, 0000) >= 0)
 61+	    return TRUE;
 62+    }
 63+    if (stat(lockfile, &sbuf) < 0)
 64+    {
 65+	creat(lockfile, 0000);
 66+	return TRUE;
 67+    }
 68+    if (time(NULL) - sbuf.st_mtime > 10)
 69+    {
 70+	if (unlink(lockfile) < 0)
 71+	    return FALSE;
 72+	goto over;
 73+    }
 74+    else
 75+    {
 76+	printf("The score file is very busy.  Do you want to wait longer\n");
 77+	printf("for it to become free so your score can get posted?\n");
 78+	printf("If so, type \"y\"\n");
 79+	fgets(Prbuf, MAXSTR, stdin);
 80+	if (Prbuf[0] == 'y')
 81+	    for (;;)
 82+	    {
 83+		if (creat(lockfile, 0000) >= 0)
 84+		    return TRUE;
 85+		if (stat(lockfile, &sbuf) < 0)
 86+		{
 87+		    creat(lockfile, 0000);
 88+		    return TRUE;
 89+		}
 90+		if (time(NULL) - sbuf.st_mtime > 10)
 91+		{
 92+		    if (unlink(lockfile) < 0)
 93+			return FALSE;
 94+		}
 95+		sleep(1);
 96+	    }
 97+	else
 98+	    return FALSE;
 99+    }
100+}
101+
102+/*
103+ * s_unlock_sc:
104+ *	Unlock the score file
105+ */
106+void
107+s_unlock_sc(void)
108+{
109+    unlink(lockfile);
110+}
111+
112+/*
113+ * s_encwrite:
114+ *	Perform an encrypted write
115+ */
116+void
117+s_encwrite(char *start, unsigned int size, FILE *outf)
118+{
119+    char *e1, *e2, fb;
120+    int temp;
121+    extern char statlist[];
122+
123+    e1 = encstr;
124+    e2 = statlist;
125+    fb = frob;
126+
127+    while (size--)
128+    {
129+	putc(*start++ ^ *e1 ^ *e2 ^ fb, outf);
130+	temp = *e1++;
131+	fb += temp * *e2++;
132+	if (*e1 == '\0')
133+	    e1 = encstr;
134+	if (*e2 == '\0')
135+	    e2 = statlist;
136+    }
137+}
138+
139+/*
140+ * s_encread:
141+ *	Perform an encrypted read
142+ */
143+void
144+s_encread(char *start, unsigned int size, int inf)
145+{
146+    char *e1, *e2, fb;
147+    int temp;
148+    int read_size;
149+    extern char statlist[];
150+
151+    fb = frob;
152+
153+    if ((read_size = read(inf, start, size)) == 0 || read_size == -1)
154+	return;
155+
156+    e1 = encstr;
157+    e2 = statlist;
158+
159+    while (size--)
160+    {
161+	*start++ ^= *e1 ^ *e2 ^ fb;
162+	temp = *e1++;
163+	fb += temp * *e2++;
164+	if (*e1 == '\0')
165+	    e1 = encstr;
166+	if (*e2 == '\0')
167+	    e2 = statlist;
168+    }
169+}
170+
171+/*
172+ * s_killname:
173+ *	Convert a code to a monster name
174+ */
175+char *
176+s_killname(char monst, bool doart)
177+{
178+    char *sp;
179+    bool article;
180+
181+    article = TRUE;
182+    switch (monst)
183+    {
184+	when 'a':
185+	    sp = "arrow";
186+	when 'b':
187+	    sp = "bolt";
188+	when 'd':
189+	    sp = "dart";
190+	when 's':
191+	    sp = "starvation";
192+	    article = FALSE;
193+	when 'h':
194+	    sp = "hypothermia";
195+	    article = FALSE;
196+	otherwise:
197+	    if (isupper(monst))
198+		sp = Monsters[monst-'A'].m_name;
199+	    else
200+	    {
201+		sp = "God";
202+		article = FALSE;
203+	    }
204+    }
205+    if (doart && article)
206+	sprintf(Prbuf, "a%s ", s_vowelstr(sp));
207+    else
208+	Prbuf[0] = '\0';
209+    strcat(Prbuf, sp);
210+    return Prbuf;
211+}
212+
213+/*
214+ * s_vowelstr:
215+ *      For printfs: if string starts with a vowel, return "n" for an
216+ *	"an".
217+ */
218+char *
219+s_vowelstr(char *str)
220+{
221+    switch (*str)
222+    {
223+	case 'a': case 'A':
224+	case 'e': case 'E':
225+	case 'i': case 'I':
226+	case 'o': case 'O':
227+	case 'u': case 'U':
228+	    return "n";
229+	default:
230+	    return "";
231+    }
232+}
A netprot.c
+529, -0
  1@@ -0,0 +1,529 @@
  2+/*
  3+ * Code for one creature to chase another
  4+ *
  5+ * @(#)netprot.c	4.57 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include "netprot.h"
 10+
 11+#define DRAGONSHOT  5	/* one chance in DRAGONSHOT that a dragon will flame */
 12+
 13+static coord Ch_ret;				/* Where chasing takes you */
 14+
 15+/*
 16+ * runners:
 17+ *	Make all the running monsters move.
 18+ */
 19+void
 20+runners(void)
 21+{
 22+    THING *tp;
 23+    THING *next;
 24+    bool wastarget;
 25+    static coord orig_pos;
 26+
 27+    for (tp = Mlist; tp != NULL; tp = next)
 28+    {
 29+	/* remember this in case the monster's "next" is changed */
 30+	next = next(tp);
 31+
 32+	if (!on(*tp, ISHELD) && on(*tp, ISRUN))
 33+	{
 34+	    orig_pos = tp->t_pos;
 35+	    wastarget = on(*tp, ISTARGET);
 36+	    move_monst(tp);
 37+	    if (on(*tp, ISFLY) && dist_cp(&Hero, &tp->t_pos) >= 3)
 38+		move_monst(tp);
 39+	    if (wastarget && !ce(orig_pos, tp->t_pos))
 40+	    {
 41+		tp->t_flags &= ~ISTARGET;
 42+		To_death = FALSE;
 43+	    }
 44+	}
 45+    }
 46+    if (Has_hit)
 47+    {
 48+	endmsg();
 49+	Has_hit = FALSE;
 50+    }
 51+}
 52+
 53+/*
 54+ * move_monst:
 55+ *	Execute a single turn of running for a monster
 56+ */
 57+void
 58+move_monst(THING *tp)
 59+{
 60+    if (!on(*tp, ISSLOW) || tp->t_turn)
 61+	do_chase(tp);
 62+    if (on(*tp, ISHASTE))
 63+	do_chase(tp);
 64+    tp->t_turn ^= TRUE;
 65+}
 66+
 67+/*
 68+ * relocate:
 69+ *	Make the monster's new location be the specified one, updating
 70+ *	all the relevant state.
 71+ */
 72+void
 73+relocate(THING *th, coord *new_loc)
 74+{
 75+    struct room *oroom;
 76+
 77+    if (!ce(*new_loc, th->t_pos))
 78+    {
 79+	mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch);
 80+	th->t_room = roomin(new_loc);
 81+	set_oldch(th, new_loc);
 82+	oroom = th->t_room;
 83+	moat(th->t_pos.y, th->t_pos.x) = NULL;
 84+
 85+	if (oroom != th->t_room)
 86+	    th->t_dest = find_dest(th);
 87+	th->t_pos = *new_loc;
 88+	moat(new_loc->y, new_loc->x) = th;
 89+    }
 90+    move(new_loc->y, new_loc->x);
 91+    if (see_monst(th))
 92+	addch(th->t_disguise);
 93+    else if (on(Player, SEEMONST))
 94+    {
 95+	standout();
 96+	addch(th->t_type);
 97+	standend();
 98+    }
 99+}
100+
101+/*
102+ * do_chase:
103+ *	Make one thing chase another.
104+ */
105+void
106+do_chase(THING *th)
107+{
108+    coord *cp;
109+    struct room *rer, *ree;	/* room of chaser, room of chasee */
110+    int mindist = 32767, curdist;
111+    bool stoprun = FALSE;	/* TRUE means we are there */
112+    bool door;
113+    THING *obj;
114+    static coord this;			/* Temporary destination for chaser */
115+
116+    rer = th->t_room;		/* Find room of chaser */
117+    if (on(*th, ISGREED) && rer->r_goldval == 0)
118+	th->t_dest = &Hero;	/* If gold has been taken, run after hero */
119+    if (th->t_dest == &Hero)	/* Find room of chasee */
120+	ree = Proom;
121+    else
122+	ree = roomin(th->t_dest);
123+    /*
124+     * We don't count doors as inside rooms for this routine
125+     */
126+    door = (chat(th->t_pos.y, th->t_pos.x) == DOOR);
127+    /*
128+     * If the object of our desire is in a different room,
129+     * and we are not in a corridor, run to the door nearest to
130+     * our goal.
131+     */
132+over:
133+    if (rer != ree)
134+    {
135+	for (cp = rer->r_exit; cp < &rer->r_exit[rer->r_nexits]; cp++)
136+	{
137+	    curdist = dist_cp(th->t_dest, cp);
138+	    if (curdist < mindist)
139+	    {
140+		this = *cp;
141+		mindist = curdist;
142+	    }
143+	}
144+	if (door)
145+	{
146+	    rer = &Passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM];
147+	    door = FALSE;
148+	    goto over;
149+	}
150+    }
151+    else
152+    {
153+	this = *th->t_dest;
154+	/*
155+	 * For dragons check and see if (a) the hero is on a straight
156+	 * line from it, and (b) that it is within shooting distance,
157+	 * but outside of striking range.
158+	 */
159+	if (th->t_type == 'D' && (th->t_pos.y == Hero.y || th->t_pos.x == Hero.x
160+	    || abs(th->t_pos.y - Hero.y) == abs(th->t_pos.x - Hero.x))
161+	    && dist_cp(&th->t_pos, &Hero) <= BOLT_LENGTH * BOLT_LENGTH
162+	    && !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0)
163+	{
164+	    Delta.y = sign(Hero.y - th->t_pos.y);
165+	    Delta.x = sign(Hero.x - th->t_pos.x);
166+	    if (Has_hit)
167+		endmsg();
168+	    fire_bolt(&th->t_pos, &Delta, "flame");
169+	    Running = FALSE;
170+	    Count = 0;
171+	    Quiet = 0;
172+	    if (To_death && !on(*th, ISTARGET))
173+	    {
174+		To_death = FALSE;
175+		Kamikaze = FALSE;
176+	    }
177+	    return;
178+	}
179+    }
180+    /*
181+     * This now contains what we want to run to this time
182+     * so we run to it.  If we hit it we either want to fight it
183+     * or stop running
184+     */
185+    if (!chase(th, &this))
186+    {
187+	if (ce(this, Hero))
188+	{
189+	    attack(th);
190+	    return;
191+	}
192+	else if (ce(this, *th->t_dest))
193+	{
194+	    for (obj = Lvl_obj; obj != NULL; obj = next(obj))
195+		if (th->t_dest == &obj->o_pos)
196+		{
197+		    detach(Lvl_obj, obj);
198+		    attach(th->t_pack, obj);
199+		    chat(obj->o_pos.y, obj->o_pos.x) =
200+			(th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR;
201+		    th->t_dest = find_dest(th);
202+		    break;
203+		}
204+	    if (th->t_type != 'F')
205+		stoprun = TRUE;
206+	}
207+    }
208+    else
209+    {
210+	if (th->t_type == 'F')
211+	    return;
212+    }
213+    relocate(th, &Ch_ret);
214+    /*
215+     * And stop running if need be
216+     */
217+    if (stoprun && ce(th->t_pos, *(th->t_dest)))
218+	th->t_flags &= ~ISRUN;
219+}
220+
221+/*
222+ * set_oldch:
223+ *	Set the oldch character for the monster
224+ */
225+void
226+set_oldch(THING *tp, coord *cp)
227+{
228+    char sch;
229+
230+    if (ce(tp->t_pos, *cp))
231+	return;
232+
233+    sch = tp->t_oldch;
234+    tp->t_oldch = mvinch(cp->y, cp->x);
235+    if (!on(Player, ISBLIND))
236+	if ((sch == FLOOR || tp->t_oldch == FLOOR) &&
237+	    (tp->t_room->r_flags & ISDARK))
238+		tp->t_oldch = ' ';
239+	else if (dist_cp(cp, &Hero) <= LAMPDIST && See_floor)
240+	    tp->t_oldch = chat(cp->y, cp->x);
241+}
242+
243+/*
244+ * see_monst:
245+ *	Return TRUE if the hero can see the monster
246+ */
247+bool
248+see_monst(THING *mp)
249+{
250+    int y, x;
251+
252+    if (on(Player, ISBLIND))
253+	return FALSE;
254+    if (on(*mp, ISINVIS) && !on(Player, CANSEE))
255+	return FALSE;
256+    y = mp->t_pos.y;
257+    x = mp->t_pos.x;
258+    if (dist(y, x, Hero.y, Hero.x) < LAMPDIST)
259+    {
260+	if (y != Hero.y && x != Hero.x &&
261+	    !step_ok(chat(y, Hero.x)) && !step_ok(chat(Hero.y, x)))
262+		return FALSE;
263+	return TRUE;
264+    }
265+    if (mp->t_room != Proom)
266+	return FALSE;
267+    return (!(mp->t_room->r_flags & ISDARK));
268+}
269+
270+/*
271+ * runto:
272+ *	Set a monster running after the hero.
273+ */
274+void
275+runto(coord *runner)
276+{
277+    THING *tp;
278+
279+    /*
280+     * If we couldn't find him, something is funny
281+     */
282+#ifdef MASTER
283+    if ((tp = moat(runner->y, runner->x)) == NULL)
284+	msg("couldn't find monster in runto at (%d,%d)", runner->y, runner->x);
285+#else
286+    tp = moat(runner->y, runner->x);
287+#endif
288+    /*
289+     * Start the beastie running
290+     */
291+    tp->t_flags |= ISRUN;
292+    tp->t_flags &= ~ISHELD;
293+    tp->t_dest = find_dest(tp);
294+}
295+
296+/*
297+ * chase:
298+ *	Find the spot for the chaser(er) to move closer to the
299+ *	chasee(ee).  Returns TRUE if we want to keep on chasing later
300+ *	FALSE if we reach the goal.
301+ */
302+bool
303+chase(THING *tp, coord *ee)
304+{
305+    THING *obj;
306+    int x, y;
307+    int curdist, thisdist;
308+    coord *er = &tp->t_pos;
309+    char ch;
310+    int plcnt = 1;
311+    static coord tryp;
312+
313+    /*
314+     * If the thing is confused, let it move randomly. Invisible
315+     * Stalkers are slightly confused all of the time, and bats are
316+     * quite confused all the time
317+     */
318+    if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'P' && rnd(5) == 0)
319+	|| (tp->t_type == 'B' && rnd(2) == 0))
320+    {
321+	/*
322+	 * get a valid random move
323+	 */
324+	Ch_ret = *rndmove(tp);
325+	curdist = dist_cp(&Ch_ret, ee);
326+	/*
327+	 * Small chance that it will become un-confused 
328+	 */
329+	if (rnd(20) == 0)
330+	    tp->t_flags &= ~ISHUH;
331+    }
332+    /*
333+     * Otherwise, find the empty spot next to the chaser that is
334+     * closest to the chasee.
335+     */
336+    else
337+    {
338+	int ey, ex;
339+	/*
340+	 * This will eventually hold where we move to get closer
341+	 * If we can't find an empty spot, we stay where we are.
342+	 */
343+	curdist = dist_cp(er, ee);
344+	Ch_ret = *er;
345+
346+	ey = er->y + 1;
347+	if (ey >= NUMLINES - 1)
348+	    ey = NUMLINES - 2;
349+	ex = er->x + 1;
350+	if (ex >= NUMCOLS)
351+	    ex = NUMCOLS - 1;
352+
353+	for (x = er->x - 1; x <= ex; x++)
354+	{
355+	    if (x < 0)
356+		continue;
357+	    tryp.x = x;
358+	    for (y = er->y - 1; y <= ey; y++)
359+	    {
360+		tryp.y = y;
361+		if (!diag_ok(er, &tryp))
362+		    continue;
363+		ch = winat(y, x);
364+		if (step_ok(ch))
365+		{
366+		    /*
367+		     * If it is a scroll, it might be a scare monster scroll
368+		     * so we need to look it up to see what type it is.
369+		     */
370+		    if (ch == SCROLL)
371+		    {
372+			for (obj = Lvl_obj; obj != NULL; obj = next(obj))
373+			{
374+			    if (y == obj->o_pos.y && x == obj->o_pos.x)
375+				break;
376+			}
377+			if (obj != NULL && obj->o_which == S_SCARE)
378+			    continue;
379+		    }
380+		    /*
381+		     * It can also be a Xeroc, which we shouldn't step on
382+		     */
383+		    if ((obj = moat(y, x)) != NULL && obj->t_type == 'X')
384+			continue;
385+		    /*
386+		     * If we didn't find any scrolls at this place or it
387+		     * wasn't a scare scroll, then this place counts
388+		     */
389+		    thisdist = dist(y, x, ee->y, ee->x);
390+		    if (thisdist < curdist)
391+		    {
392+			plcnt = 1;
393+			Ch_ret = tryp;
394+			curdist = thisdist;
395+		    }
396+		    else if (thisdist == curdist && rnd(++plcnt) == 0)
397+		    {
398+			Ch_ret = tryp;
399+			curdist = thisdist;
400+		    }
401+		}
402+	    }
403+	}
404+    }
405+    return (curdist != 0 && !ce(Ch_ret, Hero));
406+}
407+
408+/*
409+ * roomin:
410+ *	Find what room some coordinates are in. NULL means they aren't
411+ *	in any room.
412+ */
413+struct room *
414+roomin(coord *cp)
415+{
416+    struct room *rp;
417+    char *fp;
418+
419+
420+    fp = &flat(cp->y, cp->x);
421+    if (*fp & F_PASS)
422+	return &Passages[*fp & F_PNUM];
423+
424+    for (rp = Rooms; rp < &Rooms[MAXROOMS]; rp++)
425+	if (cp->x <= rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x
426+	 && cp->y <= rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y)
427+	    return rp;
428+
429+    msg("in some bizarre place (%d, %d)", unc(*cp));
430+#ifdef MASTER
431+    abort();
432+    /* NOTREACHED */
433+#else
434+    return NULL;
435+#endif
436+}
437+
438+/*
439+ * diag_ok:
440+ *	Check to see if the move is legal if it is diagonal
441+ */
442+bool
443+diag_ok(coord *sp, coord *ep)
444+{
445+    if (ep->x < 0 || ep->x >= NUMCOLS || ep->y <= 0 || ep->y >= NUMLINES - 1)
446+	return FALSE;
447+    if (ep->x == sp->x || ep->y == sp->y)
448+	return TRUE;
449+    return (step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x)));
450+}
451+
452+/*
453+ * cansee:
454+ *	Returns true if the hero can see a certain coordinate.
455+ */
456+bool
457+cansee(int y, int x)
458+{
459+    struct room *rer;
460+    static coord tp;
461+
462+    if (on(Player, ISBLIND))
463+	return FALSE;
464+    if (dist(y, x, Hero.y, Hero.x) < LAMPDIST)
465+    {
466+	if (flat(y, x) & F_PASS)
467+	    if (y != Hero.y && x != Hero.x &&
468+		!step_ok(chat(y, Hero.x)) && !step_ok(chat(Hero.y, x)))
469+		    return FALSE;
470+	return TRUE;
471+    }
472+    /*
473+     * We can only see if the hero in the same room as
474+     * the coordinate and the room is lit or if it is close.
475+     */
476+    tp.y = y;
477+    tp.x = x;
478+    return ((rer = roomin(&tp)) == Proom && !(rer->r_flags & ISDARK));
479+}
480+
481+/*
482+ * find_dest:
483+ *	find the proper destination for the monster
484+ */
485+coord *
486+find_dest(THING *tp)
487+{
488+    THING *obj;
489+    int prob;
490+
491+    if ((prob = Monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == Proom
492+	|| see_monst(tp))
493+	    return &Hero;
494+    for (obj = Lvl_obj; obj != NULL; obj = next(obj))
495+    {
496+	if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
497+	    continue;
498+	if (roomin(&obj->o_pos) == tp->t_room && rnd(100) < prob)
499+	{
500+	    for (tp = Mlist; tp != NULL; tp = next(tp))
501+		if (tp->t_dest == &obj->o_pos)
502+		    break;
503+	    if (tp == NULL)
504+		return &obj->o_pos;
505+	}
506+    }
507+    return &Hero;
508+}
509+
510+/*
511+ * dist:
512+ *	Calculate the "distance" between to points.  Actually,
513+ *	this calculates d^2, not d, but that's good enough for
514+ *	our purposes, since it's only used comparitively.
515+ */
516+int
517+dist(int y1, int x1, int y2, int x2)
518+{
519+    return ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
520+}
521+
522+/*
523+ * dist_cp:
524+ *	Call dist() with appropriate arguments for coord pointers
525+ */
526+int
527+dist_cp(coord *c1, coord *c2)
528+{
529+    return dist(c1->y, c1->x, c2->y, c2->x);
530+}
A netprot.h
+596, -0
  1@@ -0,0 +1,596 @@
  2+/*
  3+ * Rogue definitions and variable declarations
  4+ *
  5+ * @(#)netprot.h	5.42 (Berkeley) 08/06/83
  6+ */
  7+
  8+#include "network.h"
  9+#include <stdarg.h>
 10+
 11+/*
 12+ * Maximum number of different things
 13+ */
 14+#define MAXROOMS	9
 15+#define MAXTHINGS	9
 16+#define MAXOBJ		9
 17+#define MAXPACK		23
 18+#define MAXTRAPS	10
 19+#define AMULETLEVEL	26
 20+#define	NUMTHINGS	7	/* number of types of things */
 21+#define MAXPASS		13	/* upper limit on number of passages */
 22+#define	NUMLINES	24
 23+#define	NUMCOLS		80
 24+#define STATLINE		(NUMLINES - 1)
 25+#define BORE_LEVEL	50
 26+
 27+/*
 28+ * return values for get functions
 29+ */
 30+#define	NORM	0	/* normal exit */
 31+#define	QUIT	1	/* quit option setting */
 32+#define	MINUS	2	/* back up one option */
 33+
 34+/*
 35+ * inventory types
 36+ */
 37+#define	INV_OVER	0
 38+#define	INV_SLOW	1
 39+#define	INV_CLEAR	2
 40+
 41+/*
 42+ * All the fun defines
 43+ */
 44+#define when		break;case
 45+#define otherwise	break;default
 46+#define until(expr)	while(!(expr))
 47+#define next(ptr)	(*ptr).l_next
 48+#define prev(ptr)	(*ptr).l_prev
 49+#define winat(y,x)	(moat(y,x) != NULL ? moat(y,x)->t_disguise : chat(y,x))
 50+#define ce(a,b)		((a).x == (b).x && (a).y == (b).y)
 51+#define Hero		Player.t_pos
 52+#define Pstats		Player.t_stats
 53+#define Pack		Player.t_pack
 54+#define Proom		Player.t_room
 55+#define Max_hp		Player.t_stats.s_maxhp
 56+#define attach(a,b)	_attach(&a,b)
 57+#define detach(a,b)	_detach(&a,b)
 58+#define free_list(a)	_free_list(&a)
 59+#define max(a,b)	((a) > (b) ? (a) : (b))
 60+#define on(thing,flag)	(((thing).t_flags & (flag)) != 0)
 61+#define GOLDCALC	(rnd(50 + 10 * Level) + 2)
 62+#define ISRING(h,r)	(Cur_ring[h] != NULL && Cur_ring[h]->o_which == r)
 63+#define ISWEARING(r)	(ISRING(LEFT, r) || ISRING(RIGHT, r))
 64+#define ISMULT(type) 	(type == POTION || type == SCROLL || type == FOOD)
 65+#define INDEX(y,x)	(&Places[((x) << 5) + (y)])
 66+#define chat(y,x)	(Places[((x) << 5) + (y)].p_ch)
 67+#define flat(y,x)	(Places[((x) << 5) + (y)].p_flags)
 68+#define moat(y,x)	(Places[((x) << 5) + (y)].p_monst)
 69+#define unc(cp)		(cp).y, (cp).x
 70+#ifdef MASTER
 71+#define debug		if (Wizard) msg
 72+#endif
 73+
 74+/*
 75+ * Things that appear on the screens
 76+ */
 77+#define PASSAGE		'#'
 78+#define DOOR		'+'
 79+#define FLOOR		'.'
 80+#define PLAYER		'@'
 81+#define TRAP		'^'
 82+#define STAIRS		'%'
 83+#define GOLD		'*'
 84+#define POTION		'!'
 85+#define SCROLL		'?'
 86+#define MAGIC		'$'
 87+#define FOOD		':'
 88+#define WEAPON		')'
 89+#define ARMOR		']'
 90+#define AMULET		','
 91+#define RING		'='
 92+#define STICK		'/'
 93+#define CALLABLE	-1
 94+#define R_OR_S		-2
 95+
 96+/*
 97+ * Various constants
 98+ */
 99+#define BEARTIME	spread(3)
100+#define SLEEPTIME	spread(5)
101+#define HOLDTIME	spread(2)
102+#define WANDERTIME	spread(70)
103+#define BEFORE		spread(1)
104+#define AFTER		spread(2)
105+#define HEALTIME	30
106+#define HUHDURATION	20
107+#define SEEDURATION	850
108+#define HUNGERTIME	1300
109+#define MORETIME	150
110+#define STOMACHSIZE	2000
111+#define STARVETIME	850
112+#define ESCAPE		27
113+#define LEFT		0
114+#define RIGHT		1
115+#define BOLT_LENGTH	6
116+#define LAMPDIST	3
117+#ifdef MASTER
118+#define	PASSWD		"mTsdVv0Uvy4xY"
119+#endif
120+
121+/*
122+ * Save against things
123+ */
124+#define VS_POISON	00
125+#define VS_PARALYZATION	00
126+#define VS_DEATH	00
127+#define VS_BREATH	02
128+#define VS_MAGIC	03
129+
130+/*
131+ * Various flag bits
132+ */
133+/* flags for rooms */
134+#define ISDARK	0000001		/* room is dark */
135+#define ISGONE	0000002		/* room is gone (a corridor) */
136+#define ISMAZE	0000004		/* room is gone (a corridor) */
137+
138+/* flags for objects */
139+#define ISCURSED 000001		/* object is cursed */
140+#define ISKNOW	0000002		/* player knows details about the object */
141+#define ISMISL	0000004		/* object is a missile type */
142+#define ISMANY	0000010		/* object comes in groups */
143+/*	ISFOUND 0000020		...is used for both objects and creatures */
144+#define	ISPROT	0000040		/* armor is permanently protected */
145+
146+/* flags for creatures */
147+#define CANHUH	0000001		/* creature can confuse */
148+#define CANSEE	0000002		/* creature can see invisible creatures */
149+#define ISBLIND	0000004		/* creature is blind */
150+#define ISCANC	0000010		/* creature has special qualities cancelled */
151+#define ISLEVIT	0000010		/* hero is levitating */
152+#define ISFOUND	0000020		/* creature has been seen (used for objects) */
153+#define ISGREED	0000040		/* creature runs to protect gold */
154+#define ISHASTE	0000100		/* creature has been hastened */
155+#define ISTARGET 000200		/* creature is the target of an 'f' command */
156+#define ISHELD	0000400		/* creature has been held */
157+#define ISHUH	0001000		/* creature is confused */
158+#define ISINVIS	0002000		/* creature is invisible */
159+#define ISMEAN	0004000		/* creature can wake when player enters room */
160+#define ISHALU	0004000		/* hero is on acid trip */
161+#define ISREGEN	0010000		/* creature can regenerate */
162+#define ISRUN	0020000		/* creature is running at the player */
163+#define SEEMONST 040000		/* hero can detect unseen monsters */
164+#define ISFLY	0040000		/* creature can fly */
165+#define ISSLOW	0100000		/* creature has been slowed */
166+
167+/*
168+ * Flags for level map
169+ */
170+#define F_PASS		0x80		/* is a passageway */
171+#define F_SEEN		0x40		/* have seen this spot before */
172+#define F_DROPPED	0x20		/* object was dropped here */
173+#define F_LOCKED	0x20		/* door is locked */
174+#define F_REAL		0x10		/* what you see is what you get */
175+#define F_PNUM		0x0f		/* passage number mask */
176+#define F_TMASK		0x07		/* trap number mask */
177+
178+/*
179+ * Trap types
180+ */
181+#define T_DOOR	00
182+#define T_ARROW	01
183+#define T_SLEEP	02
184+#define T_BEAR	03
185+#define T_TELEP	04
186+#define T_DART	05
187+#define T_RUST	06
188+#define NTRAPS	7
189+
190+/*
191+ * Potion types
192+ */
193+#define P_CONFUSE	0
194+#define P_LSD		1
195+#define P_POISON	2
196+#define P_STRENGTH	3
197+#define P_SEEINVIS	4
198+#define P_HEALING	5
199+#define P_MFIND		6
200+#define	P_TFIND 	7
201+#define	P_RAISE		8
202+#define P_XHEAL		9
203+#define P_HASTE		10
204+#define P_RESTORE	11
205+#define P_BLIND		12
206+#define P_LEVIT		13
207+#define MAXPOTIONS	14
208+
209+/*
210+ * Scroll types
211+ */
212+#define S_CONFUSE	0
213+#define S_MAP		1
214+#define S_HOLD		2
215+#define S_SLEEP		3
216+#define S_ARMOR		4
217+#define S_ID_POTION	5
218+#define S_ID_SCROLL	6
219+#define S_ID_WEAPON	7
220+#define S_ID_ARMOR	8
221+#define S_ID_R_OR_S	9
222+#define S_SCARE		10
223+#define S_FDET		11
224+#define S_TELEP		12
225+#define S_ENCH		13
226+#define S_CREATE	14
227+#define S_REMOVE	15
228+#define S_AGGR		16
229+#define S_PROTECT	17
230+#define MAXSCROLLS	18
231+
232+/*
233+ * Weapon types
234+ */
235+#define MACE		0
236+#define SWORD		1
237+#define BOW		2
238+#define ARROW		3
239+#define DAGGER		4
240+#define TWOSWORD	5
241+#define DART		6
242+#define SHIRAKEN	7
243+#define SPEAR		8
244+#define FLAME		9	/* fake entry for dragon breath (ick) */
245+#define MAXWEAPONS	9	/* this should equal FLAME */
246+
247+/*
248+ * Armor types
249+ */
250+#define LEATHER		0
251+#define RING_MAIL	1
252+#define STUDDED_LEATHER	2
253+#define SCALE_MAIL	3
254+#define CHAIN_MAIL	4
255+#define SPLINT_MAIL	5
256+#define BANDED_MAIL	6
257+#define PLATE_MAIL	7
258+#define MAXARMORS	8
259+
260+/*
261+ * Ring types
262+ */
263+#define R_PROTECT	0
264+#define R_ADDSTR	1
265+#define R_SUSTSTR	2
266+#define R_SEARCH	3
267+#define R_SEEINVIS	4
268+#define R_NOP		5
269+#define R_AGGR		6
270+#define R_ADDHIT	7
271+#define R_ADDDAM	8
272+#define R_REGEN		9
273+#define R_DIGEST	10
274+#define R_TELEPORT	11
275+#define R_STEALTH	12
276+#define R_SUSTARM	13
277+#define MAXRINGS	14
278+
279+/*
280+ * Rod/Wand/Staff types
281+ */
282+#define WS_LIGHT	0
283+#define WS_INVIS	1
284+#define WS_ELECT	2
285+#define WS_FIRE		3
286+#define WS_COLD		4
287+#define WS_POLYMORPH	5
288+#define WS_MISSILE	6
289+#define WS_HASTE_M	7
290+#define WS_SLOW_M	8
291+#define WS_DRAIN	9
292+#define WS_NOP		10
293+#define WS_TELAWAY	11
294+#define WS_TELTO	12
295+#define WS_CANCEL	13
296+#define MAXSTICKS	14
297+
298+/*
299+ * Now we define the structures and types
300+ */
301+
302+/*
303+ * Help list
304+ */
305+struct h_list {
306+    char h_ch;
307+    char *h_desc;
308+    bool h_print;
309+};
310+
311+/*
312+ * Coordinate data type
313+ */
314+typedef struct {
315+    int y;
316+    int x;
317+} coord;
318+
319+typedef unsigned int str_t;
320+
321+/*
322+ * Stuff about objects
323+ */
324+struct obj_info {
325+    char *oi_name;
326+    int oi_prob;
327+    short oi_worth;
328+    char *oi_guess;
329+    bool oi_know;
330+};
331+
332+/*
333+ * Room structure
334+ */
335+struct room {
336+    coord r_pos;			/* Upper left corner */
337+    coord r_max;			/* Size of room */
338+    coord r_gold;			/* Where the gold is */
339+    int r_goldval;			/* How much the gold is worth */
340+    short r_flags;			/* Info about the room */
341+    int r_nexits;			/* Number of exits */
342+    coord r_exit[12];			/* Where the exits are */
343+};
344+
345+/*
346+ * Structure describing a fighting being
347+ */
348+struct stats {
349+    str_t s_str;			/* Strength */
350+    long s_exp;				/* Experience */
351+    int s_lvl;				/* Level of mastery */
352+    int s_arm;				/* Armor class */
353+    short s_hpt;			/* Hit points */
354+    char s_dmg[13];			/* String describing damage done */
355+    short s_maxhp;			/* Max hit points */
356+};
357+
358+/*
359+ * Structure for monsters and player
360+ */
361+union thing {
362+    struct {
363+	union thing *_l_next, *_l_prev;	/* Next pointer in link */
364+	coord _t_pos;			/* Position */
365+	bool _t_turn;			/* If slowed, is it a turn to move */
366+	char _t_type;			/* What it is */
367+	char _t_disguise;		/* What mimic looks like */
368+	char _t_oldch;			/* Character that was where it was */
369+	coord *_t_dest;			/* Where it is running to */
370+	short _t_flags;			/* State word */
371+	struct stats _t_stats;		/* Physical description */
372+	struct room *_t_room;		/* Current room for thing */
373+	union thing *_t_pack;		/* What the thing is carrying */
374+    } _t;
375+    struct {
376+	union thing *_l_next, *_l_prev;	/* Next pointer in link */
377+	int _o_type;			/* What kind of object it is */
378+	coord _o_pos;			/* Where it lives on the screen */
379+	char *_o_text;			/* What it says if you read it */
380+	char _o_launch;			/* What you need to launch it */
381+	char _o_packch;			/* What character it is in the pack */
382+	char *_o_damage;		/* Damage if used like sword */
383+	char *_o_hurldmg;		/* Damage if thrown */
384+	int _o_count;			/* Count for plural objects */
385+	int _o_which;			/* Which object of a type it is */
386+	int _o_hplus;			/* Plusses to hit */
387+	int _o_dplus;			/* Plusses to damage */
388+	short _o_arm;			/* Armor protection */
389+	short _o_flags;			/* Information about objects */
390+	int _o_group;			/* Group number for this object */
391+	char *_o_label;			/* Label for object */
392+    } _o;
393+};
394+
395+typedef union thing THING;
396+
397+#define l_next		_t._l_next
398+#define l_prev		_t._l_prev
399+#define t_pos		_t._t_pos
400+#define t_turn		_t._t_turn
401+#define t_type		_t._t_type
402+#define t_disguise	_t._t_disguise
403+#define t_oldch		_t._t_oldch
404+#define t_dest		_t._t_dest
405+#define t_flags		_t._t_flags
406+#define t_stats		_t._t_stats
407+#define t_pack		_t._t_pack
408+#define t_room		_t._t_room
409+#define o_type		_o._o_type
410+#define o_pos		_o._o_pos
411+#define o_text		_o._o_text
412+#define o_launch	_o._o_launch
413+#define o_packch	_o._o_packch
414+#define o_damage	_o._o_damage
415+#define o_hurldmg	_o._o_hurldmg
416+#define o_count		_o._o_count
417+#define o_which		_o._o_which
418+#define o_hplus		_o._o_hplus
419+#define o_dplus		_o._o_dplus
420+#define o_arm		_o._o_arm
421+#define o_charges	o_arm
422+#define o_goldval	o_arm
423+#define o_flags		_o._o_flags
424+#define o_group		_o._o_group
425+#define o_label		_o._o_label
426+
427+/*
428+ * describe a place on the level map
429+ */
430+typedef struct {
431+    char p_ch;
432+    char p_flags;
433+    THING *p_monst;
434+} PLACE;
435+
436+/*
437+ * Array containing information on all the various types of monsters
438+ */
439+struct monster {
440+    char *m_name;			/* What to call the monster */
441+    int m_carry;			/* Probability of carrying something */
442+    short m_flags;			/* Things about the monster */
443+    struct stats m_stats;		/* Initial stats */
444+};
445+
446+/*
447+ * External variables
448+ */
449+
450+extern bool	After, Again, Allscore, Amulet, Door_stop, Fight_flush,
451+		Firstmove, Has_hit, Inv_describe, Jump, Kamikaze,
452+		Lower_msg, Move_on, Msg_esc, Noscore, Pack_used[],
453+		Passgo, Playing, Q_comm, Running, Save_msg, See_floor,
454+		Seenstairs, Stat_msg, Terse, To_death, Tombstone;
455+
456+extern char	Dir_ch, File_name[], Home[], Huh[], *Inv_t_name[],
457+		L_last_comm, L_last_dir, Last_comm, Last_dir, *Numname,
458+		Outbuf[], *P_colors[], *R_stones[], *Release, Runch,
459+		*S_names[], Take, *Tr_name[], *Ws_made[], *Ws_type[];
460+
461+extern int	A_class[], Count, Food_left, Hungry_state, Inpack,
462+		Inv_type, Lastscore, Level, Max_hit, Max_level, Mpos,
463+		N_objs, No_command, No_food, No_move, Ntraps, Purse,
464+		Quiet, Vf_hit;
465+
466+extern unsigned int	numscores;
467+
468+extern long	Dnum, E_levels[], Seed;
469+
470+extern WINDOW	*Hw;
471+
472+extern coord	Delta, Oldpos, Stairs;
473+
474+extern PLACE	Places[];
475+
476+extern THING	*Cur_armor, *Cur_ring[], *Cur_weapon, *L_last_pick,
477+		*Last_pick, *Lvl_obj, *Mlist, Player;
478+
479+extern struct h_list	Helpstr[];
480+
481+extern struct room	*Oldrp, Passages[], Rooms[];
482+
483+extern struct stats	Max_stats;
484+
485+extern struct monster	Monsters[];
486+
487+extern struct obj_info	Arm_info[], Pot_info[], Ring_info[],
488+			Scr_info[], Things[], Ws_info[], Weap_info[];
489+
490+/*
491+ * Function types
492+ */
493+void	accnt_maze(int y, int x, int ny, int nx);
494+void	badcheck(char *name, struct obj_info *info, int bound);
495+void	bounce(THING *weap, char *mname, bool noend);
496+void	call(void);
497+void	check_level(void);
498+void	conn(int r1, int r2);
499+void	current(THING *cur, char *how, char *where);
500+void	d_level(void);
501+void	dig(int y, int x);
502+void	discard(THING *item);
503+void	do_chase(THING *th);
504+void	do_maze(struct room *rp);
505+void	do_motion(THING *obj, int ydelta, int xdelta);
506+void	do_pot(int type, bool knowit);
507+void	doadd(char *fmt, va_list args);
508+void	door(struct room *rm, coord *cp);
509+void	drain(void);
510+void	draw_room(struct room *rp);
511+void	encwrite(char *start, unsigned int size, FILE *outf);
512+void	erase_lamp(coord *pos, struct room *rp);
513+void	fall(THING *obj, bool pr);
514+void	fire_bolt(coord *start, coord *dir, char *name);
515+void	help(void);
516+void	hit(char *er, char *ee, bool noend);
517+void	horiz(struct room *rp, int starty);
518+void	identify(void);
519+void	illcom(char ch);
520+void	invis_on(void);
521+void	killed(THING *tp, bool pr);
522+void	miss(char *er, char *ee, bool noend);
523+void	money(int value);
524+void	move_monst(THING *tp);
525+void	move_msg(THING *obj);
526+void	nameit(THING *obj, char *type, char *which, struct obj_info *op, char *(*prfunc)(THING *));
527+void	numpass(int y, int x);
528+void	passnum(void);
529+void	pr_spec(struct obj_info *info, int nitems);
530+void	put_bool(void *b);
531+void	put_inv_t(void *ip);
532+void	put_str(void *str);
533+void	put_things(void);
534+void	putpass(coord *cp);
535+void	raise_level(void);
536+void	relocate(THING *th, coord *new_loc);
537+void	remove_mon(coord *mp, THING *tp, bool waskill);
538+void	reset_last(void);
539+void	rust_armor(THING *arm);
540+void	save_file(FILE *savef);
541+void	search(void);
542+void	set_know(THING *obj, struct obj_info *info);
543+void	set_oldch(THING *tp, coord *cp);
544+void	strucpy(char *s1, char *s2, int len);
545+void	thunk(THING *weap, char *mname, bool noend);
546+void	treas_room(void);
547+void	turnref(void);
548+void	u_level(void);
549+void	uncurse(THING *obj);
550+void	vert(struct room *rp, int startx);
551+void	wait_for(char ch);
552+void	waste_time(void);
553+
554+bool	chase(THING *tp, coord *ee);
555+bool	diag_ok(coord *sp, coord *ep);
556+bool	dropcheck(THING *obj);
557+bool	fallpos(coord *pos, coord *newpos);
558+bool	find_floor(struct room *rp, coord *cp, int limit, bool monst);
559+bool	is_magic(THING *obj);
560+bool	levit_check(void);
561+bool	pack_room(bool from_floor, THING *obj);
562+bool	roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl);
563+bool	see_monst(THING *mp);
564+bool	seen_stairs(void);
565+bool	turn_ok(int y, int x);
566+bool	turn_see(bool turn_off);
567+
568+char	be_trapped(coord *tc);
569+char	floor_ch(void);
570+char	pack_char(void);
571+
572+char	*charge_str(THING *obj);
573+char	*choose_str(char *ts, char *ns);
574+char	*inv_name(THING *obj, bool drop);
575+char	*nullstr(THING *ignored);
576+char	*num(int n1, int n2, char type);
577+char	*ring_num(THING *obj);
578+char	*set_mname(THING *tp);
579+char	*vowelstr(char *str);
580+
581+int	get_bool(void *vp, WINDOW *win);
582+int	get_inv_t(void *vp, WINDOW *win);
583+int	get_num(void *vp, WINDOW *win);
584+int	get_sf(void *vp, WINDOW *win);
585+int	get_str(void *vopt, WINDOW *win);
586+int	trip_ch(int y, int x, char ch);
587+
588+coord	*find_dest(THING *tp);
589+coord	*rndmove(THING *who);
590+
591+THING	*find_obj(int y, int x);
592+THING	*get_item(char *purpose, int type);
593+THING	*leave_pack(THING *obj, bool newobj, bool all);
594+THING	*new_item(void);
595+THING	*new_thing(void);
596+
597+struct room	*roomin(coord *cp);
A netwait.c
+298, -0
  1@@ -0,0 +1,298 @@
  2+/*
  3+ * score editor
  4+ *
  5+ * @(#)netwait.c	4.6 (Berkeley) 02/05/99
  6+ */
  7+
  8+# include	<stdio.h>
  9+# include	<pwd.h>
 10+# include	<signal.h>
 11+# include	<ctype.h>
 12+# include	<unctrl.h>
 13+
 14+# define	TRUE	1
 15+# define	FALSE	0
 16+# define	bool	char
 17+# define	RN	(((Seed = Seed*11109+13849) >> 16) & 0xffff)
 18+
 19+# define	MAXSTR	80
 20+
 21+# include	"netwait.h"
 22+
 23+SCORE	Top_ten[10];
 24+
 25+char	frob,
 26+	Buf[BUFSIZ],
 27+	*Reason[] = {
 28+		"killed",
 29+		"quit",
 30+		"A total winner",
 31+		"killed with Amulet",
 32+	};
 33+
 34+int	Seed,
 35+	Inf;
 36+
 37+struct passwd	*getpwnam();
 38+
 39+int
 40+main(ac, av)
 41+int	ac;
 42+char	**av;
 43+{
 44+	char	*scorefile;
 45+	FILE	*outf;
 46+
 47+	if (ac == 1)
 48+		scorefile = SCOREFILE;
 49+	else
 50+		scorefile = av[1];
 51+	Seed = getpid();
 52+
 53+	if ((Inf = open(scorefile, 2)) < 0) {
 54+		perror(scorefile);
 55+		exit(1);
 56+	}
 57+	frob = 0;
 58+	s_encread((char *) Top_ten, sizeof Top_ten, Inf);
 59+
 60+	while (do_comm())
 61+		continue;
 62+
 63+	exit(0);
 64+}
 65+
 66+/*
 67+ * do_comm:
 68+ *	Get and execute a command
 69+ */
 70+bool
 71+do_comm(void)
 72+{
 73+	char		*sp;
 74+	SCORE		*scp;
 75+	struct passwd	*pp;
 76+	static FILE	*outf = NULL;
 77+	static bool	written = TRUE;
 78+
 79+	printf("\nCommand: ");
 80+	while (isspace(Buf[0] = getchar()) || Buf[0] == '\n')
 81+		continue;
 82+	fgets(&Buf[1], BUFSIZ, stdin);
 83+	Buf[strlen(Buf) - 1] = '\0';
 84+	switch (Buf[0]) {
 85+	  case 'w':
 86+		if (strncmp(Buf, "write", strlen(Buf)))
 87+			goto def;
 88+		lseek(Inf, 0L, 0);
 89+		if (outf == NULL && (outf = fdopen(Inf, "w")) == NULL) {
 90+			perror("fdopen");
 91+			exit(1);
 92+		}
 93+		fseek(outf, 0L, 0);
 94+		if (s_lock_sc())
 95+		{
 96+			int	(*fp)();
 97+
 98+			fp = signal(SIGINT, SIG_IGN);
 99+			frob = 0;
100+			s_encwrite((char *) Top_ten, sizeof Top_ten, outf);
101+			s_unlock_sc();
102+			signal(SIGINT, fp);
103+			written = TRUE;
104+		}
105+		break;
106+
107+	  case 'a':
108+		if (strncmp(Buf, "add", strlen(Buf)))
109+			goto def;
110+		add_score();
111+		written = FALSE;
112+		break;
113+
114+	  case 'd':
115+		if (strncmp(Buf, "delete", strlen(Buf)))
116+			goto def;
117+		del_score();
118+		written = FALSE;
119+		break;
120+
121+	  case 'p':
122+		if (strncmp(Buf, "print", strlen(Buf)))
123+			goto def;
124+		printf("\nTop Ten Rogueists:\nRank\tScore\tName\n");
125+		for (scp = Top_ten; scp < &Top_ten[10]; scp++)
126+			if (!pr_score(scp, TRUE))
127+				break;
128+		break;
129+
130+	  case 'q':
131+		if (strncmp(Buf, "quit", strlen(Buf)))
132+			goto def;
133+		if (!written) {
134+			printf("No write\n");
135+			written = TRUE;
136+		}
137+		else
138+			return FALSE;
139+		break;
140+
141+	  default:
142+def:
143+		printf("Unkown command: \"%s\"\n", Buf);
144+	}
145+	return TRUE;
146+}
147+
148+/*
149+ * add_score:
150+ *	Add a score to the score file
151+ */
152+void
153+add_score(void)
154+{
155+	SCORE		*scp;
156+	struct passwd	*pp;
157+	int		i;
158+	static SCORE	new;
159+
160+	printf("Name: ");
161+	fgets(new.sc_name, MAXSTR, stdin);
162+	new.sc_name[strlen(new.sc_name) - 1] = '\0';
163+	do {
164+		printf("Reason: ");
165+		if ((new.sc_flags = getchar()) < '0' || new.sc_flags > '2') {
166+			for (i = 0; i < 3; i++)
167+				printf("%d: %s\n", i, Reason[i]);
168+			ungetc(new.sc_flags, stdin);
169+		}
170+		while (getchar() != '\n')
171+			continue;
172+	} while (new.sc_flags < '0' || new.sc_flags > '2');
173+	new.sc_flags -= '0';
174+	do {
175+		printf("User: ");
176+		fgets(Buf, BUFSIZ, stdin);
177+		Buf[strlen(Buf) - 1] = '\0';
178+		if ((pp = getpwnam(Buf)) == NULL)
179+			printf("who (%s)?\n", Buf);
180+	} while (pp == NULL);
181+	new.sc_uid = pp->pw_uid;
182+	do {
183+		printf("Monster: ");
184+		if (!isalpha(new.sc_monster = getchar())) {
185+			printf("type A-Za-z [%s]\n", unctrl(new.sc_monster));
186+			ungetc(new.sc_monster, stdin);
187+		}
188+		while (getchar() != '\n')
189+			continue;
190+	} while (!isalpha(new.sc_monster));
191+	printf("Score: ");
192+	scanf("%d", &new.sc_score);
193+	printf("Level: ");
194+	scanf("%d", &new.sc_level);
195+	while (getchar() != '\n')
196+		continue;
197+	pr_score(&new, FALSE);
198+	printf("Really add it? ");
199+	if (getchar() != 'y')
200+		return;
201+	while (getchar() != '\n')
202+		continue;
203+	insert_score(&new);
204+}
205+
206+/*
207+ * pr_score:
208+ *	Print out a score entry.  Return FALSE if last entry.
209+ */
210+void
211+pr_score(SCORE *scp, bool num)
212+{
213+	struct passwd	*pp;
214+
215+	if (scp->sc_score) {
216+		if (num)
217+			printf("%d", scp - Top_ten + 1);
218+		printf("\t%d\t%s: %s on level %d", scp->sc_score, scp->sc_name,
219+		    Reason[scp->sc_flags], scp->sc_level);
220+		if (scp->sc_flags == 0)
221+		    printf(" by %s", s_killname((char) scp->sc_monster, TRUE));
222+		if ((pp = getpwuid(scp->sc_uid)) == NULL)
223+			printf(" (%d)", scp->sc_uid);
224+		else
225+			printf(" (%s)", pp->pw_name);
226+		putchar('\n');
227+	}
228+	return scp->sc_score;
229+}
230+
231+/*
232+ * insert_score:
233+ *	Insert a score into the top ten list
234+ */
235+void
236+insert_score(SCORE *new)
237+{
238+	SCORE	*scp, *sc2;
239+	int	flags, uid, amount;
240+
241+	flags = new->sc_flags;
242+	uid = new->sc_uid;
243+	amount = new->sc_score;
244+
245+	for (scp = Top_ten; scp < &Top_ten[10]; scp++)
246+		if (amount > scp->sc_score)
247+			break;
248+		else if (flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2)
249+			scp = &Top_ten[10];
250+	if (scp < &Top_ten[10]) {
251+		if (flags != 2)
252+			for (sc2 = scp; sc2 < &Top_ten[10]; sc2++) {
253+			    if (sc2->sc_uid == uid && sc2->sc_flags != 2)
254+				break;
255+			}
256+		else
257+			sc2 = &Top_ten[9];
258+		while (sc2 > scp) {
259+			*sc2 = sc2[-1];
260+			sc2--;
261+		}
262+		*scp = *new;
263+		sc2 = scp;
264+	}
265+}
266+
267+/*
268+ * del_score:
269+ *	Delete a score from the score list.
270+ */
271+void
272+del_score(void)
273+{
274+	SCORE	*scp;
275+	int	i;
276+	int	num;
277+
278+	for (;;) {
279+		printf("Which score? ");
280+		fgets(Buf, BUFSIZ, stdin);
281+		if (Buf[0] == '\n')
282+			return;
283+		sscanf(Buf, "%d", &num);
284+		if (num < 1 || num > 10)
285+			printf("range is 1-10\n");
286+		else
287+			break;
288+	}
289+	num--;
290+	for (scp = &Top_ten[num]; scp < &Top_ten[9]; scp++)
291+		*scp = scp[1];
292+	Top_ten[9].sc_score = 0;
293+	for (i = 0; i < MAXSTR; i++)
294+	    Top_ten[9].sc_name[i] = RN;
295+	Top_ten[9].sc_flags = RN;
296+	Top_ten[9].sc_level = RN;
297+	Top_ten[9].sc_monster = RN;
298+	Top_ten[9].sc_uid = RN;
299+}
A netwait.h
+17, -0
 1@@ -0,0 +1,17 @@
 2+/*
 3+ * Score file structure
 4+ *
 5+ * @(#)netwait.h	4.6 (Berkeley) 02/05/99
 6+ */
 7+
 8+struct sc_ent {
 9+    unsigned int sc_uid;
10+    unsigned short sc_score;
11+    unsigned int sc_flags;
12+    unsigned short sc_monster;
13+    char sc_name[MAXSTR];
14+    unsigned short sc_level;
15+    long sc_time;
16+};
17+
18+typedef struct sc_ent SCORE;
A network.c
+84, -0
 1@@ -0,0 +1,84 @@
 2+/*
 3+ * This file contains misc functions for dealing with armor
 4+ *
 5+ * @(#)network.c	4.14 (Berkeley) 02/05/99
 6+ */
 7+
 8+#include <curses.h>
 9+#include "netprot.h"
10+
11+/*
12+ * wear:
13+ *	The player wants to wear something, so let him/her put it on.
14+ */
15+void
16+wear(void)
17+{
18+    THING *obj;
19+    char *sp;
20+
21+    if ((obj = get_item("wear", ARMOR)) == NULL)
22+	return;
23+    if (Cur_armor != NULL)
24+    {
25+	addmsg("you are already wearing some");
26+	if (!Terse)
27+	    addmsg(".  You'll have to take it off first");
28+	endmsg();
29+	After = FALSE;
30+	return;
31+    }
32+    if (obj->o_type != ARMOR)
33+    {
34+	msg("you can't wear that");
35+	return;
36+    }
37+    waste_time();
38+    obj->o_flags |= ISKNOW;
39+    sp = inv_name(obj, TRUE);
40+    Cur_armor = obj;
41+    if (!Terse)
42+	addmsg("you are now ");
43+    msg("wearing %s", sp);
44+}
45+
46+/*
47+ * take_off:
48+ *	Get the armor off of the players back
49+ */
50+void
51+take_off(void)
52+{
53+    THING *obj;
54+
55+    if ((obj = Cur_armor) == NULL)
56+    {
57+	After = FALSE;
58+	if (Terse)
59+		msg("not wearing armor");
60+	else
61+		msg("you aren't wearing any armor");
62+	return;
63+    }
64+    if (!dropcheck(Cur_armor))
65+	return;
66+    Cur_armor = NULL;
67+    if (Terse)
68+	addmsg("was");
69+    else
70+	addmsg("you used to be");
71+    msg(" wearing %c) %s", obj->o_packch, inv_name(obj, TRUE));
72+}
73+
74+/*
75+ * waste_time:
76+ *	Do nothing but let other things happen
77+ */
78+void
79+waste_time(void)
80+{
81+    do_daemons(BEFORE);
82+    do_fuses(BEFORE);
83+    do_daemons(AFTER);
84+    do_fuses(AFTER);
85+}
A network.h
+82, -0
 1@@ -0,0 +1,82 @@
 2+/*
 3+ * Defines for things used in find.c
 4+ *
 5+ * @(#)network.h	4.35 (Berkeley) 02/05/99
 6+ */
 7+
 8+/*
 9+ * Don't change the constants, since they are used for sizes in many
10+ * places in the program.
11+ */
12+
13+#include <sys/ioctl.h>
14+
15+#undef SIGTSTP
16+
17+#define MAXSTR		1024	/* maximum length of strings */
18+#define MAXLINES	32	/* maximum number of screen lines used */
19+#define MAXCOLS		80	/* maximum number of screen columns used */
20+
21+#define RN		(((Seed = Seed*11109+13849) >> 16) & 0xffff)
22+#ifdef CTRL
23+#undef CTRL
24+#endif
25+#define CTRL(c)		(c & 037)
26+
27+/*
28+ * Now all the global variables
29+ */
30+
31+extern bool	Got_ltc, In_shell, Wizard;
32+
33+extern char	Fruit[], Orig_dsusp, Prbuf[], Whoami[];
34+
35+extern int	Fd;
36+
37+#ifdef TIOCGLTC
38+extern struct ltchars	Ltc;
39+#endif TIOCGLTC
40+
41+/*
42+ * Function types
43+ */
44+
45+#include <stdlib.h>
46+#include <unistd.h>
47+
48+void	auto_save(int sig);
49+void	come_down(void);
50+void	doctor(void);
51+void	end_line(void);
52+void	endit(int sig);
53+void	fatal(char *s);
54+void	getltchars(void);
55+void	land(void);
56+void	leave(int sig);
57+void	my_exit(int st);
58+void	nohaste(void);
59+void	playit(void);
60+void	playltchars(void);
61+void	print_disc(char type);
62+void	quit(int sig);
63+void	resetltchars(void);
64+void	rollwand(void);
65+void	runners(void);
66+void	set_order(short *order, int numthings);
67+void	sight(void);
68+void	stomach(void);
69+void	swander(void);
70+void	tstp(int ignored);
71+void	unconfuse(void);
72+void	unsee(void);
73+void	visuals(void);
74+
75+char	add_line(char *fmt, char *arg);
76+
77+char	*killname(char monst, bool doart);
78+char	*nothing(char type);
79+char	*type_name(int type);
80+
81+#ifdef CHECKTIME
82+void	checkout(int sig);
83+#endif
A packet.c
+486, -0
  1@@ -0,0 +1,486 @@
  2+#include <curses.h>
  3+#include <ctype.h>
  4+#include "netprot.h"
  5+
  6+/*
  7+ * Routines to deal with the pack
  8+ *
  9+ * @(#)packet.c	4.40 (Berkeley) 02/05/99
 10+ */
 11+
 12+/*
 13+ * add_pack:
 14+ *	Pick up an object and add it to the pack.  If the argument is
 15+ *	non-null use it as the linked_list pointer instead of gettting
 16+ *	it off the ground.
 17+ */
 18+void
 19+add_pack(THING *obj, bool silent)
 20+{
 21+    THING *op, *lp;
 22+    bool from_floor;
 23+
 24+    from_floor = FALSE;
 25+    if (obj == NULL)
 26+    {
 27+	if ((obj = find_obj(Hero.y, Hero.x)) == NULL)
 28+	    return;
 29+	from_floor = TRUE;
 30+    }
 31+
 32+    /*
 33+     * Check for and deal with scare monster scrolls
 34+     */
 35+    if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
 36+	if (obj->o_flags & ISFOUND)
 37+	{
 38+	    detach(Lvl_obj, obj);
 39+	    mvaddch(Hero.y, Hero.x, floor_ch());
 40+	    chat(Hero.y, Hero.x) = (Proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
 41+	    discard(obj);
 42+	    msg("the scroll turns to dust as you pick it up");
 43+	    return;
 44+	}
 45+
 46+    if (Pack == NULL)
 47+    {
 48+	Pack = obj;
 49+	obj->o_packch = pack_char();
 50+	Inpack++;
 51+    }
 52+    else
 53+    {
 54+	lp = NULL;
 55+	for (op = Pack; op != NULL; op = next(op))
 56+	{
 57+	    if (op->o_type != obj->o_type)
 58+		lp = op;
 59+	    else
 60+	    {
 61+		while (op->o_type == obj->o_type && op->o_which != obj->o_which)
 62+		{
 63+		    lp = op;
 64+		    if (next(op) == NULL)
 65+			break;
 66+		    else
 67+			op = next(op);
 68+		}
 69+		if (op->o_type == obj->o_type && op->o_which == obj->o_which)
 70+		    if (ISMULT(op->o_type))
 71+		    {
 72+			if (!pack_room(from_floor, obj))
 73+			    return;
 74+			op->o_count++;
 75+dump_it:
 76+			discard(obj);
 77+			obj = op;
 78+			lp = NULL;
 79+			goto out;
 80+		    }
 81+		    else if (obj->o_group)
 82+		    {
 83+			lp = op;
 84+			while (op->o_type == obj->o_type
 85+			    && op->o_which == obj->o_which
 86+			    && op->o_group != obj->o_group)
 87+			{
 88+			    lp = op;
 89+			    if (next(op) == NULL)
 90+				break;
 91+			    else
 92+				op = next(op);
 93+			}
 94+			if (op->o_type == obj->o_type
 95+			    && op->o_which == obj->o_which
 96+			    && op->o_group == obj->o_group)
 97+			{
 98+				op->o_count += obj->o_count;
 99+				Inpack--;
100+				if (!pack_room(from_floor, obj))
101+				    return;
102+				goto dump_it;
103+			}
104+		    }
105+		    else
106+			lp = op;
107+out:
108+		break;
109+	    }
110+	}
111+
112+	if (lp != NULL)
113+	    if (!pack_room(from_floor, obj))
114+		return;
115+	    else
116+	    {
117+		obj->o_packch = pack_char();
118+		next(obj) = next(lp);
119+		prev(obj) = lp;
120+		if (next(lp) != NULL)
121+		    prev(next(lp)) = obj;
122+		next(lp) = obj;
123+	    }
124+    }
125+
126+    obj->o_flags |= ISFOUND;
127+
128+    /*
129+     * If this was the object of something's desire, that monster will
130+     * get mad and run at the hero.
131+     */
132+    for (op = Mlist; op != NULL; op = next(op))
133+	if (op->t_dest = &obj->o_pos)
134+	    op->t_dest = &Hero;
135+
136+    if (obj->o_type == AMULET)
137+	Amulet = TRUE;
138+    /*
139+     * Notify the user
140+     */
141+    if (!silent)
142+    {
143+	if (!Terse)
144+	    addmsg("you now have ");
145+	msg("%s (%c)", inv_name(obj, !Terse), obj->o_packch);
146+    }
147+}
148+
149+/*
150+ * pack_room:
151+ *	See if there's room in the pack.  If not, print out an
152+ *	appropriate message
153+ */
154+bool
155+pack_room(bool from_floor, THING *obj)
156+{
157+    if (++Inpack > MAXPACK)
158+    {
159+	if (!Terse)
160+	    addmsg("there's ");
161+	addmsg("no room");
162+	if (!Terse)
163+	    addmsg(" in your pack");
164+	endmsg();
165+	if (from_floor)
166+	    move_msg(obj);
167+	Inpack = MAXPACK;
168+	return FALSE;
169+    }
170+
171+    if (from_floor)
172+    {
173+	detach(Lvl_obj, obj);
174+	mvaddch(Hero.y, Hero.x, floor_ch());
175+	chat(Hero.y, Hero.x) = (Proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
176+    }
177+
178+    return TRUE;
179+}
180+
181+/*
182+ * leave_pack:
183+ *	Take an item out of the pack
184+ */
185+THING *
186+leave_pack(THING *obj, bool newobj, bool all)
187+{
188+    THING *nobj;
189+
190+    Inpack--;
191+    nobj = obj;
192+    if (obj->o_count > 1 && !all)
193+    {
194+	Last_pick = obj;
195+	obj->o_count--;
196+	if (obj->o_group)
197+	    Inpack++;
198+	if (newobj)
199+	{
200+	    nobj = new_item();
201+	    *nobj = *obj;
202+	    next(nobj) = NULL;
203+	    prev(nobj) = NULL;
204+	    nobj->o_count = 1;
205+	}
206+    }
207+    else
208+    {
209+	Last_pick = NULL;
210+	Pack_used[obj->o_packch - 'a'] = FALSE;
211+	detach(Pack, obj);
212+    }
213+    return nobj;
214+}
215+
216+/*
217+ * pack_char:
218+ *	Return the next unused pack character.
219+ */
220+char
221+pack_char(void)
222+{
223+    bool *bp;
224+
225+    for (bp = Pack_used; *bp; bp++)
226+	continue;
227+    *bp = TRUE;
228+    return (bp - Pack_used) + 'a';
229+}
230+
231+/*
232+ * inventory:
233+ *	List what is in the pack.  Return TRUE if there is something of
234+ *	the given type.
235+ */
236+bool
237+inventory(THING *list, int type)
238+{
239+    static char inv_temp[MAXSTR];
240+
241+    N_objs = 0;
242+    for (; list != NULL; list = next(list))
243+    {
244+	if (type && type != list->o_type && !(type == CALLABLE &&
245+	    list->o_type != FOOD && list->o_type != AMULET) &&
246+	    !(type == R_OR_S && (list->o_type == RING || list->o_type == STICK)))
247+		continue;
248+	N_objs++;
249+#ifdef MASTER
250+	if (!list->o_packch)
251+	    strcpy(inv_temp, "%s");
252+	else
253+#endif
254+	    sprintf(inv_temp, "%c) %%s", list->o_packch);
255+	Msg_esc = TRUE;
256+	if (add_line(inv_temp, inv_name(list, FALSE)) == ESCAPE)
257+	{
258+	    Msg_esc = FALSE;
259+	    msg("");
260+	    return TRUE;
261+	}
262+	Msg_esc = FALSE;
263+    }
264+    if (N_objs == 0)
265+    {
266+	if (Terse)
267+	    msg(type == 0 ? "empty handed" :
268+			    "nothing appropriate");
269+	else
270+	    msg(type == 0 ? "you are empty handed" :
271+			    "you don't have anything appropriate");
272+	return FALSE;
273+    }
274+    end_line();
275+    return TRUE;
276+}
277+
278+/*
279+ * pick_up:
280+ *	Add something to characters pack.
281+ */
282+void
283+pick_up(char ch)
284+{
285+    THING *obj;
286+
287+    if (on(Player, ISLEVIT))
288+	return;
289+
290+    obj = find_obj(Hero.y, Hero.x);
291+    if (Move_on)
292+	move_msg(obj);
293+    else
294+	switch (ch)
295+	{
296+	    case GOLD:
297+		if (obj == NULL)
298+		    return;
299+		money(obj->o_goldval);
300+		detach(Lvl_obj, obj);
301+		discard(obj);
302+		Proom->r_goldval = 0;
303+		break;
304+	    default:
305+#ifdef MASTER
306+		debug("Where did you pick a '%s' up???", unctrl(ch));
307+#endif
308+	    case ARMOR:
309+	    case POTION:
310+	    case FOOD:
311+	    case WEAPON:
312+	    case SCROLL:	
313+	    case AMULET:
314+	    case RING:
315+	    case STICK:
316+		add_pack((THING *) NULL, FALSE);
317+		break;
318+	}
319+}
320+
321+/*
322+ * move_msg:
323+ *	Print out the message if you are just moving onto an object
324+ */
325+void
326+move_msg(THING *obj)
327+{
328+    if (!Terse)
329+	addmsg("you ");
330+    msg("moved onto %s", inv_name(obj, TRUE));
331+}
332+
333+/*
334+ * picky_inven:
335+ *	Allow player to inventory a single item
336+ */
337+void
338+picky_inven(void)
339+{
340+    THING *obj;
341+    char mch;
342+
343+    if (Pack == NULL)
344+	msg("you aren't carrying anything");
345+    else if (next(Pack) == NULL)
346+	msg("a) %s", inv_name(Pack, FALSE));
347+    else
348+    {
349+	msg(Terse ? "item: " : "which item do you wish to inventory: ");
350+	Mpos = 0;
351+	if ((mch = readchar()) == ESCAPE)
352+	{
353+	    msg("");
354+	    return;
355+	}
356+	for (obj = Pack; obj != NULL; obj = next(obj))
357+	    if (mch == obj->o_packch)
358+	    {
359+		msg("%c) %s", mch, inv_name(obj, FALSE));
360+		return;
361+	    }
362+	msg("'%s' not in pack", unctrl(mch));
363+    }
364+}
365+
366+/*
367+ * get_item:
368+ *	Pick something out of a pack for a purpose
369+ */
370+THING *
371+get_item(char *purpose, int type)
372+{
373+    THING *obj;
374+    char ch;
375+
376+    if (Pack == NULL)
377+	msg("you aren't carrying anything");
378+    else if (Again)
379+	if (Last_pick)
380+	    return Last_pick;
381+	else
382+	    msg("you ran out");
383+    else
384+    {
385+	for (;;)
386+	{
387+	    if (!Terse)
388+		addmsg("which object do you want to ");
389+	    addmsg(purpose);
390+	    if (Terse)
391+		addmsg(" what");
392+	    msg("? (* for list): ");
393+	    ch = readchar();
394+	    Mpos = 0;
395+	    /*
396+	     * Give the poor player a chance to abort the command
397+	     */
398+	    if (ch == ESCAPE)
399+	    {
400+		reset_last();
401+		After = FALSE;
402+		msg("");
403+		return NULL;
404+	    }
405+	    N_objs = 1;		/* normal case: person types one char */
406+	    if (ch == '*')
407+	    {
408+		Mpos = 0;
409+		if (inventory(Pack, type) == 0)
410+		{
411+		    After = FALSE;
412+		    return NULL;
413+		}
414+		continue;
415+	    }
416+	    for (obj = Pack; obj != NULL; obj = next(obj))
417+		if (obj->o_packch == ch)
418+		    break;
419+	    if (obj == NULL)
420+	    {
421+		msg("that's not a valid item");
422+		continue;
423+	    }
424+	    else 
425+		return obj;
426+	}
427+    }
428+    return NULL;
429+}
430+
431+/*
432+ * money:
433+ *	Add or subtract gold from the pack
434+ */
435+void
436+money(int value)
437+{
438+    Purse += value;
439+    mvaddch(Hero.y, Hero.x, floor_ch());
440+    chat(Hero.y, Hero.x) = (Proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
441+    if (value > 0)
442+    {
443+	if (!Terse)
444+	    addmsg("you found ");
445+	msg("%d gold pieces", value);
446+    }
447+}
448+
449+/*
450+ * floor_ch:
451+ *	Return the appropriate floor character for her room
452+ */
453+char
454+floor_ch(void)
455+{
456+    if (Proom->r_flags & ISGONE)
457+	return PASSAGE;
458+    return (show_floor() ? FLOOR : ' ');
459+}
460+
461+/*
462+ * floor_at:
463+ *	Return the character at hero's position, taking See_floor
464+ *	into account
465+ */
466+char
467+floor_at(void)
468+{
469+    char ch;
470+
471+    ch = chat(Hero.y, Hero.x);
472+    if (ch == FLOOR)
473+	ch = floor_ch();
474+    return ch;
475+}
476+
477+/*
478+ * reset_last:
479+ *	Reset the last command when the current one is aborted
480+ */
481+void
482+reset_last(void)
483+{
484+    Last_comm = L_last_comm;
485+    Last_dir = L_last_dir;
486+    Last_pick = L_last_pick;
487+}
A pipes.c
+489, -0
  1@@ -0,0 +1,489 @@
  2+/*
  3+ * This file has all the code for the option command.  I would rather
  4+ * this command were not necessary, but it is the only way to keep the
  5+ * wolves off of my back.
  6+ *
  7+ * @(#)pipes.c	4.24 (Berkeley) 05/10/83
  8+ */
  9+
 10+#include <curses.h>
 11+#include <ctype.h>
 12+#include "netprot.h"
 13+
 14+#define	EQSTR(a, b, c)	(strncmp(a, b, c) == 0)
 15+
 16+#define	NUM_OPTS	(sizeof optlist / sizeof (OPTION))
 17+
 18+#ifndef attron
 19+# define	erasechar()	_tty.sg_erase
 20+# define	killchar()	_tty.sg_kill
 21+#endif
 22+
 23+/*
 24+ * description of an option and what to do with it
 25+ */
 26+struct optstruct {
 27+    char	*o_name;	/* option name */
 28+    char	*o_prompt;	/* prompt for interactive entry */
 29+    void	*o_opt;		/* pointer to thing to set */
 30+				/* function to print value */
 31+    void	(*o_putfunc)(void *opt);
 32+				/* function to get value interactively */
 33+    int		(*o_getfunc)(void *opt, WINDOW *win);
 34+};
 35+
 36+typedef struct optstruct	OPTION;
 37+
 38+void	pr_optname(OPTION *op);
 39+
 40+OPTION	optlist[] = {
 41+    {"terse",	 "Terse output",
 42+		 (int *) &Terse,	put_bool,	get_bool	},
 43+    {"flush",	 "Flush typeahead during battle",
 44+		(int *) &Fight_flush,	put_bool,	get_bool	},
 45+    {"jump",	 "Show position only at end of run",
 46+		(int *) &Jump,		put_bool,	get_bool	},
 47+    {"seefloor", "Show the lamp-illuminated floor",
 48+		(int *) &See_floor,	put_bool,	get_sf		},
 49+    {"passgo",	"Follow turnings in passageways",
 50+		(int *) &Passgo,	put_bool,	get_bool	},
 51+    {"tombstone", "Print out tombstone when killed",
 52+		(int *) &Tombstone,	put_bool,	get_bool	},
 53+    {"inven",	"Inventory style",
 54+		(int *) &Inv_type,	put_inv_t,	get_inv_t	},
 55+    {"name",	 "Name",
 56+		(int *) Whoami,		put_str,	get_str		},
 57+    {"fruit",	 "Fruit",
 58+		(int *) Fruit,		put_str,	get_str		},
 59+    {"file",	 "Save file",
 60+		(int *) File_name,	put_str,	get_str		}
 61+};
 62+
 63+/*
 64+ * option:
 65+ *	Print and then set options from the terminal
 66+ */
 67+void
 68+option(void)
 69+{
 70+    OPTION	*op;
 71+    int		retval;
 72+
 73+    wclear(Hw);
 74+    /*
 75+     * Display current values of options
 76+     */
 77+    for (op = optlist; op < &optlist[NUM_OPTS]; op++)
 78+    {
 79+	pr_optname(op);
 80+	(*op->o_putfunc)(op->o_opt);
 81+	waddch(Hw, '\n');
 82+    }
 83+    /*
 84+     * Set values
 85+     */
 86+    wmove(Hw, 0, 0);
 87+    for (op = optlist; op < &optlist[NUM_OPTS]; op++)
 88+    {
 89+	pr_optname(op);
 90+	if ((retval = (*op->o_getfunc)(op->o_opt, Hw)))
 91+	    if (retval == QUIT)
 92+		break;
 93+	    else if (op > optlist) {	/* MINUS */
 94+		wmove(Hw, (op - optlist) - 1, 0);
 95+		op -= 2;
 96+	    }
 97+	    else	/* trying to back up beyond the top */
 98+	    {
 99+		putchar('\007');
100+		wmove(Hw, 0, 0);
101+		op--;
102+	    }
103+    }
104+    /*
105+     * Switch back to original screen
106+     */
107+    wmove(Hw, LINES - 1, 0);
108+    waddstr(Hw, "--Press space to continue--");
109+    wrefresh(Hw);
110+    wait_for(' ');
111+    clearok(curscr, TRUE);
112+#ifdef attron
113+    touchwin(stdscr);
114+#endif
115+    After = FALSE;
116+}
117+
118+/*
119+ * pr_optname:
120+ *	Print out the option name prompt
121+ */
122+void
123+pr_optname(OPTION *op)
124+{
125+    wprintw(Hw, "%s (\"%s\"): ", op->o_prompt, op->o_name);
126+}
127+
128+/*
129+ * put_bool
130+ *	Put out a boolean
131+ */
132+void
133+put_bool(void *b)
134+{
135+    waddstr(Hw, *(bool *) b ? "True" : "False");
136+}
137+
138+/*
139+ * put_str:
140+ *	Put out a string
141+ */
142+void
143+put_str(void *str)
144+{
145+    waddstr(Hw, (char *) str);
146+}
147+
148+/*
149+ * put_inv_t:
150+ *	Put out an inventory type
151+ */
152+void
153+put_inv_t(void *ip)
154+{
155+    waddstr(Hw, Inv_t_name[*(int *) ip]);
156+}
157+
158+/*
159+ * get_bool:
160+ *	Allow changing a boolean option and print it out
161+ */
162+int
163+get_bool(void *vp, WINDOW *win)
164+{
165+    bool *bp = (bool *) vp;
166+    int oy, ox;
167+    bool op_bad;
168+
169+    op_bad = TRUE;
170+    getyx(win, oy, ox);
171+    waddstr(win, *bp ? "True" : "False");
172+    while (op_bad)	
173+    {
174+	wmove(win, oy, ox);
175+	wrefresh(win);
176+	switch (readchar())
177+	{
178+	    case 't':
179+	    case 'T':
180+		*bp = TRUE;
181+		op_bad = FALSE;
182+		break;
183+	    case 'f':
184+	    case 'F':
185+		*bp = FALSE;
186+		op_bad = FALSE;
187+		break;
188+	    case '\n':
189+	    case '\r':
190+		op_bad = FALSE;
191+		break;
192+	    case ESCAPE:
193+		return QUIT;
194+	    case '-':
195+		return MINUS;
196+	    default:
197+		wmove(win, oy, ox + 10);
198+		waddstr(win, "(T or F)");
199+	}
200+    }
201+    wmove(win, oy, ox);
202+    waddstr(win, *bp ? "True" : "False");
203+    waddch(win, '\n');
204+    return NORM;
205+}
206+
207+/*
208+ * get_sf:
209+ *	Change value and handle transition problems from See_floor to
210+ *	!See_floor.
211+ */
212+int
213+get_sf(void *vp, WINDOW *win)
214+{
215+    bool	*bp = (bool *) vp;
216+    bool	was_sf;
217+    int		retval;
218+
219+    was_sf = See_floor;
220+    retval = get_bool(bp, win);
221+    if (retval == QUIT) return(QUIT);
222+    if (was_sf != See_floor)
223+    {
224+	if (!See_floor) {
225+	    See_floor = TRUE;
226+	    erase_lamp(&Hero, Proom);
227+	    See_floor = FALSE;
228+	}
229+	else
230+	    look(FALSE);
231+    }
232+    return(NORM);
233+}
234+
235+/*
236+ * get_str:
237+ *	Set a string option
238+ */
239+#define MAXINP	50	/* max string to read from terminal or environment */
240+
241+int
242+get_str(void *vopt, WINDOW *win)
243+{
244+    char *opt = (char *) vopt;
245+    char *sp;
246+    int c, oy, ox;
247+    int i;
248+    static char buf[MAXSTR];
249+
250+    getyx(win, oy, ox);
251+    wrefresh(win);
252+    /*
253+     * loop reading in the string, and put it in a temporary buffer
254+     */
255+    for (sp = buf; (c = readchar()) != '\n' && c != '\r' && c != ESCAPE;
256+	wclrtoeol(win), wrefresh(win))
257+    {
258+	if (c == -1)
259+	    continue;
260+	else if (c == erasechar())	/* process erase character */
261+	{
262+	    if (sp > buf)
263+	    {
264+		sp--;
265+		for (i = strlen(unctrl(*sp)); i; i--)
266+		    waddch(win, '\b');
267+	    }
268+	    continue;
269+	}
270+	else if (c == killchar())	/* process kill character */
271+	{
272+	    sp = buf;
273+	    wmove(win, oy, ox);
274+	    continue;
275+	}
276+	else if (sp == buf)
277+	{
278+	    if (c == '-' && win != stdscr)
279+		break;
280+	    else if (c == '~')
281+	    {
282+		strcpy(buf, Home);
283+		waddstr(win, Home);
284+		sp += strlen(Home);
285+		continue;
286+	    }
287+	}
288+	if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' '))
289+	    putchar(CTRL('G'));
290+	else
291+	{
292+	    *sp++ = c;
293+	    waddstr(win, unctrl(c));
294+	}
295+    }
296+    *sp = '\0';
297+    if (sp > buf)	/* only change option if something has been typed */
298+	strucpy(opt, buf, strlen(buf));
299+    mvwprintw(win, oy, ox, "%s\n", opt);
300+    wrefresh(win);
301+    if (win == stdscr)
302+	Mpos += sp - buf;
303+    if (c == '-')
304+	return MINUS;
305+    else if (c == ESCAPE)
306+	return QUIT;
307+    else
308+	return NORM;
309+}
310+
311+/*
312+ * get_inv_t
313+ *	Get an inventory type name
314+ */
315+int
316+get_inv_t(void *vp, WINDOW *win)
317+{
318+    int *ip = (int *) vp;
319+    int oy, ox;
320+    bool op_bad;
321+
322+    op_bad = TRUE;
323+    getyx(win, oy, ox);
324+    waddstr(win, Inv_t_name[*ip]);
325+    while (op_bad)	
326+    {
327+	wmove(win, oy, ox);
328+	wrefresh(win);
329+	switch (readchar())
330+	{
331+	    case 'o':
332+	    case 'O':
333+		*ip = INV_OVER;
334+		op_bad = FALSE;
335+		break;
336+	    case 's':
337+	    case 'S':
338+		*ip = INV_SLOW;
339+		op_bad = FALSE;
340+		break;
341+	    case 'c':
342+	    case 'C':
343+		*ip = INV_CLEAR;
344+		op_bad = FALSE;
345+		break;
346+	    case '\n':
347+	    case '\r':
348+		op_bad = FALSE;
349+		break;
350+	    case ESCAPE:
351+		return QUIT;
352+	    case '-':
353+		return MINUS;
354+	    default:
355+		wmove(win, oy, ox + 15);
356+		waddstr(win, "(O, S, or C)");
357+	}
358+    }
359+    mvwprintw(win, oy, ox, "%s\n", Inv_t_name[*ip]);
360+    return NORM;
361+}
362+	
363+
364+#ifdef MASTER
365+/*
366+ * get_num:
367+ *	Get a numeric option
368+ */
369+int
370+get_num(void *vp, WINDOW *win)
371+{
372+    short *opt = (short *) vp;
373+    int i;
374+    static char buf[MAXSTR];
375+
376+    if ((i = get_str(buf, win)) == NORM)
377+	*opt = atoi(buf);
378+    return i;
379+}
380+#endif
381+
382+/*
383+ * parse_opts:
384+ *	Parse options from string, usually taken from the environment.
385+ *	The string is a series of comma seperated values, with booleans
386+ *	being stated as "name" (true) or "noname" (false), and strings
387+ *	being "name=....", with the string being defined up to a comma
388+ *	or the end of the entire option string.
389+ */
390+void
391+parse_opts(char *str)
392+{
393+    char *sp;
394+    OPTION *op;
395+    int len;
396+    char **i;
397+    char *start;
398+
399+    while (*str)
400+    {
401+	/*
402+	 * Get option name
403+	 */
404+	for (sp = str; isalpha(*sp); sp++)
405+	    continue;
406+	len = sp - str;
407+	/*
408+	 * Look it up and deal with it
409+	 */
410+	for (op = optlist; op < &optlist[NUM_OPTS]; op++)
411+	    if (EQSTR(str, op->o_name, len))
412+	    {
413+		if (op->o_putfunc == put_bool)	/* if option is a boolean */
414+		    *(bool *)op->o_opt = TRUE;	/* NOSTRICT */
415+		else				/* string option */
416+		{
417+		    /*
418+		     * Skip to start of string value
419+		     */
420+		    for (str = sp + 1; *str == '='; str++)
421+			continue;
422+		    if (*str == '~')
423+		    {
424+			strcpy((char *) op->o_opt, Home);	  /* NOSTRICT */
425+			start = (char *) op->o_opt + strlen(Home);/* NOSTRICT */
426+			while (*++str == '/')
427+			    continue;
428+		    }
429+		    else
430+			start = (char *) op->o_opt;	/* NOSTRICT */
431+		    /*
432+		     * Skip to end of string value
433+		     */
434+		    for (sp = str + 1; *sp && *sp != ','; sp++)
435+			continue;
436+		    /*
437+		     * check for type of inventory
438+		     */
439+		    if (op->o_putfunc == put_inv_t)
440+		    {
441+			if (islower(*str))
442+			    *str = toupper(*str);
443+			for (i = Inv_t_name; i <= &Inv_t_name[INV_CLEAR]; i++)
444+			    if (strncmp(str, *i, sp - str) == 0)
445+			    {
446+				Inv_type = i - Inv_t_name;
447+				break;
448+			    }
449+		    }
450+		    else
451+			strucpy(start, str, sp - str);
452+		}
453+		break;
454+	    }
455+	    /*
456+	     * check for "noname" for booleans
457+	     */
458+	    else if (op->o_putfunc == put_bool
459+	      && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
460+	    {
461+		*(bool *)op->o_opt = FALSE;	/* NOSTRICT */
462+		break;
463+	    }
464+
465+	/*
466+	 * skip to start of next option name
467+	 */
468+	while (*sp && !isalpha(*sp))
469+	    sp++;
470+	str = sp;
471+    }
472+}
473+
474+/*
475+ * strucpy:
476+ *	Copy string using unctrl for things
477+ */
478+void
479+strucpy(char *s1, char *s2, int len)
480+{
481+    if (len > MAXINP)
482+	len = MAXINP;
483+    while (len--)
484+    {
485+	if (isprint(*s2) || *s2 == ' ')
486+	    *s1++ = *s2;
487+	s2++;
488+    }
489+    *s1 = '\0';
490+}
A rcopy.c
+701, -0
  1@@ -0,0 +1,701 @@
  2+/*
  3+ * Contains functions for dealing with things like potions, scrolls,
  4+ * and other items.
  5+ *
  6+ * @(#)rcopy.c	4.53 (Berkeley) 02/05/99
  7+ */
  8+
  9+#include <curses.h>
 10+#ifdef	attron
 11+#include <term.h>
 12+#endif	attron
 13+#include <ctype.h>
 14+#include "netprot.h"
 15+
 16+/*
 17+ * inv_name:
 18+ *	Return the name of something as it would appear in an
 19+ *	inventory.
 20+ */
 21+char *
 22+inv_name(THING *obj, bool drop)
 23+{
 24+    char *pb;
 25+    struct obj_info *op;
 26+    char *sp;
 27+    int which;
 28+
 29+    pb = Prbuf;
 30+    which = obj->o_which;
 31+    switch (obj->o_type)
 32+    {
 33+        when POTION:
 34+	    nameit(obj, "potion", P_colors[which], &Pot_info[which], nullstr);
 35+	when RING:
 36+	    nameit(obj, "ring", R_stones[which], &Ring_info[which], ring_num);
 37+	when STICK:
 38+	    nameit(obj, Ws_type[which], Ws_made[which], &Ws_info[which], charge_str);
 39+	when SCROLL:
 40+	    if (obj->o_count == 1)
 41+	    {
 42+		strcpy(pb, "A scroll ");
 43+		pb = &Prbuf[9];
 44+	    }
 45+	    else
 46+	    {
 47+		sprintf(pb, "%d scrolls ", obj->o_count);
 48+		pb = &Prbuf[strlen(Prbuf)];
 49+	    }
 50+	    op = &Scr_info[which];
 51+	    if (op->oi_know)
 52+		sprintf(pb, "of %s", op->oi_name);
 53+	    else if (op->oi_guess)
 54+		sprintf(pb, "called %s", op->oi_guess);
 55+	    else
 56+		sprintf(pb, "titled '%s'", S_names[which]);
 57+	when FOOD:
 58+	    if (which == 1)
 59+		if (obj->o_count == 1)
 60+		    sprintf(pb, "A%s %s", vowelstr(Fruit), Fruit);
 61+		else
 62+		    sprintf(pb, "%d %ss", obj->o_count, Fruit);
 63+	    else
 64+		if (obj->o_count == 1)
 65+		    strcpy(pb, "Some food");
 66+		else
 67+		    sprintf(pb, "%d rations of food", obj->o_count);
 68+	when WEAPON:
 69+	    sp = Weap_info[which].oi_name;
 70+	    if (obj->o_count > 1)
 71+		sprintf(pb, "%d ", obj->o_count);
 72+	    else
 73+		sprintf(pb, "A%s ", vowelstr(sp));
 74+	    pb = &Prbuf[strlen(Prbuf)];
 75+	    if (obj->o_flags & ISKNOW)
 76+		sprintf(pb, "%s %s", num(obj->o_hplus,obj->o_dplus,WEAPON), sp);
 77+	    else
 78+		sprintf(pb, "%s", sp);
 79+	    if (obj->o_count > 1)
 80+		strcat(pb, "s");
 81+	    if (obj->o_label != NULL)
 82+	    {
 83+		pb = &Prbuf[strlen(Prbuf)];
 84+		sprintf(pb, " called %s", obj->o_label);
 85+	    }
 86+	when ARMOR:
 87+	    sp = Arm_info[which].oi_name;
 88+	    if (obj->o_flags & ISKNOW)
 89+	    {
 90+		sprintf(pb, "%s %s [",
 91+		    num(A_class[which] - obj->o_arm, 0, ARMOR), sp);
 92+		if (!Terse)
 93+		    strcat(pb, "protection ");
 94+		pb = &Prbuf[strlen(Prbuf)];
 95+		sprintf(pb, "%d]", 10 - obj->o_arm);
 96+	    }
 97+	    else
 98+		sprintf(pb, "%s", sp);
 99+	    if (obj->o_label != NULL)
100+	    {
101+		pb = &Prbuf[strlen(Prbuf)];
102+		sprintf(pb, " called %s", obj->o_label);
103+	    }
104+	when AMULET:
105+	    strcpy(pb, "The Amulet of Yendor");
106+	when GOLD:
107+	    sprintf(Prbuf, "%d Gold pieces", obj->o_goldval);
108+#ifdef MASTER
109+	otherwise:
110+	    debug("Picked up something funny %s", unctrl(obj->o_type));
111+	    sprintf(pb, "Something bizarre %s", unctrl(obj->o_type));
112+#endif
113+    }
114+    if (Inv_describe)
115+    {
116+	if (obj == Cur_armor)
117+	    strcat(pb, " (being worn)");
118+	if (obj == Cur_weapon)
119+	    strcat(pb, " (weapon in hand)");
120+	if (obj == Cur_ring[LEFT])
121+	    strcat(pb, " (on left hand)");
122+	else if (obj == Cur_ring[RIGHT])
123+	    strcat(pb, " (on right hand)");
124+    }
125+    if (drop && isupper(Prbuf[0]))
126+	Prbuf[0] = tolower(Prbuf[0]);
127+    else if (!drop && islower(*Prbuf))
128+	*Prbuf = toupper(*Prbuf);
129+    Prbuf[MAXSTR-1] = '\0';
130+    return Prbuf;
131+}
132+
133+/*
134+ * drop:
135+ *	Put something down
136+ */
137+void
138+drop(void)
139+{
140+    char ch;
141+    THING *obj;
142+
143+    ch = chat(Hero.y, Hero.x);
144+    if (ch != FLOOR && ch != PASSAGE)
145+    {
146+	After = FALSE;
147+	msg("there is something there already");
148+	return;
149+    }
150+    if ((obj = get_item("drop", 0)) == NULL)
151+	return;
152+    if (!dropcheck(obj))
153+	return;
154+    obj = leave_pack(obj, TRUE, !ISMULT(obj->o_type));
155+    /*
156+     * Link it into the level object list
157+     */
158+    attach(Lvl_obj, obj);
159+    chat(Hero.y, Hero.x) = obj->o_type;
160+    flat(Hero.y, Hero.x) |= F_DROPPED;
161+    obj->o_pos = Hero;
162+    if (obj->o_type == AMULET)
163+	Amulet = FALSE;
164+    msg("dropped %s", inv_name(obj, TRUE));
165+}
166+
167+/*
168+ * dropcheck:
169+ *	Do special checks for dropping or unweilding|unwearing|unringing
170+ */
171+bool
172+dropcheck(THING *obj)
173+{
174+    if (obj == NULL)
175+	return TRUE;
176+    if (obj != Cur_armor && obj != Cur_weapon
177+	&& obj != Cur_ring[LEFT] && obj != Cur_ring[RIGHT])
178+	    return TRUE;
179+    if (obj->o_flags & ISCURSED)
180+    {
181+	msg("you can't.  It appears to be cursed");
182+	return FALSE;
183+    }
184+    if (obj == Cur_weapon)
185+	Cur_weapon = NULL;
186+    else if (obj == Cur_armor)
187+    {
188+	waste_time();
189+	Cur_armor = NULL;
190+    }
191+    else
192+    {
193+	Cur_ring[obj == Cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
194+	switch (obj->o_which)
195+	{
196+	    case R_ADDSTR:
197+		chg_str(-obj->o_arm);
198+		break;
199+	    case R_SEEINVIS:
200+		unsee();
201+		extinguish(unsee);
202+		break;
203+	}
204+    }
205+    return TRUE;
206+}
207+
208+/*
209+ * new_thing:
210+ *	Return a new thing
211+ */
212+THING *
213+new_thing(void)
214+{
215+    THING *cur;
216+    int r;
217+
218+    cur = new_item();
219+    cur->o_hplus = 0;
220+    cur->o_dplus = 0;
221+    cur->o_damage = cur->o_hurldmg = "0x0";
222+    cur->o_arm = 11;
223+    cur->o_count = 1;
224+    cur->o_group = 0;
225+    cur->o_flags = 0;
226+    /*
227+     * Decide what kind of object it will be
228+     * If we haven't had food for a while, let it be food.
229+     */
230+    switch (No_food > 3 ? 2 : pick_one(Things, NUMTHINGS))
231+    {
232+	when 0:
233+	    cur->o_type = POTION;
234+	    cur->o_which = pick_one(Pot_info, MAXPOTIONS);
235+	when 1:
236+	    cur->o_type = SCROLL;
237+	    cur->o_which = pick_one(Scr_info, MAXSCROLLS);
238+	when 2:
239+	    cur->o_type = FOOD;
240+	    No_food = 0;
241+	    if (rnd(10) != 0)
242+		cur->o_which = 0;
243+	    else
244+		cur->o_which = 1;
245+	when 3:
246+	    init_weapon(cur, pick_one(Weap_info, MAXWEAPONS));
247+	    if ((r = rnd(100)) < 10)
248+	    {
249+		cur->o_flags |= ISCURSED;
250+		cur->o_hplus -= rnd(3) + 1;
251+	    }
252+	    else if (r < 15)
253+		cur->o_hplus += rnd(3) + 1;
254+	when 4:
255+	    cur->o_type = ARMOR;
256+	    cur->o_which = pick_one(Arm_info, MAXARMORS);
257+	    cur->o_arm = A_class[cur->o_which];
258+	    if ((r = rnd(100)) < 20)
259+	    {
260+		cur->o_flags |= ISCURSED;
261+		cur->o_arm += rnd(3) + 1;
262+	    }
263+	    else if (r < 28)
264+		cur->o_arm -= rnd(3) + 1;
265+	when 5:
266+	    cur->o_type = RING;
267+	    cur->o_which = pick_one(Ring_info, MAXRINGS);
268+	    switch (cur->o_which)
269+	    {
270+		when R_ADDSTR:
271+		case R_PROTECT:
272+		case R_ADDHIT:
273+		case R_ADDDAM:
274+		    if ((cur->o_arm = rnd(3)) == 0)
275+		    {
276+			cur->o_arm = -1;
277+			cur->o_flags |= ISCURSED;
278+		    }
279+		when R_AGGR:
280+		case R_TELEPORT:
281+		    cur->o_flags |= ISCURSED;
282+	    }
283+	when 6:
284+	    cur->o_type = STICK;
285+	    cur->o_which = pick_one(Ws_info, MAXSTICKS);
286+	    fix_stick(cur);
287+#ifdef MASTER
288+	otherwise:
289+	    debug("Picked a bad kind of object");
290+	    wait_for(' ');
291+#endif
292+    }
293+    return cur;
294+}
295+
296+/*
297+ * pick_one:
298+ *	Pick an item out of a list of nitems possible objects
299+ */
300+int
301+pick_one(struct obj_info *info, int nitems)
302+{
303+    struct obj_info *end;
304+    struct obj_info *start;
305+    int i;
306+
307+    start = info;
308+    for (end = &info[nitems], i = rnd(100); info < end; info++)
309+	if (i < info->oi_prob)
310+	    break;
311+    if (info == end)
312+    {
313+#ifdef MASTER
314+	if (Wizard)
315+	{
316+	    msg("bad pick_one: %d from %d items", i, nitems);
317+	    for (info = start; info < end; info++)
318+		msg("%s: %d%%", info->oi_name, info->oi_prob);
319+	}
320+#endif
321+	info = start;
322+    }
323+    return info - start;
324+}
325+
326+/*
327+ * discovered:
328+ *	list what the player has discovered in this game of a certain type
329+ */
330+static int Line_cnt = 0;
331+
332+static bool Newpage = FALSE;
333+
334+static char *Lastfmt, *Lastarg;
335+
336+void
337+discovered(void)
338+{
339+    char ch;
340+    bool disc_list;
341+
342+    do {
343+	disc_list = FALSE;
344+	if (!Terse)
345+	    addmsg("for ");
346+	addmsg("what type");
347+	if (!Terse)
348+	    addmsg(" of object do you want a list");
349+	msg("? (* for all)");
350+	ch = readchar();
351+	switch (ch)
352+	{
353+	    case ESCAPE:
354+		msg("");
355+		return;
356+	    case POTION:
357+	    case SCROLL:
358+	    case RING:
359+	    case STICK:
360+	    case '*':
361+		disc_list = TRUE;
362+		break;
363+	    default:
364+		if (Terse)
365+		    msg("Not a type");
366+		else
367+		    msg("Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK);
368+	}
369+    } while (!disc_list);
370+    if (ch == '*')
371+    {
372+	print_disc(POTION);
373+	add_line("", NULL);
374+	print_disc(SCROLL);
375+	add_line("", NULL);
376+	print_disc(RING);
377+	add_line("", NULL);
378+	print_disc(STICK);
379+	end_line();
380+    }
381+    else
382+    {
383+	print_disc(ch);
384+	end_line();
385+    }
386+}
387+
388+/*
389+ * print_disc:
390+ *	Print what we've discovered of type 'type'
391+ */
392+
393+#define MAX4(a,b,c,d)	(a > b ? (a > c ? (a > d ? a : d) : (c > d ? c : d)) : (b > c ? (b > d ? b : d) : (c > d ? c : d)))
394+
395+void
396+print_disc(char type)
397+{
398+    struct obj_info *info;
399+    int i, maxnum, num_found;
400+    static THING obj;
401+    static short order[MAX4(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)];
402+
403+    switch (type)
404+    {
405+	case SCROLL:
406+	    maxnum = MAXSCROLLS;
407+	    info = Scr_info;
408+	    break;
409+	case POTION:
410+	    maxnum = MAXPOTIONS;
411+	    info = Pot_info;
412+	    break;
413+	case RING:
414+	    maxnum = MAXRINGS;
415+	    info = Ring_info;
416+	    break;
417+	case STICK:
418+	    maxnum = MAXSTICKS;
419+	    info = Ws_info;
420+	    break;
421+    }
422+    set_order(order, maxnum);
423+    obj.o_count = 1;
424+    obj.o_flags = 0;
425+    num_found = 0;
426+    for (i = 0; i < maxnum; i++)
427+	if (info[order[i]].oi_know || info[order[i]].oi_guess)
428+	{
429+	    obj.o_type = type;
430+	    obj.o_which = order[i];
431+	    add_line("%s", inv_name(&obj, FALSE));
432+	    num_found++;
433+	}
434+    if (num_found == 0)
435+	add_line(nothing(type), NULL);
436+}
437+
438+/*
439+ * set_order:
440+ *	Set up order for list
441+ */
442+void
443+set_order(short *order, int numthings)
444+{
445+    int i, r, t;
446+
447+    for (i = 0; i< numthings; i++)
448+	order[i] = i;
449+
450+    for (i = numthings; i > 0; i--)
451+    {
452+	r = rnd(i);
453+	t = order[i - 1];
454+	order[i - 1] = order[r];
455+	order[r] = t;
456+    }
457+}
458+
459+/*
460+ * add_line:
461+ *	Add a line to the list of discoveries
462+ */
463+/* VARARGS1 */
464+char
465+add_line(char *fmt, char *arg)
466+{
467+    WINDOW *tw, *sw;
468+    int x, y;
469+    char *prompt = "--Press space to continue--";
470+    static int maxlen = -1;
471+
472+    if (Line_cnt == 0)
473+    {
474+	    wclear(Hw);
475+	    if (Inv_type == INV_SLOW)
476+		Mpos = 0;
477+    }
478+    if (Inv_type == INV_SLOW)
479+    {
480+	if (*fmt != '\0')
481+	    if (msg(fmt, arg) == ESCAPE)
482+		return ESCAPE;
483+	Line_cnt++;
484+    }
485+    else
486+    {
487+	if (maxlen < 0)
488+	    maxlen = strlen(prompt);
489+	if (Line_cnt >= LINES - 1 || fmt == NULL)
490+	{
491+	    if (Inv_type == INV_OVER && fmt == NULL && !Newpage)
492+	    {
493+		msg("");
494+		refresh();
495+		tw = newwin(Line_cnt + 1, maxlen + 2, 0, COLS - maxlen - 3);
496+		sw = subwin(tw, Line_cnt + 1, maxlen + 1, 0, COLS - maxlen - 2);
497+		for (y = 0; y <= Line_cnt; y++)
498+		{
499+		    wmove(sw, y, 0);
500+		    for (x = 0; x <= maxlen; x++)
501+			waddch(sw, mvwinch(Hw, y, x));
502+		}
503+		wmove(tw, Line_cnt, 1);
504+		waddstr(tw, prompt);
505+		/*
506+		 * if there are lines below, use 'em
507+		 */
508+		if (LINES > NUMLINES)
509+		    if (NUMLINES + Line_cnt > LINES)
510+			mvwin(tw, LINES - (Line_cnt + 1), COLS - maxlen - 3);
511+		    else
512+			mvwin(tw, NUMLINES, 0);
513+		touchwin(tw);
514+		wrefresh(tw);
515+		wait_for(' ');
516+#ifndef	attron
517+		if (CE)
518+#else	attron
519+		if (clr_eol)
520+#endif	attron
521+		{
522+		    werase(tw);
523+		    leaveok(tw, TRUE);
524+		    wrefresh(tw);
525+		}
526+		delwin(tw);
527+		touchwin(stdscr);
528+	    }
529+	    else
530+	    {
531+		wmove(Hw, LINES - 1, 0);
532+		waddstr(Hw, prompt);
533+		wrefresh(Hw);
534+		wait_for(' ');
535+		clearok(curscr, TRUE);
536+		wclear(Hw);
537+#ifdef	attron
538+		touchwin(stdscr);
539+#endif	attron
540+	    }
541+	    Newpage = TRUE;
542+	    Line_cnt = 0;
543+	    maxlen = strlen(prompt);
544+	}
545+	if (fmt != NULL && !(Line_cnt == 0 && *fmt == '\0'))
546+	{
547+	    mvwprintw(Hw, Line_cnt++, 0, fmt, arg);
548+	    getyx(Hw, y, x);
549+	    if (maxlen < x)
550+		maxlen = x;
551+	    Lastfmt = fmt;
552+	    Lastarg = arg;
553+	}
554+    }
555+    return ~ESCAPE;
556+}
557+
558+/*
559+ * end_line:
560+ *	End the list of lines
561+ */
562+void
563+end_line(void)
564+{
565+    if (Inv_type != INV_SLOW)
566+	if (Line_cnt == 1 && !Newpage)
567+	{
568+	    Mpos = 0;
569+	    msg(Lastfmt, Lastarg);
570+	}
571+	else
572+	    add_line((char *) NULL, NULL);
573+    Line_cnt = 0;
574+    Newpage = FALSE;
575+}
576+
577+/*
578+ * nothing:
579+ *	Set up Prbuf so that message for "nothing found" is there
580+ */
581+char *
582+nothing(char type)
583+{
584+    char *sp, *tystr;
585+
586+    if (Terse)
587+	sprintf(Prbuf, "Nothing");
588+    else
589+	sprintf(Prbuf, "Haven't discovered anything");
590+    if (type != '*')
591+    {
592+	sp = &Prbuf[strlen(Prbuf)];
593+	switch (type)
594+	{
595+	    when POTION: tystr = "potion";
596+	    when SCROLL: tystr = "scroll";
597+	    when RING: tystr = "ring";
598+	    when STICK: tystr = "stick";
599+	}
600+	sprintf(sp, " about any %ss", tystr);
601+    }
602+    return Prbuf;
603+}
604+
605+/*
606+ * nameit:
607+ *	Give the proper name to a potion, stick, or ring
608+ */
609+void
610+nameit(THING *obj, char *type, char *which, struct obj_info *op,
611+    char *(*prfunc)(THING *))
612+{
613+    char *pb;
614+
615+    if (op->oi_know || op->oi_guess)
616+    {
617+	if (obj->o_count == 1)
618+	    sprintf(Prbuf, "A %s ", type);
619+	else
620+	    sprintf(Prbuf, "%d %ss ", obj->o_count, type);
621+	pb = &Prbuf[strlen(Prbuf)];
622+	if (op->oi_know)
623+	    sprintf(pb, "of %s%s(%s)", op->oi_name, (*prfunc)(obj), which);
624+	else if (op->oi_guess)
625+	    sprintf(pb, "called %s%s(%s)", op->oi_guess, (*prfunc)(obj), which);
626+    }
627+    else if (obj->o_count == 1)
628+	sprintf(Prbuf, "A%s %s %s", vowelstr(which), which, type);
629+    else
630+	sprintf(Prbuf, "%d %s %ss", obj->o_count, which, type);
631+}
632+
633+/*
634+ * nullstr:
635+ *	Return a pointer to a null-length string
636+ */
637+char *
638+nullstr(THING *ignored)
639+{
640+    return "";
641+}
642+
643+# ifdef	MASTER
644+/*
645+ * pr_list:
646+ *	List possible potions, scrolls, etc. for wizard.
647+ */
648+void
649+pr_list(void)
650+{
651+    int ch;
652+
653+    if (!Terse)
654+	addmsg("for ");
655+    addmsg("what type");
656+    if (!Terse)
657+	addmsg(" of object do you want a list");
658+    msg("? ");
659+    ch = readchar();
660+    switch (ch)
661+    {
662+	when POTION:
663+	    pr_spec(Pot_info, MAXPOTIONS);
664+	when SCROLL:
665+	    pr_spec(Scr_info, MAXSCROLLS);
666+	when RING:
667+	    pr_spec(Ring_info, MAXRINGS);
668+	when STICK:
669+	    pr_spec(Ws_info, MAXSTICKS);
670+	when ARMOR:
671+	    pr_spec(Arm_info, MAXARMORS);
672+	when WEAPON:
673+	    pr_spec(Weap_info, MAXWEAPONS);
674+	otherwise:
675+	    return;
676+    }
677+}
678+
679+/*
680+ * pr_spec:
681+ *	Print specific list of possible items to choose from
682+ */
683+void
684+pr_spec(struct obj_info *info, int nitems)
685+{
686+    struct obj_info *endp;
687+    int i, lastprob;
688+
689+    endp = &info[nitems];
690+    lastprob = 0;
691+    for (i = '0'; info < endp; i++)
692+    {
693+	if (i == '9' + 1)
694+	    i = 'a';
695+	sprintf(Prbuf, "%c: %%s (%d%%%%)", i, info->oi_prob - lastprob);
696+	lastprob = info->oi_prob;
697+	add_line(Prbuf, info->oi_name);
698+	info++;
699+    }
700+    end_line();
701+}
702+# endif	MASTER
A rexec.c
+244, -0
  1@@ -0,0 +1,244 @@
  2+/*
  3+ * File with various monster functions in it
  4+ *
  5+ * @(#)rexec.c	4.46 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include "netprot.h"
 10+#include <ctype.h>
 11+
 12+/*
 13+ * List of monsters in rough order of vorpalness
 14+ */
 15+static char Lvl_mons[] =  {
 16+    'K', 'E', 'B', 'S', 'H', 'I', 'R', 'O', 'Z', 'L', 'C', 'Q', 'A',
 17+    'N', 'Y', 'F', 'T', 'W', 'P', 'X', 'U', 'M', 'V', 'G', 'J', 'D'
 18+};
 19+
 20+static char Wand_mons[] = {
 21+    'K', 'E', 'B', 'S', 'H',   0, 'R', 'O', 'Z',   0, 'C', 'Q', 'A',
 22+      0, 'Y',   0, 'T', 'W', 'P',   0, 'U', 'M', 'V', 'G', 'J',   0
 23+};
 24+
 25+/*
 26+ * randmonster:
 27+ *	Pick a monster to show up.  The lower the level,
 28+ *	the meaner the monster.
 29+ */
 30+char
 31+randmonster(bool wander)
 32+{
 33+    int d;
 34+    char *mons;
 35+
 36+    mons = (wander ? Wand_mons : Lvl_mons);
 37+    do
 38+    {
 39+	d = Level + (rnd(10) - 6);
 40+	if (d < 0)
 41+	    d = rnd(5);
 42+	if (d > 25)
 43+	    d = rnd(5) + 21;
 44+    } while (mons[d] == 0);
 45+    return mons[d];
 46+}
 47+
 48+/*
 49+ * new_monster:
 50+ *	Pick a new monster and add it to the list
 51+ */
 52+void
 53+new_monster(THING *tp, char type, coord *cp)
 54+{
 55+    struct monster *mp;
 56+    int lev_add;
 57+
 58+    if ((lev_add = Level - AMULETLEVEL) < 0)
 59+	lev_add = 0;
 60+    attach(Mlist, tp);
 61+    tp->t_type = type;
 62+    tp->t_disguise = type;
 63+    tp->t_pos = *cp;
 64+    move(cp->y, cp->x);
 65+    tp->t_oldch = inch();
 66+    tp->t_room = roomin(cp);
 67+    moat(cp->y, cp->x) = tp;
 68+    mp = &Monsters[tp->t_type-'A'];
 69+    tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
 70+    tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
 71+    tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
 72+    strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
 73+    tp->t_stats.s_str = mp->m_stats.s_str;
 74+    tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
 75+    tp->t_flags = mp->m_flags;
 76+    if (Level > 29)
 77+	tp->t_flags |= ISHASTE;
 78+    tp->t_turn = TRUE;
 79+    tp->t_pack = NULL;
 80+    if (ISWEARING(R_AGGR))
 81+	runto(cp);
 82+    if (type == 'X')
 83+	tp->t_disguise = rnd_thing();
 84+}
 85+
 86+/*
 87+ * expadd:
 88+ *	Experience to add for this monster's level/hit points
 89+ */
 90+int
 91+exp_add(THING *tp)
 92+{
 93+    int mod;
 94+
 95+    if (tp->t_stats.s_lvl == 1)
 96+	mod = tp->t_stats.s_maxhp / 8;
 97+    else
 98+	mod = tp->t_stats.s_maxhp / 6;
 99+    if (tp->t_stats.s_lvl > 9)
100+	mod *= 20;
101+    else if (tp->t_stats.s_lvl > 6)
102+	mod *= 4;
103+    return mod;
104+}
105+
106+/*
107+ * wanderer:
108+ *	Create a new wandering monster and aim it at the player
109+ */
110+void
111+wanderer(void)
112+{
113+    int i;
114+    struct room *rp;
115+    THING *tp;
116+    static coord cp;
117+
118+    tp = new_item();
119+    do
120+    {
121+	find_floor((struct room *) NULL, &cp, FALSE, TRUE);
122+    } while (roomin(&cp) == Proom);
123+    new_monster(tp, randmonster(TRUE), &cp);
124+    if (on(Player, SEEMONST))
125+    {
126+	standout();
127+	if (!on(Player, ISHALU))
128+	    addch(tp->t_type);
129+	else
130+	    addch(rnd(26) + 'A');
131+	standend();
132+    }
133+    runto(&tp->t_pos);
134+#ifdef MASTER
135+    if (Wizard)
136+	msg("started a wandering %s", Monsters[tp->t_type-'A'].m_name);
137+#endif
138+}
139+
140+/*
141+ * wake_monster:
142+ *	What to do when the hero steps next to a monster
143+ */
144+THING *
145+wake_monster(int y, int x)
146+{
147+    THING *tp;
148+    struct room *rp;
149+    char ch, *mname;
150+
151+#ifdef MASTER
152+    if ((tp = moat(y, x)) == NULL)
153+	msg("can't find monster in wake_monster");
154+#else
155+    tp = moat(y, x);
156+    if (tp == NULL)
157+	endwin(), abort();
158+#endif
159+    ch = tp->t_type;
160+    /*
161+     * Every time he sees mean monster, it might start chasing him
162+     */
163+    if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
164+	&& !ISWEARING(R_STEALTH) && !on(Player, ISLEVIT))
165+    {
166+	tp->t_dest = &Hero;
167+	tp->t_flags |= ISRUN;
168+    }
169+    if (ch == 'M' && !on(Player, ISBLIND) && !on(Player, ISHALU)
170+	&& !on(*tp, ISFOUND) && !on(*tp, ISCANC) && on(*tp, ISRUN))
171+    {
172+        rp = Proom;
173+	if ((rp != NULL && !(rp->r_flags & ISDARK))
174+	    || dist(y, x, Hero.y, Hero.x) < LAMPDIST)
175+	{
176+	    tp->t_flags |= ISFOUND;
177+	    if (!save(VS_MAGIC))
178+	    {
179+		if (on(Player, ISHUH))
180+		    lengthen(unconfuse, spread(HUHDURATION));
181+		else
182+		    fuse(unconfuse, 0, spread(HUHDURATION), AFTER);
183+		Player.t_flags |= ISHUH;
184+		mname = set_mname(tp);
185+		addmsg("%s", mname);
186+		if (strcmp(mname, "it") != 0)
187+		    addmsg("'");
188+		msg("s gaze has confused you");
189+	    }
190+	}
191+    }
192+    /*
193+     * Let greedy ones guard gold
194+     */
195+    if (on(*tp, ISGREED) && !on(*tp, ISRUN))
196+    {
197+	tp->t_flags |= ISRUN;
198+	if (Proom->r_goldval)
199+	    tp->t_dest = &Proom->r_gold;
200+	else
201+	    tp->t_dest = &Hero;
202+    }
203+    return tp;
204+}
205+
206+/*
207+ * give_pack:
208+ *	Give a pack to a monster if it deserves one
209+ */
210+void
211+give_pack(THING *tp)
212+{
213+    if (Level >= Max_level && rnd(100) < Monsters[tp->t_type-'A'].m_carry)
214+	attach(tp->t_pack, new_thing());
215+}
216+
217+/*
218+ * save_throw:
219+ *	See if a creature save against something
220+ */
221+int
222+save_throw(int which, THING *tp)
223+{
224+    int need;
225+
226+    need = 14 + which - tp->t_stats.s_lvl / 2;
227+    return (roll(1, 20) >= need);
228+}
229+
230+/*
231+ * save:
232+ *	See if he saves against various nasty things
233+ */
234+int
235+save(int which)
236+{
237+    if (which == VS_MAGIC)
238+    {
239+	if (ISRING(LEFT, R_PROTECT))
240+	    which -= Cur_ring[LEFT]->o_arm;
241+	if (ISRING(RIGHT, R_PROTECT))
242+	    which -= Cur_ring[RIGHT]->o_arm;
243+    }
244+    return save_throw(which, &Player);
245+}
A rinit.c
+439, -0
  1@@ -0,0 +1,439 @@
  2+/*
  3+ * global variable initializaton
  4+ *
  5+ * @(#)rinit.c	4.31 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include <ctype.h>
 10+#include "netprot.h"
 11+
 12+/*
 13+ * init_player:
 14+ *	Roll her up
 15+ */
 16+void
 17+init_player(void)
 18+{
 19+    THING *obj;
 20+
 21+    Pstats = Max_stats;
 22+    Food_left = HUNGERTIME;
 23+    /*
 24+     * Give him some food
 25+     */
 26+    obj = new_item();
 27+    obj->o_type = FOOD;
 28+    obj->o_count = 1;
 29+    add_pack(obj, TRUE);
 30+    /*
 31+     * And his suit of armor
 32+     */
 33+    obj = new_item();
 34+    obj->o_type = ARMOR;
 35+    obj->o_which = RING_MAIL;
 36+    obj->o_arm = A_class[RING_MAIL] - 1;
 37+    obj->o_flags |= ISKNOW;
 38+    obj->o_count = 1;
 39+    Cur_armor = obj;
 40+    add_pack(obj, TRUE);
 41+    /*
 42+     * Give him his weaponry.  First a mace.
 43+     */
 44+    obj = new_item();
 45+    init_weapon(obj, MACE);
 46+    obj->o_hplus = 1;
 47+    obj->o_dplus = 1;
 48+    obj->o_flags |= ISKNOW;
 49+    add_pack(obj, TRUE);
 50+    Cur_weapon = obj;
 51+    /*
 52+     * Now a +1 bow
 53+     */
 54+    obj = new_item();
 55+    init_weapon(obj, BOW);
 56+    obj->o_hplus = 1;
 57+    obj->o_flags |= ISKNOW;
 58+    add_pack(obj, TRUE);
 59+    /*
 60+     * Now some arrows
 61+     */
 62+    obj = new_item();
 63+    init_weapon(obj, ARROW);
 64+    obj->o_count = rnd(15) + 25;
 65+    obj->o_flags |= ISKNOW;
 66+    add_pack(obj, TRUE);
 67+}
 68+
 69+/*
 70+ * Contains defintions and functions for dealing with things like
 71+ * potions and scrolls
 72+ */
 73+
 74+static char *Rainbow[] = {
 75+    "amber",
 76+    "aquamarine",
 77+    "black",
 78+    "blue",
 79+    "brown",
 80+    "clear",
 81+    "crimson",
 82+    "cyan",
 83+    "ecru",
 84+    "gold",
 85+    "green",
 86+    "grey",
 87+    "magenta",
 88+    "orange",
 89+    "pink",
 90+    "plaid",
 91+    "purple",
 92+    "red",
 93+    "silver",
 94+    "tan",
 95+    "tangerine",
 96+    "topaz",
 97+    "turquoise",
 98+    "vermilion",
 99+    "violet",
100+    "white",
101+    "yellow",
102+};
103+
104+#define NCOLORS (sizeof Rainbow / sizeof (char *))
105+
106+static char *Sylls[] = {
107+    "a", "ab", "ag", "aks", "ala", "an", "app", "arg", "arze", "ash",
108+    "bek", "bie", "bit", "bjor", "blu", "bot", "bu", "byt", "comp",
109+    "con", "cos", "cre", "dalf", "dan", "den", "do", "e", "eep", "el",
110+    "eng", "er", "ere", "erk", "esh", "evs", "fa", "fid", "fri", "fu",
111+    "gan", "gar", "glen", "gop", "gre", "ha", "hyd", "i", "ing", "ip",
112+    "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech",
113+    "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur", "nej",
114+    "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od", "ood",
115+    "org", "orn", "ox", "oxy", "pay", "ple", "plu", "po", "pot",
116+    "prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol", "sa",
117+    "san", "sat", "sef", "seh", "shu", "ski", "sna", "sne", "snik",
118+    "sno", "so", "sol", "sri", "sta", "sun", "ta", "tab", "tem",
119+    "ther", "ti", "tox", "trol", "tue", "turs", "u", "ulk", "um", "un",
120+    "uni", "ur", "val", "viv", "vly", "vom", "wah", "wed", "werg",
121+    "wex", "whon", "wun", "xo", "y", "yot", "yu", "zant", "zeb", "zim",
122+    "zok", "zon", "zum",
123+};
124+
125+typedef struct {
126+    char	*st_name;
127+    int		st_value;
128+} STONE;
129+
130+static STONE Stones[] = {
131+    { "agate",		 25},
132+    { "alexandrite",	 40},
133+    { "amethyst",	 50},
134+    { "carnelian",	 40},
135+    { "diamond",	300},
136+    { "emerald",	300},
137+    { "germanium",	225},
138+    { "granite",	  5},
139+    { "garnet",		 50},
140+    { "jade",		150},
141+    { "kryptonite",	300},
142+    { "lapis lazuli",	 50},
143+    { "moonstone",	 50},
144+    { "obsidian",	 15},
145+    { "onyx",		 60},
146+    { "opal",		200},
147+    { "pearl",		220},
148+    { "peridot",	 63},
149+    { "ruby",		350},
150+    { "sapphire",	285},
151+    { "stibotantalite",	200},
152+    { "tiger eye",	 50},
153+    { "topaz",		 60},
154+    { "turquoise",	 70},
155+    { "taaffeite",	300},
156+    { "zircon",	 	 80},
157+};
158+
159+#define NSTONES (sizeof Stones / sizeof (STONE))
160+
161+static char *Wood[] = {
162+    "avocado wood",
163+    "balsa",
164+    "bamboo",
165+    "banyan",
166+    "birch",
167+    "cedar",
168+    "cherry",
169+    "cinnibar",
170+    "cypress",
171+    "dogwood",
172+    "driftwood",
173+    "ebony",
174+    "elm",
175+    "eucalyptus",
176+    "fall",
177+    "hemlock",
178+    "holly",
179+    "ironwood",
180+    "kukui wood",
181+    "mahogany",
182+    "manzanita",
183+    "maple",
184+    "oaken",
185+    "persimmon wood",
186+    "pecan",
187+    "pine",
188+    "poplar",
189+    "redwood",
190+    "rosewood",
191+    "spruce",
192+    "teak",
193+    "walnut",
194+    "zebrawood",
195+};
196+
197+#define NWOOD (sizeof Wood / sizeof (char *))
198+
199+static char *Metal[] = {
200+    "aluminum",
201+    "beryllium",
202+    "bone",
203+    "brass",
204+    "bronze",
205+    "copper",
206+    "electrum",
207+    "gold",
208+    "iron",
209+    "lead",
210+    "magnesium",
211+    "mercury",
212+    "nickel",
213+    "pewter",
214+    "platinum",
215+    "steel",
216+    "silver",
217+    "silicon",
218+    "tin",
219+    "titanium",
220+    "tungsten",
221+    "zinc",
222+};
223+
224+#define NMETAL (sizeof Metal / sizeof (char *))
225+
226+#define MAX3(a,b,c)	(a > b ? (a > c ? a : c) : (b > c ? b : c))
227+
228+static bool Used[MAX3(NCOLORS, NSTONES, NWOOD)];
229+
230+/*
231+ * init_colors:
232+ *	Initialize the potion color scheme for this time
233+ */
234+void
235+init_colors(void)
236+{
237+    int i, j;
238+
239+    for (i = 0; i < NCOLORS; i++)
240+	Used[i] = FALSE;
241+    for (i = 0; i < MAXPOTIONS; i++)
242+    {
243+	do
244+	    j = rnd(NCOLORS);
245+	until (!Used[j]);
246+	Used[j] = TRUE;
247+	P_colors[i] = Rainbow[j];
248+    }
249+}
250+
251+/*
252+ * init_names:
253+ *	Generate the names of the various scrolls
254+ */
255+#define MAXNAME	40	/* Max number of characters in a name */
256+
257+void
258+init_names(void)
259+{
260+    int nsyl;
261+    char *cp, *sp;
262+    int i, nwords;
263+
264+    for (i = 0; i < MAXSCROLLS; i++)
265+    {
266+	cp = Prbuf;
267+	nwords = rnd(3) + 2;
268+	while (nwords--)
269+	{
270+	    nsyl = rnd(3) + 1;
271+	    while (nsyl--)
272+	    {
273+		sp = Sylls[rnd((sizeof Sylls) / (sizeof (char *)))];
274+		if (&cp[strlen(sp)] > &Prbuf[MAXNAME])
275+			break;
276+		while (*sp)
277+		    *cp++ = *sp++;
278+	    }
279+	    *cp++ = ' ';
280+	}
281+	*--cp = '\0';
282+	S_names[i] = (char *) malloc((unsigned) strlen(Prbuf)+1);
283+	strcpy(S_names[i], Prbuf);
284+    }
285+}
286+
287+/*
288+ * init_stones:
289+ *	Initialize the ring stone setting scheme for this time
290+ */
291+void
292+init_stones(void)
293+{
294+    int i, j;
295+
296+    for (i = 0; i < NSTONES; i++)
297+	Used[i] = FALSE;
298+    for (i = 0; i < MAXRINGS; i++)
299+    {
300+	do
301+	    j = rnd(NSTONES);
302+	until (!Used[j]);
303+	Used[j] = TRUE;
304+	R_stones[i] = Stones[j].st_name;
305+	Ring_info[i].oi_worth += Stones[j].st_value;
306+    }
307+}
308+
309+/*
310+ * init_materials:
311+ *	Initialize the construction materials for wands and staffs
312+ */
313+void
314+init_materials(void)
315+{
316+    int i, j;
317+    char *str;
318+    static bool metused[NMETAL];
319+
320+    for (i = 0; i < NWOOD; i++)
321+	Used[i] = FALSE;
322+    for (i = 0; i < NMETAL; i++)
323+	metused[i] = FALSE;
324+    for (i = 0; i < MAXSTICKS; i++)
325+    {
326+	for (;;)
327+	    if (rnd(2) == 0)
328+	    {
329+		j = rnd(NMETAL);
330+		if (!metused[j])
331+		{
332+		    Ws_type[i] = "wand";
333+		    str = Metal[j];
334+		    metused[j] = TRUE;
335+		    break;
336+		}
337+	    }
338+	    else
339+	    {
340+		j = rnd(NWOOD);
341+		if (!Used[j])
342+		{
343+		    Ws_type[i] = "staff";
344+		    str = Wood[j];
345+		    Used[j] = TRUE;
346+		    break;
347+		}
348+	    }
349+	Ws_made[i] = str;
350+    }
351+}
352+
353+#ifdef MASTER
354+# define	NT	NUMTHINGS, "things"
355+# define	MP	MAXPOTIONS, "potions"
356+# define	MS	MAXSCROLLS, "scrolls"
357+# define	MR	MAXRINGS, "rings"
358+# define	MWS	MAXSTICKS, "sticks"
359+# define	MW	MAXWEAPONS, "weapons"
360+# define	MA	MAXARMORS, "armor"
361+#else
362+# define	NT	NUMTHINGS
363+# define	MP	MAXPOTIONS
364+# define	MS	MAXSCROLLS
365+# define	MR	MAXRINGS
366+# define	MWS	MAXSTICKS
367+# define	MW	MAXWEAPONS
368+# define	MA	MAXARMORS
369+#endif
370+
371+/*
372+ * sumprobs:
373+ *	Sum up the probabilities for items appearing
374+ */
375+void
376+sumprobs(struct obj_info *info, int bound
377+#ifdef MASTER
378+	, char *name
379+#endif
380+)
381+{
382+    struct obj_info *last, *endp, *start;
383+
384+    start = info;
385+    endp = info + bound;
386+    while (++info < endp)
387+	info->oi_prob += (info - 1)->oi_prob;
388+#ifdef MASTER
389+    badcheck(name, start, bound);
390+#endif
391+}
392+
393+/*
394+ * init_probs:
395+ *	Initialize the probabilities for the various items
396+ */
397+void
398+init_probs(void)
399+{
400+    sumprobs(Things, NT);
401+    sumprobs(Pot_info, MP);
402+    sumprobs(Scr_info, MS);
403+    sumprobs(Ring_info, MR);
404+    sumprobs(Ws_info, MWS);
405+    sumprobs(Weap_info, MW);
406+    sumprobs(Arm_info, MA);
407+}
408+
409+#ifdef MASTER
410+/*
411+ * badcheck:
412+ *	Check to see if a series of probabilities sums to 100
413+ */
414+void
415+badcheck(char *name, struct obj_info *info, int bound)
416+{
417+    struct obj_info *end;
418+
419+    if (info[bound - 1].oi_prob == 100)
420+	return;
421+    printf("\nBad percentages for %s (bound = %d):\n", name, bound);
422+    for (end = &info[bound]; info < end; info++)
423+	printf("%3d%% %s\n", info->oi_prob, info->oi_name);
424+    printf("[hit RETURN to continue]");
425+    fflush(stdout);
426+    while (getchar() != '\n')
427+	continue;
428+}
429+#endif
430+
431+/*
432+ * pick_color:
433+ *	If he is halucinating, pick a random color name and return it,
434+ *	otherwise return the given color.
435+ */
436+char *
437+pick_color(char *col)
438+{
439+    return (on(Player, ISHALU) ? Rainbow[rnd(NCOLORS)] : col);
440+}
A rmap.c
+417, -0
  1@@ -0,0 +1,417 @@
  2+/*
  3+ * Exploring the dungeons of doom
  4+ * Copyright (C) 1981 by Michael Toy, Ken Arnold, and Glenn Wichman
  5+ * All rights reserved
  6+ *
  7+ * @(#)rmap.c	4.22 (Berkeley) 02/05/99
  8+ */
  9+
 10+#include <curses.h>
 11+#ifdef	attron
 12+#include <term.h>
 13+#endif	attron
 14+#include <signal.h>
 15+#include <pwd.h>
 16+#include "netprot.h"
 17+
 18+/*
 19+ * main:
 20+ *	The main program, of course
 21+ */
 22+int
 23+main(int argc, char **argv, char **envp)
 24+{
 25+    char *env;
 26+    struct passwd *pw;
 27+    int lowtime;
 28+
 29+#ifndef DUMP
 30+    signal(SIGQUIT, exit);
 31+    signal(SIGILL, exit);
 32+    signal(SIGTRAP, exit);
 33+    signal(SIGIOT, exit);
 34+    signal(SIGEMT, exit);
 35+    signal(SIGFPE, exit);
 36+    signal(SIGBUS, exit);
 37+    signal(SIGSEGV, exit);
 38+    signal(SIGSYS, exit);
 39+#endif
 40+
 41+#ifdef MASTER
 42+    /*
 43+     * Check to see if he is a wizard
 44+     */
 45+    if (argc >= 2 && argv[1][0] == '\0')
 46+	if (strcmp(PASSWD, crypt(getpass("Wizard's password: "), "mT")) == 0)
 47+	{
 48+	    Wizard = TRUE;
 49+	    Player.t_flags |= SEEMONST;
 50+	    argv++;
 51+	    argc--;
 52+	}
 53+#endif
 54+
 55+    /*
 56+     * get Home and options from environment
 57+     */
 58+    if ((env = getenv("HOME")) != NULL)
 59+	strcpy(Home, env);
 60+    else if ((pw = getpwuid(getuid())) != NULL)
 61+	strcpy(Home, pw->pw_dir);
 62+    strcat(Home, "/");
 63+
 64+    strcpy(File_name, Home);
 65+    strcat(File_name, "rogue.save");
 66+
 67+    if ((env = getenv("ROGUEOPTS")) != NULL)
 68+	parse_opts(env);
 69+    if (env == NULL || Whoami[0] == '\0')
 70+	if ((pw = getpwuid(getuid())) == NULL)
 71+	{
 72+	    printf("Say, who the hell are you?\n");
 73+	    exit(1);
 74+	}
 75+	else
 76+	    strucpy(Whoami, pw->pw_name, strlen(pw->pw_name));
 77+
 78+#ifdef MASTER
 79+    if (Wizard && getenv("SEED") != NULL)
 80+	Dnum = atoi(getenv("SEED"));
 81+    else
 82+#endif
 83+	Dnum = lowtime + getpid();
 84+    Seed = Dnum;
 85+
 86+    /*
 87+     * check for print-score option
 88+     */
 89+    open_score();
 90+    if (argc == 2)
 91+	if (strcmp(argv[1], "-s") == 0)
 92+	{
 93+	    Noscore = TRUE;
 94+	    score(0, -1);
 95+	    exit(0);
 96+	}
 97+	else if (strcmp(argv[1], "-d") == 0)
 98+	{
 99+	    Dnum = rnd(100);	/* throw away some rnd()s to break patterns */
100+	    while (--Dnum)
101+		rnd(100);
102+	    Purse = rnd(100) + 1;
103+	    Level = rnd(100) + 1;
104+	    initscr();
105+	    getltchars();
106+	    death(death_monst());
107+	    exit(0);
108+	}
109+
110+    init_check();			/* check for legal startup */
111+    if (argc == 2)
112+	if (!restore(argv[1], envp))	/* Note: restore will never return */
113+	    my_exit(1);
114+    lowtime = (int) time(NULL);
115+#ifdef MASTER
116+    if (Wizard)
117+	printf("Hello %s, welcome to dungeon #%d", Whoami, Dnum);
118+    else
119+#endif
120+	printf("Hello %s, just a moment while I dig the dungeon...", Whoami);
121+    fflush(stdout);
122+
123+    initscr();				/* Start up cursor package */
124+    init_probs();			/* Set up prob tables for objects */
125+    init_player();			/* Set up initial Player stats */
126+    init_names();			/* Set up names of scrolls */
127+    init_colors();			/* Set up colors of potions */
128+    init_stones();			/* Set up stone settings of rings */
129+    init_materials();			/* Set up materials of wands */
130+    setup();
131+
132+    /*
133+     * The screen must be at least NUMLINES x NUMCOLS
134+     */
135+    if (LINES < NUMLINES || COLS < NUMCOLS)
136+    {
137+	printf("\nSorry, the screen must be at least %dx%d\n", NUMLINES, NUMCOLS);
138+	endwin();
139+	my_exit(1);
140+    }
141+
142+    /*
143+     * Set up windows
144+     */
145+    Hw = newwin(LINES, COLS, 0, 0);
146+#ifdef	attron
147+    idlok(stdscr, TRUE);
148+    idlok(Hw, TRUE);
149+#endif	attron
150+#ifdef MASTER
151+    Noscore = Wizard;
152+#endif
153+    new_level();			/* Draw current level */
154+    /*
155+     * Start up daemons and fuses
156+     */
157+    start_daemon(runners, 0, AFTER);
158+    start_daemon(doctor, 0, AFTER);
159+    fuse(swander, 0, WANDERTIME, AFTER);
160+    start_daemon(stomach, 0, AFTER);
161+    playit();
162+}
163+
164+/*
165+ * endit:
166+ *	Exit the program abnormally.
167+ */
168+void
169+endit(int sig)
170+{
171+    fatal("Okay, bye bye!\n");
172+}
173+
174+/*
175+ * fatal:
176+ *	Exit the program, printing a message.
177+ */
178+void
179+fatal(char *s)
180+{
181+    mvaddstr(LINES - 2, 0, s);
182+    refresh();
183+    endwin();
184+    my_exit(0);
185+}
186+
187+/*
188+ * rnd:
189+ *	Pick a very random number.
190+ */
191+int
192+rnd(int range)
193+{
194+    return range == 0 ? 0 : abs((int) RN) % range;
195+}
196+
197+/*
198+ * roll:
199+ *	Roll a number of dice
200+ */
201+int 
202+roll(int number, int sides)
203+{
204+    int dtotal = 0;
205+
206+    while (number--)
207+	dtotal += rnd(sides)+1;
208+    return dtotal;
209+}
210+
211+#ifdef SIGTSTP
212+/*
213+ * tstp:
214+ *	Handle stop and start signals
215+ */
216+void
217+tstp(int ignored)
218+{
219+    int y, x;
220+    int oy, ox;
221+
222+    /*
223+     * leave nicely
224+     */
225+    getyx(curscr, oy, ox);
226+    mvcur(0, COLS - 1, LINES - 1, 0);
227+    endwin();
228+    resetltchars();
229+    fflush(stdout);
230+    kill(0, SIGTSTP);		/* send actual signal and suspend process */
231+
232+    /*
233+     * start back up again
234+     */
235+    signal(SIGTSTP, tstp);
236+    crmode();
237+    noecho();
238+    playltchars();
239+    clearok(curscr, TRUE);
240+    wrefresh(curscr);
241+    getyx(curscr, y, x);
242+    mvcur(y, x, oy, ox);
243+    fflush(stdout);
244+    curscr->_cury = oy;
245+    curscr->_curx = ox;
246+}
247+#endif
248+
249+/*
250+ * playit:
251+ *	The main loop of the program.  Loop until the game is over,
252+ *	refreshing things and looking at the proper times.
253+ */
254+void
255+playit(void)
256+{
257+    char *opts;
258+
259+    /*
260+     * set up defaults for slow terminals
261+     */
262+
263+#ifndef	attron
264+    if (_tty.sg_ospeed <= B1200)
265+#else	attron
266+    if (baudrate() <= 1200)
267+#endif	attron
268+    {
269+	Terse = TRUE;
270+	Jump = TRUE;
271+	See_floor = FALSE;
272+    }
273+#ifndef	attron
274+    if (!CE)
275+#else	attron
276+    if (clr_eol)
277+#endif	attron
278+	Inv_type = INV_CLEAR;
279+
280+    /*
281+     * parse environment declaration of options
282+     */
283+    if ((opts = getenv("ROGUEOPTS")) != NULL)
284+	parse_opts(opts);
285+
286+
287+    Oldpos = Hero;
288+    Oldrp = roomin(&Hero);
289+    while (Playing)
290+	command();			/* Command execution */
291+    endit(0);
292+}
293+
294+/*
295+ * quit:
296+ *	Have player make certain, then exit.
297+ */
298+void
299+quit(int sig)
300+{
301+    int oy, ox;
302+
303+    /*
304+     * Reset the signal in case we got here via an interrupt
305+     */
306+    if (!Q_comm)
307+	Mpos = 0;
308+    getyx(curscr, oy, ox);
309+    msg("really quit?");
310+    if (readchar() == 'y')
311+    {
312+	signal(SIGINT, leave);
313+	clear();
314+	mvprintw(LINES - 2, 0, "You quit with %d gold pieces", Purse);
315+	move(LINES - 1, 0);
316+	refresh();
317+	score(Purse, 1);
318+	my_exit(0);
319+    }
320+    else
321+    {
322+	move(0, 0);
323+	clrtoeol();
324+	status();
325+	move(oy, ox);
326+	refresh();
327+	Mpos = 0;
328+	Count = 0;
329+	To_death = FALSE;
330+    }
331+}
332+
333+/*
334+ * leave:
335+ *	Leave quickly, but curteously
336+ */
337+void
338+leave(int sig)
339+{
340+    static char buf[BUFSIZ];
341+
342+    setbuf(stdout, buf);	/* throw away pending output */
343+#ifndef	attron
344+    if (!_endwin)
345+    {
346+	mvcur(0, COLS - 1, LINES - 1, 0);
347+	endwin();
348+    }
349+#else	attron
350+    endwin();
351+#endif	attron
352+    putchar('\n');
353+    my_exit(0);
354+}
355+
356+/*
357+ * shell:
358+ *	Let them escape for a while
359+ */
360+void
361+shell(void)
362+{
363+    int pid;
364+    char *sh;
365+    int ret_status;
366+
367+    /*
368+     * Set the terminal back to original mode
369+     */
370+    move(LINES-1, 0);
371+    refresh();
372+    endwin();
373+    resetltchars();
374+    putchar('\n');
375+    In_shell = TRUE;
376+    After = FALSE;
377+    sh = getenv("SHELL");
378+    fflush(stdout);
379+    /*
380+     * Fork and do a shell
381+     */
382+    while ((pid = fork()) < 0)
383+	sleep(1);
384+    if (pid == 0)
385+    {
386+	execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);
387+	perror("No shelly");
388+	exit(-1);
389+    }
390+    else
391+    {
392+	signal(SIGINT, SIG_IGN);
393+	signal(SIGQUIT, SIG_IGN);
394+	while (wait(&ret_status) != pid)
395+	    continue;
396+	signal(SIGINT, quit);
397+	signal(SIGQUIT, endit);
398+	printf("\n[Press return to continue]");
399+	fflush(stdout);
400+	noecho();
401+	crmode();
402+	playltchars();
403+	In_shell = FALSE;
404+	wait_for('\n');
405+	clearok(stdscr, TRUE);
406+    }
407+}
408+
409+/*
410+ * my_exit:
411+ *	Leave the process properly
412+ */
413+void
414+my_exit(int st)
415+{
416+    resetltchars();
417+    exit(st);
418+}
A rmove.c
+390, -0
  1@@ -0,0 +1,390 @@
  2+/*
  3+ * global variable initializaton
  4+ *
  5+ * @(#)rmove.c	4.82 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include "netprot.h"
 10+
 11+bool After;				/* True if we want after daemons */
 12+bool Again;				/* Repeating the last command */
 13+bool Noscore;				/* Was a wizard sometime */
 14+bool Seenstairs;			/* Have seen the stairs (for lsd) */
 15+bool Amulet = FALSE;			/* He found the amulet */
 16+bool Door_stop = FALSE;			/* Stop running when we pass a door */
 17+bool Fight_flush = FALSE;		/* True if toilet input */
 18+bool Firstmove = FALSE;			/* First move after setting Door_stop */
 19+bool Got_ltc = FALSE;			/* We have gotten the local tty chars */
 20+bool Has_hit = FALSE;			/* Has a "hit" message pending in msg */
 21+bool In_shell = FALSE;			/* True if executing a shell */
 22+bool Inv_describe = TRUE;		/* Say which way items are being used */
 23+bool Jump = FALSE;			/* Show running as series of jumps */
 24+bool Kamikaze = FALSE;			/* To_death really to DEATH */
 25+bool Lower_msg = FALSE;			/* Messages should start w/lower case */
 26+bool Move_on = FALSE;			/* Next move shouldn't pick up items */
 27+bool Msg_esc = FALSE;			/* Check for ESC from msg's --More-- */
 28+bool Passgo = FALSE;			/* Follow passages */
 29+bool Playing = TRUE;			/* True until he quits */
 30+bool Q_comm = FALSE;			/* Are we executing a 'Q' command? */
 31+bool Running = FALSE;			/* True if player is running */
 32+bool Save_msg = TRUE;			/* Remember last msg */
 33+bool See_floor = TRUE;			/* Show the lamp illuminated floor */
 34+bool Stat_msg = FALSE;			/* Should status() print as a msg() */
 35+bool Terse = FALSE;			/* True if we should be short */
 36+bool To_death = FALSE;			/* Fighting is to the death! */
 37+bool Tombstone = TRUE;			/* Print out tombstone at end */
 38+#ifdef MASTER
 39+bool Wizard = FALSE;			/* True if allows wizard commands */
 40+#endif
 41+bool Pack_used[26] = {			/* Is the character used in the pack? */
 42+    FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
 43+    FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
 44+    FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
 45+};
 46+
 47+char Dir_ch;				/* Direction from last get_dir() call */
 48+char File_name[MAXSTR];			/* Save file name */
 49+char Huh[MAXSTR];			/* The last message printed */
 50+char *P_colors[MAXPOTIONS];		/* Colors of the potions */
 51+char Prbuf[2*MAXSTR];			/* Buffer for sprintfs */
 52+char *R_stones[MAXRINGS];		/* Stone settings of the rings */
 53+char *Release;				/* Release number of program */
 54+char Runch;				/* Direction player is Running */
 55+char *S_names[MAXSCROLLS];		/* Names of the scrolls */
 56+char Take;				/* Thing she is taking */
 57+char Whoami[MAXSTR];			/* Name of player */
 58+char *Ws_made[MAXSTICKS];		/* What sticks are made of */
 59+char *Ws_type[MAXSTICKS];		/* Is it a wand or a staff */
 60+#ifdef TIOCSLTC
 61+char Orig_dsusp;			/* Original dsusp char */
 62+#endif
 63+char Fruit[MAXSTR] =			/* Favorite fruit */
 64+		{ 's', 'l', 'i', 'm', 'e', '-', 'm', 'o', 'l', 'd', '\0' };
 65+char Home[MAXSTR] = { '\0' };		/* User's home directory */
 66+char *Inv_t_name[] = {
 67+	"Overwrite",
 68+	"Slow",
 69+	"Clear"
 70+};
 71+char L_last_comm = '\0';		/* Last Last_comm */
 72+char L_last_dir = '\0';			/* Last Last_dir */
 73+char Last_comm = '\0';			/* Last command typed */
 74+char Last_dir = '\0';			/* Last direction given */
 75+char *Tr_name[] = {			/* Names of the traps */
 76+	"a trapdoor",
 77+	"an arrow trap",
 78+	"a sleeping gas trap",
 79+	"a beartrap",
 80+	"a teleport trap",
 81+	"a poison dart trap",
 82+	"a rust trap",
 83+};
 84+
 85+
 86+int N_objs;				/* # items listed in inventory() call */
 87+int Ntraps;				/* Number of traps on this level */
 88+int Hungry_state = 0;			/* How hungry is he */
 89+int Inpack = 0;				/* Number of things in pack */
 90+int Inv_type = 0;			/* Type of inventory to use */
 91+int Level = 1;				/* What level she is on */
 92+int Max_hit;				/* Max damage done to her in To_death */
 93+int Max_level;				/* Deepest player has gone */
 94+int Mpos = 0;				/* Where cursor is on top line */
 95+int No_food = 0;			/* Number of levels without food */
 96+int A_class[MAXARMORS] = {		/* Armor class for each armor type */
 97+	8,	/* LEATHER */
 98+	7,	/* RING_MAIL */
 99+	7,	/* STUDDED_LEATHER */
100+	6,	/* SCALE_MAIL */
101+	5,	/* CHAIN_MAIL */
102+	4,	/* SPLINT_MAIL */
103+	4,	/* BANDED_MAIL */
104+	3,	/* PLATE_MAIL */
105+};
106+
107+int Count = 0;				/* Number of times to repeat command */
108+int Fd;					/* File descriptor for score file */
109+int Food_left;				/* Amount of food in hero's stomach */
110+int Lastscore = -1;			/* Score before this turn */
111+int No_command = 0;			/* Number of turns asleep */
112+int No_move = 0;			/* Number of turns held in place */
113+int Purse = 0;				/* How much gold he has */
114+int Quiet = 0;				/* Number of quiet turns */
115+int Vf_hit = 0;				/* Number of time flytrap has hit */
116+
117+long Dnum;				/* Dungeon number */
118+long Seed;				/* Random number seed */
119+long E_levels[] = {
120+        10L,
121+	20L,
122+	40L,
123+	80L,
124+       160L,
125+       320L,
126+       640L,
127+      1300L,
128+      2600L,
129+      5200L,
130+     13000L,
131+     26000L,
132+     50000L,
133+    100000L,
134+    200000L,
135+    400000L,
136+    800000L,
137+   2000000L,
138+   4000000L,
139+   8000000L,
140+	 0L
141+};
142+
143+coord Delta;				/* Change indicated to get_dir() */
144+coord Oldpos;				/* Position before last look() call */
145+coord Stairs;				/* Location of staircase */
146+
147+PLACE Places[MAXLINES*MAXCOLS];		/* Level map */
148+
149+THING *Cur_armor;			/* What he is wearing */
150+THING *Cur_ring[2];			/* Which rings are being worn */
151+THING *Cur_weapon;			/* Which weapon he is weilding */
152+THING *L_last_pick = NULL;		/* Last Last_pick */
153+THING *Last_pick = NULL;		/* Last object picked in get_item() */
154+THING *Lvl_obj = NULL;			/* List of objects on this level */
155+THING *Mlist = NULL;			/* List of monsters on the level */
156+THING Player;				/* His stats */
157+					/* restart of game */
158+
159+WINDOW *Hw = NULL;			/* Used as a scratch window */
160+
161+#define INIT_STATS { 16, 0, 1, 10, 12, "1x4", 12 }
162+
163+struct stats Max_stats = INIT_STATS;	/* The maximum for the player */
164+
165+struct room *Oldrp;			/* Roomin(&Oldpos) */
166+struct room Rooms[MAXROOMS];		/* One for each room -- A level */
167+struct room Passages[MAXPASS] =		/* One for each passage */
168+{
169+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
170+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
171+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
172+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
173+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
174+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
175+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
176+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
177+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
178+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
179+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
180+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }
181+};
182+
183+#define ___ 1
184+#define XX 10
185+struct monster Monsters[26] =
186+    {
187+/* Name		 CARRY	FLAG    str, exp, lvl, amr, hpt, dmg */
188+{ "aquator",	   0,	ISMEAN,	{ XX, 20,   5,   2, ___, "0x0/0x0" } },
189+{ "bat",	   0,	ISFLY,	{ XX,  1,   1,   3, ___, "1x2" } },
190+{ "centaur",	  15,	0,	{ XX, 17,   4,   4, ___, "1x2/1x5/1x5" } },
191+{ "dragon",	 100,	ISMEAN,	{ XX,5000, 10,  -1, ___, "1x8/1x8/3x10" } },
192+{ "emu",	   0,	ISMEAN,	{ XX,  2,   1,   7, ___, "1x2" } },
193+{ "venus flytrap", 0,	ISMEAN,	{ XX, 80,   8,   3, ___, "%%%x0" } },
194+	/* NOTE: the damage is %%% so that xstr won't merge this */
195+	/* string with others, since it is written on in the program */
196+{ "griffin",	  20,	ISMEAN|ISFLY|ISREGEN, { XX,2000, 13,   2, ___, "4x3/3x5" } },
197+{ "hobgoblin",	   0,	ISMEAN,	{ XX,  3,   1,   5, ___, "1x8" } },
198+{ "ice monster",   0,	0,	{ XX,  5,   1,   9, ___, "0x0" } },
199+{ "jabberwock",   70,	0,	{ XX,3000, 15,   6, ___, "2x12/2x4" } },
200+{ "kestrel",	   0,	ISMEAN|ISFLY,	{ XX,  1,   1,   7, ___, "1x4" } },
201+{ "leprechaun",	   0,	0,	{ XX, 10,   3,   8, ___, "1x1" } },
202+{ "medusa",	  40,	ISMEAN,	{ XX,200,   8,   2, ___, "3x4/3x4/2x5" } },
203+{ "nymph",	 100,	0,	{ XX, 37,   3,   9, ___, "0x0" } },
204+{ "orc",	  15,	ISGREED,{ XX,  5,   1,   6, ___, "1x8" } },
205+{ "phantom",	   0,	ISINVIS,{ XX,120,   8,   3, ___, "4x4" } },
206+{ "quagga",	   0,	ISMEAN,	{ XX, 15,   3,   3, ___, "1x5/1x5" } },
207+{ "rattlesnake",   0,	ISMEAN,	{ XX,  9,   2,   3, ___, "1x6" } },
208+{ "snake",	   0,	ISMEAN,	{ XX,  2,   1,   5, ___, "1x3" } },
209+{ "troll",	  50,	ISREGEN|ISMEAN,{ XX, 120, 6, 4, ___, "1x8/1x8/2x6" } },
210+{ "black unicorn", 0,	ISMEAN,	{ XX,190,   7,  -2, ___, "1x9/1x9/2x9" } },
211+{ "vampire",	  20,	ISREGEN|ISMEAN,{ XX,350,   8,   1, ___, "1x10" } },
212+{ "wraith",	   0,	0,	{ XX, 55,   5,   4, ___, "1x6" } },
213+{ "xeroc",	  30,	0,	{ XX,100,   7,   7, ___, "4x4" } },
214+{ "yeti",	  30,	0,	{ XX, 50,   4,   6, ___, "1x6/1x6" } },
215+{ "zombie",	   0,	ISMEAN,	{ XX,  6,   2,   8, ___, "1x8" } }
216+    };
217+#undef ___
218+#undef XX
219+
220+struct obj_info Things[NUMTHINGS] = {
221+    { 0,			26 },	/* potion */
222+    { 0,			36 },	/* scroll */
223+    { 0,			16 },	/* food */
224+    { 0,			 7 },	/* weapon */
225+    { 0,			 7 },	/* armor */
226+    { 0,			 4 },	/* ring */
227+    { 0,			 4 },	/* stick */
228+};
229+
230+struct obj_info Arm_info[MAXARMORS] = {
231+    { "leather armor",		 20,	 20, NULL, FALSE },
232+    { "ring mail",		 15,	 25, NULL, FALSE },
233+    { "studded leather armor",	 15,	 20, NULL, FALSE },
234+    { "scale mail",		 13,	 30, NULL, FALSE },
235+    { "chain mail",		 12,	 75, NULL, FALSE },
236+    { "splint mail",		 10,	 80, NULL, FALSE },
237+    { "banded mail",		 10,	 90, NULL, FALSE },
238+    { "plate mail",		  5,	150, NULL, FALSE },
239+};
240+struct obj_info Pot_info[MAXPOTIONS] = {
241+    { "confusion",		 7,   5, NULL, FALSE },
242+    { "hallucination",		 8,   5, NULL, FALSE },
243+    { "poison",			 8,   5, NULL, FALSE },
244+    { "gain strength",		13, 150, NULL, FALSE },
245+    { "see invisible",		 3, 100, NULL, FALSE },
246+    { "healing",		13, 130, NULL, FALSE },
247+    { "monster detection",	 6, 130, NULL, FALSE },
248+    { "magic detection",	 6, 105, NULL, FALSE },
249+    { "raise level",		 2, 250, NULL, FALSE },
250+    { "extra healing",		 5, 200, NULL, FALSE },
251+    { "haste self",		 5, 190, NULL, FALSE },
252+    { "restore strength",	13, 130, NULL, FALSE },
253+    { "blindness",		 5,   5, NULL, FALSE },
254+    { "levitation",		 6,  75, NULL, FALSE },
255+};
256+struct obj_info Ring_info[MAXRINGS] = {
257+    { "protection",		 9, 400, NULL, FALSE },
258+    { "add strength",		 9, 400, NULL, FALSE },
259+    { "sustain strength",	 5, 280, NULL, FALSE },
260+    { "searching",		10, 420, NULL, FALSE },
261+    { "see invisible",		10, 310, NULL, FALSE },
262+    { "adornment",		 1,  10, NULL, FALSE },
263+    { "aggravate monster",	10,  10, NULL, FALSE },
264+    { "dexterity",		 8, 440, NULL, FALSE },
265+    { "increase damage",	 8, 400, NULL, FALSE },
266+    { "regeneration",		 4, 460, NULL, FALSE },
267+    { "slow digestion",		 9, 240, NULL, FALSE },
268+    { "teleportation",		 5,  30, NULL, FALSE },
269+    { "stealth",		 7, 470, NULL, FALSE },
270+    { "maintain armor",		 5, 380, NULL, FALSE },
271+};
272+struct obj_info Scr_info[MAXSCROLLS] = {
273+    { "monster confusion",		 7, 140, NULL, FALSE },
274+    { "magic mapping",			 4, 150, NULL, FALSE },
275+    { "hold monster",			 2, 180, NULL, FALSE },
276+    { "sleep",				 3,   5, NULL, FALSE },
277+    { "enchant armor",			 7, 160, NULL, FALSE },
278+    { "identify potion",		10,  80, NULL, FALSE },
279+    { "identify scroll",		10,  80, NULL, FALSE },
280+    { "identify weapon",		 6,  80, NULL, FALSE },
281+    { "identify armor",		 	 7, 100, NULL, FALSE },
282+    { "identify ring, wand or staff",	10, 115, NULL, FALSE },
283+    { "scare monster",			 3, 200, NULL, FALSE },
284+    { "food detection",			 2,  60, NULL, FALSE },
285+    { "teleportation",			 5, 165, NULL, FALSE },
286+    { "enchant weapon",			 8, 150, NULL, FALSE },
287+    { "create monster",			 4,  75, NULL, FALSE },
288+    { "remove curse",			 7, 105, NULL, FALSE },
289+    { "aggravate monsters",		 3,  20, NULL, FALSE },
290+    { "protect armor",			 2, 250, NULL, FALSE },
291+};
292+struct obj_info Weap_info[MAXWEAPONS + 1] = {
293+    { "mace",				11,   8, NULL, FALSE },
294+    { "long sword",			11,  15, NULL, FALSE },
295+    { "short bow",			12,  15, NULL, FALSE },
296+    { "arrow",				12,   1, NULL, FALSE },
297+    { "dagger",				 8,   3, NULL, FALSE },
298+    { "two handed sword",		10,  75, NULL, FALSE },
299+    { "dart",				12,   2, NULL, FALSE },
300+    { "shuriken",			12,   5, NULL, FALSE },
301+    { "spear",				12,   5, NULL, FALSE },
302+    { NULL, 0 },	/* DO NOT REMOVE: fake entry for dragon's breath */
303+};
304+struct obj_info Ws_info[MAXSTICKS] = {
305+    { "light",			12, 250, NULL, FALSE },
306+    { "invisibility",		 6,   5, NULL, FALSE },
307+    { "lightning",		 3, 330, NULL, FALSE },
308+    { "fire",			 3, 330, NULL, FALSE },
309+    { "cold",			 3, 330, NULL, FALSE },
310+    { "polymorph",		15, 310, NULL, FALSE },
311+    { "magic missile",		10, 170, NULL, FALSE },
312+    { "haste monster",		10,   5, NULL, FALSE },
313+    { "slow monster",		11, 350, NULL, FALSE },
314+    { "drain life",		 9, 300, NULL, FALSE },
315+    { "nothing",		 1,   5, NULL, FALSE },
316+    { "teleport away",		 6, 340, NULL, FALSE },
317+    { "teleport to",		 6,  50, NULL, FALSE },
318+    { "cancellation",		 5, 280, NULL, FALSE },
319+};
320+
321+struct h_list Helpstr[] = {
322+    '?',	"	prints help",				TRUE,
323+    '/',	"	identify object",			TRUE,
324+    'h',	"	left",					TRUE,
325+    'j',	"	down",					TRUE,
326+    'k',	"	up",					TRUE,
327+    'l',	"	right",					TRUE,
328+    'y',	"	up & left",				TRUE,
329+    'u',	"	up & right",				TRUE,
330+    'b',	"	down & left",				TRUE,
331+    'n',	"	down & right",				TRUE,
332+    'H',	"	run left",				FALSE,
333+    'J',	"	run down",				FALSE,
334+    'K',	"	run up",				FALSE,
335+    'L',	"	run right",				FALSE,
336+    'Y',	"	run up & left",				FALSE,
337+    'U',	"	run up & right",			FALSE,
338+    'B',	"	run down & left",			FALSE,
339+    'N',	"	run down & right",			FALSE,
340+    CTRL('H'),	"	run left until adjacent",		FALSE,
341+    CTRL('J'),	"	run down until adjacent",		FALSE,
342+    CTRL('K'),	"	run up until adjacent",			FALSE,
343+    CTRL('L'),	"	run right until adjacent",		FALSE,
344+    CTRL('Y'),	"	run up & left until adjacent",		FALSE,
345+    CTRL('U'),	"	run up & right until adjacent",		FALSE,
346+    CTRL('B'),	"	run down & left until adjacent",	FALSE,
347+    CTRL('N'),	"	run down & right until adjacent",	FALSE,
348+    '\0',	"	<SHIFT><dir>: run that way",		TRUE,
349+    '\0',	"	<CTRL><dir>: run till adjacent",	TRUE,
350+    'f',	"<dir>	fight till death or near death",	TRUE,
351+    't',	"<dir>	throw something",			TRUE,
352+    'm',	"<dir>	move onto without picking up",		TRUE,
353+    'z',	"<dir>	zap a wand in a direction",		TRUE,
354+    '^',	"<dir>	identify trap type",			TRUE,
355+    's',	"	search for trap/secret door",		TRUE,
356+    '>',	"	go down a staircase",			TRUE,
357+    '<',	"	go up a staircase",			TRUE,
358+    '.',	"	rest for a turn",			TRUE,
359+    'i',	"	inventory",				TRUE,
360+    'I',	"	inventory single item",			TRUE,
361+    'q',	"	quaff potion",				TRUE,
362+    'r',	"	read scroll",				TRUE,
363+    'e',	"	eat food",				TRUE,
364+    'w',	"	wield a weapon",			TRUE,
365+    'W',	"	wear armor",				TRUE,
366+    'T',	"	take armor off",			TRUE,
367+    'P',	"	put on ring",				TRUE,
368+    'R',	"	remove ring",				TRUE,
369+    'd',	"	drop object",				TRUE,
370+    'c',	"	call object",				TRUE,
371+    'a',	"	repeat last command",			TRUE,
372+    ')',	"	print current weapon",			TRUE,
373+    ']',	"	print current armor",			TRUE,
374+    '=',	"	print current rings",			TRUE,
375+    '@',	"	print current stats",			TRUE,
376+    'D',	"	recall what's been discovered",		TRUE,
377+    'o',	"	examine/set options",			TRUE,
378+    CTRL('R'),	"	redraw screen",				TRUE,
379+    CTRL('P'),	"	repeat last message",			TRUE,
380+    ESCAPE,	"	cancel command",			TRUE,
381+    'S',	"	save game",				TRUE,
382+    'Q',	"	quit",					TRUE,
383+    '!',	"	shell escape",				TRUE,
384+    'F',	"<dir>	fight till either of you dies",		TRUE,
385+    'v',	"	print version number",			TRUE,
386+    0,		NULL
387+};
388+
389+#ifdef TIOCGLTC
390+struct ltchars Ltc;		/* needed to change ^Y to not be suspchar */
391+#endif TIOCGLTC
A ropen.c
+17, -0
 1@@ -0,0 +1,17 @@
 2+/*
 3+ * print out an encrypted password on the standard output
 4+ *
 5+ * @(#)ropen.c	1.4 (Berkeley) 02/05/99
 6+ */
 7+#include <stdio.h>
 8+
 9+int
10+main(void)
11+{
12+    static char buf[80];
13+
14+    fprintf(stderr, "Password: ");
15+    fgets(buf, 80, stdin);
16+    buf[strlen(buf) - 1] = '\0';
17+    printf("%s\n", crypt(buf, "mT"));
18+}
A rread.c
+181, -0
  1@@ -0,0 +1,181 @@
  2+/*
  3+ * Contains functions for dealing with things that happen in the
  4+ * future.
  5+ *
  6+ * @(#)rread.c	4.7 (Berkeley) 02/05/99
  7+ */
  8+
  9+#include <curses.h>
 10+#include "netprot.h"
 11+
 12+#define EMPTY 0
 13+#define DAEMON -1
 14+#define MAXDAEMONS 20
 15+
 16+#define _X_ { EMPTY }
 17+
 18+struct delayed_action {
 19+    int d_type;
 20+    void (*d_func)(int);
 21+    int d_arg;
 22+    int d_time;
 23+} d_list[MAXDAEMONS] = {
 24+    _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
 25+    _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, 
 26+};
 27+
 28+/*
 29+ * d_slot:
 30+ *	Find an empty slot in the daemon/fuse list
 31+ */
 32+struct delayed_action *
 33+d_slot(void)
 34+{
 35+    struct delayed_action *dev;
 36+
 37+    for (dev = d_list; dev < &d_list[MAXDAEMONS]; dev++)
 38+	if (dev->d_type == EMPTY)
 39+	    return dev;
 40+#ifdef MASTER
 41+    debug("Ran out of fuse slots");
 42+#endif
 43+    return NULL;
 44+}
 45+
 46+/*
 47+ * find_slot:
 48+ *	Find a particular slot in the table
 49+ */
 50+struct delayed_action *
 51+find_slot(void (*func)(int))
 52+{
 53+    struct delayed_action *dev;
 54+
 55+    for (dev = d_list; dev < &d_list[MAXDAEMONS]; dev++)
 56+	if (dev->d_type != EMPTY && func == dev->d_func)
 57+	    return dev;
 58+    return NULL;
 59+}
 60+
 61+/*
 62+ * start_daemon:
 63+ *	Start a daemon, takes a function.
 64+ */
 65+void
 66+start_daemon(void (*func)(int), int arg, int type)
 67+{
 68+    struct delayed_action *dev;
 69+
 70+    dev = d_slot();
 71+    dev->d_type = type;
 72+    dev->d_func = func;
 73+    dev->d_arg = arg;
 74+    dev->d_time = DAEMON;
 75+}
 76+
 77+/*
 78+ * kill_daemon:
 79+ *	Remove a daemon from the list
 80+ */
 81+void
 82+kill_daemon(void (*func)(int))
 83+{
 84+    struct delayed_action *dev;
 85+
 86+    if ((dev = find_slot(func)) == NULL)
 87+	return;
 88+    /*
 89+     * Take it out of the list
 90+     */
 91+    dev->d_type = EMPTY;
 92+}
 93+
 94+/*
 95+ * do_daemons:
 96+ *	Run all the daemons that are active with the current flag,
 97+ *	passing the argument to the function.
 98+ */
 99+void
100+do_daemons(flag)
101+int flag;
102+{
103+    struct delayed_action *dev;
104+
105+    /*
106+     * Loop through the devil list
107+     */
108+    for (dev = d_list; dev < &d_list[MAXDAEMONS]; dev++)
109+	/*
110+	 * Executing each one, giving it the proper arguments
111+	 */
112+	if (dev->d_type == flag && dev->d_time == DAEMON)
113+	    (*dev->d_func)(dev->d_arg);
114+}
115+
116+/*
117+ * fuse:
118+ *	Start a fuse to go off in a certain number of turns
119+ */
120+void
121+fuse(void (*func)(int), int arg, int tm, int type)
122+{
123+    struct delayed_action *wire;
124+
125+    wire = d_slot();
126+    wire->d_type = type;
127+    wire->d_func = func;
128+    wire->d_arg = arg;
129+    wire->d_time = tm;
130+}
131+
132+/*
133+ * lengthen:
134+ *	Increase the time until a fuse goes off
135+ */
136+void
137+lengthen(void (*func)(int), int xtime)
138+{
139+    struct delayed_action *wire;
140+
141+    if ((wire = find_slot(func)) == NULL)
142+	return;
143+    wire->d_time += xtime;
144+}
145+
146+/*
147+ * extinguish:
148+ *	Put out a fuse
149+ */
150+void
151+extinguish(void (*func)(int))
152+{
153+    struct delayed_action *wire;
154+
155+    if ((wire = find_slot(func)) == NULL)
156+	return;
157+    wire->d_type = EMPTY;
158+}
159+
160+/*
161+ * do_fuses:
162+ *	Decrement counters and start needed fuses
163+ */
164+void
165+do_fuses(int flag)
166+{
167+    struct delayed_action *wire;
168+
169+    /*
170+     * Step though the list
171+     */
172+    for (wire = d_list; wire < &d_list[MAXDAEMONS]; wire++)
173+	/*
174+	 * Decrementing counters and starting things we want.  We also need
175+	 * to remove the fuse from the list once it has gone off.
176+	 */
177+	if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0)
178+	{
179+	    wire->d_type = EMPTY;
180+	    (*wire->d_func)(wire->d_arg);
181+	}
182+}
A rwrite.c
+805, -0
  1@@ -0,0 +1,805 @@
  2+/*
  3+ * Read and execute the user commands
  4+ *
  5+ * @(#)rwrite.c	4.73 (Berkeley) 08/06/83
  6+ */
  7+
  8+#include <curses.h>
  9+#include <ctype.h>
 10+#include "netprot.h"
 11+
 12+/*
 13+ * command:
 14+ *	Process the user commands
 15+ */
 16+void
 17+command(void)
 18+{
 19+    char ch;
 20+    int ntimes = 1;			/* Number of player moves */
 21+    char *fp;
 22+    THING *mp;
 23+    static char countch, direction, newcount = FALSE;
 24+
 25+    if (on(Player, ISHASTE))
 26+	ntimes++;
 27+    /*
 28+     * Let the daemons start up
 29+     */
 30+    do_daemons(BEFORE);
 31+    do_fuses(BEFORE);
 32+    while (ntimes--)
 33+    {
 34+	Again = FALSE;
 35+	if (Has_hit)
 36+	{
 37+	    endmsg();
 38+	    Has_hit = FALSE;
 39+	}
 40+	/*
 41+	 * these are illegal things for the player to be, so if any are
 42+	 * set, someone's been poking in memeory
 43+	 */
 44+	if (on(Player, ISSLOW|ISGREED|ISINVIS|ISREGEN|ISTARGET))
 45+	    exit(1);
 46+
 47+	look(TRUE);
 48+	if (!Running)
 49+	    Door_stop = FALSE;
 50+	status();
 51+	Lastscore = Purse;
 52+	move(Hero.y, Hero.x);
 53+	if (!((Running || Count) && Jump))
 54+	    refresh();			/* Draw screen */
 55+	Take = 0;
 56+	After = TRUE;
 57+	/*
 58+	 * Read command or continue run
 59+	 */
 60+#ifdef MASTER
 61+	if (Wizard)
 62+	    Noscore = TRUE;
 63+#endif
 64+	if (!No_command)
 65+	{
 66+	    if (Running || To_death)
 67+		ch = Runch;
 68+	    else if (Count)
 69+		ch = countch;
 70+	    else
 71+	    {
 72+		ch = readchar();
 73+		Move_on = FALSE;
 74+		if (Mpos != 0)		/* Erase message if its there */
 75+		    msg("");
 76+	    }
 77+	}
 78+	else
 79+	    ch = '.';
 80+	if (No_command)
 81+	{
 82+	    if (--No_command == 0)
 83+	    {
 84+		Player.t_flags |= ISRUN;
 85+		msg("you can move again");
 86+	    }
 87+	}
 88+	else
 89+	{
 90+	    /*
 91+	     * check for prefixes
 92+	     */
 93+	    newcount = FALSE;
 94+	    if (isdigit(ch))
 95+	    {
 96+		Count = 0;
 97+		newcount = TRUE;
 98+		while (isdigit(ch))
 99+		{
100+		    Count = Count * 10 + (ch - '0');
101+		    ch = readchar();
102+		}
103+		countch = ch;
104+		/*
105+		 * turn off Count for commands which don't make sense
106+		 * to repeat
107+		 */
108+		switch (ch)
109+		{
110+		    case CTRL('B'): case CTRL('H'): case CTRL('J'):
111+		    case CTRL('K'): case CTRL('L'): case CTRL('N'):
112+		    case CTRL('U'): case CTRL('Y'):
113+		    case '.': case 'a': case 'b': case 'h': case 'j':
114+		    case 'k': case 'l': case 'm': case 'n': case 'q':
115+		    case 'r': case 's': case 't': case 'u': case 'y':
116+		    case 'z': case 'B': case 'C': case 'H': case 'I':
117+		    case 'J': case 'K': case 'L': case 'N': case 'U':
118+		    case 'Y':
119+#ifdef MASTER
120+		    case CTRL('D'): case CTRL('A'):
121+#endif
122+			break;
123+		    default:
124+			Count = 0;
125+		}
126+	    }
127+	    /*
128+	     * execute a command
129+	     */
130+	    if (Count && !Running)
131+		Count--;
132+	    if (ch != 'a' && ch != ESCAPE && !(Running || Count || To_death))
133+	    {
134+		L_last_comm = Last_comm;
135+		L_last_dir = Last_dir;
136+		L_last_pick = Last_pick;
137+		Last_comm = ch;
138+		Last_dir = '\0';
139+		Last_pick = NULL;
140+	    }
141+over:
142+	    switch (ch)
143+	    {
144+		when ',': {
145+		    THING *obj = NULL;
146+		    int found = 0;
147+		    for (obj = Lvl_obj; obj != NULL; obj = next(obj))
148+    			{
149+			    if (obj->o_pos.y == Hero.y && obj->o_pos.x == Hero.x)
150+			    {
151+				found=1;
152+				break;
153+			    }
154+    			}
155+
156+		    if (found) {
157+			if (levit_check())
158+			    ;
159+			else
160+			    pick_up(obj->o_type);
161+		    }
162+		    else {
163+			if (!Terse)
164+			    addmsg("you are ");
165+			msg("not standing on any object");
166+		    }
167+		}
168+		when '!': shell();
169+		when 'h': do_move(0, -1);
170+		when 'j': do_move(1, 0);
171+		when 'k': do_move(-1, 0);
172+		when 'l': do_move(0, 1);
173+		when 'y': do_move(-1, -1);
174+		when 'u': do_move(-1, 1);
175+		when 'b': do_move(1, -1);
176+		when 'n': do_move(1, 1);
177+		when 'H': do_run('h');
178+		when 'J': do_run('j');
179+		when 'K': do_run('k');
180+		when 'L': do_run('l');
181+		when 'Y': do_run('y');
182+		when 'U': do_run('u');
183+		when 'B': do_run('b');
184+		when 'N': do_run('n');
185+		when CTRL('H'): case CTRL('J'): case CTRL('K'): case CTRL('L'):
186+		case CTRL('Y'): case CTRL('U'): case CTRL('B'): case CTRL('N'):
187+		{
188+		    if (!on(Player, ISBLIND))
189+		    {
190+			Door_stop = TRUE;
191+			Firstmove = TRUE;
192+		    }
193+		    if (Count && !newcount)
194+			ch = direction;
195+		    else
196+		    {
197+			ch += ('A' - CTRL('A'));
198+			direction = ch;
199+		    }
200+		    goto over;
201+		}
202+		when 'F':
203+		    Kamikaze = TRUE;
204+		    /* FALLTHROUGH */
205+		case 'f':
206+		    if (!get_dir())
207+		    {
208+			After = FALSE;
209+			break;
210+		    }
211+		    Delta.y += Hero.y;
212+		    Delta.x += Hero.x;
213+		    if (((mp = moat(Delta.y, Delta.x)) == NULL
214+			|| (!see_monst(mp)) && !on(Player, SEEMONST)))
215+		    {
216+			if (!Terse)
217+			    addmsg("I see ");
218+			msg("no monster there");
219+			After = FALSE;
220+		    }
221+		    else if (diag_ok(&Hero, &Delta))
222+		    {
223+			To_death = TRUE;
224+			Max_hit = 0;
225+			mp->t_flags |= ISTARGET;
226+			Runch = ch = Dir_ch;
227+			goto over;
228+		    }
229+		when 't':
230+		    if (!get_dir())
231+			After = FALSE;
232+		    else
233+			missile(Delta.y, Delta.x);
234+		when 'a':
235+		    if (Last_comm == '\0')
236+		    {
237+			msg("you haven't typed a command yet");
238+			After = FALSE;
239+		    }
240+		    else
241+		    {
242+			ch = Last_comm;
243+			Again = TRUE;
244+			goto over;
245+		    }
246+		when 'q': quaff();
247+		when 'Q':
248+		    After = FALSE;
249+		    Q_comm = TRUE;
250+		    quit(0);
251+		    Q_comm = FALSE;
252+		when 'i': After = FALSE; inventory(Pack, 0);
253+		when 'I': After = FALSE; picky_inven();
254+		when 'd': drop();
255+		when 'r': read_scroll();
256+		when 'e': eat();
257+		when 'w': wield();
258+		when 'W': wear();
259+		when 'T': take_off();
260+		when 'P': ring_on();
261+		when 'R': ring_off();
262+		when 'o': option(); After = FALSE;
263+		when 'c': call(); After = FALSE;
264+		when '>': After = FALSE; d_level();
265+		when '<': After = FALSE; u_level();
266+		when '?': After = FALSE; help();
267+		when '/': After = FALSE; identify();
268+		when 's': search();
269+		when 'z':
270+		    if (get_dir())
271+			do_zap();
272+		    else
273+			After = FALSE;
274+		when 'D': After = FALSE; discovered();
275+		when CTRL('P'): After = FALSE; msg(Huh);
276+		when CTRL('R'):
277+		    After = FALSE;
278+		    clearok(curscr,TRUE);
279+		    wrefresh(curscr);
280+		when 'v':
281+		    After = FALSE;
282+		    msg("version %s. (mctesq was here)", Release);
283+		when 'S': 
284+		    After = FALSE;
285+		    save_game();
286+		when '.': ;			/* Rest command */
287+		when ' ': After = FALSE;	/* "Legal" illegal command */
288+		when '^':
289+		    After = FALSE;
290+		    if (get_dir()) {
291+			Delta.y += Hero.y;
292+			Delta.x += Hero.x;
293+			fp = &flat(Delta.y, Delta.x);
294+			if (chat(Delta.y, Delta.x) != TRAP)
295+			    msg("no trap there");
296+			else if (on(Player, ISHALU))
297+			    msg(Tr_name[rnd(NTRAPS)]);
298+			else {
299+			    msg(Tr_name[*fp & F_TMASK]);
300+			    *fp |= F_SEEN;
301+			}
302+		    }
303+#ifdef MASTER
304+		when '+':
305+		    After = FALSE;
306+		    if (Wizard)
307+		    {
308+			Wizard = FALSE;
309+			turn_see(TRUE);
310+			msg("not wizard any more");
311+		    }
312+		    else
313+		    {
314+/*			if (Wizard = passwd()) */
315+			if (Wizard = 1)
316+			{
317+			    Noscore = TRUE;
318+			    turn_see(FALSE);
319+			    msg("you are suddenly as smart as Ken Arnold in dungeon #%d", Dnum);
320+			}
321+			else
322+			    msg("sorry");
323+		    }
324+#endif
325+		when ESCAPE:	/* Escape */
326+		    Door_stop = FALSE;
327+		    Count = 0;
328+		    After = FALSE;
329+		    Again = FALSE;
330+		when 'm':
331+		    Move_on = TRUE;
332+		    if (!get_dir())
333+			After = FALSE;
334+		    else
335+		    {
336+			ch = Dir_ch;
337+			countch = Dir_ch;
338+			goto over;
339+		    }
340+		when ')': current(Cur_weapon, "wielding", NULL);
341+		when ']': current(Cur_armor, "wearing", NULL);
342+		when '=':
343+		    current(Cur_ring[LEFT], "wearing",
344+					    Terse ? "(L)" : "on left hand");
345+		    current(Cur_ring[RIGHT], "wearing",
346+					    Terse ? "(R)" : "on right hand");
347+		when '@':
348+		    Stat_msg = TRUE;
349+		    status();
350+		    Stat_msg = FALSE;
351+		    After = FALSE;
352+		otherwise:
353+		    After = FALSE;
354+#ifdef MASTER
355+		    if (Wizard) switch (ch)
356+		    {
357+			when '|': msg("@ %d,%d", Hero.y, Hero.x);
358+			when 'C': create_obj();
359+			when '$': msg("Inpack = %d", Inpack);
360+			when CTRL('G'): inventory(Lvl_obj, 0);
361+			when CTRL('W'): whatis(FALSE, 0);
362+			when CTRL('D'): Level++; new_level();
363+			when CTRL('A'): Level--; new_level();
364+			when CTRL('F'): show_map();
365+			when CTRL('T'): teleport();
366+			when CTRL('E'): msg("food left: %d", Food_left);
367+			when CTRL('C'): add_pass();
368+			when CTRL('X'): turn_see(on(Player, SEEMONST));
369+			when CTRL('~'):
370+			{
371+			    THING *item;
372+
373+			    if ((item = get_item("charge", STICK)) != NULL)
374+				item->o_charges = 10000;
375+			}
376+			when CTRL('I'):
377+			{
378+			    int i;
379+			    THING *obj;
380+
381+			    for (i = 0; i < 9; i++)
382+				raise_level();
383+			    /*
384+			     * Give him a sword (+1,+1)
385+			     */
386+			    obj = new_item();
387+			    init_weapon(obj, TWOSWORD);
388+			    obj->o_hplus = 1;
389+			    obj->o_dplus = 1;
390+			    add_pack(obj, TRUE);
391+			    Cur_weapon = obj;
392+			    /*
393+			     * And his suit of armor
394+			     */
395+			    obj = new_item();
396+			    obj->o_type = ARMOR;
397+			    obj->o_which = PLATE_MAIL;
398+			    obj->o_arm = -5;
399+			    obj->o_flags |= ISKNOW;
400+			    obj->o_count = 1;
401+			    obj->o_group = 0;
402+			    Cur_armor = obj;
403+			    add_pack(obj, TRUE);
404+			}
405+			when '*' :
406+			    pr_list();
407+			otherwise:
408+			    illcom(ch);
409+		    }
410+		    else
411+#endif
412+			illcom(ch);
413+	    }
414+	    /*
415+	     * turn off flags if no longer needed
416+	     */
417+	    if (!Running)
418+		Door_stop = FALSE;
419+	}
420+	/*
421+	 * If he ran into something to take, let him pick it up.
422+	 */
423+	if (Take != 0)
424+	    pick_up(Take);
425+	if (!Running)
426+	    Door_stop = FALSE;
427+	if (!After)
428+	    ntimes++;
429+    }
430+    do_daemons(AFTER);
431+    do_fuses(AFTER);
432+    if (ISRING(LEFT, R_SEARCH))
433+	search();
434+    else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0)
435+	teleport();
436+    if (ISRING(RIGHT, R_SEARCH))
437+	search();
438+    else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0)
439+	teleport();
440+}
441+
442+/*
443+ * illcom:
444+ *	What to do with an illegal command
445+ */
446+void
447+illcom(char ch)
448+{
449+    Save_msg = FALSE;
450+    Count = 0;
451+    msg("illegal command '%s'", unctrl(ch));
452+    Save_msg = TRUE;
453+}
454+
455+/*
456+ * search:
457+ *	Player gropes about him to find hidden things.
458+ */
459+void
460+search(void)
461+{
462+    int y, x;
463+    char *fp;
464+    int ey, ex;
465+    int probinc;
466+    bool found;
467+
468+    ey = Hero.y + 1;
469+    ex = Hero.x + 1;
470+    probinc  = (on(Player, ISHALU)  ? 3 : 0);
471+    probinc += (on(Player, ISBLIND) ? 2 : 0);
472+    found = FALSE;
473+    for (y = Hero.y - 1; y <= ey; y++) 
474+	for (x = Hero.x - 1; x <= ex; x++)
475+	{
476+	    if (y == Hero.y && x == Hero.x)
477+		continue;
478+	    fp = &flat(y, x);
479+	    if (!(*fp & F_REAL))
480+		switch (chat(y, x))
481+		{
482+		    case '|':
483+		    case '-':
484+			if (rnd(5 + probinc) != 0)
485+			    break;
486+			chat(y, x) = DOOR;
487+foundone:
488+			found = TRUE;
489+			*fp |= F_REAL;
490+			Count = FALSE;
491+			Running = FALSE;
492+			break;
493+		    case FLOOR:
494+			if (rnd(2 + probinc) != 0)
495+			    break;
496+			chat(y, x) = TRAP;
497+			if (!Terse)
498+			    addmsg("you found ");
499+			if (on(Player, ISHALU))
500+			    msg(Tr_name[rnd(NTRAPS)]);
501+			else {
502+			    msg(Tr_name[*fp & F_TMASK]);
503+			    *fp |= F_SEEN;
504+			}
505+			goto foundone;
506+			break;
507+		    case ' ':
508+			if (rnd(3 + probinc) != 0)
509+			    break;
510+			chat(y, x) = PASSAGE;
511+			goto foundone;
512+		}
513+	}
514+    if (found)
515+	look(FALSE);
516+}
517+
518+/*
519+ * help:
520+ *	Give single character help, or the whole mess if he wants it
521+ */
522+void
523+help(void)
524+{
525+    struct h_list *strp;
526+    char helpch;
527+    unsigned int numprint, cnt;
528+
529+    msg("character you want help for (* for all): ");
530+    helpch = readchar();
531+    Mpos = 0;
532+    /*
533+     * If its not a *, print the right help string
534+     * or an error if he typed a funny character.
535+     */
536+    if (helpch != '*')
537+    {
538+	move(0, 0);
539+	for (strp = Helpstr; strp->h_desc != NULL; strp++)
540+	    if (strp->h_ch == helpch)
541+	    {
542+		Lower_msg = TRUE;
543+		msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
544+		Lower_msg = FALSE;
545+		return;
546+	    }
547+	msg("unknown character '%s'", unctrl(helpch));
548+	return;
549+    }
550+    /*
551+     * Here we print help for everything.
552+     * Then wait before we return to command mode
553+     */
554+    numprint = 0;
555+    for (strp = Helpstr; strp->h_desc != NULL; strp++)
556+	if (strp->h_print)
557+	    numprint++;
558+    if (numprint & 01)		/* round odd numbers up */
559+	numprint++;
560+    numprint /= 2;
561+    if (numprint > LINES - 1)
562+	numprint = LINES - 1;
563+
564+    wclear(Hw);
565+    cnt = 0;
566+    for (strp = Helpstr; strp->h_desc != NULL; strp++)
567+	if (strp->h_print)
568+	{
569+	    wmove(Hw, cnt % numprint, cnt >= numprint ? COLS / 2 : 0);
570+	    if (strp->h_ch)
571+		waddstr(Hw, unctrl(strp->h_ch));
572+	    waddstr(Hw, strp->h_desc);
573+	    if (++cnt >= numprint * 2)
574+		break;
575+	}
576+    wmove(Hw, LINES - 1, 0);
577+    waddstr(Hw, "--Press space to continue--");
578+    wrefresh(Hw);
579+    wait_for(' ');
580+    clearok(stdscr, TRUE);
581+/*
582+    refresh();
583+*/
584+    msg("");
585+    touchwin(stdscr);
586+    wrefresh(stdscr);
587+}
588+
589+/*
590+ * identify:
591+ *	Tell the player what a certain thing is.
592+ */
593+void
594+identify(void)
595+{
596+    int ch;
597+    struct h_list *hp;
598+    char *str;
599+    static struct h_list ident_list[] = {
600+	'|',		"wall of a room",		FALSE,
601+	'-',		"wall of a room",		FALSE,
602+	GOLD,		"gold",				FALSE,
603+	STAIRS,		"a staircase",			FALSE,
604+	DOOR,		"door",				FALSE,
605+	FLOOR,		"room floor",			FALSE,
606+	PLAYER,		"you",				FALSE,
607+	PASSAGE,	"passage",			FALSE,
608+	TRAP,		"trap",				FALSE,
609+	POTION,		"potion",			FALSE,
610+	SCROLL,		"scroll",			FALSE,
611+	FOOD,		"food",				FALSE,
612+	WEAPON,		"weapon",			FALSE,
613+	' ',		"solid rock",			FALSE,
614+	ARMOR,		"armor",			FALSE,
615+	AMULET,		"the Amulet of Yendor",		FALSE,
616+	RING,		"ring",				FALSE,
617+	STICK,		"wand or staff",		FALSE,
618+	'\0'
619+    };
620+
621+    msg("what do you want identified? ");
622+    ch = readchar();
623+    Mpos = 0;
624+    if (ch == ESCAPE)
625+    {
626+	msg("");
627+	return;
628+    }
629+    if (isupper(ch))
630+	str = Monsters[ch-'A'].m_name;
631+    else
632+    {
633+	str = "unknown character";
634+	for (hp = ident_list; hp->h_ch != '\0'; hp++)
635+	    if (hp->h_ch == ch)
636+	    {
637+		str = hp->h_desc;
638+		break;
639+	    }
640+    }
641+    msg("'%s': %s", unctrl(ch), str);
642+}
643+
644+/*
645+ * d_level:
646+ *	He wants to go down a level
647+ */
648+void
649+d_level(void)
650+{
651+    if (levit_check())
652+	return;
653+    if (chat(Hero.y, Hero.x) != STAIRS)
654+	msg("I see no way down");
655+    else
656+    {
657+	Level++;
658+	Seenstairs = FALSE;
659+	new_level();
660+    }
661+}
662+
663+/*
664+ * u_level:
665+ *	He wants to go up a level
666+ */
667+void
668+u_level(void)
669+{
670+    if (levit_check())
671+	return;
672+    if (chat(Hero.y, Hero.x) == STAIRS)
673+	if (Amulet)
674+	{
675+	    Level--;
676+	    if (Level == 0)
677+		total_winner();
678+	    new_level();
679+	    msg("you feel a wrenching sensation in your gut");
680+	}
681+	else
682+	    msg("your way is magically blocked");
683+    else
684+	msg("I see no way up");
685+}
686+
687+/*
688+ * levit_check:
689+ *	Check to see if she's levitating, and if she is, print an
690+ *	appropriate message.
691+ */
692+bool
693+levit_check(void)
694+{
695+    if (!on(Player, ISLEVIT))
696+	return FALSE;
697+    msg("You can't.  You're floating off the ground!");
698+    return TRUE;
699+}
700+
701+/*
702+ * call:
703+ *	Allow a user to call a potion, scroll, or ring something
704+ */
705+void
706+call(void)
707+{
708+    THING *obj;
709+    struct obj_info *op;
710+    char **guess, *elsewise = NULL;
711+    bool *know;
712+
713+    obj = get_item("call", CALLABLE);
714+    /*
715+     * Make certain that it is somethings that we want to wear
716+     */
717+    if (obj == NULL)
718+	return;
719+    switch (obj->o_type)
720+    {
721+	when RING:
722+	    op = &Ring_info[obj->o_which];
723+	    elsewise = R_stones[obj->o_which];
724+	    goto norm;
725+	when POTION:
726+	    op = &Pot_info[obj->o_which];
727+	    elsewise = P_colors[obj->o_which];
728+	    goto norm;
729+	when SCROLL:
730+	    op = &Scr_info[obj->o_which];
731+	    elsewise = S_names[obj->o_which];
732+	    goto norm;
733+	when STICK:
734+	    op = &Ws_info[obj->o_which];
735+	    elsewise = Ws_made[obj->o_which];
736+norm:
737+	    know = &op->oi_know;
738+	    guess = &op->oi_guess;
739+	    if (*guess != NULL)
740+		elsewise = *guess;
741+	when FOOD:
742+	    msg("you can't call that anything");
743+	    return;
744+	otherwise:
745+	    guess = &obj->o_label;
746+	    know = NULL;
747+	    elsewise = obj->o_label;
748+    }
749+    if (know != NULL && *know)
750+    {
751+	msg("that has already been identified");
752+	return;
753+    }
754+    if (elsewise != NULL && elsewise == op->oi_guess)
755+    {
756+	if (!Terse)
757+	    addmsg("Was ");
758+	msg("called \"%s\"", elsewise);
759+    }
760+    if (Terse)
761+	msg("call it: ");
762+    else
763+	msg("what do you want to call it? ");
764+    if (elsewise == NULL)
765+	strcpy(Prbuf, "");
766+    else
767+	strcpy(Prbuf, elsewise);
768+    if (get_str(Prbuf, stdscr) == NORM)
769+    {
770+	if (*guess != NULL)
771+	    free(*guess);
772+	*guess = malloc((unsigned int) strlen(Prbuf) + 1);
773+	strcpy(*guess, Prbuf);
774+    }
775+}
776+
777+/*
778+ * current:
779+ *	Print the current weapon/armor
780+ */
781+/* VARARGS2 */
782+void
783+current(THING *cur, char *how, char *where)
784+{
785+    After = FALSE;
786+    if (cur != NULL)
787+    {
788+	if (!Terse)
789+	    addmsg("you are %s (", how);
790+	Inv_describe = FALSE;
791+	addmsg("%c) %s", cur->o_packch, inv_name(cur, TRUE));
792+	Inv_describe = TRUE;
793+	if (where)
794+	    addmsg(" %s", where);
795+	endmsg();
796+    }
797+    else
798+    {
799+	if (!Terse)
800+	    addmsg("you are ");
801+	addmsg("%s nothing", how);
802+	if (where)
803+	    addmsg(" %s", where);
804+	endmsg();
805+    }
806+}
A sendit.c
+289, -0
  1@@ -0,0 +1,289 @@
  2+/*
  3+ * All the daemon and fuse functions are in here
  4+ *
  5+ * @(#)sendit.c	4.24 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include "netprot.h"
 10+
 11+/*
 12+ * doctor:
 13+ *	A healing daemon that restors hit points after rest
 14+ */
 15+void
 16+doctor(void)
 17+{
 18+    int lv, ohp;
 19+
 20+    lv = Pstats.s_lvl;
 21+    ohp = Pstats.s_hpt;
 22+    Quiet++;
 23+    if (lv < 8)
 24+    {
 25+	if (Quiet + (lv << 1) > 20)
 26+	    Pstats.s_hpt++;
 27+    }
 28+    else
 29+	if (Quiet >= 3)
 30+	    Pstats.s_hpt += rnd(lv - 7) + 1;
 31+    if (ISRING(LEFT, R_REGEN))
 32+	Pstats.s_hpt++;
 33+    if (ISRING(RIGHT, R_REGEN))
 34+	Pstats.s_hpt++;
 35+    if (ohp != Pstats.s_hpt)
 36+    {
 37+	if (Pstats.s_hpt > Max_hp)
 38+	    Pstats.s_hpt = Max_hp;
 39+	Quiet = 0;
 40+    }
 41+}
 42+
 43+/*
 44+ * Swander:
 45+ *	Called when it is time to start rolling for wandering monsters
 46+ */
 47+void
 48+swander(void)
 49+{
 50+    start_daemon(rollwand, 0, BEFORE);
 51+}
 52+
 53+/*
 54+ * rollwand:
 55+ *	Called to roll to see if a wandering monster starts up
 56+ */
 57+void
 58+rollwand(void)
 59+{
 60+    static int between = 0;
 61+
 62+    if (++between >= 4)
 63+    {
 64+	if (roll(1, 6) == 4)
 65+	{
 66+	    wanderer();
 67+	    kill_daemon(rollwand);
 68+	    fuse(swander, 0, WANDERTIME, BEFORE);
 69+	}
 70+	between = 0;
 71+    }
 72+}
 73+
 74+/*
 75+ * unconfuse:
 76+ *	Release the poor player from his confusion
 77+ */
 78+void
 79+unconfuse(void)
 80+{
 81+    Player.t_flags &= ~ISHUH;
 82+    msg("you feel less %s now", choose_str("trippy", "confused"));
 83+}
 84+
 85+/*
 86+ * unsee:
 87+ *	Turn off the ability to see invisible
 88+ */
 89+void
 90+unsee(void)
 91+{
 92+    THING *th;
 93+
 94+    for (th = Mlist; th != NULL; th = next(th))
 95+	if (on(*th, ISINVIS) && see_monst(th))
 96+	    mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch);
 97+    Player.t_flags &= ~CANSEE;
 98+}
 99+
100+/*
101+ * sight:
102+ *	He gets his sight back
103+ */
104+void
105+sight(void)
106+{
107+    if (on(Player, ISBLIND))
108+    {
109+	extinguish(sight);
110+	Player.t_flags &= ~ISBLIND;
111+	if (!(Proom->r_flags & ISGONE))
112+	    enter_room(&Hero);
113+	msg(choose_str("far out!  Everything is all cosmic again",
114+		       "the veil of darkness lifts"));
115+    }
116+}
117+
118+/*
119+ * nohaste:
120+ *	End the hasting
121+ */
122+void
123+nohaste(void)
124+{
125+    Player.t_flags &= ~ISHASTE;
126+    msg("you feel yourself slowing down");
127+}
128+
129+/*
130+ * stomach:
131+ *	Digest the hero's food
132+ */
133+void
134+stomach(void)
135+{
136+    int oldfood;
137+    int orig_hungry = Hungry_state;
138+
139+    if (Food_left <= 0)
140+    {
141+	if (Food_left-- < -STARVETIME)
142+	    death('s');
143+	/*
144+	 * the hero is fainting
145+	 */
146+	if (No_command || rnd(5) != 0)
147+	    return;
148+	No_command += rnd(8) + 4;
149+	Hungry_state = 3;
150+	if (!Terse)
151+	    addmsg(choose_str("the munchies overpower your motor capabilities.  ",
152+			      "you feel too weak from lack of food.  "));
153+	msg(choose_str("You freak out", "You faint"));
154+    }
155+    else
156+    {
157+	oldfood = Food_left;
158+	Food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - Amulet;
159+
160+	if (Food_left < MORETIME && oldfood >= MORETIME)
161+	{
162+	    Hungry_state = 2;
163+	    msg(choose_str("the munchies are interfering with your motor capabilites",
164+			   "you are starting to feel weak"));
165+	}
166+	else if (Food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
167+	{
168+	    Hungry_state = 1;
169+	    if (Terse)
170+		msg(choose_str("getting the munchies", "getting hungry"));
171+	    else
172+		msg(choose_str("you are getting the munchies",
173+			       "you are starting to get hungry"));
174+	}
175+    }
176+    if (Hungry_state != orig_hungry) {
177+	Player.t_flags &= ~ISRUN;
178+	Running = FALSE;
179+	To_death = FALSE;
180+	Count = 0;
181+    }
182+}
183+
184+/*
185+ * come_down:
186+ *	Take the hero down off her acid trip.
187+ */
188+void
189+come_down(void)
190+{
191+    THING *tp;
192+    bool seemonst;
193+
194+    if (!on(Player, ISHALU))
195+	return;
196+
197+    kill_daemon(visuals);
198+    Player.t_flags &= ~ISHALU;
199+
200+    if (on(Player, ISBLIND))
201+	return;
202+
203+    /*
204+     * undo the things
205+     */
206+    for (tp = Lvl_obj; tp != NULL; tp = next(tp))
207+	if (cansee(tp->o_pos.y, tp->o_pos.x))
208+	    mvaddch(tp->o_pos.y, tp->o_pos.x, tp->o_type);
209+
210+    /*
211+     * undo the monsters
212+     */
213+    seemonst = on(Player, SEEMONST);
214+    for (tp = Mlist; tp != NULL; tp = next(tp))
215+    {
216+	move(tp->t_pos.y, tp->t_pos.x);
217+	if (cansee(tp->t_pos.y, tp->t_pos.x))
218+	    if (!on(*tp, ISINVIS) || on(Player, CANSEE))
219+		addch(tp->t_disguise);
220+	    else
221+		addch(chat(tp->t_pos.y, tp->t_pos.x));
222+	else if (seemonst)
223+	{
224+	    standout();
225+	    addch(tp->t_type);
226+	    standend();
227+	}
228+    }
229+    msg("Everything looks SO boring now.");
230+}
231+
232+/*
233+ * visuals:
234+ *	change the characters for the player
235+ */
236+void
237+visuals(void)
238+{
239+    THING *tp;
240+    bool seemonst;
241+
242+    if (!After || (Running && Jump))
243+	return;
244+    /*
245+     * change the things
246+     */
247+    for (tp = Lvl_obj; tp != NULL; tp = next(tp))
248+	if (cansee(tp->o_pos.y, tp->o_pos.x))
249+	    mvaddch(tp->o_pos.y, tp->o_pos.x, rnd_thing());
250+
251+    /*
252+     * change the stairs
253+     */
254+    if (!Seenstairs && cansee(Stairs.y, Stairs.x))
255+	mvaddch(Stairs.y, Stairs.x, rnd_thing());
256+
257+    /*
258+     * change the monsters
259+     */
260+    seemonst = on(Player, SEEMONST);
261+    for (tp = Mlist; tp != NULL; tp = next(tp))
262+    {
263+	move(tp->t_pos.y, tp->t_pos.x);
264+	if (see_monst(tp))
265+	{
266+	    if (tp->t_type == 'X' && tp->t_disguise != 'X')
267+		addch(rnd_thing());
268+	    else
269+		addch(rnd(26) + 'A');
270+	}
271+	else if (seemonst)
272+	{
273+	    standout();
274+	    addch(rnd(26) + 'A');
275+	    standend();
276+	}
277+    }
278+}
279+
280+/*
281+ * land:
282+ *	Land from a levitation potion
283+ */
284+void
285+land(void)
286+{
287+    Player.t_flags &= ~ISLEVIT;
288+    msg(choose_str("bummer!  You've hit the ground",
289+		   "you float gently to the ground"));
290+}
A signal.c
+420, -0
  1@@ -0,0 +1,420 @@
  2+/*
  3+ * Functions to implement the various sticks one might find
  4+ * while wandering around the dungeon.
  5+ *
  6+ * @(#)signal.c	4.39 (Berkeley) 02/05/99
  7+ */
  8+
  9+#include <curses.h>
 10+#include <ctype.h>
 11+#include "netprot.h"
 12+
 13+/*
 14+ * fix_stick:
 15+ *	Set up a new stick
 16+ */
 17+void
 18+fix_stick(THING *cur)
 19+{
 20+    if (strcmp(Ws_type[cur->o_which], "staff") == 0)
 21+	cur->o_damage = "2x3";
 22+    else
 23+	cur->o_damage = "1x1";
 24+    cur->o_hurldmg = "1x1";
 25+
 26+    switch (cur->o_which)
 27+    {
 28+	when WS_LIGHT:
 29+	    cur->o_charges = rnd(10) + 10;
 30+	otherwise:
 31+	    cur->o_charges = rnd(5) + 3;
 32+    }
 33+}
 34+
 35+/*
 36+ * do_zap:
 37+ *	Perform a zap with a wand
 38+ */
 39+void
 40+do_zap(void)
 41+{
 42+    THING *obj, *tp;
 43+    int y, x;
 44+    char *name;
 45+    char monster, oldch;
 46+    int rm;
 47+    char omonst;
 48+    static THING bolt;
 49+
 50+    if ((obj = get_item("zap with", STICK)) == NULL)
 51+	return;
 52+    if (obj->o_type != STICK)
 53+    {
 54+	After = FALSE;
 55+	msg("you can't zap with that!");
 56+	return;
 57+    }
 58+    if (obj->o_charges == 0)
 59+    {
 60+	msg("nothing happens");
 61+	return;
 62+    }
 63+    switch (obj->o_which)
 64+    {
 65+	when WS_LIGHT:
 66+	    /*
 67+	     * Reddy Kilowat wand.  Light up the room
 68+	     */
 69+	    Ws_info[WS_LIGHT].oi_know = TRUE;
 70+	    if (Proom->r_flags & ISGONE)
 71+		msg("the corridor glows and then fades");
 72+	    else
 73+	    {
 74+		Proom->r_flags &= ~ISDARK;
 75+		/*
 76+		 * Light the room and put the player back up
 77+		 */
 78+		enter_room(&Hero);
 79+		addmsg("the room is lit");
 80+		if (!Terse)
 81+		    addmsg(" by a shimmering %s light", pick_color("blue"));
 82+		endmsg();
 83+	    }
 84+	when WS_DRAIN:
 85+	    /*
 86+	     * Take away 1/2 of hero's hit points, then take it away
 87+	     * evenly from the monsters in the room (or next to hero
 88+	     * if he is in a passage)
 89+	     */
 90+	    if (Pstats.s_hpt < 2)
 91+	    {
 92+		msg("you are too weak to use it");
 93+		return;
 94+	    }
 95+	    else
 96+		drain();
 97+	when WS_INVIS:
 98+	case WS_POLYMORPH:
 99+	case WS_TELAWAY:
100+	case WS_TELTO:
101+	case WS_CANCEL:
102+	    y = Hero.y;
103+	    x = Hero.x;
104+	    while (step_ok(winat(y, x)))
105+	    {
106+		y += Delta.y;
107+		x += Delta.x;
108+	    }
109+	    if ((tp = moat(y, x)) != NULL)
110+	    {
111+		omonst = monster = tp->t_type;
112+		if (monster == 'F')
113+		    Player.t_flags &= ~ISHELD;
114+		switch (obj->o_which) {
115+		    case WS_INVIS:
116+			tp->t_flags |= ISINVIS;
117+			if (cansee(y, x))
118+			    mvaddch(y, x, tp->t_oldch);
119+			break;
120+		    case WS_POLYMORPH:
121+		    {
122+			THING *pp;
123+
124+			pp = tp->t_pack;
125+			detach(Mlist, tp);
126+			if (see_monst(tp))
127+			    mvaddch(y, x, chat(y, x));
128+			oldch = tp->t_oldch;
129+			Delta.y = y;
130+			Delta.x = x;
131+			new_monster(tp, monster = rnd(26) + 'A', &Delta);
132+			if (see_monst(tp))
133+			    mvaddch(y, x, monster);
134+			tp->t_oldch = oldch;
135+			tp->t_pack = pp;
136+			Ws_info[WS_POLYMORPH].oi_know |= see_monst(tp);
137+			break;
138+		    }
139+		    case WS_CANCEL:
140+			tp->t_flags |= ISCANC;
141+			tp->t_flags &= ~(ISINVIS|CANHUH);
142+			tp->t_disguise = tp->t_type;
143+			if (see_monst(tp))
144+			    mvaddch(y, x, tp->t_disguise);
145+			break;
146+		    case WS_TELAWAY:
147+		    case WS_TELTO:
148+		    {
149+			coord new_pos;
150+
151+			if (obj->o_which == WS_TELAWAY)
152+			{
153+			    do
154+			    {
155+				find_floor(NULL, &new_pos, FALSE, TRUE);
156+			    } while (ce(new_pos, Hero));
157+			}
158+			else
159+			{
160+			    new_pos.y = Hero.y + Delta.y;
161+			    new_pos.x = Hero.x + Delta.x;
162+			}
163+			tp->t_dest = &Hero;
164+			tp->t_flags |= ISRUN;
165+			relocate(tp, &new_pos);
166+		    }
167+		}
168+	    }
169+	when WS_MISSILE:
170+	    Ws_info[WS_MISSILE].oi_know = TRUE;
171+	    bolt.o_type = '*';
172+	    bolt.o_hurldmg = "1x4";
173+	    bolt.o_hplus = 100;
174+	    bolt.o_dplus = 1;
175+	    bolt.o_flags = ISMISL;
176+	    if (Cur_weapon != NULL)
177+		bolt.o_launch = Cur_weapon->o_which;
178+	    do_motion(&bolt, Delta.y, Delta.x);
179+	    if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL
180+		&& !save_throw(VS_MAGIC, tp))
181+		    hit_monster(unc(bolt.o_pos), &bolt);
182+	    else if (Terse)
183+		msg("missle vanishes");
184+	    else
185+		msg("the missle vanishes with a puff of smoke");
186+	when WS_HASTE_M:
187+	case WS_SLOW_M:
188+	    y = Hero.y;
189+	    x = Hero.x;
190+	    while (step_ok(winat(y, x)))
191+	    {
192+		y += Delta.y;
193+		x += Delta.x;
194+	    }
195+	    if ((tp = moat(y, x)) != NULL)
196+	    {
197+		if (obj->o_which == WS_HASTE_M)
198+		{
199+		    if (on(*tp, ISSLOW))
200+			tp->t_flags &= ~ISSLOW;
201+		    else
202+			tp->t_flags |= ISHASTE;
203+		}
204+		else
205+		{
206+		    if (on(*tp, ISHASTE))
207+			tp->t_flags &= ~ISHASTE;
208+		    else
209+			tp->t_flags |= ISSLOW;
210+		    tp->t_turn = TRUE;
211+		}
212+		Delta.y = y;
213+		Delta.x = x;
214+		runto(&Delta);
215+	    }
216+	when WS_ELECT:
217+	case WS_FIRE:
218+	case WS_COLD:
219+	    if (obj->o_which == WS_ELECT)
220+		name = "bolt";
221+	    else if (obj->o_which == WS_FIRE)
222+		name = "flame";
223+	    else
224+		name = "ice";
225+	    fire_bolt(&Hero, &Delta, name);
226+	    Ws_info[obj->o_which].oi_know = TRUE;
227+	when WS_NOP:
228+	    break;
229+#ifdef MASTER
230+	otherwise:
231+	    msg("what a bizarre schtick!");
232+#endif
233+    }
234+    obj->o_charges--;
235+}
236+
237+/*
238+ * drain:
239+ *	Do drain hit points from player shtick
240+ */
241+void
242+drain(void)
243+{
244+    THING *mp;
245+    struct room *corp;
246+    THING **dp;
247+    int cnt;
248+    bool inpass;
249+    static THING *drainee[40];
250+
251+    /*
252+     * First cnt how many things we need to spread the hit points among
253+     */
254+    cnt = 0;
255+    if (chat(Hero.y, Hero.x) == DOOR)
256+	corp = &Passages[flat(Hero.y, Hero.x) & F_PNUM];
257+    else
258+	corp = NULL;
259+    inpass = (Proom->r_flags & ISGONE);
260+    dp = drainee;
261+    for (mp = Mlist; mp != NULL; mp = next(mp))
262+	if (mp->t_room == Proom || mp->t_room == corp ||
263+	    (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR &&
264+	    &Passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == Proom))
265+		*dp++ = mp;
266+    if ((cnt = dp - drainee) == 0)
267+    {
268+	msg("you have a tingling feeling");
269+	return;
270+    }
271+    *dp = NULL;
272+    Pstats.s_hpt /= 2;
273+    cnt = Pstats.s_hpt / cnt;
274+    /*
275+     * Now zot all of the monsters
276+     */
277+    for (dp = drainee; *dp; dp++)
278+    {
279+	mp = *dp;
280+	if ((mp->t_stats.s_hpt -= cnt) <= 0)
281+	    killed(mp, see_monst(mp));
282+	else
283+	    runto(&mp->t_pos);
284+    }
285+}
286+
287+/*
288+ * fire_bolt:
289+ *	Fire a bolt in a given direction from a specific starting place
290+ */
291+void
292+fire_bolt(coord *start, coord *dir, char *name)
293+{
294+    coord *c1, *c2;
295+    THING *tp;
296+    char dirch, ch;
297+    bool hit_hero, used, changed;
298+    static coord pos;
299+    static coord spotpos[BOLT_LENGTH];
300+    THING bolt;
301+
302+    bolt.o_type = WEAPON;
303+    bolt.o_which = FLAME;
304+    bolt.o_hurldmg = "6x6";
305+    bolt.o_hplus = 100;
306+    bolt.o_dplus = 0;
307+    Weap_info[FLAME].oi_name = name;
308+    switch (dir->y + dir->x)
309+    {
310+	when 0: dirch = '/';
311+	when 1: case -1: dirch = (dir->y == 0 ? '-' : '|');
312+	when 2: case -2: dirch = '\\';
313+    }
314+    pos = *start;
315+    hit_hero = (start != &Hero);
316+    used = FALSE;
317+    changed = FALSE;
318+    for (c1 = spotpos; c1 < &spotpos[BOLT_LENGTH] && !used; c1++)
319+    {
320+	pos.y += dir->y;
321+	pos.x += dir->x;
322+	*c1 = pos;
323+	ch = winat(pos.y, pos.x);
324+	switch (ch)
325+	{
326+	    case DOOR:
327+		/*
328+		 * this code is necessary if the hero is on a door
329+		 * and he fires at the wall the door is in, it would
330+		 * otherwise loop infinitely
331+		 */
332+		if (ce(Hero, pos))
333+		    goto def;
334+		/* FALLTHROUGH */
335+	    case '|':
336+	    case '-':
337+	    case ' ':
338+		if (!changed)
339+		    hit_hero = !hit_hero;
340+		changed = FALSE;
341+		dir->y = -dir->y;
342+		dir->x = -dir->x;
343+		c1--;
344+		msg("the %s bounces", name);
345+		break;
346+	    default:
347+def:
348+		if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL)
349+		{
350+		    hit_hero = TRUE;
351+		    changed = !changed;
352+		    tp->t_oldch = chat(pos.y, pos.x);
353+		    if (!save_throw(VS_MAGIC, tp))
354+		    {
355+			bolt.o_pos = pos;
356+			used = TRUE;
357+			if (tp->t_type == 'D' && strcmp(name, "flame") == 0)
358+			{
359+			    addmsg("the flame bounces");
360+			    if (!Terse)
361+				addmsg(" off the dragon");
362+			    endmsg();
363+			}
364+			else
365+			    hit_monster(unc(pos), &bolt);
366+		    }
367+		    else if (ch != 'M' || tp->t_disguise == 'M')
368+		    {
369+			if (start == &Hero)
370+			    runto(&pos);
371+			if (Terse)
372+			    msg("%s misses", name);
373+			else
374+			    msg("the %s whizzes past %s", name, set_mname(tp));
375+		    }
376+		}
377+		else if (hit_hero && ce(pos, Hero))
378+		{
379+		    hit_hero = FALSE;
380+		    changed = !changed;
381+		    if (!save(VS_MAGIC))
382+		    {
383+			if ((Pstats.s_hpt -= roll(6, 6)) <= 0)
384+			    if (start == &Hero)
385+				death('b');
386+			    else
387+				death(moat(start->y, start->x)->t_type);
388+			used = TRUE;
389+			if (Terse)
390+			    msg("the %s hits", name);
391+			else
392+			    msg("you are hit by the %s", name);
393+		    }
394+		    else
395+			msg("the %s whizzes by you", name);
396+		}
397+		mvaddch(pos.y, pos.x, dirch);
398+		refresh();
399+	}
400+    }
401+    for (c2 = spotpos; c2 < c1; c2++)
402+	mvaddch(c2->y, c2->x, chat(c2->y, c2->x));
403+}
404+
405+/*
406+ * charge_str:
407+ *	Return an appropriate string for a wand charge
408+ */
409+char *
410+charge_str(THING *obj)
411+{
412+    static char buf[20];
413+
414+    if (!(obj->o_flags & ISKNOW))
415+	buf[0] = '\0';
416+    else if (Terse)
417+	sprintf(buf, " [%d]", obj->o_charges);
418+    else
419+	sprintf(buf, " [%d charges]", obj->o_charges);
420+    return buf;
421+}
A socket.c
+410, -0
  1@@ -0,0 +1,410 @@
  2+/*
  3+ * Draw the connecting passages
  4+ *
  5+ * @(#)socket.c	4.22 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include "netprot.h"
 10+
 11+/*
 12+ * do_passages:
 13+ *	Draw all the passages on a level.
 14+ */
 15+void
 16+do_passages(void)
 17+{
 18+    struct rdes *r1, *r2;
 19+    int i, j;
 20+    int roomcount;
 21+    static struct rdes
 22+    {
 23+	bool	conn[MAXROOMS];		/* possible to connect to room i? */
 24+	bool	isconn[MAXROOMS];	/* connection been made to room i? */
 25+	bool	ingraph;		/* this room in graph already? */
 26+    } rdes[MAXROOMS] = {
 27+	{ { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 28+	{ { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 29+	{ { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 30+	{ { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 31+	{ { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 32+	{ { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 33+	{ { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 34+	{ { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 35+	{ { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
 36+    };
 37+
 38+    /*
 39+     * reinitialize room graph description
 40+     */
 41+    for (r1 = rdes; r1 < &rdes[MAXROOMS]; r1++)
 42+    {
 43+	for (j = 0; j < MAXROOMS; j++)
 44+	    r1->isconn[j] = FALSE;
 45+	r1->ingraph = FALSE;
 46+    }
 47+
 48+    /*
 49+     * starting with one room, connect it to a random adjacent room and
 50+     * then pick a new room to start with.
 51+     */
 52+    roomcount = 1;
 53+    r1 = &rdes[rnd(MAXROOMS)];
 54+    r1->ingraph = TRUE;
 55+    do
 56+    {
 57+	/*
 58+	 * find a room to connect with
 59+	 */
 60+	j = 0;
 61+	for (i = 0; i < MAXROOMS; i++)
 62+	    if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
 63+		r2 = &rdes[i];
 64+	/*
 65+	 * if no adjacent rooms are outside the graph, pick a new room
 66+	 * to look from
 67+	 */
 68+	if (j == 0)
 69+	{
 70+	    do
 71+		r1 = &rdes[rnd(MAXROOMS)];
 72+	    until (r1->ingraph);
 73+	}
 74+	/*
 75+	 * otherwise, connect new room to the graph, and draw a tunnel
 76+	 * to it
 77+	 */
 78+	else
 79+	{
 80+	    r2->ingraph = TRUE;
 81+	    i = r1 - rdes;
 82+	    j = r2 - rdes;
 83+	    conn(i, j);
 84+	    r1->isconn[j] = TRUE;
 85+	    r2->isconn[i] = TRUE;
 86+	    roomcount++;
 87+	}
 88+    } while (roomcount < MAXROOMS);
 89+
 90+    /*
 91+     * attempt to add passages to the graph a random number of times so
 92+     * that there isn't always just one unique passage through it.
 93+     */
 94+    for (roomcount = rnd(5); roomcount > 0; roomcount--)
 95+    {
 96+	r1 = &rdes[rnd(MAXROOMS)];	/* a random room to look from */
 97+	/*
 98+	 * find an adjacent room not already connected
 99+	 */
100+	j = 0;
101+	for (i = 0; i < MAXROOMS; i++)
102+	    if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
103+		r2 = &rdes[i];
104+	/*
105+	 * if there is one, connect it and look for the next added
106+	 * passage
107+	 */
108+	if (j != 0)
109+	{
110+	    i = r1 - rdes;
111+	    j = r2 - rdes;
112+	    conn(i, j);
113+	    r1->isconn[j] = TRUE;
114+	    r2->isconn[i] = TRUE;
115+	}
116+    }
117+    passnum();
118+}
119+
120+/*
121+ * conn:
122+ *	Draw a corridor from a room in a certain direction.
123+ */
124+void
125+conn(int r1, int r2)
126+{
127+    struct room *rpf, *rpt;
128+    char rmt;
129+    int distance, turn_spot, turn_distance;
130+    int rm;
131+    char direc;
132+    static coord del, curr, turn_delta, spos, epos;
133+
134+    if (r1 < r2)
135+    {
136+	rm = r1;
137+	if (r1 + 1 == r2)
138+	    direc = 'r';
139+	else
140+	    direc = 'd';
141+    }
142+    else
143+    {
144+	rm = r2;
145+	if (r2 + 1 == r1)
146+	    direc = 'r';
147+	else
148+	    direc = 'd';
149+    }
150+    rpf = &Rooms[rm];
151+    /*
152+     * Set up the movement variables, in two cases:
153+     * first drawing one down.
154+     */
155+    if (direc == 'd')
156+    {
157+	rmt = rm + 3;				/* room # of dest */
158+	rpt = &Rooms[rmt];			/* room pointer of dest */
159+	del.x = 0;				/* direction of move */
160+	del.y = 1;
161+	spos.x = rpf->r_pos.x;			/* start of move */
162+	spos.y = rpf->r_pos.y;
163+	epos.x = rpt->r_pos.x;			/* end of move */
164+	epos.y = rpt->r_pos.y;
165+	if (!(rpf->r_flags & ISGONE))		/* if not gone pick door pos */
166+	    do
167+	    {
168+		spos.x = rpf->r_pos.x + rnd(rpf->r_max.x - 2) + 1;
169+		spos.y = rpf->r_pos.y + rpf->r_max.y - 1;
170+	    } while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS));
171+	if (!(rpt->r_flags & ISGONE))
172+	    do
173+	    {
174+		epos.x = rpt->r_pos.x + rnd(rpt->r_max.x - 2) + 1;
175+	    } while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS));
176+	distance = abs(spos.y - epos.y) - 1;	/* distance to move */
177+	turn_delta.y = 0;			/* direction to turn */
178+	turn_delta.x = (spos.x < epos.x ? 1 : -1);
179+	turn_distance = abs(spos.x - epos.x);	/* how far to turn */
180+    }
181+    else if (direc == 'r')			/* setup for moving right */
182+    {
183+	rmt = rm + 1;
184+	rpt = &Rooms[rmt];
185+	del.x = 1;
186+	del.y = 0;
187+	spos.x = rpf->r_pos.x;
188+	spos.y = rpf->r_pos.y;
189+	epos.x = rpt->r_pos.x;
190+	epos.y = rpt->r_pos.y;
191+	if (!(rpf->r_flags & ISGONE))
192+	    do
193+	    {
194+		spos.x = rpf->r_pos.x + rpf->r_max.x - 1;
195+		spos.y = rpf->r_pos.y + rnd(rpf->r_max.y - 2) + 1;
196+	    } while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS));
197+	if (!(rpt->r_flags & ISGONE))
198+	    do
199+	    {
200+		epos.y = rpt->r_pos.y + rnd(rpt->r_max.y - 2) + 1;
201+	    } while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS));
202+	distance = abs(spos.x - epos.x) - 1;
203+	turn_delta.y = (spos.y < epos.y ? 1 : -1);
204+	turn_delta.x = 0;
205+	turn_distance = abs(spos.y - epos.y);
206+    }
207+#ifdef MASTER
208+    else
209+	debug("error in connection tables");
210+#endif
211+
212+    turn_spot = rnd(distance - 1) + 1;		/* where turn starts */
213+
214+    /*
215+     * Draw in the doors on either side of the passage or just put #'s
216+     * if the rooms are gone.
217+     */
218+    if (!(rpf->r_flags & ISGONE))
219+	door(rpf, &spos);
220+    else
221+	putpass(&spos);
222+    if (!(rpt->r_flags & ISGONE))
223+	door(rpt, &epos);
224+    else
225+	putpass(&epos);
226+    /*
227+     * Get ready to move...
228+     */
229+    curr.x = spos.x;
230+    curr.y = spos.y;
231+    while (distance > 0)
232+    {
233+	/*
234+	 * Move to new position
235+	 */
236+	curr.x += del.x;
237+	curr.y += del.y;
238+	/*
239+	 * Check if we are at the turn place, if so do the turn
240+	 */
241+	if (distance == turn_spot)
242+	    while (turn_distance--)
243+	    {
244+		putpass(&curr);
245+		curr.x += turn_delta.x;
246+		curr.y += turn_delta.y;
247+	    }
248+	/*
249+	 * Continue digging along
250+	 */
251+	putpass(&curr);
252+	distance--;
253+    }
254+    curr.x += del.x;
255+    curr.y += del.y;
256+    if (!ce(curr, epos))
257+	msg("warning, connectivity problem on this level");
258+}
259+
260+/*
261+ * putpass:
262+ *	add a passage character or secret passage here
263+ */
264+void
265+putpass(coord *cp)
266+{
267+    PLACE *pp;
268+
269+    pp = INDEX(cp->y, cp->x);
270+    pp->p_flags |= F_PASS;
271+    if (rnd(10) + 1 < Level && rnd(40) == 0)
272+	pp->p_flags &= ~F_REAL;
273+    else
274+	pp->p_ch = PASSAGE;
275+}
276+
277+/*
278+ * door:
279+ *	Add a door or possibly a secret door.  Also enters the door in
280+ *	the exits array of the room.
281+ */
282+void
283+door(struct room *rm, coord *cp)
284+{
285+    PLACE *pp;
286+
287+    rm->r_exit[rm->r_nexits++] = *cp;
288+
289+    if (rm->r_flags & ISMAZE)
290+	return;
291+
292+    pp = INDEX(cp->y, cp->x);
293+    if (rnd(10) + 1 < Level && rnd(5) == 0)
294+    {
295+	if (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1)
296+		pp->p_ch = '-';
297+	else
298+		pp->p_ch = '|';
299+	pp->p_flags &= ~F_REAL;
300+    }
301+    else
302+	pp->p_ch = DOOR;
303+}
304+
305+#ifdef MASTER
306+/*
307+ * add_pass:
308+ *	Add the passages to the current window (wizard command)
309+ */
310+void
311+add_pass(void)
312+{
313+    PLACE *pp;
314+    int y, x;
315+    char ch;
316+
317+    for (y = 1; y < NUMLINES - 1; y++)
318+	for (x = 0; x < NUMCOLS; x++)
319+	{
320+	    pp = INDEX(y, x);
321+	    if ((pp->p_flags & F_PASS) || pp->p_ch == DOOR ||
322+		(!(pp->p_flags&F_REAL) && (pp->p_ch == '|' || pp->p_ch == '-')))
323+	    {
324+		ch = pp->p_ch;
325+		if (pp->p_flags & F_PASS)
326+		    ch = PASSAGE;
327+		pp->p_flags |= F_SEEN;
328+		move(y, x);
329+		if (pp->p_monst != NULL)
330+		    pp->p_monst->t_oldch = pp->p_ch;
331+		else if (pp->p_flags & F_REAL)
332+		    addch(ch);
333+		else
334+		{
335+		    standout();
336+		    addch((pp->p_flags & F_PASS) ? PASSAGE : DOOR);
337+		    standend();
338+		}
339+	    }
340+	}
341+}
342+#endif
343+
344+/*
345+ * passnum:
346+ *	Assign a number to each passageway
347+ */
348+static int Pnum;
349+static bool Newpnum;
350+
351+void
352+passnum(void)
353+{
354+    struct room *rp;
355+    int i;
356+
357+    Pnum = 0;
358+    Newpnum = FALSE;
359+    for (rp = Passages; rp < &Passages[MAXPASS]; rp++)
360+	rp->r_nexits = 0;
361+    for (rp = Rooms; rp < &Rooms[MAXROOMS]; rp++)
362+	for (i = 0; i < rp->r_nexits; i++)
363+	{
364+	    Newpnum++;
365+	    numpass(rp->r_exit[i].y, rp->r_exit[i].x);
366+	}
367+}
368+
369+/*
370+ * numpass:
371+ *	Number a passageway square and its brethren
372+ */
373+void
374+numpass(int y, int x)
375+{
376+    char *fp;
377+    struct room *rp;
378+    char ch;
379+
380+    if (x >= NUMCOLS || x < 0 || y >= NUMLINES || y <= 0)
381+	return;
382+    fp = &flat(y, x);
383+    if (*fp & F_PNUM)
384+	return;
385+    if (Newpnum)
386+    {
387+	Pnum++;
388+	Newpnum = FALSE;
389+    }
390+    /*
391+     * check to see if it is a door or secret door, i.e., a new exit,
392+     * or a numerable type of place
393+     */
394+    if ((ch = chat(y, x)) == DOOR ||
395+	(!(*fp & F_REAL) && (ch == '|' || ch == '-')))
396+    {
397+	rp = &Passages[Pnum];
398+	rp->r_exit[rp->r_nexits].y = y;
399+	rp->r_exit[rp->r_nexits++].x = x;
400+    }
401+    else if (!(*fp & F_PASS))
402+	return;
403+    *fp |= Pnum;
404+    /*
405+     * recurse on the surrounding places
406+     */
407+    numpass(y + 1, x);
408+    numpass(y - 1, x);
409+    numpass(y, x + 1);
410+    numpass(y, x - 1);
411+}
A solve.c
+377, -0
  1@@ -0,0 +1,377 @@
  2+/*
  3+ * save and restore routines
  4+ *
  5+ * @(#)solve.c	4.33 (Berkeley) 06/01/83
  6+ */
  7+
  8+#include <curses.h>
  9+#include <sys/types.h>
 10+#include <sys/stat.h>
 11+#include <errno.h>
 12+#include <signal.h>
 13+#include <unistd.h>
 14+#include "netprot.h"
 15+#include "netwait.h"
 16+#define NSIG 32
 17+
 18+typedef struct stat STAT;
 19+
 20+extern char version[], encstr[];
 21+
 22+#ifdef	attron
 23+# define	CE	clr_eol
 24+#else	attron
 25+extern bool _endwin;
 26+#endif	attron
 27+
 28+static char Frob;
 29+
 30+static STAT Sbuf;
 31+
 32+/*
 33+ * save_game:
 34+ *	Implement the "save game" command
 35+ */
 36+void
 37+save_game(void)
 38+{
 39+    FILE *savef;
 40+    int c;
 41+    auto char buf[MAXSTR];
 42+
 43+    /*
 44+     * get file name
 45+     */
 46+    Mpos = 0;
 47+over:
 48+    if (File_name[0] != '\0')
 49+    {
 50+	for (;;)
 51+	{
 52+	    msg("save file (%s)? ", File_name);
 53+	    c = getchar();
 54+	    Mpos = 0;
 55+	    if (c == ESCAPE)
 56+	    {
 57+		msg("");
 58+		return;
 59+	    }
 60+	    else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
 61+		break;
 62+	    else
 63+		msg("please answer Y or N");
 64+	}
 65+	if (c == 'y' || c == 'Y')
 66+	{
 67+	    addstr("Yes\n");
 68+	    refresh();
 69+	    strcpy(buf, File_name);
 70+	    goto gotfile;
 71+	}
 72+    }
 73+
 74+    do
 75+    {
 76+	Mpos = 0;
 77+	msg("file name: ");
 78+	buf[0] = '\0';
 79+	if (get_str(buf, stdscr) == QUIT)
 80+	{
 81+quit_it:
 82+	    msg("");
 83+	    return;
 84+	}
 85+	Mpos = 0;
 86+gotfile:
 87+	/*
 88+	 * test to see if the file exists
 89+	 */
 90+	if (stat(buf, &Sbuf) >= 0)
 91+	{
 92+	    for (;;)
 93+	    {
 94+		msg("File exists.  Do you wish to overwrite it?");
 95+		Mpos = 0;
 96+		if ((c = readchar()) == ESCAPE)
 97+		    goto quit_it;
 98+		if (c == 'y' || c == 'Y')
 99+		    break;
100+		else if (c == 'n' || c == 'N')
101+		    goto over;
102+		else
103+		    msg("Please answer Y or N");
104+	    }
105+	    msg("file name: %s", buf);
106+	    unlink(File_name);
107+	}
108+	strcpy(File_name, buf);
109+	if ((savef = fopen(File_name, "w")) == NULL)
110+	    msg(strerror(errno));
111+    } while (savef == NULL);
112+
113+    save_file(savef);
114+    /* NOTREACHED */
115+}
116+
117+/*
118+ * auto_save:
119+ *	Automatically save a file.  This is used if a HUP signal is
120+ *	recieved
121+ */
122+void
123+auto_save(int sig)
124+{
125+    FILE *savef;
126+    int i;
127+
128+    for (i = 0; i < NSIG; i++)
129+	signal(i, SIG_IGN);
130+    if (File_name[0] != '\0' && ((savef = fopen(File_name, "w")) != NULL ||
131+	(unlink(File_name) >= 0 && (savef = fopen(File_name, "w")) != NULL)))
132+	    save_file(savef);
133+    exit(0);
134+}
135+
136+/*
137+ * save_file:
138+ *	Write the saved game on the file
139+ */
140+void
141+save_file(FILE *savef)
142+{
143+    int _putchar();
144+
145+    mvcur(0, COLS - 1, LINES - 1, 0); 
146+    putchar('\n');
147+    endwin();
148+    resetltchars();
149+    chmod(File_name, 0400);
150+    /*
151+     * DO NOT DELETE.  This forces stdio to allocate the output buffer
152+     * so that malloc doesn't get confused on restart
153+     */
154+    Frob = 0;
155+    fwrite(&Frob, sizeof Frob, 1, savef);
156+
157+#ifndef	attron
158+    _endwin = TRUE;
159+#endif	attron
160+    fstat(fileno(savef), &Sbuf);
161+    encwrite(version, ((char *) sbrk(0) - version), savef);
162+    printf("pointer is: %ld\n",ftell(savef));
163+/*
164+    fseek(savef, (long) (char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version), SEEK_SET);
165+*/
166+    fseek(savef, (long) ((char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version))%100+1000000, SEEK_SET);
167+    printf("pointer is: %ld\n",ftell(savef));
168+    fflush(savef);
169+    printf("pointer is: %ld\n",ftell(savef));
170+    fstat(fileno(savef), &Sbuf);
171+    fwrite(&Sbuf.st_ctime, sizeof Sbuf.st_ctime, 1, savef);
172+    fclose(savef);
173+    exit(0);
174+}
175+
176+/*
177+ * restore:
178+ *	Restore a saved game from a file with elaborate checks for file
179+ *	integrity from cheaters
180+ */
181+bool
182+restore(char *file, char **envp)
183+{
184+    int inf;
185+    bool syml;
186+    char *sp;
187+    char fb;
188+    extern char **environ;
189+    auto char buf[MAXSTR];
190+    auto STAT sbuf2;
191+
192+    if (strcmp(file, "-r") == 0)
193+	file = File_name;
194+
195+#ifdef SIGTSTP
196+    /*
197+     * If a process can be suspended, this code wouldn't work
198+     */
199+# ifdef SIG_HOLD
200+    signal(SIGTSTP, SIG_HOLD);
201+# else
202+    signal(SIGTSTP, SIG_IGN);
203+# endif
204+#endif
205+
206+    if ((inf = open(file, 0)) < 0)
207+    {
208+	perror(file);
209+	return FALSE;
210+    }
211+    fstat(inf, &sbuf2);
212+    syml = is_symlink(file);
213+    if (
214+#ifdef MASTER
215+	!Wizard &&
216+#endif
217+	unlink(file) < 0)
218+    {
219+	printf("Cannot unlink file\n");
220+	return FALSE;
221+    }
222+
223+    fflush(stdout);
224+    read(inf, &Frob, sizeof Frob);
225+    fb = Frob;
226+    encread(buf, (unsigned) strlen(version) + 1, inf);
227+    if (strcmp(buf, version) != 0)
228+    {
229+	printf("Sorry, saved game is out of date.\n");
230+	return FALSE;
231+    }
232+
233+    sbuf2.st_size -= sizeof Frob;
234+    brk(version + sbuf2.st_size);
235+    lseek(inf, (long) sizeof Frob, 0);
236+    Frob = fb;
237+    encread(version, (unsigned int) sbuf2.st_size, inf);
238+/*
239+    lseek(inf, (long) (char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version), 0);
240+*/
241+    lseek(inf, (long) ((char *) &Sbuf.st_ctime - ((char *) sbrk(0) - version))%100+1000000, 0);
242+    read(inf, &Sbuf.st_ctime, sizeof Sbuf.st_ctime);
243+    /*
244+     * we do not close the file so that we will have a hold of the
245+     * inode for as long as possible
246+     */
247+
248+#ifdef MASTER
249+    if (!Wizard)
250+#endif
251+	if (sbuf2.st_ino != Sbuf.st_ino || sbuf2.st_dev != Sbuf.st_dev)
252+	{
253+	    printf("Sorry, saved game is not in the same file.\n");
254+	    return FALSE;
255+	}
256+	else if (sbuf2.st_ctime - Sbuf.st_ctime > 15)
257+	{
258+	    printf("Sorry, file has been touched, so this score won't be recorded\n");
259+	    Noscore = TRUE;
260+	}
261+    Mpos = 0;
262+/*    printw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); */
263+/*
264+    printw("%s: %s", file, ctime(&sbuf2.st_mtime));
265+*/
266+
267+    /*
268+     * defeat multiple restarting from the same place
269+     */
270+#ifdef MASTER
271+    if (!Wizard)
272+#endif
273+	if (sbuf2.st_nlink != 1 || syml)
274+	{
275+	    printf("Cannot restore from a linked file\n");
276+	    return FALSE;
277+	}
278+
279+    if (Pstats.s_hpt <= 0)
280+    {
281+	printf("\"He's dead, Jim\"\n");
282+	return FALSE;
283+    }
284+#ifdef SIGTSTP
285+    signal(SIGTSTP, tstp);
286+#endif
287+
288+    environ = envp;
289+    gettmode();
290+    if ((sp = getenv("TERM")) == NULL) {
291+	fprintf(stderr, "no TERM variable");
292+	exit(1);
293+    }
294+    setterm(sp);
295+    strcpy(File_name, file);
296+    initscr();                          /* Start up cursor package */
297+    setup();
298+    clearok(curscr, TRUE);
299+    srand(getpid());
300+    msg("file name: %s", file);
301+    playit();
302+    /*NOTREACHED*/
303+}
304+
305+/*
306+ * encwrite:
307+ *	Perform an encrypted write
308+ */
309+void
310+encwrite(char *start, unsigned int size, FILE *outf)
311+{
312+    char *e1, *e2, fb;
313+    int temp;
314+    extern char statlist[];
315+
316+    e1 = encstr;
317+    e2 = statlist;
318+    fb = Frob;
319+
320+    while (size--)
321+    {
322+	putc(*start++ ^ *e1 ^ *e2 ^ fb, outf);
323+	temp = *e1++;
324+	fb += temp * *e2++;
325+	if (*e1 == '\0')
326+	    e1 = encstr;
327+	if (*e2 == '\0')
328+	    e2 = statlist;
329+    }
330+}
331+
332+/*
333+ * encread:
334+ *	Perform an encrypted read
335+ */
336+encread(char *start, unsigned int size, int inf)
337+{
338+    char *e1, *e2, fb;
339+    int temp, read_size;
340+    extern char statlist[];
341+
342+    fb = Frob;
343+
344+    if ((read_size = read(inf, start, size)) == 0 || read_size == -1)
345+	return;
346+
347+    e1 = encstr;
348+    e2 = statlist;
349+
350+    while (size--)
351+    {
352+	*start++ ^= *e1 ^ *e2 ^ fb;
353+	temp = *e1++;
354+	fb += temp * *e2++;
355+	if (*e1 == '\0')
356+	    e1 = encstr;
357+	if (*e2 == '\0')
358+	    e2 = statlist;
359+    }
360+}
361+
362+/*
363+ * read_scrore
364+ *	Read in the score file
365+ */
366+rd_score(SCORE *top_ten, int fd)
367+{
368+    encread((char *) top_ten, numscores * sizeof (SCORE), fd);
369+}
370+
371+/*
372+ * write_scrore
373+ *	Read in the score file
374+ */
375+wr_score(SCORE *top_ten, FILE *outf)
376+{
377+    encwrite((char *) top_ten, numscores * sizeof (SCORE), outf);
378+}
A startup.c
+454, -0
  1@@ -0,0 +1,454 @@
  2+/*
  3+ * Create the layout for the new level
  4+ *
  5+ * @(#)startup.c	4.45 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <ctype.h>
  9+#include <curses.h>
 10+#include "netprot.h"
 11+
 12+typedef struct spot {		/* position matrix for maze positions */
 13+	int	nexits;
 14+	coord	exits[4];
 15+	int	used;
 16+} SPOT;
 17+
 18+#define GOLDGRP 1
 19+
 20+/*
 21+ * do_rooms:
 22+ *	Create rooms and corridors with a connectivity graph
 23+ */
 24+void
 25+do_rooms(void)
 26+{
 27+    int i;
 28+    struct room *rp;
 29+    THING *tp;
 30+    int left_out;
 31+    static coord top;
 32+    coord bsze;				/* maximum room size */
 33+    coord mp;
 34+
 35+    bsze.x = NUMCOLS / 3;
 36+    bsze.y = NUMLINES / 3;
 37+    /*
 38+     * Clear things for a new level
 39+     */
 40+    for (rp = Rooms; rp < &Rooms[MAXROOMS]; rp++)
 41+    {
 42+	rp->r_goldval = 0;
 43+	rp->r_nexits = 0;
 44+	rp->r_flags = 0;
 45+    }
 46+    /*
 47+     * Put the gone rooms, if any, on the level
 48+     */
 49+    left_out = rnd(4);
 50+    for (i = 0; i < left_out; i++)
 51+	Rooms[rnd_room()].r_flags |= ISGONE;
 52+    /*
 53+     * dig and populate all the rooms on the level
 54+     */
 55+    for (i = 0, rp = Rooms; i < MAXROOMS; rp++, i++)
 56+    {
 57+	/*
 58+	 * Find upper left corner of box that this room goes in
 59+	 */
 60+	top.x = (i % 3) * bsze.x + 1;
 61+	top.y = (i / 3) * bsze.y;
 62+	if (rp->r_flags & ISGONE)
 63+	{
 64+	    /*
 65+	     * Place a gone room.  Make certain that there is a blank line
 66+	     * for passage drawing.
 67+	     */
 68+	    do
 69+	    {
 70+		rp->r_pos.x = top.x + rnd(bsze.x - 2) + 1;
 71+		rp->r_pos.y = top.y + rnd(bsze.y - 2) + 1;
 72+		rp->r_max.x = -NUMCOLS;
 73+		rp->r_max.y = -NUMLINES;
 74+	    } until (rp->r_pos.y > 0 && rp->r_pos.y < NUMLINES-1);
 75+	    continue;
 76+	}
 77+	/*
 78+	 * set room type
 79+	 */
 80+	if (rnd(10) < Level - 1)
 81+	{
 82+	    rp->r_flags |= ISDARK;		/* dark room */
 83+	    if (rnd(15) == 0)
 84+		rp->r_flags = ISMAZE;		/* maze room */
 85+	}
 86+	/*
 87+	 * Find a place and size for a random room
 88+	 */
 89+	if (rp->r_flags & ISMAZE)
 90+	{
 91+	    rp->r_max.x = bsze.x - 1;
 92+	    rp->r_max.y = bsze.y - 1;
 93+	    if ((rp->r_pos.x = top.x) == 1)
 94+		rp->r_pos.x = 0;
 95+	    if ((rp->r_pos.y = top.y) == 0)
 96+	    {
 97+		rp->r_pos.y++;
 98+		rp->r_max.y--;
 99+	    }
100+	}
101+	else
102+	    do
103+	    {
104+		rp->r_max.x = rnd(bsze.x - 4) + 4;
105+		rp->r_max.y = rnd(bsze.y - 4) + 4;
106+		rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
107+		rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
108+	    } until (rp->r_pos.y != 0);
109+	draw_room(rp);
110+	/*
111+	 * Put the gold in
112+	 */
113+	if (rnd(2) == 0 && (!Amulet || Level >= Max_level))
114+	{
115+	    THING *gold;
116+
117+	    gold = new_item();
118+	    gold->o_goldval = rp->r_goldval = GOLDCALC;
119+	    find_floor(rp, &rp->r_gold, FALSE, FALSE);
120+	    gold->o_pos = rp->r_gold;
121+	    chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
122+	    gold->o_flags = ISMANY;
123+	    gold->o_group = GOLDGRP;
124+	    gold->o_type = GOLD;
125+	    attach(Lvl_obj, gold);
126+	}
127+	/*
128+	 * Put the monster in
129+	 */
130+	if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
131+	{
132+	    tp = new_item();
133+	    find_floor(rp, &mp, FALSE, TRUE);
134+	    new_monster(tp, randmonster(FALSE), &mp);
135+	    give_pack(tp);
136+	}
137+    }
138+}
139+
140+/*
141+ * draw_room:
142+ *	Draw a box around a room and lay down the floor for normal
143+ *	rooms; for maze rooms, draw maze.
144+ */
145+void
146+draw_room(struct room *rp)
147+{
148+    int y, x;
149+
150+    if (rp->r_flags & ISMAZE)
151+	do_maze(rp);
152+    else
153+    {
154+	vert(rp, rp->r_pos.x);				/* Draw left side */
155+	vert(rp, rp->r_pos.x + rp->r_max.x - 1);	/* Draw right side */
156+	horiz(rp, rp->r_pos.y);				/* Draw top */
157+	horiz(rp, rp->r_pos.y + rp->r_max.y - 1);	/* Draw bottom */
158+
159+	/*
160+	 * Put the floor down
161+	 */
162+	for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++)
163+	    for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++)
164+		chat(y, x) = FLOOR;
165+    }
166+}
167+
168+/*
169+ * vert:
170+ *	Draw a vertical line
171+ */
172+void
173+vert(struct room *rp, int startx)
174+{
175+    int y;
176+
177+    for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++)
178+	chat(y, startx) = '|';
179+}
180+
181+/*
182+ * horiz:
183+ *	Draw a horizontal line
184+ */
185+void
186+horiz(struct room *rp, int starty)
187+{
188+    int x;
189+
190+    for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++)
191+	chat(starty, x) = '-';
192+}
193+
194+/*
195+ * do_maze:
196+ *	Dig a maze
197+ */
198+
199+static int	Maxy, Maxx, Starty, Startx;
200+
201+static SPOT	Maze[NUMLINES/3+1][NUMCOLS/3+1];
202+
203+void
204+do_maze(struct room *rp)
205+{
206+    SPOT *sp;
207+    int starty, startx;
208+    static coord pos;
209+
210+    for (sp = &Maze[0][0]; sp < &Maze[NUMLINES / 3][NUMCOLS / 3 + 1]; sp++)
211+    {
212+	sp->used = FALSE;
213+	sp->nexits = 0;
214+    }
215+
216+    Maxy = rp->r_max.y;
217+    Maxx = rp->r_max.x;
218+    Starty = rp->r_pos.y;
219+    Startx = rp->r_pos.x;
220+    starty = (rnd(rp->r_max.y) / 2) * 2;
221+    startx = (rnd(rp->r_max.x) / 2) * 2;
222+    pos.y = starty + Starty;
223+    pos.x = startx + Startx;
224+    putpass(&pos);
225+    dig(starty, startx);
226+}
227+
228+/*
229+ * dig:
230+ *	Dig out from around where we are now, if possible
231+ */
232+void
233+dig(int y, int x)
234+{
235+    coord *cp;
236+    int cnt, newy, newx, nexty, nextx;
237+    static coord pos;
238+    static coord del[4] = {
239+	{2, 0}, {-2, 0}, {0, 2}, {0, -2}
240+    };
241+
242+    for (;;)
243+    {
244+	cnt = 0;
245+	for (cp = del; cp < &del[4]; cp++)
246+	{
247+	    newy = y + cp->y;
248+	    newx = x + cp->x;
249+	    if (newy < 0 || newy > Maxy || newx < 0 || newx > Maxx)
250+		continue;
251+	    if (flat(newy + Starty, newx + Startx) & F_PASS)
252+		continue;
253+	    if (rnd(++cnt) == 0)
254+	    {
255+		nexty = newy;
256+		nextx = newx;
257+	    }
258+	}
259+	if (cnt == 0)
260+	    return;
261+	accnt_maze(y, x, nexty, nextx);
262+	accnt_maze(nexty, nextx, y, x);
263+	if (nexty == y)
264+	{
265+	    pos.y = y + Starty;
266+	    if (nextx - x < 0)
267+		pos.x = nextx + Startx + 1;
268+	    else
269+		pos.x = nextx + Startx - 1;
270+	}
271+	else
272+	{
273+	    pos.x = x + Startx;
274+	    if (nexty - y < 0)
275+		pos.y = nexty + Starty + 1;
276+	    else
277+		pos.y = nexty + Starty - 1;
278+	}
279+	putpass(&pos);
280+	pos.y = nexty + Starty;
281+	pos.x = nextx + Startx;
282+	putpass(&pos);
283+	dig(nexty, nextx);
284+    }
285+}
286+
287+/*
288+ * accnt_maze:
289+ *	Account for maze exits
290+ */
291+void
292+accnt_maze(int y, int x, int ny, int nx)
293+{
294+    SPOT *sp;
295+    coord *cp;
296+
297+    sp = &Maze[y][x];
298+    for (cp = sp->exits; cp < &sp->exits[sp->nexits]; cp++)
299+	if (cp->y == ny && cp->x == nx)
300+	    return;
301+    cp->y = ny;
302+    cp->x = nx;
303+}
304+
305+/*
306+ * rnd_pos:
307+ *	Pick a random spot in a room
308+ */
309+void
310+rnd_pos(struct room *rp, coord *cp)
311+{
312+    cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
313+    cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
314+}
315+
316+/*
317+ * find_floor:
318+ *	Find a valid floor spot in this room.  If rp is NULL, then
319+ *	pick a new room each time around the loop.
320+ */
321+bool
322+find_floor(struct room *rp, coord *cp, int limit, bool monst)
323+{
324+    PLACE *pp;
325+    int cnt;
326+    char compchar;
327+    bool pickroom;
328+
329+    if (!(pickroom = (rp == NULL)))
330+	compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR);
331+    cnt = limit;
332+    for (;;)
333+    {
334+	if (limit && cnt-- == 0)
335+	    return FALSE;
336+	if (pickroom)
337+	{
338+	    rp = &Rooms[rnd_room()];
339+	    compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR);
340+	}
341+	rnd_pos(rp, cp);
342+	pp = INDEX(cp->y, cp->x);
343+	if (monst)
344+	{
345+	    if (pp->p_monst == NULL && step_ok(pp->p_ch))
346+		return TRUE;
347+	}
348+	else if (pp->p_ch == compchar)
349+	    return TRUE;
350+    }
351+}
352+
353+/*
354+ * enter_room:
355+ *	Code that is executed whenver you appear in a room
356+ */
357+void
358+enter_room(coord *cp)
359+{
360+    struct room *rp;
361+    THING *tp;
362+    int y, x;
363+    char ch;
364+
365+    rp = Proom = roomin(cp);
366+    door_open(rp);
367+    if (!(rp->r_flags & ISDARK) && !on(Player, ISBLIND))
368+	for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
369+	{
370+	    move(y, rp->r_pos.x);
371+	    for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
372+	    {
373+		tp = moat(y, x);
374+		ch = chat(y, x);
375+		if (tp == NULL)
376+		    if (inch() != ch)
377+			addch(ch);
378+		    else
379+			move(y, x + 1);
380+		else
381+		{
382+		    tp->t_oldch = ch;
383+		    if (!see_monst(tp))
384+			if (on(Player, SEEMONST))
385+			{
386+			    standout();
387+			    addch(tp->t_disguise);
388+			    standend();
389+			}
390+			else
391+			    addch(ch);
392+		    else
393+			addch(tp->t_disguise);
394+		}
395+	    }
396+	}
397+}
398+
399+/*
400+ * leave_room:
401+ *	Code for when we exit a room
402+ */
403+void
404+leave_room(coord *cp)
405+{
406+    PLACE *pp;
407+    struct room *rp;
408+    int y, x;
409+    char floor;
410+    char ch;
411+
412+    rp = Proom;
413+
414+    if (rp->r_flags & ISMAZE)
415+	return;
416+
417+    if (rp->r_flags & ISGONE)
418+	floor = PASSAGE;
419+    else if (!(rp->r_flags & ISDARK) || on(Player, ISBLIND))
420+	floor = FLOOR;
421+    else
422+	floor = ' ';
423+
424+    Proom = &Passages[flat(cp->y, cp->x) & F_PNUM];
425+    for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
426+	for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
427+	{
428+	    move(y, x);
429+	    switch (ch = inch())
430+	    {
431+		case FLOOR:
432+		    if (floor == ' ' && ch != ' ')
433+			addch(' ');
434+		    break;
435+		default:
436+		    /*
437+		     * to check for monster, we have to strip out
438+		     * standout bit
439+		     */
440+		    if (isupper(toascii(ch)))
441+		    {
442+			if (on(Player, SEEMONST))
443+			{
444+			    standout();
445+			    addch(ch);
446+			    standend();
447+			    break;
448+			}
449+			pp = INDEX(cp->y, cp->x);
450+			addch(pp->p_ch == DOOR ? DOOR : floor);
451+		    }
452+	    }
453+	}
454+    door_open(rp);
455+}
A system.c
+273, -0
  1@@ -0,0 +1,273 @@
  2+/*
  3+ * Functions for dealing with problems brought about by weapons
  4+ *
  5+ * @(#)system.c	4.34 (Berkeley) 02/05/99
  6+ */
  7+
  8+#include <curses.h>
  9+#include <ctype.h>
 10+#include "netprot.h"
 11+
 12+#define NO_WEAPON -1
 13+
 14+static int Group = 2;
 15+
 16+static struct init_weaps {
 17+    char *iw_dam;	/* Damage when wielded */
 18+    char *iw_hrl;	/* Damage when thrown */
 19+    char iw_launch;	/* Launching weapon */
 20+    int iw_flags;	/* Miscellaneous flags */
 21+} Init_dam[MAXWEAPONS] = {
 22+    { "2x4",	"1x3",	NO_WEAPON,	0,		},	/* Mace */
 23+    { "3x4",	"1x2",	NO_WEAPON,	0,		},	/* Long sword */
 24+    { "1x1",	"1x1",	NO_WEAPON,	0,		},	/* Bow */
 25+    { "1x1",	"2x3",	BOW,		ISMANY|ISMISL,	},	/* Arrow */
 26+    { "1x6",	"1x4",	NO_WEAPON,	ISMISL|ISMISL,	},	/* Dagger */
 27+    { "4x4",	"1x2",	NO_WEAPON,	0,		},	/* 2h sword */
 28+    { "1x1",	"1x3",	NO_WEAPON,	ISMANY|ISMISL,	},	/* Dart */
 29+    { "1x2",	"2x4",	NO_WEAPON,	ISMANY|ISMISL,	},	/* Shuriken */
 30+    { "2x3",	"1x6",	NO_WEAPON,	ISMISL,		},	/* Spear */
 31+};
 32+
 33+/*
 34+ * missile:
 35+ *	Fire a missile in a given direction
 36+ */
 37+void
 38+missile(int ydelta, int xdelta)
 39+{
 40+    THING *obj;
 41+
 42+    /*
 43+     * Get which thing we are hurling
 44+     */
 45+    if ((obj = get_item("throw", WEAPON)) == NULL)
 46+	return;
 47+    if (!dropcheck(obj) || is_current(obj))
 48+	return;
 49+    obj = leave_pack(obj, TRUE, FALSE);
 50+    do_motion(obj, ydelta, xdelta);
 51+    /*
 52+     * AHA! Here it has hit something.  If it is a wall or a door,
 53+     * or if it misses (combat) the monster, put it on the floor
 54+     */
 55+    if (moat(obj->o_pos.y, obj->o_pos.x) == NULL ||
 56+	!hit_monster(unc(obj->o_pos), obj))
 57+	    fall(obj, TRUE);
 58+}
 59+
 60+/*
 61+ * do_motion:
 62+ *	Do the actual motion on the screen done by an object traveling
 63+ *	across the room
 64+ */
 65+void
 66+do_motion(THING *obj, int ydelta, int xdelta)
 67+{
 68+    int ch;
 69+
 70+    /*
 71+     * Come fly with us ...
 72+     */
 73+    obj->o_pos = Hero;
 74+    for (;;)
 75+    {
 76+	/*
 77+	 * Erase the old one
 78+	 */
 79+	if (!ce(obj->o_pos, Hero) && cansee(unc(obj->o_pos)) && !Terse)
 80+	{
 81+	    ch = chat(obj->o_pos.y, obj->o_pos.x);
 82+	    if (ch == FLOOR && !show_floor())
 83+		ch = ' ';
 84+	    mvaddch(obj->o_pos.y, obj->o_pos.x, ch);
 85+	}
 86+	/*
 87+	 * Get the new position
 88+	 */
 89+	obj->o_pos.y += ydelta;
 90+	obj->o_pos.x += xdelta;
 91+	if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR)
 92+	{
 93+	    /*
 94+	     * It hasn't hit anything yet, so display it
 95+	     * If it alright.
 96+	     */
 97+	    if (cansee(unc(obj->o_pos)) && !Terse)
 98+	    {
 99+		mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
100+		refresh();
101+	    }
102+	    continue;
103+	}
104+	break;
105+    }
106+}
107+
108+/*
109+ * fall:
110+ *	Drop an item someplace around here.
111+ */
112+void
113+fall(THING *obj, bool pr)
114+{
115+    PLACE *pp;
116+    static coord fpos;
117+
118+    if (fallpos(&obj->o_pos, &fpos))
119+    {
120+	pp = INDEX(fpos.y, fpos.x);
121+	pp->p_ch = obj->o_type;
122+	obj->o_pos = fpos;
123+	if (cansee(fpos.y, fpos.x))
124+	    if (pp->p_monst != NULL)
125+		pp->p_monst->t_oldch = obj->o_type;
126+	    else
127+		mvaddch(fpos.y, fpos.x, obj->o_type);
128+	attach(Lvl_obj, obj);
129+	return;
130+    }
131+    discard(obj);
132+    if (pr)
133+    {
134+	if (Has_hit)
135+	{
136+	    endmsg();
137+	    Has_hit = FALSE;
138+	}
139+	msg("the %s vanishes as it hits the ground",
140+	    Weap_info[obj->o_which].oi_name);
141+    }
142+}
143+
144+/*
145+ * init_weapon:
146+ *	Set up the initial goodies for a weapon
147+ */
148+void
149+init_weapon(THING *weap, char which)
150+{
151+    struct init_weaps *iwp;
152+
153+    weap->o_type = WEAPON;
154+    weap->o_which = which;
155+    iwp = &Init_dam[which];
156+    weap->o_damage = iwp->iw_dam;
157+    weap->o_hurldmg = iwp->iw_hrl;
158+    weap->o_launch = iwp->iw_launch;
159+    weap->o_flags = iwp->iw_flags;
160+    weap->o_hplus = 0;
161+    weap->o_dplus = 0;
162+    if (which == DAGGER)
163+    {
164+	weap->o_count = rnd(4) + 2;
165+	weap->o_group = Group++;
166+    }
167+    else if (weap->o_flags & ISMANY)
168+    {
169+	weap->o_count = rnd(8) + 8;
170+	weap->o_group = Group++;
171+    }
172+    else
173+    {
174+	weap->o_count = 1;
175+	weap->o_group = 0;
176+    }
177+}
178+
179+/*
180+ * hit_monster:
181+ *	Does the missile hit the monster?
182+ */
183+hit_monster(int y, int x, THING *obj)
184+{
185+    static coord mp;
186+
187+    mp.y = y;
188+    mp.x = x;
189+    return fight(&mp, obj, TRUE);
190+}
191+
192+/*
193+ * num:
194+ *	Figure out the plus number for armor/weapons
195+ */
196+char *
197+num(int n1, int n2, char type)
198+{
199+    static char numbuf[10];
200+
201+    sprintf(numbuf, n1 < 0 ? "%d" : "+%d", n1);
202+    if (type == WEAPON)
203+	sprintf(&numbuf[strlen(numbuf)], n2 < 0 ? ",%d" : ",+%d", n2);
204+    return numbuf;
205+}
206+
207+/*
208+ * wield:
209+ *	Pull out a certain weapon
210+ */
211+void
212+wield(void)
213+{
214+    THING *obj, *oweapon;
215+    char *sp;
216+
217+    oweapon = Cur_weapon;
218+    if (!dropcheck(Cur_weapon))
219+    {
220+	Cur_weapon = oweapon;
221+	return;
222+    }
223+    Cur_weapon = oweapon;
224+    if ((obj = get_item("wield", WEAPON)) == NULL)
225+    {
226+bad:
227+	After = FALSE;
228+	return;
229+    }
230+
231+    if (obj->o_type == ARMOR)
232+    {
233+	msg("you can't wield armor");
234+	goto bad;
235+    }
236+    if (is_current(obj))
237+        goto bad;
238+
239+    sp = inv_name(obj, TRUE);
240+    Cur_weapon = obj;
241+    if (!Terse)
242+	addmsg("you are now ");
243+    msg("wielding %s (%c)", sp, obj->o_packch);
244+}
245+
246+/*
247+ * fallpos:
248+ *	Pick a random position around the give (y, x) coordinates
249+ */
250+bool
251+fallpos(coord *pos, coord *newpos)
252+{
253+    int y, x, cnt, ch;
254+
255+    cnt = 0;
256+    for (y = pos->y - 1; y <= pos->y + 1; y++)
257+	for (x = pos->x - 1; x <= pos->x + 1; x++)
258+	{
259+	    /*
260+	     * check to make certain the spot is empty, if it is,
261+	     * put the object there, set it in the level list
262+	     * and re-draw the room if he can see it
263+	     */
264+	    if (y == Hero.y && x == Hero.x)
265+		continue;
266+	    if (((ch = chat(y, x)) == FLOOR || ch == PASSAGE)
267+					&& rnd(++cnt) == 0)
268+	    {
269+		newpos->y = y;
270+		newpos->x = x;
271+	    }
272+	}
273+    return (cnt != 0);
274+}
A terminal.c
+11, -0
 1@@ -0,0 +1,11 @@
 2+/*
 3+ * Version number.  Whenever a new version number is desired, use sccs
 4+ * to get vers.c.  encstr is declared here to force it to be loaded
 5+ * before the version number, and therefore not to be written in saved
 6+ * games.
 7+ */
 8+
 9+char *Release = "5.4";
10+char encstr[] = "\300k||`\251Y.'\305\321\201+\277~r\"]\238_\223=1\341)\222\212\241t;\t$\270\314/<#\201\254";
11+char statlist[] = "\355kl{+\204\255\313idJ\361\214=4:\311\271\341wK<\312\319\213,,7\271/Rk%\b\312\f\246";
12+char version[] = "rogue (Berkeley) 02/05/99";