/*
* Macros for encapsulation of level.monsters references.
*/
+ #if 0
#define MON_AT(x, y) \
- (level.monsters[x][y] != (struct monst *) 0 \
- && !(level.monsters[x][y])->mburied)
+ (g.level.monsters[x][y] != (struct monst *) 0 \
+ && !(g.level.monsters[x][y])->mburied)
#define MON_BURIED_AT(x, y) \
- (level.monsters[x][y] != (struct monst *) 0 \
- && (level.monsters[x][y])->mburied)
+ (g.level.monsters[x][y] != (struct monst *) 0 \
+ && (g.level.monsters[x][y])->mburied)
+ #else /* without 'mburied' */
-#define MON_AT(x, y) (level.monsters[x][y] != (struct monst *) 0)
++#define MON_AT(x, y) (g.level.monsters[x][y] != (struct monst *) 0)
+ #endif
#ifdef EXTRA_SANITY_CHECKS
#define place_worm_seg(m, x, y) \
do { \
return;
}
- ls = (light_source *) alloc(sizeof(light_source));
+ ls = (light_source *) alloc(sizeof *ls);
- ls->next = light_base;
+ ls->next = g.light_base;
ls->x = x;
ls->y = y;
ls->range = range;
}
}
- for (ls = light_base; ls; ls = ls->next) {
+ /* lit 'obj' has been thrown or kicked and is passing through x,y on the
+ way to its destination; show its light so that hero has a chance to
+ remember terrain, objects, and monsters being revealed */
+ void
+ show_transient_light(obj, x, y)
+ struct obj *obj;
+ int x, y;
+ {
+ light_source *ls;
+ struct monst *mon;
+ int radius_squared;
+
+ /* caller has verified obj->lamplit and that hero is not Blind;
+ validate light source and obtain its radius (for monster sightings) */
- place_object(obj, bhitpos.x, bhitpos.y); /* temporarily put on map */
++ for (ls = g.light_base; ls; ls = ls->next) {
+ if (ls->type != LS_OBJECT)
+ continue;
+ if (ls->id.a_obj == obj)
+ break;
+ }
+ if (!ls || obj->where != OBJ_FREE) {
+ impossible("transient light %s %s is not %s?",
+ obj->lamplit ? "lit" : "unlit", xname(obj),
+ !ls ? "a light source" : "free");
+ } else {
+ /* "expensive" but rare */
++ place_object(obj, g.bhitpos.x, g.bhitpos.y); /* temporarily put on map */
+ vision_recalc(0);
+ flush_screen(0);
+ delay_output();
+ remove_object(obj); /* take back off of map */
+
+ radius_squared = ls->range * ls->range;
+ for (mon = fmon; mon; mon = mon->nmon) {
+ if (DEADMONSTER(mon))
+ continue;
+ /* light range is the radius of a circle and we're limiting
+ canseemon() to a square exclosing that circle, but setting
+ mtemplit 'erroneously' for a seen monster is not a problem;
+ it just flags monsters for another canseemon() check when
+ 'obj' has reached its destination after missile traversal */
+ if (dist2(mon->mx, mon->my, x, y) <= radius_squared
+ && canseemon(mon))
+ mon->mtemplit = 1;
+ /* [what about worm tails?] */
+ }
+ }
+ }
+
+ /* draw "remembered, unseen monster" glyph at locations where a monster
+ was flagged for being visible during transient light movement but can't
+ be seen now */
+ void
+ transient_light_cleanup()
+ {
+ struct monst *mon;
+ int mtempcount = 0;
+
+ for (mon = fmon; mon; mon = mon->nmon) {
+ if (DEADMONSTER(mon))
+ continue;
+ if (mon->mtemplit) {
+ mon->mtemplit = 0;
+ ++mtempcount;
+ if (!canseemon(mon))
+ map_invisible(mon->mx, mon->my);
+ }
+ }
+ if (mtempcount) {
+ vision_recalc(0);
+ flush_screen(0);
+ }
+ }
+
/* (mon->mx == 0) implies migrating */
#define mon_is_local(mon) ((mon)->mx > 0)
if (is_pick(obj) && inside_shop(x, y)
&& (mtmp = shkcatch(obj, x, y)) != 0) {
tmp_at(DISP_END, 0);
- return mtmp;
+ result = mtmp;
+ goto bhit_done;
}
- typ = levl[bhitpos.x][bhitpos.y].typ;
+ typ = levl[g.bhitpos.x][g.bhitpos.y].typ;
- /* iron bars will block anything big enough */
- if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
- && typ == IRONBARS
- && hits_bars(pobj, x - ddx, y - ddy, g.bhitpos.x, g.bhitpos.y,
- point_blank ? 0 : !rn2(5), 1)) {
- /* caveat: obj might now be null... */
- obj = *pobj;
- g.bhitpos.x -= ddx;
- g.bhitpos.y -= ddy;
- break;
+ /* iron bars will block anything big enough and break some things */
+ if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) {
+ if (typ == IRONBARS
- && hits_bars(pobj, x - ddx, y - ddy, bhitpos.x, bhitpos.y,
++ && hits_bars(pobj, x - ddx, y - ddy, g.bhitpos.x, g.bhitpos.y,
+ point_blank ? 0 : !rn2(5), 1)) {
+ /* caveat: obj might now be null... */
+ obj = *pobj;
- bhitpos.x -= ddx;
- bhitpos.y -= ddy;
++ g.bhitpos.x -= ddx;
++ g.bhitpos.y -= ddy;
+ break;
+ } else if (obj->lamplit && !Blind) {
- show_transient_light(obj, bhitpos.x, bhitpos.y);
++ show_transient_light(obj, g.bhitpos.x, g.bhitpos.y);
+ }
}
if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
if (!tethered_weapon)
tmp_at(DISP_END, 0);
- if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
- map_invisible(bhitpos.x, bhitpos.y);
+ if (cansee(g.bhitpos.x, g.bhitpos.y) && !canspotmon(mtmp))
+ map_invisible(g.bhitpos.x, g.bhitpos.y);
- return mtmp;
+ result = mtmp;
+ goto bhit_done;
} else {
/* ZAPPED_WAND */
(*fhitm)(mtmp, obj);
} else {
if (weapon == KICKED_WEAPON
&& ((obj->oclass == COIN_CLASS
- && OBJ_AT(bhitpos.x, bhitpos.y))
- || ship_object(obj, bhitpos.x, bhitpos.y,
- costly_spot(bhitpos.x, bhitpos.y)))) {
+ && OBJ_AT(g.bhitpos.x, g.bhitpos.y))
+ || ship_object(obj, g.bhitpos.x, g.bhitpos.y,
+ costly_spot(g.bhitpos.x, g.bhitpos.y)))) {
tmp_at(DISP_END, 0);
- return (struct monst *) 0;
+ goto bhit_done; /* result == (struct monst *) 0 */
}
}
if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {