From a21ddbb2bfdeb872c17c386c266a7fe7c365f77d Mon Sep 17 00:00:00 2001 From: cohrs Date: Mon, 15 Jul 2002 04:17:13 +0000 Subject: [PATCH] minetown guards outside the town proper Pat forwarded a message from the newsgroup in March that the town guards enforce rules even outside the town proper. Fix: On room-based town levels, check if the location is in a room containing subrooms (roomno will often have a subroom id instead). On the other levels (e.g. minetn-5), there are no subrooms, so the whole level is fair game. Currently, this is valid. If fancier towns are added in the future, more flags or use of regions may be required to tell where the town border actually is. These checks are done in a new in_town function. --- doc/fixes34.1 | 1 + include/extern.h | 1 + src/dig.c | 3 +-- src/dokick.c | 5 ++--- src/fountain.c | 9 +++------ src/hack.c | 25 +++++++++++++++++++++++++ src/monmove.c | 3 +-- 7 files changed, 34 insertions(+), 13 deletions(-) diff --git a/doc/fixes34.1 b/doc/fixes34.1 index 9da922c11..9310cbe68 100644 --- a/doc/fixes34.1 +++ b/doc/fixes34.1 @@ -166,6 +166,7 @@ in some situations, if hero stood still, a hostile dwarf would switch back uncontrolled teleports did not handle leashed pets minetown fountain warnings shouldn't prevent finding gems/coins in fountain order of container and objects was different for mazelike and roomfilled levels +minetown guards only enforce town rules inside the town proper Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 1e290ae02..1b6cec7be 100644 --- a/include/extern.h +++ b/include/extern.h @@ -669,6 +669,7 @@ E void NDECL(domove); E void NDECL(invocation_message); E void FDECL(spoteffects, (BOOLEAN_P)); E char *FDECL(in_rooms, (XCHAR_P,XCHAR_P,int)); +E boolean FDECL(in_town, (int,int)); E void FDECL(check_special_room, (BOOLEAN_P)); E int NDECL(dopickup); E void NDECL(lookaround); diff --git a/src/dig.c b/src/dig.c index fc74204c3..e7659ecee 100644 --- a/src/dig.c +++ b/src/dig.c @@ -1006,10 +1006,9 @@ watch_dig(mtmp, x, y, zap) xchar x, y; boolean zap; { - s_level *slev = Is_special(&u.uz); struct rm *lev = &levl[x][y]; - if (slev && slev->flags.town && + if (in_town(x, y) && (closed_door(x, y) || lev->typ == SDOOR || IS_WALL(lev->typ) || IS_FOUNTAIN(lev->typ))) { if (!mtmp) { diff --git a/src/dokick.c b/src/dokick.c index 52296f51d..969baf855 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -591,7 +591,6 @@ dokick() register int x, y; int avrg_attrib; register struct monst *mtmp; - s_level *slev; boolean no_kick = FALSE; char buf[BUFSZ]; @@ -1016,7 +1015,7 @@ dumb: add_damage(x, y, 400L); pay_for_damage("break"); } - if ((slev = Is_special(&u.uz)) && slev->flags.town) + if (in_town(x, y)) for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; if((mtmp->data == &mons[PM_WATCHMAN] || @@ -1036,7 +1035,7 @@ dumb: if (Blind) feel_location(x,y); /* we know we hit it */ exercise(A_STR, TRUE); pline("WHAMMM!!!"); - if ((slev = Is_special(&u.uz)) && slev->flags.town) + if (in_town(x, y)) for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; if ((mtmp->data == &mons[PM_WATCHMAN] || diff --git a/src/fountain.c b/src/fountain.c index 69133de83..5bec5c4f0 100644 --- a/src/fountain.c +++ b/src/fountain.c @@ -152,9 +152,7 @@ boolean isyou; { if (IS_FOUNTAIN(levl[x][y].typ) && (!rn2(3) || FOUNTAIN_IS_WARNED(x,y))) { - s_level *slev = Is_special(&u.uz); - if(isyou && slev && slev->flags.town && - !FOUNTAIN_IS_WARNED(x,y)) { + if(isyou && in_town(x, y) && !FOUNTAIN_IS_WARNED(x,y)) { struct monst *mtmp; SET_FOUNTAIN_WARNED(x,y); /* Warn about future fountain use. */ @@ -188,7 +186,7 @@ boolean isyou; /* or felt if the hero is blind. */ newsym(x, y); level.flags.nfountains--; - if(isyou && slev && slev->flags.town) + if(isyou && in_town(x, y)) (void) angry_guards(FALSE); } } @@ -362,7 +360,6 @@ register struct obj *obj; && u.ulevel >= 5 && !rn2(6) && !obj->oartifact && !exist_artifact(LONG_SWORD, artiname(ART_EXCALIBUR))) { - s_level *slev = Is_special(&u.uz); if (u.ualign.type != A_LAWFUL) { /* Ha! Trying to cheat her. */ @@ -389,7 +386,7 @@ register struct obj *obj; levl[u.ux][u.uy].looted = 0; if(Invisible) newsym(u.ux, u.uy); level.flags.nfountains--; - if(slev && slev->flags.town) + if(in_town(u.ux, u.uy)) (void) angry_guards(FALSE); return; } else (void) get_wet(obj); diff --git a/src/hack.c b/src/hack.c index 136df1477..56a407ece 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1576,6 +1576,31 @@ register int typewanted; return(ptr); } +/* is (x,y) in a town? */ +boolean +in_town(x, y) +register int x, y; +{ + s_level *slev = Is_special(&u.uz); + register struct mkroom *sroom; + boolean has_subrooms = FALSE; + + if (!slev || !slev->flags.town) return FALSE; + + /* + * See if (x,y) is in a room with subrooms, if so, assume it's the + * town. If there are no subrooms, the whole level is in town. + */ + for (sroom = &rooms[0]; sroom->hx > 0; sroom++) { + if (sroom->nsubrooms > 0) { + has_subrooms = TRUE; + if (inside_room(sroom, x, y)) return TRUE; + } + } + + return !has_subrooms; +} + STATIC_OVL void move_update(newlev) register boolean newlev; diff --git a/src/monmove.c b/src/monmove.c index 44595171c..3c30c64d0 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -48,10 +48,9 @@ STATIC_OVL void watch_on_duty(mtmp) register struct monst *mtmp; { - register s_level *slev = Is_special(&u.uz); int x, y; - if(slev && slev->flags.town && mtmp->mpeaceful && + if(mtmp->mpeaceful && in_town(u.ux+u.dx, u.uy+u.dy) && mtmp->mcansee && m_canseeu(mtmp) && !rn2(3)) { if(picking_lock(&x, &y) && IS_DOOR(levl[x][y].typ) && -- 2.40.0