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!");
370 }
371 }
372 }
373 /*
374 * If can dissolve and hero has leather type armor
375 */
376 if (on(*mp, CANDISSOLVE) && cur_armor != NULL &&
377 (cur_armor->o_which == LEATHER ||
378 cur_armor->o_which == STUDDED_LEATHER ||
379 cur_armor->o_which == PADDED_ARMOR) &&
380 !(cur_armor->o_flags & ISPROT) &&
381 cur_armor->o_ac < pstats.s_arm+1) {
382 msg(terse ? "Your armor dissolves"
383 : "Your armor appears to dissolve. Oh my!");
384 cur_armor->o_ac++;
385 }
386
387 /* If a surprising monster hit you, you can see it now */
388 if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
389
390 /*
391 * If an infesting monster hits you, you get a parasite or rot
392 */
393 if (on(*mp, CANINFEST) && rnd(pstats.s_const) < mp->t_stats.s_lvl) {
394 if (ISWEARING(R_HEALTH)) msg("The wound quickly heals.");
395 else {
396 turn_off(*mp, CANINFEST);
397 msg(terse ? "You have been infested."
398 : "You have contracted a parasitic infestation!");
399 infest_dam++;
400 turn_on(player, HASINFEST);
401 }
402 }
403
404 /*
405 * Ants have poisonous bites
406 */
407 if (on(*mp, CANPOISON) && !save(VS_POISON, &player, 0)) {
408 if (ISWEARING(R_SUSABILITY))
409 msg(terse ? "Sting has no effect"
410 : "A sting momentarily weakens you");
411 else {
412 chg_str(-1);
413 msg(terse ? "A sting has weakened you" :
414 "You feel a sting in your arm and now feel weaker");
415 }
416 }
417 /*
418 * does it take wisdom away?
419 */
420 if (on(*mp, TAKEWISDOM) &&
421 !save(VS_MAGIC, &player, 0) &&
422 !ISWEARING(R_SUSABILITY)) {
423 add_wisdom(TRUE);
424 }
425 /*
426 * does it take intelligence away?
427 */
428 if (on(*mp, TAKEINTEL) &&
429 !save(VS_MAGIC, &player, 0) &&
430 !ISWEARING(R_SUSABILITY)) {
431 add_intelligence(TRUE);
432 }
433 /*
434 * Cause fear by touching
435 */
436 if (on(*mp, TOUCHFEAR)) {
437 turn_off(*mp, TOUCHFEAR);
438 if (!ISWEARING(R_HEROISM) &&
439 !save(VS_WAND, &player, 0) &&
440 !(on(player, ISFLEE) && (player.t_dest == &mp->t_pos))) {
441 turn_on(player, ISFLEE);
442 player.t_dest = &mp->t_pos;
443 msg("The %s's touch terrifies you.", mname);
444 }
445 }
446
447 /*
448 * make the hero dance (as in otto's irresistable dance)
449 */
450 if (on(*mp, CANDANCE) &&
451 !on(player, ISDANCE) &&
452 !save(VS_MAGIC, &player, -4)) {
453 turn_off(*mp, CANDANCE);
454 turn_on(player, ISDANCE);
455 msg("You begin to dance uncontrollably!");
456 fuse(undance, 0, roll(2,4), AFTER);
457 }
458
459 /*
460 * Suffocating our hero
461 */
462 if (on(*mp, CANSUFFOCATE) && (rnd(100) < 15) &&
463 (find_slot(suffocate) == FALSE)) {
464 turn_on(*mp, DIDSUFFOCATE);
465 msg("The %s is beginning to suffocate you.", mname);
466 fuse(suffocate, 0, roll(4,2), AFTER);
467 }
468
469 /*
470 * Turning to stone
471 */
472 if (on(*mp, TOUCHSTONE)) {
473 turn_off(*mp, TOUCHSTONE);
474 if (on(player, CANINWALL))
475 msg("The %s's touch has no effect.", mname);
476 else {
477 if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 15) {
478 msg("Your body begins to solidify.");
479 msg("You are turned to stone !!! --More--");
480 wait_for(cw,' ');
481 death(D_PETRIFY);
482 }
483 else {
484 msg("The %s's touch stiffens your limbs.", mname);
485 no_command += STONETIME;
486 }
487 }
488 }
489
490 /*
491 * Wraiths might drain energy levels
492 */
493 if ((on(*mp, CANDRAIN) || on(*mp, DOUBLEDRAIN)) && rnd(100) < 15) {
494 lower_level(mp->t_index);
495 if (on(*mp, DOUBLEDRAIN)) lower_level(mp->t_index);
496 turn_on(*mp, DIDDRAIN);
497 }
498
499 /*
500 * Violet fungi stops the poor guy from moving
501 */
502 if (on(*mp, CANHOLD) && off(*mp, DIDHOLD)) {
503 turn_on(player, ISHELD);
504 turn_on(*mp, DIDHOLD);
505 hold_count++;
506 }
507
508 /*
509 * Sucker will suck blood and run
510 */
511 if (on(*mp, CANDRAW)) {
512 turn_off(*mp, CANDRAW);
513 turn_on(*mp, ISFLEE);
514 msg("The %s sates itself with your blood.", mname);
515 if ((pstats.s_hpt -= 12) <= 0) death(mp->t_index);
516 }
517
518 /*
519 * Bad smell will force a reduction in strength
520 */
521 if (on(*mp, CANSMELL)) {
522 turn_off(*mp, CANSMELL);
523 if (save(VS_MAGIC, &player, 0) || ISWEARING(R_SUSABILITY))
524 msg("You smell an unpleasant odor.");
525 else {
526 int odor_str = -(rnd(6)+1);
527
528 msg("You are overcome by a foul odor.");
529 if (lost_str == 0) {
530 chg_str(odor_str);
531 fuse(res_strength, 0, SMELLTIME, AFTER);
532 lost_str -= odor_str;
533 }
534 else lengthen(res_strength, SMELLTIME);
535 }
536 }
537
538 /*
539 * Paralyzation
540 */
541 if (on(*mp, CANPARALYZE)) {
542 turn_off(*mp, CANPARALYZE);
543 if (!save(VS_PARALYZATION, &player, 0)) {
544 if (on(player, CANINWALL))
545 msg("The %s's touch has no effect.", mname);
546 else {
547 msg("The %s's touch paralyzes you.", mname);
548 no_command += FREEZETIME;
549 }
550 }
551 }
552
553 /*
554 * Painful wounds make you faint
555 */
556 if (on(*mp, CANPAIN)) {
557 turn_off(*mp, CANPAIN);
558 if (!ISWEARING(R_ALERT) && !save(VS_POISON, &player, 0)) {
559 msg("You faint from the painful wound");
560 no_command += PAINTIME;
561 }
562 }
563
564 /*
565 * The monsters touch slows the hero down
566 */
567 if (on(*mp, CANSLOW)) {
568 turn_off(*mp, CANSLOW);
569 if (!save(VS_PARALYZATION, &player, 0))
570 add_slow();
571 }
572
573 /*
574 * Rotting
575 */
576 if (on(*mp, CANROT)) {
577 if (!ISWEARING(R_HEALTH) &&
578 !save(VS_POISON, &player, 0) &&
579 off(player, DOROT)) {
580 turn_on(player, DOROT);
581 msg("You feel your skin starting to rot away!");
582 }
583 }
584
585 if (on(*mp, STEALGOLD)) {
586 /*
587 * steal some gold
588 */
589 register long lastpurse;
590 register struct linked_list *item;
591 register struct object *obj;
592
593 lastpurse = purse;
594 purse -= GOLDCALC + GOLDCALC;
595 if (!save(VS_MAGIC, &player, mp->t_stats.s_lvl/10)) {
596 if (on(*mp, ISUNIQUE))
597 purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
598 purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
599 }
600 if (purse < 0)
601 purse = 0;
602 if (purse != lastpurse) {
603 msg("Your purse feels lighter");
604
605 /* Give the gold to the thief */
606 for (item=mp->t_pack; item != NULL; item=next(item)) {
607 obj = OBJPTR(item);
608 if (obj->o_type == GOLD) {
609 obj->o_count += lastpurse - purse;
610 break;
611 }
612 }
613
614 /* Did we do it? */
615 if (item == NULL) { /* Then make some */
616 item = new_item(sizeof *obj);
617 obj = OBJPTR(item);
618 obj->o_type = GOLD;
619 obj->o_count = lastpurse - purse;
620 obj->o_hplus = obj->o_dplus = 0;
621 strcpy(obj->o_damage,"0d0");
622 strcpy(obj->o_hurldmg,"0d0");
623 obj->o_ac = 11;
624 obj->contents = NULL;
625 obj->o_group = 0;
626 obj->o_flags = 0;
627 obj->o_mark[0] = '\0';
628 obj->o_pos = mp->t_pos;
629
630 attach(mp->t_pack, item);
631 }
632 }
633
634 turn_on(*mp, ISFLEE);
635 turn_on(*mp, ISINVIS);
636 }
637
638 if (on(*mp, STEALMAGIC)) {
639 register struct linked_list *list, *steal;
640 register struct object *obj;
641 register int nobj;
642
643 /*
644 * steal a magic item, look through the pack
645 * and pick out one we like.
646 */
647 steal = NULL;
648 for (nobj = 0, list = pack; list != NULL; list = next(list))
649 {
650 obj = OBJPTR(list);
651 if (!is_current(obj) &&
652 is_magic(obj) &&
653 rnd(++nobj) == 0)
654 steal = list;
655 }
656 if (steal != NULL)
657 {
658 register struct object *obj;
659 struct linked_list *item;
660
661 obj = OBJPTR(steal);
662 if (on(*mp, ISUNIQUE))
663 monsters[mp->t_index].m_normal = TRUE;
664 item = find_mons(mp->t_pos.y, mp->t_pos.x);
665 killed(item, FALSE, FALSE);
666 if (obj->o_count > 1 && obj->o_group == 0) {
667 register int oc;
668
669 oc = --(obj->o_count);
670 obj->o_count = 1;
671 sprintf(outstring,"The %s stole %s!", mname, inv_name(obj, TRUE));
672 msg(outstring);
673 obj->o_count = oc;
674 }
675 else {
676 sprintf(outstring,"The %s stole %s!", mname, inv_name(obj, TRUE));
677 msg(outstring);
678 detach(pack, steal);
679
680 /* If this is a relic, clear its holding field */
681 if (obj->o_type == RELIC)
682 cur_relic[obj->o_which] = 0;
683
684 o_discard(steal);
685 inpack--;
686 }
687 updpack(FALSE);
688 }
689 }
690 }
691 }
692 else {
693 /* If the thing was trying to surprise, no good */
694 if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
695
696 else if (thrown) m_bounce(weapon, mp, mname);
697 else miss(weapon, mp, mname, NULL);
698 }
699 if (fight_flush)
700 md_flushinp();
701 count = 0;
702 status(FALSE);
703 return(did_hit);
704 }
705
706 /*
707 * swing:
708 * returns true if the swing hits
709 */
710
711 swing(class, at_lvl, op_arm, wplus)
712 short class;
713 int at_lvl, op_arm, wplus;
714 {
715 register int res = rnd(20)+1;
716 register int need;
717
718 need = att_mat[class].base -
719 att_mat[class].factor *
720 ((min(at_lvl, att_mat[class].max_lvl) -
721 att_mat[class].offset)/att_mat[class].range) +
722 (10 - op_arm);
723 if (need > 20 && need <= 25) need = 20;
724
725 return (res+wplus >= need);
726 }
727
728 /*
729 * roll_em:
730 * Roll several attacks
731 */
732
733 roll_em(att_er, def_er, weap, hurl, cur_weapon, back_stab)
734 struct thing *att_er, *def_er;
735 struct object *weap;
736 bool hurl;
737 struct object *cur_weapon;
738 bool back_stab;
739 {
740 register struct stats *att, *def;
741 register char *cp = NULL;
742 register int ndice, nsides, nplus, def_arm;
743 bool did_hit = FALSE;
744 int prop_hplus, prop_dplus;
745 int vampiric_damage;
746
747 /* Get statistics */
748 att = &att_er->t_stats;
749 def = &def_er->t_stats;
750
751 prop_hplus = prop_dplus = 0;
752 if (weap == NULL)
753 cp = att->s_dmg;
754 else if (hurl) {
755 if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
756 cur_weapon->o_which == weap->o_launch)
757 {
758 cp = weap->o_hurldmg;
759 prop_hplus = cur_weapon->o_hplus;
760 prop_dplus = cur_weapon->o_dplus;
761 }
762 else
763 cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg);
764 }
765 else {
766 if (weap->o_type == RELIC) {
767 switch (weap->o_which) {
768 case MUSTY_DAGGER: cp = "1d4+1/1d4+1";
769 when YEENOGHU_FLAIL: cp = "3d6/paralyze/confuse";
770 when HRUGGEK_MSTAR: cp = "3d10";
771 when MING_STAFF: cp = "1d8";
772 when ASMO_ROD: cp = "2d8+1";
773 when ORCUS_WAND: cp = "destroy";
774 }
775 }
776 else cp = weap->o_damage;
777 /*
778 * Drain a staff of striking
779 */
780 if (weap->o_type == STICK && weap->o_which == WS_HIT
781 && weap->o_charges == 0)
782 {
783 strcpy(weap->o_damage,"0d0");
784 weap->o_hplus = weap->o_dplus = 0;
785 }
786 }
787 for (;;)
788 {
789 int damage;
790 int hplus = prop_hplus;
791 int dplus = prop_dplus;
792
793 if (weap != NULL && weap->o_type == RELIC) {
794 switch (weap->o_which) {
795 case MUSTY_DAGGER:
796 if (att != &pstats || /* Not player or good stats */
797 (str_compute() > 15 && dex_compute() > 15)) {
798
799 hplus += 6;
800 dplus += 6;
801
802 /* Give an additional strength and dex bonus */
803 if (att == &pstats) {
804 hplus += str_plus(str_compute()) +
805 dext_plus(dex_compute());
806 dplus += dext_plus(dex_compute()) +
807 add_dam(str_compute());
808 }
809 else {
810 hplus += str_plus(att->s_str) +
811 dext_plus(att->s_dext);
812 dplus += dext_plus(att->s_dext) +
813 add_dam(att->s_str);
814 }
815 }
816 else {
817 hplus -= 3;
818 dplus -= 3;
819 }
820 when YEENOGHU_FLAIL:
821 case HRUGGEK_MSTAR:
822 hplus += 3;
823 dplus += 3;
824 when MING_STAFF:
825 hplus += 2;
826 dplus += 2;
827 }
828 }
829 else if (weap != NULL) {
830 hplus += weap->o_hplus;
831 dplus += weap->o_dplus;
832 }
833
834 /* Is attacker weak? */
835 if (on(*att_er, HASSTINK)) hplus -= 2;
836
837 if (att == &pstats) /* Is the attacker the player? */
838 {
839 hplus += hitweight(); /* adjust for encumberence */
840 dplus += hung_dam(); /* adjust damage for hungry player */
841 dplus += ring_value(R_ADDDAM);
842 }
843 if (back_stab || (weap && att != &pstats && on(*att_er, CANBSTAB)))
844 hplus += 4; /* add in pluses for backstabbing */
845
846 /* Get the damage */
847 while (isspace(*cp)) cp++;
848 if (!isdigit(*cp)) {
849 if (strncmp(cp, "confuse", 7) == 0) ndice = CONF_DAMAGE;
850 else if (strncmp(cp, "paralyze", 8) == 0) ndice = PARAL_DAMAGE;
851 else if (strncmp(cp, "destroy", 7) == 0) ndice = DEST_DAMAGE;
852 else ndice = 0;
853 nsides = 0;
854 nplus = 0;
855 }
856 else {
857 char *oldcp;
858
859 /* Get the number of damage dice */
860 ndice = atoi(cp);
861 if ((cp = strchr(cp, 'd')) == NULL)
862 break;
863
864 /* Skip the 'd' and get the number of sides per die */
865 nsides = atoi(++cp);
866
867 /* Check for an addition -- save old place in case none is found */
868 oldcp = cp;
869 if ((cp = strchr(cp, '+')) != NULL) nplus = atoi(++cp);
870 else {
871 nplus = 0;
872 cp = oldcp;
873 }
874 }
875
876 if (def == &pstats) { /* Monster attacks player */
877 def_arm = ac_compute() - dext_prot(dex_compute());
878 hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
879 }
880 else { /* Player attacks monster */
881 def_arm = def->s_arm - dext_prot(def->s_dext);
882 hplus += str_plus(str_compute())+dext_plus(dex_compute());
883 }
884
885 if (swing(att_er->t_ctype, att->s_lvl, def_arm, hplus)) {
886 register int proll;
887
888 /* Take care of special effects */
889 switch (ndice) {
890 case CONF_DAMAGE:
891 if (def == &pstats) { /* Monster attacks player */
892 if (!save(VS_MAGIC, &player, 0) && off(player, ISCLEAR)) {
893 msg("You feel disoriented.");
894 if (find_slot(unconfuse))
895 lengthen(unconfuse, rnd(8)+HUHDURATION);
896 else
897 fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
898 turn_on(player, ISHUH);
899 }
900 else msg("You feel dizzy, but it quickly passes.");
901 }
902 /* Player hits monster */
903 else if (!save(VS_MAGIC, def_er, 0) && off(*def_er, ISCLEAR)) {
904 msg("The artifact warms with pleasure.");
905 turn_on(*def_er, ISHUH);
906 }
907 did_hit = TRUE;
908 when PARAL_DAMAGE:
909 if (def == &pstats) { /* Monster attacks player */
910 if (!save(VS_MAGIC, &player, 0) && off(player, CANINWALL)) {
911 msg("You stiffen up.");
912 no_command += FREEZETIME;
913 }
914 }
915 else if (!save(VS_MAGIC, def_er, 0)) { /* Player hits monster */
916 msg("The artifact hums happily.");
917 turn_off(*def_er, ISRUN);
918 turn_on(*def_er, ISHELD);
919 }
920 did_hit = TRUE;
921 when DEST_DAMAGE:
922 if (def == &pstats) { /* Monster attacks player */
923 msg("You feel a tug at your life force.");
924 if (!save(VS_MAGIC, &player, -4)) {
925 msg("The wand devours your soul.");
926 def->s_hpt = 0;
927 }
928 }
929 /* Player hits monster */
930 else if (!save(VS_MAGIC, def_er, -4)) {
931 msg("The artifact draws energy.");
932
933 /* Give the player half the monster's hits */
934 att->s_hpt += def->s_hpt/2;
935 if (att->s_hpt > att_er->maxstats.s_hpt)
936 att->s_hpt = att_er->maxstats.s_hpt;
937
938 /* Kill the monster */
939 def->s_hpt = 0;
940 }
941 did_hit = TRUE;
942 otherwise:
943 /* Heil's ankh always gives maximum damage */
944 if (att == &pstats && cur_relic[HEIL_ANKH])
945 proll = ndice * nsides;
946 else proll = roll(ndice, nsides);
947
948 if (ndice + nsides > 0 && proll < 1)
949 debug("Damage for %dd%d came out %d.",
950 ndice, nsides, proll);
951 damage = dplus + proll + nplus;
952 if (def == &pstats)
953 damage += add_dam(att->s_str);
954 else
955 damage += add_dam(str_compute());
956
957 /* Check for half damage monsters */
958 if (on(*def_er, HALFDAMAGE)) damage /= 2;
959
960 /* add in multipliers for backstabbing */
961 if (back_stab ||
962 (weap && att != &pstats && on(*att_er, CANBSTAB))) {
963 int mult = 2 + (att->s_lvl-1)/4; /* Normal multiplier */
964
965 if (mult > 5 && att != &pstats)
966 mult = 5;/*be nice with maximum of 5x for monsters*/
967 if (weap->o_type == RELIC && weap->o_which == MUSTY_DAGGER)
968 mult++;
969 damage *= mult;
970 }
971
972 /* Check for no-damage and division */
973 if (on(*def_er, BLOWDIVIDE)) {
974 damage = 0;
975 creat_mons(def_er, def_er->t_index, FALSE);
976 light(&hero);
977 }
978 /* check for immunity to metal -- RELICS are always bad */
979 if (on(*def_er, NOMETAL) && weap != NULL &&
980 weap->o_type != RELIC && weap->o_flags & ISMETAL) {
981 damage = 0;
982 }
983
984 /*
985 * If defender is wearing a cloak of displacement -- no damage
986 * the first time. (unless its a hurled magic missile)
987 */
988 if ( ((weap == NULL) || weap->o_type != MISSILE) &&
989 def == &pstats &&
990 cur_misc[WEAR_CLOAK] != NULL &&
991 cur_misc[WEAR_CLOAK]->o_which == MM_DISP &&
992 off(*att_er, MISSEDDISP)) {
993 damage = 0;
994 did_hit = FALSE;
995 turn_on(*att_er, MISSEDDISP);
996 if (cansee(att_er->t_pos.y, att_er->t_pos.x) &&
997 !invisible(att_er))
998 msg("The %s looks amazed",
999 monsters[att_er->t_index].m_name);
1000 }
1001 else {
1002 def->s_hpt -= max(0, damage); /* Do the damage */
1003 did_hit = TRUE;
1004 }
1005
1006 vampiric_damage = damage;
1007 if (def->s_hpt < 0) /* only want REAL damage inflicted */
1008 vampiric_damage += def->s_hpt;
1009 if (vampiric_damage < 0)
1010 vampiric_damage = 0;
1011 if (att == &pstats && ISWEARING(R_VAMPREGEN) && !hurl) {
1012 if ((pstats.s_hpt += vampiric_damage/2) > max_stats.s_hpt)
1013 pstats.s_hpt = max_stats.s_hpt;
1014 }
1015 debug ("hplus=%d dmg=%d", hplus, damage);
1016 }
1017 }
1018 if ((cp = strchr(cp, '/')) == NULL)
1019 break;
1020 cp++;
1021 }
1022 return did_hit;
1023 }
1024
1025 /*
1026 * prname:
1027 * The print name of a combatant
1028 */
1029
1030 char *
1031 prname(who, upper)
1032 register char *who;
1033 bool upper;
1034 {
1035 static char tbuf[LINELEN];
1036
1037 *tbuf = '\0';
1038 if (who == 0)
1039 strcpy(tbuf, "you");
1040 else if (on(player, ISBLIND))
1041 strcpy(tbuf, "it");
1042 else
1043 {
1044 strcpy(tbuf, "the ");
1045 strcat(tbuf, who);
1046 }
1047 if (upper)
1048 *tbuf = toupper(*tbuf);
1049 return tbuf;
1050 }
1051
1052 /*
1053 * hit:
1054 * Print a message to indicate a succesful hit
1055 */
1056
1057 hit(weapon, tp, er, ee, back_stab)
1058 register struct object *weapon;
1059 register struct thing *tp;
1060 register char *er, *ee;
1061 bool back_stab;
1062 {
1063 register char *s = NULL;
1064 char
1065 att_name[80], /* Name of attacker */
1066 def_name[80];/* Name of defender */
1067 bool see_monst = !invisible(tp); /* Can the player see the monster? */
1068
1069 /* What do we call the attacker? */
1070 if (er == NULL) { /* Player is attacking */
1071 strcpy(att_name, prname(er, TRUE));
1072 strcpy(def_name, see_monst ? prname(ee, FALSE) : "something");
1073 }
1074 else {
1075 strcpy(att_name, see_monst ? prname(er, TRUE) : "Something");
1076
1077 /* If the monster is using a weapon and we can see it, report it */
1078 if (weapon != NULL && see_monst) {
1079 strcat(att_name, "'s ");
1080 strcat(att_name, weap_name(weapon));
1081 }
1082
1083 strcpy(def_name, prname(ee, FALSE));
1084 }
1085
1086 addmsg(att_name);
1087 if (terse) {
1088 if (back_stab)
1089 s = " backstab!";
1090 else
1091 s = " hit.";
1092 }
1093 else {
1094 if (back_stab)
1095 s = (er == 0 ? " have backstabbed " : " has backstabbed ");
1096 else {
1097 switch (rnd(4))
1098 {
1099 case 0: s = " scored an excellent hit on ";
1100 when 1: s = " hit ";
1101 when 2: s = (er == 0 ? " have injured " : " has injured ");
1102 when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");
1103 }
1104 }
1105 }
1106 addmsg(s);
1107 if (!terse)
1108 addmsg(def_name);
1109 endmsg();
1110 }
1111
1112 /*
1113 * miss:
1114 * Print a message to indicate a poor swing
1115 */
1116
1117 miss(weapon, tp, er, ee)
1118 register struct object *weapon;
1119 register struct thing *tp;
1120 register char *er, *ee;
1121 {
1122 register char *s = NULL;
1123 char
1124 att_name[80], /* Name of attacker */
1125 def_name[80];/* Name of defender */
1126 bool see_monst = !invisible(tp); /* Can the player see the monster? */
1127
1128 /* What do we call the attacker? */
1129 if (er == NULL) { /* Player is attacking */
1130 strcpy(att_name, prname(er, TRUE));
1131 strcpy(def_name, see_monst ? prname(ee, FALSE) : "something");
1132 }
1133 else {
1134 strcpy(att_name, see_monst ? prname(er, TRUE) : "Something");
1135
1136 /* If the monster is using a weapon and we can see it, report it */
1137 if (weapon != NULL && see_monst) {
1138 strcat(att_name, "'s ");
1139 strcat(att_name, weap_name(weapon));
1140 }
1141
1142 strcpy(def_name, prname(ee, FALSE));
1143 }
1144
1145 addmsg(att_name);
1146 switch (terse ? 0 : rnd(4))
1147 {
1148 case 0: s = (er == 0 ? " miss" : " misses");
1149 when 1: s = (er == 0 ? " swing and miss" : " swings and misses");
1150 when 2: s = (er == 0 ? " barely miss" : " barely misses");
1151 when 3: s = (er == 0 ? " don't hit" : " doesn't hit");
1152 }
1153 addmsg(s);
1154 if (!terse)
1155 addmsg(" %s", def_name);
1156 endmsg();
1157 }
1158
1159 /*
1160 * dext_plus:
1161 * compute to-hit bonus for dexterity
1162 */
1163
1164 dext_plus(dexterity)
1165 register int dexterity;
1166 {
1167 return (dexterity > 10 ? (dexterity-13)/3 : (dexterity-10)/3);
1168 }
1169
1170
1171 /*
1172 * dext_prot:
1173 * compute armor class bonus for dexterity
1174 */
1175
1176 dext_prot(dexterity)
1177 register int dexterity;
1178 {
1179 return ((dexterity-10)/2);
1180 }
1181 /*
1182 * str_plus:
1183 * compute bonus/penalties for strength on the "to hit" roll
1184 */
1185
1186 str_plus(str)
1187 register short str;
1188 {
1189 return((str-10)/3);
1190 }
1191
1192 /*
1193 * add_dam:
1194 * compute additional damage done for exceptionally high or low strength
1195 */
1196
1197 add_dam(str)
1198 register short str;
1199 {
1200 return((str-9)/2);
1201 }
1202
1203 /*
1204 * hung_dam:
1205 * Calculate damage depending on players hungry state
1206 */
1207 hung_dam()
1208 {
1209 reg int howmuch = 0;
1210
1211 switch(hungry_state) {
1212 case F_OKAY:
1213 case F_HUNGRY: howmuch = 0;
1214 when F_WEAK: howmuch = -1;
1215 when F_FAINT: howmuch = -2;
1216 }
1217 return howmuch;
1218 }
1219
1220 /*
1221 * thunk:
1222 * A missile hits a monster
1223 */
1224
1225 thunk(weap, tp, mname)
1226 register struct object *weap;
1227 register struct thing *tp; /* Defender */
1228 register char *mname;
1229 {
1230 char *def_name; /* Name of defender */
1231
1232 /* What do we call the defender? */
1233 if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
1234 def_name = "something";
1235 else def_name = prname(mname, FALSE);
1236
1237 if (weap->o_type == WEAPON){
1238 sprintf(outstring,"The %s hits %s", weaps[weap->o_which].w_name, def_name);
1239 msg(outstring);
1240 }
1241 else if (weap->o_type == MISSILE){
1242 sprintf(outstring,"The %s hits %s",ws_magic[weap->o_which].mi_name, def_name);
1243 msg(outstring);
1244 }
1245 else
1246 msg("You hit %s.", def_name);
1247 }
1248
1249 /*
1250 * mthunk:
1251 * A missile from a monster hits the player
1252 */
1253
1254 m_thunk(weap, tp, mname)
1255 register struct object *weap;
1256 register struct thing *tp;
1257 register char *mname;
1258 {
1259 char *att_name; /* Name of attacker */
1260
1261 /* What do we call the attacker? */
1262 if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
1263 att_name = "Something";
1264 else att_name = prname(mname, TRUE);
1265
1266 if (weap->o_type == WEAPON){
1267 sprintf(outstring,"%s's %s hits you.", att_name, weaps[weap->o_which].w_name);
1268 msg(outstring);
1269 }
1270 else if (weap->o_type == MISSILE){
1271 sprintf(outstring,"%s's %s hits you.", att_name, ws_magic[weap->o_which].mi_name);
1272 msg(outstring);
1273 }
1274 else
1275 msg("%s hits you.", att_name);
1276 }
1277
1278 /*
1279 * bounce:
1280 * A missile misses a monster
1281 */
1282
1283 bounce(weap, tp, mname)
1284 register struct object *weap;
1285 register struct thing *tp; /* Defender */
1286 register char *mname;
1287 {
1288 char *def_name; /* Name of defender */
1289
1290 /* What do we call the defender? */
1291 if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
1292 def_name = "something";
1293 else def_name = prname(mname, FALSE);
1294
1295 if (weap->o_type == WEAPON){
1296 sprintf(outstring,"The %s misses %s",weaps[weap->o_which].w_name, def_name);
1297 msg(outstring);
1298 }
1299 else if (weap->o_type == MISSILE){
1300 sprintf(outstring,"The %s misses %s",ws_magic[weap->o_which].mi_name, def_name);
1301 msg(outstring);
1302 }
1303 else
1304 msg("You missed %s.", def_name);
1305 }
1306
1307 /*
1308 * m_bounce:
1309 A missle from a monster misses the player
1310 */
1311
1312 m_bounce(weap, tp, mname)
1313 register struct object *weap;
1314 register struct thing *tp;
1315 register char *mname;
1316 {
1317 char *att_name; /* Name of attacker */
1318
1319 /* What do we call the attacker? */
1320 if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
1321 att_name = "Something";
1322 else att_name = prname(mname, TRUE);
1323
1324 if (weap->o_type == WEAPON){
1325 sprintf(outstring,"%s's %s misses you.", att_name, weaps[weap->o_which].w_name);
1326 msg(outstring);
1327 }
1328 else if (weap->o_type == MISSILE){
1329 sprintf(outstring,"%s's %s misses you.", att_name, ws_magic[weap->o_which].mi_name);
1330 msg(outstring);
1331 }
1332 else
1333 msg("%s misses you.", att_name);
1334 }
1335
1336
1337 /*
1338 * is_magic:
1339 * Returns true if an object radiates magic
1340 */
1341
1342 is_magic(obj)
1343 register struct object *obj;
1344 {
1345 switch (obj->o_type)
1346 {
1347 case ARMOR:
1348 return obj->o_ac != armors[obj->o_which].a_class;
1349 when WEAPON:
1350 return obj->o_hplus != 0 || obj->o_dplus != 0;
1351 when POTION:
1352 case SCROLL:
1353 case STICK:
1354 case RING:
1355 case MM:
1356 case RELIC:
1357 return TRUE;
1358 }
1359 return FALSE;
1360 }
1361
1362 /*
1363 * killed:
1364 * Called to put a monster to death
1365 */
1366
1367 killed(item, pr, points)
1368 register struct linked_list *item;
1369 bool pr, points;
1370 {
1371 register struct thing *tp;
1372 register struct linked_list *pitem, *nexti;
1373 const char *monst;
1374
1375 tp = THINGPTR(item);
1376
1377 if (pr)
1378 {
1379 addmsg(terse ? "Defeated " : "You have defeated ");
1380 if (on(player, ISBLIND))
1381 msg("it.");
1382 else
1383 {
1384 if (cansee(tp->t_pos.y, tp->t_pos.x) && !invisible(tp))
1385 monst = monsters[tp->t_index].m_name;
1386 else {
1387 if (terse) monst = "something";
1388 else monst = "thing";
1389 }
1390 if (!terse)
1391 addmsg("the ");
1392 msg("%s.", monst);
1393 }
1394 }
1395
1396 /* Take care of any residual effects of the monster */
1397 check_residue(tp);
1398
1399 if (points) {
1400 unsigned long test; /* For overflow check */
1401
1402 test = pstats.s_exp + tp->t_stats.s_exp;
1403
1404 /* Do an overflow check before increasing experience */
1405 if (test > pstats.s_exp) pstats.s_exp = test;
1406
1407 /*
1408 * Do adjustments if he went up a level
1409 */
1410 check_level(TRUE);
1411 }
1412
1413 /*
1414 * Empty the monsters pack
1415 */
1416 pitem = tp->t_pack;
1417
1418 /*
1419 * Get rid of the monster.
1420 */
1421 mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' ');
1422 mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
1423 detach(mlist, item);
1424 /*
1425 * empty his pack
1426 */
1427 while (pitem != NULL)
1428 {
1429 nexti = next(tp->t_pack);
1430 (OBJPTR(pitem))->o_pos = tp->t_pos;
1431 detach(tp->t_pack, pitem);
1432 if (points)
1433 fall(pitem, FALSE);
1434 else
1435 o_discard(pitem);
1436 pitem = nexti;
1437 }
1438 turn_on(*tp, ISDEAD);
1439 attach(monst_dead, item);
1440 }
1441
1442
1443 /*
1444 * Returns a pointer to the weapon the monster is wielding corresponding to
1445 * the given thrown weapon. If no thrown item is given, try to find any
1446 * decent weapon.
1447 */
1448
1449 struct object *
1450 wield_weap(thrown, mp)
1451 struct object *thrown;
1452 struct thing *mp;
1453 {
1454 int look_for = 0, /* The projectile weapon we are looking for */
1455 new_rate, /* The rating of a prospective weapon */
1456 cand_rate = -1; /* Rating of current candidate -- higher is better */
1457 register struct linked_list *pitem;
1458 register struct object *obj, *candidate = NULL;
1459
1460 if (thrown != NULL) { /* Using a projectile weapon */
1461 switch (thrown->o_which) {
1462 case BOLT: look_for = CROSSBOW; /* Find the crossbow */
1463 when ARROW: look_for = BOW; /* Find the bow */
1464 when ROCK: look_for = SLING; /* find the sling */
1465 otherwise: return(NULL);
1466 }
1467 }
1468 else if (off(*mp, ISUNIQUE) && off(*mp, CARRYWEAPON)) return(NULL);
1469
1470 for (pitem=mp->t_pack; pitem; pitem=next(pitem)) {
1471 obj = OBJPTR(pitem);
1472
1473 /*
1474 * If we have a thrown weapon, just return the first match
1475 * we come to.
1476 */
1477 if (thrown != NULL && obj->o_type == WEAPON && obj->o_which == look_for)
1478 return(obj);
1479
1480 /* If we have a usable RELIC, return it */
1481 if (thrown == NULL && obj->o_type == RELIC) {
1482 switch (obj->o_which) {
1483 case MUSTY_DAGGER:
1484 case YEENOGHU_FLAIL:
1485 case HRUGGEK_MSTAR:
1486 case MING_STAFF:
1487 case ASMO_ROD:
1488 case ORCUS_WAND:
1489 return(obj);
1490 }
1491 }
1492
1493 /* Otherwise if it's a usable weapon, it is a good candidate */
1494 else if (thrown == NULL && obj->o_type == WEAPON) {
1495 switch (obj->o_which) {
1496 case DAGGER:
1497 new_rate = 0;
1498 when BATTLEAXE:
1499 new_rate = 1;
1500 when MACE:
1501 new_rate = 2;
1502 when SWORD:
1503 new_rate = 3;
1504 when PIKE:
1505 new_rate = 4;
1506 when HALBERD:
1507 case SPETUM:
1508 new_rate = 6;
1509 when BARDICHE:
1510 new_rate = 7;
1511 when TRIDENT:
1512 new_rate = 8;
1513 when BASWORD:
1514 new_rate = 9;
1515 when TWOSWORD:
1516 new_rate = 10;
1517 otherwise:
1518 new_rate = -1;
1519 }
1520
1521 /* Only switch if this is better than the current candidate */
1522 if (new_rate > cand_rate) {
1523 cand_rate = new_rate;
1524 candidate = obj;
1525 }
1526 }
1527 }
1528
1529 return(candidate);
1530 }
1531
1532 explode(tp)
1533 register struct thing *tp;
1534 {
1535
1536 register int x,y, damage;
1537 struct linked_list *item;
1538 struct thing *th;
1539
1540 msg("the %s explodes!", monsters[tp->t_index].m_name);
1541 /*
1542 * check to see if it got the hero
1543 */
1544 if (DISTANCE(hero.x, hero.y, tp->t_pos.x, tp->t_pos.y) <= 25) {
1545 msg("the explosion hits you");
1546 damage = roll(6,6);
1547 if (save(VS_WAND, &player, 0))
1548 damage /= 2;
1549 if ((pstats.s_hpt -= damage) <= 0)
1550 death(tp->t_index);
1551 }
1552
1553 /*
1554 * now check for monsters in vicinity
1555 */
1556 for (x = tp->t_pos.x-5; x<=tp->t_pos.x+5; x++) {
1557 if (x < 0 || x > COLS - 1)
1558 continue;
1559 for (y = tp->t_pos.y-5; y<=tp->t_pos.y+5; y++) {
1560 if (y < 1 || y > LINES - 3)
1561 continue;
1562 if (isalpha(mvwinch(mw, y, x))) {
1563 if ((item = find_mons(y, x)) != NULL) {
1564 th = THINGPTR(item);
1565 if (th == tp) /* don't count gas spore */
1566 continue;
1567 damage = roll(6, 6);
1568 if (save(VS_WAND, th, 0))
1569 damage /= 2;
1570 if ((tp->t_stats.s_hpt -= damage) <= 0) {
1571 msg("the explosion kills the %s",
1572 monsters[th->t_index].m_name);
1573 killed(item, FALSE, FALSE);
1574 }
1575 }
1576 }
1577 }
1578 }
1579 }