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

Annotation of early-roguelike/arogue5/fight.c, Revision 1.1.1.1

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

CVSweb