[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     ! 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