avoid "couldn't place lregion type 5" warning when arriving at Plane of Fire
avoid crash due to delayed poly or were change no longer being valid
ensure that Priest's ability to recognize B/U/C is considered in B/U/C menus
+can't push boulders through iron bars; traps can't roll such through either;
+ likewise for objects thrown by monsters
+thrown objects susceptible to breaking might do so when they hit iron bars
+assorted monsters can pass through iron bars; ditto for polymorphed character
+attempting to dig iron bars will wake nearby monsters instead of yielding
+ "you swing your pick-axe through thin air"
+autodig won't accept iron bars as candidate location
Platform- and/or Interface-Specific Fixes
E boolean FDECL(can_blnd, (struct monst *,struct monst *,UCHAR_P,struct obj *));
E boolean FDECL(ranged_attk, (struct permonst *));
E boolean FDECL(hates_silver, (struct permonst *));
+E boolean FDECL(passes_bars, (struct permonst *));
E boolean FDECL(can_track, (struct permonst *));
E boolean FDECL(breakarm, (struct permonst *));
E boolean FDECL(sliparm, (struct permonst *));
E struct obj *FDECL(m_carrying, (struct monst *,int));
E void FDECL(m_useup, (struct monst *,struct obj *));
E void FDECL(m_throw, (struct monst *,int,int,int,int,int,struct obj *));
+E boolean FDECL(hits_bars, (struct obj **,int,int,int,int));
/* ### muse.c ### */
-/* SCCS Id: @(#)mfndpos.h 3.4 1993/05/15 */
+/* SCCS Id: @(#)mfndpos.h 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
#define ALLOW_ROCK 0x02000000L /* pushes rocks */
#define ALLOW_WALL 0x04000000L /* walks thru walls */
#define ALLOW_DIG 0x08000000L /* digs */
+#define ALLOW_BARS 0x10000000L /* may pass thru iron bars */
#define ALLOW_SANCT 0x20000000L /* enters temples */
#define ALLOW_SSM 0x40000000L /* ignores scare monster */
#ifdef NHSTDC
-/* SCCS Id: @(#)dig.c 3.4 2001/09/06 */
+/* SCCS Id: @(#)dig.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
/* (maybe `move_into_trap()' would be better) */
nomul(-d(2,2));
nomovemsg = "You pull free.";
+ } else if (lev->typ == IRONBARS) {
+ pline("Clang!");
+ wake_nearby();
} else
You("swing your %s through thin air.",
aobjnam(obj, (char *)0));
-/* SCCS Id: @(#)dogmove.c 3.4 2002/03/09 */
+/* SCCS Id: @(#)dogmove.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
if (appr == -2) return(0);
allowflags = ALLOW_M | ALLOW_TRAPS | ALLOW_SSM | ALLOW_SANCT;
- if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK|ALLOW_WALL);
+ if (passes_walls(mtmp->data)) allowflags |= (ALLOW_ROCK | ALLOW_WALL);
+ if (passes_bars(mtmp->data)) allowflags |= ALLOW_BARS;
if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK;
if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
allowflags |= ALLOW_U;
-/* SCCS Id: @(#)hack.c 3.4 2002/03/24 */
+/* SCCS Id: @(#)hack.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
goto cannot_push;
}
if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
+ levl[rx][ry].typ != IRONBARS &&
(!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) || (
#ifdef REINCARNATION
!Is_rogue_level(&u.uz) &&
if (Blind && !test_only) feel_location(x,y);
if (Passes_walls && may_passwall(x,y)) {
; /* do nothing */
+ } else if (tmpr->typ == IRONBARS) {
+ if (!(Passes_walls || passes_bars(youmonst.data)))
+ return FALSE;
} else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
/* Eat the rock. */
if (!test_only && still_chewing(x,y)) return FALSE;
-/* SCCS Id: @(#)mon.c 3.4 2002/03/09 */
+/* SCCS Id: @(#)mon.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
!((flag & ALLOW_WALL) && may_passwall(nx,ny)) &&
!((flag & ALLOW_DIG) && may_dig(nx,ny))) continue;
/* KMH -- Added iron bars */
- if (ntyp == IRONBARS &&
- !((flag & ALLOW_WALL) && may_passwall(nx,ny))) continue;
+ if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
if(IS_DOOR(ntyp) && !amorphous(mdat) &&
((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
(levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))
-/* SCCS Id: @(#)mondata.c 3.4 2002/03/24 */
+/* SCCS Id: @(#)mondata.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
(ptr->mlet==S_IMP && ptr != &mons[PM_TENGU])));
}
+/* true iff the type of monster pass through iron bars */
+boolean
+passes_bars(mptr)
+struct permonst *mptr;
+{
+ return (boolean) (passes_walls(mptr) || amorphous(mptr) ||
+ is_whirly(mptr) || verysmall(mptr) ||
+ (slithy(mptr) && !bigmonst(mptr)));
+}
+
#endif /* OVL0 */
#ifdef OVL1
-/* SCCS Id: @(#)monmove.c 3.4 2000/08/16 */
+/* SCCS Id: @(#)monmove.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
/* unicorn may not be able to avoid hero on a noteleport level */
if (is_unicorn(ptr) && !level.flags.noteleport) flag |= NOTONL;
if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK);
+ if (passes_bars(ptr)) flag |= ALLOW_BARS;
if (can_tunnel) flag |= ALLOW_DIG;
if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
if (is_undead(ptr) && ptr->mlet != S_GHOST) flag |= NOGARLIC;
if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
if (flags.verbose && canseemon(mtmp))
- pline("%s %ss under the door.", Monnam(mtmp),
+ pline("%s %s under the door.", Monnam(mtmp),
(ptr == &mons[PM_FOG_CLOUD] ||
ptr == &mons[PM_YELLOW_LIGHT])
- ? "flow" : "ooze");
+ ? "flows" : "oozes");
} else if(here->doormask & D_LOCKED && can_unlock) {
if(btrapped) {
here->doormask = D_NODOOR;
if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))
add_damage(mtmp->mx, mtmp->my, 0L);
}
+ } else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) {
+ if (flags.verbose && canseemon(mtmp))
+ Norep("%s %s %s the iron bars.", Monnam(mtmp),
+ /* pluralization fakes verb conjugation */
+ makeplural(locomotion(ptr, "pass")),
+ passes_walls(ptr) ? "through" : "between");
}
/* possibly dig */
-/* SCCS Id: @(#)mthrowu.c 3.4 2001/12/10 */
+/* SCCS Id: @(#)mthrowu.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
}
}
+ /* also need to pre-check for bars regardless of direction,
+ but we know that isok() has already been verified;
+ the random chance for small objects hitting bars is
+ skipped when reaching them at point blank range */
+ if ((levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS &&
+ hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) {
+ (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
+ return;
+ }
+
/* Note: drop_throw may destroy singleobj. Since obj must be destroyed
* early to avoid the dagger bug, anyone who modifies this code should
* be careful not to use either one after it's been freed.
|| !isok(bhitpos.x+dx,bhitpos.y+dy)
/* missile hits the wall */
|| IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
+ /* missile might hit iron bars */
+ || (levl[bhitpos.x+dx][bhitpos.y+dy].typ == IRONBARS &&
+ hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(2), 0))
#ifdef SINKS
/* Thrown objects "sink" */
|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
#endif
) {
- (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
+ if (singleobj) /* hits_bars might have destroyed it */
+ (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
break;
}
tmp_at(bhitpos.x, bhitpos.y);
return((struct obj *) 0);
}
+/* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
+boolean
+hits_bars(obj_p, x, y, always_hit, whodidit)
+struct obj **obj_p; /* *obj_p will be set to NULL if object breaks */
+int x, y;
+int always_hit; /* caller can force a hit for items which would fit through */
+int whodidit; /* 1==hero, 0=other, -1==just check whether it'll pass thru */
+{
+ struct obj *otmp = *obj_p;
+ int obj_type = otmp->otyp;
+ boolean hits = always_hit;
+
+ if (!hits)
+ switch (otmp->oclass) {
+ case WEAPON_CLASS:
+ {
+ int oskill = objects[obj_type].oc_skill;
+
+ hits = (oskill != -P_BOW && oskill != -P_CROSSBOW &&
+ oskill != -P_DART && oskill != -P_SHURIKEN &&
+ oskill != P_SPEAR && oskill != P_JAVELIN &&
+ oskill != P_KNIFE); /* but not dagger */
+ break;
+ }
+ case ARMOR_CLASS:
+ hits = (objects[obj_type].oc_armcat != ARM_GLOVES);
+ break;
+ case TOOL_CLASS:
+ hits = (obj_type != SKELETON_KEY &&
+ obj_type != LOCK_PICK &&
+#ifdef TOURIST
+ obj_type != CREDIT_CARD &&
+#endif
+ obj_type != TALLOW_CANDLE &&
+ obj_type != WAX_CANDLE &&
+ obj_type != LENSES &&
+ obj_type != TIN_WHISTLE &&
+ obj_type != MAGIC_WHISTLE);
+ break;
+ case ROCK_CLASS: /* includes boulder */
+ if (obj_type != STATUE ||
+ mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE;
+ break;
+ case FOOD_CLASS:
+ if (obj_type == CORPSE &&
+ mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE;
+ break;
+ case SPBOOK_CLASS:
+ case WAND_CLASS:
+ case BALL_CLASS:
+ case CHAIN_CLASS:
+ hits = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ if (hits && whodidit != -1) {
+ if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y))
+ *obj_p = otmp = 0; /* object is now gone */
+ /* breakage makes its own noises */
+ else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
+ pline("Whang!");
+ else if (otmp->oclass == GOLD_CLASS ||
+ objects[obj_type].oc_material == GOLD ||
+ objects[obj_type].oc_material == SILVER)
+ pline("Clink!");
+ else
+ pline("Clonk!");
+ }
+
+ return hits;
+}
+
#endif /* OVL0 */
/*mthrowu.c*/
-/* SCCS Id: @(#)trap.c 3.4 20021/03/29 */
+/* SCCS Id: @(#)trap.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
levl[bhitpos.x][bhitpos.y].doormask = D_BROKEN;
if (dist) unblock_point(bhitpos.x, bhitpos.y);
}
+
+ /* if about to hit iron bars, do so now */
+ if (dist > 0 && isok(bhitpos.x + dx,bhitpos.y + dy) &&
+ levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS) {
+ x2 = bhitpos.x, y2 = bhitpos.y; /* object stops here */
+ if (hits_bars(&singleobj, x2, y2, !rn2(20), 0)) {
+ if (!singleobj) used_up = TRUE;
+ break;
+ }
+ }
}
tmp_at(DISP_END, 0);
if (!used_up) {
} else
return 2;
}
+
#endif /* OVL3 */
#ifdef OVLB
-/* SCCS Id: @(#)zap.c 3.4 2002/03/29 */
+/* SCCS Id: @(#)zap.c 3.4 2002/04/06 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
STATIC_DCL int FDECL(zhitm, (struct monst *,int,int,struct obj **));
STATIC_DCL void FDECL(zhitu, (int,int,const char *,XCHAR_P,XCHAR_P));
STATIC_DCL void FDECL(revive_egg, (struct obj *));
-STATIC_DCL boolean FDECL(hits_bars, (struct obj *));
#ifdef STEED
STATIC_DCL boolean FDECL(zap_steed, (struct obj *));
#endif
#endif /*OVL0*/
#ifdef OVL1
-/* return TRUE if obj_type can't pass through iron bars */
-static boolean
-hits_bars(obj)
-struct obj *obj;
-{
- int obj_type = obj->otyp;
- /*
- There should be a _lot_ of things here..., but iron ball
- started this change and boulders, chests, and boxes were added later...
- Corpses and statues that are at least medium size are also screened.
- */
- if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL || obj_type == LARGE_BOX ||
- obj_type == CHEST || obj_type == ICE_BOX ||
- ((obj_type == CORPSE || obj_type == STATUE)
- && mons[obj->corpsenm].msize >= MZ_MEDIUM))
- return TRUE;
- return FALSE;
-}
-
/*
* Called for the following distance effects:
* when a weapon is thrown (weapon == THROWN_WEAPON)
FDECL((*fhito), (OBJ_P, OBJ_P));
struct obj *obj; /* object tossed/used */
{
- register struct monst *mtmp;
- register uchar typ;
- register boolean shopdoor = FALSE;
+ struct monst *mtmp;
+ uchar typ;
+ boolean shopdoor = FALSE;
if (weapon == KICKED_WEAPON) {
/* object starts one square in front of player */
typ = levl[bhitpos.x][bhitpos.y].typ;
/* iron bars will block anything big enough */
- if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
- && typ == IRONBARS && hits_bars(obj)) {
+ if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) &&
+ typ == IRONBARS &&
+ hits_bars(&obj, x - ddx, y - ddy, !rn2(20), 1)) {
+ /* caveat: obj might now be null... */
bhitpos.x -= ddx;
bhitpos.y -= ddy;
break;
if(bhitpile(obj,fhito,bhitpos.x,bhitpos.y))
range--;
} else {
-boolean costly = shop_keeper(*in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) &&
- costly_spot(bhitpos.x, bhitpos.y);
-
if(weapon == KICKED_WEAPON &&
((obj->oclass == GOLD_CLASS &&
OBJ_AT(bhitpos.x, bhitpos.y)) ||
- ship_object(obj, bhitpos.x, bhitpos.y, costly))) {
+ ship_object(obj, bhitpos.x, bhitpos.y,
+ costly_spot(bhitpos.x, bhitpos.y)))) {
tmp_at(DISP_END, 0);
return (struct monst *)0;
}