From: nethack.rankin Date: Sun, 7 Apr 2002 10:43:59 +0000 (+0000) Subject: multiple iron bars fixes X-Git-Tag: MOVE2GIT~2806 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=812b53799de2c8de486beaa7cf54926305d16a71;p=nethack 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. --- diff --git a/doc/fixes34.1 b/doc/fixes34.1 index 1353c2b3b..954c35fb2 100644 --- a/doc/fixes34.1 +++ b/doc/fixes34.1 @@ -55,6 +55,13 @@ reduce insect/monster creation from monster spells 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 diff --git a/include/extern.h b/include/extern.h index 3dba1c021..57094c4d0 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1128,6 +1128,7 @@ E boolean FDECL(resists_blnd, (struct monst *)); 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 *)); @@ -1240,6 +1241,7 @@ E boolean FDECL(lined_up, (struct monst *)); 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 ### */ diff --git a/include/mfndpos.h b/include/mfndpos.h index 96c5dd5e7..01a4bb580 100644 --- a/include/mfndpos.h +++ b/include/mfndpos.h @@ -1,4 +1,4 @@ -/* 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. */ @@ -17,6 +17,7 @@ #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 diff --git a/src/dig.c b/src/dig.c index d9aa5e5ea..b9ea46f7c 100644 --- a/src/dig.c +++ b/src/dig.c @@ -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)); diff --git a/src/dogmove.c b/src/dogmove.c index 0a78bb03a..23d57573d 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -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; diff --git a/src/hack.c b/src/hack.c index a7d25e41b..ac84a9439 100644 --- a/src/hack.c +++ b/src/hack.c @@ -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; diff --git a/src/mon.c b/src/mon.c index 4d8c64b16..9b06912bf 100644 --- a/src/mon.c +++ b/src/mon.c @@ -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)) diff --git a/src/mondata.c b/src/mondata.c index a51722c99..3a9cdb03c 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -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 diff --git a/src/monmove.c b/src/monmove.c index 1e3bad4d2..3424b7304 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -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 */ diff --git a/src/mthrowu.c b/src/mthrowu.c index a397191cb..b4e2aec75 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -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*/ diff --git a/src/trap.c b/src/trap.c index cd3aadba4..415251345 100644 --- a/src/trap.c +++ b/src/trap.c @@ -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 diff --git a/src/zap.c b/src/zap.c index 87a104e24..cc3bf4219 100644 --- a/src/zap.c +++ b/src/zap.c @@ -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; }