diff --git a/include/monst.h b/include/monst.h index 119512a54..86ab245e8 100644 --- a/include/monst.h +++ b/include/monst.h @@ -156,7 +156,7 @@ struct monst { Bitfield(iswiz, 1); /* is the Wizard of Yendor */ Bitfield(wormno, 5); /* at most 31 worms on any level */ Bitfield(mtemplit, 1); /* temporarily seen; only valid during bhit() */ - /* 1 free bit */ + Bitfield(meverseen, 1); /* mon has been seen at some point */ #define MAX_NUM_WORMS 32 /* should be 2^(wormno bitfield size) */ diff --git a/src/display.c b/src/display.c index 31c92d14c..8b3961d73 100644 --- a/src/display.c +++ b/src/display.c @@ -502,22 +502,24 @@ show_mon_or_warn(coordxy x, coordxy y, int monglyph) * */ static void -display_monster(coordxy x, coordxy y, /* display position */ - struct monst *mon, /* monster to display */ - int sightflags, /* 1 if the monster is physically seen; - 2 if detected using Detect_monsters */ - boolean worm_tail) /* mon is actually a worm tail */ +display_monster( + coordxy x, coordxy y, /* display position */ + struct monst *mon, /* monster to display */ + int sightflags, /* 1 if the monster is physically seen; + * 2 if detected using Detect_monsters */ + boolean worm_tail) /* mon is actually a worm tail */ { boolean mon_mimic = (M_AP_TYPE(mon) != M_AP_NOTHING); int sensed = (mon_mimic && (Protection_from_shape_changers - || sensemon(mon))); + || sensemon(mon))), + mgendercode = mon->female ? FEMALE : MALE; + /* * We must do the mimic check first. If the mimic is mimicing something, * and the location is in sight, we have to change the hero's memory * so that when the position is out of sight, the hero remembers what * the mimic was mimicing. */ - if (mon_mimic && (sightflags == PHYSICALLY_SEEN)) { switch (M_AP_TYPE(mon)) { default: @@ -563,13 +565,13 @@ display_monster(coordxy x, coordxy y, /* display position */ break; } - case M_AP_MONSTER: - show_glyph(x, y, - monnum_to_glyph(what_mon((int) mon->mappearance, - rn2_on_display_rng), - mon->female ? FEMALE : MALE)); + case M_AP_MONSTER: { + int mndx = what_mon((int) mon->mappearance, rn2_on_display_rng); + + show_glyph(x, y, monnum_to_glyph(mndx, mgendercode)); break; - } + } /* case M_AP_MONSTER */ + } /* switch M_AP_TYPE() */ } /* If mimic is unsuccessfully mimicing something, display the monster. */ @@ -586,26 +588,26 @@ display_monster(coordxy x, coordxy y, /* display position */ */ if (mon->mtame && !Hallucination) { if (worm_tail) - num = petnum_to_glyph(PM_LONG_WORM_TAIL, - mon->female ? FEMALE : MALE); + num = petnum_to_glyph(PM_LONG_WORM_TAIL, mgendercode); else num = pet_to_glyph(mon, rn2_on_display_rng); } else if (sightflags == DETECTED) { if (worm_tail) - num = detected_monnum_to_glyph( - what_mon(PM_LONG_WORM_TAIL, rn2_on_display_rng), - mon->female ? FEMALE : MALE); + num = detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL, + rn2_on_display_rng), + mgendercode); else num = detected_mon_to_glyph(mon, rn2_on_display_rng); } else { if (worm_tail) - num = monnum_to_glyph( - what_mon(PM_LONG_WORM_TAIL, rn2_on_display_rng), - mon->female ? FEMALE : MALE); + num = monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL, + rn2_on_display_rng), + mgendercode); else num = mon_to_glyph(mon, rn2_on_display_rng); } show_mon_or_warn(x, y, num); + mon->meverseen = 1; } } @@ -1405,13 +1407,24 @@ see_monsters(void) if (gd.defer_see_monsters) return; + /* steed and unseen engulfer/holder/holdee are recognized via touch + even if they don't aren't going to be rendered; other monsters + may get flagged as having been seen by display_monster() if it's + called by newsym() */ + if (u.usteed) + u.usteed->meverseen = 1; + if (u.ustuck) + u.ustuck->meverseen = 1; + + /* loop through level.monsters (aka fmon) */ for (mon = fmon; mon; mon = mon->nmon) { if (DEADMONSTER(mon)) continue; newsym(mon->mx, mon->my); if (mon->wormno) see_wsegs(mon); - if (Warn_of_mon && (gc.context.warntype.obj & mon->data->mflags2) != 0L) + if (Warn_of_mon + && (gc.context.warntype.obj & mon->data->mflags2) != 0L) new_warn_obj_cnt++; } diff --git a/src/mon.c b/src/mon.c index c2e32f134..f5249f68c 100644 --- a/src/mon.c +++ b/src/mon.c @@ -4822,6 +4822,8 @@ newcham( place_worm_tail_randomly(mtmp, mtmp->mx, mtmp->my); } + mtmp->meverseen = 0; /* never seen mon in present shape; newsym() -> + * display_monster() may change it right back */ newsym(mtmp->mx, mtmp->my); if (msg) { diff --git a/src/muse.c b/src/muse.c index 65debc593..d92b1fa23 100644 --- a/src/muse.c +++ b/src/muse.c @@ -240,15 +240,20 @@ mreadmsg(struct monst *mtmp, struct obj *otmp) if (vismon) { /* directly see the monster reading the scroll */ pline("%s reads %s!", Monnam(mtmp), onambuf); - } else { + } else { /* !Deaf, otherwise we wouldn't reach here */ char blindbuf[BUFSZ]; - - boolean m_is_like_u = (!Hallucination - && same_race(gy.youmonst.data, mtmp->data)); - /* describe the unseen monster accurately if it is similar to the - hero's current form (unless hallucinating), else use "someone" */ + boolean similar = same_race(gy.youmonst.data, mtmp->data), + uniqmon = ((mtmp->data->geno & G_UNIQ) != 0 + /* shopkeepers aren't unique monsters but since + they have distinct names, treat them as such */ + || mtmp->isshk), + recognize = (!Hallucination + && (mtmp->meverseen || (similar && !uniqmon))); + /* describe unseen monster accurately when not hallucinating if it + has ever been seen or is the same race as the hero (not yet seen + unique monsters excepted) */ int mflags = (SUPPRESS_INVISIBLE | SUPPRESS_SADDLE - | (m_is_like_u ? SUPPRESS_IT : AUGMENT_IT)); + | (recognize ? SUPPRESS_IT : AUGMENT_IT)); /* monster can't be seen; hero might be blind or monster might be at a spot that isn't in view or might be invisible; remember @@ -263,7 +268,7 @@ mreadmsg(struct monst *mtmp, struct obj *otmp) x_monnam(mtmp, ARTICLE_A, (char *) 0, mflags, FALSE), blindbuf); } - if (mtmp->mconf) + if (mtmp->mconf) /* (note: won't get if not seen and hero can't hear) */ pline("Being confused, %s mispronounces the magic words...", vismon ? mon_nam(mtmp) : mhe(mtmp)); } diff --git a/src/read.c b/src/read.c index 7a7b512f4..2f3fdd2e6 100644 --- a/src/read.c +++ b/src/read.c @@ -1002,6 +1002,8 @@ recharge(struct obj* obj, int curse_bless) static void forget(int howmuch) { + struct monst *mtmp; + if (Punished) u.bc_felt = 0; /* forget felt ball&chain */ @@ -1010,6 +1012,14 @@ forget(int howmuch) /* Forget some skills. */ drain_weapon_skill(rnd(howmuch ? 5 : 3)); + + /* forget having seen monsts (affects recognizing unseen ones by sound) */ + for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) + if (mtmp != u.usteed && mtmp != u.ustuck) + mtmp->meverseen = 0; + /* [perhaps ought to forget having seen every monster on every level] */ + for (mtmp = gm.migrating_mons; mtmp; mtmp = mtmp->nmon) + mtmp->meverseen = 0; } /* monster is hit by scroll of taming's effect */