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

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

1.1       rubenllo    1: /*
                      2:     fight.c - All the fighting gets done here
                      3:
                      4:     UltraRogue: The Ultimate Adventure in the Dungeons of Doom
                      5:     Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
                      6:     All rights reserved.
                      7:
                      8:     Based on "Advanced Rogue"
                      9:     Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
                     10:     All rights reserved.
                     11:
                     12:     Based on "Rogue: Exploring the Dungeons of Doom"
                     13:     Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
                     14:     All rights reserved.
                     15:
                     16:     See the file LICENSE.TXT for full copyright and licensing information.
                     17: */
                     18:
                     19: #include <stdlib.h>
                     20: #include <string.h>
                     21: #include <ctype.h>
                     22: #include "rogue.h"
                     23:
                     24: /*
                     25:  * This are the beginning experience levels for all players all further
                     26:  * experience levels are computed by multiplying by 2
                     27:  */
                     28:
                     29: static long e_levels[10] =
                     30: {
                     31:     143L,           /* Fighter     */
                     32:     182L,           /* Paladin     */
                     33:     169L,           /* Ranger      */
                     34:     127L,           /* Cleric      */
                     35:     154L,           /* Druid       */
                     36:     185L,           /* Magician    */
                     37:     169L,           /* Illusionist */
                     38:     112L,           /* Thief       */
                     39:     126L,           /* Assasin     */
                     40:     319L            /* Ninja       */
                     41: };
                     42:
                     43: static struct matrix att_mat[11] =
                     44: {
                     45:     /* Base, Max_lvl, Factor, Offset, Range */
                     46:
                     47:     {  10,     17,      2,      1,      2     },  /* fi */
                     48:     {  10,     17,      2,      1,      2     },  /* pa */
                     49:     {  10,     17,      2,      1,      2     },  /* ra */
                     50:     {  10,     19,      2,      1,      3     },  /* cl */
                     51:     {  10,     19,      2,      1,      3     },  /* dr */
                     52:     {   9,     21,      2,      1,      5     },  /* mu */
                     53:     {   9,     21,      2,      1,      5     },  /* il */
                     54:     {  10,     21,      2,      1,      4     },  /* th */
                     55:     {  10,     21,      2,      1,      4     },  /* as */
                     56:     {  10,     21,      2,      1,      4     },  /* nj */
                     57:     {   7,     25,      1,      0,      2     }   /* mn */
                     58: };
                     59:
                     60: void
                     61: do_fight(coord dir, int tothedeath)
                     62: {
                     63:     int x,y;
                     64:
                     65:     x = dir.x;
                     66:     y = dir.y;
                     67:
                     68:     if (!tothedeath && pstats.s_hpt < max_stats.s_hpt / 3)
                     69:     {
                     70:         msg("That's not wise.");
                     71:
                     72:         after = fighting = FALSE;
                     73:         return;
                     74:     }
                     75:
                     76:     if (isalpha(CCHAR(winat(hero.y + y, hero.x + x))))
                     77:     {
                     78:         after = fighting = TRUE;
                     79:         do_move(y, x);
                     80:     }
                     81:     else
                     82:     {
                     83:         if (fighting == FALSE)
                     84:             msg("Nothing there.");
                     85:
                     86:         after = fighting = FALSE;
                     87:     }
                     88:
                     89:     return;
                     90: }
                     91:
                     92: /*
                     93:     fight()
                     94:         The player attacks the monster.
                     95: */
                     96:
                     97: int
                     98: fight(coord *mp, struct object *weap, int thrown)
                     99: {
                    100:     struct thing    *tp;
                    101:     struct linked_list  *item;
                    102:     int    did_hit = TRUE;
                    103:     char    *mname;
                    104:
                    105:     /* Find the monster we want to fight */
                    106:
                    107:     if ((item = find_mons(mp->y, mp->x)) == NULL)
                    108:     {
                    109:         debug("Fight what @ %d,%d", mp->y, mp->x);
                    110:         return 0;
                    111:     }
                    112:
                    113:     tp = THINGPTR(item);
                    114:
                    115:     mname = (on(player, ISBLIND)) ? "it" : monsters[tp->t_index].m_name;
                    116:
                    117:     /* Since we are fighting, things are not quiet so no healing takes place */
                    118:
                    119:     player.t_rest_hpt = player.t_rest_pow = 0;
                    120:     tp->t_rest_hpt = tp->t_rest_pow = 0;
                    121:
                    122:     /*  Let him know it was really a mimic (if it was one). */
                    123:
                    124:     if (off(player, ISBLIND))
                    125:     {
                    126:         if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise))
                    127:         {
                    128:             msg("Wait! That's a %s!", mname);
                    129:             turn_off(*tp, ISDISGUISE);
                    130:             did_hit = thrown;
                    131:         }
                    132:
                    133:         if (on(*tp, CANSURPRISE))
                    134:         {
                    135:             turn_off(*tp, CANSURPRISE);
                    136:             if ((player.t_ctype == C_RANGER && rnd(6) != 0) ||
                    137:                 (player.t_ctype == C_NINJA && rnd(pstats.s_lvl / 2)
                    138:                  != 0))
                    139:                 msg("You notice a %s trying to hide!", mname);
                    140:             else
                    141:             {
                    142:                 msg("Wait! There's a %s!", mname);
                    143:                 did_hit = thrown;
                    144:             }
                    145:         }
                    146:     }
                    147:
                    148:     /* Protection from Normal Missiles */
                    149:
                    150:     if (thrown && on(*tp, HASMSHIELD))
                    151:     {
                    152:         msg("The %s slows as it approaches %s.",
                    153:             weaps[weap->o_which].w_name, mname);
                    154:
                    155:         did_hit = FALSE;
                    156:     }
                    157:
                    158:     if (did_hit)
                    159:     {
                    160:         did_hit = FALSE;
                    161:
                    162:         if (!can_blink(tp) &&
                    163:             (off(*tp, MAGICHIT) || (weap != NULL &&
                    164:                    (weap->o_hplus > 0 || weap->o_dplus > 0))) &&
                    165:             (off(*tp, BMAGICHIT) || (weap != NULL &&
                    166:                    (weap->o_hplus > 2 || weap->o_dplus > 2))) &&
                    167:             roll_em(&player, tp, weap, thrown, cur_weapon))
                    168:         {
                    169:             did_hit = TRUE;
                    170:             tp->t_wasshot = TRUE;
                    171:
                    172:             if (thrown)
                    173:             {
                    174:                 if (weap != NULL && weap->o_type == WEAPON
                    175:                     && weap->o_which == GRENADE)
                    176:                 {
                    177:                     hearmsg("BOOOM!");
                    178:                     aggravate();
                    179:                 }
                    180:
                    181:                 thunk(weap, mname);
                    182:             }
                    183:             else
                    184:                 hit(mname);
                    185:
                    186:             /* hitting a friendly monster is curtains */
                    187:
                    188:             if (on(*tp, ISFRIENDLY))
                    189:             {
                    190:                 turn_off(*tp, ISFRIENDLY);
                    191:                 turn_on(*tp, ISMEAN);
                    192:             }
                    193:
                    194:             /* Charmed monsters become uncharmed */
                    195:
                    196:             if (on(*tp, ISCHARMED))
                    197:             {
                    198:                 turn_off(*tp, ISCHARMED);
                    199:                 turn_on(*tp, ISMEAN);
                    200:             }
                    201:
                    202:             /*
                    203:              * If the player hit a rust monster, he better have a
                    204:              * + weapon
                    205:             */
                    206:
                    207:             if (on(*tp, CANRUST))
                    208:             {
                    209:                 if (!thrown && (weap != NULL) &&
                    210:                     (weap->o_flags & ISMETAL) &&
                    211:                     !(weap->o_flags & ISPROT) &&
                    212:                     !(weap->o_flags & ISSILVER) &&
                    213:                 (weap->o_hplus < 1) && (weap->o_dplus < 1))
                    214:                 {
                    215:                     if (rnd(100) < 50)
                    216:                         weap->o_hplus--;
                    217:                     else
                    218:                         weap->o_dplus--;
                    219:
                    220:                     msg("Your %s weakens!", weaps[weap->o_which].w_name);
                    221:                 }
                    222:                 else if (!thrown && weap != NULL && (weap->o_flags & ISMETAL))
                    223:                     msg("The rust vanishes from your %s!",
                    224:                         weaps[weap->o_which].w_name);
                    225:             }
                    226:
                    227:             /* flammable monsters die from burning weapons */
                    228:
                    229:             if (thrown && on(*tp, CANBBURN) &&
                    230:                 (weap->o_flags & CANBURN) &&
                    231:                 !save_throw(VS_WAND, tp))
                    232:             {
                    233:                 msg("The %s vanishes in a ball of flame.",
                    234:                     monsters[tp->t_index].m_name);
                    235:
                    236:                 tp->t_stats.s_hpt = 0;
                    237:             }
                    238:
                    239:             /* spores explode and infest hero  */
                    240:
                    241:             if (on(*tp, CANSPORE))
                    242:             {
                    243:                 msg("The %s explodes in a cloud of dust.",
                    244:                     monsters[tp->t_index].m_name);
                    245:
                    246:                 if (is_wearing(R_HEALTH) ||
                    247:                     player.t_ctype == C_PALADIN ||
                    248:                     (player.t_ctype == C_NINJA && pstats.s_lvl
                    249:                      > 6) ||
                    250:                     thrown && rnd(50) > 0 ||
                    251:                     rnd(20) > 0)
                    252:                 {
                    253:                     msg("The dust makes it hard to breath.");
                    254:                 }
                    255:                 else
                    256:                 {
                    257:                     msg("You have contracted a parasitic infestation!");
                    258:
                    259:                     infest_dam++;
                    260:                     turn_on(player, HASINFEST);
                    261:                 }
                    262:
                    263:                 tp->t_stats.s_hpt = 0;
                    264:             }
                    265:
                    266:             /* fireproof monsters laugh at you when burning weapon hits */
                    267:
                    268:             if (thrown && on(*tp, NOFIRE) && (weap->o_flags & CANBURN))
                    269:                 msg("The %s laughs as the %s bounces.",
                    270:                     monsters[tp->t_index].m_name,
                    271:                     weaps[weap->o_which].w_name);
                    272:
                    273:             /* sharp weapons have no effect on NOSHARP monsters */
                    274:
                    275:             if (on(*tp, NOSHARP) && (weap != NULL) &&
                    276:                 (weap->o_flags & ISSHARP))
                    277:             {
                    278:                 msg("The %s has no effect on the %s!",
                    279:                     weaps[weap->o_which].w_name,
                    280:                     monsters[tp->t_index].m_name);
                    281:
                    282:                 fighting = FALSE;
                    283:             }
                    284:
                    285:             /* metal weapons pass through NOMETAL monsters */
                    286:
                    287:             if (on(*tp, NOMETAL) && (weap != NULL) &&
                    288:                 (weap->o_flags & ISMETAL))
                    289:             {
                    290:                 msg("The %s passes through the %s!",
                    291:                     weaps[weap->o_which].w_name,
                    292:                     monsters[tp->t_index].m_name);
                    293:
                    294:                 fighting = FALSE;
                    295:             }
                    296:
                    297:             /*
                    298:              * If the player hit something that shrieks, wake the
                    299:              * dungeon
                    300:              */
                    301:
                    302:             if (on(*tp, CANSHRIEK))
                    303:             {
                    304:                 turn_off(*tp, CANSHRIEK);
                    305:
                    306:                 if (on(player, CANHEAR))
                    307:                 {
                    308:                     msg("You are stunned by the %s's shriek.", mname);
                    309:                     no_command += 4 + rnd(8);
                    310:                 }
                    311:                 else if (off(player, ISDEAF))
                    312:                     msg("The %s emits a piercing shriek.", mname);
                    313:                 else
                    314:                     msg("The %s seems to be trying to make some noise.", mname);
                    315:
                    316:                 aggravate();
                    317:
                    318:                 if (rnd(wizard ? 3 : 39) == 0 && cur_armor
                    319:                     != NULL
                    320:                     && cur_armor->o_which == CRYSTAL_ARMOR)
                    321:                 {
                    322:                     struct linked_list  *itm;
                    323:                     struct object   *obj;
                    324:
                    325:                     for (itm = pack; itm != NULL; itm = next(itm))
                    326:                     {
                    327:                         obj = OBJPTR(itm);
                    328:
                    329:                         if (obj == cur_armor)
                    330:                             break;
                    331:                     }
                    332:
                    333:                     if (itm == NULL)
                    334:                         debug("Can't find crystalline armor being worn.");
                    335:                     else
                    336:                     {
                    337:                         msg("Your armor shatters from the shriek.");
                    338:                         cur_armor = NULL;
                    339:                         del_pack(itm);
                    340:                     }
                    341:                 }
                    342:             }
                    343:
                    344:             /*
                    345:              * If the player hit something that can surprise, it
                    346:              * can't now
                    347:              */
                    348:
                    349:             if (on(*tp, CANSURPRISE))
                    350:                 turn_off(*tp, CANSURPRISE);
                    351:
                    352:             /*
                    353:              * If the player hit something that can summon, it
                    354:              * will try to
                    355:              */
                    356:
                    357:             summon_help(tp, NOFORCE);
                    358:
                    359:             /* Can the player confuse? */
                    360:
                    361:             if (on(player, CANHUH) && !thrown)
                    362:             {
                    363:                 seemsg("Your hands stop glowing red!");
                    364:                 seemsg("The %s appears confused.", mname);
                    365:                 turn_on(*tp, ISHUH);
                    366:                 turn_off(player, CANHUH);
                    367:             }
                    368:
                    369:             /* Merchants just disappear if hit */
                    370:
                    371:             /*
                    372:              * increases prices and curses objects from now on
                    373:              * though
                    374:              */
                    375:
                    376:             if (on(*tp, CANSELL))
                    377:             {
                    378:                 msg("The %s disappears with his wares with a BOOM and a flash.",
                    379:                      mname);
                    380:                 killed(NULL, item, NOMESSAGE, NOPOINTS);
                    381:                 aggravate();
                    382:                 luck++;
                    383:             }
                    384:             else if (tp->t_stats.s_hpt <= 0)
                    385:                 killed(&player, item, MESSAGE, POINTS);
                    386:
                    387:             /*
                    388:              * If the monster is fairly intelligent and about to
                    389:              * die, it may turn tail and run.
                    390:              */
                    391:
                    392:             else if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt / 10)) &&
                    393:                  (rnd(25) < tp->t_stats.s_intel))
                    394:             {
                    395:                 turn_on(*tp, ISFLEE);
                    396:
                    397:                 /* If monster was suffocating, stop it */
                    398:
                    399:                 if (on(*tp, DIDSUFFOCATE))
                    400:                 {
                    401:                     turn_off(*tp, DIDSUFFOCATE);
                    402:                     extinguish_fuse(FUSE_SUFFOCATE);
                    403:                 }
                    404:
                    405:                 /* If monster held us, stop it */
                    406:
                    407:                 if (on(*tp, DIDHOLD) && (--hold_count == 0))
                    408:                     turn_off(player, ISHELD);
                    409:
                    410:                 turn_off(*tp, DIDHOLD);
                    411:
                    412:                 if (on(*tp, CANTELEPORT))
                    413:                 {
                    414:                     int rm;
                    415:
                    416:                     /*
                    417:                      * Erase the monster from the old
                    418:                      * position
                    419:                      */
                    420:
                    421:                     if (isalpha(mvwinch(cw, tp->t_pos.y, tp->t_pos.x)))
                    422:                         mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
                    423:
                    424:                     mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' ');
                    425:
                    426:                     /* Get a new position */
                    427:
                    428:                     do
                    429:                     {
                    430:                         rm = rnd_room();
                    431:                         rnd_pos(&rooms[rm], &tp->t_pos);
                    432:                     }
                    433:                     while (winat(tp->t_pos.y, tp->t_pos.x) != FLOOR);
                    434:
                    435:                     /* Put it there */
                    436:
                    437:                     mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
                    438:                     tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
                    439:                     seemsg("The %s seems to have disappeared!", mname);
                    440:                 }
                    441:             }
                    442:         }
                    443:         else if (thrown)
                    444:             bounce(weap, mname);
                    445:         else
                    446:             miss(mname);
                    447:     }
                    448:
                    449:     if (curr_mons)
                    450:         chase_it(mp,&player);   /* after so that backstabbing can happen */
                    451:
                    452:     count = 0;
                    453:
                    454:     return(did_hit);
                    455: }
                    456:
                    457: /*
                    458:     attack()
                    459:         The monster attacks the player
                    460: */
                    461:
                    462: int
                    463: attack(struct thing *mp, struct object *weapon, int thrown)
                    464: {
                    465:     char    *mname;
                    466:     int    did_hit = FALSE;
                    467:
                    468:     /* If the monster is in a wall, it cannot attack */
                    469:
                    470:     if (on(*mp, ISINWALL))
                    471:         return (FALSE);
                    472:
                    473:     /* If two monsters start to gang up on our hero, stop fight mode */
                    474:
                    475:     if (fighting)
                    476:     {
                    477:         if (beast == NULL)
                    478:             beast = mp;
                    479:         else if (beast != mp)
                    480:             fighting = FALSE;
                    481:     }
                    482:
                    483:     /*
                    484:        Since this is an attack, stop running and any healing that was
                    485:        going on at the time.
                    486:     */
                    487:
                    488:     running = FALSE;
                    489:     player.t_rest_hpt = player.t_rest_pow = 0;
                    490:     mp->t_rest_hpt = mp->t_rest_pow = 0;
                    491:
                    492:     if (on(*mp, ISDISGUISE) && off(player, ISBLIND))
                    493:         turn_off(*mp, ISDISGUISE);
                    494:     mname = on(player, ISBLIND) ? "the monster" :
                    495:         monsters[mp->t_index].m_name;
                    496:
                    497:     if (roll_em(mp, &player, weapon, thrown, wield_weap(weapon, mp)) &&
                    498:         (!thrown || off(player, HASMSHIELD)))
                    499:     {
                    500:         did_hit = TRUE;
                    501:
                    502:         m_thunk(weapon, mname);
                    503:
                    504:         if (pstats.s_hpt <= 0)
                    505:         {
                    506:             death(mp->t_index); /* Bye bye life ... */
                    507:             return TRUE;
                    508:         }
                    509:
                    510:         /* surprising monsters appear after they shoot at you */
                    511:
                    512:         if (thrown && on(*mp, CANSURPRISE))
                    513:             turn_off(*mp, CANSURPRISE);
                    514:         else if (!thrown)
                    515:         {
                    516:
                    517:             /*
                    518:                If a vampire hits, it may take half your hit
                    519:                points
                    520:             */
                    521:
                    522:             if ( on(*mp, CANSUCK) && !save(VS_MAGIC) )
                    523:             {
                    524:                 if (pstats.s_hpt == 1)
                    525:                 {
                    526:                     death(mp->t_index);
                    527:                     return TRUE;
                    528:                 }
                    529:                 else
                    530:                 {
                    531:                     pstats.s_hpt /= 2;
                    532:                     msg("You feel your life force being drawn from you.");
                    533:                 }
                    534:             }
                    535:
                    536:             /*
                    537:                strong monsters can shatter or gong crystalline
                    538:                armor
                    539:             */
                    540:
                    541:             if (cur_armor != NULL && cur_armor->o_which == CRYSTAL_ARMOR)
                    542:             {
                    543:                 if (rnd(mp->t_stats.s_str + (cur_armor->o_ac / 2)) > 20)
                    544:                 {
                    545:                     struct linked_list  *item;
                    546:                     struct object   *obj;
                    547:
                    548:                     for (item = pack; item != NULL; item = next(item))
                    549:                     {
                    550:                         obj = OBJPTR(item);
                    551:
                    552:                         if (obj == cur_armor)
                    553:                             break;
                    554:                     }
                    555:
                    556:                     if (item == NULL)
                    557:                         debug("Can't find crystalline armor being worn.");
                    558:                     else
                    559:                     {
                    560:                         msg("Your armor is shattered by the blow.");
                    561:                         cur_armor = NULL;
                    562:                         del_pack(item);
                    563:                     }
                    564:                 }
                    565:                 else if (rnd(mp->t_stats.s_str) > 15)
                    566:                 {
                    567:                     msg("Your armor rings from the blow.");
                    568:                     aggravate();
                    569:                 }
                    570:             }
                    571:
                    572:             /* Stinking monsters reduce the player's strength */
                    573:
                    574:             if (on(*mp, CANSTINK))
                    575:             {
                    576:                 turn_off(*mp, CANSTINK);
                    577:
                    578:                 if (player.t_ctype != C_PALADIN
                    579:                     && !(player.t_ctype == C_NINJA && pstats.s_lvl > 12)
                    580:                     && !save(VS_POISON))
                    581:                 {
                    582:                     if (on(player, CANSCENT))
                    583:                     {
                    584:                         msg("You pass out from the stench of the %s.", mname);
                    585:                         no_command += 4 + rnd(8);
                    586:                     }
                    587:                     else if (off(player, ISUNSMELL))
                    588:                         msg("The stench of the %s sickens you.", mname);
                    589:
                    590:                     if (on(player, HASSTINK))
                    591:                         lengthen_fuse(FUSE_UNSTINK, STINKTIME);
                    592:                     else
                    593:                     {
                    594:                         turn_on(player, HASSTINK);
                    595:                         light_fuse(FUSE_UNSTINK, 0, STINKTIME, AFTER);
                    596:                     }
                    597:                 }
                    598:             }
                    599:
                    600:             /* chilling monster reduces strength permanently */
                    601:
                    602:             if (on(*mp, CANCHILL) &&
                    603:                 (cur_armor == NULL || cur_armor->o_which != CRYSTAL_ARMOR))
                    604:             {
                    605:                 msg("You cringe at the %s's chilling touch.", mname);
                    606:
                    607:                 if (!is_wearing(R_SUSABILITY))
                    608:                 {
                    609:                     chg_str(-1, FALSE, TRUE);
                    610:
                    611:                     if (lost_str == 0)
                    612:                         light_fuse(FUSE_RES_STRENGTH, 0, CHILLTIME, AFTER);
                    613:                     else
                    614:                         lengthen_fuse(FUSE_RES_STRENGTH, CHILLTIME);
                    615:                 }
                    616:             }
                    617:
                    618:             /* itching monsters reduce dexterity (temporarily) */
                    619:
                    620:             if (on(*mp, CANITCH) && player.t_ctype != C_PALADIN
                    621:                 && !(player.t_ctype == C_NINJA && pstats.s_lvl > 12)
                    622:                 && !save(VS_POISON))
                    623:             {
                    624:                 msg("The claws of the %s scratch you!", mname);
                    625:
                    626:                 if (is_wearing(R_SUSABILITY))
                    627:                     msg("The scratch has no effect.");
                    628:                 else
                    629:                 {
                    630:                     msg("You feel a burning itch.");
                    631:                     turn_on(player, HASITCH);
                    632:                     chg_dext(-1, FALSE, TRUE);
                    633:                     light_fuse(FUSE_UNITCH, 0, roll(4, 6), AFTER);
                    634:                 }
                    635:             }
                    636:
                    637:             /* a hugging monster may SQUEEEEEEEZE */
                    638:
                    639:             if (on(*mp, CANHUG) &&
                    640:                 (cur_armor == NULL || cur_armor->o_which != CRYSTAL_ARMOR))
                    641:             {
                    642:                 if (roll(1, 20) >= 18 || roll(1, 20) >= 18)
                    643:                 {
                    644:                     msg("The %s squeezes you against itself.", mname);
                    645:
                    646:                     if ((pstats.s_hpt -= roll(2, 8)) <= 0)
                    647:                     {
                    648:                         death(mp->t_index);
                    649:                         return TRUE;
                    650:                     }
                    651:                 }
                    652:             }
                    653:
                    654:             /* a trampling monster may step on the player */
                    655:
                    656:             if (on(*mp, CANTRAMPLE))
                    657:             {
                    658:                 if (roll(1, 20) >= 16 || roll(1, 20) >= 16)
                    659:                 {
                    660:                     msg("The %s steps on you.", mname);
                    661:
                    662:                     if ((pstats.s_hpt -= roll(3, mp->t_stats.s_lvl)) <= 0)
                    663:                     {
                    664:                         death(mp->t_index);
                    665:                         return TRUE;
                    666:                     }
                    667:                 }
                    668:             }
                    669:
                    670:             /* a disease-carrying monster may transmit the disease */
                    671:
                    672:             if (on(*mp, CANDISEASE) &&
                    673:                 (rnd(pstats.s_const) < mp->t_stats.s_lvl) &&
                    674:                 off(player, HASDISEASE))
                    675:             {
                    676:
                    677:                 if (is_wearing(R_HEALTH)
                    678:                     || (player.t_ctype == C_PALADIN)
                    679:                     || (player.t_ctype == C_NINJA &&
                    680:                     pstats.s_lvl > 6))
                    681:                     msg("The wound heals quickly.");
                    682:                 else
                    683:                 {
                    684:                     turn_on(player, HASDISEASE);
                    685:                     light_fuse(FUSE_CURE_DISEASE,0,roll(4,4) * SICKTIME, AFTER);
                    686:                     msg("You have contracted a disease!");
                    687:                 }
                    688:             }
                    689:
                    690:             /* a rust monster will weaken your armor */
                    691:
                    692:            if (on(*mp, CANRUST))
                    693:            {
                    694:                 if (cur_armor != NULL &&
                    695:                     cur_armor->o_which != SOFT_LEATHER &&
                    696:                     cur_armor->o_which != HEAVY_LEATHER &&
                    697:                     cur_armor->o_which != CUIRBOLILLI &&
                    698:                     cur_armor->o_which != PADDED_ARMOR &&
                    699:                     cur_armor->o_which != CRYSTAL_ARMOR &&
                    700:                     cur_armor->o_which != MITHRIL &&
                    701:                     !(cur_armor->o_flags & ISPROT) &&
                    702:                     cur_armor->o_ac < pstats.s_arm + 1)
                    703:                 {
                    704:                     msg("Your armor weakens!");
                    705:                     cur_armor->o_ac++;
                    706:                 }
                    707:                 else if (cur_armor != NULL &&
                    708:                      (cur_armor->o_flags & ISPROT) &&
                    709:                     cur_armor->o_which != SOFT_LEATHER &&
                    710:                      cur_armor->o_which != HEAVY_LEATHER &&
                    711:                      cur_armor->o_which != CUIRBOLILLI &&
                    712:                     cur_armor->o_which != PADDED_ARMOR &&
                    713:                      cur_armor->o_which != CRYSTAL_ARMOR &&
                    714:                      cur_armor->o_which != MITHRIL)
                    715:                     msg("The rust vanishes instantly!");
                    716:             }
                    717:
                    718:             /* If a surprising monster hit you, you can see it now */
                    719:
                    720:             if (on(*mp, CANSURPRISE))
                    721:                 turn_off(*mp, CANSURPRISE);
                    722:
                    723:             /* an infesting monster will give you a parasite or rot */
                    724:
                    725:             if (on(*mp, CANINFEST) && rnd(pstats.s_const) < mp->t_stats.s_lvl)
                    726:             {
                    727:                 if (is_wearing(R_HEALTH) || (player.t_ctype == C_PALADIN)
                    728:                     || (player.t_ctype == C_NINJA && pstats.s_lvl > 6))
                    729:                     msg("The wound quickly heals.");
                    730:                 else
                    731:                 {
                    732:                     turn_off(*mp, CANINFEST);
                    733:                     msg("You have contracted a parasitic infestation!");
                    734:                     infest_dam++;
                    735:                     turn_on(player, HASINFEST);
                    736:                 }
                    737:             }
                    738:
                    739:             /* Some monsters have poisonous bites */
                    740:
                    741:             if (on(*mp, CANPOISON) && !save(VS_POISON))
                    742:             {
                    743:                 if (is_wearing(R_SUSABILITY) || (player.t_ctype == C_PALADIN)
                    744:                     || (player.t_ctype == C_NINJA && pstats.s_lvl > 12))
                    745:                     msg("The sting has no effect on you!");
                    746:                 else
                    747:                 {
                    748:                     chg_str(-1, FALSE, FALSE);
                    749:                     msg("You feel a sting in your arm and now feel weaker.");
                    750:                 }
                    751:             }
                    752:
                    753:             /* a hideous monster may cause fear by touching */
                    754:
                    755:             if (on(*mp, TOUCHFEAR))
                    756:             {
                    757:                 turn_off(*mp, TOUCHFEAR);
                    758:
                    759:                 if (!save(VS_WAND)&&!(on(player,ISFLEE)&&(player.t_chasee==mp)))
                    760:                 {
                    761:                     if (off(player, SUPERHERO)
                    762:                          && (player.t_ctype != C_PALADIN))
                    763:                     {
                    764:                         turn_on(player, ISFLEE);
                    765:                         player.t_ischasing = FALSE;
                    766:                         player.t_chasee = mp;
                    767:                         msg("The %s's touch terrifies you.", mname);
                    768:                     }
                    769:                     else
                    770:                         msg("The %s's touch feels cold and clammy.", mname);
                    771:                 }
                    772:             }
                    773:
                    774:             /* some monsters will suffocate our hero */
                    775:
                    776:             if (on(*mp, CANSUFFOCATE) && (rnd(100) < 15) &&
                    777:                 (find_slot(FUSE_SUFFOCATE, FUSE) == NULL))
                    778:             {
                    779:                 turn_on(*mp, DIDSUFFOCATE);
                    780:                 msg("The %s is beginning to suffocate you.",
                    781:                     mname);
                    782:                 light_fuse(FUSE_SUFFOCATE, 0, roll(4, 2), AFTER);
                    783:             }
                    784:
                    785:             /* don't look now, you will get turned to stone */
                    786:
                    787:             if (on(*mp, TOUCHSTONE))
                    788:             {
                    789:                 turn_off(*mp, TOUCHSTONE);
                    790:
                    791:                 if (on(player, CANINWALL))
                    792:                     msg("The %s's touch has no effect.", mname);
                    793:                 else
                    794:                 {
                    795:                     if (!save(VS_PETRIFICATION) && rnd(100) < 3)
                    796:                     {
                    797:                         msg("Your body begins to solidify.");
                    798:                         msg("You are turned to stone !!! --More--");
                    799:                         wait_for(' ');
                    800:                         death(D_PETRIFY);
                    801:                         return TRUE;
                    802:                     }
                    803:                     else
                    804:                     {
                    805:                         msg("The %s's touch stiffens your limbs.", mname);
                    806:                         no_command = rnd(STONETIME) + 2;
                    807:                     }
                    808:                 }
                    809:             }
                    810:
                    811:             /* Undead might drain energy levels */
                    812:
                    813:             if ((on(*mp, CANDRAIN) || on(*mp, DOUBLEDRAIN)) && rnd(100) < 15)
                    814:             {
                    815:                 if (is_carrying(TR_AMULET))
                    816:                    msg("The Amulet protects you from the %s's negative energy!",
                    817:                        mname);
                    818:                 else
                    819:                 {
                    820:                     lower_level(mp->t_index);
                    821:
                    822:                     if (on(*mp, DOUBLEDRAIN))
                    823:                         lower_level(mp->t_index);
                    824:                 }
                    825:
                    826:                 turn_on(*mp, DIDDRAIN);
                    827:             }
                    828:
                    829:             /* permanently drain a wisdom point */
                    830:
                    831:             if (on(*mp, DRAINWISDOM) && rnd(100) < 15)
                    832:             {
                    833:                 int ring_str;   /* Value of ring strengths */
                    834:
                    835:                 /* Undo any ring changes */
                    836:
                    837:                 ring_str = ring_value(R_ADDWISDOM) +
                    838:                     (on(player, POWERWISDOM) ? 10 : 0);
                    839:
                    840:                 pstats.s_wisdom -= ring_str;
                    841:
                    842:                 msg("You feel slightly less wise now.");
                    843:
                    844:                 pstats.s_wisdom = max(pstats.s_wisdom - 1, 3);
                    845:                 max_stats.s_wisdom = pstats.s_wisdom;
                    846:
                    847:                 /* Now put back the ring changes */
                    848:
                    849:                 pstats.s_wisdom += ring_str;
                    850:
                    851:             }
                    852:
                    853:             /* permanently drain a intelligence point */
                    854:
                    855:             if (on(*mp, DRAINBRAIN) && rnd(100) < 15)
                    856:             {
                    857:                 int ring_str;   /* Value of ring strengths */
                    858:
                    859:                 /* Undo any ring changes */
                    860:
                    861:                 ring_str = ring_value(R_ADDINTEL) +
                    862:                     (on(player, POWERINTEL) ? 10 : 0);
                    863:
                    864:                 pstats.s_intel -= ring_str;
                    865:
                    866:                 msg("You feel slightly less intelligent now.");
                    867:                 pstats.s_intel = max(pstats.s_intel - 1, 3);
                    868:                 max_stats.s_intel = pstats.s_intel;
                    869:
                    870:                 /* Now put back the ring changes */
                    871:
                    872:                 pstats.s_intel += ring_str;
                    873:             }
                    874:
                    875:             /* Violet fungi and others hold the hero */
                    876:
                    877:             if (on(*mp, CANHOLD) && off(*mp, DIDHOLD)
                    878:                 && !is_wearing(R_FREEDOM))
                    879:             {
                    880:                 turn_on(player, ISHELD);
                    881:                 turn_on(*mp, DIDHOLD);
                    882:                 hold_count++;
                    883:             }
                    884:
                    885:             /* suckers will suck blood and run away */
                    886:
                    887:             if (on(*mp, CANDRAW))
                    888:             {
                    889:                 turn_off(*mp, CANDRAW);
                    890:                 turn_on(*mp, ISFLEE);
                    891:                 msg("The %s sates itself with your blood.", mname);
                    892:
                    893:                 if ((pstats.s_hpt -= 12) <= 0)
                    894:                 {
                    895:                     death(mp->t_index);
                    896:                     return TRUE;
                    897:                 }
                    898:             }
                    899:
                    900:             /* el stinkos will force a reduction in strength */
                    901:
                    902:             if (on(*mp, CANSMELL))
                    903:             {
                    904:                 turn_off(*mp, CANSMELL);
                    905:
                    906:                 if (save(VS_MAGIC) || is_wearing(R_SUSABILITY))
                    907:                     msg("You smell an unpleasant odor.");
                    908:                 else
                    909:                 {
                    910:                     int   odor_str = -(rnd(6) + 1);
                    911:
                    912:                     if (on(player, CANSCENT))
                    913:                     {
                    914:                         msg("You pass out from a foul odor.");
                    915:                         no_command += 4 + rnd(8);
                    916:                     }
                    917:                     else if (off(player, ISUNSMELL))
                    918:                         msg("You are overcome by a foul odor.");
                    919:
                    920:                     if (lost_str == 0)
                    921:                     {
                    922:                         chg_str(odor_str, FALSE, TRUE);
                    923:                         light_fuse(FUSE_RES_STRENGTH, 0, SMELLTIME, AFTER);
                    924:                     }
                    925:                     else
                    926:                         lengthen_fuse(FUSE_RES_STRENGTH, SMELLTIME);
                    927:                 }
                    928:             }
                    929:
                    930:             /* Paralyzation */
                    931:
                    932:             if (on(*mp, CANPARALYZE))
                    933:             {
                    934:                 turn_off(*mp, CANPARALYZE);
                    935:
                    936:                 if (!save(VS_PARALYZATION) && no_command == 0)
                    937:                 {
                    938:                     if (on(player, CANINWALL))
                    939:                         msg("The %s's touch has no effect.", mname);
                    940:                     else
                    941:                     {
                    942:                         msg("The %s's touch paralyzes you.", mname);
                    943:                         no_command = FREEZETIME;
                    944:                     }
                    945:                 }
                    946:             }
                    947:
                    948:             /* Rotting */
                    949:
                    950:             if (on(*mp, CANROT))
                    951:             {
                    952:                 turn_off(*mp, CANROT);
                    953:                 turn_on(*mp, DOROT);
                    954:             }
                    955:
                    956:             /* some monsters steal gold */
                    957:
                    958:             if (on(*mp, STEALGOLD))
                    959:             {
                    960:                 long    lastpurse;
                    961:                 struct linked_list  *item;
                    962:                 struct object   *obj;
                    963:
                    964:                 lastpurse = purse;
                    965:                 purse = (purse > GOLDCALC) ? purse - GOLDCALC : 0L;
                    966:
                    967:                 if (!save(VS_MAGIC))
                    968:                     purse = (purse > (4*GOLDCALC)) ? purse-(4*GOLDCALC) : 0L;
                    969:
                    970:                 if (purse != lastpurse)
                    971:                 {
                    972:                     msg("Your purse feels lighter.");
                    973:
                    974:                     /* Give the gold to the thief */
                    975:
                    976:                     for (item = mp->t_pack; item != NULL; item = next(item))
                    977:                     {
                    978:                         obj = OBJPTR(item);
                    979:
                    980:                         if (obj->o_type == GOLD)
                    981:                         {
                    982:                             obj->o_count += lastpurse - purse;
                    983:                             break;
                    984:                         }
                    985:                     }
                    986:
                    987:                     /* Did we do it? */
                    988:
                    989:                     if (item == NULL)  /* Then make some */
                    990:                     {
                    991:                         item = new_item(sizeof *obj);
                    992:                         obj = OBJPTR(item);
                    993:                         obj->o_type = GOLD;
                    994:                         obj->o_count = lastpurse - purse;
                    995:                         obj->o_hplus = obj->o_dplus = 0;
                    996:                         obj->o_damage = obj->o_hurldmg = "0d0";
                    997:                         obj->o_ac = 11;
                    998:                         obj->o_group = 0;
                    999:                         obj->o_flags = 0;
                   1000:                         obj->o_mark[0] = '\0';
                   1001:                         obj->o_pos = mp->t_pos;
                   1002:
                   1003:                         attach(mp->t_pack, item);
                   1004:                     }
                   1005:                 }
                   1006:
                   1007:                 if (rnd(2))
                   1008:                     turn_on(*mp, ISFLEE);
                   1009:
                   1010:                 turn_on(*mp, ISINVIS);
                   1011:             }
                   1012:
                   1013:             /* other monsters steal magic */
                   1014:
                   1015:             if (on(*mp, STEALMAGIC))
                   1016:             {
                   1017:                 struct linked_list  *list, *stealit;
                   1018:                 struct object   *obj;
                   1019:                 int worth = 0;
                   1020:
                   1021:                 stealit = NULL;
                   1022:
                   1023:                 for (list = pack; list != NULL; list = next(list))
                   1024:                 {
                   1025:                     obj = OBJPTR(list);
                   1026:
                   1027:                     if (rnd(33) == 0) /* some stuff degrades */
                   1028:                     {
                   1029:                         if (obj->o_flags & ISBLESSED)
                   1030:                             obj->o_flags &= ~ISBLESSED;
                   1031:                         else
                   1032:                             obj->o_flags |= ISCURSED;
                   1033:
                   1034:                         msg("You feel nimble fingers reach into you pack.");
                   1035:                     }
                   1036:
                   1037:                     if ((obj != cur_armor &&
                   1038:                          obj != cur_weapon &&
                   1039:                          obj != cur_ring[LEFT_1] &&
                   1040:                          obj != cur_ring[LEFT_2] &&
                   1041:                          obj != cur_ring[LEFT_3] &&
                   1042:                          obj != cur_ring[LEFT_4] &&
                   1043:                          obj != cur_ring[LEFT_5] &&
                   1044:                          obj != cur_ring[RIGHT_1] &&
                   1045:                          obj != cur_ring[RIGHT_2] &&
                   1046:                          obj != cur_ring[RIGHT_3] &&
                   1047:                          obj != cur_ring[RIGHT_4] &&
                   1048:                          obj != cur_ring[RIGHT_5] &&
                   1049:                          !(obj->o_flags & ISPROT) &&
                   1050:                          is_magic(obj)
                   1051:                          || level > 45)
                   1052:                         && get_worth(obj) > worth)
                   1053:                     {
                   1054:                         stealit = list;
                   1055:                         worth = get_worth(obj);
                   1056:                     }
                   1057:                 }
                   1058:
                   1059:                 if (stealit != NULL)
                   1060:                 {
                   1061:                     struct object   *newobj;
                   1062:
                   1063:                     newobj = OBJPTR(stealit);
                   1064:
                   1065:                     if (newobj->o_count > 1 && newobj->o_group == 0)
                   1066:                     {
                   1067:                         int oc;
                   1068:                         struct linked_list  *nitem;
                   1069:                         struct object   *op;
                   1070:
                   1071:                         oc = --(newobj->o_count);
                   1072:                         newobj->o_count = 1;
                   1073:                         nitem = new_item(sizeof *newobj);
                   1074:                         op = OBJPTR(nitem);
                   1075:                         *op = *newobj;
                   1076:
                   1077:                        msg("The %s stole %s!",mname,inv_name(newobj,LOWERCASE));
                   1078:                         newobj->o_count = oc;
                   1079:                         attach(mp->t_pack, nitem);
                   1080:                     }
                   1081:                     else
                   1082:                     {
                   1083:                        msg("The %s stole %s!",mname,inv_name(newobj,LOWERCASE));
                   1084:                         newobj->o_flags &= ~ISCURSED;
                   1085:                         dropcheck(newobj);
                   1086:                         rem_pack(newobj);
                   1087:                         attach(mp->t_pack, stealit);
                   1088:
                   1089:                         if (newobj->o_type == ARTIFACT)
                   1090:                             has_artifact &= ~(1 << newobj->o_which);
                   1091:                     }
                   1092:
                   1093:                     if (newobj->o_flags & ISOWNED)
                   1094:                     {
                   1095:                         turn_on(*mp, NOMOVE);
                   1096:                         msg("The %s is transfixed by your ownership spell.",
                   1097:                             mname);
                   1098:                     }
                   1099:
                   1100:                     if (rnd(2))
                   1101:                         turn_on(*mp, ISFLEE);
                   1102:
                   1103:                     turn_on(*mp, ISINVIS);
                   1104:                     updpack();
                   1105:                 }
                   1106:             }
                   1107:         }
                   1108:     }
                   1109:     else /* missed */
                   1110:     {
                   1111:         /* If the thing was trying to surprise, no good */
                   1112:
                   1113:         if (on(*mp, CANSURPRISE))
                   1114:             turn_off(*mp, CANSURPRISE);
                   1115:
                   1116:         m_bounce(weapon, mname);
                   1117:     }
                   1118:
                   1119:     count = 0;
                   1120:
                   1121:     status(FALSE);
                   1122:
                   1123:     return(did_hit);
                   1124: }
                   1125:
                   1126:
                   1127: /*
                   1128:     mon_mon_attack()
                   1129:         A monster attacks another monster
                   1130: */
                   1131:
                   1132: int
                   1133: mon_mon_attack(struct thing *attacker, struct linked_list *mon, struct object *weapon, int thrown)
                   1134: {
                   1135:     struct thing *attackee = THINGPTR(mon);
                   1136:     int           did_hit  = FALSE;
                   1137:     int           ee_visible = cansee(attackee->t_pos.y, attackee->t_pos.x);
                   1138:     int           er_visible = cansee(attacker->t_pos.y, attacker->t_pos.x);
                   1139:     char         *mname1   = monsters[attacker->t_index].m_name;
                   1140:     char         *mname2   = monsters[attackee->t_index].m_name;
                   1141:
                   1142:     /* Similar monsters don't hit each other */
                   1143:
                   1144:     if (attacker->t_index == attackee->t_index)
                   1145:     {
                   1146:         if (fam_ptr && attacker == THINGPTR(fam_ptr) && er_visible)
                   1147:             msg("Master, I cannot hit one of my brethren.");
                   1148:         if (!thrown && rnd(100) - attacker->t_stats.s_charisma + luck < 0)
                   1149:                {
                   1150:             if (er_visible)
                   1151:                 msg("Your %s has made a new ally.", mname1);
                   1152:
                   1153:             turn_on(*attackee, ISCHARMED);
                   1154:                }
                   1155:
                   1156:         return(FALSE);
                   1157:     }
                   1158:
                   1159:     /* stop running and any healing */
                   1160:
                   1161:     attackee->t_rest_hpt = attackee->t_rest_pow = 0;
                   1162:     attacker->t_rest_hpt = attacker->t_rest_pow = 0;
                   1163:
                   1164:     if (roll_em(attacker, attackee, weapon, thrown,
                   1165:         wield_weap(weapon, attacker)))
                   1166:     {
                   1167:         did_hit = TRUE;
                   1168:
                   1169:         if (ee_visible && on(*attackee, CANSURPRISE))
                   1170:             turn_off(*attackee, CANSURPRISE);
                   1171:
                   1172:         if (ee_visible && er_visible && weapon != NULL)
                   1173:             msg("The %s's %s hits the %s.", mname1,
                   1174:                 weaps[weapon->o_which].w_name, mname2);
                   1175:         else if (ee_visible && er_visible)
                   1176:             msg("The %s hits the %s.", mname1, mname2);
                   1177:
                   1178:         if (attackee->t_stats.s_hpt <= 0)
                   1179:         {
                   1180:             killed(attacker, mon, MESSAGE,
                   1181:                  on(*attacker, ISFAMILIAR) ? POINTS : NOPOINTS);
                   1182:             return(TRUE);
                   1183:         }
                   1184:     }
                   1185:     else  /* missed */
                   1186:        {
                   1187:            did_hit = FALSE;
                   1188:
                   1189:                if (ee_visible && er_visible && weapon != NULL)
                   1190:             msg("The %s's %s misses the %s.", mname1,
                   1191:                 weaps[weapon->o_which].w_name, mname2);
                   1192:         else if (ee_visible && er_visible)
                   1193:             msg("The %s misses the %s.", mname1, mname2);
                   1194:        }
                   1195:
                   1196:        if (er_visible && !ee_visible)
                   1197:         msg("The %s struggles with something.",mname1);
                   1198:
                   1199:     if (off(*attackee, ISMEAN) && off(*attackee, ISFAMILIAR))
                   1200:         turn_on(*attackee, ISRUN);
                   1201:
                   1202:     count = 0;
                   1203:
                   1204:     status(FALSE);
                   1205:
                   1206:     return(did_hit);
                   1207: }
                   1208:
                   1209:
                   1210: /*
                   1211:     swing()
                   1212:         returns true if the swing hits
                   1213: */
                   1214:
                   1215: int
                   1216: swing(int class, int at_lvl, int op_arm, int wplus)
                   1217: {
                   1218:     int res = rnd(20) + 1;
                   1219:     int need;
                   1220:
                   1221:     need = att_mat[class].base -
                   1222:         att_mat[class].factor *
                   1223:         ((min(at_lvl, att_mat[class].max_lvl) -
                   1224:           att_mat[class].offset) / att_mat[class].range) +
                   1225:         (10 - op_arm);
                   1226:
                   1227:     if (need > 20 && need <= 25)
                   1228:         need = 20;
                   1229:
                   1230:     return(res + wplus >= need);
                   1231: }
                   1232:
                   1233: /*
                   1234:     init_exp()
                   1235:         set up initial experience level change threshold
                   1236: */
                   1237:
                   1238: void
                   1239: init_exp(void)
                   1240: {
                   1241:     max_stats.s_exp = e_levels[player.t_ctype];
                   1242: }
                   1243:
                   1244: /*
                   1245:     next_exp_level()
                   1246:         Do the next level arithmetic Returns number of levels to jump
                   1247: */
                   1248:
                   1249: int
                   1250: next_exp_level(int print_message)
                   1251: {
                   1252:     int level_jump = 0;
                   1253:
                   1254:     while (pstats.s_exp >= max_stats.s_exp)
                   1255:     {
                   1256:         pstats.s_exp -= max_stats.s_exp;    /* excess experience points */
                   1257:         level_jump++;
                   1258:
                   1259:         if (max_stats.s_exp < 0x3fffffffL)  /* 2^30 - 1 */
                   1260:             max_stats.s_exp *= 2L;  /* twice as many for next */
                   1261:     }
                   1262:
                   1263:     if (print_message)
                   1264:         msg("You need %d more points to attain the %stitle of %s.",
                   1265:             max_stats.s_exp - pstats.s_exp,
                   1266:             (pstats.s_lvl > 14 ? "next " : ""),
                   1267:             cnames[player.t_ctype][min(pstats.s_lvl, 14)]);
                   1268:
                   1269:     return(level_jump);
                   1270: }
                   1271:
                   1272: /*
                   1273:     check_level()
                   1274:         Check to see if the guy has gone up a level.
                   1275: */
                   1276:
                   1277: void
                   1278: check_level(void)
                   1279: {
                   1280:     int num_jumped, j, add;
                   1281:     int nsides;
                   1282:
                   1283:     if ((num_jumped = next_exp_level(NOMESSAGE)) <= 0)
                   1284:         return;
                   1285:
                   1286:     pstats.s_lvl += num_jumped; /* new experience level */
                   1287:
                   1288:     switch (player.t_ctype)
                   1289:     {
                   1290:         case C_MAGICIAN:
                   1291:         case C_ILLUSION: nsides = 4;
                   1292:                          break;
                   1293:         case C_THIEF:
                   1294:         case C_ASSASIN:
                   1295:         case C_NINJA:
                   1296:         case C_MONSTER:
                   1297:         default:         nsides = 6;
                   1298:                          break;
                   1299:         case C_CLERIC:
                   1300:         case C_DRUID:    nsides = 8;
                   1301:                          break;
                   1302:
                   1303:         case C_FIGHTER:
                   1304:         case C_PALADIN:
                   1305:         case C_RANGER:
                   1306:                          nsides = 12;
                   1307:                          break;
                   1308:     }
                   1309:
                   1310:     /* Take care of multi-level jumps */
                   1311:
                   1312:     for (add = 0, j = 0; j < num_jumped; j++)
                   1313:     {
                   1314:         int increase = roll(1, nsides) + const_bonus();
                   1315:
                   1316:         add += max(1, increase);
                   1317:     }
                   1318:
                   1319:     max_stats.s_hpt += add;
                   1320:     pstats.s_hpt += add;
                   1321:
                   1322:     msg("Welcome, %s, to level %d.",
                   1323:         cnames[player.t_ctype][min(pstats.s_lvl - 1, 14)], pstats.s_lvl);
                   1324:
                   1325:     next_exp_level(MESSAGE);
                   1326:
                   1327:     /* Now add new spell points and learn new spells */
                   1328:
                   1329:     nsides = 16 - nsides;
                   1330:
                   1331:     for (add = 0, j = 0; j < num_jumped; j++)
                   1332:     {
                   1333:         int increase = roll(1, nsides) + int_wis_bonus();
                   1334:
                   1335:         add += max(1, increase);
                   1336:     }
                   1337:
                   1338:     max_stats.s_power += add;
                   1339:     pstats.s_power += add;
                   1340:
                   1341:     learn_new_spells();
                   1342:
                   1343:     /* Create a more powerful familiar (if player has one) */
                   1344:
                   1345:     if (on(player, HASFAMILIAR) && on(player, CANSUMMON))
                   1346:         summon_monster((short) 0, FAMILIAR, NOMESSAGE);
                   1347: }
                   1348:
                   1349: /*
                   1350:     roll_em()
                   1351:         Roll several attacks
                   1352: */
                   1353:
                   1354: int
                   1355: roll_em(struct thing *att_er, struct thing *def_er, struct object *weap, int thrown, struct object *my_weapon)
                   1356: {
                   1357:     struct stats *att = &att_er->t_stats;
                   1358:     struct stats *def = &def_er->t_stats;
                   1359:     int ndice, nsides, nplus, def_arm;
                   1360:     char *cp;
                   1361:     int prop_hplus = 0, prop_dplus = 0;
                   1362:     int is_player = (att_er == &player);
                   1363:     int did_hit = FALSE;
                   1364:
                   1365:     if (weap == NULL)
                   1366:         cp = att->s_dmg;
                   1367:     else if (!thrown)
                   1368:         cp = weap->o_damage;
                   1369:     else if ((weap->o_flags & ISMISL) && my_weapon != NULL &&
                   1370:          my_weapon->o_which == weap->o_launch)
                   1371:     {
                   1372:         cp = weap->o_hurldmg;
                   1373:         prop_hplus = my_weapon->o_hplus;
                   1374:         prop_dplus = my_weapon->o_dplus;
                   1375:     }
                   1376:     else
                   1377:         cp = (weap->o_flags & ISMISL ? weap->o_damage :
                   1378:             weap->o_hurldmg);
                   1379:
                   1380:     for (;;)
                   1381:     {
                   1382:         int damage;
                   1383:         int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus);
                   1384:         int dplus = prop_dplus + (weap == NULL ? 0 : weap->o_dplus);
                   1385:
                   1386:         /* Is attacker weak? */
                   1387:
                   1388:         if (on(*att_er, HASSTINK))
                   1389:             hplus -= 2;
                   1390:
                   1391:         if (is_player)
                   1392:         {
                   1393:             hplus += hitweight();   /* adjust for encumberence */
                   1394:             dplus += hung_dam();    /* adjust damage for hungry player */
                   1395:             dplus += ring_value(R_ADDDAM);
                   1396:         }
                   1397:
                   1398:         ndice = atoi(cp);
                   1399:
                   1400:         if (cp == NULL || (cp = strchr(cp, 'd')) == NULL)
                   1401:             break;
                   1402:
                   1403:         nsides = atoi(++cp);
                   1404:
                   1405:         if (cp != NULL && (cp = strchr(cp, '+')) != NULL)
                   1406:             nplus = atoi(++cp);
                   1407:         else
                   1408:             nplus = 0;
                   1409:
                   1410:         if (def == &pstats)
                   1411:         {
                   1412:             if (on(*att_er, NOMETAL) && cur_armor != NULL &&
                   1413:                 (cur_armor->o_which == RING_MAIL ||
                   1414:                  cur_armor->o_which == SCALE_MAIL ||
                   1415:                  cur_armor->o_which == CHAIN_MAIL ||
                   1416:                  cur_armor->o_which == SPLINT_MAIL ||
                   1417:                  cur_armor->o_which == BANDED_MAIL ||
                   1418:                  cur_armor->o_which == GOOD_CHAIN ||
                   1419:                  cur_armor->o_which == PLATE_MAIL ||
                   1420:                  cur_armor->o_which == PLATE_ARMOR))
                   1421:                 def_arm = def->s_arm;
                   1422:             else if (cur_armor != NULL)
                   1423:                 def_arm = cur_armor->o_ac - 10 + pstats.s_arm;
                   1424:             else
                   1425:                 def_arm = def->s_arm;
                   1426:             def_arm -= ring_value(R_PROTECT);
                   1427:         }
                   1428:         else
                   1429:             def_arm = def->s_arm;
                   1430:
                   1431:         if ((weap != NULL && weap->o_type == WEAPON &&
                   1432:              (weap->o_flags & ISSILVER) &&
                   1433:             !save_throw(VS_MAGIC, def_er)) ||
                   1434:             swing(att_er->t_ctype, att->s_lvl,
                   1435:             def_arm - dext_prot(def->s_dext),
                   1436:            hplus + str_plus(att->s_str) + dext_plus(att->s_dext)))
                   1437:         {
                   1438:             damage = roll(ndice, nsides) + dplus + nplus +
                   1439:                 add_dam(att->s_str);
                   1440:
                   1441:             /* Rangers do +1/lvl vs. ISLARGE */
                   1442:
                   1443:             if (att_er->t_ctype == C_RANGER && on(*def_er, ISLARGE))
                   1444:                 damage += pstats.s_lvl;
                   1445:
                   1446:             /* Ninja do +1 per lvl/2 */
                   1447:
                   1448:             if (att_er->t_ctype == C_NINJA)
                   1449:                 damage += pstats.s_lvl / 2;
                   1450:
                   1451:             /* Check for half damage monsters */
                   1452:
                   1453:             if (on(*def_er, HALFDAMAGE) && (weap != NULL) &&
                   1454:                 !((weap->o_flags & CANBURN) &&
                   1455:                 on(*def_er, CANBBURN)))
                   1456:                 damage /= 2;
                   1457:
                   1458:             /* undead get twice damage from silver weapons */
                   1459:
                   1460:             if (on(*def_er, ISUNDEAD) &&
                   1461:                 (weap != NULL) && (weap->o_flags & ISSILVER))
                   1462:                 damage *= 2;
                   1463:
                   1464:             /* Check for fireproof monsters */
                   1465:
                   1466:             if (on(*def_er, NOFIRE) && (weap != NULL) &&
                   1467:                 (weap->o_flags & CANBURN))
                   1468:                 damage = 0;
                   1469:
                   1470:             /* Check for metal proof monsters */
                   1471:
                   1472:             if (on(*def_er, NOMETAL) && (weap != NULL) &&
                   1473:                 (weap->o_flags & ISMETAL))
                   1474:                 damage = 0;
                   1475:
                   1476:             /* Check for monsters that ignore sharp weapons  */
                   1477:
                   1478:             if (on(*def_er, NOSHARP) && (weap != NULL) &&
                   1479:                 (weap->o_flags & ISSHARP))
                   1480:                 damage = 0;
                   1481:
                   1482:             /* Check for poisoned weapons */
                   1483:
                   1484:             if ((weap != NULL) && (weap->o_flags & ISPOISON)
                   1485:                 && off(*def_er, ISUNDEAD)
                   1486:                 && !save_throw(VS_POISON, def_er))
                   1487:                 damage = max(damage, (def->s_hpt / 2) + 5);
                   1488:
                   1489:             /* Check for no-damage and division */
                   1490:
                   1491:             if (on(*def_er, BLOWDIVIDE) && rnd(3) == 0 &&
                   1492:                 !((weap != NULL) && (weap->o_flags & CANBURN)))
                   1493:             {
                   1494:                 damage = 0;
                   1495:                 creat_mons(def_er, def_er->t_index, NOMESSAGE);
                   1496:             }
                   1497:
                   1498:             damage = max(0, damage);
                   1499:
                   1500:             /*
                   1501:              * sleeping monsters are backstabbed by certain
                   1502:              * player classes, but only when they can see
                   1503:              */
                   1504:
                   1505:             if (is_player && !thrown && damage > 0 &&
                   1506:                 (off(*def_er, ISRUN) || def_er->t_no_move > 0) &&
                   1507:                 (player.t_ctype == C_THIEF ||
                   1508:                  player.t_ctype == C_NINJA ||
                   1509:                  player.t_ctype == C_ASSASIN) &&
                   1510:                                 off(player,ISBLIND)
                   1511:                 && (wield_ok(&player, my_weapon, NOMESSAGE))
                   1512:                 && (wear_ok(&player, cur_armor, NOMESSAGE)))
                   1513:             {
                   1514:                 damage *= (pstats.s_lvl / 4 + 2);
                   1515:
                   1516:                 msg("You backstabbed the %s %d times!",
                   1517:                     monsters[def_er->t_index].m_name,
                   1518:                     (pstats.s_lvl / 4) + 2);
                   1519:
                   1520:                 if (player.t_ctype == C_NINJA ||
                   1521:                     player.t_ctype == C_ASSASIN)
                   1522:                     pstats.s_exp += def_er->t_stats.s_exp
                   1523:                         / 2;
                   1524:             }
                   1525:
                   1526:             def->s_hpt -= damage;   /* Do the damage */
                   1527:
                   1528:             debug("Hit %s for %d (%d) ",
                   1529:                   monsters[def_er->t_index].m_name, damage,
                   1530:                   def_er->t_stats.s_hpt);
                   1531:
                   1532:             if (is_player && is_wearing(R_VREGEN))
                   1533:             {
                   1534:                 damage = (ring_value(R_VREGEN) * damage) / 3;
                   1535:                 pstats.s_hpt = min(max_stats.s_hpt,
                   1536:                     pstats.s_hpt + damage);
                   1537:             }
                   1538:
                   1539:             /* stun monsters when taking more than 1/3 their max hpts */
                   1540:
                   1541:             if (is_player && !thrown && !did_hit &&
                   1542:                 (player.t_ctype == C_FIGHTER) &&
                   1543:                 (damage > def_er->maxstats.s_hpt / 3) )
                   1544:             {
                   1545:                 if (def->s_hpt > 0)
                   1546:                 {
                   1547:                     msg("The %s has been stunned!",
                   1548:                       monsters[def_er->t_index].m_name);
                   1549:                     def_er->t_no_move += rnd(4) + 1;
                   1550:                 }
                   1551:                 pstats.s_exp += def_er->t_stats.s_exp / 4;
                   1552:             }
                   1553:
                   1554:             did_hit = TRUE;
                   1555:         }
                   1556:
                   1557:         if (cp == NULL || (cp = strchr(cp, '/')) == NULL)
                   1558:             break;
                   1559:
                   1560:         cp++;
                   1561:     }
                   1562:
                   1563:     return(did_hit);
                   1564: }
                   1565:
                   1566: /*
                   1567:     prname()
                   1568:         Figure out the monsters name
                   1569: */
                   1570:
                   1571: const char *
                   1572: prname(char *who)
                   1573: {
                   1574:     if (on(player, ISBLIND))
                   1575:         return(monstern);
                   1576:     else
                   1577:         return(who);
                   1578: }
                   1579:
                   1580: /*
                   1581:     hit()
                   1582:         Print a message to indicate a succesful hit
                   1583: */
                   1584:
                   1585: void
                   1586: hit(char *ee)
                   1587: {
                   1588:     char    *s;
                   1589:
                   1590:     if (fighting)
                   1591:         return;
                   1592:
                   1593:     switch (rnd(15))
                   1594:     {
                   1595:         default:  s = "hit";                            break;
                   1596:         case 1:   s = "score an excellent hit on";      break;
                   1597:         case 2:   s = "injure";                         break;
                   1598:         case 3:   s = "swing and hit";                  break;
                   1599:         case 4:   s = "damage";                         break;
                   1600:         case 5:   s = "barely nick";                    break;
                   1601:         case 6:   s = "scratch";                        break;
                   1602:         case 7:   s = "gouge a chunk out of";           break;
                   1603:         case 8:   s = "severely wound";                 break;
                   1604:         case 9:   s = "counted coup on";                break;
                   1605:         case 10:  s = "drew blood from";                break;
                   1606:         case 11:  s = "nearly decapitate";              break;
                   1607:         case 12:  s = "deal a wacking great blow to";   break;
                   1608:     }
                   1609:
                   1610:     msg("You %s the %s.", s, prname(ee));
                   1611: }
                   1612:
                   1613: /*
                   1614:     miss()
                   1615:         Print a message to indicate a poor swing
                   1616: */
                   1617:
                   1618: void
                   1619: miss(char *ee)
                   1620: {
                   1621:     char *s;
                   1622:
                   1623:     if (fighting)
                   1624:         return;
                   1625:
                   1626:     switch (rnd(10))
                   1627:     {
                   1628:         default:  s = "miss";                          break;
                   1629:         case 1:   s = "swing and miss";                break;
                   1630:         case 2:   s = "barely miss";                   break;
                   1631:         case 3:   s = "don't hit";                     break;
                   1632:         case 4:   s = "wildly windmill around";        break;
                   1633:         case 5:   s = "almost fumble while missing";   break;
                   1634:     }
                   1635:
                   1636:     msg("You %s the %s.", s, prname(ee));
                   1637: }
                   1638:
                   1639: /*
                   1640:     save_throw()
                   1641:         See if a creature save against something
                   1642: */
                   1643:
                   1644: int
                   1645: save_throw(int which, struct thing *tp)
                   1646: {
                   1647:     int need;
                   1648:     int ring_bonus = 0;
                   1649:     int armor_bonus = 0;
                   1650:     int class_bonus = 0;
                   1651:
                   1652:     if (tp == &player)
                   1653:     {
                   1654:         if (player.t_ctype == C_PALADIN)
                   1655:             class_bonus = 2;
                   1656:
                   1657:         ring_bonus = ring_value(R_PROTECT);
                   1658:
                   1659:         if (cur_armor != NULL && (which == VS_WAND ||
                   1660:             which == VS_MAGIC))
                   1661:         {
                   1662:             if (cur_armor->o_which == MITHRIL)
                   1663:                 armor_bonus += 5;
                   1664:             armor_bonus += (armors[cur_armor->o_which].a_class
                   1665:                     - cur_armor->o_ac);
                   1666:         }
                   1667:     }
                   1668:
                   1669:     need = 14 + which - tp->t_stats.s_lvl / 2 - ring_bonus -
                   1670:         armor_bonus - class_bonus;
                   1671:
                   1672:     /* Roll of 1 always fails; 20 always saves */
                   1673:
                   1674:     if (need < 1)
                   1675:         need = 1;
                   1676:     else if (need > 20)
                   1677:         need = 20;
                   1678:
                   1679:     return(roll(1, 20) >= need);
                   1680: }
                   1681:
                   1682: /*
                   1683:     save()
                   1684:         See if he saves against various nasty things
                   1685: */
                   1686:
                   1687: int
                   1688: save(int which)
                   1689: {
                   1690:     return save_throw(which, &player);
                   1691: }
                   1692:
                   1693: /*
                   1694:     dext_plus()
                   1695:        compute to-hit bonus for dexterity
                   1696: */
                   1697:
                   1698: int
                   1699: dext_plus(int dexterity)
                   1700: {
                   1701:     return ((dexterity - 10) / 3);
                   1702: }
                   1703:
                   1704: /*
                   1705:  * dext_prot: compute armor class bonus for dexterity
                   1706:  */
                   1707:
                   1708: int
                   1709: dext_prot(int dexterity)
                   1710: {
                   1711:     return ((dexterity - 9) / 2);
                   1712: }
                   1713:
                   1714: /*
                   1715:     str_plus()
                   1716:        compute bonus/penalties for strength on the "to hit" roll
                   1717: */
                   1718:
                   1719: static const int strtohit[] =
                   1720: {
                   1721:     0, 0, 0, -3, -2, -2, -1, -1,
                   1722:     0, 0, 0, 0, 0, 0, 0, 0, 0,
                   1723:     1, 1, 3, 3, 4, 4, 5, 6, 7
                   1724: };
                   1725:
                   1726: int
                   1727: str_plus(int str)
                   1728: {
                   1729:     int ret_val = str;
                   1730:
                   1731:     if (str < 3)
                   1732:         ret_val = 3;
                   1733:     else if (str > 25)
                   1734:         ret_val = 25;
                   1735:
                   1736:     return(strtohit[ret_val]);
                   1737: }
                   1738:
                   1739: /*
                   1740:     add_dam()
                   1741:         compute additional damage done for exceptionally high or low strength
                   1742: */
                   1743:
                   1744: static const int str_damage[] =
                   1745: {
                   1746:     0, 0, 0, -1, -1, -1, 0, 0,
                   1747:     0, 0, 0, 0, 0, 0, 0, 0, 1,
                   1748:     1, 2, 7, 8, 9, 10, 11, 12, 14
                   1749: };
                   1750:
                   1751: int
                   1752: add_dam(int str)
                   1753: {
                   1754:     int ret_val = str;
                   1755:
                   1756:     if (str < 3)
                   1757:         ret_val = 3;
                   1758:     else if (str > 25)
                   1759:         ret_val = 25;
                   1760:
                   1761:     return(str_damage[ret_val]);
                   1762: }
                   1763:
                   1764: /*
                   1765:     hung_dam()
                   1766:         Calculate damage depending on players hungry state
                   1767: */
                   1768:
                   1769: int
                   1770: hung_dam(void)
                   1771: {
                   1772:     int howmuch = 0;
                   1773:
                   1774:     switch (hungry_state)
                   1775:     {
                   1776:         case F_OK:
                   1777:         case F_HUNGRY: howmuch =  0; break;
                   1778:         case F_WEAK:   howmuch = -1; break;
                   1779:         case F_FAINT:  howmuch = -2; break;
                   1780:     }
                   1781:
                   1782:     return(howmuch);
                   1783: }
                   1784:
                   1785: /*
                   1786:     raise_level()
                   1787:         The guy just magically went up a level.
                   1788: */
                   1789:
                   1790: void
                   1791: raise_level(void)
                   1792: {
                   1793:     pstats.s_exp = max_stats.s_exp;
                   1794:     check_level();
                   1795: }
                   1796:
                   1797: /*
                   1798:     thunk()
                   1799:         A missile hits a monster
                   1800: */
                   1801:
                   1802: void
                   1803: thunk(struct object *weap, char *mname)
                   1804: {
                   1805:     if (fighting)
                   1806:         return;
                   1807:
                   1808:     if (weap->o_type == WEAPON)
                   1809:         msg("The %s hits the %s.", weaps[weap->o_which].w_name, prname(mname));
                   1810:     else
                   1811:         msg("You hit the %s.", prname(mname));
                   1812: }
                   1813:
                   1814: /*
                   1815:     m_thunk()
                   1816:         A missile from a monster hits the player
                   1817: */
                   1818:
                   1819: void
                   1820: m_thunk(struct object *weap, char *mname)
                   1821: {
                   1822:     if (fighting)
                   1823:         return;
                   1824:
                   1825:     if (weap != NULL && weap->o_type == WEAPON)
                   1826:         msg("The %s's %s hits you.",prname(mname),weaps[weap->o_which].w_name);
                   1827:     else
                   1828:         msg("The %s hits you.", prname(mname));
                   1829: }
                   1830:
                   1831: /*
                   1832:     bounce()
                   1833:         A missile misses a monster
                   1834: */
                   1835:
                   1836: void
                   1837: bounce(struct object *weap, char *mname)
                   1838: {
                   1839:     if (fighting)
                   1840:         return;
                   1841:
                   1842:     if (weap->o_type == WEAPON)
                   1843:         msg("The %s misses the %s.",weaps[weap->o_which].w_name,prname(mname));
                   1844:     else
                   1845:         msg("You missed the %s.", prname(mname));
                   1846: }
                   1847:
                   1848: /*
                   1849:     m_bounce()
                   1850:         A missile from a monster misses the player
                   1851: */
                   1852:
                   1853: void
                   1854: m_bounce(struct object *weap, char *mname)
                   1855: {
                   1856:     if (fighting)
                   1857:         return;
                   1858:
                   1859:     if (weap != NULL && weap->o_type == WEAPON)
                   1860:         msg("The %s's %s misses you.", prname(mname),
                   1861:                                        weaps[weap->o_which].w_name);
                   1862:     else
                   1863:         msg("The %s misses you.", prname(mname));
                   1864: }
                   1865:
                   1866: /*
                   1867:     remove_monster()
                   1868:         remove a monster from the screen
                   1869: */
                   1870:
                   1871: void
                   1872: remove_monster(coord *mp, struct linked_list *item)
                   1873: {
                   1874:     struct thing *tp = THINGPTR(item);
                   1875:     char          ch = tp->t_oldch;
                   1876:
                   1877:     mvwaddch(mw, mp->y, mp->x, ' ');
                   1878:
                   1879:     if (ch < 33 || ch == ' ')
                   1880:         ch = CCHAR( mvwinch(stdscr, mp->y, mp->x) );
                   1881:
                   1882:     if (cansee(mp->y, mp->x))
                   1883:         mvwaddch(cw, mp->y, mp->x, ch);
                   1884:
                   1885:     detach(mlist, item);
                   1886:     discard(item);
                   1887: }
                   1888:
                   1889: /*
                   1890:     is_magic()
                   1891:         Returns true if an object radiates magic
                   1892: */
                   1893:
                   1894: int
                   1895: is_magic(struct object *obj)
                   1896: {
                   1897:     switch (obj->o_type)
                   1898:     {
                   1899:         case ARMOR:
                   1900:             return(obj->o_ac != armors[obj->o_which].a_class);
                   1901:
                   1902:         case WEAPON:
                   1903:             return(obj->o_hplus != 0 || obj->o_dplus != 0);
                   1904:
                   1905:         case POTION:
                   1906:         case SCROLL:
                   1907:         case STICK:
                   1908:         case RING:
                   1909:         case ARTIFACT:
                   1910:             return(TRUE);
                   1911:     }
                   1912:
                   1913:     return(FALSE);
                   1914: }
                   1915:
                   1916: /*
                   1917:     killed()
                   1918:         Called to put a monster to death
                   1919: */
                   1920:
                   1921: void
                   1922: killed(struct thing *killer, struct linked_list *item, int print_message,
                   1923:        int give_points)
                   1924: {
                   1925:     struct linked_list *pitem, *nitem;
                   1926:     struct thing       *tp        = THINGPTR(item);
                   1927:     int                 visible   = cansee(tp->t_pos.y, tp->t_pos.x);
                   1928:     int                 is_player = (killer == (&player));
                   1929:
                   1930:     if (item == curr_mons)
                   1931:         curr_mons = NULL;
                   1932:     else if (item == next_mons)
                   1933:         next_mons = next(next_mons);
                   1934:
                   1935:     if (on(*tp, WASSUMMONED))
                   1936:     {
                   1937:         extinguish_fuse(FUSE_UNSUMMON);
                   1938:         turn_off(player, HASSUMMONED);
                   1939:     }
                   1940:
                   1941:     if (print_message && visible)
                   1942:     {
                   1943:         if (is_player)
                   1944:             addmsg("You have defeated ");
                   1945:         else
                   1946:             addmsg("The %s has defeated ",
                   1947:                 monsters[killer->t_index].m_name);
                   1948:
                   1949:         if (on(player, ISBLIND))
                   1950:             msg("it.");
                   1951:         else
                   1952:             msg("the %s.", monsters[tp->t_index].m_name);
                   1953:     }
                   1954:     debug("Removing %s", monsters[tp->t_index].m_name);
                   1955:     if (killer != NULL && item == fam_ptr)  /* The player's familiar died */
                   1956:     {
                   1957:         turn_off(player, HASFAMILIAR);
                   1958:         fam_ptr = NULL;
                   1959:         msg("An incredible wave of sadness sweeps over you.");
                   1960:     }
                   1961:
                   1962:     check_residue(tp);
                   1963:
                   1964:     if (is_player)
                   1965:     {
                   1966:         fighting = FALSE;
                   1967:
                   1968:         if (on(*tp, ISFRIENDLY))
                   1969:         {
                   1970:             msg("You feel a slight chill run up and down your spine.");
                   1971:             luck++;
                   1972:         }
                   1973:     }
                   1974:
                   1975:     if (give_points)
                   1976:     {
                   1977:         if (killer != NULL)
                   1978:         {
                   1979:             killer->t_stats.s_exp += tp->t_stats.s_exp;
                   1980:
                   1981:             if (on(*killer, ISFAMILIAR))
                   1982:                 pstats.s_exp += tp->t_stats.s_exp;
                   1983:         }
                   1984:
                   1985:         if (is_player)
                   1986:         {
                   1987:             switch (player.t_ctype)
                   1988:             {
                   1989:                 case C_CLERIC:
                   1990:                 case C_PALADIN:
                   1991:                     if (on(*tp, ISUNDEAD) || on(*tp, ISUNIQUE))
                   1992:                     {
                   1993:                         pstats.s_exp += tp->t_stats.s_exp / 2;
                   1994:                         msg("You are to be commended for smiting the ungodly.");
                   1995:                     }
                   1996:                     break;
                   1997:
                   1998:                 case C_DRUID:
                   1999:                 case C_RANGER:
                   2000:                     if (on(*tp, ISLARGE))
                   2001:                     {
                   2002:                         pstats.s_exp += tp->t_stats.s_exp / 2;
                   2003:                         msg("Congratulations on smiting a dangerous monster.");
                   2004:                     }
                   2005:                     break;
                   2006:
                   2007:                 case C_MAGICIAN:
                   2008:                 case C_ILLUSION:
                   2009:                     if (on(*tp, DRAINBRAIN))
                   2010:                     {
                   2011:                         pstats.s_exp += tp->t_stats.s_exp / 2;
                   2012:                         msg("Congratulations on smiting a dangerous monster.");
                   2013:                     }
                   2014:
                   2015:             }
                   2016:         }
                   2017:         check_level();
                   2018:     }
                   2019:
                   2020:     /* Empty the monsters pack */
                   2021:
                   2022:     for (pitem = tp->t_pack; pitem != NULL; pitem = nitem)
                   2023:     {
                   2024:         struct object *obj = OBJPTR(pitem);
                   2025:
                   2026:         nitem = next(pitem);
                   2027:
                   2028:         obj->o_pos = tp->t_pos;
                   2029:         detach(tp->t_pack, pitem);
                   2030:
                   2031:         if (killer == NULL)
                   2032:             discard(pitem);
                   2033:         else
                   2034:             fall(killer, pitem, FALSE, FALSE);
                   2035:     }
                   2036:
                   2037:     remove_monster(&tp->t_pos, item);
                   2038: }
                   2039:
                   2040:
                   2041: /*
                   2042:     wield_weap()
                   2043:         Returns a pointer to the weapon the monster is wielding corresponding           to the given thrown weapon
                   2044: */
                   2045:
                   2046: struct object *
                   2047: wield_weap(struct object *weapon, struct thing *mp)
                   2048: {
                   2049:     int look_for;
                   2050:     struct linked_list *pitem;
                   2051:
                   2052:     if (weapon == NULL)
                   2053:         return (NULL);
                   2054:
                   2055:     switch (weapon->o_which)
                   2056:     {
                   2057:         case BOLT:
                   2058:             look_for = CROSSBOW;
                   2059:             break;
                   2060:
                   2061:         case ARROW:
                   2062:             look_for = BOW;
                   2063:             break;
                   2064:
                   2065:         case SILVERARROW:
                   2066:         case FLAMEARROW:
                   2067:             look_for = BOW;
                   2068:             break;
                   2069:
                   2070:         case ROCK:
                   2071:         case BULLET:
                   2072:             look_for = SLING;
                   2073:             break;
                   2074:
                   2075:         default:
                   2076:             return(NULL);
                   2077:     }
                   2078:
                   2079:     for (pitem = mp->t_pack; pitem; pitem = next(pitem))
                   2080:         if ((OBJPTR(pitem))->o_which == look_for)
                   2081:             return(OBJPTR(pitem));
                   2082:
                   2083:     return (NULL);
                   2084: }
                   2085:
                   2086: /*
                   2087:     summon_help()
                   2088:         Summon - see whether to summon help Returns TRUE if help comes, FALSE
                   2089:         otherwise
                   2090: */
                   2091:
                   2092: void
                   2093: summon_help(struct thing *mons, int force)
                   2094: {
                   2095:     char *helpname;
                   2096:     int   which, i;
                   2097:     char *mname = monsters[mons->t_index].m_name;
                   2098:
                   2099:     /* Try to summon if less than 1/3 max hit points */
                   2100:
                   2101:     if (on(*mons, CANSUMMON) &&
                   2102:       (force == FORCE ||
                   2103:       (mons->t_stats.s_hpt < mons->maxstats.s_hpt / 3) &&
                   2104:       (rnd(40 * 10) < (mons->t_stats.s_lvl * mons->t_stats.s_intel))))
                   2105:     {
                   2106:         turn_off(*mons, CANSUMMON);
                   2107:         msg("The %s summons its attendants!", mname);
                   2108:         helpname = monsters[mons->t_index].m_typesum;
                   2109:
                   2110:         for (which = 1; which < nummonst; which++)
                   2111:         {
                   2112:             if (strcmp(helpname, monsters[which].m_name) == 0)
                   2113:                 break;
                   2114:         }
                   2115:
                   2116:         if (which >= nummonst)
                   2117:         {
                   2118:             debug("Couldn't find summoned one.");
                   2119:             return;
                   2120:         }
                   2121:
                   2122:         /* summoned monster was genocided */
                   2123:
                   2124:         if (!monsters[which].m_normal)
                   2125:         {
                   2126:             msg("The %s becomes very annoyed at you!", mname);
                   2127:
                   2128:             if (on(*mons, ISSLOW))
                   2129:                 turn_off(*mons, ISSLOW);
                   2130:             else
                   2131:                 turn_on(*mons, ISHASTE);
                   2132:
                   2133:             return;
                   2134:         }
                   2135:         else
                   2136:             for (i = 0; i < monsters[mons->t_index].m_numsum; i++)
                   2137:             {
                   2138:                 struct linked_list  *ip;
                   2139:                 struct thing    *tp;
                   2140:
                   2141:                 if ((ip = creat_mons(mons, which, NOMESSAGE)) != NULL)
                   2142:                 {
                   2143:                     tp = THINGPTR(ip);
                   2144:                     turn_off(*tp, ISFRIENDLY);
                   2145:                 }
                   2146:             }
                   2147:     }
                   2148:
                   2149:     return;
                   2150: }
                   2151:
                   2152: /*
                   2153:     maxdamage()
                   2154:         return the max damage a weapon can do
                   2155: */
                   2156:
                   2157: int
                   2158: maxdamage(char *cp)
                   2159: {
                   2160:     int ndice, nsides, nplus;
                   2161:
                   2162:     ndice = atoi(cp);
                   2163:
                   2164:     if (cp == NULL || (cp = strchr(cp, 'd')) == NULL)
                   2165:         return(0);
                   2166:
                   2167:     nsides = atoi(++cp);
                   2168:
                   2169:     if (cp != NULL && (cp = strchr(cp, '+')) != NULL)
                   2170:         nplus = atoi(++cp);
                   2171:     else
                   2172:         nplus = 0;
                   2173:
                   2174:     return(ndice * nsides + nplus);
                   2175: }

CVSweb