From 17f63949bc5e6e89730f5d40848542d8e4c8d561 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Fri, 21 Mar 2008 03:12:14 +0000 Subject: [PATCH] probing while swallowed (trunk only) Reported recently by : probing feedback while engulfed shouldn't claim that the monster is not carrying anything when the hero is inside of it. The simple case where it's not carrying anything else was a trivial one line change; handling inventory plus hero was trickier and I wouldn't have bothered if I'd realized what it was going to take. But it's done now; trivial case The purple worm is not carrying anything besides you. and harder case The purple worm's possessions: Weapons a - an uncursed dagger Swallowed Creature > - human archeologist called wizard --- doc/fixes35.0 | 1 + include/extern.h | 1 + include/hack.h | 3 ++- src/invent.c | 26 +++++++++--------- src/pager.c | 48 +++++++++++++++++---------------- src/pickup.c | 69 +++++++++++++++++++++++++++++++++++++++--------- src/zap.c | 5 ++-- 7 files changed, 102 insertions(+), 51 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 8c08429f2..6f012fffa 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -284,6 +284,7 @@ reprompt if player fails to make a menu choice during inventory identification seen eels who were stuck in isolated pools would never re-hide can no longer get both strength and resistance from eating one giant corpse aborting key/lock pick usage via ESC at direction prompt no longer use a move +when probing from inside an engulfer, "not carrying anything" overlooked hero Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 32ba58138..9ace6362b 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1614,6 +1614,7 @@ E void NDECL(set_playmode); /* ### pager.c ### */ +E char *FDECL(self_lookat, (char *)); E int NDECL(dowhatis); E int NDECL(doquickwhatis); E int NDECL(doidtrap); diff --git a/include/hack.h b/include/hack.h index d9abaee5f..a33b1d8c6 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)hack.h 3.5 2008/02/15 */ +/* SCCS Id: @(#)hack.h 3.5 2008/03/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -223,6 +223,7 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define SIGNAL_NOMENU 0x10 /* return -1 rather than 0 if none allowed */ #define SIGNAL_ESCAPE 0x20 /* return -2 rather than 0 for ESC */ #define FEEL_COCKATRICE 0x40 /* engage cockatrice checks and react */ +#define INCLUDE_HERO 0x80 /* show hero among engulfer's inventory */ /* Flags to control query_category() */ /* BY_NEXTHERE used by query_category() too, so skip 0x01 */ diff --git a/src/invent.c b/src/invent.c index 886a5ba87..979319c03 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)invent.c 3.5 2008/02/15 */ +/* SCCS Id: @(#)invent.c 3.5 2008/03/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3166,22 +3166,20 @@ char *title; char tmp[QBUFSZ]; int n; menu_item *selected = 0; -#ifndef GOLDOBJ int do_all = (dflags & MINV_ALL) != 0, - do_gold = (do_all && mon->mgold); + incl_hero = (do_all && u.uswallow && mon == u.ustuck), +#ifndef GOLDOBJ + do_gold = (do_all && mon->mgold), + have_inv = (mon->minvent || do_gold), #else - int do_all = (dflags & MINV_ALL) != 0; + have_inv = (mon->minvent != 0), #endif + have_any = (have_inv || incl_hero); Sprintf(tmp,"%s %s:", s_suffix(noit_Monnam(mon)), do_all ? "possessions" : "armament"); -#ifndef GOLDOBJ - if (do_all ? (mon->minvent || mon->mgold) -#else - if (do_all ? (mon->minvent != 0) -#endif - : (mon->misc_worn_check || MON_WEP(mon))) { + if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) { /* Fool the 'weapon in hand' routine into * displaying 'weapon in claw', etc. properly. */ @@ -3205,9 +3203,11 @@ char *title; } #endif - n = query_objlist(title ? title : tmp, mon->minvent, INVORDER_SORT, &selected, - (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE, - do_all ? allow_all : worn_wield_only); + n = query_objlist(title ? title : tmp, mon->minvent, + INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0), + &selected, + (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE, + do_all ? allow_all : worn_wield_only); #ifndef GOLDOBJ if (do_gold) obj_extract_self(&m_gold); diff --git a/src/pager.c b/src/pager.c index 2357e0c17..cfc9c33bc 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pager.c 3.5 2008/01/30 */ +/* SCCS Id: @(#)pager.c 3.5 2008/03/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -49,6 +49,28 @@ append_str(buf, new_str) return 1; } +/* shared by monster probing (via query_objlist!) as well as lookat() */ +char * +self_lookat(outbuf) +char *outbuf; +{ + char race[QBUFSZ]; + + /* include race with role unless polymorphed */ + race[0] = '\0'; + if (!Upolyd) + Sprintf(race, "%s ", urace.adj); + Sprintf(outbuf, "%s%s%s called %s", + /* being blinded may hide invisibility from self */ + (Invis && (senseself() || !Blind)) ? "invisible " : "", + race, mons[u.umonnum].mname, plname); +#ifdef STEED + if (u.usteed) + Sprintf(eos(outbuf), ", mounted on %s", y_monnam(u.usteed)); +#endif + return outbuf; +} + /* * Return the name of the glyph found at (x,y). * If not hallucinating and the glyph is a monster, also monster data. @@ -65,35 +87,15 @@ lookat(x, y, buf, monbuf) buf[0] = monbuf[0] = 0; glyph = glyph_at(x,y); if (u.ux == x && u.uy == y && canspotself()) { - char race[QBUFSZ]; + /* fill in buf[] */ + (void)self_lookat(buf); - /* if not polymorphed, show both the role and the race */ - race[0] = 0; - if (!Upolyd) { - Sprintf(race, "%s ", urace.adj); - } - - Sprintf(buf, "%s%s%s called %s", - /* being blinded may hide invisibility from self */ - (Invis && (senseself() || !Blind)) ? "invisible " : "", - race, - mons[u.umonnum].mname, - plname); /* file lookup can't distinguish between "gnomish wizard" monster and correspondingly named player character, always picking the former; force it to find the general "wizard" entry instead */ if (Role_if(PM_WIZARD) && Race_if(PM_GNOME) && !Upolyd) pm = &mons[PM_WIZARD]; -#ifdef STEED - if (u.usteed) { - char steedbuf[BUFSZ]; - - Sprintf(steedbuf, ", mounted on %s", y_monnam(u.usteed)); - /* assert((sizeof buf >= strlen(buf)+strlen(steedbuf)+1); */ - Strcat(buf, steedbuf); - } -#endif /* When you see yourself normally, no explanation is appended (even if you could also see yourself via other means). Sensing self while blind or swallowed is treated as if it diff --git a/src/pickup.c b/src/pickup.c index 5106f2a83..8388ef5b4 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pickup.c 3.5 2008/02/15 */ +/* SCCS Id: @(#)pickup.c 3.5 2008/03/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,6 +8,8 @@ #include "hack.h" +#define CONTAINED_SYM '>' /* from invent.c */ + STATIC_DCL void FDECL(simple_look, (struct obj *,BOOLEAN_P)); #ifndef GOLDOBJ STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, @@ -716,6 +718,7 @@ menu_item **pick_list; /* list of objects and counts to pick up */ * use it. * USE_INVLET - Use object's invlet. * INVORDER_SORT - Use hero's pack order. + * INCLUDE_HERO - Showing engulfer's invent; show hero too. * SIGNAL_NOMENU - Return -1 rather than 0 if nothing passes "allow". * SIGNAL_ESCAPE - Return -1 rather than 0 if player uses ESC to * pick nothing. @@ -731,13 +734,15 @@ boolean FDECL((*allow), (OBJ_P));/* allow function */ { int n; winid win; - struct obj *curr, *last; + struct obj *curr, *last, fake_hero_object; char *pack; anything any; - boolean printed_type_name; + boolean printed_type_name, + sorted = (qflags & INVORDER_SORT) != 0, + engulfer = (qflags & INCLUDE_HERO) != 0; *pick_list = (menu_item *) 0; - if (!olist) return 0; + if (!olist && !engulfer) return 0; /* count the number of items allowed */ for (n = 0, last = 0, curr = olist; curr; curr = FOLLOW(curr, qflags)) @@ -746,6 +751,12 @@ boolean FDECL((*allow), (OBJ_P));/* allow function */ n++; } + if (engulfer) { + ++n; + /* don't autoselect swallowed hero if it's the only choice */ + qflags &= ~AUTOSELECT_SINGLE; + } + if (n == 0) /* nothing to pick here */ return (qflags & SIGNAL_NOMENU) ? -1 : 0; @@ -776,11 +787,10 @@ boolean FDECL((*allow), (OBJ_P));/* allow function */ (void) look_here(0, FALSE); return 0; } - if ((!(qflags & INVORDER_SORT) || curr->oclass == *pack) - && (*allow)(curr)) { + if ((!sorted || curr->oclass == *pack) && (*allow)(curr)) { /* if sorting, print type name (once only) */ - if (qflags & INVORDER_SORT && !printed_type_name) { + if (sorted && !printed_type_name) { any = zeroany; add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, let_to_name(*pack, FALSE), MENU_UNSELECTED); @@ -789,13 +799,32 @@ boolean FDECL((*allow), (OBJ_P));/* allow function */ any.a_obj = curr; add_menu(win, obj_to_glyph(curr), &any, - qflags & USE_INVLET ? curr->invlet : 0, + (qflags & USE_INVLET) ? curr->invlet : 0, def_oc_syms[(int)objects[curr->otyp].oc_class].sym, ATR_NONE, doname(curr), MENU_UNSELECTED); } } pack++; - } while (qflags & INVORDER_SORT && *pack); + } while (sorted && *pack); + + if (engulfer) { + char buf[BUFSZ]; + + any = zeroany; + if (sorted && n > 1) { + Sprintf(buf, "%s Creature", + is_animal(u.ustuck->data) ? "Swallowed" : "Engulfed"); + add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, + buf, MENU_UNSELECTED); + } + fake_hero_object = zeroobj; + fake_hero_object.quan = 1L; /* not strictly necessary... */ + any.a_obj = &fake_hero_object; + add_menu(win, mon_to_glyph(&youmonst), &any, + /* fake inventory letter, no group accelerator */ + CONTAINED_SYM, 0, + ATR_NONE, self_lookat(buf), MENU_UNSELECTED); + } end_menu(win, qstr); n = select_menu(win, how, pick_list); @@ -803,12 +832,28 @@ boolean FDECL((*allow), (OBJ_P));/* allow function */ if (n > 0) { menu_item *mi; - int i; + int i, k; - /* fix up counts: -1 means no count used => pick all */ - for (i = 0, mi = *pick_list; i < n; i++, mi++) + /* fix up counts: -1 means no count used => pick all; + if fake_hero_object was picked, discard that choice */ + for (i = k = 0, mi = *pick_list; i < n; i++, mi++) { + if (mi->item.a_obj == &fake_hero_object) continue; if (mi->count == -1L || mi->count > mi->item.a_obj->quan) mi->count = mi->item.a_obj->quan; + if (k < i) (*pick_list)[k] = *mi; + ++k; + } + if (!k) { + /* fake_hero was only choice so discard whole list */ + free((genericptr_t) *pick_list); + *pick_list = 0; + n = 0; + } else if (k < n) { + /* other stuff plus fake_hero; last slot is now unused */ + (*pick_list)[k].item = zeroany; + (*pick_list)[k].count = 0L; + n = k; + } } else if (n < 0) { /* -1 is used for SIGNAL_NOMENU, so callers don't expect it to indicate that the player declined to make a choice */ diff --git a/src/zap.c b/src/zap.c index 1ed66fc47..7047faffd 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)zap.c 3.5 2008/01/19 */ +/* SCCS Id: @(#)zap.c 3.5 2008/03/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -450,7 +450,8 @@ struct monst *mtmp; } (void) display_minventory(mtmp, MINV_ALL|MINV_NOLET, (char *)0); } else { - pline("%s is not carrying anything.", noit_Monnam(mtmp)); + pline("%s is not carrying anything%s.", noit_Monnam(mtmp), + (u.uswallow && mtmp == u.ustuck) ? " besides you" : ""); } }