[BACK]Return to fight.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / xrogue

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