Mercurial > hg > early-roguelike
comparison arogue5/fight.c @ 63:0ed67132cf10
Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author | elwin |
---|---|
date | Thu, 09 Aug 2012 22:58:48 +0000 |
parents | |
children | 56e748983fa8 |
comparison
equal
deleted
inserted
replaced
62:0ef99244acb8 | 63:0ed67132cf10 |
---|---|
1 /* | |
2 * All the fighting gets done here | |
3 * | |
4 * Advanced Rogue | |
5 * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T | |
6 * All rights reserved. | |
7 * | |
8 * Based on "Rogue: Exploring the Dungeons of Doom" | |
9 * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
10 * All rights reserved. | |
11 * | |
12 * See the file LICENSE.TXT for full copyright and licensing information. | |
13 */ | |
14 | |
15 #include "curses.h" | |
16 #include <ctype.h> | |
17 #include <string.h> | |
18 #include "rogue.h" | |
19 | |
20 #define CONF_DAMAGE -1 | |
21 #define PARAL_DAMAGE -2 | |
22 #define DEST_DAMAGE -3 | |
23 | |
24 static const struct matrix att_mat[5] = { | |
25 /* Base Max_lvl, Factor, Offset, Range */ | |
26 { 10, 25, 2, 1, 2 }, | |
27 { 9, 18, 2, 1, 5 }, | |
28 { 10, 19, 2, 1, 3 }, | |
29 { 10, 21, 2, 1, 4 }, | |
30 { 7, 25, 1, 0, 2 } | |
31 }; | |
32 | |
33 /* | |
34 * fight: | |
35 * The player attacks the monster. | |
36 */ | |
37 | |
38 fight(mp, weap, thrown) | |
39 register coord *mp; | |
40 struct object *weap; | |
41 bool thrown; | |
42 { | |
43 register struct thing *tp; | |
44 register struct linked_list *item; | |
45 register bool did_hit = TRUE; | |
46 bool back_stab = FALSE; | |
47 | |
48 /* | |
49 * Find the monster we want to fight | |
50 */ | |
51 if ((item = find_mons(mp->y, mp->x)) == NULL) { | |
52 return(FALSE); /* must have killed him already */ | |
53 } | |
54 tp = THINGPTR(item); | |
55 /* | |
56 * Since we are fighting, things are not quiet so no healing takes | |
57 * place. | |
58 */ | |
59 player.t_quiet = 0; | |
60 tp->t_quiet = 0; | |
61 | |
62 /* | |
63 * if its in the wall, we can't hit it | |
64 */ | |
65 if (on(*tp, ISINWALL) && off(player, CANINWALL)) | |
66 return(FALSE); | |
67 | |
68 /* | |
69 * Let him know it was really a mimic (if it was one). | |
70 */ | |
71 if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise) && | |
72 off(player, ISBLIND)) | |
73 { | |
74 msg("Wait! That's a %s!", monsters[tp->t_index].m_name); | |
75 turn_off(*tp, ISDISGUISE); | |
76 did_hit = thrown; | |
77 } | |
78 if (on(*tp, CANSURPRISE) && off(player, ISBLIND) && !ISWEARING(R_ALERT)) { | |
79 msg("Wait! There's a %s!", monsters[tp->t_index].m_name); | |
80 turn_off(*tp, CANSURPRISE); | |
81 did_hit = thrown; | |
82 } | |
83 /* | |
84 * if he's a thief and the creature is asleep then he gets a chance | |
85 * for a backstab | |
86 */ | |
87 if (player.t_ctype == C_THIEF && | |
88 (!on(*tp, ISRUN) || on(*tp, ISHELD) || tp->t_no_move > 0)&& | |
89 !on(*tp, NOSTAB)) | |
90 back_stab = TRUE; | |
91 | |
92 runto(tp, &hero); | |
93 | |
94 if (did_hit) | |
95 { | |
96 register const char *mname; | |
97 | |
98 did_hit = FALSE; | |
99 mname = (on(player, ISBLIND)) ? "it" : monsters[tp->t_index].m_name; | |
100 if (!can_blink(tp) && | |
101 ( ((weap != NULL) && (weap->o_type == RELIC)) || | |
102 ((off(*tp, MAGICHIT) || ((weap != NULL) && (weap->o_hplus > 0 || weap->o_dplus > 0)) ) && | |
103 (off(*tp, BMAGICHIT) || ((weap != NULL) && (weap->o_hplus > 1 || weap->o_dplus > 1)) ) && | |
104 (off(*tp, CMAGICHIT) || ((weap != NULL) && (weap->o_hplus > 2 || weap->o_dplus > 2)) ) ) ) | |
105 && roll_em(&player, tp, weap, thrown, cur_weapon, back_stab)) | |
106 { | |
107 did_hit = TRUE; | |
108 | |
109 if (on(*tp, NOMETAL) && weap != NULL && | |
110 weap->o_type != RELIC && weap->o_flags & ISMETAL) { | |
111 sprintf(outstring,"Your %s passes right through the %s!", | |
112 weaps[weap->o_which].w_name, mname); | |
113 msg(outstring); | |
114 } | |
115 else if (thrown) { | |
116 tp->t_wasshot = TRUE; | |
117 thunk(weap, tp, mname); | |
118 } | |
119 else | |
120 hit(weap, tp, NULL, mname, back_stab); | |
121 | |
122 /* If the player hit a rust monster, he better have a + weapon */ | |
123 if (on(*tp, CANRUST) && !thrown && (weap != NULL) && | |
124 weap->o_type != RELIC && | |
125 (weap->o_flags & ISMETAL) && | |
126 !(weap->o_flags & ISPROT) && | |
127 (weap->o_hplus < 1) && (weap->o_dplus < 1)) { | |
128 if (rnd(100) < 50) weap->o_hplus--; | |
129 else weap->o_dplus--; | |
130 msg(terse ? "Your %s weakens!" | |
131 : "Your %s appears to be weaker now!", | |
132 weaps[weap->o_which].w_name); | |
133 } | |
134 | |
135 /* If the player hit something that shrieks, wake the dungeon */ | |
136 if (on(*tp, CANSHRIEK)) { | |
137 turn_off(*tp, CANSHRIEK); | |
138 msg("The %s emits a piercing shriek.", mname); | |
139 aggravate(); | |
140 } | |
141 | |
142 /* If the player hit something that can surprise, it can't now */ | |
143 if (on(*tp, CANSURPRISE)) turn_off(*tp, CANSURPRISE); | |
144 | |
145 | |
146 /* | |
147 * Can the player confuse? | |
148 */ | |
149 if (on(player, CANHUH) && !thrown) { | |
150 msg("Your hands stop glowing red"); | |
151 msg("The %s appears confused.", mname); | |
152 turn_on(*tp, ISHUH); | |
153 turn_off(player, CANHUH); | |
154 } | |
155 /* | |
156 * does the creature explode when hit? | |
157 */ | |
158 if (on(*tp, CANEXPLODE)) | |
159 explode(tp); | |
160 | |
161 /* | |
162 * Merchants just disappear if hit | |
163 */ | |
164 if (on(*tp, CANSELL)) { | |
165 msg("The %s disappears with his wares in a flash.",mname); | |
166 killed(item, FALSE, FALSE); | |
167 } | |
168 | |
169 else if (tp->t_stats.s_hpt <= 0) | |
170 killed(item, TRUE, TRUE); | |
171 | |
172 /* If the monster is fairly intelligent and about to die, it | |
173 * may turn tail and run. | |
174 */ | |
175 else if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/10)) && | |
176 (rnd(25) < tp->t_stats.s_intel)) { | |
177 turn_on(*tp, ISFLEE); | |
178 | |
179 /* If monster was suffocating, stop it */ | |
180 if (on(*tp, DIDSUFFOCATE)) { | |
181 turn_off(*tp, DIDSUFFOCATE); | |
182 extinguish(suffocate); | |
183 } | |
184 | |
185 /* If monster held us, stop it */ | |
186 if (on(*tp, DIDHOLD) && (--hold_count == 0)) | |
187 turn_off(player, ISHELD); | |
188 turn_off(*tp, DIDHOLD); | |
189 } | |
190 } | |
191 else { | |
192 if (thrown) | |
193 bounce(weap, tp, mname); | |
194 else | |
195 miss(weap, tp, NULL, mname); | |
196 } | |
197 } | |
198 count = 0; | |
199 return did_hit; | |
200 } | |
201 | |
202 /* | |
203 * attack: | |
204 * The monster attacks the player | |
205 */ | |
206 | |
207 attack(mp, weapon, thrown) | |
208 register struct thing *mp; | |
209 register struct object *weapon; | |
210 bool thrown; | |
211 { | |
212 register const char *mname; | |
213 register bool did_hit = FALSE; | |
214 register struct object *wielded; /* The wielded weapon */ | |
215 | |
216 /* | |
217 * Since this is an attack, stop running and any healing that was | |
218 * going on at the time. | |
219 */ | |
220 running = FALSE; | |
221 player.t_quiet = 0; | |
222 mp->t_quiet = 0; | |
223 | |
224 if (on(*mp, ISDISGUISE) && off(player, ISBLIND)) | |
225 turn_off(*mp, ISDISGUISE); | |
226 mname = on(player, ISBLIND) ? "it" : monsters[mp->t_index].m_name; | |
227 | |
228 /* | |
229 * Try to find a weapon to wield. Wield_weap will return a | |
230 * projector if weapon is a projectile (eg. bow for arrow). | |
231 * If weapon is NULL, it will try to find a suitable weapon. | |
232 */ | |
233 wielded = wield_weap(weapon, mp); | |
234 if (weapon == NULL) weapon = wielded; | |
235 | |
236 if (roll_em(mp, &player, weapon, thrown, wielded, FALSE)) { | |
237 did_hit = TRUE; | |
238 | |
239 if (thrown) m_thunk(weapon, mp, mname); | |
240 else hit(weapon, mp, mname, NULL, FALSE); | |
241 | |
242 if (pstats.s_hpt <= 0) | |
243 death(mp->t_index); /* Bye bye life ... */ | |
244 | |
245 /* | |
246 * suprising monsters appear after they shoot at you | |
247 */ | |
248 if (thrown) { | |
249 if (on(*mp, CANSURPRISE)) | |
250 turn_off(*mp, CANSURPRISE); | |
251 } | |
252 if (!thrown) { | |
253 /* | |
254 * If a vampire hits, it may take half your hit points | |
255 */ | |
256 if (on(*mp, CANSUCK) && !save(VS_MAGIC, &player, 0)) { | |
257 if (pstats.s_hpt == 1) death(mp->t_index); | |
258 else { | |
259 pstats.s_hpt /= 2; | |
260 msg("You feel your life force being drawn from you."); | |
261 } | |
262 } | |
263 | |
264 /* | |
265 * Stinking monsters make player weaker (to hit) | |
266 */ | |
267 if (on(*mp, CANSTINK)) { | |
268 turn_off(*mp, CANSTINK); | |
269 if (!save(VS_POISON, &player, 0)) { | |
270 msg("The stench of the %s sickens you.", mname); | |
271 if (on(player, HASSTINK)) lengthen(unstink, STINKTIME); | |
272 else { | |
273 turn_on(player, HASSTINK); | |
274 fuse(unstink, 0, STINKTIME, AFTER); | |
275 } | |
276 } | |
277 } | |
278 | |
279 /* | |
280 * Chilling monster reduces strength each time | |
281 */ | |
282 if (on(*mp, CANCHILL)) { | |
283 if (!ISWEARING(R_SUSABILITY) && !save(VS_POISON, &player, 0)) { | |
284 msg("You cringe at the %s's chilling touch.", mname); | |
285 chg_str(-1); | |
286 if (lost_str++ == 0) | |
287 fuse(res_strength, 0, CHILLTIME, AFTER); | |
288 else lengthen(res_strength, CHILLTIME); | |
289 } | |
290 } | |
291 | |
292 /* | |
293 * itching monsters reduce dexterity (temporarily) | |
294 */ | |
295 if (on(*mp, CANITCH) && !save(VS_POISON, &player, 0)) { | |
296 msg("The claws of the %s scratch you", mname); | |
297 if(ISWEARING(R_SUSABILITY)) { | |
298 msg("The scratch has no effect"); | |
299 } | |
300 else { | |
301 turn_on(player, HASITCH); | |
302 add_dexterity(TRUE); | |
303 lost_dext++; | |
304 fuse(un_itch, 0, roll(HEALTIME,SICKTIME), AFTER); | |
305 } | |
306 } | |
307 | |
308 | |
309 /* | |
310 * If a hugging monster hits, it may SQUEEEEEEEZE | |
311 */ | |
312 if (on(*mp, CANHUG)) { | |
313 if (roll(1,20) >= 18 || roll(1,20) >= 18) { | |
314 msg("The %s squeezes you against itself.", mname); | |
315 if ((pstats.s_hpt -= roll(2,8)) <= 0) | |
316 death(mp->t_index); | |
317 } | |
318 } | |
319 | |
320 /* | |
321 * If a disease-carrying monster hits, there is a chance the | |
322 * player will catch the disease | |
323 */ | |
324 if (on(*mp, CANDISEASE) && | |
325 (rnd(pstats.s_const) < mp->t_stats.s_lvl) && | |
326 off(player, HASDISEASE)) { | |
327 if (ISWEARING(R_HEALTH)) msg("The wound heals quickly."); | |
328 else { | |
329 turn_on(player, HASDISEASE); | |
330 fuse(cure_disease, 0, roll(HEALTIME,SICKTIME), AFTER); | |
331 msg(terse ? "You have been diseased." | |
332 : "You have contracted a disease!"); | |
333 } | |
334 } | |
335 | |
336 /* | |
337 * If a rust monster hits, you lose armor | |
338 */ | |
339 if (on(*mp, CANRUST)) { | |
340 if (cur_armor != NULL && | |
341 cur_armor->o_which != LEATHER && | |
342 cur_armor->o_which != STUDDED_LEATHER && | |
343 cur_armor->o_which != PADDED_ARMOR && | |
344 !(cur_armor->o_flags & ISPROT) && | |
345 cur_armor->o_ac < pstats.s_arm+1 ) { | |
346 msg(terse ? "Your armor weakens" | |
347 : "Your armor appears to be weaker now. Oh my!"); | |
348 cur_armor->o_ac++; | |
349 } | |
350 if (cur_misc[WEAR_BRACERS] != NULL && | |
351 cur_misc[WEAR_BRACERS]->o_ac > 0 && | |
352 !(cur_misc[WEAR_BRACERS]->o_flags & ISPROT)) { | |
353 cur_misc[WEAR_BRACERS]->o_ac--; | |
354 if (cur_misc[WEAR_BRACERS]->o_ac == 0) { | |
355 register struct linked_list *item; | |
356 | |
357 for (item=pack; item!=NULL; item=next(item)) { | |
358 if (OBJPTR(item) == cur_misc[WEAR_BRACERS]) { | |
359 detach(pack, item); | |
360 o_discard(item); | |
361 break; | |
362 } | |
363 } | |
364 msg ("Your bracers crumble and fall off!"); | |
365 cur_misc[WEAR_BRACERS] = NULL; | |
366 inpack--; | |
367 } | |
368 else { | |
369 msg("Your bracers weaken!"); | |