[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

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