Neale Pickett
·
2011-10-13
rexec.c
1/*
2 * File with various monster functions in it
3 *
4 * @(#)rexec.c 4.46 (Berkeley) 02/05/99
5 */
6
7#include <curses.h>
8#include "netprot.h"
9#include <ctype.h>
10
11/*
12 * List of monsters in rough order of vorpalness
13 */
14static char Lvl_mons[] = {
15 'K', 'E', 'B', 'S', 'H', 'I', 'R', 'O', 'Z', 'L', 'C', 'Q', 'A',
16 'N', 'Y', 'F', 'T', 'W', 'P', 'X', 'U', 'M', 'V', 'G', 'J', 'D'
17};
18
19static char Wand_mons[] = {
20 'K', 'E', 'B', 'S', 'H', 0, 'R', 'O', 'Z', 0, 'C', 'Q', 'A',
21 0, 'Y', 0, 'T', 'W', 'P', 0, 'U', 'M', 'V', 'G', 'J', 0
22};
23
24/*
25 * randmonster:
26 * Pick a monster to show up. The lower the level,
27 * the meaner the monster.
28 */
29char
30randmonster(bool wander)
31{
32 int d;
33 char *mons;
34
35 mons = (wander ? Wand_mons : Lvl_mons);
36 do
37 {
38 d = Level + (rnd(10) - 6);
39 if (d < 0)
40 d = rnd(5);
41 if (d > 25)
42 d = rnd(5) + 21;
43 } while (mons[d] == 0);
44 return mons[d];
45}
46
47/*
48 * new_monster:
49 * Pick a new monster and add it to the list
50 */
51void
52new_monster(THING *tp, char type, coord *cp)
53{
54 struct monster *mp;
55 int lev_add;
56
57 if ((lev_add = Level - AMULETLEVEL) < 0)
58 lev_add = 0;
59 attach(Mlist, tp);
60 tp->t_type = type;
61 tp->t_disguise = type;
62 tp->t_pos = *cp;
63 move(cp->y, cp->x);
64 tp->t_oldch = inch();
65 tp->t_room = roomin(cp);
66 moat(cp->y, cp->x) = tp;
67 mp = &Monsters[tp->t_type-'A'];
68 tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
69 tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
70 tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
71 strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
72 tp->t_stats.s_str = mp->m_stats.s_str;
73 tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
74 tp->t_flags = mp->m_flags;
75 if (Level > 29)
76 tp->t_flags |= ISHASTE;
77 tp->t_turn = TRUE;
78 tp->t_pack = NULL;
79 if (ISWEARING(R_AGGR))
80 runto(cp);
81 if (type == 'X')
82 tp->t_disguise = rnd_thing();
83}
84
85/*
86 * expadd:
87 * Experience to add for this monster's level/hit points
88 */
89int
90exp_add(THING *tp)
91{
92 int mod;
93
94 if (tp->t_stats.s_lvl == 1)
95 mod = tp->t_stats.s_maxhp / 8;
96 else
97 mod = tp->t_stats.s_maxhp / 6;
98 if (tp->t_stats.s_lvl > 9)
99 mod *= 20;
100 else if (tp->t_stats.s_lvl > 6)
101 mod *= 4;
102 return mod;
103}
104
105/*
106 * wanderer:
107 * Create a new wandering monster and aim it at the player
108 */
109void
110wanderer(void)
111{
112 int i;
113 struct room *rp;
114 THING *tp;
115 static coord cp;
116
117 tp = new_item();
118 do
119 {
120 find_floor((struct room *) NULL, &cp, FALSE, TRUE);
121 } while (roomin(&cp) == Proom);
122 new_monster(tp, randmonster(TRUE), &cp);
123 if (on(Player, SEEMONST))
124 {
125 standout();
126 if (!on(Player, ISHALU))
127 addch(tp->t_type);
128 else
129 addch(rnd(26) + 'A');
130 standend();
131 }
132 runto(&tp->t_pos);
133#ifdef MASTER
134 if (Wizard)
135 msg("started a wandering %s", Monsters[tp->t_type-'A'].m_name);
136#endif
137}
138
139/*
140 * wake_monster:
141 * What to do when the hero steps next to a monster
142 */
143THING *
144wake_monster(int y, int x)
145{
146 THING *tp;
147 struct room *rp;
148 char ch, *mname;
149
150#ifdef MASTER
151 if ((tp = moat(y, x)) == NULL)
152 msg("can't find monster in wake_monster");
153#else
154 tp = moat(y, x);
155 if (tp == NULL)
156 endwin(), abort();
157#endif
158 ch = tp->t_type;
159 /*
160 * Every time he sees mean monster, it might start chasing him
161 */
162 if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
163 && !ISWEARING(R_STEALTH) && !on(Player, ISLEVIT))
164 {
165 tp->t_dest = &Hero;
166 tp->t_flags |= ISRUN;
167 }
168 if (ch == 'M' && !on(Player, ISBLIND) && !on(Player, ISHALU)
169 && !on(*tp, ISFOUND) && !on(*tp, ISCANC) && on(*tp, ISRUN))
170 {
171 rp = Proom;
172 if ((rp != NULL && !(rp->r_flags & ISDARK))
173 || dist(y, x, Hero.y, Hero.x) < LAMPDIST)
174 {
175 tp->t_flags |= ISFOUND;
176 if (!save(VS_MAGIC))
177 {
178 if (on(Player, ISHUH))
179 lengthen(unconfuse, spread(HUHDURATION));
180 else
181 fuse(unconfuse, 0, spread(HUHDURATION), AFTER);
182 Player.t_flags |= ISHUH;
183 mname = set_mname(tp);
184 addmsg("%s", mname);
185 if (strcmp(mname, "it") != 0)
186 addmsg("'");
187 msg("s gaze has confused you");
188 }
189 }
190 }
191 /*
192 * Let greedy ones guard gold
193 */
194 if (on(*tp, ISGREED) && !on(*tp, ISRUN))
195 {
196 tp->t_flags |= ISRUN;
197 if (Proom->r_goldval)
198 tp->t_dest = &Proom->r_gold;
199 else
200 tp->t_dest = &Hero;
201 }
202 return tp;
203}
204
205/*
206 * give_pack:
207 * Give a pack to a monster if it deserves one
208 */
209void
210give_pack(THING *tp)
211{
212 if (Level >= Max_level && rnd(100) < Monsters[tp->t_type-'A'].m_carry)
213 attach(tp->t_pack, new_thing());
214}
215
216/*
217 * save_throw:
218 * See if a creature save against something
219 */
220int
221save_throw(int which, THING *tp)
222{
223 int need;
224
225 need = 14 + which - tp->t_stats.s_lvl / 2;
226 return (roll(1, 20) >= need);
227}
228
229/*
230 * save:
231 * See if he saves against various nasty things
232 */
233int
234save(int which)
235{
236 if (which == VS_MAGIC)
237 {
238 if (ISRING(LEFT, R_PROTECT))
239 which -= Cur_ring[LEFT]->o_arm;
240 if (ISRING(RIGHT, R_PROTECT))
241 which -= Cur_ring[RIGHT]->o_arm;
242 }
243 return save_throw(which, &Player);
244}