root/trunk/src/squelch.c

Revision 171, 18.0 kB (checked in by takkaria, 3 years ago)
  • Dump squelch and autoinscribe settings as part of the options dump.
  • Make version numbers more centralised
  • Nuke MAINTAINER define, update bugs address
Line 
1 /*
2  * File: squelch.c
3  * Purpose: Item destruction
4  *
5  * Copyright (c) 2007 David T. Blackston, Iain McFall, DarkGod, Jeff Greene,
6  * David Vestal, Pete Mack, Andrew Sidwell.
7  *
8  * This work is free software; you can redistribute it and/or modify it
9  * under the terms of either:
10  *
11  * a) the GNU General Public License as published by the Free Software
12  *    Foundation, version 2, or
13  *
14  * b) the "Angband licence":
15  *    This software may be copied and distributed for educational, research,
16  *    and not for profit purposes provided that this copyright and statement
17  *    are included in all such copies.  Other copyrights may also apply.
18  */
19 #include "angband.h"
20
21 /*
22  * The squelch code has a long history.  Originally it started out as a simple
23  * sval-dependent item destroyer, but then ego-item and quality squelch was
24  * added too, and then squelched items on the dungeon floor were marked by
25  * purple dots, and by this time the code was quite unmaintainable and pretty
26  * much impossible to work with.
27  *
28  * Luckily, though, it's been cleaned up.  Here's a quick overview of the
29  * options available now:
30  *
31  * Squelched items are not automatically destroyed -- they're instead marked
32  * "{squelch}", and destroyed with a special command on the "item destruction"
33  * screen.  This is much cleaner.
34  *
35  * There is now only sval-dependent squelch and quality-based squelch, and the
36  * two don't interact -- quality-based is for items that get pseudo-id'd and
37  * sval-dependent is for potions and the like.
38  *
39  * The squelch code figures most things out itself.  If you want to make the
40  * code see if it should add the squelch flag to an object, simply call
41  * squelch_set(o_ptr), and it will do the rest.
42  *
43  * The quality-dependent squelch is much reduced in scope from how it used to
44  * be.  If less "general" settings are desired, they can be added easily enough
45  * by changing entries in type_tvals[][], adding more TYPE_* constants, and
46  * updating type_names.  Savefile compatibility is automatically ensured.
47  *
48  *
49  * The UI code is much cleaner than it was before, but the interface itself
50  * still needs some design.  XXX
51  */
52
53
54 /*
55  * List of kinds of item, for pseudo-id squelch.
56  */
57 enum
58 {
59         TYPE_WEAPON,
60         TYPE_SHOOTER,
61         TYPE_MISSILE,
62         TYPE_ARMOR,
63         TYPE_JEWELRY,
64         TYPE_DIGGER,
65
66         TYPE_MAX
67 };
68
69 /*
70  * Names of categories.
71  */
72 static const char *type_names[TYPE_MAX] =
73 {
74         "Melee weapons",
75         "Missile weapons",
76         "Ammunition",
77         "Armor",
78         "Jewelry",
79         "Diggers",
80 };
81
82 /* Mapping of tval -> type */
83 static int type_tvals[][2] =
84 {
85         { TYPE_WEAPON,  TV_SWORD },
86         { TYPE_WEAPON,  TV_POLEARM },
87         { TYPE_WEAPON,  TV_HAFTED },
88         { TYPE_SHOOTER, TV_BOW },
89         { TYPE_MISSILE, TV_ARROW },
90         { TYPE_MISSILE, TV_BOLT },
91         { TYPE_MISSILE, TV_SHOT },
92         { TYPE_ARMOR,   TV_SHIELD },
93         { TYPE_ARMOR,   TV_HELM },
94         { TYPE_ARMOR,   TV_GLOVES },
95         { TYPE_ARMOR,   TV_BOOTS },
96         { TYPE_ARMOR,   TV_DRAG_ARMOR },
97         { TYPE_ARMOR,   TV_HARD_ARMOR },
98         { TYPE_ARMOR,   TV_SOFT_ARMOR },
99         { TYPE_ARMOR,   TV_CLOAK },
100         { TYPE_ARMOR,   TV_CROWN },
101         { TYPE_JEWELRY, TV_RING },
102         { TYPE_JEWELRY, TV_AMULET },
103         { TYPE_DIGGER,  TV_DIGGING },
104 };
105
106 byte squelch_level[TYPE_MAX];
107 size_t squelch_size = TYPE_MAX;
108
109
110 /*
111  * The different kinds of quality squelch
112  */
113 enum
114 {
115         SQUELCH_NONE,
116         SQUELCH_CURSED,
117         SQUELCH_AVERAGE,
118         SQUELCH_GOOD_STRONG,
119         SQUELCH_GOOD_WEAK,
120         SQUELCH_ALL,
121
122         SQUELCH_MAX
123 };
124
125 /*
126  * The names for the various kinds of quality
127  */
128 static const char *quality_names[SQUELCH_MAX] =
129 {
130         "none",                                                 /* SQUELCH_NONE */
131         "cursed",                                               /* SQUELCH_CURSED */
132         "average",                                              /* SQUELCH_AVERAGE */
133         "good (strong pseudo-ID)",              /* SQUELCH_GOOD_STRONG */
134         "good (weak pseudo-ID)",                /* SQUELCH_GOOD_WEAK */
135         "everything except artifacts"/* SQUELCH_ALL */
136 };
137
138
139 /* Structure to describe tval/description pairings. */
140 typedef struct
141 {
142         int tval;
143         const char *desc;
144 } tval_desc;
145
146 /* Categories for sval-dependent squelch. */
147 static tval_desc sval_dependent[] =
148 {
149         { TV_STAFF,             "Staffs" },
150         { TV_WAND,              "Wands" },
151         { TV_ROD,               "Rods" },
152         { TV_SCROLL,    "Scrolls" },
153         { TV_POTION,    "Potions" },
154         { TV_RING,              "Rings" },
155         { TV_AMULET,    "Amulets" },
156         { TV_FOOD,              "Food" }
157 };
158
159
160 /*** Autoinscription stuff ***/
161
162 /*
163  * This code needs documenting.
164  */
165 int get_autoinscription_index(s16b k_idx)
166 {
167         int i;
168
169         for (i = 0; i < inscriptions_count; i++)
170         {
171                 if (k_idx == inscriptions[i].kind_idx)
172                         return i;
173         }
174
175         return -1;
176 }
177
178 /*
179  * DOCUMENT ME!
180  */
181 static cptr get_autoinscription(s16b kind_idx)
182 {
183         int i;
184
185         for (i = 0; i < inscriptions_count; i++)
186         {
187                 if (kind_idx == inscriptions[i].kind_idx)
188                         return quark_str(inscriptions[i].inscription_idx);
189         }
190
191         return 0;
192 }
193
194 /* Put the autoinscription on an object */
195 int apply_autoinscription(object_type *o_ptr)
196 {
197         char o_name[80];
198         cptr note = get_autoinscription(o_ptr->k_idx);
199         cptr existing_inscription = quark_str(o_ptr->note);
200
201         /* Don't inscribe unaware objects */
202         if (!note || !object_aware_p(o_ptr))
203                 return 0;
204
205         /* Don't re-inscribe if it's already correctly inscribed */
206         if (existing_inscription && streq(note, existing_inscription))
207                 return 0;
208
209         /* Get an object description */
210         object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 3);
211
212         if (note[0] != 0)
213                 o_ptr->note = quark_add(note);
214         else
215                 o_ptr->note = 0;
216
217         msg_format("You autoinscribe %s.", o_name);
218
219         return 1;
220 }
221
222
223 int remove_autoinscription(s16b kind)
224 {
225         int i = get_autoinscription_index(kind);
226
227         /* It's not here. */
228         if (i == -1) return 0;
229
230         while (i < inscriptions_count - 1)
231         {
232                 inscriptions[i] = inscriptions[i+1];
233                 i++;
234         }
235
236         inscriptions_count--;
237
238         return 1;
239 }
240
241
242 int add_autoinscription(s16b kind, cptr inscription)
243 {
244         int index;
245
246         /* Paranoia */
247         if (kind == 0) return 0;
248
249         /* If there's no inscription, remove it */
250         if (!inscription || (inscription[0] == 0))
251                 return remove_autoinscription(kind);
252
253         index = get_autoinscription_index(kind);
254
255         if (index == -1)
256                 index = inscriptions_count;
257
258         if (index >= AUTOINSCRIPTIONS_MAX)
259         {
260                 msg_format("This inscription (%s) cannot be added because the inscription array is full!", inscription);
261                 return 0;
262         }
263
264         inscriptions[index].kind_idx = kind;
265         inscriptions[index].inscription_idx = quark_add(inscription);
266
267         /* Only increment count if inscription added to end of array */
268         if (index == inscriptions_count)
269                 inscriptions_count++;
270
271         return 1;
272 }
273
274
275 void autoinscribe_ground(void)
276 {
277         int py = p_ptr->py;
278         int px = p_ptr->px;
279         s16b this_o_idx, next_o_idx = 0;
280
281         /* Scan the pile of objects */
282         for (this_o_idx = cave_o_idx[py][px]; this_o_idx; this_o_idx = next_o_idx)
283         {
284                 /* Get the next object */
285                 next_o_idx = o_list[this_o_idx].next_o_idx;
286
287                 /* Apply an autoinscription */
288                 apply_autoinscription(&o_list[this_o_idx]);
289         }
290 }
291
292 void autoinscribe_pack(void)
293 {
294         int i;
295
296         /* Cycle through the inventory */
297         for (i = INVEN_PACK; i > 0; i--)
298         {
299                 /* Skip empty items */
300                 if (!inventory[i].k_idx) continue;
301
302                 /* Apply the inscription */
303                 apply_autoinscription(&inventory[i]);
304         }
305
306         return;
307 }
308
309
310
311
312 /*** Squelch code ***/
313
314 /*
315  * Determines if an object is eligable for squelching.
316  */
317 static bool squelch_item_ok(object_type *o_ptr)
318 {
319         size_t i;
320         int num = -1;
321
322         bool fullid = object_aware_p(o_ptr);
323         bool sensed = (o_ptr->ident & IDENT_SENSE) || fullid;
324         byte feel   = fullid ? value_check_aux1(o_ptr) : o_ptr->pseudo;
325
326
327         /* Don't squelch artifacts */
328         if (artifact_p(o_ptr)) return FALSE;
329
330         /* Don't check things that aren't known at all */
331         if (!sensed) return FALSE;
332
333
334         /* Auto-squelch junk items */
335         if (object_value(o_ptr) == 0) return TRUE;
336
337         /* Auto-squelch dead chests */
338         if (o_ptr->tval == TV_CHEST && o_ptr->pval == 0)
339                 return TRUE;
340
341
342         /* Find the appropriate squelch group */
343         for (i = 0; i < N_ELEMENTS(type_tvals); i++)
344         {
345                 if (type_tvals[i][1] == o_ptr->tval)
346                         num = type_tvals[i][0];
347         }
348
349         /* Never squelched */
350         if (num == -1)
351                 return FALSE;
352
353
354         /* Get result based on the feeling and the squelch_level */
355         switch (squelch_level[num])
356         {
357                 case SQUELCH_CURSED:
358                 {
359                         if ((feel == INSCRIP_BROKEN) || (feel == INSCRIP_TERRIBLE) ||
360                             (feel == INSCRIP_WORTHLESS) || (feel == INSCRIP_CURSED))
361                         {
362                                 return TRUE;
363                         }
364
365                 break;
366                 }
367
368                 case SQUELCH_AVERAGE:
369                 {
370                         if ((feel == INSCRIP_BROKEN) || (feel == INSCRIP_TERRIBLE) ||
371                             (feel == INSCRIP_WORTHLESS) || (feel == INSCRIP_CURSED) ||
372                             (feel == INSCRIP_AVERAGE))
373                         {
374                                 return TRUE;
375                         }
376
377                 break;
378                 }
379
380                 case SQUELCH_GOOD_WEAK:
381                 {
382                         if ((feel == INSCRIP_BROKEN) || (feel == INSCRIP_TERRIBLE) ||
383                             (feel == INSCRIP_WORTHLESS) || (feel == INSCRIP_CURSED) ||
384                             (feel == INSCRIP_AVERAGE) || (feel == INSCRIP_GOOD))
385                         {
386                                 return TRUE;
387                         }
388
389                         break;
390                 }
391
392                 case SQUELCH_GOOD_STRONG:
393                 {
394                         if ((feel == INSCRIP_BROKEN) || (feel == INSCRIP_TERRIBLE) ||
395                             (feel == INSCRIP_WORTHLESS) || (feel == INSCRIP_CURSED) ||
396                             (feel == INSCRIP_AVERAGE) ||
397                             ((feel == INSCRIP_GOOD) &&
398                              ((fullid) || (cp_ptr->flags & CF_PSEUDO_ID_HEAVY))))
399                         {
400                                 return TRUE;
401                         }
402
403                         break;
404                 }
405
406                 case SQUELCH_ALL:
407                 {
408                         return TRUE;
409                 break;
410                 }
411         }
412
413         /* Failure */
414         return FALSE;
415 }
416
417
418 /*
419  * Set squelch inscription on an object.
420  */
421 void squelch_set(object_type *o_ptr)
422 {
423         bool can_squelch;
424
425         /* Check if we can squelch */
426         can_squelch = squelch_item_ok(o_ptr);
427
428         /* Set squelch inscription unless there's already one */
429         if (!o_ptr->note && can_squelch)
430                 o_ptr->note = quark_add("squelch");
431
432
433         /* Done */
434         return;
435 }
436
437
438 /*
439  * An item_tester_hook for squelched items.
440  */
441 static bool item_tester_squelched(const object_type *o_ptr)
442 {
443         const char *inscrip = (o_ptr->note ? quark_str(o_ptr->note) : NULL);
444
445         /* Check for inscription */
446         if (!o_ptr->note) return FALSE;
447
448         /* Find "squelch" */
449         if (inscrip && streq(inscrip, "squelch")) return TRUE;
450
451         /* Nope */
452         return FALSE;
453 }
454
455
456 /*
457  * Destroy all {squelch}able items.
458  *
459  * Imported, with thanks, from Ey... much cleaner than the original.
460  */
461 void squelch_items(void)
462 {
463         int floor_list[MAX_FLOOR_STACK];
464         int floor_num, n;
465         int count = 0;
466
467         object_type *o_ptr;
468
469         /* Set the hook and scan the floor */
470         item_tester_hook = item_tester_squelched;
471         (void)scan_floor(floor_list, &floor_num, p_ptr->py, p_ptr->px, 0x01);
472
473         if (floor_num)
474         {
475                 for (n = 0; n < floor_num; n++)
476                 {
477                         o_ptr = &o_list[floor_list[n]];
478
479                         /* Avoid artifacts */
480                         if (artifact_p(o_ptr)) continue;
481
482                         if (item_tester_okay(o_ptr))
483                         {
484                                 /* Destroy item */
485                                 floor_item_increase(floor_list[n], -o_ptr->number);
486                                 floor_item_optimize(floor_list[n]);
487                                 count++;
488                         }
489                 }
490         }
491
492         /* Scan through the slots backwards */
493         for (n = INVEN_PACK - 1; n >= 0; n--)
494         {
495                 o_ptr = &inventory[n];
496
497                 /* Skip non-objects and artifacts */
498                 if (!o_ptr->k_idx) continue;
499                 if (artifact_p(o_ptr)) continue;
500
501                 if (item_tester_okay(o_ptr))
502                 {
503                         /* Destroy item */
504                         inven_item_increase(n, -o_ptr->number);
505                         inven_item_optimize(n);
506                         count++;
507                 }
508         }
509
510         item_tester_hook = NULL;
511
512         /* Mention casualties */
513         if (count > 0)
514         {
515                 message_format(MSG_DESTROY, 0, "%d item%s squelched.",
516                                count, ((count > 1) ? "s" : ""));
517
518                 /* Combine/reorder the pack */
519                 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
520         }
521         else
522         {
523                 message(MSG_GENERIC, 0, "No squelched items to destroy.");
524         }
525
526         /* Happy now I've sold my soul */
527         return;
528 }
529
530
531
532
533
534 /*** UI stuff ***/
535
536 /*
537  * This is much simpler than it used to be.
538  */
539
540
541 /*** Quality-squelch menu ***/
542
543 /*
544  * Display an entry in the menu.
545  */
546 static void quality_display(menu_type *menu, int oid, bool cursor, int row, int col, int width)
547 {
548         const char *name = type_names[oid];
549
550         byte level = squelch_level[oid];
551         const char *level_name = quality_names[level];
552
553         byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
554
555
556         c_put_str(attr, format("%-20s : %s", name, level_name), row, col);
557 }
558
559
560 /*
561  * Display the quality squelch subtypes.
562  */
563 static void quality_subdisplay(menu_type *menu, int oid, bool cursor, int row, int col, int width)
564 {
565         const char *name = quality_names[oid];
566         byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
567
568         c_put_str(attr, name, row, col);
569 }
570
571 /*
572  * Handle "Enter".  :(
573  */
574 static bool quality_subaction(char cmd, void *db, int oid)
575 {
576         return TRUE;
577 }
578
579
580 /*
581  * Handle keypresses.
582  */
583 static bool quality_action(char cmd, void *db, int oid)
584 {
585         menu_type menu;
586         menu_iter menu_f = { 0, 0, 0, quality_subdisplay, quality_subaction };
587         region area = { 24, 5, 26, SQUELCH_MAX };
588         event_type evt;
589         int cursor;
590
591         /* Display at the right point */
592         area.row += oid;
593         cursor = squelch_level[oid];
594
595         /* Save */
596         screen_save();
597
598         /* Run menu */
599         WIPE(&menu, menu);
600         menu.cmd_keys = "\n\r";
601         menu.count = SQUELCH_MAX;
602         if (oid == TYPE_JEWELRY)
603                 menu.count = area.page_rows = SQUELCH_CURSED + 1;
604
605         menu_init2(&menu, find_menu_skin(MN_SCROLL), &menu_f, &area);
606         window_make(area.col - 2, area.row - 1, area.col + area.width + 2, area.row + area.page_rows);
607
608         evt = menu_select(&menu, &cursor, 0);
609
610         /* Set the new value appropriately */
611         if (evt.key != ESCAPE && evt.type != EVT_BACK)
612                 squelch_level[oid] = cursor;
613
614         /* Load and finish */
615         screen_load();
616         return TRUE;
617 }
618
619 /*
620  * Display quality squelch menu.
621  */
622 static void quality_menu(void)
623 {
624         menu_type menu;
625         menu_iter menu_f = { 0, 0, 0, quality_display, quality_action };
626         region area = { 1, 5, -1, -1 };
627         event_type evt;
628         int cursor = 0;
629
630         /* Save screen */
631         screen_save();
632         clear_from(0);
633
634         /* Help text */
635         prt("Quality squelch menu", 0, 0);
636
637         Term_gotoxy(1, 1);
638         text_out_to_screen(TERM_L_RED, "Use the movement keys to navigate, and Enter to change settings.");
639
640         /* Set up the menu */
641         WIPE(&menu, menu);
642         menu.cmd_keys = " \n\r";
643         menu.count = TYPE_MAX;
644         menu_init2(&menu, find_menu_skin(MN_SCROLL), &menu_f, &area);
645
646         /* Select an entry */
647         while (evt.key != ESCAPE && evt.type != EVT_BACK)
648                 evt = menu_select(&menu, &cursor, 0);
649
650         /* Load screen */
651         screen_load();
652         return;
653 }
654
655
656
657 /*** Sval-dependent menu ***/
658
659 /*
660  * Display an entry on the sval menu
661  */
662 static void sval_display(menu_type *menu, int oid, bool cursor, int row, int col, int width)
663 {
664         char buf[80];
665         const char *inscrip;
666         const u16b *choice = menu->menu_data;
667         int idx = choice[oid];
668
669         byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
670
671
672         /* Acquire the "name" of object "i" */
673         strip_name(buf, idx, TRUE);
674
675         /* Print it */
676         c_put_str(attr, format("[ ] %s", buf), row, col);
677         if (k_info[idx].squelch)
678                 c_put_str(TERM_L_RED, "*", row, col + 1);
679
680         inscrip = get_autoinscription(choice[oid]);
681         if (!inscrip) inscrip = "(none)";
682
683         c_put_str(attr, format("%-40s", inscrip), row, col + 40);
684 }
685
686 /*
687  * Deal with events on the sval menu
688  */
689 static bool sval_action(char cmd, void *db, int oid)
690 {
691         char buf[80] = "";
692         u16b *choice = db;
693
694         /* Toggle */
695         if (cmd == ' ')
696         {
697                 int idx = choice[oid];
698                 k_info[idx].squelch = !k_info[idx].squelch;
699
700                 return TRUE;
701         }
702
703         /* Set inscription */
704         else if (cmd == '\n' || cmd == '\r')
705         {
706                 s16b k_idx = choice[oid];
707                 const char *inscrip;
708
709                 /* Obtain the current inscription */
710                 inscrip = get_autoinscription(k_idx);   
711
712                 /* Copy of the current inscription, or clear the buffer */
713                 if (inscrip)
714                         my_strcpy(buf, inscrip, sizeof(buf));
715
716                 /* Get a new inscription (possibly empty) */
717                 if (get_string("Autoinscription: ", buf, sizeof(buf)))
718                 {
719                         /* Save the inscription */
720                         add_autoinscription(k_idx, buf);
721
722                         /* Notice stuff (later) */
723                         p_ptr->notice |= (PN_AUTOINSCRIBE);
724                         p_ptr->window |= (PW_INVEN | PW_EQUIP);
725                 }
726
727                 return TRUE;
728         }
729
730         return FALSE;
731 }
732
733 /*
734  * Display list of svals to be squelched.
735  */
736 static bool sval_menu(int tval, const char *desc)
737 {
738         menu_type menu;
739         menu_iter menu_f = { 0, 0, 0, sval_display, sval_action };
740         region area = { 1, 5, -1, -1 };
741         event_type evt = { EVT_NONE, 0, 0, 0, 0 };
742         int cursor = 0;
743
744         int num = 0;
745         size_t i;
746
747         u16b *choice;
748
749
750         /* Create the array */
751         C_MAKE(choice, z_info->k_max, u16b);
752
753         /* Iterate over all possible object kinds, finding ones which can be squelched */
754         for (i = 1; i < z_info->k_max; i++)
755         {
756                 object_kind *k_ptr = &k_info[i];
757
758                 /* Skip empty objects, unseen objects, and incorrect tvals */
759                 if (!k_ptr->name) continue;
760                 if (!k_ptr->everseen) continue;
761                 if (k_ptr->tval != tval) continue;
762
763                 /* Add this item to our possibles list */
764                 choice[num++] = i;
765         }
766
767         /* Return here if there are no objects */
768         if (!num)
769         {
770                 FREE(choice);
771                 return FALSE;
772         }
773
774
775         /* Save the screen and clear it */
776         screen_save();
777         clear_from(0);
778
779         /* Help text */
780
781         /* Output to the screen */
782         text_out_hook = text_out_to_screen;
783
784         /* Indent output */
785         text_out_indent = 1;
786         text_out_wrap = 79;
787         Term_gotoxy(1, 0);
788
789         /* Display some helpful information */
790         text_out("Use the ");
791         text_out_c(TERM_L_GREEN, "movement keys");
792         text_out(" to scroll the list or ");
793         text_out_c(TERM_L_GREEN, "ESC");
794         text_out(" to return to the previous menu.  ");
795         text_out_c(TERM_L_BLUE, "Space");
796         text_out(" toggles the current setting, and ");
797         text_out_c(TERM_L_GREEN, "Enter");
798         text_out(" will prompt you for a new autoinscription.");
799
800         /* Set up the menu */
801         WIPE(&menu, menu);
802         menu.cmd_keys = " \n\r";
803         menu.count = num;
804         menu.menu_data = choice;
805         menu_init2(&menu, find_menu_skin(MN_SCROLL), &menu_f, &area);
806
807         /* Select an entry */
808         while (evt.key != ESCAPE && evt.type != EVT_BACK)
809                 evt = menu_select(&menu, &cursor, 0);
810
811         /* Free memory */
812         FREE(choice);
813
814         /* Load screen */
815         screen_load();
816         return TRUE;
817 }
818
819
820
821 /*
822  * Display and handle the main squelching menu.
823  */
824 void do_cmd_options_item(void)
825 {
826         bool done = FALSE;
827         bool no_known = FALSE;
828         size_t i;
829
830         /* Save and clear screen */
831         screen_save();
832         clear_from(0);
833
834
835         /* Header */
836         prt("Item handling menu", 0, 0);
837
838         /* Print all typevals and their descriptions */
839         for (i = 0; i < N_ELEMENTS(sval_dependent); i++)
840                 prt(format("%c) %s", I2A(i), sval_dependent[i].desc), i + 3, 1);
841
842         prt("Q) Quality squelching options", i + 4, 1);
843         prt("ESC) Back to options menu.", i + 6, 1);
844
845         while (!done)
846         {
847                 char ch;
848
849                 if (no_known)
850                 {
851                         prt("You've not seen any object of that type yet.", 1, 0);
852                         no_known = FALSE;
853                 }
854                 else
855                 {
856                         prt("", 1, 0);
857                 }
858
859                 /* Prompt */
860                 ch = inkey();
861
862                 /* Choose! */
863                 if (ch == 'Q') quality_menu();         /* Switch to secondary squelching menu */
864                 else if (ch == ESCAPE) done = TRUE;         /* Finished */
865
866                 else
867                 {
868                         /* Analyze choice */
869                         int choice = A2I(ch);
870
871                         /* Ignore illegal choice */
872                         if (choice < 0 || choice >= (int)N_ELEMENTS(sval_dependent)) continue;
873
874                         if (!sval_menu(sval_dependent[choice].tval, sval_dependent[choice].desc))
875                                 no_known = TRUE;
876                 }
877         }
878
879         /* Load screen and finish */
880         screen_load();
881         return;
882 }
Note: See TracBrowser for help on using the browser.