- 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
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)
+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+}
+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+}
+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+}
+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+}
+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);
+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+}
+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;
+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+}
+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+}
+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+}
+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";