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

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