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

Annotation of early-roguelike/xrogue/monsters.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:     monsters.c - File with various monster functions in it
                      3:
                      4:     XRogue: Expeditions into the Dungeons of Doom
                      5:     Copyright (C) 1991 Robert Pietkivitch
                      6:     All rights reserved.
                      7:
                      8:     Based on "Advanced Rogue"
                      9:     Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
                     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 <curses.h>
                     20: #include <ctype.h>
                     21: #include <string.h>
                     22: #include <stdlib.h>
                     23: #include "rogue.h"
                     24:
                     25: /*
                     26:  * Check_residue takes care of any effect of the monster
                     27:  */
                     28:
                     29: void
                     30: check_residue(struct thing *tp)
                     31: {
                     32:     /*
                     33:      * Take care of special abilities
                     34:      */
                     35:     if (on(*tp, DIDHOLD) && (--hold_count == 0)) {
                     36:         turn_off(player, ISHELD);
                     37:         turn_off(*tp, DIDHOLD);
                     38:     }
                     39:
                     40:     /* If frightened of this monster, stop */
                     41:     if (on(player, ISFLEE) &&
                     42:         player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
                     43:
                     44:     /* If monster was suffocating player, stop it */
                     45:     if (on(*tp, DIDSUFFOCATE)) {
                     46:         extinguish(suffocate);
                     47:         turn_off(*tp, DIDSUFFOCATE);
                     48:     }
                     49:
                     50:     /* If something with fire, may darken */
                     51:     if (on(*tp, HASFIRE)) {
                     52:         register struct room *rp=roomin(&tp->t_pos);
                     53:         register struct linked_list *fire_item;
                     54:
                     55:         if (rp) {
                     56:             for (fire_item = rp->r_fires; fire_item != NULL;
                     57:                  fire_item = next(fire_item)) {
                     58:                 if (THINGPTR(fire_item) == tp) {
                     59:                     detach(rp->r_fires, fire_item);
                     60:                     destroy_item(fire_item);
                     61:                     if (rp->r_fires == NULL) {
                     62:                         rp->r_flags &= ~HASFIRE;
                     63:                         if (cansee(tp->t_pos.y, tp->t_pos.x)) light(&hero);
                     64:                     }
                     65:                     break;
                     66:                 }
                     67:             }
                     68:         }
                     69:     }
                     70: }
                     71:
                     72: /*
                     73:  * Creat_mons creates the specified monster -- any if 0
                     74:  * person: where to create next to
                     75:  */
                     76:
                     77: bool
                     78: creat_mons(struct thing *person, short monster, bool report)
                     79: {
                     80:     struct linked_list *nitem;
                     81:     register struct thing *tp;
                     82:     struct room *rp;
                     83:     coord *mp;
                     84:
                     85:     if (levtype == POSTLEV)
                     86:         return(FALSE);
                     87:     if ((mp = fallpos(&(person->t_pos), FALSE, 2)) != NULL) {
                     88:         nitem = new_item(sizeof (struct thing));
                     89:         new_monster(nitem,
                     90:                     monster == 0 ? randmonster(FALSE, FALSE)
                     91:                                  : monster,
                     92:                     mp,
                     93:                     TRUE);
                     94:         tp = THINGPTR(nitem);
                     95:         runto(tp, &hero);
                     96:         carry_obj(tp, monsters[tp->t_index].m_carry/2); /* only half chance */
                     97:
                     98:         /* since it just got here, it is disoriented */
                     99:         tp->t_no_move = 2 * movement(tp);
                    100:
                    101:         if (on(*tp, HASFIRE)) {
                    102:             rp = roomin(&tp->t_pos);
                    103:             if (rp) {
                    104:                 register struct linked_list *fire_item;
                    105:
                    106:                 /* Put the new fellow in the room list */
                    107:                 fire_item = creat_item();
                    108:                 ldata(fire_item) = (char *) tp;
                    109:                 attach(rp->r_fires, fire_item);
                    110:
                    111:                 rp->r_flags |= HASFIRE;
                    112:             }
                    113:         }
                    114:
                    115:         /*
                    116:          * If we can see this monster, set oldch to ' ' to make light()
                    117:          * think the creature used to be invisible (ie. not seen here)
                    118:          */
                    119:         if (cansee(tp->t_pos.y, tp->t_pos.x)) tp->t_oldch = ' ';
                    120:         return(TRUE);
                    121:     }
                    122:     if (report) msg("You hear a faint cry of anguish in the distance.. ");
                    123:     return(FALSE);
                    124: }
                    125:
                    126: /*
                    127:  * Genmonsters:
                    128:  *      Generate at least 'least' monsters for this single room level.
                    129:  *      'Treas' indicates whether this is a "treasure" level.
                    130:  */
                    131:
                    132: void
                    133: genmonsters(int least, bool treas)
                    134: {
                    135:     reg int i;
                    136:     reg struct room *rp = &rooms[0];
                    137:     reg struct linked_list *item;
                    138:     reg struct thing *mp;
                    139:     coord tp;
                    140:
                    141:     for (i = 0; i < (max(50, level) + least); i++) {
                    142:             if (!treas && rnd(100) < 65)        /* put in some little buggers */
                    143:                 continue;
                    144:
                    145:             /*
                    146:              * Put the monster in
                    147:              */
                    148:             item = new_item(sizeof *mp);
                    149:             mp = THINGPTR(item);
                    150:             do {
                    151:                     rnd_pos(rp, &tp);
                    152:             } until(mvwinch(stdscr, tp.y, tp.x) == FLOOR);
                    153:
                    154:             new_monster(item, randmonster(FALSE, FALSE), &tp, FALSE);
                    155:             /*
                    156:              * See if we want to give it a treasure to carry around.
                    157:              */
                    158:             carry_obj(mp, monsters[mp->t_index].m_carry);
                    159:
                    160:             /* Calculate a movement rate */
                    161:             mp->t_no_move = movement(mp);
                    162:
                    163:             /* Is it going to give us some light? */
                    164:             if (on(*mp, HASFIRE)) {
                    165:                 register struct linked_list *fire_item;
                    166:
                    167:                 fire_item = creat_item();
                    168:                 ldata(fire_item) = (char *) mp;
                    169:                 attach(rp->r_fires, fire_item);
                    170:                 rp->r_flags |= HASFIRE;
                    171:             }
                    172:     }
                    173: }
                    174:
                    175: /*
                    176:  * id_monst returns the index of the monster given its letter
                    177:  */
                    178:
                    179: short
                    180: id_monst(char monster)
                    181: {
                    182:     register short result;
                    183:
                    184:     if (levtype == OUTSIDE) {
                    185:         result = NLEVMONS*vlevel + (NUMMONST-NUMDINOS-1);
                    186:         if (result > NUMMONST) result = NUMMONST;
                    187:     }
                    188:     else {
                    189:         result = NLEVMONS*vlevel;
                    190:         if (result > NUMMONST-NUMDINOS) result = NUMMONST-NUMDINOS;
                    191:     }
                    192:
                    193:     if (levtype == OUTSIDE) {
                    194:         for(; result>(NUMMONST-NUMDINOS-1); result--)
                    195:             if (monsters[result].m_appear == monster) return(result);
                    196:         for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST-NUMDINOS; result++)
                    197:             if (monsters[result].m_appear == monster) return(result);
                    198:     }
                    199:     else {
                    200:         for(; result>0; result--)
                    201:             if (monsters[result].m_appear == monster) return(result);
                    202:         for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST; result++)
                    203:             if (monsters[result].m_appear == monster) return(result);
                    204:     }
                    205:     return(0);
                    206: }
                    207:
                    208:
                    209: /*
                    210:  * new_monster:
                    211:  *      Pick a new monster and add it to the list
                    212:  */
                    213:
                    214: void
                    215: new_monster(struct linked_list *item, short type, coord *cp, bool max_monster)
                    216: {
                    217:     register struct thing *tp;
                    218:     register struct monster *mp;
                    219:     register char *ip, *hitp;
                    220:     register int i, min_intel, max_intel;
                    221:     register int num_dice, num_sides=8, num_extra=0;
                    222:
                    223:     attach(mlist, item);
                    224:     tp = THINGPTR(item);
                    225:     tp->t_pack = NULL;
                    226:     tp->t_index = type;
                    227:     tp->t_wasshot = FALSE;
                    228:     tp->t_type = monsters[type].m_appear;
                    229:     tp->t_ctype = C_MONSTER;
                    230:     tp->t_action = A_NIL;
                    231:     tp->t_doorgoal.x = tp->t_doorgoal.y = -1;
                    232:     tp->t_quiet = 0;
                    233:     tp->t_dest = NULL;
                    234:     tp->t_name = NULL;
                    235:     tp->t_pos = tp->t_oldpos = *cp;
                    236:     tp->t_oldch = mvwinch(cw, cp->y, cp->x);
                    237:     mvwaddch(mw, cp->y, cp->x, tp->t_type);
                    238:     mp = &monsters[tp->t_index];
                    239:
                    240:     /* Figure out monster's hit points */
                    241:     hitp = mp->m_stats.ms_hpt;
                    242:     num_dice = atoi(hitp);
                    243:     if ((hitp = strchr(hitp, 'd')) != NULL) {
                    244:         num_sides = atoi(++hitp);
                    245:         if ((hitp = strchr(hitp, '+')) != NULL)
                    246:             num_extra = atoi(++hitp);
                    247:     }
                    248:
                    249:     tp->t_stats.s_lvladj = 0;
                    250:     tp->t_stats.s_lvl = mp->m_stats.ms_lvl;
                    251:     tp->t_stats.s_arm = mp->m_stats.ms_arm;
                    252:     strcpy(tp->t_stats.s_dmg,mp->m_stats.ms_dmg);
                    253:     tp->t_stats.s_str = mp->m_stats.ms_str;
                    254:     tp->t_stats.s_dext = mp->m_stats.ms_dex;
                    255:     tp->t_movement = mp->m_stats.ms_move;
                    256:     if (vlevel > HARDER) { /* the deeper, the meaner we get */
                    257:          tp->t_stats.s_lvl += (vlevel - HARDER);
                    258:          num_dice += (vlevel - HARDER)/2;
                    259:          tp->t_stats.s_arm -= (vlevel - HARDER) / 4;
                    260:     }
                    261:     if (max_monster)
                    262:         tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
                    263:     else
                    264:         tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
                    265:     tp->t_stats.s_exp = mp->m_stats.ms_exp + mp->m_add_exp*tp->t_stats.s_hpt;
                    266:
                    267:     /*
                    268:      * just initailize others values to something reasonable for now
                    269:      * maybe someday will *really* put these in monster table
                    270:      */
                    271:     tp->t_stats.s_wisdom = 8 + rnd(7);
                    272:     tp->t_stats.s_const = 8 + rnd(7);
                    273:     tp->t_stats.s_charisma = 8 + rnd(7);
                    274:
                    275:     /* Set the initial flags */
                    276:     for (i=0; i<16; i++) tp->t_flags[i] = 0;
                    277:     for (i=0; i<MAXFLAGS; i++)
                    278:         turn_on(*tp, mp->m_flags[i]);
                    279:
                    280:     /*
                    281:      * these are the base chances that a creatures will do something
                    282:      * assuming it can. These are(or can be) modified at runtime
                    283:      * based on what the creature experiences
                    284:      */
                    285:     tp->t_breathe = 70;         /* base chance of breathing */
                    286:     tp->t_artifact = 90;        /* base chance of using artifact */
                    287:     tp->t_summon = 50;          /* base chance of summoning */
                    288:     tp->t_cast = 70;            /* base chance of casting a spell */
                    289:     tp->t_wand = on(*tp, ISUNIQUE) ? 35 : 50;   /* base chance of using wands */
                    290:
                    291:     /* suprising monsters don't always surprise you */
                    292:     if (!max_monster            && on(*tp, CANSURPRISE) &&
                    293:         off(*tp, ISUNIQUE)      && rnd(100) < 25)
                    294:             turn_off(*tp, CANSURPRISE);
                    295:
                    296:     /* If this monster is unique, gen it */
                    297:     if (on(*tp, ISUNIQUE)) mp->m_normal = FALSE;
                    298:
                    299:     /*
                    300:      * If it is the quartermaster, then compute his level and exp pts
                    301:      * based on the level. This will make it fair when thieves try to
                    302:      * steal and give them reasonable experience if they succeed.
                    303:      * Then fill his pack with his wares.
                    304:      */
                    305:     if (on(*tp, CANSELL)) {
                    306:         tp->t_stats.s_exp = vlevel * 100;
                    307:         tp->t_stats.s_lvl = vlevel/2 + 1;
                    308:         make_sell_pack(tp);
                    309:     }
                    310:
                    311:     /* Normally scared monsters have a chance to not be scared */
                    312:     if (on(*tp, ISFLEE) && (rnd(4) == 0)) turn_off(*tp, ISFLEE);
                    313:
                    314:     /* Figure intelligence */
                    315:     min_intel = atoi(mp->m_intel);
                    316:     if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
                    317:         tp->t_stats.s_intel = min_intel;
                    318:     else {
                    319:         max_intel = atoi(++ip);
                    320:         if (max_monster)
                    321:             tp->t_stats.s_intel = max_intel;
                    322:         else
                    323:             tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
                    324:     }
                    325:     if (vlevel > HARDER)
                    326:          tp->t_stats.s_intel += ((vlevel - HARDER)/2);
                    327:     tp->maxstats = tp->t_stats;
                    328:
                    329:     /* If the monster can shoot, it may have a weapon */
                    330:     if (on(*tp, CANSHOOT) && ((rnd(100) < (20 + vlevel)) || max_monster)) {
                    331:         struct linked_list *item1;
                    332:         register struct object *cur, *cur1;
                    333:
                    334:         item = new_item(sizeof *cur);
                    335:         item1 = new_item(sizeof *cur1);
                    336:         cur = OBJPTR(item);
                    337:         cur1 = OBJPTR(item1);
                    338:         cur->o_hplus = (rnd(4) < 3) ? 0
                    339:                                     : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
                    340:         cur->o_dplus = (rnd(4) < 3) ? 0
                    341:                                     : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
                    342:         cur1->o_hplus = (rnd(4) < 3) ? 0
                    343:                                     : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
                    344:         cur1->o_dplus = (rnd(4) < 3) ? 0
                    345:                                     : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
                    346:         strcpy(cur->o_damage,"0d0");
                    347:         strcpy(cur->o_hurldmg,"0d0");
                    348:         strcpy(cur1->o_damage,"0d0");
                    349:         strcpy(cur1->o_hurldmg,"0d0");
                    350:         cur->o_ac = cur1->o_ac = 11;
                    351:         cur->o_count = cur1->o_count = 1;
                    352:         cur->o_group = cur1->o_group = 0;
                    353:         cur->contents = cur1->contents = NULL;
                    354:         if ((cur->o_hplus <= 0) && (cur->o_dplus <= 0)) cur->o_flags = ISCURSED;
                    355:         if ((cur1->o_hplus <= 0) && (cur1->o_dplus <= 0))
                    356:             cur1->o_flags = ISCURSED;
                    357:         cur->o_flags = cur1->o_flags = 0;
                    358:         cur->o_type = cur1->o_type = WEAPON;
                    359:         cur->o_mark[0] = cur1->o_mark[0] = '\0';
                    360:
                    361:         /* The monster may use a crossbow, sling, or an arrow */
                    362:         i = rnd(100);
                    363:         if (i < 35) {
                    364:             cur->o_which = CROSSBOW;
                    365:             cur1->o_which = BOLT;
                    366:             init_weapon(cur, CROSSBOW);
                    367:             init_weapon(cur1, BOLT);
                    368:         }
                    369:         else if (i < 70) {
                    370:             cur->o_which = BOW;
                    371:             cur1->o_which = ARROW;
                    372:             init_weapon(cur, BOW);
                    373:             init_weapon(cur1, ARROW);
                    374:         }
                    375:         else {
                    376:             cur->o_which = SLING;
                    377:             cur1->o_which = ROCK;
                    378:             init_weapon(cur, SLING);
                    379:             init_weapon(cur1, ROCK);
                    380:         }
                    381:
                    382:         attach(tp->t_pack, item);
                    383:         attach(tp->t_pack, item1);
                    384:     }
                    385:
                    386:
                    387:     /* Calculate the initial movement rate */
                    388:     updpack(TRUE, tp);
                    389:     tp->t_no_move = movement(tp);
                    390:
                    391:     if (ISWEARING(R_AGGR))
                    392:         runto(tp, &hero);
                    393:
                    394:     if (on(*tp, ISDISGUISE))
                    395:     {
                    396:         char mch = 0;
                    397:
                    398:         if (tp->t_pack != NULL)
                    399:             mch = (OBJPTR(tp->t_pack))->o_type;
                    400:         else
                    401:             switch (rnd(10)) {
                    402:                 case 0: mch = GOLD;
                    403:                 when 1: mch = POTION;
                    404:                 when 2: mch = SCROLL;
                    405:                 when 3: mch = FOOD;
                    406:                 when 4: mch = WEAPON;
                    407:                 when 5: mch = ARMOR;
                    408:                 when 6: mch = RING;
                    409:                 when 7: mch = STICK;
                    410:                 when 8: mch = monsters[randmonster(FALSE, FALSE)].m_appear;
                    411:                 when 9: mch = MM;
                    412:             }
                    413:         tp->t_disguise = mch;
                    414:     }
                    415: }
                    416:
                    417: /*
                    418:  * randmonster:
                    419:  *      Pick a monster to show up.  The lower the level,
                    420:  *      the meaner the monster.
                    421:  */
                    422:
                    423: short
                    424: randmonster(bool wander, bool no_unique)
                    425: {
                    426:     register int d, cur_level, range, i;
                    427:
                    428:     /*
                    429:      * Do we want a merchant? Merchant is always in place 'NUMMONST'
                    430:      */
                    431:     if (wander && monsters[NUMMONST].m_wander && rnd(100) < pstats.s_charisma/3)
                    432:         return NUMMONST;
                    433:
                    434:     cur_level = vlevel;
                    435:     range = (4*NLEVMONS)+1;  /* range is 0 thru 12 */
                    436:     i = 0;
                    437:     do
                    438:     {
                    439:         if (i++ > NUMMONST-1) {    /* in case all have be genocided */
                    440:             i = 0;
                    441:             if (--cur_level <= 0)
                    442:                 fatal("rogue: Could not find a monster to make! ");
                    443:         }
                    444:         if (levtype == OUTSIDE) {                 /* create DINOSUARS */
                    445:             d = (cur_level - rnd(range/2)) + (NUMMONST-NUMDINOS-1);
                    446:             if (d < NUMMONST-NUMDINOS)
                    447:                 d = (NUMMONST-NUMDINOS) + rnd(range/2);
                    448:             if (d > NUMMONST-1)
                    449:                 d = (NUMMONST-NUMDINOS) + rnd(NUMDINOS);
                    450:         }
                    451:         else {           /* Create NORMALs and UNIQs here */
                    452:             d = (NLEVMONS*(cur_level-1) + rnd(range) - (range-NLEVMONS-1));
                    453:             if (d < 1) d = rnd(6)+1;
                    454:
                    455:             if (d > NUMMONST-NUMDINOS-1) {    /* Entire range NORMs + UNIQs */
                    456:         if (no_unique)   /* Choose from last 12 NORMAL monsters */
                    457:                     d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/5);
                    458:         else             /* Choose from entire UNIQ monsters + range */
                    459:             d = (NUMMONST-NUMDINOS-1) - rnd(NUMUNIQUE+range);
                    460:             }
                    461:                      /* Half-way into the UNIQs now */
                    462:             else if (d > (NUMMONST-NUMDINOS-(NUMUNIQUE/2)-1)) {
                    463:         if (no_unique)   /* Choose from last 15 NORMAL monsters */
                    464:                     d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/4);
                    465:         else             /* Choose from entire UNIQ monsters + range */
                    466:                     d = (NUMMONST-NUMDINOS-1) - rnd(NUMUNIQUE+range);
                    467:         }
                    468:                      /* End NORMALs and begin relic bearing UNIQs */
                    469:             else if (d > (NUMMONST-NUMDINOS-NUMUNIQUE-1)) {
                    470:         if (no_unique)   /* Choose from last 20 NORMAL monsters */
                    471:                     d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/3);
                    472:         else             /* Choose from first 20 UNIQ monsters */
                    473:                     d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) + rnd(NUMUNIQUE/3);
                    474:         }
                    475:         }
                    476:     }
                    477:     while  (wander ? !monsters[d].m_wander || !monsters[d].m_normal
                    478:                    : !monsters[d].m_normal);
                    479:     return d;
                    480: }
                    481:
                    482: /* Sell displays a menu of goods from which the player may choose
                    483:  * to purchase something.
                    484:  */
                    485:
                    486: void
                    487: sell(struct thing *tp)
                    488: {
                    489:     register struct linked_list *item, *seller;
                    490:     register struct linked_list *sellpack;
                    491:     register struct object *obj;
                    492:     register long worth, min_worth;
                    493:     char buffer[LINELEN];
                    494:
                    495:     /*
                    496:      * Get a linked_list pointer to the seller.  We need this in case
                    497:      * he disappears so we can set him ISDEAD.
                    498:      */
                    499:     seller = find_mons(tp->t_pos.y, tp->t_pos.x);
                    500:
                    501:     sellpack = tp->t_pack;
                    502:     if (sellpack == NULL) {
                    503:         msg("%s looks puzzled and departs.", prname(monster_name(tp), TRUE));
                    504:
                    505:         /* Get rid of the monster */
                    506:         killed(seller, FALSE, FALSE, FALSE);
                    507:         return;
                    508:     }
                    509:
                    510:     /* See how much the minimum pack item is worth */
                    511:     min_worth = 100000;
                    512:     for (item = sellpack; item != NULL; item = next(item)) {
                    513:         obj = OBJPTR(item);
                    514:         obj->o_flags |= ISPOST; /* Force a long description of the item */
                    515:         worth = get_worth(obj);
                    516:         if (worth < min_worth) min_worth = worth;
                    517:     }
                    518:
                    519:     /* See if player can afford an item */
                    520:     if (min_worth > purse) {
                    521:         msg("%s eyes your small purse and departs.",
                    522:             prname(monster_name(tp), TRUE));
                    523:
                    524:         /* Get rid of the monster */
                    525:         killed(seller, FALSE, FALSE, FALSE);
                    526:         return;
                    527:     }
                    528:
                    529:     /* Announce our intentions */
                    530:     msg("%s opens his pack.  --More--", prname(monster_name(tp), TRUE));
                    531:     wait_for(' ');
                    532:
                    533:     /* Try to sell something */
                    534:     sprintf(buffer, "You got %ld gold pieces.  Buy", purse);
                    535:     item = get_item(sellpack, buffer, ALL, TRUE, TRUE);
                    536:
                    537:     /* Get rid of the monster */
                    538:     if (item != NULL) detach(tp->t_pack, item); /* Take it out of the pack */
                    539:     killed(seller, FALSE, FALSE, FALSE);
                    540:
                    541:     if (item == NULL) return;
                    542:
                    543:     /* Can he afford the selected item? */
                    544:     obj = OBJPTR(item);
                    545:
                    546:     worth = get_worth(obj);
                    547:     if (worth > purse) {
                    548:         msg("You cannot afford it.");
                    549:         o_discard(item);
                    550:         return;
                    551:     }
                    552:
                    553:     /* Charge him through the nose */
                    554:     purse -= worth;
                    555:
                    556:     /* If a stick or ring, let player know the type */
                    557:     switch (obj->o_type) {
                    558:         case RING:   r_know[obj->o_which]  = TRUE;
                    559:         when POTION: p_know[obj->o_which]  = TRUE;
                    560:         when SCROLL: s_know[obj->o_which]  = TRUE;
                    561:         when STICK:  ws_know[obj->o_which] = TRUE;
                    562:         when MM:     m_know[obj->o_which]  = TRUE;
                    563:
                    564:     }
                    565:
                    566:     /* identify it */
                    567:     whatis (item);
                    568:
                    569:     /* Remove the POST flag that we used for get_item() */
                    570:     obj->o_flags &= ~ISPOST;
                    571:
                    572:     if (add_pack(item, FALSE) == FALSE) {
                    573:         obj->o_pos = hero;
                    574:         fall(item, TRUE);
                    575:     }
                    576: }
                    577:
                    578: /*
                    579:  * what to do when the hero steps next to a monster
                    580:  */
                    581:
                    582: struct linked_list *
                    583: wake_monster(int y, int x)
                    584: {
                    585:     register struct thing *tp;
                    586:     register struct linked_list *it;
                    587:     register struct room *trp;
                    588:     register char *mname;
                    589:     bool nasty; /* Will the monster "attack"? */
                    590:
                    591:     if ((it = find_mons(y, x)) == NULL) {
                    592:         msg("Wake:  can't find monster in show (%d, %d)", y, x);
                    593:         return (NULL);
                    594:     }
                    595:     tp = THINGPTR(it);
                    596:     if (on(*tp, ISSTONE)) /* if stoned, don't do anything */
                    597:         return it;
                    598:
                    599:     /*
                    600:      * For now, if we are a friendly monster, we won't do any of
                    601:      * our special effects.
                    602:      */
                    603:     if (on(*tp, ISFRIENDLY)) return it;
                    604:
                    605:     trp = roomin(&tp->t_pos); /* Current room for monster */
                    606:
                    607:     /*
                    608:      * Let greedy ones in a room guard gold
                    609:      * (except in a maze where lots of creatures would all go for the
                    610:      * same piece of gold)
                    611:      */
                    612:     if (on(*tp, ISGREED) && off(*tp, ISRUN) && levtype != MAZELEV &&
                    613:     trp != NULL && lvl_obj != NULL) {
                    614:             register struct linked_list *item;
                    615:             register struct object *cur;
                    616:
                    617:             for (item = lvl_obj; item != NULL; item = next(item)) {
                    618:                 cur = OBJPTR(item);
                    619:                 if ((cur->o_type == GOLD) && (roomin(&cur->o_pos) == trp)) {
                    620:                     /* Run to the gold */
                    621:                     runto(tp, &cur->o_pos);
                    622:
                    623:                     /* Make it worth protecting */
                    624:                     cur->o_count += GOLDCALC + GOLDCALC;
                    625:                     break;
                    626:                 }
                    627:             }
                    628:     }
                    629:
                    630:     /*
                    631:      * Every time he sees mean monster, it might start chasing him
                    632:      */
                    633:     if (on(*tp, ISMEAN)  &&
                    634:         off(*tp, ISHELD) &&
                    635:         off(*tp, ISRUN)  &&
                    636:         rnd(100) > 35    &&
                    637:         (!is_stealth(&player) || (on(*tp, ISUNIQUE) && rnd(100) > 35)) &&
                    638:         (off(player, ISINVIS) || on(*tp, CANSEE)) ||
                    639:         (trp != NULL && (trp->r_flags & ISTREAS))) {
                    640:         runto(tp, &hero);
                    641:     }
                    642:
                    643:     /*
                    644:      * Get the name; we don't want to do it until here because we need to
                    645:      * know whether the monster is still sleeping or not.
                    646:      */
                    647:     mname = monster_name(tp);
                    648:
                    649:     /* See if the monster will bother the player */
                    650:     nasty = (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x));
                    651:
                    652:     /*
                    653:      * if the creature is awake and can see the player and the
                    654:      * player has the dreaded "eye of vecna" then see if the
                    655:      * creature is turned to stone
                    656:      */
                    657:     if (cur_relic[EYE_VECNA] && nasty && off(*tp, NOSTONE) &&
                    658:         (off(player, ISINVIS) || on(*tp, CANSEE))) {
                    659:         turn_on(*tp, NOSTONE);  /* only have to save once */
                    660:         if (!save(VS_PETRIFICATION, tp, -2)) {
                    661:                 turn_on(*tp, ISSTONE);
                    662:                 turn_off(*tp, ISRUN);
                    663:                 turn_off(*tp, ISINVIS);
                    664:                 turn_off(*tp, CANSURPRISE);
                    665:                 turn_off(*tp, ISDISGUISE);
                    666:                 msg("%s is turned to stone!", prname(mname, TRUE));
                    667:                 return it;
                    668:         }
                    669:     }
                    670:
                    671:     /*
                    672:      * Handle monsters that can gaze and do things while running
                    673:      * Player must be able to see the monster and the monster must
                    674:      * not be asleep
                    675:      */
                    676:     if (nasty && !invisible(tp)) {
                    677:         /*
                    678:          * Confusion
                    679:          */
                    680:         if (on(*tp, CANHUH)                              &&
                    681:            (off(*tp, ISINVIS)     || on(player, CANSEE)) &&
                    682:            (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
                    683:             if (!save(VS_MAGIC, &player, 0)) {
                    684:                 if (off(player, ISCLEAR)) {
                    685:                     if (find_slot(unconfuse))
                    686:                         lengthen(unconfuse, HUHDURATION);
                    687:                     else {
                    688:                         fuse(unconfuse, NULL, HUHDURATION, AFTER);
                    689:                         msg("%s's gaze has confused you.",prname(mname, TRUE));
                    690:                         turn_on(player, ISHUH);
                    691:                     }
                    692:                 }
                    693:                 else msg("You feel dizzy for a moment, but it quickly passes.");
                    694:             }
                    695:             else if (rnd(100) < 67)
                    696:                 turn_off(*tp, CANHUH); /* Once you save, maybe that's it */
                    697:         }
                    698:
                    699:         /* Sleep */
                    700:         if(on(*tp, CANSNORE) &&
                    701:            player.t_action != A_FREEZE &&
                    702:            !save(VS_PARALYZATION, &player, 0)) {
                    703:             if (ISWEARING(R_ALERT))
                    704:                 msg("You feel drowsy for a moment.. ");
                    705:             else {
                    706:                 msg("%s's gaze puts you to sleep! ", prname(mname, TRUE));
                    707:                 player.t_no_move += movement(&player) * SLEEPTIME;
                    708:                 player.t_action = A_FREEZE;
                    709:                 if (rnd(100) < 50) turn_off(*tp, CANSNORE);
                    710:             }
                    711:         }
                    712:
                    713:         /* Fear */
                    714:         if (on(*tp, CANFRIGHTEN) && !on(player, ISFLEE)) {
                    715:             turn_off(*tp, CANFRIGHTEN);
                    716:             if (!ISWEARING(R_HEROISM) &&
                    717:                 !save(VS_WAND, &player, -(tp->t_stats.s_lvl/10))) {
                    718:                     turn_on(player, ISFLEE);
                    719:                     player.t_dest = &tp->t_pos;
                    720:                     msg("The sight of %s terrifies you!", prname(mname, FALSE));
                    721:             }
                    722:         }
                    723:
                    724:         /* blinding creatures */
                    725:         if(on(*tp, CANBLIND) && !find_slot(sight)) {
                    726:             turn_off(*tp, CANBLIND);
                    727:             if (!save(VS_WAND, &player, 0)) {
                    728:                 msg("The gaze of %s blinds you! ", prname(mname, FALSE));
                    729:                 turn_on(player, ISBLIND);
                    730:                 fuse(sight, NULL, rnd(30)+20, AFTER);
                    731:                 light(&hero);
                    732:             }
                    733:         }
                    734:
                    735:         /* the sight of the ghost can age you! */
                    736:         if (on(*tp, CANAGE)) {
                    737:             turn_off (*tp, CANAGE);
                    738:             if (!save(VS_MAGIC, &player, 0)) {
                    739:                 msg ("The sight of %s ages you!", prname(mname, FALSE));
                    740:                 pstats.s_const--;
                    741:                 /* max_stats.s_const--; */
                    742:                 if (pstats.s_const < 1) {
                    743:             pstats.s_hpt = -1;
                    744:                     death (D_CONSTITUTION);
                    745:         }
                    746:             }
                    747:         }
                    748:
                    749:         /* Turning to stone */
                    750:         if (on(*tp, LOOKSTONE)) {
                    751:             turn_off(*tp, LOOKSTONE);
                    752:
                    753:             if (on(player, CANINWALL))
                    754:                 msg("The gaze of %s has no effect.", prname(mname, FALSE));
                    755:             else {
                    756:                 if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 5) {
                    757:                     pstats.s_hpt = -1;
                    758:                     msg("The gaze of %s petrifies you!", prname(mname, FALSE));
                    759:                     msg("You are turned to stone!!!  --More--");
                    760:                     wait_for(' ');
                    761:                     death(D_PETRIFY);
                    762:                 }
                    763:                 else {
                    764:                     msg("The gaze of %s stiffens your limbs.",
                    765:                         prname(mname, FALSE));
                    766:                     player.t_no_move += movement(&player) * STONETIME;
                    767:                     player.t_action = A_FREEZE;
                    768:                 }
                    769:             }
                    770:         }
                    771:     }
                    772:
                    773:     return it;
                    774: }
                    775: /*
                    776:  * wanderer:
                    777:  *      A wandering monster has awakened and is headed for the player
                    778:  */
                    779:
                    780: void
                    781: wanderer(void)
                    782: {
                    783:     register int i;
                    784:     register struct room *hr = roomin(&hero);
                    785:     register struct linked_list *item;
                    786:     register struct thing *tp;
                    787:     register long *attr;        /* Points to monsters' attributes */
                    788:     int carry;  /* Chance of wanderer carrying anything */
                    789:     short rmonst;       /* Our random wanderer */
                    790:     bool canteleport = FALSE,   /* Can the monster teleport? */
                    791:          seehim;        /* Is monster within sight? */
                    792:     coord cp;
                    793:
                    794:     rmonst = randmonster(TRUE, FALSE);  /* Choose a random wanderer */
                    795:     attr = &monsters[rmonst].m_flags[0]; /* Start of attributes */
                    796:     for (i=0; i<MAXFLAGS; i++)
                    797:         if (*attr++ == CANTELEPORT) {
                    798:             canteleport = TRUE;
                    799:             break;
                    800:         }
                    801:
                    802:     /* Find a place for it -- avoid the player's room if can't teleport */
                    803:     do {
                    804:         do {
                    805:             i = rnd_room();
                    806:         } until (canteleport || hr != &rooms[i] || levtype == MAZELEV ||
                    807:                  levtype == OUTSIDE);
                    808:
                    809:         /* Make sure the monster does not teleport on top of the player */
                    810:         do {
                    811:             rnd_pos(&rooms[i], &cp);
                    812:         } while (hr == &rooms[i] && ce(cp, hero));
                    813:     } until (step_ok(cp.y, cp.x, NOMONST, (struct thing *)NULL));
                    814:
                    815:     /* Create a new wandering monster */
                    816:     item = new_item(sizeof *tp);
                    817:     new_monster(item, rmonst, &cp, FALSE);
                    818:     tp = THINGPTR(item);
                    819:     runto(tp, &hero);
                    820:     tp->t_pos = cp;     /* Assign the position to the monster */
                    821:     seehim = cansee(tp->t_pos.y, tp->t_pos.x);
                    822:     if (on(*tp, HASFIRE)) {
                    823:         register struct room *rp;
                    824:
                    825:         rp = roomin(&tp->t_pos);
                    826:         if (rp) {
                    827:             register struct linked_list *fire_item;
                    828:
                    829:             fire_item = creat_item();
                    830:             ldata(fire_item) = (char *) tp;
                    831:             attach(rp->r_fires, fire_item);
                    832:
                    833:             rp->r_flags |= HASFIRE;
                    834:             if (seehim && next(rp->r_fires) == NULL)
                    835:                 light(&hero);
                    836:         }
                    837:     }
                    838:
                    839:     /* See if we give the monster anything */
                    840:     carry = monsters[tp->t_index].m_carry;
                    841:     if (off(*tp, ISUNIQUE)) carry /= 2; /* Non-unique has only a half chance */
                    842:     carry_obj(tp, carry);
                    843:
                    844:     /* Calculate its movement rate */
                    845:     tp->t_no_move = movement(tp);
                    846:
                    847:     /* Alert the player if a monster just teleported in */
                    848:     if (hr == &rooms[i] && canteleport && seehim && !invisible(tp)) {
                    849:         msg("A %s just teleported in", monster_name(tp));
                    850:         light(&hero);
                    851:         running = FALSE;
                    852:     }
                    853:
                    854:     if (wizard)
                    855:         msg("Started a wandering %s", monster_name(tp));
                    856: }
                    857:

CVSweb