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