Angband 3.0.9b.
[angband.git] / src / squelch.c
blob358150c9f076e7326ff02daafa1485efcee57467
1 /*
2 * File: squelch.c
3 * Purpose: Item destruction
5 * Copyright (c) 2007 David T. Blackston, Iain McFall, DarkGod, Jeff Greene,
6 * David Vestal, Pete Mack, Andrew Sidwell.
8 * This work is free software; you can redistribute it and/or modify it
9 * under the terms of either:
11 * a) the GNU General Public License as published by the Free Software
12 * Foundation, version 2, or
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.
19 #include "angband.h"
20 #include "cmds.h"
24 * The squelch code has a long history. Originally it started out as a simple
25 * sval-dependent item destroyer, but then ego-item and quality squelch was
26 * added too, and then squelched items on the dungeon floor were marked by
27 * purple dots, and by this time the code was quite unmaintainable and pretty
28 * much impossible to work with.
30 * Luckily, though, it's been cleaned up. There is now only sval-dependent
31 * squelch and quality-based squelch, and the two don't interact -- quality-based
32 * is for items that get pseudo-id'd and sval-dependent is for potions and the
33 * like.
35 * The squelch code figures most things out itself. Simply do:
36 * p_ptr->notice |= PN_SQUELCH;
37 * whenever you want to make the game check for squelched items.
39 * The quality-dependent squelch is much reduced in scope from how it used to
40 * be. If less "general" settings are desired, they can be added easily enough
41 * by changing entries in type_tvals[][], adding more TYPE_* constants, and
42 * updating type_names. Savefile compatibility is automatically ensured.
45 * The UI code is much cleaner than it was before, but the interface itself
46 * still needs some design. XXX
51 * List of kinds of item, for pseudo-id squelch.
53 enum
55 TYPE_WEAPON,
56 TYPE_SHOOTER,
57 TYPE_MISSILE,
58 TYPE_ARMOR,
59 TYPE_JEWELRY,
60 TYPE_DIGGER,
62 TYPE_MAX
66 * Names of categories.
68 static const char *type_names[TYPE_MAX] =
70 "Melee weapons",
71 "Missile weapons",
72 "Ammunition",
73 "Armor",
74 "Jewelry",
75 "Diggers",
78 /* Mapping of tval -> type */
79 static int type_tvals[][2] =
81 { TYPE_WEAPON, TV_SWORD },
82 { TYPE_WEAPON, TV_POLEARM },
83 { TYPE_WEAPON, TV_HAFTED },
84 { TYPE_SHOOTER, TV_BOW },
85 { TYPE_MISSILE, TV_ARROW },
86 { TYPE_MISSILE, TV_BOLT },
87 { TYPE_MISSILE, TV_SHOT },
88 { TYPE_ARMOR, TV_SHIELD },
89 { TYPE_ARMOR, TV_HELM },
90 { TYPE_ARMOR, TV_GLOVES },
91 { TYPE_ARMOR, TV_BOOTS },
92 { TYPE_ARMOR, TV_HARD_ARMOR },
93 { TYPE_ARMOR, TV_SOFT_ARMOR },
94 { TYPE_ARMOR, TV_CLOAK },
95 { TYPE_ARMOR, TV_CROWN },
96 { TYPE_JEWELRY, TV_RING },
97 { TYPE_JEWELRY, TV_AMULET },
98 { TYPE_DIGGER, TV_DIGGING },
101 byte squelch_level[TYPE_MAX];
102 size_t squelch_size = TYPE_MAX;
106 * The different kinds of quality squelch
108 enum
110 SQUELCH_NONE,
111 SQUELCH_CURSED,
112 SQUELCH_AVERAGE,
113 SQUELCH_GOOD_STRONG,
114 SQUELCH_GOOD_WEAK,
115 SQUELCH_ALL,
117 SQUELCH_MAX
121 * The names for the various kinds of quality
123 static const char *quality_names[SQUELCH_MAX] =
125 "none", /* SQUELCH_NONE */
126 "cursed", /* SQUELCH_CURSED */
127 "average", /* SQUELCH_AVERAGE */
128 "good (strong pseudo-ID)", /* SQUELCH_GOOD_STRONG */
129 "good (weak pseudo-ID)", /* SQUELCH_GOOD_WEAK */
130 "everything except artifacts", /* SQUELCH_ALL */
134 /* Structure to describe tval/description pairings. */
135 typedef struct
137 int tval;
138 const char *desc;
139 } tval_desc;
141 /* Categories for sval-dependent squelch. */
142 static tval_desc sval_dependent[] =
144 { TV_STAFF, "Staffs" },
145 { TV_WAND, "Wands" },
146 { TV_ROD, "Rods" },
147 { TV_SCROLL, "Scrolls" },
148 { TV_POTION, "Potions" },
149 { TV_RING, "Rings" },
150 { TV_AMULET, "Amulets" },
151 { TV_FOOD, "Food" },
152 { TV_MAGIC_BOOK, "Magic books" },
153 { TV_PRAYER_BOOK, "Prayer books" },
154 { TV_SPIKE, "Spikes" },
155 { TV_LITE, "Lights" },
156 { TV_FLASK, "Flasks of oil" },
157 { TV_DRAG_ARMOR, "Dragon mail armor" },
161 /*** Autoinscription stuff ***/
164 * This code needs documenting.
166 int get_autoinscription_index(s16b k_idx)
168 int i;
170 for (i = 0; i < inscriptions_count; i++)
172 if (k_idx == inscriptions[i].kind_idx)
173 return i;
176 return -1;
180 * DOCUMENT ME!
182 const char *get_autoinscription(s16b kind_idx)
184 int i;
186 for (i = 0; i < inscriptions_count; i++)
188 if (kind_idx == inscriptions[i].kind_idx)
189 return quark_str(inscriptions[i].inscription_idx);
192 return 0;
195 /* Put the autoinscription on an object */
196 int apply_autoinscription(object_type *o_ptr)
198 char o_name[80];
199 cptr note = get_autoinscription(o_ptr->k_idx);
200 cptr existing_inscription = quark_str(o_ptr->note);
202 /* Don't inscribe unaware objects */
203 if (!note || !object_aware_p(o_ptr))
204 return 0;
206 /* Don't re-inscribe if it's already correctly inscribed */
207 if (existing_inscription && streq(note, existing_inscription))
208 return 0;
210 /* Get an object description */
211 object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 3);
213 if (note[0] != 0)
214 o_ptr->note = quark_add(note);
215 else
216 o_ptr->note = 0;
218 msg_format("You autoinscribe %s.", o_name);
220 return 1;
224 int remove_autoinscription(s16b kind)
226 int i = get_autoinscription_index(kind);
228 /* It's not here. */
229 if (i == -1) return 0;
231 while (i < inscriptions_count - 1)
233 inscriptions[i] = inscriptions[i+1];
234 i++;
237 inscriptions_count--;
239 return 1;
243 int add_autoinscription(s16b kind, cptr inscription)
245 int index;
247 /* Paranoia */
248 if (kind == 0) return 0;
250 /* If there's no inscription, remove it */
251 if (!inscription || (inscription[0] == 0))
252 return remove_autoinscription(kind);
254 index = get_autoinscription_index(kind);
256 if (index == -1)
257 index = inscriptions_count;
259 if (index >= AUTOINSCRIPTIONS_MAX)
261 msg_format("This inscription (%s) cannot be added because the inscription array is full!", inscription);
262 return 0;
265 inscriptions[index].kind_idx = kind;
266 inscriptions[index].inscription_idx = quark_add(inscription);
268 /* Only increment count if inscription added to end of array */
269 if (index == inscriptions_count)
270 inscriptions_count++;
272 return 1;
276 void autoinscribe_ground(void)
278 int py = p_ptr->py;
279 int px = p_ptr->px;
280 s16b this_o_idx, next_o_idx = 0;
282 /* Scan the pile of objects */
283 for (this_o_idx = cave_o_idx[py][px]; this_o_idx; this_o_idx = next_o_idx)
285 /* Get the next object */
286 next_o_idx = o_list[this_o_idx].next_o_idx;
288 /* Apply an autoinscription */
289 apply_autoinscription(&o_list[this_o_idx]);
293 void autoinscribe_pack(void)
295 int i;
297 /* Cycle through the inventory */
298 for (i = INVEN_PACK; i > 0; i--)
300 /* Skip empty items */
301 if (!inventory[i].k_idx) continue;
303 /* Apply the inscription */
304 apply_autoinscription(&inventory[i]);
307 return;
313 /*** Squelch code ***/
316 * Determines whether a tval is eligable for sval-squelch.
318 bool squelch_tval(int tval)
320 size_t i;
322 /* Only squelch if the tval's allowed */
323 for (i = 0; i < N_ELEMENTS(sval_dependent); i++)
325 if (tval == sval_dependent[i].tval)
326 return TRUE;
329 return FALSE;
334 * Determines if an object is eligable for squelching.
336 bool squelch_item_ok(const object_type *o_ptr)
338 size_t i;
339 int num = -1;
341 object_kind *k_ptr = &k_info[o_ptr->k_idx];
342 bool fullid = object_known_p(o_ptr);
343 bool sensed = (o_ptr->ident & IDENT_SENSE) || fullid;
344 byte feel = fullid ? value_check_aux1(o_ptr) : o_ptr->pseudo;
347 /* Don't squelch artifacts */
348 if (artifact_p(o_ptr)) return FALSE;
350 /* Don't squelch stuff inscribed not to be destroyed (!k) */
351 if (check_for_inscrip(o_ptr, "!k") || check_for_inscrip(o_ptr, "!*"))
353 return FALSE;
356 /* Auto-squelch dead chests */
357 if (o_ptr->tval == TV_CHEST && o_ptr->pval == 0)
358 return TRUE;
360 /* Do squelching by sval, if we 'know' the flavour. */
361 if (k_ptr->squelch && (k_ptr->flavor == 0 || k_ptr->aware))
363 if (squelch_tval(k_info[o_ptr->k_idx].tval))
364 return TRUE;
368 /* Don't check pseudo-ID for nonsensed things */
369 if (!sensed) return FALSE;
373 /* Find the appropriate squelch group */
374 for (i = 0; i < N_ELEMENTS(type_tvals); i++)
376 if (type_tvals[i][1] == o_ptr->tval)
378 num = type_tvals[i][0];
379 break;
383 /* Never squelched */
384 if (num == -1)
385 return FALSE;
388 /* Get result based on the feeling and the squelch_level */
389 switch (squelch_level[num])
391 case SQUELCH_CURSED:
393 if ((feel == INSCRIP_BROKEN) || (feel == INSCRIP_TERRIBLE) ||
394 (feel == INSCRIP_WORTHLESS) || (feel == INSCRIP_CURSED))
396 return TRUE;
399 break;
402 case SQUELCH_AVERAGE:
404 if ((feel == INSCRIP_BROKEN) || (feel == INSCRIP_TERRIBLE) ||
405 (feel == INSCRIP_WORTHLESS) || (feel == INSCRIP_CURSED) ||
406 (feel == INSCRIP_AVERAGE))
408 return TRUE;
411 break;
414 case SQUELCH_GOOD_WEAK:
416 if ((feel == INSCRIP_BROKEN) || (feel == INSCRIP_TERRIBLE) ||
417 (feel == INSCRIP_WORTHLESS) || (feel == INSCRIP_CURSED) ||
418 (feel == INSCRIP_AVERAGE) || (feel == INSCRIP_GOOD))
420 return TRUE;
423 break;
426 case SQUELCH_GOOD_STRONG:
428 if ((feel == INSCRIP_BROKEN) || (feel == INSCRIP_TERRIBLE) ||
429 (feel == INSCRIP_WORTHLESS) || (feel == INSCRIP_CURSED) ||
430 (feel == INSCRIP_AVERAGE) ||
431 ((feel == INSCRIP_GOOD) &&
432 ((fullid) || (cp_ptr->flags & CF_PSEUDO_ID_HEAVY))))
434 return TRUE;
437 break;
440 case SQUELCH_ALL:
442 return TRUE;
443 break;
447 /* Failure */
448 return FALSE;
453 * Returns TRUE if an item should be hidden due to the player's
454 * current settings.
456 bool squelch_hide_item(object_type *o_ptr)
458 return (hide_squelchable ? squelch_item_ok(o_ptr) : FALSE);
463 * Destroy all {squelch}able items.
465 * Imported, with thanks, from Ey... much cleaner than the original.
467 void squelch_items(void)
469 int floor_list[MAX_FLOOR_STACK];
470 int floor_num, n;
471 int count = 0;
473 object_type *o_ptr;
475 /* Set the hook and scan the floor */
476 item_tester_hook = squelch_item_ok;
477 (void)scan_floor(floor_list, &floor_num, p_ptr->py, p_ptr->px, 0x01);
479 if (floor_num)
481 for (n = 0; n < floor_num; n++)
483 o_ptr = &o_list[floor_list[n]];
485 /* Avoid artifacts */
486 if (artifact_p(o_ptr)) continue;
488 if (item_tester_okay(o_ptr))
490 /* Destroy item */
491 floor_item_increase(floor_list[n], -o_ptr->number);
492 floor_item_optimize(floor_list[n]);
493 count++;
498 /* Scan through the slots backwards */
499 for (n = INVEN_PACK - 1; n >= 0; n--)
501 o_ptr = &inventory[n];
503 /* Skip non-objects and artifacts */
504 if (!o_ptr->k_idx) continue;
505 if (artifact_p(o_ptr)) continue;
507 if (item_tester_okay(o_ptr))
509 /* Destroy item */
510 inven_item_increase(n, -o_ptr->number);
511 inven_item_optimize(n);
512 count++;
516 item_tester_hook = NULL;
518 /* Mention casualties */
519 if (count > 0)
521 message_format(MSG_DESTROY, 0, "%d item%s squelched.",
522 count, ((count > 1) ? "s" : ""));
524 /* Combine/reorder the pack */
525 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
531 * Drop all {squelch}able items.
533 void squelch_drop(void)
535 int n;
537 /* Scan through the slots backwards */
538 for (n = INVEN_PACK - 1; n >= 0; n--)
540 object_type *o_ptr = &inventory[n];
542 /* Skip non-objects and unsquelchable objects */
543 if (!o_ptr->k_idx) continue;
544 if (!squelch_item_ok(o_ptr)) continue;
546 /* Check for !d (no drop) inscription */
547 if (!check_for_inscrip(o_ptr, "!d") && !check_for_inscrip(o_ptr, "!*"))
549 /* We're allowed to drop it. */
550 inven_drop(n, o_ptr->number);
554 /* Combine/reorder the pack */
555 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
560 /*** Quality-squelch menu ***/
563 * Display an entry in the menu.
565 static void quality_display(menu_type *menu, int oid, bool cursor, int row, int col, int width)
567 const char *name = type_names[oid];
569 byte level = squelch_level[oid];
570 const char *level_name = quality_names[level];
572 byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
575 c_put_str(attr, format("%-20s : %s", name, level_name), row, col);
580 * Display the quality squelch subtypes.
582 static void quality_subdisplay(menu_type *menu, int oid, bool cursor, int row, int col, int width)
584 const char *name = quality_names[oid];
585 byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
587 c_put_str(attr, name, row, col);
591 * Handle "Enter". :(
593 static bool quality_subaction(char cmd, void *db, int oid)
595 return TRUE;
600 * Handle keypresses.
602 static bool quality_action(char cmd, void *db, int oid)
604 menu_type menu;
605 menu_iter menu_f = { 0, 0, 0, quality_subdisplay, quality_subaction };
606 region area = { 24, 5, 26, SQUELCH_MAX };
607 event_type evt;
608 int cursor;
610 /* Display at the right point */
611 area.row += oid;
612 cursor = squelch_level[oid];
614 /* Save */
615 screen_save();
617 /* Run menu */
618 WIPE(&menu, menu);
619 menu.cmd_keys = "\n\r";
620 menu.count = SQUELCH_MAX;
621 if (oid == TYPE_JEWELRY)
622 menu.count = area.page_rows = SQUELCH_CURSED + 1;
624 menu_init2(&menu, find_menu_skin(MN_SCROLL), &menu_f, &area);
625 window_make(area.col - 2, area.row - 1, area.col + area.width + 2, area.row + area.page_rows);
627 evt = menu_select(&menu, &cursor, 0);
629 /* Set the new value appropriately */
630 if (evt.key != ESCAPE && evt.type != EVT_BACK)
631 squelch_level[oid] = cursor;
633 /* Load and finish */
634 screen_load();
635 return TRUE;
639 * Display quality squelch menu.
641 static void quality_menu(void *unused, const char *also_unused)
643 menu_type menu;
644 menu_iter menu_f = { 0, 0, 0, quality_display, quality_action };
645 region area = { 1, 5, -1, -1 };
646 event_type evt = EVENT_EMPTY;
647 int cursor = 0;
649 /* Save screen */
650 screen_save();
651 clear_from(0);
653 /* Help text */
654 prt("Quality squelch menu", 0, 0);
656 Term_gotoxy(1, 1);
657 text_out_to_screen(TERM_L_RED, "Use the movement keys to navigate, and Enter to change settings.");
659 /* Set up the menu */
660 WIPE(&menu, menu);
661 menu.cmd_keys = " \n\r";
662 menu.count = TYPE_MAX;
663 menu_init2(&menu, find_menu_skin(MN_SCROLL), &menu_f, &area);
665 /* Select an entry */
666 while (evt.key != ESCAPE)
667 evt = menu_select(&menu, &cursor, 0);
669 /* Load screen */
670 screen_load();
671 return;
676 /*** Sval-dependent menu ***/
679 * Display an entry on the sval menu
681 static void sval_display(menu_type *menu, int oid, bool cursor, int row, int col, int width)
683 char buf[80];
684 const u16b *choice = menu->menu_data;
685 int idx = choice[oid];
687 byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
690 /* Acquire the "name" of object "i" */
691 object_kind_name(buf, sizeof(buf), idx, TRUE);
693 /* Print it */
694 c_put_str(attr, format("[ ] %s", buf), row, col);
695 if (k_info[idx].squelch)
696 c_put_str(TERM_L_RED, "*", row, col + 1);
700 * Deal with events on the sval menu
702 static bool sval_action(char cmd, void *db, int oid)
704 u16b *choice = db;
706 /* Toggle */
707 if (cmd == '\n' || cmd == '\r')
709 int idx = choice[oid];
710 k_info[idx].squelch = !k_info[idx].squelch;
712 return TRUE;
715 return FALSE;
720 * Display list of svals to be squelched.
722 static bool sval_menu(int tval, const char *desc)
724 menu_type menu;
725 menu_iter menu_f = { 0, 0, 0, sval_display, sval_action };
726 region area = { 1, 5, -1, -1 };
727 event_type evt = { EVT_NONE, 0, 0, 0, 0 };
728 int cursor = 0;
730 int num = 0;
731 size_t i;
733 u16b *choice;
736 /* Create the array */
737 C_MAKE(choice, z_info->k_max, u16b);
739 /* Iterate over all possible object kinds, finding ones which can be squelched */
740 for (i = 1; i < z_info->k_max; i++)
742 object_kind *k_ptr = &k_info[i];
744 /* Skip empty objects, unseen objects, and incorrect tvals */
745 if (!k_ptr->name) continue;
746 if (!k_ptr->everseen) continue;
747 if (k_ptr->tval != tval) continue;
749 /* Add this item to our possibles list */
750 choice[num++] = i;
753 /* Return here if there are no objects */
754 if (!num)
756 FREE(choice);
757 return FALSE;
761 /* Save the screen and clear it */
762 screen_save();
763 clear_from(0);
765 /* Help text */
767 /* Output to the screen */
768 text_out_hook = text_out_to_screen;
770 /* Indent output */
771 text_out_indent = 1;
772 text_out_wrap = 79;
773 Term_gotoxy(1, 0);
775 /* Display some helpful information */
776 text_out("Use the ");
777 text_out_c(TERM_L_GREEN, "movement keys");
778 text_out(" to scroll the list or ");
779 text_out_c(TERM_L_GREEN, "ESC");
780 text_out(" to return to the previous menu. ");
781 text_out_c(TERM_L_BLUE, "Enter");
782 text_out(" toggles the current setting.");
784 text_out_indent = 0;
786 /* Set up the menu */
787 WIPE(&menu, menu);
788 menu.cmd_keys = " \n\r";
789 menu.count = num;
790 menu.menu_data = choice;
791 menu_init2(&menu, find_menu_skin(MN_SCROLL), &menu_f, &area);
793 /* Select an entry */
794 while (evt.key != ESCAPE)
795 evt = menu_select(&menu, &cursor, 0);
797 /* Free memory */
798 FREE(choice);
800 /* Load screen */
801 screen_load();
802 return TRUE;
806 /* Returns TRUE if there's anything to display a menu of */
807 static bool seen_tval(int tval)
809 int i;
811 for (i = 1; i < z_info->k_max; i++)
813 object_kind *k_ptr = &k_info[i];
815 /* Skip empty objects, unseen objects, and incorrect tvals */
816 if (!k_ptr->name) continue;
817 if (!k_ptr->everseen) continue;
818 if (k_ptr->tval != tval) continue;
820 return TRUE;
824 return FALSE;
828 /* Extra options on the "item options" menu */
829 struct
831 char tag;
832 char *name;
833 void (*action)(void *unused, const char *also_unused);
834 } extra_item_options[] =
836 { 'Q', "Quality squelching options", quality_menu },
837 { '{', "Autoinscription setup", do_cmd_knowledge_objects },
840 static char tag_options_item(menu_type *menu, int oid)
842 size_t line = (size_t) oid;
844 if (line < N_ELEMENTS(sval_dependent))
845 return I2A(oid);
847 /* Separator - blank line. */
848 if (line == N_ELEMENTS(sval_dependent))
849 return 0;
851 line = line - N_ELEMENTS(sval_dependent) - 1;
853 if (line < N_ELEMENTS(extra_item_options))
854 return extra_item_options[line].tag;
856 return 0;
859 static int valid_options_item(menu_type *menu, int oid)
861 size_t line = (size_t) oid;
863 if (line < N_ELEMENTS(sval_dependent))
864 return 1;
866 /* Separator - blank line. */
867 if (line == N_ELEMENTS(sval_dependent))
868 return 0;
870 line = line - N_ELEMENTS(sval_dependent) - 1;
872 if (line < N_ELEMENTS(extra_item_options))
873 return 1;
875 return 0;
878 static void display_options_item(menu_type *menu, int oid, bool cursor, int row, int col, int width)
880 size_t line = (size_t) oid;
882 /* First section of menu - the svals */
883 if (line < N_ELEMENTS(sval_dependent))
885 bool known = seen_tval(sval_dependent[line].tval);
886 byte attr = curs_attrs[known ? CURS_KNOWN: CURS_UNKNOWN][(int)cursor];
888 c_prt(attr, sval_dependent[line].desc, row, col);
890 /* Second section - the "extra options" */
891 else
893 byte attr = curs_attrs[CURS_KNOWN][(int)cursor];
895 line = line - N_ELEMENTS(sval_dependent) - 1;
897 if (line < N_ELEMENTS(extra_item_options))
898 c_prt(attr, extra_item_options[line].name, row, col);
903 static const menu_iter options_item_iter =
906 tag_options_item,
907 valid_options_item,
908 display_options_item,
909 NULL
914 * Display and handle the main squelching menu.
916 void do_cmd_options_item(void *unused, cptr title)
918 int cursor = 0;
919 event_type c = EVENT_EMPTY;
920 const char cmd_keys[] = { ARROW_LEFT, ARROW_RIGHT, '\0' };
922 menu_type menu;
924 WIPE(&menu, menu_type);
925 menu.title = title;
926 menu.cmd_keys = cmd_keys;
927 menu.count = N_ELEMENTS(sval_dependent) + N_ELEMENTS(extra_item_options) + 1;
928 menu_init2(&menu, find_menu_skin(MN_SCROLL), &options_item_iter, &SCREEN_REGION);
930 menu_layout(&menu, &SCREEN_REGION);
932 /* Save and clear screen */
933 screen_save();
934 clear_from(0);
936 while (c.key != ESCAPE)
938 clear_from(0);
939 c = menu_select(&menu, &cursor, 0);
941 if (c.type == EVT_SELECT)
943 if ((size_t) cursor < N_ELEMENTS(sval_dependent))
945 sval_menu(sval_dependent[cursor].tval, sval_dependent[cursor].desc);
947 else
949 cursor = cursor - N_ELEMENTS(sval_dependent) - 1;
950 if ((size_t) cursor < N_ELEMENTS(extra_item_options))
951 extra_item_options[cursor].action(NULL, NULL);
956 /* Load screen and finish */
957 screen_load();
958 return;