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

Annotation of early-roguelike/urogue/monsters.c, Revision 1.1

1.1     ! rubenllo    1: /*
        !             2:     monsters.c - File with various monster functions in it
        !             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:     summon_monster()
        !            26:         Summon a monster.
        !            27: */
        !            28:
        !            29: struct linked_list *
        !            30: summon_monster(int type, int familiar, int print_message)
        !            31: {
        !            32:     struct linked_list  *mp;
        !            33:     struct thing    *tp;
        !            34:     int   monster;
        !            35:
        !            36:     if (familiar && !is_wearing(R_WIZARD) && off(player, CANSUMMON))
        !            37:     {
        !            38:         msg("Only spellcasters can summon familiars!");
        !            39:         return(NULL);
        !            40:     }
        !            41:
        !            42:     if (type == 0)    /* Random monster modified by level */
        !            43:     {
        !            44:         int ndice = min(pstats.s_lvl, (nummonst - NUMSUMMON) / 8);
        !            45:
        !            46:         monster = min(nummonst, roll(ndice, pstats.s_charisma));
        !            47:
        !            48:                /*
        !            49:          * if a familiar exists, and it is higher in level, make it
        !            50:          * again
        !            51:          */
        !            52:
        !            53:         if (fam_ptr != NULL)
        !            54:                {
        !            55:             struct thing   *fp = THINGPTR(fam_ptr);
        !            56:
        !            57:             monster = max(fp->t_index, monster);
        !            58:         }
        !            59:        }
        !            60:     else
        !            61:         monster = type;
        !            62:
        !            63:     turn_on(player, SUMMONING);
        !            64:
        !            65:     mp = creat_mons(&player, monster, NOMESSAGE);
        !            66:
        !            67:     if (!mp)
        !            68:     {
        !            69:         msg("Summon failed.");
        !            70:         turn_off(player, SUMMONING);
        !            71:         return(NULL);
        !            72:     }
        !            73:
        !            74:     if (print_message == MESSAGE)
        !            75:     {
        !            76:         msg("A %s appears out of nowhere!", monsters[monster].m_name);
        !            77:
        !            78:         if (familiar)
        !            79:             msg("I am here to serve %s.", whoami);
        !            80:         else
        !            81:         {
        !            82:             msg("My goodness, are you Yendor?");
        !            83:             ++mons_summoned;
        !            84:             debug("%d monsters now summoned.", mons_summoned);
        !            85:         }
        !            86:     }
        !            87:
        !            88:     tp = THINGPTR(mp);
        !            89:     turn_on(*tp, ISCHARMED);    /* Summoned monsters are always charmed */
        !            90:
        !            91:     if (familiar)
        !            92:     {
        !            93:         int i;
        !            94:         static const unsigned long fam_on[]= {ISREGEN,CANSHOOT,CANWIELD,HASARMOR,ISFAMILIAR,0};
        !            95:         static const unsigned long fam_off[]={ISMEAN, ISHUH, ISINVIS,
        !            96:                     CANSURPRISE, NOMOVE,
        !            97:                     ISSLOW, ISSHADOW, ISGREED, ISFAST,
        !            98:                     CANFLY, ISFLEE, 0};
        !            99:
        !           100:         for (i = 0; fam_on[i]; i++)
        !           101:             turn_on(*tp, fam_on[i]);
        !           102:
        !           103:         for (i = 0; fam_off[i]; i++)
        !           104:             turn_off(*tp, fam_off[i]);
        !           105:
        !           106:         if (fam_ptr != NULL)    /* Get rid of old familiar */
        !           107:         {
        !           108:             struct thing    *fp = THINGPTR(fam_ptr);
        !           109:             struct linked_list  *fpack = fp->t_pack;
        !           110:             struct linked_list  *item;
        !           111:
        !           112:             if (fpack != NULL)  /* Transfer pack */
        !           113:             {
        !           114:                 if (tp->t_pack == NULL)
        !           115:                     tp->t_pack = fpack;
        !           116:                 else
        !           117:                 {
        !           118:                     for(item=tp->t_pack; item->l_next != NULL; item=next(item))
        !           119:                         ;   /* find last item in list */
        !           120:
        !           121:                     item->l_next = fpack;
        !           122:                     fpack->l_prev = item;
        !           123:                 }
        !           124:             }
        !           125:
        !           126:             fpack = NULL;
        !           127:             killed(NULL, fam_ptr, NOMESSAGE, NOPOINTS);
        !           128:         }
        !           129:
        !           130:         fam_ptr = mp;
        !           131:         fam_type = monster;
        !           132:
        !           133:         /* improve their abilities a bit */
        !           134:
        !           135:         tp->t_stats.s_hpt += roll(2, pstats.s_lvl);
        !           136:         tp->t_stats.s_lvl += roll(2, (pstats.s_lvl / 4) + 1);
        !           137:         tp->t_stats.s_arm -= roll(2, (pstats.s_lvl / 4) + 1);
        !           138:         tp->t_stats.s_str += roll(2, (pstats.s_lvl / 4) + 1);
        !           139:         tp->t_stats.s_intel += roll(2, (pstats.s_lvl / 4) + 1);
        !           140:         tp->t_stats.s_wisdom += roll(2, (pstats.s_lvl / 4) + 1);
        !           141:         tp->t_stats.s_dext += roll(2, (pstats.s_lvl / 4) + 1);
        !           142:         tp->t_stats.s_const += roll(2, (pstats.s_lvl / 4) + 1);
        !           143:         tp->t_stats.s_charisma += roll(2, (pstats.s_lvl / 4) + 1);
        !           144:
        !           145:                /* some monsters do no damage by default */
        !           146:
        !           147:                if (strcmp(tp->t_stats.s_dmg, "0d0") == 0)
        !           148:             tp->t_stats.s_dmg = "1d8";
        !           149:
        !           150:         tp->maxstats = tp->t_stats; /* structure assignment */
        !           151:     }
        !           152:
        !           153:     turn_off(player, SUMMONING);
        !           154:
        !           155:     return(mp);
        !           156: }
        !           157:
        !           158: /*
        !           159:      randmonster()
        !           160:         wander - wandering monster allowed
        !           161:         grab - a throne room monster allowed
        !           162: */
        !           163:
        !           164: int
        !           165: randmonster(int wander, int grab)
        !           166: {
        !           167:     int mons_number, cur_level, range, i;
        !           168:
        !           169:     /* Do we want a merchant? */
        !           170:
        !           171:     if (wander == WANDER && monsters[nummonst].m_wander && rnd(5000) < 3)
        !           172:         return(nummonst);
        !           173:
        !           174:     cur_level = level;
        !           175:     range = 4 * NLEVMONS;
        !           176:     i = 0;
        !           177:
        !           178:     do
        !           179:     {
        !           180:         if (i++ > range * 10)   /* just in case all have be genocided */
        !           181:         {
        !           182:             i = 0;
        !           183:
        !           184:             if (--cur_level <= 0)
        !           185:                 fatal("Rogue could not find a monster to make");
        !           186:         }
        !           187:
        !           188:         mons_number = NLEVMONS * (cur_level - 1) +
        !           189:             (rnd(range) - (range - 1 - NLEVMONS));
        !           190:
        !           191:         if (mons_number < 1)
        !           192:             mons_number = rnd(NLEVMONS) + 1;
        !           193:         else if (mons_number > nummonst - NUMSUMMON - 1)
        !           194:         {
        !           195:             if (grab == GRAB)
        !           196:                 mons_number = rnd(range + NUMSUMMON) +
        !           197:                     (nummonst - 1) -
        !           198:                     (range + NUMSUMMON - 1);
        !           199:             else if (mons_number > nummonst - 1)
        !           200:                 mons_number = rnd(range) +
        !           201:                 (nummonst - NUMSUMMON - 1) -
        !           202:                 (range - 1);
        !           203:         }
        !           204:     }
        !           205:     while (wander == WANDER ? !monsters[mons_number].m_wander ||
        !           206:         !monsters[mons_number].m_normal :
        !           207:         !monsters[mons_number].m_normal);
        !           208:
        !           209:     return((short)mons_number);
        !           210: }
        !           211:
        !           212: /*
        !           213:     new_monster()
        !           214:         Pick a new monster and add it to the list
        !           215: */
        !           216:
        !           217: void
        !           218: new_monster(struct linked_list *item, int type, coord *cp, int max_monster)
        !           219: {
        !           220:     struct thing    *tp;
        !           221:     struct monster  *mp;
        !           222:     char    *ip, *hitp;
        !           223:     int   i, min_intel, max_intel;
        !           224:     int   num_dice, num_sides = 8, num_extra = 0;
        !           225:     int eff_charisma = pstats.s_charisma;
        !           226:     int eff_intel = pstats.s_intel;
        !           227:
        !           228:     attach(mlist, item);
        !           229:     tp = THINGPTR(item);
        !           230:     tp->t_index = type;
        !           231:     tp->t_wasshot = FALSE;
        !           232:     tp->t_type = monsters[type].m_appear;
        !           233:     tp->t_ctype = C_MONSTER;
        !           234:     tp->t_no_move = 0;
        !           235:     tp->t_doorgoal = -1;
        !           236:     tp->t_pos = *cp;
        !           237:     tp->t_oldpos = *cp;
        !           238:     tp->t_oldch = CCHAR( mvwinch(cw, cp->y, cp->x) );
        !           239:     mvwaddch(mw, cp->y, cp->x, tp->t_type);
        !           240:     mp = &monsters[tp->t_index];
        !           241:
        !           242:     /* Figure out monster's hit points */
        !           243:
        !           244:     hitp = mp->m_stats.s_hpt;
        !           245:     num_dice = atoi(hitp);
        !           246:
        !           247:     if ((hitp = strchr(hitp, 'd')) != NULL)
        !           248:     {
        !           249:         num_sides = atoi(++hitp);
        !           250:
        !           251:         if ((hitp = strchr(hitp, '+')) != NULL)
        !           252:             num_extra = atoi(++hitp);
        !           253:     }
        !           254:
        !           255:     if (max_monster == MAXSTATS)
        !           256:         tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
        !           257:     else
        !           258:         tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
        !           259:
        !           260:     tp->t_stats.s_lvl = mp->m_stats.s_lvl;
        !           261:     tp->t_stats.s_arm = mp->m_stats.s_arm;
        !           262:     tp->t_stats.s_dmg = mp->m_stats.s_dmg;
        !           263:     tp->t_stats.s_exp = mp->m_stats.s_exp + mp->m_add_exp * tp->t_stats.s_hpt;
        !           264:     tp->t_stats.s_str = mp->m_stats.s_str;
        !           265:
        !           266:     if (max_level > 30)
        !           267:     {
        !           268:         tp->t_stats.s_hpt += roll(4, (max_level - 60) * 2);
        !           269:         tp->t_stats.s_lvl += roll(4, (max_level - 60) / 8);
        !           270:         tp->t_stats.s_arm -= roll(2, (max_level - 60) / 8);
        !           271:         tp->t_stats.s_str += roll(2, (max_level - 60) / 12);
        !           272:         tp->t_stats.s_exp += roll(4, (max_level - 60) * 2) * mp->m_add_exp;
        !           273:     }
        !           274:
        !           275:     /*
        !           276:      * just initailize others values to something reasonable for now
        !           277:      * maybe someday will *really* put these in monster table
        !           278:      */
        !           279:
        !           280:     tp->t_stats.s_wisdom = 8 + rnd(4);
        !           281:     tp->t_stats.s_dext = 8 + rnd(4);
        !           282:     tp->t_stats.s_const = 8 + rnd(4);
        !           283:     tp->t_stats.s_charisma = 8 + rnd(4);
        !           284:
        !           285:     if (max_level > 45)
        !           286:         tp->t_stats.s_dext += roll(2, (max_level - 50) / 8);
        !           287:
        !           288:     /* Set the initial flags */
        !           289:
        !           290:     for (i = 0; i < 16; i++)
        !           291:         tp->t_flags[i] = 0;
        !           292:
        !           293:     for (i = 0; i < 16; i++)
        !           294:         turn_on(*tp, mp->m_flags[i]);
        !           295:
        !           296:     /* suprising monsters don't always surprise you */
        !           297:
        !           298:     if (!max_monster && on(*tp, CANSURPRISE) && rnd(100) < 20)
        !           299:         turn_off(*tp, CANSURPRISE);
        !           300:
        !           301:     /* If this monster is unique, genocide it */
        !           302:
        !           303:     if (on(*tp, ISUNIQUE))
        !           304:         mp->m_normal = FALSE;
        !           305:
        !           306:     /* gods automatically get special abilities */
        !           307:
        !           308:     if (on(*tp, ISGOD))
        !           309:     {
        !           310:         turn_on(*tp, CANFRIGHTEN);
        !           311:         turn_on(*tp, CANCAST);
        !           312:         turn_on(*tp, CANFLY);
        !           313:         turn_on(*tp, CANBARGAIN);
        !           314:         turn_on(*tp, ISLARGE);
        !           315:         turn_on(*tp, CANTELEPORT);
        !           316:         turn_on(*tp, CANSPEAK);
        !           317:         turn_on(*tp, CANDARKEN);
        !           318:         turn_on(*tp, CANSEE);
        !           319:         turn_on(*tp, CANLIGHT);
        !           320:         turn_on(*tp, BMAGICHIT);
        !           321:     }
        !           322:
        !           323:     tp->t_turn = TRUE;
        !           324:     tp->t_pack = NULL;
        !           325:
        !           326:     /* Figure intelligence */
        !           327:
        !           328:     min_intel = atoi(mp->m_intel);
        !           329:
        !           330:     if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
        !           331:         tp->t_stats.s_intel = min_intel;
        !           332:     else
        !           333:     {
        !           334:         max_intel = atoi(++ip);
        !           335:
        !           336:         if (max_monster)
        !           337:             tp->t_stats.s_intel = max_intel;
        !           338:         else
        !           339:             tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
        !           340:     }
        !           341:
        !           342:     tp->t_stats.s_power = (rnd(tp->t_stats.s_lvl / 5) + 1) * tp->t_stats.s_intel;
        !           343:
        !           344:     tp->maxstats = tp->t_stats; /* structure assignment */
        !           345:
        !           346:     /* If the monster can shoot, it may have a weapon */
        !           347:
        !           348:     if (on(*tp, CANSHOOT) && (max_monster || rnd(9) < 6))
        !           349:     {
        !           350:         struct linked_list  *thrower_item, *missile_item;
        !           351:         struct object *thrower, *a_missile;
        !           352:
        !           353:         thrower_item = new_item(sizeof *thrower);
        !           354:         thrower = OBJPTR(thrower_item);
        !           355:         carried_weapon(tp, thrower);
        !           356:
        !           357:         missile_item = new_item(sizeof *a_missile);
        !           358:         a_missile = OBJPTR(missile_item);
        !           359:         carried_weapon(tp, a_missile);
        !           360:
        !           361:         /* The monster may use a crossbow, sling, footbow, or an arrow */
        !           362:         /* Take racial preferences into account */
        !           363:
        !           364:         if ((strcmp(mp->m_name, "elf") == 0) ||
        !           365:             (strcmp(mp->m_name, "noldor elf") == 0))
        !           366:         {
        !           367:             thrower->o_which = BOW;
        !           368:
        !           369:             if (rnd(5) == 0)
        !           370:                 a_missile->o_which = SILVERARROW;
        !           371:             else
        !           372:                 a_missile->o_which = ARROW;
        !           373:         }
        !           374:         else if ((strcmp(mp->m_name, "dwarf") == 0) ||
        !           375:                 (strcmp(mp->m_name, "kazad dwarf") == 0))
        !           376:         {
        !           377:             thrower->o_which = CROSSBOW;
        !           378:             a_missile->o_which = BOLT;
        !           379:         }
        !           380:         else if (on(*tp, ISSMALL))
        !           381:         {
        !           382:             switch (rnd(3))
        !           383:             {
        !           384:                 case 0:
        !           385:                     thrower->o_which = SLING;
        !           386:                     a_missile->o_which = BULLET;
        !           387:                     break;
        !           388:                 default:
        !           389:                     thrower->o_which = SLING;
        !           390:                     a_missile->o_which = ROCK;
        !           391:             }
        !           392:         }
        !           393:         else if (on(*tp, ISLARGE))
        !           394:         {
        !           395:             switch (rnd(4))
        !           396:             {
        !           397:                 case 0:
        !           398:                     thrower->o_which = CROSSBOW;
        !           399:                     a_missile->o_which = BOLT;
        !           400:                     break;
        !           401:
        !           402:                 case 1:
        !           403:                     thrower->o_which = FOOTBOW;
        !           404:                     a_missile->o_which = FBBOLT;
        !           405:                     break;
        !           406:
        !           407:                 default:
        !           408:                     thrower->o_which = BOW;
        !           409:
        !           410:                     if (rnd(5) == 0)
        !           411:                         a_missile->o_which = FLAMEARROW;
        !           412:                     else
        !           413:                         a_missile->o_which = ARROW;
        !           414:
        !           415:                     break;
        !           416:             }
        !           417:         }
        !           418:         else
        !           419:         {
        !           420:             switch (rnd(6))
        !           421:             {
        !           422:                 case 1:
        !           423:                     thrower->o_which = SLING;
        !           424:                     a_missile->o_which = ROCK;
        !           425:                     break;
        !           426:
        !           427:                 case 2:
        !           428:                     thrower->o_which = CROSSBOW;
        !           429:                     a_missile->o_which = BOLT;
        !           430:                     break;
        !           431:
        !           432:                 case 3:
        !           433:                     thrower->o_which = FOOTBOW;
        !           434:                     a_missile->o_which = FBBOLT;
        !           435:                     break;
        !           436:
        !           437:                 case 4:
        !           438:                     thrower->o_which = BOW;
        !           439:                     a_missile->o_which = ARROW;
        !           440:                     break;
        !           441:
        !           442:                 default:
        !           443:                     thrower->o_which = SLING;
        !           444:                     a_missile->o_which = BULLET;
        !           445:                     break;
        !           446:             }
        !           447:         }
        !           448:
        !           449:         init_weapon(thrower, thrower->o_which);
        !           450:         init_weapon(a_missile, a_missile->o_which);
        !           451:
        !           452:         attach(tp->t_pack, thrower_item);
        !           453:         attach(tp->t_pack, missile_item);
        !           454:     }
        !           455:
        !           456:     /* monsters that wield weapons */
        !           457:
        !           458:     if (on(*tp, CANWIELD))
        !           459:     {
        !           460:         if (max_monster || rnd(3))
        !           461:         {
        !           462:             struct linked_list  *wield_item;
        !           463:             struct object   *wielded;
        !           464:
        !           465:             wield_item = new_item(sizeof *wielded);
        !           466:             wielded = OBJPTR(wield_item);
        !           467:             carried_weapon(tp, wielded);
        !           468:
        !           469:             i = rnd(CLAYMORE - CLUB) + rnd(2 * tp->t_stats.s_lvl);
        !           470:             i = min(i, CLAYMORE);
        !           471:             wielded->o_which = i;
        !           472:             init_weapon(wielded, wielded->o_which);
        !           473:
        !           474:             /* Is it too heavy? */
        !           475:
        !           476:             if (itemweight(wielded) > 8 * tp->t_stats.s_str)
        !           477:                 discard(wield_item);
        !           478:             else
        !           479:                 attach(tp->t_pack, wield_item);
        !           480:         }
        !           481:     }
        !           482:
        !           483:     if (is_wearing(R_AGGR))
        !           484:         chase_it(cp, &player);
        !           485:     else
        !           486:     {
        !           487:         turn_off(*tp, ISRUN);
        !           488:
        !           489:         if (on(*tp, ISFLEE) && (rnd(4) == 0))
        !           490:             turn_off(*tp, ISFLEE);
        !           491:
        !           492:         if (rnd(luck) == 0)
        !           493:             switch (player.t_ctype)
        !           494:             {
        !           495:                 case C_MAGICIAN:
        !           496:                 case C_ILLUSION:
        !           497:                     eff_intel = 2 * pstats.s_intel;
        !           498:                     break;
        !           499:                 case C_DRUID:
        !           500:                     eff_intel = 2 * pstats.s_intel;
        !           501:                 case C_RANGER:
        !           502:                     eff_charisma = 2 * pstats.s_charisma;
        !           503:                     break;
        !           504:                 case C_ASSASIN:
        !           505:                 case C_THIEF:
        !           506:                 case C_NINJA:
        !           507:                     eff_charisma = pstats.s_charisma / 2;
        !           508:                     break;
        !           509:             }
        !           510:
        !           511:         /* LOWFRIENDLY monsters might be friendly */
        !           512:
        !           513:         i = roll(1,100);
        !           514:
        !           515:         if (i == 0 || (on(*tp, LOWFRIENDLY) && i < eff_charisma) ||
        !           516:             (on(*tp, MEDFRIENDLY) && i < 3 * eff_charisma) ||
        !           517:             (on(*tp, HIGHFRIENDLY) && i < 5 * eff_charisma))
        !           518:         {
        !           519:             turn_on(*tp, ISFRIENDLY);
        !           520:             turn_off(*tp, ISMEAN);
        !           521:         }
        !           522:
        !           523:         i = roll(1,100);
        !           524:
        !           525:         if (i == 0 || (on(*tp, LOWCAST) && i < eff_intel) ||
        !           526:             (on(*tp, MEDCAST) && i < 3 * eff_intel) ||
        !           527:             (on(*tp, HIGHCAST) && i < 5 * eff_intel))
        !           528:         {
        !           529:             turn_on(*tp, CANCAST);
        !           530:         }
        !           531:
        !           532:         if (on(*tp, ISDISGUISE))
        !           533:         {
        !           534:             char    mch = 0;
        !           535:
        !           536:             if (tp->t_pack != NULL)
        !           537:                 mch = (OBJPTR(tp->t_pack))->o_type;
        !           538:             else
        !           539:                 switch (rnd(level > arts[0].ar_level ? 10 : 9))
        !           540:                 {
        !           541:                     case 0: mch = GOLD;     break;
        !           542:                     case 1: mch = POTION;   break;
        !           543:                     case 2: mch = SCROLL;   break;
        !           544:                     case 3: mch = FOOD;     break;
        !           545:                     case 4: mch = WEAPON;   break;
        !           546:                     case 5: mch = ARMOR;    break;
        !           547:                     case 6: mch = RING;     break;
        !           548:                     case 7: mch = STICK;    break;
        !           549:                     case 8: mch = monsters[randmonster(NOWANDER, NOGRAB)].m_appear;
        !           550:                                 break;
        !           551:                     case 9: mch = ARTIFACT; break;
        !           552:                 }
        !           553:
        !           554:             tp->t_disguise = mch;
        !           555:         }
        !           556:     }
        !           557: }
        !           558:
        !           559: /*
        !           560:     wanderer()
        !           561:         A wandering monster has awakened and is headed for the player
        !           562: */
        !           563:
        !           564: void
        !           565: wanderer(void)
        !           566: {
        !           567:     int i, cnt = 0;
        !           568:     struct room *hr = roomin(hero);
        !           569:     struct linked_list  *item;
        !           570:     struct thing    *tp;
        !           571:     coord   cp;
        !           572:     char    *loc;
        !           573:     int which;
        !           574:
        !           575:     /* Find a place for it -- avoid the player's room */
        !           576:
        !           577:     do
        !           578:     {
        !           579:         do
        !           580:         {
        !           581:             cnt++;
        !           582:             i = rnd_room();
        !           583:         }
        !           584:         while (!(hr != &rooms[i] || levtype == MAZELEV
        !           585:                || levtype == THRONE || cnt > 5000));
        !           586:
        !           587:         rnd_pos(&rooms[i], &cp);
        !           588:     }
        !           589:     while(!step_ok(cp.y, cp.x, NOMONST, NULL));
        !           590:
        !           591:     /* Create a new wandering monster */
        !           592:
        !           593:     item = new_item(sizeof *tp);
        !           594:     which = randmonster(TRUE, FALSE);
        !           595:     new_monster(item, which, &cp, FALSE);
        !           596:
        !           597:     tp = THINGPTR(item);
        !           598:     tp->t_pos = cp;     /* Assign the position to the monster */
        !           599:
        !           600:     chase_it(&tp->t_pos, &player);
        !           601:
        !           602:     i = rnd(7);
        !           603:
        !           604:     if (on(*tp, ISSWARM) && i < 5)
        !           605:         cnt = roll(2, 4);
        !           606:     else if (on(*tp, ISFLOCK) && i < 5)
        !           607:         cnt = roll(1, 4);
        !           608:     else
        !           609:         cnt = 0;
        !           610:
        !           611:     for (i = 1; i <= cnt; i++)
        !           612:     {
        !           613:         struct linked_list  *ip = creat_mons(tp, which, NOMESSAGE);
        !           614:
        !           615:         if (ip != NULL)
        !           616:         {
        !           617:             struct thing    *mp = THINGPTR(ip);
        !           618:
        !           619:             if (on(*tp, ISFRIENDLY))
        !           620:                 turn_on(*mp, ISFRIENDLY);
        !           621:             else
        !           622:                 turn_off(*mp, ISFRIENDLY);
        !           623:         }
        !           624:     }
        !           625:
        !           626:     if (cnt > 0)
        !           627:     {
        !           628:         if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST))
        !           629:             turn_on(*tp, CANCAST);
        !           630:
        !           631:         tp->t_stats.s_hpt += roll(2, 8);
        !           632:         tp->t_stats.s_lvl += roll(2, 3);
        !           633:         tp->t_stats.s_arm -= roll(1, 6);
        !           634:         tp->t_stats.s_str += roll(2, 3);
        !           635:         tp->t_stats.s_intel += roll(2, 3);
        !           636:         tp->t_stats.s_exp += roll(2, 8) * monsters[which].m_add_exp;
        !           637:     }
        !           638:
        !           639:     i = DISTANCE(cp, hero);
        !           640:
        !           641:     if (i < 20)
        !           642:         loc = "very close to you";
        !           643:     else if (i < 400)
        !           644:         loc = "nearby";
        !           645:     else
        !           646:         loc = "in the distance";
        !           647:
        !           648:     if (wizard)
        !           649:         msg("Started a wandering %s.", monsters[tp->t_index].m_name);
        !           650:     else if (on(*tp, ISUNDEAD) && (player.t_ctype == C_CLERIC ||
        !           651:             player.t_ctype == C_PALADIN || is_wearing(R_PIETY)))
        !           652:         msg("You sense a new ungodly monster %s.", loc);
        !           653:     else if (on(player, CANHEAR) || (player.t_ctype == C_THIEF &&
        !           654:             rnd(20) == 0))
        !           655:         msg("You hear a new %s moving %s.",
        !           656:             monsters[tp->t_index].m_name, loc);
        !           657:     else if (on(player, CANSCENT) || (player.t_ctype == C_THIEF &&
        !           658:             rnd(20) == 0))
        !           659:         msg("You smell a new %s %s.", monsters[tp->t_index].m_name,
        !           660:             loc);
        !           661: }
        !           662:
        !           663: /*
        !           664:     wake_monster
        !           665:
        !           666:         what to do when the hero steps next to a monster
        !           667: */
        !           668:
        !           669: struct linked_list *
        !           670: wake_monster(int y, int x)
        !           671: {
        !           672:     struct thing    *tp;
        !           673:     struct linked_list  *it;
        !           674:     struct room *trp;
        !           675:     char    *mname;
        !           676:
        !           677:     if ((it = find_mons(y, x)) == NULL)
        !           678:     {
        !           679:         debug("Can't find monster in show.");
        !           680:         return(NULL);
        !           681:     }
        !           682:
        !           683:     tp = THINGPTR(it);
        !           684:
        !           685:     if ((good_monster(*tp)) || on(player, SUMMONING))
        !           686:     {
        !           687:         chase_it(&tp->t_pos, &player);
        !           688:         turn_off(*tp, ISINVIS);
        !           689:         turn_off(*tp, CANSURPRISE);
        !           690:         return(it);
        !           691:     }
        !           692:
        !           693:     trp = roomin(tp->t_pos);   /* Current room for monster */
        !           694:     mname = monsters[tp->t_index].m_name;
        !           695:
        !           696:     /* Let greedy ones guard gold */
        !           697:
        !           698:     if (on(*tp, ISGREED) && off(*tp, ISRUN))
        !           699:         if ((trp != NULL) && (lvl_obj != NULL))
        !           700:         {
        !           701:             struct linked_list  *item;
        !           702:             struct object   *cur;
        !           703:
        !           704:             for (item = lvl_obj; item != NULL; item = next(item))
        !           705:             {
        !           706:                 cur = OBJPTR(item);
        !           707:
        !           708:                 if ((cur->o_type == GOLD) &&
        !           709:                     (roomin(cur->o_pos) == trp))
        !           710:                 {
        !           711:                     /* Run to the gold */
        !           712:                     tp->t_horde = cur;
        !           713:                     turn_on(*tp, ISRUN);
        !           714:                     turn_off(*tp, ISDISGUISE);
        !           715:                     tp->t_ischasing = FALSE;
        !           716:                     /* Make it worth protecting */
        !           717:                     cur->o_count += roll(2, 3) * GOLDCALC;
        !           718:                     break;
        !           719:                 }
        !           720:             }
        !           721:         }
        !           722:
        !           723:     /*
        !           724:      * Every time he sees mean monster, it might start chasing him unique
        !           725:      * monsters always do
        !           726:      */
        !           727:
        !           728:     if (  (on(*tp, ISUNIQUE)) ||
        !           729:           ( (rnd(100) > 33) &&
        !           730:             on(*tp, ISMEAN) &&
        !           731:             off(*tp, ISHELD) &&
        !           732:             off(*tp, ISRUN) &&
        !           733:             !is_stealth(&player) &&
        !           734:             (off(player, ISINVIS) || on(*tp, CANSEE))
        !           735:           )
        !           736:        )
        !           737:     {
        !           738:         chase_it(&tp->t_pos, &player);
        !           739:     }
        !           740:
        !           741:     /* Handle gaze attacks */
        !           742:
        !           743:     if (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x) &&
        !           744:             off(player, ISINVIS))
        !           745:     {
        !           746:         if (on(*tp, CANHUH))    /* Confusion */
        !           747:         {
        !           748:             if (on(player, CANREFLECT))
        !           749:             {
        !           750:                 msg("You reflect the bewildering stare of the %s.", mname);
        !           751:
        !           752:                 if (save_throw(VS_MAGIC, tp))
        !           753:                 {
        !           754:                     msg("The %s is confused!", mname);
        !           755:                     turn_on(*tp, ISHUH);
        !           756:                 }
        !           757:                 else
        !           758:                     msg("The %s staggers for a moment.", mname);
        !           759:             }
        !           760:             else if (save(VS_MAGIC))
        !           761:             {
        !           762:                 msg("You feel dizzy for a moment, but it quickly passes.");
        !           763:
        !           764:                 if (rnd(100) < 67)
        !           765:                     turn_off(*tp, CANHUH);
        !           766:             }
        !           767:             else if (off(player, ISCLEAR))
        !           768:             {
        !           769:                 if (off(player, ISHUH))
        !           770:                 {
        !           771:                     light_fuse(FUSE_UNCONFUSE, 0, rnd(20) + HUHDURATION, AFTER);
        !           772:                     msg("The %s's gaze has confused you.", mname);
        !           773:                     turn_on(player, ISHUH);
        !           774:                 }
        !           775:                 else
        !           776:                     lengthen_fuse(FUSE_UNCONFUSE, rnd(20) + HUHDURATION);
        !           777:             }
        !           778:         }
        !           779:
        !           780:         if (on(*tp, CANSNORE))      /* Sleep */
        !           781:         {
        !           782:             if (on(player, CANREFLECT))
        !           783:             {
        !           784:                 msg("You reflect the lethargic glance of the %s", mname);
        !           785:
        !           786:                 if (save_throw(VS_PARALYZATION, tp))
        !           787:                 {
        !           788:                     msg("The %s falls asleep!", mname);
        !           789:                     tp->t_no_move += SLEEPTIME;
        !           790:                 }
        !           791:             }
        !           792:             else if (no_command == 0 && !save(VS_PARALYZATION))
        !           793:             {
        !           794:                 if (is_wearing(R_ALERT))
        !           795:                     msg("You feel slightly drowsy for a moment.");
        !           796:                 else
        !           797:                 {
        !           798:                     msg("The %s's gaze puts you to sleep.", mname);
        !           799:                     no_command = SLEEPTIME;
        !           800:
        !           801:                     if (rnd(100) < 50)
        !           802:                         turn_off(*tp, CANSNORE);
        !           803:                 }
        !           804:             }
        !           805:         }
        !           806:
        !           807:         if (on(*tp, CANFRIGHTEN))   /* Fear */
        !           808:         {
        !           809:             turn_off(*tp, CANFRIGHTEN);
        !           810:
        !           811:             if (on(player, CANREFLECT))
        !           812:             {
        !           813:                 msg("The %s sees its reflection. ", mname);
        !           814:
        !           815:                 if (save_throw(VS_MAGIC,tp))
        !           816:                 {
        !           817:                     msg("The %s is terrified by its reflection!", mname);
        !           818:                     turn_on(*tp, ISFLEE);
        !           819:                 }
        !           820:             }
        !           821:             else
        !           822:             {
        !           823:                 if (!save(VS_WAND) && !(on(player, ISFLEE) &&
        !           824:                        (player.t_chasee==tp)))
        !           825:                 {
        !           826:                     if ((player.t_ctype != C_PALADIN) &&
        !           827:                         off(player, SUPERHERO))
        !           828:                     {
        !           829:                         turn_on(player, ISFLEE);
        !           830:                         player.t_ischasing = FALSE;
        !           831:                         player.t_chasee    = tp;
        !           832:                         msg("The sight of the %s terrifies you.", mname);
        !           833:                     }
        !           834:                     else
        !           835:                         msg("My, the %s looks ugly.", mname);
        !           836:                 }
        !           837:             }
        !           838:         }
        !           839:
        !           840:         if (on(*tp, LOOKSLOW))     /* Slow */
        !           841:         {
        !           842:             turn_off(*tp, LOOKSLOW);
        !           843:
        !           844:             if (on(player, CANREFLECT))
        !           845:             {
        !           846:                 msg("You reflect the mournful glare of the %s.", mname);
        !           847:
        !           848:                 if (save_throw(VS_MAGIC,tp))
        !           849:                 {
        !           850:                     msg("The %s is slowing down!", mname);
        !           851:                     turn_on(*tp, ISSLOW);
        !           852:                 }
        !           853:             }
        !           854:             else if (is_wearing(R_FREEDOM) || save(VS_MAGIC))
        !           855:                 msg("You feel run-down for a moment.");
        !           856:             else
        !           857:             {
        !           858:                 if (on(player, ISHASTE))    /* Already sped up */
        !           859:                 {
        !           860:                     extinguish_fuse(FUSE_NOHASTE);
        !           861:                     nohaste(NULL);
        !           862:                 }
        !           863:                 else
        !           864:                 {
        !           865:                     msg("You feel yourself moving %sslower.",
        !           866:                      on(player, ISSLOW) ? "even " : "");
        !           867:
        !           868:                     if (on(player, ISSLOW))
        !           869:                         lengthen_fuse(FUSE_NOSLOW, rnd(4) + 4);
        !           870:                     else
        !           871:                     {
        !           872:                         turn_on(player, ISSLOW);
        !           873:                         player.t_turn = TRUE;
        !           874:                         light_fuse(FUSE_NOSLOW, 0, rnd(4) + 4, AFTER);
        !           875:                     }
        !           876:                 }
        !           877:             }
        !           878:         }
        !           879:
        !           880:         if (on(*tp, CANBLIND))  /* Blinding */
        !           881:         {
        !           882:             turn_off(*tp, CANBLIND);
        !           883:
        !           884:             if (on(player, CANREFLECT))
        !           885:             {
        !           886:                 msg("You reflect the blinding stare of the %s.", mname);
        !           887:
        !           888:                 if (save_throw(VS_WAND, tp))
        !           889:                 {
        !           890:                     msg("The %s is blinded!", mname);
        !           891:                     turn_on(*tp, ISHUH);
        !           892:                 }
        !           893:             }
        !           894:             else if (off(player, ISBLIND))
        !           895:                 if (save(VS_WAND) || is_wearing(R_TRUESEE) || is_wearing(R_SEEINVIS))
        !           896:                     msg("Your eyes film over for a moment.");
        !           897:                 else
        !           898:                 {
        !           899:                     msg("The gaze of the %s blinds you.", mname);
        !           900:                     turn_on(player, ISBLIND);
        !           901:                     light_fuse(FUSE_SIGHT, 0, rnd(30) + 20, AFTER);
        !           902:                     look(FALSE);
        !           903:                 }
        !           904:         }
        !           905:
        !           906:         if (on(*tp, LOOKSTONE))  /* Stoning */
        !           907:         {
        !           908:             turn_off(*tp, LOOKSTONE);
        !           909:
        !           910:             if (on(player, CANREFLECT))
        !           911:             {
        !           912:                 msg("You reflect the flinty look of the %s.", mname);
        !           913:
        !           914:                 if (save_throw(VS_PETRIFICATION,tp))
        !           915:                 {
        !           916:                     msg("The %s suddenly stiffens", mname);
        !           917:                     tp->t_no_move += STONETIME;
        !           918:                 }
        !           919:                 else
        !           920:                 {
        !           921:                     msg("The %s is turned to stone!", mname);
        !           922:                     killed(&player, it, NOMESSAGE, POINTS);
        !           923:                 }
        !           924:             }
        !           925:             else
        !           926:             {
        !           927:                 if (on(player, CANINWALL))
        !           928:                     msg("The %s cannot focus on you.", mname);
        !           929:                 else
        !           930:                 {
        !           931:                     msg("The gaze of the %s stiffens your limbs.", mname);
        !           932:
        !           933:                     if (save(VS_PETRIFICATION))
        !           934:                         no_command = STONETIME;
        !           935:                     else if (rnd(100))
        !           936:                         no_command = STONETIME * 3;
        !           937:                     else
        !           938:                     {
        !           939:                         msg("The gaze of the %s petrifies you.", mname);
        !           940:                         msg("You are turned to stone!!! --More--");
        !           941:                         wait_for(' ');
        !           942:                         death(D_PETRIFY);
        !           943:                         return(it);
        !           944:                     }
        !           945:                 }
        !           946:             }
        !           947:         }
        !           948:     }
        !           949:
        !           950:     /*
        !           951:      * True Sight sees all Never see ISINWALL or CANSURPRISE See ISSHADOW
        !           952:      * 80% See ISINVIS with See Invisibilty
        !           953:      */
        !           954:
        !           955:     if (off(player, CANTRUESEE) &&
        !           956:         on(*tp, ISINWALL) || on(*tp, CANSURPRISE) ||
        !           957:         (on(*tp, ISSHADOW) && rnd(100) < 80) ||
        !           958:         (on(*tp, ISINVIS) && off(player, CANSEE)))
        !           959:        {
        !           960:            /*
        !           961:            TODO: incomplete - need to finish logic
        !           962:            int ch = mvwinch(stdscr, y, x);
        !           963:            */
        !           964:        }
        !           965:
        !           966:
        !           967:     /* hero might be able to hear or smell monster if he can't see it */
        !           968:
        !           969:     if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
        !           970:             on(player, CANHEAR)) && !cansee(tp->t_pos.y, tp->t_pos.x))
        !           971:         msg("You hear a %s nearby.", mname);
        !           972:     else if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
        !           973:             on(player, CANSCENT)) && !cansee(tp->t_pos.y, tp->t_pos.x))
        !           974:         msg("You smell a %s nearby.", mname);
        !           975:
        !           976:     return(it);
        !           977: }
        !           978:
        !           979: /*
        !           980:     genocide()
        !           981:         wipe out hated monsters flags:    ISBLESSED, ISCURSED
        !           982: */
        !           983:
        !           984: void
        !           985: genocide(int flags)
        !           986: {
        !           987:     struct linked_list  *ip;
        !           988:     struct thing    *mp;
        !           989:     struct linked_list  *nip;
        !           990:     int    which_monst;
        !           991:     int    blessed = flags & ISBLESSED;
        !           992:     int    cursed = flags & ISCURSED;
        !           993:
        !           994:     while ((which_monst = get_monster_number("genocide")) == 0)
        !           995:         ;
        !           996:
        !           997:     if (cursed)    /* oops... */
        !           998:     {
        !           999:         new_level(THRONE, which_monst);
        !          1000:         msg("What's this I hear about you trying to wipe me out?");
        !          1001:         fighting = running = after = FALSE;
        !          1002:         return;
        !          1003:     }
        !          1004:
        !          1005:     /* Remove this monster from the present level */
        !          1006:
        !          1007:     for (ip = mlist; ip; ip = nip)
        !          1008:     {
        !          1009:         mp = THINGPTR(ip);
        !          1010:         nip = next(ip);
        !          1011:
        !          1012:         if (mp->t_index == which_monst)
        !          1013:         {
        !          1014:             check_residue(mp);  /* Check for special features before removing */
        !          1015:             remove_monster(&mp->t_pos, ip);
        !          1016:         }
        !          1017:     }
        !          1018:
        !          1019:     /* Remove from available monsters */
        !          1020:
        !          1021:     monsters[which_monst].m_normal = FALSE;
        !          1022:     monsters[which_monst].m_wander = FALSE;
        !          1023:     mpos = 0;
        !          1024:     msg("You have wiped out the %s.", monsters[which_monst].m_name);
        !          1025:
        !          1026:     if (blessed)
        !          1027:         genocide(ISNORMAL);
        !          1028: }
        !          1029:
        !          1030:
        !          1031: /*
        !          1032:     id_monst()
        !          1033:         lists the monsters with the displayed by the character unless
        !          1034:         there is only one in which case it is returned as the string
        !          1035: */
        !          1036:
        !          1037: void
        !          1038: id_monst(int monster)
        !          1039: {
        !          1040:     int i;
        !          1041:
        !          1042:     for (i = 1; i <= nummonst + 2; i++)
        !          1043:         if (monsters[i].m_appear == monster)
        !          1044:             add_line("A %s ", monsters[i].m_name);
        !          1045:
        !          1046:     end_line();
        !          1047: }
        !          1048:
        !          1049:
        !          1050: /*
        !          1051:     check_residue()
        !          1052:         takes care of any effect of the monster
        !          1053: */
        !          1054:
        !          1055: void
        !          1056: check_residue(struct thing *tp)
        !          1057: {
        !          1058:     /* Take care of special abilities */
        !          1059:
        !          1060:     if (on(*tp, DIDHOLD) && (--hold_count == 0))
        !          1061:         turn_off(player, ISHELD);
        !          1062:
        !          1063:     /* If it has lowered player, give him back a level, maybe */
        !          1064:
        !          1065:     if (on(*tp, DIDDRAIN) && rnd(3) == 0)
        !          1066:         raise_level();
        !          1067:
        !          1068:     /* If frightened of this monster, stop */
        !          1069:
        !          1070:     if (on(player, ISFLEE) && (player.t_chasee==tp))
        !          1071:         turn_off(player, ISFLEE);
        !          1072:
        !          1073:     /* If monster was suffocating player, stop it */
        !          1074:     if (on(*tp, DIDSUFFOCATE))
        !          1075:         extinguish_fuse(FUSE_SUFFOCATE);
        !          1076:
        !          1077:     /* If something with fire, may darken */
        !          1078:     if (on(*tp, HASFIRE))
        !          1079:     {
        !          1080:         struct room *rp = roomin(tp->t_pos);
        !          1081:
        !          1082:         if (rp && (--(rp->r_fires) <= 0))
        !          1083:         {
        !          1084:             rp->r_flags &= ~HASFIRE;
        !          1085:             light(&tp->t_pos);
        !          1086:         }
        !          1087:     }
        !          1088: }
        !          1089:
        !          1090: /*
        !          1091:     sell()
        !          1092:         displays a menu of goods from which the player may choose to
        !          1093:         purchase something.
        !          1094: */
        !          1095:
        !          1096: #define SELL_ITEMS 10       /* How many things 'q' might carry */
        !          1097:
        !          1098: void
        !          1099: sell(struct thing *tp)
        !          1100: {
        !          1101:     struct linked_list  *item;
        !          1102:     int i, j, min_worth, nitems, chance, which_item, w;
        !          1103:     char goods;
        !          1104:     struct object   *obj;
        !          1105:     char    buffer[2 * LINELEN];
        !          1106:     char    dbuf[2 * LINELEN];
        !          1107:
        !          1108:     struct
        !          1109:     {
        !          1110:         int which;
        !          1111:         int plus1, plus2;
        !          1112:         int count;
        !          1113:         int worth;
        !          1114:         int flags;
        !          1115:         char    *name;
        !          1116:     }
        !          1117:     selection[SELL_ITEMS];
        !          1118:
        !          1119:     int effective_purse = ((player.t_ctype == C_PALADIN) ?
        !          1120:                    (9 * purse / 10) : purse);
        !          1121:
        !          1122:     min_worth = -1;     /* hope item is never worth less than this */
        !          1123:     item = find_mons(tp->t_pos.y, tp->t_pos.x); /* Get pointer to monster */
        !          1124:
        !          1125:     /* Select the items */
        !          1126:
        !          1127:     nitems = rnd(6) + 5;
        !          1128:
        !          1129:     switch (rnd(6))
        !          1130:     {
        !          1131:         /* Armor */
        !          1132:         case 0:
        !          1133:         case 1:
        !          1134:             goods = ARMOR;
        !          1135:             for (i = 0; i < nitems; i++)
        !          1136:             {
        !          1137:                 chance = rnd(100);
        !          1138:
        !          1139:                 for (j = 0; j < maxarmors; j++)
        !          1140:                     if (chance < armors[j].a_prob)
        !          1141:                         break;
        !          1142:
        !          1143:                 if (j == maxarmors)
        !          1144:                 {
        !          1145:                     debug("Picked a bad armor %d", chance);
        !          1146:                     j = 0;
        !          1147:                 }
        !          1148:
        !          1149:                 selection[i].which = j;
        !          1150:                 selection[i].count = 1;
        !          1151:
        !          1152:                 if (rnd(100) < 40)
        !          1153:                     selection[i].plus1 = rnd(5) + 1;
        !          1154:                 else
        !          1155:                     selection[i].plus1 = 0;
        !          1156:
        !          1157:                 selection[i].name = armors[j].a_name;
        !          1158:
        !          1159:                 switch (luck)
        !          1160:                 {
        !          1161:                     case 0: break;
        !          1162:                     case 1:
        !          1163:                         if (rnd(3) == 0)
        !          1164:                         {
        !          1165:                             selection[i].flags |=  ISCURSED;
        !          1166:                             selection[i].plus1 =  -1 - rnd(5);
        !          1167:                         }
        !          1168:                         break;
        !          1169:
        !          1170:                     default:
        !          1171:                         if (rnd(luck))
        !          1172:                         {
        !          1173:                             selection[i].flags |= ISCURSED;
        !          1174:                             selection[i].plus1 =  -1 - rnd(5);
        !          1175:                         }
        !          1176:                         break;
        !          1177:                 }
        !          1178:
        !          1179:                 /* Calculate price */
        !          1180:
        !          1181:                 w = armors[j].a_worth;
        !          1182:                 w *= (1 + luck + (10 * selection[i].plus1));
        !          1183:                 w = (w / 2) + (roll(6, w) / 6);
        !          1184:                 selection[i].worth = max(w, 25);
        !          1185:
        !          1186:                 if (min_worth > selection[i].worth || i == 1)
        !          1187:                     min_worth = selection[i].worth;
        !          1188:             }
        !          1189:             break;
        !          1190:
        !          1191:             /* Weapon */
        !          1192:         case 2:
        !          1193:         case 3:
        !          1194:             goods = WEAPON;
        !          1195:             for (i = 0; i < nitems; i++)
        !          1196:             {
        !          1197:                 selection[i].which = rnd(maxweapons);
        !          1198:                 selection[i].count = 1;
        !          1199:
        !          1200:                 if (rnd(100) < 35)
        !          1201:                 {
        !          1202:                     selection[i].plus1 = rnd(3);
        !          1203:                     selection[i].plus2 = rnd(3);
        !          1204:                 }
        !          1205:                 else
        !          1206:                 {
        !          1207:                     selection[i].plus1 = 0;
        !          1208:                     selection[i].plus2 = 0;
        !          1209:                 }
        !          1210:
        !          1211:                 if (weaps[selection[i].which].w_flags & ISMANY)
        !          1212:                     selection[i].count = rnd(15) + 8;
        !          1213:
        !          1214:                 selection[i].name = weaps[selection[i].which].w_name;
        !          1215:
        !          1216:                 switch (luck)
        !          1217:                 {
        !          1218:                     case 0: break;
        !          1219:                     case 1:
        !          1220:                         if (rnd(3) == 0)
        !          1221:                         {
        !          1222:                             selection[i].flags |= ISCURSED;
        !          1223:                             selection[i].plus1 =  -rnd(3);
        !          1224:                             selection[i].plus2 =  -rnd(3);
        !          1225:                         }
        !          1226:                         break;
        !          1227:
        !          1228:                     default:
        !          1229:                         if (rnd(luck))
        !          1230:                         {
        !          1231:                             selection[i].flags |= ISCURSED;
        !          1232:                             selection[i].plus1 =  -rnd(3);
        !          1233:                             selection[i].plus2 =  -rnd(3);
        !          1234:                         }
        !          1235:                         break;
        !          1236:                 }
        !          1237:
        !          1238:                 w = weaps[selection[i].which].w_worth * selection[i].count;
        !          1239:                 w *= (1 + luck + (10 * selection[i].plus1 +
        !          1240:                           10 * selection[i].plus2));
        !          1241:                 w = (w / 2) + (roll(6, w) / 6);
        !          1242:                 selection[i].worth = max(w, 25);
        !          1243:
        !          1244:                 if (min_worth > selection[i].worth || i == 1)
        !          1245:                     min_worth = selection[i].worth;
        !          1246:             }
        !          1247:             break;
        !          1248:
        !          1249:             /* Staff or wand */
        !          1250:         case 4:
        !          1251:             goods = STICK;
        !          1252:
        !          1253:             for (i = 0; i < nitems; i++)
        !          1254:             {
        !          1255:                 selection[i].which = pick_one(ws_magic, maxsticks);
        !          1256:                 selection[i].plus1 = rnd(11) + 5;
        !          1257:                 selection[i].count = 1;
        !          1258:                 selection[i].name = ws_magic[selection[i].which].mi_name;
        !          1259:
        !          1260:                 switch (luck)
        !          1261:                 {
        !          1262:                     case 0: break;
        !          1263:                     case 1:
        !          1264:                         if (rnd(3) == 0)
        !          1265:                         {
        !          1266:                             selection[i].flags |= ISCURSED;
        !          1267:                             selection[i].plus1 = 1;
        !          1268:                         }
        !          1269:                         break;
        !          1270:
        !          1271:                     default:
        !          1272:                         if (rnd(luck))
        !          1273:                         {
        !          1274:                             selection[i].flags |= ISCURSED;
        !          1275:                             selection[i].plus1 = 1;
        !          1276:                         }
        !          1277:                 }
        !          1278:
        !          1279:                 w = ws_magic[selection[i].which].mi_worth;
        !          1280:                 w += (luck + 1) * 20 * selection[i].plus1;
        !          1281:                 w = (w / 2) + (roll(6, w) / 6);
        !          1282:                 selection[i].worth = max(w, 25);
        !          1283:
        !          1284:                 if (min_worth > selection[i].worth || i == 1)
        !          1285:                     min_worth = selection[i].worth;
        !          1286:             }
        !          1287:             break;
        !          1288:
        !          1289:             /* Ring */
        !          1290:
        !          1291:         case 5:
        !          1292:             goods = RING;
        !          1293:             for (i = 0; i < nitems; i++)
        !          1294:             {
        !          1295:                 selection[i].which = pick_one(r_magic, maxrings);
        !          1296:                 selection[i].plus1 = rnd(2) + 1;
        !          1297:                 selection[i].count = 1;
        !          1298:
        !          1299:                 if (rnd(100) < r_magic[selection[i].which].mi_bless + 10)
        !          1300:                     selection[i].plus1 += rnd(2) + 1;
        !          1301:
        !          1302:                 selection[i].name = r_magic[selection[i].which].mi_name;
        !          1303:
        !          1304:                 switch (luck)
        !          1305:                 {
        !          1306:                     case 0: break;
        !          1307:                     case 1:
        !          1308:                         if (rnd(3) == 0)
        !          1309:                         {
        !          1310:                             selection[i].flags |= ISCURSED;
        !          1311:                             selection[i].plus1 =  -1 - rnd(2);
        !          1312:                         }
        !          1313:                         break;
        !          1314:
        !          1315:                     default:
        !          1316:                         if (rnd(luck))
        !          1317:                         {
        !          1318:                             selection[i].flags |= ISCURSED;
        !          1319:                             selection[i].plus1 =  -1 - rnd(2);
        !          1320:                         }
        !          1321:                 }
        !          1322:
        !          1323:                 w = r_magic[selection[i].which].mi_worth;
        !          1324:
        !          1325:                 switch(selection[i].which)
        !          1326:                 {
        !          1327:                     case R_DIGEST:
        !          1328:                         if (selection[i].plus1 > 2)
        !          1329:                             selection[i].plus1 = 2;
        !          1330:                         else if (selection[i].plus1 < 1)
        !          1331:                             selection[i].plus1 = 1;
        !          1332:                     /* fall thru here to other cases */
        !          1333:                     case R_ADDSTR:
        !          1334:                     case R_ADDDAM:
        !          1335:                     case R_PROTECT:
        !          1336:                     case R_ADDHIT:
        !          1337:                     case R_ADDINTEL:
        !          1338:                     case R_ADDWISDOM:
        !          1339:                         if (selection[i].plus1 > 0)
        !          1340:                             w += selection[i].plus1 * 50;
        !          1341:                 }
        !          1342:
        !          1343:                 w *= (1 + luck);
        !          1344:                 w = (w / 2) + (roll(6, w) / 6);
        !          1345:                 selection[i].worth = max(w, 25);
        !          1346:
        !          1347:                 if (min_worth > selection[i].worth * selection[i].count)
        !          1348:                     min_worth = selection[i].worth;
        !          1349:             }
        !          1350:     }
        !          1351:
        !          1352:     /* See if player can afford an item */
        !          1353:
        !          1354:     if (min_worth > effective_purse)
        !          1355:     {
        !          1356:         msg("The %s eyes your small purse and departs.",
        !          1357:             monsters[nummonst].m_name);
        !          1358:
        !          1359:         /* Get rid of the monster */
        !          1360:
        !          1361:         killed(NULL, item, NOMESSAGE, NOPOINTS);
        !          1362:
        !          1363:         return;
        !          1364:     }
        !          1365:
        !          1366:     /* Display the goods */
        !          1367:
        !          1368:     msg("The %s shows you his wares.", monsters[nummonst].m_name);
        !          1369:     wstandout(cw);
        !          1370:     mvwaddstr(cw, 0, mpos, morestr);
        !          1371:     wstandend(cw);
        !          1372:     wrefresh(cw);
        !          1373:     wait_for(' ');
        !          1374:     msg("");
        !          1375:     clearok(cw, TRUE);
        !          1376:     touchwin(cw);
        !          1377:
        !          1378:     wclear(hw);
        !          1379:     touchwin(hw);
        !          1380:
        !          1381:     for (i = 0; i < nitems; i++)
        !          1382:     {
        !          1383:         if (selection[i].worth > effective_purse)
        !          1384:             continue;
        !          1385:
        !          1386:         wmove(hw, i + 2, 0);
        !          1387:         sprintf(dbuf, "[%c] ", ('a' + i));
        !          1388:
        !          1389:         switch(goods)
        !          1390:         {
        !          1391:             case ARMOR:
        !          1392:                 strcat(dbuf, "Some ");
        !          1393:                 break;
        !          1394:             case WEAPON:
        !          1395:                 if (selection[i].count == 1)
        !          1396:                     strcat(dbuf, "A ");
        !          1397:                 else
        !          1398:                 {
        !          1399:                     sprintf(buffer, "%2d ", selection[i].count);
        !          1400:                     strcat(dbuf, buffer);
        !          1401:                 }
        !          1402:                 break;
        !          1403:
        !          1404:             case STICK:
        !          1405:                 strcat(dbuf, "A ");
        !          1406:                 strcat(dbuf, ws_type[selection[i].which]);
        !          1407:                 strcat(dbuf, " of ");
        !          1408:                 break;
        !          1409:
        !          1410:             case RING:
        !          1411:                 strcat(dbuf, "A ring of ");
        !          1412:                 break;
        !          1413:         }
        !          1414:
        !          1415:         strcat(dbuf, selection[i].name);
        !          1416:
        !          1417:         if (selection[i].count > 1)
        !          1418:             strcat(dbuf, "s");
        !          1419:
        !          1420:         sprintf(buffer, "%-50.80s Price:  %d", dbuf, selection[i].worth);
        !          1421:         waddstr(hw, buffer);
        !          1422:     }
        !          1423:
        !          1424:     sprintf(buffer, "Purse:  %ld", purse);
        !          1425:     mvwaddstr(hw, nitems + 3, 0, buffer);
        !          1426:     mvwaddstr(hw, 0, 0, "How about one of the following goods? ");
        !          1427:     wrefresh(hw);
        !          1428:
        !          1429:     /* Get rid of the monster */
        !          1430:
        !          1431:     killed(NULL, item, NOMESSAGE, NOPOINTS);
        !          1432:
        !          1433:     which_item = (short) ((readchar() & 0177) - 'a');
        !          1434:
        !          1435:     while (which_item < 0 || which_item >= nitems ||
        !          1436:         selection[which_item].worth > effective_purse)
        !          1437:     {
        !          1438:         if (which_item == (short) ESCAPE - (short) 'a')
        !          1439:             return;
        !          1440:
        !          1441:         mvwaddstr(hw, 0, 0, "Please enter one of the listed items: ");
        !          1442:         wrefresh(hw);
        !          1443:         which_item = (short) ((readchar() & 0177) - 'a');
        !          1444:     }
        !          1445:
        !          1446:     if (purse > selection[which_item].worth)
        !          1447:          purse -= selection[which_item].worth;
        !          1448:     else
        !          1449:          purse = 0L;
        !          1450:
        !          1451:     item = spec_item(goods, selection[which_item].which,
        !          1452:           selection[which_item].plus1, selection[which_item].plus2);
        !          1453:
        !          1454:     obj = OBJPTR(item);
        !          1455:
        !          1456:     if (selection[which_item].count > 1)
        !          1457:     {
        !          1458:         obj->o_count = selection[which_item].count;
        !          1459:         obj->o_group = ++group;
        !          1460:     }
        !          1461:
        !          1462:     /* If a stick or ring, let player know the type */
        !          1463:
        !          1464:     switch (goods)
        !          1465:     {
        !          1466:         case STICK: know_items[TYP_STICK][selection[which_item].which] = TRUE;
        !          1467:                     break;
        !          1468:         case RING:  know_items[TYP_RING][selection[which_item].which] = TRUE;
        !          1469:                     break;
        !          1470:     }
        !          1471:
        !          1472:     if (add_pack(item, MESSAGE) == FALSE)
        !          1473:     {
        !          1474:         obj->o_pos = hero;
        !          1475:         fall(&player, item, TRUE, FALSE);
        !          1476:     }
        !          1477: }
        !          1478:
        !          1479: void
        !          1480: carried_weapon(struct thing *owner, struct object *weapon)
        !          1481: {
        !          1482:     weapon->o_hplus = (rnd(4) < 3) ? 0 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
        !          1483:     weapon->o_dplus = (rnd(4) < 3) ? 0 : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
        !          1484:     weapon->o_hplus += rnd(owner->t_stats.s_lvl / 3 + 1);
        !          1485:     weapon->o_hplus += rnd(owner->t_stats.s_lvl / 3 + 1);
        !          1486:     weapon->o_damage = weapon->o_hurldmg = "0d0";
        !          1487:     weapon->o_ac = 11;
        !          1488:     weapon->o_count = 1;
        !          1489:     weapon->o_group = 0;
        !          1490:
        !          1491:     if ((weapon->o_hplus <= 0) && (weapon->o_dplus <= 0))
        !          1492:         weapon->o_flags = ISCURSED;
        !          1493:
        !          1494:     weapon->o_flags = 0;
        !          1495:     weapon->o_type = WEAPON;
        !          1496:     weapon->o_mark[0] = '\0';
        !          1497: }

CVSweb