Annotation of early-roguelike/xrogue/fight.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: fight.c - All the fighting gets done here
3:
4: XRogue: Expeditions into the Dungeons of Doom
5: Copyright (C) 1991 Robert Pietkivitch
6: All rights reserved.
7:
8: Based on "Advanced Rogue"
9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
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 <curses.h>
20: #include <ctype.h>
21: #include <string.h>
22: #include <stdlib.h>
23: #include "rogue.h"
24:
25: #define CONF_DAMAGE -1
26: #define PARAL_DAMAGE -2
27: #define DEST_DAMAGE -3
28: #define DRAIN_DAMAGE -4
29:
30: bool roll_em(struct thing *att_er, struct thing *def_er, struct object *weap,
31: bool hurl, struct object *cur_weapon, bool back_stab);
32: void hit(struct object *weapon, bool see_att, bool see_def, char *er, char *ee,
33: bool back_stab, bool thrown, bool short_msg);
34: void miss(struct object *weapon, bool see_att, bool see_def, char *er, char *ee,
35: bool thrown, bool short_msg);
36: int add_dam(short str);
37: int hung_dam(void);
38:
39: int killed_chance = 0; /* cumulative chance for goodies to loose it */
40:
41: /*
42: * returns true if player has a any chance to hit the monster
43: */
44:
45: bool
46: player_can_hit(struct thing *tp, struct object *weap)
47: {
48: if (off(*tp, CMAGICHIT) && off(*tp, BMAGICHIT) && off(*tp, MAGICHIT))
49: return(TRUE);
50: if (weap && weap->o_type == RELIC)
51: return(TRUE);
52: if (on(*tp, CMAGICHIT) && weap && (weap->o_hplus>2 || weap->o_dplus>2))
53: return(TRUE);
54: if (on(*tp, BMAGICHIT) && weap && (weap->o_hplus>1 || weap->o_dplus>1))
55: return(TRUE);
56: if (on(*tp, MAGICHIT) && weap && (weap->o_hplus>0 || weap->o_dplus>0))
57: return(TRUE);
58: if (player.t_ctype == C_MONK) {
59: if (on(*tp, CMAGICHIT) && pstats.s_lvl > 15)
60: return(TRUE);
61: if (on(*tp, BMAGICHIT) && pstats.s_lvl > 10)
62: return(TRUE);
63: if (on(*tp, MAGICHIT) && pstats.s_lvl > 5)
64: return(TRUE);
65: }
66: return(FALSE);
67: }
68:
69: /*
70: * fight:
71: * The player attacks the monster.
72: */
73:
74: bool
75: fight(coord *mp, struct object *weap, bool thrown)
76: {
77: register struct thing *tp;
78: register struct linked_list *item;
79: register bool did_hit = TRUE;
80: bool see_def, back_stab = FALSE;
81: register char *mname;
82:
83: /*
84: * Find the monster we want to fight
85: */
86: if ((item = find_mons(mp->y, mp->x)) == NULL) {
87: return(FALSE); /* must have killed him already */
88: }
89: tp = THINGPTR(item);
90:
91: /*
92: * Since we are fighting, things are not quiet so no healing takes
93: * place. The -1 also tells us that we are in a fight.
94: */
95: player.t_quiet = -1;
96: tp->t_quiet = -1;
97:
98: see_def = ((off(*tp, ISINVIS) || on(player, CANSEE)) &&
99: (off(*tp, ISSHADOW) || on(player, CANSEE)) &&
100: (!thrown || cansee(unc(tp->t_pos))));
101:
102: mname = see_def ? monster_name(tp) : "something";
103:
104: /*
105: * if its in the wall, we can't hit it
106: */
107: if (on(*tp, ISINWALL) && off(player, CANINWALL))
108: return(FALSE);
109:
110: if (on(*tp, ISSTONE)) {
111: killed(item, FALSE, FALSE, FALSE);
112: if (see_def)
113: msg("%s shatters into a million pieces!", prname(mname, TRUE));
114: count = 0;
115: return (TRUE);
116: }
117: /*
118: * Let him know it was really a mimic (if it was one).
119: */
120: if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise) &&
121: off(player, ISBLIND))
122: {
123: if (see_def) {
124: msg("Wait! That's a %s!", mname);
125: turn_off(*tp, ISDISGUISE);
126: }
127: did_hit = thrown;
128: }
129: if (on(*tp, CANSURPRISE) && off(player, ISBLIND) && !ISWEARING(R_ALERT)) {
130: if (see_def) {
131: msg("Wait! There's a %s!", mname);
132: turn_off(*tp, CANSURPRISE);
133: }
134: did_hit = thrown;
135: }
136:
137: /*
138: * if he's a thief or assassin and the creature is asleep then he gets
139: * a chance for a backstab
140: */
141: if ((player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN) &&
142: !thrown &&
143: !on(*tp, NOSTAB) &&
144: !invisible(tp) &&
145: (!on(*tp, ISRUN) || on(*tp, ISHELD) || tp->t_action == A_FREEZE))
146: back_stab = TRUE;
147:
148: /*
149: * assassins get an assassination chance, if it fails then its normal
150: * damage
151: */
152: if (back_stab && player.t_ctype == C_ASSASSIN) {
153: int chance;
154:
155: chance = 50 + (pstats.s_lvl - tp->t_stats.s_lvl) * 5;
156: if (cur_weapon && (cur_weapon->o_flags & ISPOISON))
157: chance += 20;
158: if (roll(1,100) > chance || on(*tp, ISUNIQUE))
159: back_stab = FALSE;
160: }
161:
162: runto(tp, &hero);
163:
164: /* Let the monster know that the player has missiles! */
165: if (thrown) tp->t_wasshot = TRUE;
166:
167: if (did_hit)
168: {
169:
170: did_hit = FALSE;
171: if (!can_blink(tp) &&
172: player_can_hit(tp, weap) &&
173: roll_em(&player, tp, weap, thrown, cur_weapon, back_stab))
174: {
175: did_hit = TRUE;
176:
177: if (on(*tp, NOMETAL) && weap != NULL &&
178: weap->o_type != RELIC && weap->o_flags & ISMETAL) {
179: msg("Your %s passes right through %s!",
180: weaps[weap->o_which].w_name, prname(mname, FALSE));
181: }
182: else if (weap != NULL && weap->o_type == MISSILE && on(*tp, CARRYBAMULET)) {
183: msg("The magic missile has no effect on %s. ",
184: prname(mname, FALSE));
185: }
186: else {
187: hit(thrown ? (struct object *)NULL : weap,
188: TRUE, see_def,
189: thrown ? weap_name(weap) : NULL,
190: mname, back_stab, thrown, terse);
191:
192: /* See if there are any special effects */
193: if (effect(&player, tp, weap, thrown, TRUE, see_def) != 0)
194: killed(item, FALSE, FALSE, TRUE);
195:
196: /*
197: * Merchants just disappear if hit
198: */
199: else if (on(*tp, CANSELL)) {
200: if (see_def)
201: msg("%s disappears with his wares in a flash! ",
202: prname(mname, FALSE));
203: killed(item, FALSE, FALSE, FALSE);
204: }
205:
206: else if (tp->t_stats.s_hpt <= 0)
207: killed(item, TRUE, TRUE, TRUE);
208:
209: else {
210: /* If the victim was charmed, it now gets a saving throw! */
211: if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
212: msg("The eyes of %s turn clear.", prname(mname, FALSE));
213: turn_off(*tp, ISCHARMED);
214: }
215:
216: dsrpt_monster(tp, FALSE, see_def); /* Disrupt a spell? */
217: }
218: }
219: }
220: else {
221: miss(thrown ? (struct object *)NULL : weap,
222: TRUE, see_def,
223: thrown ? weap_name(weap) : (char *)NULL,
224: mname, thrown, terse);
225: }
226: }
227: count = 0;
228: return did_hit;
229: }
230:
231: /*
232: * attack:
233: * The monster attacks the player
234: */
235:
236: bool
237: attack(struct thing *mp, struct object *weapon, bool thrown)
238: {
239: register char *mname;
240: register bool see_att, did_hit = FALSE;
241: register struct object *wielded; /* The wielded weapon */
242: struct linked_list *get_wield; /* Linked list header for wielded */
243:
244: /*
245: * Since this is an attack, stop running and any healing that was
246: * going on at the time. The -1 also tells us that we're fighting.
247: */
248: running = FALSE;
249: player.t_quiet = -1;
250: mp->t_quiet = -1;
251:
252: if (on(*mp, ISDISGUISE) && off(player, ISBLIND))
253: turn_off(*mp, ISDISGUISE);
254:
255: see_att = ((off(*mp, ISINVIS) || on(player, CANSEE)) &&
256: (off(*mp, ISSHADOW) || on(player, CANSEE)) &&
257: (!thrown || cansee(unc(mp->t_pos))));
258:
259: mname = see_att ? monster_name(mp) : "something";
260:
261: /*
262: * Try to find a weapon to wield. Wield_weap will return a
263: * projector if weapon is a projectile (eg. bow for arrow).
264: * If weapon is NULL, it will try to find a suitable weapon.
265: */
266: get_wield = wield_weap(weapon, mp);
267: if (get_wield) wielded = OBJPTR(get_wield);
268: else wielded = NULL;
269:
270: /* If we aren't wielding a weapon, wield what we found (could be NULL) */
271: if (weapon == NULL) weapon = wielded;
272:
273: if (roll_em(mp, &player, weapon, thrown, wielded, FALSE)) {
274: int death_type; /* From one of the effects of getting hit */
275:
276: did_hit = TRUE;
277:
278: if (weapon != NULL && weapon->o_type == MISSILE && cur_relic[STONEBONES_AMULET]) {
279: hit(weapon, see_att, TRUE, mname, (char *)NULL, FALSE, thrown, terse);
280: msg("Your amulet absorbs the magic missile. ");
281: }
282: else {
283: hit(weapon, see_att, TRUE, mname, (char *)NULL, FALSE, thrown, terse);
284: dsrpt_player(); /* see if we disrupted some activity */
285: if (pstats.s_hpt <= 0)
286: death(mp->t_index); /* Bye bye life ... */
287: death_type = effect(mp, &player, weapon, thrown, see_att, TRUE);
288: if (death_type != 0) {
289: pstats.s_hpt = -1;
290: death(death_type);
291: }
292: }
293:
294: }
295: else {
296: /* If the thing was trying to surprise, no good */
297: if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
298:
299: /* If it couldn't surprise, let's tell the player. */
300: else miss(weapon, see_att, TRUE, mname, (char *)NULL, thrown, terse);
301: }
302: if (fight_flush) flushinp();
303: count = 0;
304: status(FALSE);
305: return(did_hit);
306: }
307:
308: /*
309: * swing:
310: * returns true if the swing hits
311: */
312:
313: bool
314: swing(short class, int at_lvl, int op_arm, int wplus)
315: {
316: register int res = rnd(20)+1;
317: register int need;
318:
319: need = char_class[class].base -
320: char_class[class].factor *
321: ((min(at_lvl, char_class[class].max_lvl) -
322: char_class[class].offset)/char_class[class].range) +
323: (10 - op_arm);
324: if (need > 20 && need <= 25) need = 20;
325:
326: return (res+wplus >= need);
327: }
328:
329: /*
330: * roll_em:
331: * Roll several attacks
332: */
333:
334: bool
335: roll_em(struct thing *att_er, struct thing *def_er, struct object *weap,
336: bool hurl, struct object *cur_weapon, bool back_stab)
337: {
338: register struct stats *att, *def;
339: register char *cp = NULL;
340: register int ndice, nsides, nplus, def_arm;
341: char dmgbuf[20];
342: bool did_hit = FALSE;
343: int prop_hplus, prop_dplus;
344: int vampiric_damage;
345:
346: /* Get statistics */
347: att = &att_er->t_stats;
348: def = &def_er->t_stats;
349:
350: prop_hplus = prop_dplus = 0;
351: if (weap == NULL) {
352: /*
353: * monks damage grows with level
354: */
355: if (att == &pstats && player.t_ctype == C_MONK) {
356: sprintf(dmgbuf, "%dd4", att->s_lvl/3+2);
357: cp = dmgbuf;
358: }
359: else
360: cp = att->s_dmg;
361: }
362: else if (weap->o_type == RELIC) {
363: switch (weap->o_which) {
364: case MUSTY_DAGGER:
365: if (player.t_ctype == C_THIEF)
366: cp = "4d8+2/4d8+2";
367: else
368: cp = "4d8/4d8";
369: when YEENOGHU_FLAIL:
370: cp = "4d8+3/paralyze/confuse";
371: when HRUGGEK_MSTAR:
372: cp = "4d8+3";
373: when AXE_AKLAD:
374: if (player.t_ctype == C_FIGHTER) {
375: if (hurl)
376: cp = "4d8+6/drain";
377: else
378: cp = "4d8+4/drain";
379: }
380: else {
381: if (hurl)
382: cp = "4d8+4/drain";
383: else
384: cp = "4d8+2/drain";
385: }
386: when MING_STAFF:
387: cp = "4d8+4";
388: when ASMO_ROD:
389: cp = "4d8/4d8";
390: when ORCUS_WAND:
391: cp = "4d8/destroy";
392: }
393: }
394: else if (hurl) {
395: if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
396: cur_weapon->o_which == weap->o_launch)
397: {
398: cp = weap->o_hurldmg;
399: prop_hplus = cur_weapon->o_hplus;
400: prop_dplus = cur_weapon->o_dplus;
401: }
402: else
403: cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg);
404: }
405: else {
406: cp = weap->o_damage;
407: /*
408: * Drain a staff of striking
409: */
410: if(weap->o_type==STICK && weap->o_which==WS_HIT && weap->o_charges==0)
411: {
412: strcpy(weap->o_damage,"4d8");
413: weap->o_hplus = weap->o_dplus = 0;
414: }
415: }
416: /*
417: * If defender is wearing a cloak of displacement -- no damage
418: * the first time. (unless its a hurled magic missile or the
419: * attacker is very smart and can see thru the illusion)
420: */
421: if ((weap == NULL || weap->o_type != MISSILE) &&
422: def == &pstats &&
423: off(*att_er, MISSEDDISP) &&
424: att->s_intel < 21 &&
425: ((cur_misc[WEAR_CLOAK]!=NULL &&
426: cur_misc[WEAR_CLOAK]->o_which==MM_DISP) ||
427: cur_relic[EMORI_CLOAK])) {
428: turn_on(*att_er, MISSEDDISP);
429: if (cansee(att_er->t_pos.y, att_er->t_pos.x) && !invisible(att_er))
430: msg("%s looks amazed! ", prname(monster_name(att_er), TRUE));
431: return (FALSE);
432: }
433: if (on(*def_er, CARRYCLOAK) &&
434: def != &pstats &&
435: (weap == NULL || weap->o_type != MISSILE) &&
436: off (*att_er, MISSEDDISP) &&
437: pstats.s_intel < 21) {
438: turn_on(*att_er, MISSEDDISP);
439: msg("You feel amazed! ");
440: return(FALSE);
441: }
442: for (;;)
443: {
444: int damage;
445: int hplus = prop_hplus;
446: int dplus = prop_dplus;
447:
448: if (weap != NULL && weap->o_type == RELIC) {
449: switch (weap->o_which) {
450: case MUSTY_DAGGER:
451: if (att != &pstats || /* Not player or good stats */
452: (str_compute() > 15 && dex_compute() > 15)) {
453:
454: hplus += 6;
455: dplus += 6;
456:
457: /* Give an additional strength and dex bonus */
458: if (att == &pstats) {
459: hplus += str_plus(str_compute()) +
460: dext_plus(dex_compute());
461: dplus += dext_plus(dex_compute()) +
462: add_dam(str_compute());
463: }
464: else {
465: hplus += str_plus(att->s_str) +
466: dext_plus(att->s_dext);
467: dplus += dext_plus(att->s_dext) +
468: add_dam(att->s_str);
469: }
470: }
471: else {
472: hplus -= 3;
473: dplus -= 3;
474: }
475: when YEENOGHU_FLAIL:
476: case HRUGGEK_MSTAR:
477: hplus += 3;
478: dplus += 3;
479: when MING_STAFF:
480: hplus += 2;
481: dplus += 2;
482: when AXE_AKLAD:
483: hplus += 5;
484: dplus += 5;
485: }
486: }
487: else if (weap != NULL) {
488: hplus += weap->o_hplus;
489: dplus += weap->o_dplus;
490: }
491:
492: /* Is attacker weak? */
493: if (on(*att_er, HASSTINK)) hplus -= 2;
494:
495: if (att == &pstats) /* Is the attacker the player? */
496: {
497: hplus += hitweight(); /* adjust for encumberence */
498: dplus += hung_dam(); /* adjust damage for hungry player */
499: dplus += ring_value(R_ADDDAM);
500: }
501: if (back_stab || (weap && att != &pstats && on(*att_er, CANBSTAB)))
502: hplus += 4; /* add in pluses for backstabbing */
503:
504: /* Get the damage */
505: while (isspace(*cp)) cp++;
506: if (!isdigit(*cp)) {
507: if (strncmp(cp, "confuse", 7) == 0) ndice = CONF_DAMAGE;
508: else if (strncmp(cp, "paralyze", 8) == 0) ndice = PARAL_DAMAGE;
509: else if (strncmp(cp, "destroy", 6) == 0) ndice = DEST_DAMAGE;
510: else if (strncmp(cp, "drain", 5) == 0) ndice = DRAIN_DAMAGE;
511: else ndice = 0;
512: nsides = 0;
513: nplus = 0;
514: }
515: else {
516: char *oldcp;
517:
518: /* Get the number of damage dice */
519: ndice = atoi(cp);
520: if ((cp = strchr(cp, 'd')) == NULL)
521: break;
522:
523: /* Skip the 'd' and get the number of sides per die */
524: nsides = atoi(++cp);
525:
526: /* Check for an addition -- save old place in case none is found */
527: oldcp = cp;
528: if ((cp = strchr(cp, '+')) != NULL) nplus = atoi(++cp);
529: else {
530: nplus = 0;
531: cp = oldcp;
532: }
533: }
534:
535: if (def == &pstats) { /* Monster attacks player */
536: if (on(*att_er, NOMETAL))
537: def_arm = ac_compute(TRUE) - dext_prot(dex_compute());
538: else
539: def_arm = ac_compute(FALSE) - dext_prot(dex_compute());
540: hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
541: }
542: else if (att == &pstats) { /* Player attacks monster */
543: def_arm = def->s_arm - dext_prot(def->s_dext);
544: if (player.t_ctype == C_MONK) /* no strength bonus for monk */
545: if (weap == NULL)
546: hplus += att->s_lvl/5; /* monks hplus varies with level */
547: else
548: hplus += str_plus(str_compute())+dext_plus(dex_compute());
549: }
550: else { /* Monster attacks monster */
551: def_arm = def->s_arm - dext_prot(def->s_dext);
552: hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
553: }
554:
555: if (swing(att_er->t_ctype, att->s_lvl, def_arm, hplus)) {
556: register int proll;
557:
558: /* Take care of special effects */
559: switch (ndice) {
560: case CONF_DAMAGE:
561: if (def == &pstats) { /* Monster attacks player */
562: if (!save(VS_MAGIC, &player, 0) && off(player, ISCLEAR)) {
563: msg("You feel disoriented.");
564: if (find_slot(unconfuse))
565: lengthen(unconfuse, HUHDURATION);
566: else
567: fuse(unconfuse, NULL, HUHDURATION, AFTER);
568: turn_on(player, ISHUH);
569: }
570: else msg("You feel dizzy, but it quickly passes.");
571: }
572: /* Player or monster hits monster */
573: else if (!save(VS_MAGIC, def_er, 0) && off(*def_er, ISCLEAR)) {
574: if (att == &pstats) {
575: if (rnd(10) > 6)
576: msg("The artifact warms you with pleasure! ");
577: }
578: turn_on(*def_er, ISHUH);
579: }
580: did_hit = TRUE;
581: when PARAL_DAMAGE:
582: if (def == &pstats) { /* Monster attacks player */
583: if (!save(VS_MAGIC, &player, 0) && off(player, CANINWALL)) {
584: msg("You stiffen up.");
585: player.t_no_move += movement(&player) * FREEZETIME;
586: player.t_action = A_FREEZE;
587: }
588: }
589: else if (!save(VS_MAGIC, def_er, 0)) { /* Player hits monster */
590: if (att == &pstats) {
591: if (rnd(10) > 6)
592: msg("The artifact hums happily! ");
593: }
594: turn_off(*def_er, ISRUN);
595: turn_on(*def_er, ISHELD);
596: }
597: did_hit = TRUE;
598: when DEST_DAMAGE:
599: if (def == &pstats) { /* Monster attacks player */
600: if (rnd(10) > 5)
601: msg("You feel a tug at your life force.");
602: if (!save(VS_MAGIC, &player, -4)) {
603: msg("The wand devours your soul! --More--");
604: wait_for(' ');
605: def->s_hpt = -1;
606: death(D_RELIC);
607: }
608: }
609: /* Player hits monster */
610: else if (!save(VS_MAGIC, def_er, -4)) {
611: if (att == &pstats) {
612: if (rnd(10) > 4)
613: msg("The artifact draws some energy.");
614: }
615: /* The player loses some major hit pts */
616: att->s_hpt -= (att->s_hpt/5)+1;
617: if (att->s_hpt <= 0) {
618: msg("The wand has devoured your soul! --More--");
619: wait_for(' ');
620: att->s_hpt = -1;
621: death(D_RELIC);
622: }
623: /* Kill the monster */
624: def->s_hpt = 0;
625: }
626: did_hit = TRUE;
627: when DRAIN_DAMAGE:
628: if (def == &pstats) { /* Monster attacks player */
629: if (!save(VS_MAGIC, &player, -4)) {
630: lower_level(att_er->t_index);
631: }
632: }
633: /* Player hits monster */
634: else if (!save(VS_MAGIC, def_er, -4)) {
635: def->s_hpt -= roll(1, 8);
636: def->s_lvl--;
637: if (def->s_lvl <= 0)
638: def->s_hpt = 0; /* he's dead */
639: if (att == &pstats) {
640: if (rnd(10) > 7)
641: msg("The artifact cackles with laughter! ");
642: }
643: }
644: did_hit = TRUE;
645: otherwise:
646: /* Heil's ankh always gives maximum damage */
647: if (att == &pstats && cur_relic[HEIL_ANKH])
648: proll = ndice * nsides;
649: else proll = roll(ndice, nsides);
650:
651: if (ndice + nsides > 0 && proll < 1)
652: debug("Damage for %dd%d came out %d.",
653: ndice, nsides, proll);
654: damage = dplus + proll + nplus;
655: if (att == &pstats) {
656: /*
657: * Monks do not get strength bonus on damage. Instead,
658: * if they are wielding a weapon, they get at extra
659: * 1/2 point per level of damage.
660: */
661: if(player.t_ctype == C_MONK) {
662: /* Bonus does not apply for hands. */
663: if (weap != NULL) damage += att->s_lvl / 2;
664: }
665: else
666: damage += add_dam(str_compute());
667: }
668: else
669: damage += add_dam(att->s_str);
670:
671: /* Check for half damage monsters */
672: if (on(*def_er, HALFDAMAGE)) damage /= 2;
673:
674: /* add in multipliers for backstabbing */
675: if (back_stab ||
676: (weap && att != &pstats && on(*att_er, CANBSTAB))) {
677: int mult = 2 + (att->s_lvl-1)/4; /* Normal multiplier */
678:
679: if (mult > 5)
680: mult = 5;
681: if (weap && weap->o_type == RELIC &&
682: weap->o_which == MUSTY_DAGGER)
683: mult++;
684: damage *= mult;
685: }
686: if (att == &pstats) {
687: if (cur_weapon && (cur_weapon->o_flags & ISPOISON)) {
688: cur_weapon->o_flags &= ~ISPOISON;
689: if (save(VS_POISON, def_er, -2))
690: damage += def->s_hpt/4;
691: else
692: damage += def->s_hpt/2;
693: }
694: if (back_stab && player.t_ctype == C_ASSASSIN)
695: damage = def->s_hpt + 1;
696: }
697: /* Check for no-damage and division */
698: if (on(*def_er, BLOWDIVIDE)) {
699: damage = 0;
700: creat_mons(def_er, def_er->t_index, FALSE);
701: if (cansee(unc(def_er->t_pos))) light(&hero);
702: }
703: /* check for immunity to metal -- RELICS are always bad */
704: if (on(*def_er, NOMETAL) && weap != NULL &&
705: weap->o_type != RELIC && weap->o_flags & ISMETAL) {
706: damage = 0;
707: }
708: if (weap != NULL && weap->o_type == MISSILE) {
709: if ((def == &pstats && cur_relic[STONEBONES_AMULET]) ||
710: (att == &pstats && on(*def_er, CARRYBAMULET))) {
711: damage = 0;
712: }
713: }
714: def->s_hpt -= max(0, damage); /* Do the damage */
715: did_hit = TRUE;
716: vampiric_damage = damage;
717: if (def->s_hpt < 0) /* only want REAL damage inflicted */
718: vampiric_damage += def->s_hpt;
719: if (vampiric_damage < 0)
720: vampiric_damage = 0;
721: if (att == &pstats && ISWEARING(R_VAMPREGEN) && !hurl) {
722: if ((pstats.s_hpt += vampiric_damage/2) > max_stats.s_hpt)
723: pstats.s_hpt = max_stats.s_hpt;
724: }
725: if (hplus < 0) hplus = 0;
726: if (damage < 0) damage = 0;
727: debug ("hplus=%d dmg=%d", hplus, damage);
728: }
729: }
730: if ((cp = strchr(cp, '/')) == NULL)
731: break;
732: cp++;
733: }
734: return did_hit;
735: }
736:
737: /*
738: * prname:
739: * The print name of a combatant
740: */
741:
742: char *
743: prname(char *who, bool upper)
744: {
745: static char tbuf[LINELEN];
746:
747: *tbuf = '\0';
748: if (who == 0)
749: strcpy(tbuf, "you");
750: else if (on(player, ISBLIND) || strcmp(who, "something") == 0)
751: strcpy(tbuf, "something");
752: else
753: {
754: /* If we have a name (starts with a capital), don't use a "the" */
755: if (islower(*who)) strcpy(tbuf, "the ");
756: strcat(tbuf, who);
757: }
758: if (upper)
759: *tbuf = toupper(*tbuf);
760: return tbuf;
761: }
762:
763: /*
764: * hit:
765: * Print a message to indicate a succesful hit
766: */
767:
768: void
769: hit(struct object *weapon, bool see_att, bool see_def, char *er, char *ee,
770: bool back_stab, bool thrown, bool short_msg)
771: {
772: register char *s = NULL;
773: char att_name[LINELEN], /* Name of attacker */
774: def_name[LINELEN]; /* Name of defender */
775:
776: /* If we can't see either the attacker or defender, don't say anything */
777: if (!see_att && !see_def) return;
778:
779: /* What do we call the attacker? */
780: strcpy(att_name, see_att ? prname(er, TRUE) : "Something");
781: if (er) { /* A monster is attacking */
782:
783: /* If the monster is using a weapon and we can see it, report it */
784: if (weapon != NULL && (see_att || thrown)) {
785: strcat(att_name, "'s ");
786: strcat(att_name, weap_name(weapon));
787: }
788: }
789:
790: /* What do we call the defender? */
791: strcpy(def_name, see_def ? prname(ee, FALSE) : "something");
792:
793: addmsg(att_name);
794: if (short_msg) {
795: if (back_stab) {
796: if (player.t_ctype == C_ASSASSIN)
797: s = (er == 0 ? " assassinate!" : " assassinates!");
798: else
799: s = (er == 0 ? " backstab!" : " backstabs!");
800: }
801: else
802: s = " hit.";
803: }
804: else {
805: if (back_stab) {
806: if (player.t_ctype == C_ASSASSIN)
807: s = (er == 0 ? " have assassinated " : " has assassinated ");
808: else
809: s = (er == 0 ? " have backstabbed " : " has backstabbed ");
810: }
811: else {
812: switch (rnd(thrown ? 2 : 3))
813: {
814: case 0: s = " hit ";
815: when 1: s = " injured ";
816: when 2: s = " smacked ";
817: }
818: }
819: }
820: if (short_msg) addmsg(s);
821: else addmsg("%s%s.", s, def_name);
822: endmsg();
823: }
824:
825: /*
826: * miss:
827: * Print a message to indicate a poor swing
828: */
829:
830: void
831: miss(struct object *weapon, bool see_att, bool see_def, char *er, char *ee,
832: bool thrown, bool short_msg)
833: {
834: register char *s = NULL;
835: char att_name[LINELEN], /* Name of attacker */
836: def_name[LINELEN]; /* Name of defender */
837:
838: /* If we can't see either the attacker or defender, don't say anything */
839: if (!see_att && !see_def) return;
840:
841: /* What do we call the attacker? */
842: strcpy(att_name, see_att ? prname(er, TRUE) : "Something");
843: if (er) { /* A monster is attacking */
844:
845: /* If the monster is using a weapon and we can see it, report it */
846: if (weapon != NULL && (see_att || thrown)) {
847: strcat(att_name, "'s ");
848: strcat(att_name, weap_name(weapon));
849: }
850: }
851:
852: /* What do we call the defender? */
853: strcpy(def_name, see_def ? prname(ee, FALSE) : "something");
854:
855: addmsg(att_name);
856: switch (short_msg ? 0 : rnd(thrown ? 3 : 2))
857: {
858: case 0: s = (er == 0 ? " miss" : " misses");
859: when 1: s = (er == 0 ? " don't hit" : " doesn't hit");
860: when 2: s = (" whizzes by");
861: }
862: if (short_msg) addmsg("%s.", s);
863: else addmsg("%s %s.", s, def_name);
864: endmsg();
865: }
866:
867: /*
868: * dext_plus:
869: * compute to-hit bonus for dexterity
870: */
871:
872: int
873: dext_plus(int dexterity)
874: {
875: return (dexterity > 10 ? (dexterity-13)/3 : (dexterity-10)/3);
876: }
877:
878:
879: /*
880: * dext_prot:
881: * compute armor class bonus for dexterity
882: */
883:
884: int
885: dext_prot(int dexterity)
886: {
887: return ((dexterity-10)/2);
888: }
889:
890: /*
891: * str_plus:
892: * compute bonus/penalties for strength on the "to hit" roll
893: */
894:
895: int
896: str_plus(short str)
897: {
898: return((str-10)/3);
899: }
900:
901: /*
902: * add_dam:
903: * compute additional damage done for exceptionally high or low strength
904: */
905:
906: int
907: add_dam(short str)
908: {
909: return((str-9)/2);
910: }
911:
912: /*
913: * hung_dam:
914: * Calculate damage depending on players hungry state
915: */
916:
917: int
918: hung_dam(void)
919: {
920: reg int howmuch = 0;
921:
922: switch(hungry_state) {
923: case F_SATIATED:
924: case F_OKAY:
925: case F_HUNGRY: howmuch = 0;
926: when F_WEAK: howmuch = -1;
927: when F_FAINT: howmuch = -2;
928: }
929: return howmuch;
930: }
931:
932: /*
933: * is_magic:
934: * Returns true if an object radiates magic
935: */
936:
937: bool
938: is_magic(struct object *obj)
939: {
940: switch (obj->o_type)
941: {
942: case ARMOR:
943: return obj->o_ac != armors[obj->o_which].a_class;
944: when WEAPON:
945: return obj->o_hplus != 0 || obj->o_dplus != 0;
946: when POTION:
947: case SCROLL:
948: case STICK:
949: case RING:
950: case MM:
951: case RELIC:
952: return TRUE;
953: }
954: return FALSE;
955: }
956:
957: /*
958: * killed:
959: * Called to put a monster to death
960: */
961:
962: void
963: killed(struct linked_list *item, bool pr, bool points, bool treasure)
964: {
965: register struct thing *tp, *mp;
966: register struct linked_list *pitem, *nexti, *mitem;
967: char *monst;
968: int adj; /* used for hit point adj. below. */
969:
970: tp = THINGPTR(item);
971:
972: if (pr)
973: {
974: addmsg(terse ? "Defeated " : "You have defeated ");
975: if (on(player, ISBLIND))
976: msg("it.");
977: else
978: {
979: if (cansee(tp->t_pos.y, tp->t_pos.x) && !invisible(tp))
980: monst = monster_name(tp);
981: else {
982: if (terse) monst = "something";
983: else monst = "thing";
984: }
985: if (!terse)
986: addmsg("the ");
987: msg("%s.", monst);
988: }
989: }
990:
991: /* Take care of any residual effects of the monster */
992: check_residue(tp);
993:
994: /* Make sure that no one is still chasing us */
995: for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
996: mp = THINGPTR(mitem);
997: if (mp->t_dest == &tp->t_pos) {
998: mp->t_dest = &hero;
999: mp->t_wasshot = FALSE;
1000: turn_off(*mp, ISFLEE); /* Be sure we aren't running away! */
1001: }
1002: }
1003: if (points) { /* you feel uneasy for a moment */
1004: if ((off(*tp, ISMEAN) || on(*tp, ISFRIENDLY)) &&
1005: (player.t_ctype == C_RANGER || player.t_ctype == C_PALADIN ||
1006: player.t_ctype == C_MONK)) {
1007: if (tp->t_stats.s_exp > pstats.s_exp)
1008: pstats.s_exp = 0;
1009: else
1010: pstats.s_exp -= tp->t_stats.s_exp;
1011: /* Take care of hit points. */
1012: if (level <= 12) adj = rnd(2)+1;
1013: else if (level <= 25) adj = rnd(3)+2;
1014: else if (level <= 50) adj = rnd(4)+3;
1015: else if (level <= 80) adj = rnd(5)+4;
1016: else adj = rnd(6)+5;
1017: /* adjust hit points */
1018: max_stats.s_hpt -= adj;
1019: pstats.s_hpt -= adj;
1020: /* Are hit points now too low? */
1021: if (pstats.s_hpt <= 0) {
1022: pstats.s_hpt = -1;
1023: death(D_STRENGTH);
1024: }
1025: killed_chance += rnd(3)+1;
1026: if (on(*tp, ISUNIQUE)) /* real bad news to kill a diety */
1027: killed_chance += 25;
1028: if (roll(1,100) < killed_chance) {
1029: msg("You had a feeling this was going to happen... ");
1030: msg("**POOF** ");
1031: changeclass(C_ASSASSIN); /* make him pay */
1032: }
1033: else {
1034: switch (rnd(9)) {
1035: case 0:
1036: msg("You become solid and stiff for a while. ");
1037: player.t_no_move += (5*movement(&player)*FREEZETIME);
1038: player.t_action = A_FREEZE;
1039: when 1:
1040: msg("You collapse, losing it totally. ");
1041: player.t_no_move += (2*movement(&player)*FREEZETIME);
1042: player.t_action = A_FREEZE;
1043: when 2:
1044: msg("Your face changes shape! ARGGHH!!!! ");
1045: pstats.s_charisma -= rnd(8)+3;
1046: if (pstats.s_charisma <= 3) pstats.s_charisma = 3;
1047: when 3:
1048: case 4:
1049: msg("You cry out, I didn't mean to do that! Honest!! ");
1050: player.t_no_move += (movement(&player)*FREEZETIME);
1051: msg("The Great Old Ones grant you a reprieve. ");
1052: otherwise: msg("You feel uneasy for a moment.. ");
1053: }
1054: }
1055: }
1056: else {
1057: unsigned long test; /* For overflow check */
1058: /*
1059: * Do an overflow check before increasing experience
1060: */
1061: test = pstats.s_exp + tp->t_stats.s_exp;
1062: if (test > pstats.s_exp)
1063: pstats.s_exp = test;
1064: }
1065:
1066: /*
1067: * Do adjustments if he went up a level
1068: */
1069: check_level();
1070: }
1071:
1072: /*
1073: * Empty the monsters pack
1074: */
1075: pitem = tp->t_pack;
1076:
1077: /*
1078: * Get rid of the monster.
1079: */
1080: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' ');
1081: mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
1082: detach(mlist, item);
1083: if (on(*tp, AREMANY) && levtype == NORMLEV) /* AREMANYs stick together */
1084: wake_room(roomin(&tp->t_pos));
1085: /*
1086: * empty his pack
1087: */
1088: while (pitem != NULL)
1089: {
1090: nexti = next(pitem);
1091: (OBJPTR(pitem))->o_pos = tp->t_pos;
1092: detach(tp->t_pack, pitem);
1093: if (treasure)
1094: fall(pitem, FALSE);
1095: else
1096: o_discard(pitem);
1097: pitem = nexti;
1098: }
1099:
1100: turn_on(*tp,ISDEAD);
1101: attach(rlist,item);
1102: }
1103:
1104: /*
1105: * Returns a pointer to the weapon the monster is wielding corresponding to
1106: * the given thrown weapon. If no thrown item is given, try to find any
1107: * decent weapon.
1108: */
1109:
1110: struct linked_list *
1111: wield_weap(struct object *thrown, struct thing *mp)
1112: {
1113: int look_for = 0, /* The projectile weapon we are looking for */
1114: new_rate, /* The rating of a prospective weapon */
1115: cand_rate = -1; /* Rating of current candidate -- higher is better */
1116: register struct linked_list *pitem, *candidate = NULL;
1117: register struct object *obj;
1118:
1119: if (thrown != NULL) { /* Using a projectile weapon */
1120: switch (thrown->o_which) {
1121: case BOLT: look_for = CROSSBOW; /* Find the crossbow */
1122: when ARROW: look_for = BOW; /* Find the bow */
1123: when ROCK: look_for = SLING; /* find the sling */
1124: otherwise: return(NULL);
1125: }
1126: }
1127: else if (off(*mp, ISUNIQUE) && off(*mp, CARRYWEAPON)) return(NULL);
1128:
1129: for (pitem=mp->t_pack; pitem; pitem=next(pitem)) {
1130: obj = OBJPTR(pitem);
1131:
1132: /*
1133: * If we have a thrown weapon, just return the first match
1134: * we come to.
1135: */
1136: if (thrown != NULL && obj->o_type == WEAPON && obj->o_which == look_for)
1137: return(pitem);
1138:
1139: /* If we have a usable RELIC, return it */
1140: if (thrown == NULL && obj->o_type == RELIC) {
1141: switch (obj->o_which) {
1142: case MUSTY_DAGGER:
1143: case YEENOGHU_FLAIL:
1144: case HRUGGEK_MSTAR:
1145: case AXE_AKLAD:
1146: case MING_STAFF:
1147: case ASMO_ROD:
1148: case ORCUS_WAND:
1149: return(pitem);
1150: }
1151: }
1152:
1153: /* Otherwise if it's a usable weapon, it is a good candidate */
1154: else if (thrown == NULL && obj->o_type == WEAPON) {
1155: switch (obj->o_which) {
1156: case DAGGER:
1157: case SPEAR:
1158: new_rate = 0;
1159: when BATTLEAXE:
1160: new_rate = 1;
1161: when MACE:
1162: new_rate = 2;
1163: when SWORD:
1164: new_rate = 3;
1165: when PIKE:
1166: new_rate = 4;
1167: when HALBERD:
1168: case SPETUM:
1169: new_rate = 6;
1170: when BARDICHE:
1171: new_rate = 7;
1172: when TRIDENT:
1173: new_rate = 8;
1174: when BASWORD:
1175: new_rate = 9;
1176: when TWOSWORD:
1177: new_rate = 10;
1178: otherwise:
1179: new_rate = -1;
1180: }
1181:
1182: /* Only switch if this is better than the current candidate */
1183: if (new_rate > cand_rate) {
1184: cand_rate = new_rate;
1185: candidate = pitem;
1186: }
1187: }
1188: }
1189:
1190: return(candidate);
1191: }
1192:
1193: void
1194: explode(struct thing *tp)
1195: {
1196:
1197: register int x,y, damage;
1198: struct linked_list *item;
1199: struct thing *th;
1200:
1201: /*
1202: * check to see if it got the hero
1203: */
1204: if (off(player, ISINWALL) &&
1205: DISTANCE(hero.x, hero.y, tp->t_pos.x, tp->t_pos.y) <= 25) {
1206: msg("The explosion hits you! ");
1207: damage = roll(6,6);
1208: if (save(VS_WAND, &player, 0))
1209: damage /= 2;
1210: pstats.s_hpt -= damage;
1211: }
1212:
1213: /*
1214: * now check for monsters in vicinity
1215: */
1216: for (x = tp->t_pos.x-5; x<=tp->t_pos.x+5; x++) {
1217: if (x < 0 || x > cols - 1)
1218: continue;
1219: for (y = tp->t_pos.y-5; y<=tp->t_pos.y+5; y++) {
1220: if (y < 1 || y > lines - 3)
1221: continue;
1222: if (isalpha(mvwinch(mw, y, x))) {
1223: if ((item = find_mons(y, x)) != NULL) {
1224: th = THINGPTR(item);
1225: if (th == tp || /* don't count gas spore */
1226: on(*th, ISINWALL)) /* Don't count monsters in wall */
1227: continue;
1228: damage = roll(6, 6);
1229: if (save(VS_WAND, th, 0))
1230: damage /= 2;
1231: runto(th, &hero);
1232: if ((th->t_stats.s_hpt -= damage) <= 0) {
1233: msg("The explosion kills %s! ",
1234: prname(monster_name(th), FALSE));
1235: killed(item, FALSE, FALSE, TRUE);
1236: }
1237: }
1238: }
1239: }
1240: }
1241: }
1242:
1243: /*
1244: * skirmish:
1245: * Called when one monster attacks another monster.
1246: */
1247:
1248: bool
1249: skirmish(struct thing *attacker, coord *mp, struct object *weap, bool thrown)
1250: {
1251: register struct thing *defender;
1252: register struct linked_list *item;
1253: register bool did_hit = TRUE, see_att, see_def;
1254: char attname[LINELEN+1], defname[LINELEN+1];
1255: struct object *wielded; /* The wielded weapon */
1256: struct linked_list *get_wield; /* Linked list header for wielded */
1257:
1258: /*
1259: * Find the monster we want to fight
1260: */
1261: if ((item = find_mons(mp->y, mp->x)) == NULL) {
1262: return(FALSE); /* must have killed him already */
1263: }
1264: defender = THINGPTR(item);
1265:
1266: /* Can the player see either of the fighters? */
1267: see_att = (cansee(unc(attacker->t_pos)) &&
1268: (off(*attacker, ISINVIS) || on(player, CANSEE)) &&
1269: (off(*attacker, ISSHADOW) || on(player, CANSEE)));
1270: see_def = (cansee(unc(defender->t_pos)) &&
1271: (off(*defender, ISINVIS) || on(player, CANSEE)) &&
1272: (off(*defender, ISSHADOW) || on(player, CANSEE)));
1273:
1274: /*
1275: * Since we are fighting, things are not quiet so no healing takes
1276: * place. The -1 also tells us that we are in a fight.
1277: */
1278: attacker->t_quiet = -1;
1279: defender->t_quiet = -1;
1280:
1281: if (see_att) strcpy(attname, monster_name(attacker));
1282: else strcpy(attname, "something");
1283:
1284: if (see_def) strcpy(defname, monster_name(defender));
1285: else strcpy(defname, "something");
1286:
1287: /*
1288: * if its in the wall, we can't hit it
1289: */
1290: if (on(*defender, ISINWALL) && off(*attacker, CANINWALL))
1291: return(FALSE);
1292:
1293: if (on(*defender, ISSTONE)) {
1294: killed(item, FALSE, FALSE, FALSE);
1295: if (see_def)
1296: msg("%s shatters into a million pieces!", prname(defname, TRUE));
1297: return (TRUE);
1298: }
1299:
1300: /*
1301: * Let him know it was really a mimic (if it was one).
1302: */
1303: if (see_def && on(*defender, ISDISGUISE) &&
1304: (defender->t_type != defender->t_disguise)) {
1305: msg("Wait! There's a %s!", defname);
1306: turn_off(*defender, ISDISGUISE);
1307: did_hit = thrown;
1308: }
1309:
1310: if (see_def && on(*defender, CANSURPRISE) && !ISWEARING(R_ALERT)) {
1311: msg("Wait! There's a %s!", defname);
1312: turn_off(*defender, CANSURPRISE);
1313: did_hit = thrown;
1314: }
1315:
1316: if (did_hit) {
1317:
1318: did_hit = FALSE;
1319:
1320: /*
1321: * Try to find a weapon to wield. Wield_weap will return a
1322: * projector if weapon is a projectile (eg. bow for arrow).
1323: * If weapon is NULL, it will try to find a suitable weapon.
1324: */
1325: get_wield = wield_weap(weap, attacker);
1326: if (get_wield) wielded = OBJPTR(get_wield);
1327: else wielded = NULL;
1328:
1329: #ifdef DOBLINK
1330: /*
1331: * For now Blink Dogs will not blink away from monsters. We
1332: * have to fix can_blink so it isn't dependant on the player
1333: * before we can add it.
1334: */
1335: if (!can_blink(defender) &&
1336: #endif
1337: if (((weap && weap->o_type == RELIC) ||
1338: ((off(*defender, MAGICHIT) ||
1339: attacker->t_stats.s_lvl > 4 ||
1340: (weap && (weap->o_hplus > 0 || weap->o_dplus > 0))) &&
1341: (off(*defender, BMAGICHIT) ||
1342: attacker->t_stats.s_lvl > 6 ||
1343: (weap && (weap->o_hplus > 1 || weap->o_dplus > 1))) &&
1344: (off(*defender, CMAGICHIT) ||
1345: attacker->t_stats.s_lvl > 8 ||
1346: (weap && (weap->o_hplus > 2 || weap->o_dplus > 2)))))
1347: && roll_em(attacker, defender, weap, thrown, wielded, FALSE))
1348: {
1349: did_hit = TRUE;
1350:
1351: /* Should we start to chase this creature? */
1352: if (attacker->t_index != defender->t_index &&
1353: (off(*defender, ISRUN) || rnd(100) < 50)) {
1354: /*
1355: * If we're intelligent enough to realize that this
1356: * is a friendly monster, we will attack the hero instead.
1357: */
1358: if (on(*attacker, ISFRIENDLY) &&
1359: roll(3,6) < defender->t_stats.s_intel) {
1360: runto(defender, &hero);
1361: debug("%s attacking %s's hero", defname, attname);
1362: }
1363:
1364: /* Otherwise, let's chase the monster */
1365: else {
1366: runto(defender, &attacker->t_pos);
1367: debug("%s now attacking %s", defname, attname);
1368: }
1369: }
1370: else if (off(*defender, ISRUN)) runto(defender, &hero);
1371:
1372: /* Let the defender know that the attacker has missiles! */
1373: if ((defender->t_dest == &attacker->t_pos) && thrown)
1374: defender->t_wasshot = TRUE;
1375:
1376: if (on(*defender, NOMETAL) && weap != NULL &&
1377: weap->o_type != RELIC && weap->o_flags & ISMETAL) {
1378: if (see_def && see_att)
1379: msg("The %s passes right through %s!",
1380: weaps[weap->o_which].w_name, prname(defname, FALSE));
1381: }
1382: else {
1383: hit(weap, see_att, see_def,
1384: attname, defname, FALSE, thrown, FALSE);
1385: }
1386:
1387: /* See if there are any special effects */
1388: if (effect(attacker, defender,
1389: weap, thrown, see_att, see_def) != 0) {
1390: killed(item, FALSE, FALSE, TRUE);
1391: if (see_def) msg("%s dies.", prname(defname, TRUE));
1392: else msg("You hear a blood-curdling scream! ");
1393: }
1394:
1395: /*
1396: * Merchants just disappear if hit
1397: */
1398: else if (on(*defender, CANSELL)) {
1399: if (see_def)
1400: msg("%s disappears with his wares in a flash! ",
1401: prname(defname, TRUE));
1402: killed(item, FALSE, FALSE, FALSE);
1403: }
1404:
1405: else if (defender->t_stats.s_hpt <= 0) {
1406: killed(item, FALSE, FALSE, TRUE);
1407: if (see_def) msg("%s dies.", prname(defname, TRUE));
1408: else msg("You hear a blood-curdling scream! ");
1409: }
1410:
1411: else {
1412: /* Did we disrupt a spell? */
1413: /* Don't turn on WASDISRUPTED since player didn't do it */
1414: if (defender->t_action == A_SUMMON ||
1415: defender->t_action == A_MISSILE) {
1416: /* Just make the old fellow start over again */
1417: defender->t_action = A_NIL;
1418: defender->t_no_move = movement(defender);
1419: defender->t_using = NULL;
1420:
1421: if (see_def)
1422: msg("%s was disrupted.", prname(defname, TRUE));
1423: }
1424:
1425: #ifdef FLEEMONST
1426: /*
1427: * If the monster is fairly intelligent and about to die,
1428: * it may turn tail and run.
1429: */
1430: if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/10)) &&
1431: (rnd(21) < tp->t_stats.s_intel)) {
1432: turn_on(*tp, ISFLEE);
1433:
1434: /* If monster was suffocating, stop it */
1435: if (on(*tp, DIDSUFFOCATE)) {
1436: turn_off(*tp, DIDSUFFOCATE);
1437: extinguish(suffocate);
1438: }
1439:
1440: /* If monster held us, stop it */
1441: if (on(*tp, DIDHOLD) && (--hold_count == 0))
1442: turn_off(player, ISHELD);
1443: turn_off(*tp, DIDHOLD);
1444:
1445: /* It is okay to turn tail */
1446: tp->t_oldpos = tp->t_pos;
1447: }
1448: #endif
1449: }
1450: }
1451: else {
1452: /* If the thing was trying to surprise, no good */
1453: if (on(*attacker, CANSURPRISE)) {
1454: /* If we can't see it, it keeps surprise (from us) */
1455: if (see_att) turn_off(*attacker, CANSURPRISE);
1456: }
1457:
1458: miss(weap, see_att, see_def, attname, defname, thrown, FALSE);
1459: }
1460: }
1461: return did_hit;
1462: }
1463:
CVSweb