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