From: PatR Date: Fri, 29 May 2015 09:07:50 +0000 (-0700) Subject: using #name to call a floor object X-Git-Tag: NetHack-3.6.0_RC01~332 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7d74a25a14da79a4a1fe9175b75afd30a6861681;p=nethack using #name to call a floor object Implement Boudewijn's suggestion that #name be extended to allow naming something of the floor. I'm sure he wants this so that he can avoid picking up gray stones, but it's something I started to implement years ago (probably at an earlier suggestion from him...) and then forgot all about. This changes the #name menu to be m - a monster i - a particular object in inventory o - the type of an object in inventory f - the type of an object upon the floor d - the type of an object on discoveries list a - record an annotation for the current level What do you want to name? with the i and o choices omitted when inventory is empty. If the 'lootabc' option is set it will use a through f instead, but then the last three entries change letters when inventory is empty. 'y' and 'n' are still accelerators (effectively hidden choices) for the i and o entries, corresponding to the answers for the 3.4.3 and earlier "name an individual object?" prompt. The floor choice asks you to pick a location. If you pick yourself, then the top object of the pile underneath you is targetted. Otherwise, the target must be an object glyph, and the object must have its dknown bit set, so have previously been seen up close or revealed via blessed potion of object detection. To make it be more useful, targetting an object on an adjacent square will set the dknown bit. (Just the top object if there is a pile there.) There's no cockatrice corpse touch check since you aren't actually touching anything, just looking. The setting of dknown bit for an adjacent object has been extended to the '/' and ';' commands for examining things on the screen as well. It's only done for adjacent spots you actively select, not all 8 spots around you. --- diff --git a/include/extern.h b/include/extern.h index bfa13669f..901326707 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1432249760 2015/05/21 23:09:20 $ $NHDT-Branch: master $:$NHDT-Revision: 1.493 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1432890461 2015/05/29 09:07:41 $ $NHDT-Branch: master $:$NHDT-Revision: 1.498 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1646,6 +1646,7 @@ E void NDECL(msgtype_free); /* ### pager.c ### */ E char *FDECL(self_lookat, (char *)); +E boolean FDECL(object_from_map, (int,int,int,struct obj **)); E int NDECL(dowhatis); E int NDECL(doquickwhatis); E int NDECL(doidtrap); diff --git a/src/do_name.c b/src/do_name.c index 44d03f717..ced3c4b68 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do_name.c $NHDT-Date: 1432512768 2015/05/25 00:12:48 $ $NHDT-Branch: master $:$NHDT-Revision: 1.72 $ */ +/* NetHack 3.6 do_name.c $NHDT-Date: 1432890462 2015/05/29 09:07:42 $ $NHDT-Branch: master $:$NHDT-Revision: 1.73 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,6 +8,7 @@ STATIC_DCL char *NDECL(nextmbuf); STATIC_DCL void FDECL(getpos_help, (BOOLEAN_P, const char *)); STATIC_DCL void NDECL(do_mname); STATIC_DCL void FDECL(do_oname, (struct obj *)); +STATIC_DCL void NDECL(namefloorobj); extern const char what_is_an_unknown_object[]; /* from pager.c */ @@ -587,9 +588,9 @@ boolean objtyp_is_callable(i) int i; { - return (boolean)( - objects[i].oc_uname - || (OBJ_DESCR(objects[i]) && index(callable, objects[i].oc_class))); + return (boolean) (objects[i].oc_uname + || (OBJ_DESCR(objects[i]) + && index(callable, objects[i].oc_class))); } /* C and #name commands - player can name monster or object or type of obj */ @@ -601,34 +602,34 @@ docallcmd() anything any; menu_item *pick_list = 0; char ch, allowall[2]; + /* if player wants a,b,c instead of i,o when looting, do that here too */ + boolean abc = flags.lootabc; win = create_nhwindow(NHW_MENU); start_menu(win); any = zeroany; - any.a_char = 'm'; /* entry 'a', group accelator 'C' */ - add_menu(win, NO_GLYPH, &any, 0, 'C', ATR_NONE, "a monster", - MENU_UNSELECTED); + any.a_char = 'm'; /* group accelerator 'C' */ + add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'C', ATR_NONE, + "a monster", MENU_UNSELECTED); if (invent) { /* we use y and n as accelerators so that we can accept user's response keyed to old "name an individual object?" prompt */ - any.a_char = 'i'; /* entry 'b', group accelator 'y' */ - add_menu(win, NO_GLYPH, &any, 0, 'y', ATR_NONE, + any.a_char = 'i'; /* group accelerator 'y' */ + add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'y', ATR_NONE, "a particular object in inventory", MENU_UNSELECTED); - any.a_char = 'o'; /* entry 'c', group accelator 'n' */ - add_menu(win, NO_GLYPH, &any, 0, 'n', ATR_NONE, + any.a_char = 'o'; /* group accelerator 'n' */ + add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'n', ATR_NONE, "the type of an object in inventory", MENU_UNSELECTED); } - any.a_char = 'd'; /* entry 'd' (or 'b'), group accelator 'd' */ - add_menu(win, NO_GLYPH, &any, 0, any.a_char, ATR_NONE, + any.a_char = 'f'; /* group accelerator ',' (or ':' instead?) */ + add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, ',', ATR_NONE, + "the type of an object upon the floor", MENU_UNSELECTED); + any.a_char = 'd'; /* group accelerator '\' */ + add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, '\\', ATR_NONE, "the type of an object on discoveries list", MENU_UNSELECTED); - any.a_char = 'e'; - add_menu(win, NO_GLYPH, &any, 0, any.a_char, ATR_NONE, - "the current level", MENU_UNSELECTED); -#if 0 - any.a_char = 'f'; /* entry 'e' (or 'c'), group accelator 'f' */ - add_menu(win, NO_GLYPH, &any, 0, any.a_char, ATR_NONE, - "the type of an object upon the floor", MENU_UNSELECTED); -#endif + any.a_char = 'a'; /* group accelerator 'l' */ + add_menu(win, NO_GLYPH, &any, abc ? 0 : any.a_char, 'l', ATR_NONE, + "record an annotation for the current level", MENU_UNSELECTED); end_menu(win, "What do you want to name?"); if (select_menu(win, PICK_ONE, &pick_list) > 0) { ch = pick_list[0].item.a_char; @@ -662,25 +663,23 @@ docallcmd() if (!obj->dknown) { You("would never recognize another one."); #if 0 - } else if (!objtyp_is_callable(obj->otyp)) { - You("know those as well as you ever will."); + } else if (!objtyp_is_callable(obj->otyp)) { + You("know those as well as you ever will."); #endif } else { docall(obj); } } break; + case 'f': /* name a type of object visible on the floor */ + namefloorobj(); + break; case 'd': /* name a type of object on the discoveries list */ rename_disco(); break; - case 'e': /* annotate level */ + case 'a': /* annotate level */ donamelevel(); break; -#if 0 - case 'f': /* name a type of object visible on the floor */ - /* [not implemented] */ - break; -#endif } return 0; } @@ -729,6 +728,57 @@ register struct obj *obj; } } +STATIC_OVL void +namefloorobj() +{ + coord cc; + int glyph; + char buf[BUFSZ]; + struct obj *obj = 0; + boolean fakeobj = FALSE, use_plural; + + cc.x = u.ux, cc.y = u.uy; + if (getpos(&cc, FALSE, "object on map (or '.' for one under you)") < 0 + || cc.x <= 0) + return; + if (cc.x == u.ux && cc.y == u.uy) { + obj = vobj_at(u.ux, u.uy); + } else { + glyph = glyph_at(cc.x, cc.y); + if (glyph_is_object(glyph)) + fakeobj = object_from_map(glyph, cc.x, cc.y, &obj); + /* else 'obj' stays null */ + } + if (!obj) { + pline("There doesn't seem to be any object %s.", + (cc.x == u.ux && cc.y == u.uy) ? "under you" : "there"); + return; + } + /* note well: 'obj' might be as instance of STRANGE_OBJECT if target + is a mimic; passing that to xname (directly or via simpleonames) + would yield "glorkum" so we need to handle it explicitly; it will + alwlays fail the Hallucination test and pass the !callable test, + resulting in the "can't be assigned a type name" message */ + Strcpy(buf, (obj->otyp != STRANGE_OBJECT) + ? simpleonames(obj) + : obj_descr[STRANGE_OBJECT].oc_name); + use_plural = (obj->quan > 1L); + if (Hallucination) { + pline("%s %s to call you \"Wibbly Wobbly.\"", + The(buf), use_plural ? "decide" : "decides"); + } else if (!objtyp_is_callable(obj->otyp)) { + pline("%s %s can't be assigned a type name.", + use_plural ? "Those" : "That", buf); + } else if (!obj->dknown) { + You("don't know %s %s well enough to name %s.", + use_plural ? "those" : "that", buf, use_plural ? "them" : "it"); + } else { + docall(obj); + } + if (fakeobj) + dealloc_obj(obj); +} + static const char *const ghostnames[] = { /* these names should have length < PL_NSIZ */ /* Capitalize the names for aesthetics -dgk */ diff --git a/src/pager.c b/src/pager.c index 5ab64103f..aa7e7ecbd 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pager.c $NHDT-Date: 1432685499 2015/05/27 00:11:39 $ $NHDT-Branch: master $:$NHDT-Revision: 1.73 $ */ +/* NetHack 3.6 pager.c $NHDT-Date: 1432890463 2015/05/29 09:07:43 $ $NHDT-Branch: master $:$NHDT-Revision: 1.74 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -71,6 +71,47 @@ char *outbuf; return outbuf; } +/* extracted from lookat(); also used by namefloorobj() */ +boolean +object_from_map(glyph, x, y, obj_p) +int glyph, x, y; +struct obj **obj_p; +{ + boolean fakeobj = FALSE; + struct monst *mtmp; + struct obj *otmp = vobj_at(x, y); + int glyphotyp = glyph_to_obj(glyph); + + *obj_p = (struct obj *) 0; + /* there might be a mimic here posing as an object */ + mtmp = m_at(x, y); + if (mtmp && mtmp->m_ap_type == M_AP_OBJECT + && mtmp->mappearance == (unsigned) glyphotyp) + otmp = 0; + else + mtmp = 0; + + if (!otmp || otmp->otyp != glyphotyp) { + /* this used to exclude STRANGE_OBJECT; now caller deals with it */ + otmp = mksobj(glyphotyp, FALSE, FALSE); + if (!otmp) + return FALSE; + fakeobj = TRUE; + if (otmp->oclass == COIN_CLASS) + otmp->quan = 2L; /* to force pluralization */ + else if (otmp->otyp == SLIME_MOLD) + otmp->spe = context.current_fruit; /* give it a type */ + if (mtmp && has_mcorpsenm(mtmp)) /* mimic as corpse/statue */ + otmp->corpsenm = MCORPSENM(mtmp); + } + /* if located at adajcent spot, mark it as having been seen up close */ + if (otmp && distu(x, y) <= 2 && !Blind && !Hallucination) + otmp->dknown = 1; + + *obj_p = otmp; + return fakeobj; /* when True, caller needs to dealloc *obj_p */ +} + /* * Return the name of the glyph found at (x,y). * If not hallucinating and the glyph is a monster, also monster data. @@ -226,32 +267,16 @@ char *buf, *monbuf; } /* mtmp */ } else if (glyph_is_object(glyph)) { - int glyphotyp = glyph_to_obj(glyph); - struct obj *otmp = vobj_at(x, y); - - /* there might be a mimic here posing as an object */ - mtmp = m_at(x, y); - if (mtmp && mtmp->m_ap_type == M_AP_OBJECT - && mtmp->mappearance == (unsigned) glyphotyp) - otmp = 0; - else - mtmp = 0; - - if (!otmp || otmp->otyp != glyphotyp) { - if (glyphotyp != STRANGE_OBJECT) { - otmp = mksobj(glyphotyp, FALSE, FALSE); - if (otmp->oclass == COIN_CLASS) - otmp->quan = 2L; /* to force pluralization */ - else if (otmp->otyp == SLIME_MOLD) - otmp->spe = context.current_fruit; /* give it a type */ - if (mtmp && has_mcorpsenm(mtmp)) /* mimic as corpse/statue */ - otmp->corpsenm = MCORPSENM(mtmp); - Strcpy(buf, distant_name(otmp, xname)); - dealloc_obj(otmp); - } else - Strcpy(buf, obj_descr[STRANGE_OBJECT].oc_name); - } else - Strcpy(buf, distant_name(otmp, xname)); + struct obj *otmp = 0; + boolean fakeobj = object_from_map(glyph, x, y, &otmp); + + if (otmp) { + Strcpy(buf, (otmp->otyp != STRANGE_OBJECT) + ? distant_name(otmp, xname) + : obj_descr[STRANGE_OBJECT].oc_name); + if (fakeobj) + dealloc_obj(otmp), otmp = 0; + } if (levl[x][y].typ == STONE || levl[x][y].typ == SCORR) Strcat(buf, " embedded in stone");