OSDN Git Service

add translation
[jnethack/source.git] / src / options.c
1 /* NetHack 3.6  options.c       $NHDT-Date: 1448241657 2015/11/23 01:20:57 $  $NHDT-Branch: master $:$NHDT-Revision: 1.243 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 /* JNetHack Copyright */
6 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
7 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016            */
8 /* JNetHack may be freely redistributed.  See license for details. */
9
10 #ifdef OPTION_LISTS_ONLY /* (AMIGA) external program for opt lists */
11 #include "config.h"
12 #include "objclass.h"
13 #include "flag.h"
14 NEARDATA struct flag flags; /* provide linkage */
15 #ifdef SYSFLAGS
16 NEARDATA struct sysflag sysflags; /* provide linkage */
17 #endif
18 NEARDATA struct instance_flags iflags; /* provide linkage */
19 #define static
20 #else
21 #include "hack.h"
22 #include "tcap.h"
23 #include <ctype.h>
24 #endif
25
26 #define BACKWARD_COMPAT
27 #define WINTYPELEN 16
28
29 #ifdef DEFAULT_WC_TILED_MAP
30 #define PREFER_TILED TRUE
31 #else
32 #define PREFER_TILED FALSE
33 #endif
34
35 #define MESSAGE_OPTION 1
36 #define STATUS_OPTION 2
37 #define MAP_OPTION 3
38 #define MENU_OPTION 4
39 #define TEXT_OPTION 5
40
41 #define PILE_LIMIT_DFLT 5
42
43 /*
44  *  NOTE:  If you add (or delete) an option, please update the short
45  *  options help (option_help()), the long options help (dat/opthelp),
46  *  and the current options setting display function (doset()),
47  *  and also the Guidebooks.
48  *
49  *  The order matters.  If an option is a an initial substring of another
50  *  option (e.g. time and timed_delay) the shorter one must come first.
51  */
52
53 static struct Bool_Opt {
54     const char *name;
55     boolean *addr, initvalue;
56     int optflags;
57 } boolopt[] = {
58     { "acoustics", &flags.acoustics, TRUE, SET_IN_GAME },
59 #if defined(SYSFLAGS) && defined(AMIGA)
60     /* Amiga altmeta causes Alt+key to be converted into Meta+key by
61        low level nethack code; on by default, can be toggled off if
62        Alt+key is needed for some ASCII chars on non-ASCII keyboard */
63     { "altmeta", &sysflags.altmeta, TRUE, DISP_IN_GAME },
64 #else
65 #ifdef ALTMETA
66     /* non-Amiga altmeta causes nethack's top level command loop to treat
67        two character sequence "ESC c" as M-c, for terminals or emulators
68        which send "ESC c" when Alt+c is pressed; off by default, enabling
69        this can potentially make trouble if user types ESC when nethack
70        is honoring this conversion request (primarily after starting a
71        count prefix prior to a command and then deciding to cancel it) */
72     { "altmeta", &iflags.altmeta, FALSE, SET_IN_GAME },
73 #else
74     { "altmeta", (boolean *) 0, TRUE, DISP_IN_GAME },
75 #endif
76 #endif
77     { "ascii_map", &iflags.wc_ascii_map, !PREFER_TILED, SET_IN_GAME }, /*WC*/
78 #if defined(SYSFLAGS) && defined(MFLOPPY)
79     { "asksavedisk", &sysflags.asksavedisk, FALSE, SET_IN_GAME },
80 #else
81     { "asksavedisk", (boolean *) 0, FALSE, SET_IN_FILE },
82 #endif
83     { "autodig", &flags.autodig, FALSE, SET_IN_GAME },
84     { "autoopen", &flags.autoopen, TRUE, SET_IN_GAME },
85     { "autopickup", &flags.pickup, TRUE, SET_IN_GAME },
86     { "autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME },
87 #if defined(MICRO) && !defined(AMIGA)
88     { "BIOS", &iflags.BIOS, FALSE, SET_IN_FILE },
89 #else
90     { "BIOS", (boolean *) 0, FALSE, SET_IN_FILE },
91 #endif
92     { "blind", &u.uroleplay.blind, FALSE, DISP_IN_GAME },
93     { "bones", &flags.bones, TRUE, SET_IN_FILE },
94 #ifdef INSURANCE
95     { "checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME },
96 #else
97     { "checkpoint", (boolean *) 0, FALSE, SET_IN_FILE },
98 #endif
99 #ifdef MFLOPPY
100     { "checkspace", &iflags.checkspace, TRUE, SET_IN_GAME },
101 #else
102     { "checkspace", (boolean *) 0, FALSE, SET_IN_FILE },
103 #endif
104     { "clicklook", &iflags.clicklook, FALSE, SET_IN_GAME },
105     { "cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME },
106 #if defined(MICRO) || defined(WIN32)
107     { "color", &iflags.wc_color, TRUE, SET_IN_GAME }, /*WC*/
108 #else /* systems that support multiple terminals, many monochrome */
109     { "color", &iflags.wc_color, FALSE, SET_IN_GAME }, /*WC*/
110 #endif
111     { "confirm", &flags.confirm, TRUE, SET_IN_GAME },
112     { "dark_room", &flags.dark_room, TRUE, SET_IN_GAME },
113     { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE,
114       SET_IN_GAME }, /*WC*/
115 #ifdef TTY_GRAPHICS
116     { "extmenu", &iflags.extmenu, FALSE, SET_IN_GAME },
117 #else
118     { "extmenu", (boolean *) 0, FALSE, SET_IN_FILE },
119 #endif
120 #ifdef OPT_DISPMAP
121     { "fast_map", &flags.fast_map, TRUE, SET_IN_GAME },
122 #else
123     { "fast_map", (boolean *) 0, TRUE, SET_IN_FILE },
124 #endif
125     { "female", &flags.female, FALSE, DISP_IN_GAME },
126     { "fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME },
127 #if defined(SYSFLAGS) && defined(AMIFLUSH)
128     { "flush", &sysflags.amiflush, FALSE, SET_IN_GAME },
129 #else
130     { "flush", (boolean *) 0, FALSE, SET_IN_FILE },
131 #endif
132     { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE },
133     { "help", &flags.help, TRUE, SET_IN_GAME },
134     { "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
135     { "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
136 #ifndef MAC
137     { "ignintr", &flags.ignintr, FALSE, SET_IN_GAME },
138 #else
139     { "ignintr", (boolean *) 0, FALSE, SET_IN_FILE },
140 #endif
141     { "implicit_uncursed", &iflags.implicit_uncursed, TRUE, SET_IN_GAME },
142     { "large_font", &iflags.obsolete, FALSE, SET_IN_FILE }, /* OBSOLETE */
143     { "legacy", &flags.legacy, TRUE, DISP_IN_GAME },
144     { "lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME },
145     { "lootabc", &flags.lootabc, FALSE, SET_IN_GAME },
146 #ifdef MAIL
147     { "mail", &flags.biff, TRUE, SET_IN_GAME },
148 #else
149     { "mail", (boolean *) 0, TRUE, SET_IN_FILE },
150 #endif
151     { "mention_walls", &iflags.mention_walls, FALSE, SET_IN_GAME },
152     { "menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME },
153     /* for menu debugging only*/
154     { "menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME },
155     { "menu_objsyms", &iflags.menu_head_objsym, FALSE, SET_IN_GAME },
156     { "mouse_support", &iflags.wc_mouse_support, TRUE, DISP_IN_GAME }, /*WC*/
157 #ifdef NEWS
158     { "news", &iflags.news, TRUE, DISP_IN_GAME },
159 #else
160     { "news", (boolean *) 0, FALSE, SET_IN_FILE },
161 #endif
162     { "nudist", &u.uroleplay.nudist, FALSE, DISP_IN_GAME },
163     { "null", &flags.null, TRUE, SET_IN_GAME },
164 #if defined(SYSFLAGS) && defined(MAC)
165     { "page_wait", &sysflags.page_wait, TRUE, SET_IN_GAME },
166 #else
167     { "page_wait", (boolean *) 0, FALSE, SET_IN_FILE },
168 #endif
169     { "perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME },
170     { "pickup_thrown", &flags.pickup_thrown, TRUE, SET_IN_GAME },
171     { "popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME },   /*WC*/
172     { "preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME }, /*WC*/
173     { "pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME },
174 #if defined(MICRO) && !defined(AMIGA)
175     { "rawio", &iflags.rawio, FALSE, DISP_IN_GAME },
176 #else
177     { "rawio", (boolean *) 0, FALSE, SET_IN_FILE },
178 #endif
179     { "rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME },
180 #ifdef RLECOMP
181     { "rlecomp", &iflags.rlecomp,
182 #if defined(COMPRESS) || defined(ZLIB_COMP)
183       FALSE,
184 #else
185       TRUE,
186 #endif
187       DISP_IN_GAME },
188 #endif
189     { "safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME },
190     { "sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME },
191     { "selectsaved", &iflags.wc2_selectsaved, TRUE, DISP_IN_GAME }, /*WC*/
192     { "showexp", &flags.showexp, FALSE, SET_IN_GAME },
193     { "showrace", &flags.showrace, FALSE, SET_IN_GAME },
194 #ifdef SCORE_ON_BOTL
195     { "showscore", &flags.showscore, FALSE, SET_IN_GAME },
196 #else
197     { "showscore", (boolean *) 0, FALSE, SET_IN_FILE },
198 #endif
199     { "silent", &flags.silent, TRUE, SET_IN_GAME },
200     { "softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE },
201     { "sortpack", &flags.sortpack, TRUE, SET_IN_GAME },
202     { "sparkle", &flags.sparkle, TRUE, SET_IN_GAME },
203     { "splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME }, /*WC*/
204     { "standout", &flags.standout, FALSE, SET_IN_GAME },
205 #if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES)
206     { "statushilites", &iflags.use_status_hilites, TRUE, SET_IN_GAME },
207 #else
208     { "statushilites", &iflags.use_status_hilites, FALSE, DISP_IN_GAME },
209 #endif
210     { "tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME }, /*WC*/
211     { "time", &flags.time, FALSE, SET_IN_GAME },
212 #ifdef TIMED_DELAY
213     { "timed_delay", &flags.nap, TRUE, SET_IN_GAME },
214 #else
215     { "timed_delay", (boolean *) 0, FALSE, SET_IN_GAME },
216 #endif
217     { "tombstone", &flags.tombstone, TRUE, SET_IN_GAME },
218     { "toptenwin", &iflags.toptenwin, FALSE, SET_IN_GAME },
219     { "travel", &flags.travelcmd, TRUE, SET_IN_GAME },
220     { "use_darkgray", &iflags.wc2_darkgray, TRUE, SET_IN_FILE },
221 #ifdef WIN32
222     { "use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME }, /*WC*/
223 #else
224     { "use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME }, /*WC*/
225 #endif
226     { "verbose", &flags.verbose, TRUE, SET_IN_GAME },
227     { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME },
228 #ifdef ZEROCOMP
229     { "zerocomp", &iflags.zerocomp,
230 #if defined(COMPRESS) || defined(ZLIB_COMP)
231       FALSE,
232 #else
233       TRUE,
234 #endif
235       DISP_IN_GAME },
236 #endif
237     { (char *) 0, (boolean *) 0, FALSE, 0 }
238 };
239
240 /* compound options, for option_help() and external programs like Amiga
241  * frontend */
242 static struct Comp_Opt {
243     const char *name, *descr;
244     int size; /* for frontends and such allocating space --
245                * usually allowed size of data in game, but
246                * occasionally maximum reasonable size for
247                * typing when game maintains information in
248                * a different format */
249     int optflags;
250 } compopt[] = {
251 /*JP
252     { "align", "your starting alignment (lawful, neutral, or chaotic)", 8,
253 */
254     { "align",    "\83Q\81[\83\80\83X\83^\81[\83g\8e\9e\82Ì\91®\90« (lawful, neutral, or chaotic\82Ì\82¢\82¸\82ê\82©)", 8,
255       DISP_IN_GAME },
256 #if 0 /*JP*/
257     { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/
258 #else
259     { "align_message", "\83\81\83b\83Z\81[\83W\83E\83B\83\93\83h\83E\82Ì\91µ\82¦", 20, DISP_IN_GAME }, /*WC*/
260 #endif
261 #if 0 /*JP*/
262     { "align_status", "status window alignment", 20, DISP_IN_GAME },   /*WC*/
263 #else
264     { "align_status", "\8fó\8bµ\83E\83B\83\93\83h\83E\82Ì\91µ\82¦", 20, DISP_IN_GAME }, /*WC*/
265 #endif
266 /*JP
267     { "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
268 */
269     { "altkeyhandler", "ALT\83L\81[\83n\83\93\83h\83\89", 20, DISP_IN_GAME },
270 #ifdef BACKWARD_COMPAT
271 /*JP
272     { "boulder", "deprecated (use S_boulder in sym file instead)", 1,
273 */
274     { "boulder",  "\8b\90\8aâ\82ð\95\\8e¦\82·\82é\83V\83\93\83{\83\8b\95\8e\9a", 1,
275       SET_IN_FILE },
276 #endif
277 /*JP
278     { "catname", "the name of your (first) cat (e.g., catname:Tabby)",
279 */
280     { "catname",  "\96`\8c¯\82ð\8b\9f\82É\82·\82é(\8dÅ\8f\89\82Ì)\94L\82Ì\96¼\91O (\97á catname:\82½\82Ü)",
281       PL_PSIZ, DISP_IN_GAME },
282 /*JP
283     { "disclose", "the kinds of information to disclose at end of game",
284 */
285     { "disclose", "\83Q\81[\83\80\8fI\97¹\8e\9e\82É\8c©\82é\8fî\95ñ\82Ì\8eí\97Þ",
286       sizeof(flags.end_disclose) * 2, SET_IN_GAME },
287 /*JP
288     { "dogname", "the name of your (first) dog (e.g., dogname:Fang)", PL_PSIZ,
289 */
290     { "dogname",  "\96`\8c¯\82ð\8b\9f\82É\82·\82é(\8dÅ\8f\89\82Ì)\8c¢\82Ì\96¼\91O (\97á dogname:\83|\83`)", PL_PSIZ,
291       DISP_IN_GAME },
292 /*JP
293     { "dungeon", "the symbols to use in drawing the dungeon map",
294 */
295     { "dungeon",  "\83_\83\93\83W\83\87\83\93\82ð\95`\89æ\82·\82é\83V\83\93\83{\83\8b\95\8e\9a",
296       MAXDCHARS + 1, SET_IN_FILE },
297 /*JP
298     { "effects", "the symbols to use in drawing special effects",
299 */
300     { "effects",  "\93Á\8eê\8cø\89Ê\82ð\95`\89æ\82·\82é\83V\83\93\83{\83\8b\95\8e\9a",
301       MAXECHARS + 1, SET_IN_FILE },
302 /*JP
303     { "font_map", "the font to use in the map window", 40,
304 */
305     { "font_map", "\83}\83b\83v\83E\83B\83\93\83h\83E\82É\8eg\97p\82·\82é\83t\83H\83\93\83g", 40,
306       DISP_IN_GAME },                                              /*WC*/
307 #if 0 /*JP*/
308     { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/
309 #else
310     { "font_menu", "\83\81\83j\83\85\81[\82É\8eg\97p\82·\82é\83t\83H\83\93\83g", 40, DISP_IN_GAME }, /*WC*/
311 #endif
312 /*JP
313     { "font_message", "the font to use in the message window", 40,
314 */
315     { "font_message", "\83\81\83b\83Z\81[\83W\83E\83B\83\93\83h\83E\82É\8eg\97p\82·\82é\83t\83H\83\93\83g", 40,
316       DISP_IN_GAME },                                                  /*WC*/
317 #if 0 /*JP*/
318     { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/
319 #else
320     { "font_size_map", "\83}\83b\83v\83t\83H\83\93\83g\82Ì\83T\83C\83Y", 20, DISP_IN_GAME }, /*WC*/
321 #endif
322 /*JP
323     { "font_size_menu", "the size of the menu font", 20,
324 */
325     { "font_size_menu", "\83\81\83j\83\85\81[\83t\83H\83\93\83g\82Ì\83T\83C\83Y", 20,
326       DISP_IN_GAME }, /*WC*/
327 /*JP
328     { "font_size_message", "the size of the message font", 20,
329 */
330     { "font_size_message", "\83\81\83b\83Z\81[\83W\83t\83H\83\93\83g\82Ì\83T\83C\83Y", 20,
331       DISP_IN_GAME }, /*WC*/
332 /*JP
333     { "font_size_status", "the size of the status font", 20,
334 */
335     { "font_size_status", "\8fó\8bµ\83t\83H\83\93\83g\82Ì\83T\83C\83Y", 20,
336       DISP_IN_GAME }, /*WC*/
337 /*JP
338     { "font_size_text", "the size of the text font", 20,
339 */
340     { "font_size_text", "\83e\83L\83X\83g\83t\83H\83\93\83g\82Ì\83T\83C\83Y", 20,
341       DISP_IN_GAME }, /*WC*/
342 /*JP
343     { "font_status", "the font to use in status window", 40,
344 */
345     { "font_status", "\8fó\8bµ\83E\83B\83\93\83h\83E\82É\8eg\97p\82·\82é\83t\83H\83\93\83g", 40,
346       DISP_IN_GAME }, /*WC*/
347 /*JP
348     { "font_text", "the font to use in text windows", 40,
349 */
350     { "font_text", "\83e\83L\83X\83g\83E\83B\83\93\83h\83E\82É\8eg\97p\82·\82é\83t\83H\83\93\83g", 40,
351       DISP_IN_GAME }, /*WC*/
352 /*JP
353     { "fruit", "the name of a fruit you enjoy eating", PL_FSIZ, SET_IN_GAME },
354 */
355     { "fruit", "\8dD\95¨\82Ì\89Ê\95¨\82Ì\96¼\91O", PL_FSIZ, SET_IN_GAME },
356 /*JP
357     { "gender", "your starting gender (male or female)", 8, DISP_IN_GAME },
358 */
359     { "gender", "\83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\90«\95Ê(male \82Ü\82½\82Í female)", 8, DISP_IN_GAME },
360 /*JP
361     { "horsename", "the name of your (first) horse (e.g., horsename:Silver)",
362 */
363     { "horsename", "\96`\8c¯\82ð\8b\9f\82É\82·\82é(\8dÅ\8f\89\82Ì)\94n\82Ì\96¼\91O (\97á ghoulname:\83V\83\8b\83o\81[)",
364       PL_PSIZ, DISP_IN_GAME },
365 #if 0 /*JP*/
366     { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/
367 #else
368     { "map_mode", "\83E\83B\83\93\83h\83E\95\\8e¦\8e\9e\82Ì\83}\83b\83v\82Ì\95\\8e¦\83\82\81[\83h", 20, DISP_IN_GAME }, /*WC*/
369 #endif
370 /*JP
371     { "menustyle", "user interface for object selection", MENUTYPELEN,
372 */
373     { "menustyle", "\83I\83u\83W\83F\83N\83g\82ð\91I\91ð\82·\82é\82Æ\82«\82Ì\83\86\81[\83U\81[\83C\83\93\83^\83t\83F\81[\83X", MENUTYPELEN,
374       SET_IN_GAME },
375 /*JP
376     { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE },
377 */
378     { "menu_deselect_all", "\91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\94ñ\91I\91ð", 4, SET_IN_FILE },
379 /*JP
380     { "menu_deselect_page", "deselect all items on this page of a menu", 4,
381 */
382     { "menu_deselect_page", "\8c»\8dÝ\95\\8e¦\82³\82ê\82Ä\82¢\82é\83y\81[\83W\82Ì\83A\83C\83e\83\80\82ð\94ñ\91I\91ð", 4,
383       SET_IN_FILE },
384 /*JP
385     { "menu_first_page", "jump to the first page in a menu", 4, SET_IN_FILE },
386 */
387     { "menu_first_page", "\83\81\83j\83\85\81[\82Ì\8dÅ\8f\89\82Ì\83y\81[\83W\82Ö", 4, SET_IN_FILE },
388 /*JP
389     { "menu_headings", "text attribute for menu headings", 9, SET_IN_GAME },
390 */
391     { "menu_headings", "\8b­\92²\81C\94½\93]\82Ü\82½\82Í\89º\90ü\82Å\8eí\97Þ\82ð\95\\8e¦\82·\82é", 9, SET_IN_GAME },
392 /*JP
393     { "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
394 */
395     { "menu_invert_all", "\91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\94½\93]", 4, SET_IN_FILE },
396 /*JP
397     { "menu_invert_page", "invert all items on this page of a menu", 4,
398 */
399     { "menu_invert_page", "\8c»\8dÝ\95\\8e¦\82³\82ê\82Ä\82¢\82é\83y\81[\83W\82Ì\83A\83C\83e\83\80\82ð\94½\93]",
400       SET_IN_FILE },
401 /*JP
402     { "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE },
403 */
404     { "menu_last_page", "\83\81\83j\83\85\81[\82Ì\8dÅ\8cã\82Ì\83y\81[\83W\82Ö", 4, SET_IN_FILE },
405 /*JP
406     { "menu_next_page", "goto the next menu page", 4, SET_IN_FILE },
407 */
408     { "menu_next_page", "\8e\9f\82Ì\83\81\83j\83\85\81[\82Ì\83y\81[\83W\82Ö", 4, SET_IN_FILE },
409 /*JP
410     { "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE },
411 */
412     { "menu_previous_page", "\91O\82Ì\83\81\83j\83\85\81[\82Ì\83y\81[\83W\82Ö", 4, SET_IN_FILE },
413 /*JP
414     { "menu_search", "search for a menu item", 4, SET_IN_FILE },
415 */
416     { "menu_search", "\83\81\83j\83\85\81[\82Ì\8c\9f\8dõ", 4, SET_IN_FILE },
417 /*JP
418     { "menu_select_all", "select all items in a menu", 4, SET_IN_FILE },
419 */
420     { "menu_select_all", "\91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\91I\91ð", 4, SET_IN_FILE },
421 /*JP
422     { "menu_select_page", "select all items on this page of a menu", 4,
423 */
424     { "menu_select_page", "\8c»\8dÝ\95\\8e¦\82³\82ê\82Ä\82¢\82é\91S\82Ä\82Ì\83A\83C\83e\83\80\82ð\91I\91ð", 4,
425       SET_IN_FILE },
426 /*JP
427     { "monsters", "the symbols to use for monsters", MAXMCLASSES,
428 */
429     { "monsters", "\83\82\83\93\83X\83^\81[\82É\8eg\97p\82³\82ê\82é\83V\83\93\83{\83\8b\95\8e\9a", MAXMCLASSES,
430       SET_IN_FILE },
431 /*JP
432     { "msghistory", "number of top line messages to save", 5, DISP_IN_GAME },
433 */
434     { "msghistory", "\90æ\93ª\8ds\82É\95\\8e¦\82³\82ê\82½\83\81\83b\83Z\81[\83W\97\9a\97ð\82Ì\95Û\91\90\94", 5, DISP_IN_GAME },
435 #ifdef TTY_GRAPHICS
436 /*JP
437     { "msg_window", "the type of message window required", 1, SET_IN_GAME },
438 */
439     {"msg_window", "\83\81\83b\83Z\81[\83W\83E\83B\83\93\83h\83E\82Ì\83^\83C\83v\82ð\90Ý\92è",1, SET_IN_GAME },
440 #else
441 /*JP
442     { "msg_window", "the type of message window required", 1, SET_IN_FILE },
443 */
444     {"msg_window", "\83\81\83b\83Z\81[\83W\83E\83B\83\93\83h\83E\82Ì\83^\83C\83v\82ð\90Ý\92è", 1, SET_IN_FILE },
445 #endif
446 /*JP
447     { "name", "your character's name (e.g., name:Merlin-W)", PL_NSIZ,
448 */
449     { "name", "\82 \82È\82½\82Ì\96¼\91O (\97á name:\83}\81[\83\8a\83\93-W)", PL_NSIZ,
450       DISP_IN_GAME },
451 /*JP
452     { "number_pad", "use the number pad for movement", 1, SET_IN_GAME },
453 */
454     { "number_pad", "\83i\83\93\83o\81[\83p\83b\83h\82ð\8eg\97p\82·\82é", 1, SET_IN_GAME },
455 /*JP
456     { "objects", "the symbols to use for objects", MAXOCLASSES, SET_IN_FILE },
457 */
458     { "objects",  "\83A\83C\83e\83\80\82É\8eg\97p\82³\82ê\82é\83V\83\93\83{\83\8b\95\8e\9a", MAXOCLASSES, SET_IN_FILE },
459 /*JP
460     { "packorder", "the inventory order of the items in your pack",
461 */
462     { "packorder", "\94w\95\89\82¢\91Ü\93à\82Ì\95¨\82Ì\8f\87\94Ô",
463       MAXOCLASSES, SET_IN_GAME },
464 #ifdef CHANGE_COLOR
465     { "palette",
466 #ifndef WIN32
467 /*JP
468       "palette (00c/880/-fff is blue/yellow/reverse white)", 15,
469 */
470       "\83p\83\8c\83b\83g (00c/880/-fff\82Í\82»\82ê\82¼\82ê\90Â/\89©/\94½\93]\94\92\82ð\8e¦\82·)", 15,
471       SET_IN_GAME },
472 #else
473 /*JP
474       "palette (adjust an RGB color in palette (color-R-G-B)", 15,
475 */
476       "\83p\83\8c\83b\83g (\83p\83\8c\83b\83g\82ÌRGB\90F\82ð\92²\90®\82·\82é (\90F-R-G-B)", 15,
477       SET_IN_FILE },
478 #endif
479 #if defined(MAC)
480 /*JP
481     { "hicolor", "same as palette, only order is reversed", 15, SET_IN_FILE },
482 */
483     { "hicolor",  "\83p\83\8c\83b\83g\82ª\93¯\82\82Æ\82«\81A\8ew\8e¦\82µ\82½\82à\82Ì\82¾\82¯\94½\93]\82³\82¹\82é", 15, SET_IN_FILE },
484 #endif
485 #endif
486 #if 0 /*JP*/
487     { "paranoid_confirmation", "extra prompting in certain situations", 28,
488       SET_IN_GAME },
489 #else
490     { "paranoid_confirmation", "\88ê\95\94\82Ì\8fó\8bµ\82Å\92Ç\89Á\82Ì\8am\94F\82ð\82·\82é", 28,
491       SET_IN_GAME },
492 #endif
493 /*JP
494     { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME },
495 */
496     { "pettype",  "\82 \82È\82½\82Ì\91I\91ð\82µ\82½\8f\89\8aú\83y\83b\83g\82Ì\8eí\97Þ", 4, DISP_IN_GAME },
497 /*JP
498     { "pickup_burden", "maximum burden picked up before prompt", 20,
499 */
500     { "pickup_burden",  "\8fE\82¤\82Æ\82«\82É\8dÅ\91å\89×\8fd\82É\82È\82é\8eè\91O\82Å\8am\94F\82·\82é", 20,
501       SET_IN_GAME },
502 /*JP
503     { "pickup_types", "types of objects to pick up automatically",
504 */
505     { "pickup_types", "\8e©\93®\82Å\8fE\82¢\82 \82°\82é\95¨\82Ì\83V\83\93\83{\83\8b",
506       MAXOCLASSES, SET_IN_GAME },
507 #if 0 /*JP*/
508     { "pile_limit", "threshold for \"there are many objects here\"", 24,
509       SET_IN_GAME },
510 #else
511     { "pile_limit", "\81u\82±\82±\82É\82Í\82½\82­\82³\82ñ\82Ì\82à\82Ì\82ª\82 \82é\81v\82Ì\82µ\82«\82¢\92l", 24,
512       SET_IN_GAME },
513 #endif
514 #if 0 /*JP*/
515     { "playmode", "normal play, non-scoring explore mode, or debug mode", 8,
516       DISP_IN_GAME },
517 #else
518     { "playmode", "\92Ê\8fí\83\82\81[\83h\81C\92T\8c\9f\83\82\81[\83h\81C\83f\83o\83b\83O\83\82\81[\83h\82Ì\82¢\82¸\82ê\82©", 8,
519       DISP_IN_GAME },
520 #endif
521 /*JP
522     { "player_selection", "choose character via dialog or prompts", 12,
523 */
524     { "player_selection", "\83L\83\83\83\89\83N\83^\81[\91I\91ð\82É\83_\83C\83A\83\8d\83O\82â\8am\94F\89æ\96Ê\82ð\8eg\82¤", 12,
525       DISP_IN_GAME },
526 /*JP
527     { "race", "your starting race (e.g., Human, Elf)", PL_CSIZ,
528 */
529     { "race",     "\83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\8eí\91° (\97á Human, Elf)", PL_CSIZ,
530       DISP_IN_GAME },
531 /*JP
532     { "role", "your starting role (e.g., Barbarian, Valkyrie)", PL_CSIZ,
533 */
534     { "role",     "\83Q\81[\83\80\8aJ\8en\8e\9e\82Ì\90E\8bÆ (\97á Barbarian, Valkyrie)", PL_CSIZ,
535       DISP_IN_GAME },
536 /*JP
537     { "runmode", "display frequency when `running' or `travelling'",
538 */
539     { "runmode", "\83g\83\89\83x\83\8b\83R\83}\83\93\83h\93\99\82Å\82Ì\98A\91±\88Ú\93®\8e\9e\82Ì\95`\89æ\95p\93x",
540       sizeof "teleport", SET_IN_GAME },
541 /*JP
542     { "scores", "the parts of the score list you wish to see", 32,
543 */
544     { "scores",   "\83Q\81[\83\80\8fI\97¹\8e\9e\82É\8c©\82é\83X\83R\83A\82Ì\8eí\97Þ", 32,
545       SET_IN_GAME },
546 /*JP
547     { "scroll_amount", "amount to scroll map when scroll_margin is reached",
548 */
549     { "scroll_amount", "scroll_margin\82É\93Í\82¢\82½\82Æ\82«\82Ì\83}\83b\83v\83X\83N\83\8d\81[\83\8b\97Ê",
550       20, DISP_IN_GAME }, /*WC*/
551 /*JP
552     { "scroll_margin", "scroll map when this far from the edge", 20,
553 */
554     { "scroll_margin", "\83}\83b\83v\92[\82©\82ç\82Ì\83}\83b\83v\83X\83N\83\8d\81[\83\8b\8aJ\8en\8b\97\97£", 20,
555       DISP_IN_GAME }, /*WC*/
556 /*JP
557     { "sortloot", "sort object selection lists by description", 4,
558 */
559     { "sortloot", "\95¨\91Ì\91I\91ð\83\8a\83X\83g\82ð\90à\96¾\82Å\83\\81[\83g\82·\82é", 4,
560       SET_IN_GAME },
561 #ifdef MSDOS
562 /*JP
563     { "soundcard", "type of sound card to use", 20, SET_IN_FILE },
564 */
565     { "soundcard", "\8eg\97p\82µ\82Ä\82¢\82é\83T\83E\83\93\83h\83J\81[\83h\82Ì\8eí\97Þ", 20, SET_IN_FILE },
566 #endif
567 #if 0 /*JP*/
568     { "symset", "load a set of display symbols from the symbols file", 70,
569       SET_IN_GAME },
570 #else
571     { "symset", "symbols\83t\83@\83C\83\8b\82©\82ç\95\\8e¦\83V\83\93\83{\83\8b\82Ì\90Ý\92è\82ð\93Ç\82Ý\8d\9e\82Þ", 70,
572       SET_IN_GAME },
573 #endif
574 #if 0 /*JP*/
575     { "roguesymset",
576       "load a set of rogue display symbols from the symbols file", 70,
577       SET_IN_GAME },
578 #else
579     { "roguesymset",
580       "symbols\83t\83@\83C\83\8b\82©\82ç\83\8d\81[\83O\83\8c\83x\83\8b\82Ì\95\\8e¦\83V\83\93\83{\83\8b\82Ì\90Ý\92è\82ð\93Ç\82Ý\8d\9e\82Þ", 70,
581       SET_IN_GAME },
582 #endif
583 /*JP
584     { "suppress_alert", "suppress alerts about version-specific features", 8,
585 */
586     { "suppress_alert", "\83o\81[\83W\83\87\83\93\8aÔ\82Ì\88á\82¢\82É\8aÖ\82·\82é\8cx\8d\90\83\81\83b\83Z\81[\83W\82Ì\96³\8cø\89»", 8,
587       SET_IN_GAME },
588 #if 0 /*JP*/
589     { "tile_width", "width of tiles", 20, DISP_IN_GAME },   /*WC*/
590 #else
591     { "tile_width", "\83^\83C\83\8b\82Ì\95\9d", 20, DISP_IN_GAME }, /*WC*/
592 #endif
593 #if 0 /*JP*/
594     { "tile_height", "height of tiles", 20, DISP_IN_GAME }, /*WC*/
595 #else
596     { "tile_height", "\83^\83C\83\8b\82Ì\8d\82\82³", 20, DISP_IN_GAME }, /*WC*/
597 #endif
598 #if 0 /*JP*/
599     { "tile_file", "name of tile file", 70, DISP_IN_GAME }, /*WC*/
600 #else
601     { "tile_file", "\83^\83C\83\8b\83t\83@\83C\83\8b\82Ì\96¼\91O", 70, DISP_IN_GAME }, /*WC*/
602 #endif
603 /*JP
604     { "traps", "the symbols to use in drawing traps", MAXTCHARS + 1,
605 */
606     { "traps", "ã©\82ð\95`\89æ\82·\82é\83V\83\93\83{\83\8b\95\8e\9a", MAXTCHARS + 1,
607       SET_IN_FILE },
608 /*JP
609     { "vary_msgcount", "show more old messages at a time", 20,
610 */
611     { "vary_msgcount", "\88ê\93x\82É\95\\8e¦\82·\82é\83\81\83b\83Z\81[\83W\82Ì\90\94", 20,
612       DISP_IN_GAME }, /*WC*/
613 #ifdef MSDOS
614 /*JP
615     { "video", "method of video updating", 20, SET_IN_FILE },
616 */
617     { "video", "\8eg\97p\82·\82é\83r\83f\83I\83\82\81[\83h\82ð\90Ý\92è\82·\82é", 20, SET_IN_FILE },
618 #endif
619 #ifdef VIDEOSHADES
620 /*JP
621     { "videocolors", "color mappings for internal screen routines", 40,
622 */
623     { "videocolors", "\93à\91 \83X\83N\83\8a\81[\83\93\83\8b\81[\83`\83\93\97p\82Ì\83J\83\89\81[\83}\83b\83v\82ð\97p\82¢\82é", 40,
624       DISP_IN_GAME },
625 /*JP
626     { "videoshades", "gray shades to map to black/gray/white", 32,
627 */
628     { "videoshades", "\95\\8e¦\82É\83O\83\8c\83C\83X\83P\81[\83\8b\82ð\97p\82¢\82é", 32,
629       DISP_IN_GAME },
630 #endif
631 #ifdef WIN32
632 /*JP
633     { "subkeyvalue", "override keystroke value", 7, SET_IN_FILE },
634 */
635     {"subkeyvalue", "\83L\81[\83}\83b\83s\83\93\83O\82ð\95Ï\8dX\82·\82é", 7, SET_IN_FILE },
636 #endif
637 #if 0 /*JP*/
638     { "windowcolors", "the foreground/background colors of windows", /*WC*/
639 #else
640     { "windowcolors",  "\83E\83B\83\93\83h\83E\82ð\8ew\92è\82µ\82½\91O\8ci\90F/\94w\8ci\90F\82Å\95\\8e¦\82·\82é", /*WC*/
641 #endif
642       80, DISP_IN_GAME },
643 /*JP
644     { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
645 */
646     { "windowtype", "\8eg\97p\82·\82é\83E\83C\83\93\83h\83E\83V\83X\83e\83\80", WINTYPELEN, DISP_IN_GAME },
647 #ifdef WINCHAIN
648 /*JP
649     { "windowchain", "window processor to use", WINTYPELEN, SET_IN_SYS },
650 */
651     { "windowchain", "\8eg\97p\82·\82é\83E\83B\83\93\83h\83E\83v\83\8d\83Z\83b\83T", WINTYPELEN, SET_IN_SYS },
652 #endif
653 #ifdef BACKWARD_COMPAT
654 /*JP
655     { "DECgraphics", "load DECGraphics display symbols", 70, SET_IN_FILE },
656 */
657     { "DECgraphics", "DECGraphics\95\\8e¦\83V\83\93\83{\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ", 70, SET_IN_FILE },
658 /*JP
659     { "IBMgraphics", "load IBMGraphics display symbols", 70, SET_IN_FILE },
660 */
661     { "IBMgraphics", "IBMGraphics\95\\8e¦\83V\83\93\83{\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ", 70, SET_IN_FILE },
662 #ifdef MAC_GRAPHICS_ENV
663 /*JP
664     { "Macgraphics", "load MACGraphics display symbols", 70, SET_IN_FILE },
665 */
666     { "Macgraphics", "MACGraphics\95\\8e¦\83V\83\93\83{\83\8b\82ð\93Ç\82Ý\8d\9e\82Þ", 70, SET_IN_FILE },
667 #endif
668 #endif
669 #if 1 /*JP*/
670     { "kcode", "\92[\96\96\82Ì\8a¿\8e\9a\83R\81[\83h,", 4, SET_IN_FILE },
671 #endif
672     { (char *) 0, (char *) 0, 0, 0 }
673 };
674
675 #ifdef OPTION_LISTS_ONLY
676 #undef static
677
678 #else /* use rest of file */
679
680 extern struct symparse loadsyms[];
681 static boolean need_redraw; /* for doset() */
682
683 #if defined(TOS) && defined(TEXTCOLOR)
684 extern boolean colors_changed;  /* in tos.c */
685 #endif
686
687 #ifdef VIDEOSHADES
688 extern char *shade[3];          /* in sys/msdos/video.c */
689 extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */
690 #endif
691
692 static char def_inv_order[MAXOCLASSES] = {
693     COIN_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS,
694     SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS,
695     TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
696 };
697
698 /*
699  * Default menu manipulation command accelerators.  These may _not_ be:
700  *
701  *      + a number - reserved for counts
702  *      + an upper or lower case US ASCII letter - used for accelerators
703  *      + ESC - reserved for escaping the menu
704  *      + NULL, CR or LF - reserved for commiting the selection(s).  NULL
705  *        is kind of odd, but the tty's xwaitforspace() will return it if
706  *        someone hits a <ret>.
707  *      + a default object class symbol - used for object class accelerators
708  *
709  * Standard letters (for now) are:
710  *
711  *              <  back 1 page
712  *              >  forward 1 page
713  *              ^  first page
714  *              |  last page
715  *              :  search
716  *
717  *              page            all
718  *               ,    select     .
719  *               \    deselect   -
720  *               ~    invert     @
721  *
722  * The command name list is duplicated in the compopt array.
723  */
724 typedef struct {
725     const char *name;
726     char cmd;
727 } menu_cmd_t;
728
729 #define NUM_MENU_CMDS 11
730 static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = {
731 /* 0*/  { "menu_first_page", MENU_FIRST_PAGE },
732         { "menu_last_page", MENU_LAST_PAGE },
733         { "menu_next_page", MENU_NEXT_PAGE },
734         { "menu_previous_page", MENU_PREVIOUS_PAGE },
735         { "menu_select_all", MENU_SELECT_ALL },
736 /* 5*/  { "menu_deselect_all", MENU_UNSELECT_ALL },
737         { "menu_invert_all", MENU_INVERT_ALL },
738         { "menu_select_page", MENU_SELECT_PAGE },
739         { "menu_deselect_page", MENU_UNSELECT_PAGE },
740         { "menu_invert_page", MENU_INVERT_PAGE },
741 /*10*/  { "menu_search", MENU_SEARCH },
742 };
743
744 /*
745  * Allow the user to map incoming characters to various menu commands.
746  * The accelerator list must be a valid C string.
747  */
748 #define MAX_MENU_MAPPED_CMDS 32 /* some number */
749 char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS + 1]; /* exported */
750 static char mapped_menu_op[MAX_MENU_MAPPED_CMDS + 1];
751 static short n_menu_mapped = 0;
752
753 static boolean initial, from_file;
754
755 STATIC_DCL void FDECL(doset_add_menu, (winid, const char *, int));
756 STATIC_DCL void FDECL(nmcpy, (char *, const char *, int));
757 STATIC_DCL void FDECL(escapes, (const char *, char *));
758 STATIC_DCL void FDECL(rejectoption, (const char *));
759 STATIC_DCL void FDECL(badoption, (const char *));
760 STATIC_DCL char *FDECL(string_for_opt, (char *, BOOLEAN_P));
761 STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *, BOOLEAN_P));
762 STATIC_DCL void FDECL(bad_negation, (const char *, BOOLEAN_P));
763 STATIC_DCL int FDECL(change_inv_order, (char *));
764 STATIC_DCL void FDECL(oc_to_str, (char *, char *));
765 STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
766 STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
767 STATIC_DCL boolean FDECL(special_handling, (const char *,
768                                             BOOLEAN_P, BOOLEAN_P));
769 STATIC_DCL void FDECL(warning_opts, (char *, const char *));
770 STATIC_DCL boolean FDECL(duplicate_opt_detection, (const char *, int));
771 STATIC_DCL void FDECL(complain_about_duplicate, (const char *, int));
772
773 STATIC_OVL void FDECL(wc_set_font_name, (int, char *));
774 STATIC_OVL int FDECL(wc_set_window_colors, (char *));
775 STATIC_OVL boolean FDECL(is_wc_option, (const char *));
776 STATIC_OVL boolean FDECL(wc_supported, (const char *));
777 STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
778 STATIC_OVL boolean FDECL(wc2_supported, (const char *));
779 STATIC_DCL void FDECL(remove_autopickup_exception,
780                       (struct autopickup_exception *));
781 STATIC_OVL int FDECL(count_ape_maps, (int *, int *));
782 STATIC_DCL const char *FDECL(attr2attrname, (int));
783 STATIC_DCL int NDECL(query_color);
784 STATIC_DCL int NDECL(query_msgtype);
785 STATIC_DCL int FDECL(query_attr, (const char *));
786 STATIC_DCL const char * FDECL(msgtype2name, (int));
787 STATIC_DCL boolean FDECL(msgtype_add, (int, char *));
788 STATIC_DCL void FDECL(free_one_msgtype, (int));
789 STATIC_DCL int NDECL(msgtype_count);
790 STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int));
791 STATIC_DCL void FDECL(free_one_menu_coloring, (int));
792 STATIC_DCL int NDECL(count_menucolors);
793 STATIC_DCL int FDECL(handle_add_list_remove, (const char *, int));
794
795 void
796 reglyph_darkroom()
797 {
798     xchar x, y;
799
800     for (x = 0; x < COLNO; x++)
801         for (y = 0; y < ROWNO; y++) {
802             struct rm *lev = &levl[x][y];
803
804             if (!flags.dark_room || !iflags.use_color
805                 || Is_rogue_level(&u.uz)) {
806                 if (lev->glyph == cmap_to_glyph(S_darkroom))
807                     lev->glyph = lev->waslit ? cmap_to_glyph(S_room)
808                                              : cmap_to_glyph(S_stone);
809             } else {
810                 if (lev->glyph == cmap_to_glyph(S_room) && lev->seenv
811                     && lev->waslit && !cansee(x, y))
812                     lev->glyph = cmap_to_glyph(S_darkroom);
813                 else if (lev->glyph == cmap_to_glyph(S_stone)
814                          && lev->typ == ROOM && lev->seenv && !cansee(x, y))
815                     lev->glyph = cmap_to_glyph(S_darkroom);
816             }
817         }
818     if (flags.dark_room && iflags.use_color)
819         showsyms[S_darkroom] = showsyms[S_room];
820     else
821         showsyms[S_darkroom] = showsyms[S_stone];
822 }
823
824 /* check whether a user-supplied option string is a proper leading
825    substring of a particular option name; option string might have
826    a colon or equals sign and arbitrary value appended to it */
827 boolean
828 match_optname(user_string, opt_name, min_length, val_allowed)
829 const char *user_string, *opt_name;
830 int min_length;
831 boolean val_allowed;
832 {
833     int len = (int) strlen(user_string);
834
835     if (val_allowed) {
836         const char *p = index(user_string, ':'),
837                    *q = index(user_string, '=');
838
839         if (!p || (q && q < p))
840             p = q;
841         while (p && p > user_string && isspace((uchar) * (p - 1)))
842             p--;
843         if (p)
844             len = (int) (p - user_string);
845     }
846
847     return (boolean) (len >= min_length
848                       && !strncmpi(opt_name, user_string, len));
849 }
850
851 /* most environment variables will eventually be printed in an error
852  * message if they don't work, and most error message paths go through
853  * BUFSZ buffers, which could be overflowed by a maliciously long
854  * environment variable.  If a variable can legitimately be long, or
855  * if it's put in a smaller buffer, the responsible code will have to
856  * bounds-check itself.
857  */
858 char *
859 nh_getenv(ev)
860 const char *ev;
861 {
862     char *getev = getenv(ev);
863
864     if (getev && strlen(getev) <= (BUFSZ / 2))
865         return getev;
866     else
867         return (char *) 0;
868 }
869
870 /* process options, possibly including SYSCF */
871 void
872 initoptions()
873 {
874     initoptions_init();
875 #ifdef SYSCF
876 /* someday there may be other SYSCF alternatives besides text file */
877 #ifdef SYSCF_FILE
878     /* If SYSCF_FILE is specified, it _must_ exist... */
879     assure_syscf_file();
880     /* ... and _must_ parse correctly. */
881     if (!read_config_file(SYSCF_FILE, SET_IN_SYS)) {
882         raw_printf("Error(s) found in SYSCF_FILE, quitting.");
883         terminate(EXIT_FAILURE);
884     }
885     /*
886      * TODO [maybe]: parse the sysopt entries which are space-separated
887      * lists of usernames into arrays with one name per element.
888      */
889 #endif
890 #endif
891     initoptions_finish();
892 }
893
894 void
895 initoptions_init()
896 {
897 #if defined(UNIX) || defined(VMS)
898     char *opts;
899 #endif
900     int i;
901
902     /* set up the command parsing */
903     reset_commands(TRUE); /* init */
904
905     /* initialize the random number generator */
906     setrandom();
907
908     /* for detection of configfile options specified multiple times */
909     iflags.opt_booldup = iflags.opt_compdup = (int *) 0;
910
911     for (i = 0; boolopt[i].name; i++) {
912         if (boolopt[i].addr)
913             *(boolopt[i].addr) = boolopt[i].initvalue;
914     }
915 #if defined(COMPRESS) || defined(ZLIB_COMP)
916     set_savepref("externalcomp");
917     set_restpref("externalcomp");
918 #ifdef RLECOMP
919     set_savepref("!rlecomp");
920     set_restpref("!rlecomp");
921 #endif
922 #else
923 #ifdef ZEROCOMP
924     set_savepref("zerocomp");
925     set_restpref("zerocomp");
926 #endif
927 #ifdef RLECOMP
928     set_savepref("rlecomp");
929     set_restpref("rlecomp");
930 #endif
931 #endif
932 #ifdef SYSFLAGS
933     Strcpy(sysflags.sysflagsid, "sysflags");
934     sysflags.sysflagsid[9] = (char) sizeof(struct sysflag);
935 #endif
936     flags.end_own = FALSE;
937     flags.end_top = 3;
938     flags.end_around = 2;
939     flags.paranoia_bits = PARANOID_PRAY; /* old prayconfirm=TRUE */
940     flags.pile_limit = PILE_LIMIT_DFLT;  /* 5 */
941     flags.runmode = RUN_LEAP;
942     iflags.msg_history = 20;
943 #ifdef TTY_GRAPHICS
944     iflags.prevmsg_window = 's';
945 #endif
946     iflags.menu_headings = ATR_INVERSE;
947
948     /* hero's role, race, &c haven't been chosen yet */
949     flags.initrole = flags.initrace = flags.initgend = flags.initalign =
950         ROLE_NONE;
951
952     /* Set the default monster and object class symbols. */
953     init_symbols();
954     for (i = 0; i < WARNCOUNT; i++)
955         warnsyms[i] = def_warnsyms[i].sym;
956     iflags.bouldersym = 0;
957
958     iflags.travelcc.x = iflags.travelcc.y = -1;
959
960     /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
961     (void) memcpy((genericptr_t) flags.inv_order,
962                   (genericptr_t) def_inv_order, sizeof flags.inv_order);
963     flags.pickup_types[0] = '\0';
964     flags.pickup_burden = MOD_ENCUMBER;
965     flags.sortloot = 'l'; /* sort only loot by default */
966
967     for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
968         flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
969     switch_symbols(FALSE); /* set default characters */
970 #if defined(UNIX) && defined(TTY_GRAPHICS)
971     /*
972      * Set defaults for some options depending on what we can
973      * detect about the environment's capabilities.
974      * This has to be done after the global initialization above
975      * and before reading user-specific initialization via
976      * config file/environment variable below.
977      */
978     /* this detects the IBM-compatible console on most 386 boxes */
979     if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
980         if (!symset[PRIMARY].name)
981             load_symset("IBMGraphics", PRIMARY);
982         if (!symset[ROGUESET].name)
983             load_symset("RogueIBM", ROGUESET);
984         switch_symbols(TRUE);
985 #ifdef TEXTCOLOR
986         iflags.use_color = TRUE;
987 #endif
988     }
989 #endif /* UNIX && TTY_GRAPHICS */
990 #if defined(UNIX) || defined(VMS)
991 #ifdef TTY_GRAPHICS
992     /* detect whether a "vt" terminal can handle alternate charsets */
993     if ((opts = nh_getenv("TERM"))
994         /* [could also check "xterm" which emulates vtXXX by default] */
995         && !strncmpi(opts, "vt", 2)
996         && AS && AE && index(AS, '\016') && index(AE, '\017')) {
997         if (!symset[PRIMARY].name)
998             load_symset("DECGraphics", PRIMARY);
999         switch_symbols(TRUE);
1000     }
1001 #endif
1002 #endif /* UNIX || VMS */
1003
1004 #ifdef MAC_GRAPHICS_ENV
1005     if (!symset[PRIMARY].name)
1006         load_symset("MACGraphics", PRIMARY);
1007     switch_symbols(TRUE);
1008 #endif /* MAC_GRAPHICS_ENV */
1009     flags.menu_style = MENU_FULL;
1010
1011     /* since this is done before init_objects(), do partial init here */
1012     objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
1013     nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
1014 }
1015
1016 void
1017 initoptions_finish()
1018 {
1019 #ifndef MAC
1020     char *opts = getenv("NETHACKOPTIONS");
1021
1022     if (!opts)
1023         opts = getenv("HACKOPTIONS");
1024     if (opts) {
1025         if (*opts == '/' || *opts == '\\' || *opts == '@') {
1026             if (*opts == '@')
1027                 opts++; /* @filename */
1028             /* looks like a filename */
1029             if (strlen(opts) < BUFSZ / 2)
1030                 read_config_file(opts, SET_IN_FILE);
1031         } else {
1032             read_config_file((char *) 0, SET_IN_FILE);
1033             /* let the total length of options be long;
1034              * parseoptions() will check each individually
1035              */
1036             parseoptions(opts, TRUE, FALSE);
1037         }
1038     } else
1039 #endif
1040         read_config_file((char *) 0, SET_IN_FILE);
1041
1042     (void) fruitadd(pl_fruit, (struct fruit *) 0);
1043     /*
1044      * Remove "slime mold" from list of object names.  This will
1045      * prevent it from being wished unless it's actually present
1046      * as a named (or default) fruit.  Wishing for "fruit" will
1047      * result in the player's preferred fruit [better than "\033"].
1048      */
1049     obj_descr[SLIME_MOLD].oc_name = "fruit";
1050
1051     if (iflags.bouldersym)
1052         update_bouldersym();
1053     reglyph_darkroom();
1054     return;
1055 }
1056
1057 STATIC_OVL void
1058 nmcpy(dest, src, maxlen)
1059 char *dest;
1060 const char *src;
1061 int maxlen;
1062 {
1063     int count;
1064
1065     for (count = 1; count < maxlen; count++) {
1066         if (*src == ',' || *src == '\0')
1067             break; /*exit on \0 terminator*/
1068         *dest++ = *src++;
1069     }
1070     *dest = 0;
1071 }
1072
1073 /*
1074  * escapes(): escape expansion for showsyms.  C-style escapes understood
1075  * include \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal).
1076  * The ^-prefix for control characters is also understood, and \[mM]
1077  * has the effect of 'meta'-ing the value which follows (so that the
1078  * alternate character set will be enabled).
1079  *
1080  * For 3.4.3 and earlier, input ending with "\M", backslash, or caret
1081  * prior to terminating '\0' would pull that '\0' into the output and then
1082  * keep processing past it, potentially overflowing the output buffer.
1083  * Now, trailing \ or ^ will act like \\ or \^ and add '\\' or '^' to the
1084  * output and stop there; trailing \M will fall through to \<other> and
1085  * yield 'M', then stop.  Any \X or \O followed by something other than
1086  * an appropriate digit will also fall through to \<other> and yield 'X'
1087  * or 'O', plus stop if the non-digit is end-of-string.
1088  */
1089 STATIC_OVL void
1090 escapes(cp, tp)
1091 const char *cp;
1092 char *tp;
1093 {
1094     static NEARDATA const char oct[] = "01234567", dec[] = "0123456789",
1095                                hex[] = "00112233445566778899aAbBcCdDeEfF";
1096     const char *dp;
1097     int cval, meta, dcount;
1098
1099     while (*cp) {
1100         /* \M has to be followed by something to do meta conversion,
1101            otherwise it will just be \M which ultimately yields 'M' */
1102         meta = (*cp == '\\' && (cp[1] == 'm' || cp[1] == 'M') && cp[2]);
1103         if (meta)
1104             cp += 2;
1105
1106         cval = dcount = 0; /* for decimal, octal, hexadecimal cases */
1107         if ((*cp != '\\' && *cp != '^') || !cp[1]) {
1108             /* simple character, or nothing left for \ or ^ to escape */
1109             cval = *cp++;
1110         } else if (*cp == '^') { /* expand control-character syntax */
1111             cval = (*++cp & 0x1f);
1112             ++cp;
1113             /* remaining cases are all for backslash and we know cp[1] is not
1114              * \0 */
1115         } else if (index(dec, cp[1])) {
1116             ++cp; /* move past backslash to first digit */
1117             do {
1118                 cval = (cval * 10) + (*cp - '0');
1119             } while (*++cp && index(dec, *cp) && ++dcount < 3);
1120         } else if ((cp[1] == 'o' || cp[1] == 'O') && cp[2]
1121                    && index(oct, cp[2])) {
1122             cp += 2; /* move past backslash and 'O' */
1123             do {
1124                 cval = (cval * 8) + (*cp - '0');
1125             } while (*++cp && index(oct, *cp) && ++dcount < 3);
1126         } else if ((cp[1] == 'x' || cp[1] == 'X') && cp[2]
1127                    && (dp = index(hex, cp[2])) != 0) {
1128             cp += 2; /* move past backslash and 'X' */
1129             do {
1130                 cval = (cval * 16) + ((int) (dp - hex) / 2);
1131             } while (*++cp && (dp = index(hex, *cp)) != 0 && ++dcount < 2);
1132         } else { /* C-style character escapes */
1133             switch (*++cp) {
1134             case '\\':
1135                 cval = '\\';
1136                 break;
1137             case 'n':
1138                 cval = '\n';
1139                 break;
1140             case 't':
1141                 cval = '\t';
1142                 break;
1143             case 'b':
1144                 cval = '\b';
1145                 break;
1146             case 'r':
1147                 cval = '\r';
1148                 break;
1149             default:
1150                 cval = *cp;
1151             }
1152             ++cp;
1153         }
1154
1155         if (meta)
1156             cval |= 0x80;
1157         *tp++ = (char) cval;
1158     }
1159     *tp = '\0';
1160 }
1161
1162 STATIC_OVL void
1163 rejectoption(optname)
1164 const char *optname;
1165 {
1166 #ifdef MICRO
1167     pline("\"%s\" settable only from %s.", optname, lastconfigfile);
1168 #else
1169     pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
1170           lastconfigfile);
1171 #endif
1172 }
1173
1174 STATIC_OVL void
1175 badoption(opts)
1176 const char *opts;
1177 {
1178     if (!initial) {
1179         if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1))
1180             option_help();
1181         else
1182             pline("Bad syntax: %s.  Enter \"?g\" for help.", opts);
1183         return;
1184     }
1185 #ifdef MAC
1186     else
1187         return;
1188 #endif
1189
1190     if (from_file)
1191         raw_printf("Bad syntax in OPTIONS in %s: %s%s.\n", lastconfigfile,
1192 #ifdef WIN32
1193                     "\n",
1194 #else
1195                     "",
1196 #endif
1197                     opts);
1198     else
1199         raw_printf("Bad syntax in NETHACKOPTIONS: %s%s.\n",
1200 #ifdef WIN32
1201                     "\n",
1202 #else
1203                     "",
1204 #endif
1205                     opts);
1206     wait_synch();
1207 }
1208
1209 STATIC_OVL char *
1210 string_for_opt(opts, val_optional)
1211 char *opts;
1212 boolean val_optional;
1213 {
1214     char *colon, *equals;
1215
1216     colon = index(opts, ':');
1217     equals = index(opts, '=');
1218     if (!colon || (equals && equals < colon))
1219         colon = equals;
1220
1221     if (!colon || !*++colon) {
1222         if (!val_optional)
1223             badoption(opts);
1224         return (char *) 0;
1225     }
1226     return colon;
1227 }
1228
1229 STATIC_OVL char *
1230 string_for_env_opt(optname, opts, val_optional)
1231 const char *optname;
1232 char *opts;
1233 boolean val_optional;
1234 {
1235     if (!initial) {
1236         rejectoption(optname);
1237         return (char *) 0;
1238     }
1239     return string_for_opt(opts, val_optional);
1240 }
1241
1242 STATIC_OVL void
1243 bad_negation(optname, with_parameter)
1244 const char *optname;
1245 boolean with_parameter;
1246 {
1247     pline_The("%s option may not %sbe negated.", optname,
1248               with_parameter ? "both have a value and " : "");
1249 }
1250
1251 /*
1252  * Change the inventory order, using the given string as the new order.
1253  * Missing characters in the new order are filled in at the end from
1254  * the current inv_order, except for gold, which is forced to be first
1255  * if not explicitly present.
1256  *
1257  * This routine returns 1 unless there is a duplicate or bad char in
1258  * the string.
1259  */
1260 STATIC_OVL int
1261 change_inv_order(op)
1262 char *op;
1263 {
1264     int oc_sym, num;
1265     char *sp, buf[BUFSZ];
1266
1267     num = 0;
1268     /*  !!!! probably unnecessary with gold as normal inventory */
1269
1270     for (sp = op; *sp; sp++) {
1271         oc_sym = def_char_to_objclass(*sp);
1272         /* reject bad or duplicate entries */
1273         if (oc_sym == MAXOCLASSES || oc_sym == RANDOM_CLASS
1274             || oc_sym == ILLOBJ_CLASS || !index(flags.inv_order, oc_sym)
1275             || index(sp + 1, *sp))
1276             return 0;
1277         /* retain good ones */
1278         buf[num++] = (char) oc_sym;
1279     }
1280     buf[num] = '\0';
1281
1282     /* fill in any omitted classes, using previous ordering */
1283     for (sp = flags.inv_order; *sp; sp++)
1284         if (!index(buf, *sp)) {
1285             buf[num++] = *sp;
1286             buf[num] = '\0'; /* explicitly terminate for next index() */
1287         }
1288
1289     Strcpy(flags.inv_order, buf);
1290     return 1;
1291 }
1292
1293 STATIC_OVL void
1294 warning_opts(opts, optype)
1295 register char *opts;
1296 const char *optype;
1297 {
1298     uchar translate[WARNCOUNT];
1299     int length, i;
1300
1301     if (!(opts = string_for_env_opt(optype, opts, FALSE)))
1302         return;
1303     escapes(opts, opts);
1304
1305     length = (int) strlen(opts);
1306     /* match the form obtained from PC configuration files */
1307     for (i = 0; i < WARNCOUNT; i++)
1308         translate[i] = (i >= length) ? 0
1309                                      : opts[i] ? (uchar) opts[i]
1310                                                : def_warnsyms[i].sym;
1311     assign_warnings(translate);
1312 }
1313
1314 void
1315 assign_warnings(graph_chars)
1316 register uchar *graph_chars;
1317 {
1318     int i;
1319
1320     for (i = 0; i < WARNCOUNT; i++)
1321         if (graph_chars[i])
1322             warnsyms[i] = graph_chars[i];
1323 }
1324
1325 STATIC_OVL int
1326 feature_alert_opts(op, optn)
1327 char *op;
1328 const char *optn;
1329 {
1330     char buf[BUFSZ];
1331     boolean rejectver = FALSE;
1332     unsigned long fnv = get_feature_notice_ver(op); /* version.c */
1333
1334     if (fnv == 0L)
1335         return 0;
1336     if (fnv > get_current_feature_ver())
1337         rejectver = TRUE;
1338     else
1339         flags.suppress_alert = fnv;
1340     if (rejectver) {
1341         if (!initial) {
1342             You_cant("disable new feature alerts for future versions.");
1343         } else {
1344             Sprintf(buf,
1345                     "\n%s=%s Invalid reference to a future version ignored",
1346                     optn, op);
1347             badoption(buf);
1348         }
1349         return 0;
1350     }
1351     if (!initial) {
1352         Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
1353                 FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
1354         pline(
1355           "Feature change alerts disabled for NetHack %s features and prior.",
1356               buf);
1357     }
1358     return 1;
1359 }
1360
1361 void
1362 set_duplicate_opt_detection(on_or_off)
1363 int on_or_off;
1364 {
1365     int k, *optptr;
1366
1367     if (on_or_off != 0) {
1368         /*-- ON --*/
1369         if (iflags.opt_booldup)
1370             impossible("iflags.opt_booldup already on (memory leak)");
1371         iflags.opt_booldup = (int *) alloc(SIZE(boolopt) * sizeof(int));
1372         optptr = iflags.opt_booldup;
1373         for (k = 0; k < SIZE(boolopt); ++k)
1374             *optptr++ = 0;
1375
1376         if (iflags.opt_compdup)
1377             impossible("iflags.opt_compdup already on (memory leak)");
1378         iflags.opt_compdup = (int *) alloc(SIZE(compopt) * sizeof(int));
1379         optptr = iflags.opt_compdup;
1380         for (k = 0; k < SIZE(compopt); ++k)
1381             *optptr++ = 0;
1382     } else {
1383         /*-- OFF --*/
1384         if (iflags.opt_booldup)
1385             free((genericptr_t) iflags.opt_booldup);
1386         iflags.opt_booldup = (int *) 0;
1387         if (iflags.opt_compdup)
1388             free((genericptr_t) iflags.opt_compdup);
1389         iflags.opt_compdup = (int *) 0;
1390     }
1391 }
1392
1393 STATIC_OVL boolean
1394 duplicate_opt_detection(opts, iscompound)
1395 const char *opts;
1396 int iscompound; /* 0 == boolean option, 1 == compound */
1397 {
1398     int i, *optptr;
1399
1400     if (!iscompound && iflags.opt_booldup && initial && from_file) {
1401         for (i = 0; boolopt[i].name; i++) {
1402             if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
1403                 optptr = iflags.opt_booldup + i;
1404                 *optptr += 1;
1405                 if (*optptr > 1)
1406                     return TRUE;
1407                 else
1408                     return FALSE;
1409             }
1410         }
1411     } else if (iscompound && iflags.opt_compdup && initial && from_file) {
1412         for (i = 0; compopt[i].name; i++) {
1413             if (match_optname(opts, compopt[i].name, strlen(compopt[i].name),
1414                               TRUE)) {
1415                 optptr = iflags.opt_compdup + i;
1416                 *optptr += 1;
1417                 if (*optptr > 1)
1418                     return TRUE;
1419                 else
1420                     return FALSE;
1421             }
1422         }
1423     }
1424     return FALSE;
1425 }
1426
1427 STATIC_OVL void
1428 complain_about_duplicate(opts, iscompound)
1429 const char *opts;
1430 int iscompound; /* 0 == boolean option, 1 == compound */
1431 {
1432 #ifdef MAC
1433     /* the Mac has trouble dealing with the output of messages while
1434      * processing the config file.  That should get fixed one day.
1435      * For now just return.
1436      */
1437 #else /* !MAC */
1438     raw_printf("\nWarning - %s option specified multiple times: %s.\n",
1439                iscompound ? "compound" : "boolean", opts);
1440     wait_synch();
1441 #endif /* ?MAC */
1442     return;
1443 }
1444
1445 /* paranoia[] - used by parseoptions() and special_handling() */
1446 STATIC_VAR const struct paranoia_opts {
1447     int flagmask;        /* which paranoid option */
1448     const char *argname; /* primary name */
1449     int argMinLen;       /* minimum number of letters to match */
1450     const char *synonym; /* alternate name (optional) */
1451     int synMinLen;
1452     const char *explain; /* for interactive menu */
1453 } paranoia[] = {
1454     /* there are some initial-letter conflicts: "a"ttack vs "a"ll, "attack"
1455        takes precedence and "all" isn't present in the interactive menu,
1456        and "d"ie vs "d"eath, synonyms for each other so doesn't matter;
1457        (also "p"ray vs "P"aranoia, "pray" takes precedence since "Paranoia"
1458        is just a synonym for "Confirm") */
1459     { PARANOID_CONFIRM, "Confirm", 1, "Paranoia", 2,
1460       "for \"yes\" confirmations, require \"no\" to reject" },
1461     { PARANOID_QUIT, "quit", 1, "explore", 1,
1462       "yes vs y to quit or to enter explore mode" },
1463     { PARANOID_DIE, "die", 1, "death", 2,
1464       "yes vs y to die (explore mode or debug mode)" },
1465     { PARANOID_BONES, "bones", 1, 0, 0,
1466       "yes vs y to save bones data when dying in debug mode" },
1467     { PARANOID_HIT, "attack", 1, "hit", 1,
1468       "yes vs y to attack a peaceful monster" },
1469     { PARANOID_PRAY, "pray", 1, 0, 0,
1470       "y to pray (supersedes old \"prayconfirm\" option)" },
1471     { PARANOID_REMOVE, "Remove", 1, "Takeoff", 1,
1472       "always pick from inventory for Remove and Takeoff" },
1473     { PARANOID_BREAKWAND, "wand", 1, "breakwand", 2,
1474       "yes vs y to break a wand" },
1475     /* for config file parsing; interactive menu skips these */
1476     { 0, "none", 4, 0, 0, 0 }, /* require full word match */
1477     { ~0, "all", 3, 0, 0, 0 }, /* ditto */
1478 };
1479
1480 extern struct menucoloring *menu_colorings;
1481
1482 static const struct {
1483     const char *name;
1484     const int color;
1485 } colornames[] = {
1486     { "black", CLR_BLACK },
1487     { "red", CLR_RED },
1488     { "green", CLR_GREEN },
1489     { "brown", CLR_BROWN },
1490     { "blue", CLR_BLUE },
1491     { "magenta", CLR_MAGENTA },
1492     { "cyan", CLR_CYAN },
1493     { "gray", CLR_GRAY },
1494     { "grey", CLR_GRAY },
1495     { "orange", CLR_ORANGE },
1496     { "light green", CLR_BRIGHT_GREEN },
1497     { "yellow", CLR_YELLOW },
1498     { "light blue", CLR_BRIGHT_BLUE },
1499     { "light magenta", CLR_BRIGHT_MAGENTA },
1500     { "light cyan", CLR_BRIGHT_CYAN },
1501     { "white", CLR_WHITE }
1502 };
1503
1504 static const struct {
1505     const char *name;
1506     const int attr;
1507 } attrnames[] = {
1508     { "none", ATR_NONE },
1509     { "bold", ATR_BOLD },
1510     { "dim", ATR_DIM },
1511     { "underline", ATR_ULINE },
1512     { "blink", ATR_BLINK },
1513     { "inverse", ATR_INVERSE }
1514 };
1515
1516 const char *
1517 clr2colorname(clr)
1518 int clr;
1519 {
1520     int i;
1521
1522     for (i = 0; i < SIZE(colornames); i++)
1523         if (colornames[i].color == clr)
1524             return colornames[i].name;
1525     return (char *) 0;
1526 }
1527
1528 const char *
1529 attr2attrname(attr)
1530 int attr;
1531 {
1532     int i;
1533
1534     for (i = 0; i < SIZE(attrnames); i++)
1535         if (attrnames[i].attr == attr)
1536             return attrnames[i].name;
1537     return (char *) 0;
1538 }
1539
1540 int
1541 query_color()
1542 {
1543     winid tmpwin;
1544     anything any;
1545     int i, pick_cnt;
1546     menu_item *picks = (menu_item *) 0;
1547
1548     tmpwin = create_nhwindow(NHW_MENU);
1549     start_menu(tmpwin);
1550     any = zeroany;
1551     for (i = 0; i < SIZE(colornames); i++) {
1552         if (!strcmp(colornames[i].name, "grey"))
1553             continue;
1554         any.a_int = i + 1;
1555         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name,
1556                  MENU_UNSELECTED);
1557     }
1558     end_menu(tmpwin, "Pick a color");
1559     pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
1560     destroy_nhwindow(tmpwin);
1561     if (pick_cnt > 0) {
1562         i = colornames[picks->item.a_int - 1].color;
1563         free((genericptr_t) picks);
1564         return i;
1565     }
1566     return -1;
1567 }
1568
1569 int
1570 query_attr(prompt)
1571 const char *prompt;
1572 {
1573     winid tmpwin;
1574     anything any;
1575     int i, pick_cnt;
1576     menu_item *picks = (menu_item *) 0;
1577
1578     tmpwin = create_nhwindow(NHW_MENU);
1579     start_menu(tmpwin);
1580     any = zeroany;
1581     for (i = 0; i < SIZE(attrnames); i++) {
1582         any.a_int = i + 1;
1583         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr,
1584                  attrnames[i].name, MENU_UNSELECTED);
1585     }
1586     end_menu(tmpwin, prompt ? prompt : "Pick an attribute");
1587     pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
1588     destroy_nhwindow(tmpwin);
1589     if (pick_cnt > 0) {
1590         i = attrnames[picks->item.a_int - 1].attr;
1591         free((genericptr_t) picks);
1592         return i;
1593     }
1594     return -1;
1595 }
1596
1597 static const struct {
1598     const char *name;
1599     const xchar msgtyp;
1600     const char *descr;
1601 } msgtype_names[] = {
1602     { "show", MSGTYP_NORMAL, "Show message normally" },
1603     { "hide", MSGTYP_NOSHOW, "Hide message" },
1604     { "noshow", MSGTYP_NOSHOW, NULL },
1605     { "stop", MSGTYP_STOP, "Prompt for more after the message" },
1606     { "more", MSGTYP_STOP, NULL },
1607     { "norep", MSGTYP_NOREP, "Do not repeat the message" }
1608 };
1609
1610 const char *
1611 msgtype2name(typ)
1612 int typ;
1613 {
1614     int i;
1615
1616     for (i = 0; i < SIZE(msgtype_names); i++)
1617         if (msgtype_names[i].descr && msgtype_names[i].msgtyp == typ)
1618             return msgtype_names[i].name;
1619     return (char *) 0;
1620 }
1621
1622 int
1623 query_msgtype()
1624 {
1625     winid tmpwin;
1626     anything any;
1627     int i, pick_cnt;
1628     menu_item *picks = (menu_item *) 0;
1629
1630     tmpwin = create_nhwindow(NHW_MENU);
1631     start_menu(tmpwin);
1632     any = zeroany;
1633     for (i = 0; i < SIZE(msgtype_names); i++)
1634         if (msgtype_names[i].descr) {
1635             any.a_int = msgtype_names[i].msgtyp + 1;
1636             add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
1637                  msgtype_names[i].descr, MENU_UNSELECTED);
1638         }
1639     end_menu(tmpwin, "How to show the message");
1640     pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
1641     destroy_nhwindow(tmpwin);
1642     if (pick_cnt > 0) {
1643         i = picks->item.a_int - 1;
1644         free((genericptr_t) picks);
1645         return i;
1646     }
1647     return -1;
1648 }
1649
1650 boolean
1651 msgtype_add(typ, pattern)
1652 int typ;
1653 char *pattern;
1654 {
1655     struct plinemsg_type *tmp
1656               = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type));
1657
1658     if (!tmp)
1659         return FALSE;
1660     tmp->msgtype = typ;
1661     tmp->regex = regex_init();
1662     if (!regex_compile(pattern, tmp->regex)) {
1663         static const char *re_error = "MSGTYPE regex error";
1664
1665         if (!iflags.window_inited)
1666             raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->regex));
1667         else
1668             pline("%s: %s", re_error, regex_error_desc(tmp->regex));
1669         wait_synch();
1670         regex_free(tmp->regex);
1671         free((genericptr_t) tmp);
1672         return FALSE;
1673     }
1674     tmp->pattern = dupstr(pattern);
1675     tmp->next = plinemsg_types;
1676     plinemsg_types = tmp;
1677     return TRUE;
1678 }
1679
1680 void
1681 msgtype_free()
1682 {
1683     struct plinemsg_type *tmp, *tmp2 = 0;
1684
1685     for (tmp = plinemsg_types; tmp; tmp = tmp2) {
1686         tmp2 = tmp->next;
1687         free((genericptr_t) tmp->pattern);
1688         regex_free(tmp->regex);
1689         free((genericptr_t) tmp);
1690     }
1691     plinemsg_types = (struct plinemsg_type *) 0;
1692 }
1693
1694 void
1695 free_one_msgtype(idx)
1696 int idx; /* 0 .. */
1697 {
1698     struct plinemsg_type *tmp = plinemsg_types;
1699     struct plinemsg_type *prev = NULL;
1700
1701     while (tmp) {
1702         if (idx == 0) {
1703             struct plinemsg_type *next = tmp->next;
1704
1705             regex_free(tmp->regex);
1706             free((genericptr_t) tmp->pattern);
1707             free((genericptr_t) tmp);
1708             if (prev)
1709                 prev->next = next;
1710             else
1711                 plinemsg_types = next;
1712             return;
1713         }
1714         idx--;
1715         prev = tmp;
1716         tmp = tmp->next;
1717     }
1718 }
1719
1720 int
1721 msgtype_type(msg)
1722 const char *msg;
1723 {
1724     struct plinemsg_type *tmp = plinemsg_types;
1725
1726     while (tmp) {
1727         if (regex_match(msg, tmp->regex))
1728             return tmp->msgtype;
1729         tmp = tmp->next;
1730     }
1731     return MSGTYP_NORMAL;
1732 }
1733
1734 int
1735 msgtype_count()
1736 {
1737     int c = 0;
1738     struct plinemsg_type *tmp = plinemsg_types;
1739
1740     while (tmp) {
1741         c++;
1742         tmp = tmp->next;
1743     }
1744     return c;
1745 }
1746
1747 boolean
1748 msgtype_parse_add(str)
1749 char *str;
1750 {
1751     char pattern[256];
1752     char msgtype[11];
1753
1754     if (sscanf(str, "%10s \"%255[^\"]\"", msgtype, pattern) == 2) {
1755         int typ = -1;
1756         int i;
1757
1758         for (i = 0; i < SIZE(msgtype_names); i++)
1759             if (!strncmpi(msgtype_names[i].name, msgtype, strlen(msgtype))) {
1760                 typ = msgtype_names[i].msgtyp;
1761                 break;
1762             }
1763         if (typ != -1)
1764             return msgtype_add(typ, pattern);
1765     }
1766     return FALSE;
1767 }
1768
1769 boolean
1770 add_menu_coloring_parsed(str, c, a)
1771 char *str;
1772 int c, a;
1773 {
1774     static const char re_error[] = "Menucolor regex error";
1775     struct menucoloring *tmp;
1776
1777     if (!str)
1778         return FALSE;
1779     tmp = (struct menucoloring *) alloc(sizeof (struct menucoloring));
1780     tmp->match = regex_init();
1781     if (!regex_compile(str, tmp->match)) {
1782         if (!iflags.window_inited)
1783             raw_printf("\n%s: %s\n", re_error, regex_error_desc(tmp->match));
1784         else
1785             pline("%s: %s", re_error, regex_error_desc(tmp->match));
1786         wait_synch();
1787         regex_free(tmp->match);
1788         free(tmp);
1789         return FALSE;
1790     } else {
1791         tmp->next = menu_colorings;
1792         tmp->origstr = dupstr(str);
1793         tmp->color = c;
1794         tmp->attr = a;
1795         menu_colorings = tmp;
1796         return TRUE;
1797     }
1798 }
1799
1800 /* parse '"regex_string"=color&attr' and add it to menucoloring */
1801 boolean
1802 add_menu_coloring(str)
1803 char *str;
1804 {
1805     int i, c = NO_COLOR, a = ATR_NONE;
1806     char *tmps, *cs, *amp;
1807
1808     if (!str || (cs = index(str, '=')) == 0)
1809         return FALSE;
1810
1811     tmps = cs + 1; /* advance past '=' */
1812     mungspaces(tmps);
1813     if ((amp = index(tmps, '&')) != 0)
1814         *amp = '\0';
1815
1816     /* allow "lightblue", "light blue", and "light-blue" to match "light blue"
1817        (also junk like "_l i-gh_t---b l u e" but we won't worry about that);
1818        also copes with trailing space; mungspaces removed any leading space */
1819     for (i = 0; i < SIZE(colornames); i++)
1820         if (fuzzymatch(tmps, colornames[i].name, " -_", TRUE)) {
1821             c = colornames[i].color;
1822             break;
1823         }
1824     if (i == SIZE(colornames) && (*tmps >= '0' && *tmps <= '9'))
1825         c = atoi(tmps);
1826
1827     if (c > 15)
1828         return FALSE;
1829
1830     if (amp) {
1831         tmps = amp + 1; /* advance past '&' */
1832         /* unlike colors, none of he attribute names has any embedded spaces,
1833            but use of fuzzymatch() allows us ignore the presence of leading
1834            and/or trailing (and also embedded) spaces in the user's string;
1835            dash and underscore skipping could be omitted but does no harm */
1836         for (i = 0; i < SIZE(attrnames); i++)
1837             if (fuzzymatch(tmps, attrnames[i].name, " -_", TRUE)) {
1838                 a = attrnames[i].attr;
1839                 break;
1840             }
1841         if (i == SIZE(attrnames) && (*tmps >= '0' && *tmps <= '9'))
1842             a = atoi(tmps);
1843     }
1844
1845     /* the regexp portion here has not been condensed by mungspaces() */
1846     *cs = '\0';
1847     tmps = str;
1848     if (*tmps == '"' || *tmps == '\'') {
1849         cs--;
1850         while (isspace((uchar) *cs))
1851             cs--;
1852         if (*cs == *tmps) {
1853             *cs = '\0';
1854             tmps++;
1855         }
1856     }
1857
1858     return add_menu_coloring_parsed(tmps, c, a);
1859 }
1860
1861 boolean
1862 get_menu_coloring(str, color, attr)
1863 char *str;
1864 int *color, *attr;
1865 {
1866     struct menucoloring *tmpmc;
1867
1868     if (iflags.use_menu_color)
1869         for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next)
1870             if (regex_match(str, tmpmc->match)) {
1871                 *color = tmpmc->color;
1872                 *attr = tmpmc->attr;
1873                 return TRUE;
1874             }
1875     return FALSE;
1876 }
1877
1878 void
1879 free_menu_coloring()
1880 {
1881     struct menucoloring *tmp = menu_colorings;
1882
1883     while (tmp) {
1884         struct menucoloring *tmp2 = tmp->next;
1885
1886         regex_free(tmp->match);
1887         free((genericptr_t) tmp->origstr);
1888         free((genericptr_t) tmp);
1889         tmp = tmp2;
1890     }
1891 }
1892
1893 void
1894 free_one_menu_coloring(idx)
1895 int idx; /* 0 .. */
1896 {
1897     struct menucoloring *tmp = menu_colorings;
1898     struct menucoloring *prev = NULL;
1899
1900     while (tmp) {
1901         if (idx == 0) {
1902             struct menucoloring *next = tmp->next;
1903
1904             regex_free(tmp->match);
1905             free((genericptr_t) tmp->origstr);
1906             free((genericptr_t) tmp);
1907             if (prev)
1908                 prev->next = next;
1909             else
1910                 menu_colorings = next;
1911             return;
1912         }
1913         idx--;
1914         prev = tmp;
1915         tmp = tmp->next;
1916     }
1917 }
1918
1919 int
1920 count_menucolors()
1921 {
1922     int count = 0;
1923     struct menucoloring *tmp = menu_colorings;
1924
1925     while (tmp) {
1926         count++;
1927         tmp = tmp->next;
1928     }
1929     return count;
1930 }
1931
1932 void
1933 parseoptions(opts, tinitial, tfrom_file)
1934 register char *opts;
1935 boolean tinitial, tfrom_file;
1936 {
1937     register char *op;
1938     unsigned num;
1939     boolean negated, val_negated, duplicate;
1940     int i;
1941     const char *fullname;
1942
1943     initial = tinitial;
1944     from_file = tfrom_file;
1945     if ((op = index(opts, ',')) != 0) {
1946         *op++ = 0;
1947         parseoptions(op, initial, from_file);
1948     }
1949     if (strlen(opts) > BUFSZ / 2) {
1950         badoption("option too long");
1951         return;
1952     }
1953
1954     /* strip leading and trailing white space */
1955     while (isspace((uchar) *opts))
1956         opts++;
1957     op = eos(opts);
1958     while (--op >= opts && isspace((uchar) *op))
1959         *op = '\0';
1960
1961     if (!*opts)
1962         return;
1963     negated = FALSE;
1964     while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
1965         if (*opts == '!')
1966             opts++;
1967         else
1968             opts += 2;
1969         negated = !negated;
1970     }
1971
1972     /* variant spelling */
1973
1974     if (match_optname(opts, "colour", 5, FALSE))
1975         Strcpy(opts, "color"); /* fortunately this isn't longer */
1976
1977     /* special boolean options */
1978
1979     if (match_optname(opts, "female", 3, FALSE)) {
1980         if (duplicate_opt_detection(opts, 0))
1981             complain_about_duplicate(opts, 0);
1982         if (!initial && flags.female == negated)
1983             pline("That is not anatomically possible.");
1984         else
1985             flags.initgend = flags.female = !negated;
1986         return;
1987     }
1988
1989     if (match_optname(opts, "male", 4, FALSE)) {
1990         if (duplicate_opt_detection(opts, 0))
1991             complain_about_duplicate(opts, 0);
1992         if (!initial && flags.female != negated)
1993             pline("That is not anatomically possible.");
1994         else
1995             flags.initgend = flags.female = negated;
1996         return;
1997     }
1998
1999 #if defined(MICRO) && !defined(AMIGA)
2000     /* included for compatibility with old NetHack.cnf files */
2001     if (match_optname(opts, "IBM_", 4, FALSE)) {
2002         iflags.BIOS = !negated;
2003         return;
2004     }
2005 #endif /* MICRO */
2006
2007     /* compound options */
2008
2009     /* This first batch can be duplicated if their values are negated */
2010
2011     /* align:string */
2012     fullname = "align";
2013     if (match_optname(opts, fullname, sizeof("align") - 1, TRUE)) {
2014         if (negated) {
2015             bad_negation(fullname, FALSE);
2016         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2017             val_negated = FALSE;
2018             while ((*op == '!') || !strncmpi(op, "no", 2)) {
2019                 if (*op == '!')
2020                     op++;
2021                 else
2022                     op += 2;
2023                 val_negated = !val_negated;
2024             }
2025             if (val_negated) {
2026                 if (!setrolefilter(op))
2027                     badoption(opts);
2028             } else {
2029                 if (duplicate_opt_detection(opts, 1))
2030                     complain_about_duplicate(opts, 1);
2031                 if ((flags.initalign = str2align(op)) == ROLE_NONE)
2032                     badoption(opts);
2033             }
2034         }
2035         return;
2036     }
2037
2038     /* role:string or character:string */
2039     fullname = "role";
2040     if (match_optname(opts, fullname, 4, TRUE)
2041         || match_optname(opts, (fullname = "character"), 4, TRUE)) {
2042         if (negated) {
2043             bad_negation(fullname, FALSE);
2044         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2045             val_negated = FALSE;
2046             while ((*op == '!') || !strncmpi(op, "no", 2)) {
2047                 if (*op == '!')
2048                     op++;
2049                 else
2050                     op += 2;
2051                 val_negated = !val_negated;
2052             }
2053             if (val_negated) {
2054                 if (!setrolefilter(op))
2055                     badoption(opts);
2056             } else {
2057                 if (duplicate_opt_detection(opts, 1))
2058                     complain_about_duplicate(opts, 1);
2059                 if ((flags.initrole = str2role(op)) == ROLE_NONE)
2060                     badoption(opts);
2061                 else /* Backwards compatibility */
2062                     nmcpy(pl_character, op, PL_NSIZ);
2063             }
2064         }
2065         return;
2066     }
2067
2068     /* race:string */
2069     fullname = "race";
2070     if (match_optname(opts, fullname, 4, TRUE)) {
2071         if (negated) {
2072             bad_negation(fullname, FALSE);
2073         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2074             val_negated = FALSE;
2075             while ((*op == '!') || !strncmpi(op, "no", 2)) {
2076                 if (*op == '!')
2077                     op++;
2078                 else
2079                     op += 2;
2080                 val_negated = !val_negated;
2081             }
2082             if (val_negated) {
2083                 if (!setrolefilter(op))
2084                     badoption(opts);
2085             } else {
2086                 if (duplicate_opt_detection(opts, 1))
2087                     complain_about_duplicate(opts, 1);
2088                 if ((flags.initrace = str2race(op)) == ROLE_NONE)
2089                     badoption(opts);
2090                 else /* Backwards compatibility */
2091                     pl_race = *op;
2092             }
2093         }
2094         return;
2095     }
2096
2097     /* gender:string */
2098     fullname = "gender";
2099     if (match_optname(opts, fullname, 4, TRUE)) {
2100         if (negated) {
2101             bad_negation(fullname, FALSE);
2102         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2103             val_negated = FALSE;
2104             while ((*op == '!') || !strncmpi(op, "no", 2)) {
2105                 if (*op == '!')
2106                     op++;
2107                 else
2108                     op += 2;
2109                 val_negated = !val_negated;
2110             }
2111             if (val_negated) {
2112                 if (!setrolefilter(op))
2113                     badoption(opts);
2114             } else {
2115                 if (duplicate_opt_detection(opts, 1))
2116                     complain_about_duplicate(opts, 1);
2117                 if ((flags.initgend = str2gend(op)) == ROLE_NONE)
2118                     badoption(opts);
2119                 else
2120                     flags.female = flags.initgend;
2121             }
2122         }
2123         return;
2124     }
2125
2126     /* We always check for duplicates on the remaining compound options,
2127        although individual option processing can choose to complain or not */
2128
2129     duplicate =
2130         duplicate_opt_detection(opts, 1); /* 1 means check compounds */
2131
2132     fullname = "pettype";
2133     if (match_optname(opts, fullname, 3, TRUE)) {
2134         if (duplicate)
2135             complain_about_duplicate(opts, 1);
2136         if ((op = string_for_env_opt(fullname, opts, negated)) != 0) {
2137             if (negated)
2138                 bad_negation(fullname, TRUE);
2139             else
2140                 switch (lowc(*op)) {
2141                 case 'd': /* dog */
2142                     preferred_pet = 'd';
2143                     break;
2144                 case 'c': /* cat */
2145                 case 'f': /* feline */
2146                     preferred_pet = 'c';
2147                     break;
2148                 case 'h': /* horse */
2149                 case 'q': /* quadruped */
2150                     /* avoids giving "unrecognized type of pet" but
2151                        pet_type(dog.c) won't actually honor this */
2152                     preferred_pet = 'h';
2153                     break;
2154                 case 'n': /* no pet */
2155                     preferred_pet = 'n';
2156                     break;
2157                 case '*': /* random */
2158                     preferred_pet = '\0';
2159                     break;
2160                 default:
2161 #if 0 /*JP*/
2162                     pline("Unrecognized pet type '%s'.", op);
2163 #else
2164                     pline("'%s'\82Í\83y\83b\83g\82Ì\8eí\97Þ\82Æ\82µ\82Ä\8eó\82¯\95t\82¯\82ç\82ê\82Ü\82¹\82ñ\81D", op);
2165 #endif
2166                     break;
2167                 }
2168         } else if (negated)
2169             preferred_pet = 'n';
2170         return;
2171     }
2172
2173     fullname = "catname";
2174     if (match_optname(opts, fullname, 3, TRUE)) {
2175         if (duplicate)
2176             complain_about_duplicate(opts, 1);
2177         if (negated)
2178             bad_negation(fullname, FALSE);
2179         else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
2180             nmcpy(catname, op, PL_PSIZ);
2181         sanitize_name(catname);
2182         return;
2183     }
2184
2185     fullname = "dogname";
2186     if (match_optname(opts, fullname, 3, TRUE)) {
2187         if (duplicate)
2188             complain_about_duplicate(opts, 1);
2189         if (negated)
2190             bad_negation(fullname, FALSE);
2191         else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
2192             nmcpy(dogname, op, PL_PSIZ);
2193         sanitize_name(dogname);
2194         return;
2195     }
2196
2197     fullname = "horsename";
2198     if (match_optname(opts, fullname, 5, TRUE)) {
2199         if (duplicate)
2200             complain_about_duplicate(opts, 1);
2201         if (negated)
2202             bad_negation(fullname, FALSE);
2203         else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
2204             nmcpy(horsename, op, PL_PSIZ);
2205         sanitize_name(horsename);
2206         return;
2207     }
2208
2209     fullname = "number_pad";
2210     if (match_optname(opts, fullname, 10, TRUE)) {
2211         boolean compat = (strlen(opts) <= 10);
2212
2213         if (duplicate)
2214             complain_about_duplicate(opts, 1);
2215         op = string_for_opt(opts, (compat || !initial));
2216         if (!op) {
2217             if (compat || negated || initial) {
2218                 /* for backwards compatibility, "number_pad" without a
2219                    value is a synonym for number_pad:1 */
2220                 iflags.num_pad = !negated;
2221                 iflags.num_pad_mode = 0;
2222             }
2223         } else if (negated) {
2224             bad_negation("number_pad", TRUE);
2225             return;
2226         } else {
2227             int mode = atoi(op);
2228
2229             if (mode < -1 || mode > 4 || (mode == 0 && *op != '0')) {
2230                 badoption(opts);
2231                 return;
2232             } else if (mode <= 0) {
2233                 iflags.num_pad = FALSE;
2234                 /* German keyboard; y and z keys swapped */
2235                 iflags.num_pad_mode = (mode < 0); /* 0 or 1 */
2236             } else {                              /* mode > 0 */
2237                 iflags.num_pad = TRUE;
2238                 iflags.num_pad_mode = 0;
2239                 /* PC Hack / MSDOS compatibility */
2240                 if (mode == 2 || mode == 4)
2241                     iflags.num_pad_mode |= 1;
2242                 /* phone keypad layout */
2243                 if (mode == 3 || mode == 4)
2244                     iflags.num_pad_mode |= 2;
2245             }
2246         }
2247         reset_commands(FALSE);
2248         number_pad(iflags.num_pad ? 1 : 0);
2249         return;
2250     }
2251
2252     fullname = "roguesymset";
2253     if (match_optname(opts, fullname, 7, TRUE)) {
2254         if (duplicate)
2255             complain_about_duplicate(opts, 1);
2256         if (negated) {
2257             bad_negation(fullname, FALSE);
2258         } else if ((op = string_for_opt(opts, FALSE)) != 0) {
2259             symset[ROGUESET].name = dupstr(op);
2260             if (!read_sym_file(ROGUESET)) {
2261                 clear_symsetentry(ROGUESET, TRUE);
2262                 raw_printf("Unable to load symbol set \"%s\" from \"%s\".",
2263                            op, SYMBOLS);
2264                 wait_synch();
2265             } else {
2266                 if (!initial && Is_rogue_level(&u.uz))
2267                     assign_graphics(ROGUESET);
2268                 need_redraw = TRUE;
2269             }
2270         }
2271         return;
2272     }
2273
2274     fullname = "symset";
2275     if (match_optname(opts, fullname, 6, TRUE)) {
2276         if (duplicate)
2277             complain_about_duplicate(opts, 1);
2278         if (negated) {
2279             bad_negation(fullname, FALSE);
2280         } else if ((op = string_for_opt(opts, FALSE)) != 0) {
2281             symset[PRIMARY].name = dupstr(op);
2282             if (!read_sym_file(PRIMARY)) {
2283                 clear_symsetentry(PRIMARY, TRUE);
2284                 raw_printf("Unable to load symbol set \"%s\" from \"%s\".",
2285                            op, SYMBOLS);
2286                 wait_synch();
2287             } else {
2288                 switch_symbols(TRUE);
2289                 need_redraw = TRUE;
2290             }
2291         }
2292         return;
2293     }
2294
2295     fullname = "runmode";
2296     if (match_optname(opts, fullname, 4, TRUE)) {
2297         if (duplicate)
2298             complain_about_duplicate(opts, 1);
2299         if (negated) {
2300             flags.runmode = RUN_TPORT;
2301         } else if ((op = string_for_opt(opts, FALSE)) != 0) {
2302             if (!strncmpi(op, "teleport", strlen(op)))
2303                 flags.runmode = RUN_TPORT;
2304             else if (!strncmpi(op, "run", strlen(op)))
2305                 flags.runmode = RUN_LEAP;
2306             else if (!strncmpi(op, "walk", strlen(op)))
2307                 flags.runmode = RUN_STEP;
2308             else if (!strncmpi(op, "crawl", strlen(op)))
2309                 flags.runmode = RUN_CRAWL;
2310             else
2311                 badoption(opts);
2312         }
2313         return;
2314     }
2315
2316     /* menucolor:"regex_string"=color */
2317     fullname = "menucolor";
2318     if (match_optname(opts, fullname, 9, TRUE)) {
2319         if (negated)
2320             bad_negation(fullname, FALSE);
2321         else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
2322             if (!add_menu_coloring(op))
2323                 badoption(opts);
2324         return;
2325     }
2326
2327     fullname = "msghistory";
2328     if (match_optname(opts, fullname, 3, TRUE)) {
2329         if (duplicate)
2330             complain_about_duplicate(opts, 1);
2331         op = string_for_env_opt(fullname, opts, negated);
2332         if ((negated && !op) || (!negated && op)) {
2333             iflags.msg_history = negated ? 0 : atoi(op);
2334         } else if (negated)
2335             bad_negation(fullname, TRUE);
2336         return;
2337     }
2338
2339     fullname = "msg_window";
2340     /* msg_window:single, combo, full or reversed */
2341     if (match_optname(opts, fullname, 4, TRUE)) {
2342 /* allow option to be silently ignored by non-tty ports */
2343 #ifdef TTY_GRAPHICS
2344         int tmp;
2345
2346         if (duplicate)
2347             complain_about_duplicate(opts, 1);
2348         if (!(op = string_for_opt(opts, TRUE))) {
2349             tmp = negated ? 's' : 'f';
2350         } else {
2351             if (negated) {
2352                 bad_negation(fullname, TRUE);
2353                 return;
2354             }
2355             tmp = tolower(*op);
2356         }
2357         switch (tmp) {
2358         case 's': /* single message history cycle (default if negated) */
2359             iflags.prevmsg_window = 's';
2360             break;
2361         case 'c': /* combination: two singles, then full page reversed */
2362             iflags.prevmsg_window = 'c';
2363             break;
2364         case 'f': /* full page (default if no opts) */
2365             iflags.prevmsg_window = 'f';
2366             break;
2367         case 'r': /* full page (reversed) */
2368             iflags.prevmsg_window = 'r';
2369             break;
2370         default:
2371             badoption(opts);
2372         }
2373 #endif
2374         return;
2375     }
2376
2377     /* WINCAP
2378      * setting font options  */
2379     fullname = "font";
2380     if (!strncmpi(opts, fullname, 4)) {
2381         int opttype = -1;
2382         char *fontopts = opts + 4;
2383
2384         if (!strncmpi(fontopts, "map", 3) || !strncmpi(fontopts, "_map", 4))
2385             opttype = MAP_OPTION;
2386         else if (!strncmpi(fontopts, "message", 7)
2387                  || !strncmpi(fontopts, "_message", 8))
2388             opttype = MESSAGE_OPTION;
2389         else if (!strncmpi(fontopts, "text", 4)
2390                  || !strncmpi(fontopts, "_text", 5))
2391             opttype = TEXT_OPTION;
2392         else if (!strncmpi(fontopts, "menu", 4)
2393                  || !strncmpi(fontopts, "_menu", 5))
2394             opttype = MENU_OPTION;
2395         else if (!strncmpi(fontopts, "status", 6)
2396                  || !strncmpi(fontopts, "_status", 7))
2397             opttype = STATUS_OPTION;
2398         else if (!strncmpi(fontopts, "_size", 5)) {
2399             if (!strncmpi(fontopts, "_size_map", 8))
2400                 opttype = MAP_OPTION;
2401             else if (!strncmpi(fontopts, "_size_message", 12))
2402                 opttype = MESSAGE_OPTION;
2403             else if (!strncmpi(fontopts, "_size_text", 9))
2404                 opttype = TEXT_OPTION;
2405             else if (!strncmpi(fontopts, "_size_menu", 9))
2406                 opttype = MENU_OPTION;
2407             else if (!strncmpi(fontopts, "_size_status", 11))
2408                 opttype = STATUS_OPTION;
2409             else {
2410                 badoption(opts);
2411                 return;
2412             }
2413             if (duplicate)
2414                 complain_about_duplicate(opts, 1);
2415             if (opttype > 0 && !negated
2416                 && (op = string_for_opt(opts, FALSE)) != 0) {
2417                 switch (opttype) {
2418                 case MAP_OPTION:
2419                     iflags.wc_fontsiz_map = atoi(op);
2420                     break;
2421                 case MESSAGE_OPTION:
2422                     iflags.wc_fontsiz_message = atoi(op);
2423                     break;
2424                 case TEXT_OPTION:
2425                     iflags.wc_fontsiz_text = atoi(op);
2426                     break;
2427                 case MENU_OPTION:
2428                     iflags.wc_fontsiz_menu = atoi(op);
2429                     break;
2430                 case STATUS_OPTION:
2431                     iflags.wc_fontsiz_status = atoi(op);
2432                     break;
2433                 }
2434             }
2435             return;
2436         } else {
2437             badoption(opts);
2438         }
2439         if (opttype > 0 && (op = string_for_opt(opts, FALSE)) != 0) {
2440             wc_set_font_name(opttype, op);
2441 #ifdef MAC
2442             set_font_name(opttype, op);
2443 #endif
2444             return;
2445         } else if (negated)
2446             bad_negation(fullname, TRUE);
2447         return;
2448     }
2449 #ifdef CHANGE_COLOR
2450     if (match_optname(opts, "palette", 3, TRUE)
2451 #ifdef MAC
2452         || match_optname(opts, "hicolor", 3, TRUE)
2453 #endif
2454             ) {
2455         int color_number, color_incr;
2456
2457 #ifndef WIN32
2458         if (duplicate)
2459             complain_about_duplicate(opts, 1);
2460 #endif
2461 #ifdef MAC
2462         if (match_optname(opts, "hicolor", 3, TRUE)) {
2463             if (negated) {
2464                 bad_negation("hicolor", FALSE);
2465                 return;
2466             }
2467             color_number = CLR_MAX + 4; /* HARDCODED inverse number */
2468             color_incr = -1;
2469         } else {
2470 #endif
2471             if (negated) {
2472                 bad_negation("palette", FALSE);
2473                 return;
2474             }
2475             color_number = 0;
2476             color_incr = 1;
2477 #ifdef MAC
2478         }
2479 #endif
2480 #ifdef WIN32
2481         op = string_for_opt(opts, TRUE);
2482         if (!alternative_palette(op))
2483             badoption(opts);
2484 #else
2485         if ((op = string_for_opt(opts, FALSE)) != (char *) 0) {
2486             char *pt = op;
2487             int cnt, tmp, reverse;
2488             long rgb;
2489
2490             while (*pt && color_number >= 0) {
2491                 cnt = 3;
2492                 rgb = 0L;
2493                 if (*pt == '-') {
2494                     reverse = 1;
2495                     pt++;
2496                 } else {
2497                     reverse = 0;
2498                 }
2499                 while (cnt-- > 0) {
2500                     if (*pt && *pt != '/') {
2501 #ifdef AMIGA
2502                         rgb <<= 4;
2503 #else
2504                         rgb <<= 8;
2505 #endif
2506                         tmp = *(pt++);
2507                         if (isalpha(tmp)) {
2508                             tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */
2509                         } else {
2510                             tmp &= 0xf; /* Digits in ASCII too... */
2511                         }
2512 #ifndef AMIGA
2513                         /* Add an extra so we fill f -> ff and 0 -> 00 */
2514                         rgb += tmp << 4;
2515 #endif
2516                         rgb += tmp;
2517                     }
2518                 }
2519                 if (*pt == '/') {
2520                     pt++;
2521                 }
2522                 change_color(color_number, rgb, reverse);
2523                 color_number += color_incr;
2524             }
2525         }
2526 #endif /* !WIN32 */
2527         if (!initial) {
2528             need_redraw = TRUE;
2529         }
2530         return;
2531     }
2532 #endif /* CHANGE_COLOR */
2533
2534     if (match_optname(opts, "fruit", 2, TRUE)) {
2535         struct fruit *forig = 0;
2536         char empty_str = '\0';
2537
2538         if (duplicate)
2539             complain_about_duplicate(opts, 1);
2540         op = string_for_opt(opts, negated);
2541         if (negated) {
2542             if (op) {
2543                 bad_negation("fruit", TRUE);
2544                 return;
2545             }
2546             op = &empty_str;
2547             goto goodfruit;
2548         }
2549         if (!op)
2550             return;
2551         if (!initial) {
2552             struct fruit *f;
2553
2554             num = 0;
2555             for (f = ffruit; f; f = f->nextf) {
2556                 if (!strcmp(op, f->fname))
2557                     break;
2558                 num++;
2559             }
2560             if (!flags.made_fruit) {
2561                 for (forig = ffruit; forig; forig = forig->nextf) {
2562                     if (!strcmp(pl_fruit, forig->fname)) {
2563                         break;
2564                     }
2565                 }
2566             }
2567             if (!forig && num >= 100) {
2568 /*JP
2569                 pline("Doing that so many times isn't very fruitful.");
2570 */
2571                 pline("\82»\82ñ\82È\82É\89½\89ñ\82à\82â\82Á\82Ä\82à\82Ù\82Æ\82ñ\82Ç\88Ó\96¡\82Í\82È\82¢\81D");
2572                 return;
2573             }
2574         }
2575     goodfruit:
2576         nmcpy(pl_fruit, op, PL_FSIZ);
2577         sanitize_name(pl_fruit);
2578         /* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */
2579         if (!*pl_fruit)
2580             nmcpy(pl_fruit, "slime mold", PL_FSIZ);
2581         if (!initial) {
2582             (void) fruitadd(pl_fruit, forig);
2583             pline("Fruit is now \"%s\".", pl_fruit);
2584         }
2585         /* If initial, then initoptions is allowed to do it instead
2586          * of here (initoptions always has to do it even if there's
2587          * no fruit option at all.  Also, we don't want people
2588          * setting multiple fruits in their options.)
2589          */
2590         return;
2591     }
2592
2593     fullname = "warnings";
2594     if (match_optname(opts, fullname, 5, TRUE)) {
2595         if (duplicate)
2596             complain_about_duplicate(opts, 1);
2597         if (negated)
2598             bad_negation(fullname, FALSE);
2599         else
2600             warning_opts(opts, fullname);
2601         return;
2602     }
2603
2604 #ifdef BACKWARD_COMPAT
2605     /* boulder:symbol */
2606     fullname = "boulder";
2607     if (match_optname(opts, fullname, 7, TRUE)) {
2608         int clash = 0;
2609         if (duplicate)
2610             complain_about_duplicate(opts, 1);
2611         if (negated) {
2612             bad_negation(fullname, FALSE);
2613             return;
2614         }
2615         /* if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
2616          */
2617         if (!(opts = string_for_opt(opts, FALSE)))
2618             return;
2619         escapes(opts, opts);
2620         if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
2621             clash = 1;
2622         else if (opts[0] >= '1' && opts[0] <= '5')
2623             clash = 2;
2624         if (clash) {
2625             /* symbol chosen matches a used monster or warning
2626                symbol which is not good - reject it*/
2627             pline(
2628                 "Badoption - boulder symbol '%c' conflicts with a %s symbol.",
2629                 opts[0], (clash == 1) ? "monster" : "warning");
2630         } else {
2631             /*
2632              * Override the default boulder symbol.
2633              */
2634             iflags.bouldersym = (uchar) opts[0];
2635         }
2636         if (!initial)
2637             need_redraw = TRUE;
2638         return;
2639     }
2640 #endif
2641
2642     /* name:string */
2643     fullname = "name";
2644     if (match_optname(opts, fullname, 4, TRUE)) {
2645         if (duplicate)
2646             complain_about_duplicate(opts, 1);
2647         if (negated)
2648             bad_negation(fullname, FALSE);
2649         else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
2650             nmcpy(plname, op, PL_NSIZ);
2651         return;
2652     }
2653
2654     /* altkeyhandler:string */
2655     fullname = "altkeyhandler";
2656     if (match_optname(opts, fullname, 4, TRUE)) {
2657         if (duplicate)
2658             complain_about_duplicate(opts, 1);
2659         if (negated) {
2660             bad_negation(fullname, FALSE);
2661         } else if ((op = string_for_opt(opts, negated)) != 0) {
2662 #ifdef WIN32
2663             (void) strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5);
2664             load_keyboard_handler();
2665 #endif
2666         }
2667         return;
2668     }
2669
2670     /* WINCAP
2671      * align_status:[left|top|right|bottom] */
2672     fullname = "align_status";
2673     if (match_optname(opts, fullname, sizeof("align_status") - 1, TRUE)) {
2674         op = string_for_opt(opts, negated);
2675         if (op && !negated) {
2676             if (!strncmpi(op, "left", sizeof("left") - 1))
2677                 iflags.wc_align_status = ALIGN_LEFT;
2678             else if (!strncmpi(op, "top", sizeof("top") - 1))
2679                 iflags.wc_align_status = ALIGN_TOP;
2680             else if (!strncmpi(op, "right", sizeof("right") - 1))
2681                 iflags.wc_align_status = ALIGN_RIGHT;
2682             else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
2683                 iflags.wc_align_status = ALIGN_BOTTOM;
2684             else
2685                 badoption(opts);
2686         } else if (negated)
2687             bad_negation(fullname, TRUE);
2688         return;
2689     }
2690     /* WINCAP
2691      * align_message:[left|top|right|bottom] */
2692     fullname = "align_message";
2693     if (match_optname(opts, fullname, sizeof("align_message") - 1, TRUE)) {
2694         if (duplicate)
2695             complain_about_duplicate(opts, 1);
2696         op = string_for_opt(opts, negated);
2697         if (op && !negated) {
2698             if (!strncmpi(op, "left", sizeof("left") - 1))
2699                 iflags.wc_align_message = ALIGN_LEFT;
2700             else if (!strncmpi(op, "top", sizeof("top") - 1))
2701                 iflags.wc_align_message = ALIGN_TOP;
2702             else if (!strncmpi(op, "right", sizeof("right") - 1))
2703                 iflags.wc_align_message = ALIGN_RIGHT;
2704             else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
2705                 iflags.wc_align_message = ALIGN_BOTTOM;
2706             else
2707                 badoption(opts);
2708         } else if (negated)
2709             bad_negation(fullname, TRUE);
2710         return;
2711     }
2712     /* the order to list the pack */
2713     fullname = "packorder";
2714     if (match_optname(opts, fullname, 4, TRUE)) {
2715         if (duplicate)
2716             complain_about_duplicate(opts, 1);
2717         if (negated) {
2718             bad_negation(fullname, FALSE);
2719             return;
2720         } else if (!(op = string_for_opt(opts, FALSE)))
2721             return;
2722
2723         if (!change_inv_order(op))
2724             badoption(opts);
2725         return;
2726     }
2727
2728     /* user can change required response for some prompts (quit, die, hit),
2729        or add an extra prompt (pray, Remove) that isn't ordinarily there */
2730     fullname = "paranoid_confirmation";
2731     if (match_optname(opts, fullname, 8, TRUE)) {
2732         /* at present we don't complain about duplicates for this
2733            option, but we do throw away the old settings whenever
2734            we process a new one [clearing old flags is essential
2735            for handling default paranoid_confirm:pray sanely] */
2736         flags.paranoia_bits = 0; /* clear all */
2737         if (negated) {
2738             flags.paranoia_bits = 0; /* [now redundant...] */
2739         } else if ((op = string_for_opt(opts, TRUE)) != 0) {
2740             char *pp, buf[BUFSZ];
2741
2742             op = mungspaces(strcpy(buf, op));
2743             for (;;) {
2744                 /* We're looking to parse
2745                    "paranoid_confirm:whichone wheretwo whothree"
2746                    and "paranoid_confirm:" prefix has already
2747                    been stripped off by the time we get here */
2748                 pp = index(op, ' ');
2749                 if (pp)
2750                     *pp = '\0';
2751                 /* we aren't matching option names but match_optname
2752                    does what we want once we've broken the space
2753                    delimited aggregate into separate tokens */
2754                 for (i = 0; i < SIZE(paranoia); ++i) {
2755                     if (match_optname(op, paranoia[i].argname,
2756                                       paranoia[i].argMinLen, FALSE)
2757                         || (paranoia[i].synonym
2758                             && match_optname(op, paranoia[i].synonym,
2759                                              paranoia[i].synMinLen, FALSE))) {
2760                         if (paranoia[i].flagmask)
2761                             flags.paranoia_bits |= paranoia[i].flagmask;
2762                         else /* 0 == "none", so clear all */
2763                             flags.paranoia_bits = 0;
2764                         break;
2765                     }
2766                 }
2767                 if (i == SIZE(paranoia)) {
2768                     /* didn't match anything, so arg is bad;
2769                        any flags already set will stay set */
2770                     badoption(opts);
2771                     break;
2772                 }
2773                 /* move on to next token */
2774                 if (pp)
2775                     op = pp + 1;
2776                 else
2777                     break; /* no next token */
2778             }              /* for(;;) */
2779         }
2780         return;
2781     }
2782
2783     /* accept deprecated boolean; superseded by paranoid_confirm:pray */
2784     fullname = "prayconfirm";
2785     if (match_optname(opts, fullname, 4, FALSE)) {
2786         if (negated)
2787             flags.paranoia_bits &= ~PARANOID_PRAY;
2788         else
2789             flags.paranoia_bits |= PARANOID_PRAY;
2790         return;
2791     }
2792
2793     /* maximum burden picked up before prompt (Warren Cheung) */
2794     fullname = "pickup_burden";
2795     if (match_optname(opts, fullname, 8, TRUE)) {
2796         if (duplicate)
2797             complain_about_duplicate(opts, 1);
2798         if (negated) {
2799             bad_negation(fullname, FALSE);
2800             return;
2801         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2802             switch (tolower(*op)) {
2803             /* Unencumbered */
2804             case 'u':
2805                 flags.pickup_burden = UNENCUMBERED;
2806                 break;
2807             /* Burdened (slight encumbrance) */
2808             case 'b':
2809                 flags.pickup_burden = SLT_ENCUMBER;
2810                 break;
2811             /* streSsed (moderate encumbrance) */
2812             case 's':
2813                 flags.pickup_burden = MOD_ENCUMBER;
2814                 break;
2815             /* straiNed (heavy encumbrance) */
2816             case 'n':
2817                 flags.pickup_burden = HVY_ENCUMBER;
2818                 break;
2819             /* OverTaxed (extreme encumbrance) */
2820             case 'o':
2821             case 't':
2822                 flags.pickup_burden = EXT_ENCUMBER;
2823                 break;
2824             /* overLoaded */
2825             case 'l':
2826                 flags.pickup_burden = OVERLOADED;
2827                 break;
2828             default:
2829                 badoption(opts);
2830             }
2831         }
2832         return;
2833     }
2834
2835     /* types of objects to pick up automatically */
2836     if (match_optname(opts, "pickup_types", 8, TRUE)) {
2837         char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], qbuf[QBUFSZ],
2838             abuf[BUFSZ];
2839         int oc_sym;
2840         boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
2841
2842         if (duplicate)
2843             complain_about_duplicate(opts, 1);
2844         oc_to_str(flags.pickup_types, tbuf);
2845         flags.pickup_types[0] = '\0'; /* all */
2846         op = string_for_opt(opts, (compat || !initial));
2847         if (!op) {
2848             if (compat || negated || initial) {
2849                 /* for backwards compatibility, "pickup" without a
2850                    value is a synonym for autopickup of all types
2851                    (and during initialization, we can't prompt yet) */
2852                 flags.pickup = !negated;
2853                 return;
2854             }
2855             oc_to_str(flags.inv_order, ocl);
2856             use_menu = TRUE;
2857             if (flags.menu_style == MENU_TRADITIONAL
2858                 || flags.menu_style == MENU_COMBINATION) {
2859                 use_menu = FALSE;
2860 #if 0 /*JP*/
2861                 Sprintf(qbuf, "New pickup_types: [%s am] (%s)", ocl,
2862                         *tbuf ? tbuf : "all");
2863 #else
2864                 Sprintf(qbuf, "\90V\82µ\82¢pickup_type\82ð\93ü\97Í\82µ\82Ä\82­\82¾\82³\82¢\81F[%s am] (%s)", ocl,
2865                         *tbuf ? tbuf : "all");
2866 #endif
2867                 getlin(qbuf, abuf);
2868                 op = mungspaces(abuf);
2869                 if (abuf[0] == '\0' || abuf[0] == '\033')
2870                     op = tbuf; /* restore */
2871                 else if (abuf[0] == 'm')
2872                     use_menu = TRUE;
2873             }
2874             if (use_menu) {
2875 #if 0 /*JP*/
2876                 (void) choose_classes_menu("Auto-Pickup what?", 1, TRUE, ocl,
2877                                            tbuf);
2878 #else
2879                 (void) choose_classes_menu("\82Ç\82ê\82ð\8e©\93®\8fE\82¢\82É\90Ý\92è\82·\82é\81H", 1, TRUE, ocl,
2880                                            tbuf);
2881 #endif
2882                 op = tbuf;
2883             }
2884         }
2885         if (negated) {
2886             bad_negation("pickup_types", TRUE);
2887             return;
2888         }
2889         while (*op == ' ')
2890             op++;
2891         if (*op != 'a' && *op != 'A') {
2892             num = 0;
2893             while (*op) {
2894                 oc_sym = def_char_to_objclass(*op);
2895                 /* make sure all are valid obj symbols occurring once */
2896                 if (oc_sym != MAXOCLASSES
2897                     && !index(flags.pickup_types, oc_sym)) {
2898                     flags.pickup_types[num] = (char) oc_sym;
2899                     flags.pickup_types[++num] = '\0';
2900                 } else
2901                     badopt = TRUE;
2902                 op++;
2903             }
2904             if (badopt)
2905                 badoption(opts);
2906         }
2907         return;
2908     }
2909
2910     /* pile limit: when walking over objects, number which triggers
2911        "there are several/many objects here" instead of listing them */
2912     fullname = "pile_limit";
2913     if (match_optname(opts, fullname, 4, TRUE)) {
2914         if (duplicate)
2915             complain_about_duplicate(opts, 1);
2916         op = string_for_opt(opts, negated);
2917         if ((negated && !op) || (!negated && op))
2918             flags.pile_limit = negated ? 0 : atoi(op);
2919         else if (negated)
2920             bad_negation(fullname, TRUE);
2921         else /* !op */
2922             flags.pile_limit = PILE_LIMIT_DFLT;
2923         /* sanity check */
2924         if (flags.pile_limit < 0)
2925             flags.pile_limit = PILE_LIMIT_DFLT;
2926         return;
2927     }
2928
2929     /* play mode: normal, explore/discovery, or debug/wizard */
2930     fullname = "playmode";
2931     if (match_optname(opts, fullname, 4, TRUE)) {
2932         if (duplicate)
2933             complain_about_duplicate(opts, 1);
2934         if (negated)
2935             bad_negation(fullname, FALSE);
2936         if (duplicate || negated)
2937             return;
2938         op = string_for_opt(opts, TRUE);
2939         if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) {
2940             wizard = discover = FALSE;
2941         } else if (!strncmpi(op, "explore", 6)
2942                    || !strncmpi(op, "discovery", 6)) {
2943             wizard = FALSE, discover = TRUE;
2944         } else if (!strncmpi(op, "debug", 5) || !strncmpi(op, "wizard", 6)) {
2945             wizard = TRUE, discover = FALSE;
2946         } else {
2947             raw_printf("Invalid value for \"%s\":%s.", fullname, op);
2948         }
2949         return;
2950     }
2951
2952     /* WINCAP
2953      * player_selection: dialog | prompts */
2954     fullname = "player_selection";
2955     if (match_optname(opts, fullname, sizeof("player_selection") - 1, TRUE)) {
2956         if (duplicate)
2957             complain_about_duplicate(opts, 1);
2958         op = string_for_opt(opts, negated);
2959         if (op && !negated) {
2960             if (!strncmpi(op, "dialog", sizeof("dialog") - 1))
2961                 iflags.wc_player_selection = VIA_DIALOG;
2962             else if (!strncmpi(op, "prompt", sizeof("prompt") - 1))
2963                 iflags.wc_player_selection = VIA_PROMPTS;
2964             else
2965                 badoption(opts);
2966         } else if (negated)
2967             bad_negation(fullname, TRUE);
2968         return;
2969     }
2970
2971     /* things to disclose at end of game */
2972     if (match_optname(opts, "disclose", 7, TRUE)) {
2973         /*
2974          * The order that the end_disclose options are stored:
2975          *      inventory, attribs, vanquished, genocided,
2976          *      conduct, overview.
2977          * There is an array in flags:
2978          *      end_disclose[NUM_DISCLOSURE_OPT];
2979          * with option settings for the each of the following:
2980          * iagvc [see disclosure_options in decl.c]:
2981          * Legal setting values in that array are:
2982          *      DISCLOSE_PROMPT_DEFAULT_YES  ask with default answer yes
2983          *      DISCLOSE_PROMPT_DEFAULT_NO   ask with default answer no
2984          *      DISCLOSE_YES_WITHOUT_PROMPT  always disclose and don't ask
2985          *      DISCLOSE_NO_WITHOUT_PROMPT   never disclose and don't ask
2986          *
2987          * Those setting values can be used in the option
2988          * string as a prefix to get the desired behaviour.
2989          *
2990          * For backward compatibility, no prefix is required,
2991          * and the presence of a i,a,g,v, or c without a prefix
2992          * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
2993          */
2994         boolean badopt = FALSE;
2995         int idx, prefix_val;
2996
2997         if (duplicate)
2998             complain_about_duplicate(opts, 1);
2999         op = string_for_opt(opts, TRUE);
3000         if (op && negated) {
3001             bad_negation("disclose", TRUE);
3002             return;
3003         }
3004         /* "disclose" without a value means "all with prompting"
3005            and negated means "none without prompting" */
3006         if (!op || !strcmpi(op, "all") || !strcmpi(op, "none")) {
3007             if (op && !strcmpi(op, "none"))
3008                 negated = TRUE;
3009             for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++)
3010                 flags.end_disclose[num] = negated
3011                                               ? DISCLOSE_NO_WITHOUT_PROMPT
3012                                               : DISCLOSE_PROMPT_DEFAULT_YES;
3013             return;
3014         }
3015
3016         num = 0;
3017         prefix_val = -1;
3018         while (*op && num < sizeof flags.end_disclose - 1) {
3019             static char valid_settings[] = {
3020                 DISCLOSE_PROMPT_DEFAULT_YES, DISCLOSE_PROMPT_DEFAULT_NO,
3021                 DISCLOSE_YES_WITHOUT_PROMPT, DISCLOSE_NO_WITHOUT_PROMPT, '\0'
3022             };
3023             register char c, *dop;
3024
3025             c = lowc(*op);
3026             if (c == 'k')
3027                 c = 'v'; /* killed -> vanquished */
3028             if (c == 'd')
3029                 c = 'o'; /* dungeon -> overview */
3030             dop = index(disclosure_options, c);
3031             if (dop) {
3032                 idx = (int) (dop - disclosure_options);
3033                 if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) {
3034                     impossible("bad disclosure index %d %c", idx, c);
3035                     continue;
3036                 }
3037                 if (prefix_val != -1) {
3038                     flags.end_disclose[idx] = prefix_val;
3039                     prefix_val = -1;
3040                 } else
3041                     flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT;
3042             } else if (index(valid_settings, c)) {
3043                 prefix_val = c;
3044             } else if (c == ' ') {
3045                 ; /* do nothing */
3046             } else
3047                 badopt = TRUE;
3048             op++;
3049         }
3050         if (badopt)
3051             badoption(opts);
3052         return;
3053     }
3054 #if 1 /*JP*/
3055     if (!strncmpi(opts, "kcode", 3)){
3056         if ((op = string_for_env_opt("kcode", opts, FALSE)) != 0){
3057             setkcode(*op);
3058         }
3059         return;
3060     }
3061 #endif
3062
3063     /* scores:5t[op] 5a[round] o[wn] */
3064     if (match_optname(opts, "scores", 4, TRUE)) {
3065         if (duplicate)
3066             complain_about_duplicate(opts, 1);
3067         if (negated) {
3068             bad_negation("scores", FALSE);
3069             return;
3070         }
3071         if (!(op = string_for_opt(opts, FALSE)))
3072             return;
3073
3074         while (*op) {
3075             int inum = 1;
3076
3077             if (digit(*op)) {
3078                 inum = atoi(op);
3079                 while (digit(*op))
3080                     op++;
3081             } else if (*op == '!') {
3082                 negated = !negated;
3083                 op++;
3084             }
3085             while (*op == ' ')
3086                 op++;
3087
3088             switch (*op) {
3089             case 't':
3090             case 'T':
3091                 flags.end_top = inum;
3092                 break;
3093             case 'a':
3094             case 'A':
3095                 flags.end_around = inum;
3096                 break;
3097             case 'o':
3098             case 'O':
3099                 flags.end_own = !negated;
3100                 break;
3101             default:
3102                 badoption(opts);
3103                 return;
3104             }
3105             while (letter(*++op) || *op == ' ')
3106                 continue;
3107             if (*op == '/')
3108                 op++;
3109         }
3110         return;
3111     }
3112
3113     fullname = "sortloot";
3114     if (match_optname(opts, fullname, 4, TRUE)) {
3115         op = string_for_env_opt(fullname, opts, FALSE);
3116         if (op) {
3117             switch (tolower(*op)) {
3118             case 'n':
3119             case 'l':
3120             case 'f':
3121                 flags.sortloot = tolower(*op);
3122                 break;
3123             default:
3124                 badoption(opts);
3125                 return;
3126             }
3127         }
3128         return;
3129     }
3130
3131     fullname = "suppress_alert";
3132     if (match_optname(opts, fullname, 4, TRUE)) {
3133         if (duplicate)
3134             complain_about_duplicate(opts, 1);
3135         op = string_for_opt(opts, negated);
3136         if (negated)
3137             bad_negation(fullname, FALSE);
3138         else if (op)
3139             (void) feature_alert_opts(op, fullname);
3140         return;
3141     }
3142
3143 #ifdef VIDEOSHADES
3144     /* videocolors:string */
3145     fullname = "videocolors";
3146     if (match_optname(opts, fullname, 6, TRUE)
3147         || match_optname(opts, "videocolours", 10, TRUE)) {
3148         if (duplicate)
3149             complain_about_duplicate(opts, 1);
3150         if (negated) {
3151             bad_negation(fullname, FALSE);
3152             return;
3153         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3154             return;
3155         }
3156         if (!assign_videocolors(opts))
3157             badoption(opts);
3158         return;
3159     }
3160     /* videoshades:string */
3161     fullname = "videoshades";
3162     if (match_optname(opts, fullname, 6, TRUE)) {
3163         if (duplicate)
3164             complain_about_duplicate(opts, 1);
3165         if (negated) {
3166             bad_negation(fullname, FALSE);
3167             return;
3168         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3169             return;
3170         }
3171         if (!assign_videoshades(opts))
3172             badoption(opts);
3173         return;
3174     }
3175 #endif /* VIDEOSHADES */
3176 #ifdef MSDOS
3177 #ifdef NO_TERMS
3178     /* video:string -- must be after longer tests */
3179     fullname = "video";
3180     if (match_optname(opts, fullname, 5, TRUE)) {
3181         if (duplicate)
3182             complain_about_duplicate(opts, 1);
3183         if (negated) {
3184             bad_negation(fullname, FALSE);
3185             return;
3186         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3187             return;
3188         }
3189         if (!assign_video(opts))
3190             badoption(opts);
3191         return;
3192     }
3193 #endif /* NO_TERMS */
3194     /* soundcard:string -- careful not to match boolean 'sound' */
3195     fullname = "soundcard";
3196     if (match_optname(opts, fullname, 6, TRUE)) {
3197         if (duplicate)
3198             complain_about_duplicate(opts, 1);
3199         if (negated) {
3200             bad_negation(fullname, FALSE);
3201             return;
3202         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3203             return;
3204         }
3205         if (!assign_soundcard(opts))
3206             badoption(opts);
3207         return;
3208     }
3209 #endif /* MSDOS */
3210
3211     /* WINCAP
3212      *
3213      *  map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|
3214      *            ascii8x12|ascii16x12|ascii12x16|ascii10x18|fit_to_screen]
3215      */
3216     fullname = "map_mode";
3217     if (match_optname(opts, fullname, sizeof("map_mode") - 1, TRUE)) {
3218         if (duplicate)
3219             complain_about_duplicate(opts, 1);
3220         op = string_for_opt(opts, negated);
3221         if (op && !negated) {
3222             if (!strncmpi(op, "tiles", sizeof("tiles") - 1))
3223                 iflags.wc_map_mode = MAP_MODE_TILES;
3224             else if (!strncmpi(op, "ascii4x6", sizeof("ascii4x6") - 1))
3225                 iflags.wc_map_mode = MAP_MODE_ASCII4x6;
3226             else if (!strncmpi(op, "ascii6x8", sizeof("ascii6x8") - 1))
3227                 iflags.wc_map_mode = MAP_MODE_ASCII6x8;
3228             else if (!strncmpi(op, "ascii8x8", sizeof("ascii8x8") - 1))
3229                 iflags.wc_map_mode = MAP_MODE_ASCII8x8;
3230             else if (!strncmpi(op, "ascii16x8", sizeof("ascii16x8") - 1))
3231                 iflags.wc_map_mode = MAP_MODE_ASCII16x8;
3232             else if (!strncmpi(op, "ascii7x12", sizeof("ascii7x12") - 1))
3233                 iflags.wc_map_mode = MAP_MODE_ASCII7x12;
3234             else if (!strncmpi(op, "ascii8x12", sizeof("ascii8x12") - 1))
3235                 iflags.wc_map_mode = MAP_MODE_ASCII8x12;
3236             else if (!strncmpi(op, "ascii16x12", sizeof("ascii16x12") - 1))
3237                 iflags.wc_map_mode = MAP_MODE_ASCII16x12;
3238             else if (!strncmpi(op, "ascii12x16", sizeof("ascii12x16") - 1))
3239                 iflags.wc_map_mode = MAP_MODE_ASCII12x16;
3240             else if (!strncmpi(op, "ascii10x18", sizeof("ascii10x18") - 1))
3241                 iflags.wc_map_mode = MAP_MODE_ASCII10x18;
3242             else if (!strncmpi(op, "fit_to_screen",
3243                                sizeof("fit_to_screen") - 1))
3244                 iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
3245             else
3246                 badoption(opts);
3247         } else if (negated)
3248             bad_negation(fullname, TRUE);
3249         return;
3250     }
3251     /* WINCAP
3252      * scroll_amount:nn */
3253     fullname = "scroll_amount";
3254     if (match_optname(opts, fullname, sizeof("scroll_amount") - 1, TRUE)) {
3255         if (duplicate)
3256             complain_about_duplicate(opts, 1);
3257         op = string_for_opt(opts, negated);
3258         if ((negated && !op) || (!negated && op)) {
3259             iflags.wc_scroll_amount = negated ? 1 : atoi(op);
3260         } else if (negated)
3261             bad_negation(fullname, TRUE);
3262         return;
3263     }
3264     /* WINCAP
3265      * scroll_margin:nn */
3266     fullname = "scroll_margin";
3267     if (match_optname(opts, fullname, sizeof("scroll_margin") - 1, TRUE)) {
3268         if (duplicate)
3269             complain_about_duplicate(opts, 1);
3270         op = string_for_opt(opts, negated);
3271         if ((negated && !op) || (!negated && op)) {
3272             iflags.wc_scroll_margin = negated ? 5 : atoi(op);
3273         } else if (negated)
3274             bad_negation(fullname, TRUE);
3275         return;
3276     }
3277     fullname = "subkeyvalue";
3278     if (match_optname(opts, fullname, 5, TRUE)) {
3279         /* no duplicate complaint here */
3280         if (negated) {
3281             bad_negation(fullname, FALSE);
3282         } else {
3283 #if defined(WIN32)
3284             op = string_for_opt(opts, 0);
3285             map_subkeyvalue(op);
3286 #endif
3287         }
3288         return;
3289     }
3290     /* WINCAP
3291      * tile_width:nn */
3292     fullname = "tile_width";
3293     if (match_optname(opts, fullname, sizeof("tile_width") - 1, TRUE)) {
3294         if (duplicate)
3295             complain_about_duplicate(opts, 1);
3296         op = string_for_opt(opts, negated);
3297         if ((negated && !op) || (!negated && op)) {
3298             iflags.wc_tile_width = negated ? 0 : atoi(op);
3299         } else if (negated)
3300             bad_negation(fullname, TRUE);
3301         return;
3302     }
3303     /* WINCAP
3304      * tile_file:name */
3305     fullname = "tile_file";
3306     if (match_optname(opts, fullname, sizeof("tile_file") - 1, TRUE)) {
3307         if (duplicate)
3308             complain_about_duplicate(opts, 1);
3309         if ((op = string_for_opt(opts, FALSE)) != 0) {
3310             if (iflags.wc_tile_file)
3311                 free(iflags.wc_tile_file);
3312             iflags.wc_tile_file = (char *) alloc(strlen(op) + 1);
3313             Strcpy(iflags.wc_tile_file, op);
3314         }
3315         return;
3316     }
3317     /* WINCAP
3318      * tile_height:nn */
3319     fullname = "tile_height";
3320     if (match_optname(opts, fullname, sizeof("tile_height") - 1, TRUE)) {
3321         if (duplicate)
3322             complain_about_duplicate(opts, 1);
3323         op = string_for_opt(opts, negated);
3324         if ((negated && !op) || (!negated && op)) {
3325             iflags.wc_tile_height = negated ? 0 : atoi(op);
3326         } else if (negated)
3327             bad_negation(fullname, TRUE);
3328         return;
3329     }
3330     /* WINCAP
3331      * vary_msgcount:nn */
3332     fullname = "vary_msgcount";
3333     if (match_optname(opts, fullname, sizeof("vary_msgcount") - 1, TRUE)) {
3334         if (duplicate)
3335             complain_about_duplicate(opts, 1);
3336         op = string_for_opt(opts, negated);
3337         if ((negated && !op) || (!negated && op)) {
3338             iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
3339         } else if (negated)
3340             bad_negation(fullname, TRUE);
3341         return;
3342     }
3343     fullname = "windowtype";
3344     if (match_optname(opts, fullname, 3, TRUE)) {
3345         if (duplicate)
3346             complain_about_duplicate(opts, 1);
3347         if (negated) {
3348             bad_negation(fullname, FALSE);
3349             return;
3350         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
3351             char buf[WINTYPELEN];
3352             nmcpy(buf, op, WINTYPELEN);
3353             choose_windows(buf);
3354         }
3355         return;
3356     }
3357 #ifdef WINCHAIN
3358     fullname = "windowchain";
3359     if (match_optname(opts, fullname, 3, TRUE)) {
3360         if (negated) {
3361             bad_negation(fullname, FALSE);
3362             return;
3363         } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
3364             char buf[WINTYPELEN];
3365             nmcpy(buf, op, WINTYPELEN);
3366             addto_windowchain(buf);
3367         }
3368         return;
3369     }
3370 #endif
3371
3372     /* WINCAP
3373      * setting window colors
3374      * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd
3375      */
3376     fullname = "windowcolors";
3377     if (match_optname(opts, fullname, 7, TRUE)) {
3378         if (duplicate)
3379             complain_about_duplicate(opts, 1);
3380         if ((op = string_for_opt(opts, FALSE)) != 0) {
3381             if (!wc_set_window_colors(op))
3382                 badoption(opts);
3383         } else if (negated)
3384             bad_negation(fullname, TRUE);
3385         return;
3386     }
3387
3388     /* menustyle:traditional or combination or full or partial */
3389     if (match_optname(opts, "menustyle", 4, TRUE)) {
3390         int tmp;
3391         boolean val_required = (strlen(opts) > 5 && !negated);
3392
3393         if (duplicate)
3394             complain_about_duplicate(opts, 1);
3395         if (!(op = string_for_opt(opts, !val_required))) {
3396             if (val_required)
3397                 return; /* string_for_opt gave feedback */
3398             tmp = negated ? 'n' : 'f';
3399         } else {
3400             tmp = tolower(*op);
3401         }
3402         switch (tmp) {
3403         case 'n': /* none */
3404         case 't': /* traditional */
3405             flags.menu_style = MENU_TRADITIONAL;
3406             break;
3407         case 'c': /* combo: trad.class sel+menu */
3408             flags.menu_style = MENU_COMBINATION;
3409             break;
3410         case 'p': /* partial: no class menu */
3411             flags.menu_style = MENU_PARTIAL;
3412             break;
3413         case 'f': /* full: class menu + menu */
3414             flags.menu_style = MENU_FULL;
3415             break;
3416         default:
3417             badoption(opts);
3418         }
3419         return;
3420     }
3421
3422     fullname = "menu_headings";
3423     if (match_optname(opts, fullname, 12, TRUE)) {
3424         if (duplicate)
3425             complain_about_duplicate(opts, 1);
3426         if (negated) {
3427             bad_negation(fullname, FALSE);
3428             return;
3429         } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3430             return;
3431         }
3432         for (i = 0; i < SIZE(attrnames); i++)
3433             if (!strcmpi(opts, attrnames[i].name)) {
3434                 iflags.menu_headings = attrnames[i].attr;
3435                 return;
3436             }
3437         badoption(opts);
3438         return;
3439     }
3440
3441     /* check for menu command mapping */
3442     for (i = 0; i < NUM_MENU_CMDS; i++) {
3443         fullname = default_menu_cmd_info[i].name;
3444         if (duplicate)
3445             complain_about_duplicate(opts, 1);
3446         if (match_optname(opts, fullname, (int) strlen(fullname), TRUE)) {
3447             if (negated) {
3448                 bad_negation(fullname, FALSE);
3449             } else if ((op = string_for_opt(opts, FALSE)) != 0) {
3450                 int j;
3451                 char c, op_buf[BUFSZ];
3452                 boolean isbad = FALSE;
3453
3454                 escapes(op, op_buf);
3455                 c = *op_buf;
3456
3457                 if (c == 0 || c == '\r' || c == '\n' || c == '\033'
3458                     || c == ' ' || digit(c) || (letter(c) && c != '@'))
3459                     isbad = TRUE;
3460                 else /* reject default object class symbols */
3461                     for (j = 1; j < MAXOCLASSES; j++)
3462                         if (c == def_oc_syms[i].sym) {
3463                             isbad = TRUE;
3464                             break;
3465                         }
3466
3467                 if (isbad)
3468                     badoption(opts);
3469                 else
3470                     add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
3471             }
3472             return;
3473         }
3474     }
3475 #if defined(STATUS_VIA_WINDOWPORT) && defined(STATUS_HILITES)
3476     /* hilite fields in status prompt */
3477     if (match_optname(opts, "hilite_status", 13, TRUE)) {
3478         if (duplicate)
3479             complain_about_duplicate(opts, 1);
3480         op = string_for_opt(opts, TRUE);
3481         if (op && negated) {
3482             clear_status_hilites(tfrom_file);
3483             return;
3484         } else if (!op) {
3485             /* a value is mandatory */
3486             badoption(opts);
3487             return;
3488         }
3489         if (!set_status_hilites(op, tfrom_file))
3490             badoption(opts);
3491         return;
3492     }
3493 #endif
3494
3495 #if defined(BACKWARD_COMPAT)
3496     fullname = "DECgraphics";
3497     if (match_optname(opts, fullname, 3, TRUE)) {
3498         boolean badflag = FALSE;
3499
3500         if (duplicate)
3501             complain_about_duplicate(opts, 1);
3502         if (!negated) {
3503             /* There is no rogue level DECgraphics-specific set */
3504             if (symset[PRIMARY].name) {
3505                 badflag = TRUE;
3506             } else {
3507                 symset[PRIMARY].name = dupstr(fullname);
3508                 if (!read_sym_file(PRIMARY)) {
3509                     badflag = TRUE;
3510                     clear_symsetentry(PRIMARY, TRUE);
3511                 } else
3512                     switch_symbols(TRUE);
3513             }
3514             if (badflag) {
3515                 pline("Failure to load symbol set %s.", fullname);
3516                 wait_synch();
3517             }
3518         }
3519         return;
3520     }
3521     fullname = "IBMgraphics";
3522     if (match_optname(opts, fullname, 3, TRUE)) {
3523         const char *sym_name = fullname;
3524         boolean badflag = FALSE;
3525
3526         if (duplicate)
3527             complain_about_duplicate(opts, 1);
3528         if (!negated) {
3529             for (i = 0; i < NUM_GRAPHICS; ++i) {
3530                 if (symset[i].name) {
3531                     badflag = TRUE;
3532                 } else {
3533                     if (i == ROGUESET)
3534                         sym_name = "RogueIBM";
3535                     symset[i].name = dupstr(sym_name);
3536                     if (!read_sym_file(i)) {
3537                         badflag = TRUE;
3538                         clear_symsetentry(i, TRUE);
3539                         break;
3540                     }
3541                 }
3542             }
3543             if (badflag) {
3544                 pline("Failure to load symbol set %s.", sym_name);
3545                 wait_synch();
3546             } else {
3547                 switch_symbols(TRUE);
3548                 if (!initial && Is_rogue_level(&u.uz))
3549                     assign_graphics(ROGUESET);
3550             }
3551         }
3552         return;
3553     }
3554 #endif
3555 #ifdef MAC_GRAPHICS_ENV
3556     fullname = "MACgraphics";
3557     if (match_optname(opts, fullname, 3, TRUE)) {
3558         boolean badflag = FALSE;
3559
3560         if (duplicate)
3561             complain_about_duplicate(opts, 1);
3562         if (!negated) {
3563             if (symset[PRIMARY].name) {
3564                 badflag = TRUE;
3565             } else {
3566                 symset[PRIMARY].name = dupstr(fullname);
3567                 if (!read_sym_file(PRIMARY)) {
3568                     badflag = TRUE;
3569                     clear_symsetentry(PRIMARY, TRUE);
3570                 }
3571             }
3572             if (badflag) {
3573                 pline("Failure to load symbol set %s.", fullname);
3574                 wait_synch();
3575             } else {
3576                 switch_symbols(TRUE);
3577                 if (!initial && Is_rogue_level(&u.uz))
3578                     assign_graphics(ROGUESET);
3579             }
3580         }
3581         return;
3582     }
3583 #endif
3584
3585     /* OK, if we still haven't recognized the option, check the boolean
3586      * options list
3587      */
3588     for (i = 0; boolopt[i].name; i++) {
3589         if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
3590             /* options that don't exist */
3591             if (!boolopt[i].addr) {
3592                 if (!initial && !negated)
3593                     pline_The("\"%s\" option is not available.",
3594                               boolopt[i].name);
3595                 return;
3596             }
3597             /* options that must come from config file */
3598             if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
3599                 rejectoption(boolopt[i].name);
3600                 return;
3601             }
3602
3603             *(boolopt[i].addr) = !negated;
3604
3605             /* 0 means boolean opts */
3606             if (duplicate_opt_detection(boolopt[i].name, 0))
3607                 complain_about_duplicate(boolopt[i].name, 0);
3608
3609 #ifdef RLECOMP
3610             if ((boolopt[i].addr) == &iflags.rlecomp) {
3611                 if (*boolopt[i].addr)
3612                     set_savepref("rlecomp");
3613                 else
3614                     set_savepref("!rlecomp");
3615             }
3616 #endif
3617 #ifdef ZEROCOMP
3618             if ((boolopt[i].addr) == &iflags.zerocomp) {
3619                 if (*boolopt[i].addr)
3620                     set_savepref("zerocomp");
3621                 else
3622                     set_savepref("externalcomp");
3623             }
3624 #endif
3625             /* only do processing below if setting with doset() */
3626             if (initial)
3627                 return;
3628
3629             if ((boolopt[i].addr) == &flags.time
3630                 || (boolopt[i].addr) == &flags.showexp
3631 #ifdef SCORE_ON_BOTL
3632                 || (boolopt[i].addr) == &flags.showscore
3633 #endif
3634                 ) {
3635 #ifdef STATUS_VIA_WINDOWPORT
3636                 status_initialize(REASSESS_ONLY);
3637 #endif
3638                 context.botl = TRUE;
3639             } else if ((boolopt[i].addr) == &flags.invlet_constant) {
3640                 if (flags.invlet_constant)
3641                     reassign();
3642             } else if (((boolopt[i].addr) == &flags.lit_corridor)
3643                        || ((boolopt[i].addr) == &flags.dark_room)) {
3644                 /*
3645                  * All corridor squares seen via night vision or
3646                  * candles & lamps change.  Update them by calling
3647                  * newsym() on them.  Don't do this if we are
3648                  * initializing the options --- the vision system
3649                  * isn't set up yet.
3650                  */
3651                 vision_recalc(2);       /* shut down vision */
3652                 vision_full_recalc = 1; /* delayed recalc */
3653                 if (iflags.use_color)
3654                     need_redraw = TRUE; /* darkroom refresh */
3655             } else if ((boolopt[i].addr) == &iflags.use_inverse
3656                        || (boolopt[i].addr) == &flags.showrace
3657                        || (boolopt[i].addr) == &iflags.hilite_pet) {
3658                 need_redraw = TRUE;
3659 #ifdef TEXTCOLOR
3660             } else if ((boolopt[i].addr) == &iflags.use_color) {
3661                 need_redraw = TRUE;
3662 #ifdef TOS
3663                 if ((boolopt[i].addr) == &iflags.use_color && iflags.BIOS) {
3664                     if (colors_changed)
3665                         restore_colors();
3666                     else
3667                         set_colors();
3668                 }
3669 #endif
3670 #endif /* TEXTCOLOR */
3671             }
3672             return;
3673         }
3674     }
3675
3676     /* out of valid options */
3677     badoption(opts);
3678 }
3679
3680 static NEARDATA const char *menutype[] = { "traditional", "combination",
3681                                            "full", "partial" };
3682
3683 static NEARDATA const char *burdentype[] = { "unencumbered", "burdened",
3684                                              "stressed",     "strained",
3685                                              "overtaxed",    "overloaded" };
3686
3687 static NEARDATA const char *runmodes[] = { "teleport", "run", "walk",
3688                                            "crawl" };
3689
3690 static NEARDATA const char *sortltype[] = { "none", "loot", "full" };
3691
3692 /*
3693  * Convert the given string of object classes to a string of default object
3694  * symbols.
3695  */
3696 STATIC_OVL void
3697 oc_to_str(src, dest)
3698 char *src, *dest;
3699 {
3700     int i;
3701
3702     while ((i = (int) *src++) != 0) {
3703         if (i < 0 || i >= MAXOCLASSES)
3704             impossible("oc_to_str:  illegal object class %d", i);
3705         else
3706             *dest++ = def_oc_syms[i].sym;
3707     }
3708     *dest = '\0';
3709 }
3710
3711 /*
3712  * Add the given mapping to the menu command map list.  Always keep the
3713  * maps valid C strings.
3714  */
3715 void
3716 add_menu_cmd_alias(from_ch, to_ch)
3717 char from_ch, to_ch;
3718 {
3719     if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS) {
3720         pline("out of menu map space.");
3721     } else {
3722         mapped_menu_cmds[n_menu_mapped] = from_ch;
3723         mapped_menu_op[n_menu_mapped] = to_ch;
3724         n_menu_mapped++;
3725         mapped_menu_cmds[n_menu_mapped] = 0;
3726         mapped_menu_op[n_menu_mapped] = 0;
3727     }
3728 }
3729
3730 /*
3731  * Map the given character to its corresponding menu command.  If it
3732  * doesn't match anything, just return the original.
3733  */
3734 char
3735 map_menu_cmd(ch)
3736 char ch;
3737 {
3738     char *found = index(mapped_menu_cmds, ch);
3739     if (found) {
3740         int idx = (int) (found - mapped_menu_cmds);
3741         ch = mapped_menu_op[idx];
3742     }
3743     return ch;
3744 }
3745
3746 #if defined(MICRO) || defined(MAC) || defined(WIN32)
3747 #define OPTIONS_HEADING "OPTIONS"
3748 #else
3749 #define OPTIONS_HEADING "NETHACKOPTIONS"
3750 #endif
3751
3752 static char fmtstr_doset_add_menu[] = "%s%-15s [%s]   ";
3753 static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]";
3754
3755 STATIC_OVL void
3756 doset_add_menu(win, option, indexoffset)
3757 winid win;          /* window to add to */
3758 const char *option; /* option name */
3759 int indexoffset;    /* value to add to index in compopt[], or zero
3760                        if option cannot be changed */
3761 {
3762     const char *value = "unknown"; /* current value */
3763     char buf[BUFSZ], buf2[BUFSZ];
3764     anything any;
3765     int i;
3766
3767     any = zeroany;
3768     if (indexoffset == 0) {
3769         any.a_int = 0;
3770         value = get_compopt_value(option, buf2);
3771     } else {
3772         for (i = 0; compopt[i].name; i++)
3773             if (strcmp(option, compopt[i].name) == 0)
3774                 break;
3775
3776         if (compopt[i].name) {
3777             any.a_int = i + 1 + indexoffset;
3778             value = get_compopt_value(option, buf2);
3779         } else {
3780             /* We are trying to add an option not found in compopt[].
3781                This is almost certainly bad, but we'll let it through anyway
3782                (with a zero value, so it can't be selected). */
3783             any.a_int = 0;
3784         }
3785     }
3786     /* "    " replaces "a - " -- assumes menus follow that style */
3787     if (!iflags.menu_tab_sep)
3788         Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ", option,
3789                 value);
3790     else
3791         Sprintf(buf, fmtstr_doset_add_menu_tab, option, value);
3792     add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
3793 }
3794
3795 /* Changing options via menu by Per Liboriussen */
3796 int
3797 doset()
3798 {
3799     char buf[BUFSZ], buf2[BUFSZ];
3800     int i = 0, pass, boolcount, pick_cnt, pick_idx, opt_indx;
3801     boolean *bool_p;
3802     winid tmpwin;
3803     anything any;
3804     menu_item *pick_list;
3805     int indexoffset, startpass, endpass;
3806     boolean setinitial = FALSE, fromfile = FALSE;
3807     int biggest_name = 0;
3808     const char *n_currently_set = "(%d currently set)";
3809
3810     tmpwin = create_nhwindow(NHW_MENU);
3811     start_menu(tmpwin);
3812
3813     any = zeroany;
3814     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3815 /*JP
3816              "Booleans (selecting will toggle value):", MENU_UNSELECTED);
3817 */
3818              "\90^\8bU\83I\83v\83V\83\87\83\93 (\91I\91ð\82·\82é\82Æ\92l\82ª\90Ø\82è\91Ö\82í\82è\82Ü\82·)\81F", MENU_UNSELECTED);
3819     any.a_int = 0;
3820     /* first list any other non-modifiable booleans, then modifiable ones */
3821     for (pass = 0; pass <= 1; pass++)
3822         for (i = 0; boolopt[i].name; i++)
3823             if ((bool_p = boolopt[i].addr) != 0
3824                 && ((boolopt[i].optflags == DISP_IN_GAME && pass == 0)
3825                     || (boolopt[i].optflags == SET_IN_GAME && pass == 1))) {
3826                 if (bool_p == &flags.female)
3827                     continue; /* obsolete */
3828                 if (bool_p == &iflags.sanity_check && !wizard)
3829                     continue;
3830                 if (bool_p == &iflags.menu_tab_sep && !wizard)
3831                     continue;
3832                 if (is_wc_option(boolopt[i].name)
3833                     && !wc_supported(boolopt[i].name))
3834                     continue;
3835                 if (is_wc2_option(boolopt[i].name)
3836                     && !wc2_supported(boolopt[i].name))
3837                     continue;
3838                 any.a_int = (pass == 0) ? 0 : i + 1;
3839                 if (!iflags.menu_tab_sep)
3840                     Sprintf(buf, "%s%-17s [%s]", pass == 0 ? "    " : "",
3841                             boolopt[i].name, *bool_p ? "true" : "false");
3842                 else
3843                     Sprintf(buf, "%s\t[%s]", boolopt[i].name,
3844                             *bool_p ? "true" : "false");
3845                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
3846                          MENU_UNSELECTED);
3847             }
3848
3849     boolcount = i;
3850     indexoffset = boolcount;
3851     any = zeroany;
3852     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
3853 #if 0 /*JP*/
3854     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3855              "Compounds (selecting will prompt for new value):",
3856              MENU_UNSELECTED);
3857 #else
3858     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3859              "\95\8e\9a\97ñ\83I\83v\83V\83\87\83\93 (\91I\91ð\82·\82é\82Æ\90V\82µ\82¢\92l\82Ì\93ü\97Í\82ð\8b\81\82ß\82Ü\82·)\81F",
3860              MENU_UNSELECTED);
3861 #endif
3862
3863 #ifdef notyet /* SYSCF */
3864     /* XXX I think this is still fragile.  Fixing initial/from_file and/or
3865      changing
3866      the SET_* etc to bitmaps will let me make this better. */
3867     if (wizard)
3868         startpass = SET_IN_SYS;
3869     else
3870 #endif
3871         startpass = DISP_IN_GAME;
3872     endpass = SET_IN_GAME;
3873
3874     /* spin through the options to find the biggest name
3875        and adjust the format string accordingly if needed */
3876     biggest_name = 0;
3877     for (i = 0; compopt[i].name; i++)
3878         if (compopt[i].optflags >= startpass && compopt[i].optflags <= endpass
3879             && strlen(compopt[i].name) > (unsigned) biggest_name)
3880             biggest_name = (int) strlen(compopt[i].name);
3881     if (biggest_name > 30)
3882         biggest_name = 30;
3883     if (!iflags.menu_tab_sep)
3884         Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name);
3885
3886     /* deliberately put `playmode', `name', `role', `race', `gender' first
3887        (also alignment if anything ever comes before it in compopt[]) */
3888     doset_add_menu(tmpwin, "playmode", 0);
3889     doset_add_menu(tmpwin, "name", 0);
3890     doset_add_menu(tmpwin, "role", 0);
3891     doset_add_menu(tmpwin, "race", 0);
3892     doset_add_menu(tmpwin, "gender", 0);
3893
3894     for (pass = startpass; pass <= endpass; pass++)
3895         for (i = 0; compopt[i].name; i++)
3896             if (compopt[i].optflags == pass) {
3897                 if (!strcmp(compopt[i].name, "playmode")
3898                     || !strcmp(compopt[i].name, "name")
3899                     || !strcmp(compopt[i].name, "role")
3900                     || !strcmp(compopt[i].name, "race")
3901                     || !strcmp(compopt[i].name, "gender"))
3902                     continue;
3903                 else if (is_wc_option(compopt[i].name)
3904                          && !wc_supported(compopt[i].name))
3905                     continue;
3906                 else if (is_wc2_option(compopt[i].name)
3907                          && !wc2_supported(compopt[i].name))
3908                     continue;
3909                 else
3910                     doset_add_menu(tmpwin, compopt[i].name,
3911                                    (pass == DISP_IN_GAME) ? 0 : indexoffset);
3912             }
3913     any.a_int = -4;
3914     Sprintf(buf2, n_currently_set, msgtype_count());
3915     Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
3916             "message types", buf2);
3917     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
3918     any.a_int = -3;
3919     Sprintf(buf2, n_currently_set, count_menucolors());
3920     Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
3921             "menucolors", buf2);
3922     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
3923 #ifdef STATUS_VIA_WINDOWPORT
3924 #ifdef STATUS_HILITES
3925     any.a_int = -2;
3926     get_status_hilites(buf2, 60);
3927     if (!*buf2)
3928         Sprintf(buf2, "%s", "(none)");
3929     if (!iflags.menu_tab_sep)
3930         Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
3931                 "status_hilites", buf2);
3932     else
3933         Sprintf(buf, fmtstr_doset_add_menu_tab, "status_hilites", buf2);
3934     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
3935 #endif
3936 #endif
3937     any.a_int = -1;
3938     Sprintf(buf2, n_currently_set, count_ape_maps((int *) 0, (int *) 0));
3939     Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : "    ",
3940             "autopickup exceptions", buf2);
3941     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
3942 #ifdef PREFIXES_IN_USE
3943     any = zeroany;
3944     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
3945     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3946              "Variable playground locations:", MENU_UNSELECTED);
3947     for (i = 0; i < PREFIX_COUNT; i++)
3948         doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
3949 #endif
3950 /*JP
3951     end_menu(tmpwin, "Set what options?");
3952 */
3953     end_menu(tmpwin, "\82Ç\82Ì\83I\83v\83V\83\87\83\93\82ð\90Ý\92è\82µ\82Ü\82·\82©\81H");
3954     need_redraw = FALSE;
3955     if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) {
3956         /*
3957          * Walk down the selection list and either invert the booleans
3958          * or prompt for new values. In most cases, call parseoptions()
3959          * to take care of options that require special attention, like
3960          * redraws.
3961          */
3962         for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
3963             opt_indx = pick_list[pick_idx].item.a_int - 1;
3964             if (opt_indx == -2) {
3965                 /* -2 due to -1 offset for select_menu() */
3966                 (void) special_handling("autopickup_exception", setinitial,
3967                                         fromfile);
3968 #ifdef STATUS_VIA_WINDOWPORT
3969 #ifdef STATUS_HILITES
3970             } else if (opt_indx == -3) {
3971                 /* -3 due to -1 offset for select_menu() */
3972                 if (!status_hilite_menu()) {
3973                     pline("Bad status hilite(s) specified.");
3974                 } else {
3975                     if (wc2_supported("status_hilites"))
3976                         preference_update("status_hilites");
3977                 }
3978 #endif
3979 #endif
3980             } else if (opt_indx == -4) {
3981                     (void) special_handling("menucolors", setinitial,
3982                                             fromfile);
3983             } else if (opt_indx == -5) {
3984                     (void) special_handling("msgtype", setinitial, fromfile);
3985             } else if (opt_indx < boolcount) {
3986                 /* boolean option */
3987                 Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
3988                         boolopt[opt_indx].name);
3989                 parseoptions(buf, setinitial, fromfile);
3990                 if (wc_supported(boolopt[opt_indx].name)
3991                     || wc2_supported(boolopt[opt_indx].name))
3992                     preference_update(boolopt[opt_indx].name);
3993             } else {
3994                 /* compound option */
3995                 opt_indx -= boolcount;
3996
3997                 if (!special_handling(compopt[opt_indx].name, setinitial,
3998                                       fromfile)) {
3999 /*JP
4000                     Sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
4001 */
4002                     Sprintf(buf, "%s\82É\89½\82ð\90Ý\92è\82·\82é\81H", compopt[opt_indx].name);
4003                     getlin(buf, buf2);
4004                     if (buf2[0] == '\033')
4005                         continue;
4006                     Sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2);
4007                     /* pass the buck */
4008                     parseoptions(buf, setinitial, fromfile);
4009                 }
4010                 if (wc_supported(compopt[opt_indx].name)
4011                     || wc2_supported(compopt[opt_indx].name))
4012                     preference_update(compopt[opt_indx].name);
4013             }
4014         }
4015         free((genericptr_t) pick_list);
4016         pick_list = (menu_item *) 0;
4017     }
4018
4019     destroy_nhwindow(tmpwin);
4020     if (need_redraw) {
4021         reglyph_darkroom();
4022         (void) doredraw();
4023     }
4024     return 0;
4025 }
4026
4027 int
4028 handle_add_list_remove(optname, numtotal)
4029 const char *optname;
4030 int numtotal;
4031 {
4032     winid tmpwin;
4033     anything any;
4034     int i, pick_cnt, pick_idx, opt_idx;
4035     menu_item *pick_list = (menu_item *) 0;
4036     static const struct action {
4037         char letr;
4038         const char *desc;
4039     } action_titles[] = {
4040 #if 0 /*JP*/
4041         { 'a', "add new %s" },         /* [0] */
4042 #else
4043         { 'a', "\90V\82µ\82¢%s\82ð\92Ç\89Á" },     /* [0] */
4044 #endif
4045 #if 0 /*JP*/
4046         { 'l', "list %s" },            /* [1] */
4047 #else
4048         { 'l', "%s\82ð\88ê\97\97\95\\8e¦" },       /* [1] */
4049 #endif
4050 #if 0 /*JP*/
4051         { 'r', "remove existing %s" }, /* [2] */
4052 #else
4053         { 'r', "\8aù\82É\82 \82é%s\82ð\8dí\8f\9c" },   /* [2] */
4054 #endif
4055 #if 0 /*JP*/
4056         { 'x', "exit this menu" },     /* [3] */
4057 #else
4058         { 'x', "\82±\82Ì\83\81\83j\83\85\81[\82ð\95Â\82\82é" }, /* [3] */
4059 #endif
4060     };
4061
4062     opt_idx = 0;
4063     tmpwin = create_nhwindow(NHW_MENU);
4064     start_menu(tmpwin);
4065     any = zeroany;
4066     for (i = 0; i < SIZE(action_titles); i++) {
4067         char tmpbuf[BUFSZ];
4068         any.a_int++;
4069         /* omit list and remove if there aren't any yet */
4070         if (!numtotal && (i == 1 || i == 2))
4071             continue;
4072         Sprintf(tmpbuf, action_titles[i].desc,
4073                 (i == 1) ? makeplural(optname) : optname);
4074         add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr, 0, ATR_NONE,
4075                  tmpbuf,
4076 #if 0 /* this ought to work but doesn't... */
4077                  (action_titles[i].letr == 'x') ? MENU_SELECTED :
4078 #endif
4079                  MENU_UNSELECTED);
4080     }
4081 /*JP
4082     end_menu(tmpwin, "Do what?");
4083 */
4084     end_menu(tmpwin, "\82Ç\82¤\82·\82é\81H");
4085     if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
4086         for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
4087             opt_idx = pick_list[pick_idx].item.a_int - 1;
4088         }
4089         free((genericptr_t) pick_list);
4090         pick_list = (menu_item *) 0;
4091     }
4092     destroy_nhwindow(tmpwin);
4093
4094     if (pick_cnt < 1)
4095         opt_idx = 3; /* none selected, exit menu */
4096     return opt_idx;
4097 }
4098
4099 struct symsetentry *symset_list = 0; /* files.c will populate this with
4100                                               list of available sets */
4101
4102 STATIC_OVL boolean
4103 special_handling(optname, setinitial, setfromfile)
4104 const char *optname;
4105 boolean setinitial, setfromfile;
4106 {
4107     winid tmpwin;
4108     anything any;
4109     int i;
4110     char buf[BUFSZ];
4111
4112     /* Special handling of menustyle, pickup_burden, pickup_types,
4113      * disclose, runmode, msg_window, menu_headings, sortloot,
4114      * and number_pad options.
4115      * Also takes care of interactive autopickup_exception_handling changes.
4116      */
4117     if (!strcmp("menustyle", optname)) {
4118         const char *style_name;
4119         menu_item *style_pick = (menu_item *) 0;
4120         tmpwin = create_nhwindow(NHW_MENU);
4121         start_menu(tmpwin);
4122         any = zeroany;
4123         for (i = 0; i < SIZE(menutype); i++) {
4124             style_name = menutype[i];
4125             /* note: separate `style_name' variable used
4126                to avoid an optimizer bug in VAX C V2.3 */
4127             any.a_int = i + 1;
4128             add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0, ATR_NONE,
4129                      style_name, MENU_UNSELECTED);
4130         }
4131 /*JP
4132         end_menu(tmpwin, "Select menustyle:");
4133 */
4134         end_menu(tmpwin, "\83\81\83j\83\85\81[\83X\83^\83C\83\8b\82ð\91I\91ð\82µ\82Ä\82­\82¾\82³\82¢\81F");
4135         if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) {
4136             flags.menu_style = style_pick->item.a_int - 1;
4137             free((genericptr_t) style_pick);
4138         }
4139         destroy_nhwindow(tmpwin);
4140     } else if (!strcmp("paranoid_confirmation", optname)) {
4141         menu_item *paranoia_picks = (menu_item *) 0;
4142
4143         tmpwin = create_nhwindow(NHW_MENU);
4144         start_menu(tmpwin);
4145         any = zeroany;
4146         for (i = 0; paranoia[i].flagmask != 0; ++i) {
4147             if (paranoia[i].flagmask == PARANOID_BONES && !wizard)
4148                 continue;
4149             any.a_int = paranoia[i].flagmask;
4150             add_menu(tmpwin, NO_GLYPH, &any, *paranoia[i].argname, 0,
4151                      ATR_NONE, paranoia[i].explain,
4152                      (flags.paranoia_bits & paranoia[i].flagmask)
4153                          ? MENU_SELECTED
4154                          : MENU_UNSELECTED);
4155         }
4156         end_menu(tmpwin, "Actions requiring extra confirmation:");
4157         i = select_menu(tmpwin, PICK_ANY, &paranoia_picks);
4158         if (i >= 0) {
4159             /* player didn't cancel; we reset all the paranoia options
4160                here even if there were no items picked, since user
4161                could have toggled off preselected ones to end up with 0 */
4162             flags.paranoia_bits = 0;
4163             if (i > 0) {
4164                 /* at least 1 item set, either preselected or newly picked */
4165                 while (--i >= 0)
4166                     flags.paranoia_bits |= paranoia_picks[i].item.a_int;
4167                 free((genericptr_t) paranoia_picks);
4168             }
4169         }
4170         destroy_nhwindow(tmpwin);
4171     } else if (!strcmp("pickup_burden", optname)) {
4172         const char *burden_name, *burden_letters = "ubsntl";
4173         menu_item *burden_pick = (menu_item *) 0;
4174
4175         tmpwin = create_nhwindow(NHW_MENU);
4176         start_menu(tmpwin);
4177         any = zeroany;
4178         for (i = 0; i < SIZE(burdentype); i++) {
4179             burden_name = burdentype[i];
4180             any.a_int = i + 1;
4181             add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0, ATR_NONE,
4182                      burden_name, MENU_UNSELECTED);
4183         }
4184 /*JP
4185         end_menu(tmpwin, "Select encumbrance level:");
4186 */
4187         end_menu(tmpwin, "\8cx\8d\90\82ð\8fo\82·\89×\8fd\83\8c\83x\83\8b\82ð\91I\91ð\82µ\82Ä\82­\82¾\82³\82¢\81F");
4188         if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) {
4189             flags.pickup_burden = burden_pick->item.a_int - 1;
4190             free((genericptr_t) burden_pick);
4191         }
4192         destroy_nhwindow(tmpwin);
4193     } else if (!strcmp("pickup_types", optname)) {
4194         /* parseoptions will prompt for the list of types */
4195         parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile);
4196     } else if (!strcmp("disclose", optname)) {
4197         /* order of disclose_names[] must correspond to
4198            disclosure_options in decl.c */
4199         static const char *disclosure_names[] = {
4200             "inventory", "attributes", "vanquished",
4201             "genocides", "conduct",    "overview",
4202         };
4203         int disc_cat[NUM_DISCLOSURE_OPTIONS];
4204         int pick_cnt, pick_idx, opt_idx;
4205         menu_item *disclosure_pick = (menu_item *) 0;
4206
4207         tmpwin = create_nhwindow(NHW_MENU);
4208         start_menu(tmpwin);
4209         any = zeroany;
4210         for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
4211             Sprintf(buf, "%-12s[%c%c]", disclosure_names[i],
4212                     flags.end_disclose[i], disclosure_options[i]);
4213             any.a_int = i + 1;
4214             add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0,
4215                      ATR_NONE, buf, MENU_UNSELECTED);
4216             disc_cat[i] = 0;
4217         }
4218 /*JP
4219         end_menu(tmpwin, "Change which disclosure options categories:");
4220 */
4221         end_menu(tmpwin, "\82Ç\82Ì\83J\83e\83S\83\8a\82Ì\95\\8e¦\8fî\95ñ\83I\83v\83V\83\87\83\93\82ð\95Ï\8dX\82µ\82Ü\82·\82©\81F");
4222         pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_pick);
4223         if (pick_cnt > 0) {
4224             for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
4225                 opt_idx = disclosure_pick[pick_idx].item.a_int - 1;
4226                 disc_cat[opt_idx] = 1;
4227             }
4228             free((genericptr_t) disclosure_pick);
4229             disclosure_pick = (menu_item *) 0;
4230         }
4231         destroy_nhwindow(tmpwin);
4232
4233         for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
4234             if (disc_cat[i]) {
4235 /*JP
4236                 Sprintf(buf, "Disclosure options for %s:",
4237 */
4238                 Sprintf(buf, "%s\82Ì\8fo\97Í\8c`\8e®\81F",
4239                         disclosure_names[i]);
4240                 tmpwin = create_nhwindow(NHW_MENU);
4241                 start_menu(tmpwin);
4242                 any = zeroany;
4243                 /* 'y','n',and '+' work as alternate selectors; '-' doesn't */
4244                 any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
4245                 add_menu(tmpwin, NO_GLYPH, &any, 'a', any.a_char, ATR_NONE,
4246 /*JP
4247                          "Never disclose, without prompting",
4248 */
4249                          "\8am\94F\82¹\82¸\82É\8fo\97Í\82à\82µ\82È\82¢",
4250                          MENU_UNSELECTED);
4251                 any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
4252                 add_menu(tmpwin, NO_GLYPH, &any, 'b', any.a_char, ATR_NONE,
4253 /*JP
4254                          "Always disclose, without prompting",
4255 */
4256                          "\8am\94F\82¹\82¸\82É\8fo\97Í\82·\82é",
4257                          MENU_UNSELECTED);
4258                 any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
4259                 add_menu(tmpwin, NO_GLYPH, &any, 'c', any.a_char, ATR_NONE,
4260 /*JP
4261                          "Prompt, with default answer of \"No\"",
4262 */
4263                          "\8am\94F\82·\82é\81C\83f\83t\83H\83\8b\83g\82Í\81u\8fo\97Í\82µ\82È\82¢\81v",
4264                          MENU_UNSELECTED);
4265                 any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
4266                 add_menu(tmpwin, NO_GLYPH, &any, 'd', any.a_char, ATR_NONE,
4267 /*JP
4268                          "Prompt, with default answer of \"Yes\"",
4269 */
4270                          "\8am\94F\82·\82é\81C\83f\83t\83H\83\8b\83g\82Í\81u\8fo\97Í\82·\82é\81v",
4271                          MENU_UNSELECTED);
4272                 end_menu(tmpwin, buf);
4273                 if (select_menu(tmpwin, PICK_ONE, &disclosure_pick) > 0) {
4274                     flags.end_disclose[i] = disclosure_pick->item.a_char;
4275                     free((genericptr_t) disclosure_pick);
4276                 }
4277                 destroy_nhwindow(tmpwin);
4278             }
4279         }
4280     } else if (!strcmp("runmode", optname)) {
4281         const char *mode_name;
4282         menu_item *mode_pick = (menu_item *) 0;
4283
4284         tmpwin = create_nhwindow(NHW_MENU);
4285         start_menu(tmpwin);
4286         any = zeroany;
4287         for (i = 0; i < SIZE(runmodes); i++) {
4288             mode_name = runmodes[i];
4289             any.a_int = i + 1;
4290             add_menu(tmpwin, NO_GLYPH, &any, *mode_name, 0, ATR_NONE,
4291                      mode_name, MENU_UNSELECTED);
4292         }
4293 /*JP
4294         end_menu(tmpwin, "Select run/travel display mode:");
4295 */
4296         end_menu(tmpwin, "\91\96\8ds/\83g\83\89\83x\83\8b\82Ì\95\\8e¦\83\82\81[\83h\82ð\91I\91ð\82µ\82Ä\82­\82¾\82³\82¢\81F");
4297         if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
4298             flags.runmode = mode_pick->item.a_int - 1;
4299             free((genericptr_t) mode_pick);
4300         }
4301         destroy_nhwindow(tmpwin);
4302     } else if (!strcmp("msg_window", optname)) {
4303 #ifdef TTY_GRAPHICS
4304         /* by Christian W. Cooper */
4305         menu_item *window_pick = (menu_item *) 0;
4306
4307         tmpwin = create_nhwindow(NHW_MENU);
4308         start_menu(tmpwin);
4309         any = zeroany;
4310         any.a_char = 's';
4311         add_menu(tmpwin, NO_GLYPH, &any, 's', 0, ATR_NONE, "single",
4312                  MENU_UNSELECTED);
4313         any.a_char = 'c';
4314         add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE, "combination",
4315                  MENU_UNSELECTED);
4316         any.a_char = 'f';
4317         add_menu(tmpwin, NO_GLYPH, &any, 'f', 0, ATR_NONE, "full",
4318                  MENU_UNSELECTED);
4319         any.a_char = 'r';
4320         add_menu(tmpwin, NO_GLYPH, &any, 'r', 0, ATR_NONE, "reversed",
4321                  MENU_UNSELECTED);
4322 /*JP
4323         end_menu(tmpwin, "Select message history display type:");
4324 */
4325         end_menu(tmpwin, "\83\81\83b\83Z\81[\83W\97\9a\97ð\82Ì\95\\8e¦\95û\96@\82ð\91I\91ð\82µ\82Ä\82­\82¾\82³\82¢\81F");
4326         if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
4327             iflags.prevmsg_window = window_pick->item.a_char;
4328             free((genericptr_t) window_pick);
4329         }
4330         destroy_nhwindow(tmpwin);
4331 #endif
4332     } else if (!strcmp("sortloot", optname)) {
4333         const char *sortl_name;
4334         menu_item *sortl_pick = (menu_item *) 0;
4335
4336         tmpwin = create_nhwindow(NHW_MENU);
4337         start_menu(tmpwin);
4338         any = zeroany;
4339         for (i = 0; i < SIZE(sortltype); i++) {
4340             sortl_name = sortltype[i];
4341             any.a_char = *sortl_name;
4342             add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0, ATR_NONE,
4343                      sortl_name, MENU_UNSELECTED);
4344         }
4345         end_menu(tmpwin, "Select loot sorting type:");
4346         if (select_menu(tmpwin, PICK_ONE, &sortl_pick) > 0) {
4347             flags.sortloot = sortl_pick->item.a_char;
4348             free((genericptr_t) sortl_pick);
4349         }
4350         destroy_nhwindow(tmpwin);
4351     } else if (!strcmp("align_message", optname)
4352                || !strcmp("align_status", optname)) {
4353         menu_item *window_pick = (menu_item *) 0;
4354         char abuf[BUFSZ];
4355         boolean msg = (*(optname + 6) == 'm');
4356
4357         tmpwin = create_nhwindow(NHW_MENU);
4358         start_menu(tmpwin);
4359         any = zeroany;
4360         any.a_int = ALIGN_TOP;
4361         add_menu(tmpwin, NO_GLYPH, &any, 't', 0, ATR_NONE, "top",
4362                  MENU_UNSELECTED);
4363         any.a_int = ALIGN_BOTTOM;
4364         add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, ATR_NONE, "bottom",
4365                  MENU_UNSELECTED);
4366         any.a_int = ALIGN_LEFT;
4367         add_menu(tmpwin, NO_GLYPH, &any, 'l', 0, ATR_NONE, "left",
4368                  MENU_UNSELECTED);
4369         any.a_int = ALIGN_RIGHT;
4370         add_menu(tmpwin, NO_GLYPH, &any, 'r', 0, ATR_NONE, "right",
4371                  MENU_UNSELECTED);
4372 #if 0 /*JP*/
4373         Sprintf(abuf, "Select %s window placement relative to the map:",
4374                 msg ? "message" : "status");
4375 #else
4376         Sprintf(abuf, "%s\83E\83B\83\93\83h\83E\82Ì\83}\83b\83v\82É\91Î\82·\82é\95\\8e¦\88Ê\92u\82ð\91I\91ð\82µ\82Ä\82­\82¾\82³\82¢\81F",
4377                 msg ? "\83\81\83b\83Z\81[\83W" : "\8fó\91Ô");
4378 #endif
4379         end_menu(tmpwin, abuf);
4380         if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
4381             if (msg)
4382                 iflags.wc_align_message = window_pick->item.a_int;
4383             else
4384                 iflags.wc_align_status = window_pick->item.a_int;
4385             free((genericptr_t) window_pick);
4386         }
4387         destroy_nhwindow(tmpwin);
4388     } else if (!strcmp("number_pad", optname)) {
4389         static const char *npchoices[] = {
4390 /*JP
4391             " 0 (off)", " 1 (on)", " 2 (on, MSDOS compatible)",
4392 */
4393             "0 (\96³\8cø)", "1 (\97L\8cø)", "2 (\97L\8cø\81CMSDOS\8cÝ\8a·)",
4394 /*JP
4395             " 3 (on, phone-style digit layout)",
4396 */
4397             " 3 (\97L\8cø\81C\93d\98b\8e®\82Ì\90\94\8e\9a\94z\92u)",
4398 /*JP
4399             " 4 (on, phone-style layout, MSDOS compatible)",
4400 */
4401             " 4 (\97L\8cø\81C\93d\98b\8e®\82Ì\94z\92u\81CMSDOS \8cÝ\8a·)",
4402 /*JP
4403             "-1 (off, 'z' to move upper-left, 'y' to zap wands)"
4404 */
4405             "-1 (\96³\8cø\81C'z' \82Å\8d\8fã\82É\88Ú\93®\81C'y' \82Å\8fñ\82ð\90U\82é)"
4406         };
4407         menu_item *mode_pick = (menu_item *) 0;
4408
4409         tmpwin = create_nhwindow(NHW_MENU);
4410         start_menu(tmpwin);
4411         any = zeroany;
4412         for (i = 0; i < SIZE(npchoices); i++) {
4413             any.a_int = i + 1;
4414             add_menu(tmpwin, NO_GLYPH, &any, 'a' + i, 0, ATR_NONE,
4415                      npchoices[i], MENU_UNSELECTED);
4416         }
4417 /*JP
4418         end_menu(tmpwin, "Select number_pad mode:");
4419 */
4420         end_menu(tmpwin, "number_pad\83\82\81[\83h\82ð\91I\91ð\82µ\82Ä\82­\82¾\82³\82¢\81F");
4421         if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
4422             switch (mode_pick->item.a_int - 1) {
4423             case 0:
4424                 iflags.num_pad = FALSE;
4425                 iflags.num_pad_mode = 0;
4426                 break;
4427             case 1:
4428                 iflags.num_pad = TRUE;
4429                 iflags.num_pad_mode = 0;
4430                 break;
4431             case 2:
4432                 iflags.num_pad = TRUE;
4433                 iflags.num_pad_mode = 1;
4434                 break;
4435             case 3:
4436                 iflags.num_pad = TRUE;
4437                 iflags.num_pad_mode = 2;
4438                 break;
4439             case 4:
4440                 iflags.num_pad = TRUE;
4441                 iflags.num_pad_mode = 3;
4442                 break;
4443             /* last menu choice: number_pad == -1 */
4444             case 5:
4445                 iflags.num_pad = FALSE;
4446                 iflags.num_pad_mode = 1;
4447                 break;
4448             }
4449             reset_commands(FALSE);
4450             number_pad(iflags.num_pad ? 1 : 0);
4451             free((genericptr_t) mode_pick);
4452         }
4453         destroy_nhwindow(tmpwin);
4454     } else if (!strcmp("menu_headings", optname)) {
4455 /*JP
4456         int mhattr = query_attr("How to highlight menu headings:");
4457 */
4458         int mhattr = query_attr("\83\81\83j\83\85\81[\83w\83b\83_\82Ì\8b­\92²\95û\96@\82ð\91I\91ð\82µ\82Ä\82­\82¾\82³\82¢\81F");
4459
4460         if (mhattr != -1)
4461             iflags.menu_headings = mhattr;
4462     } else if (!strcmp("msgtype", optname)) {
4463         int opt_idx, nmt, mttyp;
4464         char mtbuf[BUFSZ];
4465
4466     msgtypes_again:
4467         nmt = msgtype_count();
4468         opt_idx = handle_add_list_remove("message type", nmt);
4469         if (opt_idx == 3) {
4470             ; /* done--fall through to function exit */
4471         } else if (opt_idx == 0) { /* add new */
4472             getlin("What new message pattern?", mtbuf);
4473             if (*mtbuf == '\033' || !*mtbuf)
4474                 goto msgtypes_again;
4475             mttyp = query_msgtype();
4476             if (mttyp == -1)
4477                 goto msgtypes_again;
4478             if (!msgtype_add(mttyp, mtbuf)) {
4479                 pline("Error adding the message type.");
4480                 wait_synch();
4481                 goto msgtypes_again;
4482             }
4483         } else { /* list or remove */
4484             int pick_idx, pick_cnt;
4485             int mt_idx;
4486             menu_item *pick_list = (menu_item *) 0;
4487             struct plinemsg_type *tmp = plinemsg_types;
4488
4489             tmpwin = create_nhwindow(NHW_MENU);
4490             start_menu(tmpwin);
4491             any = zeroany;
4492             mt_idx = 0;
4493             while (tmp) {
4494                 const char *mtype = msgtype2name(tmp->msgtype);
4495
4496                 any.a_int = ++mt_idx;
4497                 Sprintf(mtbuf, "%-5s \"%s\"", mtype, tmp->pattern);
4498                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mtbuf,
4499                          MENU_UNSELECTED);
4500                 tmp = tmp->next;
4501             }
4502             Sprintf(mtbuf, "%s message types",
4503                     (opt_idx == 1) ? "List of" : "Remove which");
4504             end_menu(tmpwin, mtbuf);
4505             pick_cnt = select_menu(tmpwin,
4506                                    (opt_idx == 1) ? PICK_NONE : PICK_ANY,
4507                                    &pick_list);
4508             if (pick_cnt > 0) {
4509                 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
4510                     free_one_msgtype(pick_list[pick_idx].item.a_int - 1
4511                                            - pick_idx);
4512                 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
4513             }
4514             destroy_nhwindow(tmpwin);
4515             if (pick_cnt >= 0)
4516                 goto msgtypes_again;
4517         }
4518     } else if (!strcmp("menucolors", optname)) {
4519         int opt_idx, nmc, mcclr, mcattr;
4520         char mcbuf[BUFSZ];
4521
4522     menucolors_again:
4523         nmc = count_menucolors();
4524         opt_idx = handle_add_list_remove("menucolor", nmc);
4525         if (opt_idx == 3) {
4526             ;                      /* done--fall through to function exit */
4527         } else if (opt_idx == 0) { /* add new */
4528             getlin("What new menucolor pattern?", mcbuf);
4529             if (*mcbuf == '\033' || !*mcbuf)
4530                 goto menucolors_again;
4531             mcclr = query_color();
4532             if (mcclr == -1)
4533                 goto menucolors_again;
4534             mcattr = query_attr(NULL);
4535             if (mcattr == -1)
4536                 goto menucolors_again;
4537             if (!add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
4538                 pline("Error adding the menu color.");
4539                 wait_synch();
4540                 goto menucolors_again;
4541             }
4542         } else { /* list or remove */
4543             int pick_idx, pick_cnt;
4544             int mc_idx;
4545             menu_item *pick_list = (menu_item *) 0;
4546             struct menucoloring *tmp = menu_colorings;
4547
4548             tmpwin = create_nhwindow(NHW_MENU);
4549             start_menu(tmpwin);
4550             any = zeroany;
4551             mc_idx = 0;
4552             while (tmp) {
4553                 const char *sattr = attr2attrname(tmp->attr);
4554                 const char *sclr = clr2colorname(tmp->color);
4555
4556                 any.a_int = (++mc_idx);
4557                 Sprintf(mcbuf, "\"%s\"=%s%s%s", tmp->origstr, sclr,
4558                         (tmp->attr != ATR_NONE) ? " & " : "",
4559                         (tmp->attr != ATR_NONE) ? sattr : "");
4560                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mcbuf,
4561                          MENU_UNSELECTED);
4562                 tmp = tmp->next;
4563             }
4564             Sprintf(mcbuf, "%s menu colors",
4565                     (opt_idx == 1) ? "List of" : "Remove which");
4566             end_menu(tmpwin, mcbuf);
4567             pick_cnt = select_menu(tmpwin,
4568                                    (opt_idx == 1) ? PICK_NONE : PICK_ANY,
4569                                    &pick_list);
4570             if (pick_cnt > 0) {
4571                 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
4572                     free_one_menu_coloring(pick_list[pick_idx].item.a_int - 1
4573                                            - pick_idx);
4574                 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
4575             }
4576             destroy_nhwindow(tmpwin);
4577             if (pick_cnt >= 0)
4578                 goto menucolors_again;
4579         }
4580     } else if (!strcmp("autopickup_exception", optname)) {
4581         int opt_idx, pass, totalapes = 0, numapes[2] = { 0, 0 };
4582         char apebuf[1 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */
4583         struct autopickup_exception *ape;
4584
4585     ape_again:
4586         totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
4587         opt_idx = handle_add_list_remove("autopickup exception", totalapes);
4588         if (opt_idx == 3) {
4589             ;                      /* done--fall through to function exit */
4590         } else if (opt_idx == 0) { /* add new */
4591 /*JP
4592             getlin("What new autopickup exception pattern?", &apebuf[1]);
4593 */
4594             getlin("\90V\82µ\82¢\8e©\93®\8fE\82¢\97á\8aO\82Ì\83p\83^\81[\83\93\82ð\93ü\97Í\82µ\82Ä\82­\82¾\82³\82¢\81F", &apebuf[1]);
4595             mungspaces(&apebuf[1]); /* regularize whitespace */
4596             if (apebuf[1] == '\033') {
4597                 ; /* fall through to function exit */
4598             } else {
4599                 if (apebuf[1]) {
4600                     apebuf[0] = '\"';
4601                     /* guarantee room for \" prefix and \"\0 suffix;
4602                        -2 is good enough for apebuf[] but -3 makes
4603                        sure the whole thing fits within normal BUFSZ */
4604                     apebuf[sizeof apebuf - 3] = '\0';
4605                     Strcat(apebuf, "\"");
4606                     add_autopickup_exception(apebuf);
4607                 }
4608                 goto ape_again;
4609             }
4610         } else { /* list or remove */
4611             int pick_idx, pick_cnt;
4612             menu_item *pick_list = (menu_item *) 0;
4613
4614             tmpwin = create_nhwindow(NHW_MENU);
4615             start_menu(tmpwin);
4616             for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
4617                 if (numapes[pass] == 0)
4618                     continue;
4619                 ape = iflags.autopickup_exceptions[pass];
4620                 any = zeroany;
4621                 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
4622 /*JP
4623                          (pass == 0) ? "Never pickup" : "Always pickup",
4624 */
4625                          (pass == 0) ? "\8fí\82É\8fE\82í\82È\82¢" : "\8fí\82É\8fE\82¤",
4626                          MENU_UNSELECTED);
4627                 for (i = 0; i < numapes[pass] && ape; i++) {
4628                     any.a_void = (opt_idx == 1) ? 0 : ape;
4629                     Sprintf(apebuf, "\"%s\"", ape->pattern);
4630                     add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, apebuf,
4631                              MENU_UNSELECTED);
4632                     ape = ape->next;
4633                 }
4634             }
4635 #if 0 /*JP*/
4636             Sprintf(apebuf, "%s autopickup exceptions",
4637                     (opt_idx == 1) ? "List of" : "Remove which");
4638 #else
4639             Sprintf(apebuf, "%s\8e©\93®\8fE\82¢\97á\8aO%s",
4640                     (opt_idx == 1) ? "" : "\82Ç\82Ì",
4641                     (opt_idx == 1) ? "\82Ì\88ê\97\97" : "\82ð\8dí\8f\9c\82µ\82Ü\82·\82©\81H");
4642 #endif
4643             end_menu(tmpwin, apebuf);
4644             pick_cnt = select_menu(tmpwin,
4645                                    (opt_idx == 1) ? PICK_NONE : PICK_ANY,
4646                                    &pick_list);
4647             if (pick_cnt > 0) {
4648                 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
4649                     remove_autopickup_exception(
4650                                          (struct autopickup_exception *)
4651                                              pick_list[pick_idx].item.a_void);
4652                 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
4653             }
4654             destroy_nhwindow(tmpwin);
4655             if (pick_cnt >= 0)
4656                 goto ape_again;
4657         }
4658     } else if (!strcmp("symset", optname)
4659                || !strcmp("roguesymset", optname)) {
4660         menu_item *symset_pick = (menu_item *) 0;
4661         boolean primaryflag = (*optname == 's'),
4662                 rogueflag = (*optname == 'r'),
4663                 ready_to_switch = FALSE,
4664                 nothing_to_do = FALSE;
4665         char *symset_name, fmtstr[20];
4666         struct symsetentry *sl;
4667         int res, which_set, setcount = 0, chosen = -2;
4668
4669         if (rogueflag)
4670             which_set = ROGUESET;
4671         else
4672             which_set = PRIMARY;
4673
4674         /* clear symset[].name as a flag to read_sym_file() to build list */
4675         symset_name = symset[which_set].name;
4676         symset[which_set].name = (char *) 0;
4677         symset_list = (struct symsetentry *) 0;
4678
4679         res = read_sym_file(which_set);
4680         if (res && symset_list) {
4681             char symsetchoice[BUFSZ];
4682             int let = 'a', biggest = 0, thissize = 0;
4683
4684             sl = symset_list;
4685             while (sl) {
4686                 /* check restrictions */
4687                 if ((!rogueflag && sl->rogue)
4688                     || (!primaryflag && sl->primary)) {
4689                     sl = sl->next;
4690                     continue;
4691                 }
4692                 setcount++;
4693                 /* find biggest name */
4694                 if (sl->name)
4695                     thissize = strlen(sl->name);
4696                 if (thissize > biggest)
4697                     biggest = thissize;
4698                 sl = sl->next;
4699             }
4700             if (!setcount) {
4701                 pline("There are no appropriate %ssymbol sets available.",
4702                       (rogueflag) ? "rogue level "
4703                                   : (primaryflag) ? "primary " : "");
4704                 return TRUE;
4705             }
4706
4707             Sprintf(fmtstr, "%%-%ds %%s", biggest + 5);
4708             tmpwin = create_nhwindow(NHW_MENU);
4709             start_menu(tmpwin);
4710             any = zeroany;
4711             any.a_int = 1;
4712             add_menu(tmpwin, NO_GLYPH, &any, let++, 0, ATR_NONE,
4713                      "Default Symbols", MENU_UNSELECTED);
4714
4715             sl = symset_list;
4716             while (sl) {
4717                 /* check restrictions */
4718                 if ((!rogueflag && sl->rogue)
4719                     || (!primaryflag && sl->primary)) {
4720                     sl = sl->next;
4721                     continue;
4722                 }
4723                 if (sl->name) {
4724                     any.a_int = sl->idx + 2;
4725                     Sprintf(symsetchoice, fmtstr, sl->name,
4726                             sl->desc ? sl->desc : "");
4727                     add_menu(tmpwin, NO_GLYPH, &any, let, 0, ATR_NONE,
4728                              symsetchoice, MENU_UNSELECTED);
4729                     if (let == 'z')
4730                         let = 'A';
4731                     else
4732                         let++;
4733                 }
4734                 sl = sl->next;
4735             }
4736             end_menu(tmpwin, "Select symbol set:");
4737             if (select_menu(tmpwin, PICK_ONE, &symset_pick) > 0) {
4738                 chosen = symset_pick->item.a_int - 2;
4739                 free((genericptr_t) symset_pick);
4740             }
4741             destroy_nhwindow(tmpwin);
4742
4743             if (chosen > -1) {
4744                 /* chose an actual symset name from file */
4745                 sl = symset_list;
4746                 while (sl) {
4747                     if (sl->idx == chosen) {
4748                         if (symset_name) {
4749                             free((genericptr_t) symset_name);
4750                             symset_name = (char *) 0;
4751                         }
4752                         /* free the now stale attributes */
4753                         clear_symsetentry(which_set, TRUE);
4754
4755                         /* transfer only the name of the symbol set */
4756                         symset[which_set].name = dupstr(sl->name);
4757                         ready_to_switch = TRUE;
4758                         break;
4759                     }
4760                     sl = sl->next;
4761                 }
4762             } else if (chosen == -1) {
4763                 /* explicit selection of defaults */
4764                 /* free the now stale symset attributes */
4765                 if (symset_name) {
4766                     free((genericptr_t) symset_name);
4767                     symset_name = (char *) 0;
4768                 }
4769                 clear_symsetentry(which_set, TRUE);
4770             } else
4771                 nothing_to_do = TRUE;
4772         } else if (!res) {
4773             /* The symbols file could not be accessed */
4774             pline("Unable to access \"%s\" file.", SYMBOLS);
4775             return TRUE;
4776         } else if (!symset_list) {
4777             /* The symbols file was empty */
4778             pline("There were no symbol sets found in \"%s\".", SYMBOLS);
4779             return TRUE;
4780         }
4781
4782         /* clean up */
4783         while (symset_list) {
4784             sl = symset_list;
4785             if (sl->name)
4786                 free((genericptr_t) sl->name);
4787             sl->name = (char *) 0;
4788
4789             if (sl->desc)
4790                 free((genericptr_t) sl->desc);
4791             sl->desc = (char *) 0;
4792
4793             symset_list = sl->next;
4794             free((genericptr_t) sl);
4795         }
4796
4797         if (nothing_to_do)
4798             return TRUE;
4799
4800         if (!symset[which_set].name && symset_name)
4801             symset[which_set].name = symset_name; /* not dupstr() here */
4802
4803         /* Set default symbols and clear the handling value */
4804         if (rogueflag)
4805             init_r_symbols();
4806         else
4807             init_l_symbols();
4808
4809         if (symset[which_set].name) {
4810             if (read_sym_file(which_set)) {
4811                 ready_to_switch = TRUE;
4812             } else {
4813                 clear_symsetentry(which_set, TRUE);
4814                 return TRUE;
4815             }
4816         }
4817
4818         if (ready_to_switch)
4819             switch_symbols(TRUE);
4820
4821         if (Is_rogue_level(&u.uz)) {
4822             if (rogueflag)
4823                 assign_graphics(ROGUESET);
4824         } else if (!rogueflag)
4825             assign_graphics(PRIMARY);
4826         need_redraw = TRUE;
4827         return TRUE;
4828
4829     } else {
4830         /* didn't match any of the special options */
4831         return FALSE;
4832     }
4833     return TRUE;
4834 }
4835
4836 #define rolestring(val, array, field) \
4837     ((val >= 0) ? array[val].field : (val == ROLE_RANDOM) ? randomrole : none)
4838
4839 /* This is ugly. We have all the option names in the compopt[] array,
4840    but we need to look at each option individually to get the value. */
4841 STATIC_OVL const char *
4842 get_compopt_value(optname, buf)
4843 const char *optname;
4844 char *buf;
4845 {
4846     char ocl[MAXOCLASSES + 1];
4847 #if 0 /*JP*/
4848     static const char none[] = "(none)", randomrole[] = "random",
4849                       to_be_done[] = "(to be done)", defopt[] = "default",
4850                       defbrief[] = "def";
4851 #else
4852     static const char none[] = "(\82È\82µ)", randomrole[] = "\83\89\83\93\83_\83\80",
4853                       to_be_done[] = "(\96¢\90Ý\92è)", defopt[] = "\83f\83t\83H\83\8b\83g",
4854                       defbrief[] = "def";
4855 #endif
4856     int i;
4857
4858     buf[0] = '\0';
4859     if (!strcmp(optname, "align_message"))
4860 #if 0 /*JP*/
4861         Sprintf(buf, "%s",
4862                 iflags.wc_align_message == ALIGN_TOP
4863                     ? "top"
4864                     : iflags.wc_align_message == ALIGN_LEFT
4865                           ? "left"
4866                           : iflags.wc_align_message == ALIGN_BOTTOM
4867                                 ? "bottom"
4868                                 : iflags.wc_align_message == ALIGN_RIGHT
4869                                       ? "right"
4870                                       : defopt);
4871 #else
4872         Sprintf(buf, "%s",
4873                 iflags.wc_align_message == ALIGN_TOP
4874                     ? "\8fã\91¤"
4875                     : iflags.wc_align_message == ALIGN_LEFT
4876                           ? "\8d\91¤"
4877                           : iflags.wc_align_message == ALIGN_BOTTOM
4878                                 ? "\89º\91¤"
4879                                 : iflags.wc_align_message == ALIGN_RIGHT
4880                                       ? "\89E\91¤" : defopt);
4881 #endif
4882     else if (!strcmp(optname, "align_status"))
4883 #if 0 /*JP*/
4884         Sprintf(buf, "%s",
4885                 iflags.wc_align_status == ALIGN_TOP
4886                     ? "top"
4887                     : iflags.wc_align_status == ALIGN_LEFT
4888                           ? "left"
4889                           : iflags.wc_align_status == ALIGN_BOTTOM
4890                                 ? "bottom"
4891                                 : iflags.wc_align_status == ALIGN_RIGHT
4892                                       ? "right"
4893                                       : defopt);
4894 #else
4895         Sprintf(buf, "%s",
4896                 iflags.wc_align_status == ALIGN_TOP
4897                     ? "\8fã\91¤"
4898                     : iflags.wc_align_status == ALIGN_LEFT
4899                           ? "\8d\91¤"
4900                           : iflags.wc_align_status == ALIGN_BOTTOM
4901                                 ? "\89º\91¤"
4902                                 : iflags.wc_align_status == ALIGN_RIGHT
4903                                       ? "\89E\91¤"
4904                                       : defopt);
4905 #endif
4906     else if (!strcmp(optname, "align"))
4907         Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj));
4908 #ifdef WIN32
4909     else if (!strcmp(optname, "altkeyhandler"))
4910         Sprintf(buf, "%s",
4911 /*JP
4912                 iflags.altkeyhandler[0] ? iflags.altkeyhandler : "default");
4913 */
4914                 iflags.altkeyhandler[0] ? iflags.altkeyhandler : defopt);
4915 #endif
4916 #ifdef BACKWARD_COMPAT
4917     else if (!strcmp(optname, "boulder"))
4918         Sprintf(buf, "%c",
4919                 iflags.bouldersym
4920                     ? iflags.bouldersym
4921                     : showsyms[(int) objects[BOULDER].oc_class + SYM_OFF_O]);
4922 #endif
4923     else if (!strcmp(optname, "catname"))
4924         Sprintf(buf, "%s", catname[0] ? catname : none);
4925     else if (!strcmp(optname, "disclose"))
4926         for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
4927             if (i)
4928                 (void) strkitten(buf, ' ');
4929             (void) strkitten(buf, flags.end_disclose[i]);
4930             (void) strkitten(buf, disclosure_options[i]);
4931         }
4932     else if (!strcmp(optname, "dogname"))
4933         Sprintf(buf, "%s", dogname[0] ? dogname : none);
4934     else if (!strcmp(optname, "dungeon"))
4935         Sprintf(buf, "%s", to_be_done);
4936     else if (!strcmp(optname, "effects"))
4937         Sprintf(buf, "%s", to_be_done);
4938     else if (!strcmp(optname, "font_map"))
4939         Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt);
4940     else if (!strcmp(optname, "font_message"))
4941         Sprintf(buf, "%s",
4942                 iflags.wc_font_message ? iflags.wc_font_message : defopt);
4943     else if (!strcmp(optname, "font_status"))
4944         Sprintf(buf, "%s",
4945                 iflags.wc_font_status ? iflags.wc_font_status : defopt);
4946     else if (!strcmp(optname, "font_menu"))
4947         Sprintf(buf, "%s",
4948                 iflags.wc_font_menu ? iflags.wc_font_menu : defopt);
4949     else if (!strcmp(optname, "font_text"))
4950         Sprintf(buf, "%s",
4951                 iflags.wc_font_text ? iflags.wc_font_text : defopt);
4952     else if (!strcmp(optname, "font_size_map")) {
4953         if (iflags.wc_fontsiz_map)
4954             Sprintf(buf, "%d", iflags.wc_fontsiz_map);
4955         else
4956             Strcpy(buf, defopt);
4957     } else if (!strcmp(optname, "font_size_message")) {
4958         if (iflags.wc_fontsiz_message)
4959             Sprintf(buf, "%d", iflags.wc_fontsiz_message);
4960         else
4961             Strcpy(buf, defopt);
4962     } else if (!strcmp(optname, "font_size_status")) {
4963         if (iflags.wc_fontsiz_status)
4964             Sprintf(buf, "%d", iflags.wc_fontsiz_status);
4965         else
4966             Strcpy(buf, defopt);
4967     } else if (!strcmp(optname, "font_size_menu")) {
4968         if (iflags.wc_fontsiz_menu)
4969             Sprintf(buf, "%d", iflags.wc_fontsiz_menu);
4970         else
4971             Strcpy(buf, defopt);
4972     } else if (!strcmp(optname, "font_size_text")) {
4973         if (iflags.wc_fontsiz_text)
4974             Sprintf(buf, "%d", iflags.wc_fontsiz_text);
4975         else
4976             Strcpy(buf, defopt);
4977     } else if (!strcmp(optname, "fruit"))
4978         Sprintf(buf, "%s", pl_fruit);
4979     else if (!strcmp(optname, "gender"))
4980         Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
4981     else if (!strcmp(optname, "horsename"))
4982         Sprintf(buf, "%s", horsename[0] ? horsename : none);
4983     else if (!strcmp(optname, "map_mode"))
4984         Sprintf(buf, "%s",
4985                 iflags.wc_map_mode == MAP_MODE_TILES
4986                   ? "tiles"
4987                   : iflags.wc_map_mode == MAP_MODE_ASCII4x6
4988                      ? "ascii4x6"
4989                      : iflags.wc_map_mode == MAP_MODE_ASCII6x8
4990                         ? "ascii6x8"
4991                         : iflags.wc_map_mode == MAP_MODE_ASCII8x8
4992                            ? "ascii8x8"
4993                            : iflags.wc_map_mode == MAP_MODE_ASCII16x8
4994                               ? "ascii16x8"
4995                               : iflags.wc_map_mode == MAP_MODE_ASCII7x12
4996                                  ? "ascii7x12"
4997                                  : iflags.wc_map_mode == MAP_MODE_ASCII8x12
4998                                     ? "ascii8x12"
4999                                     : iflags.wc_map_mode
5000                                       == MAP_MODE_ASCII16x12
5001                                        ? "ascii16x12"
5002                                        : iflags.wc_map_mode
5003                                          == MAP_MODE_ASCII12x16
5004                                           ? "ascii12x16"
5005                                           : iflags.wc_map_mode
5006                                             == MAP_MODE_ASCII10x18
5007                                              ? "ascii10x18"
5008                                              : iflags.wc_map_mode
5009                                                == MAP_MODE_ASCII_FIT_TO_SCREEN
5010                                                 ? "fit_to_screen"
5011                                                 : defopt);
5012     else if (!strcmp(optname, "menustyle"))
5013         Sprintf(buf, "%s", menutype[(int) flags.menu_style]);
5014     else if (!strcmp(optname, "menu_deselect_all"))
5015         Sprintf(buf, "%s", to_be_done);
5016     else if (!strcmp(optname, "menu_deselect_page"))
5017         Sprintf(buf, "%s", to_be_done);
5018     else if (!strcmp(optname, "menu_first_page"))
5019         Sprintf(buf, "%s", to_be_done);
5020     else if (!strcmp(optname, "menu_invert_all"))
5021         Sprintf(buf, "%s", to_be_done);
5022     else if (!strcmp(optname, "menu_headings"))
5023         Sprintf(buf, "%s", attr2attrname(iflags.menu_headings));
5024     else if (!strcmp(optname, "menu_invert_page"))
5025         Sprintf(buf, "%s", to_be_done);
5026     else if (!strcmp(optname, "menu_last_page"))
5027         Sprintf(buf, "%s", to_be_done);
5028     else if (!strcmp(optname, "menu_next_page"))
5029         Sprintf(buf, "%s", to_be_done);
5030     else if (!strcmp(optname, "menu_previous_page"))
5031         Sprintf(buf, "%s", to_be_done);
5032     else if (!strcmp(optname, "menu_search"))
5033         Sprintf(buf, "%s", to_be_done);
5034     else if (!strcmp(optname, "menu_select_all"))
5035         Sprintf(buf, "%s", to_be_done);
5036     else if (!strcmp(optname, "menu_select_page"))
5037         Sprintf(buf, "%s", to_be_done);
5038     else if (!strcmp(optname, "monsters")) {
5039         Sprintf(buf, "%s", to_be_done);
5040     } else if (!strcmp(optname, "msghistory")) {
5041         Sprintf(buf, "%u", iflags.msg_history);
5042 #ifdef TTY_GRAPHICS
5043     } else if (!strcmp(optname, "msg_window")) {
5044         Sprintf(buf, "%s", (iflags.prevmsg_window == 's')
5045                                ? "single"
5046                                : (iflags.prevmsg_window == 'c')
5047                                      ? "combination"
5048                                      : (iflags.prevmsg_window == 'f')
5049                                            ? "full"
5050                                            : "reversed");
5051 #endif
5052     } else if (!strcmp(optname, "name")) {
5053         Sprintf(buf, "%s", plname);
5054     } else if (!strcmp(optname, "number_pad")) {
5055         static const char *numpadmodes[] = {
5056 /*JP
5057             "0=off", "1=on", "2=on, MSDOS compatible",
5058 */
5059             "0=\96³\8cø", "1=\97L\8cø", "2=\97L\8cø\81CDOS\8cÝ\8a·",
5060 /*JP
5061             "3=on, phone-style layout",
5062 */
5063             "3=\97L\8cø\81C\93d\98b\8e®\82Ì\90\94\8e\9a\94z\92u",
5064 /*JP
5065             "4=on, phone layout, MSDOS compatible",
5066 */
5067             "4=\97L\8cø\81C\93d\98b\8e®\82Ì\94z\92u\81CMSDOS \8cÝ\8a·",
5068 #if 0 /*JP*/
5069             "-1=off, y & z swapped", /*[5]*/
5070 #else
5071             "-1=\96³\8cø\81Cy\82Æz\82ð\93ü\82ê\91Ö\82¦", /*[5]*/
5072 #endif
5073         };
5074         int indx = Cmd.num_pad
5075                        ? (Cmd.phone_layout ? (Cmd.pcHack_compat ? 4 : 3)
5076                                            : (Cmd.pcHack_compat ? 2 : 1))
5077                        : Cmd.swap_yz ? 5 : 0;
5078
5079         Strcpy(buf, numpadmodes[indx]);
5080     } else if (!strcmp(optname, "objects")) {
5081         Sprintf(buf, "%s", to_be_done);
5082     } else if (!strcmp(optname, "packorder")) {
5083         oc_to_str(flags.inv_order, ocl);
5084         Sprintf(buf, "%s", ocl);
5085 #ifdef CHANGE_COLOR
5086     } else if (!strcmp(optname, "palette")) {
5087         Sprintf(buf, "%s", get_color_string());
5088 #endif
5089     } else if (!strcmp(optname, "paranoid_confirmation")) {
5090         char tmpbuf[QBUFSZ];
5091
5092         tmpbuf[0] = '\0';
5093         if (ParanoidConfirm)
5094             Strcat(tmpbuf, " Confirm");
5095         if (ParanoidQuit)
5096             Strcat(tmpbuf, " quit");
5097         if (ParanoidDie)
5098             Strcat(tmpbuf, " die");
5099         if (ParanoidBones)
5100             Strcat(tmpbuf, " bones");
5101         if (ParanoidHit)
5102             Strcat(tmpbuf, " attack");
5103         if (ParanoidPray)
5104             Strcat(tmpbuf, " pray");
5105         if (ParanoidRemove)
5106             Strcat(tmpbuf, " Remove");
5107         Strcpy(buf, tmpbuf[0] ? &tmpbuf[1] : "none");
5108     } else if (!strcmp(optname, "pettype")) {
5109 #if 0 /*JP*/
5110         Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat"
5111                            : (preferred_pet == 'd') ? "dog"
5112                              : (preferred_pet == 'h') ? "horse"
5113                                : (preferred_pet == 'n') ? "none"
5114                                  : "random");
5115 #else
5116         Sprintf(buf, "%s", (preferred_pet == 'c') ? "\94L"
5117                            : (preferred_pet == 'd') ? "\8c¢"
5118                              : (preferred_pet == 'h') ? "\94n"
5119                                : (preferred_pet == 'n') ? "\82È\82µ"
5120                                  : "\83\89\83\93\83_\83\80");
5121 #endif
5122     } else if (!strcmp(optname, "pickup_burden")) {
5123         Sprintf(buf, "%s", burdentype[flags.pickup_burden]);
5124     } else if (!strcmp(optname, "pickup_types")) {
5125         oc_to_str(flags.pickup_types, ocl);
5126         Sprintf(buf, "%s", ocl[0] ? ocl : "all");
5127     } else if (!strcmp(optname, "pile_limit")) {
5128         Sprintf(buf, "%d", flags.pile_limit);
5129     } else if (!strcmp(optname, "playmode")) {
5130         Strcpy(buf, wizard ? "debug" : discover ? "explore" : "normal");
5131     } else if (!strcmp(optname, "race")) {
5132         Sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
5133     } else if (!strcmp(optname, "roguesymset")) {
5134         Sprintf(buf, "%s",
5135                 symset[ROGUESET].name ? symset[ROGUESET].name : "default");
5136         if (currentgraphics == ROGUESET && symset[ROGUESET].name)
5137             Strcat(buf, ", active");
5138     } else if (!strcmp(optname, "role")) {
5139         Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
5140     } else if (!strcmp(optname, "runmode")) {
5141         Sprintf(buf, "%s", runmodes[flags.runmode]);
5142     } else if (!strcmp(optname, "scores")) {
5143         Sprintf(buf, "%d top/%d around%s", flags.end_top, flags.end_around,
5144                 flags.end_own ? "/own" : "");
5145     } else if (!strcmp(optname, "scroll_amount")) {
5146         if (iflags.wc_scroll_amount)
5147             Sprintf(buf, "%d", iflags.wc_scroll_amount);
5148         else
5149             Strcpy(buf, defopt);
5150     } else if (!strcmp(optname, "scroll_margin")) {
5151         if (iflags.wc_scroll_margin)
5152             Sprintf(buf, "%d", iflags.wc_scroll_margin);
5153         else
5154             Strcpy(buf, defopt);
5155     } else if (!strcmp(optname, "sortloot")) {
5156         for (i = 0; i < SIZE(sortltype); i++)
5157             if (flags.sortloot == sortltype[i][0]) {
5158                 Strcpy(buf, sortltype[i]);
5159                 break;
5160             }
5161     } else if (!strcmp(optname, "player_selection")) {
5162 #if 0 /*JP*/
5163         Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
5164 #else
5165         Sprintf(buf, "%s\93ü\97Í", iflags.wc_player_selection ? "\83v\83\8d\83\93\83v\83g" : "\83_\83C\83A\83\8d\83O");
5166 #endif
5167 #ifdef MSDOS
5168     } else if (!strcmp(optname, "soundcard")) {
5169         Sprintf(buf, "%s", to_be_done);
5170 #endif
5171     } else if (!strcmp(optname, "suppress_alert")) {
5172         if (flags.suppress_alert == 0L)
5173             Strcpy(buf, none);
5174         else
5175             Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
5176                     FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
5177     } else if (!strcmp(optname, "symset")) {
5178         Sprintf(buf, "%s",
5179                 symset[PRIMARY].name ? symset[PRIMARY].name : "default");
5180         if (currentgraphics == PRIMARY && symset[PRIMARY].name)
5181             Strcat(buf, ", active");
5182     } else if (!strcmp(optname, "tile_file")) {
5183         Sprintf(buf, "%s",
5184                 iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
5185     } else if (!strcmp(optname, "tile_height")) {
5186         if (iflags.wc_tile_height)
5187             Sprintf(buf, "%d", iflags.wc_tile_height);
5188         else
5189             Strcpy(buf, defopt);
5190     } else if (!strcmp(optname, "tile_width")) {
5191         if (iflags.wc_tile_width)
5192             Sprintf(buf, "%d", iflags.wc_tile_width);
5193         else
5194             Strcpy(buf, defopt);
5195     } else if (!strcmp(optname, "traps")) {
5196         Sprintf(buf, "%s", to_be_done);
5197     } else if (!strcmp(optname, "vary_msgcount")) {
5198         if (iflags.wc_vary_msgcount)
5199             Sprintf(buf, "%d", iflags.wc_vary_msgcount);
5200         else
5201             Strcpy(buf, defopt);
5202 #ifdef MSDOS
5203     } else if (!strcmp(optname, "video")) {
5204         Sprintf(buf, "%s", to_be_done);
5205 #endif
5206 #ifdef VIDEOSHADES
5207     } else if (!strcmp(optname, "videoshades")) {
5208         Sprintf(buf, "%s-%s-%s", shade[0], shade[1], shade[2]);
5209     } else if (!strcmp(optname, "videocolors")) {
5210         Sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
5211                 ttycolors[CLR_RED], ttycolors[CLR_GREEN],
5212                 ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
5213                 ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN],
5214                 ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
5215                 ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
5216                 ttycolors[CLR_BRIGHT_MAGENTA], ttycolors[CLR_BRIGHT_CYAN]);
5217 #endif /* VIDEOSHADES */
5218     } else if (!strcmp(optname, "windowtype")) {
5219         Sprintf(buf, "%s", windowprocs.name);
5220     } else if (!strcmp(optname, "windowcolors")) {
5221         Sprintf(
5222             buf, "%s/%s %s/%s %s/%s %s/%s",
5223             iflags.wc_foregrnd_menu ? iflags.wc_foregrnd_menu : defbrief,
5224             iflags.wc_backgrnd_menu ? iflags.wc_backgrnd_menu : defbrief,
5225             iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message
5226                                        : defbrief,
5227             iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message
5228                                        : defbrief,
5229             iflags.wc_foregrnd_status ? iflags.wc_foregrnd_status : defbrief,
5230             iflags.wc_backgrnd_status ? iflags.wc_backgrnd_status : defbrief,
5231             iflags.wc_foregrnd_text ? iflags.wc_foregrnd_text : defbrief,
5232             iflags.wc_backgrnd_text ? iflags.wc_backgrnd_text : defbrief);
5233 #ifdef PREFIXES_IN_USE
5234     } else {
5235         for (i = 0; i < PREFIX_COUNT; ++i)
5236             if (!strcmp(optname, fqn_prefix_names[i]) && fqn_prefix[i])
5237                 Sprintf(buf, "%s", fqn_prefix[i]);
5238 #endif
5239     }
5240
5241     if (buf[0])
5242         return buf;
5243     else
5244 /*JP
5245         return "unknown";
5246 */
5247         return "\95s\96¾";
5248 }
5249
5250 int
5251 dotogglepickup()
5252 {
5253     char buf[BUFSZ], ocl[MAXOCLASSES + 1];
5254
5255     flags.pickup = !flags.pickup;
5256     if (flags.pickup) {
5257         oc_to_str(flags.pickup_types, ocl);
5258 #if 0 /*JP*/
5259         Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all",
5260                 (iflags.autopickup_exceptions[AP_LEAVE]
5261                  || iflags.autopickup_exceptions[AP_GRAB])
5262                     ? ((count_ape_maps((int *) 0, (int *) 0) == 1)
5263                            ? ", with one exception"
5264                            : ", with some exceptions")
5265                     : "");
5266 #else
5267         Sprintf(buf, "%s\83A\83C\83e\83\80\82É\82Â\82¢\82Ä\83I\83\93%s", ocl[0] ? ocl : "\91S\82Ä\82Ì",
5268                 (iflags.autopickup_exceptions[AP_LEAVE]
5269                  || iflags.autopickup_exceptions[AP_GRAB])
5270                     ? "\81C\97á\8aO\82 \82è"
5271                     : "");
5272 #endif
5273     } else {
5274 /*JP
5275         Strcpy(buf, "OFF");
5276 */
5277         Strcpy(buf, "\83I\83t");
5278     }
5279 /*JP
5280     pline("Autopickup: %s.", buf);
5281 */
5282     pline("\8e©\93®\8fE\82¢\81F%s\81D", buf);
5283     return 0;
5284 }
5285
5286 int
5287 add_autopickup_exception(mapping)
5288 const char *mapping;
5289 {
5290     struct autopickup_exception *ape, **apehead;
5291     char text[256], *text2;
5292     boolean grab = FALSE;
5293
5294     if (sscanf(mapping, "\"%255[^\"]\"", text) == 1) {
5295         text2 = &text[0];
5296         if (*text2 == '<') { /* force autopickup */
5297             grab = TRUE;
5298             ++text2;
5299         } else if (*text2 == '>') { /* default - Do not pickup */
5300             grab = FALSE;
5301             ++text2;
5302         }
5303         apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB]
5304                          : &iflags.autopickup_exceptions[AP_LEAVE];
5305         ape = (struct autopickup_exception *) alloc(
5306                                         sizeof (struct autopickup_exception));
5307         ape->regex = regex_init();
5308         if (!regex_compile(text2, ape->regex)) {
5309             raw_print("regex error in AUTOPICKUP_EXCEPTION");
5310             regex_free(ape->regex);
5311             free((genericptr_t) ape);
5312             return 0;
5313         }
5314         ape->pattern = (char *) alloc(strlen(text2) + 1);
5315         strcpy(ape->pattern, text2);
5316         ape->grab = grab;
5317         ape->next = *apehead;
5318         *apehead = ape;
5319     } else {
5320         raw_print("syntax error in AUTOPICKUP_EXCEPTION");
5321         return 0;
5322     }
5323     return 1;
5324 }
5325
5326 STATIC_OVL void
5327 remove_autopickup_exception(whichape)
5328 struct autopickup_exception *whichape;
5329 {
5330     struct autopickup_exception *ape, *prev = 0;
5331     int chain = whichape->grab ? AP_GRAB : AP_LEAVE;
5332
5333     for (ape = iflags.autopickup_exceptions[chain]; ape;) {
5334         if (ape == whichape) {
5335             struct autopickup_exception *freeape = ape;
5336
5337             ape = ape->next;
5338             if (prev)
5339                 prev->next = ape;
5340             else
5341                 iflags.autopickup_exceptions[chain] = ape;
5342             regex_free(freeape->regex);
5343             free((genericptr_t) freeape->pattern);
5344             free((genericptr_t) freeape);
5345         } else {
5346             prev = ape;
5347             ape = ape->next;
5348         }
5349     }
5350 }
5351
5352 STATIC_OVL int
5353 count_ape_maps(leave, grab)
5354 int *leave, *grab;
5355 {
5356     struct autopickup_exception *ape;
5357     int pass, totalapes, numapes[2] = { 0, 0 };
5358
5359     for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
5360         ape = iflags.autopickup_exceptions[pass];
5361         while (ape) {
5362             ape = ape->next;
5363             numapes[pass]++;
5364         }
5365     }
5366     totalapes = numapes[AP_LEAVE] + numapes[AP_GRAB];
5367     if (leave)
5368         *leave = numapes[AP_LEAVE];
5369     if (grab)
5370         *grab = numapes[AP_GRAB];
5371     return totalapes;
5372 }
5373
5374 void
5375 free_autopickup_exceptions()
5376 {
5377     struct autopickup_exception *ape;
5378     int pass;
5379
5380     for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
5381         while ((ape = iflags.autopickup_exceptions[pass]) != 0) {
5382             regex_free(ape->regex);
5383             free((genericptr_t) ape->pattern);
5384             iflags.autopickup_exceptions[pass] = ape->next;
5385             free((genericptr_t) ape);
5386         }
5387     }
5388 }
5389
5390 /* bundle some common usage into one easy-to-use routine */
5391 int
5392 load_symset(s, which_set)
5393 const char *s;
5394 int which_set;
5395 {
5396     clear_symsetentry(which_set, TRUE);
5397
5398     if (symset[which_set].name)
5399         free((genericptr_t) symset[which_set].name);
5400     symset[which_set].name = dupstr(s);
5401
5402     if (read_sym_file(which_set)) {
5403         switch_symbols(TRUE);
5404     } else {
5405         clear_symsetentry(which_set, TRUE);
5406         return 0;
5407     }
5408     return 1;
5409 }
5410
5411 void
5412 free_symsets()
5413 {
5414     clear_symsetentry(PRIMARY, TRUE);
5415     clear_symsetentry(ROGUESET, TRUE);
5416
5417     /* symset_list is cleaned up as soon as it's used, so we shouldn't
5418        have to anything about it here */
5419     /* assert( symset_list == NULL ); */
5420 }
5421
5422 /* Parse the value of a SYMBOLS line from a config file */
5423 void
5424 parsesymbols(opts)
5425 register char *opts;
5426 {
5427     int val;
5428     char *op, *symname, *strval;
5429     struct symparse *symp;
5430
5431     if ((op = index(opts, ',')) != 0) {
5432         *op++ = 0;
5433         parsesymbols(op);
5434     }
5435
5436     /* S_sample:string */
5437     symname = opts;
5438     strval = index(opts, ':');
5439     if (!strval)
5440         strval = index(opts, '=');
5441     if (!strval)
5442         return;
5443     *strval++ = '\0';
5444
5445     /* strip leading and trailing white space from symname and strval */
5446     mungspaces(symname);
5447     mungspaces(strval);
5448
5449     symp = match_sym(symname);
5450     if (!symp)
5451         return;
5452
5453     if (symp->range && symp->range != SYM_CONTROL) {
5454         val = sym_val(strval);
5455         update_l_symset(symp, val);
5456     }
5457 }
5458
5459 struct symparse *
5460 match_sym(buf)
5461 char *buf;
5462 {
5463     size_t len = strlen(buf);
5464     const char *p = index(buf, ':'), *q = index(buf, '=');
5465     struct symparse *sp = loadsyms;
5466
5467     if (!p || (q && q < p))
5468         p = q;
5469     if (p) {
5470         /* note: there will be at most one space before the '='
5471            because caller has condensed buf[] with mungspaces() */
5472         if (p > buf && p[-1] == ' ')
5473             p--;
5474         len = (int) (p - buf);
5475     }
5476     while (sp->range) {
5477         if ((len >= strlen(sp->name)) && !strncmpi(buf, sp->name, len))
5478             return sp;
5479         sp++;
5480     }
5481     return (struct symparse *) 0;
5482 }
5483
5484 int
5485 sym_val(strval)
5486 char *strval;
5487 {
5488     char buf[QBUFSZ];
5489     buf[0] = '\0';
5490     escapes(strval, buf);
5491     return (int) *buf;
5492 }
5493
5494 /* data for option_help() */
5495 static const char *opt_intro[] = {
5496 /*JP
5497     "", "                 NetHack Options Help:", "",
5498 */
5499     "", "               NetHack\83I\83v\83V\83\87\83\93\83w\83\8b\83v\81F", "",
5500 #define CONFIG_SLOT 3 /* fill in next value at run-time */
5501     (char *) 0,
5502 #if !defined(MICRO) && !defined(MAC)
5503 /*JP
5504     "or use `NETHACKOPTIONS=\"<options>\"' in your environment",
5505 */
5506     "\82Ü\82½\82Í\8aÂ\8b«\95Ï\90\94\82É`NETHACKOPTIONS=\"<options>\"'\82Æ\92è\8b`\82Å\82«\82Ü\82·",
5507 #endif
5508 /*JP
5509     "(<options> is a list of options separated by commas)",
5510 */
5511     "(<options>\82Í\83J\83\93\83}\82Å\8bæ\90Ø\82Á\82½\83I\83v\83V\83\87\83\93\82Å\82·)",
5512 #ifdef VMS
5513 /*JP
5514     "-- for example, $ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
5515 */
5516     "-- \97á\82¦\82Î\8e\9f\82Ì\82æ\82¤\82É\82µ\82Ü\82·\81F$ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
5517 #endif
5518 /*JP
5519     "or press \"O\" while playing and use the menu.", "",
5520 */
5521     "\82à\82µ\82­\82Í\83Q\81[\83\80\83v\83\8c\83C\92\86\82É\"O\"\83{\83^\83\93\82ð\89\9f\82·\82±\82Æ\82Å\90Ý\92è\89Â\94\\82Å\82·\81D",
5522 /*JP
5523  "Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
5524 */
5525  "\90^\8bU\92l\83I\83v\83V\83\87\83\93 (\94Û\92è\82Ì\92l\82ð\8ew\92è\82·\82é\8fê\8d\87\81C'!'\82à\82µ\82­\82Í\"no\"\82ð\90æ\93ª\82É\95t\89Á\82µ\82Ü\82·):",
5526     (char *) 0
5527 };
5528
5529 static const char *opt_epilog[] = {
5530     "",
5531 /*JP
5532     "Some of the options can be set only before the game is started; those",
5533 */
5534     "\83I\83v\83V\83\87\83\93\82É\82Í\83Q\81[\83\80\8aJ\8en\91O\82Ì\82Ý\82É\82µ\82©\90Ý\92è\82Å\82«\82È\82¢\82à\82Ì\82ª\82 \82è\82Ü\82·\81D",
5535 /*JP
5536     "items will not be selectable in the 'O' command's menu.", (char *) 0
5537 */
5538     "\82»\82ê\82ç\82Í'O'\83R\83}\83\93\83h\82Ì\83\81\83j\83\85\81[\82Å\82Í\91I\91ð\82·\82é\82±\82Æ\82ª\82Å\82«\82Ü\82¹\82ñ\81D", (char *) 0
5539 };
5540
5541 void
5542 option_help()
5543 {
5544     char buf[BUFSZ], buf2[BUFSZ];
5545     register int i;
5546     winid datawin;
5547
5548     datawin = create_nhwindow(NHW_TEXT);
5549 /*JP
5550     Sprintf(buf, "Set options as OPTIONS=<options> in %s", lastconfigfile);
5551 */
5552     Sprintf(buf, "\83I\83v\83V\83\87\83\93\82Í%s\82Ì\92\86\82ÅOPTIONS=<options>\82Æ\90Ý\92è\82µ\82Ü\82·", lastconfigfile);
5553     opt_intro[CONFIG_SLOT] = (const char *) buf;
5554     for (i = 0; opt_intro[i]; i++)
5555         putstr(datawin, 0, opt_intro[i]);
5556
5557     /* Boolean options */
5558     for (i = 0; boolopt[i].name; i++) {
5559         if (boolopt[i].addr) {
5560             if (boolopt[i].addr == &iflags.sanity_check && !wizard)
5561                 continue;
5562             if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard)
5563                 continue;
5564             next_opt(datawin, boolopt[i].name);
5565         }
5566     }
5567     next_opt(datawin, "");
5568
5569     /* Compound options */
5570 /*JP
5571     putstr(datawin, 0, "Compound options:");
5572 */
5573     putstr(datawin, 0, "\95\8e\9a\97ñ\83I\83v\83V\83\87\83\93:");
5574     for (i = 0; compopt[i].name; i++) {
5575         Sprintf(buf2, "`%s'", compopt[i].name);
5576         Sprintf(buf, "%-20s - %s%c", buf2, compopt[i].descr,
5577                 compopt[i + 1].name ? ',' : '.');
5578         putstr(datawin, 0, buf);
5579     }
5580
5581     for (i = 0; opt_epilog[i]; i++)
5582         putstr(datawin, 0, opt_epilog[i]);
5583
5584     display_nhwindow(datawin, FALSE);
5585     destroy_nhwindow(datawin);
5586     return;
5587 }
5588
5589 /*
5590  * prints the next boolean option, on the same line if possible, on a new
5591  * line if not. End with next_opt("").
5592  */
5593 void
5594 next_opt(datawin, str)
5595 winid datawin;
5596 const char *str;
5597 {
5598     static char *buf = 0;
5599     int i;
5600     char *s;
5601
5602     if (!buf)
5603         *(buf = (char *) alloc(BUFSZ)) = '\0';
5604
5605     if (!*str) {
5606         s = eos(buf);
5607         if (s > &buf[1] && s[-2] == ',')
5608             Strcpy(s - 2, "."); /* replace last ", " */
5609         i = COLNO;              /* (greater than COLNO - 2) */
5610     } else {
5611         i = strlen(buf) + strlen(str) + 2;
5612     }
5613
5614     if (i > COLNO - 2) { /* rule of thumb */
5615         putstr(datawin, 0, buf);
5616         buf[0] = 0;
5617     }
5618     if (*str) {
5619         Strcat(buf, str);
5620         Strcat(buf, ", ");
5621     } else {
5622         putstr(datawin, 0, str);
5623         free((genericptr_t) buf), buf = 0;
5624     }
5625     return;
5626 }
5627
5628 /* Returns the fid of the fruit type; if that type already exists, it
5629  * returns the fid of that one; if it does not exist, it adds a new fruit
5630  * type to the chain and returns the new one.
5631  * If replace_fruit is sent in, replace the fruit in the chain rather than
5632  * adding a new entry--for user specified fruits only.
5633  */
5634 int
5635 fruitadd(str, replace_fruit)
5636 char *str;
5637 struct fruit *replace_fruit;
5638 {
5639     register int i;
5640     register struct fruit *f;
5641     int highest_fruit_id = 0;
5642     char buf[PL_FSIZ], altname[PL_FSIZ];
5643     boolean user_specified = (str == pl_fruit);
5644     /* if not user-specified, then it's a fruit name for a fruit on
5645      * a bones level...
5646      */
5647
5648     /* Note: every fruit has an id (kept in obj->spe) of at least 1;
5649      * 0 is an error.
5650      */
5651     if (user_specified) {
5652         boolean found = FALSE, numeric = FALSE;
5653
5654         /* force fruit to be singular; this handling is not
5655            needed--or wanted--for fruits from bones because
5656            they already received it in their original game */
5657         nmcpy(pl_fruit, makesingular(str), PL_FSIZ);
5658         /* assert( str == pl_fruit ); */
5659
5660         /* disallow naming after other foods (since it'd be impossible
5661          * to tell the difference)
5662          */
5663
5664         for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS; i++) {
5665             if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
5666                 found = TRUE;
5667                 break;
5668             }
5669         }
5670         {
5671             char *c;
5672
5673             c = pl_fruit;
5674
5675             for (c = pl_fruit; *c >= '0' && *c <= '9'; c++)
5676                 ;
5677             if (isspace((uchar) *c) || *c == 0)
5678                 numeric = TRUE;
5679         }
5680         if (found || numeric || !strncmp(str, "cursed ", 7)
5681             || !strncmp(str, "uncursed ", 9) || !strncmp(str, "blessed ", 8)
5682             || !strncmp(str, "partly eaten ", 13)
5683             || (!strncmp(str, "tin of ", 7)
5684                 && (!strcmp(str + 7, "spinach")
5685                     || name_to_mon(str + 7) >= LOW_PM))
5686             || !strcmp(str, "empty tin")
5687             || ((str_end_is(str, " corpse")
5688                  || str_end_is(str, " egg"))
5689                 && name_to_mon(str) >= LOW_PM)) {
5690             Strcpy(buf, pl_fruit);
5691             Strcpy(pl_fruit, "candied ");
5692             nmcpy(pl_fruit + 8, buf, PL_FSIZ - 8);
5693         }
5694         *altname = '\0';
5695         /* This flag indicates that a fruit has been made since the
5696          * last time the user set the fruit.  If it hasn't, we can
5697          * safely overwrite the current fruit, preventing the user from
5698          * setting many fruits in a row and overflowing.
5699          * Possible expansion: check for specific fruit IDs, not for
5700          * any fruit.
5701          */
5702         flags.made_fruit = FALSE;
5703         if (replace_fruit) {
5704             for (f = ffruit; f; f = f->nextf) {
5705                 if (f == replace_fruit) {
5706                     copynchars(f->fname, str, PL_FSIZ - 1);
5707                     goto nonew;
5708                 }
5709             }
5710         }
5711     } else {
5712         /* not user_supplied, so assumed to be from bones */
5713         copynchars(altname, str, PL_FSIZ - 1);
5714         sanitize_name(altname);
5715         flags.made_fruit = TRUE; /* for safety.  Any fruit name added from a
5716                                     bones level should exist anyway. */
5717     }
5718     for (f = ffruit; f; f = f->nextf) {
5719         if (f->fid > highest_fruit_id)
5720             highest_fruit_id = f->fid;
5721         if (!strncmp(str, f->fname, PL_FSIZ - 1)
5722             || (*altname && !strcmp(altname, f->fname)))
5723             goto nonew;
5724     }
5725     /* if adding another fruit would overflow spe, use a random
5726        fruit instead... we've got a lot to choose from.
5727        current_fruit remains as is. */
5728     if (highest_fruit_id >= 127)
5729         return rnd(127);
5730
5731     f = newfruit();
5732     copynchars(f->fname, *altname ? altname : str, PL_FSIZ - 1);
5733     f->fid = ++highest_fruit_id;
5734     /* we used to go out of our way to add it at the end of the list,
5735        but the order is arbitrary so use simpler insertion at start */
5736     f->nextf = ffruit;
5737     ffruit = f;
5738 nonew:
5739     if (user_specified)
5740         context.current_fruit = f->fid;
5741     return f->fid;
5742 }
5743
5744 /*
5745  * This is a somewhat generic menu for taking a list of NetHack style
5746  * class choices and presenting them via a description
5747  * rather than the traditional NetHack characters.
5748  * (Benefits users whose first exposure to NetHack is via tiles).
5749  *
5750  * prompt
5751  *           The title at the top of the menu.
5752  *
5753  * category: 0 = monster class
5754  *           1 = object  class
5755  *
5756  * way
5757  *           FALSE = PICK_ONE, TRUE = PICK_ANY
5758  *
5759  * class_list
5760  *           a null terminated string containing the list of choices.
5761  *
5762  * class_selection
5763  *           a null terminated string containing the selected characters.
5764  *
5765  * Returns number selected.
5766  */
5767 int
5768 choose_classes_menu(prompt, category, way, class_list, class_select)
5769 const char *prompt;
5770 int category;
5771 boolean way;
5772 char *class_list;
5773 char *class_select;
5774 {
5775     menu_item *pick_list = (menu_item *) 0;
5776     winid win;
5777     anything any;
5778     char buf[BUFSZ];
5779     int i, n;
5780     int ret;
5781     int next_accelerator, accelerator;
5782
5783     if (class_list == (char *) 0 || class_select == (char *) 0)
5784         return 0;
5785     accelerator = 0;
5786     next_accelerator = 'a';
5787     any = zeroany;
5788     win = create_nhwindow(NHW_MENU);
5789     start_menu(win);
5790     while (*class_list) {
5791         const char *text;
5792         boolean selected;
5793
5794         text = (char *) 0;
5795         selected = FALSE;
5796         switch (category) {
5797         case 0:
5798             text = def_monsyms[def_char_to_monclass(*class_list)].explain;
5799             accelerator = *class_list;
5800             Sprintf(buf, "%s", text);
5801             break;
5802         case 1:
5803             text = def_oc_syms[def_char_to_objclass(*class_list)].explain;
5804             accelerator = next_accelerator;
5805             Sprintf(buf, "%c  %s", *class_list, text);
5806             break;
5807         default:
5808             impossible("choose_classes_menu: invalid category %d", category);
5809         }
5810         if (way && *class_select) { /* Selections there already */
5811             if (index(class_select, *class_list)) {
5812                 selected = TRUE;
5813             }
5814         }
5815         any.a_int = *class_list;
5816         add_menu(win, NO_GLYPH, &any, accelerator, category ? *class_list : 0,
5817                  ATR_NONE, buf, selected);
5818         ++class_list;
5819         if (category > 0) {
5820             ++next_accelerator;
5821             if (next_accelerator == ('z' + 1))
5822                 next_accelerator = 'A';
5823             if (next_accelerator == ('Z' + 1))
5824                 break;
5825         }
5826     }
5827     end_menu(win, prompt);
5828     n = select_menu(win, way ? PICK_ANY : PICK_ONE, &pick_list);
5829     destroy_nhwindow(win);
5830     if (n > 0) {
5831         for (i = 0; i < n; ++i)
5832             *class_select++ = (char) pick_list[i].item.a_int;
5833         free((genericptr_t) pick_list);
5834         ret = n;
5835     } else if (n == -1) {
5836         class_select = eos(class_select);
5837         ret = -1;
5838     } else
5839         ret = 0;
5840     *class_select = '\0';
5841     return ret;
5842 }
5843
5844 struct wc_Opt wc_options[] = { { "ascii_map", WC_ASCII_MAP },
5845                                { "color", WC_COLOR },
5846                                { "eight_bit_tty", WC_EIGHT_BIT_IN },
5847                                { "hilite_pet", WC_HILITE_PET },
5848                                { "popup_dialog", WC_POPUP_DIALOG },
5849                                { "player_selection", WC_PLAYER_SELECTION },
5850                                { "preload_tiles", WC_PRELOAD_TILES },
5851                                { "tiled_map", WC_TILED_MAP },
5852                                { "tile_file", WC_TILE_FILE },
5853                                { "tile_width", WC_TILE_WIDTH },
5854                                { "tile_height", WC_TILE_HEIGHT },
5855                                { "use_inverse", WC_INVERSE },
5856                                { "align_message", WC_ALIGN_MESSAGE },
5857                                { "align_status", WC_ALIGN_STATUS },
5858                                { "font_map", WC_FONT_MAP },
5859                                { "font_menu", WC_FONT_MENU },
5860                                { "font_message", WC_FONT_MESSAGE },
5861 #if 0
5862                                {"perm_invent", WC_PERM_INVENT},
5863 #endif
5864                                { "font_size_map", WC_FONTSIZ_MAP },
5865                                { "font_size_menu", WC_FONTSIZ_MENU },
5866                                { "font_size_message", WC_FONTSIZ_MESSAGE },
5867                                { "font_size_status", WC_FONTSIZ_STATUS },
5868                                { "font_size_text", WC_FONTSIZ_TEXT },
5869                                { "font_status", WC_FONT_STATUS },
5870                                { "font_text", WC_FONT_TEXT },
5871                                { "map_mode", WC_MAP_MODE },
5872                                { "scroll_amount", WC_SCROLL_AMOUNT },
5873                                { "scroll_margin", WC_SCROLL_MARGIN },
5874                                { "splash_screen", WC_SPLASH_SCREEN },
5875                                { "vary_msgcount", WC_VARY_MSGCOUNT },
5876                                { "windowcolors", WC_WINDOWCOLORS },
5877                                { "mouse_support", WC_MOUSE_SUPPORT },
5878                                { (char *) 0, 0L } };
5879
5880 struct wc_Opt wc2_options[] = { { "fullscreen", WC2_FULLSCREEN },
5881                                 { "softkeyboard", WC2_SOFTKEYBOARD },
5882                                 { "wraptext", WC2_WRAPTEXT },
5883                                 { "use_darkgray", WC2_DARKGRAY },
5884 #ifdef STATUS_VIA_WINDOWPORT
5885                                 { "hilite_status", WC2_HILITE_STATUS },
5886 #endif
5887                                 { (char *) 0, 0L } };
5888
5889 /*
5890  * If a port wants to change or ensure that the SET_IN_SYS,
5891  * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is
5892  * correct (for controlling its display in the option menu) call
5893  * set_option_mod_status()
5894  * with the appropriate second argument.
5895  */
5896 void
5897 set_option_mod_status(optnam, status)
5898 const char *optnam;
5899 int status;
5900 {
5901     int k;
5902
5903     if (SET__IS_VALUE_VALID(status)) {
5904         impossible("set_option_mod_status: status out of range %d.", status);
5905         return;
5906     }
5907     for (k = 0; boolopt[k].name; k++) {
5908         if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) {
5909             boolopt[k].optflags = status;
5910             return;
5911         }
5912     }
5913     for (k = 0; compopt[k].name; k++) {
5914         if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) {
5915             compopt[k].optflags = status;
5916             return;
5917         }
5918     }
5919 }
5920
5921 /*
5922  * You can set several wc_options in one call to
5923  * set_wc_option_mod_status() by setting
5924  * the appropriate bits for each option that you
5925  * are setting in the optmask argument
5926  * prior to calling.
5927  *    example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN,
5928  * SET_IN_GAME);
5929  */
5930 void
5931 set_wc_option_mod_status(optmask, status)
5932 unsigned long optmask;
5933 int status;
5934 {
5935     int k = 0;
5936
5937     if (SET__IS_VALUE_VALID(status)) {
5938         impossible("set_wc_option_mod_status: status out of range %d.",
5939                    status);
5940         return;
5941     }
5942     while (wc_options[k].wc_name) {
5943         if (optmask & wc_options[k].wc_bit) {
5944             set_option_mod_status(wc_options[k].wc_name, status);
5945         }
5946         k++;
5947     }
5948 }
5949
5950 STATIC_OVL boolean
5951 is_wc_option(optnam)
5952 const char *optnam;
5953 {
5954     int k = 0;
5955
5956     while (wc_options[k].wc_name) {
5957         if (strcmp(wc_options[k].wc_name, optnam) == 0)
5958             return TRUE;
5959         k++;
5960     }
5961     return FALSE;
5962 }
5963
5964 STATIC_OVL boolean
5965 wc_supported(optnam)
5966 const char *optnam;
5967 {
5968     int k = 0;
5969
5970     while (wc_options[k].wc_name) {
5971         if (!strcmp(wc_options[k].wc_name, optnam)
5972             && (windowprocs.wincap & wc_options[k].wc_bit))
5973             return TRUE;
5974         k++;
5975     }
5976     return FALSE;
5977 }
5978
5979 /*
5980  * You can set several wc2_options in one call to
5981  * set_wc2_option_mod_status() by setting
5982  * the appropriate bits for each option that you
5983  * are setting in the optmask argument
5984  * prior to calling.
5985  *    example:
5986  * set_wc2_option_mod_status(WC2_FULLSCREEN|WC2_SOFTKEYBOARD|WC2_WRAPTEXT,
5987  * SET_IN_FILE);
5988  */
5989
5990 void
5991 set_wc2_option_mod_status(optmask, status)
5992 unsigned long optmask;
5993 int status;
5994 {
5995     int k = 0;
5996
5997     if (SET__IS_VALUE_VALID(status)) {
5998         impossible("set_wc2_option_mod_status: status out of range %d.",
5999                    status);
6000         return;
6001     }
6002     while (wc2_options[k].wc_name) {
6003         if (optmask & wc2_options[k].wc_bit) {
6004             set_option_mod_status(wc2_options[k].wc_name, status);
6005         }
6006         k++;
6007     }
6008 }
6009
6010 STATIC_OVL boolean
6011 is_wc2_option(optnam)
6012 const char *optnam;
6013 {
6014     int k = 0;
6015
6016     while (wc2_options[k].wc_name) {
6017         if (strcmp(wc2_options[k].wc_name, optnam) == 0)
6018             return TRUE;
6019         k++;
6020     }
6021     return FALSE;
6022 }
6023
6024 STATIC_OVL boolean
6025 wc2_supported(optnam)
6026 const char *optnam;
6027 {
6028     int k = 0;
6029
6030     while (wc2_options[k].wc_name) {
6031         if (!strcmp(wc2_options[k].wc_name, optnam)
6032             && (windowprocs.wincap2 & wc2_options[k].wc_bit))
6033             return TRUE;
6034         k++;
6035     }
6036     return FALSE;
6037 }
6038
6039 STATIC_OVL void
6040 wc_set_font_name(opttype, fontname)
6041 int opttype;
6042 char *fontname;
6043 {
6044     char **fn = (char **) 0;
6045
6046     if (!fontname)
6047         return;
6048     switch (opttype) {
6049     case MAP_OPTION:
6050         fn = &iflags.wc_font_map;
6051         break;
6052     case MESSAGE_OPTION:
6053         fn = &iflags.wc_font_message;
6054         break;
6055     case TEXT_OPTION:
6056         fn = &iflags.wc_font_text;
6057         break;
6058     case MENU_OPTION:
6059         fn = &iflags.wc_font_menu;
6060         break;
6061     case STATUS_OPTION:
6062         fn = &iflags.wc_font_status;
6063         break;
6064     default:
6065         return;
6066     }
6067     if (fn) {
6068         if (*fn)
6069             free((genericptr_t) *fn);
6070         *fn = dupstr(fontname);
6071     }
6072     return;
6073 }
6074
6075 STATIC_OVL int
6076 wc_set_window_colors(op)
6077 char *op;
6078 {
6079     /* syntax:
6080      *  menu white/black message green/yellow status white/blue text
6081      * white/black
6082      */
6083     int j;
6084     char buf[BUFSZ];
6085     char *wn, *tfg, *tbg, *newop;
6086     static const char *wnames[] = { "menu", "message", "status", "text" };
6087     static const char *shortnames[] = { "mnu", "msg", "sts", "txt" };
6088     static char **fgp[] = { &iflags.wc_foregrnd_menu,
6089                             &iflags.wc_foregrnd_message,
6090                             &iflags.wc_foregrnd_status,
6091                             &iflags.wc_foregrnd_text };
6092     static char **bgp[] = { &iflags.wc_backgrnd_menu,
6093                             &iflags.wc_backgrnd_message,
6094                             &iflags.wc_backgrnd_status,
6095                             &iflags.wc_backgrnd_text };
6096
6097     Strcpy(buf, op);
6098     newop = mungspaces(buf);
6099     while (newop && *newop) {
6100         wn = tfg = tbg = (char *) 0;
6101
6102         /* until first non-space in case there's leading spaces - before
6103          * colorname*/
6104         if (*newop == ' ')
6105             newop++;
6106         if (*newop)
6107             wn = newop;
6108         else
6109             return 0;
6110
6111         /* until first space - colorname*/
6112         while (*newop && *newop != ' ')
6113             newop++;
6114         if (*newop)
6115             *newop = '\0';
6116         else
6117             return 0;
6118         newop++;
6119
6120         /* until first non-space - before foreground*/
6121         if (*newop == ' ')
6122             newop++;
6123         if (*newop)
6124             tfg = newop;
6125         else
6126             return 0;
6127
6128         /* until slash - foreground */
6129         while (*newop && *newop != '/')
6130             newop++;
6131         if (*newop)
6132             *newop = '\0';
6133         else
6134             return 0;
6135         newop++;
6136
6137         /* until first non-space (in case there's leading space after slash) -
6138          * before background */
6139         if (*newop == ' ')
6140             newop++;
6141         if (*newop)
6142             tbg = newop;
6143         else
6144             return 0;
6145
6146         /* until first space - background */
6147         while (*newop && *newop != ' ')
6148             newop++;
6149         if (*newop)
6150             *newop++ = '\0';
6151
6152         for (j = 0; j < 4; ++j) {
6153             if (!strcmpi(wn, wnames[j]) || !strcmpi(wn, shortnames[j])) {
6154                 if (tfg && !strstri(tfg, " ")) {
6155                     if (*fgp[j])
6156                         free((genericptr_t) *fgp[j]);
6157                     *fgp[j] = dupstr(tfg);
6158                 }
6159                 if (tbg && !strstri(tbg, " ")) {
6160                     if (*bgp[j])
6161                         free((genericptr_t) *bgp[j]);
6162                     *bgp[j] = dupstr(tbg);
6163                 }
6164                 break;
6165             }
6166         }
6167     }
6168     return 1;
6169 }
6170
6171 /* set up for wizard mode if player or save file has requested to it;
6172    called from port-specific startup code to handle `nethack -D' or
6173    OPTIONS=playmode:debug, or from dorecover()'s restgamestate() if
6174    restoring a game which was saved in wizard mode */
6175 void
6176 set_playmode()
6177 {
6178     if (wizard) {
6179         if (authorize_wizard_mode())
6180             Strcpy(plname, "wizard");
6181         else
6182             wizard = FALSE; /* not allowed or not available */
6183         /* force explore mode if we didn't make it into wizard mode */
6184         discover = !wizard;
6185         iflags.deferred_X = FALSE;
6186     }
6187     /* don't need to do anything special for explore mode or normal play */
6188 }
6189
6190 #endif /* OPTION_LISTS_ONLY */
6191
6192 /*options.c*/