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!");