avoid "It turns into it"

<Someone> drew attention to the silly message in the newsgroup

Since I'm not sure if the act of polymorphing has a sound,
I opted to use a new usmellmon() routine to put out a
message based on the smell of the resulting monster
under those circumstances.

Not every monster has a recognizable smell, so no
message at all is given in that case.

olfactory(youmonst.data) will determine whether
you are capable of detecting smells.

There is lots of room for enhancement, and some of the
existing smell-related messages in the source should perhaps
be checking olfactory(youmonst.data) too, but this patch
doesn't go that far.
This commit is contained in:
nethack.allison
2004-01-17 20:42:14 +00:00
parent 569cb15070
commit f2101638db
5 changed files with 203 additions and 4 deletions

View File

@@ -13,6 +13,7 @@ trap messages referring to named steed were ackwardly worded when hallucination
overrode use of the name
some actions such as eating corpses off the floor didn't check whether hero
could reach the bottom of a pit
usmellmon() instead of "It turns into it" during monster polymorph
Platform- and/or Interface-Specific Fixes

View File

@@ -973,6 +973,7 @@ E void FDECL(mkmonmoney, (struct monst *, long));
#endif
E void FDECL(bagotricks, (struct obj *));
E boolean FDECL(propagate, (int, BOOLEAN_P,BOOLEAN_P));
E boolean FDECL(usmellmon, (struct permonst *));
/* ### mapglyph.c ### */
@@ -1223,6 +1224,7 @@ E const char *FDECL(locomotion, (const struct permonst *,const char *));
E const char *FDECL(stagger, (const struct permonst *,const char *));
E const char *FDECL(on_fire, (struct permonst *,struct attack *));
E const struct permonst *FDECL(raceptr, (struct monst *));
E boolean FDECL(olfaction, (struct permonst *));
/* ### monmove.c ### */

View File

