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

Annotation of early-roguelike/rogue4/chase.c, Revision 1.1

1.1     ! rubenllo    1: /*
        !             2:  * Code for one creature to chase another
        !             3:  *
        !             4:  * @(#)chase.c 4.25 (Berkeley) 5/5/82
        !             5:  *
        !             6:  * Rogue: Exploring the Dungeons of Doom
        !             7:  * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * See the file LICENSE.TXT for full copyright and licensing information.
        !            11:  */
        !            12:
        !            13: #include <stdlib.h>
        !            14: #include <curses.h>
        !            15: #include "rogue.h"
        !            16:
        !            17: #define DRAGONSHOT  5  /* one chance in DRAGONSHOT that a dragon will flame */
        !            18:
        !            19: coord ch_ret;                          /* Where chasing takes you */
        !            20:
        !            21: bool chase(THING *tp, coord *ee);
        !            22: int do_chase(THING *th);
        !            23: coord *find_dest(THING *tp);
        !            24:
        !            25: /*
        !            26:  * runners:
        !            27:  *     Make all the running monsters move.
        !            28:  */
        !            29: void
        !            30: runners(void)
        !            31: {
        !            32:     register THING *tp;
        !            33:        register THING *ntp;
        !            34:
        !            35:     for (tp = mlist; tp != NULL; tp = ntp)
        !            36:     {
        !            37:        ntp = next(tp);
        !            38:        if (!on(*tp, ISHELD) && on(*tp, ISRUN))
        !            39:        {
        !            40:            if (!on(*tp, ISSLOW) || tp->t_turn)
        !            41:                if (do_chase(tp) == -1)
        !            42:                        continue;
        !            43:            if (on(*tp, ISHASTE))
        !            44:                if (do_chase(tp) == -1)
        !            45:                        continue;
        !            46:            tp->t_turn ^= TRUE;
        !            47:        }
        !            48:     }
        !            49: }
        !            50:
        !            51: /*
        !            52:  * do_chase:
        !            53:  *     Make one thing chase another.
        !            54:  */
        !            55: int
        !            56: do_chase(THING *th)
        !            57: {
        !            58:     register struct room *rer, *ree;   /* room of chaser, room of chasee */
        !            59:     register int mindist = 32767, i, dist;
        !            60:     register bool stoprun = FALSE;     /* TRUE means we are there */
        !            61:     register char sch;
        !            62:     register bool door;
        !            63:     register THING *obj;
        !            64:     register struct room *oroom;
        !            65:     coord this;                                /* Temporary destination for chaser */
        !            66:
        !            67:     rer = th->t_room;          /* Find room of chaser */
        !            68:     if (on(*th, ISGREED) && rer->r_goldval == 0)
        !            69:        th->t_dest = &hero;     /* If gold has been taken, run after hero */
        !            70:     if (th->t_dest == &hero)   /* Find room of chasee */
        !            71:        ree = proom;
        !            72:     else
        !            73:        ree = roomin(th->t_dest);
        !            74:     /*
        !            75:      * We don't count doors as inside rooms for this routine
        !            76:      */
        !            77:     door = (chat(th->t_pos.y, th->t_pos.x) == DOOR);
        !            78:     /*
        !            79:      * If the object of our desire is in a different room,
        !            80:      * and we are not in a corridor, run to the door nearest to
        !            81:      * our goal.
        !            82:      */
        !            83: over:
        !            84:     if (rer != ree)
        !            85:     {
        !            86:        for (i = 0; i < rer->r_nexits; i++)     /* loop through doors */
        !            87:        {
        !            88:            dist = DISTANCE(th->t_dest->y, th->t_dest->x,
        !            89:                            rer->r_exit[i].y, rer->r_exit[i].x);
        !            90:            if (dist < mindist)
        !            91:            {
        !            92:                this = rer->r_exit[i];
        !            93:                mindist = dist;
        !            94:            }
        !            95:        }
        !            96:        if (door)
        !            97:        {
        !            98:            rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM];
        !            99:            door = FALSE;
        !           100:            goto over;
        !           101:        }
        !           102:     }
        !           103:     else
        !           104:     {
        !           105:        this = *th->t_dest;
        !           106:        /*
        !           107:         * For dragons check and see if (a) the hero is on a straight
        !           108:         * line from it, and (b) that it is within shooting distance,
        !           109:         * but outside of striking range.
        !           110:         */
        !           111:        if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x
        !           112:            || abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x))
        !           113:            && DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x) <= BOLT_LENGTH * BOLT_LENGTH
        !           114:            && !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0)
        !           115:        {
        !           116:            delta.y = sign(hero.y - th->t_pos.y);
        !           117:            delta.x = sign(hero.x - th->t_pos.x);
        !           118:            fire_bolt(&th->t_pos, &delta, "flame");
        !           119:            running = FALSE;
        !           120:            count = quiet = 0;
        !           121:            return 0;
        !           122:        }
        !           123:     }
        !           124:     /*
        !           125:      * This now contains what we want to run to this time
        !           126:      * so we run to it.  If we hit it we either want to fight it
        !           127:      * or stop running
        !           128:      */
        !           129:     if (!chase(th, &this))
        !           130:     {
        !           131:        if (ce(this, hero))
        !           132:        {
        !           133:            return ( attack(th) );
        !           134:        }
        !           135:        else if (ce(this, *th->t_dest))
        !           136:        {
        !           137:            for (obj = lvl_obj; obj != NULL; obj = next(obj))
        !           138:                if (th->t_dest == &obj->o_pos)
        !           139:                {
        !           140:                    detach(lvl_obj, obj);
        !           141:                    attach(th->t_pack, obj);
        !           142:                    chat(obj->o_pos.y, obj->o_pos.x) =
        !           143:                        (th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR;
        !           144:                    th->t_dest = find_dest(th);
        !           145:                    break;
        !           146:                }
        !           147:            if (th->t_type != 'F')
        !           148:                stoprun = TRUE;
        !           149:        }
        !           150:     }
        !           151:     else if (th->t_type == 'F')
        !           152:        return(0);
        !           153:     mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch);
        !           154:     if (!ce(ch_ret, th->t_pos))
        !           155:     {
        !           156:        sch = mvinch(ch_ret.y, ch_ret.x);
        !           157:        if (sch == FLOOR && (th->t_room->r_flags & ISDARK)
        !           158:            && DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x)
        !           159:            && !on(player, ISBLIND))
        !           160:                th->t_oldch = ' ';
        !           161:        else
        !           162:            th->t_oldch = sch;
        !           163:        oroom = th->t_room;
        !           164:        th->t_room = roomin(&ch_ret);
        !           165:        if (oroom != th->t_room)
        !           166:            th->t_dest = find_dest(th);
        !           167:
        !           168:        moat(th->t_pos.y, th->t_pos.x) = NULL;
        !           169:        moat(ch_ret.y, ch_ret.x) = th;
        !           170:        th->t_pos = ch_ret;
        !           171:     }
        !           172:     if (see_monst(th))
        !           173:        mvaddch(ch_ret.y, ch_ret.x, th->t_disguise);
        !           174:     else if (on(player, SEEMONST))
        !           175:     {
        !           176:        standout();
        !           177:        mvaddch(ch_ret.y, ch_ret.x, th->t_type);
        !           178:        standend();
        !           179:     }
        !           180:     /*
        !           181:      * And stop running if need be
        !           182:      */
        !           183:     if (stoprun && ce(th->t_pos, *(th->t_dest)))
        !           184:        th->t_flags &= ~ISRUN;
        !           185:
        !           186:     return(0);
        !           187: }
        !           188:
        !           189: /*
        !           190:  * see_monst:
        !           191:  *     Return TRUE if the hero can see the monster
        !           192:  */
        !           193: bool
        !           194: see_monst(THING *mp)
        !           195: {
        !           196:     if (on(player, ISBLIND))
        !           197:        return FALSE;
        !           198:     if (on(*mp, ISINVIS) && !on(player, CANSEE))
        !           199:        return FALSE;
        !           200:     if (DISTANCE(mp->t_pos.y, mp->t_pos.x, hero.y, hero.x) < LAMPDIST)
        !           201:        return TRUE;
        !           202:     if (mp->t_room != proom)
        !           203:        return FALSE;
        !           204:     return (!(mp->t_room->r_flags & ISDARK));
        !           205: }
        !           206:
        !           207: /*
        !           208:  * runto:
        !           209:  *     Set a mosnter running after something or stop it from running
        !           210:  *     (for when it dies)
        !           211:  */
        !           212: void
        !           213: runto(coord *runner, coord *spot)
        !           214: {
        !           215:     register THING *tp;
        !           216:
        !           217:     /*
        !           218:      * If we couldn't find him, something is funny
        !           219:      */
        !           220: #ifdef WIZARD
        !           221:     if ((tp = moat(runner->y, runner->x)) == NULL)
        !           222:        msg("couldn't find monster in runto at (%d,%d)", runner->y, runner->x);
        !           223: #else
        !           224:     tp = moat(runner->y, runner->x);
        !           225: #endif
        !           226:     /*
        !           227:      * Start the beastie running
        !           228:      */
        !           229:     if (tp == NULL)
        !           230:         return;
        !           231:     tp->t_flags |= ISRUN;
        !           232:     tp->t_flags &= ~ISHELD;
        !           233:     tp->t_dest = find_dest(tp);
        !           234: }
        !           235:
        !           236: /*
        !           237:  * chase:
        !           238:  *     Find the spot for the chaser(er) to move closer to the
        !           239:  *     chasee(ee).  Returns TRUE if we want to keep on chasing later
        !           240:  *     FALSE if we reach the goal.
        !           241:  */
        !           242: bool
        !           243: chase(THING *tp, coord *ee)
        !           244: {
        !           245:     register int x, y;
        !           246:     register int dist, thisdist;
        !           247:     register THING *obj;
        !           248:     register coord *er = &tp->t_pos;
        !           249:     register char ch;
        !           250:     register int plcnt = 1;
        !           251:
        !           252:     /*
        !           253:      * If the thing is confused, let it move randomly. Invisible
        !           254:      * Stalkers are slightly confused all of the time, and bats are
        !           255:      * quite confused all the time
        !           256:      */
        !           257:     if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'I' && rnd(5) == 0)
        !           258:        || (tp->t_type == 'B' && rnd(2) == 0))
        !           259:     {
        !           260:        /*
        !           261:         * get a valid random move
        !           262:         */
        !           263:        ch_ret = *rndmove(tp);
        !           264:        dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
        !           265:        /*
        !           266:         * Small chance that it will become un-confused
        !           267:         */
        !           268:        if (rnd(20) == 0)
        !           269:            tp->t_flags &= ~ISHUH;
        !           270:     }
        !           271:     /*
        !           272:      * Otherwise, find the empty spot next to the chaser that is
        !           273:      * closest to the chasee.
        !           274:      */
        !           275:     else
        !           276:     {
        !           277:        register int ey, ex;
        !           278:        /*
        !           279:         * This will eventually hold where we move to get closer
        !           280:         * If we can't find an empty spot, we stay where we are.
        !           281:         */
        !           282:        dist = DISTANCE(er->y, er->x, ee->y, ee->x);
        !           283:        ch_ret = *er;
        !           284:
        !           285:        ey = er->y + 1;
        !           286:        ex = er->x + 1;
        !           287:        for (x = er->x - 1; x <= ex; x++)
        !           288:            for (y = er->y - 1; y <= ey; y++)
        !           289:            {
        !           290:                coord tryp;
        !           291:
        !           292:                tryp.x = x;
        !           293:                tryp.y = y;
        !           294:                if (!diag_ok(er, &tryp))
        !           295:                    continue;
        !           296:                ch = winat(y, x);
        !           297:                if (step_ok(ch))
        !           298:                {
        !           299:                    /*
        !           300:                     * If it is a scroll, it might be a scare monster scroll
        !           301:                     * so we need to look it up to see what type it is.
        !           302:                     */
        !           303:                    if (ch == SCROLL)
        !           304:                    {
        !           305:                        for (obj = lvl_obj; obj != NULL; obj = next(obj))
        !           306:                        {
        !           307:                            if (y == obj->o_pos.y && x == obj->o_pos.x)
        !           308:                                break;
        !           309:                        }
        !           310:                        if (obj != NULL && obj->o_which == S_SCARE)
        !           311:                            continue;
        !           312:                    }
        !           313:                    /*
        !           314:                     * It can also be a Mimic, which we shouldn't step on
        !           315:                     */
        !           316:                    if ((obj = moat(y, x)) != NULL && obj->t_type == 'M')
        !           317:                        continue;
        !           318:                    /*
        !           319:                     * If we didn't find any scrolls at this place or it
        !           320:                     * wasn't a scare scroll, then this place counts
        !           321:                     */
        !           322:                    thisdist = DISTANCE(y, x, ee->y, ee->x);
        !           323:                    if (thisdist < dist)
        !           324:                    {
        !           325:                        plcnt = 1;
        !           326:                        ch_ret = tryp;
        !           327:                        dist = thisdist;
        !           328:                    }
        !           329:                    else if (thisdist == dist && rnd(++plcnt) == 0)
        !           330:                    {
        !           331:                        ch_ret = tryp;
        !           332:                        dist = thisdist;
        !           333:                    }
        !           334:                }
        !           335:            }
        !           336:     }
        !           337:     return (dist != 0 && !ce(ch_ret, hero));
        !           338: }
        !           339:
        !           340: /*
        !           341:  * roomin:
        !           342:  *     Find what room some coordinates are in. NULL means they aren't
        !           343:  *     in any room.
        !           344:  */
        !           345: struct room *
        !           346: roomin(coord *cp)
        !           347: {
        !           348:     register struct room *rp;
        !           349:     register char *fp;
        !           350:
        !           351:     for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
        !           352:        if (cp->x < rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x
        !           353:         && cp->y < rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y)
        !           354:            return rp;
        !           355:     fp = &flat(cp->y, cp->x);
        !           356:     if (*fp & F_PASS)
        !           357:        return &passages[*fp & F_PNUM];
        !           358:     msg("in some bizarre place (%d, %d)", unc(*cp));
        !           359:     return NULL;
        !           360: }
        !           361:
        !           362: /*
        !           363:  * diag_ok:
        !           364:  *     Check to see if the move is legal if it is diagonal
        !           365:  */
        !           366: bool
        !           367: diag_ok(coord *sp, coord *ep)
        !           368: {
        !           369:     if (ep->x == sp->x || ep->y == sp->y)
        !           370:        return TRUE;
        !           371:     return (step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x)));
        !           372: }
        !           373:
        !           374: /*
        !           375:  * cansee:
        !           376:  *     Returns true if the hero can see a certain coordinate.
        !           377:  */
        !           378: bool
        !           379: cansee(int y, int x)
        !           380: {
        !           381:     register struct room *rer;
        !           382:     coord tp;
        !           383:
        !           384:     if (on(player, ISBLIND))
        !           385:        return FALSE;
        !           386:     if (DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
        !           387:        return TRUE;
        !           388:     /*
        !           389:      * We can only see if the hero in the same room as
        !           390:      * the coordinate and the room is lit or if it is close.
        !           391:      */
        !           392:     tp.y = y;
        !           393:     tp.x = x;
        !           394:     return ((rer = roomin(&tp)) == proom && !(rer->r_flags & ISDARK));
        !           395: }
        !           396:
        !           397: /*
        !           398:  * find_dest:
        !           399:  *     find the proper destination for the monster
        !           400:  */
        !           401: coord *
        !           402: find_dest(THING *tp)
        !           403: {
        !           404:     register THING *obj;
        !           405:     register int prob;
        !           406:     register struct room *rp;
        !           407:
        !           408:     if ((prob = monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == proom
        !           409:        || see_monst(tp))
        !           410:            return &hero;
        !           411:     rp = tp->t_room;
        !           412:     for (obj = lvl_obj; obj != NULL; obj = next(obj))
        !           413:     {
        !           414:        if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
        !           415:            continue;
        !           416:        if (roomin(&obj->o_pos) == rp && rnd(100) < prob)
        !           417:        {
        !           418:            for (tp = mlist; tp != NULL; tp = next(tp))
        !           419:                if (tp->t_dest == &obj->o_pos)
        !           420:                    break;
        !           421:            if (tp == NULL)
        !           422:                return &obj->o_pos;
        !           423:        }
        !           424:     }
        !           425:     return &hero;
        !           426: }

CVSweb