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

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

1.1       rubenllo    1: /*
                      2:  * File with various monster functions in it
                      3:  *
                      4:  * @(#)monsters.c      9.0     (rdk)    7/17/84
                      5:  *
                      6:  * Super-Rogue
                      7:  * Copyright (C) 1984 Robert D. Kindelberger
                      8:  * All rights reserved.
                      9:  *
                     10:  * Based on "Rogue: Exploring the Dungeons of Doom"
                     11:  * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
                     12:  * All rights reserved.
                     13:  *
                     14:  * See the file LICENSE.TXT for full copyright and licensing information.
                     15:  */
                     16:
                     17: #include <string.h>
                     18: #include "rogue.h"
                     19: #include <ctype.h>
                     20: #include "rogue.ext"
                     21:
                     22: /*
                     23:  * rnd_mon:
                     24:  *     Pick a monster to show up.  The lower the level,
                     25:  *     the meaner the monster.
                     26:  */
                     27: char
                     28: rnd_mon(bool wander, bool baddie)
                     29: {
                     30:        /* baddie; TRUE when from a polymorph stick */
                     31:        reg int i, ok, cnt;
                     32:
                     33:        cnt = 0;
                     34:        if (levcount == 0)                      /* if only asmodeus possible */
                     35:                return(MAXMONS);
                     36:        if (baddie) {
                     37:                while (1) {
                     38:                        i = rnd(MAXMONS);                                       /* pick ANY monster */
                     39:                        if (monsters[i].m_lev.l_lev < 0)        /* skip genocided ones */
                     40:                                continue;
                     41:                        return i;
                     42:                }
                     43:        }
                     44:        ok = FALSE;
                     45:        do {
                     46:                /*
                     47:                 * get a random monster from this range
                     48:                 */
                     49:                i = rnd(levcount);
                     50:                /*
                     51:                 * Only create a wandering monster if we want one
                     52:                 * (or the count is exceeded)
                     53:                 */
                     54:                if (!wander || mtlev[i]->m_lev.d_wand || ++cnt > 500)
                     55:                        ok = TRUE;
                     56:        } while(!ok);
                     57:        return (midx(mtlev[i]->m_show));
                     58: }
                     59:
                     60: /*
                     61:  * lev_mon:
                     62:  *     This gets all monsters possible on this level
                     63:  */
                     64: void
                     65: lev_mon(void)
                     66: {
                     67:        reg int i;
                     68:        reg struct monster *mm;
                     69:
                     70:        levcount = 0;
                     71:        for (i = 0; i < MAXMONS; i++) {
                     72:                mm = &monsters[i];
                     73:                if (mm->m_lev.h_lev >= level && mm->m_lev.l_lev <= level) {
                     74:                        mtlev[levcount] = mm;
                     75:                        if (++levcount >= MONRANGE)
                     76:                                break;
                     77:                }
                     78:        }
                     79:        if (levcount == 0)                                      /* if no monsters are possible */
                     80:                mtlev[0] = &monsters[MAXMONS];  /* then asmodeus 'A' */
                     81: }
                     82:
                     83: /*
                     84:  * new_monster:
                     85:  *     Pick a new monster and add it to the list
                     86:  */
                     87: struct linked_list *
                     88: new_monster(char type, struct coord *cp, bool treas)
                     89: {
                     90:        reg struct linked_list *item;
                     91:        reg struct thing *tp;
                     92:        reg struct monster *mp;
                     93:        reg struct stats *st;
                     94:        float killexp;          /* experience gotten for killing him */
                     95:
                     96:        item = new_item(sizeof(struct thing));
                     97:        attach(mlist, item);
                     98:        tp = THINGPTR(item);
                     99:        st = &tp->t_stats;
                    100:        mp = &monsters[type];           /* point to this monsters structure */
                    101:        tp->t_type = mp->m_show;
                    102:        tp->t_indx = type;
                    103:        tp->t_pos = *cp;
                    104:        tp->t_room = roomin(cp);
                    105:        tp->t_oldch = mvwinch(cw, cp->y, cp->x);
                    106:        tp->t_nomove = 0;
                    107:        tp->t_nocmd = 0;
                    108:        mvwaddch(mw, cp->y, cp->x, tp->t_type);
                    109:
                    110:        /*
                    111:         * copy monster data
                    112:         */
                    113:        tp->t_stats = mp->m_stats;
                    114:
                    115:        /*
                    116:         * If below amulet level, make the monsters meaner the
                    117:         * deeper the hero goes.
                    118:         */
                    119:        if (level > AMLEVEL)
                    120:                st->s_lvl += ((level - AMLEVEL) / 4);
                    121:
                    122:        /*
                    123:         * If monster in treasure room, then tougher.
                    124:         */
                    125:        if (treas)
                    126:                st->s_lvl += 1;
                    127:        if (levtype == MAZELEV)
                    128:                st->s_lvl += 1;
                    129:        /*
                    130:         * If the hero is going back up, then the monsters are more
                    131:         * prepared for him, so tougher.
                    132:         */
                    133:        if (goingup())
                    134:                st->s_lvl += 1;
                    135:
                    136:        /*
                    137:         * Get hit points for monster depending on his experience
                    138:         */
                    139:        st->s_hpt = roll(st->s_lvl, 8);
                    140:        st->s_maxhp = st->s_hpt;
                    141:        /*
                    142:         * Adjust experience point we get for killing it by the
                    143:         *  strength of this particular monster by ~~ +- 50%
                    144:         */
                    145:        killexp = mp->m_stats.s_exp * (0.47 + (float)st->s_hpt /
                    146:                (8 * (float)st->s_lvl));
                    147:
                    148:        st->s_exp = killexp;                    /* use float for accuracy */
                    149:        if(st->s_exp < 1)
                    150:                st->s_exp = 1;                          /* minimum 1 experience point */
                    151:        tp->t_flags = mp->m_flags;
                    152:        /*
                    153:         * If monster in treasure room, then MEAN
                    154:         */
                    155:        if (treas || levtype == MAZELEV)
                    156:                tp->t_flags |= ISMEAN;
                    157:        tp->t_turn = TRUE;
                    158:        tp->t_pack = NULL;
                    159:        /*
                    160:         * Dont wander if treas room
                    161:         */
                    162:        if (iswearing(R_AGGR) && !treas)
                    163:                runto(cp, &hero);
                    164:        if (tp->t_type == 'M') {
                    165:                char mch;
                    166:
                    167:                if (tp->t_pack != NULL)
                    168:                        mch = (OBJPTR(tp->t_pack))->o_type;
                    169:                else {
                    170:                        switch (rnd(level >= AMLEVEL ? 9 : 8)) {
                    171:                                case 0: mch = GOLD;
                    172:                                when 1: mch = POTION;
                    173:                                when 2: mch = SCROLL;
                    174:                                when 3: mch = STAIRS;
                    175:                                when 4: mch = WEAPON;
                    176:                                when 5: mch = ARMOR;
                    177:                                when 6: mch = RING;
                    178:                                when 7: mch = STICK;
                    179:                                when 8: mch = AMULET;
                    180:                        }
                    181:                }
                    182:                if (treas)
                    183:                        mch = 'M';              /* no disguise in treasure room */
                    184:                tp->t_disguise = mch;
                    185:        }
                    186:        return item;
                    187: }
                    188:
                    189: /*
                    190:  * wanderer:
                    191:  *     A wandering monster has awakened and is headed for the player
                    192:  */
                    193: void
                    194: wanderer(void)
                    195: {
                    196:        reg int ch = '-';
                    197:        reg struct room *rp, *hr = player.t_room;
                    198:        reg struct linked_list *item;
                    199:        reg struct thing *tp;
                    200:        struct coord mp;
                    201:
                    202:        do {
                    203:                rp = &rooms[rnd_room()];
                    204:                if (rp != hr || levtype == MAZELEV) {
                    205:                        mp = *rnd_pos(rp);
                    206:                        ch = mvinch(mp.y, mp.x);
                    207:                }
                    208:        } while (!step_ok(ch));
                    209:        item = new_monster(rnd_mon(TRUE,FALSE), &mp, FALSE);
                    210:        tp = THINGPTR(item);
                    211:        tp->t_flags |= ISRUN;
                    212:        tp->t_dest = &hero;
                    213: }
                    214:
                    215: /*
                    216:  * wake_monster:
                    217:  *     What to do when the hero steps next to a monster
                    218:  */
                    219: struct linked_list *
                    220: wake_monster(int y, int x)
                    221: {
                    222:        reg struct thing *tp;
                    223:        reg struct linked_list *it;
                    224:        reg struct room *rp;
                    225:        reg char ch;
                    226:        bool treas = FALSE;
                    227:
                    228:        if ((it = find_mons(y, x)) == NULL)
                    229:                return NULL;
                    230:        tp = THINGPTR(it);
                    231:        ch = tp->t_type;
                    232:        /*
                    233:         * Every time he sees mean monster, it might start chasing him
                    234:         */
                    235:        rp = player.t_room;
                    236:        if (rp != NULL && rf_on(rp,ISTREAS)) {
                    237:                tp->t_flags &= ~ISHELD;
                    238:                treas = TRUE;
                    239:        }
                    240:        if (treas || (rnd(100) > 33 && on(*tp,ISMEAN) && off(*tp,ISHELD) &&
                    241:          !iswearing(R_STEALTH))) {
                    242:                tp->t_dest = &hero;
                    243:                tp->t_flags |= ISRUN;
                    244:        }
                    245:        if (ch == 'U' && pl_off(ISBLIND)) {
                    246:                if ((rp != NULL && !rf_on(rp,ISDARK) && levtype != MAZELEV)
                    247:                  || DISTANCE(y, x, hero.y, hero.x) < 3) {
                    248:                        if (off(*tp,ISFOUND) && !save(VS_PETRIFICATION)
                    249:                          && !iswearing(R_SUSAB) && pl_off(ISINVINC)) {
                    250:                                msg("The umber hulk's gaze has confused you.");
                    251:                                if (pl_on(ISHUH))
                    252:                                        lengthen(unconfuse,rnd(20)+HUHDURATION);
                    253:                                else
                    254:                                        fuse(unconfuse,TRUE,rnd(20)+HUHDURATION);
                    255:                                player.t_flags |= ISHUH;
                    256:                        }
                    257:                        tp->t_flags |= ISFOUND;
                    258:                }
                    259:        }
                    260:        /*
                    261:         * Hide invisible monsters
                    262:         */
                    263:        if ((tp->t_flags & ISINVIS) && pl_off(CANSEE))
                    264:                ch = mvinch(y, x);
                    265:        /*
                    266:         * Let greedy ones guard gold
                    267:         */
                    268:        if (on(*tp, ISGREED) && off(*tp, ISRUN)) {
                    269:                if (rp != NULL && rp->r_goldval) {
                    270:                        tp->t_dest = &rp->r_gold;
                    271:                        tp->t_flags |= ISRUN;
                    272:                }
                    273:        }
                    274:        return it;
                    275: }
                    276:
                    277: /*
                    278:  * genocide:
                    279:  *     Eradicate a monster forevermore
                    280:  */
                    281: void
                    282: genocide(void)
                    283: {
                    284:        reg struct linked_list *ip, *nip;
                    285:        reg struct thing *mp;
                    286:        struct monster *mm;
                    287:        reg int i, ii, c;
                    288:
                    289:        if (levcount == 0) {
                    290:                mpos = 0;
                    291:                msg("You cannot genocide Asmodeus !!");
                    292:                return;
                    293:        }
                    294: tryagain:
                    295:        i = TRUE;               /* assume an error now */
                    296:        while (i) {
                    297:                msg("Which monster (remember UPPER & lower case)?");
                    298:                c = readchar();         /* get a char */
                    299:                if (c == ESCAPE) {      /* he can abort (the fool) */
                    300:                        msg("");
                    301:                        return;
                    302:                }
                    303:                if (isalpha(c))         /* valid char here */
                    304:                        i = FALSE;              /* exit the loop */
                    305:                else {                          /* he didn't type a letter */
                    306:                        mpos = 0;
                    307:                        msg("Please specify a letter between 'A' and 'z'");
                    308:                }
                    309:        }
                    310:        i = midx(c);                                            /* get index to monster */
                    311:        mm = &monsters[i];
                    312:        if (mm->m_lev.l_lev < 0) {
                    313:                mpos = 0;
                    314:                msg("You have already eliminated the %s.",mm->m_name);
                    315:                goto tryagain;
                    316:        }
                    317:        for (ip = mlist; ip != NULL; ip = nip) {
                    318:                mp = THINGPTR(ip);
                    319:                nip = next(ip);
                    320:                if (mp->t_type == c)
                    321:                        remove_monster(&mp->t_pos, ip);
                    322:        }
                    323:        mm->m_lev.l_lev = -1;                           /* get rid of it */
                    324:        mm->m_lev.h_lev = -1;
                    325:        lev_mon();                                                      /* redo monster list */
                    326:        mpos = 0;
                    327:        msg("You have wiped out the %s.",mm->m_name);
                    328: }
                    329:
                    330: /*
                    331:  * unhold:
                    332:  *     Release the player from being held
                    333:  */
                    334: void
                    335: unhold(char whichmon)
                    336: {
                    337:        struct linked_list *item;
                    338:        struct thing *mon;
                    339:
                    340:        switch (whichmon) {
                    341:                case 'F':
                    342:                        fung_hit = 0;
                    343:                        for (item = mlist; item != NULL; item = next(item)) {
                    344:                                mon = THINGPTR(item);
                    345:                                if (mon->t_type == 'F')
                    346:                                        strcpy(mon->t_stats.s_dmg, "000d0");
                    347:                        }
                    348:                case 'd':
                    349:                        player.t_flags &= ~ISHELD;
                    350:        }
                    351: }
                    352:
                    353: /*
                    354:  * midx:
                    355:  *     This returns an index to 'whichmon'
                    356:  */
                    357: int
                    358: midx(char whichmon)
                    359: {
                    360:        if (isupper(whichmon))
                    361:                return(whichmon - 'A');                 /* 0 to 25 for uppercase */
                    362:        else if (islower(whichmon))
                    363:                return(whichmon - 'a' + 26);    /* 26 to 51 for lowercase */
                    364:        else
                    365:                return(MAXMONS);                                /* 52 for Asmodeus */
                    366: }
                    367:
                    368: /*
                    369:  * monhurt:
                    370:  *     See when monster should run or fight. Return
                    371:  *     TRUE if hit points less than acceptable.
                    372:  */
                    373: bool
                    374: monhurt(struct thing *th)
                    375: {
                    376:        reg int ewis, crithp, f1, f2;
                    377:        reg struct stats *st;
                    378:
                    379:        st = &th->t_stats;
                    380:        ewis = st->s_ef.a_wis;
                    381:        if (ewis <= MONWIS)                             /* stupid monsters dont know */
                    382:                return FALSE;
                    383:        f1 = st->s_maxhp / 4;                   /* base hpt for being hurt */
                    384:        f2 = (ewis - MONWIS) * 5 / 3;   /* bonus for smart monsters */
                    385:        if (th->t_flags & ISWOUND)              /* if recovering from being */
                    386:                f1 *= 2;                                        /* wounded, then double the base */
                    387:        crithp = f1 + f2;                               /* get critical hpt for hurt */
                    388:        if (crithp > st->s_maxhp)               /* only up to max hpt */
                    389:                crithp = st->s_maxhp;
                    390:        if (st->s_hpt < crithp)                 /* if < critical, then still hurt */
                    391:                return TRUE;
                    392:        return FALSE;
                    393: }

CVSweb