diff --git a/include/extern.h b/include/extern.h index d15118c6d..fbbaea8ee 100644 --- a/include/extern.h +++ b/include/extern.h @@ -365,9 +365,9 @@ E void FDECL(new_oname, (struct obj *,int)); E void FDECL(free_oname, (struct obj *)); E const char *FDECL(safe_oname, (struct obj *)); E struct monst *FDECL(christen_monst, (struct monst *,const char *)); -E int NDECL(do_mname); E struct obj *FDECL(oname, (struct obj *,const char *)); -E int NDECL(ddocall); +E boolean FDECL(objtyp_is_callable, (int)); +E int NDECL(docallcmd); E void FDECL(docall, (struct obj *)); E const char *NDECL(rndghostname); E char *FDECL(x_monnam, (struct monst *,int,const char *,int,BOOLEAN_P)); @@ -1513,6 +1513,7 @@ E void FDECL(restnames, (int)); E void FDECL(discover_object, (int,BOOLEAN_P,BOOLEAN_P)); E void FDECL(undiscover_object, (int)); E int NDECL(dodiscovered); +E void NDECL(rename_disco); /* ### objects.c ### */ diff --git a/src/cmd.c b/src/cmd.c index d31f2ce52..68c2a7d9b 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -42,8 +42,7 @@ extern int NDECL(dodown); /**/ extern int NDECL(doup); /**/ extern int NDECL(donull); /**/ extern int NDECL(dowipe); /**/ -extern int NDECL(do_mname); /**/ -extern int NDECL(ddocall); /**/ +extern int NDECL(docallcnd); /**/ extern int NDECL(dotakeoff); /**/ extern int NDECL(doremring); /**/ extern int NDECL(dowear); /**/ @@ -1646,7 +1645,7 @@ static const struct func_tab cmdlist[] = { {M('a'), TRUE, doorganize}, /* 'b', 'B' : go sw */ {'c', FALSE, doclose}, - {'C', TRUE, do_mname}, + {'C', TRUE, docallcmd}, {M('c'), TRUE, dotalk}, {'d', FALSE, dodrop}, {'D', FALSE, doddrop}, @@ -1671,9 +1670,9 @@ static const struct func_tab cmdlist[] = { {M('l'), FALSE, doloot}, /* 'n' prefixes a count if number_pad is on */ {M('m'), TRUE, domonability}, - {'N', TRUE, ddocall}, /* if number_pad is on */ - {M('n'), TRUE, ddocall}, - {M('N'), TRUE, ddocall}, + {'N', TRUE, docallcmd}, /* if number_pad is on */ + {M('n'), TRUE, docallcmd}, + {M('N'), TRUE, docallcmd}, {'o', FALSE, doopen}, {'O', TRUE, doset}, {M('o'), FALSE, dosacrifice}, @@ -1753,7 +1752,7 @@ struct ext_func_tab extcmdlist[] = { {"jump", "jump to a location", dojump, FALSE}, {"loot", "loot a box on the floor", doloot, FALSE}, {"monster", "use a monster's special ability", domonability, TRUE}, - {"name", "name an item or type of object", ddocall, TRUE}, + {"name", "name an item or type of object", docallcmd, TRUE}, {"offer", "offer a sacrifice to the gods", dosacrifice, FALSE}, #ifdef DUNGEON_OVERVIEW {"overview", "show an overview of the dungeon", dooverview, TRUE}, diff --git a/src/do_name.c b/src/do_name.c index 885e69554..e57126c32 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -1,12 +1,13 @@ -/* SCCS Id: @(#)do_name.c 3.5 2006/05/22 */ +/* SCCS Id: @(#)do_name.c 3.5 2007/05/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" -STATIC_DCL void FDECL(do_oname, (struct obj *)); -STATIC_DCL void FDECL(getpos_help, (BOOLEAN_P,const char *)); 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 *)); extern const char what_is_an_unknown_object[]; /* from pager.c */ @@ -305,7 +306,8 @@ const char *name; return mtmp; } -int +/* allow player to assign a name to some chosen monster */ +STATIC_OVL void do_mname() { char buf[BUFSZ], monnambuf[BUFSZ]; @@ -316,13 +318,13 @@ do_mname() if (Hallucination) { You("would never recognize it anyway."); - return 0; + return; } cc.x = u.ux; cc.y = u.uy; if (getpos(&cc, FALSE, "the monster you want to name") < 0 || (cx = cc.x) < 0) - return 0; + return; cy = cc.y; if (cx == u.ux && cy == u.uy) { @@ -336,7 +338,7 @@ do_mname() (flags.female ? "beautiful" : "handsome") : "ugly", plname); - return(0); + return; #ifdef STEED } #endif @@ -349,13 +351,13 @@ do_mname() || mtmp->m_ap_type == M_AP_OBJECT || (mtmp->minvis && !See_invisible)))) { pline("I see no monster there."); - return(0); + return; } /* special case similar to the one in lookat() */ Sprintf(qbuf, "What do you want to call %s?", distant_monnam(mtmp, ARTICLE_THE, monnambuf)); getlin(qbuf,buf); - if(!*buf || *buf == '\033') return(0); + if (!*buf || *buf == '\033') return; /* strip leading and trailing spaces; unnames monster if all spaces */ (void)mungspaces(buf); @@ -372,7 +374,6 @@ do_mname() pline("%s will not accept the name %s.", upstart(monnambuf), buf); else (void) christen_monst(mtmp, buf); - return(0); } /* @@ -459,34 +460,70 @@ static NEARDATA const char callable[] = { SCROLL_CLASS, POTION_CLASS, WAND_CLASS, RING_CLASS, AMULET_CLASS, GEM_CLASS, SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0 }; -int -ddocall() +boolean +objtyp_is_callable(i) +int i; { - register struct obj *obj; -#ifdef REDO - char ch; -#endif - char allowall[2]; + return (boolean)(objects[i].oc_uname || + (OBJ_DESCR(objects[i]) && + index(callable, objects[i].oc_class))); +} - switch( -#ifdef REDO - ch = +/* C and #name commands - player can name monster or object or type of obj */ +int +docallcmd() +{ + struct obj *obj; + winid win; + anything any; + menu_item *pick_list = 0; + char ch, allowall[2]; + + 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); + 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, + "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, + "a type of 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, + "a type of object on discoveries list", 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, + "a type of object upon the floor", MENU_UNSELECTED); #endif - ynq("Name an individual object?")) { + 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; + free((genericptr_t)pick_list); + } else + ch = 'q'; + destroy_nhwindow(win); + + switch (ch) { + default: case 'q': break; - case 'y': -#ifdef REDO - savech(ch); -#endif + case 'm': /* name a visible monster */ + do_mname(); + break; + case 'i': /* name an individual object in inventory */ allowall[0] = ALL_CLASSES; allowall[1] = '\0'; obj = getobj(allowall, "name"); if(obj) do_oname(obj); break; - default : -#ifdef REDO - savech(ch); -#endif + case 'o': /* name a type of object in inventory */ obj = getobj(callable, "call"); if (obj) { /* behave as if examining it in inventory; @@ -495,12 +532,24 @@ ddocall() (void) xname(obj); if (!obj->dknown) { - You("would never recognize another one."); - return 0; + You("would never recognize another one."); +#if 0 + } else if (!objtyp_is_callable(obj->otyp)) { + You("know those as well as you ever will."); +#endif + } else { + docall(obj); } - docall(obj); } break; + case 'd': /* name a type of object on the discoveries list */ + rename_disco(); + break; +#if 0 + case 'f': /* name a type of object visible on the floor */ + /* [not implemented] */ + break; +#endif } return 0; } diff --git a/src/invent.c b/src/invent.c index a34c7445a..0d1475a28 100644 --- a/src/invent.c +++ b/src/invent.c @@ -971,6 +971,7 @@ register const char *let,*word; (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown || !objects[HORN_OF_PLENTY].oc_name_known)) || (!strcmp(word, "charge") && !is_chargeable(otmp)) + || (!strcmp(word, "call") && !objtyp_is_callable(otyp)) ) foo--; /* ugly check for unworn armor that can't be worn */ diff --git a/src/o_init.c b/src/o_init.c index d019ef23b..79cd1c3f0 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)o_init.c 3.5 2005/11/14 */ +/* SCCS Id: @(#)o_init.c 3.5 2007/05/21 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -407,10 +407,9 @@ int dodiscovered() /* free after Robert Viduya */ { register int i, dis; - int ct = 0; - char *s, oclass, prev_class, classes[MAXOCLASSES]; + int ct = 0; + char *s, oclass, prev_class, classes[MAXOCLASSES], buf[BUFSZ]; winid tmpwin; - char buf[BUFSZ]; tmpwin = create_nhwindow(NHW_MENU); putstr(tmpwin, 0, "Discoveries"); @@ -442,7 +441,7 @@ dodiscovered() /* free after Robert Viduya */ prev_class = oclass + 1; /* forced different from oclass */ for (i = bases[(int)oclass]; i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) { - if ((dis = disco[i]) && interesting_to_discover(dis)) { + if ((dis = disco[i]) != 0 && interesting_to_discover(dis)) { ct++; if (oclass != prev_class) { putstr(tmpwin, iflags.menu_headings, let_to_name(oclass, FALSE)); @@ -463,4 +462,77 @@ dodiscovered() /* free after Robert Viduya */ return 0; } +/* put up nameable subset of discoveries list as a menu */ +void +rename_disco() +{ + register int i, dis; + int ct = 0, mn = 0, sl; + char *s, oclass, prev_class; + winid tmpwin; + anything any; + menu_item *selected = 0; + + any = zeroany; + tmpwin = create_nhwindow(NHW_MENU); + start_menu(tmpwin); + + /* + * Skip the "unique objects" section (each will appear within its + * regular class if it is nameable) and the artifacts section. + * We assume that classes omitted from packorder aren't nameable + * so we skip venom too. + */ + + /* for each class, show discoveries in that class */ + for (s = flags.inv_order; *s; s++) { + oclass = *s; + prev_class = oclass + 1; /* forced different from oclass */ + for (i = bases[(int)oclass]; + i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) { + dis = disco[i]; + if (!dis || !interesting_to_discover(dis)) continue; + ct++; + if (!objtyp_is_callable(dis)) continue; + mn++; + + if (oclass != prev_class) { + any.a_int = 0; + add_menu(tmpwin, NO_GLYPH, &any, ' ', iflags.menu_headings, + ATR_NONE, let_to_name(oclass, FALSE), MENU_UNSELECTED); + prev_class = oclass; + } + any.a_int = dis; + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, + obj_typename(dis), MENU_UNSELECTED); + } + } + if (ct == 0) { + You("haven't discovered anything yet..."); + } else if (mn == 0) { + pline("None of your discoveries can be assigned names..."); + } else { + end_menu(tmpwin, "Pick an object type to name"); + dis = STRANGE_OBJECT; + sl = select_menu(tmpwin, PICK_ONE, &selected); + if (sl > 0) { + dis = selected[0].item.a_int; + free((genericptr_t)selected); + } + if (dis != STRANGE_OBJECT) { + struct obj odummy; + + odummy = zeroobj; + odummy.otyp = dis; + odummy.oclass = objects[dis].oc_class; + odummy.quan = 1L; + odummy.known = !objects[dis].oc_uses_known; + odummy.dknown = 1; + docall(&odummy); + } + } + destroy_nhwindow(tmpwin); + return; +} + /*o_init.c*/