diff --git a/include/engrave.h b/include/engrave.h index 6af923860..c09cc5eaa 100644 --- a/include/engrave.h +++ b/include/engrave.h @@ -20,10 +20,15 @@ struct engr { #define ENGR_BLOOD 5 #define HEADSTONE 6 #define N_ENGRAVE 6 + Bitfield(guardobjects, 1); /* if engr_txt is "Elbereth", it is effective + * against monsters when an object is present + * even when hero isn't (so behaves similarly + * to how Elbereth did in 3.4.3) */ + /* 7 free bits */ }; #define newengr(lth) \ - (struct engr *) alloc((unsigned)(lth) + sizeof(struct engr)) -#define dealloc_engr(engr) free((genericptr_t)(engr)) + (struct engr *) alloc((unsigned) (lth) + (unsigned) sizeof (struct engr)) +#define dealloc_engr(engr) free((genericptr_t) (engr)) #endif /* ENGRAVE_H */ diff --git a/include/extern.h b/include/extern.h index 815bf6a4e..d36dcad82 100644 --- a/include/extern.h +++ b/include/extern.h @@ -809,7 +809,7 @@ extern void cant_reach_floor(coordxy, coordxy, boolean, boolean); extern const char *surface(coordxy, coordxy); extern const char *ceiling(coordxy, coordxy); extern struct engr *engr_at(coordxy, coordxy); -extern boolean sengr_at(const char *, coordxy, coordxy, boolean); +extern struct engr *sengr_at(const char *, coordxy, coordxy, boolean); extern void u_wipe_engr(int); extern void wipe_engr_at(coordxy, coordxy, xint16, boolean); extern void read_engr_at(coordxy, coordxy); diff --git a/src/engrave.c b/src/engrave.c index a7dd57fb2..cae185878 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -271,16 +271,17 @@ engr_at(coordxy x, coordxy y) * If strict checking is requested, the word is only considered to be * present if it is intact and is the entire content of the engraving. */ -boolean +struct engr * sengr_at(const char *s, coordxy x, coordxy y, boolean strict) { - register struct engr *ep = engr_at(x, y); + struct engr *ep = engr_at(x, y); if (ep && ep->engr_type != HEADSTONE && ep->engr_time <= g.moves) { - return (strict ? !strcmpi(ep->engr_txt, s) - : (strstri(ep->engr_txt, s) != 0)); + if (strict ? !strcmpi(ep->engr_txt, s) + : (strstri(ep->engr_txt, s) != 0)) + return ep; } - return FALSE; + return (struct engr *) NULL; } void @@ -395,16 +396,22 @@ make_engr_at(coordxy x, coordxy y, const char *s, long e_time, xint16 e_type) if ((ep = engr_at(x, y)) != 0) del_engr(ep); ep = newengr(smem); - (void) memset((genericptr_t)ep, 0, smem + sizeof(struct engr)); + (void) memset((genericptr_t) ep, 0, smem + sizeof (struct engr)); ep->nxt_engr = head_engr; head_engr = ep; ep->engr_x = x; ep->engr_y = y; ep->engr_txt = (char *) (ep + 1); Strcpy(ep->engr_txt, s); - /* engraving Elbereth shows wisdom */ - if (!g.in_mklev && !strcmp(s, "Elbereth")) - exercise(A_WIS, TRUE); + if (!strcmp(s, "Elbereth")) { + /* engraving "Elbereth": if done when making a level, it creates + an old-style Elbereth that deters monsters when any objects are + present; otherwise (done by the player), exercises wisdom */ + if (g.in_mklev) + ep->guardobjects = 1; + else + exercise(A_WIS, TRUE); + } ep->engr_time = e_time; ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE - 1); ep->engr_lth = smem; diff --git a/src/monmove.c b/src/monmove.c index 51e91cc5e..c1398cd0f 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -167,8 +167,10 @@ dochugw( } boolean -onscary(coordxy x, coordxy y, struct monst* mtmp) +onscary(coordxy x, coordxy y, struct monst *mtmp) { + struct engr *ep; + /* creatures who are directly resistant to magical scaring: * humans aren't monsters * uniques have ascended their base monster instincts @@ -208,15 +210,16 @@ onscary(coordxy x, coordxy y, struct monst* mtmp) * Elbereth doesn't work in Gehennom, the Elemental Planes, or the * Astral Plane; the influence of the Valar only reaches so far. */ - return (sengr_at("Elbereth", x, y, TRUE) - && (u_at(x, y) || (Displaced && mtmp->mux == x && mtmp->muy == y)) + return ((ep = sengr_at("Elbereth", x, y, TRUE)) != 0 + && (u_at(x, y) + || (Displaced && mtmp->mux == x && mtmp->muy == y) + || (ep->guardobjects && vobj_at(x, y))) && !(mtmp->isshk || mtmp->isgd || !mtmp->mcansee || mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN || mtmp->data == &mons[PM_MINOTAUR] || Inhell || In_endgame(&u.uz))); } - /* regenerate lost hit points */ void mon_regen(struct monst *mon, boolean digest_meal) diff --git a/src/teleport.c b/src/teleport.c index 8df35115f..97b34b318 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -40,7 +40,8 @@ noteleport_level(struct monst* mon) } /* this is an approximation of onscary() that doesn't use any 'struct monst' - fields aside from 'monst->data' */ + fields aside from 'monst->data'; used primarily for new monster creation + and monster teleport destination, not for ordinary monster movement */ static boolean goodpos_onscary( coordxy x, coordxy y, @@ -60,10 +61,11 @@ goodpos_onscary( /* engraved Elbereth doesn't work in Gehennom or the end-game */ if (Inhell || In_endgame(&u.uz)) return FALSE; - /* creatures who don't (or can't) fear a written Elbereth */ + /* creatures who don't (or can't) fear a written Elbereth and weren't + caught by the minions check */ if (mptr == &mons[PM_MINOTAUR] || !haseyes(mptr)) return FALSE; - return sengr_at("Elbereth", x, y, TRUE); + return sengr_at("Elbereth", x, y, TRUE) ? TRUE : FALSE; } /*