1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-07-28 16:32:27 +01:00

Delusions Madness rework, part 1

Laying out the ground for changing the madness -- monsters mimicking monsters needed more thorough handling.

Now fools:  monster naming functions, probing, farlook, scent/other detection
Not found out by most methods. Found out by:  being attacked, searching.

Many of these functionalities make more sense for the madness than for a mimic that is capable of mimicking a creature.
This commit is contained in:
NeroOneTrueKing 2021-05-02 00:01:43 -05:00
parent 4abfa5dfe0
commit a33e39acaa
13 changed files with 75 additions and 42 deletions

View file

@ -1568,6 +1568,7 @@ E void FDECL(wake_nearto, (int,int,int));
E void FDECL(wake_nearto_noisy, (int,int,int));
E void FDECL(seemimic_ambush, (struct monst *));
E void FDECL(seemimic, (struct monst *));
E void FDECL(see_passive_mimic, (struct monst *));
E void NDECL(rescham);
E void NDECL(restartcham);
E void FDECL(restore_cham, (struct monst *));

View file

@ -3797,7 +3797,7 @@ struct obj *obj;
}
wakeup(mtmp, TRUE);
} else {
if (mtmp->m_ap_type &&
if ((mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER) &&
!Protection_from_shape_changers && !sensemon(mtmp))
stumble_onto_mimic(mtmp);
else You("flick your whip towards %s.", mon_nam(mtmp));

View file

@ -416,9 +416,10 @@ display_monster(x, y, mon, sightflags, worm_tail)
/* 2 if detected using Detect_monsters */
register xchar worm_tail; /* mon is actually a worm tail */
{
/* we want M_AP_MONSTER to not be revealed by monster dectection */
register boolean mon_mimic = (mon->m_ap_type != M_AP_NOTHING);
register int sensed = mon_mimic &&
(Protection_from_shape_changers || sensemon(mon));
register int sensed = mon_mimic && (Protection_from_shape_changers || sensemon(mon));
register int appear = mon->mtyp;
/*
* 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
@ -464,14 +465,15 @@ display_monster(x, y, mon, sightflags, worm_tail)
}
case M_AP_MONSTER:
show_glyph(x,y, monnum_to_glyph(what_mon((int)mon->mappearance, mon)));
appear = mon->mappearance;
//show_glyph(x,y, monnum_to_glyph(what_mon((int)mon->mappearance, mon)));
break;
}
}
/* If the mimic is unsucessfully mimicing something, display the monster */
if (!mon_mimic || sensed) {
if (!mon_mimic || sensed || mon->m_ap_type == M_AP_MONSTER) {
int num;
if (mon->mtame && !Hallucination) {
@ -479,13 +481,13 @@ display_monster(x, y, mon, sightflags, worm_tail)
petnum_to_glyph(PM_HUNTING_HORROR_TAIL):
petnum_to_glyph(PM_LONG_WORM_TAIL);
else
num = pet_to_glyph(mon);
num = petnum_to_glyph(appear);
} else if (mon->mpeaceful && !Hallucination) {
if (worm_tail) num = mon->mtyp == PM_HUNTING_HORROR ?
peacenum_to_glyph(PM_HUNTING_HORROR_TAIL):
peacenum_to_glyph(PM_LONG_WORM_TAIL);
else
num = peace_to_glyph(mon);
num = peacenum_to_glyph(appear);
}
else if (!Hallucination && (
has_template(mon, VAMPIRIC) ||
@ -499,7 +501,7 @@ display_monster(x, y, mon, sightflags, worm_tail)
zombienum_to_glyph(PM_HUNTING_HORROR_TAIL):
zombienum_to_glyph(PM_LONG_WORM_TAIL);
else
num = zombie_to_glyph(mon);
num = zombienum_to_glyph(appear);
/* [ALI] Only use detected glyphs when monster wouldn't be
* visible by any other means.
*/
@ -508,13 +510,13 @@ display_monster(x, y, mon, sightflags, worm_tail)
detected_monnum_to_glyph(what_mon(PM_HUNTING_HORROR_TAIL, mon)):
detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL, mon));
else
num = detected_mon_to_glyph(mon);
num = detected_monnum_to_glyph(appear);
} else {
if (worm_tail) num = mon->mtyp == PM_HUNTING_HORROR ?
monnum_to_glyph(what_mon(PM_HUNTING_HORROR_TAIL, mon)):
monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL, mon));
else
num = mon_to_glyph(mon);
num = monnum_to_glyph(appear);
}
show_glyph(x,y,num);
}

View file

@ -918,6 +918,8 @@ boolean called;
static char buffers[XMONNAM_BUFFERS][BUFSZ];
#endif
struct permonst *mdat = mtmp->data;
const char * appearname = mdat->mname;
int appeartype = mdat->mtyp;
boolean do_hallu, do_invis, do_it, do_saddle;
boolean name_at_start, has_adjectives;
char *bp;
@ -971,6 +973,12 @@ boolean called;
return strcpy(buf, name);
}
/* monsters appearing as other monsters */
if ((mtmp->m_ap_type == M_AP_MONSTER) && !(suppress & SUPPRESS_HALLUCINATION)) {
appeartype = mtmp->mappearance;
appearname = mons[appeartype].mname;
}
/* Shopkeepers: use shopkeeper name. For normal shopkeepers, just
* "Asidonhopo"; for unusual ones, "Asidonhopo the invisible
* shopkeeper" or "Asidonhopo the blue dragon". If hallucinating,
@ -986,11 +994,11 @@ boolean called;
return buf;
}
Strcat(buf, shkname(mtmp));
if (mdat->mtyp == PM_SHOPKEEPER && !do_invis)
if (appeartype == PM_SHOPKEEPER && !do_invis)
return buf;
Strcat(buf, " the ");
if (do_invis) Strcat(buf, "invisible ");
if (mtmp->mflee && mtmp->mtyp == PM_BANDERSNATCH){
if (mtmp->mflee && appeartype == PM_BANDERSNATCH){
Strcat(buf, "frumious ");
name_at_start = FALSE;
}
@ -1014,7 +1022,7 @@ boolean called;
Sprintf(eos(buf), "%sed ", OBJ_DESCR(objects[mtmp->mvar_syllable]));
name_at_start = FALSE;
}
Strcat(buf, mdat->mname);
Strcat(buf, appearname);
append_template_desc(mtmp, buf, TRUE);
return buf;
}
@ -1044,17 +1052,17 @@ boolean called;
} else if (M_HAS_NAME(mtmp)) {
char *name = MNAME(mtmp);
if (mdat->mtyp == PM_GHOST) {
if (appeartype == PM_GHOST) {
Sprintf(eos(buf), "%s ghost", s_suffix(name));
name_at_start = TRUE;
} else if (mdat->mtyp == PM_SHADE) {
} else if (appeartype == PM_SHADE) {
Sprintf(eos(buf), "%s shade", s_suffix(name));
name_at_start = TRUE;
} else if (mdat->mtyp == PM_BROKEN_SHADOW) {
} else if (appeartype == PM_BROKEN_SHADOW) {
Sprintf(eos(buf), "%s broken shadow", s_suffix(name));
name_at_start = TRUE;
} else if (called) {
if (mtmp->mflee && mtmp->mtyp == PM_BANDERSNATCH){
if (mtmp->mflee && appeartype == PM_BANDERSNATCH){
Sprintf(eos(buf), "frumious ");
name_at_start = FALSE;
}
@ -1078,7 +1086,7 @@ boolean called;
name_at_start = FALSE;
}
Sprintf(eos(buf), "%s", mdat->mname);
Sprintf(eos(buf), "%s", appearname);
append_template_desc(mtmp, buf, type_is_pname(mdat));
Sprintf(eos(buf), " called %s", name);
@ -1109,7 +1117,7 @@ boolean called;
name_at_start = FALSE;
} else {
name_at_start = (boolean)type_is_pname(mdat);
if (mtmp->mflee && mtmp->mtyp == PM_BANDERSNATCH){
if (mtmp->mflee && appeartype == PM_BANDERSNATCH){
Strcat(buf, "frumious ");
name_at_start = FALSE;
}
@ -1133,16 +1141,16 @@ boolean called;
Sprintf(eos(buf), "%sed ", OBJ_DESCR(objects[mtmp->mvar_syllable]));
name_at_start = FALSE;
}
Strcat(buf, mdat->mname);
Strcat(buf, appearname);
append_template_desc(mtmp, buf, type_is_pname(mdat));
}
if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) {
if (mdat->mtyp == PM_WIZARD_OF_YENDOR)
if (appeartype == PM_WIZARD_OF_YENDOR)
article = ARTICLE_THE;
else
article = ARTICLE_NONE;
} else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A && mdat->mtyp != PM_GOD) {
} else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A && appeartype != PM_GOD) {
article = ARTICLE_THE;
}

View file

@ -39,7 +39,9 @@ register boolean clumsy;
boolean trapkilled = FALSE;
int result;
if(mon->m_ap_type) seemimic(mon);
if(mon->m_ap_type) {
if(mon->m_ap_type == M_AP_MONSTER) seemimic_ambush(mon); else seemimic(mon);
}
check_caitiff(mon);
result = xmeleehity(&youmonst, mon, &basickick, (struct obj **)0, -1, 1000, FALSE);

View file

@ -545,7 +545,7 @@ boolean yours; /* is it your fault (for killing monsters) */
"fried");
}
} else if (!silent && cansee(xi, yi)) {
if(mtmp->m_ap_type) seemimic(mtmp);
if(mtmp->m_ap_type) see_passive_mimic(mtmp);
pline("%s is caught in the %s!", Monnam(mtmp), str);
}

