1 /* NetHack 3.6 o_init.c $NHDT-Date: 1674864731 2023/01/28 00:12:11 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.27 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2022 */
9 /* JNetHack may be freely redistributed. See license for details. */
12 #include "lev.h" /* save & restore info */
14 STATIC_DCL void FDECL(setgemprobs, (d_level *));
15 STATIC_DCL void FDECL(shuffle, (int, int, BOOLEAN_P));
16 STATIC_DCL void NDECL(shuffle_all);
17 STATIC_DCL boolean FDECL(interesting_to_discover, (int));
18 STATIC_DCL void FDECL(disco_append_typename, (char *, int));
19 STATIC_DCL char *FDECL(oclass_to_name, (CHAR_P, char *));
21 static NEARDATA short disco[NUM_OBJECTS] = DUMMY;
24 STATIC_DCL void NDECL(shuffle_tiles);
25 extern short glyph2tile[]; /* from tile.c */
27 /* Shuffle tile assignments to match descriptions, so a red potion isn't
28 * displayed with a blue tile and so on.
30 * Tile assignments are not saved, and shouldn't be so that a game can
31 * be resumed on an otherwise identical non-tile-using binary, so we have
32 * to reshuffle the assignments from oc_descr_idx information when a game
33 * is restored. So might as well do that the first time instead of writing
40 short tmp_tilemap[NUM_OBJECTS];
42 for (i = 0; i < NUM_OBJECTS; i++)
43 tmp_tilemap[i] = glyph2tile[objects[i].oc_descr_idx + GLYPH_OBJ_OFF];
45 for (i = 0; i < NUM_OBJECTS; i++)
46 glyph2tile[i + GLYPH_OBJ_OFF] = tmp_tilemap[i];
48 #endif /* USE_TILES */
57 lev = (ledger_no(dlev) > maxledgerno()) ? maxledgerno()
61 first = bases[GEM_CLASS];
63 for (j = 0; j < 9 - lev / 3; j++)
64 objects[first + j].oc_prob = 0;
66 if (first > LAST_GEM || objects[first].oc_class != GEM_CLASS
67 || OBJ_NAME(objects[first]) == (char *) 0) {
68 raw_printf("Not enough gems? - first=%d j=%d LAST_GEM=%d", first, j,
72 for (j = first; j <= LAST_GEM; j++)
73 objects[j].oc_prob = (171 + j - first) / (LAST_GEM + 1 - first);
76 /* shuffle descriptions on objects o_low to o_high */
78 shuffle(o_low, o_high, domaterial)
82 int i, j, num_to_shuffle;
86 for (num_to_shuffle = 0, j = o_low; j <= o_high; j++)
87 if (!objects[j].oc_name_known)
89 if (num_to_shuffle < 2)
92 for (j = o_low; j <= o_high; j++) {
93 if (objects[j].oc_name_known)
96 i = j + rn2(o_high - j + 1);
97 while (objects[i].oc_name_known);
98 sw = objects[j].oc_descr_idx;
99 objects[j].oc_descr_idx = objects[i].oc_descr_idx;
100 objects[i].oc_descr_idx = sw;
101 sw = objects[j].oc_tough;
102 objects[j].oc_tough = objects[i].oc_tough;
103 objects[i].oc_tough = sw;
104 color = objects[j].oc_color;
105 objects[j].oc_color = objects[i].oc_color;
106 objects[i].oc_color = color;
108 /* shuffle material */
110 sw = objects[j].oc_material;
111 objects[j].oc_material = objects[i].oc_material;
112 objects[i].oc_material = sw;
120 register int i, first, last, sum;
121 register char oclass;
123 #define COPY_OBJ_DESCR(o_dst, o_src) \
124 o_dst.oc_descr_idx = o_src.oc_descr_idx, o_dst.oc_color = o_src.oc_color
126 #define COPY_OBJ_DESCR(o_dst, o_src) o_dst.oc_descr_idx = o_src.oc_descr_idx
129 /* bug fix to prevent "initialization error" abort on Intel Xenix.
130 * reported by mikew@semike
132 for (i = 0; i < MAXOCLASSES; i++)
134 /* initialize object descriptions */
135 for (i = 0; i < NUM_OBJECTS; i++)
136 objects[i].oc_name_idx = objects[i].oc_descr_idx = i;
137 /* init base; if probs given check that they add up to 1000,
138 otherwise compute probs */
140 while (first < NUM_OBJECTS) {
141 oclass = objects[first].oc_class;
143 while (last < NUM_OBJECTS && objects[last].oc_class == oclass)
145 bases[(int) oclass] = first;
147 if (oclass == GEM_CLASS) {
148 setgemprobs((d_level *) 0);
150 if (rn2(2)) { /* change turquoise from green to blue? */
151 COPY_OBJ_DESCR(objects[TURQUOISE], objects[SAPPHIRE]);
153 if (rn2(2)) { /* change aquamarine from green to blue? */
154 COPY_OBJ_DESCR(objects[AQUAMARINE], objects[SAPPHIRE]);
156 switch (rn2(4)) { /* change fluorite from violet? */
160 COPY_OBJ_DESCR(objects[FLUORITE], objects[SAPPHIRE]);
163 COPY_OBJ_DESCR(objects[FLUORITE], objects[DIAMOND]);
166 COPY_OBJ_DESCR(objects[FLUORITE], objects[EMERALD]);
172 for (i = first; i < last; i++)
173 sum += objects[i].oc_prob;
175 for (i = first; i < last; i++)
176 objects[i].oc_prob = (1000 + i - first) / (last - first);
180 error("init-prob error for class %d (%d%%)", oclass, sum);
183 /* shuffle descriptions */
188 objects[WAN_NOTHING].oc_dir = rn2(2) ? NODIR : IMMEDIATE;
191 /* retrieve the range of objects that otyp shares descriptions with */
193 obj_shuffle_range(otyp, lo_p, hi_p)
194 int otyp; /* input: representative item */
195 int *lo_p, *hi_p; /* output: range that item belongs among */
197 int i, ocls = objects[otyp].oc_class;
199 /* default is just the object itself */
200 *lo_p = *hi_p = otyp;
204 if (otyp >= HELMET && otyp <= HELM_OF_TELEPATHY)
205 *lo_p = HELMET, *hi_p = HELM_OF_TELEPATHY;
206 else if (otyp >= LEATHER_GLOVES && otyp <= GAUNTLETS_OF_DEXTERITY)
207 *lo_p = LEATHER_GLOVES, *hi_p = GAUNTLETS_OF_DEXTERITY;
208 else if (otyp >= CLOAK_OF_PROTECTION && otyp <= CLOAK_OF_DISPLACEMENT)
209 *lo_p = CLOAK_OF_PROTECTION, *hi_p = CLOAK_OF_DISPLACEMENT;
210 else if (otyp >= SPEED_BOOTS && otyp <= LEVITATION_BOOTS)
211 *lo_p = SPEED_BOOTS, *hi_p = LEVITATION_BOOTS;
214 /* potion of water has the only fixed description */
215 *lo_p = bases[POTION_CLASS];
216 *hi_p = POT_WATER - 1;
221 /* exclude non-magic types and also unique ones */
223 for (i = *lo_p; objects[i].oc_class == ocls; i++)
224 if (objects[i].oc_unique || !objects[i].oc_magic)
233 for (i = *lo_p; objects[i].oc_class == ocls; i++)
239 /* artifact checking might ask about item which isn't part of any range
240 but fell within the classes that do have ranges specified above */
241 if (otyp < *lo_p || otyp > *hi_p)
242 *lo_p = *hi_p = otyp;
246 /* randomize object descriptions */
250 /* entire classes; obj_shuffle_range() handles their exceptions */
251 static char shuffle_classes[] = {
252 AMULET_CLASS, POTION_CLASS, RING_CLASS, SCROLL_CLASS,
253 SPBOOK_CLASS, WAND_CLASS, VENOM_CLASS,
255 /* sub-class type ranges (one item from each group) */
256 static short shuffle_types[] = {
257 HELMET, LEATHER_GLOVES, CLOAK_OF_PROTECTION, SPEED_BOOTS,
259 int first, last, idx;
261 /* do whole classes (amulets, &c) */
262 for (idx = 0; idx < SIZE(shuffle_classes); idx++) {
263 obj_shuffle_range(bases[(int) shuffle_classes[idx]], &first, &last);
264 shuffle(first, last, TRUE);
266 /* do type ranges (helms, &c) */
267 for (idx = 0; idx < SIZE(shuffle_types); idx++) {
268 obj_shuffle_range(shuffle_types[idx], &first, &last);
269 shuffle(first, last, FALSE);
274 /* find the object index for snow boots; used [once] by slippery ice code */
279 register const char *s;
281 for (i = SPEED_BOOTS; i <= LEVITATION_BOOTS; i++)
283 if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "snow boots"))
285 if ((s = OBJ_DESCR(objects[i])) != 0 && !strcmp(s, "
\90á
\8cC"))
288 impossible("snow boots not found?");
289 return -1; /* not 0, or caller would try again each move */
292 /* level dependent initialization */
306 if (perform_bwrite(mode)) {
307 bwrite(fd, (genericptr_t) bases, sizeof bases);
308 bwrite(fd, (genericptr_t) disco, sizeof disco);
309 bwrite(fd, (genericptr_t) objects,
310 sizeof(struct objclass) * NUM_OBJECTS);
312 /* as long as we use only one version of Hack we
313 need not save oc_name and oc_descr, but we must save
314 oc_uname for all objects */
315 for (i = 0; i < NUM_OBJECTS; i++)
316 if (objects[i].oc_uname) {
317 if (perform_bwrite(mode)) {
318 len = strlen(objects[i].oc_uname) + 1;
319 bwrite(fd, (genericptr_t) &len, sizeof len);
320 bwrite(fd, (genericptr_t) objects[i].oc_uname, len);
322 if (release_data(mode)) {
323 free((genericptr_t) objects[i].oc_uname);
324 objects[i].oc_uname = 0;
336 mread(fd, (genericptr_t) bases, sizeof bases);
337 mread(fd, (genericptr_t) disco, sizeof disco);
338 mread(fd, (genericptr_t) objects, sizeof(struct objclass) * NUM_OBJECTS);
339 for (i = 0; i < NUM_OBJECTS; i++)
340 if (objects[i].oc_uname) {
341 mread(fd, (genericptr_t) &len, sizeof len);
342 objects[i].oc_uname = (char *) alloc(len);
343 mread(fd, (genericptr_t) objects[i].oc_uname, len);
351 discover_object(oindx, mark_as_known, credit_hero)
353 boolean mark_as_known;
356 if (!objects[oindx].oc_name_known) {
357 register int dindx, acls = objects[oindx].oc_class;
359 /* Loop thru disco[] 'til we find the target (which may have been
360 uname'd) or the next open slot; one or the other will be found
361 before we reach the next class...
363 for (dindx = bases[acls]; disco[dindx] != 0; dindx++)
364 if (disco[dindx] == oindx)
366 disco[dindx] = oindx;
369 objects[oindx].oc_name_known = 1;
371 exercise(A_WIS, TRUE);
373 /* moves==1L => initial inventory, gameover => final disclosure */
374 if (moves > 1L && !program_state.gameover) {
375 if (objects[oindx].oc_class == GEM_CLASS)
376 gem_learned(oindx); /* could affect price of unpaid gems */
382 /* if a class name has been cleared, we may need to purge it from disco[] */
384 undiscover_object(oindx)
387 if (!objects[oindx].oc_name_known) {
388 register int dindx, acls = objects[oindx].oc_class;
389 register boolean found = FALSE;
391 /* find the object; shift those behind it forward one slot */
392 for (dindx = bases[acls]; dindx < NUM_OBJECTS && disco[dindx] != 0
393 && objects[dindx].oc_class == acls;
396 disco[dindx - 1] = disco[dindx];
397 else if (disco[dindx] == oindx)
400 /* clear last slot */
402 disco[dindx - 1] = 0;
404 impossible("named object not in disco");
406 if (objects[oindx].oc_class == GEM_CLASS)
407 gem_learned(oindx); /* ok, it's actually been unlearned */
413 interesting_to_discover(i)
416 /* Pre-discovered objects are now printed with a '*' */
417 return (boolean) (objects[i].oc_uname != (char *) 0
418 || (objects[i].oc_name_known
419 && OBJ_DESCR(objects[i]) != (char *) 0));
422 /* items that should stand out once they're known */
423 static short uniq_objs[] = {
424 AMULET_OF_YENDOR, SPE_BOOK_OF_THE_DEAD, CANDELABRUM_OF_INVOCATION,
428 /* append typename(dis) to buf[], possibly truncating in the process */
430 disco_append_typename(buf, dis)
434 unsigned len = (unsigned) strlen(buf);
435 char *p, *typnm = obj_typename(dis);
437 if (len + (unsigned) strlen(typnm) < BUFSZ) {
440 } else if ((p = rindex(typnm, '(')) != 0
441 && p > typnm && p[-1] == ' ' && index(p, ')') != 0) {
442 /* typename() returned "really long user-applied name (actual type)"
443 and we want to truncate from "really long user-applied name" while
444 keeping " (actual type)" intact */
445 --p; /* back up to space in front of open paren */
446 (void) strncat(buf, typnm, BUFSZ - 1 - (len + (unsigned) strlen(p)));
449 /* unexpected; just truncate from end of typename */
450 (void) strncat(buf, typnm, BUFSZ - 1 - len);
454 /* the '\' command - show discovered object types */
456 dodiscovered() /* free after Robert Viduya */
460 char *s, oclass, prev_class, classes[MAXOCLASSES], buf[BUFSZ];
463 tmpwin = create_nhwindow(NHW_MENU);
465 putstr(tmpwin, 0, "Discoveries");
467 putstr(tmpwin, 0, "
\94
\8c©
\95¨
\88ê
\97\97");
468 putstr(tmpwin, 0, "");
470 /* gather "unique objects" into a pseudo-class; note that they'll
471 also be displayed individually within their regular class */
472 for (i = dis = 0; i < SIZE(uniq_objs); i++)
473 if (objects[uniq_objs[i]].oc_name_known) {
476 putstr(tmpwin, iflags.menu_headings, "Unique items");
478 putstr(tmpwin, iflags.menu_headings, "
\93Á
\8eê
\83A
\83C
\83e
\83\80");
479 Sprintf(buf, " %s", OBJ_NAME(objects[uniq_objs[i]]));
480 putstr(tmpwin, 0, buf);
483 /* display any known artifacts as another pseudo-class */
484 ct += disp_artifact_discoveries(tmpwin);
486 /* several classes are omitted from packorder; one is of interest here */
487 Strcpy(classes, flags.inv_order);
488 if (!index(classes, VENOM_CLASS))
489 (void) strkitten(classes, VENOM_CLASS); /* append char to string */
491 for (s = classes; *s; s++) {
493 prev_class = oclass + 1; /* forced different from oclass */
494 for (i = bases[(int) oclass];
495 i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) {
496 if ((dis = disco[i]) != 0 && interesting_to_discover(dis)) {
498 if (oclass != prev_class) {
499 putstr(tmpwin, iflags.menu_headings,
500 let_to_name(oclass, FALSE, FALSE));
503 Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
504 disco_append_typename(buf, dis);
505 putstr(tmpwin, 0, buf);
511 You("haven't discovered anything yet...");
513 You("
\82Ü
\82¾
\89½
\82à
\94
\8c©
\82µ
\82Ä
\82¢
\82È
\82¢
\81D
\81D
\81D");
515 display_nhwindow(tmpwin, TRUE);
516 destroy_nhwindow(tmpwin);
521 /* lower case let_to_name() output, which differs from def_oc_syms[].name */
523 oclass_to_name(oclass, buf)
527 #if 0 /*JP*//*
\8eg
\82í
\82È
\82¢*/
531 Strcpy(buf, let_to_name(oclass, FALSE, FALSE));
532 #if 0 /*JP*//*
\8f¬
\95¶
\8e\9a\89»
\82µ
\82È
\82¢*/
533 for (s = buf; *s; ++s)
539 /* the '`' command - show discovered object types for one class */
543 static NEARDATA const char
545 prompt[] = "View discoveries for which sort of objects?",
547 prompt[] = "
\82Ç
\82Ì
\8eí
\97Þ
\82Ì
\94
\8c©
\95¨
\82ð
\8c©
\82Ü
\82·
\82©
\81H",
549 havent_discovered_any[] = "haven't discovered any %s yet.",
551 havent_discovered_any[] = "
\82Ü
\82¾
\89½
\82à%s
\82ð
\94
\8c©
\82µ
\82Ä
\82¢
\82È
\82¢
\81D",
553 unique_items[] = "unique items",
555 unique_items[] = "
\93Á
\8eê
\83A
\83C
\83e
\83\80",
557 artifact_items[] = "artifacts";
559 artifact_items[] = "
\90¹
\8aí";
560 char *s, c, oclass, menulet, allclasses[MAXOCLASSES],
561 discosyms[2 + MAXOCLASSES + 1], buf[BUFSZ];
562 int i, ct, dis, xtras;
564 winid tmpwin = WIN_ERR;
566 menu_item *pick_list = 0;
569 traditional = (flags.menu_style == MENU_TRADITIONAL
570 || flags.menu_style == MENU_COMBINATION);
572 tmpwin = create_nhwindow(NHW_MENU);
578 /* check whether we've discovered any unique objects */
579 for (i = 0; i < SIZE(uniq_objs); i++)
580 if (objects[uniq_objs[i]].oc_name_known) {
581 Strcat(discosyms, "u");
584 add_menu(tmpwin, NO_GLYPH, &any, menulet++, 0, ATR_NONE,
585 unique_items, MENU_UNSELECTED);
590 /* check whether we've discovered any artifacts */
591 if (disp_artifact_discoveries(WIN_ERR) > 0) {
592 Strcat(discosyms, "a");
595 add_menu(tmpwin, NO_GLYPH, &any, menulet++, 0, ATR_NONE,
596 artifact_items, MENU_UNSELECTED);
600 /* collect classes with discoveries, in packorder ordering; several
601 classes are omitted from packorder and one is of interest here */
602 Strcpy(allclasses, flags.inv_order);
603 if (!index(allclasses, VENOM_CLASS))
604 (void) strkitten(allclasses, VENOM_CLASS); /* append char to string */
605 /* construct discosyms[] */
606 for (s = allclasses; *s; ++s) {
608 c = def_oc_syms[(int) oclass].sym;
609 for (i = bases[(int) oclass];
610 i < NUM_OBJECTS && objects[i].oc_class == oclass; ++i)
611 if ((dis = disco[i]) != 0 && interesting_to_discover(dis)) {
612 if (!index(discosyms, c)) {
613 Sprintf(eos(discosyms), "%c", c);
616 add_menu(tmpwin, NO_GLYPH, &any, menulet++, c,
617 ATR_NONE, oclass_to_name(oclass, buf),
624 /* there might not be anything for us to do... */
627 You(havent_discovered_any, "items");
629 You(havent_discovered_any, "
\83A
\83C
\83e
\83\80");
630 if (tmpwin != WIN_ERR)
631 destroy_nhwindow(tmpwin);
635 /* have player choose a class */
636 c = '\0'; /* class not chosen yet */
638 /* we'll prompt even if there's only one viable class; we add all
639 nonviable classes as unseen acceptable choices so player can ask
640 for discoveries of any class whether it has discoveries or not */
641 for (s = allclasses, xtras = 0; *s; ++s) {
642 c = def_oc_syms[(int) *s].sym;
643 if (!index(discosyms, c)) {
645 (void) strkitten(discosyms, '\033');
646 (void) strkitten(discosyms, c);
649 /* get the class (via its symbol character) */
650 c = yn_function(prompt, discosyms, '\0');
653 clear_nhwindow(WIN_MESSAGE);
655 /* menustyle:full or menustyle:partial */
656 if (!discosyms[1] && flags.menu_style == MENU_PARTIAL) {
657 /* only one class; menustyle:partial normally jumps past class
658 filtering straight to final menu so skip class filter here */
661 /* more than one choice, or menustyle:full which normally has
662 an intermediate class selection menu before the final menu */
663 end_menu(tmpwin, prompt);
664 i = select_menu(tmpwin, PICK_ONE, &pick_list);
666 c = pick_list[0].item.a_int;
667 free((genericptr_t) pick_list);
668 } /* else c stays 0 */
670 destroy_nhwindow(tmpwin);
673 return 0; /* player declined to make a selection */
676 * show discoveries for object class c
678 tmpwin = create_nhwindow(NHW_MENU);
682 putstr(tmpwin, iflags.menu_headings,
683 upstart(strcpy(buf, unique_items)));
684 for (i = 0; i < SIZE(uniq_objs); i++)
685 if (objects[uniq_objs[i]].oc_name_known) {
686 Sprintf(buf, " %s", OBJ_NAME(objects[uniq_objs[i]]));
687 putstr(tmpwin, 0, buf);
691 You(havent_discovered_any, unique_items);
694 /* disp_artifact_discoveries() includes a header */
695 ct = disp_artifact_discoveries(tmpwin);
697 You(havent_discovered_any, artifact_items);
700 oclass = def_char_to_objclass(c);
702 Sprintf(buf, "Discovered %s", let_to_name(oclass, FALSE, FALSE));
704 Sprintf(buf, "
\94
\8c©
\82µ
\82½%s", let_to_name(oclass, FALSE, FALSE));
705 putstr(tmpwin, iflags.menu_headings, buf);
706 for (i = bases[(int) oclass];
707 i < NUM_OBJECTS && objects[i].oc_class == oclass; ++i) {
708 if ((dis = disco[i]) != 0 && interesting_to_discover(dis)) {
709 Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
710 disco_append_typename(buf, dis);
711 putstr(tmpwin, 0, buf);
716 You(havent_discovered_any, oclass_to_name(oclass, buf));
720 display_nhwindow(tmpwin, TRUE);
721 destroy_nhwindow(tmpwin);
725 /* put up nameable subset of discoveries list as a menu */
730 int ct = 0, mn = 0, sl;
731 char *s, oclass, prev_class;
734 menu_item *selected = 0;
737 tmpwin = create_nhwindow(NHW_MENU);
741 * Skip the "unique objects" section (each will appear within its
742 * regular class if it is nameable) and the artifacts section.
743 * We assume that classes omitted from packorder aren't nameable
744 * so we skip venom too.
747 /* for each class, show discoveries in that class */
748 for (s = flags.inv_order; *s; s++) {
750 prev_class = oclass + 1; /* forced different from oclass */
751 for (i = bases[(int) oclass];
752 i < NUM_OBJECTS && objects[i].oc_class == oclass; i++) {
754 if (!dis || !interesting_to_discover(dis))
757 if (!objtyp_is_callable(dis))
761 if (oclass != prev_class) {
763 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
764 let_to_name(oclass, FALSE, FALSE),
769 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
770 obj_typename(dis), MENU_UNSELECTED);
775 You("haven't discovered anything yet...");
777 You("
\82Ü
\82¾
\89½
\82à
\94
\8c©
\82µ
\82Ä
\82¢
\82È
\82¢
\81D
\81D
\81D");
778 } else if (mn == 0) {
780 pline("None of your discoveries can be assigned names...");
782 pline("
\96¼
\91O
\82Ì
\95t
\82¯
\82ç
\82ê
\82é
\94
\8c©
\95¨
\82Í
\82È
\82¢
\81D
\81D
\81D");
785 end_menu(tmpwin, "Pick an object type to name");
787 end_menu(tmpwin, "
\96¼
\91O
\82ð
\95t
\82¯
\82é
\83I
\83u
\83W
\83F
\83N
\83g
\82Ì
\8eí
\97Þ
\82ð
\91I
\82ñ
\82Å
\82
\82¾
\82³
\82¢");
788 dis = STRANGE_OBJECT;
789 sl = select_menu(tmpwin, PICK_ONE, &selected);
791 dis = selected[0].item.a_int;
792 free((genericptr_t) selected);
794 if (dis != STRANGE_OBJECT) {
799 odummy.oclass = objects[dis].oc_class;
801 odummy.known = !objects[dis].oc_uses_known;
806 destroy_nhwindow(tmpwin);