1 /* NetHack 3.6 options.c $NHDT-Date: 1578996303 2020/01/14 10:05:03 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.396 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Michael Allison, 2008. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2022 */
9 /* JNetHack may be freely redistributed. See license for details. */
11 #ifdef OPTION_LISTS_ONLY /* (AMIGA) external program for opt lists */
15 NEARDATA struct flag flags; /* provide linkage */
17 NEARDATA struct sysflag sysflags; /* provide linkage */
19 NEARDATA struct instance_flags iflags; /* provide linkage */
27 #define BACKWARD_COMPAT
29 #ifdef DEFAULT_WC_TILED_MAP
30 #define PREFER_TILED TRUE
32 #define PREFER_TILED FALSE
35 #ifdef CURSES_GRAPHICS
36 extern int curses_read_attrs(const char *attrs);
37 extern char *curses_fmt_attrs(char *);
40 enum window_option_types {
48 #define PILE_LIMIT_DFLT 5
50 static char empty_optstr[] = { '\0' };
53 * NOTE: If you add (or delete) an option, please update the short
54 * options help (option_help()), the long options help (dat/opthelp),
55 * and the current options setting display function (doset()),
56 * and also the Guidebooks.
58 * The order matters. If an option is a an initial substring of another
59 * option (e.g. time and timed_delay) the shorter one must come first.
62 static struct Bool_Opt {
64 boolean *addr, initvalue;
67 { "acoustics", &flags.acoustics, TRUE, SET_IN_GAME },
68 #if defined(SYSFLAGS) && defined(AMIGA)
69 /* Amiga altmeta causes Alt+key to be converted into Meta+key by
70 low level nethack code; on by default, can be toggled off if
71 Alt+key is needed for some ASCII chars on non-ASCII keyboard */
72 { "altmeta", &sysflags.altmeta, TRUE, DISP_IN_GAME },
75 /* non-Amiga altmeta causes nethack's top level command loop to treat
76 two character sequence "ESC c" as M-c, for terminals or emulators
77 which send "ESC c" when Alt+c is pressed; off by default, enabling
78 this can potentially make trouble if user types ESC when nethack
79 is honoring this conversion request (primarily after starting a
80 count prefix prior to a command and then deciding to cancel it) */
81 { "altmeta", &iflags.altmeta, FALSE, SET_IN_GAME },
83 { "altmeta", (boolean *) 0, TRUE, DISP_IN_GAME },
86 { "ascii_map", &iflags.wc_ascii_map, !PREFER_TILED, SET_IN_GAME }, /*WC*/
87 #if defined(SYSFLAGS) && defined(MFLOPPY)
88 { "asksavedisk", &sysflags.asksavedisk, FALSE, SET_IN_GAME },
90 { "asksavedisk", (boolean *) 0, FALSE, SET_IN_FILE },
92 { "autodescribe", &iflags.autodescribe, TRUE, SET_IN_GAME },
93 { "autodig", &flags.autodig, FALSE, SET_IN_GAME },
94 { "autoopen", &flags.autoopen, TRUE, SET_IN_GAME },
95 { "autopickup", &flags.pickup, TRUE, SET_IN_GAME },
96 { "autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME },
97 #if defined(MICRO) && !defined(AMIGA)
98 { "BIOS", &iflags.BIOS, FALSE, SET_IN_FILE },
100 { "BIOS", (boolean *) 0, FALSE, SET_IN_FILE },
102 { "blind", &u.uroleplay.blind, FALSE, DISP_IN_GAME },
103 { "bones", &flags.bones, TRUE, SET_IN_FILE },
105 { "checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME },
107 { "checkpoint", (boolean *) 0, FALSE, SET_IN_FILE },
110 { "checkspace", &iflags.checkspace, TRUE, SET_IN_GAME },
112 { "checkspace", (boolean *) 0, FALSE, SET_IN_FILE },
114 { "clicklook", &iflags.clicklook, FALSE, SET_IN_GAME },
115 { "cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME },
116 #if defined(MICRO) || defined(WIN32) || defined(CURSES_GRAPHICS)
117 { "color", &iflags.wc_color, TRUE, SET_IN_GAME }, /* on/off: use WC or not */
118 #else /* systems that support multiple terminals, many monochrome */
119 { "color", &iflags.wc_color, FALSE, SET_IN_GAME },
121 { "confirm", &flags.confirm, TRUE, SET_IN_GAME },
122 { "dark_room", &flags.dark_room, TRUE, SET_IN_GAME },
123 { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME }, /*WC*/
124 #if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS) || defined(X11_GRAPHICS)
125 { "extmenu", &iflags.extmenu, FALSE, SET_IN_GAME },
127 { "extmenu", (boolean *) 0, FALSE, SET_IN_FILE },
130 { "fast_map", &flags.fast_map, TRUE, SET_IN_GAME },
132 { "fast_map", (boolean *) 0, TRUE, SET_IN_FILE },
134 { "female", &flags.female, FALSE, DISP_IN_GAME },
135 { "fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME },
136 #if defined(SYSFLAGS) && defined(AMIFLUSH)
137 { "flush", &sysflags.amiflush, FALSE, SET_IN_GAME },
139 { "flush", (boolean *) 0, FALSE, SET_IN_FILE },
141 { "force_invmenu", &iflags.force_invmenu, FALSE, SET_IN_GAME },
142 { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE }, /*WC2*/
143 { "goldX", &iflags.goldX, FALSE, SET_IN_GAME },
144 { "guicolor", &iflags.wc2_guicolor, TRUE, SET_IN_GAME}, /*WC2*/
145 { "help", &flags.help, TRUE, SET_IN_GAME },
146 { "herecmd_menu", &iflags.herecmd_menu, FALSE, SET_IN_GAME },
147 { "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
148 { "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
149 { "hitpointbar", &iflags.wc2_hitpointbar, FALSE, SET_IN_GAME }, /*WC2*/
151 { "ignintr", &flags.ignintr, FALSE, SET_IN_GAME },
153 { "ignintr", (boolean *) 0, FALSE, SET_IN_FILE },
155 { "implicit_uncursed", &iflags.implicit_uncursed, TRUE, SET_IN_GAME },
156 { "large_font", &iflags.obsolete, FALSE, SET_IN_FILE }, /* OBSOLETE */
157 { "legacy", &flags.legacy, TRUE, DISP_IN_GAME },
158 { "lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME },
159 { "lootabc", &flags.lootabc, FALSE, SET_IN_GAME },
161 { "mail", &flags.biff, TRUE, SET_IN_GAME },
163 { "mail", (boolean *) 0, TRUE, SET_IN_FILE },
165 { "mention_walls", &iflags.mention_walls, FALSE, SET_IN_GAME },
166 { "menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME },
167 /* for menu debugging only*/
168 { "menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_WIZGAME },
169 { "menu_objsyms", &iflags.menu_head_objsym, FALSE, SET_IN_GAME },
171 { "menu_overlay", &iflags.menu_overlay, TRUE, SET_IN_GAME },
173 { "menu_overlay", (boolean *) 0, FALSE, SET_IN_FILE },
175 { "monpolycontrol", &iflags.mon_polycontrol, FALSE, SET_IN_WIZGAME },
177 { "news", &iflags.news, TRUE, DISP_IN_GAME },
179 { "news", (boolean *) 0, FALSE, SET_IN_FILE },
181 { "nudist", &u.uroleplay.nudist, FALSE, DISP_IN_GAME },
182 { "null", &flags.null, TRUE, SET_IN_GAME },
183 #if defined(SYSFLAGS) && defined(MAC)
184 { "page_wait", &sysflags.page_wait, TRUE, SET_IN_GAME },
186 { "page_wait", (boolean *) 0, FALSE, SET_IN_FILE },
188 /* moved perm_invent from flags to iflags and out of save file in 3.6.2 */
189 { "perm_invent", &iflags.perm_invent, FALSE, SET_IN_GAME },
190 { "pickup_thrown", &flags.pickup_thrown, TRUE, SET_IN_GAME },
191 { "popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME }, /*WC*/
192 { "preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME }, /*WC*/
193 { "pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME },
194 #if defined(MICRO) && !defined(AMIGA)
195 { "rawio", &iflags.rawio, FALSE, DISP_IN_GAME },
197 { "rawio", (boolean *) 0, FALSE, SET_IN_FILE },
199 { "rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME },
201 { "rlecomp", &iflags.rlecomp,
202 #if defined(COMPRESS) || defined(ZLIB_COMP)
209 { "safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME },
210 { "sanity_check", &iflags.sanity_check, FALSE, SET_IN_WIZGAME },
211 { "selectsaved", &iflags.wc2_selectsaved, TRUE, DISP_IN_GAME }, /*WC*/
212 { "showexp", &flags.showexp, FALSE, SET_IN_GAME },
213 { "showrace", &flags.showrace, FALSE, SET_IN_GAME },
215 { "showscore", &flags.showscore, FALSE, SET_IN_GAME },
217 { "showscore", (boolean *) 0, FALSE, SET_IN_FILE },
219 { "silent", &flags.silent, TRUE, SET_IN_GAME },
220 { "softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE }, /*WC2*/
221 { "sortpack", &flags.sortpack, TRUE, SET_IN_GAME },
222 { "sparkle", &flags.sparkle, TRUE, SET_IN_GAME },
223 { "splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME }, /*WC*/
224 { "standout", &flags.standout, FALSE, SET_IN_GAME },
225 { "status_updates", &iflags.status_updates, TRUE, DISP_IN_GAME },
226 { "tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME }, /*WC*/
227 { "time", &flags.time, FALSE, SET_IN_GAME },
229 { "timed_delay", &flags.nap, TRUE, SET_IN_GAME },
231 { "timed_delay", (boolean *) 0, FALSE, SET_IN_GAME },
233 { "tombstone", &flags.tombstone, TRUE, SET_IN_GAME },
234 { "toptenwin", &iflags.toptenwin, FALSE, SET_IN_GAME },
235 { "travel", &flags.travelcmd, TRUE, SET_IN_GAME },
237 { "travel_debug", &iflags.trav_debug, FALSE, SET_IN_WIZGAME }, /*hack.c*/
239 { "use_darkgray", &iflags.wc2_darkgray, TRUE, SET_IN_FILE }, /*WC2*/
241 { "use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME }, /*WC*/
243 { "use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME }, /*WC*/
245 { "verbose", &flags.verbose, TRUE, SET_IN_GAME },
246 #ifdef TTY_TILES_ESCCODES
247 { "vt_tiledata", &iflags.vt_tiledata, FALSE, SET_IN_FILE },
249 { "vt_tiledata", (boolean *) 0, FALSE, SET_IN_FILE },
251 { "whatis_menu", &iflags.getloc_usemenu, FALSE, SET_IN_GAME },
252 { "whatis_moveskip", &iflags.getloc_moveskip, FALSE, SET_IN_GAME },
253 { "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME },
254 { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME }, /*WC2*/
256 { "zerocomp", &iflags.zerocomp,
257 #if defined(COMPRESS) || defined(ZLIB_COMP)
264 { (char *) 0, (boolean *) 0, FALSE, 0 }
267 /* compound options, for option_help() and external programs like Amiga
269 static struct Comp_Opt {
270 const char *name, *descr;
271 int size; /* for frontends and such allocating space --
272 * usually allowed size of data in game, but
273 * occasionally maximum reasonable size for
274 * typing when game maintains information in
275 * a different format */
279 { "align", "your starting alignment (lawful, neutral, or chaotic)", 8,
281 { "align", "
\83Q
\81[
\83\80\83X
\83^
\81[
\83g
\8e\9e\82Ì
\91®
\90« (lawful, neutral, or chaotic
\82Ì
\82¢
\82¸
\82ê
\82©)", 8,
284 { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/
286 { "align_message", "
\83\81\83b
\83Z
\81[
\83W
\83E
\83B
\83\93\83h
\83E
\82Ì
\91µ
\82¦", 20, DISP_IN_GAME }, /*WC*/
289 { "align_status", "status window alignment", 20, DISP_IN_GAME }, /*WC*/
291 { "align_status", "
\8fó
\8bµ
\83E
\83B
\83\93\83h
\83E
\82Ì
\91µ
\82¦", 20, DISP_IN_GAME }, /*WC*/
294 { "altkeyhandler", "alternate key handler", 20, SET_IN_GAME },
296 { "altkeyhandler", "ALT
\83L
\81[
\83n
\83\93\83h
\83\89", 20, SET_IN_GAME },
297 #ifdef BACKWARD_COMPAT
299 { "boulder", "deprecated (use S_boulder in sym file instead)", 1,
301 { "boulder", "
\8b\90\8aâ
\82ð
\95\
\8e¦
\82·
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a", 1,
305 { "catname", "the name of your (first) cat (e.g., catname:Tabby)",
307 { "catname", "
\96`
\8c¯
\82ð
\8b\9f\82É
\82·
\82é(
\8dÅ
\8f\89\82Ì)
\94L
\82Ì
\96¼
\91O (
\97á catname:
\82½
\82Ü)",
308 PL_PSIZ, DISP_IN_GAME },
310 { "disclose", "the kinds of information to disclose at end of game",
312 { "disclose", "
\83Q
\81[
\83\80\8fI
\97¹
\8e\9e\82É
\8c©
\82é
\8fî
\95ñ
\82Ì
\8eí
\97Þ",
313 sizeof flags.end_disclose * 2, SET_IN_GAME },
315 { "dogname", "the name of your (first) dog (e.g., dogname:Fang)", PL_PSIZ,
317 { "dogname", "
\96`
\8c¯
\82ð
\8b\9f\82É
\82·
\82é(
\8dÅ
\8f\89\82Ì)
\8c¢
\82Ì
\96¼
\91O (
\97á dogname:
\83|
\83`)", PL_PSIZ,
320 { "dungeon", "the symbols to use in drawing the dungeon map",
322 { "dungeon", "
\83_
\83\93\83W
\83\87\83\93\82ð
\95`
\89æ
\82·
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a",
323 MAXDCHARS + 1, SET_IN_FILE },
325 { "effects", "the symbols to use in drawing special effects",
327 { "effects", "
\93Á
\8eê
\8cø
\89Ê
\82ð
\95`
\89æ
\82·
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a",
328 MAXECHARS + 1, SET_IN_FILE },
330 { "font_map", "the font to use in the map window", 40,
332 { "font_map", "
\83}
\83b
\83v
\83E
\83B
\83\93\83h
\83E
\82É
\8eg
\97p
\82·
\82é
\83t
\83H
\83\93\83g", 40,
333 DISP_IN_GAME }, /*WC*/
335 { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/
337 { "font_menu", "
\83\81\83j
\83\85\81[
\82É
\8eg
\97p
\82·
\82é
\83t
\83H
\83\93\83g", 40, DISP_IN_GAME }, /*WC*/
340 { "font_message", "the font to use in the message window", 40,
342 { "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,
343 DISP_IN_GAME }, /*WC*/
345 { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/
347 { "font_size_map", "
\83}
\83b
\83v
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20, DISP_IN_GAME }, /*WC*/
350 { "font_size_menu", "the size of the menu font", 20,
352 { "font_size_menu", "
\83\81\83j
\83\85\81[
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20,
353 DISP_IN_GAME }, /*WC*/
355 { "font_size_message", "the size of the message font", 20,
357 { "font_size_message", "
\83\81\83b
\83Z
\81[
\83W
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20,
358 DISP_IN_GAME }, /*WC*/
360 { "font_size_status", "the size of the status font", 20,
362 { "font_size_status", "
\8fó
\8bµ
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20,
363 DISP_IN_GAME }, /*WC*/
365 { "font_size_text", "the size of the text font", 20,
367 { "font_size_text", "
\83e
\83L
\83X
\83g
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20,
368 DISP_IN_GAME }, /*WC*/
370 { "font_status", "the font to use in status window", 40,
372 { "font_status", "
\8fó
\8bµ
\83E
\83B
\83\93\83h
\83E
\82É
\8eg
\97p
\82·
\82é
\83t
\83H
\83\93\83g", 40,
373 DISP_IN_GAME }, /*WC*/
375 { "font_text", "the font to use in text windows", 40,
377 { "font_text", "
\83e
\83L
\83X
\83g
\83E
\83B
\83\93\83h
\83E
\82É
\8eg
\97p
\82·
\82é
\83t
\83H
\83\93\83g", 40,
378 DISP_IN_GAME }, /*WC*/
380 { "fruit", "the name of a fruit you enjoy eating", PL_FSIZ, SET_IN_GAME },
382 { "fruit", "
\8dD
\95¨
\82Ì
\89Ê
\95¨
\82Ì
\96¼
\91O", PL_FSIZ, SET_IN_GAME },
384 { "gender", "your starting gender (male or female)", 8, DISP_IN_GAME },
386 { "gender", "
\83Q
\81[
\83\80\8aJ
\8en
\8e\9e\82Ì
\90«
\95Ê(male
\82Ü
\82½
\82Í female)", 8, DISP_IN_GAME },
388 { "horsename", "the name of your (first) horse (e.g., horsename:Silver)",
390 { "horsename", "
\96`
\8c¯
\82ð
\8b\9f\82É
\82·
\82é(
\8dÅ
\8f\89\82Ì)
\94n
\82Ì
\96¼
\91O (
\97á ghoulname:
\83V
\83\8b\83o
\81[)",
391 PL_PSIZ, DISP_IN_GAME },
393 { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/
395 { "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*/
398 { "menustyle", "user interface for object selection", MENUTYPELEN,
400 { "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,
403 { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE },
405 { "menu_deselect_all", "
\91S
\82Ä
\82Ì
\83A
\83C
\83e
\83\80\82ð
\94ñ
\91I
\91ð", 4, SET_IN_FILE },
407 { "menu_deselect_page", "deselect all items on this page of a menu", 4,
409 { "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,
412 { "menu_first_page", "jump to the first page in a menu", 4, SET_IN_FILE },
414 { "menu_first_page", "
\83\81\83j
\83\85\81[
\82Ì
\8dÅ
\8f\89\82Ì
\83y
\81[
\83W
\82Ö", 4, SET_IN_FILE },
416 { "menu_headings", "text attribute for menu headings", 9, SET_IN_GAME },
418 { "menu_headings", "
\8b
\92²
\81C
\94½
\93]
\82Ü
\82½
\82Í
\89º
\90ü
\82Å
\8eí
\97Þ
\82ð
\95\
\8e¦
\82·
\82é", 9, SET_IN_GAME },
420 { "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
422 { "menu_invert_all", "
\91S
\82Ä
\82Ì
\83A
\83C
\83e
\83\80\82ð
\94½
\93]", 4, SET_IN_FILE },
424 { "menu_invert_page", "invert all items on this page of a menu", 4,
426 { "menu_invert_page", "
\8c»
\8dÝ
\95\
\8e¦
\82³
\82ê
\82Ä
\82¢
\82é
\83y
\81[
\83W
\82Ì
\83A
\83C
\83e
\83\80\82ð
\94½
\93]",
429 { "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE },
431 { "menu_last_page", "
\83\81\83j
\83\85\81[
\82Ì
\8dÅ
\8cã
\82Ì
\83y
\81[
\83W
\82Ö", 4, SET_IN_FILE },
433 { "menu_next_page", "goto the next menu page", 4, SET_IN_FILE },
435 { "menu_next_page", "
\8e\9f\82Ì
\83\81\83j
\83\85\81[
\82Ì
\83y
\81[
\83W
\82Ö", 4, SET_IN_FILE },
437 { "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE },
439 { "menu_previous_page", "
\91O
\82Ì
\83\81\83j
\83\85\81[
\82Ì
\83y
\81[
\83W
\82Ö", 4, SET_IN_FILE },
441 { "menu_search", "search for a menu item", 4, SET_IN_FILE },
443 { "menu_search", "
\83\81\83j
\83\85\81[
\82Ì
\8c\9f\8dõ", 4, SET_IN_FILE },
445 { "menu_select_all", "select all items in a menu", 4, SET_IN_FILE },
447 { "menu_select_all", "
\91S
\82Ä
\82Ì
\83A
\83C
\83e
\83\80\82ð
\91I
\91ð", 4, SET_IN_FILE },
449 { "menu_select_page", "select all items on this page of a menu", 4,
451 { "menu_select_page", "
\8c»
\8dÝ
\95\
\8e¦
\82³
\82ê
\82Ä
\82¢
\82é
\91S
\82Ä
\82Ì
\83A
\83C
\83e
\83\80\82ð
\91I
\91ð", 4,
454 { "monsters", "the symbols to use for monsters", MAXMCLASSES,
456 { "monsters", "
\83\82\83\93\83X
\83^
\81[
\82É
\8eg
\97p
\82³
\82ê
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a", MAXMCLASSES,
459 { "msghistory", "number of top line messages to save", 5, DISP_IN_GAME },
461 { "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 },
462 #if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS)
464 { "msg_window", "the type of message window required", 1, SET_IN_GAME },
466 { "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 },
469 { "msg_window", "the type of message window required", 1, SET_IN_FILE },
471 { "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 },
474 { "name", "your character's name (e.g., name:Merlin-W)", PL_NSIZ,
476 { "name", "
\82 \82È
\82½
\82Ì
\96¼
\91O (
\97á name:
\83}
\81[
\83\8a\83\93-W)", PL_NSIZ,
479 { "mouse_support", "game receives click info from mouse", 0, SET_IN_GAME },
481 { "mouse_support", "
\83Q
\81[
\83\80\82ª
\83}
\83E
\83X
\82©
\82ç
\82Ì
\83N
\83\8a\83b
\83N
\8fî
\95ñ
\82ð
\8eó
\82¯
\8eæ
\82é", 0, SET_IN_GAME },
483 { "number_pad", "use the number pad for movement", 1, SET_IN_GAME },
485 { "number_pad", "
\83i
\83\93\83o
\81[
\83p
\83b
\83h
\82ð
\8eg
\97p
\82·
\82é", 1, SET_IN_GAME },
487 { "objects", "the symbols to use for objects", MAXOCLASSES, SET_IN_FILE },
489 { "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 },
491 { "packorder", "the inventory order of the items in your pack",
493 { "packorder", "
\94w
\95\89\82¢
\91Ü
\93à
\82Ì
\95¨
\82Ì
\8f\87\94Ô",
494 MAXOCLASSES, SET_IN_GAME },
499 "palette (00c/880/-fff is blue/yellow/reverse white)", 15, SET_IN_GAME
501 "
\83p
\83\8c\83b
\83g (00c/880/-fff
\82Í
\82»
\82ê
\82¼
\82ê
\90Â/
\89©/
\94½
\93]
\94\92\82ð
\8e¦
\82·)", 15, SET_IN_GAME
504 "palette (adjust an RGB color in palette (color-R-G-B)", 15, SET_IN_FILE
506 "
\83p
\83\8c\83b
\83g (
\83p
\83\8c\83b
\83g
\82ÌRGB
\90F
\82ð
\92²
\90®
\82·
\82é (
\90F-R-G-B)", 15, SET_IN_FILE
511 { "hicolor", "same as palette, only order is reversed", 15, SET_IN_FILE },
513 { "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 },
517 { "paranoid_confirmation", "extra prompting in certain situations", 28,
520 { "paranoid_confirmation", "
\88ê
\95\94\82Ì
\8fó
\8bµ
\82Å
\92Ç
\89Á
\82Ì
\8am
\94F
\82ð
\82·
\82é", 28,
524 { "petattr", "attributes for highlighting pets", 88, SET_IN_GAME },
526 { "petattr", "
\83y
\83b
\83g
\82ð
\83n
\83C
\83\89\83C
\83g
\82·
\82é
\82½
\82ß
\82Ì
\91®
\90«", 88, SET_IN_GAME },
528 { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME },
530 { "pettype", "
\82 \82È
\82½
\82Ì
\91I
\91ð
\82µ
\82½
\8f\89\8aú
\83y
\83b
\83g
\82Ì
\8eí
\97Þ", 4, DISP_IN_GAME },
532 { "pickup_burden", "maximum burden picked up before prompt", 20,
534 { "pickup_burden", "
\8fE
\82¤
\82Æ
\82«
\82É
\8dÅ
\91å
\89×
\8fd
\82É
\82È
\82é
\8eè
\91O
\82Å
\8am
\94F
\82·
\82é", 20,
537 { "pickup_types", "types of objects to pick up automatically",
539 { "pickup_types", "
\8e©
\93®
\82Å
\8fE
\82¢
\82 \82°
\82é
\95¨
\82Ì
\83V
\83\93\83{
\83\8b",
540 MAXOCLASSES, SET_IN_GAME },
542 { "pile_limit", "threshold for \"there are many objects here\"", 24,
545 { "pile_limit", "
\81u
\82±
\82±
\82É
\82Í
\82½
\82
\82³
\82ñ
\82Ì
\82à
\82Ì
\82ª
\82 \82é
\81v
\82Ì
\82µ
\82«
\82¢
\92l", 24,
549 { "playmode", "normal play, non-scoring explore mode, or debug mode", 8,
552 { "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,
556 { "player_selection", "choose character via dialog or prompts", 12,
558 { "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,
561 { "race", "your starting race (e.g., Human, Elf)", PL_CSIZ,
563 { "race", "
\83Q
\81[
\83\80\8aJ
\8en
\8e\9e\82Ì
\8eí
\91° (
\97á Human, Elf)", PL_CSIZ,
566 { "role", "your starting role (e.g., Barbarian, Valkyrie)", PL_CSIZ,
568 { "role", "
\83Q
\81[
\83\80\8aJ
\8en
\8e\9e\82Ì
\90E
\8bÆ (
\97á Barbarian, Valkyrie)", PL_CSIZ,
571 { "runmode", "display frequency when `running' or `travelling'",
573 { "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",
574 sizeof "teleport", SET_IN_GAME },
576 { "scores", "the parts of the score list you wish to see", 32,
578 { "scores", "
\83Q
\81[
\83\80\8fI
\97¹
\8e\9e\82É
\8c©
\82é
\83X
\83R
\83A
\82Ì
\8eí
\97Þ", 32,
581 { "scroll_amount", "amount to scroll map when scroll_margin is reached",
583 { "scroll_amount", "scroll_margin
\82É
\93Í
\82¢
\82½
\82Æ
\82«
\82Ì
\83}
\83b
\83v
\83X
\83N
\83\8d\81[
\83\8b\97Ê",
584 20, DISP_IN_GAME }, /*WC*/
586 { "scroll_margin", "scroll map when this far from the edge", 20,
588 { "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,
589 DISP_IN_GAME }, /*WC*/
591 { "sortloot", "sort object selection lists by description", 4,
593 { "sortloot", "
\95¨
\91Ì
\91I
\91ð
\83\8a\83X
\83g
\82ð
\90à
\96¾
\82Å
\83\
\81[
\83g
\82·
\82é", 4,
597 { "soundcard", "type of sound card to use", 20, SET_IN_FILE },
599 { "soundcard", "
\8eg
\97p
\82µ
\82Ä
\82¢
\82é
\83T
\83E
\83\93\83h
\83J
\81[
\83h
\82Ì
\8eí
\97Þ", 20, SET_IN_FILE },
602 #ifdef STATUS_HILITES
604 "0=no status highlighting, N=show highlights for N turns",
606 "0=
\83X
\83e
\81[
\83^
\83X
\83n
\83C
\83\89\83C
\83g
\82È
\82µ
\81CN
\83^
\81[
\83\93\96\88\82É
\83n
\83C
\83\89\83C
\83g
\95\
\8e¦",
611 "highlight control", 20, SET_IN_FILE
613 "
\83n
\83C
\83\89\83C
\83g
\82Ì
\90§
\8cä", 20, SET_IN_FILE
617 #ifdef CURSES_GRAPHICS
619 "2 or 3 lines for horizontal (bottom or top) status display",
621 "
\90\82\92¼(
\89º
\82©
\8fã)
\82Ì
\83X
\83e
\81[
\83^
\83X
\95\
\8e¦
\82É2,3
\8ds
\8eg
\82¤",
625 "2 or 3 lines for status display",
627 "
\83X
\83e
\81[
\83^
\83X
\95\
\8e¦
\82É2,3
\8ds
\8eg
\82¤",
632 { "symset", "load a set of display symbols from the symbols file", 70,
635 { "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,
640 "load a set of rogue display symbols from the symbols file", 70,
644 "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,
649 { "subkeyvalue", "override keystroke value", 7, SET_IN_FILE },
651 { "subkeyvalue", "
\83L
\81[
\83}
\83b
\83s
\83\93\83O
\82ð
\95Ï
\8dX
\82·
\82é", 7, SET_IN_FILE },
654 { "suppress_alert", "suppress alerts about version-specific features", 8,
656 { "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,
658 /* term_cols,term_rows -> WC2_TERM_SIZE (6: room to format 1..32767) */
660 { "term_cols", "number of columns", 6, SET_IN_FILE }, /*WC2*/
662 { "term_cols", "
\8c\85\90\94", 6, SET_IN_FILE }, /*WC2*/
665 { "term_rows", "number of rows", 6, SET_IN_FILE }, /*WC2*/
667 { "term_rows", "
\8ds
\90\94", 6, SET_IN_FILE }, /*WC2*/
670 { "tile_width", "width of tiles", 20, DISP_IN_GAME }, /*WC*/
672 { "tile_width", "
\83^
\83C
\83\8b\82Ì
\95\9d", 20, DISP_IN_GAME }, /*WC*/
675 { "tile_height", "height of tiles", 20, DISP_IN_GAME }, /*WC*/
677 { "tile_height", "
\83^
\83C
\83\8b\82Ì
\8d\82\82³", 20, DISP_IN_GAME }, /*WC*/
680 { "tile_file", "name of tile file", 70, DISP_IN_GAME }, /*WC*/
682 { "tile_file", "
\83^
\83C
\83\8b\83t
\83@
\83C
\83\8b\82Ì
\96¼
\91O", 70, DISP_IN_GAME }, /*WC*/
685 { "traps", "the symbols to use in drawing traps", MAXTCHARS + 1,
687 { "traps", "ã©
\82ð
\95`
\89æ
\82·
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a", MAXTCHARS + 1,
690 { "vary_msgcount", "show more old messages at a time", 20,
692 { "vary_msgcount", "
\88ê
\93x
\82É
\95\
\8e¦
\82·
\82é
\83\81\83b
\83Z
\81[
\83W
\82Ì
\90\94", 20,
693 DISP_IN_GAME }, /*WC*/
696 { "video", "method of video updating", 20, SET_IN_FILE },
698 { "video", "
\8eg
\97p
\82·
\82é
\83r
\83f
\83I
\83\82\81[
\83h
\82ð
\90Ý
\92è
\82·
\82é", 20, SET_IN_FILE },
702 { "videocolors", "color mappings for internal screen routines", 40,
704 { "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,
707 { "videoshades", "gray shades to map to black/gray/white", 32,
709 { "videoshades", "
\95\
\8e¦
\82É
\83O
\83\8c\83C
\83X
\83P
\81[
\83\8b\82ð
\97p
\82¢
\82é", 32,
713 { "whatis_coord", "show coordinates when auto-describing cursor position",
716 { "whatis_coord", "
\83J
\81[
\83\
\83\8b\88Ê
\92u
\82ð
\8e©
\93®
\90à
\96¾
\82·
\82é
\82Æ
\82«
\82É
\8dÀ
\95W
\82ð
\95\
\8e¦
\82·
\82é",
721 "filter coordinate locations when targeting next or previous",
725 "
\8e\9f\82â
\8eè
\91O
\82ð
\83^
\81[
\83Q
\83b
\83g
\82·
\82é
\82Æ
\82«
\82É
\8dÀ
\95W
\88Ê
\92u
\82ð
\83t
\83B
\83\8b\83^
\82·
\82é",
728 { "windowborders", "0 (off), 1 (on), 2 (auto)", 9, SET_IN_GAME }, /*WC2*/
730 { "windowcolors", "the foreground/background colors of windows", /*WC*/
733 { "windowcolors", "
\83E
\83B
\83\93\83h
\83E
\82ð
\8ew
\92è
\82µ
\82½
\91O
\8ci
\90F/
\94w
\8ci
\90F
\82Å
\95\
\8e¦
\82·
\82é", /*WC*/
737 { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
739 { "windowtype", "
\8eg
\97p
\82·
\82é
\83E
\83C
\83\93\83h
\83E
\83V
\83X
\83e
\83\80", WINTYPELEN, DISP_IN_GAME },
742 { "windowchain", "window processor to use", WINTYPELEN, SET_IN_SYS },
744 { "windowchain", "
\8eg
\97p
\82·
\82é
\83E
\83B
\83\93\83h
\83E
\83v
\83\8d\83Z
\83b
\83T", WINTYPELEN, SET_IN_SYS },
746 #ifdef BACKWARD_COMPAT
748 { "DECgraphics", "load DECGraphics display symbols", 70, SET_IN_FILE },
750 { "DECgraphics", "DECGraphics
\95\
\8e¦
\83V
\83\93\83{
\83\8b\82ð
\93Ç
\82Ý
\8d\9e\82Þ", 70, SET_IN_FILE },
752 { "IBMgraphics", "load IBMGraphics display symbols", 70, SET_IN_FILE },
754 { "IBMgraphics", "IBMGraphics
\95\
\8e¦
\83V
\83\93\83{
\83\8b\82ð
\93Ç
\82Ý
\8d\9e\82Þ", 70, SET_IN_FILE },
755 #ifdef CURSES_GRAPHICS
757 { "cursesgraphics", "load curses display symbols", 70, SET_IN_FILE },
759 { "cursesgraphics", "curses
\95\
\8e¦
\83V
\83\93\83{
\83\8b\82ð
\93Ç
\82Ý
\8d\9e\82Þ", 70, SET_IN_FILE },
761 #ifdef MAC_GRAPHICS_ENV
763 { "Macgraphics", "load MACGraphics display symbols", 70, SET_IN_FILE },
765 { "Macgraphics", "MACGraphics
\95\
\8e¦
\83V
\83\93\83{
\83\8b\82ð
\93Ç
\82Ý
\8d\9e\82Þ", 70, SET_IN_FILE },
769 { "kcode", "
\92[
\96\96\82Ì
\8a¿
\8e\9a\83R
\81[
\83h,", 4, SET_IN_FILE },
771 { (char *) 0, (char *) 0, 0, 0 }
774 #ifdef OPTION_LISTS_ONLY
777 #else /* use rest of file */
779 extern char configfile[]; /* for messages */
781 extern struct symparse loadsyms[];
782 static boolean need_redraw; /* for doset() */
784 #if defined(TOS) && defined(TEXTCOLOR)
785 extern boolean colors_changed; /* in tos.c */
789 extern char *shade[3]; /* in sys/msdos/video.c */
790 extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */
793 static char def_inv_order[MAXOCLASSES] = {
794 COIN_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS,
795 SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS,
796 TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
800 * Default menu manipulation command accelerators. These may _not_ be:
802 * + a number - reserved for counts
803 * + an upper or lower case US ASCII letter - used for accelerators
804 * + ESC - reserved for escaping the menu
805 * + NULL, CR or LF - reserved for commiting the selection(s). NULL
806 * is kind of odd, but the tty's xwaitforspace() will return it if
807 * someone hits a <ret>.
808 * + a default object class symbol - used for object class accelerators
810 * Standard letters (for now) are:
823 * The command name list is duplicated in the compopt array.
831 static const menu_cmd_t default_menu_cmd_info[] = {
833 { "menu_first_page", MENU_FIRST_PAGE, "Go to first page" },
835 { "menu_first_page", MENU_FIRST_PAGE, "
\90æ
\93ª
\83y
\81[
\83W
\82É
\88Ú
\93®" },
837 { "menu_last_page", MENU_LAST_PAGE, "Go to last page" },
839 { "menu_last_page", MENU_LAST_PAGE, "
\8dÅ
\8fI
\83y
\81[
\83W
\82É
\88Ú
\93®" },
841 { "menu_next_page", MENU_NEXT_PAGE, "Go to next page" },
843 { "menu_next_page", MENU_NEXT_PAGE, "
\8e\9f\82Ì
\83y
\81[
\83W
\82É
\88Ú
\93®" },
845 { "menu_previous_page", MENU_PREVIOUS_PAGE, "Go to previous page" },
847 { "menu_previous_page", MENU_PREVIOUS_PAGE, "
\91O
\82Ì
\83y
\81[
\83W
\82É
\88Ú
\93®" },
849 { "menu_select_all", MENU_SELECT_ALL, "Select all items" },
851 { "menu_select_all", MENU_SELECT_ALL, "
\91S
\82Ä
\82Ì
\8d\80\96Ú
\82ð
\91I
\91ð" },
853 { "menu_deselect_all", MENU_UNSELECT_ALL, "Unselect all items" },
855 { "menu_deselect_all", MENU_UNSELECT_ALL, "
\91S
\82Ä
\82Ì
\8d\80\96Ú
\82ð
\91I
\91ð
\89ð
\8f\9c" },
857 { "menu_invert_all", MENU_INVERT_ALL, "Invert selection" },
859 { "menu_invert_all", MENU_INVERT_ALL, "
\91I
\91ð
\82ð
\94½
\93]" },
861 { "menu_select_page", MENU_SELECT_PAGE, "Select items in current page" },
863 { "menu_select_page", MENU_SELECT_PAGE, "
\8c»
\8dÝ
\82Ì
\83y
\81[
\83W
\82Ì
\8d\80\96Ú
\82ð
\91I
\91ð" },
864 { "menu_deselect_page", MENU_UNSELECT_PAGE,
866 "Unselect items in current page" },
868 "
\8c»
\8dÝ
\82Ì
\83y
\81[
\83W
\82Ì
\8d\80\96Ú
\82ð
\91I
\91ð
\89ð
\8f\9c" },
870 { "menu_invert_page", MENU_INVERT_PAGE, "Invert current page selection" },
872 { "menu_invert_page", MENU_INVERT_PAGE, "
\8c»
\8dÝ
\82Ì
\83y
\81[
\83W
\82Ì
\91I
\91ð
\82ð
\94½
\93]" },
874 { "menu_search", MENU_SEARCH, "Search and toggle matching items" },
876 { "menu_search", MENU_SEARCH, "
\8c\9f\8dõ
\82µ
\82Ä
\83}
\83b
\83`
\83\93\83O
\82µ
\82½
\8d\80\96Ú
\82ð
\83g
\83O
\83\8b" },
880 * Allow the user to map incoming characters to various menu commands.
881 * The accelerator list must be a valid C string.
883 #define MAX_MENU_MAPPED_CMDS 32 /* some number */
884 char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS + 1]; /* exported */
885 static char mapped_menu_op[MAX_MENU_MAPPED_CMDS + 1];
886 static short n_menu_mapped = 0;
888 static boolean initial, from_file;
890 STATIC_DCL void FDECL(nmcpy, (char *, const char *, int));
891 STATIC_DCL void FDECL(escapes, (const char *, char *));
892 STATIC_DCL void FDECL(rejectoption, (const char *));
893 STATIC_DCL char *FDECL(string_for_opt, (char *, BOOLEAN_P));
894 STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *, BOOLEAN_P));
895 STATIC_DCL void FDECL(bad_negation, (const char *, BOOLEAN_P));
896 STATIC_DCL int FDECL(change_inv_order, (char *));
897 STATIC_DCL boolean FDECL(warning_opts, (char *, const char *));
898 STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
899 STATIC_DCL boolean FDECL(duplicate_opt_detection, (const char *, int));
900 STATIC_DCL void FDECL(complain_about_duplicate, (const char *, int));
902 STATIC_DCL const char *FDECL(attr2attrname, (int));
903 STATIC_DCL const char * FDECL(msgtype2name, (int));
904 STATIC_DCL int NDECL(query_msgtype);
905 STATIC_DCL boolean FDECL(msgtype_add, (int, char *));
906 STATIC_DCL void FDECL(free_one_msgtype, (int));
907 STATIC_DCL int NDECL(msgtype_count);
908 STATIC_DCL boolean FDECL(test_regex_pattern, (const char *, const char *));
909 STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int));
910 STATIC_DCL void FDECL(free_one_menu_coloring, (int));
911 STATIC_DCL int NDECL(count_menucolors);
912 STATIC_DCL boolean FDECL(parse_role_opts, (BOOLEAN_P, const char *,
915 STATIC_DCL void FDECL(doset_add_menu, (winid, const char *, int));
916 STATIC_DCL void FDECL(opts_add_others, (winid, const char *, int,
918 STATIC_DCL int FDECL(handle_add_list_remove, (const char *, int));
919 STATIC_DCL boolean FDECL(special_handling, (const char *,
920 BOOLEAN_P, BOOLEAN_P));
921 STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
922 STATIC_DCL void FDECL(remove_autopickup_exception,
923 (struct autopickup_exception *));
925 STATIC_DCL boolean FDECL(is_wc_option, (const char *));
926 STATIC_DCL boolean FDECL(wc_supported, (const char *));
927 STATIC_DCL boolean FDECL(is_wc2_option, (const char *));
928 STATIC_DCL boolean FDECL(wc2_supported, (const char *));
929 STATIC_DCL void FDECL(wc_set_font_name, (int, char *));
930 STATIC_DCL int FDECL(wc_set_window_colors, (char *));
937 for (x = 0; x < COLNO; x++)
938 for (y = 0; y < ROWNO; y++) {
939 struct rm *lev = &levl[x][y];
941 if (!flags.dark_room || !iflags.use_color
942 || Is_rogue_level(&u.uz)) {
943 if (lev->glyph == cmap_to_glyph(S_darkroom))
944 lev->glyph = lev->waslit ? cmap_to_glyph(S_room)
945 : cmap_to_glyph(S_stone);
947 if (lev->glyph == cmap_to_glyph(S_room) && lev->seenv
948 && lev->waslit && !cansee(x, y))
949 lev->glyph = cmap_to_glyph(S_darkroom);
950 else if (lev->glyph == cmap_to_glyph(S_stone)
951 && lev->typ == ROOM && lev->seenv && !cansee(x, y))
952 lev->glyph = cmap_to_glyph(S_darkroom);
955 if (flags.dark_room && iflags.use_color)
956 showsyms[S_darkroom] = showsyms[S_room];
958 showsyms[S_darkroom] = showsyms[S_stone];
961 /* check whether a user-supplied option string is a proper leading
962 substring of a particular option name; option string might have
963 a colon or equals sign and arbitrary value appended to it */
965 match_optname(user_string, opt_name, min_length, val_allowed)
966 const char *user_string, *opt_name;
970 int len = (int) strlen(user_string);
973 const char *p = index(user_string, ':'),
974 *q = index(user_string, '=');
976 if (!p || (q && q < p))
979 /* 'user_string' hasn't necessarily been through mungspaces()
980 so might have tabs or consecutive spaces */
981 while (p > user_string && isspace((uchar) *(p - 1)))
983 len = (int) (p - user_string);
987 return (boolean) (len >= min_length
988 && !strncmpi(opt_name, user_string, len));
991 /* most environment variables will eventually be printed in an error
992 * message if they don't work, and most error message paths go through
993 * BUFSZ buffers, which could be overflowed by a maliciously long
994 * environment variable. If a variable can legitimately be long, or
995 * if it's put in a smaller buffer, the responsible code will have to
996 * bounds-check itself.
1002 char *getev = getenv(ev);
1004 if (getev && strlen(getev) <= (BUFSZ / 2))
1010 /* process options, possibly including SYSCF */
1016 /* someday there may be other SYSCF alternatives besides text file */
1018 /* If SYSCF_FILE is specified, it _must_ exist... */
1019 assure_syscf_file();
1020 config_error_init(TRUE, SYSCF_FILE, FALSE);
1022 /* ... and _must_ parse correctly. */
1023 if (!read_config_file(SYSCF_FILE, SET_IN_SYS)) {
1024 if (config_error_done() && !iflags.initoptions_noterminate)
1025 nh_terminate(EXIT_FAILURE);
1027 config_error_done();
1029 * TODO [maybe]: parse the sysopt entries which are space-separated
1030 * lists of usernames into arrays with one name per element.
1034 initoptions_finish();
1040 #if (defined(UNIX) || defined(VMS)) && defined(TTY_GRAPHICS)
1045 /* set up the command parsing */
1046 reset_commands(TRUE); /* init */
1048 /* initialize the random number generator(s) */
1050 init_random(rn2_on_display_rng);
1052 /* for detection of configfile options specified multiple times */
1053 iflags.opt_booldup = iflags.opt_compdup = (int *) 0;
1055 for (i = 0; boolopt[i].name; i++) {
1056 if (boolopt[i].addr)
1057 *(boolopt[i].addr) = boolopt[i].initvalue;
1059 #if defined(COMPRESS) || defined(ZLIB_COMP)
1060 set_savepref("externalcomp");
1061 set_restpref("externalcomp");
1063 set_savepref("!rlecomp");
1064 set_restpref("!rlecomp");
1068 set_savepref("zerocomp");
1069 set_restpref("zerocomp");
1072 set_savepref("rlecomp");
1073 set_restpref("rlecomp");
1077 Strcpy(sysflags.sysflagsid, "sysflags");
1078 sysflags.sysflagsid[9] = (char) sizeof (struct sysflag);
1080 flags.end_own = FALSE;
1082 flags.end_around = 2;
1083 flags.paranoia_bits = PARANOID_PRAY; /* old prayconfirm=TRUE */
1084 flags.pile_limit = PILE_LIMIT_DFLT; /* 5 */
1085 flags.runmode = RUN_LEAP;
1086 iflags.msg_history = 20;
1087 /* msg_window has conflicting defaults for multi-interface binary */
1089 iflags.prevmsg_window = 's';
1091 #ifdef CURSES_GRAPHICS
1092 iflags.prevmsg_window = 'r';
1095 iflags.menu_headings = ATR_INVERSE;
1096 iflags.getpos_coords = GPCOORDS_NONE;
1098 /* hero's role, race, &c haven't been chosen yet */
1099 flags.initrole = flags.initrace = flags.initgend = flags.initalign
1102 init_ov_primary_symbols();
1103 init_ov_rogue_symbols();
1104 /* Set the default monster and object class symbols. */
1106 for (i = 0; i < WARNCOUNT; i++)
1107 warnsyms[i] = def_warnsyms[i].sym;
1109 /* for "special achievement" tracking (see obj.h,
1110 create_object(sp_lev.c), addinv_core1(invent.c) */
1111 iflags.mines_prize_type = LUCKSTONE;
1112 iflags.soko_prize_type1 = BAG_OF_HOLDING;
1113 iflags.soko_prize_type2 = AMULET_OF_REFLECTION;
1115 /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
1116 (void) memcpy((genericptr_t) flags.inv_order,
1117 (genericptr_t) def_inv_order, sizeof flags.inv_order);
1118 flags.pickup_types[0] = '\0';
1119 flags.pickup_burden = MOD_ENCUMBER;
1120 flags.sortloot = 'l'; /* sort only loot by default */
1122 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
1123 flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
1124 switch_symbols(FALSE); /* set default characters */
1125 init_rogue_symbols();
1126 #if 0 /*JP*//*
\83V
\83\93\83{
\83\8b\82Ì
\8e©
\93®
\90Ý
\92è
\82Í
\8aQ
\82ª
\91å
\82«
\82¢
\82Ì
\82Å
\83R
\83\81\83\93\83g
\83A
\83E
\83g*/
1127 #if defined(UNIX) && defined(TTY_GRAPHICS)
1129 * Set defaults for some options depending on what we can
1130 * detect about the environment's capabilities.
1131 * This has to be done after the global initialization above
1132 * and before reading user-specific initialization via
1133 * config file/environment variable below.
1135 /* this detects the IBM-compatible console on most 386 boxes */
1136 if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
1137 if (!symset[PRIMARY].explicitly)
1138 load_symset("IBMGraphics", PRIMARY);
1139 if (!symset[ROGUESET].explicitly)
1140 load_symset("RogueIBM", ROGUESET);
1141 switch_symbols(TRUE);
1143 iflags.use_color = TRUE;
1146 #endif /* UNIX && TTY_GRAPHICS */
1147 #if defined(UNIX) || defined(VMS)
1149 /* detect whether a "vt" terminal can handle alternate charsets */
1150 if ((opts = nh_getenv("TERM"))
1151 /* [could also check "xterm" which emulates vtXXX by default] */
1152 && !strncmpi(opts, "vt", 2)
1153 && AS && AE && index(AS, '\016') && index(AE, '\017')) {
1154 if (!symset[PRIMARY].explicitly)
1155 load_symset("DECGraphics", PRIMARY);
1156 switch_symbols(TRUE);
1159 #endif /* UNIX || VMS */
1161 #if defined(MSDOS) || defined(WIN32)
1162 /* Use IBM defaults. Can be overridden via config file */
1163 if (!symset[PRIMARY].explicitly)
1164 load_symset("IBMGraphics_2", PRIMARY);
1165 if (!symset[ROGUESET].explicitly)
1166 load_symset("RogueEpyx", ROGUESET);
1168 #ifdef MAC_GRAPHICS_ENV
1169 if (!symset[PRIMARY].explicitly)
1170 load_symset("MACGraphics", PRIMARY);
1171 switch_symbols(TRUE);
1172 #endif /* MAC_GRAPHICS_ENV */
1174 flags.menu_style = MENU_FULL;
1176 iflags.wc_align_message = ALIGN_TOP;
1177 iflags.wc_align_status = ALIGN_BOTTOM;
1178 /* used by tty and curses */
1179 iflags.wc2_statuslines = 2;
1180 /* only used by curses */
1181 iflags.wc2_windowborders = 2; /* 'Auto' */
1183 /* since this is done before init_objects(), do partial init here */
1184 objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
1185 nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
1189 initoptions_finish()
1193 char *opts = getenv("NETHACKOPTIONS");
1196 opts = getenv("HACKOPTIONS");
1198 if (*opts == '/' || *opts == '\\' || *opts == '@') {
1200 opts++; /* @filename */
1201 /* looks like a filename */
1202 if (strlen(opts) < BUFSZ / 2) {
1203 config_error_init(TRUE, opts, CONFIG_ERROR_SECURE);
1204 read_config_file(opts, SET_IN_FILE);
1205 config_error_done();
1208 config_error_init(TRUE, (char *) 0, FALSE);
1209 read_config_file((char *) 0, SET_IN_FILE);
1210 config_error_done();
1211 /* let the total length of options be long;
1212 * parseoptions() will check each individually
1214 config_error_init(FALSE, "NETHACKOPTIONS", FALSE);
1215 (void) parseoptions(opts, TRUE, FALSE);
1216 config_error_done();
1221 config_error_init(TRUE, (char *) 0, FALSE);
1222 read_config_file((char *) 0, SET_IN_FILE);
1223 config_error_done();
1226 (void) fruitadd(pl_fruit, (struct fruit *) 0);
1228 * Remove "slime mold" from list of object names. This will
1229 * prevent it from being wished unless it's actually present
1230 * as a named (or default) fruit. Wishing for "fruit" will
1231 * result in the player's preferred fruit [better than "\033"].
1233 obj_descr[SLIME_MOLD].oc_name = "fruit";
1235 sym = get_othersym(SYM_BOULDER,
1236 Is_rogue_level(&u.uz) ? ROGUESET : PRIMARY);
1238 showsyms[SYM_BOULDER + SYM_OFF_X] = sym;
1241 #ifdef STATUS_HILITES
1243 * A multi-interface binary might only support status highlighting
1244 * for some of the interfaces; check whether we asked for it but are
1245 * using one which doesn't.
1247 * Option processing can take place before a user-decided WindowPort
1248 * is even initialized, so check for that too.
1250 if (!WINDOWPORT("safe-startup")) {
1251 if (iflags.hilite_delta && !wc2_supported("statushilites")) {
1252 raw_printf("Status highlighting not supported for %s interface.",
1254 iflags.hilite_delta = 0;
1261 /* copy up to maxlen-1 characters; 'dest' must be able to hold maxlen;
1262 treat comma as alternate end of 'src' */
1264 nmcpy(dest, src, maxlen)
1271 for (count = 1; count < maxlen; count++) {
1272 if (*src == ',' || *src == '\0')
1273 break; /*exit on \0 terminator*/
1280 * escapes(): escape expansion for showsyms. C-style escapes understood
1281 * include \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal).
1282 * (Note: unlike in C, leading digit 0 is not used to indicate octal;
1283 * the letter o (either upper or lower case) is used for that.
1284 * The ^-prefix for control characters is also understood, and \[mM]
1285 * has the effect of 'meta'-ing the value which follows (so that the
1286 * alternate character set will be enabled).
1292 * For 3.4.3 and earlier, input ending with "\M", backslash, or caret
1293 * prior to terminating '\0' would pull that '\0' into the output and then
1294 * keep processing past it, potentially overflowing the output buffer.
1295 * Now, trailing \ or ^ will act like \\ or \^ and add '\\' or '^' to the
1296 * output and stop there; trailing \M will fall through to \<other> and
1297 * yield 'M', then stop. Any \X or \O followed by something other than
1298 * an appropriate digit will also fall through to \<other> and yield 'X'
1299 * or 'O', plus stop if the non-digit is end-of-string.
1303 const char *cp; /* might be 'tp', updating in place */
1304 char *tp; /* result is never longer than 'cp' */
1306 static NEARDATA const char oct[] = "01234567", dec[] = "0123456789",
1307 hex[] = "00112233445566778899aAbBcCdDeEfF";
1309 int cval, meta, dcount;
1312 /* \M has to be followed by something to do meta conversion,
1313 otherwise it will just be \M which ultimately yields 'M' */
1314 meta = (*cp == '\\' && (cp[1] == 'm' || cp[1] == 'M') && cp[2]);
1318 cval = dcount = 0; /* for decimal, octal, hexadecimal cases */
1319 if ((*cp != '\\' && *cp != '^') || !cp[1]) {
1320 /* simple character, or nothing left for \ or ^ to escape */
1322 } else if (*cp == '^') { /* expand control-character syntax */
1323 cval = (*++cp & 0x1f);
1326 /* remaining cases are all for backslash; we know cp[1] is not \0 */
1327 } else if (index(dec, cp[1])) {
1328 ++cp; /* move past backslash to first digit */
1330 cval = (cval * 10) + (*cp - '0');
1331 } while (*++cp && index(dec, *cp) && ++dcount < 3);
1332 } else if ((cp[1] == 'o' || cp[1] == 'O') && cp[2]
1333 && index(oct, cp[2])) {
1334 cp += 2; /* move past backslash and 'O' */
1336 cval = (cval * 8) + (*cp - '0');
1337 } while (*++cp && index(oct, *cp) && ++dcount < 3);
1338 } else if ((cp[1] == 'x' || cp[1] == 'X') && cp[2]
1339 && (dp = index(hex, cp[2])) != 0) {
1340 cp += 2; /* move past backslash and 'X' */
1342 cval = (cval * 16) + ((int) (dp - hex) / 2);
1343 } while (*++cp && (dp = index(hex, *cp)) != 0 && ++dcount < 2);
1344 } else { /* C-style character escapes */
1369 *tp++ = (char) cval;
1375 rejectoption(optname)
1376 const char *optname;
1379 pline("\"%s\" settable only from %s.", optname, configfile);
1381 pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
1389 OPTIONS=aaaaaaaaaa[ more than 247 (255 - 8 for 'OPTIONS=') total ]aaaaaaaaaa
1392 MSGTYPE=stop"You swap places with "
1393 MSGTYPE=st.op "You swap places with "
1394 MSGTYPE=stop "You swap places with \"
1395 MENUCOLOR=" blessed "green&none
1396 MENUCOLOR=" holy " = green&reverse
1397 MENUCOLOR=" cursed " = red&uline
1398 MENUCOLOR=" unholy " = reed
1399 OPTIONS=!legacy:true,fooo
1406 string_for_opt(opts, val_optional)
1408 boolean val_optional;
1410 char *colon, *equals;
1412 colon = index(opts, ':');
1413 equals = index(opts, '=');
1414 if (!colon || (equals && equals < colon))
1417 if (!colon || !*++colon) {
1420 config_error_add("Missing parameter for '%s'", opts);
1422 config_error_add("'%s'
\82Ì
\88ø
\90\94\82ª
\82 \82è
\82Ü
\82¹
\82ñ", opts);
1423 return empty_optstr;
1429 string_for_env_opt(optname, opts, val_optional)
1430 const char *optname;
1432 boolean val_optional;
1435 rejectoption(optname);
1436 return empty_optstr;
1438 return string_for_opt(opts, val_optional);
1442 bad_negation(optname, with_parameter)
1443 const char *optname;
1444 boolean with_parameter;
1447 pline_The("%s option may not %sbe negated.", optname,
1448 with_parameter ? "both have a value and " : "");
1450 pline_The("%s
\83I
\83v
\83V
\83\87\83\93\82Í
\94Û
\92è%s
\82Å
\82«
\82È
\82¢
\81D", optname,
1451 with_parameter ? "
\82Æ
\92l
\8ew
\92è
\82Ì
\97¼
\95û
\82Í" : "");
1456 * Change the inventory order, using the given string as the new order.
1457 * Missing characters in the new order are filled in at the end from
1458 * the current inv_order, except for gold, which is forced to be first
1459 * if not explicitly present.
1461 * This routine returns 1 unless there is a duplicate or bad char in
1465 change_inv_order(op)
1469 char *sp, buf[QBUFSZ];
1473 if (!index(op, GOLD_SYM))
1474 buf[num++] = COIN_CLASS;
1476 for (sp = op; *sp; sp++) {
1477 boolean fail = FALSE;
1478 oc_sym = def_char_to_objclass(*sp);
1479 /* reject bad or duplicate entries */
1480 if (oc_sym == MAXOCLASSES) { /* not an object class char */
1481 config_error_add("Not an object class '%c'", *sp);
1484 } else if (!index(flags.inv_order, oc_sym)) {
1485 /* VENOM_CLASS, RANDOM_CLASS, and ILLOBJ_CLASS are excluded
1486 because they aren't in def_inv_order[] so don't make it
1487 into flags.inv_order, hence always fail this index() test */
1488 config_error_add("Object class '%c' not allowed", *sp);
1491 } else if (index(sp + 1, *sp)) {
1492 config_error_add("Duplicate object class '%c'", *sp);
1496 /* retain good ones */
1498 buf[num++] = (char) oc_sym;
1502 /* fill in any omitted classes, using previous ordering */
1503 for (sp = flags.inv_order; *sp; sp++)
1504 if (!index(buf, *sp))
1505 (void) strkitten(&buf[num++], *sp);
1506 buf[MAXOCLASSES - 1] = '\0';
1508 Strcpy(flags.inv_order, buf);
1513 warning_opts(opts, optype)
1514 register char *opts;
1517 uchar translate[WARNCOUNT];
1520 if ((opts = string_for_env_opt(optype, opts, FALSE)) == empty_optstr)
1522 escapes(opts, opts);
1524 length = (int) strlen(opts);
1525 /* match the form obtained from PC configuration files */
1526 for (i = 0; i < WARNCOUNT; i++)
1527 translate[i] = (i >= length) ? 0
1528 : opts[i] ? (uchar) opts[i]
1529 : def_warnsyms[i].sym;
1530 assign_warnings(translate);
1535 assign_warnings(graph_chars)
1536 register uchar *graph_chars;
1540 for (i = 0; i < WARNCOUNT; i++)
1542 warnsyms[i] = graph_chars[i];
1546 feature_alert_opts(op, optn)
1551 unsigned long fnv = get_feature_notice_ver(op); /* version.c */
1555 if (fnv > get_current_feature_ver()) {
1558 You_cant("disable new feature alerts for future versions.");
1560 You_cant("
\8f«
\97\88\82Ì
\83o
\81[
\83W
\83\87\83\93\82Ì
\8b@
\94\
\8cx
\8d\90\82ð
\96³
\8cø
\82É
\82·
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
1563 "%s=%s Invalid reference to a future version ignored",
1569 flags.suppress_alert = fnv;
1571 Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
1572 FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
1575 "Feature change alerts disabled for NetHack %s features and prior.",
1579 "NetHack %s
\88È
\91O
\82Ì
\8b@
\94\
\82É
\91Î
\82·
\82é
\8b@
\94\
\95Ï
\8dX
\8cx
\8d\90\82ð
\96³
\8cø
\82É
\82µ
\82½
\81D",
1587 set_duplicate_opt_detection(on_or_off)
1592 if (on_or_off != 0) {
1594 if (iflags.opt_booldup)
1595 impossible("iflags.opt_booldup already on (memory leak)");
1596 iflags.opt_booldup = (int *) alloc(SIZE(boolopt) * sizeof (int));
1597 optptr = iflags.opt_booldup;
1598 for (k = 0; k < SIZE(boolopt); ++k)
1601 if (iflags.opt_compdup)
1602 impossible("iflags.opt_compdup already on (memory leak)");
1603 iflags.opt_compdup = (int *) alloc(SIZE(compopt) * sizeof (int));
1604 optptr = iflags.opt_compdup;
1605 for (k = 0; k < SIZE(compopt); ++k)
1609 if (iflags.opt_booldup)
1610 free((genericptr_t) iflags.opt_booldup);
1611 iflags.opt_booldup = (int *) 0;
1612 if (iflags.opt_compdup)
1613 free((genericptr_t) iflags.opt_compdup);
1614 iflags.opt_compdup = (int *) 0;
1619 duplicate_opt_detection(opts, iscompound)
1621 int iscompound; /* 0 == boolean option, 1 == compound */
1625 if (!iscompound && iflags.opt_booldup && initial && from_file) {
1626 for (i = 0; boolopt[i].name; i++) {
1627 if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
1628 optptr = iflags.opt_booldup + i;
1636 } else if (iscompound && iflags.opt_compdup && initial && from_file) {
1637 for (i = 0; compopt[i].name; i++) {
1638 if (match_optname(opts, compopt[i].name, strlen(compopt[i].name),
1640 optptr = iflags.opt_compdup + i;
1653 complain_about_duplicate(opts, iscompound)
1655 int iscompound; /* 0 == boolean option, 1 == compound */
1658 /* the Mac has trouble dealing with the output of messages while
1659 * processing the config file. That should get fixed one day.
1660 * For now just return.
1664 config_error_add("%s option specified multiple times: %s",
1665 iscompound ? "compound" : "boolean", opts);
1667 config_error_add("%s
\83I
\83v
\83V
\83\87\83\93\82ª
\95¡
\90\94\89ñ
\8ew
\92è
\82³
\82ê
\82Ä
\82¢
\82Ü
\82·
\81F%s",
1668 iscompound ? "
\95¡
\8d\87" : "
\90^
\8bU
\92l", opts);
1674 /* paranoia[] - used by parseoptions() and special_handling() */
1675 STATIC_VAR const struct paranoia_opts {
1676 int flagmask; /* which paranoid option */
1677 const char *argname; /* primary name */
1678 int argMinLen; /* minimum number of letters to match */
1679 const char *synonym; /* alternate name (optional) */
1681 const char *explain; /* for interactive menu */
1683 /* there are some initial-letter conflicts: "a"ttack vs "a"ll, "attack"
1684 takes precedence and "all" isn't present in the interactive menu,
1685 and "d"ie vs "d"eath, synonyms for each other so doesn't matter;
1686 (also "p"ray vs "P"aranoia, "pray" takes precedence since "Paranoia"
1687 is just a synonym for "Confirm"); "b"ones vs "br"eak-wand, the
1688 latter requires at least two letters; "e"at vs "ex"plore,
1689 "cont"inue eating vs "C"onfirm; "wand"-break vs "Were"-change,
1690 both require at least two letters during config processing and use
1691 case-senstivity for 'O's interactive menu */
1692 { PARANOID_CONFIRM, "Confirm", 1, "Paranoia", 2,
1694 "for \"yes\" confirmations, require \"no\" to reject" },
1696 "\"yes\"
\82ð
\8am
\94F
\82·
\82é
\82Æ
\82«
\82É
\81C
\8b\91\94Û
\82·
\82é
\82Æ
\82«
\82É
\82Í\"no\"
\82ª
\95K
\97v" },
1697 { PARANOID_QUIT, "quit", 1, "explore", 2,
1699 "yes vs y to quit or to enter explore mode" },
1701 "
\8fI
\97¹
\82Ü
\82½
\82Í
\92T
\8c\9f\83\82\81[
\83h
\82É
\93ü
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1702 { PARANOID_DIE, "die", 1, "death", 2,
1704 "yes vs y to die (explore mode or debug mode)" },
1706 "(
\92T
\8c\9f\83\82\81[
\83h
\82©
\83f
\83o
\83b
\83O
\83\82\81[
\83h
\82Å)
\8e\80\82Ê
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1707 { PARANOID_BONES, "bones", 1, 0, 0,
1709 "yes vs y to save bones data when dying in debug mode" },
1711 "
\83f
\83o
\83b
\83O
\83\82\81[
\83h
\82Å
\8e\80\82ñ
\82Å
\8d\9c\83f
\81[
\83^
\82ð
\95Û
\91¶
\82·
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1712 { PARANOID_HIT, "attack", 1, "hit", 1,
1714 "yes vs y to attack a peaceful monster" },
1716 "
\97F
\8dD
\93I
\89ö
\95¨
\82ð
\8dU
\8c\82\82·
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1717 { PARANOID_BREAKWAND, "wand-break", 2, "break-wand", 2,
1719 "yes vs y to break a wand via (a)pply" },
1721 "(a)pply
\82Å
\8fñ
\82ð
\90Ü
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1722 { PARANOID_EATING, "eat", 1, "continue", 4,
1724 "yes vs y to continue eating after first bite when satiated" },
1726 "
\96\9e\95 \82Ì
\8e\9e\82É
\88ê
\8cû
\90H
\82×
\82½
\8cã
\90H
\82×
\91±
\82¯
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1727 { PARANOID_WERECHANGE, "Were-change", 2, (const char *) 0, 0,
1729 "yes vs y to change form when lycanthropy is controllable" },
1731 "
\8fb
\89»
\95a
\82ª
\90§
\8cä
\89Â
\94\
\82È
\8fê
\8d\87\82É
\95Ï
\89»
\82·
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1732 { PARANOID_PRAY, "pray", 1, 0, 0,
1734 "y to pray (supersedes old \"prayconfirm\" option)" },
1736 "
\8bF
\82é
\82Æ
\82«
\82Éy
\82ª
\95K
\97v(
\8cÃ
\82¢\"prayconfirm\"
\83I
\83v
\83V
\83\87\83\93\82ð
\8fã
\8f\91\82«
\82·
\82é)" },
1737 { PARANOID_REMOVE, "Remove", 1, "Takeoff", 1,
1739 "always pick from inventory for Remove and Takeoff" },
1741 "Remove
\82ÆTakeoff
\82Å
\8fí
\82É
\8e\9d\82¿
\95¨
\88ê
\97\97\82©
\82ç
\91I
\82Ô" },
1742 /* for config file parsing; interactive menu skips these */
1743 { 0, "none", 4, 0, 0, 0 }, /* require full word match */
1744 { ~0, "all", 3, 0, 0, 0 }, /* ditto */
1747 extern struct menucoloring *menu_colorings;
1749 static const struct {
1753 { "black", CLR_BLACK },
1755 { "green", CLR_GREEN },
1756 { "brown", CLR_BROWN },
1757 { "blue", CLR_BLUE },
1758 { "magenta", CLR_MAGENTA },
1759 { "cyan", CLR_CYAN },
1760 { "gray", CLR_GRAY },
1761 { "orange", CLR_ORANGE },
1762 { "light green", CLR_BRIGHT_GREEN },
1763 { "yellow", CLR_YELLOW },
1764 { "light blue", CLR_BRIGHT_BLUE },
1765 { "light magenta", CLR_BRIGHT_MAGENTA },
1766 { "light cyan", CLR_BRIGHT_CYAN },
1767 { "white", CLR_WHITE },
1768 { "no color", NO_COLOR },
1769 { NULL, CLR_BLACK }, /* everything after this is an alias */
1770 { "transparent", NO_COLOR },
1771 { "purple", CLR_MAGENTA },
1772 { "light purple", CLR_BRIGHT_MAGENTA },
1773 { "bright purple", CLR_BRIGHT_MAGENTA },
1774 { "grey", CLR_GRAY },
1775 { "bright red", CLR_ORANGE },
1776 { "bright green", CLR_BRIGHT_GREEN },
1777 { "bright blue", CLR_BRIGHT_BLUE },
1778 { "bright magenta", CLR_BRIGHT_MAGENTA },
1779 { "bright cyan", CLR_BRIGHT_CYAN }
1782 static const struct {
1786 { "none", ATR_NONE },
1787 { "bold", ATR_BOLD },
1789 { "underline", ATR_ULINE },
1790 { "blink", ATR_BLINK },
1791 { "inverse", ATR_INVERSE },
1792 { NULL, ATR_NONE }, /* everything after this is an alias */
1793 { "normal", ATR_NONE },
1794 { "uline", ATR_ULINE },
1795 { "reverse", ATR_INVERSE },
1804 for (i = 0; i < SIZE(colornames); i++)
1805 if (colornames[i].name && colornames[i].color == clr)
1806 return colornames[i].name;
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; caller has removed any leading space */
1819 for (i = 0; i < SIZE(colornames); i++)
1820 if (colornames[i].name
1821 && fuzzymatch(str, colornames[i].name, " -_", TRUE)) {
1822 c = colornames[i].color;
1825 if (i == SIZE(colornames) && digit(*str))
1828 if (c < 0 || c >= CLR_MAX) {
1829 config_error_add("Unknown color '%.60s'", str);
1830 c = CLR_MAX; /* "none of the above" */
1836 STATIC_OVL const char *
1842 for (i = 0; i < SIZE(attrnames); i++)
1843 if (attrnames[i].attr == attr)
1844 return attrnames[i].name;
1849 match_str2attr(str, complain)
1855 for (i = 0; i < SIZE(attrnames); i++)
1856 if (attrnames[i].name
1857 && fuzzymatch(str, attrnames[i].name, " -_", TRUE)) {
1858 a = attrnames[i].attr;
1862 if (a == -1 && complain)
1863 config_error_add("Unknown text attribute '%.50s'", str);
1875 menu_item *picks = (menu_item *) 0;
1877 tmpwin = create_nhwindow(NHW_MENU);
1880 for (i = 0; i < SIZE(colornames); i++) {
1881 if (!colornames[i].name)
1884 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name,
1885 (colornames[i].color == NO_COLOR) ? MENU_SELECTED
1888 end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick a color");
1889 pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
1890 destroy_nhwindow(tmpwin);
1892 i = colornames[picks[0].item.a_int - 1].color;
1893 /* pick_cnt==2: explicitly picked something other than the
1894 preselected entry */
1895 if (pick_cnt == 2 && i == NO_COLOR)
1896 i = colornames[picks[1].item.a_int - 1].color;
1897 free((genericptr_t) picks);
1899 } else if (pick_cnt == 0) {
1900 /* pick_cnt==0: explicitly picking preselected entry toggled it off */
1906 /* ask about highlighting attribute; for menu headers and menu
1907 coloring patterns, only one attribute at a time is allowed;
1908 for status highlighting, multiple attributes are allowed [overkill;
1909 life would be much simpler if that were restricted to one also...] */
1917 menu_item *picks = (menu_item *) 0;
1918 boolean allow_many = (prompt && !strncmpi(prompt, "Choose", 6));
1919 int default_attr = ATR_NONE;
1921 if (prompt && strstri(prompt, "menu headings"))
1922 default_attr = iflags.menu_headings;
1923 tmpwin = create_nhwindow(NHW_MENU);
1926 for (i = 0; i < SIZE(attrnames); i++) {
1927 if (!attrnames[i].name)
1930 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr,
1932 (attrnames[i].attr == default_attr) ? MENU_SELECTED
1935 end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick an attribute");
1936 pick_cnt = select_menu(tmpwin, allow_many ? PICK_ANY : PICK_ONE, &picks);
1937 destroy_nhwindow(tmpwin);
1942 /* PICK_ANY, with one preselected entry (ATR_NONE) which
1943 should be excluded if any other choices were picked */
1944 for (i = 0; i < pick_cnt; ++i) {
1945 j = picks[i].item.a_int - 1;
1946 if (attrnames[j].attr != ATR_NONE || pick_cnt == 1) {
1947 switch (attrnames[j].attr) {
1970 /* PICK_ONE, but might get 0 or 2 due to preselected entry */
1971 j = picks[0].item.a_int - 1;
1972 /* pick_cnt==2: explicitly picked something other than the
1973 preselected entry */
1974 if (pick_cnt == 2 && attrnames[j].attr == default_attr)
1975 j = picks[1].item.a_int - 1;
1976 k = attrnames[j].attr;
1978 free((genericptr_t) picks);
1980 } else if (pick_cnt == 0 && !allow_many) {
1981 /* PICK_ONE, preselected entry explicitly chosen */
1982 return default_attr;
1984 /* either ESC to explicitly cancel (pick_cnt==-1) or
1985 PICK_ANY with preselected entry toggled off and nothing chosen */
1989 static const struct {
1993 } msgtype_names[] = {
1995 { "show", MSGTYP_NORMAL, "Show message normally" },
1997 { "show", MSGTYP_NORMAL, "
\92Ê
\8fí
\92Ê
\82è
\83\81\83b
\83Z
\81[
\83W
\82ð
\95\
\8e¦
\82·
\82é" },
1999 { "hide", MSGTYP_NOSHOW, "Hide message" },
2001 { "hide", MSGTYP_NOSHOW, "
\83\81\83b
\83Z
\81[
\83W
\82ð
\95\
\8e¦
\82µ
\82È
\82¢" },
2002 { "noshow", MSGTYP_NOSHOW, NULL },
2004 { "stop", MSGTYP_STOP, "Prompt for more after the message" },
2006 { "stop", MSGTYP_STOP, "more
\83v
\83\8d\83\93\83v
\83g
\82Å
\91Ò
\82Â" },
2007 { "more", MSGTYP_STOP, NULL },
2009 { "norep", MSGTYP_NOREP, "Do not repeat the message" }
2011 { "norep", MSGTYP_NOREP, "
\82±
\82Ì
\83\81\83b
\83Z
\81[
\83W
\82Í
\8cJ
\82è
\95Ô
\82³
\82È
\82¢" }
2014 STATIC_OVL const char *
2020 for (i = 0; i < SIZE(msgtype_names); i++)
2021 if (msgtype_names[i].descr && msgtype_names[i].msgtyp == typ)
2022 return msgtype_names[i].name;
2032 menu_item *picks = (menu_item *) 0;
2034 tmpwin = create_nhwindow(NHW_MENU);
2037 for (i = 0; i < SIZE(msgtype_names); i++)
2038 if (msgtype_names[i].descr) {
2039 any.a_int = msgtype_names[i].msgtyp + 1;
2040 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
2041 msgtype_names[i].descr, MENU_UNSELECTED);
2044 end_menu(tmpwin, "How to show the message");
2046 end_menu(tmpwin, "
\83\81\83b
\83Z
\81[
\83W
\82Ì
\95\
\8e¦
\95û
\96@");
2047 pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
2048 destroy_nhwindow(tmpwin);
2050 i = picks->item.a_int - 1;
2051 free((genericptr_t) picks);
2058 msgtype_add(typ, pattern)
2062 struct plinemsg_type *tmp = (struct plinemsg_type *) alloc(sizeof *tmp);
2065 tmp->regex = regex_init();
2066 if (!regex_compile(pattern, tmp->regex)) {
2067 static const char *re_error = "MSGTYPE regex error";
2069 config_error_add("%s: %s", re_error, regex_error_desc(tmp->regex));
2070 regex_free(tmp->regex);
2071 free((genericptr_t) tmp);
2074 tmp->pattern = dupstr(pattern);
2075 tmp->next = plinemsg_types;
2076 plinemsg_types = tmp;
2083 struct plinemsg_type *tmp, *tmp2 = 0;
2085 for (tmp = plinemsg_types; tmp; tmp = tmp2) {
2087 free((genericptr_t) tmp->pattern);
2088 regex_free(tmp->regex);
2089 free((genericptr_t) tmp);
2091 plinemsg_types = (struct plinemsg_type *) 0;
2095 free_one_msgtype(idx)
2098 struct plinemsg_type *tmp = plinemsg_types;
2099 struct plinemsg_type *prev = NULL;
2103 struct plinemsg_type *next = tmp->next;
2105 regex_free(tmp->regex);
2106 free((genericptr_t) tmp->pattern);
2107 free((genericptr_t) tmp);
2111 plinemsg_types = next;
2121 msgtype_type(msg, norepeat)
2123 boolean norepeat; /* called from Norep(via pline) */
2125 struct plinemsg_type *tmp = plinemsg_types;
2128 /* we don't exclude entries with negative msgtype values
2129 because then the msg might end up matching a later pattern */
2130 if (regex_match(msg, tmp->regex))
2131 return tmp->msgtype;
2134 return norepeat ? MSGTYP_NOREP : MSGTYP_NORMAL;
2137 /* negate one or more types of messages so that their type handling will
2138 be disabled or re-enabled; MSGTYPE_NORMAL (value 0) is not affected */
2140 hide_unhide_msgtypes(hide, hide_mask)
2144 struct plinemsg_type *tmp;
2147 /* negative msgtype value won't be recognized by pline, so does nothing */
2148 for (tmp = plinemsg_types; tmp; tmp = tmp->next) {
2151 mt = -mt; /* unhide: negate negative, yielding positive */
2152 if (mt > 0 && ((1 << mt) & hide_mask))
2153 tmp->msgtype = -tmp->msgtype;
2158 msgtype_count(VOID_ARGS)
2161 struct plinemsg_type *tmp = plinemsg_types;
2171 msgtype_parse_add(str)
2177 if (sscanf(str, "%10s \"%255[^\"]\"", msgtype, pattern) == 2) {
2181 for (i = 0; i < SIZE(msgtype_names); i++)
2182 if (!strncmpi(msgtype_names[i].name, msgtype, strlen(msgtype))) {
2183 typ = msgtype_names[i].msgtyp;
2187 return msgtype_add(typ, pattern);
2189 config_error_add("Unknown message type '%s'", msgtype);
2191 config_error_add("Malformed MSGTYPE");
2197 test_regex_pattern(str, errmsg)
2201 static const char re_error[] = "Regex error";
2202 struct nhregex *match;
2203 boolean retval = TRUE;
2208 match = regex_init();
2210 config_error_add("NHregex error");
2214 if (!regex_compile(str, match)) {
2215 config_error_add("%s: %s", errmsg ? errmsg : re_error,
2216 regex_error_desc(match));
2224 add_menu_coloring_parsed(str, c, a)
2228 static const char re_error[] = "Menucolor regex error";
2229 struct menucoloring *tmp;
2233 tmp = (struct menucoloring *) alloc(sizeof *tmp);
2234 tmp->match = regex_init();
2235 if (!regex_compile(str, tmp->match)) {
2236 config_error_add("%s: %s", re_error, regex_error_desc(tmp->match));
2237 regex_free(tmp->match);
2241 tmp->next = menu_colorings;
2242 tmp->origstr = dupstr(str);
2245 menu_colorings = tmp;
2250 /* parse '"regex_string"=color&attr' and add it to menucoloring */
2252 add_menu_coloring(tmpstr)
2253 char *tmpstr; /* never Null but could be empty */
2255 int c = NO_COLOR, a = ATR_NONE;
2256 char *tmps, *cs, *amp;
2259 (void) strncpy(str, tmpstr, sizeof str - 1);
2260 str[sizeof str - 1] = '\0';
2262 if ((cs = index(str, '=')) == 0) {
2263 config_error_add("Malformed MENUCOLOR");
2267 tmps = cs + 1; /* advance past '=' */
2269 if ((amp = index(tmps, '&')) != 0)
2272 c = match_str2clr(tmps);
2277 tmps = amp + 1; /* advance past '&' */
2278 a = match_str2attr(tmps, TRUE);
2283 /* the regexp portion here has not been condensed by mungspaces() */
2286 if (*tmps == '"' || *tmps == '\'') {
2288 while (isspace((uchar) *cs))
2295 return add_menu_coloring_parsed(tmps, c, a);
2299 get_menu_coloring(str, color, attr)
2303 struct menucoloring *tmpmc;
2305 if (iflags.use_menu_color)
2306 for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next)
2307 if (regex_match(str, tmpmc->match)) {
2308 *color = tmpmc->color;
2309 *attr = tmpmc->attr;
2316 free_menu_coloring()
2318 struct menucoloring *tmp, *tmp2;
2320 for (tmp = menu_colorings; tmp; tmp = tmp2) {
2322 regex_free(tmp->match);
2323 free((genericptr_t) tmp->origstr);
2324 free((genericptr_t) tmp);
2329 free_one_menu_coloring(idx)
2332 struct menucoloring *tmp = menu_colorings;
2333 struct menucoloring *prev = NULL;
2337 struct menucoloring *next = tmp->next;
2339 regex_free(tmp->match);
2340 free((genericptr_t) tmp->origstr);
2341 free((genericptr_t) tmp);
2345 menu_colorings = next;
2355 count_menucolors(VOID_ARGS)
2357 struct menucoloring *tmp;
2360 for (tmp = menu_colorings; tmp; tmp = tmp->next)
2366 parse_role_opts(negated, fullname, opts, opp)
2368 const char *fullname;
2375 bad_negation(fullname, FALSE);
2376 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
2378 boolean val_negated = FALSE;
2380 while ((*op == '!') || !strncmpi(op, "no", 2)) {
2385 val_negated = !val_negated;
2388 if (!setrolefilter(op)) {
2389 config_error_add("Unknown negated parameter '%s'", op);
2393 if (duplicate_opt_detection(opts, 1))
2394 complain_about_duplicate(opts, 1);
2402 /* Check if character c is illegal as a menu command key */
2404 illegal_menu_cmd_key(c)
2407 if (c == 0 || c == '\r' || c == '\n' || c == '\033'
2408 || c == ' ' || digit(c) || (letter(c) && c != '@')) {
2409 config_error_add("Reserved menu command key '%s'", visctrl(c));
2411 } else { /* reject default object class symbols */
2413 for (j = 1; j < MAXOCLASSES; j++)
2414 if (c == def_oc_syms[j].sym) {
2415 config_error_add("Menu command key '%s' is an object class",
2424 parseoptions(opts, tinitial, tfrom_file)
2425 register char *opts;
2426 boolean tinitial, tfrom_file;
2430 boolean negated, duplicate;
2432 const char *fullname;
2433 boolean retval = TRUE;
2436 from_file = tfrom_file;
2437 if ((op = index(opts, ',')) != 0) {
2439 if (!parseoptions(op, initial, from_file))
2442 if (strlen(opts) > BUFSZ / 2) {
2443 config_error_add("Option too long, max length is %i characters",
2448 /* strip leading and trailing white space */
2449 while (isspace((uchar) *opts))
2452 while (--op >= opts && isspace((uchar) *op))
2456 config_error_add("Empty statement");
2460 while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
2468 /* variant spelling */
2470 if (match_optname(opts, "colour", 5, FALSE))
2471 Strcpy(opts, "color"); /* fortunately this isn't longer */
2473 /* special boolean options */
2475 if (match_optname(opts, "female", 3, FALSE)) {
2476 if (duplicate_opt_detection(opts, 0))
2477 complain_about_duplicate(opts, 0);
2478 if (!initial && flags.female == negated) {
2479 config_error_add("That is not anatomically possible.");
2482 flags.initgend = flags.female = !negated;
2486 if (match_optname(opts, "male", 4, FALSE)) {
2487 if (duplicate_opt_detection(opts, 0))
2488 complain_about_duplicate(opts, 0);
2489 if (!initial && flags.female != negated) {
2490 config_error_add("That is not anatomically possible.");
2493 flags.initgend = flags.female = negated;
2497 #if defined(MICRO) && !defined(AMIGA)
2498 /* included for compatibility with old NetHack.cnf files */
2499 if (match_optname(opts, "IBM_", 4, FALSE)) {
2500 iflags.BIOS = !negated;
2505 /* compound options */
2507 /* This first batch can be duplicated if their values are negated */
2511 if (match_optname(opts, fullname, sizeof "align" - 1, TRUE)) {
2512 if (parse_role_opts(negated, fullname, opts, &op)) {
2513 if ((flags.initalign = str2align(op)) == ROLE_NONE) {
2514 config_error_add("Unknown %s '%s'", fullname, op);
2522 /* role:string or character:string */
2524 if (match_optname(opts, fullname, 4, TRUE)
2525 || match_optname(opts, (fullname = "character"), 4, TRUE)) {
2526 if (parse_role_opts(negated, fullname, opts, &op)) {
2527 if ((flags.initrole = str2role(op)) == ROLE_NONE) {
2528 config_error_add("Unknown %s '%s'", fullname, op);
2530 } else /* Backwards compatibility */
2531 nmcpy(pl_character, op, PL_NSIZ);
2539 if (match_optname(opts, fullname, 4, TRUE)) {
2540 if (parse_role_opts(negated, fullname, opts, &op)) {
2541 if ((flags.initrace = str2race(op)) == ROLE_NONE) {
2542 config_error_add("Unknown %s '%s'", fullname, op);
2544 } else /* Backwards compatibility */
2552 fullname = "gender";
2553 if (match_optname(opts, fullname, 4, TRUE)) {
2554 if (parse_role_opts(negated, fullname, opts, &op)) {
2555 if ((flags.initgend = str2gend(op)) == ROLE_NONE) {
2556 config_error_add("Unknown %s '%s'", fullname, op);
2559 flags.female = flags.initgend;
2565 /* We always check for duplicates on the remaining compound options,
2566 although individual option processing can choose to complain or not */
2568 duplicate = duplicate_opt_detection(opts, 1); /* 1: check compounds */
2570 fullname = "pettype";
2571 if (match_optname(opts, fullname, 3, TRUE)) {
2573 complain_about_duplicate(opts, 1);
2574 if ((op = string_for_env_opt(fullname, opts, negated))
2577 bad_negation(fullname, TRUE);
2580 switch (lowc(*op)) {
2582 preferred_pet = 'd';
2585 case 'f': /* feline */
2586 preferred_pet = 'c';
2588 case 'h': /* horse */
2589 case 'q': /* quadruped */
2590 /* avoids giving "unrecognized type of pet" but
2591 pet_type(dog.c) won't actually honor this */
2592 preferred_pet = 'h';
2594 case 'n': /* no pet */
2595 preferred_pet = 'n';
2597 case '*': /* random */
2598 preferred_pet = '\0';
2602 config_error_add("Unrecognized pet type '%s'.", op);
2604 pline("'%s'
\82Í
\83y
\83b
\83g
\82Ì
\8eí
\97Þ
\82Æ
\82µ
\82Ä
\8eó
\82¯
\95t
\82¯
\82ç
\82ê
\82Ü
\82¹
\82ñ
\81D", op);
2609 preferred_pet = 'n';
2613 fullname = "catname";
2614 if (match_optname(opts, fullname, 3, TRUE)) {
2616 complain_about_duplicate(opts, 1);
2618 bad_negation(fullname, FALSE);
2620 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
2622 nmcpy(catname, op, PL_PSIZ);
2625 sanitize_name(catname);
2629 fullname = "dogname";
2630 if (match_optname(opts, fullname, 3, TRUE)) {
2632 complain_about_duplicate(opts, 1);
2634 bad_negation(fullname, FALSE);
2636 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
2638 nmcpy(dogname, op, PL_PSIZ);
2641 sanitize_name(dogname);
2645 fullname = "horsename";
2646 if (match_optname(opts, fullname, 5, TRUE)) {
2648 complain_about_duplicate(opts, 1);
2650 bad_negation(fullname, FALSE);
2652 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
2654 nmcpy(horsename, op, PL_PSIZ);
2657 sanitize_name(horsename);
2661 fullname = "mouse_support";
2662 if (match_optname(opts, fullname, 13, TRUE)) {
2663 boolean compat = (strlen(opts) <= 13);
2666 complain_about_duplicate(opts, 1);
2667 op = string_for_opt(opts, (compat || !initial));
2668 if (op == empty_optstr) {
2669 if (compat || negated || initial) {
2670 /* for backwards compatibility, "mouse_support" without a
2671 value is a synonym for mouse_support:1 */
2672 iflags.wc_mouse_support = !negated;
2674 } else if (negated) {
2675 bad_negation(fullname, TRUE);
2678 int mode = atoi(op);
2680 if (mode < 0 || mode > 2 || (mode == 0 && *op != '0')) {
2681 config_error_add("Illegal %s parameter '%s'", fullname, op);
2683 } else { /* mode >= 0 */
2684 iflags.wc_mouse_support = mode;
2690 fullname = "number_pad";
2691 if (match_optname(opts, fullname, 10, TRUE)) {
2692 boolean compat = (strlen(opts) <= 10);
2695 complain_about_duplicate(opts, 1);
2696 op = string_for_opt(opts, (compat || !initial));
2697 if (op == empty_optstr) {
2698 if (compat || negated || initial) {
2699 /* for backwards compatibility, "number_pad" without a
2700 value is a synonym for number_pad:1 */
2701 iflags.num_pad = !negated;
2702 iflags.num_pad_mode = 0;
2704 } else if (negated) {
2705 bad_negation(fullname, TRUE);
2708 int mode = atoi(op);
2710 if (mode < -1 || mode > 4 || (mode == 0 && *op != '0')) {
2711 config_error_add("Illegal %s parameter '%s'", fullname, op);
2713 } else if (mode <= 0) {
2714 iflags.num_pad = FALSE;
2715 /* German keyboard; y and z keys swapped */
2716 iflags.num_pad_mode = (mode < 0); /* 0 or 1 */
2717 } else { /* mode > 0 */
2718 iflags.num_pad = TRUE;
2719 iflags.num_pad_mode = 0;
2720 /* PC Hack / MSDOS compatibility */
2721 if (mode == 2 || mode == 4)
2722 iflags.num_pad_mode |= 1;
2723 /* phone keypad layout */
2724 if (mode == 3 || mode == 4)
2725 iflags.num_pad_mode |= 2;
2728 reset_commands(FALSE);
2729 number_pad(iflags.num_pad ? 1 : 0);
2733 fullname = "roguesymset";
2734 if (match_optname(opts, fullname, 7, TRUE)) {
2736 complain_about_duplicate(opts, 1);
2738 bad_negation(fullname, FALSE);
2740 } else if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
2741 symset[ROGUESET].name = dupstr(op);
2742 if (!read_sym_file(ROGUESET)) {
2743 clear_symsetentry(ROGUESET, TRUE);
2745 "Unable to load symbol set \"%s\" from \"%s\"",
2749 if (!initial && Is_rogue_level(&u.uz))
2750 assign_graphics(ROGUESET);
2758 fullname = "symset";
2759 if (match_optname(opts, fullname, 6, TRUE)) {
2761 complain_about_duplicate(opts, 1);
2763 bad_negation(fullname, FALSE);
2765 } else if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
2766 symset[PRIMARY].name = dupstr(op);
2767 if (!read_sym_file(PRIMARY)) {
2768 clear_symsetentry(PRIMARY, TRUE);
2770 "Unable to load symbol set \"%s\" from \"%s\"",
2774 switch_symbols(symset[PRIMARY].name != (char *) 0);
2782 fullname = "runmode";
2783 if (match_optname(opts, fullname, 4, TRUE)) {
2785 complain_about_duplicate(opts, 1);
2787 flags.runmode = RUN_TPORT;
2788 } else if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
2789 if (!strncmpi(op, "teleport", strlen(op)))
2790 flags.runmode = RUN_TPORT;
2791 else if (!strncmpi(op, "run", strlen(op)))
2792 flags.runmode = RUN_LEAP;
2793 else if (!strncmpi(op, "walk", strlen(op)))
2794 flags.runmode = RUN_STEP;
2795 else if (!strncmpi(op, "crawl", strlen(op)))
2796 flags.runmode = RUN_CRAWL;
2798 config_error_add("Unknown %s parameter '%s'", fullname, op);
2806 /* menucolor:"regex_string"=color */
2807 fullname = "menucolor";
2808 if (match_optname(opts, fullname, 9, TRUE)) {
2810 bad_negation(fullname, FALSE);
2812 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
2814 if (!add_menu_coloring(op))
2821 fullname = "msghistory";
2822 if (match_optname(opts, fullname, 3, TRUE)) {
2824 complain_about_duplicate(opts, 1);
2825 op = string_for_env_opt(fullname, opts, negated);
2826 if ((negated && op == empty_optstr)
2827 || (!negated && op != empty_optstr)) {
2828 iflags.msg_history = negated ? 0 : atoi(op);
2829 } else if (negated) {
2830 bad_negation(fullname, TRUE);
2836 fullname = "msg_window";
2837 /* msg_window:single, combo, full or reversed */
2838 if (match_optname(opts, fullname, 4, TRUE)) {
2839 /* allow option to be silently ignored by non-tty ports */
2844 complain_about_duplicate(opts, 1);
2845 if ((op = string_for_opt(opts, TRUE)) == empty_optstr) {
2846 tmp = negated ? 's' : 'f';
2849 bad_negation(fullname, TRUE);
2855 case 's': /* single message history cycle (default if negated) */
2856 iflags.prevmsg_window = 's';
2858 case 'c': /* combination: two singles, then full page */
2859 iflags.prevmsg_window = 'c';
2861 case 'f': /* full page (default if specified without argument) */
2862 iflags.prevmsg_window = 'f';
2864 case 'r': /* full page (reversed) */
2865 iflags.prevmsg_window = 'r';
2868 config_error_add("Unknown %s parameter '%s'", fullname, op);
2876 * setting font options */
2878 if (!strncmpi(opts, fullname, 4)) {
2880 char *fontopts = opts + 4;
2882 if (!strncmpi(fontopts, "map", 3) || !strncmpi(fontopts, "_map", 4))
2883 opttype = MAP_OPTION;
2884 else if (!strncmpi(fontopts, "message", 7)
2885 || !strncmpi(fontopts, "_message", 8))
2886 opttype = MESSAGE_OPTION;
2887 else if (!strncmpi(fontopts, "text", 4)
2888 || !strncmpi(fontopts, "_text", 5))
2889 opttype = TEXT_OPTION;
2890 else if (!strncmpi(fontopts, "menu", 4)
2891 || !strncmpi(fontopts, "_menu", 5))
2892 opttype = MENU_OPTION;
2893 else if (!strncmpi(fontopts, "status", 6)
2894 || !strncmpi(fontopts, "_status", 7))
2895 opttype = STATUS_OPTION;
2896 else if (!strncmpi(fontopts, "_size", 5)) {
2897 if (!strncmpi(fontopts, "_size_map", 8))
2898 opttype = MAP_OPTION;
2899 else if (!strncmpi(fontopts, "_size_message", 12))
2900 opttype = MESSAGE_OPTION;
2901 else if (!strncmpi(fontopts, "_size_text", 9))
2902 opttype = TEXT_OPTION;
2903 else if (!strncmpi(fontopts, "_size_menu", 9))
2904 opttype = MENU_OPTION;
2905 else if (!strncmpi(fontopts, "_size_status", 11))
2906 opttype = STATUS_OPTION;
2908 config_error_add("Unknown %s parameter '%s'", fullname, opts);
2912 complain_about_duplicate(opts, 1);
2913 if (opttype > 0 && !negated
2914 && (op = string_for_opt(opts, FALSE)) != empty_optstr) {
2917 iflags.wc_fontsiz_map = atoi(op);
2919 case MESSAGE_OPTION:
2920 iflags.wc_fontsiz_message = atoi(op);
2923 iflags.wc_fontsiz_text = atoi(op);
2926 iflags.wc_fontsiz_menu = atoi(op);
2929 iflags.wc_fontsiz_status = atoi(op);
2935 config_error_add("Unknown %s parameter '%s'", fullname, opts);
2939 && (op = string_for_opt(opts, FALSE)) != empty_optstr) {
2940 wc_set_font_name(opttype, op);
2942 set_font_name(opttype, op);
2945 } else if (negated) {
2946 bad_negation(fullname, TRUE);
2953 if (match_optname(opts, "palette", 3, TRUE)
2955 || match_optname(opts, "hicolor", 3, TRUE)
2958 int color_number, color_incr;
2962 complain_about_duplicate(opts, 1);
2965 if (match_optname(opts, "hicolor", 3, TRUE)) {
2967 bad_negation("hicolor", FALSE);
2970 color_number = CLR_MAX + 4; /* HARDCODED inverse number */
2976 bad_negation("palette", FALSE);
2983 op = string_for_opt(opts, TRUE);
2984 if (op == empty_optstr || !alternative_palette(op)) {
2985 config_error_add("Error in palette parameter '%s'", op);
2989 if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
2991 int cnt, tmp, reverse;
2994 while (*pt && color_number >= 0) {
3004 if (*pt && *pt != '/') {
3011 if (isalpha((uchar) tmp)) {
3012 tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */
3014 tmp &= 0xf; /* Digits in ASCII too... */
3017 /* Add an extra so we fill f -> ff and 0 -> 00 */
3025 change_color(color_number, rgb, reverse);
3026 color_number += color_incr;
3035 #endif /* CHANGE_COLOR */
3037 if (match_optname(opts, "fruit", 2, TRUE)) {
3038 struct fruit *forig = 0;
3041 complain_about_duplicate(opts, 1);
3042 op = string_for_opt(opts, negated || !initial);
3044 if (op != empty_optstr) {
3045 bad_negation("fruit", TRUE);
3051 if (op == empty_optstr)
3053 /* strip leading/trailing spaces, condense internal ones (3.6.2) */
3059 /* count number of named fruits; if 'op' is found among them,
3060 then the count doesn't matter because we won't be adding it */
3061 f = fruit_from_name(op, FALSE, &fnum);
3063 if (!flags.made_fruit)
3064 forig = fruit_from_name(pl_fruit, FALSE, (int *) 0);
3066 if (!forig && fnum >= 100) {
3069 "Doing that so many times isn't very fruitful.");
3072 "
\82»
\82ñ
\82È
\82É
\89½
\89ñ
\82à
\82â
\82Á
\82Ä
\82à
\82Ù
\82Æ
\82ñ
\82Ç
\88Ó
\96¡
\82Í
\82È
\82¢
\81D");
3079 nmcpy(pl_fruit, op, PL_FSIZ);
3080 sanitize_name(pl_fruit);
3081 /* OBJ_NAME(objects[SLIME_MOLD]) won't work for this after
3082 initialization; it gets changed to generic "fruit" */
3084 nmcpy(pl_fruit, "slime mold", PL_FSIZ);
3086 /* if 'forig' is nonNull, we replace it rather than add
3087 a new fruit; it can only be nonNull if no fruits have
3088 been created since the previous name was put in place */
3089 (void) fruitadd(pl_fruit, forig);
3090 pline("Fruit is now \"%s\".", pl_fruit);
3092 /* If initial, then initoptions is allowed to do it instead
3093 * of here (initoptions always has to do it even if there's
3094 * no fruit option at all. Also, we don't want people
3095 * setting multiple fruits in their options.)
3100 fullname = "whatis_coord";
3101 if (match_optname(opts, fullname, 8, TRUE)) {
3103 complain_about_duplicate(opts, 1);
3105 iflags.getpos_coords = GPCOORDS_NONE;
3107 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
3109 static char gpcoords[] = { GPCOORDS_NONE, GPCOORDS_COMPASS,
3110 GPCOORDS_COMFULL, GPCOORDS_MAP,
3111 GPCOORDS_SCREEN, '\0' };
3114 if (c && index(gpcoords, c))
3115 iflags.getpos_coords = c;
3117 config_error_add("Unknown %s parameter '%s'", fullname, op);
3125 fullname = "whatis_filter";
3126 if (match_optname(opts, fullname, 8, TRUE)) {
3128 complain_about_duplicate(opts, 1);
3130 iflags.getloc_filter = GFILTER_NONE;
3132 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
3138 iflags.getloc_filter = GFILTER_NONE;
3141 iflags.getloc_filter = GFILTER_VIEW;
3144 iflags.getloc_filter = GFILTER_AREA;
3147 config_error_add("Unknown %s parameter '%s'", fullname, op);
3156 fullname = "warnings";
3157 if (match_optname(opts, fullname, 5, TRUE)) {
3159 complain_about_duplicate(opts, 1);
3161 bad_negation(fullname, FALSE);
3164 return warning_opts(opts, fullname);
3167 /* boulder:symbol */
3168 fullname = "boulder";
3169 if (match_optname(opts, fullname, 7, TRUE)) {
3170 #ifdef BACKWARD_COMPAT
3174 complain_about_duplicate(opts, 1);
3176 bad_negation(fullname, FALSE);
3179 /* if ((opts = string_for_env_opt(fullname, opts, FALSE))
3182 if ((opts = string_for_opt(opts, FALSE)) == empty_optstr)
3184 escapes(opts, opts);
3185 /* note: dummy monclass #0 has symbol value '\0'; we allow that--
3186 attempting to set bouldersym to '^@'/'\0' will reset to default */
3187 if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
3188 clash = opts[0] ? 1 : 0;
3189 else if (opts[0] >= '1' && opts[0] < WARNCOUNT + '0')
3192 /* symbol chosen matches a used monster or warning
3193 symbol which is not good - reject it */
3195 "Badoption - boulder symbol '%s' would conflict with a %s symbol",
3197 (clash == 1) ? "monster" : "warning");
3200 * Override the default boulder symbol.
3202 ov_primary_syms[SYM_BOULDER + SYM_OFF_X] = (nhsym) opts[0];
3203 ov_rogue_syms[SYM_BOULDER + SYM_OFF_X] = (nhsym) opts[0];
3204 /* for 'initial', update of BOULDER symbol is done in
3205 initoptions_finish(), after all symset options
3206 have been processed */
3208 nhsym sym = get_othersym(SYM_BOULDER,
3209 Is_rogue_level(&u.uz) ? ROGUESET : PRIMARY);
3211 showsyms[SYM_BOULDER + SYM_OFF_X] = sym;
3217 config_error_add("'%s' no longer supported; use S_boulder:c instead",
3225 if (match_optname(opts, fullname, 4, TRUE)) {
3227 complain_about_duplicate(opts, 1);
3229 bad_negation(fullname, FALSE);
3231 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
3233 nmcpy(plname, op, PL_NSIZ);
3239 /* altkeyhandler:string */
3240 fullname = "altkeyhandler";
3241 if (match_optname(opts, fullname, 4, TRUE)) {
3243 complain_about_duplicate(opts, 1);
3245 bad_negation(fullname, FALSE);
3247 } else if ((op = string_for_opt(opts, negated)) != empty_optstr) {
3248 #if defined(WIN32) && defined(TTY_GRAPHICS)
3249 set_altkeyhandling(op);
3257 * align_status:[left|top|right|bottom] */
3258 fullname = "align_status";
3259 if (match_optname(opts, fullname, sizeof "align_status" - 1, TRUE)) {
3260 op = string_for_opt(opts, negated);
3261 if ((op != empty_optstr) && !negated) {
3262 if (!strncmpi(op, "left", sizeof "left" - 1))
3263 iflags.wc_align_status = ALIGN_LEFT;
3264 else if (!strncmpi(op, "top", sizeof "top" - 1))
3265 iflags.wc_align_status = ALIGN_TOP;
3266 else if (!strncmpi(op, "right", sizeof "right" - 1))
3267 iflags.wc_align_status = ALIGN_RIGHT;
3268 else if (!strncmpi(op, "bottom", sizeof "bottom" - 1))
3269 iflags.wc_align_status = ALIGN_BOTTOM;
3271 config_error_add("Unknown %s parameter '%s'", fullname, op);
3274 } else if (negated) {
3275 bad_negation(fullname, TRUE);
3282 * align_message:[left|top|right|bottom] */
3283 fullname = "align_message";
3284 if (match_optname(opts, fullname, sizeof "align_message" - 1, TRUE)) {
3286 complain_about_duplicate(opts, 1);
3287 op = string_for_opt(opts, negated);
3288 if ((op != empty_optstr) && !negated) {
3289 if (!strncmpi(op, "left", sizeof "left" - 1))
3290 iflags.wc_align_message = ALIGN_LEFT;
3291 else if (!strncmpi(op, "top", sizeof "top" - 1))
3292 iflags.wc_align_message = ALIGN_TOP;
3293 else if (!strncmpi(op, "right", sizeof "right" - 1))
3294 iflags.wc_align_message = ALIGN_RIGHT;
3295 else if (!strncmpi(op, "bottom", sizeof "bottom" - 1))
3296 iflags.wc_align_message = ALIGN_BOTTOM;
3298 config_error_add("Unknown %s parameter '%s'", fullname, op);
3301 } else if (negated) {
3302 bad_negation(fullname, TRUE);
3308 /* the order to list inventory */
3309 fullname = "packorder";
3310 if (match_optname(opts, fullname, 4, TRUE)) {
3312 complain_about_duplicate(opts, 1);
3314 bad_negation(fullname, FALSE);
3316 } else if ((op = string_for_opt(opts, FALSE)) == empty_optstr)
3319 if (!change_inv_order(op))
3324 /* user can change required response for some prompts (quit, die, hit),
3325 or add an extra prompt (pray, Remove) that isn't ordinarily there */
3326 fullname = "paranoid_confirmation";
3327 if (match_optname(opts, fullname, 8, TRUE)) {
3328 /* at present we don't complain about duplicates for this
3329 option, but we do throw away the old settings whenever
3330 we process a new one [clearing old flags is essential
3331 for handling default paranoid_confirm:pray sanely] */
3332 flags.paranoia_bits = 0; /* clear all */
3334 flags.paranoia_bits = 0; /* [now redundant...] */
3335 } else if ((op = string_for_opt(opts, TRUE)) != empty_optstr) {
3336 char *pp, buf[BUFSZ];
3338 strncpy(buf, op, sizeof buf - 1);
3339 buf[sizeof buf - 1] = '\0';
3340 op = mungspaces(buf);
3342 /* We're looking to parse
3343 "paranoid_confirm:whichone wheretwo whothree"
3344 and "paranoid_confirm:" prefix has already
3345 been stripped off by the time we get here */
3346 pp = index(op, ' ');
3349 /* we aren't matching option names but match_optname()
3350 does what we want once we've broken the space
3351 delimited aggregate into separate tokens */
3352 for (i = 0; i < SIZE(paranoia); ++i) {
3353 if (match_optname(op, paranoia[i].argname,
3354 paranoia[i].argMinLen, FALSE)
3355 || (paranoia[i].synonym
3356 && match_optname(op, paranoia[i].synonym,
3357 paranoia[i].synMinLen, FALSE))) {
3358 if (paranoia[i].flagmask)
3359 flags.paranoia_bits |= paranoia[i].flagmask;
3360 else /* 0 == "none", so clear all */
3361 flags.paranoia_bits = 0;
3365 if (i == SIZE(paranoia)) {
3366 /* didn't match anything, so arg is bad;
3367 any flags already set will stay set */
3368 config_error_add("Unknown %s parameter '%s'",
3372 /* move on to next token */
3376 break; /* no next token */
3383 /* accept deprecated boolean; superseded by paranoid_confirm:pray */
3384 fullname = "prayconfirm";
3385 if (match_optname(opts, fullname, 4, FALSE)) {
3387 flags.paranoia_bits &= ~PARANOID_PRAY;
3389 flags.paranoia_bits |= PARANOID_PRAY;
3393 /* maximum burden picked up before prompt (Warren Cheung) */
3394 fullname = "pickup_burden";
3395 if (match_optname(opts, fullname, 8, TRUE)) {
3397 complain_about_duplicate(opts, 1);
3399 bad_negation(fullname, FALSE);
3401 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
3403 switch (lowc(*op)) {
3404 case 'u': /* Unencumbered */
3405 flags.pickup_burden = UNENCUMBERED;
3407 case 'b': /* Burdened (slight encumbrance) */
3408 flags.pickup_burden = SLT_ENCUMBER;
3410 case 's': /* streSsed (moderate encumbrance) */
3411 flags.pickup_burden = MOD_ENCUMBER;
3413 case 'n': /* straiNed (heavy encumbrance) */
3414 flags.pickup_burden = HVY_ENCUMBER;
3416 case 'o': /* OverTaxed (extreme encumbrance) */
3418 flags.pickup_burden = EXT_ENCUMBER;
3420 case 'l': /* overLoaded */
3421 flags.pickup_burden = OVERLOADED;
3424 config_error_add("Unknown %s parameter '%s'", fullname, op);
3432 /* types of objects to pick up automatically */
3433 fullname = "pickup_types";
3434 if (match_optname(opts, fullname, 8, TRUE)) {
3435 char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1],
3436 qbuf[QBUFSZ], abuf[BUFSZ];
3438 boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
3441 complain_about_duplicate(opts, 1);
3442 oc_to_str(flags.pickup_types, tbuf);
3443 flags.pickup_types[0] = '\0'; /* all */
3444 op = string_for_opt(opts, (compat || !initial));
3445 if (op == empty_optstr) {
3446 if (compat || negated || initial) {
3447 /* for backwards compatibility, "pickup" without a
3448 value is a synonym for autopickup of all types
3449 (and during initialization, we can't prompt yet) */
3450 flags.pickup = !negated;
3453 oc_to_str(flags.inv_order, ocl);
3455 if (flags.menu_style == MENU_TRADITIONAL
3456 || flags.menu_style == MENU_COMBINATION) {
3461 Sprintf(qbuf, "New %s: [%s am] (%s)", fullname, ocl,
3462 *tbuf ? tbuf : "all");
3464 Sprintf(qbuf, "
\90V
\82µ
\82¢%s: [%s am] (%s)", fullname, ocl,
3465 *tbuf ? tbuf : "all");
3469 wasspace = (abuf[0] == ' '); /* before mungspaces */
3470 op = mungspaces(abuf);
3471 if (wasspace && !abuf[0])
3472 ; /* one or more spaces will remove old value */
3473 else if (!abuf[0] || abuf[0] == '\033')
3474 op = tbuf; /* restore */
3475 else if (abuf[0] == 'm')
3477 /* note: abuf[0]=='a' is already handled via clearing the
3478 the old value (above) as a default action */
3481 if (wizard && !index(ocl, VENOM_SYM))
3482 strkitten(ocl, VENOM_SYM);
3484 (void) choose_classes_menu("Autopickup what?", 1, TRUE, ocl,
3487 (void) choose_classes_menu("
\82Ç
\82ê
\82ð
\8e©
\93®
\8fE
\82¢
\82É
\90Ý
\92è
\82·
\82é
\81H", 1, TRUE, ocl,
3494 bad_negation(fullname, TRUE);
3499 if (*op != 'a' && *op != 'A') {
3502 oc_sym = def_char_to_objclass(*op);
3503 /* make sure all are valid obj symbols occurring once */
3504 if (oc_sym != MAXOCLASSES
3505 && !index(flags.pickup_types, oc_sym)) {
3506 flags.pickup_types[num] = (char) oc_sym;
3507 flags.pickup_types[++num] = '\0';
3513 config_error_add("Unknown %s parameter '%s'", fullname, op);
3520 /* pile limit: when walking over objects, number which triggers
3521 "there are several/many objects here" instead of listing them */
3522 fullname = "pile_limit";
3523 if (match_optname(opts, fullname, 4, TRUE)) {
3525 complain_about_duplicate(opts, 1);
3526 op = string_for_opt(opts, negated);
3527 if ((negated && op == empty_optstr)
3528 || (!negated && op != empty_optstr))
3529 flags.pile_limit = negated ? 0 : atoi(op);
3531 bad_negation(fullname, TRUE);
3533 } else /* op == empty_optstr */
3534 flags.pile_limit = PILE_LIMIT_DFLT;
3536 if (flags.pile_limit < 0)
3537 flags.pile_limit = PILE_LIMIT_DFLT;
3541 /* play mode: normal, explore/discovery, or debug/wizard */
3542 fullname = "playmode";
3543 if (match_optname(opts, fullname, 4, TRUE)) {
3545 complain_about_duplicate(opts, 1);
3547 bad_negation(fullname, FALSE);
3548 if (duplicate || negated)
3550 op = string_for_opt(opts, FALSE);
3551 if (op == empty_optstr)
3553 if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) {
3554 wizard = discover = FALSE;
3555 } else if (!strncmpi(op, "explore", 6)
3556 || !strncmpi(op, "discovery", 6)) {
3557 wizard = FALSE, discover = TRUE;
3558 } else if (!strncmpi(op, "debug", 5) || !strncmpi(op, "wizard", 6)) {
3559 wizard = TRUE, discover = FALSE;
3561 config_error_add("Invalid value for \"%s\":%s", fullname, op);
3568 * player_selection: dialog | prompt/prompts/prompting */
3569 fullname = "player_selection";
3570 if (match_optname(opts, fullname, sizeof "player_selection" - 1, TRUE)) {
3572 complain_about_duplicate(opts, 1);
3573 op = string_for_opt(opts, negated);
3574 if (op != empty_optstr && !negated) {
3575 if (!strncmpi(op, "dialog", sizeof "dialog" - 1)) {
3576 iflags.wc_player_selection = VIA_DIALOG;
3577 } else if (!strncmpi(op, "prompt", sizeof "prompt" - 1)) {
3578 iflags.wc_player_selection = VIA_PROMPTS;
3580 config_error_add("Unknown %s parameter '%s'", fullname, op);
3583 } else if (negated) {
3584 bad_negation(fullname, TRUE);
3590 /* things to disclose at end of game */
3591 fullname = "disclose";
3592 if (match_optname(opts, fullname, 7, TRUE)) {
3594 * The order that the end_disclose options are stored:
3595 * inventory, attribs, vanquished, genocided,
3596 * conduct, overview.
3597 * There is an array in flags:
3598 * end_disclose[NUM_DISCLOSURE_OPT];
3599 * with option settings for the each of the following:
3600 * iagvc [see disclosure_options in decl.c]:
3601 * Allowed setting values in that array are:
3602 * DISCLOSE_PROMPT_DEFAULT_YES ask with default answer yes
3603 * DISCLOSE_PROMPT_DEFAULT_NO ask with default answer no
3604 * DISCLOSE_YES_WITHOUT_PROMPT always disclose and don't ask
3605 * DISCLOSE_NO_WITHOUT_PROMPT never disclose and don't ask
3606 * DISCLOSE_PROMPT_DEFAULT_SPECIAL for 'vanquished' only...
3607 * DISCLOSE_SPECIAL_WITHOUT_PROMPT ...to set up sort order.
3609 * Those setting values can be used in the option
3610 * string as a prefix to get the desired behaviour.
3612 * For backward compatibility, no prefix is required,
3613 * and the presence of a i,a,g,v, or c without a prefix
3614 * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
3616 int idx, prefix_val;
3619 complain_about_duplicate(opts, 1);
3620 op = string_for_opt(opts, TRUE);
3621 if (op != empty_optstr && negated) {
3622 bad_negation(fullname, TRUE);
3625 /* "disclose" without a value means "all with prompting"
3626 and negated means "none without prompting" */
3627 if (op == empty_optstr
3628 || !strcmpi(op, "all") || !strcmpi(op, "none")) {
3629 if (op != empty_optstr && !strcmpi(op, "none"))
3631 for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++)
3632 flags.end_disclose[num] = negated
3633 ? DISCLOSE_NO_WITHOUT_PROMPT
3634 : DISCLOSE_PROMPT_DEFAULT_YES;
3640 while (*op && num < sizeof flags.end_disclose - 1) {
3641 static char valid_settings[] = {
3642 DISCLOSE_PROMPT_DEFAULT_YES, DISCLOSE_PROMPT_DEFAULT_NO,
3643 DISCLOSE_PROMPT_DEFAULT_SPECIAL,
3644 DISCLOSE_YES_WITHOUT_PROMPT, DISCLOSE_NO_WITHOUT_PROMPT,
3645 DISCLOSE_SPECIAL_WITHOUT_PROMPT, '\0'
3647 register char c, *dop;
3651 c = 'v'; /* killed -> vanquished */
3653 c = 'o'; /* dungeon -> overview */
3654 dop = index(disclosure_options, c);
3656 idx = (int) (dop - disclosure_options);
3657 if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) {
3658 impossible("bad disclosure index %d %c", idx, c);
3661 if (prefix_val != -1) {
3663 if (prefix_val == DISCLOSE_PROMPT_DEFAULT_SPECIAL)
3664 prefix_val = DISCLOSE_PROMPT_DEFAULT_YES;
3665 if (prefix_val == DISCLOSE_SPECIAL_WITHOUT_PROMPT)
3666 prefix_val = DISCLOSE_YES_WITHOUT_PROMPT;
3668 flags.end_disclose[idx] = prefix_val;
3671 flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT;
3672 } else if (index(valid_settings, c)) {
3674 } else if (c == ' ') {
3677 config_error_add("Unknown %s parameter '%c'", fullname, *op);
3685 if (!strncmpi(opts, "kcode", 3)){
3686 if ((op = string_for_env_opt("kcode", opts, FALSE)) != 0){
3693 /* scores:5t[op] 5a[round] o[wn] */
3694 fullname = "scores";
3695 if (match_optname(opts, fullname, 4, TRUE)) {
3697 complain_about_duplicate(opts, 1);
3699 bad_negation(fullname, FALSE);
3702 if ((op = string_for_opt(opts, FALSE)) == empty_optstr)
3712 } else if (*op == '!') {
3722 flags.end_top = inum;
3726 flags.end_around = inum;
3730 flags.end_own = !negated;
3733 config_error_add("Unknown %s parameter '%s'", fullname, op);
3736 /* "3a" is sufficient but accept "3around" (or "3abracadabra") */
3739 /* t, a, and o can be separated by space(s) or slash or both */
3748 fullname = "sortloot";
3749 if (match_optname(opts, fullname, 4, TRUE)) {
3750 op = string_for_env_opt(fullname, opts, FALSE);
3751 if (op != empty_optstr) {
3755 case 'n': /* none */
3756 case 'l': /* loot (pickup) */
3757 case 'f': /* full (pickup + invent) */
3761 config_error_add("Unknown %s parameter '%s'", fullname, op);
3769 fullname = "suppress_alert";
3770 if (match_optname(opts, fullname, 4, TRUE)) {
3772 complain_about_duplicate(opts, 1);
3773 op = string_for_opt(opts, negated);
3775 bad_negation(fullname, FALSE);
3777 } else if (op != empty_optstr)
3778 (void) feature_alert_opts(op, fullname);
3783 /* videocolors:string */
3784 fullname = "videocolors";
3785 if (match_optname(opts, fullname, 6, TRUE)
3786 || match_optname(opts, "videocolours", 10, TRUE)) {
3788 complain_about_duplicate(opts, 1);
3790 bad_negation(fullname, FALSE);
3792 } else if ((opts = string_for_env_opt(fullname, opts, FALSE))
3796 if (!assign_videocolors(opts)) {
3797 config_error_add("Unknown error handling '%s'", fullname);
3802 /* videoshades:string */
3803 fullname = "videoshades";
3804 if (match_optname(opts, fullname, 6, TRUE)) {
3806 complain_about_duplicate(opts, 1);
3808 bad_negation(fullname, FALSE);
3810 } else if ((opts = string_for_env_opt(fullname, opts, FALSE))
3814 if (!assign_videoshades(opts)) {
3815 config_error_add("Unknown error handling '%s'", fullname);
3820 #endif /* VIDEOSHADES */
3824 /* video:string -- must be after longer tests */
3826 if (match_optname(opts, fullname, 5, TRUE)) {
3828 complain_about_duplicate(opts, 1);
3830 bad_negation(fullname, FALSE);
3832 } else if ((opts = string_for_env_opt(fullname, opts, FALSE))
3836 if (!assign_video(opts)) {
3837 config_error_add("Unknown error handling '%s'", fullname);
3842 #endif /* NO_TERMS */
3843 /* soundcard:string -- careful not to match boolean 'sound' */
3844 fullname = "soundcard";
3845 if (match_optname(opts, fullname, 6, TRUE)) {
3847 complain_about_duplicate(opts, 1);
3849 bad_negation(fullname, FALSE);
3851 } else if ((opts = string_for_env_opt(fullname, opts, FALSE))
3855 if (!assign_soundcard(opts)) {
3856 config_error_add("Unknown error handling '%s'", fullname);
3865 * map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12
3866 * |ascii8x12|ascii16x12|ascii12x16|ascii10x18|fit_to_screen
3867 * |ascii_fit_to_screen|tiles_fit_to_screen]
3869 fullname = "map_mode";
3870 if (match_optname(opts, fullname, sizeof "map_mode" - 1, TRUE)) {
3872 complain_about_duplicate(opts, 1);
3873 op = string_for_opt(opts, negated);
3874 if (op != empty_optstr && !negated) {
3875 if (!strcmpi(op, "tiles"))
3876 iflags.wc_map_mode = MAP_MODE_TILES;
3877 else if (!strncmpi(op, "ascii4x6", sizeof "ascii4x6" - 1))
3878 iflags.wc_map_mode = MAP_MODE_ASCII4x6;
3879 else if (!strncmpi(op, "ascii6x8", sizeof "ascii6x8" - 1))
3880 iflags.wc_map_mode = MAP_MODE_ASCII6x8;
3881 else if (!strncmpi(op, "ascii8x8", sizeof "ascii8x8" - 1))
3882 iflags.wc_map_mode = MAP_MODE_ASCII8x8;
3883 else if (!strncmpi(op, "ascii16x8", sizeof "ascii16x8" - 1))
3884 iflags.wc_map_mode = MAP_MODE_ASCII16x8;
3885 else if (!strncmpi(op, "ascii7x12", sizeof "ascii7x12" - 1))
3886 iflags.wc_map_mode = MAP_MODE_ASCII7x12;
3887 else if (!strncmpi(op, "ascii8x12", sizeof "ascii8x12" - 1))
3888 iflags.wc_map_mode = MAP_MODE_ASCII8x12;
3889 else if (!strncmpi(op, "ascii16x12", sizeof "ascii16x12" - 1))
3890 iflags.wc_map_mode = MAP_MODE_ASCII16x12;
3891 else if (!strncmpi(op, "ascii12x16", sizeof "ascii12x16" - 1))
3892 iflags.wc_map_mode = MAP_MODE_ASCII12x16;
3893 else if (!strncmpi(op, "ascii10x18", sizeof "ascii10x18" - 1))
3894 iflags.wc_map_mode = MAP_MODE_ASCII10x18;
3895 else if (!strncmpi(op, "fit_to_screen",
3896 sizeof "fit_to_screen" - 1))
3897 iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
3898 else if (!strncmpi(op, "ascii_fit_to_screen",
3899 sizeof "ascii_fit_to_screen" - 1))
3900 iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
3901 else if (!strncmpi(op, "tiles_fit_to_screen",
3902 sizeof "tiles_fit_to_screen" - 1))
3903 iflags.wc_map_mode = MAP_MODE_TILES_FIT_TO_SCREEN;
3905 config_error_add("Unknown %s parameter '%s'", fullname, op);
3908 } else if (negated) {
3909 bad_negation(fullname, TRUE);
3916 * scroll_amount:nn */
3917 fullname = "scroll_amount";
3918 if (match_optname(opts, fullname, sizeof "scroll_amount" - 1, TRUE)) {
3920 complain_about_duplicate(opts, 1);
3921 op = string_for_opt(opts, negated);
3922 if ((negated && op == empty_optstr)
3923 || (!negated && op != empty_optstr)) {
3924 iflags.wc_scroll_amount = negated ? 1 : atoi(op);
3925 } else if (negated) {
3926 bad_negation(fullname, TRUE);
3933 * scroll_margin:nn */
3934 fullname = "scroll_margin";
3935 if (match_optname(opts, fullname, sizeof "scroll_margin" - 1, TRUE)) {
3937 complain_about_duplicate(opts, 1);
3938 op = string_for_opt(opts, negated);
3939 if ((negated && op == empty_optstr)
3940 || (!negated && op != empty_optstr)) {
3941 iflags.wc_scroll_margin = negated ? 5 : atoi(op);
3942 } else if (negated) {
3943 bad_negation(fullname, TRUE);
3949 fullname = "subkeyvalue";
3950 if (match_optname(opts, fullname, 5, TRUE)) {
3951 /* no duplicate complaint here */
3953 bad_negation(fullname, FALSE);
3957 op = string_for_opt(opts, 0);
3958 if (op == empty_optstr)
3961 map_subkeyvalue(op);
3970 fullname = "tile_width";
3971 if (match_optname(opts, fullname, sizeof "tile_width" - 1, TRUE)) {
3973 complain_about_duplicate(opts, 1);
3974 op = string_for_opt(opts, negated);
3975 if ((negated && op == empty_optstr)
3976 || (!negated && op != empty_optstr)) {
3977 iflags.wc_tile_width = negated ? 0 : atoi(op);
3978 } else if (negated) {
3979 bad_negation(fullname, TRUE);
3986 fullname = "tile_file";
3987 if (match_optname(opts, fullname, sizeof "tile_file" - 1, TRUE)) {
3989 complain_about_duplicate(opts, 1);
3990 if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
3991 if (iflags.wc_tile_file)
3992 free(iflags.wc_tile_file);
3993 iflags.wc_tile_file = dupstr(op);
4000 fullname = "tile_height";
4001 if (match_optname(opts, fullname, sizeof "tile_height" - 1, TRUE)) {
4003 complain_about_duplicate(opts, 1);
4004 op = string_for_opt(opts, negated);
4005 if ((negated && op == empty_optstr)
4006 || (!negated && op != empty_optstr)) {
4007 iflags.wc_tile_height = negated ? 0 : atoi(op);
4008 } else if (negated) {
4009 bad_negation(fullname, TRUE);
4016 * vary_msgcount:nn */
4017 fullname = "vary_msgcount";
4018 if (match_optname(opts, fullname, sizeof "vary_msgcount" - 1, TRUE)) {
4020 complain_about_duplicate(opts, 1);
4021 op = string_for_opt(opts, negated);
4022 if ((negated && op == empty_optstr)
4023 || (!negated && op != empty_optstr)) {
4024 iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
4025 } else if (negated) {
4026 bad_negation(fullname, TRUE);
4033 * windowtype: option to choose the interface for binaries built
4034 * with support for more than one interface (tty + X11, for instance).
4036 * Ideally, 'windowtype' should be processed first, because it
4037 * causes the wc_ and wc2_ flags to be set up.
4038 * For user, making it be first in a config file is trivial, use
4039 * OPTIONS=windowtype:Foo
4040 * as the first non-comment line of the file.
4041 * Making it first in NETHACKOPTIONS requires it to be at the _end_
4042 * because comma-separated option strings are processed from right
4045 fullname = "windowtype";
4046 if (match_optname(opts, fullname, 3, TRUE)) {
4047 if (iflags.windowtype_locked)
4050 complain_about_duplicate(opts, 1);
4052 bad_negation(fullname, FALSE);
4054 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
4056 if (!iflags.windowtype_deferred) {
4057 char buf[WINTYPELEN];
4059 nmcpy(buf, op, WINTYPELEN);
4060 choose_windows(buf);
4062 nmcpy(chosen_windowtype, op, WINTYPELEN);
4070 fullname = "windowchain";
4071 if (match_optname(opts, fullname, 3, TRUE)) {
4073 bad_negation(fullname, FALSE);
4075 } else if ((op = string_for_env_opt(fullname, opts, FALSE))
4077 char buf[WINTYPELEN];
4079 nmcpy(buf, op, WINTYPELEN);
4080 addto_windowchain(buf);
4088 * setting window colors
4089 * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd
4091 fullname = "windowcolors";
4092 if (match_optname(opts, fullname, 7, TRUE)) {
4094 complain_about_duplicate(opts, 1);
4095 if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
4096 if (!wc_set_window_colors(op)) {
4097 config_error_add("Could not set %s '%s'", fullname, op);
4100 } else if (negated) {
4101 bad_negation(fullname, TRUE);
4107 #ifdef CURSES_GRAPHICS
4109 * term_cols:amount or term_rows:amount */
4110 fullname = "term_cols";
4111 if (match_optname(opts, fullname, 8, TRUE)
4112 /* alternate spelling */
4113 || match_optname(opts, "term_columns", 9, TRUE)
4114 /* different option but identical handlng */
4115 || (fullname = "term_rows", match_optname(opts, fullname, 8, TRUE))) {
4118 if ((op = string_for_opt(opts, negated)) != empty_optstr) {
4121 bad_negation(fullname, FALSE);
4124 /* just checks atol() sanity, not logical window size sanity */
4125 } else if (ltmp <= 0L || ltmp >= (long) LARGEST_INT) {
4126 config_error_add("Invalid %s: %ld", fullname, ltmp);
4130 if (!strcmp(fullname, "term_rows"))
4131 iflags.wc2_term_rows = (int) ltmp;
4132 else /* !strcmp(fullname, "term_cols") */
4133 iflags.wc2_term_cols = (int) ltmp;
4141 fullname = "petattr";
4142 if (match_optname(opts, fullname, sizeof "petattr" - 1, TRUE)) {
4143 op = string_for_opt(opts, negated);
4144 if (op != empty_optstr && negated) {
4145 bad_negation(fullname, TRUE);
4147 } else if (op != empty_optstr) {
4148 #ifdef CURSES_GRAPHICS
4149 int itmp = curses_read_attrs(op);
4152 config_error_add("Unknown %s parameter '%s'", fullname, opts);
4155 iflags.wc2_petattr = itmp;
4157 /* non-curses windowports will not use this flag anyway
4158 * but the above will not compile if we don't have curses.
4159 * Just set it to a sensible default: */
4160 iflags.wc2_petattr = ATR_INVERSE;
4162 } else if (negated) {
4163 iflags.wc2_petattr = ATR_NONE;
4166 iflags.hilite_pet = (iflags.wc2_petattr != ATR_NONE);
4174 * windowborders:n */
4175 fullname = "windowborders";
4176 if (match_optname(opts, fullname, 10, TRUE)) {
4177 op = string_for_opt(opts, negated);
4178 if (negated && op != empty_optstr) {
4179 bad_negation(fullname, TRUE);
4186 else if (op == empty_optstr)
4188 else /* Value supplied; expect 0 (off), 1 (on), or 2 (auto) */
4191 if (itmp < 0 || itmp > 2) {
4192 config_error_add("Invalid %s (should be 0, 1, or 2): %s",
4196 iflags.wc2_windowborders = itmp;
4201 #endif /* CURSES_GRAPHICS */
4205 fullname = "statuslines";
4206 if (match_optname(opts, fullname, 11, TRUE)) {
4209 op = string_for_opt(opts, negated);
4211 bad_negation(fullname, TRUE);
4214 } else if (op != empty_optstr) {
4217 if (itmp < 2 || itmp > 3) {
4218 config_error_add("'%s' requires a value of 2 or 3", fullname);
4221 iflags.wc2_statuslines = itmp;
4228 /* menustyle:traditional or combination or full or partial */
4229 fullname = "menustyle";
4230 if (match_optname(opts, fullname, 4, TRUE)) {
4232 boolean val_required = (strlen(opts) > 5 && !negated);
4235 complain_about_duplicate(opts, 1);
4236 if ((op = string_for_opt(opts, !val_required)) == empty_optstr) {
4238 return FALSE; /* string_for_opt gave feedback */
4239 tmp = negated ? 'n' : 'f';
4244 case 'n': /* none */
4245 case 't': /* traditional: prompt for class(es) by symbol,
4246 prompt for each item within class(es) one at a time */
4247 flags.menu_style = MENU_TRADITIONAL;
4249 case 'c': /* combination: prompt for class(es) by symbol,
4250 choose items within selected class(es) by menu */
4251 flags.menu_style = MENU_COMBINATION;
4253 case 'f': /* full: choose class(es) by first menu,
4254 choose items within selected class(es) by second menu */
4255 flags.menu_style = MENU_FULL;
4257 case 'p': /* partial: skip class filtering,
4258 choose items among all classes by menu */
4259 flags.menu_style = MENU_PARTIAL;
4262 config_error_add("Unknown %s parameter '%s'", fullname, op);
4268 fullname = "menu_headings";
4269 if (match_optname(opts, fullname, 12, TRUE)) {
4273 complain_about_duplicate(opts, 1);
4275 bad_negation(fullname, FALSE);
4277 } else if ((opts = string_for_env_opt(fullname, opts, FALSE))
4281 tmpattr = match_str2attr(opts, TRUE);
4285 iflags.menu_headings = tmpattr;
4289 /* check for menu command mapping */
4290 for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
4291 fullname = default_menu_cmd_info[i].name;
4293 complain_about_duplicate(opts, 1);
4294 if (match_optname(opts, fullname, (int) strlen(fullname), TRUE)) {
4296 bad_negation(fullname, FALSE);
4298 } else if ((op = string_for_opt(opts, FALSE)) != empty_optstr) {
4299 char c, op_buf[BUFSZ];
4301 escapes(op, op_buf);
4304 if (illegal_menu_cmd_key(c))
4307 add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
4313 /* hilite fields in status prompt */
4314 fullname = "hilite_status";
4315 if (match_optname(opts, fullname, 13, TRUE)) {
4316 #ifdef STATUS_HILITES
4318 complain_about_duplicate(opts, 1);
4319 op = string_for_opt(opts, TRUE);
4320 if (op != empty_optstr && negated) {
4321 clear_status_hilites();
4323 } else if (op == empty_optstr) {
4324 config_error_add("Value is mandatory for hilite_status");
4327 if (!parse_status_hl1(op, tfrom_file))
4331 config_error_add("'%s' is not supported", fullname);
4336 /* control over whether highlights should be displayed, and for how long */
4337 fullname = "statushilites";
4338 if (match_optname(opts, fullname, 9, TRUE)) {
4339 #ifdef STATUS_HILITES
4341 iflags.hilite_delta = 0L;
4343 op = string_for_opt(opts, TRUE);
4344 iflags.hilite_delta = (op == empty_optstr || !*op) ? 3L : atol(op);
4345 if (iflags.hilite_delta < 0L)
4346 iflags.hilite_delta = 1L;
4349 reset_status_hilites();
4352 config_error_add("'%s' is not supported", fullname);
4357 fullname = "DECgraphics";
4358 if (match_optname(opts, fullname, 3, TRUE)) {
4359 #ifdef BACKWARD_COMPAT
4360 boolean badflag = FALSE;
4363 complain_about_duplicate(opts, 1);
4365 /* There is no rogue level DECgraphics-specific set */
4366 if (symset[PRIMARY].name) {
4369 symset[PRIMARY].name = dupstr(fullname);
4370 if (!read_sym_file(PRIMARY)) {
4372 clear_symsetentry(PRIMARY, TRUE);
4374 switch_symbols(TRUE);
4377 config_error_add("Failure to load symbol set %s.", fullname);
4383 config_error_add("'%s' no longer supported; use 'symset:%s' instead",
4384 fullname, fullname);
4387 } /* "DECgraphics" */
4389 fullname = "IBMgraphics";
4390 if (match_optname(opts, fullname, 3, TRUE)) {
4391 #ifdef BACKWARD_COMPAT
4392 const char *sym_name = fullname;
4393 boolean badflag = FALSE;
4396 complain_about_duplicate(opts, 1);
4398 for (i = 0; i < NUM_GRAPHICS; ++i) {
4399 if (symset[i].name) {
4403 sym_name = "RogueIBM";
4404 symset[i].name = dupstr(sym_name);
4405 if (!read_sym_file(i)) {
4407 clear_symsetentry(i, TRUE);
4413 config_error_add("Failure to load symbol set %s.", sym_name);
4416 switch_symbols(TRUE);
4417 if (!initial && Is_rogue_level(&u.uz))
4418 assign_graphics(ROGUESET);
4423 config_error_add("'%s' no longer supported; use 'symset:%s' instead",
4424 fullname, fullname);
4427 } /* "IBMgraphics" */
4429 fullname = "MACgraphics";
4430 if (match_optname(opts, fullname, 3, TRUE)) {
4431 #if defined(MAC_GRAPHICS_ENV) && defined(BACKWARD_COMPAT)
4432 boolean badflag = FALSE;
4435 complain_about_duplicate(opts, 1);
4437 if (symset[PRIMARY].name) {
4440 symset[PRIMARY].name = dupstr(fullname);
4441 if (!read_sym_file(PRIMARY)) {
4443 clear_symsetentry(PRIMARY, TRUE);
4447 config_error_add("Failure to load symbol set %s.", fullname);
4450 switch_symbols(TRUE);
4451 if (!initial && Is_rogue_level(&u.uz))
4452 assign_graphics(ROGUESET);
4456 #else /* !(MAC_GRAPHICS_ENV && BACKWARD_COMPAT) */
4457 config_error_add("'%s' %s; use 'symset:%s' instead",
4459 #ifdef MAC_GRAPHICS_ENV /* implies BACKWARD_COMPAT is not defined */
4460 "no longer supported",
4466 #endif /* ?(MAC_GRAPHICS_ENV && BACKWARD_COMPAT) */
4467 } /* "MACgraphics" */
4470 * OK, if we still haven't recognized the option, check the boolean
4473 for (i = 0; boolopt[i].name; i++) {
4474 if (match_optname(opts, boolopt[i].name, 3, TRUE)) {
4475 /* options that don't exist */
4476 if (!boolopt[i].addr) {
4477 if (!initial && !negated)
4478 pline_The("\"%s\" option is not available.",
4482 /* options that must come from config file */
4483 if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
4484 rejectoption(boolopt[i].name);
4488 op = string_for_opt(opts, TRUE);
4489 if (op != empty_optstr) {
4492 "Negated boolean '%s' should not have a parameter",
4496 if (!strcmp(op, "true") || !strcmp(op, "yes")) {
4498 } else if (!strcmp(op, "false") || !strcmp(op, "no")) {
4501 config_error_add("Illegal parameter for a boolean");
4505 if (iflags.debug_fuzzer && !initial) {
4506 /* don't randomly toggle this/these */
4507 if (boolopt[i].addr == &flags.silent)
4511 *(boolopt[i].addr) = !negated;
4513 /* 0 means boolean opts */
4514 if (duplicate_opt_detection(boolopt[i].name, 0))
4515 complain_about_duplicate(boolopt[i].name, 0);
4517 if (boolopt[i].addr == &iflags.rlecomp)
4518 set_savepref(iflags.rlecomp ? "rlecomp" : "!rlecomp");
4521 if (boolopt[i].addr == &iflags.zerocomp)
4522 set_savepref(iflags.zerocomp ? "zerocomp" : "externalcomp");
4524 if (boolopt[i].addr == &iflags.wc_ascii_map) {
4525 /* toggling ascii_map; set tiled_map to its opposite;
4526 what does it mean to turn off ascii map if tiled map
4527 isn't supported? -- right now, we do nothing */
4528 iflags.wc_tiled_map = negated;
4529 } else if (boolopt[i].addr == &iflags.wc_tiled_map) {
4530 /* toggling tiled_map; set ascii_map to its opposite;
4531 as with ascii_map, what does it mean to turn off tiled
4532 map if ascii map isn't supported? */
4533 iflags.wc_ascii_map = negated;
4535 /* only do processing below if setting with doset() */
4539 if (boolopt[i].addr == &flags.time
4540 #ifdef SCORE_ON_BOTL
4541 || boolopt[i].addr == &flags.showscore
4543 || boolopt[i].addr == &flags.showexp) {
4544 if (VIA_WINDOWPORT())
4545 status_initialize(REASSESS_ONLY);
4546 context.botl = TRUE;
4547 } else if (boolopt[i].addr == &flags.invlet_constant
4548 || boolopt[i].addr == &flags.sortpack
4549 || boolopt[i].addr == &iflags.implicit_uncursed) {
4550 if (!flags.invlet_constant)
4553 } else if (boolopt[i].addr == &flags.lit_corridor
4554 || boolopt[i].addr == &flags.dark_room) {
4556 * All corridor squares seen via night vision or
4557 * candles & lamps change. Update them by calling
4558 * newsym() on them. Don't do this if we are
4559 * initializing the options --- the vision system
4562 vision_recalc(2); /* shut down vision */
4563 vision_full_recalc = 1; /* delayed recalc */
4564 if (iflags.use_color)
4565 need_redraw = TRUE; /* darkroom refresh */
4566 } else if (boolopt[i].addr == &flags.showrace
4567 || boolopt[i].addr == &iflags.use_inverse
4568 || boolopt[i].addr == &iflags.hilite_pile
4569 || boolopt[i].addr == &iflags.perm_invent
4570 #ifdef CURSES_GRAPHICS
4571 || boolopt[i].addr == &iflags.cursesgraphics
4573 || boolopt[i].addr == &iflags.wc_ascii_map
4574 || boolopt[i].addr == &iflags.wc_tiled_map) {
4576 } else if (boolopt[i].addr == &iflags.hilite_pet) {
4577 #ifdef CURSES_GRAPHICS
4578 if (WINDOWPORT("curses")) {
4579 /* if we're enabling hilite_pet and petattr isn't set,
4580 set it to Inverse; if we're disabling, leave petattr
4581 alone so that re-enabling will get current value back */
4582 if (iflags.hilite_pet && !iflags.wc2_petattr)
4583 iflags.wc2_petattr = curses_read_attrs("I");
4587 } else if (boolopt[i].addr == &iflags.wc2_hitpointbar) {
4588 if (VIA_WINDOWPORT()) {
4589 /* [is reassessment really needed here?] */
4590 status_initialize(REASSESS_ONLY);
4594 } else if (boolopt[i].addr == &iflags.use_color) {
4604 } else if (boolopt[i].addr == &iflags.use_menu_color
4605 || boolopt[i].addr == &iflags.wc2_guicolor) {
4607 #endif /* TEXTCOLOR */
4613 /* Is it a symbol? */
4614 if (strstr(opts, "S_") == opts && parsesymbols(opts, PRIMARY)) {
4615 switch_symbols(TRUE);
4616 check_gold_symbol();
4620 /* out of valid options */
4621 config_error_add("Unknown option '%s'", opts);
4625 /* parse key:command */
4627 parsebindings(bindings)
4633 boolean ret = FALSE;
4635 /* break off first binding from the rest; parse the rest */
4636 if ((bind = index(bindings, ',')) != 0) {
4638 ret |= parsebindings(bind);
4641 /* parse a single binding: first split around : */
4642 if (! (bind = index(bindings, ':')))
4643 return FALSE; /* it's not a binding */
4646 /* read the key to be bound */
4647 key = txt2key(bindings);
4649 config_error_add("Unknown key binding key '%s'", bindings);
4653 bind = trimspaces(bind);
4655 /* is it a special key? */
4656 if (bind_specialkey(key, bind))
4659 /* is it a menu command? */
4660 for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
4661 if (!strcmp(default_menu_cmd_info[i].name, bind)) {
4662 if (illegal_menu_cmd_key(key)) {
4663 config_error_add("Bad menu key %s:%s", visctrl(key), bind);
4666 add_menu_cmd_alias(key, default_menu_cmd_info[i].cmd);
4671 /* extended command? */
4672 if (!bind_key(key, bind)) {
4673 config_error_add("Unknown key binding command '%s'", bind);
4679 static NEARDATA const char *menutype[] = { "traditional", "combination",
4680 "full", "partial" };
4682 static NEARDATA const char *burdentype[] = { "unencumbered", "burdened",
4683 "stressed", "strained",
4684 "overtaxed", "overloaded" };
4686 static NEARDATA const char *runmodes[] = { "teleport", "run", "walk",
4689 static NEARDATA const char *sortltype[] = { "none", "loot", "full" };
4692 * Convert the given string of object classes to a string of default object
4696 oc_to_str(src, dest)
4701 while ((i = (int) *src++) != 0) {
4702 if (i < 0 || i >= MAXOCLASSES)
4703 impossible("oc_to_str: illegal object class %d", i);
4705 *dest++ = def_oc_syms[i].sym;
4711 * Add the given mapping to the menu command map list. Always keep the
4712 * maps valid C strings.
4715 add_menu_cmd_alias(from_ch, to_ch)
4716 char from_ch, to_ch;
4718 if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS) {
4719 pline("out of menu map space.");
4721 mapped_menu_cmds[n_menu_mapped] = from_ch;
4722 mapped_menu_op[n_menu_mapped] = to_ch;
4724 mapped_menu_cmds[n_menu_mapped] = '\0';
4725 mapped_menu_op[n_menu_mapped] = '\0';
4730 get_menu_cmd_key(ch)
4733 char *found = index(mapped_menu_op, ch);
4736 int idx = (int) (found - mapped_menu_op);
4738 ch = mapped_menu_cmds[idx];
4744 * Map the given character to its corresponding menu command. If it
4745 * doesn't match anything, just return the original.
4751 char *found = index(mapped_menu_cmds, ch);
4754 int idx = (int) (found - mapped_menu_cmds);
4756 ch = mapped_menu_op[idx];
4762 show_menu_controls(win, dolist)
4769 putstr(win, 0, "Menu control keys:");
4771 putstr(win, 0, "
\83\81\83j
\83\85\81[
\90§
\8cä
\83L
\81[:");
4775 for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
4776 Sprintf(buf, "%-8s %s",
4777 visctrl(get_menu_cmd_key(default_menu_cmd_info[i].cmd)),
4778 default_menu_cmd_info[i].desc);
4779 putstr(win, 0, buf);
4783 fmt3[] = " %-12s %-2s %-2s %s",
4784 fmt2[] = " %-12s %-2s %-2s",
4785 fmt1[] = " %10s %-2s %s",
4786 fmt0[] = " %14s %s";
4790 putstr(win, 0, "Selection: On page Full menu");
4792 putstr(win, 0, "
\91I
\91ð:
\83y
\81[
\83W
\8a®
\91S
\83\81\83j
\83\85\81[");
4794 Sprintf(buf, fmt2, "Select all",
4796 Sprintf(buf, fmt2, "
\91S
\82Ä
\91I
\91ð",
4797 visctrl(get_menu_cmd_key(MENU_SELECT_PAGE)),
4798 visctrl(get_menu_cmd_key(MENU_SELECT_ALL)));
4799 putstr(win, 0, buf);
4801 Sprintf(buf, fmt2, "Deselect all",
4803 Sprintf(buf, fmt2, "
\91S
\82Ä
\91I
\91ð
\89ð
\8f\9c",
4804 visctrl(get_menu_cmd_key(MENU_UNSELECT_PAGE)),
4805 visctrl(get_menu_cmd_key(MENU_UNSELECT_ALL)));
4806 putstr(win, 0, buf);
4808 Sprintf(buf, fmt2, "Invert all",
4810 Sprintf(buf, fmt2, "
\91S
\82Ä
\94½
\93]",
4811 visctrl(get_menu_cmd_key(MENU_INVERT_PAGE)),
4812 visctrl(get_menu_cmd_key(MENU_INVERT_ALL)));
4813 putstr(win, 0, buf);
4815 Sprintf(buf, fmt3, "Text match", "",
4817 Sprintf(buf, fmt3, "
\83e
\83L
\83X
\83g
\83}
\83b
\83`", "",
4818 visctrl(get_menu_cmd_key(MENU_SEARCH)),
4820 "Search and toggle matching entries");
4822 "
\8c\9f\8dõ
\82µ
\82Ä
\83}
\83b
\83`
\82µ
\82½
\83G
\83\93\83g
\83\8a\82ð
\83g
\83O
\83\8b");
4823 putstr(win, 0, buf);
4826 putstr(win, 0, "Navigation:");
4828 putstr(win, 0, "
\91\80\8dì:");
4830 Sprintf(buf, fmt1, "Go to ",
4832 Sprintf(buf, fmt1, "
\88Ú
\93® ",
4833 visctrl(get_menu_cmd_key(MENU_NEXT_PAGE)),
4837 "
\8e\9f\82Ì
\83y
\81[
\83W");
4838 putstr(win, 0, buf);
4839 Sprintf(buf, fmt1, "",
4840 visctrl(get_menu_cmd_key(MENU_PREVIOUS_PAGE)),
4844 "
\91O
\82Ì
\83y
\81[
\83W");
4845 putstr(win, 0, buf);
4846 Sprintf(buf, fmt1, "",
4847 visctrl(get_menu_cmd_key(MENU_FIRST_PAGE)),
4851 "
\90æ
\93ª
\83y
\81[
\83W");
4852 putstr(win, 0, buf);
4853 Sprintf(buf, fmt1, "",
4854 visctrl(get_menu_cmd_key(MENU_LAST_PAGE)),
4858 "
\8dÅ
\8fI
\83y
\81[
\83W");
4859 putstr(win, 0, buf);
4861 Sprintf(buf, fmt0, "SPACE", "Next page, if any, otherwise RETURN");
4863 Sprintf(buf, fmt0, "SPACE", "
\82 \82ê
\82Î
\8e\9f\82Ì
\83y
\81[
\83W
\81A
\82È
\82¯
\82ê
\82ÎRETURN");
4864 putstr(win, 0, buf);
4865 Sprintf(buf, fmt0, "RETURN/ENTER",
4867 "Finish menu with any selection(s) made");
4869 "
\91I
\91ð
\82µ
\82Ä
\83\81\83j
\83\85\81[
\8fI
\97¹");
4870 putstr(win, 0, buf);
4871 Sprintf(buf, fmt0, "ESCAPE",
4873 "Cancel menu without selecting anything");
4875 "
\89½
\82à
\91I
\91ð
\82¹
\82¸
\82É
\83\81\83j
\83\85\81[
\82ð
\83L
\83\83\83\93\83Z
\83\8b");
4876 putstr(win, 0, buf);
4880 #if defined(MICRO) || defined(MAC) || defined(WIN32)
4881 #define OPTIONS_HEADING "OPTIONS"
4883 #define OPTIONS_HEADING "NETHACKOPTIONS"
4886 static char fmtstr_doset[] = "%s%-15s [%s] ";
4887 static char fmtstr_doset_tab[] = "%s\t[%s]";
4889 static char n_currently_set[] = "(%d currently set)";
4891 static char n_currently_set[] = "(%d
\8cÂ
\90Ý
\92è
\92\86)";
4893 /* doset('O' command) menu entries for compound options */
4895 doset_add_menu(win, option, indexoffset)
4896 winid win; /* window to add to */
4897 const char *option; /* option name */
4898 int indexoffset; /* value to add to index in compopt[], or zero
4899 if option cannot be changed */
4901 const char *value = "unknown"; /* current value */
4902 char buf[BUFSZ], buf2[BUFSZ];
4907 if (indexoffset == 0) {
4909 value = get_compopt_value(option, buf2);
4911 for (i = 0; compopt[i].name; i++)
4912 if (strcmp(option, compopt[i].name) == 0)
4915 if (compopt[i].name) {
4916 any.a_int = i + 1 + indexoffset;
4917 value = get_compopt_value(option, buf2);
4919 /* We are trying to add an option not found in compopt[].
4920 This is almost certainly bad, but we'll let it through anyway
4921 (with a zero value, so it can't be selected). */
4925 /* " " replaces "a - " -- assumes menus follow that style */
4926 if (!iflags.menu_tab_sep)
4927 Sprintf(buf, fmtstr_doset, any.a_int ? "" : " ", option,
4930 Sprintf(buf, fmtstr_doset_tab, option, value);
4931 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
4935 opts_add_others(win, name, id, bufx, nset)
4942 char buf[BUFSZ], buf2[BUFSZ];
4943 anything any = zeroany;
4947 Sprintf(buf2, n_currently_set, nset);
4949 Sprintf(buf2, "%s", bufx);
4950 if (!iflags.menu_tab_sep)
4951 Sprintf(buf, fmtstr_doset, any.a_int ? "" : " ",
4954 Sprintf(buf, fmtstr_doset_tab, name, buf2);
4955 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
4959 count_apes(VOID_ARGS)
4962 struct autopickup_exception *ape = apelist;
4972 enum opt_other_enums {
4973 OPT_OTHER_MSGTYPE = -4,
4974 OPT_OTHER_MENUCOLOR = -3,
4975 OPT_OTHER_STATHILITE = -2,
4976 OPT_OTHER_APEXC = -1
4977 /* these must be < 0 */
4980 static struct other_opts {
4983 enum opt_other_enums code;
4984 int NDECL((*othr_count_func));
4986 { "autopickup exceptions", SET_IN_GAME, OPT_OTHER_APEXC, count_apes },
4987 { "menu colors", SET_IN_GAME, OPT_OTHER_MENUCOLOR, count_menucolors },
4988 { "message types", SET_IN_GAME, OPT_OTHER_MSGTYPE, msgtype_count },
4989 #ifdef STATUS_HILITES
4990 { "status hilite rules", SET_IN_GAME, OPT_OTHER_STATHILITE,
4991 count_status_hilites },
4993 { (char *) 0, 0, (enum opt_other_enums) 0 },
4996 /* the 'O' command */
4998 doset() /* changing options via menu by Per Liboriussen */
5000 static boolean made_fmtstr = FALSE;
5003 int i = 0, pass, boolcount, pick_cnt, pick_idx, opt_indx;
5007 menu_item *pick_list;
5008 int indexoffset, startpass, endpass, optflags;
5009 boolean setinitial = FALSE, fromfile = FALSE;
5010 unsigned longest_name_len;
5012 tmpwin = create_nhwindow(NHW_MENU);
5015 #ifdef notyet /* SYSCF */
5016 /* XXX I think this is still fragile. Fixing initial/from_file and/or
5017 changing the SET_* etc to bitmaps will let me make this better. */
5019 startpass = SET_IN_SYS;
5022 startpass = DISP_IN_GAME;
5023 endpass = (wizard) ? SET_IN_WIZGAME : SET_IN_GAME;
5025 if (!made_fmtstr && !iflags.menu_tab_sep) {
5026 /* spin through the options to find the longest name
5027 and adjust the format string accordingly */
5028 longest_name_len = 0;
5029 for (pass = 0; pass <= 2; pass++)
5030 for (i = 0; (name = ((pass == 0) ? boolopt[i].name
5031 : (pass == 1) ? compopt[i].name
5032 : othropt[i].name)) != 0; i++) {
5033 if (pass == 0 && !boolopt[i].addr)
5035 optflags = (pass == 0) ? boolopt[i].optflags
5036 : (pass == 1) ? compopt[i].optflags
5037 : othropt[i].optflags;
5038 if (optflags < startpass || optflags > endpass)
5040 if ((is_wc_option(name) && !wc_supported(name))
5041 || (is_wc2_option(name) && !wc2_supported(name)))
5044 if (strlen(name) > longest_name_len)
5045 longest_name_len = strlen(name);
5047 Sprintf(fmtstr_doset, "%%s%%-%us [%%s]", longest_name_len);
5052 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
5054 "Booleans (selecting will toggle value):", MENU_UNSELECTED);
5056 "
\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);
5058 /* first list any other non-modifiable booleans, then modifiable ones */
5059 for (pass = 0; pass <= 1; pass++)
5060 for (i = 0; (name = boolopt[i].name) != 0; i++)
5061 if ((bool_p = boolopt[i].addr) != 0
5062 && ((boolopt[i].optflags <= DISP_IN_GAME && pass == 0)
5063 || (boolopt[i].optflags >= SET_IN_GAME && pass == 1))) {
5064 if (bool_p == &flags.female)
5065 continue; /* obsolete */
5066 if (boolopt[i].optflags == SET_IN_WIZGAME && !wizard)
5068 if ((is_wc_option(name) && !wc_supported(name))
5069 || (is_wc2_option(name) && !wc2_supported(name)))
5072 any.a_int = (pass == 0) ? 0 : i + 1;
5073 if (!iflags.menu_tab_sep)
5074 Sprintf(buf, fmtstr_doset, (pass == 0) ? " " : "",
5075 name, *bool_p ? "true" : "false");
5077 Sprintf(buf, fmtstr_doset_tab,
5078 name, *bool_p ? "true" : "false");
5079 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
5084 indexoffset = boolcount;
5086 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
5088 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
5089 "Compounds (selecting will prompt for new value):",
5092 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
5093 "
\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",
5097 /* deliberately put playmode, name, role+race+gender+align first */
5098 doset_add_menu(tmpwin, "playmode", 0);
5099 doset_add_menu(tmpwin, "name", 0);
5100 doset_add_menu(tmpwin, "role", 0);
5101 doset_add_menu(tmpwin, "race", 0);
5102 doset_add_menu(tmpwin, "gender", 0);
5103 doset_add_menu(tmpwin, "align", 0);
5105 for (pass = startpass; pass <= endpass; pass++)
5106 for (i = 0; (name = compopt[i].name) != 0; i++)
5107 if (compopt[i].optflags == pass) {
5108 if (!strcmp(name, "playmode") || !strcmp(name, "name")
5109 || !strcmp(name, "role") || !strcmp(name, "race")
5110 || !strcmp(name, "gender") || !strcmp(name, "align"))
5112 if ((is_wc_option(name) && !wc_supported(name))
5113 || (is_wc2_option(name) && !wc2_supported(name)))
5116 doset_add_menu(tmpwin, name,
5117 (pass == DISP_IN_GAME) ? 0 : indexoffset);
5121 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
5122 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
5123 "Other settings:", MENU_UNSELECTED);
5125 for (i = 0; (name = othropt[i].name) != 0; i++) {
5126 if ((is_wc_option(name) && !wc_supported(name))
5127 || (is_wc2_option(name) && !wc2_supported(name)))
5129 opts_add_others(tmpwin, name, othropt[i].code,
5130 (char *) 0, othropt[i].othr_count_func());
5133 #ifdef PREFIXES_IN_USE
5135 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
5136 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
5137 "Variable playground locations:", MENU_UNSELECTED);
5138 for (i = 0; i < PREFIX_COUNT; i++)
5139 doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
5142 end_menu(tmpwin, "Set what options?");
5144 end_menu(tmpwin, "
\82Ç
\82Ì
\83I
\83v
\83V
\83\87\83\93\82ð
\90Ý
\92è
\82µ
\82Ü
\82·
\82©
\81H");
5145 need_redraw = FALSE;
5146 if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) {
5148 * Walk down the selection list and either invert the booleans
5149 * or prompt for new values. In most cases, call parseoptions()
5150 * to take care of options that require special attention, like
5153 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
5154 opt_indx = pick_list[pick_idx].item.a_int - 1;
5156 opt_indx++; /* -1 offset for select_menu() */
5157 if (opt_indx == OPT_OTHER_APEXC) {
5158 (void) special_handling("autopickup_exception", setinitial,
5160 #ifdef STATUS_HILITES
5161 } else if (opt_indx == OPT_OTHER_STATHILITE) {
5162 if (!status_hilite_menu()) {
5163 pline("Bad status hilite(s) specified.");
5165 if (wc2_supported("hilite_status"))
5166 preference_update("hilite_status");
5169 } else if (opt_indx == OPT_OTHER_MENUCOLOR) {
5170 (void) special_handling("menu_colors", setinitial,
5172 } else if (opt_indx == OPT_OTHER_MSGTYPE) {
5173 (void) special_handling("msgtype", setinitial, fromfile);
5174 } else if (opt_indx < boolcount) {
5175 /* boolean option */
5176 Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
5177 boolopt[opt_indx].name);
5178 (void) parseoptions(buf, setinitial, fromfile);
5179 if (wc_supported(boolopt[opt_indx].name)
5180 || wc2_supported(boolopt[opt_indx].name))
5181 preference_update(boolopt[opt_indx].name);
5183 /* compound option */
5184 opt_indx -= boolcount;
5186 if (!special_handling(compopt[opt_indx].name, setinitial,
5191 Sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
5193 Sprintf(buf, "%s
\82É
\89½
\82ð
\90Ý
\92è
\82·
\82é
\81H", compopt[opt_indx].name);
5196 if (abuf[0] == '\033')
5198 Sprintf(buf, "%s:", compopt[opt_indx].name);
5199 (void) strncat(eos(buf), abuf,
5200 (sizeof buf - 1 - strlen(buf)));
5202 (void) parseoptions(buf, setinitial, fromfile);
5204 if (wc_supported(compopt[opt_indx].name)
5205 || wc2_supported(compopt[opt_indx].name))
5206 preference_update(compopt[opt_indx].name);
5209 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
5212 destroy_nhwindow(tmpwin);
5214 check_gold_symbol();
5221 /* common to msg-types, menu-colors, autopickup-exceptions */
5223 handle_add_list_remove(optname, numtotal)
5224 const char *optname;
5229 int i, pick_cnt, opt_idx;
5230 menu_item *pick_list = (menu_item *) 0;
5231 static const struct action {
5234 } action_titles[] = {
5236 { 'a', "add new %s" }, /* [0] */
5238 { 'a', "
\90V
\82µ
\82¢%s
\82ð
\92Ç
\89Á" }, /* [0] */
5241 { 'l', "list %s" }, /* [1] */
5243 { 'l', "%s
\82ð
\88ê
\97\97\95\
\8e¦" }, /* [1] */
5246 { 'r', "remove existing %s" }, /* [2] */
5248 { 'r', "
\8aù
\82É
\82 \82é%s
\82ð
\8dí
\8f\9c" }, /* [2] */
5251 { 'x', "exit this menu" }, /* [3] */
5253 { 'x', "
\82±
\82Ì
\83\81\83j
\83\85\81[
\82ð
\95Â
\82¶
\82é" }, /* [3] */
5258 tmpwin = create_nhwindow(NHW_MENU);
5261 for (i = 0; i < SIZE(action_titles); i++) {
5265 /* omit list and remove if there aren't any yet */
5266 if (!numtotal && (i == 1 || i == 2))
5268 Sprintf(tmpbuf, action_titles[i].desc,
5269 (i == 1) ? makeplural(optname) : optname);
5270 add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr, 0, ATR_NONE,
5271 tmpbuf, (i == 3) ? MENU_SELECTED : MENU_UNSELECTED);
5274 end_menu(tmpwin, "Do what?");
5276 end_menu(tmpwin, "
\82Ç
\82¤
\82·
\82é
\81H");
5277 if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
5278 opt_idx = pick_list[0].item.a_int - 1;
5279 if (pick_cnt > 1 && opt_idx == 3)
5280 opt_idx = pick_list[1].item.a_int - 1;
5281 free((genericptr_t) pick_list);
5283 opt_idx = 3; /* none selected, exit menu */
5284 destroy_nhwindow(tmpwin);
5288 struct symsetentry *symset_list = 0; /* files.c will populate this with
5289 * list of available sets */
5292 special_handling(optname, setinitial, setfromfile)
5293 const char *optname;
5294 boolean setinitial, setfromfile;
5301 /* Special handling of menustyle, pickup_burden, pickup_types,
5302 * disclose, runmode, msg_window, menu_headings, sortloot,
5303 * and number_pad options.
5304 * Also takes care of interactive autopickup_exception_handling changes.
5306 if (!strcmp("menustyle", optname)) {
5307 const char *style_name;
5308 menu_item *style_pick = (menu_item *) 0;
5310 tmpwin = create_nhwindow(NHW_MENU);
5313 for (i = 0; i < SIZE(menutype); i++) {
5314 style_name = menutype[i];
5315 /* note: separate `style_name' variable used
5316 to avoid an optimizer bug in VAX C V2.3 */
5318 add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0, ATR_NONE,
5319 style_name, MENU_UNSELECTED);
5322 end_menu(tmpwin, "Select menustyle:");
5324 end_menu(tmpwin, "
\83\81\83j
\83\85\81[
\83X
\83^
\83C
\83\8b\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F");
5325 if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) {
5326 flags.menu_style = style_pick->item.a_int - 1;
5327 free((genericptr_t) style_pick);
5329 destroy_nhwindow(tmpwin);
5330 } else if (!strcmp("paranoid_confirmation", optname)) {
5331 menu_item *paranoia_picks = (menu_item *) 0;
5333 tmpwin = create_nhwindow(NHW_MENU);
5336 for (i = 0; paranoia[i].flagmask != 0; ++i) {
5337 if (paranoia[i].flagmask == PARANOID_BONES && !wizard)
5339 any.a_int = paranoia[i].flagmask;
5340 add_menu(tmpwin, NO_GLYPH, &any, *paranoia[i].argname, 0,
5341 ATR_NONE, paranoia[i].explain,
5342 (flags.paranoia_bits & paranoia[i].flagmask)
5346 end_menu(tmpwin, "Actions requiring extra confirmation:");
5347 i = select_menu(tmpwin, PICK_ANY, ¶noia_picks);
5349 /* player didn't cancel; we reset all the paranoia options
5350 here even if there were no items picked, since user
5351 could have toggled off preselected ones to end up with 0 */
5352 flags.paranoia_bits = 0;
5354 /* at least 1 item set, either preselected or newly picked */
5356 flags.paranoia_bits |= paranoia_picks[i].item.a_int;
5357 free((genericptr_t) paranoia_picks);
5360 destroy_nhwindow(tmpwin);
5361 } else if (!strcmp("pickup_burden", optname)) {
5362 const char *burden_name, *burden_letters = "ubsntl";
5363 menu_item *burden_pick = (menu_item *) 0;
5365 tmpwin = create_nhwindow(NHW_MENU);
5368 for (i = 0; i < SIZE(burdentype); i++) {
5369 burden_name = burdentype[i];
5371 add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0, ATR_NONE,
5372 burden_name, MENU_UNSELECTED);
5375 end_menu(tmpwin, "Select encumbrance level:");
5377 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");
5378 if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) {
5379 flags.pickup_burden = burden_pick->item.a_int - 1;
5380 free((genericptr_t) burden_pick);
5382 destroy_nhwindow(tmpwin);
5383 } else if (!strcmp("pickup_types", optname)) {
5384 /* parseoptions will prompt for the list of types */
5385 (void) parseoptions(strcpy(buf, "pickup_types"),
5386 setinitial, setfromfile);
5387 } else if (!strcmp("disclose", optname)) {
5388 /* order of disclose_names[] must correspond to
5389 disclosure_options in decl.c */
5390 static const char *disclosure_names[] = {
5391 "inventory", "attributes", "vanquished",
5392 "genocides", "conduct", "overview",
5394 int disc_cat[NUM_DISCLOSURE_OPTIONS];
5395 int pick_cnt, pick_idx, opt_idx;
5397 menu_item *disclosure_pick = (menu_item *) 0;
5399 tmpwin = create_nhwindow(NHW_MENU);
5402 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
5403 Sprintf(buf, "%-12s[%c%c]", disclosure_names[i],
5404 flags.end_disclose[i], disclosure_options[i]);
5406 add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0,
5407 ATR_NONE, buf, MENU_UNSELECTED);
5411 end_menu(tmpwin, "Change which disclosure options categories:");
5413 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");
5414 pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_pick);
5416 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
5417 opt_idx = disclosure_pick[pick_idx].item.a_int - 1;
5418 disc_cat[opt_idx] = 1;
5420 free((genericptr_t) disclosure_pick);
5421 disclosure_pick = (menu_item *) 0;
5423 destroy_nhwindow(tmpwin);
5425 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
5427 c = flags.end_disclose[i];
5429 Sprintf(buf, "Disclosure options for %s:",
5431 Sprintf(buf, "%s
\82Ì
\8fo
\97Í
\8c`
\8e®
\81F",
5432 disclosure_names[i]);
5433 tmpwin = create_nhwindow(NHW_MENU);
5436 /* 'y','n',and '+' work as alternate selectors; '-' doesn't */
5437 any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
5438 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
5440 "Never disclose, without prompting",
5442 "
\8am
\94F
\82¹
\82¸
\82É
\8fo
\97Í
\82à
\82µ
\82È
\82¢",
5443 (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
5444 any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
5445 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
5447 "Always disclose, without prompting",
5449 "
\8am
\94F
\82¹
\82¸
\82É
\8fo
\97Í
\82·
\82é",
5450 (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
5451 if (*disclosure_names[i] == 'v') {
5452 any.a_char = DISCLOSE_SPECIAL_WITHOUT_PROMPT; /* '#' */
5453 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
5455 "Always disclose, pick sort order from menu",
5457 "
\83\81\83j
\83\85\81[
\82©
\82ç
\83\
\81[
\83g
\8f\87\82ð
\91I
\82ñ
\82Å
\8fí
\82É
\8fo
\97Í
\82·
\82é",
5458 (c == any.a_char) ? MENU_SELECTED
5461 any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
5462 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
5464 "Prompt, with default answer of \"No\"",
5466 "
\8am
\94F
\82·
\82é
\81C
\83f
\83t
\83H
\83\8b\83g
\82Í
\81u
\8fo
\97Í
\82µ
\82È
\82¢
\81v",
5467 (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
5468 any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
5469 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
5471 "Prompt, with default answer of \"Yes\"",
5473 "
\8am
\94F
\82·
\82é
\81C
\83f
\83t
\83H
\83\8b\83g
\82Í
\81u
\8fo
\97Í
\82·
\82é
\81v",
5474 (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
5475 if (*disclosure_names[i] == 'v') {
5476 any.a_char = DISCLOSE_PROMPT_DEFAULT_SPECIAL; /* '?' */
5477 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
5479 "Prompt, with default answer of \"Ask\" to request sort menu",
5481 "
\8am
\94F
\82·
\82é
\81C
\83\
\81[
\83g
\83\81\83j
\83\85\81[
\82ð
\97v
\8b\81\82·
\82é
\95W
\8f\80\82Ì
\93\9a\82¦
\82Í \"Ask\"",
5482 (c == any.a_char) ? MENU_SELECTED
5485 end_menu(tmpwin, buf);
5486 n = select_menu(tmpwin, PICK_ONE, &disclosure_pick);
5488 flags.end_disclose[i] = disclosure_pick[0].item.a_char;
5489 if (n > 1 && flags.end_disclose[i] == c)
5490 flags.end_disclose[i] = disclosure_pick[1].item.a_char;
5491 free((genericptr_t) disclosure_pick);
5493 destroy_nhwindow(tmpwin);
5496 } else if (!strcmp("runmode", optname)) {
5497 const char *mode_name;
5498 menu_item *mode_pick = (menu_item *) 0;
5500 tmpwin = create_nhwindow(NHW_MENU);
5503 for (i = 0; i < SIZE(runmodes); i++) {
5504 mode_name = runmodes[i];
5506 add_menu(tmpwin, NO_GLYPH, &any, *mode_name, 0, ATR_NONE,
5507 mode_name, MENU_UNSELECTED);
5510 end_menu(tmpwin, "Select run/travel display mode:");
5512 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");
5513 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
5514 flags.runmode = mode_pick->item.a_int - 1;
5515 free((genericptr_t) mode_pick);
5517 destroy_nhwindow(tmpwin);
5518 } else if (!strcmp("whatis_coord", optname)) {
5519 menu_item *window_pick = (menu_item *) 0;
5521 char gp = iflags.getpos_coords;
5523 tmpwin = create_nhwindow(NHW_MENU);
5526 any.a_char = GPCOORDS_COMPASS;
5527 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMPASS, 0, ATR_NONE,
5528 "compass ('east' or '3s' or '2n,4w')",
5529 (gp == GPCOORDS_COMPASS) ? MENU_SELECTED : MENU_UNSELECTED);
5530 any.a_char = GPCOORDS_COMFULL;
5531 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMFULL, 0, ATR_NONE,
5532 "full compass ('east' or '3south' or '2north,4west')",
5533 (gp == GPCOORDS_COMFULL) ? MENU_SELECTED : MENU_UNSELECTED);
5534 any.a_char = GPCOORDS_MAP;
5535 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_MAP, 0, ATR_NONE,
5537 (gp == GPCOORDS_MAP) ? MENU_SELECTED : MENU_UNSELECTED);
5538 any.a_char = GPCOORDS_SCREEN;
5539 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_SCREEN, 0, ATR_NONE,
5540 "screen [row,column]",
5541 (gp == GPCOORDS_SCREEN) ? MENU_SELECTED : MENU_UNSELECTED);
5542 any.a_char = GPCOORDS_NONE;
5543 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_NONE, 0, ATR_NONE,
5544 "none (no coordinates displayed)",
5545 (gp == GPCOORDS_NONE) ? MENU_SELECTED : MENU_UNSELECTED);
5547 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
5548 Sprintf(buf, "map: upper-left: <%d,%d>, lower-right: <%d,%d>%s",
5549 1, 0, COLNO - 1, ROWNO - 1,
5550 flags.verbose ? "; column 0 unused, off left edge" : "");
5551 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
5552 if (strcmp(windowprocs.name, "tty")) /* only show for non-tty */
5553 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
5554 "screen: row is offset to accommodate tty interface's use of top line",
5557 #define COL80ARG flags.verbose ? "; column 80 is not used" : ""
5561 Sprintf(buf, "screen: upper-left: [%02d,%02d], lower-right: [%d,%d]%s",
5562 0 + 2, 1, ROWNO - 1 + 2, COLNO - 1, COL80ARG);
5564 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
5565 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
5567 "Select coordinate display when auto-describing a map position:");
5568 if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) {
5569 iflags.getpos_coords = window_pick[0].item.a_char;
5570 /* PICK_ONE doesn't unselect preselected entry when
5571 selecting another one */
5572 if (pick_cnt > 1 && iflags.getpos_coords == gp)
5573 iflags.getpos_coords = window_pick[1].item.a_char;
5574 free((genericptr_t) window_pick);
5576 destroy_nhwindow(tmpwin);
5577 } else if (!strcmp("whatis_filter", optname)) {
5578 menu_item *window_pick = (menu_item *) 0;
5580 char gf = iflags.getloc_filter;
5582 tmpwin = create_nhwindow(NHW_MENU);
5585 any.a_char = (GFILTER_NONE + 1);
5586 add_menu(tmpwin, NO_GLYPH, &any, 'n',
5587 0, ATR_NONE, "no filtering",
5588 (gf == GFILTER_NONE) ? MENU_SELECTED : MENU_UNSELECTED);
5589 any.a_char = (GFILTER_VIEW + 1);
5590 add_menu(tmpwin, NO_GLYPH, &any, 'v',
5591 0, ATR_NONE, "in view only",
5592 (gf == GFILTER_VIEW) ? MENU_SELECTED : MENU_UNSELECTED);
5593 any.a_char = (GFILTER_AREA + 1);
5594 add_menu(tmpwin, NO_GLYPH, &any, 'a',
5595 0, ATR_NONE, "in same area",
5596 (gf == GFILTER_AREA) ? MENU_SELECTED : MENU_UNSELECTED);
5598 "Select location filtering when going for next/previous map position:");
5599 if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) {
5600 iflags.getloc_filter = (window_pick[0].item.a_char - 1);
5601 /* PICK_ONE doesn't unselect preselected entry when
5602 selecting another one */
5603 if (pick_cnt > 1 && iflags.getloc_filter == gf)
5604 iflags.getloc_filter = (window_pick[1].item.a_char - 1);
5605 free((genericptr_t) window_pick);
5607 destroy_nhwindow(tmpwin);
5608 } else if (!strcmp("msg_window", optname)) {
5609 #if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS)
5610 if (WINDOWPORT("tty") || WINDOWPORT("curses")) {
5611 /* by Christian W. Cooper */
5612 menu_item *window_pick = (menu_item *) 0;
5614 tmpwin = create_nhwindow(NHW_MENU);
5617 if (!WINDOWPORT("curses")) {
5619 add_menu(tmpwin, NO_GLYPH, &any, 's', 0, ATR_NONE,
5620 "single", MENU_UNSELECTED);
5622 add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE,
5623 "combination", MENU_UNSELECTED);
5626 add_menu(tmpwin, NO_GLYPH, &any, 'f', 0, ATR_NONE, "full",
5629 add_menu(tmpwin, NO_GLYPH, &any, 'r', 0, ATR_NONE, "reversed",
5632 end_menu(tmpwin, "Select message history display type:");
5634 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");
5635 if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
5636 iflags.prevmsg_window = window_pick->item.a_char;
5637 free((genericptr_t) window_pick);
5639 destroy_nhwindow(tmpwin);
5641 #endif /* msg_window for tty or curses */
5642 pline("'%s' option is not supported for '%s'.",
5643 optname, windowprocs.name);
5644 } else if (!strcmp("sortloot", optname)) {
5645 const char *sortl_name;
5646 menu_item *sortl_pick = (menu_item *) 0;
5648 tmpwin = create_nhwindow(NHW_MENU);
5651 for (i = 0; i < SIZE(sortltype); i++) {
5652 sortl_name = sortltype[i];
5653 any.a_char = *sortl_name;
5654 add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0, ATR_NONE,
5655 sortl_name, (flags.sortloot == *sortl_name)
5656 ? MENU_SELECTED : MENU_UNSELECTED);
5658 end_menu(tmpwin, "Select loot sorting type:");
5659 n = select_menu(tmpwin, PICK_ONE, &sortl_pick);
5661 char c = sortl_pick[0].item.a_char;
5663 if (n > 1 && c == flags.sortloot)
5664 c = sortl_pick[1].item.a_char;
5666 free((genericptr_t) sortl_pick);
5668 destroy_nhwindow(tmpwin);
5669 } else if (!strcmp("align_message", optname)
5670 || !strcmp("align_status", optname)) {
5671 menu_item *window_pick = (menu_item *) 0;
5673 boolean msg = (*(optname + 6) == 'm');
5675 tmpwin = create_nhwindow(NHW_MENU);
5678 any.a_int = ALIGN_TOP;
5679 add_menu(tmpwin, NO_GLYPH, &any, 't', 0, ATR_NONE, "top",
5681 any.a_int = ALIGN_BOTTOM;
5682 add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, ATR_NONE, "bottom",
5684 any.a_int = ALIGN_LEFT;
5685 add_menu(tmpwin, NO_GLYPH, &any, 'l', 0, ATR_NONE, "left",
5687 any.a_int = ALIGN_RIGHT;
5688 add_menu(tmpwin, NO_GLYPH, &any, 'r', 0, ATR_NONE, "right",
5691 Sprintf(abuf, "Select %s window placement relative to the map:",
5692 msg ? "message" : "status");
5694 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",
5695 msg ? "
\83\81\83b
\83Z
\81[
\83W" : "
\8fó
\91Ô");
5697 end_menu(tmpwin, abuf);
5698 if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
5700 iflags.wc_align_message = window_pick->item.a_int;
5702 iflags.wc_align_status = window_pick->item.a_int;
5703 free((genericptr_t) window_pick);
5705 destroy_nhwindow(tmpwin);
5706 } else if (!strcmp("number_pad", optname)) {
5707 static const char *npchoices[] = {
5709 " 0 (off)", " 1 (on)", " 2 (on, MSDOS compatible)",
5711 "0 (
\96³
\8cø)", "1 (
\97L
\8cø)", "2 (
\97L
\8cø
\81CMSDOS
\8cÝ
\8a·)",
5713 " 3 (on, phone-style digit layout)",
5715 " 3 (
\97L
\8cø
\81C
\93d
\98b
\8e®
\82Ì
\90\94\8e\9a\94z
\92u)",
5717 " 4 (on, phone-style layout, MSDOS compatible)",
5719 " 4 (
\97L
\8cø
\81C
\93d
\98b
\8e®
\82Ì
\94z
\92u
\81CMSDOS
\8cÝ
\8a·)",
5721 "-1 (off, 'z' to move upper-left, 'y' to zap wands)"
5723 "-1 (
\96³
\8cø
\81C'z'
\82Å
\8d¶
\8fã
\82É
\88Ú
\93®
\81C'y'
\82Å
\8fñ
\82ð
\90U
\82é)"
5725 menu_item *mode_pick = (menu_item *) 0;
5727 tmpwin = create_nhwindow(NHW_MENU);
5730 for (i = 0; i < SIZE(npchoices); i++) {
5732 add_menu(tmpwin, NO_GLYPH, &any, 'a' + i, 0, ATR_NONE,
5733 npchoices[i], MENU_UNSELECTED);
5736 end_menu(tmpwin, "Select number_pad mode:");
5738 end_menu(tmpwin, "number_pad
\83\82\81[
\83h
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F");
5739 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
5740 switch (mode_pick->item.a_int - 1) {
5742 iflags.num_pad = FALSE;
5743 iflags.num_pad_mode = 0;
5746 iflags.num_pad = TRUE;
5747 iflags.num_pad_mode = 0;
5750 iflags.num_pad = TRUE;
5751 iflags.num_pad_mode = 1;
5754 iflags.num_pad = TRUE;
5755 iflags.num_pad_mode = 2;
5758 iflags.num_pad = TRUE;
5759 iflags.num_pad_mode = 3;
5761 /* last menu choice: number_pad == -1 */
5763 iflags.num_pad = FALSE;
5764 iflags.num_pad_mode = 1;
5767 reset_commands(FALSE);
5768 number_pad(iflags.num_pad ? 1 : 0);
5769 free((genericptr_t) mode_pick);
5771 destroy_nhwindow(tmpwin);
5772 } else if (!strcmp("menu_headings", optname)) {
5774 int mhattr = query_attr("How to highlight menu headings:");
5776 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");
5779 iflags.menu_headings = mhattr;
5780 } else if (!strcmp("msgtype", optname)) {
5781 int opt_idx, nmt, mttyp;
5785 nmt = msgtype_count();
5787 opt_idx = handle_add_list_remove("message type", nmt);
5789 opt_idx = handle_add_list_remove("
\83\81\83b
\83Z
\81[
\83W
\8c^", nmt);
5790 if (opt_idx == 3) { /* done */
5792 } else if (opt_idx == 0) { /* add new */
5795 getlin("What new message pattern?", mtbuf);
5797 getlin("
\90V
\82µ
\82¢
\83\81\83b
\83Z
\81[
\83W
\83p
\83^
\81[
\83\93\81F", mtbuf);
5798 if (*mtbuf == '\033')
5801 && test_regex_pattern(mtbuf, (const char *)0)
5802 && (mttyp = query_msgtype()) != -1
5803 && !msgtype_add(mttyp, mtbuf)) {
5805 pline("Error adding the message type.");
5807 pline("
\83\81\83b
\83Z
\81[
\83W
\8c^
\92Ç
\89Á
\83G
\83\89\81[
\81D");
5810 goto msgtypes_again;
5811 } else { /* list (1) or remove (2) */
5812 int pick_idx, pick_cnt;
5816 menu_item *pick_list = (menu_item *) 0;
5817 struct plinemsg_type *tmp = plinemsg_types;
5819 tmpwin = create_nhwindow(NHW_MENU);
5824 mtype = msgtype2name(tmp->msgtype);
5825 any.a_int = ++mt_idx;
5826 Sprintf(mtbuf, "%-5s \"", mtype);
5827 ln = sizeof mtbuf - strlen(mtbuf) - sizeof "\"";
5828 if (strlen(tmp->pattern) > ln)
5829 Strcat(strncat(mtbuf, tmp->pattern, ln - 3), "...\"");
5831 Strcat(strcat(mtbuf, tmp->pattern), "\"");
5832 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mtbuf,
5837 Sprintf(mtbuf, "%s message types",
5838 (opt_idx == 1) ? "List of" : "Remove which");
5840 Strcpy(mtbuf, (opt_idx == 1) ?
5841 "
\83\81\83b
\83Z
\81[
\83W
\8c^
\88ê
\97\97" : "
\8dí
\8f\9c\82·
\82é
\83\81\83b
\83Z
\81[
\83W
\8c^");
5843 end_menu(tmpwin, mtbuf);
5844 pick_cnt = select_menu(tmpwin,
5845 (opt_idx == 1) ? PICK_NONE : PICK_ANY,
5848 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
5849 free_one_msgtype(pick_list[pick_idx].item.a_int - 1
5851 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
5853 destroy_nhwindow(tmpwin);
5855 goto msgtypes_again;
5857 } else if (!strcmp("menu_colors", optname)) {
5858 int opt_idx, nmc, mcclr, mcattr;
5862 nmc = count_menucolors();
5864 opt_idx = handle_add_list_remove("menucolor", nmc);
5866 opt_idx = handle_add_list_remove("
\83\81\83j
\83\85\81[
\90F", nmc);
5867 if (opt_idx == 3) { /* done */
5869 /* in case we've made a change which impacts current persistent
5870 inventory window; we don't track whether an actual changed
5871 occurred, so just assume there was one and that it matters;
5872 if we're wrong, a redundant update is cheap... */
5873 if (iflags.use_menu_color)
5876 /* menu colors aren't being used; if any are defined, remind
5877 player how to use them */
5880 "To have menu colors become active, toggle 'menucolors' option to True.");
5883 } else if (opt_idx == 0) { /* add new */
5886 getlin("What new menucolor pattern?", mcbuf);
5888 getlin("
\90V
\82µ
\82¢
\83\81\83j
\83\85\81[
\90F
\83p
\83^
\81[
\83\93\81F", mcbuf);
5889 if (*mcbuf == '\033')
5890 goto menucolors_done;
5892 && test_regex_pattern(mcbuf, (const char *)0)
5893 && (mcclr = query_color((char *) 0)) != -1
5894 && (mcattr = query_attr((char *) 0)) != -1
5895 && !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
5897 pline("Error adding the menu color.");
5899 pline("
\83\81\83j
\83\85\81[
\90F
\92Ç
\89Á
\83G
\83\89\81[
\81D");
5902 goto menucolors_again;
5904 } else { /* list (1) or remove (2) */
5905 int pick_idx, pick_cnt;
5908 const char *sattr, *sclr;
5909 menu_item *pick_list = (menu_item *) 0;
5910 struct menucoloring *tmp = menu_colorings;
5911 char clrbuf[QBUFSZ];
5913 tmpwin = create_nhwindow(NHW_MENU);
5918 sattr = attr2attrname(tmp->attr);
5919 sclr = strcpy(clrbuf, clr2colorname(tmp->color));
5920 (void) strNsubst(clrbuf, " ", "-", 0);
5921 any.a_int = ++mc_idx;
5922 /* construct suffix */
5923 Sprintf(buf, "\"\"=%s%s%s", sclr,
5924 (tmp->attr != ATR_NONE) ? "&" : "",
5925 (tmp->attr != ATR_NONE) ? sattr : "");
5926 /* now main string */
5927 ln = sizeof buf - strlen(buf) - 1; /* length available */
5928 Strcpy(mcbuf, "\"");
5929 if (strlen(tmp->origstr) > ln)
5930 Strcat(strncat(mcbuf, tmp->origstr, ln - 3), "...");
5932 Strcat(mcbuf, tmp->origstr);
5933 /* combine main string and suffix */
5934 Strcat(mcbuf, &buf[1]); /* skip buf[]'s initial quote */
5935 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mcbuf,
5940 Sprintf(mcbuf, "%s menu colors",
5941 (opt_idx == 1) ? "List of" : "Remove which");
5943 Strcpy(mcbuf, (opt_idx == 1) ?
5944 "
\83\81\83j
\83\85\81[
\90F
\88ê
\97\97" : "
\8dí
\8f\9c\82·
\82é
\83\81\83j
\83\85\81[
\90F");
5946 end_menu(tmpwin, mcbuf);
5947 pick_cnt = select_menu(tmpwin,
5948 (opt_idx == 1) ? PICK_NONE : PICK_ANY,
5951 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
5952 free_one_menu_coloring(pick_list[pick_idx].item.a_int - 1
5954 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
5956 destroy_nhwindow(tmpwin);
5958 goto menucolors_again;
5960 } else if (!strcmp("autopickup_exception", optname)) {
5961 int opt_idx, numapes = 0;
5962 char apebuf[2 + BUFSZ]; /* so &apebuf[1] is BUFSZ long for getlin() */
5963 struct autopickup_exception *ape;
5966 numapes = count_apes();
5968 opt_idx = handle_add_list_remove("autopickup exception", numapes);
5970 opt_idx = handle_add_list_remove("
\8e©
\93®
\8fE
\82¢
\97á
\8aO", numapes);
5971 if (opt_idx == 3) { /* done */
5973 } else if (opt_idx == 0) { /* add new */
5974 /* EDIT_GETLIN: assume user doesn't user want previous
5975 exception used as default input string for this one... */
5976 apebuf[0] = apebuf[1] = '\0';
5978 getlin("What new autopickup exception pattern?", &apebuf[1]);
5980 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]);
5981 mungspaces(&apebuf[1]); /* regularize whitespace */
5982 if (apebuf[1] == '\033')
5986 /* guarantee room for \" prefix and \"\0 suffix;
5987 -2 is good enough for apebuf[] but -3 makes
5988 sure the whole thing fits within normal BUFSZ */
5989 apebuf[sizeof apebuf - 2] = '\0';
5990 Strcat(apebuf, "\"");
5991 add_autopickup_exception(apebuf);
5994 } else { /* list (1) or remove (2) */
5995 int pick_idx, pick_cnt;
5996 menu_item *pick_list = (menu_item *) 0;
5998 tmpwin = create_nhwindow(NHW_MENU);
6004 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
6005 "Always pickup '<'; never pickup '>'",
6008 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
6009 "
\8fí
\82É
\8fE
\82¤ '<';
\8fí
\82É
\8fE
\82í
\82È
\82¢ '>'",
6012 for (i = 0; i < numapes && ape; i++) {
6013 any.a_void = (opt_idx == 1) ? 0 : ape;
6014 /* length of pattern plus quotes (plus '<'/'>') is
6016 Sprintf(apebuf, "\"%c%s\"", ape->grab ? '<' : '>',
6018 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, apebuf,
6024 Sprintf(apebuf, "%s autopickup exceptions",
6025 (opt_idx == 1) ? "List of" : "Remove which");
6027 Sprintf(apebuf, "%s
\8e©
\93®
\8fE
\82¢
\97á
\8aO%s",
6028 (opt_idx == 1) ? "" : "
\82Ç
\82Ì",
6029 (opt_idx == 1) ? "
\82Ì
\88ê
\97\97" : "
\82ð
\8dí
\8f\9c\82µ
\82Ü
\82·
\82©
\81H");
6031 end_menu(tmpwin, apebuf);
6032 pick_cnt = select_menu(tmpwin,
6033 (opt_idx == 1) ? PICK_NONE : PICK_ANY,
6036 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
6037 remove_autopickup_exception(
6038 (struct autopickup_exception *)
6039 pick_list[pick_idx].item.a_void);
6040 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
6042 destroy_nhwindow(tmpwin);
6046 } else if (!strcmp("symset", optname)
6047 || !strcmp("roguesymset", optname)) {
6048 menu_item *symset_pick = (menu_item *) 0;
6049 boolean rogueflag = (*optname == 'r'),
6050 ready_to_switch = FALSE,
6051 nothing_to_do = FALSE;
6052 char *symset_name, fmtstr[20];
6053 struct symsetentry *sl;
6054 int res, which_set, setcount = 0, chosen = -2, defindx = 0;
6056 which_set = rogueflag ? ROGUESET : PRIMARY;
6057 symset_list = (struct symsetentry *) 0;
6058 /* clear symset[].name as a flag to read_sym_file() to build list */
6059 symset_name = symset[which_set].name;
6060 symset[which_set].name = (char *) 0;
6062 res = read_sym_file(which_set);
6063 /* put symset name back */
6064 symset[which_set].name = symset_name;
6066 if (res && symset_list) {
6068 biggest = (int) (sizeof "Default Symbols" - sizeof ""),
6071 for (sl = symset_list; sl; sl = sl->next) {
6072 /* check restrictions */
6073 if (rogueflag ? sl->primary : sl->rogue)
6075 #ifndef MAC_GRAPHICS_ENV
6076 if (sl->handling == H_MAC)
6081 /* find biggest name */
6082 thissize = sl->name ? (int) strlen(sl->name) : 0;
6083 if (thissize > biggest)
6085 thissize = sl->desc ? (int) strlen(sl->desc) : 0;
6086 if (thissize > big_desc)
6087 big_desc = thissize;
6091 pline("There are no appropriate %s symbol sets available.",
6092 rogueflag ? "rogue level" : "primary");
6094 pline("
\93K
\90Ø
\82È%s
\83V
\83\93\83{
\83\8b\90Ý
\92è
\82ª
\82 \82è
\82Ü
\82¹
\82ñ
\81D",
6095 rogueflag ? "rogue
\83\8c\83x
\83\8b" : "
\97D
\90æ");
6100 Sprintf(fmtstr, "%%-%ds %%s", biggest + 2);
6101 tmpwin = create_nhwindow(NHW_MENU);
6104 any.a_int = 1; /* -1 + 2 [see 'if (sl->name) {' below]*/
6106 defindx = any.a_int;
6107 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
6109 (any.a_int == defindx) ? MENU_SELECTED
6112 for (sl = symset_list; sl; sl = sl->next) {
6113 /* check restrictions */
6114 if (rogueflag ? sl->primary : sl->rogue)
6116 #ifndef MAC_GRAPHICS_ENV
6117 if (sl->handling == H_MAC)
6121 /* +2: sl->idx runs from 0 to N-1 for N symsets;
6122 +1 because Defaults are implicitly in slot [0];
6123 +1 again so that valid data is never 0 */
6124 any.a_int = sl->idx + 2;
6125 if (symset_name && !strcmpi(sl->name, symset_name))
6126 defindx = any.a_int;
6127 Sprintf(buf, fmtstr, sl->name, sl->desc ? sl->desc : "");
6128 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
6129 (any.a_int == defindx) ? MENU_SELECTED
6134 Sprintf(buf, "Select %ssymbol set:",
6135 rogueflag ? "rogue level " : "");
6137 Sprintf(buf, "%s
\83V
\83\93\83{
\83\8b\90Ý
\92è
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F",
6138 rogueflag ? "rogue
\83\8c\83x
\83\8b" : "");
6140 end_menu(tmpwin, buf);
6141 n = select_menu(tmpwin, PICK_ONE, &symset_pick);
6143 chosen = symset_pick[0].item.a_int;
6144 /* if picking non-preselected entry yields 2, make sure
6145 that we're going with the non-preselected one */
6146 if (n == 2 && chosen == defindx)
6147 chosen = symset_pick[1].item.a_int;
6148 chosen -= 2; /* convert menu index to symset index;
6149 * "Default symbols" have index -1 */
6150 free((genericptr_t) symset_pick);
6151 } else if (n == 0 && defindx > 0) {
6152 chosen = defindx - 2;
6154 destroy_nhwindow(tmpwin);
6157 /* chose an actual symset name from file */
6158 for (sl = symset_list; sl; sl = sl->next)
6159 if (sl->idx == chosen)
6162 /* free the now stale attributes */
6163 clear_symsetentry(which_set, TRUE);
6165 /* transfer only the name of the symbol set */
6166 symset[which_set].name = dupstr(sl->name);
6167 ready_to_switch = TRUE;
6169 } else if (chosen == -1) {
6170 /* explicit selection of defaults */
6171 /* free the now stale symset attributes */
6172 clear_symsetentry(which_set, TRUE);
6174 nothing_to_do = TRUE;
6176 /* The symbols file could not be accessed */
6178 pline("Unable to access \"%s\" file.", SYMBOLS);
6180 pline("\"%s\"
\83t
\83@
\83C
\83\8b\82É
\83A
\83N
\83Z
\83X
\82Å
\82«
\82Ü
\82¹
\82ñ
\81D", SYMBOLS);
6182 } else if (!symset_list) {
6183 /* The symbols file was empty */
6185 pline("There were no symbol sets found in \"%s\".", SYMBOLS);
6187 pline("\"%s\"
\82É
\83V
\83\93\83{
\83\8b\90Ý
\92è
\82ª
\82 \82è
\82Ü
\82¹
\82ñ
\81D", SYMBOLS);
6192 while ((sl = symset_list) != 0) {
6193 symset_list = sl->next;
6195 free((genericptr_t) sl->name), sl->name = (char *) 0;
6197 free((genericptr_t) sl->desc), sl->desc = (char *) 0;
6198 free((genericptr_t) sl);
6204 /* Set default symbols and clear the handling value */
6206 init_rogue_symbols();
6208 init_primary_symbols();
6210 if (symset[which_set].name) {
6211 /* non-default symbols */
6212 if (read_sym_file(which_set)) {
6213 ready_to_switch = TRUE;
6215 clear_symsetentry(which_set, TRUE);
6220 if (ready_to_switch)
6221 switch_symbols(TRUE);
6223 if (Is_rogue_level(&u.uz)) {
6225 assign_graphics(ROGUESET);
6226 } else if (!rogueflag)
6227 assign_graphics(PRIMARY);
6228 preference_update("symset");
6231 } else if (!strcmp("altkeyhandler", optname)
6232 || !strcmp("altkeyhandling", optname)) {
6233 return set_keyhandling_via_option();
6236 /* didn't match any of the special options */
6242 #define rolestring(val, array, field) \
6243 ((val >= 0) ? array[val].field : (val == ROLE_RANDOM) ? randomrole : none)
6245 /* This is ugly. We have all the option names in the compopt[] array,
6246 but we need to look at each option individually to get the value. */
6247 STATIC_OVL const char *
6248 get_compopt_value(optname, buf)
6249 const char *optname;
6253 static const char none[] = "(none)", randomrole[] = "random",
6254 to_be_done[] = "(to be done)",
6255 defopt[] = "default", defbrief[] = "def";
6257 static const char none[] = "(
\82È
\82µ)", randomrole[] = "
\83\89\83\93\83_
\83\80",
6258 to_be_done[] = "(
\96¢
\90Ý
\92è)",
6259 defopt[] = "
\83f
\83t
\83H
\83\8b\83g", defbrief[] = "def";
6261 char ocl[MAXOCLASSES + 1];
6265 if (!strcmp(optname, "align_message")
6266 || !strcmp(optname, "align_status")) {
6267 int which = !strcmp(optname, "align_status") ? iflags.wc_align_status
6268 : iflags.wc_align_message;
6271 (which == ALIGN_TOP) ? "top"
6272 : (which == ALIGN_LEFT) ? "left"
6273 : (which == ALIGN_BOTTOM) ? "bottom"
6274 : (which == ALIGN_RIGHT) ? "right"
6278 (which == ALIGN_TOP) ? "
\8fã
\91¤"
6279 : (which == ALIGN_LEFT) ? "
\8d¶
\91¤"
6280 : (which == ALIGN_BOTTOM) ? "
\89º
\91¤"
6281 : (which == ALIGN_RIGHT) ? "
\89E
\91¤"
6284 } else if (!strcmp(optname, "align"))
6286 Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj));
6288 Sprintf(buf, "%s", rolestring(flags.initalign, aligns, noun));
6291 else if (!strcmp(optname, "altkeyhandler"))
6293 (iflags.key_handling == ray_keyhandling)
6295 : (iflags.key_handling == nh340_keyhandling)
6299 #ifdef BACKWARD_COMPAT
6300 else if (!strcmp(optname, "boulder"))
6302 ov_primary_syms[SYM_BOULDER + SYM_OFF_X]
6303 ? ov_primary_syms[SYM_BOULDER + SYM_OFF_X]
6304 : showsyms[(int) objects[BOULDER].oc_class + SYM_OFF_O]);
6306 else if (!strcmp(optname, "catname"))
6307 Sprintf(buf, "%s", catname[0] ? catname : none);
6308 else if (!strcmp(optname, "disclose"))
6309 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
6311 (void) strkitten(buf, ' ');
6312 (void) strkitten(buf, flags.end_disclose[i]);
6313 (void) strkitten(buf, disclosure_options[i]);
6315 else if (!strcmp(optname, "dogname"))
6316 Sprintf(buf, "%s", dogname[0] ? dogname : none);
6317 else if (!strcmp(optname, "dungeon"))
6318 Sprintf(buf, "%s", to_be_done);
6319 else if (!strcmp(optname, "effects"))
6320 Sprintf(buf, "%s", to_be_done);
6321 else if (!strcmp(optname, "font_map"))
6322 Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt);
6323 else if (!strcmp(optname, "font_message"))
6325 iflags.wc_font_message ? iflags.wc_font_message : defopt);
6326 else if (!strcmp(optname, "font_status"))
6328 iflags.wc_font_status ? iflags.wc_font_status : defopt);
6329 else if (!strcmp(optname, "font_menu"))
6331 iflags.wc_font_menu ? iflags.wc_font_menu : defopt);
6332 else if (!strcmp(optname, "font_text"))
6334 iflags.wc_font_text ? iflags.wc_font_text : defopt);
6335 else if (!strcmp(optname, "font_size_map")) {
6336 if (iflags.wc_fontsiz_map)
6337 Sprintf(buf, "%d", iflags.wc_fontsiz_map);
6339 Strcpy(buf, defopt);
6340 } else if (!strcmp(optname, "font_size_message")) {
6341 if (iflags.wc_fontsiz_message)
6342 Sprintf(buf, "%d", iflags.wc_fontsiz_message);
6344 Strcpy(buf, defopt);
6345 } else if (!strcmp(optname, "font_size_status")) {
6346 if (iflags.wc_fontsiz_status)
6347 Sprintf(buf, "%d", iflags.wc_fontsiz_status);
6349 Strcpy(buf, defopt);
6350 } else if (!strcmp(optname, "font_size_menu")) {
6351 if (iflags.wc_fontsiz_menu)
6352 Sprintf(buf, "%d", iflags.wc_fontsiz_menu);
6354 Strcpy(buf, defopt);
6355 } else if (!strcmp(optname, "font_size_text")) {
6356 if (iflags.wc_fontsiz_text)
6357 Sprintf(buf, "%d", iflags.wc_fontsiz_text);
6359 Strcpy(buf, defopt);
6360 } else if (!strcmp(optname, "fruit"))
6361 Sprintf(buf, "%s", pl_fruit);
6362 else if (!strcmp(optname, "gender"))
6363 Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
6364 else if (!strcmp(optname, "horsename"))
6365 Sprintf(buf, "%s", horsename[0] ? horsename : none);
6366 else if (!strcmp(optname, "map_mode")) {
6367 i = iflags.wc_map_mode;
6369 (i == MAP_MODE_TILES) ? "tiles"
6370 : (i == MAP_MODE_ASCII4x6) ? "ascii4x6"
6371 : (i == MAP_MODE_ASCII6x8) ? "ascii6x8"
6372 : (i == MAP_MODE_ASCII8x8) ? "ascii8x8"
6373 : (i == MAP_MODE_ASCII16x8) ? "ascii16x8"
6374 : (i == MAP_MODE_ASCII7x12) ? "ascii7x12"
6375 : (i == MAP_MODE_ASCII8x12) ? "ascii8x12"
6376 : (i == MAP_MODE_ASCII16x12) ? "ascii16x12"
6377 : (i == MAP_MODE_ASCII12x16) ? "ascii12x16"
6378 : (i == MAP_MODE_ASCII10x18) ? "ascii10x18"
6379 : (i == MAP_MODE_ASCII_FIT_TO_SCREEN)
6382 } else if (!strcmp(optname, "menustyle"))
6383 Sprintf(buf, "%s", menutype[(int) flags.menu_style]);
6384 else if (!strcmp(optname, "menu_deselect_all"))
6385 Sprintf(buf, "%s", to_be_done);
6386 else if (!strcmp(optname, "menu_deselect_page"))
6387 Sprintf(buf, "%s", to_be_done);
6388 else if (!strcmp(optname, "menu_first_page"))
6389 Sprintf(buf, "%s", to_be_done);
6390 else if (!strcmp(optname, "menu_invert_all"))
6391 Sprintf(buf, "%s", to_be_done);
6392 else if (!strcmp(optname, "menu_headings"))
6393 Sprintf(buf, "%s", attr2attrname(iflags.menu_headings));
6394 else if (!strcmp(optname, "menu_invert_page"))
6395 Sprintf(buf, "%s", to_be_done);
6396 else if (!strcmp(optname, "menu_last_page"))
6397 Sprintf(buf, "%s", to_be_done);
6398 else if (!strcmp(optname, "menu_next_page"))
6399 Sprintf(buf, "%s", to_be_done);
6400 else if (!strcmp(optname, "menu_previous_page"))
6401 Sprintf(buf, "%s", to_be_done);
6402 else if (!strcmp(optname, "menu_search"))
6403 Sprintf(buf, "%s", to_be_done);
6404 else if (!strcmp(optname, "menu_select_all"))
6405 Sprintf(buf, "%s", to_be_done);
6406 else if (!strcmp(optname, "menu_select_page"))
6407 Sprintf(buf, "%s", to_be_done);
6408 else if (!strcmp(optname, "monsters")) {
6409 Sprintf(buf, "%s", to_be_done);
6410 } else if (!strcmp(optname, "msghistory")) {
6411 Sprintf(buf, "%u", iflags.msg_history);
6413 } else if (!strcmp(optname, "msg_window")) {
6414 Sprintf(buf, "%s", (iflags.prevmsg_window == 's') ? "single"
6415 : (iflags.prevmsg_window == 'c') ? "combination"
6416 : (iflags.prevmsg_window == 'f') ? "full"
6419 } else if (!strcmp(optname, "name")) {
6420 Sprintf(buf, "%s", plname);
6421 } else if (!strcmp(optname, "mouse_support")) {
6423 #define MOUSEFIX1 ", QuickEdit off"
6424 #define MOUSEFIX2 ", QuickEdit unchanged"
6426 #define MOUSEFIX1 ", O/S adjusted"
6427 #define MOUSEFIX2 ", O/S unchanged"
6429 static const char *mousemodes[][2] = {
6431 { "1=on", MOUSEFIX1 },
6432 { "2=on", MOUSEFIX2 },
6436 int ms = iflags.wc_mouse_support;
6438 if (ms >= 0 && ms <= 2)
6439 Sprintf(buf, "%s%s", mousemodes[ms][0], mousemodes[ms][1]);
6440 } else if (!strcmp(optname, "number_pad")) {
6441 static const char *numpadmodes[] = {
6443 "0=off", "1=on", "2=on, MSDOS compatible",
6445 "0=
\96³
\8cø", "1=
\97L
\8cø", "2=
\97L
\8cø
\81CDOS
\8cÝ
\8a·",
6447 "3=on, phone-style layout",
6449 "3=
\97L
\8cø
\81C
\93d
\98b
\8e®
\82Ì
\90\94\8e\9a\94z
\92u",
6451 "4=on, phone layout, MSDOS compatible",
6453 "4=
\97L
\8cø
\81C
\93d
\98b
\8e®
\82Ì
\94z
\92u
\81CMSDOS
\8cÝ
\8a·",
6455 "-1=off, y & z swapped", /*[5]*/
6457 "-1=
\96³
\8cø
\81Cy
\82Æz
\82ð
\93ü
\82ê
\91Ö
\82¦", /*[5]*/
6460 int indx = Cmd.num_pad
6461 ? (Cmd.phone_layout ? (Cmd.pcHack_compat ? 4 : 3)
6462 : (Cmd.pcHack_compat ? 2 : 1))
6463 : Cmd.swap_yz ? 5 : 0;
6465 Strcpy(buf, numpadmodes[indx]);
6466 } else if (!strcmp(optname, "objects")) {
6467 Sprintf(buf, "%s", to_be_done);
6468 } else if (!strcmp(optname, "packorder")) {
6469 oc_to_str(flags.inv_order, ocl);
6470 Sprintf(buf, "%s", ocl);
6472 } else if (!strcmp(optname, "palette")) {
6473 Sprintf(buf, "%s", get_color_string());
6475 } else if (!strcmp(optname, "paranoid_confirmation")) {
6476 char tmpbuf[QBUFSZ];
6479 for (i = 0; paranoia[i].flagmask != 0; ++i)
6480 if (flags.paranoia_bits & paranoia[i].flagmask)
6481 Sprintf(eos(tmpbuf), " %s", paranoia[i].argname);
6482 Strcpy(buf, tmpbuf[0] ? &tmpbuf[1] : "none");
6483 } else if (!strcmp(optname, "petattr")) {
6484 #ifdef CURSES_GRAPHICS
6485 if (WINDOWPORT("curses")) {
6486 char tmpbuf[QBUFSZ];
6488 Strcpy(buf, curses_fmt_attrs(tmpbuf));
6491 if (iflags.wc2_petattr != 0)
6492 Sprintf(buf, "0x%08x", iflags.wc2_petattr);
6494 Strcpy(buf, defopt);
6495 } else if (!strcmp(optname, "pettype")) {
6497 Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat"
6498 : (preferred_pet == 'd') ? "dog"
6499 : (preferred_pet == 'h') ? "horse"
6500 : (preferred_pet == 'n') ? "none"
6503 Sprintf(buf, "%s", (preferred_pet == 'c') ? "
\94L"
6504 : (preferred_pet == 'd') ? "
\8c¢"
6505 : (preferred_pet == 'h') ? "
\94n"
6506 : (preferred_pet == 'n') ? "
\82È
\82µ"
6507 : "
\83\89\83\93\83_
\83\80");
6509 } else if (!strcmp(optname, "pickup_burden")) {
6510 Sprintf(buf, "%s", burdentype[flags.pickup_burden]);
6511 } else if (!strcmp(optname, "pickup_types")) {
6512 oc_to_str(flags.pickup_types, ocl);
6513 Sprintf(buf, "%s", ocl[0] ? ocl : "all");
6514 } else if (!strcmp(optname, "pile_limit")) {
6515 Sprintf(buf, "%d", flags.pile_limit);
6516 } else if (!strcmp(optname, "playmode")) {
6517 Strcpy(buf, wizard ? "debug" : discover ? "explore" : "normal");
6518 } else if (!strcmp(optname, "race")) {
6519 Sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
6520 } else if (!strcmp(optname, "roguesymset")) {
6522 symset[ROGUESET].name ? symset[ROGUESET].name : "default");
6523 if (currentgraphics == ROGUESET && symset[ROGUESET].name)
6524 Strcat(buf, ", active");
6525 } else if (!strcmp(optname, "role")) {
6526 Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
6527 } else if (!strcmp(optname, "runmode")) {
6528 Sprintf(buf, "%s", runmodes[flags.runmode]);
6529 } else if (!strcmp(optname, "whatis_coord")) {
6531 (iflags.getpos_coords == GPCOORDS_MAP) ? "map"
6532 : (iflags.getpos_coords == GPCOORDS_COMPASS) ? "compass"
6533 : (iflags.getpos_coords == GPCOORDS_COMFULL) ? "full compass"
6534 : (iflags.getpos_coords == GPCOORDS_SCREEN) ? "screen"
6536 } else if (!strcmp(optname, "whatis_filter")) {
6538 (iflags.getloc_filter == GFILTER_VIEW) ? "view"
6539 : (iflags.getloc_filter == GFILTER_AREA) ? "area"
6541 } else if (!strcmp(optname, "scores")) {
6542 Sprintf(buf, "%d top/%d around%s", flags.end_top, flags.end_around,
6543 flags.end_own ? "/own" : "");
6544 } else if (!strcmp(optname, "scroll_amount")) {
6545 if (iflags.wc_scroll_amount)
6546 Sprintf(buf, "%d", iflags.wc_scroll_amount);
6548 Strcpy(buf, defopt);
6549 } else if (!strcmp(optname, "scroll_margin")) {
6550 if (iflags.wc_scroll_margin)
6551 Sprintf(buf, "%d", iflags.wc_scroll_margin);
6553 Strcpy(buf, defopt);
6554 } else if (!strcmp(optname, "sortloot")) {
6555 for (i = 0; i < SIZE(sortltype); i++)
6556 if (flags.sortloot == sortltype[i][0]) {
6557 Strcpy(buf, sortltype[i]);
6560 } else if (!strcmp(optname, "player_selection")) {
6562 Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
6564 Sprintf(buf, "%s
\93ü
\97Í", iflags.wc_player_selection ? "
\83v
\83\8d\83\93\83v
\83g" : "
\83_
\83C
\83A
\83\8d\83O");
6567 } else if (!strcmp(optname, "soundcard")) {
6568 Sprintf(buf, "%s", to_be_done);
6570 #ifdef STATUS_HILITES
6571 } else if (!strcmp("statushilites", optname)) {
6572 if (!iflags.hilite_delta)
6573 Strcpy(buf, "0 (off: don't highlight status fields)");
6575 Sprintf(buf, "%ld (on: highlight status for %ld turns)",
6576 iflags.hilite_delta, iflags.hilite_delta);
6578 } else if (!strcmp(optname,"statuslines")) {
6579 if (wc2_supported(optname))
6580 Strcpy(buf, (iflags.wc2_statuslines < 3) ? "2" : "3");
6581 /* else default to "unknown" */
6582 } else if (!strcmp(optname, "suppress_alert")) {
6583 if (flags.suppress_alert == 0L)
6586 Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
6587 FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
6588 } else if (!strcmp(optname, "symset")) {
6590 symset[PRIMARY].name ? symset[PRIMARY].name : "default");
6591 if (currentgraphics == PRIMARY && symset[PRIMARY].name)
6592 Strcat(buf, ", active");
6593 } else if (!strcmp(optname, "term_cols")) {
6594 if (iflags.wc2_term_cols)
6595 Sprintf(buf, "%d", iflags.wc2_term_cols);
6597 Strcpy(buf, defopt);
6598 } else if (!strcmp(optname, "term_rows")) {
6599 if (iflags.wc2_term_rows)
6600 Sprintf(buf, "%d", iflags.wc2_term_rows);
6602 Strcpy(buf, defopt);
6603 } else if (!strcmp(optname, "tile_file")) {
6605 iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
6606 } else if (!strcmp(optname, "tile_height")) {
6607 if (iflags.wc_tile_height)
6608 Sprintf(buf, "%d", iflags.wc_tile_height);
6610 Strcpy(buf, defopt);
6611 } else if (!strcmp(optname, "tile_width")) {
6612 if (iflags.wc_tile_width)
6613 Sprintf(buf, "%d", iflags.wc_tile_width);
6615 Strcpy(buf, defopt);
6616 } else if (!strcmp(optname, "traps")) {
6617 Sprintf(buf, "%s", to_be_done);
6618 } else if (!strcmp(optname, "vary_msgcount")) {
6619 if (iflags.wc_vary_msgcount)
6620 Sprintf(buf, "%d", iflags.wc_vary_msgcount);
6622 Strcpy(buf, defopt);
6624 } else if (!strcmp(optname, "video")) {
6625 Sprintf(buf, "%s", to_be_done);
6628 } else if (!strcmp(optname, "videoshades")) {
6629 Sprintf(buf, "%s-%s-%s", shade[0], shade[1], shade[2]);
6630 } else if (!strcmp(optname, "videocolors")) {
6631 Sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
6632 ttycolors[CLR_RED], ttycolors[CLR_GREEN],
6633 ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
6634 ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN],
6635 ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
6636 ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
6637 ttycolors[CLR_BRIGHT_MAGENTA], ttycolors[CLR_BRIGHT_CYAN]);
6638 #endif /* VIDEOSHADES */
6639 } else if (!strcmp(optname,"windowborders")) {
6641 (iflags.wc2_windowborders == 0) ? "0=off"
6642 : (iflags.wc2_windowborders == 1) ? "1=on"
6643 : (iflags.wc2_windowborders == 2) ? "2=auto"
6645 } else if (!strcmp(optname, "windowtype")) {
6646 Sprintf(buf, "%s", windowprocs.name);
6647 } else if (!strcmp(optname, "windowcolors")) {
6649 buf, "%s/%s %s/%s %s/%s %s/%s",
6650 iflags.wc_foregrnd_menu ? iflags.wc_foregrnd_menu : defbrief,
6651 iflags.wc_backgrnd_menu ? iflags.wc_backgrnd_menu : defbrief,
6652 iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message
6654 iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message
6656 iflags.wc_foregrnd_status ? iflags.wc_foregrnd_status : defbrief,
6657 iflags.wc_backgrnd_status ? iflags.wc_backgrnd_status : defbrief,
6658 iflags.wc_foregrnd_text ? iflags.wc_foregrnd_text : defbrief,
6659 iflags.wc_backgrnd_text ? iflags.wc_backgrnd_text : defbrief);
6660 #ifdef PREFIXES_IN_USE
6662 for (i = 0; i < PREFIX_COUNT; ++i)
6663 if (!strcmp(optname, fqn_prefix_names[i]) && fqn_prefix[i])
6664 Sprintf(buf, "%s", fqn_prefix[i]);
6670 Strcpy(buf, "unknown");
6672 Strcpy(buf, "
\95s
\96¾");
6679 char buf[BUFSZ], ocl[MAXOCLASSES + 1];
6681 flags.pickup = !flags.pickup;
6683 oc_to_str(flags.pickup_types, ocl);
6685 Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all",
6687 ? ((count_apes() == 1)
6688 ? ", with one exception"
6689 : ", with some exceptions")
6692 Sprintf(buf, "%s
\83A
\83C
\83e
\83\80\82É
\82Â
\82¢
\82Ä
\83I
\83\93%s", ocl[0] ? ocl : "
\91S
\82Ä
\82Ì",
6694 ? "
\81C
\97á
\8aO
\82 \82è"
6701 Strcpy(buf, "
\83I
\83t");
6704 pline("Autopickup: %s.", buf);
6706 pline("
\8e©
\93®
\8fE
\82¢
\81F%s
\81D", buf);
6711 add_autopickup_exception(mapping)
6712 const char *mapping;
6715 APE_regex_error[] = "regex error in AUTOPICKUP_EXCEPTION",
6716 APE_syntax_error[] = "syntax error in AUTOPICKUP_EXCEPTION";
6718 struct autopickup_exception *ape;
6719 char text[256], end;
6721 boolean grab = FALSE;
6723 /* scan length limit used to be 255, but smaller size allows the
6724 quoted value to fit within BUFSZ, simplifying formatting elsewhere;
6725 this used to ignore the possibility of trailing junk but now checks
6726 for it, accepting whitespace but rejecting anything else unless it
6727 starts with '#" for a comment */
6729 if ((n = sscanf(mapping, "\"<%253[^\"]\" %c", text, &end)) == 1
6730 || (n == 2 && end == '#')) {
6732 } else if ((n = sscanf(mapping, "\">%253[^\"]\" %c", text, &end)) == 1
6733 || (n = sscanf(mapping, "\"%253[^\"]\" %c", text, &end)) == 1
6734 || (n == 2 && end == '#')) {
6737 config_error_add("%s", APE_syntax_error);
6741 ape = (struct autopickup_exception *) alloc(sizeof *ape);
6742 ape->regex = regex_init();
6743 if (!regex_compile(text, ape->regex)) {
6744 config_error_add("%s: %s", APE_regex_error,
6745 regex_error_desc(ape->regex));
6746 regex_free(ape->regex);
6747 free((genericptr_t) ape);
6751 ape->pattern = dupstr(text);
6753 ape->next = apelist;
6759 remove_autopickup_exception(whichape)
6760 struct autopickup_exception *whichape;
6762 struct autopickup_exception *ape, *freeape, *prev = 0;
6764 for (ape = apelist; ape;) {
6765 if (ape == whichape) {
6772 regex_free(freeape->regex);
6773 free((genericptr_t) freeape->pattern);
6774 free((genericptr_t) freeape);
6783 free_autopickup_exceptions()
6785 struct autopickup_exception *ape = apelist;
6787 while ((ape = apelist) != 0) {
6788 regex_free(ape->regex);
6789 free((genericptr_t) ape->pattern);
6790 apelist = ape->next;
6791 free((genericptr_t) ape);
6795 /* bundle some common usage into one easy-to-use routine */
6797 load_symset(s, which_set)
6801 clear_symsetentry(which_set, TRUE);
6803 if (symset[which_set].name)
6804 free((genericptr_t) symset[which_set].name);
6805 symset[which_set].name = dupstr(s);
6807 if (read_sym_file(which_set)) {
6808 switch_symbols(TRUE);
6810 clear_symsetentry(which_set, TRUE);
6819 clear_symsetentry(PRIMARY, TRUE);
6820 clear_symsetentry(ROGUESET, TRUE);
6822 /* symset_list is cleaned up as soon as it's used, so we shouldn't
6823 have to anything about it here */
6824 /* assert( symset_list == NULL ); */
6827 /* Parse the value of a SYMBOLS line from a config file */
6829 parsesymbols(opts, which_set)
6830 register char *opts;
6834 char *op, *symname, *strval;
6835 struct symparse *symp;
6837 if ((op = index(opts, ',')) != 0) {
6839 if (!parsesymbols(op, which_set))
6843 /* S_sample:string */
6845 strval = index(opts, ':');
6847 strval = index(opts, '=');
6852 /* strip leading and trailing white space from symname and strval */
6853 mungspaces(symname);
6856 symp = match_sym(symname);
6860 if (symp->range && symp->range != SYM_CONTROL) {
6861 val = sym_val(strval);
6862 if (which_set == ROGUESET)
6863 update_ov_rogue_symset(symp, val);
6865 update_ov_primary_symset(symp, val);
6874 size_t len = strlen(buf);
6875 const char *p = index(buf, ':'), *q = index(buf, '=');
6876 struct symparse *sp = loadsyms;
6878 if (!p || (q && q < p))
6881 /* note: there will be at most one space before the '='
6882 because caller has condensed buf[] with mungspaces() */
6883 if (p > buf && p[-1] == ' ')
6885 len = (int) (p - buf);
6888 if ((len >= strlen(sp->name)) && !strncmpi(buf, sp->name, len))
6892 return (struct symparse *) 0;
6897 const char *strval; /* up to 4*BUFSZ-1 long; only first few chars matter */
6899 char buf[QBUFSZ], tmp[QBUFSZ]; /* to hold trucated copy of 'strval' */
6902 if (!strval[0] || !strval[1]) { /* empty, or single character */
6903 /* if single char is space or tab, leave buf[0]=='\0' */
6904 if (!isspace((uchar) strval[0]))
6906 } else if (strval[0] == '\'') { /* single quote */
6907 /* simple matching single quote; we know strval[1] isn't '\0' */
6908 if (strval[2] == '\'' && !strval[3]) {
6909 /* accepts '\' as backslash and ''' as single quote */
6912 /* if backslash, handle single or double quote or second backslash */
6913 } else if (strval[1] == '\\' && strval[2] && strval[3] == '\''
6914 && index("'\"\\", strval[2]) && !strval[4]) {
6917 /* not simple quote or basic backslash;
6918 strip closing quote and let escapes() deal with it */
6922 /* +1: skip opening single quote */
6923 (void) strncpy(tmp, strval + 1, sizeof tmp - 1);
6924 tmp[sizeof tmp - 1] = '\0';
6925 if ((p = rindex(tmp, '\'')) != 0) {
6928 } /* else buf[0] stays '\0' */
6930 } else { /* not lone char nor single quote */
6931 (void) strncpy(tmp, strval, sizeof tmp - 1);
6932 tmp[sizeof tmp - 1] = '\0';
6939 /* data for option_help() */
6940 static const char *opt_intro[] = {
6943 " NetHack Options Help:", "",
6945 " NetHack
\83I
\83v
\83V
\83\87\83\93\83w
\83\8b\83v
\81F", "",
6946 #define CONFIG_SLOT 3 /* fill in next value at run-time */
6948 #if !defined(MICRO) && !defined(MAC)
6950 "or use `NETHACKOPTIONS=\"<options>\"' in your environment",
6952 "
\82Ü
\82½
\82Í
\8aÂ
\8b«
\95Ï
\90\94\82É`NETHACKOPTIONS=\"<options>\"'
\82Æ
\92è
\8b`
\82Å
\82«
\82Ü
\82·",
6955 "(<options> is a list of options separated by commas)",
6957 "(<options>
\82Í
\83J
\83\93\83}
\82Å
\8bæ
\90Ø
\82Á
\82½
\83I
\83v
\83V
\83\87\83\93\82Å
\82·)",
6960 "-- for example, $ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
6962 "--
\97á
\82¦
\82Î
\8e\9f\82Ì
\82æ
\82¤
\82É
\82µ
\82Ü
\82·
\81F$ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
6965 "or press \"O\" while playing and use the menu.",
6967 "
\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",
6970 "Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
6972 "
\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·):",
6976 static const char *opt_epilog[] = {
6979 "Some of the options can be set only before the game is started; those",
6981 "
\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",
6983 "items will not be selectable in the 'O' command's menu.",
6985 "
\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",
6992 char buf[BUFSZ], buf2[BUFSZ];
6996 datawin = create_nhwindow(NHW_TEXT);
6998 Sprintf(buf, "Set options as OPTIONS=<options> in %s", configfile);
7000 Sprintf(buf, "
\83I
\83v
\83V
\83\87\83\93\82Í %s
\82Ì
\92\86\82ÅOPTIONS=<options>
\82Æ
\90Ý
\92è
\82µ
\82Ü
\82·", configfile);
7001 opt_intro[CONFIG_SLOT] = (const char *) buf;
7002 for (i = 0; opt_intro[i]; i++)
7003 putstr(datawin, 0, opt_intro[i]);
7005 /* Boolean options */
7006 for (i = 0; boolopt[i].name; i++) {
7007 if (boolopt[i].addr) {
7008 if (boolopt[i].addr == &iflags.sanity_check && !wizard)
7010 if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard)
7012 next_opt(datawin, boolopt[i].name);
7015 next_opt(datawin, "");
7017 /* Compound options */
7019 putstr(datawin, 0, "Compound options:");
7021 putstr(datawin, 0, "
\95¶
\8e\9a\97ñ
\83I
\83v
\83V
\83\87\83\93:");
7022 for (i = 0; compopt[i].name; i++) {
7023 Sprintf(buf2, "`%s'", compopt[i].name);
7024 Sprintf(buf, "%-20s - %s%c", buf2, compopt[i].descr,
7025 compopt[i + 1].name ? ',' : '.');
7026 putstr(datawin, 0, buf);
7029 for (i = 0; opt_epilog[i]; i++)
7030 putstr(datawin, 0, opt_epilog[i]);
7032 display_nhwindow(datawin, FALSE);
7033 destroy_nhwindow(datawin);
7038 * prints the next boolean option, on the same line if possible, on a new
7039 * line if not. End with next_opt("").
7042 next_opt(datawin, str)
7046 static char *buf = 0;
7051 *(buf = (char *) alloc(BUFSZ)) = '\0';
7055 if (s > &buf[1] && s[-2] == ',')
7056 Strcpy(s - 2, "."); /* replace last ", " */
7057 i = COLNO; /* (greater than COLNO - 2) */
7059 i = strlen(buf) + strlen(str) + 2;
7062 if (i > COLNO - 2) { /* rule of thumb */
7063 putstr(datawin, 0, buf);
7070 putstr(datawin, 0, str);
7071 free((genericptr_t) buf), buf = 0;
7076 /* Returns the fid of the fruit type; if that type already exists, it
7077 * returns the fid of that one; if it does not exist, it adds a new fruit
7078 * type to the chain and returns the new one.
7079 * If replace_fruit is sent in, replace the fruit in the chain rather than
7080 * adding a new entry--for user specified fruits only.
7083 fruitadd(str, replace_fruit)
7085 struct fruit *replace_fruit;
7088 register struct fruit *f;
7089 int highest_fruit_id = 0, globpfx;
7090 char buf[PL_FSIZ], altname[PL_FSIZ];
7091 boolean user_specified = (str == pl_fruit);
7092 /* if not user-specified, then it's a fruit name for a fruit on
7093 * a bones level or from orctown raider's loot...
7096 /* Note: every fruit has an id (kept in obj->spe) of at least 1;
7099 if (user_specified) {
7100 boolean found = FALSE, numeric = FALSE;
7102 /* force fruit to be singular; this handling is not
7103 needed--or wanted--for fruits from bones because
7104 they already received it in their original game;
7105 str==pl_fruit but makesingular() creates a copy
7106 so we need to copy that back into pl_fruit */
7107 nmcpy(pl_fruit, makesingular(str), PL_FSIZ);
7108 /* (assertion doesn't matter; we use 'pl_fruit' from here on out) */
7109 /* assert( str == pl_fruit ); */
7111 /* disallow naming after other foods (since it'd be impossible
7112 * to tell the difference); globs might have a size prefix which
7113 * needs to be skipped in order to match the object type name
7115 globpfx = (!strncmp(pl_fruit, "small ", 6)
7116 || !strncmp(pl_fruit, "large ", 6)) ? 6
7117 : (!strncmp(pl_fruit, "very large ", 11)) ? 11
7119 for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS; i++) {
7120 if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)
7122 && !strcmp(OBJ_NAME(objects[i]), &pl_fruit[globpfx]))) {
7130 for (c = pl_fruit; *c >= '0' && *c <= '9'; c++)
7132 if (!*c || isspace((uchar) *c))
7135 if (found || numeric
7136 /* these checks for applying food attributes to actual items
7137 are case sensitive; "glob of foo" is caught by 'found'
7138 if 'foo' is a valid glob; when not valid, allow it as-is */
7139 || !strncmp(pl_fruit, "cursed ", 7)
7140 || !strncmp(pl_fruit, "uncursed ", 9)
7141 || !strncmp(pl_fruit, "blessed ", 8)
7142 || !strncmp(pl_fruit, "partly eaten ", 13)
7143 || (!strncmp(pl_fruit, "tin of ", 7)
7144 && (!strcmp(pl_fruit + 7, "spinach")
7145 || name_to_mon(pl_fruit + 7) >= LOW_PM))
7146 || !strcmp(pl_fruit, "empty tin")
7147 || (!strcmp(pl_fruit, "glob")
7148 || (globpfx > 0 && !strcmp("glob", &pl_fruit[globpfx])))
7149 || ((str_end_is(pl_fruit, " corpse")
7150 || str_end_is(pl_fruit, " egg"))
7151 && name_to_mon(pl_fruit) >= LOW_PM)) {
7152 Strcpy(buf, pl_fruit);
7153 Strcpy(pl_fruit, "candied ");
7154 nmcpy(pl_fruit + 8, buf, PL_FSIZ - 8);
7157 /* This flag indicates that a fruit has been made since the
7158 * last time the user set the fruit. If it hasn't, we can
7159 * safely overwrite the current fruit, preventing the user from
7160 * setting many fruits in a row and overflowing.
7161 * Possible expansion: check for specific fruit IDs, not for
7164 flags.made_fruit = FALSE;
7165 if (replace_fruit) {
7166 /* replace_fruit is already part of the fruit chain;
7167 update it in place rather than looking it up again */
7169 copynchars(f->fname, pl_fruit, PL_FSIZ - 1);
7173 /* not user_supplied, so assumed to be from bones (or orc gang) */
7174 copynchars(altname, str, PL_FSIZ - 1);
7175 sanitize_name(altname);
7176 flags.made_fruit = TRUE; /* for safety. Any fruit name added from a
7177 * bones level should exist anyway. */
7179 f = fruit_from_name(*altname ? altname : str, FALSE, &highest_fruit_id);
7183 /* Maximum number of named fruits is 127, even if obj->spe can
7184 handle bigger values. If adding another fruit would overflow,
7185 use a random fruit instead... we've got a lot to choose from.
7186 current_fruit remains as is. */
7187 if (highest_fruit_id >= 127)
7191 (void) memset((genericptr_t) f, 0, sizeof (struct fruit));
7192 copynchars(f->fname, *altname ? altname : str, PL_FSIZ - 1);
7193 f->fid = ++highest_fruit_id;
7194 /* we used to go out of our way to add it at the end of the list,
7195 but the order is arbitrary so use simpler insertion at start */
7200 context.current_fruit = f->fid;
7205 * This is a somewhat generic menu for taking a list of NetHack style
7206 * class choices and presenting them via a description
7207 * rather than the traditional NetHack characters.
7208 * (Benefits users whose first exposure to NetHack is via tiles).
7211 * The title at the top of the menu.
7213 * category: 0 = monster class
7217 * FALSE = PICK_ONE, TRUE = PICK_ANY
7220 * a null terminated string containing the list of choices.
7223 * a null terminated string containing the selected characters.
7225 * Returns number selected.
7228 choose_classes_menu(prompt, category, way, class_list, class_select)
7235 menu_item *pick_list = (menu_item *) 0;
7241 int next_accelerator, accelerator;
7243 if (class_list == (char *) 0 || class_select == (char *) 0)
7246 next_accelerator = 'a';
7248 win = create_nhwindow(NHW_MENU);
7250 while (*class_list) {
7258 text = def_monsyms[def_char_to_monclass(*class_list)].explain;
7259 accelerator = *class_list;
7260 Sprintf(buf, "%s", text);
7263 text = def_oc_syms[def_char_to_objclass(*class_list)].explain;
7264 accelerator = next_accelerator;
7265 Sprintf(buf, "%c %s", *class_list, text);
7268 impossible("choose_classes_menu: invalid category %d", category);
7270 if (way && *class_select) { /* Selections there already */
7271 if (index(class_select, *class_list)) {
7275 any.a_int = *class_list;
7276 add_menu(win, NO_GLYPH, &any, accelerator, category ? *class_list : 0,
7277 ATR_NONE, buf, selected);
7281 if (next_accelerator == ('z' + 1))
7282 next_accelerator = 'A';
7283 if (next_accelerator == ('Z' + 1))
7287 if (category == 1 && next_accelerator <= 'z') {
7288 /* for objects, add "A - ' ' all classes", after a separator */
7290 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
7291 any.a_int = (int) ' ';
7292 Sprintf(buf, "%c %s", (char) any.a_int, "all classes of objects");
7293 /* we won't preselect this even if the incoming list is empty;
7294 having it selected means that it would have to be explicitly
7295 de-selected in order to select anything else */
7296 add_menu(win, NO_GLYPH, &any, 'A', 0, ATR_NONE, buf, MENU_UNSELECTED);
7298 end_menu(win, prompt);
7299 n = select_menu(win, way ? PICK_ANY : PICK_ONE, &pick_list);
7300 destroy_nhwindow(win);
7302 if (category == 1) {
7303 /* for object classes, first check for 'all'; it means 'use
7304 a blank list' rather than 'collect every possible choice' */
7305 for (i = 0; i < n; ++i)
7306 if (pick_list[i].item.a_int == ' ') {
7307 pick_list[0].item.a_int = ' ';
7308 n = 1; /* return 1; also an implicit 'break;' */
7311 for (i = 0; i < n; ++i)
7312 *class_select++ = (char) pick_list[i].item.a_int;
7313 free((genericptr_t) pick_list);
7315 } else if (n == -1) {
7316 class_select = eos(class_select);
7320 *class_select = '\0';
7324 static struct wc_Opt wc_options[] = {
7325 { "ascii_map", WC_ASCII_MAP },
7326 { "color", WC_COLOR },
7327 { "eight_bit_tty", WC_EIGHT_BIT_IN },
7328 { "hilite_pet", WC_HILITE_PET },
7329 { "popup_dialog", WC_POPUP_DIALOG },
7330 { "player_selection", WC_PLAYER_SELECTION },
7331 { "preload_tiles", WC_PRELOAD_TILES },
7332 { "tiled_map", WC_TILED_MAP },
7333 { "tile_file", WC_TILE_FILE },
7334 { "tile_width", WC_TILE_WIDTH },
7335 { "tile_height", WC_TILE_HEIGHT },
7336 { "use_inverse", WC_INVERSE },
7337 { "align_message", WC_ALIGN_MESSAGE },
7338 { "align_status", WC_ALIGN_STATUS },
7339 { "font_map", WC_FONT_MAP },
7340 { "font_menu", WC_FONT_MENU },
7341 { "font_message", WC_FONT_MESSAGE },
7343 {"perm_invent", WC_PERM_INVENT},
7345 { "font_size_map", WC_FONTSIZ_MAP },
7346 { "font_size_menu", WC_FONTSIZ_MENU },
7347 { "font_size_message", WC_FONTSIZ_MESSAGE },
7348 { "font_size_status", WC_FONTSIZ_STATUS },
7349 { "font_size_text", WC_FONTSIZ_TEXT },
7350 { "font_status", WC_FONT_STATUS },
7351 { "font_text", WC_FONT_TEXT },
7352 { "map_mode", WC_MAP_MODE },
7353 { "scroll_amount", WC_SCROLL_AMOUNT },
7354 { "scroll_margin", WC_SCROLL_MARGIN },
7355 { "splash_screen", WC_SPLASH_SCREEN },
7356 { "vary_msgcount", WC_VARY_MSGCOUNT },
7357 { "windowcolors", WC_WINDOWCOLORS },
7358 { "mouse_support", WC_MOUSE_SUPPORT },
7361 static struct wc_Opt wc2_options[] = {
7362 { "fullscreen", WC2_FULLSCREEN },
7363 { "softkeyboard", WC2_SOFTKEYBOARD },
7364 { "wraptext", WC2_WRAPTEXT },
7365 { "use_darkgray", WC2_DARKGRAY },
7366 { "hitpointbar", WC2_HITPOINTBAR },
7367 { "hilite_status", WC2_HILITE_STATUS },
7368 /* name shown in 'O' menu is different */
7369 { "status hilite rules", WC2_HILITE_STATUS },
7370 /* statushilites doesn't have its own bit */
7371 { "statushilites", WC2_HILITE_STATUS },
7372 { "term_cols", WC2_TERM_SIZE },
7373 { "term_rows", WC2_TERM_SIZE },
7374 { "petattr", WC2_PETATTR },
7375 { "guicolor", WC2_GUICOLOR },
7376 { "statuslines", WC2_STATUSLINES },
7377 { "windowborders", WC2_WINDOWBORDERS },
7382 * If a port wants to change or ensure that the SET_IN_SYS,
7383 * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is
7384 * correct (for controlling its display in the option menu) call
7385 * set_option_mod_status()
7386 * with the appropriate second argument.
7389 set_option_mod_status(optnam, status)
7395 if (SET__IS_VALUE_VALID(status)) {
7396 impossible("set_option_mod_status: status out of range %d.", status);
7399 for (k = 0; boolopt[k].name; k++) {
7400 if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) {
7401 boolopt[k].optflags = status;
7405 for (k = 0; compopt[k].name; k++) {
7406 if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) {
7407 compopt[k].optflags = status;
7414 * You can set several wc_options in one call to
7415 * set_wc_option_mod_status() by setting
7416 * the appropriate bits for each option that you
7417 * are setting in the optmask argument
7419 * example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN,
7423 set_wc_option_mod_status(optmask, status)
7424 unsigned long optmask;
7429 if (SET__IS_VALUE_VALID(status)) {
7430 impossible("set_wc_option_mod_status: status out of range %d.",
7434 while (wc_options[k].wc_name) {
7435 if (optmask & wc_options[k].wc_bit) {
7436 set_option_mod_status(wc_options[k].wc_name, status);
7443 is_wc_option(optnam)
7448 while (wc_options[k].wc_name) {
7449 if (strcmp(wc_options[k].wc_name, optnam) == 0)
7457 wc_supported(optnam)
7462 for (k = 0; wc_options[k].wc_name; ++k) {
7463 if (!strcmp(wc_options[k].wc_name, optnam))
7464 return (windowprocs.wincap & wc_options[k].wc_bit) ? TRUE : FALSE;
7470 * You can set several wc2_options in one call to
7471 * set_wc2_option_mod_status() by setting
7472 * the appropriate bits for each option that you
7473 * are setting in the optmask argument
7476 * set_wc2_option_mod_status(WC2_FULLSCREEN|WC2_SOFTKEYBOARD|WC2_WRAPTEXT,
7481 set_wc2_option_mod_status(optmask, status)
7482 unsigned long optmask;
7487 if (SET__IS_VALUE_VALID(status)) {
7488 impossible("set_wc2_option_mod_status: status out of range %d.",
7492 while (wc2_options[k].wc_name) {
7493 if (optmask & wc2_options[k].wc_bit) {
7494 set_option_mod_status(wc2_options[k].wc_name, status);
7501 is_wc2_option(optnam)
7506 while (wc2_options[k].wc_name) {
7507 if (strcmp(wc2_options[k].wc_name, optnam) == 0)
7515 wc2_supported(optnam)
7520 for (k = 0; wc2_options[k].wc_name; ++k) {
7521 if (!strcmp(wc2_options[k].wc_name, optnam))
7522 return (windowprocs.wincap2 & wc2_options[k].wc_bit) ? TRUE
7529 wc_set_font_name(opttype, fontname)
7533 char **fn = (char **) 0;
7539 fn = &iflags.wc_font_map;
7541 case MESSAGE_OPTION:
7542 fn = &iflags.wc_font_message;
7545 fn = &iflags.wc_font_text;
7548 fn = &iflags.wc_font_menu;
7551 fn = &iflags.wc_font_status;
7558 free((genericptr_t) *fn);
7559 *fn = dupstr(fontname);
7565 wc_set_window_colors(op)
7569 * menu white/black message green/yellow status white/blue text
7574 char *wn, *tfg, *tbg, *newop;
7575 static const char *wnames[] = { "menu", "message", "status", "text" };
7576 static const char *shortnames[] = { "mnu", "msg", "sts", "txt" };
7577 static char **fgp[] = { &iflags.wc_foregrnd_menu,
7578 &iflags.wc_foregrnd_message,
7579 &iflags.wc_foregrnd_status,
7580 &iflags.wc_foregrnd_text };
7581 static char **bgp[] = { &iflags.wc_backgrnd_menu,
7582 &iflags.wc_backgrnd_message,
7583 &iflags.wc_backgrnd_status,
7584 &iflags.wc_backgrnd_text };
7587 newop = mungspaces(buf);
7588 while (newop && *newop) {
7589 wn = tfg = tbg = (char *) 0;
7591 /* until first non-space in case there's leading spaces - before
7600 /* until first space - colorname*/
7601 while (*newop && *newop != ' ')
7609 /* until first non-space - before foreground*/
7617 /* until slash - foreground */
7618 while (*newop && *newop != '/')
7626 /* until first non-space (in case there's leading space after slash) -
7627 * before background */
7635 /* until first space - background */
7636 while (*newop && *newop != ' ')
7641 for (j = 0; j < 4; ++j) {
7642 if (!strcmpi(wn, wnames[j]) || !strcmpi(wn, shortnames[j])) {
7643 if (tfg && !strstri(tfg, " ")) {
7645 free((genericptr_t) *fgp[j]);
7646 *fgp[j] = dupstr(tfg);
7648 if (tbg && !strstri(tbg, " ")) {
7650 free((genericptr_t) *bgp[j]);
7651 *bgp[j] = dupstr(tbg);
7660 /* set up for wizard mode if player or save file has requested to it;
7661 called from port-specific startup code to handle `nethack -D' or
7662 OPTIONS=playmode:debug, or from dorecover()'s restgamestate() if
7663 restoring a game which was saved in wizard mode */
7668 if (authorize_wizard_mode())
7669 Strcpy(plname, "wizard");
7671 wizard = FALSE; /* not allowed or not available */
7672 /* force explore mode if we didn't make it into wizard mode */
7674 iflags.deferred_X = FALSE;
7676 /* don't need to do anything special for explore mode or normal play */
7679 #endif /* OPTION_LISTS_ONLY */