@@ -121,6 +121,7 @@ STATIC_PTR int NDECL(wiz_level_tele);
STATIC_PTR int NDECL(wiz_level_change);
STATIC_PTR int NDECL(wiz_show_seenv);
STATIC_PTR int NDECL(wiz_show_vision);
STATIC_PTR int NDECL(wiz_smell);
STATIC_PTR int NDECL(wiz_mon_polycontrol);
STATIC_PTR int NDECL(wiz_show_wmodes);
#if defined(__BORLANDC__) && !defined(_WIN32)
@@ -750,6 +751,53 @@ wiz_show_wmodes()
return 0;
}
/* #wizsmell command - test usmellmon(). */
STATIC_PTR int
wiz_smell()
{
char out_str[BUFSZ];
const char *firstmatch = 0;
struct permonst *pm = 0;
int ans = 0;
int mndx; /* monster index */
int found; /* count of matching mndxs found */
coord cc; /* screen pos of unknown glyph */
int glyph; /* glyph at selected position */
cc.x = u.ux;
cc.y = u.uy;
mndx = 0; /* gcc -Wall lint */
if (!olfaction(youmonst.data)) {
You("are incapable of detecting odors in your present form.");
return 0;
}
pline("You can move the cursor to a monster that you want to smell.");
do {
/* Reset some variables. */
pm = (struct permonst *)0;
found = 0;
out_str[0] = '\0';
pline("Pick a monster to smell.");
ans = getpos(&cc, TRUE, "a monster");
if (ans < 0 || cc.x < 0) {
return 0; /* done */
}
/* Convert the glyph at the selected position to a mndxbol. */
glyph = glyph_at(cc.x,cc.y);
if (glyph_is_monster(glyph))
mndx = glyph_to_mon(glyph);
else
mndx = 0;
/* Is it a monster? */
if (mndx) {
if (!usmellmon(&mons[mndx]))
pline("That monster seems to give off no smell.");
} else pline("That is not a monster.");
} while (TRUE);
return 0;
}
#endif /* WIZARD */
@@ -1516,6 +1564,7 @@ struct ext_func_tab extcmdlist[] = {
{(char *)0, (char *)0, donull, TRUE},
{(char *)0, (char *)0, donull, TRUE},
{(char *)0, (char *)0, donull, TRUE},
{(char *)0, (char *)0, donull, TRUE},
#ifdef DEBUG
{(char *)0, (char *)0, donull, TRUE},
#endif
@@ -1541,6 +1590,7 @@ static const struct ext_func_tab debug_extcmdlist[] = {
{"stats", "show memory statistics", wiz_show_stats, TRUE},
{"timeout", "look at timeout queue", wiz_timeout_queue, TRUE},
{"vision", "show vision array", wiz_show_vision, TRUE},
{"wizsmell", "smell monster", wiz_smell, TRUE},
#ifdef DEBUG
{"wizdebug", "wizard debug command", wiz_debug_cmd, TRUE},
#endif

128
src/mon.c
View File

@@ -2347,7 +2347,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */
int mhp, hpn, hpd;
int mndx, tryct;
struct permonst *olddata = mtmp->data;
char oldname[BUFSZ];
char oldname[BUFSZ], newname[BUFSZ];
if (msg) {
/* like Monnam() but never mention saddle */
@@ -2487,9 +2487,13 @@ boolean msg; /* "The oldmon turns into a newmon!" */
if (msg) {
uchar save_mnamelth = mtmp->mnamelth;
mtmp->mnamelth = 0;
pline("%s turns into %s!", oldname,
mdat == &mons[PM_GREEN_SLIME] ? "slime" :
x_monnam(mtmp, ARTICLE_A, (char*)0, SUPPRESS_SADDLE, FALSE));
Strcpy(newname,
(mdat == &mons[PM_GREEN_SLIME]) ? "slime" :
x_monnam(mtmp, ARTICLE_A, (char *)0,SUPPRESS_SADDLE, FALSE));
if (!strcmpi(oldname,"it") && !strcmpi(newname,"it"))
(void) usmellmon(mdat);
else
pline("%s turns into %s!", oldname, newname);
mtmp->mnamelth = save_mnamelth;
}
@@ -2768,4 +2772,120 @@ short otyp;
}
}
boolean
usmellmon(mdat)
struct permonst *mdat;
{
int mndx;
boolean nonspecific = FALSE;
boolean msg_given = FALSE;
if (mdat) {
if (!olfaction(youmonst.data)) return FALSE;
mndx = monsndx(mdat);
switch (mndx) {
case PM_MINOTAUR:
You("notice a bovine smell.");
msg_given = TRUE;
break;
case PM_CAVEMAN:
case PM_CAVEWOMAN:
case PM_BARBARIAN:
case PM_NEANDERTHAL:
You("smell body odor.");
msg_given = TRUE;
break;
/*
case PM_PESTILENCE:
case PM_FAMINE:
case PM_DEATH:
break;
*/
case PM_HORNED_DEVIL:
case PM_BALROG:
case PM_ASMODEUS:
case PM_DISPATER:
case PM_YEENOGHU:
case PM_ORCUS:
break;
case PM_HUMAN_WEREJACKAL:
case PM_HUMAN_WERERAT:
case PM_HUMAN_WEREWOLF:
case PM_WEREJACKAL:
case PM_WERERAT:
case PM_WEREWOLF:
case PM_OWLBEAR:
You("detect an odor reminiscent of an animal's den.");
msg_given = TRUE;
break;
/*
case PM_PURPLE_WORM:
break;
*/
case PM_STEAM_VORTEX:
You("smell steam.");
msg_given = TRUE;
break;
case PM_GREEN_SLIME:
pline("%s stinks.", Something);
msg_given = TRUE;
break;
case PM_VIOLET_FUNGUS:
case PM_SHRIEKER:
You("smell mushrooms.");
msg_given = TRUE;
break;
/* These are here to avoid triggering the
nonspecific treatment through the default case below*/
case PM_WHITE_UNICORN:
case PM_GRAY_UNICORN:
case PM_BLACK_UNICORN:
case PM_JELLYFISH:
break;
default:
nonspecific = TRUE;
break;
}
if (nonspecific) switch(mdat->mlet) {
case S_DOG:
You("notice a dog smell.");
msg_given = TRUE;
break;
case S_DRAGON:
You("smell a dragon!");
msg_given = TRUE;
break;
case S_FUNGUS:
pline("%s smells moldy.", Something);
msg_given = TRUE;
break;
case S_UNICORN:
You("detect a%s odor reminiscent of a stable.",
(mndx == PM_PONY) ? "n" : " strong");
msg_given = TRUE;
break;
case S_ZOMBIE:
You("smell rotting flesh.");
msg_given = TRUE;
break;
case S_EEL:
You("smell fish.");
msg_given = TRUE;
break;
case S_ORC:
if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC)))
You("notice an attractive smell.");
else
pline(
"A foul stench makes you feel a little nauseated.");
msg_given = TRUE;
break;
default:
break;
}
}
return (msg_given) ? TRUE : FALSE;
}
/*mon.c*/

View File

@@ -720,4 +720,30 @@ struct attack *mattk;
return what;
}
/*
* Returns:
* TRUE if monster is presumed to have a sense of smell.
* FALSE if monster definitely does not have a sense of smell.
*
* Do not base this on presence of a head or nose, since many
* creatures sense smells other ways (feelers, forked-tongues, etc.)
* We're assuming all insects can smell at a distance too.
*/
boolean
olfaction(mdat)
struct permonst *mdat;
{
if (mdat && (is_golem(mdat) ||
mdat->mlet == S_EYE || /* spheres */
mdat->mlet == S_JELLY ||
mdat->mlet == S_PUDDING ||
mdat->mlet == S_BLOB ||
mdat->mlet == S_VORTEX ||
mdat->mlet == S_ELEMENTAL ||
mdat->mlet == S_FUNGUS || /* mushrooms and fungi */
mdat->mlet == S_LIGHT))
return FALSE;
return TRUE;
}
/*mondata.c*/