Annotation of researchv10no/games/rogue/chase.c, revision 1.1.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.