From 223818ff410a7653980a2ca1411aff84b22b61f9 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 28 Nov 2022 01:44:19 -0800 Subject: [PATCH] github issue #934 - hearing unseem mon read scroll Issue reported by Melon2007: when non-deaf hero heard an unseen monster read a scroll, the monster's type was identified accurately (unless distorted by hallucination). That was intentional but it doesn't seem plausible for the hero's hearing to be that acute. Change it to report the monster type accurately if not hallucinating and monster is the same species as the hero (as the current form if hero is poly'd), otherwise report it as "someone" when it's humanoid, otherwise as "something". Also, if the monster is heard at a spot that would be visible if hero could see, draw a "remembered, unseen monster" glyph there. Fixes #934 --- doc/fixes3-7-0.txt | 3 +++ src/muse.c | 67 ++++++++++++++++++++++++---------------------- src/objnam.c | 2 +- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index c16c10987..8c8dc26b9 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1054,6 +1054,9 @@ phrasing of the "you can't" message when attempting to name any monster defined with a unique name or title sounded strange when rejecting to remove the existing name without assigning a new one some instances of using up or stealing shop-owned boulder didn't charge for it +when hero hears an unseen monster reading a scroll, only describe the monster + acccurately if hero is not hallucinating and monster is same species + as hero's current form Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/muse.c b/src/muse.c index 3fa587130..a68ff93d0 100644 --- a/src/muse.c +++ b/src/muse.c @@ -48,7 +48,7 @@ static boolean green_mon(struct monst *); * anything (i.e. it teleported) and 1 if it's dead. */ static int -precheck(struct monst* mon, struct obj* obj) +precheck(struct monst *mon, struct obj *obj) { boolean vis; @@ -219,53 +219,55 @@ mplayhorn( otmp->spe -= 1; /* use a charge */ } +/* see or hear a monster reading a scroll; + when scroll hasn't been seen, its label is revealed unless hero is deaf */ static void -mreadmsg(struct monst* mtmp, struct obj* otmp) +mreadmsg(struct monst *mtmp, struct obj *otmp) { - boolean vismon = canseemon(mtmp); char onambuf[BUFSZ]; - short saverole; - unsigned savebknown; + boolean vismon = canseemon(mtmp); if (!vismon && Deaf) return; /* no feedback */ - otmp->dknown = 1; /* seeing or hearing it read reveals its label */ - /* shouldn't be able to hear curse/bless status of unseen scrolls; - for priest characters, bknown will always be set during naming */ - savebknown = otmp->bknown; - saverole = Role_switch; - if (!vismon) { - otmp->bknown = 0; - if (Role_if(PM_CLERIC)) - Role_switch = 0; - } - Strcpy(onambuf, singular(otmp, doname)); - Role_switch = saverole; - otmp->bknown = savebknown; + otmp->dknown = 1; /* seeing or hearing scroll read reveals its label */ + Strcpy(onambuf, singular(otmp, vismon ? doname : ansimpleoname)); - if (vismon) + if (vismon) { + /* directly see the monster reading the scroll */ pline("%s reads %s!", Monnam(mtmp), onambuf); - else - You_hear("%s reading %s.", - x_monnam(mtmp, ARTICLE_A, (char *) 0, - (SUPPRESS_IT | SUPPRESS_INVISIBLE | SUPPRESS_SADDLE), - FALSE), - onambuf); + } else { + boolean m_is_like_u = (!Hallucination + && same_race(g.youmonst.data, mtmp->data)); + /* describe the unseen monster accurately if it is similar to the + hero's current form (unless hallucinating), else use "someone" */ + int mflags = (SUPPRESS_INVISIBLE | SUPPRESS_SADDLE + | (m_is_like_u ? 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 + it if the spot is within line of sight and relatively close */ + if (couldsee(mtmp->mx, mtmp->my) && mdistu(mtmp) <= 10 * 10) + map_invisible(mtmp->mx, mtmp->my); + + You_hear("%s reading %s.", + x_monnam(mtmp, ARTICLE_A, (char *) 0, mflags, FALSE), + onambuf); + } if (mtmp->mconf) pline("Being confused, %s mispronounces the magic words...", vismon ? mon_nam(mtmp) : mhe(mtmp)); } static void -mquaffmsg(struct monst* mtmp, struct obj* otmp) +mquaffmsg(struct monst *mtmp, struct obj *otmp) { if (canseemon(mtmp)) { otmp->dknown = 1; pline("%s drinks %s!", Monnam(mtmp), singular(otmp, doname)); - } else if (!Deaf) + } else if (!Deaf) { You_hear("a chugging sound."); + } } /* Defines for various types of stuff. The order in which monsters prefer @@ -301,7 +303,7 @@ mquaffmsg(struct monst* mtmp, struct obj* otmp) */ static boolean -m_use_healing(struct monst* mtmp) +m_use_healing(struct monst *mtmp) { struct obj *obj; @@ -942,8 +944,8 @@ use_defensive(struct monst* mtmp) } else { if (vismon) pline("%s escapes upstairs!", Monnam(mtmp)); - migrate_to_level(mtmp, ledger_no(&(stway->tolev)), MIGR_STAIRS_DOWN, - (coord *) 0); + migrate_to_level(mtmp, ledger_no(&(stway->tolev)), + MIGR_STAIRS_DOWN, (coord *) 0); } return 2; case MUSE_DOWNSTAIRS: @@ -1656,7 +1658,8 @@ use_offensive(struct monst* mtmp) case MUSE_FROST_HORN: mplayhorn(mtmp, otmp, FALSE); g.m_using = TRUE; - buzz(BZ_M_WAND(BZ_OFS_AD((otmp->otyp == FROST_HORN) ? AD_COLD : AD_FIRE)), + buzz(BZ_M_WAND(BZ_OFS_AD((otmp->otyp == FROST_HORN) ? AD_COLD + : AD_FIRE)), rn1(6, 6), mtmp->mx, mtmp->my, sgn(mtmp->mux - mtmp->mx), sgn(mtmp->muy - mtmp->my)); g.m_using = FALSE; @@ -2646,7 +2649,7 @@ mon_consume_unstone( struct monst *mon, struct obj *obj, boolean by_you, - boolean stoning) /* True: stop petrification, False: cure stun && confusion */ + boolean stoning) /* T: stop petrification, F: cure stun && confusion */ { boolean vis = canseemon(mon), tinned = obj->otyp == TIN, food = obj->otyp == CORPSE || tinned, diff --git a/src/objnam.c b/src/objnam.c index 6e6f48f51..b55f349f1 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -2132,7 +2132,7 @@ ansimpleoname(struct obj* obj) int otyp = obj->otyp; /* prefix with "the" if a unique item, or a fake one imitating same, - has been formatted with its actual name (we let typename() handle + has been formatted with its actual name (we let minimal_xname() handle any `known' and `dknown' checking necessary) */ if (otyp == FAKE_AMULET_OF_YENDOR) otyp = AMULET_OF_YENDOR;