|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.