diff --git a/dat/castle.des b/dat/castle.des index 6a6bcab44..f6252667e 100644 --- a/dat/castle.des +++ b/dat/castle.des @@ -1,5 +1,4 @@ -# NetHack 3.6 castle.des $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ -# NetHack 3.6 castle.des $Date: 2009/05/06 10:44:18 $ $Revision: 1.5 $ +# NetHack 3.6 castle.des $NHDT-Date: 1430348677 2015/04/29 23:04:37 $ $NHDT-Branch: derek-elbereth $:$NHDT-Revision: 1.8 $ # SCCS Id: @(#)castle.des 3.5 2002/05/02 # Copyright (c) 1989 by Jean-Christophe Collet # NetHack may be freely redistributed. See license for details. @@ -143,6 +142,7 @@ OBJECT:('/',"wishing") } # Prevent monsters from eating it. (@'s never eat objects) ENGRAVING:$place[0],burn,"Elbereth" +OBJECT:('?',"scare monster"),$place[0],cursed # The treasure of the lord OBJECT:('(',"chest"),(37,08) # Traps diff --git a/dat/sokoban.des b/dat/sokoban.des index 84a3a783f..30ad5a632 100644 --- a/dat/sokoban.des +++ b/dat/sokoban.des @@ -1,5 +1,4 @@ -# NetHack 3.6 sokoban.des $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ -# NetHack 3.6 sokoban.des $Date: 2009/05/06 10:44:24 $ $Revision: 1.5 $ +# NetHack 3.6 sokoban.des $NHDT-Date: 1430348694 2015/04/29 23:04:54 $ $NHDT-Branch: derek-elbereth $:$NHDT-Revision: 1.11 $ # SCCS Id: @(#)sokoban.des 3.5 1999/03/15 # Copyright (c) 1998-1999 by Kevin Hugo # NetHack may be freely redistributed. See license for details. @@ -535,6 +534,7 @@ IF [50%] { OBJECT:('"',"amulet of reflection"),$place[0] } ENGRAVING:$place[0],burn,"Elbereth" +OBJECT:('?', "scare monster"),$place[0],cursed MAZE:"soko1-2",' ' @@ -635,3 +635,4 @@ IF [50%] { OBJECT:('"',"amulet of reflection"),$place[0] } ENGRAVING:$place[0],burn,"Elbereth" +OBJECT:('?', "scare monster"),$place[0],cursed diff --git a/include/extern.h b/include/extern.h index bc741bc57..1b6bb6fcf 100644 --- a/include/extern.h +++ b/include/extern.h @@ -655,9 +655,9 @@ E void FDECL(cant_reach_floor, (int,int,BOOLEAN_P,BOOLEAN_P)); E const char *FDECL(surface, (int,int)); E const char *FDECL(ceiling, (int,int)); E struct engr *FDECL(engr_at, (XCHAR_P,XCHAR_P)); -E int FDECL(sengr_at, (const char *,XCHAR_P,XCHAR_P)); +E int FDECL(sengr_at, (const char *,XCHAR_P,XCHAR_P,BOOLEAN_P)); E void FDECL(u_wipe_engr, (int)); -E void FDECL(wipe_engr_at, (XCHAR_P,XCHAR_P,XCHAR_P)); +E void FDECL(wipe_engr_at, (XCHAR_P,XCHAR_P,XCHAR_P,BOOLEAN_P)); E void FDECL(read_engr_at, (int,int)); E void FDECL(make_engr_at, (int,int,const char *,long,XCHAR_P)); E void FDECL(del_engr_at, (int,int)); diff --git a/src/engrave.c b/src/engrave.c index 71ec13882..938cff1e5 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -219,16 +219,24 @@ xchar x, y; /* Decide whether a particular string is engraved at a specified * location; a case-insensitive substring match used. * Ignore headstones, in case the player names herself "Elbereth". + * + * If strict checking is requested, the word is only considered to be + * present if it is intact and is the first word in the engraving. + * ("Elbereth burrito" matches; "o Elbereth" does not.) */ int -sengr_at(s, x, y) +sengr_at(s, x, y, strict) const char *s; xchar x, y; + boolean strict; { register struct engr *ep = engr_at(x,y); - return (ep && ep->engr_type != HEADSTONE && - ep->engr_time <= moves && strstri(ep->engr_txt, s) != 0); + if (ep && ep->engr_type != HEADSTONE && ep->engr_time <= moves) { + return strict ? (strncmpi(ep->engr_txt, s, strlen(s)) == 0) : + (strstri(ep->engr_txt, s) != 0); + } + return FALSE; } void @@ -236,27 +244,29 @@ u_wipe_engr(cnt) register int cnt; { if (can_reach_floor(TRUE)) - wipe_engr_at(u.ux, u.uy, cnt); + wipe_engr_at(u.ux, u.uy, cnt, FALSE); } void -wipe_engr_at(x,y,cnt) -register xchar x,y,cnt; +wipe_engr_at(x,y,cnt,magical) +register xchar x,y,cnt,magical; { - register struct engr *ep = engr_at(x,y); + register struct engr *ep = engr_at(x,y); - /* Headstones are indelible */ - if(ep && ep->engr_type != HEADSTONE){ - if(ep->engr_type != BURN || is_ice(x,y)) { - if(ep->engr_type != DUST && ep->engr_type != ENGR_BLOOD) { - cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; - } - wipeout_text(ep->engr_txt, (int)cnt, 0); - while(ep->engr_txt[0] == ' ') - ep->engr_txt++; - if(!ep->engr_txt[0]) del_engr(ep); - } - } + /* Headstones are indelible */ + if(ep && ep->engr_type != HEADSTONE) { + debugpline1("asked to erode %d characters", cnt); + if(ep->engr_type != BURN || is_ice(x,y) || (magical && !rn2(2))) { + if(ep->engr_type != DUST && ep->engr_type != ENGR_BLOOD) { + cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; + debugpline1("actually eroding %d characters", cnt); + } + wipeout_text(ep->engr_txt, (int)cnt, 0); + while(ep->engr_txt[0] == ' ') + ep->engr_txt++; + if(!ep->engr_txt[0]) del_engr(ep); + } + } } void diff --git a/src/mklev.c b/src/mklev.c index 059c7a328..1ecf46f67 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -1,5 +1,4 @@ -/* NetHack 3.6 mklev.c $NHDT-Date: 1426465436 2015/03/16 00:23:56 $ $NHDT-Branch: debug $:$NHDT-Revision: 1.25 $ */ -/* NetHack 3.6 mklev.c $Date: 2012/02/15 01:55:33 $ $Revision: 1.20 $ */ +/* NetHack 3.6 mklev.c $NHDT-Date: 1430172946 2015/04/27 22:15:46 $ $NHDT-Branch: derek-elbereth $:$NHDT-Revision: 1.38 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -495,7 +494,7 @@ int trap_type; if (trap_engravings[trap_type]) { make_engr_at(xx, yy-dy, trap_engravings[trap_type], 0L, DUST); - wipe_engr_at(xx, yy-dy, 5); /* age it a little */ + wipe_engr_at(xx, yy-dy, 5, FALSE); /* age it a little */ } } } diff --git a/src/monmove.c b/src/monmove.c index 9e293277d..633e66e21 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1,5 +1,4 @@ -/* NetHack 3.6 monmove.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */ -/* NetHack 3.6 monmove.c $Date: 2011/08/30 22:13:27 $ $Revision: 1.46 $ */ +/* NetHack 3.6 monmove.c $NHDT-Date: 1430172947 2015/04/27 22:15:47 $ $NHDT-Branch: derek-elbereth $:$NHDT-Revision: 1.62 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -123,17 +122,42 @@ onscary(x, y, mtmp) int x, y; struct monst *mtmp; { - if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee || - mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN || - is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL] || - is_rider(mtmp->data) || mtmp->data == &mons[PM_MINOTAUR]) - return(FALSE); + boolean epresent = sengr_at("Elbereth", x, y, TRUE); + + /* creatures who are directly resistant to magical scaring: + * Rodney, lawful minions, angels, the Riders + */ + if (mtmp->iswiz || is_lminion(mtmp) + || mtmp->data == &mons[PM_ANGEL] + || is_rider(mtmp->data)) + return(FALSE); - return (boolean)(sobj_at(SCR_SCARE_MONSTER, x, y) || - sengr_at("Elbereth", x, y) || - (IS_ALTAR(levl[x][y].typ) && - (mtmp->data->mlet == S_VAMPIRE || - is_vampshifter(mtmp)))); + /* creatures who don't (or can't) fear a written Elbereth: + * all the above plus shopkeepers, guards, blind or + * peaceful monsters, humans, and minotaurs. + * + * Elbereth doesn't work in Gehennom, the Elemental Planes, or the + * Astral Plane; the influence of the Valar only reaches so far. + */ + if (epresent && (mtmp->isshk || mtmp->isgd || !mtmp->mcansee + || mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN + || mtmp->data == &mons[PM_MINOTAUR] + || Inhell || In_endgame(&u.uz))) + return(FALSE); + + /* should this still be true for defiled/molochian altars? */ + if (IS_ALTAR(levl[x][y].typ) && (mtmp->data->mlet == S_VAMPIRE + || is_vampshifter(mtmp))) + return(TRUE); + + /* if the player isn't actually on the square OR the player's image + * isn't displaced to the square, no protection is being granted + * + * the scare monster scroll, though, is quite powerful. + */ + return (boolean)(sobj_at(SCR_SCARE_MONSTER, x, y) + || (epresent && ((u.ux == x && u.uy == y) + || (Displaced && mtmp->mux == x && mtmp->muy == y)))); } /* regenerate lost hit points */ @@ -254,6 +278,7 @@ register struct monst *mtmp; int *inrange, *nearby, *scared; { int seescaryx, seescaryy; + boolean sawscary = FALSE; *inrange = (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= (BOLT_LIM * BOLT_LIM)); @@ -273,11 +298,18 @@ int *inrange, *nearby, *scared; seescaryx = u.ux; seescaryy = u.uy; } - if (*nearby && - (onscary(seescaryx, seescaryy, mtmp) || - (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))) { + + sawscary = onscary(seescaryx, seescaryy, mtmp); + if (*nearby && (sawscary || (!mtmp->mpeaceful + && in_your_sanctuary(mtmp, 0, 0)))) { *scared = 1; monflee(mtmp, rnd(rn2(7) ? 10 : 100), TRUE, TRUE); + + /* magical protection won't last forever, so there'll be a + * chance of the magic being used up regardless of type */ + if (sawscary) { + wipe_engr_at(seescaryx, seescaryy, 1, TRUE); + } } else *scared = 0; } @@ -337,7 +369,7 @@ register struct monst *mtmp; } /* not frozen or sleeping: wipe out texts written in the dust */ - wipe_engr_at(mtmp->mx, mtmp->my, 1); + wipe_engr_at(mtmp->mx, mtmp->my, 1, FALSE); /* confused monsters get unconfused with small probability */ if (mtmp->mconf && !rn2(50)) mtmp->mconf = 0; diff --git a/src/zap.c b/src/zap.c index fb41561ac..67cb4fa14 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,5 +1,4 @@ /* NetHack 3.6 zap.c $NHDT-Date: 1430355196 2015/04/30 00:53:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.218 $ */ -/* NetHack 3.6 zap.c $Date: 2013/11/05 00:57:56 $ $Revision: 1.183 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2720,12 +2719,12 @@ struct obj *obj; /* wand or spell */ pline_The(Hallucination ? "floor runs like butter!" : "edges on the floor get smoother."); - wipe_engr_at(x, y, d(2,4)); + wipe_engr_at(x, y, d(2,4), TRUE); } break; case WAN_STRIKING: case SPE_FORCE_BOLT: - wipe_engr_at(x, y, d(2,4)); + wipe_engr_at(x, y, d(2,4), TRUE); break; default: break;