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