This patch adds a new "Held" status flag for the bottom line, which kicks in when you get grabbed by a kraken, owlbear, large mimic, or whatever. I vote it "Most Likely To Prevent A Late Game YASD" from among my patches. This patch was built on patchable Nethack, so you have to apply that patch first. It's at http://www.argon.org/~roderick/nethack/#patchable. Bones/save compatibility: This patch doesn't affect saved games or bones files. This patch is available at http://www.argon.org/~roderick/nethack/. Roderick Schertler diff -r -X /home/roderick/.diff-exclude -uN base.patchable/include/hack.h work.botl-held/include/hack.h --- base.patchable/include/hack.h 2003-02-23 09:43:20.000000000 -0500 +++ work.botl-held/include/hack.h 2003-03-18 17:08:58.000000000 -0500 @@ -279,6 +279,7 @@ #define makeknown(x) discover_object((x),TRUE,TRUE) #define distu(xx,yy) dist2((int)(xx),(int)(yy),(int)u.ux,(int)u.uy) #define onlineu(xx,yy) online2((int)(xx),(int)(yy),(int)u.ux,(int)u.uy) +#define setustuck(v) (flags.botl = 1, u.ustuck = (v)) #define rn1(x,y) (rn2(x)+(y)) diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/apply.c work.botl-held/src/apply.c --- base.patchable/src/apply.c 2003-02-23 09:43:24.000000000 -0500 +++ work.botl-held/src/apply.c 2003-03-18 17:08:58.000000000 -0500 @@ -1221,7 +1221,7 @@ } else if (u.ustuck) { if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf) { You("pull free from %s.", mon_nam(u.ustuck)); - u.ustuck = 0; + setustuck(0); return 1; } if (magic) { diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/artifact.c work.botl-held/src/artifact.c --- base.patchable/src/artifact.c 2003-02-23 09:43:24.000000000 -0500 +++ work.botl-held/src/artifact.c 2003-03-18 17:08:58.000000000 -0500 @@ -855,7 +855,7 @@ nomul(-3); nomovemsg = ""; if (magr && magr == u.ustuck && sticks(youmonst.data)) { - u.ustuck = (struct monst *)0; + setustuck((struct monst *)0); You("release %s!", mon_nam(magr)); } } diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/botl.c work.botl-held/src/botl.c --- base.patchable/src/botl.c 2003-02-23 09:43:25.000000000 -0500 +++ work.botl-held/src/botl.c 2003-03-18 17:08:58.000000000 -0500 @@ -25,11 +25,12 @@ * * longest practical second status line at the moment is * Astral Plane $:12345 HP:700(700) Pw:111(111) AC:-127 Xp:30/123456789 - * T:123456 Satiated Conf FoodPois Ill Blind Stun Hallu Overloaded - * -- or somewhat over 130 characters + * T:123456 Satiated Conf FoodPois Ill Blind Stun Hallu Slime + * Held Overloaded + * -- or somewhat over 140 characters */ -#if COLNO <= 140 -#define MAXCO 160 +#if COLNO <= 150 +#define MAXCO 170 #else #define MAXCO (COLNO+20) #endif @@ -290,6 +291,8 @@ if(Stunned) Sprintf(nb = eos(nb), " Stun"); if(Hallucination) Sprintf(nb = eos(nb), " Hallu"); if(Slimed) Sprintf(nb = eos(nb), " Slime"); + if(u.ustuck && !u.uswallow) + Sprintf(nb = eos(nb), " Held"); if(cap > UNENCUMBERED) Sprintf(nb = eos(nb), " %s", enc_stat[cap]); curs(WIN_STATUS, 1, 1); diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/do.c work.botl-held/src/do.c --- base.patchable/src/do.c 2003-02-23 09:43:25.000000000 -0500 +++ work.botl-held/src/do.c 2003-03-18 17:08:58.000000000 -0500 @@ -1010,7 +1010,7 @@ if (Punished) unplacebc(); u.utrap = 0; /* needed in level_tele */ fill_pit(u.ux, u.uy); - u.ustuck = 0; /* idem */ + setustuck(0); /* idem */ u.uinwater = 0; u.uundetected = 0; /* not hidden, even if means are available */ keepdogs(FALSE); diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/hack.c work.botl-held/src/hack.c --- base.patchable/src/hack.c 2003-02-23 09:43:27.000000000 -0500 +++ work.botl-held/src/hack.c 2003-03-18 17:08:58.000000000 -0500 @@ -945,13 +945,13 @@ if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) { if (distu(u.ustuck->mx, u.ustuck->my) > 2) { /* perhaps it fled (or was teleported or ... ) */ - u.ustuck = 0; + setustuck(0); } else if (sticks(youmonst.data)) { /* When polymorphed into a sticking monster, * u.ustuck means it's stuck to you, not you to it. */ You("release %s.", mon_nam(u.ustuck)); - u.ustuck = 0; + setustuck(0); } else { /* If holder is asleep or paralyzed: * 37.5% chance of getting away, @@ -966,7 +966,7 @@ case 0: case 1: case 2: pull_free: You("pull free from %s.", mon_nam(u.ustuck)); - u.ustuck = 0; + setustuck(0); break; case 3: if (!u.ustuck->mcanmove) { diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/mhitm.c work.botl-held/src/mhitm.c --- base.patchable/src/mhitm.c 2003-02-23 09:43:27.000000000 -0500 +++ work.botl-held/src/mhitm.c 2003-03-18 17:08:58.000000000 -0500 @@ -133,7 +133,7 @@ if(!u.uswallow && (mtmp == u.ustuck)) { if(!rn2(4)) { pline("%s releases you!", Monnam(mtmp)); - u.ustuck = 0; + setustuck(0); } else break; } diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/mhitu.c work.botl-held/src/mhitu.c --- base.patchable/src/mhitu.c 2003-02-23 09:43:27.000000000 -0500 +++ work.botl-held/src/mhitu.c 2003-03-18 17:08:58.000000000 -0500 @@ -431,7 +431,7 @@ if (!youseeit) pline("It gets stuck on you."); else pline("Wait, %s! That's a %s named %s!", m_monnam(mtmp), youmonst.data->mname, plname); - u.ustuck = mtmp; + setustuck(mtmp); youmonst.m_ap_type = M_AP_NOTHING; youmonst.mappearance = 0; newsym(u.ux,u.uy); @@ -899,7 +899,7 @@ if (u_slip_free(mtmp, mattk)) { dmg = 0; } else { - u.ustuck = mtmp; + setustuck(mtmp); pline("%s grabs you!", Monnam(mtmp)); } } else if(u.ustuck == mtmp) { @@ -1182,7 +1182,7 @@ case AD_STCK: hitmsg(mtmp, mattk); if (uncancelled && !u.ustuck && !sticks(youmonst.data)) - u.ustuck = mtmp; + setustuck(mtmp); break; case AD_WRAP: if ((!mtmp->mcan || u.ustuck == mtmp) && !sticks(youmonst.data)) { @@ -1192,7 +1192,7 @@ } else { pline("%s swings itself around you!", Monnam(mtmp)); - u.ustuck = mtmp; + setustuck(mtmp); } } else if(u.ustuck == mtmp) { if (is_pool(mtmp->mx,mtmp->my) && !Swimming @@ -1609,7 +1609,6 @@ remove_monster(mtmp->mx, mtmp->my); mtmp->mtrapped = 0; /* no longer on old trap */ place_monster(mtmp, u.ux, u.uy); - u.ustuck = mtmp; newsym(mtmp->mx,mtmp->my); #ifdef STEED if (is_animal(mtmp->data) && u.usteed) { @@ -1650,6 +1649,7 @@ display_nhwindow(WIN_MESSAGE, FALSE); vision_recalc(2); /* hero can't see anything */ u.uswallow = 1; + setustuck(mtmp); /* u.uswldtim always set > 1 */ tim_tmp = 25 - (int)mtmp->m_lev; if (tim_tmp > 0) tim_tmp = rnd(tim_tmp) / 2; diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/mon.c work.botl-held/src/mon.c --- base.patchable/src/mon.c 2003-02-23 09:43:28.000000000 -0500 +++ work.botl-held/src/mon.c 2003-03-18 17:08:58.000000000 -0500 @@ -1254,7 +1254,7 @@ } mtmp2->nmon = fmon; fmon = mtmp2; - if (u.ustuck == mtmp) u.ustuck = mtmp2; + if (u.ustuck == mtmp) setustuck(mtmp2); #ifdef STEED if (u.usteed == mtmp) u.usteed = mtmp2; #endif @@ -1669,7 +1669,7 @@ vision_full_recalc = 1; docrt(); } - u.ustuck = 0; + setustuck(0); } } diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/polyself.c work.botl-held/src/polyself.c --- base.patchable/src/polyself.c 2003-02-23 09:43:29.000000000 -0500 +++ work.botl-held/src/polyself.c 2003-03-18 17:08:58.000000000 -0500 @@ -468,7 +468,7 @@ } newsym(u.ux,u.uy); /* Change symbol */ - if (!sticky && !u.uswallow && u.ustuck && sticks(youmonst.data)) u.ustuck = 0; + if (!sticky && !u.uswallow && u.ustuck && sticks(youmonst.data)) setustuck(0); else if (sticky && !sticks(youmonst.data)) uunstick(); #ifdef STEED if (u.usteed) { @@ -1092,7 +1092,7 @@ uunstick() { pline("%s is no longer in your clutches.", Monnam(u.ustuck)); - u.ustuck = 0; + setustuck(0); } void diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/restore.c work.botl-held/src/restore.c --- base.patchable/src/restore.c 2003-02-23 09:43:29.000000000 -0500 +++ work.botl-held/src/restore.c 2003-03-18 17:08:58.000000000 -0500 @@ -461,7 +461,7 @@ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) if (mtmp->m_id == stuckid) break; if (!mtmp) panic("Cannot find the monster ustuck."); - u.ustuck = mtmp; + setustuck(mtmp); } #ifdef STEED if (steedid) { @@ -572,7 +572,7 @@ * afterwards, and in the meantime at least u.usteed may mislead * place_monster() on other levels */ - u.ustuck = (struct monst *)0; + setustuck((struct monst *)0); #ifdef STEED u.usteed = (struct monst *)0; #endif diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/save.c work.botl-held/src/save.c --- base.patchable/src/save.c 2003-02-23 09:43:30.000000000 -0500 +++ work.botl-held/src/save.c 2003-03-18 17:08:58.000000000 -0500 @@ -223,7 +223,7 @@ /* these pointers are no longer valid, and at least u.usteed * may mislead place_monster() on other levels */ - u.ustuck = (struct monst *)0; + setustuck((struct monst *)0); #ifdef STEED u.usteed = (struct monst *)0; #endif diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/teleport.c work.botl-held/src/teleport.c --- base.patchable/src/teleport.c 2003-02-23 09:43:30.000000000 -0500 +++ work.botl-held/src/teleport.c 2003-03-18 17:08:58.000000000 -0500 @@ -264,7 +264,7 @@ } } u.utrap = 0; - u.ustuck = 0; + setustuck(0); u.ux0 = u.ux; u.uy0 = u.uy; @@ -917,7 +917,7 @@ u.ux = x; u.uy = y; docrt(); - } else u.ustuck = 0; + } else setustuck(0); } newsym(x, y); /* update new location */ diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/u_init.c work.botl-held/src/u_init.c --- base.patchable/src/u_init.c 2003-02-23 09:43:31.000000000 -0500 +++ work.botl-held/src/u_init.c 2003-03-18 17:08:59.000000000 -0500 @@ -524,7 +524,7 @@ /* zero u, including pointer values -- * necessary when aborting from a failed restore */ (void) memset((genericptr_t)&u, 0, sizeof(u)); - u.ustuck = (struct monst *)0; + setustuck((struct monst *)0); #if 0 /* documentation of more zero values as desirable */ u.usick_cause[0] = 0; diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/uhitm.c work.botl-held/src/uhitm.c --- base.patchable/src/uhitm.c 2003-02-23 09:43:31.000000000 -0500 +++ work.botl-held/src/uhitm.c 2003-03-18 17:08:59.000000000 -0500 @@ -140,7 +140,7 @@ */ if(mtmp->m_ap_type && !Protection_from_shape_changers) { if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK)) - u.ustuck = mtmp; + setustuck(mtmp); } wakeup(mtmp); /* always necessary; also un-mimics mimics */ return TRUE; @@ -450,7 +450,7 @@ } else monflee(mon, 0, FALSE, TRUE); if(u.ustuck == mon && !u.uswallow && !sticks(youmonst.data)) - u.ustuck = 0; + setustuck(0); } /* Vorpal Blade hit converted to miss */ /* could be headless monster or worm tail */ @@ -1531,7 +1531,7 @@ break; case AD_STCK: if (!negated && !sticks(mdef->data)) - u.ustuck = mdef; /* it's now stuck to you */ + setustuck(mdef); /* it's now stuck to you */ break; case AD_WRAP: if (!sticks(mdef->data)) { @@ -1541,7 +1541,7 @@ } else { You("swing yourself around %s!", mon_nam(mdef)); - u.ustuck = mdef; + setustuck(mdef); } } else if(u.ustuck == mdef) { /* Monsters don't wear amulets of magical breathing */ @@ -2012,7 +2012,7 @@ sum[i] = damageum(mon, mattk); } else if(i >= 2 && sum[i-1] && sum[i-2]) { You("grab %s!", mon_nam(mon)); - u.ustuck = mon; + setustuck(mon); sum[i] = damageum(mon, mattk); } } @@ -2365,7 +2365,7 @@ *what = 0; if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK)) - u.ustuck = mtmp; + setustuck(mtmp); if (Blind) { if (!Blind_telepat) diff -r -X /home/roderick/.diff-exclude -uN base.patchable/util/makedefs.c work.botl-held/util/makedefs.c --- base.patchable/util/makedefs.c 2003-03-18 17:05:58.000000000 -0500 +++ work.botl-held/util/makedefs.c 2003-03-18 17:09:18.000000000 -0500 @@ -752,6 +752,10 @@ /* * patch list patch point; see $top/README.patchable */ + "patch: botl-held 3.4.1-1", + /* + * patch list patch point; see $top/README.patchable + */ /* * patch list patch point; see $top/README.patchable */