multiple iron bars fixes

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.
This commit is contained in:
nethack.rankin
2002-04-07 10:43:59 +00:00
parent b940ca0ee7
commit 812b53799d
12 changed files with 158 additions and 45 deletions

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -874,6 +874,9 @@ struct obj *obj;
/* (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));

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -543,7 +543,8 @@ register int after; /* this is extra fast monster movement */
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;

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -89,6 +89,7 @@ moverock()
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) &&
@@ -543,6 +544,9 @@ boolean test_only;
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;

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -963,8 +963,7 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
!((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))

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -247,6 +247,16 @@ register struct permonst *ptr;
(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

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -890,6 +890,7 @@ not_special:
/* 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;
@@ -1048,10 +1049,10 @@ postmov:
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;
@@ -1110,6 +1111,12 @@ postmov:
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 */

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -312,6 +312,16 @@ m_throw(mon, x, y, dx, dy, range, obj)
}
}
/* 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.
@@ -437,12 +447,16 @@ m_throw(mon, x, y, dx, dy, range, obj)
|| !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);
@@ -747,6 +761,80 @@ int type;
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*/

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -1330,6 +1330,16 @@ int style;
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) {
@@ -1340,6 +1350,7 @@ int style;
} else
return 2;
}
#endif /* OVL3 */
#ifdef OVLB

View File

@@ -1,4 +1,4 @@
/* 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. */
@@ -28,7 +28,6 @@ STATIC_DCL boolean FDECL(zap_updown, (struct obj *));
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
@@ -2550,25 +2549,6 @@ register struct monst *mtmp;
#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)
@@ -2595,9 +2575,9 @@ int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
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 */
@@ -2636,8 +2616,10 @@ struct obj *obj; /* object tossed/used */
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;
@@ -2714,13 +2696,11 @@ struct obj *obj; /* object tossed/used */
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;
}