// The main loop of the program. Loop until the game is over, // refreshing things and looking at the proper times. void playit() { oldpos = new coord(); oldpos.CopyFrom(hero); oldrp = roomin(hero); while (playing) command(); /* Command execution */ endit(0); }
// The main loop of the program. Loop until the game is over, // refreshing things and looking at the proper times. void playit() { oldpos = new coord(); oldpos.CopyFrom(hero); oldrp = roomin(hero); while (playing) { command(); /* Command execution */ } endit(0); }
static coord ret = new coord(); /* what we will be returning */ // Move in a random direction if the monster/person is confused coord rndmove(THING who) { THING obj; int x, y; char ch; y = ret.y = who.t_pos.y + rnd(3) - 1; x = ret.x = who.t_pos.x + rnd(3) - 1; /* * Now check to see if that's a legal move. If not, don't move. * (I.e., bump into the wall or whatever) */ if (y == who.t_pos.y && x == who.t_pos.x) { return(ret); } if (!diag_ok(who.t_pos, ret)) { goto bad; } else { ch = winat(y, x); if (!step_ok(ch)) { goto bad; } if (ch == SCROLL) { for (obj = lvl_obj; obj != null; obj = next(obj)) { if (y == obj.o_pos.y && x == obj.o_pos.x) { break; } } if (obj != null && obj.o_which == S_SCARE) { goto bad; } } } return(ret); bad: ret.CopyFrom(who.t_pos); return(ret); }
// Find the spot for the chaser(er) to move closer to the // chasee(ee). Returns TRUE if we want to keep on chasing later // FALSE if we reach the goal. bool chase(THING tp, coord ee) { THING obj; int x, y; int curdist, thisdist; coord er = tp.t_pos; char ch; int plcnt = 1; /* * If the thing is confused, let it move randomly. Invisible * Stalkers are slightly confused all of the time, and bats are * quite confused all the time */ if ((on(tp, ISHUH) && rnd(5) != 0) || (tp.t_type == 'P' && rnd(5) == 0) || (tp.t_type == 'B' && rnd(2) == 0)) { /* * get a valid random move */ ch_ret.CopyFrom(rndmove(tp)); curdist = dist_cp(ch_ret, ee); /* * Small chance that it will become un-confused */ if (rnd(20) == 0) { tp.t_flags &= ~ISHUH; } } /* * Otherwise, find the empty spot next to the chaser that is * closest to the chasee. */ else { int ey, ex; /* * This will eventually hold where we move to get closer * If we can't find an empty spot, we stay where we are. */ curdist = dist_cp(er, ee); ch_ret.CopyFrom(er); ey = er.y + 1; if (ey >= NUMLINES - 1) { ey = NUMLINES - 2; } ex = er.x + 1; if (ex >= NUMCOLS) { ex = NUMCOLS - 1; } for (x = er.x - 1; x <= ex; x++) { if (x < 0) { continue; } tryp.x = x; for (y = er.y - 1; y <= ey; y++) { tryp.y = y; if (!diag_ok(er, tryp)) { continue; } ch = winat(y, x); if (step_ok(ch)) { /* * If it is a scroll, it might be a scare monster scroll * so we need to look it up to see what type it is. */ if (ch == SCROLL) { for (obj = lvl_obj; obj != null; obj = next(obj)) { if (y == obj.o_pos.y && x == obj.o_pos.x) { break; } } if (obj != null && obj.o_which == S_SCARE) { continue; } } /* * It can also be a Xeroc, which we shouldn't step on */ if ((obj = moat(y, x)) != null && obj.t_type == 'X') { continue; } /* * If we didn't find any scrolls at this place or it * wasn't a scare scroll, then this place counts */ thisdist = dist(y, x, ee.y, ee.x); if (thisdist < curdist) { plcnt = 1; ch_ret.CopyFrom(tryp); curdist = thisdist; } else if (thisdist == curdist && rnd(++plcnt) == 0) { ch_ret.CopyFrom(tryp); curdist = thisdist; } } } } } return((bool)(curdist != 0 && !ce(ch_ret, hero))); }
static coord thisCoord = new coord(); /* Temporary destination for chaser */ // Make one thing chase another. int do_chase(THING th) { coord cp; room rer, ree; /* room of chaser, room of chasee */ int mindist = 32767, curdist; bool stoprun = false; /* TRUE means we are there */ bool door; THING obj; rer = th.t_room; /* Find room of chaser */ if (on(th, ISGREED) && rer.r_goldval == 0) { th.t_dest = hero; /* If gold has been taken, run after hero */ } if (th.t_dest == hero) /* Find room of chasee */ { ree = proom; } else { ree = roomin(th.t_dest); } /* * We don't count doors as inside rooms for this routine */ door = (chat(th.t_pos.y, th.t_pos.x) == DOOR); /* * If the object of our desire is in a different room, * and we are not in a corridor, run to the door nearest to * our goal. */ over: if (rer != ree) { for (int i = 0; i < rer.r_nexits; i++) { cp = rer.r_exit[i]; curdist = dist_cp(th.t_dest, cp); if (curdist < mindist) { thisCoord.CopyFrom(cp); mindist = curdist; } } if (door) { rer = passages[flat(th.t_pos.y, th.t_pos.x) & F_PNUM]; door = false; goto over; } } else { thisCoord.CopyFrom(th.t_dest); /* * For dragons check and see if (a) the hero is on a straight * line from it, and (b) that it is within shooting distance, * but outside of striking range. */ if (th.t_type == 'D' && (th.t_pos.y == hero.y || th.t_pos.x == hero.x || Math.Abs(th.t_pos.y - hero.y) == Math.Abs(th.t_pos.x - hero.x)) && dist_cp(th.t_pos, hero) <= BOLT_LENGTH * BOLT_LENGTH && !on(th, ISCANC) && rnd(DRAGONSHOT) == 0) { delta.y = Math.Sign(hero.y - th.t_pos.y); delta.x = Math.Sign(hero.x - th.t_pos.x); if (has_hit) { endmsg(); } fire_bolt(th.t_pos, delta, "flame"); running = false; count = 0; quiet = 0; if (to_death && !on(th, ISTARGET)) { to_death = false; kamikaze = false; } return(0); } } /* * This now contains what we want to run to this time * so we run to it. If we hit it we either want to fight it * or stop running */ if (!chase(th, thisCoord)) { if (ce(thisCoord, hero)) { return(attack(th)); } else if (ce(thisCoord, th.t_dest)) { for (obj = lvl_obj; obj != null; obj = next(obj)) { if (th.t_dest == obj.o_pos) { detach(ref lvl_obj, obj); attach(ref th.t_pack, obj); chat(obj.o_pos.y, obj.o_pos.x, (th.t_room.r_flags & ISGONE) != 0 ? PASSAGE : FLOOR); th.t_dest = find_dest(th); break; } } if (th.t_type != 'F') { stoprun = true; } } } else { if (th.t_type == 'F') { return(0); } } relocate(th, ch_ret); /* * And stop running if need be */ if (stoprun && ce(th.t_pos, th.t_dest)) { th.t_flags &= ~ISRUN; } return(0); }
// Fire a bolt in a given direction from a specific starting place void fire_bolt(coord start, coord dir, string name) { int c1, c2; THING tp; char dirch = (char)0, ch; bool hit_hero, used, changed; coord pos = new coord(); coord[] spotpos = new coord[BOLT_LENGTH]; THING bolt = new THING(); bolt.o_type = WEAPON; bolt.o_which = FLAME; bolt.o_hurldmg = "6x6"; bolt.o_hplus = 100; bolt.o_dplus = 0; bolt.o_launch = -1; weap_info[FLAME].oi_name = name; switch (dir.y + dir.x) { case 0: dirch = '/'; break; case 1: case -1: dirch = (dir.y == 0 ? '-' : '|'); break; case 2: case -2: dirch = '\\'; break; } pos.CopyFrom(start); hit_hero = (bool)(start != hero); used = false; changed = false; for (c1 = 0; c1 <= BOLT_LENGTH - 1 && !used; c1++) { pos.y += dir.y; pos.x += dir.x; spotpos[c1] = new coord(pos.y, pos.x); ch = winat(pos.y, pos.x); switch (ch) { case DOOR: /* * this code is necessary if the hero is on a door * and he fires at the wall the door is in, it would * otherwise loop infinitely */ if (ce(hero, pos)) { goto def; } /* FALLTHROUGH */ goto case '|'; case '|': case '-': case ' ': if (!changed) { hit_hero = !hit_hero; } changed = false; dir.y = -dir.y; dir.x = -dir.x; c1--; msg("the {0} bounces", name); break; default: def: if (!hit_hero && (tp = moat(pos.y, pos.x)) != null) { hit_hero = true; changed = !changed; tp.t_oldch = chat(pos.y, pos.x); if (!save_throw(VS_MAGIC, tp)) { bolt.o_pos = pos; used = true; if (tp.t_type == 'D' && name == "flame") { addmsg("the flame bounces"); if (!terse) { addmsg(" off the dragon"); } endmsg(); } else { hit_monster(pos.y, pos.x, bolt); } } else if (ch != 'M' || tp.t_disguise == 'M') { if (start == hero) { runto(pos); } if (terse) { msg("{0} misses", name); } else { msg("the {0} whizzes past {1}", name, set_mname(tp)); } } } else if (hit_hero && ce(pos, hero)) { hit_hero = false; changed = !changed; if (!save(VS_MAGIC)) { if ((pstats.s_hpt -= roll(6, 6)) <= 0) { if (start == hero) { death('b'); } else { death(moat(start.y, start.x).t_type); } } used = true; if (terse) { msg("the {0} hits", name); } else { msg("you are hit by the {0}", name); } } else { msg("the {0} whizzes by you", name); } } mvaddch(pos.y, pos.x, dirch); refresh(); break; } } for (c2 = 0; c2 < c1; c2++) { mvaddch(spotpos[c2].y, spotpos[c2].x, chat(spotpos[c2].y, spotpos[c2].x)); } }