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

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

1.1     ! rubenllo    1: /*
        !             2:  * Code for one object to chase another
        !             3:  *
        !             4:  * @(#)chase.c 3.17 (Berkeley) 6/15/81
        !             5:  *
        !             6:  * Rogue: Exploring the Dungeons of Doom
        !             7:  * Copyright (C) 1980, 1981 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 "curses.h"
        !            14: #include "rogue.h"
        !            15:
        !            16: coord ch_ret;                          /* Where chasing takes you */
        !            17:
        !            18: /*
        !            19:  * runners:
        !            20:  *     Make all the running monsters move.
        !            21:  */
        !            22:
        !            23: void
        !            24: runners()
        !            25: {
        !            26:     struct linked_list *item;
        !            27:     struct thing *tp;
        !            28:
        !            29:     for (item = mlist; item != NULL;)
        !            30:     {
        !            31:        tp = (struct thing *) ldata(item);
        !            32:         item = next(item);
        !            33:        if (off(*tp, ISHELD) && on(*tp, ISRUN))
        !            34:        {
        !            35:            if (off(*tp, ISSLOW) || tp->t_turn)
        !            36:                if (do_chase(tp) == -1)
        !            37:                     continue;
        !            38:            if (on(*tp, ISHASTE))
        !            39:                if (do_chase(tp) == -1)
        !            40:                     continue;
        !            41:            tp->t_turn ^= TRUE;
        !            42:        }
        !            43:     }
        !            44: }
        !            45:
        !            46: /*
        !            47:  * do_chase:
        !            48:  *     Make one thing chase another.
        !            49:  */
        !            50:
        !            51: int
        !            52: do_chase(struct thing *th)
        !            53: {
        !            54:     struct room *rer, *ree;    /* room of chaser, room of chasee */
        !            55:     int mindist = 32767, i, dist;
        !            56:     int stoprun = FALSE;       /* TRUE means we are there */
        !            57:     int sch;
        !            58:     coord this;                                /* Temporary destination for chaser */
        !            59:
        !            60:     rer = roomin(&th->t_pos);  /* Find room of chaser */
        !            61:     ree = roomin(th->t_dest);  /* Find room of chasee */
        !            62:     /*
        !            63:      * We don't count doors as inside rooms for this routine
        !            64:      */
        !            65:     if (mvwinch(stdscr, th->t_pos.y, th->t_pos.x) == DOOR)
        !            66:        rer = NULL;
        !            67:     this = *th->t_dest;
        !            68:     /*
        !            69:      * If the object of our desire is in a different room,
        !            70:      * than we are and we ar not in a corridor, run to the
        !            71:      * door nearest to our goal.
        !            72:      */
        !            73:     if (rer != NULL && rer != ree)
        !            74:        for (i = 0; i < rer->r_nexits; i++)     /* loop through doors */
        !            75:        {
        !            76:            dist = DISTANCE(th->t_dest->y, th->t_dest->x,
        !            77:                            rer->r_exit[i].y, rer->r_exit[i].x);
        !            78:            if (dist < mindist)                 /* minimize distance */
        !            79:            {
        !            80:                this = rer->r_exit[i];
        !            81:                mindist = dist;
        !            82:            }
        !            83:        }
        !            84:     /*
        !            85:      * this now contains what we want to run to this time
        !            86:      * so we run to it.  If we hit it we either want to fight it
        !            87:      * or stop running
        !            88:      */
        !            89:     if (!chase(th, &this))
        !            90:     {
        !            91:        if (ce(this, hero))
        !            92:        {
        !            93:            return( attack(th) );
        !            94:        }
        !            95:        else if (th->t_type != 'F')
        !            96:            stoprun = TRUE;
        !            97:     }
        !            98:     else if (th->t_type == 'F')
        !            99:        return(0);
        !           100:     mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
        !           101:     sch = mvwinch(cw, ch_ret.y, ch_ret.x);
        !           102:     if (rer != NULL && (rer->r_flags & ISDARK) && sch == FLOOR
        !           103:        && DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < 3
        !           104:        && off(player, ISBLIND))
        !           105:            th->t_oldch = ' ';
        !           106:     else
        !           107:        th->t_oldch = sch;
        !           108:
        !           109:     if (cansee(unc(ch_ret)) && !on(*th, ISINVIS))
        !           110:         mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);
        !           111:     mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
        !           112:     mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);
        !           113:     th->t_pos = ch_ret;
        !           114:     /*
        !           115:      * And stop running if need be
        !           116:      */
        !           117:     if (stoprun && ce(th->t_pos, *(th->t_dest)))
        !           118:        th->t_flags &= ~ISRUN;
        !           119:
        !           120:     return(0);
        !           121: }
        !           122:
        !           123: /*
        !           124:  * runto:
        !           125:  *     Set a mosnter running after something
        !           126:  *     or stop it from running (for when it dies)
        !           127:  */
        !           128:
        !           129: void
        !           130: runto(coord *runner, coord *spot)
        !           131: {
        !           132:     struct linked_list *item;
        !           133:     struct thing *tp;
        !           134:
        !           135:     /*
        !           136:      * If we couldn't find him, something is funny
        !           137:      */
        !           138:     if ((item = find_mons(runner->y, runner->x)) == NULL)
        !           139:     {
        !           140:        msg("CHASER '%s'", unctrl(winat(runner->y, runner->x)));
        !           141:        return;
        !           142:     }
        !           143:     tp = (struct thing *) ldata(item);
        !           144:     /*
        !           145:      * Start the beastie running
        !           146:      */
        !           147:     tp->t_dest = spot;
        !           148:     tp->t_flags |= ISRUN;
        !           149:     tp->t_flags &= ~ISHELD;
        !           150: }
        !           151:
        !           152: /*
        !           153:  * chase:
        !           154:  *     Find the spot for the chaser(er) to move closer to the
        !           155:  *     chasee(ee).  Returns TRUE if we want to keep on chasing later
        !           156:  *     FALSE if we reach the goal.
        !           157:  */
        !           158:
        !           159: int
        !           160: chase(struct thing *tp, coord *ee)
        !           161: {
        !           162:     int x, y;
        !           163:     int dist, thisdist;
        !           164:     struct linked_list *item;
        !           165:     struct object *obj = NULL;
        !           166:     coord *er = &tp->t_pos;
        !           167:     int ch;
        !           168:
        !           169:     /*
        !           170:      * If the thing is confused, let it move randomly. Invisible
        !           171:      * Stalkers are slightly confused all of the time, and bats are
        !           172:      * quite confused all the time
        !           173:      */
        !           174:     if ((on(*tp, ISHUH) && rnd(10) < 8) || (tp->t_type == 'I' && rnd(100) < 20)
        !           175:        || (tp->t_type == 'B' && rnd(100) < 50))
        !           176:     {
        !           177:        /*
        !           178:         * get a valid random move
        !           179:         */
        !           180:        ch_ret = *rndmove(tp);
        !           181:        dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
        !           182:        /*
        !           183:         * Small chance that it will become un-confused
        !           184:         */
        !           185:        if (rnd(1000) < 50)
        !           186:            tp->t_flags &= ~ISHUH;
        !           187:     }
        !           188:     /*
        !           189:      * Otherwise, find the empty spot next to the chaser that is
        !           190:      * closest to the chasee.
        !           191:      */
        !           192:     else
        !           193:     {
        !           194:        int ey, ex;
        !           195:        /*
        !           196:         * This will eventually hold where we move to get closer
        !           197:         * If we can't find an empty spot, we stay where we are.
        !           198:         */
        !           199:        dist = DISTANCE(er->y, er->x, ee->y, ee->x);
        !           200:        ch_ret = *er;
        !           201:
        !           202:        ey = er->y + 1;
        !           203:        ex = er->x + 1;
        !           204:        for (x = er->x - 1; x <= ex; x++)
        !           205:            for (y = er->y - 1; y <= ey; y++)
        !           206:            {
        !           207:                coord tryp;
        !           208:
        !           209:                tryp.x = x;
        !           210:                tryp.y = y;
        !           211:                if (!diag_ok(er, &tryp))
        !           212:                    continue;
        !           213:                ch = winat(y, x);
        !           214:                if (step_ok(ch))
        !           215:                {
        !           216:                    /*
        !           217:                     * If it is a scroll, it might be a scare monster scroll
        !           218:                     * so we need to look it up to see what type it is.
        !           219:                     */
        !           220:                    if (ch == SCROLL)
        !           221:                    {
        !           222:                        for (item = lvl_obj; item != NULL; item = next(item))
        !           223:                        {
        !           224:                            obj = (struct object *) ldata(item);
        !           225:                            if (y == obj->o_pos.y && x == obj->o_pos.x)
        !           226:                                break;
        !           227:                        }
        !           228:                        if (item != NULL && obj->o_which == S_SCARE)
        !           229:                            continue;
        !           230:                    }
        !           231:                    /*
        !           232:                     * If we didn't find any scrolls at this place or it
        !           233:                     * wasn't a scare scroll, then this place counts
        !           234:                     */
        !           235:                    thisdist = DISTANCE(y, x, ee->y, ee->x);
        !           236:                    if (thisdist < dist)
        !           237:                    {
        !           238:                        ch_ret = tryp;
        !           239:                        dist = thisdist;
        !           240:                    }
        !           241:                }
        !           242:            }
        !           243:     }
        !           244:     return (dist != 0);
        !           245: }
        !           246:
        !           247: /*
        !           248:  * roomin:
        !           249:  *     Find what room some coordinates are in. NULL means they aren't
        !           250:  *     in any room.
        !           251:  */
        !           252:
        !           253: struct room *
        !           254: roomin(coord *cp)
        !           255: {
        !           256:     struct room *rp;
        !           257:
        !           258:     for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)
        !           259:        if (inroom(rp, cp))
        !           260:            return rp;
        !           261:     return NULL;
        !           262: }
        !           263:
        !           264: /*
        !           265:  * find_mons:
        !           266:  *     Find the monster from his corrdinates
        !           267:  */
        !           268:
        !           269: struct linked_list *
        !           270: find_mons(int y, int x)
        !           271: {
        !           272:     struct linked_list *item;
        !           273:     struct thing *th;
        !           274:
        !           275:     for (item = mlist; item != NULL; item = next(item))
        !           276:     {
        !           277:        th = (struct thing *) ldata(item);
        !           278:        if (th->t_pos.y == y && th->t_pos.x == x)
        !           279:            return item;
        !           280:     }
        !           281:     return NULL;
        !           282: }
        !           283:
        !           284: /*
        !           285:  * diag_ok:
        !           286:  *     Check to see if the move is legal if it is diagonal
        !           287:  */
        !           288:
        !           289: int
        !           290: diag_ok(coord *sp, coord *ep)
        !           291: {
        !           292:     if (ep->x == sp->x || ep->y == sp->y)
        !           293:        return TRUE;
        !           294:     return (step_ok(mvinch(ep->y, sp->x)) && step_ok(mvinch(sp->y, ep->x)));
        !           295: }
        !           296:
        !           297: /*
        !           298:  * cansee:
        !           299:  *     returns true if the hero can see a certain coordinate.
        !           300:  */
        !           301:
        !           302: int
        !           303: cansee(int y, int x)
        !           304: {
        !           305:     struct room *rer;
        !           306:     coord tp;
        !           307:
        !           308:     if (on(player, ISBLIND))
        !           309:        return FALSE;
        !           310:     tp.y = y;
        !           311:     tp.x = x;
        !           312:     rer = roomin(&tp);
        !           313:     /*
        !           314:      * We can only see if the hero in the same room as
        !           315:      * the coordinate and the room is lit or if it is close.
        !           316:      */
        !           317:     return (rer != NULL && rer == roomin(&hero) && !(rer->r_flags&ISDARK)) ||
        !           318:            DISTANCE(y, x, hero.y, hero.x) < 3;
        !           319: }

CVSweb