comparison rogue4/monsters.c @ 12:9535a08ddc39

Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author edwarj4
date Sat, 24 Oct 2009 16:52:52 +0000
parents
children 1b73a8641b37
comparison
equal deleted inserted replaced
11:949d558c2162 12:9535a08ddc39
1 /*
2 * File with various monster functions in it
3 *
4 * @(#)monsters.c 4.24 (Berkeley) 4/6/82
5 *
6 * Rogue: Exploring the Dungeons of Doom
7 * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
8 * All rights reserved.
9 *
10 * See the file LICENSE.TXT for full copyright and licensing information.
11 */
12
13 #include <curses.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include "rogue.h"
17
18 /*
19 * List of monsters in rough order of vorpalness
20 *
21 * NOTE: This not initialized using strings so that xstr doesn't set up
22 * the string not to be saved. Otherwise genocide is lost through
23 * saving a game.
24 */
25 char lvl_mons[] = {
26 'K', 'J', 'B', 'S', 'H', 'E', 'A', 'O', 'Z', 'G', 'L', 'C', 'R',
27 'Q', 'N', 'Y', 'T', 'W', 'F', 'I', 'X', 'U', 'M', 'V', 'P', 'D',
28 '\0'
29 };
30
31 char wand_mons[] = {
32 'K', 'J', 'B', 'S', 'H', ' ', 'A', 'O', 'Z', 'G', ' ', 'C', 'R',
33 'Q', ' ', 'Y', 'T', 'W', ' ', 'I', 'X', 'U', ' ', 'V', 'P', ' ',
34 '\0'
35 };
36
37 /*
38 * randmonster:
39 * Pick a monster to show up. The lower the level,
40 * the meaner the monster.
41 */
42 randmonster(wander)
43 bool wander;
44 {
45 register int d;
46 register char *mons;
47
48 mons = wander ? wand_mons : lvl_mons;
49 do
50 {
51 d = level + (rnd(10) - 5);
52 if (d < 1)
53 d = rnd(5) + 1;
54 if (d > 26)
55 d = rnd(5) + 22;
56 } while (mons[--d] == ' ');
57 return mons[d];
58 }
59
60 /*
61 * new_monster:
62 * Pick a new monster and add it to the list
63 */
64 new_monster(tp, type, cp)
65 register THING *tp;
66 char type;
67 register coord *cp;
68 {
69 register struct monster *mp;
70 register int lev_add;
71
72 if ((lev_add = level - AMULETLEVEL) < 0)
73 lev_add = 0;
74 attach(mlist, tp);
75 tp->t_type = type;
76 tp->t_disguise = type;
77 tp->t_pos = *cp;
78 tp->t_oldch = mvinch(cp->y, cp->x);
79 tp->t_room = roomin(cp);
80 moat(cp->y, cp->x) = tp;
81 mp = &monsters[tp->t_type-'A'];
82 tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
83 tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
84 tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
85 strncpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg,16);
86 tp->t_stats.s_str = mp->m_stats.s_str;
87 tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
88 tp->t_flags = mp->m_flags;
89 tp->t_turn = TRUE;
90 tp->t_pack = NULL;
91 if (ISWEARING(R_AGGR))
92 runto(cp, &hero);
93 if (type == 'M')
94 switch (rnd(level > 25 ? 9 : 8))
95 {
96 case 0: tp->t_disguise = GOLD;
97 when 1: tp->t_disguise = POTION;
98 when 2: tp->t_disguise = SCROLL;
99 when 3: tp->t_disguise = STAIRS;
100 when 4: tp->t_disguise = WEAPON;
101 when 5: tp->t_disguise = ARMOR;
102 when 6: tp->t_disguise = RING;
103 when 7: tp->t_disguise = STICK;
104 when 8: tp->t_disguise = AMULET;
105 }
106 }
107
108 /*
109 * expadd:
110 * Experience to add for this monster's level/hit points
111 */
112 exp_add(tp)
113 register THING *tp;
114 {
115 register int mod;
116
117 if (tp->t_stats.s_lvl == 1)
118 mod = tp->t_stats.s_maxhp / 8;
119 else
120 mod = tp->t_stats.s_maxhp / 6;
121 if (tp->t_stats.s_lvl > 9)
122 mod *= 20;
123 else if (tp->t_stats.s_lvl > 6)
124 mod *= 4;
125 return mod;
126 }
127
128 /*
129 * wanderer:
130 * Create a new wandering monster and aim it at the player
131 */
132 wanderer()
133 {
134 register int i;
135 register struct room *rp;
136 register THING *tp;
137 coord cp = {0,0};
138 register int cnt = 0;
139
140 tp = new_item();
141 do
142 {
143 /* Avoid endless loop when all rooms are filled with monsters
144 * and the player room is not accessible to the monsters.
145 */
146 if (cnt++ >= 500)
147 {
148 discard(tp);
149 return;
150 }
151 i = rnd_room();
152 if ((rp = &rooms[i]) == proom)
153 continue;
154 rnd_pos(rp, &cp);
155 } until (rp != proom && step_ok(winat(cp.y, cp.x)));
156 new_monster(tp, randmonster(TRUE), &cp);
157 runto(&tp->t_pos, &hero);
158 #ifdef WIZARD
159 if (wizard)
160 msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
161 #endif
162 }
163
164 /*
165 * wake_monster:
166 * What to do when the hero steps next to a monster
167 */
168 THING *
169 wake_monster(y, x)
170 int y, x;
171 {
172 register THING *tp;
173 register struct room *rp;
174 register char ch;
175
176 #ifdef WIZARD
177 if ((tp = moat(y, x)) == NULL)
178 msg("can't find monster in wake_monster");
179 #else
180 tp = moat(y, x);
181 #endif
182 ch = tp->t_type;
183 /*
184 * Every time he sees mean monster, it might start chasing him
185 */
186 if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
187 && !ISWEARING(R_STEALTH))
188 {
189 tp->t_dest = &hero;
190 tp->t_flags |= ISRUN;
191 }
192 if (ch == 'U' && !on(player, ISBLIND) && !on(*tp, ISFOUND)
193 && !on(*tp, ISCANC) && on(*tp, ISRUN))
194 {
195 rp = proom;
196 if ((rp != NULL && !(rp->r_flags & ISDARK))
197 || DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
198 {
199 tp->t_flags |= ISFOUND;
200 if (!save(VS_MAGIC))
201 {
202 if (on(player, ISHUH))
203 lengthen(unconfuse, rnd(20) + HUHDURATION);
204 else
205 fuse(unconfuse, 0, rnd(20) + HUHDURATION, AFTER);
206 player.t_flags |= ISHUH;
207 msg("the umber hulk's gaze has confused you");
208 }
209 }
210 }
211 /*
212 * Let greedy ones guard gold
213 */
214 if (on(*tp, ISGREED) && !on(*tp, ISRUN))
215 {
216 tp->t_flags |= ISRUN;
217 if (proom->r_goldval)
218 tp->t_dest = &proom->r_gold;
219 else
220 tp->t_dest = &hero;
221 }
222 return tp;
223 }
224
225 /*
226 * genocide:
227 * Wipe one monster out of existence (for now...)
228 */
229 genocide()
230 {
231 register THING *mp;
232 register char c;
233 register int i;
234 register THING *nmp;
235
236 addmsg("which monster");
237 if (!terse)
238 addmsg(" do you wish to wipe out");
239 msg("? ");
240 while (!isalpha(c = readchar()))
241 if (c == ESCAPE)
242 return;
243 else
244 {
245 mpos = 0;
246 msg("please specifiy a letter between 'A' and 'Z'");
247 }
248 mpos = 0;
249 if (islower(c))
250 c = toupper(c);
251 for (mp = mlist; mp; mp = nmp)
252 {
253 nmp = next(mp);
254 if (mp->t_type == c)
255 remove_monster(&mp->t_pos, mp, FALSE);
256 }
257 for (i = 0; i < 26; i++)
258 if (lvl_mons[i] == c)
259 {
260 lvl_mons[i] = ' ';
261 wand_mons[i] = ' ';
262 break;
263 }
264 if (!terse)
265 addmsg("there will be ");
266 msg("no more %ss", monsters[c - 'A'].m_name);
267 }
268
269 /*
270 * give_pack:
271 * Give a pack to a monster if it deserves one
272 */
273 give_pack(tp)
274 register THING *tp;
275 {
276 if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
277 attach(tp->t_pack, new_thing());
278 }