View file

@ -1205,7 +1205,7 @@ domove()
* different message and makes the player remember the monster. */
if(flags.nopick &&
(canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){
if(mtmp->m_ap_type && !Protection_from_shape_changers
if((mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER) && !Protection_from_shape_changers
&& !sensemon(mtmp))
stumble_onto_mimic(mtmp);
else if (mtmp->mpeaceful && !Hallucination)

View file

@ -5787,7 +5787,7 @@ int anger;
mtmp->meating = 0; /* assume there's no salvagable food left */
mtmp->mstrategy &= ~(STRAT_WAITMASK);
if(anger) setmangry(mtmp);
if(mtmp->m_ap_type) seemimic(mtmp);
if(mtmp->m_ap_type) see_passive_mimic(mtmp);
else if (flags.forcefight && !flags.mon_moving && mtmp->mundetected) {
mtmp->mundetected = 0;
newsym(mtmp->mx, mtmp->my);
@ -5932,6 +5932,7 @@ register int x, y, distance;
}
}
/* reveals monster-mimickers as well as passive-mimickers with a surprised message */
void
seemimic_ambush(mtmp)
struct monst *mtmp;
@ -5941,7 +5942,7 @@ struct monst *mtmp;
seemimic(mtmp);
if (canseemon(mtmp) && !sensemon(mtmp)) {
if (canseemon(mtmp) && !(sensemon(mtmp) && old_ap_type != M_AP_MONSTER)) {
const char * app;
switch (old_ap_type)
{
@ -5971,6 +5972,7 @@ struct monst *mtmp;
/* NOTE: we must check for mimicry before calling this routine */
/* reveals monster-mimickers as well as passive-mimickers, with no message */
void
seemimic(mtmp)
register struct monst *mtmp;
@ -5993,6 +5995,15 @@ register struct monst *mtmp;
newsym(mtmp->mx,mtmp->my);
}
/* seemimic() for furniture and objects only */
void
see_passive_mimic(mtmp)
register struct monst * mtmp;
{
if (mtmp->m_ap_type == M_AP_FURNITURE || mtmp->m_ap_type == M_AP_OBJECT)
seemimic(mtmp);
}
/* force all chameleons to become normal */
void
rescham()
@ -6010,7 +6021,7 @@ rescham()
}
if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
new_were(mtmp);
if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my) && mtmp->m_ap_type != M_AP_MONSTER) {
seemimic(mtmp);
/* we pretend that the mimic doesn't */
/* know that it has been unmasked. */

View file

@ -1210,7 +1210,7 @@ register struct obj *otmp;
boolean reveal_invis = FALSE;
if (mtmp != &youmonst) {
mtmp->msleeping = 0;
if (mtmp->m_ap_type) seemimic(mtmp);
if (mtmp->m_ap_type) see_passive_mimic(mtmp);
}
switch(otmp->otyp) {
case WAN_STRIKING:
@ -1251,7 +1251,7 @@ register struct obj *otmp;
if (cansee(mtmp->mx, mtmp->my))
pline("%s resists the magic!", Monnam(mtmp));
mtmp->msleeping = 0;
if(mtmp->m_ap_type) seemimic(mtmp);
if(mtmp->m_ap_type) see_passive_mimic(mtmp);
} else if (!tele_restrict(mtmp))
(void) rloc(mtmp, FALSE);
}

View file

@ -2117,9 +2117,18 @@ get_description_of_monster_type(struct monst * mtmp, char * description)
struct permonst * ptr = mtmp->data;
int monsternumber = monsndx(ptr);
/* monsters pretending to be other monsters won't be given away by the pokedex */
struct monst fakemon;
if (mtmp->m_ap_type == M_AP_MONSTER) {
fakemon = *mtmp;
monsternumber = fakemon.mtyp = mtmp->mappearance;
ptr = fakemon.data = &mons[monsternumber];
mtmp = &fakemon;
}
char name[BUFSZ] = "";
Strcat(name, ptr->mname);
if (type_is_pname(mtmp->data)){
if (type_is_pname(ptr)){
if (has_template(mtmp, MISTWEAVER)){
if (mtmp->female) Strcat(name, ", Daughter of the Black Goat");
else Strcat(name, ", Child of the Black Goat");

View file

@ -995,6 +995,7 @@ int tary;
continue;
}
/* make the attack */
if ((vis&VIS_MAGR) && magr->mappearance) seemimic_ambush(magr); // its true form must be revealed
result = xengulfhity(magr, mdef, attk, vis);
/* increment number of attacks made */
attacksmade++;
@ -2279,9 +2280,6 @@ boolean nearmiss;
if (!(vis&VIS_MDEF))
map_invisible(x(mdef), y(mdef));
if (mdef->m_ap_type) seemimic(mdef);
if (magr->m_ap_type) seemimic(magr);
pline("%s %s %s.",
Monnam(magr),
(compat ? "pretends to be friendly to" : "misses"),
@ -3679,11 +3677,10 @@ boolean ranged;
wake_nearto(x(mdef), y(mdef), /* call function to wake nearby monsters */
combatNoise(pa) / (((youagr || youdef) && Stealth) ? 2 : 1)); /* range is reduced if the player is involved and stealthy */
/* show mimics */
if (magr->mappearance)
seemimic_ambush(magr);
if (mdef->mappearance)
seemimic(mdef);
/* show mimics on successful attack */
if (mdef->mappearance && hit) {
if (youagr) seemimic_ambush(mdef); else seemimic(mdef);
}
/* If the monster is undetected and hits you, you should know where the attack came from. */
if (youdef && magr->mundetected && hit && (hides_under(pa) || is_underswimmer(pa))) {
magr->mundetected = 0;

View file

@ -199,7 +199,7 @@ struct obj * wep; /* uwep for attack(), null for kick_monster() */
return ATTACKCHECK_NONE;
}
if (mdef->m_ap_type && !Protection_from_shape_changers &&
if ((mdef->m_ap_type && mdef->m_ap_type != M_AP_MONSTER) && !Protection_from_shape_changers &&
!sensemon(mdef) &&
!glyph_is_warning(glyph_at(u.ux + u.dx, u.uy + u.dy))) {
/* If a hidden mimic was in a square where a player remembers
@ -398,6 +398,9 @@ struct monst *mtmp;
if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
u.ustuck = mtmp;
/* clear mimicking before generating message to get an accurate a_monnam() */
seemimic(mtmp);
if (Blind) {
if (!Blind_telepat)
what = generic; /* with default fmt */
@ -423,7 +426,7 @@ struct monst *mtmp;
}
if (what) pline(fmt, what);
wakeup(mtmp, TRUE); /* clears mimicking */
wakeup(mtmp, TRUE);
}

View file

@ -4468,7 +4468,7 @@ struct obj *otmp; /* source of flash */
/* at this point, reveal them */
mtmp->mundetected = 0;
if (mtmp->m_ap_type)
seemimic(mtmp);
see_passive_mimic(mtmp);
newsym(mtmp->mx, mtmp->my);
if (mtmp->mtyp == PM_GREMLIN) {
/* Rule #1: Keep them out of the light. */