Mercurial > hg > early-roguelike
comparison rogue3/fight.c @ 0:527e2150eaf0
Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author | edwarj4 |
---|---|
date | Tue, 13 Oct 2009 13:33:34 +0000 |
parents | |
children | e7aab31362af |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:527e2150eaf0 |
---|---|
1 /* | |
2 * All the fighting gets done here | |
3 * | |
4 * @(#)fight.c 3.28 (Berkeley) 6/15/81 | |
5 * | |
6 * Rogue: Exploring the Dungeons of Doom | |
7 * Copyright (C) 1980, 1981 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 <ctype.h> | |
15 #include <string.h> | |
16 #include <stdlib.h> | |
17 #include "rogue.h" | |
18 | |
19 int e_levels[] = { | |
20 10,20,40,80,160,320,640,1280,2560,5120,10240,20480, | |
21 40920, 81920, 163840, 327680, 655360, 1310720, 2621440, 0 }; | |
22 | |
23 /* | |
24 * fight: | |
25 * The player attacks the monster. | |
26 */ | |
27 | |
28 int | |
29 fight(coord *mp, int mn, struct object *weap, int thrown) | |
30 { | |
31 struct thing *tp; | |
32 struct linked_list *item; | |
33 int did_hit = TRUE; | |
34 | |
35 /* | |
36 * Find the monster we want to fight | |
37 */ | |
38 if ((item = find_mons(mp->y, mp->x)) == NULL) | |
39 { | |
40 debug("Fight what @ %d,%d", mp->y, mp->x); | |
41 return(0); | |
42 } | |
43 tp = (struct thing *) ldata(item); | |
44 /* | |
45 * Since we are fighting, things are not quiet so no healing takes | |
46 * place. | |
47 */ | |
48 quiet = 0; | |
49 runto(mp, &hero); | |
50 /* | |
51 * Let him know it was really a mimic (if it was one). | |
52 */ | |
53 if (tp->t_type == 'M' && tp->t_disguise != 'M' && off(player, ISBLIND)) | |
54 { | |
55 msg("Wait! That's a mimic!"); | |
56 tp->t_disguise = 'M'; | |
57 did_hit = thrown; | |
58 } | |
59 if (did_hit) | |
60 { | |
61 char *mname; | |
62 | |
63 did_hit = FALSE; | |
64 if (on(player, ISBLIND)) | |
65 mname = "it"; | |
66 else | |
67 mname = monsters[mn-'A'].m_name; | |
68 if (roll_em(&pstats, &tp->t_stats, weap, thrown)) | |
69 { | |
70 did_hit = TRUE; | |
71 if (thrown) | |
72 thunk(weap, mname); | |
73 else | |
74 hit(NULL, mname); | |
75 if (on(player, CANHUH)) | |
76 { | |
77 msg("Your hands stop glowing red"); | |
78 msg("The %s appears confused.", mname); | |
79 tp->t_flags |= ISHUH; | |
80 player.t_flags &= ~CANHUH; | |
81 } | |
82 if (tp->t_stats.s_hpt <= 0) | |
83 killed(item, TRUE); | |
84 } | |
85 else | |
86 if (thrown) | |
87 bounce(weap, mname); | |
88 else | |
89 miss(NULL, mname); | |
90 } | |
91 count = 0; | |
92 return did_hit; | |
93 } | |
94 | |
95 /* | |
96 * attack: | |
97 * The monster attacks the player | |
98 */ | |
99 | |
100 int | |
101 attack(struct thing *mp) | |
102 { | |
103 char *mname; | |
104 | |
105 /* | |
106 * Since this is an attack, stop running and any healing that was | |
107 * going on at the time. | |
108 */ | |
109 running = FALSE; | |
110 quiet = 0; | |
111 if (mp->t_type == 'M' && off(player, ISBLIND)) | |
112 mp->t_disguise = 'M'; | |
113 if (on(player, ISBLIND)) | |
114 mname = "it"; | |
115 else | |
116 mname = monsters[mp->t_type-'A'].m_name; | |
117 if (roll_em(&mp->t_stats, &pstats, NULL, FALSE)) | |
118 { | |
119 if (mp->t_type != 'E') | |
120 hit(mname, NULL); | |
121 if (pstats.s_hpt <= 0) | |
122 death(mp->t_type); /* Bye bye life ... */ | |
123 if (off(*mp, ISCANC)) | |
124 switch (mp->t_type) | |
125 { | |
126 case 'R': | |
127 /* | |
128 * If a rust monster hits, you lose armor | |
129 */ | |
130 if (cur_armor != NULL && cur_armor->o_ac < 9) | |
131 { | |
132 if (!terse) | |
133 msg("Your armor appears to be weaker now. Oh my!"); | |
134 else | |
135 msg("Your armor weakens"); | |
136 cur_armor->o_ac++; | |
137 } | |
138 when 'E': | |
139 /* | |
140 * The gaze of the floating eye hypnotizes you | |
141 */ | |
142 if (on(player, ISBLIND)) | |
143 break; | |
144 if (!no_command) | |
145 { | |
146 addmsg("You are transfixed"); | |
147 if (!terse) | |
148 addmsg(" by the gaze of the floating eye."); | |
149 endmsg(); | |
150 } | |
151 no_command += rnd(2)+2; | |
152 if (no_command > 100 && food_left <= 0) | |
153 death('E'); | |
154 when 'A': | |
155 /* | |
156 * Ants have poisonous bites | |
157 */ | |
158 if (!save(VS_POISON)) | |
159 if (!ISWEARING(R_SUSTSTR)) | |
160 { | |
161 chg_str(-1); | |
162 if (!terse) | |
163 msg("You feel a sting in your arm and now feel weaker"); | |
164 else | |
165 msg("A sting has weakened you"); | |
166 } | |
167 else | |
168 if (!terse) | |
169 msg("A sting momentarily weakens you"); | |
170 else | |
171 msg("Sting has no effect"); | |
172 when 'W': | |
173 /* | |
174 * Wraiths might drain energy levels | |
175 */ | |
176 if (rnd(100) < 15) | |
177 { | |
178 int fewer; | |
179 | |
180 if (pstats.s_exp == 0) | |
181 death('W'); /* All levels gone */ | |
182 msg("You suddenly feel weaker."); | |
183 if (--pstats.s_lvl == 0) | |
184 { | |
185 pstats.s_exp = 0; | |
186 pstats.s_lvl = 1; | |
187 } | |
188 else | |
189 pstats.s_exp = e_levels[pstats.s_lvl-1]+1; | |
190 fewer = roll(1, 10); | |
191 pstats.s_hpt -= fewer; | |
192 max_hp -= fewer; | |
193 if (pstats.s_hpt < 1) | |
194 pstats.s_hpt = 1; | |
195 if (max_hp < 1) | |
196 death('W'); | |
197 } | |
198 when 'F': | |
199 /* | |
200 * Violet fungi stops the poor guy from moving | |
201 */ | |
202 player.t_flags |= ISHELD; | |
203 sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit); | |
204 when 'L': | |
205 { | |
206 /* | |
207 * Leperachaun steals some gold | |
208 */ | |
209 int lastpurse; | |
210 | |
211 lastpurse = purse; | |
212 purse -= GOLDCALC; | |
213 if (!save(VS_MAGIC)) | |
214 purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC; | |
215 if (purse < 0) | |
216 purse = 0; | |
217 if (purse != lastpurse) | |
218 msg("Your purse feels lighter"); | |
219 remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x)); | |
220 mp = NULL; | |
221 } | |
222 when 'N': | |
223 { | |
224 struct linked_list *list, *steal; | |
225 struct object *obj; | |
226 int nobj; | |
227 | |
228 /* | |
229 * Nymph's steal a magic item, look through the pack | |
230 * and pick out one we like. | |
231 */ | |
232 steal = NULL; | |
233 for (nobj = 0, list = pack; list != NULL; list = next(list)) | |
234 { | |
235 obj = (struct object *) ldata(list); | |
236 if (obj != cur_armor && | |
237 obj != cur_weapon && | |
238 obj != cur_ring[LEFT] && | |
239 obj != cur_ring[RIGHT] && /* Nymph bug fix */ | |
240 is_magic(obj) && | |
241 rnd(++nobj) == 0) | |
242 steal = list; | |
243 } | |
244 if (steal != NULL) | |
245 { | |
246 struct object *sobj; | |
247 | |
248 sobj = (struct object *) ldata(steal); | |
249 remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x)); | |
250 mp = NULL; | |
251 if (sobj->o_count > 1 && sobj->o_group == 0) | |
252 { | |
253 int oc; | |
254 | |
255 oc = sobj->o_count; | |
256 sobj->o_count = 1; | |
257 msg("She stole %s!", inv_name(sobj, TRUE)); | |
258 sobj->o_count = oc - 1; | |
259 } | |
260 else | |
261 { | |
262 msg("She stole %s!", inv_name(sobj, TRUE)); | |
263 detach(pack, steal); | |
264 discard(steal); | |
265 } | |
266 inpack--; | |
267 } | |
268 } | |
269 otherwise: | |
270 break; | |
271 } | |
272 } | |
273 else if (mp->t_type != 'E') | |
274 { | |
275 if (mp->t_type == 'F') | |
276 { | |
277 pstats.s_hpt -= fung_hit; | |
278 if (pstats.s_hpt <= 0) | |
279 death(mp->t_type); /* Bye bye life ... */ | |
280 } | |
281 miss(mname, NULL); | |
282 } | |
283 /* | |
284 * Check to see if this is a regenerating monster and let it heal if | |
285 * it is. | |
286 */ | |
287 if ((mp != NULL) && (on(*mp, ISREGEN) && rnd(100) < 33)) | |
288 mp->t_stats.s_hpt++; | |
289 if (fight_flush) | |
290 { | |
291 flush_type(); /* flush typeahead */ | |
292 } | |
293 count = 0; | |
294 status(); | |
295 | |
296 if (mp == NULL) | |
297 return(-1); | |
298 else | |
299 return(0); | |
300 } | |
301 | |
302 /* | |
303 * swing: | |
304 * returns true if the swing hits | |
305 */ | |
306 | |
307 int | |
308 swing(int at_lvl, int op_arm, int wplus) | |
309 { | |
310 int res = rnd(20)+1; | |
311 int need = (21-at_lvl)-op_arm; | |
312 | |
313 return (res+wplus >= need); | |
314 } | |
315 | |
316 /* | |
317 * check_level: | |
318 * Check to see if the guy has gone up a level. | |
319 */ | |
320 | |
321 void | |
322 check_level() | |
323 { | |
324 int i, add; | |
325 | |
326 for (i = 0; e_levels[i] != 0; i++) | |
327 if (e_levels[i] > pstats.s_exp) | |
328 break; | |
329 i++; | |
330 if (i > pstats.s_lvl) | |
331 { | |
332 add = roll(i-pstats.s_lvl,10); | |
333 max_hp += add; | |
334 if ((pstats.s_hpt += add) > max_hp) | |
335 pstats.s_hpt = max_hp; | |
336 msg("Welcome to level %d", i); | |
337 } | |
338 pstats.s_lvl = i; | |
339 } | |
340 | |
341 /* | |
342 * roll_em: | |
343 * Roll several attacks | |
344 */ | |
345 | |
346 int | |
347 roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl) | |
348 { | |
349 char *cp; | |
350 int ndice, nsides, def_arm; | |
351 int did_hit = FALSE; | |
352 int prop_hplus, prop_dplus; | |
353 | |
354 prop_hplus = prop_dplus = 0; | |
355 if (weap == NULL) | |
356 cp = att->s_dmg; | |
357 else if (hurl) | |
358 if ((weap->o_flags&ISMISL) && cur_weapon != NULL && | |
359 cur_weapon->o_which == weap->o_launch) | |
360 { | |
361 cp = weap->o_hurldmg; | |
362 prop_hplus = cur_weapon->o_hplus; | |
363 prop_dplus = cur_weapon->o_dplus; | |
364 } | |
365 else | |
366 cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg); | |
367 else | |
368 { | |
369 cp = weap->o_damage; | |
370 /* | |
371 * Drain a staff of striking | |
372 */ | |
373 if (weap->o_type == STICK && weap->o_which == WS_HIT | |
374 && weap->o_charges == 0) | |
375 { | |
376 strcpy(weap->o_damage,"0d0"); | |
377 weap->o_hplus = weap->o_dplus = 0; | |
378 } | |
379 } | |
380 for (;;) | |
381 { | |
382 int damage; | |
383 int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus); | |