Annotation of researchv10no/games/rogue/chase.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.