hearing an unseen monster read a scroll
Heroes recognized unseen same-race monsters by voice, but it yielded an unexpected result if the monster was unique. Change it so that hero will recognize any type of monster by its voice if that monster has been seen and limit unseen same-race ones to non-unique monsters. Treats shopkeepers as unique since they have distinct names. This adds a new flag to struct monst in order to track whether each specific monster has ever been seen or sensed.
This commit is contained in:
@@ -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) */
|
||||
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
21
src/muse.c
21
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));
|
||||
}
|
||||
|
||||
10
src/read.c
10
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 */
|
||||
|
||||
Reference in New Issue
Block a user