1 /* NetHack 3.6 options.c $NHDT-Date: 1510963525 2017/11/18 00:05:25 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.319 $ */
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-2018 */
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
30 #ifdef DEFAULT_WC_TILED_MAP
31 #define PREFER_TILED TRUE
33 #define PREFER_TILED FALSE
36 enum window_option_types {
44 #define PILE_LIMIT_DFLT 5
47 * NOTE: If you add (or delete) an option, please update the short
48 * options help (option_help()), the long options help (dat/opthelp),
49 * and the current options setting display function (doset()),
50 * and also the Guidebooks.
52 * The order matters. If an option is a an initial substring of another
53 * option (e.g. time and timed_delay) the shorter one must come first.
56 static struct Bool_Opt {
58 boolean *addr, initvalue;
61 { "acoustics", &flags.acoustics, TRUE, SET_IN_GAME },
62 #if defined(SYSFLAGS) && defined(AMIGA)
63 /* Amiga altmeta causes Alt+key to be converted into Meta+key by
64 low level nethack code; on by default, can be toggled off if
65 Alt+key is needed for some ASCII chars on non-ASCII keyboard */
66 { "altmeta", &sysflags.altmeta, TRUE, DISP_IN_GAME },
69 /* non-Amiga altmeta causes nethack's top level command loop to treat
70 two character sequence "ESC c" as M-c, for terminals or emulators
71 which send "ESC c" when Alt+c is pressed; off by default, enabling
72 this can potentially make trouble if user types ESC when nethack
73 is honoring this conversion request (primarily after starting a
74 count prefix prior to a command and then deciding to cancel it) */
75 { "altmeta", &iflags.altmeta, FALSE, SET_IN_GAME },
77 { "altmeta", (boolean *) 0, TRUE, DISP_IN_GAME },
80 { "ascii_map", &iflags.wc_ascii_map, !PREFER_TILED, SET_IN_GAME }, /*WC*/
81 #if defined(SYSFLAGS) && defined(MFLOPPY)
82 { "asksavedisk", &sysflags.asksavedisk, FALSE, SET_IN_GAME },
84 { "asksavedisk", (boolean *) 0, FALSE, SET_IN_FILE },
86 { "autodescribe", &iflags.autodescribe, FALSE, SET_IN_GAME },
87 { "autodig", &flags.autodig, FALSE, SET_IN_GAME },
88 { "autoopen", &flags.autoopen, TRUE, SET_IN_GAME },
89 { "autopickup", &flags.pickup, TRUE, SET_IN_GAME },
90 { "autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME },
91 #if defined(MICRO) && !defined(AMIGA)
92 { "BIOS", &iflags.BIOS, FALSE, SET_IN_FILE },
94 { "BIOS", (boolean *) 0, FALSE, SET_IN_FILE },
96 { "blind", &u.uroleplay.blind, FALSE, DISP_IN_GAME },
97 { "bones", &flags.bones, TRUE, SET_IN_FILE },
99 { "checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME },
101 { "checkpoint", (boolean *) 0, FALSE, SET_IN_FILE },
104 { "checkspace", &iflags.checkspace, TRUE, SET_IN_GAME },
106 { "checkspace", (boolean *) 0, FALSE, SET_IN_FILE },
108 { "clicklook", &iflags.clicklook, FALSE, SET_IN_GAME },
109 { "cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME },
110 #if defined(MICRO) || defined(WIN32)
111 { "color", &iflags.wc_color, TRUE, SET_IN_GAME }, /*WC*/
112 #else /* systems that support multiple terminals, many monochrome */
113 { "color", &iflags.wc_color, FALSE, SET_IN_GAME }, /*WC*/
115 { "confirm", &flags.confirm, TRUE, SET_IN_GAME },
116 { "dark_room", &flags.dark_room, TRUE, SET_IN_GAME },
117 { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME }, /*WC*/
119 { "extmenu", &iflags.extmenu, FALSE, SET_IN_GAME },
121 { "extmenu", (boolean *) 0, FALSE, SET_IN_FILE },
124 { "fast_map", &flags.fast_map, TRUE, SET_IN_GAME },
126 { "fast_map", (boolean *) 0, TRUE, SET_IN_FILE },
128 { "female", &flags.female, FALSE, DISP_IN_GAME },
129 { "fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME },
130 #if defined(SYSFLAGS) && defined(AMIFLUSH)
131 { "flush", &sysflags.amiflush, FALSE, SET_IN_GAME },
133 { "flush", (boolean *) 0, FALSE, SET_IN_FILE },
135 { "force_invmenu", &iflags.force_invmenu, FALSE, SET_IN_GAME },
136 { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE },
137 { "goldX", &iflags.goldX, FALSE, SET_IN_GAME },
138 { "help", &flags.help, TRUE, SET_IN_GAME },
139 { "herecmd_menu", &iflags.herecmd_menu, FALSE, SET_IN_GAME },
140 { "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
141 { "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
142 { "hitpointbar", &iflags.wc2_hitpointbar, FALSE, SET_IN_GAME }, /*WC2*/
144 { "ignintr", &flags.ignintr, FALSE, SET_IN_GAME },
146 { "ignintr", (boolean *) 0, FALSE, SET_IN_FILE },
148 { "implicit_uncursed", &iflags.implicit_uncursed, TRUE, SET_IN_GAME },
149 { "large_font", &iflags.obsolete, FALSE, SET_IN_FILE }, /* OBSOLETE */
150 { "legacy", &flags.legacy, TRUE, DISP_IN_GAME },
151 { "lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME },
152 { "lootabc", &flags.lootabc, FALSE, SET_IN_GAME },
154 { "mail", &flags.biff, TRUE, SET_IN_GAME },
156 { "mail", (boolean *) 0, TRUE, SET_IN_FILE },
158 { "mention_walls", &iflags.mention_walls, FALSE, SET_IN_GAME },
159 { "menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME },
160 /* for menu debugging only*/
161 { "menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_WIZGAME },
162 { "menu_objsyms", &iflags.menu_head_objsym, FALSE, SET_IN_GAME },
164 { "menu_overlay", &iflags.menu_overlay, TRUE, SET_IN_GAME },
166 { "menu_overlay", (boolean *) 0, FALSE, SET_IN_FILE },
168 { "mouse_support", &iflags.wc_mouse_support, TRUE, DISP_IN_GAME }, /*WC*/
170 { "news", &iflags.news, TRUE, DISP_IN_GAME },
172 { "news", (boolean *) 0, FALSE, SET_IN_FILE },
174 { "nudist", &u.uroleplay.nudist, FALSE, DISP_IN_GAME },
175 { "null", &flags.null, TRUE, SET_IN_GAME },
176 #if defined(SYSFLAGS) && defined(MAC)
177 { "page_wait", &sysflags.page_wait, TRUE, SET_IN_GAME },
179 { "page_wait", (boolean *) 0, FALSE, SET_IN_FILE },
181 { "perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME },
182 { "pickup_thrown", &flags.pickup_thrown, TRUE, SET_IN_GAME },
183 { "popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME }, /*WC*/
184 { "preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME }, /*WC*/
185 { "pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME },
186 #if defined(MICRO) && !defined(AMIGA)
187 { "rawio", &iflags.rawio, FALSE, DISP_IN_GAME },
189 { "rawio", (boolean *) 0, FALSE, SET_IN_FILE },
191 { "rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME },
193 { "rlecomp", &iflags.rlecomp,
194 #if defined(COMPRESS) || defined(ZLIB_COMP)
201 { "safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME },
202 { "sanity_check", &iflags.sanity_check, FALSE, SET_IN_WIZGAME },
203 { "selectsaved", &iflags.wc2_selectsaved, TRUE, DISP_IN_GAME }, /*WC*/
204 { "showexp", &flags.showexp, FALSE, SET_IN_GAME },
205 { "showrace", &flags.showrace, FALSE, SET_IN_GAME },
207 { "showscore", &flags.showscore, FALSE, SET_IN_GAME },
209 { "showscore", (boolean *) 0, FALSE, SET_IN_FILE },
211 { "silent", &flags.silent, TRUE, SET_IN_GAME },
212 { "softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE },
213 { "sortpack", &flags.sortpack, TRUE, SET_IN_GAME },
214 { "sparkle", &flags.sparkle, TRUE, SET_IN_GAME },
215 { "splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME }, /*WC*/
216 { "standout", &flags.standout, FALSE, SET_IN_GAME },
217 { "status_updates", &iflags.status_updates, TRUE, DISP_IN_GAME },
218 { "tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME }, /*WC*/
219 { "time", &flags.time, FALSE, SET_IN_GAME },
221 { "timed_delay", &flags.nap, TRUE, SET_IN_GAME },
223 { "timed_delay", (boolean *) 0, FALSE, SET_IN_GAME },
225 { "tombstone", &flags.tombstone, TRUE, SET_IN_GAME },
226 { "toptenwin", &iflags.toptenwin, FALSE, SET_IN_GAME },
227 { "travel", &flags.travelcmd, TRUE, SET_IN_GAME },
228 { "use_darkgray", &iflags.wc2_darkgray, TRUE, SET_IN_FILE },
230 { "use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME }, /*WC*/
232 { "use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME }, /*WC*/
234 { "verbose", &flags.verbose, TRUE, SET_IN_GAME },
235 #ifdef TTY_TILES_ESCCODES
236 { "vt_tiledata", &iflags.vt_tiledata, FALSE, SET_IN_FILE },
238 { "vt_tiledata", (boolean *) 0, FALSE, SET_IN_FILE },
240 { "whatis_menu", &iflags.getloc_usemenu, FALSE, SET_IN_GAME },
241 { "whatis_moveskip", &iflags.getloc_moveskip, FALSE, SET_IN_GAME },
242 { "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME },
243 { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME },
245 { "zerocomp", &iflags.zerocomp,
246 #if defined(COMPRESS) || defined(ZLIB_COMP)
253 { (char *) 0, (boolean *) 0, FALSE, 0 }
256 /* compound options, for option_help() and external programs like Amiga
258 static struct Comp_Opt {
259 const char *name, *descr;
260 int size; /* for frontends and such allocating space --
261 * usually allowed size of data in game, but
262 * occasionally maximum reasonable size for
263 * typing when game maintains information in
264 * a different format */
268 { "align", "your starting alignment (lawful, neutral, or chaotic)", 8,
270 { "align", "
\83Q
\81[
\83\80\83X
\83^
\81[
\83g
\8e\9e\82Ì
\91®
\90« (lawful, neutral, or chaotic
\82Ì
\82¢
\82¸
\82ê
\82©)", 8,
273 { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/
275 { "align_message", "
\83\81\83b
\83Z
\81[
\83W
\83E
\83B
\83\93\83h
\83E
\82Ì
\91µ
\82¦", 20, DISP_IN_GAME }, /*WC*/
278 { "align_status", "status window alignment", 20, DISP_IN_GAME }, /*WC*/
280 { "align_status", "
\8fó
\8bµ
\83E
\83B
\83\93\83h
\83E
\82Ì
\91µ
\82¦", 20, DISP_IN_GAME }, /*WC*/
283 { "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
285 { "altkeyhandler", "ALT
\83L
\81[
\83n
\83\93\83h
\83\89", 20, DISP_IN_GAME },
286 #ifdef BACKWARD_COMPAT
288 { "boulder", "deprecated (use S_boulder in sym file instead)", 1,
290 { "boulder", "
\8b\90\8aâ
\82ð
\95\
\8e¦
\82·
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a", 1,
294 { "catname", "the name of your (first) cat (e.g., catname:Tabby)",
296 { "catname", "
\96`
\8c¯
\82ð
\8b\9f\82É
\82·
\82é(
\8dÅ
\8f\89\82Ì)
\94L
\82Ì
\96¼
\91O (
\97á catname:
\82½
\82Ü)",
297 PL_PSIZ, DISP_IN_GAME },
299 { "disclose", "the kinds of information to disclose at end of game",
301 { "disclose", "
\83Q
\81[
\83\80\8fI
\97¹
\8e\9e\82É
\8c©
\82é
\8fî
\95ñ
\82Ì
\8eí
\97Þ",
302 sizeof(flags.end_disclose) * 2, SET_IN_GAME },
304 { "dogname", "the name of your (first) dog (e.g., dogname:Fang)", PL_PSIZ,
306 { "dogname", "
\96`
\8c¯
\82ð
\8b\9f\82É
\82·
\82é(
\8dÅ
\8f\89\82Ì)
\8c¢
\82Ì
\96¼
\91O (
\97á dogname:
\83|
\83`)", PL_PSIZ,
309 { "dungeon", "the symbols to use in drawing the dungeon map",
311 { "dungeon", "
\83_
\83\93\83W
\83\87\83\93\82ð
\95`
\89æ
\82·
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a",
312 MAXDCHARS + 1, SET_IN_FILE },
314 { "effects", "the symbols to use in drawing special effects",
316 { "effects", "
\93Á
\8eê
\8cø
\89Ê
\82ð
\95`
\89æ
\82·
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a",
317 MAXECHARS + 1, SET_IN_FILE },
319 { "font_map", "the font to use in the map window", 40,
321 { "font_map", "
\83}
\83b
\83v
\83E
\83B
\83\93\83h
\83E
\82É
\8eg
\97p
\82·
\82é
\83t
\83H
\83\93\83g", 40,
322 DISP_IN_GAME }, /*WC*/
324 { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/
326 { "font_menu", "
\83\81\83j
\83\85\81[
\82É
\8eg
\97p
\82·
\82é
\83t
\83H
\83\93\83g", 40, DISP_IN_GAME }, /*WC*/
329 { "font_message", "the font to use in the message window", 40,
331 { "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,
332 DISP_IN_GAME }, /*WC*/
334 { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/
336 { "font_size_map", "
\83}
\83b
\83v
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20, DISP_IN_GAME }, /*WC*/
339 { "font_size_menu", "the size of the menu font", 20,
341 { "font_size_menu", "
\83\81\83j
\83\85\81[
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20,
342 DISP_IN_GAME }, /*WC*/
344 { "font_size_message", "the size of the message font", 20,
346 { "font_size_message", "
\83\81\83b
\83Z
\81[
\83W
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20,
347 DISP_IN_GAME }, /*WC*/
349 { "font_size_status", "the size of the status font", 20,
351 { "font_size_status", "
\8fó
\8bµ
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20,
352 DISP_IN_GAME }, /*WC*/
354 { "font_size_text", "the size of the text font", 20,
356 { "font_size_text", "
\83e
\83L
\83X
\83g
\83t
\83H
\83\93\83g
\82Ì
\83T
\83C
\83Y", 20,
357 DISP_IN_GAME }, /*WC*/
359 { "font_status", "the font to use in status window", 40,
361 { "font_status", "
\8fó
\8bµ
\83E
\83B
\83\93\83h
\83E
\82É
\8eg
\97p
\82·
\82é
\83t
\83H
\83\93\83g", 40,
362 DISP_IN_GAME }, /*WC*/
364 { "font_text", "the font to use in text windows", 40,
366 { "font_text", "
\83e
\83L
\83X
\83g
\83E
\83B
\83\93\83h
\83E
\82É
\8eg
\97p
\82·
\82é
\83t
\83H
\83\93\83g", 40,
367 DISP_IN_GAME }, /*WC*/
369 { "fruit", "the name of a fruit you enjoy eating", PL_FSIZ, SET_IN_GAME },
371 { "fruit", "
\8dD
\95¨
\82Ì
\89Ê
\95¨
\82Ì
\96¼
\91O", PL_FSIZ, SET_IN_GAME },
373 { "gender", "your starting gender (male or female)", 8, DISP_IN_GAME },
375 { "gender", "
\83Q
\81[
\83\80\8aJ
\8en
\8e\9e\82Ì
\90«
\95Ê(male
\82Ü
\82½
\82Í female)", 8, DISP_IN_GAME },
377 { "horsename", "the name of your (first) horse (e.g., horsename:Silver)",
379 { "horsename", "
\96`
\8c¯
\82ð
\8b\9f\82É
\82·
\82é(
\8dÅ
\8f\89\82Ì)
\94n
\82Ì
\96¼
\91O (
\97á ghoulname:
\83V
\83\8b\83o
\81[)",
380 PL_PSIZ, DISP_IN_GAME },
382 { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/
384 { "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*/
387 { "menustyle", "user interface for object selection", MENUTYPELEN,
389 { "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,
392 { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE },
394 { "menu_deselect_all", "
\91S
\82Ä
\82Ì
\83A
\83C
\83e
\83\80\82ð
\94ñ
\91I
\91ð", 4, SET_IN_FILE },
396 { "menu_deselect_page", "deselect all items on this page of a menu", 4,
398 { "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,
401 { "menu_first_page", "jump to the first page in a menu", 4, SET_IN_FILE },
403 { "menu_first_page", "
\83\81\83j
\83\85\81[
\82Ì
\8dÅ
\8f\89\82Ì
\83y
\81[
\83W
\82Ö", 4, SET_IN_FILE },
405 { "menu_headings", "text attribute for menu headings", 9, SET_IN_GAME },
407 { "menu_headings", "
\8b
\92²
\81C
\94½
\93]
\82Ü
\82½
\82Í
\89º
\90ü
\82Å
\8eí
\97Þ
\82ð
\95\
\8e¦
\82·
\82é", 9, SET_IN_GAME },
409 { "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
411 { "menu_invert_all", "
\91S
\82Ä
\82Ì
\83A
\83C
\83e
\83\80\82ð
\94½
\93]", 4, SET_IN_FILE },
413 { "menu_invert_page", "invert all items on this page of a menu", 4,
415 { "menu_invert_page", "
\8c»
\8dÝ
\95\
\8e¦
\82³
\82ê
\82Ä
\82¢
\82é
\83y
\81[
\83W
\82Ì
\83A
\83C
\83e
\83\80\82ð
\94½
\93]",
418 { "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE },
420 { "menu_last_page", "
\83\81\83j
\83\85\81[
\82Ì
\8dÅ
\8cã
\82Ì
\83y
\81[
\83W
\82Ö", 4, SET_IN_FILE },
422 { "menu_next_page", "goto the next menu page", 4, SET_IN_FILE },
424 { "menu_next_page", "
\8e\9f\82Ì
\83\81\83j
\83\85\81[
\82Ì
\83y
\81[
\83W
\82Ö", 4, SET_IN_FILE },
426 { "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE },
428 { "menu_previous_page", "
\91O
\82Ì
\83\81\83j
\83\85\81[
\82Ì
\83y
\81[
\83W
\82Ö", 4, SET_IN_FILE },
430 { "menu_search", "search for a menu item", 4, SET_IN_FILE },
432 { "menu_search", "
\83\81\83j
\83\85\81[
\82Ì
\8c\9f\8dõ", 4, SET_IN_FILE },
434 { "menu_select_all", "select all items in a menu", 4, SET_IN_FILE },
436 { "menu_select_all", "
\91S
\82Ä
\82Ì
\83A
\83C
\83e
\83\80\82ð
\91I
\91ð", 4, SET_IN_FILE },
438 { "menu_select_page", "select all items on this page of a menu", 4,
440 { "menu_select_page", "
\8c»
\8dÝ
\95\
\8e¦
\82³
\82ê
\82Ä
\82¢
\82é
\91S
\82Ä
\82Ì
\83A
\83C
\83e
\83\80\82ð
\91I
\91ð", 4,
443 { "monsters", "the symbols to use for monsters", MAXMCLASSES,
445 { "monsters", "
\83\82\83\93\83X
\83^
\81[
\82É
\8eg
\97p
\82³
\82ê
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a", MAXMCLASSES,
448 { "msghistory", "number of top line messages to save", 5, DISP_IN_GAME },
450 { "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 },
453 { "msg_window", "the type of message window required", 1, SET_IN_GAME },
455 {"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 },
458 { "msg_window", "the type of message window required", 1, SET_IN_FILE },
460 {"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 },
463 { "name", "your character's name (e.g., name:Merlin-W)", PL_NSIZ,
465 { "name", "
\82 \82È
\82½
\82Ì
\96¼
\91O (
\97á name:
\83}
\81[
\83\8a\83\93-W)", PL_NSIZ,
468 { "number_pad", "use the number pad for movement", 1, SET_IN_GAME },
470 { "number_pad", "
\83i
\83\93\83o
\81[
\83p
\83b
\83h
\82ð
\8eg
\97p
\82·
\82é", 1, SET_IN_GAME },
472 { "objects", "the symbols to use for objects", MAXOCLASSES, SET_IN_FILE },
474 { "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 },
476 { "packorder", "the inventory order of the items in your pack",
478 { "packorder", "
\94w
\95\89\82¢
\91Ü
\93à
\82Ì
\95¨
\82Ì
\8f\87\94Ô",
479 MAXOCLASSES, SET_IN_GAME },
484 "palette (00c/880/-fff is blue/yellow/reverse white)", 15,
486 "
\83p
\83\8c\83b
\83g (00c/880/-fff
\82Í
\82»
\82ê
\82¼
\82ê
\90Â/
\89©/
\94½
\93]
\94\92\82ð
\8e¦
\82·)", 15,
490 "palette (adjust an RGB color in palette (color-R-G-B)", 15,
492 "
\83p
\83\8c\83b
\83g (
\83p
\83\8c\83b
\83g
\82ÌRGB
\90F
\82ð
\92²
\90®
\82·
\82é (
\90F-R-G-B)", 15,
497 { "hicolor", "same as palette, only order is reversed", 15, SET_IN_FILE },
499 { "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 },
503 { "paranoid_confirmation", "extra prompting in certain situations", 28,
506 { "paranoid_confirmation", "
\88ê
\95\94\82Ì
\8fó
\8bµ
\82Å
\92Ç
\89Á
\82Ì
\8am
\94F
\82ð
\82·
\82é", 28,
510 { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME },
512 { "pettype", "
\82 \82È
\82½
\82Ì
\91I
\91ð
\82µ
\82½
\8f\89\8aú
\83y
\83b
\83g
\82Ì
\8eí
\97Þ", 4, DISP_IN_GAME },
514 { "pickup_burden", "maximum burden picked up before prompt", 20,
516 { "pickup_burden", "
\8fE
\82¤
\82Æ
\82«
\82É
\8dÅ
\91å
\89×
\8fd
\82É
\82È
\82é
\8eè
\91O
\82Å
\8am
\94F
\82·
\82é", 20,
519 { "pickup_types", "types of objects to pick up automatically",
521 { "pickup_types", "
\8e©
\93®
\82Å
\8fE
\82¢
\82 \82°
\82é
\95¨
\82Ì
\83V
\83\93\83{
\83\8b",
522 MAXOCLASSES, SET_IN_GAME },
524 { "pile_limit", "threshold for \"there are many objects here\"", 24,
527 { "pile_limit", "
\81u
\82±
\82±
\82É
\82Í
\82½
\82
\82³
\82ñ
\82Ì
\82à
\82Ì
\82ª
\82 \82é
\81v
\82Ì
\82µ
\82«
\82¢
\92l", 24,
531 { "playmode", "normal play, non-scoring explore mode, or debug mode", 8,
534 { "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,
538 { "player_selection", "choose character via dialog or prompts", 12,
540 { "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,
543 { "race", "your starting race (e.g., Human, Elf)", PL_CSIZ,
545 { "race", "
\83Q
\81[
\83\80\8aJ
\8en
\8e\9e\82Ì
\8eí
\91° (
\97á Human, Elf)", PL_CSIZ,
548 { "role", "your starting role (e.g., Barbarian, Valkyrie)", PL_CSIZ,
550 { "role", "
\83Q
\81[
\83\80\8aJ
\8en
\8e\9e\82Ì
\90E
\8bÆ (
\97á Barbarian, Valkyrie)", PL_CSIZ,
553 { "runmode", "display frequency when `running' or `travelling'",
555 { "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",
556 sizeof "teleport", SET_IN_GAME },
558 { "scores", "the parts of the score list you wish to see", 32,
560 { "scores", "
\83Q
\81[
\83\80\8fI
\97¹
\8e\9e\82É
\8c©
\82é
\83X
\83R
\83A
\82Ì
\8eí
\97Þ", 32,
563 { "scroll_amount", "amount to scroll map when scroll_margin is reached",
565 { "scroll_amount", "scroll_margin
\82É
\93Í
\82¢
\82½
\82Æ
\82«
\82Ì
\83}
\83b
\83v
\83X
\83N
\83\8d\81[
\83\8b\97Ê",
566 20, DISP_IN_GAME }, /*WC*/
568 { "scroll_margin", "scroll map when this far from the edge", 20,
570 { "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,
571 DISP_IN_GAME }, /*WC*/
573 { "sortloot", "sort object selection lists by description", 4,
575 { "sortloot", "
\95¨
\91Ì
\91I
\91ð
\83\8a\83X
\83g
\82ð
\90à
\96¾
\82Å
\83\
\81[
\83g
\82·
\82é", 4,
579 { "soundcard", "type of sound card to use", 20, SET_IN_FILE },
581 { "soundcard", "
\8eg
\97p
\82µ
\82Ä
\82¢
\82é
\83T
\83E
\83\93\83h
\83J
\81[
\83h
\82Ì
\8eí
\97Þ", 20, SET_IN_FILE },
583 #ifdef STATUS_HILITES
586 "0=no status highlighting, N=show highlights for N turns",
589 "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¦",
594 { "statushilites", "highlight control", 20, SET_IN_FILE },
596 { "statushilites", "
\83n
\83C
\83\89\83C
\83g
\82Ì
\90§
\8cä", 20, SET_IN_FILE },
599 { "symset", "load a set of display symbols from the symbols file", 70,
602 { "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,
607 "load a set of rogue display symbols from the symbols file", 70,
611 "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,
616 { "subkeyvalue", "override keystroke value", 7, SET_IN_FILE },
618 {"subkeyvalue", "
\83L
\81[
\83}
\83b
\83s
\83\93\83O
\82ð
\95Ï
\8dX
\82·
\82é", 7, SET_IN_FILE },
621 { "suppress_alert", "suppress alerts about version-specific features", 8,
623 { "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,
626 { "tile_width", "width of tiles", 20, DISP_IN_GAME }, /*WC*/
628 { "tile_width", "
\83^
\83C
\83\8b\82Ì
\95\9d", 20, DISP_IN_GAME }, /*WC*/
631 { "tile_height", "height of tiles", 20, DISP_IN_GAME }, /*WC*/
633 { "tile_height", "
\83^
\83C
\83\8b\82Ì
\8d\82\82³", 20, DISP_IN_GAME }, /*WC*/
636 { "tile_file", "name of tile file", 70, DISP_IN_GAME }, /*WC*/
638 { "tile_file", "
\83^
\83C
\83\8b\83t
\83@
\83C
\83\8b\82Ì
\96¼
\91O", 70, DISP_IN_GAME }, /*WC*/
641 { "traps", "the symbols to use in drawing traps", MAXTCHARS + 1,
643 { "traps", "ã©
\82ð
\95`
\89æ
\82·
\82é
\83V
\83\93\83{
\83\8b\95¶
\8e\9a", MAXTCHARS + 1,
646 { "vary_msgcount", "show more old messages at a time", 20,
648 { "vary_msgcount", "
\88ê
\93x
\82É
\95\
\8e¦
\82·
\82é
\83\81\83b
\83Z
\81[
\83W
\82Ì
\90\94", 20,
649 DISP_IN_GAME }, /*WC*/
652 { "video", "method of video updating", 20, SET_IN_FILE },
654 { "video", "
\8eg
\97p
\82·
\82é
\83r
\83f
\83I
\83\82\81[
\83h
\82ð
\90Ý
\92è
\82·
\82é", 20, SET_IN_FILE },
658 { "videocolors", "color mappings for internal screen routines", 40,
660 { "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,
663 { "videoshades", "gray shades to map to black/gray/white", 32,
665 { "videoshades", "
\95\
\8e¦
\82É
\83O
\83\8c\83C
\83X
\83P
\81[
\83\8b\82ð
\97p
\82¢
\82é", 32,
669 { "whatis_coord", "show coordinates when auto-describing cursor position",
672 { "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é",
677 "filter coordinate locations when targeting next or previous",
681 "
\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é",
685 { "windowcolors", "the foreground/background colors of windows", /*WC*/
688 { "windowcolors", "
\83E
\83B
\83\93\83h
\83E
\82ð
\8ew
\92è
\82µ
\82½
\91O
\8ci
\90F/
\94w
\8ci
\90F
\82Å
\95\
\8e¦
\82·
\82é", /*WC*/
692 { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
694 { "windowtype", "
\8eg
\97p
\82·
\82é
\83E
\83C
\83\93\83h
\83E
\83V
\83X
\83e
\83\80", WINTYPELEN, DISP_IN_GAME },
697 { "windowchain", "window processor to use", WINTYPELEN, SET_IN_SYS },
699 { "windowchain", "
\8eg
\97p
\82·
\82é
\83E
\83B
\83\93\83h
\83E
\83v
\83\8d\83Z
\83b
\83T", WINTYPELEN, SET_IN_SYS },
701 #ifdef BACKWARD_COMPAT
703 { "DECgraphics", "load DECGraphics display symbols", 70, SET_IN_FILE },
705 { "DECgraphics", "DECGraphics
\95\
\8e¦
\83V
\83\93\83{
\83\8b\82ð
\93Ç
\82Ý
\8d\9e\82Þ", 70, SET_IN_FILE },
707 { "IBMgraphics", "load IBMGraphics display symbols", 70, SET_IN_FILE },
709 { "IBMgraphics", "IBMGraphics
\95\
\8e¦
\83V
\83\93\83{
\83\8b\82ð
\93Ç
\82Ý
\8d\9e\82Þ", 70, SET_IN_FILE },
710 #ifdef MAC_GRAPHICS_ENV
712 { "Macgraphics", "load MACGraphics display symbols", 70, SET_IN_FILE },
714 { "Macgraphics", "MACGraphics
\95\
\8e¦
\83V
\83\93\83{
\83\8b\82ð
\93Ç
\82Ý
\8d\9e\82Þ", 70, SET_IN_FILE },
718 { "kcode", "
\92[
\96\96\82Ì
\8a¿
\8e\9a\83R
\81[
\83h,", 4, SET_IN_FILE },
720 { (char *) 0, (char *) 0, 0, 0 }
723 #ifdef OPTION_LISTS_ONLY
726 #else /* use rest of file */
728 extern char configfile[]; /* for messages */
730 extern struct symparse loadsyms[];
731 static boolean need_redraw; /* for doset() */
733 #if defined(TOS) && defined(TEXTCOLOR)
734 extern boolean colors_changed; /* in tos.c */
738 extern char *shade[3]; /* in sys/msdos/video.c */
739 extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */
742 static char def_inv_order[MAXOCLASSES] = {
743 COIN_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS,
744 SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS,
745 TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0,
749 * Default menu manipulation command accelerators. These may _not_ be:
751 * + a number - reserved for counts
752 * + an upper or lower case US ASCII letter - used for accelerators
753 * + ESC - reserved for escaping the menu
754 * + NULL, CR or LF - reserved for commiting the selection(s). NULL
755 * is kind of odd, but the tty's xwaitforspace() will return it if
756 * someone hits a <ret>.
757 * + a default object class symbol - used for object class accelerators
759 * Standard letters (for now) are:
772 * The command name list is duplicated in the compopt array.
780 static const menu_cmd_t default_menu_cmd_info[] = {
781 { "menu_first_page", MENU_FIRST_PAGE, "Go to first page" },
782 { "menu_last_page", MENU_LAST_PAGE, "Go to last page" },
783 { "menu_next_page", MENU_NEXT_PAGE, "Go to next page" },
784 { "menu_previous_page", MENU_PREVIOUS_PAGE, "Go to previous page" },
785 { "menu_select_all", MENU_SELECT_ALL, "Select all items" },
786 { "menu_deselect_all", MENU_UNSELECT_ALL, "Unselect all items" },
787 { "menu_invert_all", MENU_INVERT_ALL, "Invert selection" },
788 { "menu_select_page", MENU_SELECT_PAGE, "Select items in current page" },
789 { "menu_deselect_page", MENU_UNSELECT_PAGE,
790 "Unselect items in current page" },
791 { "menu_invert_page", MENU_INVERT_PAGE, "Invert current page selection" },
792 { "menu_search", MENU_SEARCH, "Search and toggle matching items" },
796 * Allow the user to map incoming characters to various menu commands.
797 * The accelerator list must be a valid C string.
799 #define MAX_MENU_MAPPED_CMDS 32 /* some number */
800 char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS + 1]; /* exported */
801 static char mapped_menu_op[MAX_MENU_MAPPED_CMDS + 1];
802 static short n_menu_mapped = 0;
804 static boolean initial, from_file;
806 STATIC_DCL void FDECL(nmcpy, (char *, const char *, int));
807 STATIC_DCL void FDECL(escapes, (const char *, char *));
808 STATIC_DCL void FDECL(rejectoption, (const char *));
809 STATIC_DCL char *FDECL(string_for_opt, (char *, BOOLEAN_P));
810 STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *, BOOLEAN_P));
811 STATIC_DCL void FDECL(bad_negation, (const char *, BOOLEAN_P));
812 STATIC_DCL int FDECL(change_inv_order, (char *));
813 STATIC_DCL boolean FDECL(warning_opts, (char *, const char *));
814 STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *));
815 STATIC_DCL boolean FDECL(duplicate_opt_detection, (const char *, int));
816 STATIC_DCL void FDECL(complain_about_duplicate, (const char *, int));
818 STATIC_DCL const char *FDECL(attr2attrname, (int));
819 STATIC_DCL const char * FDECL(msgtype2name, (int));
820 STATIC_DCL int NDECL(query_msgtype);
821 STATIC_DCL boolean FDECL(msgtype_add, (int, char *));
822 STATIC_DCL void FDECL(free_one_msgtype, (int));
823 STATIC_DCL int NDECL(msgtype_count);
824 STATIC_DCL boolean FDECL(test_regex_pattern, (const char *, const char *));
825 STATIC_DCL boolean FDECL(add_menu_coloring_parsed, (char *, int, int));
826 STATIC_DCL void FDECL(free_one_menu_coloring, (int));
827 STATIC_DCL int NDECL(count_menucolors);
828 STATIC_DCL boolean FDECL(parse_role_opts, (BOOLEAN_P, const char *,
831 STATIC_DCL void FDECL(oc_to_str, (char *, char *));
832 STATIC_DCL void FDECL(doset_add_menu, (winid, const char *, int));
833 STATIC_DCL void FDECL(opts_add_others, (winid, const char *, int,
835 STATIC_DCL int FDECL(handle_add_list_remove, (const char *, int));
836 STATIC_DCL boolean FDECL(special_handling, (const char *,
837 BOOLEAN_P, BOOLEAN_P));
838 STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *));
839 STATIC_DCL void FDECL(remove_autopickup_exception,
840 (struct autopickup_exception *));
841 STATIC_DCL int FDECL(count_ape_maps, (int *, int *));
843 STATIC_DCL boolean FDECL(is_wc_option, (const char *));
844 STATIC_DCL boolean FDECL(wc_supported, (const char *));
845 STATIC_DCL boolean FDECL(is_wc2_option, (const char *));
846 STATIC_DCL boolean FDECL(wc2_supported, (const char *));
847 STATIC_DCL void FDECL(wc_set_font_name, (int, char *));
848 STATIC_DCL int FDECL(wc_set_window_colors, (char *));
855 for (x = 0; x < COLNO; x++)
856 for (y = 0; y < ROWNO; y++) {
857 struct rm *lev = &levl[x][y];
859 if (!flags.dark_room || !iflags.use_color
860 || Is_rogue_level(&u.uz)) {
861 if (lev->glyph == cmap_to_glyph(S_darkroom))
862 lev->glyph = lev->waslit ? cmap_to_glyph(S_room)
863 : cmap_to_glyph(S_stone);
865 if (lev->glyph == cmap_to_glyph(S_room) && lev->seenv
866 && lev->waslit && !cansee(x, y))
867 lev->glyph = cmap_to_glyph(S_darkroom);
868 else if (lev->glyph == cmap_to_glyph(S_stone)
869 && lev->typ == ROOM && lev->seenv && !cansee(x, y))
870 lev->glyph = cmap_to_glyph(S_darkroom);
873 if (flags.dark_room && iflags.use_color)
874 showsyms[S_darkroom] = showsyms[S_room];
876 showsyms[S_darkroom] = showsyms[S_stone];
879 /* check whether a user-supplied option string is a proper leading
880 substring of a particular option name; option string might have
881 a colon or equals sign and arbitrary value appended to it */
883 match_optname(user_string, opt_name, min_length, val_allowed)
884 const char *user_string, *opt_name;
888 int len = (int) strlen(user_string);
891 const char *p = index(user_string, ':'),
892 *q = index(user_string, '=');
894 if (!p || (q && q < p))
897 /* 'user_string' hasn't necessarily been through mungspaces()
898 so might have tabs or consecutive spaces */
899 while (p > user_string && isspace((uchar) *(p - 1)))
901 len = (int) (p - user_string);
905 return (boolean) (len >= min_length
906 && !strncmpi(opt_name, user_string, len));
909 /* most environment variables will eventually be printed in an error
910 * message if they don't work, and most error message paths go through
911 * BUFSZ buffers, which could be overflowed by a maliciously long
912 * environment variable. If a variable can legitimately be long, or
913 * if it's put in a smaller buffer, the responsible code will have to
914 * bounds-check itself.
920 char *getev = getenv(ev);
922 if (getev && strlen(getev) <= (BUFSZ / 2))
928 /* process options, possibly including SYSCF */
934 /* someday there may be other SYSCF alternatives besides text file */
936 /* If SYSCF_FILE is specified, it _must_ exist... */
938 config_error_init(TRUE, SYSCF_FILE, FALSE);
940 /* ... and _must_ parse correctly. */
941 if (!read_config_file(SYSCF_FILE, SET_IN_SYS)) {
942 if (config_error_done())
943 nh_terminate(EXIT_FAILURE);
947 * TODO [maybe]: parse the sysopt entries which are space-separated
948 * lists of usernames into arrays with one name per element.
952 initoptions_finish();
958 #if defined(UNIX) || defined(VMS)
963 /* set up the command parsing */
964 reset_commands(TRUE); /* init */
966 /* initialize the random number generator */
969 /* for detection of configfile options specified multiple times */
970 iflags.opt_booldup = iflags.opt_compdup = (int *) 0;
972 for (i = 0; boolopt[i].name; i++) {
974 *(boolopt[i].addr) = boolopt[i].initvalue;
976 #if defined(COMPRESS) || defined(ZLIB_COMP)
977 set_savepref("externalcomp");
978 set_restpref("externalcomp");
980 set_savepref("!rlecomp");
981 set_restpref("!rlecomp");
985 set_savepref("zerocomp");
986 set_restpref("zerocomp");
989 set_savepref("rlecomp");
990 set_restpref("rlecomp");
994 Strcpy(sysflags.sysflagsid, "sysflags");
995 sysflags.sysflagsid[9] = (char) sizeof(struct sysflag);
997 flags.end_own = FALSE;
999 flags.end_around = 2;
1000 flags.paranoia_bits = PARANOID_PRAY; /* old prayconfirm=TRUE */
1001 flags.pile_limit = PILE_LIMIT_DFLT; /* 5 */
1002 flags.runmode = RUN_LEAP;
1003 iflags.msg_history = 20;
1005 iflags.prevmsg_window = 's';
1007 iflags.menu_headings = ATR_INVERSE;
1008 iflags.getpos_coords = GPCOORDS_NONE;
1010 /* hero's role, race, &c haven't been chosen yet */
1011 flags.initrole = flags.initrace = flags.initgend = flags.initalign
1014 /* Set the default monster and object class symbols. */
1016 for (i = 0; i < WARNCOUNT; i++)
1017 warnsyms[i] = def_warnsyms[i].sym;
1018 iflags.bouldersym = 0;
1020 iflags.travelcc.x = iflags.travelcc.y = -1;
1022 /* for "special achievement" tracking (see obj.h,
1023 create_object(sp_lev.c), addinv_core1(invent.c) */
1024 iflags.mines_prize_type = LUCKSTONE;
1025 iflags.soko_prize_type1 = BAG_OF_HOLDING;
1026 iflags.soko_prize_type2 = AMULET_OF_REFLECTION;
1028 /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
1029 (void) memcpy((genericptr_t) flags.inv_order,
1030 (genericptr_t) def_inv_order, sizeof flags.inv_order);
1031 flags.pickup_types[0] = '\0';
1032 flags.pickup_burden = MOD_ENCUMBER;
1033 flags.sortloot = 'l'; /* sort only loot by default */
1035 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
1036 flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
1037 switch_symbols(FALSE); /* set default characters */
1038 #if defined(UNIX) && defined(TTY_GRAPHICS)
1040 * Set defaults for some options depending on what we can
1041 * detect about the environment's capabilities.
1042 * This has to be done after the global initialization above
1043 * and before reading user-specific initialization via
1044 * config file/environment variable below.
1046 /* this detects the IBM-compatible console on most 386 boxes */
1047 if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
1048 if (!symset[PRIMARY].name)
1049 load_symset("IBMGraphics", PRIMARY);
1050 if (!symset[ROGUESET].name)
1051 load_symset("RogueIBM", ROGUESET);
1052 switch_symbols(TRUE);
1054 iflags.use_color = TRUE;
1057 #endif /* UNIX && TTY_GRAPHICS */
1058 #if defined(UNIX) || defined(VMS)
1060 /* detect whether a "vt" terminal can handle alternate charsets */
1061 if ((opts = nh_getenv("TERM"))
1062 /* [could also check "xterm" which emulates vtXXX by default] */
1063 && !strncmpi(opts, "vt", 2)
1064 && AS && AE && index(AS, '\016') && index(AE, '\017')) {
1065 if (!symset[PRIMARY].name)
1066 load_symset("DECGraphics", PRIMARY);
1067 switch_symbols(TRUE);
1070 #endif /* UNIX || VMS */
1072 #ifdef MAC_GRAPHICS_ENV
1073 if (!symset[PRIMARY].name)
1074 load_symset("MACGraphics", PRIMARY);
1075 switch_symbols(TRUE);
1076 #endif /* MAC_GRAPHICS_ENV */
1077 flags.menu_style = MENU_FULL;
1079 /* since this is done before init_objects(), do partial init here */
1080 objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
1081 nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
1085 initoptions_finish()
1088 char *opts = getenv("NETHACKOPTIONS");
1091 opts = getenv("HACKOPTIONS");
1093 if (*opts == '/' || *opts == '\\' || *opts == '@') {
1095 opts++; /* @filename */
1096 /* looks like a filename */
1097 if (strlen(opts) < BUFSZ / 2) {
1098 config_error_init(TRUE, opts, CONFIG_ERROR_SECURE);
1099 read_config_file(opts, SET_IN_FILE);
1100 config_error_done();
1103 config_error_init(TRUE, (char *) 0, FALSE);
1104 read_config_file((char *) 0, SET_IN_FILE);
1105 config_error_done();
1106 /* let the total length of options be long;
1107 * parseoptions() will check each individually
1109 config_error_init(FALSE, "NETHACKOPTIONS", FALSE);
1110 (void) parseoptions(opts, TRUE, FALSE);
1111 config_error_done();
1116 config_error_init(TRUE, (char *) 0, FALSE);
1117 read_config_file((char *) 0, SET_IN_FILE);
1118 config_error_done();
1121 (void) fruitadd(pl_fruit, (struct fruit *) 0);
1123 * Remove "slime mold" from list of object names. This will
1124 * prevent it from being wished unless it's actually present
1125 * as a named (or default) fruit. Wishing for "fruit" will
1126 * result in the player's preferred fruit [better than "\033"].
1128 obj_descr[SLIME_MOLD].oc_name = "fruit";
1130 if (iflags.bouldersym)
1131 update_bouldersym();
1134 #ifdef STATUS_HILITES
1136 * A multi-interface binary might only support status highlighting
1137 * for some of the interfaces; check whether we asked for it but are
1138 * using one which doesn't.
1140 if (iflags.hilite_delta && !wc2_supported("statushilites")) {
1141 raw_printf("Status highlighting not supported for %s interface.",
1143 iflags.hilite_delta = 0;
1150 nmcpy(dest, src, maxlen)
1157 for (count = 1; count < maxlen; count++) {
1158 if (*src == ',' || *src == '\0')
1159 break; /*exit on \0 terminator*/
1166 * escapes(): escape expansion for showsyms. C-style escapes understood
1167 * include \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal).
1168 * The ^-prefix for control characters is also understood, and \[mM]
1169 * has the effect of 'meta'-ing the value which follows (so that the
1170 * alternate character set will be enabled).
1176 * For 3.4.3 and earlier, input ending with "\M", backslash, or caret
1177 * prior to terminating '\0' would pull that '\0' into the output and then
1178 * keep processing past it, potentially overflowing the output buffer.
1179 * Now, trailing \ or ^ will act like \\ or \^ and add '\\' or '^' to the
1180 * output and stop there; trailing \M will fall through to \<other> and
1181 * yield 'M', then stop. Any \X or \O followed by something other than
1182 * an appropriate digit will also fall through to \<other> and yield 'X'
1183 * or 'O', plus stop if the non-digit is end-of-string.
1190 static NEARDATA const char oct[] = "01234567", dec[] = "0123456789",
1191 hex[] = "00112233445566778899aAbBcCdDeEfF";
1193 int cval, meta, dcount;
1196 /* \M has to be followed by something to do meta conversion,
1197 otherwise it will just be \M which ultimately yields 'M' */
1198 meta = (*cp == '\\' && (cp[1] == 'm' || cp[1] == 'M') && cp[2]);
1202 cval = dcount = 0; /* for decimal, octal, hexadecimal cases */
1203 if ((*cp != '\\' && *cp != '^') || !cp[1]) {
1204 /* simple character, or nothing left for \ or ^ to escape */
1206 } else if (*cp == '^') { /* expand control-character syntax */
1207 cval = (*++cp & 0x1f);
1210 /* remaining cases are all for backslash; we know cp[1] is not \0 */
1211 } else if (index(dec, cp[1])) {
1212 ++cp; /* move past backslash to first digit */
1214 cval = (cval * 10) + (*cp - '0');
1215 } while (*++cp && index(dec, *cp) && ++dcount < 3);
1216 } else if ((cp[1] == 'o' || cp[1] == 'O') && cp[2]
1217 && index(oct, cp[2])) {
1218 cp += 2; /* move past backslash and 'O' */
1220 cval = (cval * 8) + (*cp - '0');
1221 } while (*++cp && index(oct, *cp) && ++dcount < 3);
1222 } else if ((cp[1] == 'x' || cp[1] == 'X') && cp[2]
1223 && (dp = index(hex, cp[2])) != 0) {
1224 cp += 2; /* move past backslash and 'X' */
1226 cval = (cval * 16) + ((int) (dp - hex) / 2);
1227 } while (*++cp && (dp = index(hex, *cp)) != 0 && ++dcount < 2);
1228 } else { /* C-style character escapes */
1253 *tp++ = (char) cval;
1259 rejectoption(optname)
1260 const char *optname;
1263 pline("\"%s\" settable only from %s.", optname, configfile);
1265 pline("%s can be set only from NETHACKOPTIONS or %s.", optname,
1273 OPTIONS=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1276 MSGTYPE=stop"You swap places with "
1277 MSGTYPE=st.op "You swap places with "
1278 MSGTYPE=stop "You swap places with \"
1279 MENUCOLOR=" blessed "green&none
1280 MENUCOLOR=" holy " = green&reverse
1281 MENUCOLOR=" cursed " = red&uline
1282 MENUCOLOR=" unholy " = reed
1283 OPTIONS=!legacy:true,fooo
1290 string_for_opt(opts, val_optional)
1292 boolean val_optional;
1294 char *colon, *equals;
1296 colon = index(opts, ':');
1297 equals = index(opts, '=');
1298 if (!colon || (equals && equals < colon))
1301 if (!colon || !*++colon) {
1304 config_error_add("Missing parameter for '%s'", opts);
1306 config_error_add("'%s'
\82Ì
\88ø
\90\94\82ª
\82 \82è
\82Ü
\82¹
\82ñ", opts);
1313 string_for_env_opt(optname, opts, val_optional)
1314 const char *optname;
1316 boolean val_optional;
1319 rejectoption(optname);
1322 return string_for_opt(opts, val_optional);
1326 bad_negation(optname, with_parameter)
1327 const char *optname;
1328 boolean with_parameter;
1331 pline_The("%s option may not %sbe negated.", optname,
1332 with_parameter ? "both have a value and " : "");
1334 pline_The("%s
\83I
\83v
\83V
\83\87\83\93\82Í
\94Û
\92è%s
\82Å
\82«
\82È
\82¢
\81D", optname,
1335 with_parameter ? "
\82Æ
\92l
\8ew
\92è
\82Ì
\97¼
\95û
\82Í" : "");
1340 * Change the inventory order, using the given string as the new order.
1341 * Missing characters in the new order are filled in at the end from
1342 * the current inv_order, except for gold, which is forced to be first
1343 * if not explicitly present.
1345 * This routine returns 1 unless there is a duplicate or bad char in
1349 change_inv_order(op)
1353 char *sp, buf[QBUFSZ];
1357 if (!index(op, GOLD_SYM))
1358 buf[num++] = COIN_CLASS;
1360 for (sp = op; *sp; sp++) {
1361 boolean fail = FALSE;
1362 oc_sym = def_char_to_objclass(*sp);
1363 /* reject bad or duplicate entries */
1364 if (oc_sym == MAXOCLASSES) { /* not an object class char */
1365 config_error_add("Not an object class '%c'", *sp);
1368 } else if (!index(flags.inv_order, oc_sym)) {
1369 /* VENOM_CLASS, RANDOM_CLASS, and ILLOBJ_CLASS are excluded
1370 because they aren't in def_inv_order[] so don't make it
1371 into flags.inv_order, hence always fail this index() test */
1372 config_error_add("Object class '%c' not allowed", *sp);
1375 } else if (index(sp + 1, *sp)) {
1376 config_error_add("Duplicate object class '%c'", *sp);
1380 /* retain good ones */
1382 buf[num++] = (char) oc_sym;
1386 /* fill in any omitted classes, using previous ordering */
1387 for (sp = flags.inv_order; *sp; sp++)
1388 if (!index(buf, *sp))
1389 (void) strkitten(&buf[num++], *sp);
1390 buf[MAXOCLASSES - 1] = '\0';
1392 Strcpy(flags.inv_order, buf);
1397 warning_opts(opts, optype)
1398 register char *opts;
1401 uchar translate[WARNCOUNT];
1404 if (!(opts = string_for_env_opt(optype, opts, FALSE)))
1406 escapes(opts, opts);
1408 length = (int) strlen(opts);
1409 /* match the form obtained from PC configuration files */
1410 for (i = 0; i < WARNCOUNT; i++)
1411 translate[i] = (i >= length) ? 0
1412 : opts[i] ? (uchar) opts[i]
1413 : def_warnsyms[i].sym;
1414 assign_warnings(translate);
1419 assign_warnings(graph_chars)
1420 register uchar *graph_chars;
1424 for (i = 0; i < WARNCOUNT; i++)
1426 warnsyms[i] = graph_chars[i];
1430 feature_alert_opts(op, optn)
1435 unsigned long fnv = get_feature_notice_ver(op); /* version.c */
1439 if (fnv > get_current_feature_ver()) {
1442 You_cant("disable new feature alerts for future versions.");
1444 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");
1447 "%s=%s Invalid reference to a future version ignored",
1453 flags.suppress_alert = fnv;
1455 Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
1456 FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
1459 "Feature change alerts disabled for NetHack %s features and prior.",
1463 "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",
1471 set_duplicate_opt_detection(on_or_off)
1476 if (on_or_off != 0) {
1478 if (iflags.opt_booldup)
1479 impossible("iflags.opt_booldup already on (memory leak)");
1480 iflags.opt_booldup = (int *) alloc(SIZE(boolopt) * sizeof (int));
1481 optptr = iflags.opt_booldup;
1482 for (k = 0; k < SIZE(boolopt); ++k)
1485 if (iflags.opt_compdup)
1486 impossible("iflags.opt_compdup already on (memory leak)");
1487 iflags.opt_compdup = (int *) alloc(SIZE(compopt) * sizeof (int));
1488 optptr = iflags.opt_compdup;
1489 for (k = 0; k < SIZE(compopt); ++k)
1493 if (iflags.opt_booldup)
1494 free((genericptr_t) iflags.opt_booldup);
1495 iflags.opt_booldup = (int *) 0;
1496 if (iflags.opt_compdup)
1497 free((genericptr_t) iflags.opt_compdup);
1498 iflags.opt_compdup = (int *) 0;
1503 duplicate_opt_detection(opts, iscompound)
1505 int iscompound; /* 0 == boolean option, 1 == compound */
1509 if (!iscompound && iflags.opt_booldup && initial && from_file) {
1510 for (i = 0; boolopt[i].name; i++) {
1511 if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
1512 optptr = iflags.opt_booldup + i;
1520 } else if (iscompound && iflags.opt_compdup && initial && from_file) {
1521 for (i = 0; compopt[i].name; i++) {
1522 if (match_optname(opts, compopt[i].name, strlen(compopt[i].name),
1524 optptr = iflags.opt_compdup + i;
1537 complain_about_duplicate(opts, iscompound)
1539 int iscompound; /* 0 == boolean option, 1 == compound */
1542 /* the Mac has trouble dealing with the output of messages while
1543 * processing the config file. That should get fixed one day.
1544 * For now just return.
1548 config_error_add("%s option specified multiple times: %s",
1549 iscompound ? "compound" : "boolean", opts);
1551 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",
1552 iscompound ? "
\95¡
\8d\87" : "
\90^
\8bU
\92l", opts);
1558 /* paranoia[] - used by parseoptions() and special_handling() */
1559 STATIC_VAR const struct paranoia_opts {
1560 int flagmask; /* which paranoid option */
1561 const char *argname; /* primary name */
1562 int argMinLen; /* minimum number of letters to match */
1563 const char *synonym; /* alternate name (optional) */
1565 const char *explain; /* for interactive menu */
1567 /* there are some initial-letter conflicts: "a"ttack vs "a"ll, "attack"
1568 takes precedence and "all" isn't present in the interactive menu,
1569 and "d"ie vs "d"eath, synonyms for each other so doesn't matter;
1570 (also "p"ray vs "P"aranoia, "pray" takes precedence since "Paranoia"
1571 is just a synonym for "Confirm"); "b"ones vs "br"eak-wand, the
1572 latter requires at least two letters; "wand"-break vs "Were"-change,
1573 both require at least two letters during config processing and use
1574 case-senstivity for 'O's interactive menu */
1575 { PARANOID_CONFIRM, "Confirm", 1, "Paranoia", 2,
1577 "for \"yes\" confirmations, require \"no\" to reject" },
1579 "\"yes\"
\82ð
\8am
\94F
\82·
\82é
\82Æ
\82«
\82É
\81C
\8b\91\94Û
\82·
\82é
\82Æ
\82«
\82É
\82Í\"no\"
\82ª
\95K
\97v" },
1580 { PARANOID_QUIT, "quit", 1, "explore", 1,
1582 "yes vs y to quit or to enter explore mode" },
1584 "
\8fI
\97¹
\82Ü
\82½
\82Í
\92T
\8c\9f\83\82\81[
\83h
\82É
\93ü
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1585 { PARANOID_DIE, "die", 1, "death", 2,
1587 "yes vs y to die (explore mode or debug mode)" },
1589 "(
\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" },
1590 { PARANOID_BONES, "bones", 1, 0, 0,
1592 "yes vs y to save bones data when dying in debug mode" },
1594 "
\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" },
1595 { PARANOID_HIT, "attack", 1, "hit", 1,
1597 "yes vs y to attack a peaceful monster" },
1599 "
\97F
\8dD
\93I
\89ö
\95¨
\82ð
\8dU
\8c\82\82·
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1600 { PARANOID_BREAKWAND, "wand-break", 2, "break-wand", 2,
1602 "yes vs y to break a wand via (a)pply" },
1604 "(a)pply
\82Å
\8fñ
\82ð
\90Ü
\82é
\82Æ
\82«
\82Éy
\82Å
\82Í
\82È
\82yes" },
1605 { PARANOID_WERECHANGE, "Were-change", 2, (const char *) 0, 0,
1607 "yes vs y to change form when lycanthropy is controllable" },
1609 "
\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" },
1610 { PARANOID_PRAY, "pray", 1, 0, 0,
1612 "y to pray (supersedes old \"prayconfirm\" option)" },
1614 "
\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é)" },
1615 { PARANOID_REMOVE, "Remove", 1, "Takeoff", 1,
1617 "always pick from inventory for Remove and Takeoff" },
1619 "Remove
\82ÆTakeoff
\82Å
\8fí
\82É
\8e\9d\82¿
\95¨
\88ê
\97\97\82©
\82ç
\91I
\82Ô" },
1620 /* for config file parsing; interactive menu skips these */
1621 { 0, "none", 4, 0, 0, 0 }, /* require full word match */
1622 { ~0, "all", 3, 0, 0, 0 }, /* ditto */
1625 extern struct menucoloring *menu_colorings;
1627 static const struct {
1631 { "black", CLR_BLACK },
1633 { "green", CLR_GREEN },
1634 { "brown", CLR_BROWN },
1635 { "blue", CLR_BLUE },
1636 { "magenta", CLR_MAGENTA },
1637 { "cyan", CLR_CYAN },
1638 { "gray", CLR_GRAY },
1639 { "orange", CLR_ORANGE },
1640 { "light green", CLR_BRIGHT_GREEN },
1641 { "yellow", CLR_YELLOW },
1642 { "light blue", CLR_BRIGHT_BLUE },
1643 { "light magenta", CLR_BRIGHT_MAGENTA },
1644 { "light cyan", CLR_BRIGHT_CYAN },
1645 { "white", CLR_WHITE },
1646 { "no color", NO_COLOR },
1647 { NULL, CLR_BLACK }, /* everything after this is an alias */
1648 { "transparent", NO_COLOR },
1649 { "purple", CLR_MAGENTA },
1650 { "light purple", CLR_BRIGHT_MAGENTA },
1651 { "bright purple", CLR_BRIGHT_MAGENTA },
1652 { "grey", CLR_GRAY },
1653 { "bright red", CLR_ORANGE },
1654 { "bright green", CLR_BRIGHT_GREEN },
1655 { "bright blue", CLR_BRIGHT_BLUE },
1656 { "bright magenta", CLR_BRIGHT_MAGENTA },
1657 { "bright cyan", CLR_BRIGHT_CYAN }
1660 static const struct {
1664 { "none", ATR_NONE },
1665 { "bold", ATR_BOLD },
1667 { "underline", ATR_ULINE },
1668 { "blink", ATR_BLINK },
1669 { "inverse", ATR_INVERSE },
1670 { NULL, ATR_NONE }, /* everything after this is an alias */
1671 { "normal", ATR_NONE },
1672 { "uline", ATR_ULINE }
1681 for (i = 0; i < SIZE(colornames); i++)
1682 if (colornames[i].name && colornames[i].color == clr)
1683 return colornames[i].name;
1693 /* allow "lightblue", "light blue", and "light-blue" to match "light blue"
1694 (also junk like "_l i-gh_t---b l u e" but we won't worry about that);
1695 also copes with trailing space; mungspaces removed any leading space */
1696 for (i = 0; i < SIZE(colornames); i++)
1697 if (colornames[i].name
1698 && fuzzymatch(str, colornames[i].name, " -_", TRUE)) {
1699 c = colornames[i].color;
1702 if (i == SIZE(colornames) && (*str >= '0' && *str <= '9'))
1706 config_error_add("Unknown color '%s'", str);
1711 STATIC_OVL const char *
1717 for (i = 0; i < SIZE(attrnames); i++)
1718 if (attrnames[i].attr == attr)
1719 return attrnames[i].name;
1724 match_str2attr(str, complain)
1730 for (i = 0; i < SIZE(attrnames); i++)
1731 if (attrnames[i].name
1732 && fuzzymatch(str, attrnames[i].name, " -_", TRUE)) {
1733 a = attrnames[i].attr;
1737 if (a == -1 && complain)
1738 config_error_add("Unknown text attribute '%s'", str);
1750 menu_item *picks = (menu_item *) 0;
1752 tmpwin = create_nhwindow(NHW_MENU);
1755 for (i = 0; i < SIZE(colornames); i++) {
1756 if (!colornames[i].name)
1759 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, colornames[i].name,
1762 end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick a color");
1763 pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
1764 destroy_nhwindow(tmpwin);
1766 i = colornames[picks->item.a_int - 1].color;
1767 free((genericptr_t) picks);
1780 menu_item *picks = (menu_item *) 0;
1782 tmpwin = create_nhwindow(NHW_MENU);
1785 for (i = 0; i < SIZE(attrnames); i++) {
1786 if (!attrnames[i].name)
1789 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, attrnames[i].attr,
1790 attrnames[i].name, MENU_UNSELECTED);
1792 end_menu(tmpwin, (prompt && *prompt) ? prompt : "Pick an attribute");
1793 pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
1794 destroy_nhwindow(tmpwin);
1796 i = attrnames[picks->item.a_int - 1].attr;
1797 free((genericptr_t) picks);
1803 static const struct {
1807 } msgtype_names[] = {
1809 { "show", MSGTYP_NORMAL, "Show message normally" },
1811 { "show", MSGTYP_NORMAL, "
\92Ê
\8fí
\92Ê
\82è
\83\81\83b
\83Z
\81[
\83W
\82ð
\95\
\8e¦
\82·
\82é" },
1813 { "hide", MSGTYP_NOSHOW, "Hide message" },
1815 { "hide", MSGTYP_NOSHOW, "
\83\81\83b
\83Z
\81[
\83W
\82ð
\95\
\8e¦
\82µ
\82È
\82¢" },
1816 { "noshow", MSGTYP_NOSHOW, NULL },
1818 { "stop", MSGTYP_STOP, "Prompt for more after the message" },
1820 { "stop", MSGTYP_STOP, "more
\83v
\83\8d\83\93\83v
\83g
\82Å
\91Ò
\82Â" },
1821 { "more", MSGTYP_STOP, NULL },
1823 { "norep", MSGTYP_NOREP, "Do not repeat the message" }
1825 { "norep", MSGTYP_NOREP, "
\82±
\82Ì
\83\81\83b
\83Z
\81[
\83W
\82Í
\8cJ
\82è
\95Ô
\82³
\82È
\82¢" }
1828 STATIC_OVL const char *
1834 for (i = 0; i < SIZE(msgtype_names); i++)
1835 if (msgtype_names[i].descr && msgtype_names[i].msgtyp == typ)
1836 return msgtype_names[i].name;
1846 menu_item *picks = (menu_item *) 0;
1848 tmpwin = create_nhwindow(NHW_MENU);
1851 for (i = 0; i < SIZE(msgtype_names); i++)
1852 if (msgtype_names[i].descr) {
1853 any.a_int = msgtype_names[i].msgtyp + 1;
1854 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
1855 msgtype_names[i].descr, MENU_UNSELECTED);
1858 end_menu(tmpwin, "How to show the message");
1860 end_menu(tmpwin, "
\83\81\83b
\83Z
\81[
\83W
\82Ì
\95\
\8e¦
\95û
\96@");
1861 pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
1862 destroy_nhwindow(tmpwin);
1864 i = picks->item.a_int - 1;
1865 free((genericptr_t) picks);
1872 msgtype_add(typ, pattern)
1876 struct plinemsg_type
1877 *tmp = (struct plinemsg_type *) alloc(sizeof (struct plinemsg_type));
1880 tmp->regex = regex_init();
1881 if (!regex_compile(pattern, tmp->regex)) {
1882 static const char *re_error = "MSGTYPE regex error";
1884 config_error_add("%s: %s", re_error, regex_error_desc(tmp->regex));
1885 regex_free(tmp->regex);
1886 free((genericptr_t) tmp);
1889 tmp->pattern = dupstr(pattern);
1890 tmp->next = plinemsg_types;
1891 plinemsg_types = tmp;
1898 struct plinemsg_type *tmp, *tmp2 = 0;
1900 for (tmp = plinemsg_types; tmp; tmp = tmp2) {
1902 free((genericptr_t) tmp->pattern);
1903 regex_free(tmp->regex);
1904 free((genericptr_t) tmp);
1906 plinemsg_types = (struct plinemsg_type *) 0;
1910 free_one_msgtype(idx)
1913 struct plinemsg_type *tmp = plinemsg_types;
1914 struct plinemsg_type *prev = NULL;
1918 struct plinemsg_type *next = tmp->next;
1920 regex_free(tmp->regex);
1921 free((genericptr_t) tmp->pattern);
1922 free((genericptr_t) tmp);
1926 plinemsg_types = next;
1936 msgtype_type(msg, norepeat)
1938 boolean norepeat; /* called from Norep(via pline) */
1940 struct plinemsg_type *tmp = plinemsg_types;
1943 /* we don't exclude entries with negative msgtype values
1944 because then the msg might end up matching a later pattern */
1945 if (regex_match(msg, tmp->regex))
1946 return tmp->msgtype;
1949 return norepeat ? MSGTYP_NOREP : MSGTYP_NORMAL;
1952 /* negate one or more types of messages so that their type handling will
1953 be disabled or re-enabled; MSGTYPE_NORMAL (value 0) is not affected */
1955 hide_unhide_msgtypes(hide, hide_mask)
1959 struct plinemsg_type *tmp;
1962 /* negative msgtype value won't be recognized by pline, so does nothing */
1963 for (tmp = plinemsg_types; tmp; tmp = tmp->next) {
1966 mt = -mt; /* unhide: negate negative, yielding positive */
1967 if (mt > 0 && ((1 << mt) & hide_mask))
1968 tmp->msgtype = -tmp->msgtype;
1973 msgtype_count(VOID_ARGS)
1976 struct plinemsg_type *tmp = plinemsg_types;
1986 msgtype_parse_add(str)
1992 if (sscanf(str, "%10s \"%255[^\"]\"", msgtype, pattern) == 2) {
1996 for (i = 0; i < SIZE(msgtype_names); i++)
1997 if (!strncmpi(msgtype_names[i].name, msgtype, strlen(msgtype))) {
1998 typ = msgtype_names[i].msgtyp;
2002 return msgtype_add(typ, pattern);
2004 config_error_add("Unknown message type '%s'", msgtype);
2006 config_error_add("Malformed MSGTYPE");
2012 test_regex_pattern(str, errmsg)
2016 static const char re_error[] = "Regex error";
2017 struct nhregex *match;
2018 boolean retval = TRUE;
2023 match = regex_init();
2025 config_error_add("NHregex error");
2029 if (!regex_compile(str, match)) {
2030 config_error_add("%s: %s", errmsg ? errmsg : re_error,
2031 regex_error_desc(match));
2039 add_menu_coloring_parsed(str, c, a)
2043 static const char re_error[] = "Menucolor regex error";
2044 struct menucoloring *tmp;
2048 tmp = (struct menucoloring *) alloc(sizeof (struct menucoloring));
2049 tmp->match = regex_init();
2050 if (!regex_compile(str, tmp->match)) {
2051 config_error_add("%s: %s", re_error, regex_error_desc(tmp->match));
2052 regex_free(tmp->match);
2056 tmp->next = menu_colorings;
2057 tmp->origstr = dupstr(str);
2060 menu_colorings = tmp;
2065 /* parse '"regex_string"=color&attr' and add it to menucoloring */
2067 add_menu_coloring(tmpstr)
2070 int c = NO_COLOR, a = ATR_NONE;
2071 char *tmps, *cs, *amp;
2074 Sprintf(str, "%s", tmpstr);
2076 if (!tmpstr || (cs = index(str, '=')) == 0) {
2077 config_error_add("Malformed MENUCOLOR");
2081 tmps = cs + 1; /* advance past '=' */
2083 if ((amp = index(tmps, '&')) != 0)
2086 c = match_str2clr(tmps);
2091 tmps = amp + 1; /* advance past '&' */
2092 a = match_str2attr(tmps, TRUE);
2097 /* the regexp portion here has not been condensed by mungspaces() */
2100 if (*tmps == '"' || *tmps == '\'') {
2102 while (isspace((uchar) *cs))
2110 return add_menu_coloring_parsed(tmps, c, a);
2114 get_menu_coloring(str, color, attr)
2118 struct menucoloring *tmpmc;
2120 if (iflags.use_menu_color)
2121 for (tmpmc = menu_colorings; tmpmc; tmpmc = tmpmc->next)
2122 if (regex_match(str, tmpmc->match)) {
2123 *color = tmpmc->color;
2124 *attr = tmpmc->attr;
2131 free_menu_coloring()
2133 struct menucoloring *tmp = menu_colorings;
2136 struct menucoloring *tmp2 = tmp->next;
2138 regex_free(tmp->match);
2139 free((genericptr_t) tmp->origstr);
2140 free((genericptr_t) tmp);
2146 free_one_menu_coloring(idx)
2149 struct menucoloring *tmp = menu_colorings;
2150 struct menucoloring *prev = NULL;
2154 struct menucoloring *next = tmp->next;
2156 regex_free(tmp->match);
2157 free((genericptr_t) tmp->origstr);
2158 free((genericptr_t) tmp);
2162 menu_colorings = next;
2172 count_menucolors(VOID_ARGS)
2175 struct menucoloring *tmp = menu_colorings;
2185 parse_role_opts(negated, fullname, opts, opp)
2187 const char *fullname;
2194 bad_negation(fullname, FALSE);
2195 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2196 boolean val_negated = FALSE;
2198 while ((*op == '!') || !strncmpi(op, "no", 2)) {
2203 val_negated = !val_negated;
2206 if (!setrolefilter(op)) {
2207 config_error_add("Unknown negated parameter '%s'", op);
2211 if (duplicate_opt_detection(opts, 1))
2212 complain_about_duplicate(opts, 1);
2220 /* Check if character c is illegal as a menu command key */
2222 illegal_menu_cmd_key(c)
2225 if (c == 0 || c == '\r' || c == '\n' || c == '\033'
2226 || c == ' ' || digit(c) || (letter(c) && c != '@')) {
2227 config_error_add("Reserved menu command key '%s'", visctrl(c));
2229 } else { /* reject default object class symbols */
2231 for (j = 1; j < MAXOCLASSES; j++)
2232 if (c == def_oc_syms[j].sym) {
2233 config_error_add("Menu command key '%s' is an object class",
2242 parseoptions(opts, tinitial, tfrom_file)
2243 register char *opts;
2244 boolean tinitial, tfrom_file;
2248 boolean negated, duplicate;
2250 const char *fullname;
2251 boolean retval = TRUE;
2254 from_file = tfrom_file;
2255 if ((op = index(opts, ',')) != 0) {
2257 if (!parseoptions(op, initial, from_file))
2260 if (strlen(opts) > BUFSZ / 2) {
2261 config_error_add("Option too long, max length is %i characters",
2266 /* strip leading and trailing white space */
2267 while (isspace((uchar) *opts))
2270 while (--op >= opts && isspace((uchar) *op))
2274 config_error_add("Empty statement");
2278 while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
2286 /* variant spelling */
2288 if (match_optname(opts, "colour", 5, FALSE))
2289 Strcpy(opts, "color"); /* fortunately this isn't longer */
2291 /* special boolean options */
2293 if (match_optname(opts, "female", 3, FALSE)) {
2294 if (duplicate_opt_detection(opts, 0))
2295 complain_about_duplicate(opts, 0);
2296 if (!initial && flags.female == negated) {
2297 config_error_add("That is not anatomically possible.");
2300 flags.initgend = flags.female = !negated;
2304 if (match_optname(opts, "male", 4, FALSE)) {
2305 if (duplicate_opt_detection(opts, 0))
2306 complain_about_duplicate(opts, 0);
2307 if (!initial && flags.female != negated) {
2308 config_error_add("That is not anatomically possible.");
2311 flags.initgend = flags.female = negated;
2315 #if defined(MICRO) && !defined(AMIGA)
2316 /* included for compatibility with old NetHack.cnf files */
2317 if (match_optname(opts, "IBM_", 4, FALSE)) {
2318 iflags.BIOS = !negated;
2323 /* compound options */
2325 /* This first batch can be duplicated if their values are negated */
2329 if (match_optname(opts, fullname, sizeof("align") - 1, TRUE)) {
2330 if (parse_role_opts(negated, fullname, opts, &op)) {
2331 if ((flags.initalign = str2align(op)) == ROLE_NONE) {
2332 config_error_add("Unknown %s '%s'", fullname, op);
2340 /* role:string or character:string */
2342 if (match_optname(opts, fullname, 4, TRUE)
2343 || match_optname(opts, (fullname = "character"), 4, TRUE)) {
2344 if (parse_role_opts(negated, fullname, opts, &op)) {
2345 if ((flags.initrole = str2role(op)) == ROLE_NONE) {
2346 config_error_add("Unknown %s '%s'", fullname, op);
2348 } else /* Backwards compatibility */
2349 nmcpy(pl_character, op, PL_NSIZ);
2357 if (match_optname(opts, fullname, 4, TRUE)) {
2358 if (parse_role_opts(negated, fullname, opts, &op)) {
2359 if ((flags.initrace = str2race(op)) == ROLE_NONE) {
2360 config_error_add("Unknown %s '%s'", fullname, op);
2362 } else /* Backwards compatibility */
2370 fullname = "gender";
2371 if (match_optname(opts, fullname, 4, TRUE)) {
2372 if (parse_role_opts(negated, fullname, opts, &op)) {
2373 if ((flags.initgend = str2gend(op)) == ROLE_NONE) {
2374 config_error_add("Unknown %s '%s'", fullname, op);
2377 flags.female = flags.initgend;
2383 /* We always check for duplicates on the remaining compound options,
2384 although individual option processing can choose to complain or not */
2386 duplicate = duplicate_opt_detection(opts, 1); /* 1: check compounds */
2388 fullname = "pettype";
2389 if (match_optname(opts, fullname, 3, TRUE)) {
2391 complain_about_duplicate(opts, 1);
2392 if ((op = string_for_env_opt(fullname, opts, negated)) != 0) {
2394 bad_negation(fullname, TRUE);
2397 switch (lowc(*op)) {
2399 preferred_pet = 'd';
2402 case 'f': /* feline */
2403 preferred_pet = 'c';
2405 case 'h': /* horse */
2406 case 'q': /* quadruped */
2407 /* avoids giving "unrecognized type of pet" but
2408 pet_type(dog.c) won't actually honor this */
2409 preferred_pet = 'h';
2411 case 'n': /* no pet */
2412 preferred_pet = 'n';
2414 case '*': /* random */
2415 preferred_pet = '\0';
2419 config_error_add("Unrecognized pet type '%s'.", op);
2421 pline("'%s'
\82Í
\83y
\83b
\83g
\82Ì
\8eí
\97Þ
\82Æ
\82µ
\82Ä
\8eó
\82¯
\95t
\82¯
\82ç
\82ê
\82Ü
\82¹
\82ñ
\81D", op);
2426 preferred_pet = 'n';
2430 fullname = "catname";
2431 if (match_optname(opts, fullname, 3, TRUE)) {
2433 complain_about_duplicate(opts, 1);
2435 bad_negation(fullname, FALSE);
2437 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2438 nmcpy(catname, op, PL_PSIZ);
2441 sanitize_name(catname);
2445 fullname = "dogname";
2446 if (match_optname(opts, fullname, 3, TRUE)) {
2448 complain_about_duplicate(opts, 1);
2450 bad_negation(fullname, FALSE);
2452 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2453 nmcpy(dogname, op, PL_PSIZ);
2456 sanitize_name(dogname);
2460 fullname = "horsename";
2461 if (match_optname(opts, fullname, 5, TRUE)) {
2463 complain_about_duplicate(opts, 1);
2465 bad_negation(fullname, FALSE);
2467 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2468 nmcpy(horsename, op, PL_PSIZ);
2471 sanitize_name(horsename);
2475 fullname = "number_pad";
2476 if (match_optname(opts, fullname, 10, TRUE)) {
2477 boolean compat = (strlen(opts) <= 10);
2480 complain_about_duplicate(opts, 1);
2481 op = string_for_opt(opts, (compat || !initial));
2483 if (compat || negated || initial) {
2484 /* for backwards compatibility, "number_pad" without a
2485 value is a synonym for number_pad:1 */
2486 iflags.num_pad = !negated;
2487 iflags.num_pad_mode = 0;
2489 } else if (negated) {
2490 bad_negation(fullname, TRUE);
2493 int mode = atoi(op);
2495 if (mode < -1 || mode > 4 || (mode == 0 && *op != '0')) {
2496 config_error_add("Illegal %s parameter '%s'", fullname, op);
2498 } else if (mode <= 0) {
2499 iflags.num_pad = FALSE;
2500 /* German keyboard; y and z keys swapped */
2501 iflags.num_pad_mode = (mode < 0); /* 0 or 1 */
2502 } else { /* mode > 0 */
2503 iflags.num_pad = TRUE;
2504 iflags.num_pad_mode = 0;
2505 /* PC Hack / MSDOS compatibility */
2506 if (mode == 2 || mode == 4)
2507 iflags.num_pad_mode |= 1;
2508 /* phone keypad layout */
2509 if (mode == 3 || mode == 4)
2510 iflags.num_pad_mode |= 2;
2513 reset_commands(FALSE);
2514 number_pad(iflags.num_pad ? 1 : 0);
2518 fullname = "roguesymset";
2519 if (match_optname(opts, fullname, 7, TRUE)) {
2521 complain_about_duplicate(opts, 1);
2523 bad_negation(fullname, FALSE);
2525 } else if ((op = string_for_opt(opts, FALSE)) != 0) {
2526 symset[ROGUESET].name = dupstr(op);
2527 if (!read_sym_file(ROGUESET)) {
2528 clear_symsetentry(ROGUESET, TRUE);
2529 config_error_add("Unable to load symbol set \"%s\" from \"%s\"",
2533 if (!initial && Is_rogue_level(&u.uz))
2534 assign_graphics(ROGUESET);
2542 fullname = "symset";
2543 if (match_optname(opts, fullname, 6, TRUE)) {
2545 complain_about_duplicate(opts, 1);
2547 bad_negation(fullname, FALSE);
2549 } else if ((op = string_for_opt(opts, FALSE)) != 0) {
2550 symset[PRIMARY].name = dupstr(op);
2551 if (!read_sym_file(PRIMARY)) {
2552 clear_symsetentry(PRIMARY, TRUE);
2554 "Unable to load symbol set \"%s\" from \"%s\"",
2558 switch_symbols(symset[PRIMARY].name != (char *) 0);
2566 fullname = "runmode";
2567 if (match_optname(opts, fullname, 4, TRUE)) {
2569 complain_about_duplicate(opts, 1);
2571 flags.runmode = RUN_TPORT;
2572 } else if ((op = string_for_opt(opts, FALSE)) != 0) {
2573 if (!strncmpi(op, "teleport", strlen(op)))
2574 flags.runmode = RUN_TPORT;
2575 else if (!strncmpi(op, "run", strlen(op)))
2576 flags.runmode = RUN_LEAP;
2577 else if (!strncmpi(op, "walk", strlen(op)))
2578 flags.runmode = RUN_STEP;
2579 else if (!strncmpi(op, "crawl", strlen(op)))
2580 flags.runmode = RUN_CRAWL;
2582 config_error_add("Unknown %s parameter '%s'", fullname, op);
2590 /* menucolor:"regex_string"=color */
2591 fullname = "menucolor";
2592 if (match_optname(opts, fullname, 9, TRUE)) {
2594 bad_negation(fullname, FALSE);
2596 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2597 if (!add_menu_coloring(op))
2604 fullname = "msghistory";
2605 if (match_optname(opts, fullname, 3, TRUE)) {
2607 complain_about_duplicate(opts, 1);
2608 op = string_for_env_opt(fullname, opts, negated);
2609 if ((negated && !op) || (!negated && op)) {
2610 iflags.msg_history = negated ? 0 : atoi(op);
2611 } else if (negated) {
2612 bad_negation(fullname, TRUE);
2618 fullname = "msg_window";
2619 /* msg_window:single, combo, full or reversed */
2620 if (match_optname(opts, fullname, 4, TRUE)) {
2621 /* allow option to be silently ignored by non-tty ports */
2626 complain_about_duplicate(opts, 1);
2627 if (!(op = string_for_opt(opts, TRUE))) {
2628 tmp = negated ? 's' : 'f';
2631 bad_negation(fullname, TRUE);
2637 case 's': /* single message history cycle (default if negated) */
2638 iflags.prevmsg_window = 's';
2640 case 'c': /* combination: two singles, then full page reversed */
2641 iflags.prevmsg_window = 'c';
2643 case 'f': /* full page (default if no opts) */
2644 iflags.prevmsg_window = 'f';
2646 case 'r': /* full page (reversed) */
2647 iflags.prevmsg_window = 'r';
2650 config_error_add("Unknown %s parameter '%s'", fullname, op);
2659 * setting font options */
2661 if (!strncmpi(opts, fullname, 4)) {
2663 char *fontopts = opts + 4;
2665 if (!strncmpi(fontopts, "map", 3) || !strncmpi(fontopts, "_map", 4))
2666 opttype = MAP_OPTION;
2667 else if (!strncmpi(fontopts, "message", 7)
2668 || !strncmpi(fontopts, "_message", 8))
2669 opttype = MESSAGE_OPTION;
2670 else if (!strncmpi(fontopts, "text", 4)
2671 || !strncmpi(fontopts, "_text", 5))
2672 opttype = TEXT_OPTION;
2673 else if (!strncmpi(fontopts, "menu", 4)
2674 || !strncmpi(fontopts, "_menu", 5))
2675 opttype = MENU_OPTION;
2676 else if (!strncmpi(fontopts, "status", 6)
2677 || !strncmpi(fontopts, "_status", 7))
2678 opttype = STATUS_OPTION;
2679 else if (!strncmpi(fontopts, "_size", 5)) {
2680 if (!strncmpi(fontopts, "_size_map", 8))
2681 opttype = MAP_OPTION;
2682 else if (!strncmpi(fontopts, "_size_message", 12))
2683 opttype = MESSAGE_OPTION;
2684 else if (!strncmpi(fontopts, "_size_text", 9))
2685 opttype = TEXT_OPTION;
2686 else if (!strncmpi(fontopts, "_size_menu", 9))
2687 opttype = MENU_OPTION;
2688 else if (!strncmpi(fontopts, "_size_status", 11))
2689 opttype = STATUS_OPTION;
2691 config_error_add("Unknown %s parameter '%s'", fullname, opts);
2695 complain_about_duplicate(opts, 1);
2696 if (opttype > 0 && !negated
2697 && (op = string_for_opt(opts, FALSE)) != 0) {
2700 iflags.wc_fontsiz_map = atoi(op);
2702 case MESSAGE_OPTION:
2703 iflags.wc_fontsiz_message = atoi(op);
2706 iflags.wc_fontsiz_text = atoi(op);
2709 iflags.wc_fontsiz_menu = atoi(op);
2712 iflags.wc_fontsiz_status = atoi(op);
2718 config_error_add("Unknown %s parameter '%s'", fullname, opts);
2721 if (opttype > 0 && (op = string_for_opt(opts, FALSE)) != 0) {
2722 wc_set_font_name(opttype, op);
2724 set_font_name(opttype, op);
2727 } else if (negated) {
2728 bad_negation(fullname, TRUE);
2735 if (match_optname(opts, "palette", 3, TRUE)
2737 || match_optname(opts, "hicolor", 3, TRUE)
2740 int color_number, color_incr;
2744 complain_about_duplicate(opts, 1);
2747 if (match_optname(opts, "hicolor", 3, TRUE)) {
2749 bad_negation("hicolor", FALSE);
2752 color_number = CLR_MAX + 4; /* HARDCODED inverse number */
2758 bad_negation("palette", FALSE);
2765 op = string_for_opt(opts, TRUE);
2766 if (!alternative_palette(op)) {
2767 config_error_add("Error in palette parameter '%s'", op);
2771 if ((op = string_for_opt(opts, FALSE)) != (char *) 0) {
2773 int cnt, tmp, reverse;
2776 while (*pt && color_number >= 0) {
2786 if (*pt && *pt != '/') {
2793 if (isalpha((uchar) tmp)) {
2794 tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */
2796 tmp &= 0xf; /* Digits in ASCII too... */
2799 /* Add an extra so we fill f -> ff and 0 -> 00 */
2807 change_color(color_number, rgb, reverse);
2808 color_number += color_incr;
2817 #endif /* CHANGE_COLOR */
2819 if (match_optname(opts, "fruit", 2, TRUE)) {
2820 struct fruit *forig = 0;
2821 char empty_str = '\0';
2824 complain_about_duplicate(opts, 1);
2825 op = string_for_opt(opts, negated);
2828 bad_negation("fruit", TRUE);
2840 /* count number of named fruits; if 'op' is found among them,
2841 then the count doesn't matter because we won't be adding it */
2842 f = fruit_from_name(op, FALSE, &fnum);
2844 if (!flags.made_fruit)
2845 forig = fruit_from_name(pl_fruit, FALSE, (int *) 0);
2847 if (!forig && fnum >= 100) {
2850 "Doing that so many times isn't very fruitful.");
2853 "
\82»
\82ñ
\82È
\82É
\89½
\89ñ
\82à
\82â
\82Á
\82Ä
\82à
\82Ù
\82Æ
\82ñ
\82Ç
\88Ó
\96¡
\82Í
\82È
\82¢
\81D");
2860 nmcpy(pl_fruit, op, PL_FSIZ);
2861 sanitize_name(pl_fruit);
2862 /* OBJ_NAME(objects[SLIME_MOLD]) won't work for this after
2863 initialization; it gets changed to generic "fruit" */
2865 nmcpy(pl_fruit, "slime mold", PL_FSIZ);
2867 /* if 'forig' is nonNull, we replace it rather than add
2868 a new fruit; it can only be nonNull if no fruits have
2869 been created since the previous name was put in place */
2870 (void) fruitadd(pl_fruit, forig);
2871 pline("Fruit is now \"%s\".", pl_fruit);
2873 /* If initial, then initoptions is allowed to do it instead
2874 * of here (initoptions always has to do it even if there's
2875 * no fruit option at all. Also, we don't want people
2876 * setting multiple fruits in their options.)
2881 fullname = "whatis_coord";
2882 if (match_optname(opts, fullname, 8, TRUE)) {
2884 complain_about_duplicate(opts, 1);
2886 iflags.getpos_coords = GPCOORDS_NONE;
2888 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2889 static char gpcoords[] = { GPCOORDS_NONE, GPCOORDS_COMPASS,
2890 GPCOORDS_COMFULL, GPCOORDS_MAP,
2891 GPCOORDS_SCREEN, '\0' };
2894 if (c && index(gpcoords, c))
2895 iflags.getpos_coords = c;
2897 config_error_add("Unknown %s parameter '%s'", fullname, op);
2905 fullname = "whatis_filter";
2906 if (match_optname(opts, fullname, 8, TRUE)) {
2908 complain_about_duplicate(opts, 1);
2910 iflags.getloc_filter = GFILTER_NONE;
2912 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2917 iflags.getloc_filter = GFILTER_NONE;
2920 iflags.getloc_filter = GFILTER_VIEW;
2923 iflags.getloc_filter = GFILTER_AREA;
2926 config_error_add("Unknown %s parameter '%s'", fullname, op);
2935 fullname = "warnings";
2936 if (match_optname(opts, fullname, 5, TRUE)) {
2938 complain_about_duplicate(opts, 1);
2940 bad_negation(fullname, FALSE);
2943 return warning_opts(opts, fullname);
2946 /* boulder:symbol */
2947 fullname = "boulder";
2948 if (match_optname(opts, fullname, 7, TRUE)) {
2949 #ifdef BACKWARD_COMPAT
2953 complain_about_duplicate(opts, 1);
2955 bad_negation(fullname, FALSE);
2958 /* if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
2960 if (!(opts = string_for_opt(opts, FALSE)))
2962 escapes(opts, opts);
2963 if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
2965 else if (opts[0] >= '1' && opts[0] <= '5')
2968 /* symbol chosen matches a used monster or warning
2969 symbol which is not good - reject it*/
2971 "Badoption - boulder symbol '%c' conflicts with a %s symbol.",
2972 opts[0], (clash == 1) ? "monster" : "warning");
2975 * Override the default boulder symbol.
2977 iflags.bouldersym = (uchar) opts[0];
2979 /* for 'initial', update_bouldersym() is done in initoptions_finish(),
2980 after all symset options have been processed */
2982 update_bouldersym();
2987 config_error_add("'%s' no longer supported; use S_boulder:c instead",
2995 if (match_optname(opts, fullname, 4, TRUE)) {
2997 complain_about_duplicate(opts, 1);
2999 bad_negation(fullname, FALSE);
3001 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
3002 nmcpy(plname, op, PL_NSIZ);
3008 /* altkeyhandler:string */
3009 fullname = "altkeyhandler";
3010 if (match_optname(opts, fullname, 4, TRUE)) {
3012 complain_about_duplicate(opts, 1);
3014 bad_negation(fullname, FALSE);
3016 } else if ((op = string_for_opt(opts, negated)) != 0) {
3018 (void) strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5);
3019 load_keyboard_handler();
3027 * align_status:[left|top|right|bottom] */
3028 fullname = "align_status";
3029 if (match_optname(opts, fullname, sizeof("align_status") - 1, TRUE)) {
3030 op = string_for_opt(opts, negated);
3031 if (op && !negated) {
3032 if (!strncmpi(op, "left", sizeof("left") - 1))
3033 iflags.wc_align_status = ALIGN_LEFT;
3034 else if (!strncmpi(op, "top", sizeof("top") - 1))
3035 iflags.wc_align_status = ALIGN_TOP;
3036 else if (!strncmpi(op, "right", sizeof("right") - 1))
3037 iflags.wc_align_status = ALIGN_RIGHT;
3038 else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
3039 iflags.wc_align_status = ALIGN_BOTTOM;
3041 config_error_add("Unknown %s parameter '%s'", fullname, op);
3044 } else if (negated) {
3045 bad_negation(fullname, TRUE);
3052 * align_message:[left|top|right|bottom] */
3053 fullname = "align_message";
3054 if (match_optname(opts, fullname, sizeof("align_message") - 1, TRUE)) {
3056 complain_about_duplicate(opts, 1);
3057 op = string_for_opt(opts, negated);
3058 if (op && !negated) {
3059 if (!strncmpi(op, "left", sizeof("left") - 1))
3060 iflags.wc_align_message = ALIGN_LEFT;
3061 else if (!strncmpi(op, "top", sizeof("top") - 1))
3062 iflags.wc_align_message = ALIGN_TOP;
3063 else if (!strncmpi(op, "right", sizeof("right") - 1))
3064 iflags.wc_align_message = ALIGN_RIGHT;
3065 else if (!strncmpi(op, "bottom", sizeof("bottom") - 1))
3066 iflags.wc_align_message = ALIGN_BOTTOM;
3068 config_error_add("Unknown %s parameter '%s'", fullname, op);
3071 } else if (negated) {
3072 bad_negation(fullname, TRUE);
3078 /* the order to list inventory */
3079 fullname = "packorder";
3080 if (match_optname(opts, fullname, 4, TRUE)) {
3082 complain_about_duplicate(opts, 1);
3084 bad_negation(fullname, FALSE);
3086 } else if (!(op = string_for_opt(opts, FALSE)))
3089 if (!change_inv_order(op))
3094 /* user can change required response for some prompts (quit, die, hit),
3095 or add an extra prompt (pray, Remove) that isn't ordinarily there */
3096 fullname = "paranoid_confirmation";
3097 if (match_optname(opts, fullname, 8, TRUE)) {
3098 /* at present we don't complain about duplicates for this
3099 option, but we do throw away the old settings whenever
3100 we process a new one [clearing old flags is essential
3101 for handling default paranoid_confirm:pray sanely] */
3102 flags.paranoia_bits = 0; /* clear all */
3104 flags.paranoia_bits = 0; /* [now redundant...] */
3105 } else if ((op = string_for_opt(opts, TRUE)) != 0) {
3106 char *pp, buf[BUFSZ];
3108 strncpy(buf, op, sizeof buf - 1);
3109 buf[sizeof buf - 1] = '\0';
3110 op = mungspaces(buf);
3112 /* We're looking to parse
3113 "paranoid_confirm:whichone wheretwo whothree"
3114 and "paranoid_confirm:" prefix has already
3115 been stripped off by the time we get here */
3116 pp = index(op, ' ');
3119 /* we aren't matching option names but match_optname
3120 does what we want once we've broken the space
3121 delimited aggregate into separate tokens */
3122 for (i = 0; i < SIZE(paranoia); ++i) {
3123 if (match_optname(op, paranoia[i].argname,
3124 paranoia[i].argMinLen, FALSE)
3125 || (paranoia[i].synonym
3126 && match_optname(op, paranoia[i].synonym,
3127 paranoia[i].synMinLen, FALSE))) {
3128 if (paranoia[i].flagmask)
3129 flags.paranoia_bits |= paranoia[i].flagmask;
3130 else /* 0 == "none", so clear all */
3131 flags.paranoia_bits = 0;
3135 if (i == SIZE(paranoia)) {
3136 /* didn't match anything, so arg is bad;
3137 any flags already set will stay set */
3138 config_error_add("Unknown %s parameter '%s'",
3142 /* move on to next token */
3146 break; /* no next token */
3153 /* accept deprecated boolean; superseded by paranoid_confirm:pray */
3154 fullname = "prayconfirm";
3155 if (match_optname(opts, fullname, 4, FALSE)) {
3157 flags.paranoia_bits &= ~PARANOID_PRAY;
3159 flags.paranoia_bits |= PARANOID_PRAY;
3163 /* maximum burden picked up before prompt (Warren Cheung) */
3164 fullname = "pickup_burden";
3165 if (match_optname(opts, fullname, 8, TRUE)) {
3167 complain_about_duplicate(opts, 1);
3169 bad_negation(fullname, FALSE);
3171 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
3172 switch (lowc(*op)) {
3173 case 'u': /* Unencumbered */
3174 flags.pickup_burden = UNENCUMBERED;
3176 case 'b': /* Burdened (slight encumbrance) */
3177 flags.pickup_burden = SLT_ENCUMBER;
3179 case 's': /* streSsed (moderate encumbrance) */
3180 flags.pickup_burden = MOD_ENCUMBER;
3182 case 'n': /* straiNed (heavy encumbrance) */
3183 flags.pickup_burden = HVY_ENCUMBER;
3185 case 'o': /* OverTaxed (extreme encumbrance) */
3187 flags.pickup_burden = EXT_ENCUMBER;
3189 case 'l': /* overLoaded */
3190 flags.pickup_burden = OVERLOADED;
3193 config_error_add("Unknown %s parameter '%s'", fullname, op);
3201 /* types of objects to pick up automatically */
3202 fullname = "pickup_types";
3203 if (match_optname(opts, fullname, 8, TRUE)) {
3204 char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], qbuf[QBUFSZ],
3205 abuf[BUFSZ] = DUMMY;
3207 boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
3210 complain_about_duplicate(opts, 1);
3211 oc_to_str(flags.pickup_types, tbuf);
3212 flags.pickup_types[0] = '\0'; /* all */
3213 op = string_for_opt(opts, (compat || !initial));
3215 if (compat || negated || initial) {
3216 /* for backwards compatibility, "pickup" without a
3217 value is a synonym for autopickup of all types
3218 (and during initialization, we can't prompt yet) */
3219 flags.pickup = !negated;
3222 oc_to_str(flags.inv_order, ocl);
3224 if (flags.menu_style == MENU_TRADITIONAL
3225 || flags.menu_style == MENU_COMBINATION) {
3228 Sprintf(qbuf, "New %s: [%s am] (%s)", fullname, ocl,
3229 *tbuf ? tbuf : "all");
3231 Sprintf(qbuf, "
\90V
\82µ
\82¢%s: [%s am] (%s)", fullname, ocl,
3232 *tbuf ? tbuf : "all");
3235 op = mungspaces(abuf);
3236 if (abuf[0] == '\0' || abuf[0] == '\033')
3237 op = tbuf; /* restore */
3238 else if (abuf[0] == 'm')
3243 (void) choose_classes_menu("Auto-Pickup what?", 1, TRUE, ocl,
3246 (void) choose_classes_menu("
\82Ç
\82ê
\82ð
\8e©
\93®
\8fE
\82¢
\82É
\90Ý
\92è
\82·
\82é
\81H", 1, TRUE, ocl,
3253 bad_negation(fullname, TRUE);
3258 if (*op != 'a' && *op != 'A') {
3261 oc_sym = def_char_to_objclass(*op);
3262 /* make sure all are valid obj symbols occurring once */
3263 if (oc_sym != MAXOCLASSES
3264 && !index(flags.pickup_types, oc_sym)) {
3265 flags.pickup_types[num] = (char) oc_sym;
3266 flags.pickup_types[++num] = '\0';
3272 config_error_add("Unknown %s parameter '%s'", fullname, op);
3279 /* pile limit: when walking over objects, number which triggers
3280 "there are several/many objects here" instead of listing them */
3281 fullname = "pile_limit";
3282 if (match_optname(opts, fullname, 4, TRUE)) {
3284 complain_about_duplicate(opts, 1);
3285 op = string_for_opt(opts, negated);
3286 if ((negated && !op) || (!negated && op))
3287 flags.pile_limit = negated ? 0 : atoi(op);
3289 bad_negation(fullname, TRUE);
3292 flags.pile_limit = PILE_LIMIT_DFLT;
3294 if (flags.pile_limit < 0)
3295 flags.pile_limit = PILE_LIMIT_DFLT;
3299 /* play mode: normal, explore/discovery, or debug/wizard */
3300 fullname = "playmode";
3301 if (match_optname(opts, fullname, 4, TRUE)) {
3303 complain_about_duplicate(opts, 1);
3305 bad_negation(fullname, FALSE);
3306 if (duplicate || negated)
3308 op = string_for_opt(opts, FALSE);
3311 if (!strncmpi(op, "normal", 6) || !strcmpi(op, "play")) {
3312 wizard = discover = FALSE;
3313 } else if (!strncmpi(op, "explore", 6)
3314 || !strncmpi(op, "discovery", 6)) {
3315 wizard = FALSE, discover = TRUE;
3316 } else if (!strncmpi(op, "debug", 5) || !strncmpi(op, "wizard", 6)) {
3317 wizard = TRUE, discover = FALSE;
3319 config_error_add("Invalid value for \"%s\":%s", fullname, op);
3326 * player_selection: dialog | prompts */
3327 fullname = "player_selection";
3328 if (match_optname(opts, fullname, sizeof("player_selection") - 1, TRUE)) {
3330 complain_about_duplicate(opts, 1);
3331 op = string_for_opt(opts, negated);
3332 if (op && !negated) {
3333 if (!strncmpi(op, "dialog", sizeof("dialog") - 1))
3334 iflags.wc_player_selection = VIA_DIALOG;
3335 else if (!strncmpi(op, "prompt", sizeof("prompt") - 1))
3336 iflags.wc_player_selection = VIA_PROMPTS;
3338 config_error_add("Unknown %s parameter '%s'", fullname, op);
3341 } else if (negated) {
3342 bad_negation(fullname, TRUE);
3348 /* things to disclose at end of game */
3349 fullname = "disclose";
3350 if (match_optname(opts, fullname, 7, TRUE)) {
3352 * The order that the end_disclose options are stored:
3353 * inventory, attribs, vanquished, genocided,
3354 * conduct, overview.
3355 * There is an array in flags:
3356 * end_disclose[NUM_DISCLOSURE_OPT];
3357 * with option settings for the each of the following:
3358 * iagvc [see disclosure_options in decl.c]:
3359 * Legal setting values in that array are:
3360 * DISCLOSE_PROMPT_DEFAULT_YES ask with default answer yes
3361 * DISCLOSE_PROMPT_DEFAULT_NO ask with default answer no
3362 * DISCLOSE_YES_WITHOUT_PROMPT always disclose and don't ask
3363 * DISCLOSE_NO_WITHOUT_PROMPT never disclose and don't ask
3365 * Those setting values can be used in the option
3366 * string as a prefix to get the desired behaviour.
3368 * For backward compatibility, no prefix is required,
3369 * and the presence of a i,a,g,v, or c without a prefix
3370 * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
3372 int idx, prefix_val;
3375 complain_about_duplicate(opts, 1);
3376 op = string_for_opt(opts, TRUE);
3377 if (op && negated) {
3378 bad_negation(fullname, TRUE);
3381 /* "disclose" without a value means "all with prompting"
3382 and negated means "none without prompting" */
3383 if (!op || !strcmpi(op, "all") || !strcmpi(op, "none")) {
3384 if (op && !strcmpi(op, "none"))
3386 for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++)
3387 flags.end_disclose[num] = negated
3388 ? DISCLOSE_NO_WITHOUT_PROMPT
3389 : DISCLOSE_PROMPT_DEFAULT_YES;
3395 while (*op && num < sizeof flags.end_disclose - 1) {
3396 static char valid_settings[] = {
3397 DISCLOSE_PROMPT_DEFAULT_YES, DISCLOSE_PROMPT_DEFAULT_NO,
3398 DISCLOSE_PROMPT_DEFAULT_SPECIAL,
3399 DISCLOSE_YES_WITHOUT_PROMPT, DISCLOSE_NO_WITHOUT_PROMPT,
3400 DISCLOSE_SPECIAL_WITHOUT_PROMPT, '\0'
3402 register char c, *dop;
3406 c = 'v'; /* killed -> vanquished */
3408 c = 'o'; /* dungeon -> overview */
3409 dop = index(disclosure_options, c);
3411 idx = (int) (dop - disclosure_options);
3412 if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) {
3413 impossible("bad disclosure index %d %c", idx, c);
3416 if (prefix_val != -1) {
3418 if (prefix_val == DISCLOSE_PROMPT_DEFAULT_SPECIAL)
3419 prefix_val = DISCLOSE_PROMPT_DEFAULT_YES;
3420 if (prefix_val == DISCLOSE_SPECIAL_WITHOUT_PROMPT)
3421 prefix_val = DISCLOSE_YES_WITHOUT_PROMPT;
3423 flags.end_disclose[idx] = prefix_val;
3426 flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT;
3427 } else if (index(valid_settings, c)) {
3429 } else if (c == ' ') {
3432 config_error_add("Unknown %s parameter '%c'", fullname, *op);
3440 if (!strncmpi(opts, "kcode", 3)){
3441 if ((op = string_for_env_opt("kcode", opts, FALSE)) != 0){
3448 /* scores:5t[op] 5a[round] o[wn] */
3449 fullname = "scores";
3450 if (match_optname(opts, fullname, 4, TRUE)) {
3452 complain_about_duplicate(opts, 1);
3454 bad_negation(fullname, FALSE);
3457 if (!(op = string_for_opt(opts, FALSE)))
3467 } else if (*op == '!') {
3477 flags.end_top = inum;
3481 flags.end_around = inum;
3485 flags.end_own = !negated;
3488 config_error_add("Unknown %s parameter '%s'", fullname, op);
3491 while (letter(*++op) || *op == ' ')
3499 fullname = "sortloot";
3500 if (match_optname(opts, fullname, 4, TRUE)) {
3501 op = string_for_env_opt(fullname, opts, FALSE);
3506 case 'n': /* none */
3507 case 'l': /* loot (pickup) */
3508 case 'f': /* full (pickup + invent) */
3512 config_error_add("Unknown %s parameter '%s'", fullname, op);
3520 fullname = "suppress_alert";
3521 if (match_optname(opts, fullname, 4, TRUE)) {
3523 complain_about_duplicate(opts, 1);
3524 op = string_for_opt(opts, negated);
3526 bad_negation(fullname, FALSE);
3529 (void) feature_alert_opts(op, fullname);
3534 /* videocolors:string */
3535 fullname = "videocolors";
3536 if (match_optname(opts, fullname, 6, TRUE)
3537 || match_optname(opts, "videocolours", 10, TRUE)) {
3539 complain_about_duplicate(opts, 1);
3541 bad_negation(fullname, FALSE);
3543 } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3546 if (!assign_videocolors(opts)) /* TODO: error msg */
3550 /* videoshades:string */
3551 fullname = "videoshades";
3552 if (match_optname(opts, fullname, 6, TRUE)) {
3554 complain_about_duplicate(opts, 1);
3556 bad_negation(fullname, FALSE);
3558 } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3561 if (!assign_videoshades(opts)) /* TODO: error msg */
3565 #endif /* VIDEOSHADES */
3568 /* video:string -- must be after longer tests */
3570 if (match_optname(opts, fullname, 5, TRUE)) {
3572 complain_about_duplicate(opts, 1);
3574 bad_negation(fullname, FALSE);
3576 } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3579 if (!assign_video(opts)) /* TODO: error msg */
3583 #endif /* NO_TERMS */
3584 /* soundcard:string -- careful not to match boolean 'sound' */
3585 fullname = "soundcard";
3586 if (match_optname(opts, fullname, 6, TRUE)) {
3588 complain_about_duplicate(opts, 1);
3590 bad_negation(fullname, FALSE);
3592 } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3595 if (!assign_soundcard(opts)) /* TODO: error msg */
3603 * map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|
3604 * ascii8x12|ascii16x12|ascii12x16|ascii10x18|fit_to_screen]
3606 fullname = "map_mode";
3607 if (match_optname(opts, fullname, sizeof("map_mode") - 1, TRUE)) {
3609 complain_about_duplicate(opts, 1);
3610 op = string_for_opt(opts, negated);
3611 if (op && !negated) {
3612 if (!strncmpi(op, "tiles", sizeof("tiles") - 1))
3613 iflags.wc_map_mode = MAP_MODE_TILES;
3614 else if (!strncmpi(op, "ascii4x6", sizeof("ascii4x6") - 1))
3615 iflags.wc_map_mode = MAP_MODE_ASCII4x6;
3616 else if (!strncmpi(op, "ascii6x8", sizeof("ascii6x8") - 1))
3617 iflags.wc_map_mode = MAP_MODE_ASCII6x8;
3618 else if (!strncmpi(op, "ascii8x8", sizeof("ascii8x8") - 1))
3619 iflags.wc_map_mode = MAP_MODE_ASCII8x8;
3620 else if (!strncmpi(op, "ascii16x8", sizeof("ascii16x8") - 1))
3621 iflags.wc_map_mode = MAP_MODE_ASCII16x8;
3622 else if (!strncmpi(op, "ascii7x12", sizeof("ascii7x12") - 1))
3623 iflags.wc_map_mode = MAP_MODE_ASCII7x12;
3624 else if (!strncmpi(op, "ascii8x12", sizeof("ascii8x12") - 1))
3625 iflags.wc_map_mode = MAP_MODE_ASCII8x12;
3626 else if (!strncmpi(op, "ascii16x12", sizeof("ascii16x12") - 1))
3627 iflags.wc_map_mode = MAP_MODE_ASCII16x12;
3628 else if (!strncmpi(op, "ascii12x16", sizeof("ascii12x16") - 1))
3629 iflags.wc_map_mode = MAP_MODE_ASCII12x16;
3630 else if (!strncmpi(op, "ascii10x18", sizeof("ascii10x18") - 1))
3631 iflags.wc_map_mode = MAP_MODE_ASCII10x18;
3632 else if (!strncmpi(op, "fit_to_screen",
3633 sizeof("fit_to_screen") - 1))
3634 iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
3636 config_error_add("Unknown %s parameter '%s'", fullname, op);
3639 } else if (negated) {
3640 bad_negation(fullname, TRUE);
3647 * scroll_amount:nn */
3648 fullname = "scroll_amount";
3649 if (match_optname(opts, fullname, sizeof "scroll_amount" - 1, TRUE)) {
3651 complain_about_duplicate(opts, 1);
3652 op = string_for_opt(opts, negated);
3653 if ((negated && !op) || (!negated && op)) {
3654 iflags.wc_scroll_amount = negated ? 1 : atoi(op);
3655 } else if (negated) {
3656 bad_negation(fullname, TRUE);
3663 * scroll_margin:nn */
3664 fullname = "scroll_margin";
3665 if (match_optname(opts, fullname, sizeof "scroll_margin" - 1, TRUE)) {
3667 complain_about_duplicate(opts, 1);
3668 op = string_for_opt(opts, negated);
3669 if ((negated && !op) || (!negated && op)) {
3670 iflags.wc_scroll_margin = negated ? 5 : atoi(op);
3671 } else if (negated) {
3672 bad_negation(fullname, TRUE);
3678 fullname = "subkeyvalue";
3679 if (match_optname(opts, fullname, 5, TRUE)) {
3680 /* no duplicate complaint here */
3682 bad_negation(fullname, FALSE);
3686 op = string_for_opt(opts, 0);
3689 map_subkeyvalue(op);
3697 fullname = "tile_width";
3698 if (match_optname(opts, fullname, sizeof("tile_width") - 1, TRUE)) {
3700 complain_about_duplicate(opts, 1);
3701 op = string_for_opt(opts, negated);
3702 if ((negated && !op) || (!negated && op)) {
3703 iflags.wc_tile_width = negated ? 0 : atoi(op);
3704 } else if (negated) {
3705 bad_negation(fullname, TRUE);
3712 fullname = "tile_file";
3713 if (match_optname(opts, fullname, sizeof("tile_file") - 1, TRUE)) {
3715 complain_about_duplicate(opts, 1);
3716 if ((op = string_for_opt(opts, FALSE)) != 0) {
3717 if (iflags.wc_tile_file)
3718 free(iflags.wc_tile_file);
3719 iflags.wc_tile_file = dupstr(op);
3726 fullname = "tile_height";
3727 if (match_optname(opts, fullname, sizeof("tile_height") - 1, TRUE)) {
3729 complain_about_duplicate(opts, 1);
3730 op = string_for_opt(opts, negated);
3731 if ((negated && !op) || (!negated && op)) {
3732 iflags.wc_tile_height = negated ? 0 : atoi(op);
3733 } else if (negated) {
3734 bad_negation(fullname, TRUE);
3741 * vary_msgcount:nn */
3742 fullname = "vary_msgcount";
3743 if (match_optname(opts, fullname, sizeof("vary_msgcount") - 1, TRUE)) {
3745 complain_about_duplicate(opts, 1);
3746 op = string_for_opt(opts, negated);
3747 if ((negated && !op) || (!negated && op)) {
3748 iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
3749 } else if (negated) {
3750 bad_negation(fullname, TRUE);
3757 * windowtype: option to choose the interface for binaries built
3758 * with support for more than one interface (tty + X11, for instance).
3760 * Ideally, 'windowtype' should be processed first, because it
3761 * causes the wc_ and wc2_ flags to be set up.
3762 * For user, making it be first in a config file is trivial, use
3763 * OPTIONS=windowtype:Foo
3764 * as the first non-comment line of the file.
3765 * Making it first in NETHACKOPTIONS requires it to be at the _end_
3766 * because option strings are processed from right to left.
3768 fullname = "windowtype";
3769 if (match_optname(opts, fullname, 3, TRUE)) {
3771 complain_about_duplicate(opts, 1);
3773 bad_negation(fullname, FALSE);
3775 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
3776 char buf[WINTYPELEN];
3778 nmcpy(buf, op, WINTYPELEN);
3779 choose_windows(buf);
3786 fullname = "windowchain";
3787 if (match_optname(opts, fullname, 3, TRUE)) {
3789 bad_negation(fullname, FALSE);
3791 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
3792 char buf[WINTYPELEN];
3794 nmcpy(buf, op, WINTYPELEN);
3795 addto_windowchain(buf);
3803 * setting window colors
3804 * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd
3806 fullname = "windowcolors";
3807 if (match_optname(opts, fullname, 7, TRUE)) {
3809 complain_about_duplicate(opts, 1);
3810 if ((op = string_for_opt(opts, FALSE)) != 0) {
3811 if (!wc_set_window_colors(op)) /* TODO: error msg*/
3814 bad_negation(fullname, TRUE);
3818 /* menustyle:traditional or combination or full or partial */
3819 fullname = "menustyle";
3820 if (match_optname(opts, fullname, 4, TRUE)) {
3822 boolean val_required = (strlen(opts) > 5 && !negated);
3825 complain_about_duplicate(opts, 1);
3826 if (!(op = string_for_opt(opts, !val_required))) {
3828 return FALSE; /* string_for_opt gave feedback */
3829 tmp = negated ? 'n' : 'f';
3834 case 'n': /* none */
3835 case 't': /* traditional: prompt for class(es) by symbol,
3836 prompt for each item within class(es) one at a time */
3837 flags.menu_style = MENU_TRADITIONAL;
3839 case 'c': /* combination: prompt for class(es) by symbol,
3840 choose items within selected class(es) by menu */
3841 flags.menu_style = MENU_COMBINATION;
3843 case 'f': /* full: choose class(es) by first menu,
3844 choose items within selected class(es) by second menu */
3845 flags.menu_style = MENU_FULL;
3847 case 'p': /* partial: skip class filtering,
3848 choose items among all classes by menu */
3849 flags.menu_style = MENU_PARTIAL;
3852 config_error_add("Unknown %s parameter '%s'", fullname, op);
3858 fullname = "menu_headings";
3859 if (match_optname(opts, fullname, 12, TRUE)) {
3863 complain_about_duplicate(opts, 1);
3865 bad_negation(fullname, FALSE);
3867 } else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3870 tmpattr = match_str2attr(opts, TRUE);
3874 iflags.menu_headings = tmpattr;
3878 /* check for menu command mapping */
3879 for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
3880 fullname = default_menu_cmd_info[i].name;
3882 complain_about_duplicate(opts, 1);
3883 if (match_optname(opts, fullname, (int) strlen(fullname), TRUE)) {
3885 bad_negation(fullname, FALSE);
3887 } else if ((op = string_for_opt(opts, FALSE)) != 0) {
3888 char c, op_buf[BUFSZ];
3890 escapes(op, op_buf);
3893 if (illegal_menu_cmd_key(c)) {
3896 add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
3902 /* hilite fields in status prompt */
3903 fullname = "hilite_status";
3904 if (match_optname(opts, fullname, 13, TRUE)) {
3905 #ifdef STATUS_HILITES
3907 complain_about_duplicate(opts, 1);
3908 op = string_for_opt(opts, TRUE);
3909 if (op && negated) {
3910 clear_status_hilites();
3913 config_error_add("Value is mandatory for hilite_status");
3916 if (!parse_status_hl1(op, tfrom_file))
3920 config_error_add("'%s' is not supported", fullname);
3925 /* control over whether highlights should be displayed, and for how long */
3926 fullname = "statushilites";
3927 if (match_optname(opts, fullname, 9, TRUE)) {
3928 #ifdef STATUS_HILITES
3930 iflags.hilite_delta = 0L;
3932 op = string_for_opt(opts, TRUE);
3933 iflags.hilite_delta = (!op || !*op) ? 3L : atol(op);
3934 if (iflags.hilite_delta < 0L)
3935 iflags.hilite_delta = 1L;
3938 reset_status_hilites();
3941 config_error_add("'%s' is not supported", fullname);
3946 fullname = "DECgraphics";
3947 if (match_optname(opts, fullname, 3, TRUE)) {
3948 #ifdef BACKWARD_COMPAT
3949 boolean badflag = FALSE;
3952 complain_about_duplicate(opts, 1);
3954 /* There is no rogue level DECgraphics-specific set */
3955 if (symset[PRIMARY].name) {
3958 symset[PRIMARY].name = dupstr(fullname);
3959 if (!read_sym_file(PRIMARY)) {
3961 clear_symsetentry(PRIMARY, TRUE);
3963 switch_symbols(TRUE);
3966 config_error_add("Failure to load symbol set %s.", fullname);
3972 config_error_add("'%s' no longer supported; use 'symset:%s' instead",
3973 fullname, fullname);
3976 } /* "DECgraphics" */
3978 fullname = "IBMgraphics";
3979 if (match_optname(opts, fullname, 3, TRUE)) {
3980 #ifdef BACKWARD_COMPAT
3981 const char *sym_name = fullname;
3982 boolean badflag = FALSE;
3985 complain_about_duplicate(opts, 1);
3987 for (i = 0; i < NUM_GRAPHICS; ++i) {
3988 if (symset[i].name) {
3992 sym_name = "RogueIBM";
3993 symset[i].name = dupstr(sym_name);
3994 if (!read_sym_file(i)) {
3996 clear_symsetentry(i, TRUE);
4002 config_error_add("Failure to load symbol set %s.", sym_name);
4005 switch_symbols(TRUE);
4006 if (!initial && Is_rogue_level(&u.uz))
4007 assign_graphics(ROGUESET);
4012 config_error_add("'%s' no longer supported; use 'symset:%s' instead",
4013 fullname, fullname);
4016 } /* "IBMgraphics" */
4018 fullname = "MACgraphics";
4019 if (match_optname(opts, fullname, 3, TRUE)) {
4020 #if defined(MAC_GRAPHICS_ENV) && defined(BACKWARD_COMPAT)
4021 boolean badflag = FALSE;
4024 complain_about_duplicate(opts, 1);
4026 if (symset[PRIMARY].name) {
4029 symset[PRIMARY].name = dupstr(fullname);
4030 if (!read_sym_file(PRIMARY)) {
4032 clear_symsetentry(PRIMARY, TRUE);
4036 config_error_add("Failure to load symbol set %s.", fullname);
4039 switch_symbols(TRUE);
4040 if (!initial && Is_rogue_level(&u.uz))
4041 assign_graphics(ROGUESET);
4045 #else /* !(MAC_GRAPHICS_ENV && BACKWARD_COMPAT) */
4046 config_error_add("'%s' %s; use 'symset:%s' instead",
4048 #ifdef MAC_GRAPHICS_ENV /* implies BACKWARD_COMPAT is not defined */
4049 "no longer supported",
4055 #endif /* ?(MAC_GRAPHICS_ENV && BACKWARD_COMPAT) */
4056 } /* "MACgraphics" */
4058 /* OK, if we still haven't recognized the option, check the boolean
4061 for (i = 0; boolopt[i].name; i++) {
4062 if (match_optname(opts, boolopt[i].name, 3, TRUE)) {
4063 /* options that don't exist */
4064 if (!boolopt[i].addr) {
4065 if (!initial && !negated)
4066 pline_The("\"%s\" option is not available.",
4070 /* options that must come from config file */
4071 if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
4072 rejectoption(boolopt[i].name);
4076 op = string_for_opt(opts, TRUE);
4081 "Negated boolean '%s' should not have a parameter",
4085 if (!strcmp(op, "true") || !strcmp(op, "yes")) {
4087 } else if (!strcmp(op, "false") || !strcmp(op, "no")) {
4090 config_error_add("Illegal parameter for a boolean");
4095 *(boolopt[i].addr) = !negated;
4097 /* 0 means boolean opts */
4098 if (duplicate_opt_detection(boolopt[i].name, 0))
4099 complain_about_duplicate(boolopt[i].name, 0);
4101 if (boolopt[i].addr == &iflags.rlecomp)
4102 set_savepref(iflags.rlecomp ? "rlecomp" : "!rlecomp");
4105 if (boolopt[i].addr == &iflags.zerocomp)
4106 set_savepref(iflags.zerocomp ? "zerocomp" : "externalcomp");
4108 if (boolopt[i].addr == &iflags.wc_ascii_map) {
4109 /* toggling ascii_map; set tiled_map to its opposite;
4110 what does it mean to turn off ascii map if tiled map
4111 isn't supported? -- right now, we do nothing */
4112 iflags.wc_tiled_map = negated;
4113 } else if (boolopt[i].addr == &iflags.wc_tiled_map) {
4114 /* toggling tiled_map; set ascii_map to its opposite;
4115 as with ascii_map, what does it mean to turn off tiled
4116 map if ascii map isn't supported? */
4117 iflags.wc_ascii_map = negated;
4119 /* only do processing below if setting with doset() */
4123 if (boolopt[i].addr == &flags.time
4124 #ifdef SCORE_ON_BOTL
4125 || boolopt[i].addr == &flags.showscore
4127 || boolopt[i].addr == &flags.showexp) {
4128 #ifdef STATUS_HILITES
4129 status_initialize(REASSESS_ONLY);
4131 context.botl = TRUE;
4132 } else if (boolopt[i].addr == &flags.invlet_constant) {
4133 if (flags.invlet_constant)
4135 } else if (boolopt[i].addr == &flags.lit_corridor
4136 || boolopt[i].addr == &flags.dark_room) {
4138 * All corridor squares seen via night vision or
4139 * candles & lamps change. Update them by calling
4140 * newsym() on them. Don't do this if we are
4141 * initializing the options --- the vision system
4144 vision_recalc(2); /* shut down vision */
4145 vision_full_recalc = 1; /* delayed recalc */
4146 if (iflags.use_color)
4147 need_redraw = TRUE; /* darkroom refresh */
4148 } else if (boolopt[i].addr == &flags.showrace
4149 || boolopt[i].addr == &iflags.use_inverse
4150 || boolopt[i].addr == &iflags.hilite_pile
4151 || boolopt[i].addr == &iflags.hilite_pet
4152 || boolopt[i].addr == &iflags.wc_ascii_map
4153 || boolopt[i].addr == &iflags.wc_tiled_map) {
4155 #ifdef STATUS_HILITES
4156 } else if (boolopt[i].addr == &iflags.wc2_hitpointbar) {
4157 status_initialize(REASSESS_ONLY);
4161 } else if (boolopt[i].addr == &iflags.use_color) {
4171 #endif /* TEXTCOLOR */
4177 /* Is it a symbol? */
4178 if (strstr(opts, "S_") == opts && parsesymbols(opts)) {
4179 switch_symbols(TRUE);
4180 check_gold_symbol();
4184 /* out of valid options */
4185 config_error_add("Unknown option '%s'", opts);
4189 /* parse key:command */
4191 parsebindings(bindings)
4197 boolean ret = FALSE;
4199 /* break off first binding from the rest; parse the rest */
4200 if ((bind = index(bindings, ',')) != 0) {
4202 ret |= parsebindings(bind);
4205 /* parse a single binding: first split around : */
4206 if (! (bind = index(bindings, ':')))
4207 return FALSE; /* it's not a binding */
4210 /* read the key to be bound */
4211 key = txt2key(bindings);
4213 config_error_add("Unknown key binding key '%s'", bindings);
4217 bind = trimspaces(bind);
4219 /* is it a special key? */
4220 if (bind_specialkey(key, bind))
4223 /* is it a menu command? */
4224 for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
4225 if (!strcmp(default_menu_cmd_info[i].name, bind)) {
4226 if (illegal_menu_cmd_key(key)) {
4227 config_error_add("Bad menu key %s:%s", visctrl(key), bind);
4230 add_menu_cmd_alias(key, default_menu_cmd_info[i].cmd);
4235 /* extended command? */
4236 if (!bind_key(key, bind)) {
4237 config_error_add("Unknown key binding command '%s'", bind);
4243 static NEARDATA const char *menutype[] = { "traditional", "combination",
4244 "full", "partial" };
4246 static NEARDATA const char *burdentype[] = { "unencumbered", "burdened",
4247 "stressed", "strained",
4248 "overtaxed", "overloaded" };
4250 static NEARDATA const char *runmodes[] = { "teleport", "run", "walk",
4253 static NEARDATA const char *sortltype[] = { "none", "loot", "full" };
4256 * Convert the given string of object classes to a string of default object
4260 oc_to_str(src, dest)
4265 while ((i = (int) *src++) != 0) {
4266 if (i < 0 || i >= MAXOCLASSES)
4267 impossible("oc_to_str: illegal object class %d", i);
4269 *dest++ = def_oc_syms[i].sym;
4275 * Add the given mapping to the menu command map list. Always keep the
4276 * maps valid C strings.
4279 add_menu_cmd_alias(from_ch, to_ch)
4280 char from_ch, to_ch;
4282 if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS) {
4283 pline("out of menu map space.");
4285 mapped_menu_cmds[n_menu_mapped] = from_ch;
4286 mapped_menu_op[n_menu_mapped] = to_ch;
4288 mapped_menu_cmds[n_menu_mapped] = 0;
4289 mapped_menu_op[n_menu_mapped] = 0;
4294 get_menu_cmd_key(ch)
4297 char *found = index(mapped_menu_op, ch);
4300 int idx = (int) (found - mapped_menu_op);
4302 ch = mapped_menu_cmds[idx];
4308 * Map the given character to its corresponding menu command. If it
4309 * doesn't match anything, just return the original.
4315 char *found = index(mapped_menu_cmds, ch);
4318 int idx = (int) (found - mapped_menu_cmds);
4320 ch = mapped_menu_op[idx];
4326 show_menu_controls(win, dolist)
4332 putstr(win, 0, "Menu control keys:");
4336 for (i = 0; i < SIZE(default_menu_cmd_info); i++) {
4337 Sprintf(buf, "%-8s %s",
4338 visctrl(get_menu_cmd_key(default_menu_cmd_info[i].cmd)),
4339 default_menu_cmd_info[i].desc);
4340 putstr(win, 0, buf);
4344 putstr(win, 0, " Page All items");
4345 Sprintf(buf, " Select %s %s",
4346 visctrl(get_menu_cmd_key(MENU_SELECT_PAGE)),
4347 visctrl(get_menu_cmd_key(MENU_SELECT_ALL)));
4348 putstr(win, 0, buf);
4349 Sprintf(buf, "Deselect %s %s",
4350 visctrl(get_menu_cmd_key(MENU_UNSELECT_PAGE)),
4351 visctrl(get_menu_cmd_key(MENU_UNSELECT_ALL)));
4352 putstr(win, 0, buf);
4353 Sprintf(buf, " Invert %s %s",
4354 visctrl(get_menu_cmd_key(MENU_INVERT_PAGE)),
4355 visctrl(get_menu_cmd_key(MENU_INVERT_ALL)));
4356 putstr(win, 0, buf);
4358 Sprintf(buf, " Go to %s Next page",
4359 visctrl(get_menu_cmd_key(MENU_NEXT_PAGE)));
4360 putstr(win, 0, buf);
4361 Sprintf(buf, " %s Previous page",
4362 visctrl(get_menu_cmd_key(MENU_PREVIOUS_PAGE)));
4363 putstr(win, 0, buf);
4364 Sprintf(buf, " %s First page",
4365 visctrl(get_menu_cmd_key(MENU_FIRST_PAGE)));
4366 putstr(win, 0, buf);
4367 Sprintf(buf, " %s Last page",
4368 visctrl(get_menu_cmd_key(MENU_LAST_PAGE)));
4369 putstr(win, 0, buf);
4371 Sprintf(buf, " %s Search and toggle matching entries",
4372 visctrl(get_menu_cmd_key(MENU_SEARCH)));
4373 putstr(win, 0, buf);
4377 #if defined(MICRO) || defined(MAC) || defined(WIN32)
4378 #define OPTIONS_HEADING "OPTIONS"
4380 #define OPTIONS_HEADING "NETHACKOPTIONS"
4383 static char fmtstr_doset[] = "%s%-15s [%s] ";
4384 static char fmtstr_doset_tab[] = "%s\t[%s]";
4386 static char n_currently_set[] = "(%d currently set)";
4388 static char n_currently_set[] = "(%d
\8cÂ
\90Ý
\92è
\92\86)";
4390 /* doset('O' command) menu entries for compound options */
4392 doset_add_menu(win, option, indexoffset)
4393 winid win; /* window to add to */
4394 const char *option; /* option name */
4395 int indexoffset; /* value to add to index in compopt[], or zero
4396 if option cannot be changed */
4398 const char *value = "unknown"; /* current value */
4399 char buf[BUFSZ], buf2[BUFSZ];
4404 if (indexoffset == 0) {
4406 value = get_compopt_value(option, buf2);
4408 for (i = 0; compopt[i].name; i++)
4409 if (strcmp(option, compopt[i].name) == 0)
4412 if (compopt[i].name) {
4413 any.a_int = i + 1 + indexoffset;
4414 value = get_compopt_value(option, buf2);
4416 /* We are trying to add an option not found in compopt[].
4417 This is almost certainly bad, but we'll let it through anyway
4418 (with a zero value, so it can't be selected). */
4422 /* " " replaces "a - " -- assumes menus follow that style */
4423 if (!iflags.menu_tab_sep)
4424 Sprintf(buf, fmtstr_doset, any.a_int ? "" : " ", option,
4427 Sprintf(buf, fmtstr_doset_tab, option, value);
4428 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
4432 opts_add_others(win, name, id, bufx, nset)
4439 char buf[BUFSZ], buf2[BUFSZ];
4440 anything any = zeroany;
4444 Sprintf(buf2, n_currently_set, nset);
4446 Sprintf(buf2, "%s", bufx);
4447 if (!iflags.menu_tab_sep)
4448 Sprintf(buf, fmtstr_doset, any.a_int ? "" : " ",
4451 Sprintf(buf, fmtstr_doset_tab, name, buf2);
4452 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
4456 count_apes(VOID_ARGS)
4458 return count_ape_maps((int *) 0, (int *) 0);
4461 enum opt_other_enums {
4462 OPT_OTHER_MSGTYPE = -4,
4463 OPT_OTHER_MENUCOLOR = -3,
4464 OPT_OTHER_STATHILITE = -2,
4465 OPT_OTHER_APEXC = -1
4466 /* these must be < 0 */
4469 static struct other_opts {
4472 enum opt_other_enums code;
4473 int NDECL((*othr_count_func));
4475 { "autopickup exceptions", SET_IN_GAME, OPT_OTHER_APEXC, count_apes },
4476 { "menucolors", SET_IN_GAME, OPT_OTHER_MENUCOLOR, count_menucolors },
4477 { "message types", SET_IN_GAME, OPT_OTHER_MSGTYPE, msgtype_count },
4478 #ifdef STATUS_HILITES
4479 { "status hilite rules", SET_IN_GAME, OPT_OTHER_STATHILITE,
4480 count_status_hilites },
4482 { (char *) 0, 0, (enum opt_other_enums) 0 },
4485 /* the 'O' command */
4487 doset() /* changing options via menu by Per Liboriussen */
4489 static boolean made_fmtstr = FALSE;
4490 char buf[BUFSZ], buf2[BUFSZ] = DUMMY;
4492 int i = 0, pass, boolcount, pick_cnt, pick_idx, opt_indx;
4496 menu_item *pick_list;
4497 int indexoffset, startpass, endpass, optflags;
4498 boolean setinitial = FALSE, fromfile = FALSE;
4499 unsigned longest_name_len;
4501 tmpwin = create_nhwindow(NHW_MENU);
4504 #ifdef notyet /* SYSCF */
4505 /* XXX I think this is still fragile. Fixing initial/from_file and/or
4506 changing the SET_* etc to bitmaps will let me make this better. */
4508 startpass = SET_IN_SYS;
4511 startpass = DISP_IN_GAME;
4512 endpass = (wizard) ? SET_IN_WIZGAME : SET_IN_GAME;
4514 if (!made_fmtstr && !iflags.menu_tab_sep) {
4515 /* spin through the options to find the longest name
4516 and adjust the format string accordingly */
4517 longest_name_len = 0;
4518 for (pass = 0; pass <= 2; pass++)
4519 for (i = 0; (name = ((pass == 0)
4523 : othropt[i].name)) != 0; i++) {
4524 if (pass == 0 && !boolopt[i].addr)
4526 optflags = (pass == 0) ? boolopt[i].optflags
4528 ? compopt[i].optflags
4529 : othropt[i].optflags;
4530 if (optflags < startpass || optflags > endpass)
4532 if ((is_wc_option(name) && !wc_supported(name))
4533 || (is_wc2_option(name) && !wc2_supported(name)))
4536 if (strlen(name) > longest_name_len)
4537 longest_name_len = strlen(name);
4539 Sprintf(fmtstr_doset, "%%s%%-%us [%%s]", longest_name_len);
4544 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
4546 "Booleans (selecting will toggle value):", MENU_UNSELECTED);
4548 "
\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);
4550 /* first list any other non-modifiable booleans, then modifiable ones */
4551 for (pass = 0; pass <= 1; pass++)
4552 for (i = 0; (name = boolopt[i].name) != 0; i++)
4553 if ((bool_p = boolopt[i].addr) != 0
4554 && ((boolopt[i].optflags <= DISP_IN_GAME && pass == 0)
4555 || (boolopt[i].optflags >= SET_IN_GAME && pass == 1))) {
4556 if (bool_p == &flags.female)
4557 continue; /* obsolete */
4558 if (boolopt[i].optflags == SET_IN_WIZGAME && !wizard)
4560 if ((is_wc_option(name) && !wc_supported(name))
4561 || (is_wc2_option(name) && !wc2_supported(name)))
4564 any.a_int = (pass == 0) ? 0 : i + 1;
4565 if (!iflags.menu_tab_sep)
4566 Sprintf(buf, fmtstr_doset, (pass == 0) ? " " : "",
4567 name, *bool_p ? "true" : "false");
4569 Sprintf(buf, fmtstr_doset_tab,
4570 name, *bool_p ? "true" : "false");
4571 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
4576 indexoffset = boolcount;
4578 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4580 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
4581 "Compounds (selecting will prompt for new value):",
4584 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
4585 "
\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",
4589 /* deliberately put playmode, name, role+race+gender+align first */
4590 doset_add_menu(tmpwin, "playmode", 0);
4591 doset_add_menu(tmpwin, "name", 0);
4592 doset_add_menu(tmpwin, "role", 0);
4593 doset_add_menu(tmpwin, "race", 0);
4594 doset_add_menu(tmpwin, "gender", 0);
4595 doset_add_menu(tmpwin, "align", 0);
4597 for (pass = startpass; pass <= endpass; pass++)
4598 for (i = 0; (name = compopt[i].name) != 0; i++)
4599 if (compopt[i].optflags == pass) {
4600 if (!strcmp(name, "playmode") || !strcmp(name, "name")
4601 || !strcmp(name, "role") || !strcmp(name, "race")
4602 || !strcmp(name, "gender") || !strcmp(name, "align"))
4604 if ((is_wc_option(name) && !wc_supported(name))
4605 || (is_wc2_option(name) && !wc2_supported(name)))
4608 doset_add_menu(tmpwin, name,
4609 (pass == DISP_IN_GAME) ? 0 : indexoffset);
4613 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4614 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
4615 "Other settings:", MENU_UNSELECTED);
4617 for (i = 0; (name = othropt[i].name) != 0; i++) {
4618 if ((is_wc_option(name) && !wc_supported(name))
4619 || (is_wc2_option(name) && !wc2_supported(name)))
4621 opts_add_others(tmpwin, name, othropt[i].code,
4622 (char *) 0, othropt[i].othr_count_func());
4625 #ifdef PREFIXES_IN_USE
4627 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
4628 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
4629 "Variable playground locations:", MENU_UNSELECTED);
4630 for (i = 0; i < PREFIX_COUNT; i++)
4631 doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
4634 end_menu(tmpwin, "Set what options?");
4636 end_menu(tmpwin, "
\82Ç
\82Ì
\83I
\83v
\83V
\83\87\83\93\82ð
\90Ý
\92è
\82µ
\82Ü
\82·
\82©
\81H");
4637 need_redraw = FALSE;
4638 if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) {
4640 * Walk down the selection list and either invert the booleans
4641 * or prompt for new values. In most cases, call parseoptions()
4642 * to take care of options that require special attention, like
4645 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
4646 opt_indx = pick_list[pick_idx].item.a_int - 1;
4648 opt_indx++; /* -1 offset for select_menu() */
4649 if (opt_indx == OPT_OTHER_APEXC) {
4650 (void) special_handling("autopickup_exception", setinitial,
4652 #ifdef STATUS_HILITES
4653 } else if (opt_indx == OPT_OTHER_STATHILITE) {
4654 if (!status_hilite_menu()) {
4655 pline("Bad status hilite(s) specified.");
4657 if (wc2_supported("hilite_status"))
4658 preference_update("hilite_status");
4661 } else if (opt_indx == OPT_OTHER_MENUCOLOR) {
4662 (void) special_handling("menucolors", setinitial,
4664 } else if (opt_indx == OPT_OTHER_MSGTYPE) {
4665 (void) special_handling("msgtype", setinitial, fromfile);
4666 } else if (opt_indx < boolcount) {
4667 /* boolean option */
4668 Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
4669 boolopt[opt_indx].name);
4670 parseoptions(buf, setinitial, fromfile);
4671 if (wc_supported(boolopt[opt_indx].name)
4672 || wc2_supported(boolopt[opt_indx].name))
4673 preference_update(boolopt[opt_indx].name);
4675 /* compound option */
4676 opt_indx -= boolcount;
4678 if (!special_handling(compopt[opt_indx].name, setinitial,
4681 Sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
4683 Sprintf(buf, "%s
\82É
\89½
\82ð
\90Ý
\92è
\82·
\82é
\81H", compopt[opt_indx].name);
4685 if (buf2[0] == '\033')
4687 Sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2);
4689 parseoptions(buf, setinitial, fromfile);
4691 if (wc_supported(compopt[opt_indx].name)
4692 || wc2_supported(compopt[opt_indx].name))
4693 preference_update(compopt[opt_indx].name);
4696 free((genericptr_t) pick_list);
4697 pick_list = (menu_item *) 0;
4700 destroy_nhwindow(tmpwin);
4702 check_gold_symbol();
4710 handle_add_list_remove(optname, numtotal)
4711 const char *optname;
4716 int i, pick_cnt, opt_idx;
4717 menu_item *pick_list = (menu_item *) 0;
4718 static const struct action {
4721 } action_titles[] = {
4723 { 'a', "add new %s" }, /* [0] */
4725 { 'a', "
\90V
\82µ
\82¢%s
\82ð
\92Ç
\89Á" }, /* [0] */
4728 { 'l', "list %s" }, /* [1] */
4730 { 'l', "%s
\82ð
\88ê
\97\97\95\
\8e¦" }, /* [1] */
4733 { 'r', "remove existing %s" }, /* [2] */
4735 { 'r', "
\8aù
\82É
\82 \82é%s
\82ð
\8dí
\8f\9c" }, /* [2] */
4738 { 'x', "exit this menu" }, /* [3] */
4740 { 'x', "
\82±
\82Ì
\83\81\83j
\83\85\81[
\82ð
\95Â
\82¶
\82é" }, /* [3] */
4745 tmpwin = create_nhwindow(NHW_MENU);
4748 for (i = 0; i < SIZE(action_titles); i++) {
4752 /* omit list and remove if there aren't any yet */
4753 if (!numtotal && (i == 1 || i == 2))
4755 Sprintf(tmpbuf, action_titles[i].desc,
4756 (i == 1) ? makeplural(optname) : optname);
4757 add_menu(tmpwin, NO_GLYPH, &any, action_titles[i].letr, 0, ATR_NONE,
4758 tmpbuf, (i == 3) ? MENU_SELECTED : MENU_UNSELECTED);
4761 end_menu(tmpwin, "Do what?");
4763 end_menu(tmpwin, "
\82Ç
\82¤
\82·
\82é
\81H");
4764 if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
4765 opt_idx = pick_list[0].item.a_int - 1;
4766 if (pick_cnt > 1 && opt_idx == 3)
4767 opt_idx = pick_list[1].item.a_int - 1;
4768 free((genericptr_t) pick_list);
4770 opt_idx = 3; /* none selected, exit menu */
4771 destroy_nhwindow(tmpwin);
4775 struct symsetentry *symset_list = 0; /* files.c will populate this with
4776 list of available sets */
4779 special_handling(optname, setinitial, setfromfile)
4780 const char *optname;
4781 boolean setinitial, setfromfile;
4788 /* Special handling of menustyle, pickup_burden, pickup_types,
4789 * disclose, runmode, msg_window, menu_headings, sortloot,
4790 * and number_pad options.
4791 * Also takes care of interactive autopickup_exception_handling changes.
4793 if (!strcmp("menustyle", optname)) {
4794 const char *style_name;
4795 menu_item *style_pick = (menu_item *) 0;
4797 tmpwin = create_nhwindow(NHW_MENU);
4800 for (i = 0; i < SIZE(menutype); i++) {
4801 style_name = menutype[i];
4802 /* note: separate `style_name' variable used
4803 to avoid an optimizer bug in VAX C V2.3 */
4805 add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0, ATR_NONE,
4806 style_name, MENU_UNSELECTED);
4809 end_menu(tmpwin, "Select menustyle:");
4811 end_menu(tmpwin, "
\83\81\83j
\83\85\81[
\83X
\83^
\83C
\83\8b\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F");
4812 if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) {
4813 flags.menu_style = style_pick->item.a_int - 1;
4814 free((genericptr_t) style_pick);
4816 destroy_nhwindow(tmpwin);
4817 } else if (!strcmp("paranoid_confirmation", optname)) {
4818 menu_item *paranoia_picks = (menu_item *) 0;
4820 tmpwin = create_nhwindow(NHW_MENU);
4823 for (i = 0; paranoia[i].flagmask != 0; ++i) {
4824 if (paranoia[i].flagmask == PARANOID_BONES && !wizard)
4826 any.a_int = paranoia[i].flagmask;
4827 add_menu(tmpwin, NO_GLYPH, &any, *paranoia[i].argname, 0,
4828 ATR_NONE, paranoia[i].explain,
4829 (flags.paranoia_bits & paranoia[i].flagmask)
4833 end_menu(tmpwin, "Actions requiring extra confirmation:");
4834 i = select_menu(tmpwin, PICK_ANY, ¶noia_picks);
4836 /* player didn't cancel; we reset all the paranoia options
4837 here even if there were no items picked, since user
4838 could have toggled off preselected ones to end up with 0 */
4839 flags.paranoia_bits = 0;
4841 /* at least 1 item set, either preselected or newly picked */
4843 flags.paranoia_bits |= paranoia_picks[i].item.a_int;
4844 free((genericptr_t) paranoia_picks);
4847 destroy_nhwindow(tmpwin);
4848 } else if (!strcmp("pickup_burden", optname)) {
4849 const char *burden_name, *burden_letters = "ubsntl";
4850 menu_item *burden_pick = (menu_item *) 0;
4852 tmpwin = create_nhwindow(NHW_MENU);
4855 for (i = 0; i < SIZE(burdentype); i++) {
4856 burden_name = burdentype[i];
4858 add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0, ATR_NONE,
4859 burden_name, MENU_UNSELECTED);
4862 end_menu(tmpwin, "Select encumbrance level:");
4864 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");
4865 if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) {
4866 flags.pickup_burden = burden_pick->item.a_int - 1;
4867 free((genericptr_t) burden_pick);
4869 destroy_nhwindow(tmpwin);
4870 } else if (!strcmp("pickup_types", optname)) {
4871 /* parseoptions will prompt for the list of types */
4872 parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile);
4873 } else if (!strcmp("disclose", optname)) {
4874 /* order of disclose_names[] must correspond to
4875 disclosure_options in decl.c */
4876 static const char *disclosure_names[] = {
4877 "inventory", "attributes", "vanquished",
4878 "genocides", "conduct", "overview",
4880 int disc_cat[NUM_DISCLOSURE_OPTIONS];
4881 int pick_cnt, pick_idx, opt_idx;
4883 menu_item *disclosure_pick = (menu_item *) 0;
4885 tmpwin = create_nhwindow(NHW_MENU);
4888 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
4889 Sprintf(buf, "%-12s[%c%c]", disclosure_names[i],
4890 flags.end_disclose[i], disclosure_options[i]);
4892 add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0,
4893 ATR_NONE, buf, MENU_UNSELECTED);
4897 end_menu(tmpwin, "Change which disclosure options categories:");
4899 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");
4900 pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_pick);
4902 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
4903 opt_idx = disclosure_pick[pick_idx].item.a_int - 1;
4904 disc_cat[opt_idx] = 1;
4906 free((genericptr_t) disclosure_pick);
4907 disclosure_pick = (menu_item *) 0;
4909 destroy_nhwindow(tmpwin);
4911 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
4913 c = flags.end_disclose[i];
4915 Sprintf(buf, "Disclosure options for %s:",
4917 Sprintf(buf, "%s
\82Ì
\8fo
\97Í
\8c`
\8e®
\81F",
4918 disclosure_names[i]);
4919 tmpwin = create_nhwindow(NHW_MENU);
4922 /* 'y','n',and '+' work as alternate selectors; '-' doesn't */
4923 any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
4924 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
4926 "Never disclose, without prompting",
4928 "
\8am
\94F
\82¹
\82¸
\82É
\8fo
\97Í
\82à
\82µ
\82È
\82¢",
4929 (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
4930 any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
4931 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
4933 "Always disclose, without prompting",
4935 "
\8am
\94F
\82¹
\82¸
\82É
\8fo
\97Í
\82·
\82é",
4936 (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
4937 if (*disclosure_names[i] == 'v') {
4938 any.a_char = DISCLOSE_SPECIAL_WITHOUT_PROMPT; /* '#' */
4939 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
4940 "Always disclose, pick sort order from menu",
4941 (c == any.a_char) ? MENU_SELECTED
4944 any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
4945 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
4947 "Prompt, with default answer of \"No\"",
4949 "
\8am
\94F
\82·
\82é
\81C
\83f
\83t
\83H
\83\8b\83g
\82Í
\81u
\8fo
\97Í
\82µ
\82È
\82¢
\81v",
4950 (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
4951 any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
4952 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
4954 "Prompt, with default answer of \"Yes\"",
4956 "
\8am
\94F
\82·
\82é
\81C
\83f
\83t
\83H
\83\8b\83g
\82Í
\81u
\8fo
\97Í
\82·
\82é
\81v",
4957 (c == any.a_char) ? MENU_SELECTED : MENU_UNSELECTED);
4958 if (*disclosure_names[i] == 'v') {
4959 any.a_char = DISCLOSE_PROMPT_DEFAULT_SPECIAL; /* '?' */
4960 add_menu(tmpwin, NO_GLYPH, &any, 0, any.a_char, ATR_NONE,
4961 "Prompt, with default answer of \"Ask\" to request sort menu",
4962 (c == any.a_char) ? MENU_SELECTED
4965 end_menu(tmpwin, buf);
4966 n = select_menu(tmpwin, PICK_ONE, &disclosure_pick);
4968 flags.end_disclose[i] = disclosure_pick[0].item.a_char;
4969 if (n > 1 && flags.end_disclose[i] == c)
4970 flags.end_disclose[i] = disclosure_pick[1].item.a_char;
4971 free((genericptr_t) disclosure_pick);
4973 destroy_nhwindow(tmpwin);
4976 } else if (!strcmp("runmode", optname)) {
4977 const char *mode_name;
4978 menu_item *mode_pick = (menu_item *) 0;
4980 tmpwin = create_nhwindow(NHW_MENU);
4983 for (i = 0; i < SIZE(runmodes); i++) {
4984 mode_name = runmodes[i];
4986 add_menu(tmpwin, NO_GLYPH, &any, *mode_name, 0, ATR_NONE,
4987 mode_name, MENU_UNSELECTED);
4990 end_menu(tmpwin, "Select run/travel display mode:");
4992 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");
4993 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
4994 flags.runmode = mode_pick->item.a_int - 1;
4995 free((genericptr_t) mode_pick);
4997 destroy_nhwindow(tmpwin);
4998 } else if (!strcmp("whatis_coord", optname)) {
4999 menu_item *window_pick = (menu_item *) 0;
5001 char gp = iflags.getpos_coords;
5003 tmpwin = create_nhwindow(NHW_MENU);
5006 any.a_char = GPCOORDS_COMPASS;
5007 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMPASS,
5008 0, ATR_NONE, "compass ('east' or '3s' or '2n,4w')",
5009 (gp == GPCOORDS_COMPASS) ? MENU_SELECTED : MENU_UNSELECTED);
5010 any.a_char = GPCOORDS_COMFULL;
5011 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_COMFULL, 0, ATR_NONE,
5012 "full compass ('east' or '3south' or '2north,4west')",
5013 (gp == GPCOORDS_COMFULL) ? MENU_SELECTED : MENU_UNSELECTED);
5014 any.a_char = GPCOORDS_MAP;
5015 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_MAP,
5016 0, ATR_NONE, "map <x,y>",
5017 (gp == GPCOORDS_MAP) ? MENU_SELECTED : MENU_UNSELECTED);
5018 any.a_char = GPCOORDS_SCREEN;
5019 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_SCREEN,
5020 0, ATR_NONE, "screen [row,column]",
5021 (gp == GPCOORDS_SCREEN) ? MENU_SELECTED : MENU_UNSELECTED);
5022 any.a_char = GPCOORDS_NONE;
5023 add_menu(tmpwin, NO_GLYPH, &any, GPCOORDS_NONE,
5024 0, ATR_NONE, "none (no coordinates displayed)",
5025 (gp == GPCOORDS_NONE) ? MENU_SELECTED : MENU_UNSELECTED);
5027 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
5028 Sprintf(buf, "map: upper-left: <%d,%d>, lower-right: <%d,%d>%s",
5029 1, 0, COLNO - 1, ROWNO - 1,
5030 flags.verbose ? "; column 0 unused, off left edge" : "");
5031 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
5032 if (strcmp(windowprocs.name, "tty"))
5033 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
5034 "screen: row is offset to accommodate tty interface's use of top line",
5037 #define COL80ARG flags.verbose ? "; column 80 is not used" : ""
5041 Sprintf(buf, "screen: upper-left: [%02d,%02d], lower-right: [%d,%d]%s",
5042 0 + 2, 1, ROWNO - 1 + 2, COLNO - 1, COL80ARG);
5044 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
5045 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
5047 "Select coordinate display when auto-describing a map position:");
5048 if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) {
5049 iflags.getpos_coords = window_pick[0].item.a_char;
5050 /* PICK_ONE doesn't unselect preselected entry when
5051 selecting another one */
5052 if (pick_cnt > 1 && iflags.getpos_coords == gp)
5053 iflags.getpos_coords = window_pick[1].item.a_char;
5054 free((genericptr_t) window_pick);
5056 destroy_nhwindow(tmpwin);
5057 } else if (!strcmp("whatis_filter", optname)) {
5058 menu_item *window_pick = (menu_item *) 0;
5060 char gf = iflags.getloc_filter;
5062 tmpwin = create_nhwindow(NHW_MENU);
5065 any.a_char = (GFILTER_NONE + 1);
5066 add_menu(tmpwin, NO_GLYPH, &any, 'n',
5067 0, ATR_NONE, "no filtering",
5068 (gf == GFILTER_NONE) ? MENU_SELECTED : MENU_UNSELECTED);
5069 any.a_char = (GFILTER_VIEW + 1);
5070 add_menu(tmpwin, NO_GLYPH, &any, 'v',
5071 0, ATR_NONE, "in view only",
5072 (gf == GFILTER_VIEW) ? MENU_SELECTED : MENU_UNSELECTED);
5073 any.a_char = (GFILTER_AREA + 1);
5074 add_menu(tmpwin, NO_GLYPH, &any, 'a',
5075 0, ATR_NONE, "in same area",
5076 (gf == GFILTER_AREA) ? MENU_SELECTED : MENU_UNSELECTED);
5078 "Select location filtering when going for next/previous map position:");
5079 if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &window_pick)) > 0) {
5080 iflags.getloc_filter = (window_pick[0].item.a_char - 1);
5081 /* PICK_ONE doesn't unselect preselected entry when
5082 selecting another one */
5083 if (pick_cnt > 1 && iflags.getloc_filter == gf)
5084 iflags.getloc_filter = (window_pick[1].item.a_char - 1);
5085 free((genericptr_t) window_pick);
5087 destroy_nhwindow(tmpwin);
5088 } else if (!strcmp("msg_window", optname)) {
5090 /* by Christian W. Cooper */
5091 menu_item *window_pick = (menu_item *) 0;
5093 tmpwin = create_nhwindow(NHW_MENU);
5097 add_menu(tmpwin, NO_GLYPH, &any, 's', 0, ATR_NONE, "single",
5100 add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, ATR_NONE, "combination",
5103 add_menu(tmpwin, NO_GLYPH, &any, 'f', 0, ATR_NONE, "full",
5106 add_menu(tmpwin, NO_GLYPH, &any, 'r', 0, ATR_NONE, "reversed",
5109 end_menu(tmpwin, "Select message history display type:");
5111 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");
5112 if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
5113 iflags.prevmsg_window = window_pick->item.a_char;
5114 free((genericptr_t) window_pick);
5116 destroy_nhwindow(tmpwin);
5118 } else if (!strcmp("sortloot", optname)) {
5119 const char *sortl_name;
5120 menu_item *sortl_pick = (menu_item *) 0;
5122 tmpwin = create_nhwindow(NHW_MENU);
5125 for (i = 0; i < SIZE(sortltype); i++) {
5126 sortl_name = sortltype[i];
5127 any.a_char = *sortl_name;
5128 add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0, ATR_NONE,
5129 sortl_name, (flags.sortloot == *sortl_name)
5130 ? MENU_SELECTED : MENU_UNSELECTED);
5132 end_menu(tmpwin, "Select loot sorting type:");
5133 n = select_menu(tmpwin, PICK_ONE, &sortl_pick);
5135 char c = sortl_pick[0].item.a_char;
5137 if (n > 1 && c == flags.sortloot)
5138 c = sortl_pick[1].item.a_char;
5140 free((genericptr_t) sortl_pick);
5142 destroy_nhwindow(tmpwin);
5143 } else if (!strcmp("align_message", optname)
5144 || !strcmp("align_status", optname)) {
5145 menu_item *window_pick = (menu_item *) 0;
5147 boolean msg = (*(optname + 6) == 'm');
5149 tmpwin = create_nhwindow(NHW_MENU);
5152 any.a_int = ALIGN_TOP;
5153 add_menu(tmpwin, NO_GLYPH, &any, 't', 0, ATR_NONE, "top",
5155 any.a_int = ALIGN_BOTTOM;
5156 add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, ATR_NONE, "bottom",
5158 any.a_int = ALIGN_LEFT;
5159 add_menu(tmpwin, NO_GLYPH, &any, 'l', 0, ATR_NONE, "left",
5161 any.a_int = ALIGN_RIGHT;
5162 add_menu(tmpwin, NO_GLYPH, &any, 'r', 0, ATR_NONE, "right",
5165 Sprintf(abuf, "Select %s window placement relative to the map:",
5166 msg ? "message" : "status");
5168 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",
5169 msg ? "
\83\81\83b
\83Z
\81[
\83W" : "
\8fó
\91Ô");
5171 end_menu(tmpwin, abuf);
5172 if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
5174 iflags.wc_align_message = window_pick->item.a_int;
5176 iflags.wc_align_status = window_pick->item.a_int;
5177 free((genericptr_t) window_pick);
5179 destroy_nhwindow(tmpwin);
5180 } else if (!strcmp("number_pad", optname)) {
5181 static const char *npchoices[] = {
5183 " 0 (off)", " 1 (on)", " 2 (on, MSDOS compatible)",
5185 "0 (
\96³
\8cø)", "1 (
\97L
\8cø)", "2 (
\97L
\8cø
\81CMSDOS
\8cÝ
\8a·)",
5187 " 3 (on, phone-style digit layout)",
5189 " 3 (
\97L
\8cø
\81C
\93d
\98b
\8e®
\82Ì
\90\94\8e\9a\94z
\92u)",
5191 " 4 (on, phone-style layout, MSDOS compatible)",
5193 " 4 (
\97L
\8cø
\81C
\93d
\98b
\8e®
\82Ì
\94z
\92u
\81CMSDOS
\8cÝ
\8a·)",
5195 "-1 (off, 'z' to move upper-left, 'y' to zap wands)"
5197 "-1 (
\96³
\8cø
\81C'z'
\82Å
\8d¶
\8fã
\82É
\88Ú
\93®
\81C'y'
\82Å
\8fñ
\82ð
\90U
\82é)"
5199 menu_item *mode_pick = (menu_item *) 0;
5201 tmpwin = create_nhwindow(NHW_MENU);
5204 for (i = 0; i < SIZE(npchoices); i++) {
5206 add_menu(tmpwin, NO_GLYPH, &any, 'a' + i, 0, ATR_NONE,
5207 npchoices[i], MENU_UNSELECTED);
5210 end_menu(tmpwin, "Select number_pad mode:");
5212 end_menu(tmpwin, "number_pad
\83\82\81[
\83h
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F");
5213 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
5214 switch (mode_pick->item.a_int - 1) {
5216 iflags.num_pad = FALSE;
5217 iflags.num_pad_mode = 0;
5220 iflags.num_pad = TRUE;
5221 iflags.num_pad_mode = 0;
5224 iflags.num_pad = TRUE;
5225 iflags.num_pad_mode = 1;
5228 iflags.num_pad = TRUE;
5229 iflags.num_pad_mode = 2;
5232 iflags.num_pad = TRUE;
5233 iflags.num_pad_mode = 3;
5235 /* last menu choice: number_pad == -1 */
5237 iflags.num_pad = FALSE;
5238 iflags.num_pad_mode = 1;
5241 reset_commands(FALSE);
5242 number_pad(iflags.num_pad ? 1 : 0);
5243 free((genericptr_t) mode_pick);
5245 destroy_nhwindow(tmpwin);
5246 } else if (!strcmp("menu_headings", optname)) {
5248 int mhattr = query_attr("How to highlight menu headings:");
5250 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");
5253 iflags.menu_headings = mhattr;
5254 } else if (!strcmp("msgtype", optname)) {
5255 int opt_idx, nmt, mttyp;
5256 char mtbuf[BUFSZ] = DUMMY;
5259 nmt = msgtype_count();
5261 opt_idx = handle_add_list_remove("message type", nmt);
5263 opt_idx = handle_add_list_remove("
\83\81\83b
\83Z
\81[
\83W
\8c^", nmt);
5264 if (opt_idx == 3) { /* done */
5266 } else if (opt_idx == 0) { /* add new */
5268 getlin("What new message pattern?", mtbuf);
5270 getlin("
\90V
\82µ
\82¢
\83\81\83b
\83Z
\81[
\83W
\83p
\83^
\81[
\83\93\81F", mtbuf);
5271 if (*mtbuf == '\033')
5274 && test_regex_pattern(mtbuf, (const char *)0)
5275 && (mttyp = query_msgtype()) != -1
5276 && !msgtype_add(mttyp, mtbuf)) {
5278 pline("Error adding the message type.");
5280 pline("
\83\81\83b
\83Z
\81[
\83W
\8c^
\92Ç
\89Á
\83G
\83\89\81[
\81D");
5283 goto msgtypes_again;
5284 } else { /* list (1) or remove (2) */
5285 int pick_idx, pick_cnt;
5289 menu_item *pick_list = (menu_item *) 0;
5290 struct plinemsg_type *tmp = plinemsg_types;
5292 tmpwin = create_nhwindow(NHW_MENU);
5297 mtype = msgtype2name(tmp->msgtype);
5298 any.a_int = ++mt_idx;
5299 Sprintf(mtbuf, "%-5s \"", mtype);
5300 ln = sizeof mtbuf - strlen(mtbuf) - sizeof "\"";
5301 if (strlen(tmp->pattern) > ln)
5302 Strcat(strncat(mtbuf, tmp->pattern, ln - 3), "...\"");
5304 Strcat(mtbuf, "\"");
5305 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mtbuf,
5310 Sprintf(mtbuf, "%s message types",
5311 (opt_idx == 1) ? "List of" : "Remove which");
5313 Strcpy(mtbuf, (opt_idx == 1) ?
5314 "
\83\81\83b
\83Z
\81[
\83W
\8c^
\88ê
\97\97" : "
\8dí
\8f\9c\82·
\82é
\83\81\83b
\83Z
\81[
\83W
\8c^");
5316 end_menu(tmpwin, mtbuf);
5317 pick_cnt = select_menu(tmpwin,
5318 (opt_idx == 1) ? PICK_NONE : PICK_ANY,
5321 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
5322 free_one_msgtype(pick_list[pick_idx].item.a_int - 1
5324 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
5326 destroy_nhwindow(tmpwin);
5328 goto msgtypes_again;
5330 } else if (!strcmp("menucolors", optname)) {
5331 int opt_idx, nmc, mcclr, mcattr;
5332 char mcbuf[BUFSZ] = DUMMY;
5335 nmc = count_menucolors();
5337 opt_idx = handle_add_list_remove("menucolor", nmc);
5339 opt_idx = handle_add_list_remove("
\83\81\83j
\83\85\81[
\90F", nmc);
5340 if (opt_idx == 3) { /* done */
5342 } else if (opt_idx == 0) { /* add new */
5344 getlin("What new menucolor pattern?", mcbuf);
5346 getlin("
\90V
\82µ
\82¢
\83\81\83j
\83\85\81[
\90F
\83p
\83^
\81[
\83\93\81F", mcbuf);
5347 if (*mcbuf == '\033')
5350 && test_regex_pattern(mcbuf, (const char *)0)
5351 && (mcclr = query_color((char *) 0)) != -1
5352 && (mcattr = query_attr((char *) 0)) != -1
5353 && !add_menu_coloring_parsed(mcbuf, mcclr, mcattr)) {
5355 pline("Error adding the menu color.");
5357 pline("
\83\81\83j
\83\85\81[
\90F
\92Ç
\89Á
\83G
\83\89\81[
\81D");
5360 goto menucolors_again;
5361 } else { /* list (1) or remove (2) */
5362 int pick_idx, pick_cnt;
5365 const char *sattr, *sclr;
5366 menu_item *pick_list = (menu_item *) 0;
5367 struct menucoloring *tmp = menu_colorings;
5369 tmpwin = create_nhwindow(NHW_MENU);
5374 sattr = attr2attrname(tmp->attr);
5375 sclr = clr2colorname(tmp->color);
5376 any.a_int = ++mc_idx;
5377 /* construct suffix */
5378 Sprintf(buf, "\"\"=%s%s%s", sclr,
5379 (tmp->attr != ATR_NONE) ? " & " : "",
5380 (tmp->attr != ATR_NONE) ? sattr : "");
5381 /* now main string */
5382 ln = sizeof buf - strlen(buf) - 1; /* length available */
5383 Strcpy(mcbuf, "\"");
5384 if (strlen(tmp->origstr) > ln)
5385 Strcat(strncat(mcbuf, tmp->origstr, ln - 3), "...");
5387 Strcat(mcbuf, tmp->origstr);
5388 /* combine main string and suffix */
5389 Strcat(mcbuf, &buf[1]); /* skip buf[]'s initial quote */
5390 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, mcbuf,
5395 Sprintf(mcbuf, "%s menu colors",
5396 (opt_idx == 1) ? "List of" : "Remove which");
5398 Strcpy(mcbuf, (opt_idx == 1) ?
5399 "
\83\81\83j
\83\85\81[
\90F
\88ê
\97\97" : "
\8dí
\8f\9c\82·
\82é
\83\81\83j
\83\85\81[
\90F");
5401 end_menu(tmpwin, mcbuf);
5402 pick_cnt = select_menu(tmpwin,
5403 (opt_idx == 1) ? PICK_NONE : PICK_ANY,
5406 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
5407 free_one_menu_coloring(pick_list[pick_idx].item.a_int - 1
5409 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
5411 destroy_nhwindow(tmpwin);
5413 goto menucolors_again;
5415 } else if (!strcmp("autopickup_exception", optname)) {
5416 int opt_idx, pass, totalapes = 0, numapes[2] = { 0, 0 };
5417 char apebuf[1 + BUFSZ] = DUMMY; /* so &apebuf[1] is BUFSZ long for getlin() */
5418 struct autopickup_exception *ape;
5421 totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
5423 opt_idx = handle_add_list_remove("autopickup exception", totalapes);
5425 opt_idx = handle_add_list_remove("
\8e©
\93®
\8fE
\82¢
\97á
\8aO", totalapes);
5426 if (opt_idx == 3) { /* done */
5428 } else if (opt_idx == 0) { /* add new */
5430 getlin("What new autopickup exception pattern?", &apebuf[1]);
5432 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]);
5433 mungspaces(&apebuf[1]); /* regularize whitespace */
5434 if (apebuf[1] == '\033')
5438 /* guarantee room for \" prefix and \"\0 suffix;
5439 -2 is good enough for apebuf[] but -3 makes
5440 sure the whole thing fits within normal BUFSZ */
5441 apebuf[sizeof apebuf - 3] = '\0';
5442 Strcat(apebuf, "\"");
5443 add_autopickup_exception(apebuf);
5446 } else { /* list (1) or remove (2) */
5447 int pick_idx, pick_cnt;
5448 menu_item *pick_list = (menu_item *) 0;
5450 tmpwin = create_nhwindow(NHW_MENU);
5452 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
5453 if (numapes[pass] == 0)
5455 ape = iflags.autopickup_exceptions[pass];
5457 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
5459 (pass == 0) ? "Never pickup" : "Always pickup",
5461 (pass == 0) ? "
\8fí
\82É
\8fE
\82í
\82È
\82¢" : "
\8fí
\82É
\8fE
\82¤",
5463 for (i = 0; i < numapes[pass] && ape; i++) {
5464 any.a_void = (opt_idx == 1) ? 0 : ape;
5465 /* length of pattern plus quotes is less than BUFSZ */
5466 Sprintf(apebuf, "\"%s\"", ape->pattern);
5467 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, apebuf,
5473 Sprintf(apebuf, "%s autopickup exceptions",
5474 (opt_idx == 1) ? "List of" : "Remove which");
5476 Sprintf(apebuf, "%s
\8e©
\93®
\8fE
\82¢
\97á
\8aO%s",
5477 (opt_idx == 1) ? "" : "
\82Ç
\82Ì",
5478 (opt_idx == 1) ? "
\82Ì
\88ê
\97\97" : "
\82ð
\8dí
\8f\9c\82µ
\82Ü
\82·
\82©
\81H");
5480 end_menu(tmpwin, apebuf);
5481 pick_cnt = select_menu(tmpwin,
5482 (opt_idx == 1) ? PICK_NONE : PICK_ANY,
5485 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
5486 remove_autopickup_exception(
5487 (struct autopickup_exception *)
5488 pick_list[pick_idx].item.a_void);
5489 free((genericptr_t) pick_list), pick_list = (menu_item *) 0;
5491 destroy_nhwindow(tmpwin);
5495 } else if (!strcmp("symset", optname)
5496 || !strcmp("roguesymset", optname)) {
5497 menu_item *symset_pick = (menu_item *) 0;
5498 boolean primaryflag = (*optname == 's'),
5499 rogueflag = (*optname == 'r'),
5500 ready_to_switch = FALSE,
5501 nothing_to_do = FALSE;
5502 char *symset_name, fmtstr[20];
5503 struct symsetentry *sl;
5504 int res, which_set, setcount = 0, chosen = -2;
5506 which_set = rogueflag ? ROGUESET : PRIMARY;
5508 /* clear symset[].name as a flag to read_sym_file() to build list */
5509 symset_name = symset[which_set].name;
5510 symset[which_set].name = (char *) 0;
5511 symset_list = (struct symsetentry *) 0;
5513 res = read_sym_file(which_set);
5514 if (res && symset_list) {
5515 char symsetchoice[BUFSZ];
5516 int let = 'a', biggest = 0, thissize = 0;
5520 /* check restrictions */
5521 if ((!rogueflag && sl->rogue)
5522 || (!primaryflag && sl->primary)) {
5527 /* find biggest name */
5529 thissize = strlen(sl->name);
5530 if (thissize > biggest)
5536 pline("There are no appropriate %ssymbol sets available.",
5537 (rogueflag) ? "rogue level "
5538 : (primaryflag) ? "primary " : "");
5540 pline("
\93K
\90Ø
\82È%s
\83V
\83\93\83{
\83\8b\90Ý
\92è
\82ª
\82 \82è
\82Ü
\82¹
\82ñ
\81D",
5541 (rogueflag) ? "rogue
\83\8c\83x
\83\8b"
5542 : (primaryflag) ? "
\97D
\90æ" : "");
5547 Sprintf(fmtstr, "%%-%ds %%s", biggest + 5);
5548 tmpwin = create_nhwindow(NHW_MENU);
5552 add_menu(tmpwin, NO_GLYPH, &any, let++, 0, ATR_NONE,
5553 "Default Symbols", MENU_UNSELECTED);
5557 /* check restrictions */
5558 if ((!rogueflag && sl->rogue)
5559 || (!primaryflag && sl->primary)) {
5564 any.a_int = sl->idx + 2;
5565 Sprintf(symsetchoice, fmtstr, sl->name,
5566 sl->desc ? sl->desc : "");
5567 add_menu(tmpwin, NO_GLYPH, &any, let, 0, ATR_NONE,
5568 symsetchoice, MENU_UNSELECTED);
5577 Sprintf(buf, "Select %ssymbol set:",
5578 rogueflag ? "rogue level " : "");
5580 Sprintf(buf, "%s
\83V
\83\93\83{
\83\8b\90Ý
\92è
\82ð
\91I
\91ð
\82µ
\82Ä
\82
\82¾
\82³
\82¢
\81F",
5581 rogueflag ? "rogue
\83\8c\83x
\83\8b" : "");
5583 end_menu(tmpwin, buf);
5584 if (select_menu(tmpwin, PICK_ONE, &symset_pick) > 0) {
5585 chosen = symset_pick->item.a_int - 2;
5586 free((genericptr_t) symset_pick);
5588 destroy_nhwindow(tmpwin);
5591 /* chose an actual symset name from file */
5594 if (sl->idx == chosen) {
5596 free((genericptr_t) symset_name);
5597 symset_name = (char *) 0;
5599 /* free the now stale attributes */
5600 clear_symsetentry(which_set, TRUE);
5602 /* transfer only the name of the symbol set */
5603 symset[which_set].name = dupstr(sl->name);
5604 ready_to_switch = TRUE;
5609 } else if (chosen == -1) {
5610 /* explicit selection of defaults */
5611 /* free the now stale symset attributes */
5613 free((genericptr_t) symset_name);
5614 symset_name = (char *) 0;
5616 clear_symsetentry(which_set, TRUE);
5618 nothing_to_do = TRUE;
5620 /* The symbols file could not be accessed */
5622 pline("Unable to access \"%s\" file.", SYMBOLS);
5624 pline("\"%s\"
\83t
\83@
\83C
\83\8b\82É
\83A
\83N
\83Z
\83X
\82Å
\82«
\82Ü
\82¹
\82ñ
\81D", SYMBOLS);
5626 } else if (!symset_list) {
5627 /* The symbols file was empty */
5629 pline("There were no symbol sets found in \"%s\".", SYMBOLS);
5631 pline("\"%s\"
\82É
\83V
\83\93\83{
\83\8b\90Ý
\92è
\82ª
\82 \82è
\82Ü
\82¹
\82ñ
\81D", SYMBOLS);
5636 while (symset_list) {
5639 free((genericptr_t) sl->name);
5640 sl->name = (char *) 0;
5643 free((genericptr_t) sl->desc);
5644 sl->desc = (char *) 0;
5646 symset_list = sl->next;
5647 free((genericptr_t) sl);
5653 if (!symset[which_set].name && symset_name)
5654 symset[which_set].name = symset_name; /* not dupstr() here */
5656 /* Set default symbols and clear the handling value */
5662 if (symset[which_set].name) {
5663 if (read_sym_file(which_set)) {
5664 ready_to_switch = TRUE;
5666 clear_symsetentry(which_set, TRUE);
5671 if (ready_to_switch)
5672 switch_symbols(TRUE);
5674 if (Is_rogue_level(&u.uz)) {
5676 assign_graphics(ROGUESET);
5677 } else if (!rogueflag)
5678 assign_graphics(PRIMARY);
5679 preference_update("symset");
5684 /* didn't match any of the special options */
5690 #define rolestring(val, array, field) \
5691 ((val >= 0) ? array[val].field : (val == ROLE_RANDOM) ? randomrole : none)
5693 /* This is ugly. We have all the option names in the compopt[] array,
5694 but we need to look at each option individually to get the value. */
5695 STATIC_OVL const char *
5696 get_compopt_value(optname, buf)
5697 const char *optname;
5700 char ocl[MAXOCLASSES + 1];
5702 static const char none[] = "(none)", randomrole[] = "random",
5703 to_be_done[] = "(to be done)", defopt[] = "default",
5706 static const char none[] = "(
\82È
\82µ)", randomrole[] = "
\83\89\83\93\83_
\83\80",
5707 to_be_done[] = "(
\96¢
\90Ý
\92è)", defopt[] = "
\83f
\83t
\83H
\83\8b\83g",
5713 if (!strcmp(optname, "align_message"))
5716 iflags.wc_align_message == ALIGN_TOP
5718 : iflags.wc_align_message == ALIGN_LEFT
5720 : iflags.wc_align_message == ALIGN_BOTTOM
5722 : iflags.wc_align_message == ALIGN_RIGHT
5727 iflags.wc_align_message == ALIGN_TOP
5729 : iflags.wc_align_message == ALIGN_LEFT
5731 : iflags.wc_align_message == ALIGN_BOTTOM
5733 : iflags.wc_align_message == ALIGN_RIGHT
5734 ? "
\89E
\91¤" : defopt);
5736 else if (!strcmp(optname, "align_status"))
5739 iflags.wc_align_status == ALIGN_TOP
5741 : iflags.wc_align_status == ALIGN_LEFT
5743 : iflags.wc_align_status == ALIGN_BOTTOM
5745 : iflags.wc_align_status == ALIGN_RIGHT
5750 iflags.wc_align_status == ALIGN_TOP
5752 : iflags.wc_align_status == ALIGN_LEFT
5754 : iflags.wc_align_status == ALIGN_BOTTOM
5756 : iflags.wc_align_status == ALIGN_RIGHT
5760 else if (!strcmp(optname, "align"))
5762 Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj));
5764 Sprintf(buf, "%s", rolestring(flags.initalign, aligns, noun));
5767 else if (!strcmp(optname, "altkeyhandler"))
5770 iflags.altkeyhandler[0] ? iflags.altkeyhandler : "default");
5772 iflags.altkeyhandler[0] ? iflags.altkeyhandler : defopt);
5774 #ifdef BACKWARD_COMPAT
5775 else if (!strcmp(optname, "boulder"))
5779 : showsyms[(int) objects[BOULDER].oc_class + SYM_OFF_O]);
5781 else if (!strcmp(optname, "catname"))
5782 Sprintf(buf, "%s", catname[0] ? catname : none);
5783 else if (!strcmp(optname, "disclose"))
5784 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
5786 (void) strkitten(buf, ' ');
5787 (void) strkitten(buf, flags.end_disclose[i]);
5788 (void) strkitten(buf, disclosure_options[i]);
5790 else if (!strcmp(optname, "dogname"))
5791 Sprintf(buf, "%s", dogname[0] ? dogname : none);
5792 else if (!strcmp(optname, "dungeon"))
5793 Sprintf(buf, "%s", to_be_done);
5794 else if (!strcmp(optname, "effects"))
5795 Sprintf(buf, "%s", to_be_done);
5796 else if (!strcmp(optname, "font_map"))
5797 Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt);
5798 else if (!strcmp(optname, "font_message"))
5800 iflags.wc_font_message ? iflags.wc_font_message : defopt);
5801 else if (!strcmp(optname, "font_status"))
5803 iflags.wc_font_status ? iflags.wc_font_status : defopt);
5804 else if (!strcmp(optname, "font_menu"))
5806 iflags.wc_font_menu ? iflags.wc_font_menu : defopt);
5807 else if (!strcmp(optname, "font_text"))
5809 iflags.wc_font_text ? iflags.wc_font_text : defopt);
5810 else if (!strcmp(optname, "font_size_map")) {
5811 if (iflags.wc_fontsiz_map)
5812 Sprintf(buf, "%d", iflags.wc_fontsiz_map);
5814 Strcpy(buf, defopt);
5815 } else if (!strcmp(optname, "font_size_message")) {
5816 if (iflags.wc_fontsiz_message)
5817 Sprintf(buf, "%d", iflags.wc_fontsiz_message);
5819 Strcpy(buf, defopt);
5820 } else if (!strcmp(optname, "font_size_status")) {
5821 if (iflags.wc_fontsiz_status)
5822 Sprintf(buf, "%d", iflags.wc_fontsiz_status);
5824 Strcpy(buf, defopt);
5825 } else if (!strcmp(optname, "font_size_menu")) {
5826 if (iflags.wc_fontsiz_menu)
5827 Sprintf(buf, "%d", iflags.wc_fontsiz_menu);
5829 Strcpy(buf, defopt);
5830 } else if (!strcmp(optname, "font_size_text")) {
5831 if (iflags.wc_fontsiz_text)
5832 Sprintf(buf, "%d", iflags.wc_fontsiz_text);
5834 Strcpy(buf, defopt);
5835 } else if (!strcmp(optname, "fruit"))
5836 Sprintf(buf, "%s", pl_fruit);
5837 else if (!strcmp(optname, "gender"))
5838 Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
5839 else if (!strcmp(optname, "horsename"))
5840 Sprintf(buf, "%s", horsename[0] ? horsename : none);
5841 else if (!strcmp(optname, "map_mode")) {
5842 i = iflags.wc_map_mode;
5844 (i == MAP_MODE_TILES) ? "tiles"
5845 : (i == MAP_MODE_ASCII4x6) ? "ascii4x6"
5846 : (i == MAP_MODE_ASCII6x8) ? "ascii6x8"
5847 : (i == MAP_MODE_ASCII8x8) ? "ascii8x8"
5848 : (i == MAP_MODE_ASCII16x8) ? "ascii16x8"
5849 : (i == MAP_MODE_ASCII7x12) ? "ascii7x12"
5850 : (i == MAP_MODE_ASCII8x12) ? "ascii8x12"
5851 : (i == MAP_MODE_ASCII16x12) ? "ascii16x12"
5852 : (i == MAP_MODE_ASCII12x16) ? "ascii12x16"
5853 : (i == MAP_MODE_ASCII10x18) ? "ascii10x18"
5854 : (i == MAP_MODE_ASCII_FIT_TO_SCREEN)
5857 } else if (!strcmp(optname, "menustyle"))
5858 Sprintf(buf, "%s", menutype[(int) flags.menu_style]);
5859 else if (!strcmp(optname, "menu_deselect_all"))
5860 Sprintf(buf, "%s", to_be_done);
5861 else if (!strcmp(optname, "menu_deselect_page"))
5862 Sprintf(buf, "%s", to_be_done);
5863 else if (!strcmp(optname, "menu_first_page"))
5864 Sprintf(buf, "%s", to_be_done);
5865 else if (!strcmp(optname, "menu_invert_all"))
5866 Sprintf(buf, "%s", to_be_done);
5867 else if (!strcmp(optname, "menu_headings"))
5868 Sprintf(buf, "%s", attr2attrname(iflags.menu_headings));
5869 else if (!strcmp(optname, "menu_invert_page"))
5870 Sprintf(buf, "%s", to_be_done);
5871 else if (!strcmp(optname, "menu_last_page"))
5872 Sprintf(buf, "%s", to_be_done);
5873 else if (!strcmp(optname, "menu_next_page"))
5874 Sprintf(buf, "%s", to_be_done);
5875 else if (!strcmp(optname, "menu_previous_page"))
5876 Sprintf(buf, "%s", to_be_done);
5877 else if (!strcmp(optname, "menu_search"))
5878 Sprintf(buf, "%s", to_be_done);
5879 else if (!strcmp(optname, "menu_select_all"))
5880 Sprintf(buf, "%s", to_be_done);
5881 else if (!strcmp(optname, "menu_select_page"))
5882 Sprintf(buf, "%s", to_be_done);
5883 else if (!strcmp(optname, "monsters")) {
5884 Sprintf(buf, "%s", to_be_done);
5885 } else if (!strcmp(optname, "msghistory")) {
5886 Sprintf(buf, "%u", iflags.msg_history);
5888 } else if (!strcmp(optname, "msg_window")) {
5889 Sprintf(buf, "%s", (iflags.prevmsg_window == 's') ? "single"
5890 : (iflags.prevmsg_window == 'c') ? "combination"
5891 : (iflags.prevmsg_window == 'f') ? "full"
5894 } else if (!strcmp(optname, "name")) {
5895 Sprintf(buf, "%s", plname);
5896 } else if (!strcmp(optname, "number_pad")) {
5897 static const char *numpadmodes[] = {
5899 "0=off", "1=on", "2=on, MSDOS compatible",
5901 "0=
\96³
\8cø", "1=
\97L
\8cø", "2=
\97L
\8cø
\81CDOS
\8cÝ
\8a·",
5903 "3=on, phone-style layout",
5905 "3=
\97L
\8cø
\81C
\93d
\98b
\8e®
\82Ì
\90\94\8e\9a\94z
\92u",
5907 "4=on, phone layout, MSDOS compatible",
5909 "4=
\97L
\8cø
\81C
\93d
\98b
\8e®
\82Ì
\94z
\92u
\81CMSDOS
\8cÝ
\8a·",
5911 "-1=off, y & z swapped", /*[5]*/
5913 "-1=
\96³
\8cø
\81Cy
\82Æz
\82ð
\93ü
\82ê
\91Ö
\82¦", /*[5]*/
5916 int indx = Cmd.num_pad
5917 ? (Cmd.phone_layout ? (Cmd.pcHack_compat ? 4 : 3)
5918 : (Cmd.pcHack_compat ? 2 : 1))
5919 : Cmd.swap_yz ? 5 : 0;
5921 Strcpy(buf, numpadmodes[indx]);
5922 } else if (!strcmp(optname, "objects")) {
5923 Sprintf(buf, "%s", to_be_done);
5924 } else if (!strcmp(optname, "packorder")) {
5925 oc_to_str(flags.inv_order, ocl);
5926 Sprintf(buf, "%s", ocl);
5928 } else if (!strcmp(optname, "palette")) {
5929 Sprintf(buf, "%s", get_color_string());
5931 } else if (!strcmp(optname, "paranoid_confirmation")) {
5932 char tmpbuf[QBUFSZ];
5935 for (i = 0; paranoia[i].flagmask != 0; ++i)
5936 if (flags.paranoia_bits & paranoia[i].flagmask)
5937 Sprintf(eos(tmpbuf), " %s", paranoia[i].argname);
5938 Strcpy(buf, tmpbuf[0] ? &tmpbuf[1] : "none");
5939 } else if (!strcmp(optname, "pettype")) {
5941 Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat"
5942 : (preferred_pet == 'd') ? "dog"
5943 : (preferred_pet == 'h') ? "horse"
5944 : (preferred_pet == 'n') ? "none"
5947 Sprintf(buf, "%s", (preferred_pet == 'c') ? "
\94L"
5948 : (preferred_pet == 'd') ? "
\8c¢"
5949 : (preferred_pet == 'h') ? "
\94n"
5950 : (preferred_pet == 'n') ? "
\82È
\82µ"
5951 : "
\83\89\83\93\83_
\83\80");
5953 } else if (!strcmp(optname, "pickup_burden")) {
5954 Sprintf(buf, "%s", burdentype[flags.pickup_burden]);
5955 } else if (!strcmp(optname, "pickup_types")) {
5956 oc_to_str(flags.pickup_types, ocl);
5957 Sprintf(buf, "%s", ocl[0] ? ocl : "all");
5958 } else if (!strcmp(optname, "pile_limit")) {
5959 Sprintf(buf, "%d", flags.pile_limit);
5960 } else if (!strcmp(optname, "playmode")) {
5961 Strcpy(buf, wizard ? "debug" : discover ? "explore" : "normal");
5962 } else if (!strcmp(optname, "race")) {
5963 Sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
5964 } else if (!strcmp(optname, "roguesymset")) {
5966 symset[ROGUESET].name ? symset[ROGUESET].name : "default");
5967 if (currentgraphics == ROGUESET && symset[ROGUESET].name)
5968 Strcat(buf, ", active");
5969 } else if (!strcmp(optname, "role")) {
5970 Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
5971 } else if (!strcmp(optname, "runmode")) {
5972 Sprintf(buf, "%s", runmodes[flags.runmode]);
5973 } else if (!strcmp(optname, "whatis_coord")) {
5975 (iflags.getpos_coords == GPCOORDS_MAP) ? "map"
5976 : (iflags.getpos_coords == GPCOORDS_COMPASS) ? "compass"
5977 : (iflags.getpos_coords == GPCOORDS_COMFULL) ? "full compass"
5978 : (iflags.getpos_coords == GPCOORDS_SCREEN) ? "screen"
5980 } else if (!strcmp(optname, "whatis_filter")) {
5982 (iflags.getloc_filter == GFILTER_VIEW) ? "view"
5983 : (iflags.getloc_filter == GFILTER_AREA) ? "area"
5985 } else if (!strcmp(optname, "scores")) {
5986 Sprintf(buf, "%d top/%d around%s", flags.end_top, flags.end_around,
5987 flags.end_own ? "/own" : "");
5988 } else if (!strcmp(optname, "scroll_amount")) {
5989 if (iflags.wc_scroll_amount)
5990 Sprintf(buf, "%d", iflags.wc_scroll_amount);
5992 Strcpy(buf, defopt);
5993 } else if (!strcmp(optname, "scroll_margin")) {
5994 if (iflags.wc_scroll_margin)
5995 Sprintf(buf, "%d", iflags.wc_scroll_margin);
5997 Strcpy(buf, defopt);
5998 } else if (!strcmp(optname, "sortloot")) {
5999 for (i = 0; i < SIZE(sortltype); i++)
6000 if (flags.sortloot == sortltype[i][0]) {
6001 Strcpy(buf, sortltype[i]);
6004 } else if (!strcmp(optname, "player_selection")) {
6006 Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
6008 Sprintf(buf, "%s
\93ü
\97Í", iflags.wc_player_selection ? "
\83v
\83\8d\83\93\83v
\83g" : "
\83_
\83C
\83A
\83\8d\83O");
6011 } else if (!strcmp(optname, "soundcard")) {
6012 Sprintf(buf, "%s", to_be_done);
6014 #ifdef STATUS_HILITES
6015 } else if (!strcmp("statushilites", optname)) {
6016 if (!iflags.hilite_delta)
6017 Strcpy(buf, "0 (off: don't highlight status fields)");
6019 Sprintf(buf, "%ld (on: highlight status for %ld turns)",
6020 iflags.hilite_delta, iflags.hilite_delta);
6022 } else if (!strcmp(optname, "suppress_alert")) {
6023 if (flags.suppress_alert == 0L)
6026 Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
6027 FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
6028 } else if (!strcmp(optname, "symset")) {
6030 symset[PRIMARY].name ? symset[PRIMARY].name : "default");
6031 if (currentgraphics == PRIMARY && symset[PRIMARY].name)
6032 Strcat(buf, ", active");
6033 } else if (!strcmp(optname, "tile_file")) {
6035 iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
6036 } else if (!strcmp(optname, "tile_height")) {
6037 if (iflags.wc_tile_height)
6038 Sprintf(buf, "%d", iflags.wc_tile_height);
6040 Strcpy(buf, defopt);
6041 } else if (!strcmp(optname, "tile_width")) {
6042 if (iflags.wc_tile_width)
6043 Sprintf(buf, "%d", iflags.wc_tile_width);
6045 Strcpy(buf, defopt);
6046 } else if (!strcmp(optname, "traps")) {
6047 Sprintf(buf, "%s", to_be_done);
6048 } else if (!strcmp(optname, "vary_msgcount")) {
6049 if (iflags.wc_vary_msgcount)
6050 Sprintf(buf, "%d", iflags.wc_vary_msgcount);
6052 Strcpy(buf, defopt);
6054 } else if (!strcmp(optname, "video")) {
6055 Sprintf(buf, "%s", to_be_done);
6058 } else if (!strcmp(optname, "videoshades")) {
6059 Sprintf(buf, "%s-%s-%s", shade[0], shade[1], shade[2]);
6060 } else if (!strcmp(optname, "videocolors")) {
6061 Sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
6062 ttycolors[CLR_RED], ttycolors[CLR_GREEN],
6063 ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
6064 ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN],
6065 ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
6066 ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
6067 ttycolors[CLR_BRIGHT_MAGENTA], ttycolors[CLR_BRIGHT_CYAN]);
6068 #endif /* VIDEOSHADES */
6069 } else if (!strcmp(optname, "windowtype")) {
6070 Sprintf(buf, "%s", windowprocs.name);
6071 } else if (!strcmp(optname, "windowcolors")) {
6073 buf, "%s/%s %s/%s %s/%s %s/%s",
6074 iflags.wc_foregrnd_menu ? iflags.wc_foregrnd_menu : defbrief,
6075 iflags.wc_backgrnd_menu ? iflags.wc_backgrnd_menu : defbrief,
6076 iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message
6078 iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message
6080 iflags.wc_foregrnd_status ? iflags.wc_foregrnd_status : defbrief,
6081 iflags.wc_backgrnd_status ? iflags.wc_backgrnd_status : defbrief,
6082 iflags.wc_foregrnd_text ? iflags.wc_foregrnd_text : defbrief,
6083 iflags.wc_backgrnd_text ? iflags.wc_backgrnd_text : defbrief);
6084 #ifdef PREFIXES_IN_USE
6086 for (i = 0; i < PREFIX_COUNT; ++i)
6087 if (!strcmp(optname, fqn_prefix_names[i]) && fqn_prefix[i])
6088 Sprintf(buf, "%s", fqn_prefix[i]);
6104 char buf[BUFSZ], ocl[MAXOCLASSES + 1];
6106 flags.pickup = !flags.pickup;
6108 oc_to_str(flags.pickup_types, ocl);
6110 Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all",
6111 (iflags.autopickup_exceptions[AP_LEAVE]
6112 || iflags.autopickup_exceptions[AP_GRAB])
6113 ? ((count_ape_maps((int *) 0, (int *) 0) == 1)
6114 ? ", with one exception"
6115 : ", with some exceptions")
6118 Sprintf(buf, "%s
\83A
\83C
\83e
\83\80\82É
\82Â
\82¢
\82Ä
\83I
\83\93%s", ocl[0] ? ocl : "
\91S
\82Ä
\82Ì",
6119 (iflags.autopickup_exceptions[AP_LEAVE]
6120 || iflags.autopickup_exceptions[AP_GRAB])
6121 ? "
\81C
\97á
\8aO
\82 \82è"
6128 Strcpy(buf, "
\83I
\83t");
6131 pline("Autopickup: %s.", buf);
6133 pline("
\8e©
\93®
\8fE
\82¢
\81F%s
\81D", buf);
6138 add_autopickup_exception(mapping)
6139 const char *mapping;
6142 APE_regex_error[] = "regex error in AUTOPICKUP_EXCEPTION",
6143 APE_syntax_error[] = "syntax error in AUTOPICKUP_EXCEPTION";
6145 struct autopickup_exception *ape, **apehead;
6146 char text[256], end;
6148 boolean grab = FALSE;
6150 /* scan length limit used to be 255, but smaller size allows the
6151 quoted value to fit within BUFSZ, simplifying formatting elsewhere;
6152 this used to ignore the possibility of trailing junk but now checks
6153 for it, accepting whitespace but rejecting anything else unless it
6154 starts with '#" for a comment */
6156 if ((n = sscanf(mapping, "\"<%253[^\"]\" %c", text, &end)) == 1
6157 || (n == 2 && end == '#')) {
6159 } else if ((n = sscanf(mapping, "\">%253[^\"]\" %c", text, &end)) == 1
6160 || (n = sscanf(mapping, "\"%253[^\"]\" %c", text, &end)) == 1
6161 || (n == 2 && end == '#')) {
6164 config_error_add("%s", APE_syntax_error);
6168 ape = (struct autopickup_exception *) alloc(sizeof *ape);
6169 ape->regex = regex_init();
6170 if (!regex_compile(text, ape->regex)) {
6171 config_error_add("%s: %s", APE_regex_error,
6172 regex_error_desc(ape->regex));
6173 regex_free(ape->regex);
6174 free((genericptr_t) ape);
6177 apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB]
6178 : &iflags.autopickup_exceptions[AP_LEAVE];
6180 ape->pattern = dupstr(text);
6182 ape->next = *apehead;
6188 remove_autopickup_exception(whichape)
6189 struct autopickup_exception *whichape;
6191 struct autopickup_exception *ape, *prev = 0;
6192 int chain = whichape->grab ? AP_GRAB : AP_LEAVE;
6194 for (ape = iflags.autopickup_exceptions[chain]; ape;) {
6195 if (ape == whichape) {
6196 struct autopickup_exception *freeape = ape;
6202 iflags.autopickup_exceptions[chain] = ape;
6203 regex_free(freeape->regex);
6204 free((genericptr_t) freeape->pattern);
6205 free((genericptr_t) freeape);
6214 count_ape_maps(leave, grab)
6217 struct autopickup_exception *ape;
6218 int pass, totalapes, numapes[2];
6220 numapes[0] = numapes[1] = 0;
6221 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
6222 ape = iflags.autopickup_exceptions[pass];
6228 totalapes = numapes[AP_LEAVE] + numapes[AP_GRAB];
6230 *leave = numapes[AP_LEAVE];
6232 *grab = numapes[AP_GRAB];
6237 free_autopickup_exceptions()
6239 struct autopickup_exception *ape;
6242 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
6243 while ((ape = iflags.autopickup_exceptions[pass]) != 0) {
6244 regex_free(ape->regex);
6245 free((genericptr_t) ape->pattern);
6246 iflags.autopickup_exceptions[pass] = ape->next;
6247 free((genericptr_t) ape);
6252 /* bundle some common usage into one easy-to-use routine */
6254 load_symset(s, which_set)
6258 clear_symsetentry(which_set, TRUE);
6260 if (symset[which_set].name)
6261 free((genericptr_t) symset[which_set].name);
6262 symset[which_set].name = dupstr(s);
6264 if (read_sym_file(which_set)) {
6265 switch_symbols(TRUE);
6267 clear_symsetentry(which_set, TRUE);
6276 clear_symsetentry(PRIMARY, TRUE);
6277 clear_symsetentry(ROGUESET, TRUE);
6279 /* symset_list is cleaned up as soon as it's used, so we shouldn't
6280 have to anything about it here */
6281 /* assert( symset_list == NULL ); */
6284 /* Parse the value of a SYMBOLS line from a config file */
6287 register char *opts;
6290 char *op, *symname, *strval;
6291 struct symparse *symp;
6293 if ((op = index(opts, ',')) != 0) {
6295 if (!parsesymbols(op))
6299 /* S_sample:string */
6301 strval = index(opts, ':');
6303 strval = index(opts, '=');
6308 /* strip leading and trailing white space from symname and strval */
6309 mungspaces(symname);
6312 symp = match_sym(symname);
6316 if (symp->range && symp->range != SYM_CONTROL) {
6317 val = sym_val(strval);
6318 update_l_symset(symp, val);
6327 size_t len = strlen(buf);
6328 const char *p = index(buf, ':'), *q = index(buf, '=');
6329 struct symparse *sp = loadsyms;
6331 if (!p || (q && q < p))
6334 /* note: there will be at most one space before the '='
6335 because caller has condensed buf[] with mungspaces() */
6336 if (p > buf && p[-1] == ' ')
6338 len = (int) (p - buf);
6341 if ((len >= strlen(sp->name)) && !strncmpi(buf, sp->name, len))
6345 return (struct symparse *) 0;
6355 if (!strval[0] || !strval[1]) { /* empty, or single character */
6356 /* if single char is space or tab, leave buf[0]=='\0' */
6357 if (!isspace((uchar) strval[0]))
6359 } else if (strval[0] == '\'') { /* single quote */
6360 /* simple matching single quote; we know strval[1] isn't '\0' */
6361 if (strval[2] == '\'' && !strval[3]) {
6362 /* accepts '\' as backslash and ''' as single quote */
6365 /* if backslash, handle single or double quote or second backslash */
6366 } else if (strval[1] == '\\' && strval[2] && strval[3] == '\''
6367 && index("'\"\\", strval[2]) && !strval[4]) {
6370 /* not simple quote or basic backslash;
6371 strip closing quote and let escapes() deal with it */
6373 char *p, tmp[QBUFSZ];
6375 (void) strncpy(tmp, strval + 1, sizeof tmp - 1);
6376 tmp[sizeof tmp - 1] = '\0';
6377 if ((p = rindex(tmp, '\'')) != 0) {
6380 } /* else buf[0] stays '\0' */
6382 } else /* not lone char nor single quote */
6383 escapes(strval, buf);
6388 /* data for option_help() */
6389 static const char *opt_intro[] = {
6391 "", " NetHack Options Help:", "",
6393 "", " NetHack
\83I
\83v
\83V
\83\87\83\93\83w
\83\8b\83v
\81F", "",
6394 #define CONFIG_SLOT 3 /* fill in next value at run-time */
6396 #if !defined(MICRO) && !defined(MAC)
6398 "or use `NETHACKOPTIONS=\"<options>\"' in your environment",
6400 "
\82Ü
\82½
\82Í
\8aÂ
\8b«
\95Ï
\90\94\82É`NETHACKOPTIONS=\"<options>\"'
\82Æ
\92è
\8b`
\82Å
\82«
\82Ü
\82·",
6403 "(<options> is a list of options separated by commas)",
6405 "(<options>
\82Í
\83J
\83\93\83}
\82Å
\8bæ
\90Ø
\82Á
\82½
\83I
\83v
\83V
\83\87\83\93\82Å
\82·)",
6408 "-- for example, $ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
6410 "--
\97á
\82¦
\82Î
\8e\9f\82Ì
\82æ
\82¤
\82É
\82µ
\82Ü
\82·
\81F$ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"",
6413 "or press \"O\" while playing and use the menu.", "",
6415 "
\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",
6417 "Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
6419 "
\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·):",
6423 static const char *opt_epilog[] = {
6426 "Some of the options can be set only before the game is started; those",
6428 "
\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",
6430 "items will not be selectable in the 'O' command's menu.", (char *) 0
6432 "
\82»
\82ê
\82ç
\82Í'O'
\83R
\83}
\83\93\83h
\82Ì
\83\81\83j
\83\85\81[
\82Å
\82Í
\91I
\91ð
\82·
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82Ü
\82¹
\82ñ
\81D", (char *) 0
6438 char buf[BUFSZ], buf2[BUFSZ];
6442 datawin = create_nhwindow(NHW_TEXT);
6444 Sprintf(buf, "Set options as OPTIONS=<options> in %s", configfile);
6446 Sprintf(buf, "
\83I
\83v
\83V
\83\87\83\93\82Í%s
\82Ì
\92\86\82ÅOPTIONS=<options>
\82Æ
\90Ý
\92è
\82µ
\82Ü
\82·", configfile);
6447 opt_intro[CONFIG_SLOT] = (const char *) buf;
6448 for (i = 0; opt_intro[i]; i++)
6449 putstr(datawin, 0, opt_intro[i]);
6451 /* Boolean options */
6452 for (i = 0; boolopt[i].name; i++) {
6453 if (boolopt[i].addr) {
6454 if (boolopt[i].addr == &iflags.sanity_check && !wizard)
6456 if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard)
6458 next_opt(datawin, boolopt[i].name);
6461 next_opt(datawin, "");
6463 /* Compound options */
6465 putstr(datawin, 0, "Compound options:");
6467 putstr(datawin, 0, "
\95¶
\8e\9a\97ñ
\83I
\83v
\83V
\83\87\83\93:");
6468 for (i = 0; compopt[i].name; i++) {
6469 Sprintf(buf2, "`%s'", compopt[i].name);
6470 Sprintf(buf, "%-20s - %s%c", buf2, compopt[i].descr,
6471 compopt[i + 1].name ? ',' : '.');
6472 putstr(datawin, 0, buf);
6475 for (i = 0; opt_epilog[i]; i++)
6476 putstr(datawin, 0, opt_epilog[i]);
6478 display_nhwindow(datawin, FALSE);
6479 destroy_nhwindow(datawin);
6484 * prints the next boolean option, on the same line if possible, on a new
6485 * line if not. End with next_opt("").
6488 next_opt(datawin, str)
6492 static char *buf = 0;
6497 *(buf = (char *) alloc(BUFSZ)) = '\0';
6501 if (s > &buf[1] && s[-2] == ',')
6502 Strcpy(s - 2, "."); /* replace last ", " */
6503 i = COLNO; /* (greater than COLNO - 2) */
6505 i = strlen(buf) + strlen(str) + 2;
6508 if (i > COLNO - 2) { /* rule of thumb */
6509 putstr(datawin, 0, buf);
6516 putstr(datawin, 0, str);
6517 free((genericptr_t) buf), buf = 0;
6522 /* Returns the fid of the fruit type; if that type already exists, it
6523 * returns the fid of that one; if it does not exist, it adds a new fruit
6524 * type to the chain and returns the new one.
6525 * If replace_fruit is sent in, replace the fruit in the chain rather than
6526 * adding a new entry--for user specified fruits only.
6529 fruitadd(str, replace_fruit)
6531 struct fruit *replace_fruit;
6534 register struct fruit *f;
6535 int highest_fruit_id = 0;
6536 char buf[PL_FSIZ], altname[PL_FSIZ];
6537 boolean user_specified = (str == pl_fruit);
6538 /* if not user-specified, then it's a fruit name for a fruit on
6542 /* Note: every fruit has an id (kept in obj->spe) of at least 1;
6545 if (user_specified) {
6546 boolean found = FALSE, numeric = FALSE;
6548 /* force fruit to be singular; this handling is not
6549 needed--or wanted--for fruits from bones because
6550 they already received it in their original game */
6551 nmcpy(pl_fruit, makesingular(str), PL_FSIZ);
6552 /* assert( str == pl_fruit ); */
6554 /* disallow naming after other foods (since it'd be impossible
6555 * to tell the difference)
6557 for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS; i++) {
6558 if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
6566 for (c = pl_fruit; *c >= '0' && *c <= '9'; c++)
6568 if (isspace((uchar) *c) || *c == 0)
6571 if (found || numeric
6572 || !strncmp(str, "cursed ", 7)
6573 || !strncmp(str, "uncursed ", 9)
6574 || !strncmp(str, "blessed ", 8)
6575 || !strncmp(str, "partly eaten ", 13)
6576 || (!strncmp(str, "tin of ", 7)
6577 && (!strcmp(str + 7, "spinach")
6578 || name_to_mon(str + 7) >= LOW_PM))
6579 || !strcmp(str, "empty tin")
6580 || ((str_end_is(str, " corpse")
6581 || str_end_is(str, " egg"))
6582 && name_to_mon(str) >= LOW_PM)) {
6583 Strcpy(buf, pl_fruit);
6584 Strcpy(pl_fruit, "candied ");
6585 nmcpy(pl_fruit + 8, buf, PL_FSIZ - 8);
6588 /* This flag indicates that a fruit has been made since the
6589 * last time the user set the fruit. If it hasn't, we can
6590 * safely overwrite the current fruit, preventing the user from
6591 * setting many fruits in a row and overflowing.
6592 * Possible expansion: check for specific fruit IDs, not for
6595 flags.made_fruit = FALSE;
6596 if (replace_fruit) {
6597 /* replace_fruit is already part of the fruit chain;
6598 update it in place rather than looking it up again */
6600 copynchars(f->fname, str, PL_FSIZ - 1);
6604 /* not user_supplied, so assumed to be from bones */
6605 copynchars(altname, str, PL_FSIZ - 1);
6606 sanitize_name(altname);
6607 flags.made_fruit = TRUE; /* for safety. Any fruit name added from a
6608 * bones level should exist anyway. */
6610 f = fruit_from_name(*altname ? altname : str, FALSE, &highest_fruit_id);
6614 /* Maximum number of named fruits is 127, even if obj->spe can
6615 handle bigger values. If adding another fruit would overflow,
6616 use a random fruit instead... we've got a lot to choose from.
6617 current_fruit remains as is. */
6618 if (highest_fruit_id >= 127)
6622 (void) memset((genericptr_t) f, 0, sizeof (struct fruit));
6623 copynchars(f->fname, *altname ? altname : str, PL_FSIZ - 1);
6624 f->fid = ++highest_fruit_id;
6625 /* we used to go out of our way to add it at the end of the list,
6626 but the order is arbitrary so use simpler insertion at start */
6631 context.current_fruit = f->fid;
6636 * This is a somewhat generic menu for taking a list of NetHack style
6637 * class choices and presenting them via a description
6638 * rather than the traditional NetHack characters.
6639 * (Benefits users whose first exposure to NetHack is via tiles).
6642 * The title at the top of the menu.
6644 * category: 0 = monster class
6648 * FALSE = PICK_ONE, TRUE = PICK_ANY
6651 * a null terminated string containing the list of choices.
6654 * a null terminated string containing the selected characters.
6656 * Returns number selected.
6659 choose_classes_menu(prompt, category, way, class_list, class_select)
6666 menu_item *pick_list = (menu_item *) 0;
6672 int next_accelerator, accelerator;
6674 if (class_list == (char *) 0 || class_select == (char *) 0)
6677 next_accelerator = 'a';
6679 win = create_nhwindow(NHW_MENU);
6681 while (*class_list) {
6689 text = def_monsyms[def_char_to_monclass(*class_list)].explain;
6690 accelerator = *class_list;
6691 Sprintf(buf, "%s", text);
6694 text = def_oc_syms[def_char_to_objclass(*class_list)].explain;
6695 accelerator = next_accelerator;
6696 Sprintf(buf, "%c %s", *class_list, text);
6699 impossible("choose_classes_menu: invalid category %d", category);
6701 if (way && *class_select) { /* Selections there already */
6702 if (index(class_select, *class_list)) {
6706 any.a_int = *class_list;
6707 add_menu(win, NO_GLYPH, &any, accelerator, category ? *class_list : 0,
6708 ATR_NONE, buf, selected);
6712 if (next_accelerator == ('z' + 1))
6713 next_accelerator = 'A';
6714 if (next_accelerator == ('Z' + 1))
6718 end_menu(win, prompt);
6719 n = select_menu(win, way ? PICK_ANY : PICK_ONE, &pick_list);
6720 destroy_nhwindow(win);
6722 for (i = 0; i < n; ++i)
6723 *class_select++ = (char) pick_list[i].item.a_int;
6724 free((genericptr_t) pick_list);
6726 } else if (n == -1) {
6727 class_select = eos(class_select);
6731 *class_select = '\0';
6735 static struct wc_Opt wc_options[] = {
6736 { "ascii_map", WC_ASCII_MAP },
6737 { "color", WC_COLOR },
6738 { "eight_bit_tty", WC_EIGHT_BIT_IN },
6739 { "hilite_pet", WC_HILITE_PET },
6740 { "popup_dialog", WC_POPUP_DIALOG },
6741 { "player_selection", WC_PLAYER_SELECTION },
6742 { "preload_tiles", WC_PRELOAD_TILES },
6743 { "tiled_map", WC_TILED_MAP },
6744 { "tile_file", WC_TILE_FILE },
6745 { "tile_width", WC_TILE_WIDTH },
6746 { "tile_height", WC_TILE_HEIGHT },
6747 { "use_inverse", WC_INVERSE },
6748 { "align_message", WC_ALIGN_MESSAGE },
6749 { "align_status", WC_ALIGN_STATUS },
6750 { "font_map", WC_FONT_MAP },
6751 { "font_menu", WC_FONT_MENU },
6752 { "font_message", WC_FONT_MESSAGE },
6754 {"perm_invent", WC_PERM_INVENT},
6756 { "font_size_map", WC_FONTSIZ_MAP },
6757 { "font_size_menu", WC_FONTSIZ_MENU },
6758 { "font_size_message", WC_FONTSIZ_MESSAGE },
6759 { "font_size_status", WC_FONTSIZ_STATUS },
6760 { "font_size_text", WC_FONTSIZ_TEXT },
6761 { "font_status", WC_FONT_STATUS },
6762 { "font_text", WC_FONT_TEXT },
6763 { "map_mode", WC_MAP_MODE },
6764 { "scroll_amount", WC_SCROLL_AMOUNT },
6765 { "scroll_margin", WC_SCROLL_MARGIN },
6766 { "splash_screen", WC_SPLASH_SCREEN },
6767 { "vary_msgcount", WC_VARY_MSGCOUNT },
6768 { "windowcolors", WC_WINDOWCOLORS },
6769 { "mouse_support", WC_MOUSE_SUPPORT },
6772 static struct wc_Opt wc2_options[] = {
6773 { "fullscreen", WC2_FULLSCREEN },
6774 { "softkeyboard", WC2_SOFTKEYBOARD },
6775 { "wraptext", WC2_WRAPTEXT },
6776 { "use_darkgray", WC2_DARKGRAY },
6777 { "hitpointbar", WC2_HITPOINTBAR },
6778 { "hilite_status", WC2_HILITE_STATUS },
6779 /* name shown in 'O' menu is different */
6780 { "status hilite rules", WC2_HILITE_STATUS },
6781 /* statushilites doesn't have its own bit */
6782 { "statushilites", WC2_HILITE_STATUS },
6787 * If a port wants to change or ensure that the SET_IN_SYS,
6788 * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is
6789 * correct (for controlling its display in the option menu) call
6790 * set_option_mod_status()
6791 * with the appropriate second argument.
6794 set_option_mod_status(optnam, status)
6800 if (SET__IS_VALUE_VALID(status)) {
6801 impossible("set_option_mod_status: status out of range %d.", status);
6804 for (k = 0; boolopt[k].name; k++) {
6805 if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) {
6806 boolopt[k].optflags = status;
6810 for (k = 0; compopt[k].name; k++) {
6811 if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) {
6812 compopt[k].optflags = status;
6819 * You can set several wc_options in one call to
6820 * set_wc_option_mod_status() by setting
6821 * the appropriate bits for each option that you
6822 * are setting in the optmask argument
6824 * example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN,
6828 set_wc_option_mod_status(optmask, status)
6829 unsigned long optmask;
6834 if (SET__IS_VALUE_VALID(status)) {
6835 impossible("set_wc_option_mod_status: status out of range %d.",
6839 while (wc_options[k].wc_name) {
6840 if (optmask & wc_options[k].wc_bit) {
6841 set_option_mod_status(wc_options[k].wc_name, status);
6848 is_wc_option(optnam)
6853 while (wc_options[k].wc_name) {
6854 if (strcmp(wc_options[k].wc_name, optnam) == 0)
6862 wc_supported(optnam)
6867 for (k = 0; wc_options[k].wc_name; ++k) {
6868 if (!strcmp(wc_options[k].wc_name, optnam))
6869 return (windowprocs.wincap & wc_options[k].wc_bit) ? TRUE : FALSE;
6875 * You can set several wc2_options in one call to
6876 * set_wc2_option_mod_status() by setting
6877 * the appropriate bits for each option that you
6878 * are setting in the optmask argument
6881 * set_wc2_option_mod_status(WC2_FULLSCREEN|WC2_SOFTKEYBOARD|WC2_WRAPTEXT,
6886 set_wc2_option_mod_status(optmask, status)
6887 unsigned long optmask;
6892 if (SET__IS_VALUE_VALID(status)) {
6893 impossible("set_wc2_option_mod_status: status out of range %d.",
6897 while (wc2_options[k].wc_name) {
6898 if (optmask & wc2_options[k].wc_bit) {
6899 set_option_mod_status(wc2_options[k].wc_name, status);
6906 is_wc2_option(optnam)
6911 while (wc2_options[k].wc_name) {
6912 if (strcmp(wc2_options[k].wc_name, optnam) == 0)
6920 wc2_supported(optnam)
6925 for (k = 0; wc2_options[k].wc_name; ++k) {
6926 if (!strcmp(wc2_options[k].wc_name, optnam))
6927 return (windowprocs.wincap2 & wc2_options[k].wc_bit) ? TRUE
6934 wc_set_font_name(opttype, fontname)
6938 char **fn = (char **) 0;
6944 fn = &iflags.wc_font_map;
6946 case MESSAGE_OPTION:
6947 fn = &iflags.wc_font_message;
6950 fn = &iflags.wc_font_text;
6953 fn = &iflags.wc_font_menu;
6956 fn = &iflags.wc_font_status;
6963 free((genericptr_t) *fn);
6964 *fn = dupstr(fontname);
6970 wc_set_window_colors(op)
6974 * menu white/black message green/yellow status white/blue text
6979 char *wn, *tfg, *tbg, *newop;
6980 static const char *wnames[] = { "menu", "message", "status", "text" };
6981 static const char *shortnames[] = { "mnu", "msg", "sts", "txt" };
6982 static char **fgp[] = { &iflags.wc_foregrnd_menu,
6983 &iflags.wc_foregrnd_message,
6984 &iflags.wc_foregrnd_status,
6985 &iflags.wc_foregrnd_text };
6986 static char **bgp[] = { &iflags.wc_backgrnd_menu,
6987 &iflags.wc_backgrnd_message,
6988 &iflags.wc_backgrnd_status,
6989 &iflags.wc_backgrnd_text };
6992 newop = mungspaces(buf);
6993 while (newop && *newop) {
6994 wn = tfg = tbg = (char *) 0;
6996 /* until first non-space in case there's leading spaces - before
7005 /* until first space - colorname*/
7006 while (*newop && *newop != ' ')
7014 /* until first non-space - before foreground*/
7022 /* until slash - foreground */
7023 while (*newop && *newop != '/')
7031 /* until first non-space (in case there's leading space after slash) -
7032 * before background */
7040 /* until first space - background */
7041 while (*newop && *newop != ' ')
7046 for (j = 0; j < 4; ++j) {
7047 if (!strcmpi(wn, wnames[j]) || !strcmpi(wn, shortnames[j])) {
7048 if (tfg && !strstri(tfg, " ")) {
7050 free((genericptr_t) *fgp[j]);
7051 *fgp[j] = dupstr(tfg);
7053 if (tbg && !strstri(tbg, " ")) {
7055 free((genericptr_t) *bgp[j]);
7056 *bgp[j] = dupstr(tbg);
7065 /* set up for wizard mode if player or save file has requested to it;
7066 called from port-specific startup code to handle `nethack -D' or
7067 OPTIONS=playmode:debug, or from dorecover()'s restgamestate() if
7068 restoring a game which was saved in wizard mode */
7073 if (authorize_wizard_mode())
7074 Strcpy(plname, "wizard");
7076 wizard = FALSE; /* not allowed or not available */
7077 /* force explore mode if we didn't make it into wizard mode */
7079 iflags.deferred_X = FALSE;
7081 /* don't need to do anything special for explore mode or normal play */
7084 #endif /* OPTION_LISTS_ONLY */