diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 37b61cb72..5d8433ce4 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -108,6 +108,7 @@ fix wording for "leprechaun steals gold from between your feet" when mounted fix monsndx panic which happened after currently moving monster expelled swallowed hero onto magic trap and was made tame by its effect; taming no longer replaces monster +reduced message verbosity when re-entering a temple Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 793915ba0..efb311413 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1686,6 +1686,7 @@ E char *FDECL(priestname, (struct monst *,char *)); E boolean FDECL(p_coaligned, (struct monst *)); E struct monst *FDECL(findpriest, (CHAR_P)); E void FDECL(intemple, (int)); +E void FDECL(forget_temple_entry, (struct monst *)); E void FDECL(priest_talk, (struct monst *)); E struct monst *FDECL(mk_roamer, (struct permonst *,ALIGNTYP_P, XCHAR_P,XCHAR_P,BOOLEAN_P)); diff --git a/include/mextra.h b/include/mextra.h index 99a6dcb10..fee06fa57 100644 --- a/include/mextra.h +++ b/include/mextra.h @@ -86,6 +86,10 @@ struct epri { schar shroom; /* index in rooms */ coord shrpos; /* position of shrine */ d_level shrlevel; /* level (& dungeon) of shrine */ + long intone_time, /* used to limit verbosity +*/ + enter_time, /*+ of temple entry messages */ + hostile_time, /* forbidding feeling */ + peaceful_time; /* sense of peace */ }; /* note: roaming priests (no shrine) switch from ispriest to isminion (and emin extension) */ diff --git a/include/patchlevel.h b/include/patchlevel.h index 073f31ab7..ffa059e7b 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -13,7 +13,7 @@ * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. */ -#define EDITLEVEL 25 +#define EDITLEVEL 26 #define COPYRIGHT_BANNER_A \ "NetHack, Copyright 1985-2006" diff --git a/src/mkobj.c b/src/mkobj.c index 62c51cc80..2d297cf64 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1074,6 +1074,7 @@ struct monst *mtmp; int lth, namelth; namelth = obj->onamelth ? strlen(ONAME(obj)) + 1 : 0; + if (mtmp->ispriest) forget_temple_entry(mtmp); /* EPRI() */ buffer = mon_to_buffer(mtmp, <h); otmp = realloc_obj(obj, lth, buffer, namelth, ONAME(obj)); free(buffer); diff --git a/src/priest.c b/src/priest.c index 55cae96d8..0a44222eb 100644 --- a/src/priest.c +++ b/src/priest.c @@ -5,8 +5,9 @@ #include "hack.h" #include "mfndpos.h" -/* this matches the categorizations shown by enlightenment */ -#define ALGN_SINNED (-4) /* worse than strayed */ +/* these match the categorizations shown by enlightenment */ +#define ALGN_SINNED (-4) /* worse than strayed (-1..-3) */ +#define ALGN_PIOUS 14 /* better than fervent (9..13) */ STATIC_DCL boolean FDECL(histemple_at,(struct monst *,XCHAR_P,XCHAR_P)); STATIC_DCL boolean FDECL(has_shrine,(struct monst *)); @@ -317,13 +318,14 @@ has_shrine(pri) struct monst *pri; { struct rm *lev; + struct epri *epri_p; - if(!pri) - return(FALSE); - lev = &levl[EPRI(pri)->shrpos.x][EPRI(pri)->shrpos.y]; - if (!IS_ALTAR(lev->typ) || !(lev->altarmask & AM_SHRINE)) - return(FALSE); - return((boolean)(EPRI(pri)->shralign == Amask2align(lev->altarmask & ~AM_SHRINE))); + if (!pri) return FALSE; + epri_p = EPRI(pri); + lev = &levl[epri_p->shrpos.x][epri_p->shrpos.y]; + if (!IS_ALTAR(lev->typ) || !(lev->altarmask & AM_SHRINE)) return FALSE; + return (boolean)(epri_p->shralign == + (Amask2align(lev->altarmask & ~AM_SHRINE))); } struct monst * @@ -344,81 +346,133 @@ char roomno; /* called from check_special_room() when the player enters the temple room */ void intemple(roomno) -register int roomno; +int roomno; { - register struct monst *priest = findpriest((char)roomno); - boolean tended = (priest != (struct monst *)0); - boolean shrined, sanctum, can_speak; - const char *msg1, *msg2; - char buf[BUFSZ]; + struct monst *priest, *mtmp; + struct epri *epri_p; + boolean shrined, sanctum, can_speak; + long *this_time, *other_time; + const char *msg1, *msg2; + char buf[BUFSZ]; - if(!temple_occupied(u.urooms0)) { - if(tended) { - shrined = has_shrine(priest); - sanctum = (priest->data == &mons[PM_HIGH_PRIEST] && - (Is_sanctum(&u.uz) || In_endgame(&u.uz))); - can_speak = (priest->mcanmove && !priest->msleeping && - !Deaf); - if (can_speak) { - unsigned save_priest = priest->ispriest; - /* don't reveal the altar's owner upon temple entry in - the endgame; for the Sanctum, the next message names - Moloch so suppress the "of Moloch" for him here too */ - if (sanctum && !Hallucination) priest->ispriest = 0; - pline("%s intones:", - canseemon(priest) ? Monnam(priest) : "A nearby voice"); - priest->ispriest = save_priest; - } - msg2 = 0; - if(sanctum && Is_sanctum(&u.uz)) { - if(priest->mpeaceful) { - msg1 = "Infidel, you have entered Moloch's Sanctum!"; - msg2 = "Be gone!"; - priest->mpeaceful = 0; - set_malign(priest); - } else - msg1 = "You desecrate this place by your presence!"; - } else { - Sprintf(buf, "Pilgrim, you enter a %s place!", - !shrined ? "desecrated" : "sacred"); - msg1 = buf; - } - if (can_speak) { - verbalize(msg1); - if (msg2) verbalize(msg2); - } - if(!sanctum) { - /* !tended -> !shrined */ - if (!shrined || !p_coaligned(priest) || - u.ualign.record <= ALGN_SINNED) - You("have a%s forbidding feeling...", - (!shrined) ? "" : " strange"); - else You("experience a strange sense of peace."); - } + /* don't do anything if hero is already in the room */ + if (temple_occupied(u.urooms0)) return; + + if ((priest = findpriest((char)roomno)) != 0) { + /* tended */ + + epri_p = EPRI(priest); + shrined = has_shrine(priest); + sanctum = (priest->data == &mons[PM_HIGH_PRIEST] && + (Is_sanctum(&u.uz) || In_endgame(&u.uz))); + can_speak = (priest->mcanmove && !priest->msleeping); + if (can_speak && !Deaf && moves >= epri_p->intone_time) { + unsigned save_priest = priest->ispriest; + + /* don't reveal the altar's owner upon temple entry in + the endgame; for the Sanctum, the next message names + Moloch so suppress the "of Moloch" for him here too */ + if (sanctum && !Hallucination) priest->ispriest = 0; + pline("%s intones:", + canseemon(priest) ? Monnam(priest) : "A nearby voice"); + priest->ispriest = save_priest; + epri_p->intone_time = moves + (long)d(10, 500); /* ~2505 */ + /* make sure that we don't suppress entry message when + we've just given its "priest intones" introduction */ + epri_p->enter_time = 0L; + } + msg1 = msg2 = 0; + if (sanctum && Is_sanctum(&u.uz)) { + if (priest->mpeaceful) { + /* first time inside */ + msg1 = "Infidel, you have entered Moloch's Sanctum!"; + msg2 = "Be gone!"; + priest->mpeaceful = 0; + /* became angry voluntarily; no penalty for attacking him */ + set_malign(priest); } else { - switch(rn2(3)) { - case 0: You("have an eerie feeling..."); break; - case 1: You_feel("like you are being watched."); break; - default: pline("A shiver runs down your %s.", - body_part(SPINE)); break; - } - if(!rn2(5)) { - struct monst *mtmp; + /* repeat visit, or attacked priest before entering */ + msg1 = "You desecrate this place by your presence!"; + } + } else if (moves >= epri_p->enter_time) { + Sprintf(buf, "Pilgrim, you enter a %s place!", + !shrined ? "desecrated" : "sacred"); + msg1 = buf; + } + if (msg1 && can_speak && !Deaf) { + verbalize(msg1); + if (msg2) verbalize(msg2); + epri_p->enter_time = moves + (long)d(10, 100); /* ~505 */ + } + if (!sanctum) { + if (!shrined || !p_coaligned(priest) || + u.ualign.record <= ALGN_SINNED) { + msg1 = "have a%s forbidding feeling..."; + msg2 = (!shrined || !p_coaligned(priest)) ? "" : " strange"; + this_time = &epri_p->hostile_time; + other_time = &epri_p->peaceful_time; + } else { + msg1 = "experience %s sense of peace."; + msg2 = (u.ualign.record >= ALGN_PIOUS) ? "a" : "an unusual"; + this_time = &epri_p->peaceful_time; + other_time = &epri_p->hostile_time; + } + /* give message if we haven't seen it recently or + if alignment update has caused it to switch from + forbidding to sense-of-peace or vice versa */ + if (moves >= *this_time || *other_time >= *this_time) { + You(msg1, msg2); + *this_time = moves + (long)d(10, 20); /* ~55 */ + /* avoid being tricked by the RNG: switch might have just + happened and previous random threshold could be larger */ + if (*this_time <= *other_time) *other_time = *this_time - 1L; + } + } + } else { + /* untended */ - if(!(mtmp = makemon(&mons[PM_GHOST],u.ux,u.uy,NO_MM_FLAGS))) - return; - if (!Blind || sensemon(mtmp)) - pline("An enormous ghost appears next to you!"); - else You("sense a presence close by!"); - mtmp->mpeaceful = 0; - set_malign(mtmp); - if(flags.verbose) - You("are frightened to death, and unable to move."); - nomul(-3); - nomovemsg = "You regain your composure."; - } - } - } + switch (rn2(4)) { + case 0: You("have an eerie feeling..."); break; + case 1: You_feel("like you are being watched."); break; + case 2: pline("A shiver runs down your %s.", + body_part(SPINE)); break; + default: break; /* no message; unfortunately there's no + EPRI(priest)->eerie_time available to + make sure we give one the first time */ + } + if (!rn2(5) && + (mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS)) != 0) { + /* [TODO: alter this (at a minimum, by switching from + an exclamation to a simple declaration) if hero has + already killed enough ghosts.] */ + if (canspotmon(mtmp)) + pline("An enormous ghost appears next to you!"); + else + You("sense a presence close by!"); + mtmp->mpeaceful = 0; + set_malign(mtmp); + if (flags.verbose) + You("are frightened to death, and unable to move."); + nomul(-3); + nomovemsg = "You regain your composure."; + } + } +} + +/* reset the move counters used to limit temple entry feedback; + leaving the level and then returning yields a fresh start */ +void +forget_temple_entry(priest) +struct monst *priest; +{ + struct epri *epri_p = priest->ispriest ? EPRI(priest) : 0; + + if (!epri_p) { + impossible("attempting to manipulate shrine data for non-priest?"); + return; + } + epri_p->intone_time = epri_p->enter_time = + epri_p->peaceful_time = epri_p->hostile_time = 0L; } void diff --git a/src/save.c b/src/save.c index d5526f3bd..22a57d278 100644 --- a/src/save.c +++ b/src/save.c @@ -1093,6 +1093,7 @@ register struct monst *mtmp; mtmp2 = mtmp->nmon; if (perform_bwrite(mode)) { mtmp->mnum = monsndx(mtmp->data); + if (mtmp->ispriest) forget_temple_entry(mtmp); /* EPRI() */ #ifndef GOLDOBJ if (mtmp->mgold) { struct obj *goldobj = mksobj(GOLD_PIECE, FALSE, FALSE);