Mercurial > hg > early-roguelike
comparison urogue/fight.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 31 Jan 2017 19:56:04 -0500 |
parents | |
children | 317166b49d8a |
comparison
equal
deleted
inserted
replaced
253:d9badb9c0179 | 256:c495a4f288c6 |
---|---|
1 /* | |
2 fight.c - All the fighting gets done here | |
3 | |
4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom | |
5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong | |
6 All rights reserved. | |
7 | |
8 Based on "Advanced Rogue" | |
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka | |
10 All rights reserved. | |
11 | |
12 Based on "Rogue: Exploring the Dungeons of Doom" | |
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
14 All rights reserved. | |
15 | |
16 See the file LICENSE.TXT for full copyright and licensing information. | |
17 */ | |
18 | |
19 #include <stdlib.h> | |
20 #include <string.h> | |
21 #include <ctype.h> | |
22 #include "rogue.h" | |
23 | |
24 /* | |
25 * This are the beginning experience levels for all players all further | |
26 * experience levels are computed by multiplying by 2 | |
27 */ | |
28 | |
29 static long e_levels[10] = | |
30 { | |
31 143L, /* Fighter */ | |
32 182L, /* Paladin */ | |
33 169L, /* Ranger */ | |
34 127L, /* Cleric */ | |
35 154L, /* Druid */ | |
36 185L, /* Magician */ | |
37 169L, /* Illusionist */ | |
38 112L, /* Thief */ | |
39 126L, /* Assasin */ | |
40 319L /* Ninja */ | |
41 }; | |
42 | |
43 static struct matrix att_mat[11] = | |
44 { | |
45 /* Base, Max_lvl, Factor, Offset, Range */ | |
46 | |
47 { 10, 17, 2, 1, 2 }, /* fi */ | |
48 { 10, 17, 2, 1, 2 }, /* pa */ | |
49 { 10, 17, 2, 1, 2 }, /* ra */ | |
50 { 10, 19, 2, 1, 3 }, /* cl */ | |
51 { 10, 19, 2, 1, 3 }, /* dr */ | |
52 { 9, 21, 2, 1, 5 }, /* mu */ | |
53 { 9, 21, 2, 1, 5 }, /* il */ | |
54 { 10, 21, 2, 1, 4 }, /* th */ | |
55 { 10, 21, 2, 1, 4 }, /* as */ | |
56 { 10, 21, 2, 1, 4 }, /* nj */ | |
57 { 7, 25, 1, 0, 2 } /* mn */ | |
58 }; | |
59 | |
60 void | |
61 do_fight(coord dir, int tothedeath) | |
62 { | |
63 int x,y; | |
64 | |
65 x = dir.x; | |
66 y = dir.y; | |
67 | |
68 if (!tothedeath && pstats.s_hpt < max_stats.s_hpt / 3) | |
69 { | |
70 msg("That's not wise."); | |
71 | |
72 after = fighting = FALSE; | |
73 return; | |
74 } | |
75 | |
76 if (isalpha(CCHAR(winat(hero.y + y, hero.x + x)))) | |
77 { | |
78 after = fighting = TRUE; | |
79 do_move(y, x); | |
80 } | |
81 else | |
82 { | |
83 if (fighting == FALSE) | |
84 msg("Nothing there."); | |
85 | |
86 after = fighting = FALSE; | |
87 } | |
88 | |
89 return; | |
90 } | |
91 | |
92 /* | |
93 fight() | |
94 The player attacks the monster. | |
95 */ | |
96 | |
97 int | |
98 fight(coord *mp, struct object *weap, int thrown) | |
99 { | |
100 struct thing *tp; | |
101 struct linked_list *item; | |
102 int did_hit = TRUE; | |
103 char *mname; | |
104 | |
105 /* Find the monster we want to fight */ | |
106 | |
107 if ((item = find_mons(mp->y, mp->x)) == NULL) | |
108 { | |
109 debug("Fight what @ %d,%d", mp->y, mp->x); | |
110 return 0; | |
111 } | |
112 | |
113 tp = THINGPTR(item); | |
114 | |
115 mname = (on(player, ISBLIND)) ? "it" : monsters[tp->t_index].m_name; | |
116 | |
117 /* Since we are fighting, things are not quiet so no healing takes place */ | |
118 | |
119 player.t_rest_hpt = player.t_rest_pow = 0; | |
120 tp->t_rest_hpt = tp->t_rest_pow = 0; | |
121 | |
122 /* Let him know it was really a mimic (if it was one). */ | |
123 | |
124 if (off(player, ISBLIND)) | |
125 { | |
126 if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise)) | |
127 { | |
128 msg("Wait! That's a %s!", mname); | |
129 turn_off(*tp, ISDISGUISE); | |
130 did_hit = thrown; | |
131 } | |
132 | |
133 if (on(*tp, CANSURPRISE)) | |
134 { | |
135 turn_off(*tp, CANSURPRISE); | |
136 if ((player.t_ctype == C_RANGER && rnd(6) != 0) || | |
137 (player.t_ctype == C_NINJA && rnd(pstats.s_lvl / 2) | |
138 != 0)) | |
139 msg("You notice a %s trying to hide!", mname); | |
140 else | |
141 { | |
142 msg("Wait! There's a %s!", mname); | |
143 did_hit = thrown; | |
144 } | |
145 } | |
146 } | |
147 | |
148 /* Protection from Normal Missiles */ | |
149 | |
150 if (thrown && on(*tp, HASMSHIELD)) | |
151 { | |
152 msg("The %s slows as it approaches %s.", | |
153 weaps[weap->o_which].w_name, mname); | |
154 | |
155 did_hit = FALSE; | |
156 } | |
157 | |
158 if (did_hit) | |
159 { | |
160 did_hit = FALSE; | |
161 | |
162 if (!can_blink(tp) && | |
163 (off(*tp, MAGICHIT) || (weap != NULL && | |
164 (weap->o_hplus > 0 || weap->o_dplus > 0))) && | |
165 (off(*tp, BMAGICHIT) || (weap != NULL && | |
166 (weap->o_hplus > 2 || weap->o_dplus > 2))) && | |
167 roll_em(&player, tp, weap, thrown, cur_weapon)) | |
168 { | |
169 did_hit = TRUE; | |
170 tp->t_wasshot = TRUE; | |
171 | |
172 if (thrown) | |
173 { | |
174 if (weap != NULL && weap->o_type == WEAPON | |
175 && weap->o_which == GRENADE) | |
176 { | |
177 hearmsg("BOOOM!"); | |
178 aggravate(); | |
179 } | |
180 | |
181 thunk(weap, mname); | |
182 } | |
183 else | |
184 hit(mname); | |
185 | |
186 /* hitting a friendly monster is curtains */ | |
187 | |
188 if (on(*tp, ISFRIENDLY)) | |
189 { | |
190 turn_off(*tp, ISFRIENDLY); | |
191 turn_on(*tp, ISMEAN); | |
192 } | |
193 | |
194 /* Charmed monsters become uncharmed */ | |
195 | |
196 if (on(*tp, ISCHARMED)) | |
197 { | |
198 turn_off(*tp, ISCHARMED); | |
199 turn_on(*tp, ISMEAN); | |
200 } | |
201 | |
202 /* | |
203 * If the player hit a rust monster, he better have a | |
204 * + weapon | |
205 */ | |
206 | |
207 if (on(*tp, CANRUST)) | |
208 { | |
209 if (!thrown && (weap != NULL) && | |
210 (weap->o_flags & ISMETAL) && | |
211 !(weap->o_flags & ISPROT) && | |
212 !(weap->o_flags & ISSILVER) && | |
213 (weap->o_hplus < 1) && (weap->o_dplus < 1)) | |
214 { | |
215 if (rnd(100) < 50) | |
216 weap->o_hplus--; | |
217 else | |
218 weap->o_dplus--; | |
219 | |
220 msg("Your %s weakens!", weaps[weap->o_which].w_name); | |
221 } | |
222 else if (!thrown && weap != NULL && (weap->o_flags & ISMETAL)) | |
223 msg("The rust vanishes from your %s!", | |
224 weaps[weap->o_which].w_name); | |
225 } | |
226 | |
227 /* flammable monsters die from burning weapons */ | |
228 | |
229 if (thrown && on(*tp, CANBBURN) && | |
230 (weap->o_flags & CANBURN) && | |
231 !save_throw(VS_WAND, tp)) | |
232 { | |
233 msg("The %s vanishes in a ball of flame.", | |
234 monsters[tp->t_index].m_name); | |
235 | |
236 tp->t_stats.s_hpt = 0; | |
237 } | |
238 | |
239 /* spores explode and infest hero */ | |
240 | |
241 if (on(*tp, CANSPORE)) | |
242 { | |
243 msg("The %s explodes in a cloud of dust.", | |
244 monsters[tp->t_index].m_name); | |
245 | |
246 if (is_wearing(R_HEALTH) || | |
247 player.t_ctype == C_PALADIN || | |
248 (player.t_ctype == C_NINJA && pstats.s_lvl | |
249 > 6) || | |
250 thrown && rnd(50) > 0 || | |
251 rnd(20) > 0) | |
252 { | |
253 msg("The dust makes it hard to breath."); | |
254 } | |
255 else | |
256 { | |
257 msg("You have contracted a parasitic infestation!"); | |
258 | |
259 infest_dam++; | |
260 turn_on(player, HASINFEST); | |
261 } | |
262 | |
263 tp->t_stats.s_hpt = 0; | |
264 } | |
265 | |
266 /* fireproof monsters laugh at you when burning weapon hits */ | |
267 | |
268 if (thrown && on(*tp, NOFIRE) && (weap->o_flags & CANBURN)) | |
269 msg("The %s laughs as the %s bounces.", | |
270 monsters[tp->t_index].m_name, | |
271 weaps[weap->o_which].w_name); | |
272 | |
273 /* sharp weapons have no effect on NOSHARP monsters */ | |
274 | |
275 if (on(*tp, NOSHARP) && (weap != NULL) && | |
276 (weap->o_flags & ISSHARP)) | |
277 { | |
278 msg("The %s has no effect on the %s!", | |
279 weaps[weap->o_which].w_name, | |
280 monsters[tp->t_index].m_name); | |
281 | |
282 fighting = FALSE; | |
283 } | |
284 | |
285 /* metal weapons pass through NOMETAL monsters */ | |
286 | |
287 if (on(*tp, NOMETAL) && (weap != NULL) && | |
288 (weap->o_flags & ISMETAL)) | |
289 { | |
290 msg("The %s passes through the %s!", | |
291 weaps[weap->o_which].w_name, | |
292 monsters[tp->t_index].m_name); | |
293 | |
294 fighting = FALSE; | |
295 } | |
296 | |
297 /* | |
298 * If the player hit something that shrieks, wake the | |
299 * dungeon | |
300 */ | |
301 | |
302 if (on(*tp, CANSHRIEK)) | |
303 { | |
304 turn_off(*tp, CANSHRIEK); | |
305 | |
306 if (on(player, CANHEAR)) | |
307 { | |
308 msg("You are stunned by the %s's shriek.", mname); | |
309 no_command += 4 + rnd(8); | |
310 } | |
311 else if (off(player, ISDEAF)) | |
312 msg("The %s emits a piercing shriek.", mname); | |
313 else | |
314 msg("The %s seems to be trying to make some noise.", mname); | |
315 | |
316 aggravate(); | |
317 | |
318 if (rnd(wizard ? 3 : 39) == 0 && cur_armor | |
319 != NULL | |
320 && cur_armor->o_which == CRYSTAL_ARMOR) | |
321 { | |
322 struct linked_list *itm; | |
323 struct object *obj; | |
324 | |
325 for (itm = pack; itm != NULL; itm = next(itm)) | |
326 { | |
327 obj = OBJPTR(itm); | |
328 | |
329 if (obj == cur_armor) | |
330 break; | |
331 } | |
332 | |
333 if (itm == NULL) | |
334 debug("Can't find crystalline armor being worn."); | |
335 else | |
336 { | |
337 msg("Your armor shatters from the shriek."); | |
338 cur_armor = NULL; | |
339 del_pack(itm); | |
340 } | |
341 } | |
342 } | |
343 | |
344 /* | |
345 * If the player hit something that can surprise, it | |
346 * can't now | |
347 */ | |
348 | |
349 if (on(*tp, CANSURPRISE)) | |
350 turn_off(*tp, CANSURPRISE); | |
351 | |
352 /* | |
353 * If the player hit something that can summon, it | |
354 * will try to | |
355 */ | |
356 | |
357 summon_help(tp, NOFORCE); | |
358 | |
359 /* Can the player confuse? */ | |
360 | |
361 if (on(player, CANHUH) && !thrown) | |
362 { | |
363 seemsg("Your hands stop glowing red!"); | |
364 seemsg("The %s appears confused.", mname); | |
365 turn_on(*tp, ISHUH); | |
366 turn_off(player, CANHUH); | |
367 } | |
368 | |
369 /* Merchants just disappear if hit */ | |
370 | |
371 /* | |
372 * increases prices and curses objects from now on | |
373 * though | |
374 */ | |
375 | |
376 if (on(*tp, CANSELL)) | |
377 { | |
378 msg("The %s disappears with his wares with a BOOM and a flash.", | |
379 mname); | |
380 killed(NULL, item, NOMESSAGE, NOPOINTS); | |
381 aggravate(); | |
382 luck++; | |
383 } | |
384 else if (tp->t_stats.s_hpt <= 0) | |
385 killed(&player, item, MESSAGE, POINTS); | |
386 | |
387 /* | |
388 * If the monster is fairly intelligent and about to | |
389 * die, it may turn tail and run. | |
390 */ | |
391 | |
392 else if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt / 10)) && | |
393 (rnd(25) < tp->t_stats.s_intel)) | |
394 { | |
395 turn_on(*tp, ISFLEE); | |
396 | |
397 /* If monster was suffocating, stop it */ | |
398 | |
399 if (on(*tp, DIDSUFFOCATE)) | |
400 { | |
401 turn_off(*tp, DIDSUFFOCATE); | |
402 extinguish_fuse(FUSE_SUFFOCATE); | |
403 } | |
404 | |
405 /* If monster held us, stop it */ | |
406 | |
407 if (on(*tp, DIDHOLD) && (--hold_count == 0)) | |
408 turn_off(player, ISHELD); | |
409 | |
410 turn_off(*tp, DIDHOLD); | |
411 | |
412 if (on(*tp, CANTELEPORT)) | |
413 { | |
414 int rm; | |
415 | |
416 /* | |
417 * Erase the monster from the old | |
418 * position | |
419 */ | |
420 | |
421 if (isalpha(mvwinch(cw, tp->t_pos.y, tp->t_pos.x))) | |
422 mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch); | |
423 | |
424 mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' '); | |
425 | |
426 /* Get a new position */ | |
427 | |
428 do | |
429 { | |
430 rm = rnd_room(); | |
431 rnd_pos(&rooms[rm], &tp->t_pos); | |
432 } | |
433 while (winat(tp->t_pos.y, tp->t_pos.x) != FLOOR); | |
434 | |
435 /* Put it there */ | |
436 | |
437 mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type); | |
438 tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) ); | |
439 seemsg("The %s seems to have disappeared!", mname); | |
440 } | |
441 } | |
442 } | |
443 else if (thrown) | |
444 bounce(weap, mname); | |
445 else | |
446 miss(mname); | |
447 } | |
448 | |
449 if (curr_mons) | |
450 chase_it(mp,&player); /* after so that backstabbing can happen */ | |
451 | |
452 count = 0; | |
453 | |
454 return(did_hit); | |
455 } | |
456 | |
457 /* | |
458 attack() | |
459 The monster attacks the player | |
460 */ | |
461 | |
462 int | |
463 attack(struct thing *mp, struct object *weapon, int thrown) | |
464 { | |
465 char *mname; | |
466 int did_hit = FALSE; | |
467 | |
468 /* If the monster is in a wall, it cannot attack */ | |
469 | |
470 if (on(*mp, ISINWALL)) | |
471 return (FALSE); | |
472 | |
473 /* If two monsters start to gang up on our hero, stop fight mode */ | |
474 | |
475 if (fighting) | |
476 { | |
477 if (beast == NULL) | |
478 beast = mp; | |
479 else if (beast != mp) | |
480 fighting = FALSE; | |
481 } | |
482 | |
483 /* | |
484 Since this is an attack, stop running and any healing that was | |
485 going on at the time. | |
486 */ | |
487 | |
488 running = FALSE; | |
489 player.t_rest_hpt = player.t_rest_pow = 0; | |
490 mp->t_rest_hpt = mp->t_rest_pow = 0; | |
491 | |
492 if (on(*mp, ISDISGUISE) && off(player, ISBLIND)) | |
493 turn_off(*mp, ISDISGUISE); | |
494 mname = on(player, ISBLIND) ? "the monster" : | |
495 monsters[mp->t_index].m_name; | |
496 | |
497 if (roll_em(mp, &player, weapon, thrown, wield_weap(weapon, mp)) && | |
498 (!thrown || off(player, HASMSHIELD))) | |
499 { | |
500 did_hit = TRUE; | |
501 | |
502 m_thunk(weapon, mname); | |
503 | |
504 if (pstats.s_hpt <= 0) | |
505 { | |
506 death(mp->t_index); /* Bye bye life ... */ | |
507 return TRUE; | |
508 } | |
509 | |
510 /* surprising monsters appear after they shoot at you */ | |
511 | |
512 if (thrown && on(*mp, CANSURPRISE)) | |
513 turn_off(*mp, CANSURPRISE); | |
514 else if (!thrown) | |
515 { | |
516 | |
517 /* | |
518 If a vampire hits, it may take half your hit | |
519 points | |
520 */ | |
521 | |
522 if ( on(*mp, CANSUCK) && !save(VS_MAGIC) ) | |
523 { | |
524 if (pstats.s_hpt == 1) | |
525 { | |
526 death(mp->t_index); | |
527 return TRUE; | |
528 } | |
529 else | |
530 { | |
531 pstats.s_hpt /= 2; | |
532 msg("You feel your life force being drawn from you."); | |
533 } | |
534 } | |
535 | |
536 /* | |
537 strong monsters can shatter or gong crystalline | |
538 armor | |
539 */ | |
540 | |
541 if (cur_armor != NULL && cur_armor->o_which == CRYSTAL_ARMOR) | |
542 { | |
543 if (rnd(mp->t_stats.s_str + (cur_armor->o_ac / 2)) > 20) | |
544 { | |
545 struct linked_list *item; | |
546 struct object *obj; | |
547 | |
548 for (item = pack; item != NULL; item = next(item)) | |
549 { | |
550 obj = OBJPTR(item); | |
551 | |
552 if (obj == cur_armor) | |
553 break; | |
554 } | |
555 | |
556 if (item == NULL) | |
557 debug("Can't find crystalline armor being worn."); | |
558 else | |
559 { | |
560 msg("Your armor is shattered by the blow."); | |
561 cur_armor = NULL; | |
562 del_pack(item); | |
563 } | |
564 } | |
565 else if (rnd(mp->t_stats.s_str) > 15) | |
566 { | |
567 msg("Your armor rings from the blow."); | |
568 aggravate(); | |
569 } | |
570 } | |
571 | |
572 /* Stinking monsters reduce the player's strength */ | |
573 | |
574 if (on(*mp, CANSTINK)) | |
575 { | |
576 turn_off(*mp, CANSTINK); | |
577 | |
578 if (player.t_ctype != C_PALADIN | |
579 && !(player.t_ctype == C_NINJA && pstats.s_lvl > 12) | |
580 && !save(VS_POISON)) | |
581 { | |
582 if (on(player, CANSCENT)) | |
583 { | |
584 msg("You pass out from the stench of the %s.", mname); | |
585 no_command += 4 + rnd(8); | |
586 } | |
587 else if (off(player, ISUNSMELL)) | |
588 msg("The stench of the %s sickens you.", mname); | |
589 | |
590 if (on(player, HASSTINK)) | |
591 lengthen_fuse(FUSE_UNSTINK, STINKTIME); | |
592 else | |
593 { | |
594 turn_on(player, HASSTINK); | |
595 light_fuse(FUSE_UNSTINK, 0, STINKTIME, AFTER); | |
596 } | |
597 } | |
598 } | |
599 | |
600 /* chilling monster reduces strength permanently */ | |
601 | |
602 if (on(*mp, CANCHILL) && | |
603 (cur_armor == NULL || cur_armor->o_which != CRYSTAL_ARMOR)) | |
604 { | |
605 msg("You cringe at the %s's chilling touch.", mname); | |
606 | |
607 if (!is_wearing(R_SUSABILITY)) | |
608 { | |
609 chg_str(-1, FALSE, TRUE); | |
610 | |
611 if (lost_str == 0) | |
612 light_fuse(FUSE_RES_STRENGTH, 0, CHILLTIME, AFTER); | |
613 else | |
614 lengthen_fuse(FUSE_RES_STRENGTH, CHILLTIME); | |
615 } | |
616 } | |
617 | |
618 /* itching monsters reduce dexterity (temporarily) */ | |
619 | |
620 if (on(*mp, CANITCH) && player.t_ctype != C_PALADIN | |
621 && !(player.t_ctype == C_NINJA && pstats.s_lvl > 12) | |
622 && !save(VS_POISON)) | |
623 { | |
624 msg("The claws of the %s scratch you!", mname); | |
625 | |
626 if (is_wearing(R_SUSABILITY)) | |
627 msg("The scratch has no effect."); | |
628 else | |
629 { | |
630 msg("You feel a burning itch."); | |
631 turn_on(player, HASITCH); | |
632 chg_dext(-1, FALSE, TRUE); | |
633 light_fuse(FUSE_UNITCH, 0, roll(4, 6), AFTER); | |
634 } | |
635 } | |
636 | |
637 /* a hugging monster may SQUEEEEEEEZE */ | |
638 | |
639 if (on(*mp, CANHUG) && | |
640 (cur_armor == NULL || cur_armor->o_which != CRYSTAL_ARMOR)) | |
641 { | |
642 if (roll(1, 20) >= 18 || roll(1, 20) >= 18) | |
643 { | |
644 msg("The %s squeezes you against itself.", mname); | |
645 | |
646 if ((pstats.s_hpt -= roll(2, 8)) <= 0) | |
647 { | |
648 death(mp->t_index); | |
649 return TRUE; | |
650 } | |
651 } | |
652 } | |
653 | |
654 /* a trampling monster may step on the player */ | |
655 | |
656 if (on(*mp, CANTRAMPLE)) | |
657 { | |
658 if (roll(1, 20) >= 16 || roll(1, 20) >= 16) | |
659 { | |
660 msg("The %s steps on you.", mname); | |
661 | |
662 if ((pstats.s_hpt -= roll(3, mp->t_stats.s_lvl)) <= 0) | |
663 { | |
664 death(mp->t_index); | |
665 return TRUE; | |
666 } | |
667 } | |
668 } | |
669 | |
670 /* a disease-carrying monster may transmit the disease */ | |
671 | |
672 if (on(*mp, CANDISEASE) && | |
673 (rnd(pstats.s_const) < mp->t_stats.s_lvl) && | |
674 off(player, HASDISEASE)) | |
675 { | |
676 | |
677 if (is_wearing(R_HEALTH) | |
678 || (player.t_ctype == C_PALADIN) | |
679 || (player.t_ctype == C_NINJA && | |
680 pstats.s_lvl > 6)) | |
681 msg("The wound heals quickly."); | |
682 else | |
683 { | |
684 turn_on(player, HASDISEASE); | |
685 light_fuse(FUSE_CURE_DISEASE,0,roll(4,4) * SICKTIME, AFTER); | |
686 msg("You have contracted a disease!"); | |
687 } | |
688 } | |
689 | |
690 /* a rust monster will weaken your armor */ | |
691 | |
692 if (on(*mp, CANRUST)) | |
693 { | |
694 if (cur_armor != NULL && | |
695 cur_armor->o_which != SOFT_LEATHER && | |
696 cur_armor->o_which != HEAVY_LEATHER && | |
697 cur_armor->o_which != CUIRBOLILLI && | |
698 cur_armor->o_which != PADDED_ARMOR && | |
699 cur_armor->o_which != CRYSTAL_ARMOR && | |
700 cur_armor->o_which != MITHRIL && | |
701 !(cur_armor->o_flags & ISPROT) && | |
702 cur_armor->o_ac < pstats.s_arm + 1) | |
703 { | |
704 msg("Your armor weakens!"); | |
705 cur_armor->o_ac++; | |
706 } | |
707 else if (cur_armor != NULL && | |
708 (cur_armor->o_flags & ISPROT) && | |
709 cur_armor->o_which != SOFT_LEATHER && | |
710 cur_armor->o_which != HEAVY_LEATHER && | |
711 cur_armor->o_which != CUIRBOLILLI && | |
712 cur_armor->o_which != PADDED_ARMOR && | |
713 cur_armor->o_which != CRYSTAL_ARMOR && | |
714 cur_armor->o_which != MITHRIL) | |
715 msg("The rust vanishes instantly!"); | |
716 } | |
717 | |
718 /* If a surprising monster hit you, you can see it now */ | |
719 | |
720 if (on(*mp, CANSURPRISE)) | |
721 turn_off(*mp, CANSURPRISE); | |
722 | |
723 /* an infesting monster will give you a parasite or rot */ | |
724 | |
725 if (on(*mp, CANINFEST) && rnd(pstats.s_const) < mp->t_stats.s_lvl) | |
726 { | |
727 if (is_wearing(R_HEALTH) || (player.t_ctype == C_PALADIN) | |
728 || (player.t_ctype == C_NINJA && pstats.s_lvl > 6)) | |
729 msg("The wound quickly heals."); | |
730 else | |
731 { | |
732 turn_off(*mp, CANINFEST); | |
733 msg("You have contracted a parasitic infestation!"); | |
734 infest_dam++; | |
735 turn_on(player, HASINFEST); | |
736 } | |
737 } | |
738 | |
739 /* Some monsters have poisonous bites */ | |
740 | |
741 if (on(*mp, CANPOISON) && !save(VS_POISON)) | |
742 { | |
743 if (is_wearing(R_SUSABILITY) || (player.t_ctype == C_PALADIN) | |
744 || (player.t_ctype == C_NINJA && pstats.s_lvl > 12)) | |
745 msg("The sting has no effect on you!"); | |
746 else | |
747 { | |
748 chg_str(-1, FALSE, FALSE); | |
749 msg("You feel a sting in your arm and now feel weaker."); | |
750 } | |
751 } | |
752 | |
753 /* a hideous monster may cause fear by touching */ | |
754 | |
755 if (on(*mp, TOUCHFEAR)) | |
756 { | |
757 turn_off(*mp, TOUCHFEAR); | |
758 | |
759 if (!save(VS_WAND)&&!(on(player,ISFLEE)&&(player.t_chasee==mp))) | |
760 { | |
761 if (off(player, SUPERHERO) | |
762 && (player.t_ctype != C_PALADIN)) | |
763 { | |
764 turn_on(player, ISFLEE); | |
765 player.t_ischasing = FALSE; | |
766 player.t_chasee = mp; | |
767 msg("The %s's touch terrifies you.", mname); | |
768 } | |
769 else | |
770 msg("The %s's touch feels cold and clammy.", mname); | |
771 } | |
772 } | |
773 | |
774 /* some monsters will suffocate our hero */ | |
775 | |
776 if (on(*mp, CANSUFFOCATE) && (rnd(100) < 15) && | |
777 (find_slot(FUSE_SUFFOCATE, FUSE) == NULL)) | |
778 { | |
779 turn_on(*mp, DIDSUFFOCATE); | |
780 msg("The %s is beginning to suffocate you.", | |
781 mname); | |
782 light_fuse(FUSE_SUFFOCATE, 0, roll(4, 2), AFTER); | |
783 } | |
784 | |
785 /* don't look now, you will get turned to stone */ | |
786 | |
787 if (on(*mp, TOUCHSTONE)) | |
788 { | |
789 turn_off(*mp, TOUCHSTONE); | |
790 | |
791 if (on(player, CANINWALL)) | |
792 msg("The %s's touch has no effect.", mname); | |
793 else | |
794 { | |
795 if (!save(VS_PETRIFICATION) && rnd(100) < 3) | |
796 { | |
797 msg("Your body begins to solidify."); | |
798 msg("You are turned to stone !!! --More--"); | |
799 wait_for(' '); | |
800 death(D_PETRIFY); | |
801 return TRUE; | |
802 } | |
803 else | |
804 { | |
805 msg("The %s's touch stiffens your limbs.", mname); | |
806 no_command = rnd(STONETIME) + 2; | |
807 } | |
808 } | |
809 } | |
810 | |
811 /* Undead might drain energy levels */ | |
812 | |
813 if ((on(*mp, CANDRAIN) || on(*mp, DOUBLEDRAIN)) && rnd(100) < 15) | |
814 { | |
815 if (is_carrying(TR_AMULET)) | |
816 msg("The Amulet protects you from the %s's negative energy!", | |
817 mname); | |
818 else | |
819 { | |
820 lower_level(mp->t_index); | |
821 | |
822 if (on(*mp, DOUBLEDRAIN)) | |
823 lower_level(mp->t_index); | |
824 } | |
825 | |
826 turn_on(*mp, DIDDRAIN); | |
827 } | |
828 | |
829 /* permanently drain a wisdom point */ | |
830 | |
831 if (on(*mp, DRAINWISDOM) && rnd(100) < 15) | |
832 { | |
833 int ring_str; /* Value of ring strengths */ | |
834 | |
835 /* Undo any ring changes */ | |
836 | |
837 ring_str = ring_value(R_ADDWISDOM) + | |
838 (on(player, POWERWISDOM) ? 10 : 0); | |
839 | |
840 pstats.s_wisdom -= ring_str; | |
841 | |
842 msg("You feel slightly less wise now."); | |
843 | |
844 pstats.s_wisdom = max(pstats.s_wisdom - 1, 3); | |
845 max_stats.s_wisdom = pstats.s_wisdom; | |
846 | |
847 /* Now put back the ring changes */ | |
848 | |
849 pstats.s_wisdom += ring_str; | |
850 | |
851 } | |
852 | |
853 /* permanently drain a intelligence point */ | |
854 | |
855 if (on(*mp, DRAINBRAIN) && rnd(100) < 15) | |
856 { | |
857 int ring_str; /* Value of ring strengths */ | |
858 | |
859 /* Undo any ring changes */ | |
860 | |
861 ring_str = ring_value(R_ADDINTEL) + | |
862 (on(player, POWERINTEL) ? 10 : 0); | |
863 | |
864 pstats.s_intel -= ring_str; | |
865 | |
866 msg("You feel slightly less intelligent now."); | |
867 pstats.s_intel = max(pstats.s_intel - 1, 3); | |
868 max_stats.s_intel = pstats.s_intel; | |
869 | |
870 /* Now put back the ring changes */ | |
871 | |
872 pstats.s_intel += ring_str; | |
873 } | |
874 | |
875 /* Violet fungi and others hold the hero */ | |
876 | |
877 if (on(*mp, CANHOLD) && off(*mp, DIDHOLD) | |
878 && !is_wearing(R_FREEDOM)) | |
879 { | |
880 turn_on(player, ISHELD); | |
881 turn_on(*mp, DIDHOLD); | |
882 hold_count++; | |
883 } | |
884 | |
885 /* suckers will suck blood and run away */ | |
886 | |
887 if (on(*mp, CANDRAW)) | |
888 { | |
889 turn_off(*mp, CANDRAW); | |
890 turn_on(*mp, ISFLEE); | |
891 msg("The %s sates itself with your blood.", mname); | |
892 | |
893 if ((pstats.s_hpt -= 12) <= 0) | |
894 { | |
895 death(mp->t_index); | |
896 return TRUE; | |
897 } | |
898 } | |
899 | |
900 /* el stinkos will force a reduction in strength */ | |
901 | |
902 if (on(*mp, CANSMELL)) | |
903 { | |
904 turn_off(*mp, CANSMELL); | |
905 | |
906 if (save(VS_MAGIC) || is_wearing(R_SUSABILITY)) | |
907 msg("You smell an unpleasant odor."); | |
908 else | |
909 { | |
910 int odor_str = -(rnd(6) + 1); | |
911 | |
912 if (on(player, CANSCENT)) | |
913 { | |
914 msg("You pass out from a foul odor."); | |
915 no_command += 4 + rnd(8); | |
916 } | |
917 else if (off(player, ISUNSMELL)) | |
918 msg("You are overcome by a foul odor."); | |
919 | |
920 if (lost_str == 0) | |
921 { | |
922 chg_str(odor_str, FALSE, TRUE); | |
923 light_fuse(FUSE_RES_STRENGTH, 0, SMELLTIME, AFTER); | |
924 } | |
925 else | |
926 lengthen_fuse(FUSE_RES_STRENGTH, SMELLTIME); | |
927 } | |
928 } | |
929 | |
930 /* Paralyzation */ | |
931 | |
932 if (on(*mp, CANPARALYZE)) | |
933 { | |
934 turn_off(*mp, CANPARALYZE); | |
935 | |
936 if (!save(VS_PARALYZATION) && no_command == 0) | |
937 { | |
938 if (on(player, CANINWALL)) | |
939 msg("The %s's touch has no effect.", mname); | |
940 else | |
941 { | |
942 msg("The %s's touch paralyzes you.", mname); | |
943 no_command = FREEZETIME; | |
944 } | |
945 } | |
946 } | |
947 | |
948 /* Rotting */ | |
949 | |
950 if (on(*mp, CANROT)) | |
951 { | |
952 turn_off(*mp, CANROT); | |
953 turn_on(*mp, DOROT); | |
954 } | |
955 | |
956 /* some monsters steal gold */ | |
957 | |
958 if (on(*mp, STEALGOLD)) | |
959 { | |
960 long lastpurse; | |
961 struct linked_list *item; | |
962 struct object *obj; | |
963 | |
964 lastpurse = purse; | |
965 purse = (purse > GOLDCALC) ? purse - GOLDCALC : 0L; | |
966 | |
967 if (!save(VS_MAGIC)) | |
968 purse = (purse > (4*GOLDCALC)) ? purse-(4*GOLDCALC) : 0L; | |
969 | |
970 if (purse != lastpurse) | |
971 { | |
972 msg("Your purse feels lighter."); | |
973 | |
974 /* Give the gold to the thief */ | |
975 | |
976 for (item = mp->t_pack; item != NULL; item = next(item)) | |
977 { | |
978 obj = OBJPTR(item); | |
979 | |
980 if (obj->o_type == GOLD) | |
981 { | |
982 obj->o_count += lastpurse - purse; | |
983 break; | |
984 } | |
985 } | |
986 | |
987 /* Did we do it? */ | |
988 | |
989 if (item == NULL) /* Then make some */ | |
990 { | |
991 item = new_item(sizeof *obj); | |
992 obj = OBJPTR(item); | |
993 obj->o_type = GOLD; | |
994 obj->o_count = lastpurse - purse; | |
995 obj->o_hplus = obj->o_dplus = 0; | |
996 obj->o_damage = obj->o_hurldmg = "0d0"; | |
997 obj->o_ac = 11; | |
998 obj->o_group = 0; | |
999 obj->o_flags = 0; | |
1000 obj->o_mark[0] = '\0'; | |
1001 obj->o_pos = mp->t_pos; | |
1002 | |
1003 attach(mp->t_pack, item); | |
1004 } | |
1005 } | |
1006 | |
1007 if (rnd(2)) | |
1008 turn_on(*mp, ISFLEE); | |
1009 | |
1010 turn_on(*mp, ISINVIS); | |
1011 } | |
1012 | |
1013 /* other monsters steal magic */ | |
1014 | |
1015 if (on(*mp, STEALMAGIC)) | |
1016 { | |
1017 struct linked_list *list, *stealit; | |
1018 struct object *obj; | |
1019 int worth = 0; | |
1020 | |
1021 stealit = NULL; | |
1022 | |
1023 for (list = pack; list != NULL; list = next(list)) | |
1024 { | |
1025 obj = OBJPTR(list); | |
1026 | |
1027 if (rnd(33) == 0) /* some stuff degrades */ | |
1028 { | |
1029 if (obj->o_flags & ISBLESSED) | |
1030 obj->o_flags &= ~ISBLESSED; | |
1031 else | |
1032 obj->o_flags |= ISCURSED; | |
1033 | |
1034 msg("You feel nimble fingers reach into you pack."); | |
1035 } | |
1036 | |
1037 if ((obj != cur_armor && | |
1038 obj != cur_weapon && | |
1039 obj != cur_ring[LEFT_1] && | |
1040 obj != cur_ring[LEFT_2] && | |
1041 obj != cur_ring[LEFT_3] && | |
1042 obj != cur_ring[LEFT_4] && | |
1043 obj != cur_ring[LEFT_5] && | |
1044 obj != cur_ring[RIGHT_1] && | |
1045 obj != cur_ring[RIGHT_2] && | |
1046 obj != cur_ring[RIGHT_3] && | |
1047 obj != cur_ring[RIGHT_4] && | |
1048 obj != cur_ring[RIGHT_5] && | |
1049 !(obj->o_flags & ISPROT) && | |
1050 is_magic(obj) | |
1051 || level > 45) | |
1052 && get_worth(obj) > worth) | |
1053 { | |
1054 stealit = list; | |
1055 worth = get_worth(obj); | |
1056 } | |
1057 } | |
1058 | |
1059 if (stealit != NULL) | |
1060 { | |
1061 struct object *newobj; | |
1062 | |
1063 newobj = OBJPTR(stealit); | |
1064 | |
1065 if (newobj->o_count > 1 && newobj->o_group == 0) | |
1066 { | |
1067 int oc; | |
1068 struct linked_list *nitem; | |
1069 struct object *op; | |
1070 | |
1071 oc = --(newobj->o_count); | |
1072 newobj->o_count = 1; | |
1073 nitem = new_item(sizeof *newobj); | |
1074 op = OBJPTR(nitem); | |
1075 *op = *newobj; | |
1076 | |
1077 msg("The %s stole %s!",mname,inv_name(newobj,LOWERCASE)); | |
1078 newobj->o_count = oc; | |
1079 attach(mp->t_pack, nitem); | |
1080 } | |
1081 else | |
1082 { | |
1083 msg("The %s stole %s!",mname,inv_name(newobj,LOWERCASE)); | |
1084 newobj->o_flags &= ~ISCURSED; | |
1085 dropcheck(newobj); | |
1086 rem_pack(newobj); | |
1087 attach(mp->t_pack, stealit); | |
1088 | |
1089 if (newobj->o_type == ARTIFACT) | |
1090 has_artifact &= ~(1 << newobj->o_which); | |
1091 } | |
1092 | |
1093 if (newobj->o_flags & ISOWNED) | |
1094 { | |
1095 turn_on(*mp, NOMOVE); | |
1096 msg("The %s is transfixed by your ownership spell.", | |
1097 mname); | |
1098 } | |
1099 | |
1100 if (rnd(2)) | |
1101 turn_on(*mp, ISFLEE); | |
1102 | |
1103 turn_on(*mp, ISINVIS); | |
1104 updpack(); | |
1105 } | |
1106 } | |
1107 } | |
1108 } | |
1109 else /* missed */ | |
1110 { | |
1111 /* If the thing was trying to surprise, no good */ | |
1112 | |
1113 if (on(*mp, CANSURPRISE)) | |
1114 turn_off(*mp, CANSURPRISE); | |
1115 | |
1116 m_bounce(weapon, mname); | |
1117 } | |
1118 | |
1119 count = 0; | |
1120 | |
1121 status(FALSE); | |
1122 | |
1123 return(did_hit); | |
1124 } | |
1125 | |
1126 | |
1127 /* | |
1128 mon_mon_attack() | |
1129 A monster attacks another monster | |
1130 */ | |
1131 | |
1132 int | |
1133 mon_mon_attack(struct thing *attacker, struct linked_list *mon, struct object *weapon, int thrown) | |
1134 { | |
1135 struct thing *attackee = THINGPTR(mon); | |
1136 int did_hit = FALSE; | |
1137 int ee_visible = cansee(attackee->t_pos.y, attackee->t_pos.x); | |
1138 int er_visible = cansee(attacker->t_pos.y, attacker->t_pos.x); | |
1139 char *mname1 = monsters[attacker->t_index].m_name; | |
1140 char *mname2 = monsters[attackee->t_index].m_name; | |
1141 | |
1142 /* Similar monsters don't hit each other */ | |
1143 | |
1144 if (attacker->t_index == attackee->t_index) | |
1145 { | |
1146 if (attacker == THINGPTR(fam_ptr) && er_visible) | |
1147 msg("Master, I cannot hit one of my brethren."); | |
1148 if (!thrown && rnd(100) - attacker->t_stats.s_charisma + luck < 0) | |
1149 { | |
1150 if (er_visible) | |
1151 msg("Your %s has made a new ally.", mname1); | |
1152 | |
1153 turn_on(*attackee, ISCHARMED); | |
1154 } | |
1155 | |
1156 return(FALSE); | |
1157 } | |
1158 | |
1159 /* stop running and any healing */ | |
1160 | |
1161 attackee->t_rest_hpt = attackee->t_rest_pow = 0; | |
1162 attacker->t_rest_hpt = attacker->t_rest_pow = 0; | |
1163 | |
1164 if (roll_em(attacker, attackee, weapon, thrown, | |
1165 wield_weap(weapon, attacker))) | |
1166 { | |
1167 did_hit = TRUE; | |
1168 | |
1169 if (ee_visible && on(*attackee, CANSURPRISE)) | |
1170 turn_off(*attackee, CANSURPRISE); | |
1171 | |
1172 if (ee_visible && er_visible && weapon != NULL) | |
1173 msg("The %s's %s hits the %s.", mname1, | |
1174 weaps[weapon->o_which].w_name, mname2); | |
1175 else if (ee_visible && er_visible) | |
1176 msg("The %s hits the %s.", mname1, mname2); | |
1177 | |
1178 if (attackee->t_stats.s_hpt <= 0) | |
1179 { | |
1180 killed(attacker, mon, MESSAGE, | |
1181 on(*attacker, ISFAMILIAR) ? POINTS : NOPOINTS); | |
1182 return(TRUE); | |
1183 } | |
1184 } | |
1185 else /* missed */ | |
1186 { | |
1187 did_hit = FALSE; | |
1188 | |
1189 if (ee_visible && er_visible && weapon != NULL) | |
1190 msg("The %s's %s misses the %s.", mname1, | |
1191 weaps[weapon->o_which].w_name, mname2); | |
1192 else if (ee_visible && er_visible) | |
1193 msg("The %s misses the %s.", mname1, mname2); | |
1194 } | |
1195 | |
1196 if (er_visible && !ee_visible) | |
1197 msg("The %s struggles with something.",mname1); | |
1198 | |
1199 if (off(*attackee, ISMEAN) && off(*attackee, ISFAMILIAR)) | |
1200 turn_on(*attackee, ISRUN); | |
1201 | |
1202 count = 0; | |
1203 | |
1204 status(FALSE); | |
1205 | |
1206 return(did_hit); | |
1207 } | |
1208 | |
1209 | |
1210 /* | |
1211 swing() | |
1212 returns true if the swing hits | |
1213 */ | |
1214 | |
1215 int | |
1216 swing(int class, int at_lvl, int op_arm, int wplus) | |
1217 { | |
1218 int res = rnd(20) + 1; | |
1219 int need; | |
1220 | |
1221 need = att_mat[class].base - | |
1222 att_mat[class].factor * | |
1223 ((min(at_lvl, att_mat[class].max_lvl) - | |
1224 att_mat[class].offset) / att_mat[class].range) + | |
1225 (10 - op_arm); | |
1226 | |
1227 if (need > 20 && need <= 25) | |
1228 need = 20; | |
1229 | |
1230 return(res + wplus >= need); | |
1231 } | |
1232 | |
1233 /* | |
1234 init_exp() | |
1235 set up initial experience level change threshold | |
1236 */ | |
1237 | |
1238 void | |
1239 init_exp(void) | |
1240 { | |
1241 max_stats.s_exp = e_levels[player.t_ctype]; | |
1242 } | |
1243 | |
1244 /* | |
1245 next_exp_level() | |
1246 Do the next level arithmetic Returns number of levels to jump | |
1247 */ | |
1248 | |
1249 int | |
1250 next_exp_level(int print_message) | |
1251 { | |
1252 int level_jump = 0; | |
1253 | |
1254 while (pstats.s_exp >= max_stats.s_exp) | |
1255 { | |
1256 pstats.s_exp -= max_stats.s_exp; /* excess experience points */ | |
1257 level_jump++; | |
1258 | |
1259 if (max_stats.s_exp < 0x3fffffffL) /* 2^30 - 1 */ | |
1260 max_stats.s_exp *= 2L; /* twice as many for next */ | |
1261 } | |
1262 | |
1263 if (print_message) | |
1264 msg("You need %d more points to attain the %stitle of %s.", | |
1265 max_stats.s_exp - pstats.s_exp, | |
1266 (pstats.s_lvl > 14 ? "next " : ""), | |
1267 cnames[player.t_ctype][min(pstats.s_lvl, 14)]); | |
1268 | |
1269 return(level_jump); | |
1270 } | |
1271 | |
1272 /* | |
1273 check_level() | |
1274 Check to see if the guy has gone up a level. | |
1275 */ | |
1276 | |
1277 void | |
1278 check_level(void) | |
1279 { | |
1280 int num_jumped, j, add; | |
1281 int nsides; | |
1282 | |
1283 if ((num_jumped = next_exp_level(NOMESSAGE)) <= 0) | |
1284 return; | |
1285 | |
1286 pstats.s_lvl += num_jumped; /* new experience level */ | |
1287 | |
1288 switch (player.t_ctype) | |
1289 { | |
1290 case C_MAGICIAN: | |
1291 case C_ILLUSION: nsides = 4; | |
1292 break; | |
1293 case C_THIEF: | |
1294 case C_ASSASIN: | |
1295 case C_NINJA: | |
1296 case C_MONSTER: | |
1297 default: nsides = 6; | |
1298 break; | |
1299 case C_CLERIC: | |
1300 case C_DRUID: nsides = 8; | |
1301 break; | |
1302 | |
1303 case C_FIGHTER: | |
1304 case C_PALADIN: | |
1305 case C_RANGER: | |
1306 nsides = 12; | |
1307 break; | |
1308 } | |
1309 | |
1310 /* Take care of multi-level jumps */ | |
1311 | |
1312 for (add = 0, j = 0; j < num_jumped; j++) | |
1313 { | |
1314 int increase = roll(1, nsides) + const_bonus(); | |
1315 | |
1316 add += max(1, increase); | |
1317 } | |
1318 | |
1319 max_stats.s_hpt += add; | |
1320 pstats.s_hpt += add; | |
1321 | |
1322 msg("Welcome, %s, to level %d.", | |
1323 cnames[player.t_ctype][min(pstats.s_lvl - 1, 14)], pstats.s_lvl); | |
1324 | |
1325 next_exp_level(MESSAGE); | |
1326 | |
1327 /* Now add new spell points and learn new spells */ | |
1328 | |
1329 nsides = 16 - nsides; | |
1330 | |
1331 for (add = 0, j = 0; j < num_jumped; j++) | |
1332 { | |
1333 int increase = roll(1, nsides) + int_wis_bonus(); | |
1334 | |
1335 add += max(1, increase); | |
1336 } | |
1337 | |
1338 max_stats.s_power += add; | |
1339 pstats.s_power += add; | |
1340 | |
1341 learn_new_spells(); | |
1342 | |
1343 /* Create a more powerful familiar (if player has one) */ | |
1344 | |
1345 if (on(player, HASFAMILIAR) && on(player, CANSUMMON)) | |
1346 summon_monster((short) 0, FAMILIAR, NOMESSAGE); | |
1347 } | |
1348 | |
1349 /* | |
1350 roll_em() | |
1351 Roll several attacks | |
1352 */ | |
1353 | |
1354 int | |
1355 roll_em(struct thing *att_er, struct thing *def_er, struct object *weap, int thrown, struct object *my_weapon) | |
1356 { | |
1357 struct stats *att = &att_er->t_stats; | |
1358 struct stats *def = &def_er->t_stats; | |
1359 int ndice, nsides, nplus, def_arm; | |
1360 char *cp; | |
1361 int prop_hplus = 0, prop_dplus = 0; | |
1362 int is_player = (att_er == &player); | |
1363 int did_hit = FALSE; | |
1364 | |
1365 if (weap == NULL) | |
1366 cp = att->s_dmg; | |
1367 else if (!thrown) | |
1368 cp = weap->o_damage; | |
1369 else if ((weap->o_flags & ISMISL) && my_weapon != NULL && | |
1370 my_weapon->o_which == weap->o_launch) | |
1371 { | |
1372 cp = weap->o_hurldmg; | |
1373 prop_hplus = my_weapon->o_hplus; | |
1374 prop_dplus = my_weapon->o_dplus; | |
1375 } | |
1376 else | |
1377 cp = (weap->o_flags & ISMISL ? weap->o_damage : | |
1378 weap->o_hurldmg); | |
1379 | |
1380 for (;;) | |
1381 { | |
1382 int damage; | |
1383 int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus); | |
1384 int dplus = prop_dplus + (weap == NULL ? 0 : weap->o_dplus); | |
1385 | |
1386 /* Is attacker weak? */ | |
1387 | |
1388 if (on(*att_er, HASSTINK)) | |
1389 hplus -= 2; | |
1390 | |
1391 if (is_player) | |
1392 { | |
1393 hplus += hitweight(); /* adjust for encumberence */ | |
1394 dplus += hung_dam(); /* adjust damage for hungry player */ | |
1395 dplus += ring_value(R_ADDDAM); | |
1396 } | |
1397 | |
1398 ndice = atoi(cp); | |
1399 | |
1400 if (cp == NULL || (cp = strchr(cp, 'd')) == NULL) | |
1401 break; | |
1402 | |
1403 nsides = atoi(++cp); | |
1404 | |
1405 if (cp != NULL && (cp = strchr(cp, '+')) != NULL) | |
1406 nplus = atoi(++cp); | |
1407 else | |
1408 nplus = 0; | |
1409 | |
1410 if (def == &pstats) | |
1411 { | |
1412 if (on(*att_er, NOMETAL) && cur_armor != NULL && | |
1413 (cur_armor->o_which == RING_MAIL || | |
1414 cur_armor->o_which == SCALE_MAIL || | |
1415 cur_armor->o_which == CHAIN_MAIL || | |
1416 cur_armor->o_which == SPLINT_MAIL || | |
1417 cur_armor->o_which == BANDED_MAIL || | |
1418 cur_armor->o_which == GOOD_CHAIN || | |
1419 cur_armor->o_which == PLATE_MAIL || | |
1420 cur_armor->o_which == PLATE_ARMOR)) | |
1421 def_arm = def->s_arm; | |
1422 else if (cur_armor != NULL) | |
1423 def_arm = cur_armor->o_ac - 10 + pstats.s_arm; | |
1424 else | |
1425 def_arm = def->s_arm; | |
1426 def_arm -= ring_value(R_PROTECT); | |
1427 } | |
1428 else | |
1429 def_arm = def->s_arm; | |
1430 | |
1431 if ((weap != NULL && weap->o_type == WEAPON && | |
1432 (weap->o_flags & ISSILVER) && | |
1433 !save_throw(VS_MAGIC, def_er)) || | |
1434 swing(att_er->t_ctype, att->s_lvl, | |
1435 def_arm - dext_prot(def->s_dext), | |
1436 hplus + str_plus(att->s_str) + dext_plus(att->s_dext))) | |
1437 { | |
1438 damage = roll(ndice, nsides) + dplus + nplus + | |
1439 add_dam(att->s_str); | |
1440 | |
1441 /* Rangers do +1/lvl vs. ISLARGE */ | |
1442 | |
1443 if (att_er->t_ctype == C_RANGER && on(*def_er, ISLARGE)) | |
1444 damage += pstats.s_lvl; | |
1445 | |
1446 /* Ninja do +1 per lvl/2 */ | |
1447 | |
1448 if (att_er->t_ctype == C_NINJA) | |
1449 damage += pstats.s_lvl / 2; | |
1450 | |
1451 /* Check for half damage monsters */ | |
1452 | |
1453 if (on(*def_er, HALFDAMAGE) && (weap != NULL) && | |
1454 !((weap->o_flags & CANBURN) && | |
1455 on(*def_er, CANBBURN))) | |
1456 damage /= 2; | |
1457 | |
1458 /* undead get twice damage from silver weapons */ | |
1459 | |
1460 if (on(*def_er, ISUNDEAD) && | |
1461 (weap != NULL) && (weap->o_flags & ISSILVER)) | |
1462 damage *= 2; | |
1463 | |
1464 /* Check for fireproof monsters */ | |
1465 | |
1466 if (on(*def_er, NOFIRE) && (weap != NULL) && | |
1467 (weap->o_flags & CANBURN)) | |
1468 damage = 0; | |
1469 | |
1470 /* Check for metal proof monsters */ | |
1471 | |
1472 if (on(*def_er, NOMETAL) && (weap != NULL) && | |
1473 (weap->o_flags & ISMETAL)) | |
1474 damage = 0; | |
1475 | |
1476 /* Check for monsters that ignore sharp weapons */ | |
1477 | |
1478 if (on(*def_er, NOSHARP) && (weap != NULL) && | |
1479 (weap->o_flags & ISSHARP)) | |
1480 damage = 0; | |
1481 | |
1482 /* Check for poisoned weapons */ | |
1483 | |
1484 if ((weap != NULL) && (weap->o_flags & ISPOISON) | |
1485 && off(*def_er, ISUNDEAD) | |
1486 && !save_throw(VS_POISON, def_er)) | |
1487 damage = max(damage, (def->s_hpt / 2) + 5); | |
1488 | |
1489 /* Check for no-damage and division */ | |
1490 | |
1491 if (on(*def_er, BLOWDIVIDE) && rnd(3) == 0 && | |
1492 !((weap != NULL) && (weap->o_flags & CANBURN))) | |
1493 { | |
1494 damage = 0; | |
1495 creat_mons(def_er, def_er->t_index, NOMESSAGE); | |
1496 } | |
1497 | |
1498 damage = max(0, damage); | |
1499 | |
1500 /* | |
1501 * sleeping monsters are backstabbed by certain | |
1502 * player classes, but only when they can see | |
1503 */ | |
1504 | |
1505 if (is_player && !thrown && damage > 0 && | |
1506 (off(*def_er, ISRUN) || def_er->t_no_move > 0) && | |
1507 (player.t_ctype == C_THIEF || | |
1508 player.t_ctype == C_NINJA || | |
1509 player.t_ctype == C_ASSASIN) && | |
1510 off(player,ISBLIND) | |
1511 && (wield_ok(&player, my_weapon, NOMESSAGE)) | |
1512 && (wear_ok(&player, cur_armor, NOMESSAGE))) | |
1513 { | |
1514 damage *= (pstats.s_lvl / 4 + 2); | |
1515 | |
1516 msg("You backstabbed the %s %d times!", | |
1517 monsters[def_er->t_index].m_name, | |
1518 (pstats.s_lvl / 4) + 2); | |
1519 | |
1520 if (player.t_ctype == C_NINJA || | |
1521 player.t_ctype == C_ASSASIN) | |
1522 pstats.s_exp += def_er->t_stats.s_exp | |
1523 / 2; | |
1524 } | |
1525 | |
1526 def->s_hpt -= damage; /* Do the damage */ | |
1527 | |
1528 debug("Hit %s for %d (%d) ", | |
1529 monsters[def_er->t_index].m_name, damage, | |
1530 def_er->t_stats.s_hpt); | |
1531 | |
1532 if (is_player && is_wearing(R_VREGEN)) | |
1533 { | |
1534 damage = (ring_value(R_VREGEN) * damage) / 3; | |
1535 pstats.s_hpt = min(max_stats.s_hpt, | |
1536 pstats.s_hpt + damage); | |
1537 } | |
1538 | |
1539 /* stun monsters when taking more than 1/3 their max hpts */ | |
1540 | |
1541 if (is_player && !thrown && !did_hit && | |
1542 (player.t_ctype == C_FIGHTER) && | |
1543 (damage > def_er->maxstats.s_hpt / 3) ) | |
1544 { | |
1545 if (def->s_hpt > 0) | |
1546 { | |
1547 msg("The %s has been stunned!", | |
1548 monsters[def_er->t_index].m_name); | |
1549 def_er->t_no_move += rnd(4) + 1; | |
1550 } | |
1551 pstats.s_exp += def_er->t_stats.s_exp / 4; | |
1552 } | |
1553 | |
1554 did_hit = TRUE; | |
1555 } | |
1556 | |
1557 if (cp == NULL || (cp = strchr(cp, '/')) == NULL) | |
1558 break; | |
1559 | |
1560 cp++; | |
1561 } | |
1562 | |
1563 return(did_hit); | |
1564 } | |
1565 | |
1566 /* | |
1567 prname() | |
1568 Figure out the monsters name | |
1569 */ | |
1570 | |
1571 const char * | |
1572 prname(char *who) | |
1573 { | |
1574 if (on(player, ISBLIND)) | |
1575 return(monstern); | |
1576 else | |
1577 return(who); | |
1578 } | |
1579 | |
1580 /* | |
1581 hit() | |
1582 Print a message to indicate a succesful hit | |
1583 */ | |
1584 | |
1585 void | |
1586 hit(char *ee) | |
1587 { | |
1588 char *s; | |
1589 | |
1590 if (fighting) | |
1591 return; | |
1592 | |
1593 switch (rnd(15)) | |
1594 { | |
1595 default: s = "hit"; break; | |
1596 case 1: s = "score an excellent hit on"; break; | |
1597 case 2: s = "injure"; break; | |
1598 case 3: s = "swing and hit"; break; | |
1599 case 4: s = "damage"; break; | |
1600 case 5: s = "barely nick"; break; | |
1601 case 6: s = "scratch"; break; | |
1602 case 7: s = "gouge a chunk out of"; break; | |
1603 case 8: s = "severely wound"; break; | |
1604 case 9: s = "counted coup on"; break; | |
1605 case 10: s = "drew blood from"; break; | |
1606 case 11: s = "nearly decapitate"; break; | |
1607 case 12: s = "deal a wacking great blow to"; break; | |
1608 } | |
1609 | |
1610 msg("You %s the %s.", s, prname(ee)); | |
1611 } | |
1612 | |
1613 /* | |
1614 miss() | |
1615 Print a message to indicate a poor swing | |
1616 */ | |
1617 | |
1618 void | |
1619 miss(char *ee) | |
1620 { | |
1621 char *s; | |
1622 | |
1623 if (fighting) | |
1624 return; | |
1625 | |
1626 switch (rnd(10)) | |
1627 { | |
1628 default: s = "miss"; break; | |
1629 case 1: s = "swing and miss"; break; | |
1630 case 2: s = "barely miss"; break; | |
1631 case 3: s = "don't hit"; break; | |
1632 case 4: s = "wildly windmill around"; break; | |
1633 case 5: s = "almost fumble while missing"; break; | |
1634 } | |
1635 | |
1636 msg("You %s the %s.", s, prname(ee)); | |
1637 } | |
1638 | |
1639 /* | |
1640 save_throw() | |
1641 See if a creature save against something | |
1642 */ | |
1643 | |
1644 int | |
1645 save_throw(int which, struct thing *tp) | |
1646 { | |
1647 int need; | |
1648 int ring_bonus = 0; | |
1649 int armor_bonus = 0; | |
1650 int class_bonus = 0; | |
1651 | |
1652 if (tp == &player) | |
1653 { | |
1654 if (player.t_ctype == C_PALADIN) | |
1655 class_bonus = 2; | |
1656 | |
1657 ring_bonus = ring_value(R_PROTECT); | |
1658 | |
1659 if (cur_armor != NULL && (which == VS_WAND || | |
1660 which == VS_MAGIC)) | |
1661 { | |
1662 if (cur_armor->o_which == MITHRIL) | |
1663 armor_bonus += 5; | |
1664 armor_bonus += (armors[cur_armor->o_which].a_class | |
1665 - cur_armor->o_ac); | |
1666 } | |
1667 } | |
1668 | |
1669 need = 14 + which - tp->t_stats.s_lvl / 2 - ring_bonus - | |
1670 armor_bonus - class_bonus; | |
1671 | |
1672 /* Roll of 1 always fails; 20 always saves */ | |
1673 | |
1674 if (need < 1) | |
1675 need = 1; | |
1676 else if (need > 20) | |
1677 need = 20; | |
1678 | |
1679 return(roll(1, 20) >= need); | |
1680 } | |
1681 | |
1682 /* | |
1683 save() | |
1684 See if he saves against various nasty things | |
1685 */ | |
1686 | |
1687 int | |
1688 save(int which) | |
1689 { | |
1690 return save_throw(which, &player); | |
1691 } | |
1692 | |
1693 /* | |
1694 dext_plus() | |
1695 compute to-hit bonus for dexterity | |
1696 */ | |
1697 | |
1698 int | |
1699 dext_plus(int dexterity) | |
1700 { | |
1701 return ((dexterity - 10) / 3); | |
1702 } | |
1703 | |
1704 /* | |
1705 * dext_prot: compute armor class bonus for dexterity | |
1706 */ | |
1707 | |
1708 int | |
1709 dext_prot(int dexterity) | |
1710 { | |
1711 return ((dexterity - 9) / 2); | |
1712 } | |
1713 | |
1714 /* | |
1715 str_plus() | |
1716 compute bonus/penalties for strength on the "to hit" roll | |
1717 */ | |
1718 | |
1719 static const int strtohit[] = | |
1720 { | |
1721 0, 0, 0, -3, -2, -2, -1, -1, | |
1722 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
1723 1, 1, 3, 3, 4, 4, 5, 6, 7 | |
1724 }; | |
1725 | |
1726 int | |
1727 str_plus(int str) | |
1728 { | |
1729 int ret_val = str; | |
1730 | |
1731 if (str < 3) | |
1732 ret_val = 3; | |
1733 else if (str > 25) | |
1734 ret_val = 25; | |
1735 | |
1736 return(strtohit[ret_val]); | |
1737 } | |
1738 | |
1739 /* | |
1740 add_dam() | |
1741 compute additional damage done for exceptionally high or low strength | |
1742 */ | |
1743 | |
1744 static const int str_damage[] = | |
1745 { | |
1746 0, 0, 0, -1, -1, -1, 0, 0, | |
1747 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
1748 1, 2, 7, 8, 9, 10, 11, 12, 14 | |
1749 }; | |
1750 | |
1751 int | |
1752 add_dam(int str) | |
1753 { | |
1754 int ret_val = str; | |
1755 | |
1756 if (str < 3) | |
1757 ret_val = 3; | |
1758 else if (str > 25) | |
1759 ret_val = 25; | |
1760 | |
1761 return(str_damage[ret_val]); | |
1762 } | |
1763 | |
1764 /* | |
1765 hung_dam() | |
1766 Calculate damage depending on players hungry state | |
1767 */ | |
1768 | |
1769 int | |
1770 hung_dam(void) | |
1771 { | |
1772 int howmuch = 0; | |
1773 | |
1774 switch (hungry_state) | |
1775 { | |
1776 case F_OK: | |
1777 case F_HUNGRY: howmuch = 0; break; | |
1778 case F_WEAK: howmuch = -1; break; | |
1779 case F_FAINT: howmuch = -2; break; | |
1780 } | |
1781 | |
1782 return(howmuch); | |
1783 } | |
1784 | |
1785 /* | |
1786 raise_level() | |
1787 The guy just magically went up a level. | |
1788 */ | |
1789 | |
1790 void | |
1791 raise_level(void) | |
1792 { | |
1793 pstats.s_exp = max_stats.s_exp; | |
1794 check_level(); | |
1795 } | |
1796 | |
1797 /* | |
1798 thunk() | |
1799 A missile hits a monster | |
1800 */ | |
1801 | |
1802 void | |
1803 thunk(struct object *weap, char *mname) | |
1804 { | |
1805 if (fighting) | |
1806 return; | |
1807 | |
1808 if (weap->o_type == WEAPON) | |
1809 msg("The %s hits the %s.", weaps[weap->o_which].w_name, prname(mname)); | |
1810 else | |
1811 msg("You hit the %s.", prname(mname)); | |
1812 } | |
1813 | |
1814 /* | |
1815 m_thunk() | |
1816 A missile from a monster hits the player | |
1817 */ | |
1818 | |
1819 void | |
1820 m_thunk(struct object *weap, char *mname) | |
1821 { | |
1822 if (fighting) | |
1823 return; | |
1824 | |
1825 if (weap != NULL && weap->o_type == WEAPON) | |
1826 msg("The %s's %s hits you.",prname(mname),weaps[weap->o_which].w_name); | |
1827 else | |
1828 msg("The %s hits you.", prname(mname)); | |
1829 } | |
1830 | |
1831 /* | |
1832 bounce() | |
1833 A missile misses a monster | |
1834 */ | |
1835 | |
1836 void | |
1837 bounce(struct object *weap, char *mname) | |
1838 { | |
1839 if (fighting) | |
1840 return; | |
1841 | |
1842 if (weap->o_type == WEAPON) | |
1843 msg("The %s misses the %s.",weaps[weap->o_which].w_name,prname(mname)); | |
1844 else | |
1845 msg("You missed the %s.", prname(mname)); | |
1846 } | |
1847 | |
1848 /* | |
1849 m_bounce() | |
1850 A missile from a monster misses the player | |
1851 */ | |
1852 | |
1853 void | |
1854 m_bounce(struct object *weap, char *mname) | |
1855 { | |
1856 if (fighting) | |
1857 return; | |
1858 | |
1859 if (weap != NULL && weap->o_type == WEAPON) | |
1860 msg("The %s's %s misses you.", prname(mname), | |
1861 weaps[weap->o_which].w_name); | |
1862 else | |
1863 msg("The %s misses you.", prname(mname)); | |
1864 } | |
1865 | |
1866 /* | |
1867 remove_monster() | |
1868 remove a monster from the screen | |
1869 */ | |
1870 | |
1871 void | |
1872 remove_monster(coord *mp, struct linked_list *item) | |
1873 { | |
1874 struct thing *tp = THINGPTR(item); | |
1875 char ch = tp->t_oldch; | |
1876 | |
1877 mvwaddch(mw, mp->y, mp->x, ' '); | |
1878 | |
1879 if (ch < 33 || ch == ' ') | |
1880 ch = CCHAR( mvwinch(stdscr, mp->y, mp->x) ); | |
1881 | |
1882 if (cansee(mp->y, mp->x)) | |
1883 mvwaddch(cw, mp->y, mp->x, ch); | |
1884 | |
1885 detach(mlist, item); | |
1886 discard(item); | |
1887 } | |
1888 | |
1889 /* | |
1890 is_magic() | |
1891 Returns true if an object radiates magic | |
1892 */ | |
1893 | |
1894 int | |
1895 is_magic(struct object *obj) | |
1896 { | |
1897 switch (obj->o_type) | |
1898 { | |
1899 case ARMOR: | |
1900 return(obj->o_ac != armors[obj->o_which].a_class); | |
1901 | |
1902 case WEAPON: | |
1903 return(obj->o_hplus != 0 || obj->o_dplus != 0); | |
1904 | |
1905 case POTION: | |
1906 case SCROLL: | |
1907 case STICK: | |
1908 case RING: | |
1909 case ARTIFACT: | |
1910 return(TRUE); | |
1911 } | |
1912 | |
1913 return(FALSE); | |
1914 } | |
1915 | |
1916 /* | |
1917 killed() | |
1918 Called to put a monster to death | |
1919 */ | |
1920 | |
1921 void | |
1922 killed(struct thing *killer, struct linked_list *item, int print_message, | |
1923 int give_points) | |
1924 { | |
1925 struct linked_list *pitem, *nitem; | |
1926 struct thing *tp = THINGPTR(item); | |
1927 int visible = cansee(tp->t_pos.y, tp->t_pos.x); | |
1928 int is_player = (killer == (&player)); | |
1929 | |
1930 if (item == curr_mons) | |
1931 curr_mons = NULL; | |
1932 else if (item == next_mons) | |
1933 next_mons = next(next_mons); | |
1934 | |
1935 if (on(*tp, WASSUMMONED)) | |
1936 { | |
1937 extinguish_fuse(FUSE_UNSUMMON); | |
1938 turn_off(player, HASSUMMONED); | |
1939 } | |
1940 | |
1941 if (print_message && visible) | |
1942 { | |
1943 if (is_player) | |
1944 addmsg("You have defeated "); | |
1945 else | |
1946 addmsg("The %s has defeated ", | |
1947 monsters[killer->t_index].m_name); | |
1948 | |
1949 if (on(player, ISBLIND)) | |
1950 msg("it."); | |
1951 else | |
1952 msg("the %s.", monsters[tp->t_index].m_name); | |
1953 } | |
1954 debug("Removing %s", monsters[tp->t_index].m_name); | |
1955 if (killer != NULL && item == fam_ptr) /* The player's familiar died */ | |
1956 { | |
1957 turn_off(player, HASFAMILIAR); | |
1958 fam_ptr = NULL; | |
1959 msg("An incredible wave of sadness sweeps over you."); | |
1960 } | |
1961 | |
1962 check_residue(tp); | |
1963 | |
1964 if (is_player) | |
1965 { | |
1966 fighting = FALSE; | |
1967 | |
1968 if (on(*tp, ISFRIENDLY)) | |
1969 { | |
1970 msg("You feel a slight chill run up and down your spine."); | |
1971 luck++; | |
1972 } | |
1973 } | |
1974 | |
1975 if (give_points) | |
1976 { | |
1977 if (killer != NULL) | |
1978 { | |
1979 killer->t_stats.s_exp += tp->t_stats.s_exp; | |
1980 | |
1981 if (on(*killer, ISFAMILIAR)) | |
1982 pstats.s_exp += tp->t_stats.s_exp; | |
1983 } | |
1984 | |
1985 if (is_player) | |
1986 { | |
1987 switch (player.t_ctype) | |
1988 { | |
1989 case C_CLERIC: | |
1990 case C_PALADIN: | |
1991 if (on(*tp, ISUNDEAD) || on(*tp, ISUNIQUE)) | |
1992 { | |
1993 pstats.s_exp += tp->t_stats.s_exp / 2; | |
1994 msg("You are to be commended for smiting the ungodly."); | |
1995 } | |
1996 break; | |
1997 | |
1998 case C_DRUID: | |
1999 case C_RANGER: | |
2000 if (on(*tp, ISLARGE)) | |
2001 { | |
2002 pstats.s_exp += tp->t_stats.s_exp / 2; | |
2003 msg("Congratulations on smiting a dangerous monster."); | |
2004 } | |
2005 break; | |
2006 | |
2007 case C_MAGICIAN: | |
2008 case C_ILLUSION: | |
2009 if (on(*tp, DRAINBRAIN)) | |
2010 { | |
2011 pstats.s_exp += tp->t_stats.s_exp / 2; | |
2012 msg("Congratulations on smiting a dangerous monster."); | |
2013 } | |
2014 | |
2015 } | |
2016 } | |
2017 check_level(); | |
2018 } | |
2019 | |
2020 /* Empty the monsters pack */ | |
2021 | |
2022 for (pitem = tp->t_pack; pitem != NULL; pitem = nitem) | |
2023 { | |
2024 struct object *obj = OBJPTR(pitem); | |
2025 | |
2026 nitem = next(pitem); | |
2027 | |
2028 obj->o_pos = tp->t_pos; | |
2029 detach(tp->t_pack, pitem); | |
2030 | |
2031 if (killer == NULL) | |
2032 discard(pitem); | |
2033 else | |
2034 fall(killer, pitem, FALSE, FALSE); | |
2035 } | |
2036 | |
2037 remove_monster(&tp->t_pos, item); | |
2038 } | |
2039 | |
2040 | |
2041 /* | |
2042 wield_weap() | |
2043 Returns a pointer to the weapon the monster is wielding corresponding to the given thrown weapon | |
2044 */ | |
2045 | |
2046 struct object * | |
2047 wield_weap(struct object *weapon, struct thing *mp) | |
2048 { | |
2049 int look_for; | |
2050 struct linked_list *pitem; | |
2051 | |
2052 if (weapon == NULL) | |
2053 return (NULL); | |
2054 | |
2055 switch (weapon->o_which) | |
2056 { | |
2057 case BOLT: | |
2058 look_for = CROSSBOW; | |
2059 break; | |
2060 | |
2061 case ARROW: | |
2062 look_for = BOW; | |
2063 break; | |
2064 | |
2065 case SILVERARROW: | |
2066 case FLAMEARROW: | |
2067 look_for = BOW; | |
2068 break; | |
2069 | |
2070 case ROCK: | |
2071 case BULLET: | |
2072 look_for = SLING; | |
2073 break; | |
2074 | |
2075 default: | |
2076 return(NULL); | |
2077 } | |
2078 | |
2079 for (pitem = mp->t_pack; pitem; pitem = next(pitem)) | |
2080 if ((OBJPTR(pitem))->o_which == look_for) | |
2081 return(OBJPTR(pitem)); | |
2082 | |
2083 return (NULL); | |
2084 } | |
2085 | |
2086 /* | |
2087 summon_help() | |
2088 Summon - see whether to summon help Returns TRUE if help comes, FALSE | |
2089 otherwise | |
2090 */ | |
2091 | |
2092 void | |
2093 summon_help(struct thing *mons, int force) | |
2094 { | |
2095 char *helpname; | |
2096 int which, i; | |
2097 char *mname = monsters[mons->t_index].m_name; | |
2098 | |
2099 /* Try to summon if less than 1/3 max hit points */ | |
2100 | |
2101 if (on(*mons, CANSUMMON) && | |
2102 (force == FORCE || | |
2103 (mons->t_stats.s_hpt < mons->maxstats.s_hpt / 3) && | |
2104 (rnd(40 * 10) < (mons->t_stats.s_lvl * mons->t_stats.s_intel)))) | |
2105 { | |
2106 turn_off(*mons, CANSUMMON); | |
2107 msg("The %s summons its attendants!", mname); | |
2108 helpname = monsters[mons->t_index].m_typesum; | |
2109 | |
2110 for (which = 1; which < nummonst; which++) | |
2111 { | |
2112 if (strcmp(helpname, monsters[which].m_name) == 0) | |
2113 break; | |
2114 } | |
2115 | |
2116 if (which >= nummonst) | |
2117 { | |
2118 debug("Couldn't find summoned one."); | |
2119 return; | |
2120 } | |
2121 | |
2122 /* summoned monster was genocided */ | |
2123 | |
2124 if (!monsters[which].m_normal) | |
2125 { | |
2126 msg("The %s becomes very annoyed at you!", mname); | |
2127 | |
2128 if (on(*mons, ISSLOW)) | |
2129 turn_off(*mons, ISSLOW); | |
2130 else | |
2131 turn_on(*mons, ISHASTE); | |
2132 | |
2133 return; | |
2134 } | |
2135 else | |
2136 for (i = 0; i < monsters[mons->t_index].m_numsum; i++) | |
2137 { | |
2138 struct linked_list *ip; | |
2139 struct thing *tp; | |
2140 | |
2141 if ((ip = creat_mons(mons, which, NOMESSAGE)) != NULL) | |
2142 { | |
2143 tp = THINGPTR(ip); | |
2144 turn_off(*tp, ISFRIENDLY); | |
2145 } | |
2146 } | |
2147 } | |
2148 | |
2149 return; | |
2150 } | |
2151 | |
2152 /* | |
2153 maxdamage() | |
2154 return the max damage a weapon can do | |
2155 */ | |
2156 | |
2157 int | |
2158 maxdamage(char *cp) | |
2159 { | |
2160 int ndice, nsides, nplus; | |
2161 | |
2162 ndice = atoi(cp); | |
2163 | |
2164 if (cp == NULL || (cp = strchr(cp, 'd')) == NULL) | |
2165 return(0); | |
2166 | |
2167 nsides = atoi(++cp); | |
2168 | |
2169 if (cp != NULL && (cp = strchr(cp, '+')) != NULL) | |
2170 nplus = atoi(++cp); | |
2171 else | |
2172 nplus = 0; | |
2173 | |
2174 return(ndice * nsides + nplus); | |
2175 } |