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