NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / src / o_init.c
blob55123064d6b78745ecbb136c8de710c1cc08b4f1
1 /* aNetHack 0.0.1 o_init.c $ANH-Date: 1450318588 2015/12/17 02:16:28 $ $ANH-Branch: master $:$ANH-Revision: 1.22 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* aNetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
6 #include "lev.h" /* save & restore info */
8 STATIC_DCL void FDECL(setgemprobs, (d_level *));
9 STATIC_DCL void FDECL(shuffle, (int, int, BOOLEAN_P));
10 STATIC_DCL void NDECL(shuffle_all);
11 STATIC_DCL boolean FDECL(interesting_to_discover, (int));
12 STATIC_DCL char *FDECL(oclass_to_name, (CHAR_P, char *));
14 static NEARDATA short disco[NUM_OBJECTS] = DUMMY;
16 #ifdef USE_TILES
17 STATIC_DCL void NDECL(shuffle_tiles);
18 extern short glyph2tile[]; /* from tile.c */
20 /* Shuffle tile assignments to match descriptions, so a red potion isn't
21 * displayed with a blue tile and so on.
23 * Tile assignments are not saved, and shouldn't be so that a game can
24 * be resumed on an otherwise identical non-tile-using binary, so we have
25 * to reshuffle the assignments from oc_descr_idx information when a game
26 * is restored. So might as well do that the first time instead of writing
27 * another routine.
29 STATIC_OVL void
30 shuffle_tiles()
32 int i;
33 short tmp_tilemap[NUM_OBJECTS];
35 for (i = 0; i < NUM_OBJECTS; i++)
36 tmp_tilemap[i] = glyph2tile[objects[i].oc_descr_idx + GLYPH_OBJ_OFF];
38 for (i = 0; i < NUM_OBJECTS; i++)
39 glyph2tile[i + GLYPH_OBJ_OFF] = tmp_tilemap[i];
41 #endif /* USE_TILES */
43 STATIC_OVL void
44 setgemprobs(dlev)
45 d_level *dlev;
47 int j, first, lev;
49 if (dlev)
50 lev = (ledger_no(dlev) > maxledgerno()) ? maxledgerno()
51 : ledger_no(dlev);
52 else
53 lev = 0;
54 first = bases[GEM_CLASS];
56 for (j = 0; j < 9 - lev / 3; j++)
57 objects[first + j].oc_prob = 0;
58 first += j;
59 if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS
60 || OBJ_NAME(objects[first]) == (char *) 0) {
61 raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d", first, j,
62 LAST_GEM);
63 wait_synch();
65 for (j = first; j <= LAST_GEM; j++)
66 objects[j].oc_prob = (171 + j - first) / (LAST_GEM + 1 - first);
69 /* shuffle descriptions on objects o_low to o_high */
70 STATIC_OVL void
71 shuffle(o_low, o_high, domaterial)
72 int o_low, o_high;
73 boolean domaterial;
75 int i, j, num_to_shuffle;
76 short sw;
77 int color;
79 for (num_to_shuffle = 0, j = o_low; j <= o_high; j++)
80 if (!objects[j].oc_name_known)
81 num_to_shuffle++;
82 if (num_to_shuffle < 2)
83 return;
85 for (j = o_low; j <= o_high; j++) {
86 if (objects[j].oc_name_known)
87 continue;
89 i = j + rn2(o_high - j + 1);
90 while (objects[i].oc_name_known);
91 sw = objects[j].oc_descr_idx;
92 objects[j].oc_descr_idx = objects[i].oc_descr_idx;
93 objects[i].oc_descr_idx = sw;
94 sw = objects[j].oc_tough;
95 objects[j].oc_tough = objects[i].oc_tough;
96 objects[i].oc_tough = sw;
97 color = objects[j].oc_color;
98 objects[j].oc_color = objects[i].oc_color;
99 objects[i].oc_color = color;
101 /* shuffle material */
102 if (domaterial) {
103 sw = objects[j].oc_material;
104 objects[j].oc_material = objects[i].oc_material;
105 objects[i].oc_material = sw;
110 void
111 init_objects()
113 register int i, first, last, sum;
114 register char oclass;
115 #ifdef TEXTCOLOR
116 #define COPY_OBJ_DESCR(o_dst, o_src) \
117 o_dst.oc_descr_idx = o_src.oc_descr_idx, o_dst.oc_color = o_src.oc_color
118 #else
119 #define COPY_OBJ_DESCR(o_dst, o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx
120 #endif
122 /* bug fix to prevent "initialization error" abort on Intel Xenix.
123 * reported by mikew@semike
125 for (i = 0; i < MAXOCLASSES; i++)
126 bases[i] = 0;
127 /* initialize object descriptions */
128 for (i = 0; i < NUM_OBJECTS; i++)
129 objects[i].oc_name_idx = objects[i].oc_descr_idx = i;
130 /* init base; if probs given check that they add up to 1000,
131 otherwise compute probs */
132 first = 0;
133 while (first < NUM_OBJECTS) {
134 oclass = objects[first].oc_class;
135 last = first + 1;
136 while (last < NUM_OBJECTS && objects[last].oc_class == oclass)
137 last++;
138 bases[(int) oclass] = first;
140 if (oclass == GEM_CLASS) {
141 setgemprobs((d_level *) 0);
143 if (rn2(2)) { /* change turquoise from green to blue? */
144 COPY_OBJ_DESCR(objects[TURQUOISE], objects[SAPPHIRE]);
146 if (rn2(2)) { /* change aquamarine from green to blue? */
147 COPY_OBJ_DESCR(objects[AQUAMARINE], objects[SAPPHIRE]);
149 switch (rn2(4)) { /* change fluorite from violet? */
150 case 0:
151 break;
152 case 1: /* blue */
153 COPY_OBJ_DESCR(objects[FLUORITE], objects[SAPPHIRE]);
154 break;
155 case 2: /* white */
156 COPY_OBJ_DESCR(objects[FLUORITE], objects[DIAMOND]);
157 break;
158 case 3: /* green */
159 COPY_OBJ_DESCR(objects[FLUORITE], objects[EMERALD]);
160 break;
163 check:
164 sum = 0;
165 for (i = first; i < last; i++)
166 sum += objects[i].oc_prob;
167 if (sum == 0) {
168 for (i = first; i < last; i++)
169 objects[i].oc_prob = (1000 + i - first) / (last - first);
170 goto check;
172 if (sum != 1000)
173 error("init-prob error for class %d (%d%%)", oclass, sum);
174 first = last;
176 /* shuffle descriptions */
177 shuffle_all();
178 #ifdef USE_TILES
179 shuffle_tiles();
180 #endif
181 objects[WAN_NOTHING].oc_dir = rn2(2) ? NODIR : IMMEDIATE;
184 /* retrieve the range of objects that otyp shares descriptions with */
185 void
186 obj_shuffle_range(otyp, lo_p, hi_p)
187 int otyp; /* input: representative item */
188 int *lo_p, *hi_p; /* output: range that item belongs among */
190 int i, ocls = objects[otyp].oc_class;
192 /* default is just the object itself */
193 *lo_p = *hi_p = otyp;
195 switch (ocls) {
196 case ARMOR_CLASS:
197 if (otyp >= HELMET && otyp <= HELM_OF_TELEPATHY)
198 *lo_p = HELMET, *hi_p = HELM_OF_TELEPATHY;
199 else if (otyp >= LEATHER_GLOVES && otyp <= GAUNTLETS_OF_DEXTERITY)
200 *lo_p = LEATHER_GLOVES, *hi_p = GAUNTLETS_OF_DEXTERITY;
201 else if (otyp >= CLOAK_OF_PROTECTION && otyp <= CLOAK_OF_DISPLACEMENT)
202 *lo_p = CLOAK_OF_PROTECTION, *hi_p = CLOAK_OF_DISPLACEMENT;
203 else if (otyp >= SPEED_BOOTS && otyp <= LEVITATION_BOOTS)
204 *lo_p = SPEED_BOOTS, *hi_p = LEVITATION_BOOTS;
205 break;
206 case POTION_CLASS:
207 /* potion of water has the only fixed description */
208 *lo_p = bases[POTION_CLASS];
209 *hi_p = POT_WATER - 1;
210 break;
211 case AMULET_CLASS:
212 case SCROLL_CLASS:
213 case SPBOOK_CLASS:
214 /* exclude non-magic types and also unique ones */
215 *lo_p = bases[ocls];
216 for (i = *lo_p; objects[i].oc_class == ocls; i++)
217 if (objects[i].oc_unique || !objects[i].oc_magic)
218 break;
219 *hi_p = i - 1;
220 break;
221 case RING_CLASS:
222 case WAND_CLASS:
223 case VENOM_CLASS:
224 /* entire class */
225 *lo_p = bases[ocls];
226 for (i = *lo_p; objects[i].oc_class == ocls; i++)
227 continue;
228 *hi_p = i - 1;
229 break;
232 /* artifact checking might ask about item which isn't part of any range
233 but fell within the classes that do have ranges specified above */
234 if (otyp < *lo_p || otyp > *hi_p)
235 *lo_p = *hi_p = otyp;
236 return;
239 /* randomize object descriptions */
240 STATIC_OVL void
241 shuffle_all()
243 /* entire classes; obj_shuffle_range() handles their exceptions */
244 static char shuffle_classes[] = {
245 AMULET_CLASS, POTION_CLASS, RING_CLASS, SCROLL_CLASS,
246 SPBOOK_CLASS, WAND_CLASS, VENOM_CLASS,
248 /* sub-class type ranges (one item from each group) */
249 static short shuffle_types[] = {
250 HELMET, LEATHER_GLOVES, CLOAK_OF_PROTECTION, SPEED_BOOTS,
252 int first, last, idx;
254 /* do whole classes (amulets, &c) */
255 for (idx = 0; idx < SIZE(shuffle_classes); idx++) {
256 obj_shuffle_range(bases[(int) shuffle_classes[idx]], &first, &last);
257 shuffle(first, last, TRUE);
259 /* do type ranges (helms, &c) */
260 for (idx = 0; idx < SIZE(shuffle_types); idx++) {
261 obj_shuffle_range(shuffle_types[idx], &first, &last);
262 shuffle(first, last, FALSE);
264 return;
267 /* find the object index for snow boots; used [once] by slippery ice code */
269 find_skates()
271 register int i;
272 register const char *s;
274 for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++)
275 if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots"))
276 return i;
278 impossible("snow boots not found?");
279 return -1; /* not 0, or caller would try again each move */
282 /* level dependent initialization */
283 void
284 oinit()
286 setgemprobs(&u.uz);
289 void
290 savenames(fd, mode)
291 int fd, mode;
293 register int i;
294 unsigned int len;
296 if (perform_bwrite(mode)) {
297 bwrite(fd, (genericptr_t) bases, sizeof bases);
298 bwrite(fd, (genericptr_t) disco, sizeof disco);
299 bwrite(fd, (genericptr_t) objects,
300 sizeof(struct objclass) * NUM_OBJECTS);
302 /* as long as we use only one version of Hack we
303 need not save oc_name and oc_descr, but we must save
304 oc_uname for all objects */
305 for (i = 0; i < NUM_OBJECTS; i++)
306 if (objects[i].oc_uname) {
307 if (perform_bwrite(mode)) {
308 len = strlen(objects[i].oc_uname) + 1;
309 bwrite(fd, (genericptr_t) &len, sizeof len);
310 bwrite(fd, (genericptr_t) objects[i].oc_uname, len);
312 if (release_data(mode)) {
313 free((genericptr_t) objects[i].oc_uname);
314 objects[i].oc_uname = 0;
319 void
320 restnames(fd)
321 register int fd;
323 register int i;
324 unsigned int len;
326 mread(fd, (genericptr_t) bases, sizeof bases);
327 mread(fd, (genericptr_t) disco, sizeof disco);
328 mread(fd, (genericptr_t) objects, sizeof(struct objclass) * NUM_OBJECTS);
329 for (i = 0; i < NUM_OBJECTS; i++)
330 if (objects[i].oc_uname) {
331 mread(fd, (genericptr_t) &len, sizeof len);
332 objects[i].oc_uname = (char *) alloc(len);
333 mread(fd, (genericptr_t) objects[i].oc_uname, len);
335 #ifdef USE_TILES
336 shuffle_tiles();
337 #endif
340 void
341 discover_object(oindx, mark_as_known, credit_hero)
342 register int oindx;
343 boolean mark_as_known;
344 boolean credit_hero;
346 if (!objects[oindx].oc_name_known) {
347 register int dindx, acls = objects[oindx].oc_class;
349 /* Loop thru disco[] 'til we find the target (which may have been
350 uname'd) or the next open slot; one or the other will be found
351 before we reach the next class...
353 for (dindx = bases[acls]; disco[dindx] != 0; dindx++)
354 if (disco[dindx] == oindx)
355 break;
356 disco[dindx] = oindx;
358 if (mark_as_known) {
359 objects[oindx].oc_name_known = 1;
360 if (credit_hero)
361 exercise(A_WIS, TRUE);
363 if (moves > 1L)
364 update_inventory();
368 /* if a class name has been cleared, we may need to purge it from disco[] */
369 void
370 undiscover_object(oindx)
371 register int oindx;
373 if (!objects[oindx].oc_name_known) {
374 register int dindx, acls = objects[oindx].oc_class;
375 register boolean found = FALSE;
377 /* find the object; shift those behind it forward one slot */
378 for (dindx = bases[acls]; dindx < NUM_OBJECTS && disco[dindx] != 0
379 && objects[dindx].oc_class == acls;
380 dindx++)
381 if (found)
382 disco[dindx - 1] = disco[dindx];
383 else if (disco[dindx] == oindx)
384 found = TRUE;
386 /* clear last slot */
387 if (found)
388 disco[dindx - 1] = 0;
389 else
390 impossible("named object not in disco");
391 update_inventory();
395 STATIC_OVL boolean
396 interesting_to_discover(i)
397 register int i;
399 /* Pre-discovered objects are now printed with a '*' */
400 return (boolean) (objects[i].oc_uname != (char *) 0
401 || (objects[i].oc_name_known
402 && OBJ_DESCR(objects[i]) != (char *) 0));
405 /* items that should stand out once they're known */
406 static short uniq_objs[] = {
407 AMULET_OF_YENDOR, SPE_BOOK_OF_THE_DEAD, CANDELABRUM_OF_INVOCATION,
408 BELL_OF_OPENING,
411 /* the '\' command - show discovered object types */
413 dodiscovered() /* free after Robert Viduya */
415 register int i, dis;
416 int ct = 0;
417 char *s, oclass, prev_class, classes[MAXOCLASSES], buf[BUFSZ];
418 winid tmpwin;
420 tmpwin = create_nhwindow(NHW_MENU);
421 putstr(tmpwin, 0, "Discoveries");
422 putstr(tmpwin, 0, "");
424 /* gather "unique objects" into a pseudo-class; note that they'll
425 also be displayed individually within their regular class */
426 for (i = dis = 0; i < SIZE(uniq_objs); i++)
427 if (objects[uniq_objs[i]].oc_name_known) {
428 if (!dis++)
429 putstr(tmpwin, iflags.menu_headings, "Unique items");
430 Sprintf(buf, " %s", OBJ_NAME(objects[uniq_objs[i]]));
431 putstr(tmpwin, 0, buf);
432 ++ct;
434 /* display any known artifacts as another pseudo-class */
435 ct += disp_artifact_discoveries(tmpwin);
437 /* several classes are omitted from packorder; one is of interest here */
438 Strcpy(classes, flags.inv_order);
439 if (!index(classes, VENOM_CLASS))
440 (void) strkitten(classes, VENOM_CLASS); /* append char to string */
442 for (s = classes; *s; s++) {
443 oclass = *s;
444 prev_class = oclass + 1; /* forced different from oclass */
445 for (i = bases[(int) oclass];
446 i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) {
447 if ((dis = disco[i]) != 0 && interesting_to_discover(dis)) {
448 ct++;
449 if (oclass != prev_class) {
450 putstr(tmpwin, iflags.menu_headings,
451 let_to_name(oclass, FALSE, FALSE));
452 prev_class = oclass;
454 Sprintf(buf, "%s %s",
455 (objects[dis].oc_pre_discovered ? "*" : " "),
456 obj_typename(dis));
457 putstr(tmpwin, 0, buf);
461 if (ct == 0) {
462 You("haven't discovered anything yet...");
463 } else
464 display_nhwindow(tmpwin, TRUE);
465 destroy_nhwindow(tmpwin);
467 return 0;
470 /* lower case let_to_name() output, which differs from def_oc_syms[].name */
471 STATIC_OVL char *
472 oclass_to_name(oclass, buf)
473 char oclass;
474 char *buf;
476 char *s;
478 Strcpy(buf, let_to_name(oclass, FALSE, FALSE));
479 for (s = buf; *s; ++s)
480 *s = lowc(*s);
481 return buf;
484 /* the '`' command - show discovered object types for one class */
486 doclassdisco()
488 static NEARDATA const char
489 prompt[] = "View discoveries for which sort of objects?",
490 havent_discovered_any[] = "haven't discovered any %s yet.",
491 unique_items[] = "unique items",
492 artifact_items[] = "artifacts";
493 char *s, c, oclass, menulet, allclasses[MAXOCLASSES],
494 discosyms[2 + MAXOCLASSES + 1], buf[BUFSZ];
495 int i, ct, dis, xtras;
496 boolean traditional;
497 winid tmpwin = WIN_ERR;
498 anything any;
499 menu_item *pick_list = 0;
501 discosyms[0] = '\0';
502 traditional = (flags.menu_style == MENU_TRADITIONAL
503 || flags.menu_style == MENU_COMBINATION);
504 if (!traditional) {
505 tmpwin = create_nhwindow(NHW_MENU);
506 start_menu(tmpwin);
508 any = zeroany;
509 menulet = 'a';
511 /* check whether we've discovered any unique objects */
512 for (i = 0; i < SIZE(uniq_objs); i++)
513 if (objects[uniq_objs[i]].oc_name_known) {
514 Strcat(discosyms, "u");
515 if (!traditional) {
516 any.a_int = 'u';
517 add_menu(tmpwin, NO_GLYPH, &any, menulet++, 0, ATR_NONE,
518 unique_items, MENU_UNSELECTED);
520 break;
523 /* check whether we've discovered any artifacts */
524 if (disp_artifact_discoveries(WIN_ERR) > 0) {
525 Strcat(discosyms, "a");
526 if (!traditional) {
527 any.a_int = 'a';
528 add_menu(tmpwin, NO_GLYPH, &any, menulet++, 0, ATR_NONE,
529 artifact_items, MENU_UNSELECTED);
533 /* collect classes with discoveries, in packorder ordering; several
534 classes are omitted from packorder and one is of interest here */
535 Strcpy(allclasses, flags.inv_order);
536 if (!index(allclasses, VENOM_CLASS))
537 (void) strkitten(allclasses, VENOM_CLASS); /* append char to string */
538 /* construct discosyms[] */
539 for (s = allclasses; *s; ++s) {
540 oclass = *s;
541 c = def_oc_syms[(int) oclass].sym;
542 for (i = bases[(int) oclass];
543 i < NUM_OBJECTS && objects[i].oc_class == oclass; ++i)
544 if ((dis = disco[i]) != 0 && interesting_to_discover(dis)) {
545 if (!index(discosyms, c)) {
546 Sprintf(eos(discosyms), "%c", c);
547 if (!traditional) {
548 any.a_int = c;
549 add_menu(tmpwin, NO_GLYPH, &any, menulet++, c,
550 ATR_NONE, oclass_to_name(oclass, buf),
551 MENU_UNSELECTED);
557 /* there might not be anything for us to do... */
558 if (!discosyms[0]) {
559 You(havent_discovered_any, "items");
560 if (tmpwin != WIN_ERR)
561 destroy_nhwindow(tmpwin);
562 return 0;
565 /* have player choose a class */
566 c = '\0'; /* class not chosen yet */
567 if (traditional) {
568 /* we'll prompt even if there's only one viable class; we add all
569 nonviable classes as unseen acceptable choices so player can ask
570 for discoveries of any class whether it has discoveries or not */
571 for (s = allclasses, xtras = 0; *s; ++s) {
572 c = def_oc_syms[(int) *s].sym;
573 if (!index(discosyms, c)) {
574 if (!xtras++)
575 (void) strkitten(discosyms, '\033');
576 (void) strkitten(discosyms, c);
579 /* get the class (via its symbol character) */
580 c = yn_function(prompt, discosyms, '\0');
581 savech(c);
582 if (!c)
583 clear_nhwindow(WIN_MESSAGE);
584 } else {
585 /* menustyle:full or menustyle:partial */
586 if (!discosyms[1] && flags.menu_style == MENU_PARTIAL) {
587 /* only one class; menustyle:partial normally jumps past class
588 filtering straight to final menu so skip class filter here */
589 c = discosyms[0];
590 } else {
591 /* more than one choice, or menustyle:full which normally has
592 an intermediate class selection menu before the final menu */
593 end_menu(tmpwin, prompt);
594 i = select_menu(tmpwin, PICK_ONE, &pick_list);
595 if (i > 0) {
596 c = pick_list[0].item.a_int;
597 free((genericptr_t) pick_list);
598 } /* else c stays 0 */
600 destroy_nhwindow(tmpwin);
602 if (!c)
603 return 0; /* player declined to make a selection */
606 * show discoveries for object class c
608 tmpwin = create_nhwindow(NHW_MENU);
609 ct = 0;
610 switch (c) {
611 case 'u':
612 putstr(tmpwin, iflags.menu_headings,
613 upstart(strcpy(buf, unique_items)));
614 for (i = 0; i < SIZE(uniq_objs); i++)
615 if (objects[uniq_objs[i]].oc_name_known) {
616 Sprintf(buf, " %s", OBJ_NAME(objects[uniq_objs[i]]));
617 putstr(tmpwin, 0, buf);
618 ++ct;
620 if (!ct)
621 You(havent_discovered_any, unique_items);
622 break;
623 case 'a':
624 /* disp_artifact_discoveries() includes a header */
625 ct = disp_artifact_discoveries(tmpwin);
626 if (!ct)
627 You(havent_discovered_any, artifact_items);
628 break;
629 default:
630 oclass = def_char_to_objclass(c);
631 Sprintf(buf, "Discovered %s", let_to_name(oclass, FALSE, FALSE));
632 putstr(tmpwin, iflags.menu_headings, buf);
633 for (i = bases[(int) oclass];
634 i < NUM_OBJECTS && objects[i].oc_class == oclass; ++i) {
635 if ((dis = disco[i]) != 0 && interesting_to_discover(dis)) {
636 Sprintf(buf, "%s %s",
637 objects[dis].oc_pre_discovered ? "*" : " ",
638 obj_typename(dis));
639 putstr(tmpwin, 0, buf);
640 ++ct;
643 if (!ct)
644 You(havent_discovered_any, oclass_to_name(oclass, buf));
645 break;
647 if (ct)
648 display_nhwindow(tmpwin, TRUE);
649 destroy_nhwindow(tmpwin);
650 return 0;
653 /* put up nameable subset of discoveries list as a menu */
654 void
655 rename_disco()
657 register int i, dis;
658 int ct = 0, mn = 0, sl;
659 char *s, oclass, prev_class;
660 winid tmpwin;
661 anything any;
662 menu_item *selected = 0;
664 any = zeroany;
665 tmpwin = create_nhwindow(NHW_MENU);
666 start_menu(tmpwin);
669 * Skip the "unique objects" section (each will appear within its
670 * regular class if it is nameable) and the artifacts section.
671 * We assume that classes omitted from packorder aren't nameable
672 * so we skip venom too.
675 /* for each class, show discoveries in that class */
676 for (s = flags.inv_order; *s; s++) {
677 oclass = *s;
678 prev_class = oclass + 1; /* forced different from oclass */
679 for (i = bases[(int) oclass];
680 i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) {
681 dis = disco[i];
682 if (!dis || !interesting_to_discover(dis))
683 continue;
684 ct++;
685 if (!objtyp_is_callable(dis))
686 continue;
687 mn++;
689 if (oclass != prev_class) {
690 any.a_int = 0;
691 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
692 let_to_name(oclass, FALSE, FALSE),
693 MENU_UNSELECTED);
694 prev_class = oclass;
696 any.a_int = dis;
697 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
698 obj_typename(dis), MENU_UNSELECTED);
701 if (ct == 0) {
702 You("haven't discovered anything yet...");
703 } else if (mn == 0) {
704 pline("None of your discoveries can be assigned names...");
705 } else {
706 end_menu(tmpwin, "Pick an object type to name");
707 dis = STRANGE_OBJECT;
708 sl = select_menu(tmpwin, PICK_ONE, &selected);
709 if (sl > 0) {
710 dis = selected[0].item.a_int;
711 free((genericptr_t) selected);
713 if (dis != STRANGE_OBJECT) {
714 struct obj odummy;
716 odummy = zeroobj;
717 odummy.otyp = dis;
718 odummy.oclass = objects[dis].oc_class;
719 odummy.quan = 1L;
720 odummy.known = !objects[dis].oc_uses_known;
721 odummy.dknown = 1;
722 docall(&odummy);
725 destroy_nhwindow(tmpwin);
726 return;
729 /*o_init.c*/