Annotation of early-roguelike/arogue5/fight.c, Revision 1.1.1.1
1.1 rubenllo 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 <stdlib.h>
17: #include <ctype.h>
18: #include <string.h>
19: #include "rogue.h"
20:
21: bool roll_em(struct thing *att_er, struct thing *def_er, struct object *weap,
22: bool hurl, struct object *cur_weapon, bool back_stab);
23: void hit(struct object *weapon, struct thing *tp, const char *er,
24: const char *ee, bool back_stab);
25: void miss(struct object *weapon, struct thing *tp, const char *er,
26: const char *ee);
27: int dext_plus(int dexterity);
28: int str_plus(short str);
29: int add_dam(short str);
30: int hung_dam(void);
31: void thunk(struct object *weap, struct thing *tp, const char *mname);
32: void m_thunk(struct object *weap, struct thing *tp, const char *mname);
33: void bounce(struct object *weap, struct thing *tp, const char *mname);
34: void m_bounce(struct object *weap, struct thing *tp, const char *mname);
35: struct object *wield_weap(struct object *thrown, struct thing *mp);
36: void explode(struct thing *tp);
37:
38: #define CONF_DAMAGE -1
39: #define PARAL_DAMAGE -2
40: #define DEST_DAMAGE -3
41:
42: static const struct matrix att_mat[5] = {
43: /* Base Max_lvl, Factor, Offset, Range */
44: { 10, 25, 2, 1, 2 },
45: { 9, 18, 2, 1, 5 },
46: { 10, 19, 2, 1, 3 },
47: { 10, 21, 2, 1, 4 },
48: { 7, 25, 1, 0, 2 }
49: };
50:
51: /*
52: * fight:
53: * The player attacks the monster.
54: */
55:
56: bool
57: fight(coord *mp, struct object *weap, bool thrown)
58: {
59: register struct thing *tp;
60: register struct linked_list *item;
61: register bool did_hit = TRUE;
62: bool back_stab = FALSE;
63:
64: /*
65: * Find the monster we want to fight
66: */
67: if ((item = find_mons(mp->y, mp->x)) == NULL) {
68: return(FALSE); /* must have killed him already */
69: }
70: tp = THINGPTR(item);
71: /*
72: * Since we are fighting, things are not quiet so no healing takes
73: * place.
74: */
75: player.t_quiet = 0;
76: tp->t_quiet = 0;
77:
78: /*
79: * if its in the wall, we can't hit it
80: */
81: if (on(*tp, ISINWALL) && off(player, CANINWALL))
82: return(FALSE);
83:
84: /*
85: * Let him know it was really a mimic (if it was one).
86: */
87: if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise) &&
88: off(player, ISBLIND))
89: {
90: msg("Wait! That's a %s!", monsters[tp->t_index].m_name);
91: turn_off(*tp, ISDISGUISE);
92: did_hit = thrown;
93: }
94: if (on(*tp, CANSURPRISE) && off(player, ISBLIND) && !ISWEARING(R_ALERT)) {
95: msg("Wait! There's a %s!", monsters[tp->t_index].m_name);
96: turn_off(*tp, CANSURPRISE);
97: did_hit = thrown;
98: }
99: /*
100: * if he's a thief and the creature is asleep then he gets a chance
101: * for a backstab
102: */
103: if (player.t_ctype == C_THIEF &&
104: (!on(*tp, ISRUN) || on(*tp, ISHELD) || tp->t_no_move > 0)&&
105: !on(*tp, NOSTAB))
106: back_stab = TRUE;
107:
108: runto(tp, &hero);
109:
110: if (did_hit)
111: {
112: register const char *mname;
113:
114: did_hit = FALSE;
115: mname = (on(player, ISBLIND)) ? "it" : monsters[tp->t_index].m_name;
116: if (!can_blink(tp) &&
117: ( ((weap != NULL) && (weap->o_type == RELIC)) ||
118: ((off(*tp, MAGICHIT) || ((weap != NULL) && (weap->o_hplus > 0 || weap->o_dplus > 0)) ) &&
119: (off(*tp, BMAGICHIT) || ((weap != NULL) && (weap->o_hplus > 1 || weap->o_dplus > 1)) ) &&
120: (off(*tp, CMAGICHIT) || ((weap != NULL) && (weap->o_hplus > 2 || weap->o_dplus > 2)) ) ) )
121: && roll_em(&player, tp, weap, thrown, cur_weapon, back_stab))
122: {
123: did_hit = TRUE;
124:
125: if (on(*tp, NOMETAL) && weap != NULL &&
126: weap->o_type != RELIC && weap->o_flags & ISMETAL) {
127: sprintf(outstring,"Your %s passes right through the %s!",
128: weaps[weap->o_which].w_name, mname);
129: msg(outstring);
130: }
131: else if (thrown) {
132: tp->t_wasshot = TRUE;
133: thunk(weap, tp, mname);
134: }
135: else
136: hit(weap, tp, NULL, mname, back_stab);
137:
138: /* If the player hit a rust monster, he better have a + weapon */
139: if (on(*tp, CANRUST) && !thrown && (weap != NULL) &&
140: weap->o_type != RELIC &&
141: (weap->o_flags & ISMETAL) &&
142: !(weap->o_flags & ISPROT) &&
143: (weap->o_hplus < 1) && (weap->o_dplus < 1)) {
144: if (rnd(100) < 50) weap->o_hplus--;
145: else weap->o_dplus--;
146: msg(terse ? "Your %s weakens!"
147: : "Your %s appears to be weaker now!",
148: weaps[weap->o_which].w_name);
149: }
150:
151: /* If the player hit something that shrieks, wake the dungeon */
152: if (on(*tp, CANSHRIEK)) {
153: turn_off(*tp, CANSHRIEK);
154: msg("The %s emits a piercing shriek.", mname);
155: aggravate();
156: }
157:
158: /* If the player hit something that can surprise, it can't now */
159: if (on(*tp, CANSURPRISE)) turn_off(*tp, CANSURPRISE);
160:
161:
162: /*
163: * Can the player confuse?
164: */
165: if (on(player, CANHUH) && !thrown) {
166: msg("Your hands stop glowing red");
167: msg("The %s appears confused.", mname);
168: turn_on(*tp, ISHUH);
169: turn_off(player, CANHUH);
170: }
171: /*
172: * does the creature explode when hit?
173: */
174: if (on(*tp, CANEXPLODE))
175: explode(tp);
176:
177: /*
178: * Merchants just disappear if hit
179: */
180: if (on(*tp, CANSELL)) {
181: msg("The %s disappears with his wares in a flash.",mname);
182: killed(item, FALSE, FALSE);
183: }
184:
185: else if (tp->t_stats.s_hpt <= 0)
186: killed(item, TRUE, TRUE);
187:
188: /* If the monster is fairly intelligent and about to die, it
189: * may turn tail and run.
190: */
191: else if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/10)) &&
192: (rnd(25) < tp->t_stats.s_intel)) {
193: turn_on(*tp, ISFLEE);
194:
195: /* If monster was suffocating, stop it */
196: if (on(*tp, DIDSUFFOCATE)) {
197: turn_off(*tp, DIDSUFFOCATE);
198: extinguish(suffocate);
199: }
200:
201: /* If monster held us, stop it */
202: if (on(*tp, DIDHOLD) && (--hold_count == 0))
203: turn_off(player, ISHELD);
204: turn_off(*tp, DIDHOLD);
205: }
206: }
207: else {
208: if (thrown)
209: bounce(weap, tp, mname);
210: else
211: miss(weap, tp, NULL, mname);
212: }
213: }
214: count = 0;
215: return did_hit;
216: }
217:
218: /*
219: * attack:
220: * The monster attacks the player
221: */
222:
223: bool
224: attack(struct thing *mp, struct object *weapon, bool thrown)
225: {
226: register const char *mname;
227: register bool did_hit = FALSE;
228: register struct object *wielded; /* The wielded weapon */
229:
230: /*
231: * Since this is an attack, stop running and any healing that was
232: * going on at the time.
233: */
234: running = FALSE;
235: player.t_quiet = 0;
236: mp->t_quiet = 0;
237:
238: if (on(*mp, ISDISGUISE) && off(player, ISBLIND))
239: turn_off(*mp, ISDISGUISE);
240: mname = on(player, ISBLIND) ? "it" : monsters[mp->t_index].m_name;
241:
242: /*
243: * Try to find a weapon to wield. Wield_weap will return a
244: * projector if weapon is a projectile (eg. bow for arrow).
245: * If weapon is NULL, it will try to find a suitable weapon.
246: */
247: wielded = wield_weap(weapon, mp);
248: if (weapon == NULL) weapon = wielded;
249:
250: if (roll_em(mp, &player, weapon, thrown, wielded, FALSE)) {
251: did_hit = TRUE;
252:
253: if (thrown) m_thunk(weapon, mp, mname);
254: else hit(weapon, mp, mname, NULL, FALSE);
255:
256: if (pstats.s_hpt <= 0)
257: death(mp->t_index); /* Bye bye life ... */
258:
259: /*
260: * suprising monsters appear after they shoot at you
261: */
262: if (thrown) {
263: if (on(*mp, CANSURPRISE))
264: turn_off(*mp, CANSURPRISE);
265: }
266: if (!thrown) {
267: /*
268: * If a vampire hits, it may take half your hit points
269: */
270: if (on(*mp, CANSUCK) && !save(VS_MAGIC, &player, 0)) {
271: if (pstats.s_hpt == 1) death(mp->t_index);
272: else {
273: pstats.s_hpt /= 2;
274: msg("You feel your life force being drawn from you.");
275: }
276: }
277:
278: /*
279: * Stinking monsters make player weaker (to hit)
280: */
281: if (on(*mp, CANSTINK)) {
282: turn_off(*mp, CANSTINK);
283: if (!save(VS_POISON, &player, 0)) {
284: msg("The stench of the %s sickens you.", mname);
285: if (on(player, HASSTINK)) lengthen(unstink, STINKTIME);
286: else {
287: turn_on(player, HASSTINK);
288: fuse(unstink, 0, STINKTIME, AFTER);
289: }
290: }
291: }
292:
293: /*
294: * Chilling monster reduces strength each time
295: */
296: if (on(*mp, CANCHILL)) {
297: if (!ISWEARING(R_SUSABILITY) && !save(VS_POISON, &player, 0)) {
298: msg("You cringe at the %s's chilling touch.", mname);
299: chg_str(-1);
300: if (lost_str++ == 0)
301: fuse(res_strength, 0, CHILLTIME, AFTER);
302: else lengthen(res_strength, CHILLTIME);
303: }
304: }
305:
306: /*
307: * itching monsters reduce dexterity (temporarily)
308: */
309: if (on(*mp, CANITCH) && !save(VS_POISON, &player, 0)) {
310: msg("The claws of the %s scratch you", mname);
311: if(ISWEARING(R_SUSABILITY)) {
312: msg("The scratch has no effect");
313: }
314: else {
315: turn_on(player, HASITCH);
316: add_dexterity(TRUE);
317: lost_dext++;
318: fuse(un_itch, 0, roll(HEALTIME,SICKTIME), AFTER);
319: }
320: }
321:
322:
323: /*
324: * If a hugging monster hits, it may SQUEEEEEEEZE
325: */
326: if (on(*mp, CANHUG)) {
327: if (roll(1,20) >= 18 || roll(1,20) >= 18) {
328: msg("The %s squeezes you against itself.", mname);
329: if ((pstats.s_hpt -= roll(2,8)) <= 0)
330: death(mp->t_index);
331: }
332: }
333:
334: /*
335: * If a disease-carrying monster hits, there is a chance the
336: * player will catch the disease
337: */
338: if (on(*mp, CANDISEASE) &&
339: (rnd(pstats.s_const) < mp->t_stats.s_lvl) &&
340: off(player, HASDISEASE)) {
341: if (ISWEARING(R_HEALTH)) msg("The wound heals quickly.");
342: else {
343: turn_on(player, HASDISEASE);
344: fuse(cure_disease, 0, roll(HEALTIME,SICKTIME), AFTER);
345: msg(terse ? "You have been diseased."
346: : "You have contracted a disease!");
347: }
348: }
349:
350: /*
351: * If a rust monster hits, you lose armor
352: */
353: if (on(*mp, CANRUST)) {
354: if (cur_armor != NULL &&
355: cur_armor->o_which != LEATHER &&
356: cur_armor->o_which != STUDDED_LEATHER &&
357: cur_armor->o_which != PADDED_ARMOR &&
358: !(cur_armor->o_flags & ISPROT) &&
359: cur_armor->o_ac < pstats.s_arm+1 ) {
360: msg(terse ? "Your armor weakens"
361: : "Your armor appears to be weaker now. Oh my!");
362: cur_armor->o_ac++;
363: }
364: if (cur_misc[WEAR_BRACERS] != NULL &&
365: cur_misc[WEAR_BRACERS]->o_ac > 0 &&
366: !(cur_misc[WEAR_BRACERS]->o_flags & ISPROT)) {
367: cur_misc[WEAR_BRACERS]->o_ac--;
368: if (cur_misc[WEAR_BRACERS]->o_ac == 0) {
369: register struct linked_list *item;
370:
371: for (item=pack; item!=NULL; item=next(item)) {
372: if (OBJPTR(item) == cur_misc[WEAR_BRACERS]) {
373: detach(pack, item);
374: o_discard(item);
375: break;
376: }
377: }
378: msg ("Your bracers crumble and fall off!");
379: cur_misc[WEAR_BRACERS] = NULL;
380: inpack--;
381: }
382: else {
383: msg("Your bracers weaken!");
384: }
385: }
386: }
387: /*
388: * If can dissolve and hero has leather type armor
389: */
390: if (on(*mp, CANDISSOLVE) && cur_armor != NULL &&
391: (cur_armor->o_which == LEATHER ||
392: cur_armor->o_which == STUDDED_LEATHER ||
393: cur_armor->o_which == PADDED_ARMOR) &&
394: !(cur_armor->o_flags & ISPROT) &&
395: cur_armor->o_ac < pstats.s_arm+1) {
396: msg(terse ? "Your armor dissolves"
397: : "Your armor appears to dissolve. Oh my!");
398: cur_armor->o_ac++;
399: }
400:
401: /* If a surprising monster hit you, you can see it now */
402: if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
403:
404: /*
405: * If an infesting monster hits you, you get a parasite or rot
406: */
407: if (on(*mp, CANINFEST) && rnd(pstats.s_const) < mp->t_stats.s_lvl) {
408: if (ISWEARING(R_HEALTH)) msg("The wound quickly heals.");
409: else {
410: turn_off(*mp, CANINFEST);
411: msg(terse ? "You have been infested."
412: : "You have contracted a parasitic infestation!");
413: infest_dam++;
414: turn_on(player, HASINFEST);
415: }
416: }
417:
418: /*
419: * Ants have poisonous bites
420: */
421: if (on(*mp, CANPOISON) && !save(VS_POISON, &player, 0)) {
422: if (ISWEARING(R_SUSABILITY))
423: msg(terse ? "Sting has no effect"
424: : "A sting momentarily weakens you");
425: else {
426: chg_str(-1);
427: msg(terse ? "A sting has weakened you" :
428: "You feel a sting in your arm and now feel weaker");
429: }
430: }
431: /*
432: * does it take wisdom away?
433: */
434: if (on(*mp, TAKEWISDOM) &&
435: !save(VS_MAGIC, &player, 0) &&
436: !ISWEARING(R_SUSABILITY)) {
437: add_wisdom(TRUE);
438: }
439: /*
440: * does it take intelligence away?
441: */
442: if (on(*mp, TAKEINTEL) &&
443: !save(VS_MAGIC, &player, 0) &&
444: !ISWEARING(R_SUSABILITY)) {
445: add_intelligence(TRUE);
446: }
447: /*
448: * Cause fear by touching
449: */
450: if (on(*mp, TOUCHFEAR)) {
451: turn_off(*mp, TOUCHFEAR);
452: if (!ISWEARING(R_HEROISM) &&
453: !save(VS_WAND, &player, 0) &&
454: !(on(player, ISFLEE) && (player.t_dest == &mp->t_pos))) {
455: turn_on(player, ISFLEE);
456: player.t_dest = &mp->t_pos;
457: msg("The %s's touch terrifies you.", mname);
458: }
459: }
460:
461: /*
462: * make the hero dance (as in otto's irresistable dance)
463: */
464: if (on(*mp, CANDANCE) &&
465: !on(player, ISDANCE) &&
466: !save(VS_MAGIC, &player, -4)) {
467: turn_off(*mp, CANDANCE);
468: turn_on(player, ISDANCE);
469: msg("You begin to dance uncontrollably!");
470: fuse(undance, 0, roll(2,4), AFTER);
471: }
472:
473: /*
474: * Suffocating our hero
475: */
476: if (on(*mp, CANSUFFOCATE) && (rnd(100) < 15) &&
477: (find_slot(suffocate) == FALSE)) {
478: turn_on(*mp, DIDSUFFOCATE);
479: msg("The %s is beginning to suffocate you.", mname);
480: fuse(suffocate, 0, roll(4,2), AFTER);
481: }
482:
483: /*
484: * Turning to stone
485: */
486: if (on(*mp, TOUCHSTONE)) {
487: turn_off(*mp, TOUCHSTONE);
488: if (on(player, CANINWALL))
489: msg("The %s's touch has no effect.", mname);
490: else {
491: if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 15) {
492: msg("Your body begins to solidify.");
493: msg("You are turned to stone !!! --More--");
494: wait_for(cw,' ');
495: death(D_PETRIFY);
496: }
497: else {
498: msg("The %s's touch stiffens your limbs.", mname);
499: no_command += STONETIME;
500: }
501: }
502: }
503:
504: /*
505: * Wraiths might drain energy levels
506: */
507: if ((on(*mp, CANDRAIN) || on(*mp, DOUBLEDRAIN)) && rnd(100) < 15) {
508: lower_level(mp->t_index);
509: if (on(*mp, DOUBLEDRAIN)) lower_level(mp->t_index);
510: turn_on(*mp, DIDDRAIN);
511: }
512:
513: /*
514: * Violet fungi stops the poor guy from moving
515: */
516: if (on(*mp, CANHOLD) && off(*mp, DIDHOLD)) {
517: turn_on(player, ISHELD);
518: turn_on(*mp, DIDHOLD);
519: hold_count++;
520: }
521:
522: /*
523: * Sucker will suck blood and run
524: */
525: if (on(*mp, CANDRAW)) {
526: turn_off(*mp, CANDRAW);
527: turn_on(*mp, ISFLEE);
528: msg("The %s sates itself with your blood.", mname);
529: if ((pstats.s_hpt -= 12) <= 0) death(mp->t_index);
530: }
531:
532: /*
533: * Bad smell will force a reduction in strength
534: */
535: if (on(*mp, CANSMELL)) {
536: turn_off(*mp, CANSMELL);
537: if (save(VS_MAGIC, &player, 0) || ISWEARING(R_SUSABILITY))
538: msg("You smell an unpleasant odor.");
539: else {
540: int odor_str = -(rnd(6)+1);
541:
542: msg("You are overcome by a foul odor.");
543: if (lost_str == 0) {
544: chg_str(odor_str);
545: fuse(res_strength, 0, SMELLTIME, AFTER);
546: lost_str -= odor_str;
547: }
548: else lengthen(res_strength, SMELLTIME);
549: }
550: }
551:
552: /*
553: * Paralyzation
554: */
555: if (on(*mp, CANPARALYZE)) {
556: turn_off(*mp, CANPARALYZE);
557: if (!save(VS_PARALYZATION, &player, 0)) {
558: if (on(player, CANINWALL))
559: msg("The %s's touch has no effect.", mname);
560: else {
561: msg("The %s's touch paralyzes you.", mname);
562: no_command += FREEZETIME;
563: }
564: }
565: }
566:
567: /*
568: * Painful wounds make you faint
569: */
570: if (on(*mp, CANPAIN)) {
571: turn_off(*mp, CANPAIN);
572: if (!ISWEARING(R_ALERT) && !save(VS_POISON, &player, 0)) {
573: msg("You faint from the painful wound");
574: no_command += PAINTIME;
575: }
576: }
577:
578: /*
579: * The monsters touch slows the hero down
580: */
581: if (on(*mp, CANSLOW)) {
582: turn_off(*mp, CANSLOW);
583: if (!save(VS_PARALYZATION, &player, 0))
584: add_slow();
585: }
586:
587: /*
588: * Rotting
589: */
590: if (on(*mp, CANROT)) {
591: if (!ISWEARING(R_HEALTH) &&
592: !save(VS_POISON, &player, 0) &&
593: off(player, DOROT)) {
594: turn_on(player, DOROT);
595: msg("You feel your skin starting to rot away!");
596: }
597: }
598:
599: if (on(*mp, STEALGOLD)) {
600: /*
601: * steal some gold
602: */
603: register long lastpurse;
604: register struct linked_list *item;
605: register struct object *obj;
606:
607: lastpurse = purse;
608: purse -= GOLDCALC + GOLDCALC;
609: if (!save(VS_MAGIC, &player, mp->t_stats.s_lvl/10)) {
610: if (on(*mp, ISUNIQUE))
611: purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
612: purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
613: }
614: if (purse < 0)
615: purse = 0;
616: if (purse != lastpurse) {
617: msg("Your purse feels lighter");
618:
619: /* Give the gold to the thief */
620: for (item=mp->t_pack; item != NULL; item=next(item)) {
621: obj = OBJPTR(item);
622: if (obj->o_type == GOLD) {
623: obj->o_count += lastpurse - purse;
624: break;
625: }
626: }
627:
628: /* Did we do it? */
629: if (item == NULL) { /* Then make some */
630: item = new_item(sizeof *obj);
631: obj = OBJPTR(item);
632: obj->o_type = GOLD;
633: obj->o_count = lastpurse - purse;
634: obj->o_hplus = obj->o_dplus = 0;
635: strcpy(obj->o_damage,"0d0");
636: strcpy(obj->o_hurldmg,"0d0");
637: obj->o_ac = 11;
638: obj->contents = NULL;
639: obj->o_group = 0;
640: obj->o_flags = 0;
641: obj->o_mark[0] = '\0';
642: obj->o_pos = mp->t_pos;
643:
644: attach(mp->t_pack, item);
645: }
646: }
647:
648: turn_on(*mp, ISFLEE);
649: turn_on(*mp, ISINVIS);
650: }
651:
652: if (on(*mp, STEALMAGIC)) {
653: register struct linked_list *list, *steal;
654: register struct object *obj;
655: register int nobj;
656:
657: /*
658: * steal a magic item, look through the pack
659: * and pick out one we like.
660: */
661: steal = NULL;
662: for (nobj = 0, list = pack; list != NULL; list = next(list))
663: {
664: obj = OBJPTR(list);
665: if (!is_current(obj) &&
666: is_magic(obj) &&
667: rnd(++nobj) == 0)
668: steal = list;
669: }
670: if (steal != NULL)
671: {
672: register struct object *obj;
673: struct linked_list *item;
674:
675: obj = OBJPTR(steal);
676: if (on(*mp, ISUNIQUE))
677: monsters[mp->t_index].m_normal = TRUE;
678: item = find_mons(mp->t_pos.y, mp->t_pos.x);
679: killed(item, FALSE, FALSE);
680: if (obj->o_count > 1 && obj->o_group == 0) {
681: register int oc;
682:
683: oc = --(obj->o_count);
684: obj->o_count = 1;
685: sprintf(outstring,"The %s stole %s!", mname, inv_name(obj, TRUE));
686: msg(outstring);
687: obj->o_count = oc;
688: }
689: else {
690: sprintf(outstring,"The %s stole %s!", mname, inv_name(obj, TRUE));
691: msg(outstring);
692: detach(pack, steal);
693:
694: /* If this is a relic, clear its holding field */
695: if (obj->o_type == RELIC)
696: cur_relic[obj->o_which] = 0;
697:
698: o_discard(steal);
699: inpack--;
700: }
701: updpack(FALSE);
702: }
703: }
704: }
705: }
706: else {
707: /* If the thing was trying to surprise, no good */
708: if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
709:
710: else if (thrown) m_bounce(weapon, mp, mname);
711: else miss(weapon, mp, mname, NULL);
712: }
713: if (fight_flush)
714: md_flushinp();
715: count = 0;
716: status(FALSE);
717: return(did_hit);
718: }
719:
720: /*
721: * swing:
722: * returns true if the swing hits
723: */
724:
725: bool
726: swing(short class, int at_lvl, int op_arm, int wplus)
727: {
728: register int res = rnd(20)+1;
729: register int need;
730:
731: need = att_mat[class].base -
732: att_mat[class].factor *
733: ((min(at_lvl, att_mat[class].max_lvl) -
734: att_mat[class].offset)/att_mat[class].range) +
735: (10 - op_arm);
736: if (need > 20 && need <= 25) need = 20;
737:
738: return (res+wplus >= need);
739: }
740:
741: /*
742: * roll_em:
743: * Roll several attacks
744: */
745:
746: bool
747: roll_em(struct thing *att_er, struct thing *def_er, struct object *weap,
748: bool hurl, struct object *cur_weapon, bool back_stab)
749: {
750: register struct stats *att, *def;
751: register char *cp = NULL;
752: register int ndice, nsides, nplus, def_arm;
753: bool did_hit = FALSE;
754: int prop_hplus, prop_dplus;
755: int vampiric_damage;
756:
757: /* Get statistics */
758: att = &att_er->t_stats;
759: def = &def_er->t_stats;
760:
761: prop_hplus = prop_dplus = 0;
762: if (weap == NULL)
763: cp = att->s_dmg;
764: else if (hurl) {
765: if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
766: cur_weapon->o_which == weap->o_launch)
767: {
768: cp = weap->o_hurldmg;
769: prop_hplus = cur_weapon->o_hplus;
770: prop_dplus = cur_weapon->o_dplus;
771: }
772: else
773: cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg);
774: }
775: else {
776: if (weap->o_type == RELIC) {
777: switch (weap->o_which) {
778: case MUSTY_DAGGER: cp = "1d4+1/1d4+1";
779: when YEENOGHU_FLAIL: cp = "3d6/paralyze/confuse";
780: when HRUGGEK_MSTAR: cp = "3d10";
781: when MING_STAFF: cp = "1d8";
782: when ASMO_ROD: cp = "2d8+1";
783: when ORCUS_WAND: cp = "destroy";
784: }
785: }
786: else cp = weap->o_damage;
787: /*
788: * Drain a staff of striking
789: */
790: if (weap->o_type == STICK && weap->o_which == WS_HIT
791: && weap->o_charges == 0)
792: {
793: strcpy(weap->o_damage,"0d0");
794: weap->o_hplus = weap->o_dplus = 0;
795: }
796: }
797: for (;;)
798: {
799: int damage;
800: int hplus = prop_hplus;
801: int dplus = prop_dplus;
802:
803: if (weap != NULL && weap->o_type == RELIC) {
804: switch (weap->o_which) {
805: case MUSTY_DAGGER:
806: if (att != &pstats || /* Not player or good stats */
807: (str_compute() > 15 && dex_compute() > 15)) {
808:
809: hplus += 6;
810: dplus += 6;
811:
812: /* Give an additional strength and dex bonus */
813: if (att == &pstats) {
814: hplus += str_plus(str_compute()) +
815: dext_plus(dex_compute());
816: dplus += dext_plus(dex_compute()) +
817: add_dam(str_compute());
818: }
819: else {
820: hplus += str_plus(att->s_str) +
821: dext_plus(att->s_dext);
822: dplus += dext_plus(att->s_dext) +
823: add_dam(att->s_str);
824: }
825: }
826: else {
827: hplus -= 3;
828: dplus -= 3;
829: }
830: when YEENOGHU_FLAIL:
831: case HRUGGEK_MSTAR:
832: hplus += 3;
833: dplus += 3;
834: when MING_STAFF:
835: hplus += 2;
836: dplus += 2;
837: }
838: }
839: else if (weap != NULL) {
840: hplus += weap->o_hplus;
841: dplus += weap->o_dplus;
842: }
843:
844: /* Is attacker weak? */
845: if (on(*att_er, HASSTINK)) hplus -= 2;
846:
847: if (att == &pstats) /* Is the attacker the player? */
848: {
849: hplus += hitweight(); /* adjust for encumberence */
850: dplus += hung_dam(); /* adjust damage for hungry player */
851: dplus += ring_value(R_ADDDAM);
852: }
853: if (back_stab || (weap && att != &pstats && on(*att_er, CANBSTAB)))
854: hplus += 4; /* add in pluses for backstabbing */
855:
856: /* Get the damage */
857: while (isspace(*cp)) cp++;
858: if (!isdigit(*cp)) {
859: if (strncmp(cp, "confuse", 7) == 0) ndice = CONF_DAMAGE;
860: else if (strncmp(cp, "paralyze", 8) == 0) ndice = PARAL_DAMAGE;
861: else if (strncmp(cp, "destroy", 7) == 0) ndice = DEST_DAMAGE;
862: else ndice = 0;
863: nsides = 0;
864: nplus = 0;
865: }
866: else {
867: char *oldcp;
868:
869: /* Get the number of damage dice */
870: ndice = atoi(cp);
871: if ((cp = strchr(cp, 'd')) == NULL)
872: break;
873:
874: /* Skip the 'd' and get the number of sides per die */
875: nsides = atoi(++cp);
876:
877: /* Check for an addition -- save old place in case none is found */
878: oldcp = cp;
879: if ((cp = strchr(cp, '+')) != NULL) nplus = atoi(++cp);
880: else {
881: nplus = 0;
882: cp = oldcp;
883: }
884: }
885:
886: if (def == &pstats) { /* Monster attacks player */
887: def_arm = ac_compute() - dext_prot(dex_compute());
888: hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
889: }
890: else { /* Player attacks monster */
891: def_arm = def->s_arm - dext_prot(def->s_dext);
892: hplus += str_plus(str_compute())+dext_plus(dex_compute());
893: }
894:
895: if (swing(att_er->t_ctype, att->s_lvl, def_arm, hplus)) {
896: register int proll;
897:
898: /* Take care of special effects */
899: switch (ndice) {
900: case CONF_DAMAGE:
901: if (def == &pstats) { /* Monster attacks player */
902: if (!save(VS_MAGIC, &player, 0) && off(player, ISCLEAR)) {
903: msg("You feel disoriented.");
904: if (find_slot(unconfuse))
905: lengthen(unconfuse, rnd(8)+HUHDURATION);
906: else
907: fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
908: turn_on(player, ISHUH);
909: }
910: else msg("You feel dizzy, but it quickly passes.");
911: }
912: /* Player hits monster */
913: else if (!save(VS_MAGIC, def_er, 0) && off(*def_er, ISCLEAR)) {
914: msg("The artifact warms with pleasure.");
915: turn_on(*def_er, ISHUH);
916: }
917: did_hit = TRUE;
918: when PARAL_DAMAGE:
919: if (def == &pstats) { /* Monster attacks player */
920: if (!save(VS_MAGIC, &player, 0) && off(player, CANINWALL)) {
921: msg("You stiffen up.");
922: no_command += FREEZETIME;
923: }
924: }
925: else if (!save(VS_MAGIC, def_er, 0)) { /* Player hits monster */
926: msg("The artifact hums happily.");
927: turn_off(*def_er, ISRUN);
928: turn_on(*def_er, ISHELD);
929: }
930: did_hit = TRUE;
931: when DEST_DAMAGE:
932: if (def == &pstats) { /* Monster attacks player */
933: msg("You feel a tug at your life force.");
934: if (!save(VS_MAGIC, &player, -4)) {
935: msg("The wand devours your soul.");
936: def->s_hpt = 0;
937: }
938: }
939: /* Player hits monster */
940: else if (!save(VS_MAGIC, def_er, -4)) {
941: msg("The artifact draws energy.");
942:
943: /* Give the player half the monster's hits */
944: att->s_hpt += def->s_hpt/2;
945: if (att->s_hpt > att_er->maxstats.s_hpt)
946: att->s_hpt = att_er->maxstats.s_hpt;
947:
948: /* Kill the monster */
949: def->s_hpt = 0;
950: }
951: did_hit = TRUE;
952: otherwise:
953: /* Heil's ankh always gives maximum damage */
954: if (att == &pstats && cur_relic[HEIL_ANKH])
955: proll = ndice * nsides;
956: else proll = roll(ndice, nsides);
957:
958: if (ndice + nsides > 0 && proll < 1)
959: debug("Damage for %dd%d came out %d.",
960: ndice, nsides, proll);
961: damage = dplus + proll + nplus;
962: if (def == &pstats)
963: damage += add_dam(att->s_str);
964: else
965: damage += add_dam(str_compute());
966:
967: /* Check for half damage monsters */
968: if (on(*def_er, HALFDAMAGE)) damage /= 2;
969:
970: /* add in multipliers for backstabbing */
971: if (back_stab ||
972: (weap && att != &pstats && on(*att_er, CANBSTAB))) {
973: int mult = 2 + (att->s_lvl-1)/4; /* Normal multiplier */
974:
975: if (mult > 5 && att != &pstats)
976: mult = 5;/*be nice with maximum of 5x for monsters*/
977: if (weap->o_type == RELIC && weap->o_which == MUSTY_DAGGER)
978: mult++;
979: damage *= mult;
980: }
981:
982: /* Check for no-damage and division */
983: if (on(*def_er, BLOWDIVIDE)) {
984: damage = 0;
985: creat_mons(def_er, def_er->t_index, FALSE);
986: light(&hero);
987: }
988: /* check for immunity to metal -- RELICS are always bad */
989: if (on(*def_er, NOMETAL) && weap != NULL &&
990: weap->o_type != RELIC && weap->o_flags & ISMETAL) {
991: damage = 0;
992: }
993:
994: /*
995: * If defender is wearing a cloak of displacement -- no damage
996: * the first time. (unless its a hurled magic missile)
997: */
998: if ( ((weap == NULL) || weap->o_type != MISSILE) &&
999: def == &pstats &&
1000: cur_misc[WEAR_CLOAK] != NULL &&
1001: cur_misc[WEAR_CLOAK]->o_which == MM_DISP &&
1002: off(*att_er, MISSEDDISP)) {
1003: damage = 0;
1004: did_hit = FALSE;
1005: turn_on(*att_er, MISSEDDISP);
1006: if (cansee(att_er->t_pos.y, att_er->t_pos.x) &&
1007: !invisible(att_er))
1008: msg("The %s looks amazed",
1009: monsters[att_er->t_index].m_name);
1010: }
1011: else {
1012: def->s_hpt -= max(0, damage); /* Do the damage */
1013: did_hit = TRUE;
1014: }
1015:
1016: vampiric_damage = damage;
1017: if (def->s_hpt < 0) /* only want REAL damage inflicted */
1018: vampiric_damage += def->s_hpt;
1019: if (vampiric_damage < 0)
1020: vampiric_damage = 0;
1021: if (att == &pstats && ISWEARING(R_VAMPREGEN) && !hurl) {
1022: if ((pstats.s_hpt += vampiric_damage/2) > max_stats.s_hpt)
1023: pstats.s_hpt = max_stats.s_hpt;
1024: }
1025: debug ("hplus=%d dmg=%d", hplus, damage);
1026: }
1027: }
1028: if ((cp = strchr(cp, '/')) == NULL)
1029: break;
1030: cp++;
1031: }
1032: return did_hit;
1033: }
1034:
1035: /*
1036: * prname:
1037: * The print name of a combatant
1038: */
1039:
1040: char *
1041: prname(const char *who, bool upper)
1042: {
1043: static char tbuf[LINELEN];
1044:
1045: *tbuf = '\0';
1046: if (who == 0)
1047: strcpy(tbuf, "you");
1048: else if (on(player, ISBLIND))
1049: strcpy(tbuf, "it");
1050: else
1051: {
1052: strcpy(tbuf, "the ");
1053: strcat(tbuf, who);
1054: }
1055: if (upper)
1056: *tbuf = toupper(*tbuf);
1057: return tbuf;
1058: }
1059:
1060: /*
1061: * hit:
1062: * Print a message to indicate a succesful hit
1063: */
1064:
1065: void
1066: hit(struct object *weapon, struct thing *tp, const char *er, const char *ee,
1067: bool back_stab)
1068: {
1069: register char *s = NULL;
1070: char
1071: att_name[80], /* Name of attacker */
1072: def_name[80];/* Name of defender */
1073: bool see_monst = !invisible(tp); /* Can the player see the monster? */
1074:
1075: /* What do we call the attacker? */
1076: if (er == NULL) { /* Player is attacking */
1077: strcpy(att_name, prname(er, TRUE));
1078: strcpy(def_name, see_monst ? prname(ee, FALSE) : "something");
1079: }
1080: else {
1081: strcpy(att_name, see_monst ? prname(er, TRUE) : "Something");
1082:
1083: /* If the monster is using a weapon and we can see it, report it */
1084: if (weapon != NULL && see_monst) {
1085: strcat(att_name, "'s ");
1086: strcat(att_name, weap_name(weapon));
1087: }
1088:
1089: strcpy(def_name, prname(ee, FALSE));
1090: }
1091:
1092: addmsg(att_name);
1093: if (terse) {
1094: if (back_stab)
1095: s = " backstab!";
1096: else
1097: s = " hit.";
1098: }
1099: else {
1100: if (back_stab)
1101: s = (er == 0 ? " have backstabbed " : " has backstabbed ");
1102: else {
1103: switch (rnd(4))
1104: {
1105: case 0: s = " scored an excellent hit on ";
1106: when 1: s = " hit ";
1107: when 2: s = (er == 0 ? " have injured " : " has injured ");
1108: when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");
1109: }
1110: }
1111: }
1112: addmsg(s);
1113: if (!terse)
1114: addmsg(def_name);
1115: endmsg();
1116: }
1117:
1118: /*
1119: * miss:
1120: * Print a message to indicate a poor swing
1121: */
1122:
1123: void
1124: miss(struct object *weapon, struct thing *tp, const char *er, const char *ee)
1125: {
1126: register char *s = NULL;
1127: char
1128: att_name[80], /* Name of attacker */
1129: def_name[80];/* Name of defender */
1130: bool see_monst = !invisible(tp); /* Can the player see the monster? */
1131:
1132: /* What do we call the attacker? */
1133: if (er == NULL) { /* Player is attacking */
1134: strcpy(att_name, prname(er, TRUE));
1135: strcpy(def_name, see_monst ? prname(ee, FALSE) : "something");
1136: }
1137: else {
1138: strcpy(att_name, see_monst ? prname(er, TRUE) : "Something");
1139:
1140: /* If the monster is using a weapon and we can see it, report it */
1141: if (weapon != NULL && see_monst) {
1142: strcat(att_name, "'s ");
1143: strcat(att_name, weap_name(weapon));
1144: }
1145:
1146: strcpy(def_name, prname(ee, FALSE));
1147: }
1148:
1149: addmsg(att_name);
1150: switch (terse ? 0 : rnd(4))
1151: {
1152: case 0: s = (er == 0 ? " miss" : " misses");
1153: when 1: s = (er == 0 ? " swing and miss" : " swings and misses");
1154: when 2: s = (er == 0 ? " barely miss" : " barely misses");
1155: when 3: s = (er == 0 ? " don't hit" : " doesn't hit");
1156: }
1157: addmsg(s);
1158: if (!terse)
1159: addmsg(" %s", def_name);
1160: endmsg();
1161: }
1162:
1163: /*
1164: * dext_plus:
1165: * compute to-hit bonus for dexterity
1166: */
1167:
1168: int
1169: dext_plus(int dexterity)
1170: {
1171: return (dexterity > 10 ? (dexterity-13)/3 : (dexterity-10)/3);
1172: }
1173:
1174:
1175: /*
1176: * dext_prot:
1177: * compute armor class bonus for dexterity
1178: */
1179:
1180: int
1181: dext_prot(int dexterity)
1182: {
1183: return ((dexterity-10)/2);
1184: }
1185: /*
1186: * str_plus:
1187: * compute bonus/penalties for strength on the "to hit" roll
1188: */
1189:
1190: int
1191: str_plus(short str)
1192: {
1193: return((str-10)/3);
1194: }
1195:
1196: /*
1197: * add_dam:
1198: * compute additional damage done for exceptionally high or low strength
1199: */
1200:
1201: int
1202: add_dam(short str)
1203: {
1204: return((str-9)/2);
1205: }
1206:
1207: /*
1208: * hung_dam:
1209: * Calculate damage depending on players hungry state
1210: */
1211: int
1212: hung_dam(void)
1213: {
1214: reg int howmuch = 0;
1215:
1216: switch(hungry_state) {
1217: case F_OKAY:
1218: case F_HUNGRY: howmuch = 0;
1219: when F_WEAK: howmuch = -1;
1220: when F_FAINT: howmuch = -2;
1221: }
1222: return howmuch;
1223: }
1224:
1225: /*
1226: * thunk:
1227: * A missile hits a monster
1228: */
1229:
1230: void
1231: thunk(struct object *weap, struct thing *tp, const char *mname)
1232: {
1233: /* tp: Defender */
1234: char *def_name; /* Name of defender */
1235:
1236: /* What do we call the defender? */
1237: if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
1238: def_name = "something";
1239: else def_name = prname(mname, FALSE);
1240:
1241: if (weap->o_type == WEAPON){
1242: sprintf(outstring,"The %s hits %s", weaps[weap->o_which].w_name, def_name);
1243: msg(outstring);
1244: }
1245: else if (weap->o_type == MISSILE){
1246: sprintf(outstring,"The %s hits %s",ws_magic[weap->o_which].mi_name, def_name);
1247: msg(outstring);
1248: }
1249: else
1250: msg("You hit %s.", def_name);
1251: }
1252:
1253: /*
1254: * mthunk:
1255: * A missile from a monster hits the player
1256: */
1257:
1258: void
1259: m_thunk(struct object *weap, struct thing *tp, const char *mname)
1260: {
1261: char *att_name; /* Name of attacker */
1262:
1263: /* What do we call the attacker? */
1264: if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
1265: att_name = "Something";
1266: else att_name = prname(mname, TRUE);
1267:
1268: if (weap->o_type == WEAPON){
1269: sprintf(outstring,"%s's %s hits you.", att_name, weaps[weap->o_which].w_name);
1270: msg(outstring);
1271: }
1272: else if (weap->o_type == MISSILE){
1273: sprintf(outstring,"%s's %s hits you.", att_name, ws_magic[weap->o_which].mi_name);
1274: msg(outstring);
1275: }
1276: else
1277: msg("%s hits you.", att_name);
1278: }
1279:
1280: /*
1281: * bounce:
1282: * A missile misses a monster
1283: */
1284:
1285: void
1286: bounce(struct object *weap, struct thing *tp, const char *mname)
1287: {
1288: /* tp: Defender */
1289: char *def_name; /* Name of defender */
1290:
1291: /* What do we call the defender? */
1292: if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
1293: def_name = "something";
1294: else def_name = prname(mname, FALSE);
1295:
1296: if (weap->o_type == WEAPON){
1297: sprintf(outstring,"The %s misses %s",weaps[weap->o_which].w_name, def_name);
1298: msg(outstring);
1299: }
1300: else if (weap->o_type == MISSILE){
1301: sprintf(outstring,"The %s misses %s",ws_magic[weap->o_which].mi_name, def_name);
1302: msg(outstring);
1303: }
1304: else
1305: msg("You missed %s.", def_name);
1306: }
1307:
1308: /*
1309: * m_bounce:
1310: A missle from a monster misses the player
1311: */
1312:
1313: void
1314: m_bounce(struct object *weap, struct thing *tp, const char *mname)
1315: {
1316: char *att_name; /* Name of attacker */
1317:
1318: /* What do we call the attacker? */
1319: if (!cansee(tp->t_pos.y, tp->t_pos.x) || invisible(tp))
1320: att_name = "Something";
1321: else att_name = prname(mname, TRUE);
1322:
1323: if (weap->o_type == WEAPON){
1324: sprintf(outstring,"%s's %s misses you.", att_name, weaps[weap->o_which].w_name);
1325: msg(outstring);
1326: }
1327: else if (weap->o_type == MISSILE){
1328: sprintf(outstring,"%s's %s misses you.", att_name, ws_magic[weap->o_which].mi_name);
1329: msg(outstring);
1330: }
1331: else
1332: msg("%s misses you.", att_name);
1333: }
1334:
1335:
1336: /*
1337: * is_magic:
1338: * Returns true if an object radiates magic
1339: */
1340:
1341: bool
1342: is_magic(struct object *obj)
1343: {
1344: switch (obj->o_type)
1345: {
1346: case ARMOR:
1347: return obj->o_ac != armors[obj->o_which].a_class;
1348: when WEAPON:
1349: return obj->o_hplus != 0 || obj->o_dplus != 0;
1350: when POTION:
1351: case SCROLL:
1352: case STICK:
1353: case RING:
1354: case MM:
1355: case RELIC:
1356: return TRUE;
1357: }
1358: return FALSE;
1359: }
1360:
1361: /*
1362: * killed:
1363: * Called to put a monster to death
1364: */
1365:
1366: void
1367: killed(struct linked_list *item, bool pr, bool points)
1368: {
1369: register struct thing *tp;
1370: register struct linked_list *pitem, *nexti;
1371: const char *monst;
1372:
1373: tp = THINGPTR(item);
1374:
1375: if (pr)
1376: {
1377: addmsg(terse ? "Defeated " : "You have defeated ");
1378: if (on(player, ISBLIND))
1379: msg("it.");
1380: else
1381: {
1382: if (cansee(tp->t_pos.y, tp->t_pos.x) && !invisible(tp))
1383: monst = monsters[tp->t_index].m_name;
1384: else {
1385: if (terse) monst = "something";
1386: else monst = "thing";
1387: }
1388: if (!terse)
1389: addmsg("the ");
1390: msg("%s.", monst);
1391: }
1392: }
1393:
1394: /* Take care of any residual effects of the monster */
1395: check_residue(tp);
1396:
1397: if (points) {
1398: unsigned long test; /* For overflow check */
1399:
1400: test = pstats.s_exp + tp->t_stats.s_exp;
1401:
1402: /* Do an overflow check before increasing experience */
1403: if (test > pstats.s_exp) pstats.s_exp = test;
1404:
1405: /*
1406: * Do adjustments if he went up a level
1407: */
1408: check_level(TRUE);
1409: }
1410:
1411: /*
1412: * Empty the monsters pack
1413: */
1414: pitem = tp->t_pack;
1415:
1416: /*
1417: * Get rid of the monster.
1418: */
1419: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' ');
1420: mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
1421: detach(mlist, item);
1422: /*
1423: * empty his pack
1424: */
1425: while (pitem != NULL)
1426: {
1427: nexti = next(tp->t_pack);
1428: (OBJPTR(pitem))->o_pos = tp->t_pos;
1429: detach(tp->t_pack, pitem);
1430: if (points)
1431: fall(pitem, FALSE);
1432: else
1433: o_discard(pitem);
1434: pitem = nexti;
1435: }
1436: turn_on(*tp, ISDEAD);
1437: attach(monst_dead, item);
1438: }
1439:
1440:
1441: /*
1442: * Returns a pointer to the weapon the monster is wielding corresponding to
1443: * the given thrown weapon. If no thrown item is given, try to find any
1444: * decent weapon.
1445: */
1446:
1447: struct object *
1448: wield_weap(struct object *thrown, struct thing *mp)
1449: {
1450: int look_for = 0, /* The projectile weapon we are looking for */
1451: new_rate, /* The rating of a prospective weapon */
1452: cand_rate = -1; /* Rating of current candidate -- higher is better */
1453: register struct linked_list *pitem;
1454: register struct object *obj, *candidate = NULL;
1455:
1456: if (thrown != NULL) { /* Using a projectile weapon */
1457: switch (thrown->o_which) {
1458: case BOLT: look_for = CROSSBOW; /* Find the crossbow */
1459: when ARROW: look_for = BOW; /* Find the bow */
1460: when ROCK: look_for = SLING; /* find the sling */
1461: otherwise: return(NULL);
1462: }
1463: }
1464: else if (off(*mp, ISUNIQUE) && off(*mp, CARRYWEAPON)) return(NULL);
1465:
1466: for (pitem=mp->t_pack; pitem; pitem=next(pitem)) {
1467: obj = OBJPTR(pitem);
1468:
1469: /*
1470: * If we have a thrown weapon, just return the first match
1471: * we come to.
1472: */
1473: if (thrown != NULL && obj->o_type == WEAPON && obj->o_which == look_for)
1474: return(obj);
1475:
1476: /* If we have a usable RELIC, return it */
1477: if (thrown == NULL && obj->o_type == RELIC) {
1478: switch (obj->o_which) {
1479: case MUSTY_DAGGER:
1480: case YEENOGHU_FLAIL:
1481: case HRUGGEK_MSTAR:
1482: case MING_STAFF:
1483: case ASMO_ROD:
1484: case ORCUS_WAND:
1485: return(obj);
1486: }
1487: }
1488:
1489: /* Otherwise if it's a usable weapon, it is a good candidate */
1490: else if (thrown == NULL && obj->o_type == WEAPON) {
1491: switch (obj->o_which) {
1492: case DAGGER:
1493: new_rate = 0;
1494: when BATTLEAXE:
1495: new_rate = 1;
1496: when MACE:
1497: new_rate = 2;
1498: when SWORD:
1499: new_rate = 3;
1500: when PIKE:
1501: new_rate = 4;
1502: when HALBERD:
1503: case SPETUM:
1504: new_rate = 6;
1505: when BARDICHE:
1506: new_rate = 7;
1507: when TRIDENT:
1508: new_rate = 8;
1509: when BASWORD:
1510: new_rate = 9;
1511: when TWOSWORD:
1512: new_rate = 10;
1513: otherwise:
1514: new_rate = -1;
1515: }
1516:
1517: /* Only switch if this is better than the current candidate */
1518: if (new_rate > cand_rate) {
1519: cand_rate = new_rate;
1520: candidate = obj;
1521: }
1522: }
1523: }
1524:
1525: return(candidate);
1526: }
1527:
1528: void
1529: explode(struct thing *tp)
1530: {
1531:
1532: register int x,y, damage;
1533: struct linked_list *item;
1534: struct thing *th;
1535:
1536: msg("the %s explodes!", monsters[tp->t_index].m_name);
1537: /*
1538: * check to see if it got the hero
1539: */
1540: if (DISTANCE(hero.x, hero.y, tp->t_pos.x, tp->t_pos.y) <= 25) {
1541: msg("the explosion hits you");
1542: damage = roll(6,6);
1543: if (save(VS_WAND, &player, 0))
1544: damage /= 2;
1545: if ((pstats.s_hpt -= damage) <= 0)
1546: death(tp->t_index);
1547: }
1548:
1549: /*
1550: * now check for monsters in vicinity
1551: */
1552: for (x = tp->t_pos.x-5; x<=tp->t_pos.x+5; x++) {
1553: if (x < 0 || x > COLS - 1)
1554: continue;
1555: for (y = tp->t_pos.y-5; y<=tp->t_pos.y+5; y++) {
1556: if (y < 1 || y > LINES - 3)
1557: continue;
1558: if (isalpha(mvwinch(mw, y, x))) {
1559: if ((item = find_mons(y, x)) != NULL) {
1560: th = THINGPTR(item);
1561: if (th == tp) /* don't count gas spore */
1562: continue;
1563: damage = roll(6, 6);
1564: if (save(VS_WAND, th, 0))
1565: damage /= 2;
1566: if ((tp->t_stats.s_hpt -= damage) <= 0) {
1567: msg("the explosion kills the %s",
1568: monsters[th->t_index].m_name);
1569: killed(item, FALSE, FALSE);
1570: }
1571: }
1572: }
1573: }
1574: }
1575: }
CVSweb