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