From: nhmall Date: Sat, 8 Jun 2019 13:38:27 +0000 (-0400) Subject: Merge branch 'NetHack-3.6' X-Git-Tag: NetHack-3.7.0_WIP~384 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d0210d9c90b72d8cba03578da1da4099e221f4bb;p=nethack Merge branch 'NetHack-3.6' --- d0210d9c90b72d8cba03578da1da4099e221f4bb diff --cc include/rm.h index e001d8e0c,1190a355b..e104fc20f --- a/include/rm.h +++ b/include/rm.h @@@ -615,12 -624,16 +615,16 @@@ typedef struct /* * 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 { \ diff --cc src/light.c index 51e3a0d97,7c2dc1f2d..ab0e619f4 --- a/src/light.c +++ b/src/light.c @@@ -63,9 -65,9 +63,9 @@@ anything *id 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; @@@ -208,6 -210,80 +208,80 @@@ char **cs_rows } } + /* 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) */ - for (ls = light_base; ls; ls = ls->next) { ++ 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, bhitpos.x, bhitpos.y); /* temporarily put on map */ ++ 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) diff --cc src/zap.c index aa53e0f84,1563d434c..60bcee3a7 --- a/src/zap.c +++ b/src/zap.c @@@ -3264,21 -3272,25 +3264,25 @@@ struct obj **pobj; /* object tossed/use 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)) { @@@ -3374,9 -3389,10 +3381,10 @@@ 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); @@@ -3395,11 -3411,11 +3403,11 @@@ } 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)) {