diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 4727c5b06..7fdc7c9da 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1861,6 +1861,11 @@ if an amulet of flying gets stolen while hero is over lava without other poison gas breath from green dragon or iron golem that hit and was reflected left target enveloped in a gas cloud (reflection now takes precedence; somewhat odd though: gas that misses still leaves target enveloped) +Warning didn't show nearby monsters who were inside poison gas/steam/smoke + regions +map didn't show adjacent monsters if they were inside a gas region unless + they were seen via telepathy or extended monster detection, but they + were described as if visible in messages (combat, for instance) Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository diff --git a/src/display.c b/src/display.c index c2dc9b74d..6486fc6d2 100644 --- a/src/display.c +++ b/src/display.c @@ -128,6 +128,7 @@ static void display_monster(coordxy, coordxy, struct monst *, int, boolean) NONNULLPTRS; static int swallow_to_glyph(int, int); static void display_warning(struct monst *) NONNULLARG1; +static boolean next_to_gas(struct monst *) NONNULLARG1; static int check_pos(coordxy, coordxy, int); static void get_bkglyph_and_framecolor(coordxy x, coordxy y, int *, uint32 *); @@ -650,6 +651,20 @@ warning_of(struct monst *mon) return wl; } +/* returns True if mon is adjacent and would be seen if vision wasn't + blocked by being in a gas cloud (implicit; caller has already checked) */ +static boolean +next_to_gas(struct monst *mon) +{ + int r = (u.xray_range > 1) ? (u.xray_range + 1) : 2; + + if (distu(mon->mx, mon->my) > r * (r - 1)) + return FALSE; + if (!_mon_visible(mon) && !_see_with_infrared(mon)) + return FALSE; + return TRUE; +} + /* map or status window might not be ready for output during level creation or game restoration (something like u.usteed which affects display of the hero and also a status condition might not be set up yet) */ @@ -907,14 +922,29 @@ newsym(coordxy x, coordxy y) * Normal region shown only on accessible positions, but * poison clouds and steam clouds also shown above lava, * pools and moats. - * However, sensed monsters take precedence over all regions. + * However, sensed monsters (via detection or telepathy or + * warning) take precedence over all regions. + * Adjacent monsters also take precedence if they would be + * seen when there's no gas region. + * + * FIXME: + * The adjacency checking here works when the hero is outside + * the region and the monster is inside, and when they're both + * inside, but not when the hero is inside and monster outside + * (because 'reg' will be Null for mon's ). Checking + * whether hero is inside a region for every newsym() seems + * excessive. The hero is usually blind when in a gas cloud + * so the problem is less noticeable then it might otherwise be. */ - if (reg - && (ACCESSIBLE(lev->typ) - || (reg->visible && is_pool_or_lava(x, y))) - && (!mon || worm_tail || !sensemon(mon))) { - show_region(reg, x, y); - return; + if (reg && (ACCESSIBLE(lev->typ) + || (reg->visible && is_pool_or_lava(x, y)))) { + if (mon && !worm_tail && (sensemon(mon) || mon_warning(mon) + || next_to_gas(mon))) { + ; /* skip region; the 'if' is more comphrehensible this way */ + } else { + show_region(reg, x, y); + return; + } } if (u_at(x, y)) { @@ -944,7 +974,7 @@ newsym(coordxy x, coordxy y) display_monster(x, y, mon, see_it ? PHYSICALLY_SEEN : DETECTED, worm_tail); - } else if (mon && mon_warning(mon) && !is_worm_tail(mon)) { + } else if (mon && mon_warning(mon) && !worm_tail) { display_warning(mon); } else if (glyph_is_invisible(lev->glyph)) { map_invisible(x, y); @@ -963,7 +993,7 @@ newsym(coordxy x, coordxy y) && ((see_it = (tp_sensemon(mon) || MATCH_WARN_OF_MON(mon) || (see_with_infrared(mon) && mon_visible(mon)))) != 0 - || Detect_monsters)) { + || (Detect_monsters && !is_worm_tail(mon)))) { /* Seen or sensed monsters are printed every time. This also gets rid of any invisibility glyph. */ display_monster(x, y, mon, see_it ? 0 : DETECTED, diff --git a/src/vision.c b/src/vision.c index 004a9d5eb..adc66230f 100644 --- a/src/vision.c +++ b/src/vision.c @@ -134,7 +134,10 @@ vision_init(void) /* * does_block() * - * Returns true if something at (x,y) blocks sight. + * Returns 0 if nothing at (x,y) blocks sight, 1 if anything other than + * an opaque region (gas cloud rather than CLOUD terrain) blocks sight, + * or 2 if an opaque region potions sight. [At present, the rest of the + * code makes no distinction between 1 and 2, just between 0 and non-0.] */ int does_block(int x, int y, struct rm *lev) @@ -158,8 +161,7 @@ does_block(int x, int y, struct rm *lev) #ifdef DEBUG if (gs.seethru != 1) { #endif - if (lev->typ == CLOUD || IS_WATERWALL(lev->typ) - || lev->typ == LAVAWALL + if (lev->typ == CLOUD || IS_WATERWALL(lev->typ) || lev->typ == LAVAWALL || (Underwater && is_moat(x, y))) return 1; #ifdef DEBUG @@ -181,7 +183,7 @@ does_block(int x, int y, struct rm *lev) #endif /* Clouds (poisonous or not) block light. */ if (visible_region_at(x, y)) - return 1; + return 2; #ifdef DEBUG } /* gs.seethru */ #endif @@ -929,7 +931,7 @@ unblock_point(int x, int y) * + If you are a blocked spot, then your right will point to the * right-most blocked spot to your right that is connected to you. * This means that a right-edge (a blocked spot that has an open - * spot on its right) will point to itself. + * spot on its right) will point to itself. */ static void dig_point(int row, int col)