Blindfold removal fix
[slashemextended.git] / src / options.c
blobca23ea3e153ab84d39cc49b2e3fb37831033697d
1 /* SCCS Id: @(#)options.c 3.4 2003/11/14 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #ifdef OPTION_LISTS_ONLY /* (AMIGA) external program for opt lists */
6 #include "config.h"
7 #include "objclass.h"
8 #include "flag.h"
9 NEARDATA struct flag flags; /* provide linkage */
10 NEARDATA struct instance_flags iflags; /* provide linkage */
11 #define static
12 #else
13 #include "hack.h"
14 #include "tcap.h"
15 #include <ctype.h>
16 #endif
18 #if defined(GL_GRAPHICS) || defined(SDL_GRAPHICS)
19 #include "winGL.h" /* Sdlgl_parse_options */
20 #endif
22 #include "filename.h"
24 #define WINTYPELEN 16
26 #ifdef DEFAULT_WC_TILED_MAP
27 #define PREFER_TILED TRUE
28 #else
29 #define PREFER_TILED FALSE
30 #endif
32 #ifdef CURSES_GRAPHICS
33 extern int curses_read_attrs(char *attrs);
34 #endif
37 * NOTE: If you add (or delete) an option, please update the short
38 * options help (option_help()), the long options help (dat/opthelp),
39 * and the current options setting display function (doset()),
40 * and also the Guidebooks.
42 * The order matters. If an option is a an initial substring of another
43 * option (e.g. time and timed_delay) the shorter one must come first.
46 static struct Bool_Opt
48 const char *name;
49 boolean *addr, initvalue;
50 int optflags;
51 } boolopt[] = {
53 {"alphabet_inv", &flags.alphabetinv, FALSE, SET_IN_FILE},
55 #ifdef AMIGA
56 {"altmeta", &flags.altmeta, TRUE, DISP_IN_GAME},
57 #else
58 {"altmeta", (boolean *)0, TRUE, DISP_IN_GAME},
59 #endif
60 {"ascii_map", &iflags.wc_ascii_map, !PREFER_TILED, SET_IN_GAME}, /*WC*/
61 #ifdef MFLOPPY
62 {"asksavedisk", &flags.asksavedisk, FALSE, SET_IN_GAME},
63 #else
64 {"asksavedisk", (boolean *)0, FALSE, SET_IN_GAME},
65 #endif
66 {"autodig", &flags.autodig, FALSE, SET_IN_GAME},
68 {"autopickup", &flags.pickup, FALSE, SET_IN_GAME},
69 #ifdef AUTO_OPEN
70 {"autoopen", &iflags.autoopen, TRUE, SET_IN_GAME},
71 #endif /* AUTO_OPEN */
72 {"autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME},
74 {"bash_reminder", &flags.bash_reminder, TRUE, SET_IN_GAME},
76 #if defined(MICRO) && !defined(AMIGA)
77 {"BIOS", &iflags.BIOS, FALSE, SET_IN_FILE},
78 #else
79 {"BIOS", (boolean *)0, FALSE, SET_IN_FILE},
80 #endif
81 {"bones", &iflags.bones, TRUE, SET_IN_FILE},
82 #ifdef INSURANCE
83 {"checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME},
84 #else
85 {"checkpoint", (boolean *)0, FALSE, SET_IN_FILE},
86 #endif
87 #ifdef MFLOPPY
88 {"checkspace", &iflags.checkspace, TRUE, SET_IN_GAME},
89 #else
90 {"checkspace", (boolean *)0, FALSE, SET_IN_FILE},
91 #endif
92 {"cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME},
93 # if defined(MICRO) || defined(WIN32) || defined(UNIX) || defined(CURSES_GRAPHICS)
94 {"color", &iflags.wc_color,TRUE, SET_IN_GAME}, /*WC*/
95 # else /* systems that support multiple terminals, many monochrome */
96 {"color", &iflags.wc_color, FALSE, SET_IN_GAME}, /*WC*/
97 # endif
99 {"contentwarning", &flags.contentwarning, TRUE, SET_IN_FILE},
101 {"confirm",&flags.confirm, TRUE, SET_IN_GAME},
102 #ifdef CURSES_GRAPHICS
103 {"classic_status", &iflags.classic_status, TRUE, SET_IN_GAME},
104 {"cursesgraphics", &iflags.cursesgraphics, TRUE, SET_IN_GAME},
105 #else
106 {"classic_status", (boolean *)0, TRUE, SET_IN_FILE},
107 {"cursesgraphics", (boolean *)0, FALSE, SET_IN_FILE},
108 #endif
109 #ifndef PUBLIC_SERVER
110 {"death_explore", &iflags.death_expl, TRUE, SET_IN_GAME},
111 #endif
112 #if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV)
113 {"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME},
114 #else
115 {"DECgraphics", (boolean *)0, FALSE, SET_IN_FILE},
116 #endif
117 {"eatingboulders", &flags.eatingboulders, TRUE, SET_IN_GAME},
118 {"eatingconfirm", &flags.eatingconfirm, FALSE, SET_IN_GAME},
119 {"eatingdoors", &flags.eatingdoors, TRUE, SET_IN_GAME},
120 {"eatingwalls", &flags.eatingwalls, TRUE, SET_IN_GAME},
121 {"eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME}, /*WC*/
122 {"epyxmode", &flags.epyxmode, TRUE, SET_IN_GAME},
123 #if defined(TTY_GRAPHICS) || defined(CURSES_GRAPIHCS)
124 {"extmenu", &iflags.extmenu, FALSE, SET_IN_GAME},
125 #else
126 {"extmenu", (boolean *)0, FALSE, SET_IN_FILE},
127 #endif
128 #ifdef OPT_DISPMAP
129 {"fast_map", &flags.fast_map, TRUE, SET_IN_GAME},
130 #else
131 {"fast_map", (boolean *)0, TRUE, SET_IN_FILE},
132 #endif
133 {"female", &flags.female, FALSE, DISP_IN_GAME},
134 {"fixinv", &flags.invlet_constant, TRUE, SET_IN_FILE},
135 #ifdef AMIFLUSH
136 {"flush", &flags.amiflush, FALSE, SET_IN_GAME},
137 #else
138 {"flush", (boolean *)0, FALSE, SET_IN_FILE},
139 #endif
140 {"fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE},
141 {"gmmessage", &flags.gmmessage, TRUE, SET_IN_GAME},
142 {"graffitihilite", &flags.graffitihilite, TRUE, SET_IN_GAME},
143 {"guicolor", &iflags.wc2_guicolor, TRUE, SET_IN_GAME},
144 {"help", &flags.help, TRUE, SET_IN_GAME},
145 {"hilite_pet", &iflags.wc_hilite_pet, TRUE, SET_IN_GAME}, /*WC*/
146 {"hitpointbar", &flags.hitpointbar, TRUE, SET_IN_GAME},
147 #ifdef ASCIIGRAPH
148 {"IBMgraphics", &iflags.IBMgraphics, FALSE, SET_IN_GAME},
149 #else
150 {"IBMgraphics", (boolean *)0, FALSE, SET_IN_FILE},
151 #endif
152 #ifndef MAC
153 {"ignintr", &flags.ignintr, FALSE, SET_IN_GAME},
154 #else
155 {"ignintr", (boolean *)0, FALSE, SET_IN_FILE},
156 #endif
157 {"inertiaconfirm", &flags.inertiaconfirm, FALSE, SET_IN_GAME},
158 #ifdef SHOW_WEIGHT
159 {"invweight", &flags.invweight, TRUE, SET_IN_GAME},
160 #else
161 {"invweight", (boolean *)0, FALSE, SET_IN_FILE},
162 #endif
163 /*WAC the keep savefile option...*/
164 #ifdef KEEP_SAVE
165 {"keep_savefile", &flags.keep_savefile, FALSE, SET_IN_FILE},
166 #else
167 {"keep_savefile", (boolean *)0, FALSE, DISP_IN_GAME},
168 #endif
169 {"knapsacklimit", &flags.knapsacklimit, FALSE, SET_IN_GAME},
171 {"large_font", &iflags.obsolete, FALSE, SET_IN_FILE}, /* OBSOLETE */
172 {"legacy", &flags.legacy, TRUE, DISP_IN_GAME},
173 {"lit_corridor", &flags.lit_corridor, TRUE, SET_IN_GAME},
174 {"lootabc", &iflags.lootabc, FALSE, SET_IN_GAME},
175 #ifdef MAC_GRAPHICS_ENV
176 {"Macgraphics", &iflags.MACgraphics, TRUE, SET_IN_GAME},
177 #else
178 {"Macgraphics", (boolean *)0, FALSE, SET_IN_FILE},
179 #endif
180 #ifdef MAIL
181 {"mail", &flags.biff, TRUE, SET_IN_GAME},
182 #else
183 {"mail", (boolean *)0, TRUE, SET_IN_FILE},
184 #endif
186 {"materialglyph", &flags.materialglyph, FALSE, SET_IN_GAME},
188 {"memorizationknown", &iflags.memorizationknown, FALSE, SET_IN_GAME},
190 #if defined(STATUS_COLORS) && defined(TEXTCOLOR)
191 {"statuscolors", &iflags.use_status_colors, TRUE, SET_IN_GAME},
192 #else
193 {"statuscolors", (boolean *)0, TRUE, SET_IN_GAME},
194 #endif
195 #ifdef MENU_COLOR
196 # ifdef MICRO
197 {"menucolors", &iflags.use_menu_color, TRUE, SET_IN_GAME},
198 # else
199 {"menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME},
200 # endif
201 #else
202 {"menucolors", (boolean *)0, FALSE, SET_IN_GAME},
203 #endif
204 /* Not supported in tty at the moment (hence SET_IN_FILE), but curses has it */
205 {"menu_on_esc", &flags.menu_on_esc, TRUE, SET_IN_GAME},
206 {"menu_glyphs", &iflags.use_menu_glyphs, FALSE, SET_IN_GAME},
207 #ifdef WIZARD
208 /* for menu debugging only*/
209 {"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME},
210 #else
211 {"menu_tab_sep", (boolean *)0, FALSE, SET_IN_FILE},
212 #endif
214 {"missing_safety", &flags.missing_safety, TRUE, SET_IN_GAME},
216 #ifdef WIZARD
217 {"mon_polycontrol", &iflags.mon_polycontrol, FALSE, SET_IN_GAME},
218 #else
219 {"mon_polycontrol", (boolean *)0, FALSE, SET_IN_FILE},
220 #endif
222 {"moreforced", &flags.moreforced, TRUE, SET_IN_GAME},
224 #ifdef CURSES_GRAPHICS
225 {"mouse_support", &iflags.wc_mouse_support, FALSE, DISP_IN_GAME}, /*WC*/
226 #else
227 {"mouse_support", &iflags.wc_mouse_support, TRUE, DISP_IN_GAME}, /*WC*/
228 #endif
229 #ifdef NEWS
230 {"news", &iflags.news, TRUE, DISP_IN_GAME},
231 #else
232 {"news", (boolean *)0, FALSE, SET_IN_FILE},
233 #endif
234 {"numpadmessage", &iflags.numpadmessage, TRUE, SET_IN_GAME},
235 {"null", &flags.null, TRUE, SET_IN_GAME},
236 #ifdef MAC
237 {"page_wait", &flags.page_wait, TRUE, SET_IN_GAME},
238 #else
239 {"page_wait", (boolean *)0, FALSE, SET_IN_FILE},
240 #endif
241 {"paranoidquit", &flags.paranoidquit, TRUE, SET_IN_GAME},
242 {"perm_invent", &flags.perm_invent, TRUE, SET_IN_GAME},
243 {"pickup_thrown", &flags.pickup_thrown, TRUE, SET_IN_GAME},
244 {"pickup_cursed", &flags.pickup_cursed, FALSE, SET_IN_GAME},
246 {"pokedex", &flags.pokedex, TRUE, SET_IN_GAME},
248 {"popup_dialog", &iflags.wc_popup_dialog, TRUE, SET_IN_GAME}, /*WC*/
249 {"prayconfirm", &flags.prayconfirm, TRUE, SET_IN_GAME},
250 {"preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME}, /*WC*/
251 {"pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME},
252 {"quiver_fired", &iflags.quiver_fired, FALSE, SET_IN_GAME},
253 {"qwertz_layout", &iflags.qwertz_layout, FALSE, SET_IN_GAME},
254 {"radar", (boolean *)0, FALSE, SET_IN_FILE}, /* OBSOLETE */
255 #if defined(MICRO) && !defined(AMIGA)
256 {"rawio", &iflags.rawio, FALSE, DISP_IN_GAME},
257 #else
258 {"rawio", (boolean *)0, FALSE, SET_IN_FILE},
259 #endif
260 {"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME},
261 {"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME},
262 #if defined(OBJ_SANITY)
263 {"sanity_check", &iflags.sanity_check, TRUE, SET_IN_GAME},
264 #elif defined(WIZARD)
265 {"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME},
266 #else
267 {"sanity_check", (boolean *)0, FALSE, SET_IN_FILE},
268 #endif
269 {"should_change_color", &iflags.should_change_color, TRUE, SET_IN_FILE},
270 {"showexp", &flags.showexp, FALSE, SET_IN_GAME},
271 {"showrace", &iflags.showrace, FALSE, SET_IN_GAME},
272 #ifdef REALTIME_ON_BOTL
273 {"showrealtime", &iflags.showrealtime, FALSE, SET_IN_GAME},
274 #endif
275 {"showscore", &flags.showscore, FALSE, SET_IN_GAME},
276 {"showsym", &iflags.showsym, TRUE, SET_IN_GAME},
277 /* WAC made the [ xx pts] dmg display optional */
278 #ifdef SHOW_DMG
279 {"showdmg", &flags.showdmg, TRUE, SET_IN_GAME},
280 #else
281 {"showdmg", (boolean *)0, FALSE, SET_IN_FILE},
282 #endif
283 #ifdef SHOW_WEIGHT
284 {"showweight", &flags.showweight, FALSE, SET_IN_GAME},
285 #else
286 {"showweight", (boolean *)0, FALSE, SET_IN_FILE},
287 #endif
289 {"showmc", &flags.showmc, FALSE, SET_IN_GAME},
290 {"showmovement", &flags.showmovement, FALSE, SET_IN_GAME},
291 {"showlongstats", &flags.showlongstats, FALSE, SET_IN_GAME},
292 {"showsanity", &flags.showsanity, FALSE, SET_IN_GAME},
293 {"showsymbiotehp", &flags.showsymbiotehp, FALSE, SET_IN_GAME},
295 {"silent", &flags.silent, TRUE, SET_IN_GAME},
296 {"simpledescs", &flags.simpledescs, FALSE, SET_IN_GAME},
297 {"softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE},
298 {"sortpack", &flags.sortpack, TRUE, SET_IN_GAME},
299 {"sound", &flags.soundok, TRUE, SET_IN_GAME},
300 {"sparkle", &flags.sparkle, TRUE, SET_IN_GAME},
301 {"standout", &flags.standout, FALSE, SET_IN_GAME},
302 {"splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME}, /*WC*/
304 {"tabcursesconfirm", &flags.tabcursesconfirm, FALSE, SET_IN_GAME},
306 {"tech_description", &flags.tech_description, TRUE, SET_IN_GAME},
308 {"tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME}, /*WC*/
309 {"time", &flags.time, TRUE, SET_IN_GAME},
311 {"timed_autosave", &flags.etimed_autosave, TRUE, SET_IN_GAME},
312 {"quick_autosave", &flags.xtimed_autosave, FALSE, SET_IN_GAME},
314 {"tombstone",&flags.tombstone, TRUE, SET_IN_GAME},
315 {"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME},
316 {"travel", &iflags.travelcmd, TRUE, SET_IN_GAME},
317 #ifdef WIN32CON
318 {"use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME}, /*WC*/
319 #else
320 {"use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME}, /*WC*/
321 #endif
322 {"verbose", &flags.verbose, TRUE, SET_IN_GAME},
323 {"wallglyph", &flags.wallglyph, TRUE, SET_IN_GAME},
324 {"winggraphics", &iflags.winggraphics, FALSE, DISP_IN_GAME},
325 {"wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME},
327 {"blindfox", &flags.blindfox, FALSE, DISP_IN_GAME},
328 {"dudley", &flags.dudley, FALSE, DISP_IN_GAME},
329 {"gehenna", &flags.gehenna, FALSE, DISP_IN_GAME},
330 {"hippie", &flags.hippie, FALSE, DISP_IN_GAME},
331 {"iwbtg", &flags.iwbtg, FALSE, DISP_IN_GAME},
332 {"elmstreet", &flags.elmstreet, FALSE, DISP_IN_GAME},
333 {"lostsoul", &flags.lostsoul, FALSE, DISP_IN_GAME},
334 {"uberlostsoul", &flags.uberlostsoul, FALSE, DISP_IN_GAME},
335 #ifdef GMMODE
336 {"gmmode", &flags.gmmode, FALSE, DISP_IN_GAME},
337 {"supergmmode", &flags.supergmmode, FALSE, DISP_IN_GAME},
338 #endif
339 {"assholemode", &flags.assholemode, FALSE, DISP_IN_GAME},
340 {"wonderland", &flags.wonderland, FALSE, DISP_IN_GAME},
341 {"zapem", &flags.zapem, FALSE, DISP_IN_GAME},
343 {"askforalias", &flags.askforalias, FALSE, DISP_IN_GAME},
345 {"hybridangbander", &flags.hybridangbander, FALSE, SET_IN_FILE},
346 {"hybridaquarian", &flags.hybridaquarian, FALSE, SET_IN_FILE},
347 {"hybridcurser", &flags.hybridcurser, FALSE, SET_IN_FILE},
348 {"hybridhaxor", &flags.hybridhaxor, FALSE, SET_IN_FILE},
349 {"hybridhomicider", &flags.hybridhomicider, FALSE, SET_IN_FILE},
350 {"hybridsuxxor", &flags.hybridsuxxor, FALSE, SET_IN_FILE},
351 {"hybridwarper", &flags.hybridwarper, FALSE, SET_IN_FILE},
352 {"hybridrandomizer", &flags.hybridrandomizer, FALSE, SET_IN_FILE},
353 {"hybridnullrace", &flags.hybridnullrace, FALSE, SET_IN_FILE},
354 {"hybridmazewalker", &flags.hybridmazewalker, FALSE, SET_IN_FILE},
355 {"hybridsoviet", &flags.hybridsoviet, FALSE, SET_IN_FILE},
356 {"hybridxrace", &flags.hybridxrace, FALSE, SET_IN_FILE},
357 {"hybridheretic", &flags.hybridheretic, FALSE, SET_IN_FILE},
358 {"hybridsokosolver", &flags.hybridsokosolver, FALSE, SET_IN_FILE},
359 {"hybridspecialist", &flags.hybridspecialist, FALSE, SET_IN_FILE},
360 {"hybridamerican", &flags.hybridamerican, FALSE, SET_IN_FILE},
361 {"hybridminimalist", &flags.hybridminimalist, FALSE, SET_IN_FILE},
362 {"hybridnastinator", &flags.hybridnastinator, FALSE, SET_IN_FILE},
363 {"hybridrougelike", &flags.hybridrougelike, FALSE, SET_IN_FILE},
364 {"hybridsegfaulter", &flags.hybridsegfaulter, FALSE, SET_IN_FILE},
365 {"hybridironman", &flags.hybridironman, FALSE, SET_IN_FILE},
366 {"hybridamnesiac", &flags.hybridamnesiac, FALSE, SET_IN_FILE},
367 {"hybridproblematic", &flags.hybridproblematic, FALSE, SET_IN_FILE},
368 {"hybridwindinhabitant", &flags.hybridwindinhabitant, FALSE, SET_IN_FILE},
369 {"hybridaggravator", &flags.hybridaggravator, FALSE, SET_IN_FILE},
370 {"hybridevilvariant", &flags.hybridevilvariant, FALSE, SET_IN_FILE},
371 {"hybridlevelscaler", &flags.hybridlevelscaler, FALSE, SET_IN_FILE},
372 {"hybriderosator", &flags.hybriderosator, FALSE, SET_IN_FILE},
373 {"hybridroommate", &flags.hybridroommate, FALSE, SET_IN_FILE},
374 {"hybridextravator", &flags.hybridextravator, FALSE, SET_IN_FILE},
375 {"hybridhallucinator", &flags.hybridhallucinator, FALSE, SET_IN_FILE},
376 {"hybridbossrusher", &flags.hybridbossrusher, FALSE, SET_IN_FILE},
377 {"hybriddorian", &flags.hybriddorian, FALSE, SET_IN_FILE},
378 {"hybridtechless", &flags.hybridtechless, FALSE, SET_IN_FILE},
379 {"hybridblait", &flags.hybridblait, FALSE, SET_IN_FILE},
380 {"hybridgrouper", &flags.hybridgrouper, FALSE, SET_IN_FILE},
381 {"hybridscriptor", &flags.hybridscriptor, FALSE, SET_IN_FILE},
382 {"hybridunbalancor", &flags.hybridunbalancor, FALSE, SET_IN_FILE},
383 {"hybridbeacher", &flags.hybridbeacher, FALSE, SET_IN_FILE},
384 {"hybridstairseeker", &flags.hybridstairseeker, FALSE, SET_IN_FILE},
385 {"hybridmatrayser", &flags.hybridmatrayser, FALSE, SET_IN_FILE},
386 {"hybridfeminizer", &flags.hybridfeminizer, FALSE, SET_IN_FILE},
387 {"hybridchallenger", &flags.hybridchallenger, FALSE, SET_IN_FILE},
388 {"hybridhardmoder", &flags.hybridhardmoder, FALSE, SET_IN_FILE},
389 {"hybridstunfish", &flags.hybridstunfish, FALSE, SET_IN_FILE},
390 {"hybridkillfiller", &flags.hybridkillfiller, FALSE, SET_IN_FILE},
391 {"hybridbadstatter", &flags.hybridbadstatter, FALSE, SET_IN_FILE},
392 {"hybriddroughter", &flags.hybriddroughter, FALSE, SET_IN_FILE},
393 {"hybridvanillaoid", &flags.hybridvanillaoid, FALSE, SET_IN_FILE},
395 {"randomhybrids", &flags.randomhybrids, TRUE, DISP_IN_GAME},
397 {(char *)0, (boolean *)0, FALSE, 0}
400 void * nh_option_get_boolopt()
402 return (void *)boolopt;
405 /* compound options, for option_help() and external programs like Amiga
406 * frontend */
407 static struct Comp_Opt
409 const char *name, *descr;
410 int size; /* for frontends and such allocating space --
411 * usually allowed size of data in game, but
412 * occasionally maximum reasonable size for
413 * typing when game maintains information in
414 * a different format */
415 int optflags;
416 } compopt[] = {
417 { "align", "your starting alignment (lawful, neutral, or chaotic)",
418 8, DISP_IN_GAME },
419 { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/
420 { "align_status", "status window alignment", 20, DISP_IN_GAME }, /*WC*/
421 { "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
422 { "boulder", "the symbol to use for displaying boulders",
423 1, SET_IN_GAME },
424 { "catname", "the name of your (first) cat (e.g., catname:Tabby)",
425 PL_PSIZ, DISP_IN_GAME },
426 /* { "coinsname", "the name of your (first) pile of copper coins (e.g., coinsname:Dollars)",
427 PL_PSIZ, DISP_IN_GAME },*/
428 { "disclose", "the kinds of information to disclose at end of game",
429 sizeof(flags.end_disclose) * 2,
430 SET_IN_GAME },
431 { "dogname", "the name of your (first) dog (e.g., dogname:Fang)",
432 PL_PSIZ, DISP_IN_GAME },
433 { "dragonname", "the name of your (first) dragon (e.g., dragonname:Wintersdotir)",
434 PL_PSIZ, DISP_IN_GAME },
435 { "monkeyname", "the name of your (first) monkey (e.g., monkeyname:DonkeyKong)",
436 PL_PSIZ, DISP_IN_GAME },
437 { "parrotname", "the name of your (first) parrot (e.g., parrotname:Polly)",
438 PL_PSIZ, DISP_IN_GAME },
439 { "girlname", "the name of your (first) girl (e.g., girlname:Sarah)",
440 PL_PSIZ, DISP_IN_GAME },
441 { "boyname", "the name of your (first) boy (e.g., boyname:Jonas)",
442 PL_PSIZ, DISP_IN_GAME },
443 { "ravenname", "the name of your (first) raven (e.g., ravenname:Nevermore)",
444 PL_PSIZ, DISP_IN_GAME },
445 #ifdef DUMP_LOG
446 { "dumpfile", "where to dump data (e.g., dumpfile:/tmp/dump.nh)",
447 #ifdef DUMP_FN
448 PL_PSIZ, DISP_IN_GAME },
449 #else
450 PL_PSIZ, SET_IN_GAME },
451 #endif
452 #endif
453 { "dungeon", "the symbols to use in drawing the dungeon map",
454 MAXDCHARS+1, SET_IN_FILE },
455 { "effects", "the symbols to use in drawing special effects",
456 MAXECHARS+1, SET_IN_FILE },
457 { "font_map", "the font to use in the map window", 40, DISP_IN_GAME }, /*WC*/
458 { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/
459 { "font_message", "the font to use in the message window",
460 40, DISP_IN_GAME }, /*WC*/
461 { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/
462 { "font_size_menu", "the size of the menu font", 20, DISP_IN_GAME }, /*WC*/
463 { "font_size_message", "the size of the message font", 20, DISP_IN_GAME }, /*WC*/
464 { "font_size_status", "the size of the status font", 20, DISP_IN_GAME }, /*WC*/
465 { "font_size_text", "the size of the text font", 20, DISP_IN_GAME }, /*WC*/
466 { "font_status", "the font to use in status window", 40, DISP_IN_GAME }, /*WC*/
467 { "font_text", "the font to use in text windows", 40, DISP_IN_GAME }, /*WC*/
468 { "fruit", "the name of a fruit you enjoy eating",
469 PL_FSIZ, SET_IN_GAME },
470 { "gender", "your starting gender (male or female)",
471 8, DISP_IN_GAME },
472 { "ghoulname", "the name of your (first) ghoul (e.g., ghoulname:Casper)",
473 PL_PSIZ, DISP_IN_GAME },
474 { "horsename", "the name of your (first) horse (e.g., horsename:Silver)",
475 PL_PSIZ, DISP_IN_GAME },
476 /* { "lichenname", "the name of your (first) lichen (e.g., lichenname:Fungus)",
477 PL_PSIZ, DISP_IN_GAME },*/
478 { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/
479 { "menucolor", "set menu colors", PL_PSIZ, SET_IN_FILE },
480 { "menustyle", "user interface for object selection",
481 MENUTYPELEN, SET_IN_GAME },
482 { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE },
483 { "menu_deselect_page", "deselect all items on this page of a menu",
484 4, SET_IN_FILE },
485 { "menu_first_page", "jump to the first page in a menu",
486 4, SET_IN_FILE },
487 { "menu_headings", "bold, inverse, or underline headings", 9, SET_IN_GAME },
488 { "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
489 { "menu_invert_page", "invert all items on this page of a menu",
490 4, SET_IN_FILE },
491 { "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE },
492 { "menu_next_page", "goto the next menu page", 4, SET_IN_FILE },
493 { "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE },
494 { "menu_search", "search for a menu item", 4, SET_IN_FILE },
495 { "menu_select_all", "select all items in a menu", 4, SET_IN_FILE },
496 { "menu_select_page", "select all items on this page of a menu",
497 4, SET_IN_FILE },
498 { "monsters", "the symbols to use for monsters",
499 MAXMCLASSES, SET_IN_FILE },
500 { "msghistory", "number of top line messages to save",
501 5, DISP_IN_GAME },
502 # ifdef TTY_GRAPHICS
503 {"msg_window", "the type of message window required",1, SET_IN_GAME},
504 # else
505 {"msg_window", "the type of message window required", 1, SET_IN_FILE},
506 # endif
507 { "name", "your character's name (e.g., name:Merlin-W)",
508 PL_NSIZ, DISP_IN_GAME },
509 { "number_pad", "use the number pad", 1, SET_IN_GAME},
510 { "objects", "the symbols to use for objects",
511 MAXOCLASSES, SET_IN_FILE },
512 { "packorder", "the inventory order of the items in your pack",
513 MAXOCLASSES, SET_IN_GAME },
514 #ifdef CHANGE_COLOR
515 { "palette", "palette (00c/880/-fff is blue/yellow/reverse white)",
516 15 , SET_IN_GAME },
517 # if defined(MAC)
518 { "hicolor", "same as palette, only order is reversed",
519 15, SET_IN_FILE },
520 # endif
521 #endif
522 { "petattr", "attributes for highlighting pets", 12, SET_IN_FILE },
523 { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME },
524 { "pickup_burden", "maximum burden picked up before prompt",
525 20, SET_IN_GAME },
526 { "pickup_types", "types of objects to pick up automatically",
527 MAXOCLASSES, SET_IN_GAME },
528 { "pilesize", "maximum number of items on floor to list automatically",
529 20, SET_IN_GAME },
530 { "plalias", "your alias name",
531 PL_NSIZ, DISP_IN_GAME },
532 { "player_selection", "choose character via dialog or prompts",
533 12, DISP_IN_GAME },
534 { "race", "your starting race (e.g., Human, Elf)",
535 PL_CSIZ, DISP_IN_GAME },
536 { "ratname", "the name of your (first) rat (e.g., ratname:Squeak)",
537 PL_PSIZ, DISP_IN_GAME },
538 { "role", "your starting role (e.g., Barbarian, Valkyrie)",
539 PL_CSIZ, DISP_IN_GAME },
540 /* { "rothename", "the name of your (first) rothe (e.g., rothename:Badger)",
541 PL_PSIZ, DISP_IN_GAME },*/
542 { "runmode", "display frequency when `running' or `travelling'",
543 sizeof "teleport", SET_IN_GAME },
544 { "scores", "the parts of the score list you wish to see",
545 32, SET_IN_GAME },
546 { "scroll_amount", "amount to scroll map when scroll_margin is reached",
547 20, DISP_IN_GAME }, /*WC*/
548 { "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/
549 { "sortloot", "sort object selection lists by description", 4, SET_IN_GAME },
550 #ifdef MSDOS
551 { "soundcard", "type of sound card to use", 20, SET_IN_FILE },
552 #endif
553 { "statuscolor", "set status colors", PL_PSIZ, SET_IN_FILE },
554 { "suppress_alert", "suppress alerts about version-specific features",
555 8, SET_IN_GAME },
556 { "tile_width", "width of tiles", 20, DISP_IN_GAME}, /*WC*/
557 { "tile_height", "height of tiles", 20, DISP_IN_GAME}, /*WC*/
558 { "tile_file", "name of tile file", 70, DISP_IN_GAME}, /*WC*/
559 { "tileset", "name of predefined tileset to use",
560 PL_PSIZ, SET_IN_GAME },
561 { "traps", "the symbols to use in drawing traps",
562 MAXTCHARS+1, SET_IN_FILE },
563 { "vary_msgcount", "show more old messages at a time", 20, DISP_IN_GAME }, /*WC*/
564 #ifdef MSDOS
565 { "video", "method of video updating", 20, SET_IN_FILE },
566 #endif
567 #ifdef VIDEOSHADES
568 { "videocolors", "color mappings for internal screen routines",
569 40, DISP_IN_GAME },
570 #ifdef MSDOS
571 { "videoshades", "gray shades to map to black/gray/white",
572 32, DISP_IN_GAME },
573 #endif
574 #endif
575 #ifdef WIN32CON
576 {"subkeyvalue", "override keystroke value", 7, SET_IN_FILE},
577 #endif
578 { "windowcolors", "the foreground/background colors of windows", /*WC*/
579 80, DISP_IN_GAME },
580 { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME },
581 { "wolfname", "the name of your (first) wolf (e.g., wolfname:Beast)",
582 PL_PSIZ, DISP_IN_GAME },
583 { (char *)0, (char *)0, 0, 0 }
586 static struct Bool_Tile_Opt
588 const char *name;
589 unsigned long flag;
590 unsigned long initvalue;
591 } booltileopt[] = {
592 {"transparent", TILESET_TRANSPARENT, 0},
593 {"pseudo3D", TILESET_PSEUDO3D, 0},
594 {(char *)0, 0, 0}
597 #ifdef OPTION_LISTS_ONLY
598 #undef static
600 #else /* use rest of file */
602 static boolean need_redraw; /* for doset() */
604 #if defined(TOS) && defined(TEXTCOLOR)
605 extern boolean colors_changed; /* in tos.c */
606 #endif
608 #ifdef VIDEOSHADES
609 extern char *shade[3]; /* in sys/msdos/video.c */
610 extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c, win/tty/termcap.c*/
611 #endif
613 static char def_inv_order[MAXOCLASSES] = {
614 COIN_CLASS, AMULET_CLASS, IMPLANT_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS,
615 SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS,
616 TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, VENOM_CLASS, 0, 0,
620 * Default menu manipulation command accelerators. These may _not_ be:
622 * + a number - reserved for counts
623 * + an upper or lower case US ASCII letter - used for accelerators
624 * + ESC - reserved for escaping the menu
625 * + NULL, CR or LF - reserved for commiting the selection(s). NULL
626 * is kind of odd, but the tty's xwaitforspace() will return it if
627 * someone hits a <ret>.
628 * + a default object class symbol - used for object class accelerators
630 * Standard letters (for now) are:
632 * < back 1 page
633 * > forward 1 page
634 * ^ first page
635 * | last page
636 * : search
638 * page all
639 * , select .
640 * \ deselect -
641 * ~ invert @
643 * The command name list is duplicated in the compopt array.
645 typedef struct {
646 const char *name;
647 char cmd;
648 } menu_cmd_t;
650 #define NUM_MENU_CMDS 11
651 static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = {
652 /* 0*/ { "menu_first_page", MENU_FIRST_PAGE },
653 { "menu_last_page", MENU_LAST_PAGE },
654 { "menu_next_page", MENU_NEXT_PAGE },
655 { "menu_previous_page", MENU_PREVIOUS_PAGE },
656 { "menu_select_all", MENU_SELECT_ALL },
657 /* 5*/ { "menu_deselect_all", MENU_UNSELECT_ALL },
658 { "menu_invert_all", MENU_INVERT_ALL },
659 { "menu_select_page", MENU_SELECT_PAGE },
660 { "menu_deselect_page", MENU_UNSELECT_PAGE },
661 { "menu_invert_page", MENU_INVERT_PAGE },
662 /*10*/ { "menu_search", MENU_SEARCH },
666 * Allow the user to map incoming characters to various menu commands.
667 * The accelerator list must be a valid C string.
669 #define MAX_MENU_MAPPED_CMDS 32 /* some number */
670 char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS+1]; /* exported */
671 static char mapped_menu_op[MAX_MENU_MAPPED_CMDS+1];
672 static short n_menu_mapped = 0;
674 static boolean initial, from_file;
676 STATIC_DCL void doset_add_menu(winid,const char *,int);
677 STATIC_DCL void nmcpy(char *, const char *, int);
678 STATIC_DCL void escapes(const char *, char *);
679 STATIC_DCL void rejectoption(const char *);
680 STATIC_DCL void badoption(const char *);
681 STATIC_OVL void badtileoption(const char *);
682 STATIC_DCL char *string_for_opt(char *,BOOLEAN_P);
683 STATIC_OVL char *string_for_tile_opt(char *, BOOLEAN_P);
684 STATIC_DCL char *string_for_env_opt(const char *, char *,BOOLEAN_P);
685 STATIC_DCL void bad_negation(const char *,BOOLEAN_P);
686 STATIC_DCL int change_inv_order(char *);
687 STATIC_DCL void oc_to_str(char *, char *);
688 STATIC_DCL void graphics_opts(char *,const char *,int,int);
689 STATIC_DCL int feature_alert_opts(char *, const char *);
690 STATIC_DCL const char *get_compopt_value(const char *, char *);
691 STATIC_DCL boolean special_handling(const char *, BOOLEAN_P, BOOLEAN_P);
692 STATIC_DCL void warning_opts(char *,const char *);
693 STATIC_DCL void duplicate_opt_detection(const char *, int);
695 STATIC_OVL void wc_set_font_name(int, char *);
696 STATIC_OVL int wc_set_window_colors(char *);
697 STATIC_OVL boolean is_wc_option(const char *);
698 STATIC_OVL boolean wc_supported(const char *);
699 STATIC_OVL boolean is_wc2_option(const char *);
700 STATIC_OVL boolean wc2_supported(const char *);
701 #ifdef AUTOPICKUP_EXCEPTIONS
702 STATIC_DCL void remove_autopickup_exception(struct autopickup_exception *);
703 STATIC_OVL int count_ape_maps(int *, int *);
704 #endif
706 /* check whether a user-supplied option string is a proper leading
707 substring of a particular option name; option string might have
708 a colon or equals sign and arbitrary value appended to it */
709 boolean
710 match_optname(user_string, opt_name, min_length, val_allowed)
711 const char *user_string, *opt_name;
712 int min_length;
713 boolean val_allowed;
715 int len = (int)strlen(user_string);
717 if (val_allowed) {
718 const char *p = index(user_string, ':'),
719 *q = index(user_string, '=');
721 if (!p || (q && q < p)) p = q;
722 while(p && p > user_string && isspace(*(p-1))) p--;
723 if (p) len = (int)(p - user_string);
726 return (len >= min_length) && !strncmpi(opt_name, user_string, len);
729 /* most environment variables will eventually be printed in an error
730 * message if they don't work, and most error message paths go through
731 * BUFSZ buffers, which could be overflowed by a maliciously long
732 * environment variable. if a variable can legitimately be long, or
733 * if it's put in a smaller buffer, the responsible code will have to
734 * bounds-check itself.
736 char *
737 nh_getenv(ev)
738 const char *ev;
740 char *getev = getenv(ev);
742 if (getev && strlen(getev) <= (BUFSZ / 2))
743 return getev;
744 else
745 return (char *)0;
748 void
749 initoptions()
751 #ifndef MAC
752 char *opts;
753 #endif
754 int i;
756 /* initialize the random number generator */
757 setrandom();
759 /* for detection of configfile options specified multiple times */
760 iflags.opt_booldup = iflags.opt_compdup = (int *)0;
762 for (i = 0; boolopt[i].name; i++) {
763 if (boolopt[i].addr)
764 *(boolopt[i].addr) = boolopt[i].initvalue;
766 flags.end_own = FALSE;
767 flags.end_top = 3;
768 flags.end_around = 2;
769 iflags.runmode = RUN_LEAP;
770 iflags.msg_history = 20;
771 #ifdef TTY_GRAPHICS
772 iflags.prevmsg_window = 's';
773 #endif
774 iflags.menu_headings = ATR_INVERSE;
775 iflags.pilesize = 5;
777 /* Use negative indices to indicate not yet selected */
778 flags.initrole = -1;
779 flags.initrace = -1;
780 flags.initgend = -1;
781 flags.initalign = -1;
783 /* Set the default monster and object class symbols. Don't use */
784 /* memcpy() --- sizeof char != sizeof uchar on some machines. */
785 for (i = 0; i < MAXOCLASSES; i++)
786 oc_syms[i] = (uchar) def_oc_syms[i];
787 for (i = 0; i < MAXMCLASSES; i++)
788 monsyms[i] = (uchar) def_monsyms[i];
789 for (i = 0; i < WARNCOUNT; i++)
790 warnsyms[i] = def_warnsyms[i].sym;
791 iflags.bouldersym = 0;
792 iflags.travelcc.x = iflags.travelcc.y = -1;
793 flags.warnlevel = /*1*/0;
794 flags.warntype = 0L;
796 /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */
797 (void)memcpy((void *)flags.inv_order,
798 (void *)def_inv_order, sizeof flags.inv_order);
799 flags.pickup_types[0] = '\0';
800 flags.pickup_burden = MOD_ENCUMBER;
801 iflags.sortloot = 'n';
803 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
804 flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
805 switch_graphics(ASCII_GRAPHICS); /* set default characters */
806 #if defined(UNIX) && defined(TTY_GRAPHICS)
808 * Set defaults for some options depending on what we can
809 * detect about the environment's capabilities.
810 * This has to be done after the global initialization above
811 * and before reading user-specific initialization via
812 * config file/environment variable below.
814 /* this detects the IBM-compatible console on most 386 boxes */
815 if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) {
816 switch_graphics(IBM_GRAPHICS);
817 # ifdef TEXTCOLOR
818 iflags.use_color = TRUE;
819 # endif
821 #endif /* UNIX && TTY_GRAPHICS */
822 #if defined(UNIX) || defined(VMS)
823 # ifdef TTY_GRAPHICS
824 /* detect whether a "vt" terminal can handle alternate charsets */
825 if ((opts = nh_getenv("TERM")) &&
826 !strncmpi(opts, "vt", 2) && AS && AE &&
827 index(AS, '\016') && index(AE, '\017')) {
828 switch_graphics(DEC_GRAPHICS);
830 # endif
831 #endif /* UNIX || VMS */
833 #ifdef MAC_GRAPHICS_ENV
834 switch_graphics(MAC_GRAPHICS);
835 #endif /* MAC_GRAPHICS_ENV */
836 flags.menu_style = MENU_FULL;
838 /* since this is done before init_objects(), do partial init here */
839 objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
840 nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
841 #ifndef MAC
842 opts = getenv(NETHACK_ENV_OPTIONS);
843 if (!opts) opts = getenv("NETHACKOPTIONS");
844 if (!opts) opts = getenv("HACKOPTIONS");
845 if (opts) {
846 if (*opts == '/' || *opts == '\\' || *opts == '@') {
847 if (*opts == '@') opts++; /* @filename */
848 /* looks like a filename */
849 if (strlen(opts) < BUFSZ/2)
850 read_config_file(opts);
851 } else {
852 read_config_file((char *)0);
853 /* let the total length of options be long;
854 * parseoptions() will check each individually
856 parseoptions(opts, TRUE, FALSE);
858 } else
859 #endif
860 read_config_file((char *)0);
862 (void)fruitadd(pl_fruit);
863 /* Remove "slime mold" from list of object names; this will */
864 /* prevent it from being wished unless it's actually present */
865 /* as a named (or default) fruit. Wishing for "fruit" will */
866 /* result in the player's preferred fruit [better than "\033"]. */
867 obj_descr[SLIME_MOLD].oc_name = "fruit";
869 if (flags.lit_corridor && iflags.use_color) {
870 showsyms[S_darkroom]=showsyms[S_room];
871 } else {
872 showsyms[S_darkroom]=showsyms[S_stone];
875 #if defined(GL_GRAPHICS) || defined(SDL_GRAPHICS)
876 /* -AJA- SDL/GL support. Needs to happen after main config
877 * file has been read.
879 opts = getenv(SDLGL_ENV_VAR);
880 if (opts)
881 Sdlgl_parse_options(opts, TRUE, FALSE);
882 #endif
884 return;
887 STATIC_OVL void
888 nmcpy(dest, src, maxlen)
889 char *dest;
890 const char *src;
891 int maxlen;
893 int count;
895 for(count = 1; count < maxlen; count++) {
896 if(*src == ',' || *src == '\0') break; /*exit on \0 terminator*/
897 *dest++ = *src++;
899 *dest = 0;
903 * escapes(): escape expansion for showsyms. C-style escapes understood
904 * include \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal).
905 * (Note: unlike in C, leading digit 0 is not used to indicate octal;
906 * the letter o (either upper or lower case) is used for that.
907 * The ^-prefix for control characters is also understood, and \[mM]
908 * has the effect of 'meta'-ing the value which follows (so that the
909 * alternate character set will be enabled).
911 * X normal key X
912 * ^X control-X
913 * \mX meta-X
915 * For 3.4.3 and earlier, input ending with "\M", backslash, or caret
916 * prior to terminating '\0' would pull that '\0' into the output and then
917 * keep processing past it, potentially overflowing the output buffer.
918 * Now, trailing \ or ^ will act like \\ or \^ and add '\\' or '^' to the
919 * output and stop there; trailing \M will fall through to \<other> and
920 * yield 'M', then stop. Any \X or \O followed by something other than
921 * an appropriate digit will also fall through to \<other> and yield 'X'
922 * or 'O', plus stop if the non-digit is end-of-string.
924 STATIC_OVL void
925 escapes(cp, tp)
926 const char *cp; /* might be 'tp', updating in place */
927 char *tp; /* result is never longer than 'cp' */
929 static NEARDATA const char oct[] = "01234567", dec[] = "0123456789",
930 hex[] = "00112233445566778899aAbBcCdDeEfF";
931 const char *dp;
932 int cval, meta, dcount;
934 while (*cp) {
935 /* \M has to be followed by something to do meta conversion,
936 otherwise it will just be \M which ultimately yields 'M' */
937 meta = (*cp == '\\' && (cp[1] == 'm' || cp[1] == 'M') && cp[2]);
938 if (meta)
939 cp += 2;
941 cval = dcount = 0; /* for decimal, octal, hexadecimal cases */
942 if ((*cp != '\\' && *cp != '^') || !cp[1]) {
943 /* simple character, or nothing left for \ or ^ to escape */
944 cval = *cp++;
945 } else if (*cp == '^') { /* expand control-character syntax */
946 cval = (*++cp & 0x1f);
947 ++cp;
949 /* remaining cases are all for backslash; we know cp[1] is not \0 */
950 } else if (index(dec, cp[1])) {
951 ++cp; /* move past backslash to first digit */
952 do {
953 cval = (cval * 10) + (*cp - '0');
954 } while (*++cp && index(dec, *cp) && ++dcount < 3);
955 } else if ((cp[1] == 'o' || cp[1] == 'O') && cp[2]
956 && index(oct, cp[2])) {
957 cp += 2; /* move past backslash and 'O' */
958 do {
959 cval = (cval * 8) + (*cp - '0');
960 } while (*++cp && index(oct, *cp) && ++dcount < 3);
961 } else if ((cp[1] == 'x' || cp[1] == 'X') && cp[2]
962 && (dp = index(hex, cp[2])) != 0) {
963 cp += 2; /* move past backslash and 'X' */
964 do {
965 cval = (cval * 16) + ((int) (dp - hex) / 2);
966 } while (*++cp && (dp = index(hex, *cp)) != 0 && ++dcount < 2);
967 } else { /* C-style character escapes */
968 switch (*++cp) {
969 case '\\':
970 cval = '\\';
971 break;
972 case 'n':
973 cval = '\n';
974 break;
975 case 't':
976 cval = '\t';
977 break;
978 case 'b':
979 cval = '\b';
980 break;
981 case 'r':
982 cval = '\r';
983 break;
984 default:
985 cval = *cp;
987 ++cp;
990 if (meta)
991 cval |= 0x80;
992 *tp++ = (char) cval;
994 *tp = '\0';
997 STATIC_OVL void
998 rejectoption(optname)
999 const char *optname;
1001 #ifdef MICRO
1002 pline("\"%s\" settable only from %s.", optname, configfile);
1003 #else
1004 pline("%s can be set only from %s or %s.", optname,
1005 NETHACK_ENV_OPTIONS, configfile);
1006 #endif
1009 STATIC_OVL void
1010 badoption(opts)
1011 const char *opts;
1013 if (!initial) {
1014 if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1))
1015 option_help();
1016 else
1017 pline("Bad syntax: %s. Enter \"?g\" for help.", opts);
1018 return;
1020 #ifdef MAC
1021 else return;
1022 #endif
1024 if(from_file)
1025 raw_printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts);
1026 else
1027 raw_printf("Bad syntax in %s: %s.", NETHACK_ENV_OPTIONS, opts);
1029 wait_synch();
1032 STATIC_OVL void
1033 badauthoption(opts)
1034 const char *opts;
1036 raw_printf("Bad syntax in AUTHENTICATION in %s: %s.", configfile, opts);
1037 wait_synch();
1040 STATIC_OVL void
1041 badtileoption(opts)
1042 const char *opts;
1044 raw_printf("Bad syntax in TILESET in %s: %s.", configfile, opts);
1045 wait_synch();
1048 STATIC_OVL char *
1049 string_for_opt(opts, val_optional)
1050 char *opts;
1051 boolean val_optional;
1053 char *colon, *equals;
1055 colon = index(opts, ':');
1056 equals = index(opts, '=');
1057 if (!colon || (equals && equals < colon)) colon = equals;
1059 if (!colon || !*++colon) {
1060 if (!val_optional) badoption(opts);
1061 return (char *)0;
1063 return colon;
1066 STATIC_OVL char *
1067 string_for_auth_opt(opts, val_optional)
1068 char *opts;
1069 boolean val_optional;
1071 char *colon = string_for_opt(opts, TRUE);
1072 if (!colon && !val_optional) badauthoption(opts);
1073 return colon;
1076 STATIC_OVL char *
1077 string_for_tile_opt(opts, val_optional)
1078 char *opts;
1079 boolean val_optional;
1081 char *colon = string_for_opt(opts, TRUE);
1082 if (!colon && !val_optional) badtileoption(opts);
1083 return colon;
1086 STATIC_OVL char *
1087 string_for_env_opt(optname, opts, val_optional)
1088 const char *optname;
1089 char *opts;
1090 boolean val_optional;
1092 if(!initial) {
1093 rejectoption(optname);
1094 return (char *)0;
1096 return string_for_opt(opts, val_optional);
1099 STATIC_OVL void
1100 bad_negation(optname, with_parameter)
1101 const char *optname;
1102 boolean with_parameter;
1104 pline_The("%s option may not %sbe negated.",
1105 optname,
1106 with_parameter ? "both have a value and " : "");
1110 * Change the inventory order, using the given string as the new order.
1111 * Missing characters in the new order are filled in at the end from
1112 * the current inv_order, except for gold, which is forced to be first
1113 * if not explicitly present.
1115 * This routine returns 1 unless there is a duplicate or bad char in
1116 * the string.
1118 STATIC_OVL int
1119 change_inv_order(op)
1120 char *op;
1122 int oc_sym, num;
1123 char *sp, buf[BUFSZ];
1125 num = 0;
1126 #ifndef GOLDOBJ
1127 if (!index(op, GOLD_SYM))
1128 buf[num++] = COIN_CLASS;
1129 #else
1130 /* !!!! probably unnecessary with gold as normal inventory */
1131 #endif
1133 for (sp = op; *sp; sp++) {
1134 oc_sym = def_char_to_objclass(*sp);
1135 /* reject bad or duplicate entries */
1136 if (oc_sym == MAXOCLASSES ||
1137 oc_sym == RANDOM_CLASS || oc_sym == ILLOBJ_CLASS ||
1138 !index(flags.inv_order, oc_sym) || index(sp+1, *sp))
1139 return 0;
1140 /* retain good ones */
1141 buf[num++] = (char) oc_sym;
1143 buf[num] = '\0';
1145 /* fill in any omitted classes, using previous ordering */
1146 for (sp = flags.inv_order; *sp; sp++)
1147 if (!index(buf, *sp)) {
1148 buf[num++] = *sp;
1149 buf[num] = '\0'; /* explicitly terminate for next index() */
1152 strcpy(flags.inv_order, buf);
1153 return 1;
1156 STATIC_OVL void
1157 graphics_opts(opts, optype, maxlen, offset)
1158 register char *opts;
1159 const char *optype;
1160 int maxlen, offset;
1162 uchar translate[MAXPCHARS+1];
1163 int length, i;
1165 if (!(opts = string_for_env_opt(optype, opts, FALSE)))
1166 return;
1167 escapes(opts, opts);
1169 length = strlen(opts);
1170 if (length > maxlen) length = maxlen;
1171 /* match the form obtained from PC configuration files */
1172 for (i = 0; i < length; i++)
1173 translate[i] = (uchar) opts[i];
1174 assign_graphics(translate, length, maxlen, offset);
1177 STATIC_OVL void
1178 warning_opts(opts, optype)
1179 register char *opts;
1180 const char *optype;
1182 uchar translate[MAXPCHARS+1];
1183 int length, i;
1185 if (!(opts = string_for_env_opt(optype, opts, FALSE)))
1186 return;
1187 escapes(opts, opts);
1189 length = strlen(opts);
1190 if (length > WARNCOUNT) length = WARNCOUNT;
1191 /* match the form obtained from PC configuration files */
1192 for (i = 0; i < length; i++)
1193 translate[i] = (((i < WARNCOUNT) && opts[i]) ?
1194 (uchar) opts[i] : def_warnsyms[i].sym);
1195 assign_warnings(translate);
1198 void
1199 assign_warnings(graph_chars)
1200 register uchar *graph_chars;
1202 int i;
1203 for (i = 0; i < WARNCOUNT; i++)
1204 if (graph_chars[i]) warnsyms[i] = graph_chars[i];
1207 STATIC_OVL int
1208 feature_alert_opts(op, optn)
1209 char *op;
1210 const char *optn;
1212 char buf[BUFSZ];
1213 boolean rejectver = FALSE;
1214 unsigned long fnv = get_feature_notice_ver(op); /* version.c */
1215 if (fnv == 0L) return 0;
1216 if (fnv > get_current_feature_ver())
1217 rejectver = TRUE;
1218 else
1219 flags.suppress_alert = fnv;
1220 if (rejectver) {
1221 if (!initial)
1222 You_cant("disable new feature alerts for future versions.");
1223 else {
1224 sprintf(buf,
1225 "\n%s=%s Invalid reference to a future version ignored",
1226 optn, op);
1227 badoption(buf);
1229 return 0;
1231 if (!initial) {
1232 sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
1233 FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
1234 pline("Feature change alerts disabled for Slash'EM %s features and prior.",
1235 buf);
1237 return 1;
1240 void
1241 set_duplicate_opt_detection(on_or_off)
1242 int on_or_off;
1244 int k, *optptr;
1245 if (on_or_off != 0) {
1246 /*-- ON --*/
1247 if (iflags.opt_booldup)
1248 impossible("iflags.opt_booldup already on (memory leak)");
1249 iflags.opt_booldup = (int *)alloc(SIZE(boolopt) * sizeof(int));
1250 optptr = iflags.opt_booldup;
1251 for (k = 0; k < SIZE(boolopt); ++k)
1252 *optptr++ = 0;
1254 if (iflags.opt_compdup)
1255 impossible("iflags.opt_compdup already on (memory leak)");
1256 iflags.opt_compdup = (int *)alloc(SIZE(compopt) * sizeof(int));
1257 optptr = iflags.opt_compdup;
1258 for (k = 0; k < SIZE(compopt); ++k)
1259 *optptr++ = 0;
1260 } else {
1261 /*-- OFF --*/
1262 if (iflags.opt_booldup) free((void *) iflags.opt_booldup);
1263 iflags.opt_booldup = (int *)0;
1264 if (iflags.opt_compdup) free((void *) iflags.opt_compdup);
1265 iflags.opt_compdup = (int *)0;
1269 STATIC_OVL void
1270 duplicate_opt_detection(opts, bool_or_comp)
1271 const char *opts;
1272 int bool_or_comp; /* 0 == boolean option, 1 == compound */
1274 int i, *optptr;
1275 #if defined(MAC)
1276 /* the Mac has trouble dealing with the output of messages while
1277 * processing the config file. That should get fixed one day.
1278 * For now just return.
1280 return;
1281 #endif
1282 if ((bool_or_comp == 0) && iflags.opt_booldup && initial && from_file) {
1283 for (i = 0; boolopt[i].name; i++) {
1284 if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
1285 optptr = iflags.opt_booldup + i;
1286 if (*optptr == 1) {
1287 raw_printf(
1288 "\nWarning - Boolean option specified multiple times: %s.\n",
1289 opts);
1290 wait_synch();
1292 *optptr += 1;
1293 break; /* don't match multiple options */
1296 } else if ((bool_or_comp == 1) && iflags.opt_compdup && initial && from_file) {
1297 for (i = 0; compopt[i].name; i++) {
1298 if (match_optname(opts, compopt[i].name, strlen(compopt[i].name), TRUE)) {
1299 optptr = iflags.opt_compdup + i;
1300 if (*optptr == 1) {
1301 raw_printf(
1302 "\nWarning - compound option specified multiple times: %s.\n",
1303 compopt[i].name);
1304 wait_synch();
1306 *optptr += 1;
1307 break; /* don't match multiple options */
1313 #ifdef MENU_COLOR
1314 extern struct menucoloring *menu_colorings;
1316 static const struct {
1317 const char *name;
1318 const int color;
1319 } colornames[] = {
1320 {"black", CLR_BLACK},
1321 {"red", CLR_RED},
1322 {"green", CLR_GREEN},
1323 {"brown", CLR_BROWN},
1324 {"blue", CLR_BLUE},
1325 {"magenta", CLR_MAGENTA},
1326 {"cyan", CLR_CYAN},
1327 {"gray", CLR_GRAY},
1328 {"orange", CLR_ORANGE},
1329 {"lightgreen", CLR_BRIGHT_GREEN},
1330 {"yellow", CLR_YELLOW},
1331 {"lightblue", CLR_BRIGHT_BLUE},
1332 {"lightmagenta", CLR_BRIGHT_MAGENTA},
1333 {"lightcyan", CLR_BRIGHT_CYAN},
1334 {"white", CLR_WHITE}
1337 static const struct {
1338 const char *name;
1339 const int attr;
1340 } attrnames[] = {
1341 {"none", ATR_NONE},
1342 {"bold", ATR_BOLD},
1343 {"dim", ATR_DIM},
1344 {"underline", ATR_ULINE},
1345 {"blink", ATR_BLINK},
1346 {"inverse", ATR_INVERSE}
1350 /* parse '"regex_string"=color' and add it to menucoloring */
1351 boolean
1352 add_menu_coloring(str)
1353 char *str;
1357 int i, c = NO_COLOR, a = ATR_NONE;
1358 struct menucoloring *tmp;
1359 char *tmps, *cs = strchr(str, '=');
1360 #ifdef POSIX_REGEX
1361 int errnum;
1362 char errbuf[80];
1363 #endif
1364 const char *err = (char *)0;
1366 if (!cs || !str) return FALSE;
1368 tmps = cs;
1369 tmps++;
1370 while (*tmps && isspace(*tmps)) tmps++;
1372 for (i = 0; i < SIZE(colornames); i++)
1373 if (strstri(tmps, colornames[i].name) == tmps) {
1374 c = colornames[i].color;
1375 break;
1377 if ((i == SIZE(colornames)) && (*tmps >= '0' && *tmps <='9'))
1378 c = atoi(tmps);
1380 if (c > 15) return FALSE;
1382 tmps = strchr(str, '&');
1383 if (tmps) {
1384 tmps++;
1385 while (*tmps && isspace(*tmps)) tmps++;
1386 for (i = 0; i < SIZE(attrnames); i++)
1387 if (strstri(tmps, attrnames[i].name) == tmps) {
1388 a = attrnames[i].attr;
1389 break;
1391 if ((i == SIZE(attrnames)) && (*tmps >= '0' && *tmps <='9'))
1392 a = atoi(tmps);
1395 *cs = '\0';
1396 tmps = str;
1397 if ((*tmps == '"') || (*tmps == '\'')) {
1398 cs--;
1399 while (isspace(*cs)) cs--;
1400 if (*cs == *tmps) {
1401 *cs = '\0';
1402 tmps++;
1406 tmp = (struct menucoloring *)alloc(sizeof(struct menucoloring));
1408 #ifdef USE_REGEX_MATCH
1409 # ifdef GNU_REGEX
1410 tmp->match.translate = 0;
1411 tmp->match.fastmap = 0;
1412 tmp->match.buffer = 0;
1413 tmp->match.allocated = 0;
1414 tmp->match.regs_allocated = REGS_FIXED;
1415 err = re_compile_pattern(tmps, strlen(tmps), &tmp->match);
1416 # else
1417 # ifdef POSIX_REGEX
1418 errnum = regcomp(&tmp->match, tmps, REG_EXTENDED | REG_NOSUB);
1419 if (errnum != 0) {
1420 regerror(errnum, &tmp->match, errbuf, sizeof(errbuf));
1421 err = errbuf;
1423 # endif
1424 # endif
1425 #else
1426 tmp->match = (char *)alloc(strlen(tmps)+1);
1427 (void) memcpy((void *)tmp->match, (void *)tmps, strlen(tmps)+1);
1428 #endif
1429 if (err) {
1430 raw_printf("\nMenucolor regex error: %s\n", err);
1431 wait_synch();
1432 free(tmp);
1433 return FALSE;
1434 } else {
1435 tmp->next = menu_colorings;
1436 tmp->color = c;
1437 tmp->attr = a;
1438 menu_colorings = tmp;
1439 return TRUE;
1442 #endif /* MENU_COLOR */
1444 #if defined(STATUS_COLORS) && defined(TEXTCOLOR)
1446 struct name_value {
1447 char *name;
1448 int value;
1451 const struct name_value status_colornames[] = {
1452 { "black", CLR_BLACK },
1453 { "red", CLR_RED },
1454 { "green", CLR_GREEN },
1455 { "brown", CLR_BROWN },
1456 { "blue", CLR_BLUE },
1457 { "magenta", CLR_MAGENTA },
1458 { "cyan", CLR_CYAN },
1459 { "gray", CLR_GRAY },
1460 { "orange", CLR_ORANGE },
1461 { "lightgreen", CLR_BRIGHT_GREEN },
1462 { "yellow", CLR_YELLOW },
1463 { "lightblue", CLR_BRIGHT_BLUE },
1464 { "lightmagenta", CLR_BRIGHT_MAGENTA },
1465 { "lightcyan", CLR_BRIGHT_CYAN },
1466 { "white", CLR_WHITE },
1467 { NULL, -1 }
1470 const struct name_value status_attrnames[] = {
1471 { "none", ATR_NONE },
1472 { "bold", ATR_BOLD },
1473 { "dim", ATR_DIM },
1474 { "underline", ATR_ULINE },
1475 { "blink", ATR_BLINK },
1476 { "inverse", ATR_INVERSE },
1477 { NULL, -1 }
1481 value_of_name(name, name_values)
1482 const char *name;
1483 const struct name_value *name_values;
1485 while (name_values->name && !strstri(name_values->name, name))
1486 ++name_values;
1487 return name_values->value;
1490 struct color_option
1491 parse_color_option(start)
1492 char *start;
1494 struct color_option result = {NO_COLOR, 0};
1495 char last;
1496 char *end;
1497 int attr;
1499 for (end = start; *end != '&' && *end != '\0'; ++end);
1500 last = *end;
1501 *end = '\0';
1502 result.color = value_of_name(start, status_colornames);
1504 while (last == '&') {
1505 for (start = ++end; *end != '&' && *end != '\0'; ++end);
1506 last = *end;
1507 *end = '\0';
1508 attr = value_of_name(start, status_attrnames);
1509 if (attr >= 0)
1510 result.attr_bits |= 1 << attr;
1513 return result;
1516 const struct percent_color_option *hp_colors = NULL;
1517 const struct percent_color_option *pw_colors = NULL;
1518 const struct text_color_option *text_colors = NULL;
1520 struct percent_color_option *
1521 add_percent_option(new_option, list_head)
1522 struct percent_color_option *new_option;
1523 struct percent_color_option *list_head;
1525 if (list_head == NULL)
1526 return new_option;
1527 if (new_option->percentage <= list_head->percentage) {
1528 new_option->next = list_head;
1529 return new_option;
1531 list_head->next = add_percent_option(new_option, list_head->next);
1532 return list_head;
1535 boolean
1536 parse_status_color_option(start)
1537 char *start;
1539 char *middle;
1541 while (*start && isspace(*start)) start++;
1542 for (middle = start; *middle != ':' && *middle != '=' && *middle != '\0'; ++middle);
1543 *middle++ = '\0';
1544 if (middle - start > 2 && start[2] == '%') {
1545 struct percent_color_option *percent_color_option =
1546 (struct percent_color_option *)alloc(sizeof(*percent_color_option));
1547 percent_color_option->next = NULL;
1548 percent_color_option->percentage = atoi(start + 3);
1549 percent_color_option->color_option = parse_color_option(middle);
1550 start[2] = '\0';
1551 if (percent_color_option->color_option.color >= 0
1552 && percent_color_option->color_option.attr_bits >= 0) {
1553 if (!strcmpi(start, "hp")) {
1554 hp_colors = add_percent_option(percent_color_option, hp_colors);
1555 return TRUE;
1557 if (!strcmpi(start, "pw")) {
1558 pw_colors = add_percent_option(percent_color_option, pw_colors);
1559 return TRUE;
1562 free(percent_color_option);
1563 return FALSE;
1564 } else {
1565 int length = strlen(start) + 1;
1566 struct text_color_option *text_color_option =
1567 (struct text_color_option *)alloc(sizeof(*text_color_option));
1568 text_color_option->next = NULL;
1569 text_color_option->text = (char *)alloc(length);
1570 memcpy((char *)text_color_option->text, start, length);
1571 text_color_option->color_option = parse_color_option(middle);
1572 if (text_color_option->color_option.color >= 0
1573 && text_color_option->color_option.attr_bits >= 0) {
1574 text_color_option->next = text_colors;
1575 text_colors = text_color_option;
1576 return TRUE;
1578 free(text_color_option->text);
1579 free(text_color_option);
1580 return FALSE;
1584 boolean
1585 parse_status_color_options(start)
1586 char *start;
1588 char last = ',';
1589 char *end = start - 1;
1590 boolean ok = TRUE;
1591 while (last == ',') {
1592 for (start = ++end; *end != ',' && *end != '\0'; ++end);
1593 last = *end;
1594 *end = '\0';
1595 ok = parse_status_color_option(start) && ok;
1597 return ok;
1601 #endif /* STATUS_COLORS */
1603 void
1604 parseoptions(opts, tinitial, tfrom_file)
1605 register char *opts;
1606 boolean tinitial, tfrom_file;
1608 register char *op;
1609 unsigned num;
1610 boolean negated;
1611 int i;
1612 const char *fullname;
1614 initial = tinitial;
1615 from_file = tfrom_file;
1616 if ((op = index(opts, ',')) != 0) {
1617 *op++ = 0;
1618 parseoptions(op, initial, from_file);
1620 if (strlen(opts) > BUFSZ/2) {
1621 badoption("option too long");
1622 return;
1625 /* strip leading and trailing white space */
1626 opts = stripspace(opts);
1628 if (!*opts) return;
1629 negated = FALSE;
1630 while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
1631 if (*opts == '!') opts++; else opts += 2;
1632 negated = !negated;
1635 /* variant spelling */
1637 if (match_optname(opts, "hybridangbander", 15, FALSE)) {
1638 flags.hybridization++;
1640 if (match_optname(opts, "hybridaquarian", 14, FALSE)) {
1641 flags.hybridization++;
1643 if (match_optname(opts, "hybridcurser", 12, FALSE)) {
1644 flags.hybridization++;
1646 if (match_optname(opts, "hybridhaxor", 11, FALSE)) {
1647 flags.hybridization++;
1649 if (match_optname(opts, "hybridhomicider", 15, FALSE)) {
1650 flags.hybridization++;
1652 if (match_optname(opts, "hybridsuxxor", 11, FALSE)) {
1653 flags.hybridization++;
1655 if (match_optname(opts, "hybridwarper", 12, FALSE)) {
1656 flags.hybridization++;
1658 if (match_optname(opts, "hybridrandomizer", 16, FALSE)) {
1659 flags.hybridization++;
1661 if (match_optname(opts, "hybridnullrace", 14, FALSE)) {
1662 flags.hybridization++;
1664 if (match_optname(opts, "hybridmazewalker", 16, FALSE)) {
1665 flags.hybridization++;
1667 if (match_optname(opts, "hybridsoviet", 12, FALSE)) {
1668 flags.hybridization++;
1670 if (match_optname(opts, "hybridxrace", 11, FALSE)) {
1671 flags.hybridization++;
1673 if (match_optname(opts, "hybridheretic", 13, FALSE)) {
1674 flags.hybridization++;
1676 if (match_optname(opts, "hybridsokosolver", 16, FALSE)) {
1677 flags.hybridization++;
1679 if (match_optname(opts, "hybridspecialist", 16, FALSE)) {
1680 flags.hybridization++;
1682 if (match_optname(opts, "hybridamerican", 14, FALSE)) {
1683 flags.hybridization++;
1685 if (match_optname(opts, "hybridminimalist", 16, FALSE)) {
1686 flags.hybridization++;
1688 if (match_optname(opts, "hybridnastinator", 16, FALSE)) {
1689 flags.hybridization++;
1691 if (match_optname(opts, "hybridrougelike", 15, FALSE)) {
1692 flags.hybridization++;
1694 if (match_optname(opts, "hybridsegfaulter", 16, FALSE)) {
1695 flags.hybridization++;
1697 if (match_optname(opts, "hybridironman", 13, FALSE)) {
1698 flags.hybridization++;
1700 if (match_optname(opts, "hybridamnesiac", 14, FALSE)) {
1701 flags.hybridization++;
1703 if (match_optname(opts, "hybridproblematic", 17, FALSE)) {
1704 flags.hybridization++;
1706 if (match_optname(opts, "hybridwindinhabitant", 20, FALSE)) {
1707 flags.hybridization++;
1709 if (match_optname(opts, "hybridaggravator", 16, FALSE)) {
1710 flags.hybridization++;
1712 if (match_optname(opts, "hybridevilvariant", 17, FALSE)) {
1713 flags.hybridization++;
1715 if (match_optname(opts, "hybridlevelscaler", 17, FALSE)) {
1716 flags.hybridization++;
1718 if (match_optname(opts, "hybriderosator", 14, FALSE)) {
1719 flags.hybridization++;
1721 if (match_optname(opts, "hybridroommate", 14, FALSE)) {
1722 flags.hybridization++;
1724 if (match_optname(opts, "hybridextravator", 16, FALSE)) {
1725 flags.hybridization++;
1727 if (match_optname(opts, "hybridhallucinator", 18, FALSE)) {
1728 flags.hybridization++;
1730 if (match_optname(opts, "hybridbossrusher", 16, FALSE)) {
1731 flags.hybridization++;
1733 if (match_optname(opts, "hybriddorian", 12, FALSE)) {
1734 flags.hybridization++;
1736 if (match_optname(opts, "hybridtechless", 14, FALSE)) {
1737 flags.hybridization++;
1739 if (match_optname(opts, "hybridblait", 11, FALSE)) {
1740 flags.hybridization++;
1742 if (match_optname(opts, "hybridgrouper", 13, FALSE)) {
1743 flags.hybridization++;
1745 if (match_optname(opts, "hybridscriptor", 14, FALSE)) {
1746 flags.hybridization++;
1748 if (match_optname(opts, "hybridunbalancor", 16, FALSE)) {
1749 flags.hybridization++;
1751 if (match_optname(opts, "hybridbeacher", 13, FALSE)) {
1752 flags.hybridization++;
1754 if (match_optname(opts, "hybridstairseeker", 17, FALSE)) {
1755 flags.hybridization++;
1757 if (match_optname(opts, "hybridmatrayser", 15, FALSE)) {
1758 flags.hybridization++;
1760 if (match_optname(opts, "hybridfeminizer", 15, FALSE)) {
1761 flags.hybridization++;
1763 if (match_optname(opts, "hybridchallenger", 16, FALSE)) {
1764 flags.hybridization++;
1766 if (match_optname(opts, "hybridhardmoder", 15, FALSE)) {
1767 flags.hybridization++;
1769 if (match_optname(opts, "hybridstunfish", 14, FALSE)) {
1770 flags.hybridization++;
1772 if (match_optname(opts, "hybridkillfiller", 16, FALSE)) {
1773 flags.hybridization++;
1775 if (match_optname(opts, "hybridbadstatter", 16, FALSE)) {
1776 flags.hybridization++;
1778 if (match_optname(opts, "hybriddroughter", 15, FALSE)) {
1779 flags.hybridization++;
1781 if (match_optname(opts, "hybridvanillaoid", 16, FALSE)) {
1782 flags.hybridization++;
1785 if (match_optname(opts, "colour", 5, FALSE))
1786 strcpy(opts, "color"); /* fortunately this isn't longer */
1787 if (match_optname(opts, "menucolours", 11, FALSE))
1788 strcpy(opts, "menucolors"); /* fortunately this isn't longer */
1789 if (match_optname(opts, "statuscolours", 13, FALSE))
1790 strcpy(opts, "statuscolors"); /* fortunately this isn't longer */
1792 if (!match_optname(opts, "subkeyvalue", 11, TRUE)) /* allow multiple */
1793 duplicate_opt_detection(opts, 1); /* 1 means compound opts */
1795 /* special boolean options */
1797 if (match_optname(opts, "female", 3, FALSE)) {
1798 if(!initial && flags.female == negated)
1799 pline("That is not anatomically possible.");
1800 else
1801 flags.initgend = flags.female = !negated;
1802 return;
1805 if (match_optname(opts, "male", 4, FALSE)) {
1806 if(!initial && flags.female != negated)
1807 pline("That is not anatomically possible.");
1808 else
1809 flags.initgend = flags.female = negated;
1810 return;
1813 #if defined(MICRO) && !defined(AMIGA)
1814 /* included for compatibility with old NetHack.cnf files */
1815 if (match_optname(opts, "IBM_", 4, FALSE)) {
1816 iflags.BIOS = !negated;
1817 return;
1819 #endif /* MICRO */
1821 /* compound options */
1823 fullname = "pettype";
1824 if (match_optname(opts, fullname, 3, TRUE)) {
1825 if ((op = string_for_env_opt(fullname, opts, negated)) != 0) {
1826 if (negated) bad_negation(fullname, TRUE);
1827 else switch (*op) {
1828 case 'd': /* dog */
1829 case 'D':
1830 preferred_pet = 'd';
1831 break;
1832 case 'c': /* cat */
1833 case 'C':
1834 case 'f': /* feline */
1835 case 'F':
1836 preferred_pet = 'c';
1837 break;
1838 case 'n': /* no pet */
1839 case 'N':
1840 preferred_pet = 'n';
1841 break;
1842 default:
1843 pline("Unrecognized pet type '%s'.", op);
1844 break;
1846 } else if (negated) preferred_pet = 'n';
1847 return;
1850 fullname = "ghoulname";
1851 if (match_optname(opts, fullname, 3, TRUE)) {
1852 if (negated) bad_negation(fullname, FALSE);
1853 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1854 nmcpy(ghoulname, op, PL_PSIZ);
1855 return;
1858 fullname = "wolfname";
1859 if (match_optname(opts, fullname, 3, TRUE)) {
1860 if (negated) bad_negation(fullname, FALSE);
1861 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1862 nmcpy(wolfname, op, PL_PSIZ);
1863 return;
1866 fullname = "catname";
1867 if (match_optname(opts, fullname, 3, TRUE)) {
1868 if (negated) bad_negation(fullname, FALSE);
1869 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1870 nmcpy(catname, op, PL_PSIZ);
1871 return;
1874 fullname = "dogname";
1875 if (match_optname(opts, fullname, 3, TRUE)) {
1876 if (negated) bad_negation(fullname, FALSE);
1877 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1878 nmcpy(dogname, op, PL_PSIZ);
1879 return;
1882 fullname = "monkeyname";
1883 if (match_optname(opts, fullname, 3, TRUE)) {
1884 if (negated) bad_negation(fullname, FALSE);
1885 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1886 nmcpy(monkeyname, op, PL_PSIZ);
1887 return;
1890 fullname = "parrotname";
1891 if (match_optname(opts, fullname, 3, TRUE)) {
1892 if (negated) bad_negation(fullname, FALSE);
1893 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1894 nmcpy(parrotname, op, PL_PSIZ);
1895 return;
1898 fullname = "girlname";
1899 if (match_optname(opts, fullname, 3, TRUE)) {
1900 if (negated) bad_negation(fullname, FALSE);
1901 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1902 nmcpy(girlname, op, PL_PSIZ);
1903 return;
1906 fullname = "boyname";
1907 if (match_optname(opts, fullname, 3, TRUE)) {
1908 if (negated) bad_negation(fullname, FALSE);
1909 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1910 nmcpy(boyname, op, PL_PSIZ);
1911 return;
1914 fullname = "ravenname";
1915 if (match_optname(opts, fullname, 3, TRUE)) {
1916 if (negated) bad_negation(fullname, FALSE);
1917 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1918 nmcpy(ravenname, op, PL_PSIZ);
1919 return;
1922 fullname = "dragonname";
1923 if (match_optname(opts, fullname, 3, TRUE)) {
1924 if (negated) bad_negation(fullname, FALSE);
1925 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1926 nmcpy(dragonname, op, PL_PSIZ);
1927 return;
1930 #ifdef DUMP_LOG
1931 fullname = "dumpfile";
1932 if (match_optname(opts, fullname, 3, TRUE)) {
1933 #ifndef DUMP_FN
1934 if (negated) bad_negation(fullname, FALSE);
1935 else if ((op = string_for_opt(opts, !tfrom_file)) != 0
1936 && strlen(op) > 1)
1937 nmcpy(dump_fn, op, PL_PSIZ);
1938 #endif
1939 return;
1941 #endif
1943 fullname = "horsename";
1944 if (match_optname(opts, fullname, 5, TRUE)) {
1945 if (negated) bad_negation(fullname, FALSE);
1946 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1947 nmcpy(horsename, op, PL_PSIZ);
1948 return;
1951 /* menucolor:"regex_string"=color */
1952 fullname = "menucolor";
1953 if (match_optname(opts, fullname, 9, TRUE)) {
1954 #ifdef MENU_COLOR
1955 if (negated) bad_negation(fullname, FALSE);
1956 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1957 if (!add_menu_coloring(op))
1958 badoption(opts);
1959 #endif
1960 return;
1963 fullname = "ratname";
1964 if (match_optname(opts, fullname, 3, TRUE)) {
1965 if (negated) bad_negation(fullname, FALSE);
1966 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1967 nmcpy(ratname, op, PL_PSIZ);
1968 return;
1971 /* fullname = "lichenname";
1972 if (match_optname(opts, fullname, 3, TRUE)) {
1973 if (negated) bad_negation(fullname, FALSE);
1974 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1975 nmcpy(lichenname, op, PL_PSIZ);
1976 return;
1979 fullname = "coinsname";
1980 if (match_optname(opts, fullname, 3, TRUE)) {
1981 if (negated) bad_negation(fullname, FALSE);
1982 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1983 nmcpy(coinsname, op, PL_PSIZ);
1984 return;
1987 fullname = "rothename";
1988 if (match_optname(opts, fullname, 3, TRUE)) {
1989 if (negated) bad_negation(fullname, FALSE);
1990 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
1991 nmcpy(rothename, op, PL_PSIZ);
1992 return;
1995 fullname = "number_pad";
1996 if (match_optname(opts, fullname, 10, TRUE)) {
1997 boolean compat = (strlen(opts) <= 10);
1998 op = string_for_opt(opts, (compat || !initial));
1999 if (!op) {
2000 if (compat || negated || initial) {
2001 /* for backwards compatibility, "number_pad" without a
2002 value is a synonym for number_pad:1 */
2003 iflags.num_pad = !negated;
2004 if (iflags.num_pad) iflags.num_pad_mode = 0;
2005 number_pad(iflags.num_pad);
2007 return;
2009 if (negated) {
2010 bad_negation("number_pad", TRUE);
2011 return;
2013 if (*op == '1' || *op == '2') {
2014 iflags.num_pad = 1;
2015 if (*op == '2') iflags.num_pad_mode = 1;
2016 else iflags.num_pad_mode = 0;
2017 number_pad(1);
2018 } else if (*op == '0') {
2019 iflags.num_pad = 0;
2020 iflags.num_pad_mode = 0;
2021 number_pad(0);
2022 } else badoption(opts);
2023 return;
2026 fullname = "qwertz_layout";
2027 if (match_optname(opts, fullname, 6, FALSE)) {
2028 if (negated)
2029 sdir=qykbd_dir;
2030 else
2031 sdir=qzkbd_dir;
2032 iflags.qwertz_layout=!negated;
2033 return;
2036 fullname = "runmode";
2037 if (match_optname(opts, fullname, 4, TRUE)) {
2038 if (negated) {
2039 iflags.runmode = RUN_TPORT;
2040 } else if ((op = string_for_opt(opts, FALSE)) != 0) {
2041 if (!strncmpi(op, "teleport", strlen(op)))
2042 iflags.runmode = RUN_TPORT;
2043 else if (!strncmpi(op, "run", strlen(op)))
2044 iflags.runmode = RUN_LEAP;
2045 else if (!strncmpi(op, "walk", strlen(op)))
2046 iflags.runmode = RUN_STEP;
2047 else if (!strncmpi(op, "crawl", strlen(op)))
2048 iflags.runmode = RUN_CRAWL;
2049 else
2050 badoption(opts);
2052 return;
2055 fullname = "msghistory";
2056 if (match_optname(opts, fullname, 3, TRUE)) {
2057 op = string_for_env_opt(fullname, opts, negated);
2058 if ((negated && !op) || (!negated && op)) {
2059 iflags.msg_history = negated ? 0 : atoi(op);
2060 } else if (negated) bad_negation(fullname, TRUE);
2061 return;
2064 fullname="msg_window";
2065 /* msg_window:single, combo, full or reversed */
2066 if (match_optname(opts, fullname, 4, TRUE)) {
2067 /* allow option to be silently ignored by non-tty ports */
2068 #ifdef TTY_GRAPHICS
2069 int tmp;
2070 if (!(op = string_for_opt(opts, TRUE))) {
2071 tmp = negated ? 's' : 'f';
2072 } else {
2073 if (negated) {
2074 bad_negation(fullname, TRUE);
2075 return;
2077 tmp = tolower(*op);
2079 switch (tmp) {
2080 case 's': /* single message history cycle (default if negated) */
2081 iflags.prevmsg_window = 's';
2082 break;
2083 case 'c': /* combination: two singles, then full page reversed */
2084 iflags.prevmsg_window = 'c';
2085 break;
2086 case 'f': /* full page (default if no opts) */
2087 iflags.prevmsg_window = 'f';
2088 break;
2089 case 'r': /* full page (reversed) */
2090 iflags.prevmsg_window = 'r';
2091 break;
2092 default:
2093 badoption(opts);
2095 #endif
2096 return;
2099 /* WINCAP
2100 * setting font options */
2101 fullname = "font";
2102 if (!strncmpi(opts, fullname, 4))
2104 int wintype = -1;
2105 char *fontopts = opts + 4;
2107 if (!strncmpi(fontopts, "map", 3) ||
2108 !strncmpi(fontopts, "_map", 4))
2109 wintype = NHW_MAP;
2110 else if (!strncmpi(fontopts, "message", 7) ||
2111 !strncmpi(fontopts, "_message", 8))
2112 wintype = NHW_MESSAGE;
2113 else if (!strncmpi(fontopts, "text", 4) ||
2114 !strncmpi(fontopts, "_text", 5))
2115 wintype = NHW_TEXT;
2116 else if (!strncmpi(fontopts, "menu", 4) ||
2117 !strncmpi(fontopts, "_menu", 5))
2118 wintype = NHW_MENU;
2119 else if (!strncmpi(fontopts, "status", 6) ||
2120 !strncmpi(fontopts, "_status", 7))
2121 wintype = NHW_STATUS;
2122 else if (!strncmpi(fontopts, "_size", 5)) {
2123 if (!strncmpi(fontopts, "_size_map", 8))
2124 wintype = NHW_MAP;
2125 else if (!strncmpi(fontopts, "_size_message", 12))
2126 wintype = NHW_MESSAGE;
2127 else if (!strncmpi(fontopts, "_size_text", 9))
2128 wintype = NHW_TEXT;
2129 else if (!strncmpi(fontopts, "_size_menu", 9))
2130 wintype = NHW_MENU;
2131 else if (!strncmpi(fontopts, "_size_status", 11))
2132 wintype = NHW_STATUS;
2133 else {
2134 badoption(opts);
2135 return;
2137 if (wintype > 0 && !negated &&
2138 (op = string_for_opt(opts, FALSE)) != 0) {
2139 switch(wintype) {
2140 case NHW_MAP:
2141 iflags.wc_fontsiz_map = atoi(op);
2142 break;
2143 case NHW_MESSAGE:
2144 iflags.wc_fontsiz_message = atoi(op);
2145 break;
2146 case NHW_TEXT:
2147 iflags.wc_fontsiz_text = atoi(op);
2148 break;
2149 case NHW_MENU:
2150 iflags.wc_fontsiz_menu = atoi(op);
2151 break;
2152 case NHW_STATUS:
2153 iflags.wc_fontsiz_status = atoi(op);
2154 break;
2157 return;
2158 } else {
2159 badoption(opts);
2161 if (wintype > 0 &&
2162 (op = string_for_opt(opts, FALSE)) != 0) {
2163 wc_set_font_name(wintype, op);
2164 #ifdef MAC
2165 set_font_name (wintype, op);
2166 #endif
2167 return;
2168 } else if (negated) bad_negation(fullname, TRUE);
2169 return;
2171 #ifdef CHANGE_COLOR
2172 if (match_optname(opts, "palette", 3, TRUE)
2173 # ifdef MAC
2174 || match_optname(opts, "hicolor", 3, TRUE)
2175 # endif
2177 int color_number, color_incr;
2179 # ifdef MAC
2180 if (match_optname(opts, "hicolor", 3, TRUE)) {
2181 if (negated) {
2182 bad_negation("hicolor", FALSE);
2183 return;
2185 color_number = CLR_MAX + 4; /* HARDCODED inverse number */
2186 color_incr = -1;
2187 } else {
2188 # endif
2189 if (negated) {
2190 bad_negation("palette", FALSE);
2191 return;
2193 color_number = 0;
2194 color_incr = 1;
2195 # ifdef MAC
2197 # endif
2198 if ((op = string_for_opt(opts, FALSE)) != (char *)0) {
2199 char *pt = op;
2200 int cnt, tmp, reverse;
2201 long rgb;
2203 while (*pt && color_number >= 0) {
2204 cnt = 3;
2205 rgb = 0L;
2206 if (*pt == '-') {
2207 reverse = 1;
2208 pt++;
2209 } else {
2210 reverse = 0;
2212 while (cnt-- > 0) {
2213 if (*pt && *pt != '/') {
2214 # ifdef AMIGA
2215 rgb <<= 4;
2216 # else
2217 rgb <<= 8;
2218 # endif
2219 tmp = *(pt++);
2220 if (isalpha(tmp)) {
2221 tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */
2222 } else {
2223 tmp &= 0xf; /* Digits in ASCII too... */
2225 # ifndef AMIGA
2226 /* Add an extra so we fill f -> ff and 0 -> 00 */
2227 rgb += tmp << 4;
2228 # endif
2229 rgb += tmp;
2232 if (*pt == '/') {
2233 pt++;
2235 change_color(color_number, rgb, reverse);
2236 color_number += color_incr;
2239 if (!initial) {
2240 need_redraw = TRUE;
2242 return;
2244 #endif /* CHANGE_COLOR */
2246 if (match_optname(opts, "fruit", 2, TRUE)) {
2247 char empty_str = '\0';
2248 op = string_for_opt(opts, negated);
2249 if (negated) {
2250 if (op) {
2251 bad_negation("fruit", TRUE);
2252 return;
2254 op = &empty_str;
2255 goto goodfruit;
2257 if (!op) return;
2258 if (!initial) {
2259 struct fruit *f;
2261 num = 0;
2262 for(f=ffruit; f; f=f->nextf) {
2263 if (!strcmp(op, f->fname)) goto goodfruit;
2264 num++;
2266 if (num >= 100) {
2267 pline("Doing that so many times isn't very fruitful.");
2268 return;
2271 goodfruit:
2272 nmcpy(pl_fruit, op, PL_FSIZ);
2273 /* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */
2274 if (!*pl_fruit)
2275 nmcpy(pl_fruit, "slime mold", PL_FSIZ);
2276 if (!initial)
2277 (void)fruitadd(pl_fruit);
2278 /* If initial, then initoptions is allowed to do it instead
2279 * of here (initoptions always has to do it even if there's
2280 * no fruit option at all. Also, we don't want people
2281 * setting multiple fruits in their options.)
2283 return;
2286 /* graphics:string */
2287 fullname = "graphics";
2288 if (match_optname(opts, fullname, 2, TRUE)) {
2289 if (negated) bad_negation(fullname, FALSE);
2290 else graphics_opts(opts, fullname, MAXPCHARS, 0);
2291 return;
2293 fullname = "dungeon";
2294 if (match_optname(opts, fullname, 2, TRUE)) {
2295 if (negated) bad_negation(fullname, FALSE);
2296 else graphics_opts(opts, fullname, MAXDCHARS, 0);
2297 return;
2299 fullname = "traps";
2300 if (match_optname(opts, fullname, 2, TRUE)) {
2301 if (negated) bad_negation(fullname, FALSE);
2302 else graphics_opts(opts, fullname, MAXTCHARS, MAXDCHARS);
2303 return;
2305 fullname = "effects";
2306 if (match_optname(opts, fullname, 2, TRUE)) {
2307 if (negated) bad_negation(fullname, FALSE);
2308 else
2309 graphics_opts(opts, fullname, MAXECHARS, MAXDCHARS+MAXTCHARS);
2310 return;
2313 /* objects:string */
2314 fullname = "objects";
2315 if (match_optname(opts, fullname, 7, TRUE)) {
2316 int length;
2318 if (negated) {
2319 bad_negation(fullname, FALSE);
2320 return;
2322 if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
2323 return;
2324 escapes(opts, opts);
2327 * Override the default object class symbols. The first
2328 * object in the object class is the "random object". I
2329 * don't want to use 0 as an object class, so the "random
2330 * object" is basically a place holder.
2332 * The object class symbols have already been initialized in
2333 * initoptions().
2335 length = strlen(opts);
2336 if (length >= MAXOCLASSES)
2337 length = MAXOCLASSES-1; /* don't count RANDOM_OBJECT */
2339 for (i = 0; i < length; i++)
2340 oc_syms[i+1] = (uchar) opts[i];
2341 return;
2344 /* monsters:string */
2345 fullname = "monsters";
2346 if (match_optname(opts, fullname, 8, TRUE)) {
2347 int length;
2349 if (negated) {
2350 bad_negation(fullname, FALSE);
2351 return;
2353 if (!(opts = string_for_env_opt(fullname, opts, FALSE)))
2354 return;
2355 escapes(opts, opts);
2357 /* Override default mon class symbols set in initoptions(). */
2358 length = strlen(opts);
2359 if (length >= MAXMCLASSES)
2360 length = MAXMCLASSES-1; /* mon class 0 unused */
2362 for (i = 0; i < length; i++)
2363 monsyms[i+1] = (uchar) opts[i];
2364 return;
2366 fullname = "warnings";
2367 if (match_optname(opts, fullname, 5, TRUE)) {
2368 if (negated) bad_negation(fullname, FALSE);
2369 else warning_opts(opts, fullname);
2370 return;
2372 /* boulder:symbol */
2373 fullname = "boulder";
2374 if (match_optname(opts, fullname, 7, TRUE)) {
2375 int clash = 0;
2376 if (negated) {
2377 bad_negation(fullname, FALSE);
2378 return;
2380 /* if (!(opts = string_for_env_opt(fullname, opts, FALSE))) */
2381 if (!(opts = string_for_opt(opts, FALSE)))
2382 return;
2383 escapes(opts, opts);
2384 if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
2385 clash = 1;
2386 else if (opts[0] >= '1' && opts[0] <= '5')
2387 clash = 2;
2388 if (clash) {
2389 /* symbol chosen matches a used monster or warning
2390 symbol which is not good - reject it*/
2391 pline(
2392 "Badoption - boulder symbol '%c' conflicts with a %s symbol.",
2393 opts[0], (clash == 1) ? "monster" : "warning");
2394 } else {
2396 * Override the default boulder symbol.
2398 iflags.bouldersym = (uchar) opts[0];
2400 if (!initial) need_redraw = TRUE;
2401 return;
2404 /* name:string */
2405 fullname = "name";
2406 if (match_optname(opts, fullname, 4, TRUE)) {
2407 if (negated) bad_negation(fullname, FALSE);
2408 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
2409 #ifdef PROXY_GRAPHICS
2411 * Can't change player name if authentication required.
2413 if (!getenv("HACKAUTHENTICATION"))
2414 #endif
2415 nmcpy(plname, op, PL_NSIZ);
2416 return;
2419 /* role:string or character:string */
2420 fullname = "role";
2421 if (match_optname(opts, fullname, 4, TRUE) ||
2422 match_optname(opts, (fullname = "character"), 4, TRUE)) {
2423 if (negated) bad_negation(fullname, FALSE);
2424 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2425 if ((flags.initrole = str2role(op)) == ROLE_NONE)
2426 badoption(opts);
2427 else /* Backwards compatibility */
2428 nmcpy(pl_character, op, PL_NSIZ);
2430 return;
2433 /* race:string */
2434 fullname = "race";
2435 if (match_optname(opts, fullname, 4, TRUE)) {
2436 if (negated) bad_negation(fullname, FALSE);
2437 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2438 if ((flags.initrace = str2race(op)) == ROLE_NONE)
2439 badoption(opts);
2440 else /* Backwards compatibility */
2441 pl_race = *op;
2443 return;
2446 /* gender:string */
2447 fullname = "gender";
2448 if (match_optname(opts, fullname, 4, TRUE)) {
2449 if (negated) bad_negation(fullname, FALSE);
2450 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2451 if ((flags.initgend = str2gend(op)) == ROLE_NONE)
2452 badoption(opts);
2453 else
2454 flags.female = flags.initgend;
2456 return;
2459 /* altkeyhandler:string */
2460 fullname = "altkeyhandler";
2461 if (match_optname(opts, fullname, 4, TRUE)) {
2462 if (negated) bad_negation(fullname, FALSE);
2463 else if ((op = string_for_opt(opts, negated))) {
2464 #ifdef WIN32CON
2465 (void)strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5);
2466 load_keyboard_handler();
2467 #endif
2469 return;
2472 /* WINCAP
2473 * align_status:[left|top|right|bottom] */
2474 fullname = "align_status";
2475 if (match_optname(opts, fullname, sizeof("align_status")-1, TRUE)) {
2476 op = string_for_opt(opts, negated);
2477 if (op && !negated) {
2478 if (!strncmpi (op, "left", sizeof("left")-1))
2479 iflags.wc_align_status = ALIGN_LEFT;
2480 else if (!strncmpi (op, "top", sizeof("top")-1))
2481 iflags.wc_align_status = ALIGN_TOP;
2482 else if (!strncmpi (op, "right", sizeof("right")-1))
2483 iflags.wc_align_status = ALIGN_RIGHT;
2484 else if (!strncmpi (op, "bottom", sizeof("bottom")-1))
2485 iflags.wc_align_status = ALIGN_BOTTOM;
2486 else
2487 badoption(opts);
2488 } else if (negated) bad_negation(fullname, TRUE);
2489 return;
2491 /* WINCAP
2492 * align_message:[left|top|right|bottom] */
2493 fullname = "align_message";
2494 if (match_optname(opts, fullname, sizeof("align_message")-1, TRUE)) {
2495 op = string_for_opt(opts, negated);
2496 if (op && !negated) {
2497 if (!strncmpi (op, "left", sizeof("left")-1))
2498 iflags.wc_align_message = ALIGN_LEFT;
2499 else if (!strncmpi (op, "top", sizeof("top")-1))
2500 iflags.wc_align_message = ALIGN_TOP;
2501 else if (!strncmpi (op, "right", sizeof("right")-1))
2502 iflags.wc_align_message = ALIGN_RIGHT;
2503 else if (!strncmpi (op, "bottom", sizeof("bottom")-1))
2504 iflags.wc_align_message = ALIGN_BOTTOM;
2505 else
2506 badoption(opts);
2507 } else if (negated) bad_negation(fullname, TRUE);
2508 return;
2510 /* align:string */
2511 fullname = "align";
2512 if (match_optname(opts, fullname, sizeof("align")-1, TRUE)) {
2513 if (negated) bad_negation(fullname, FALSE);
2514 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
2515 if ((flags.initalign = str2align(op)) == ROLE_NONE)
2516 badoption(opts);
2517 return;
2520 /* the order to list the pack */
2521 fullname = "packorder";
2522 if (match_optname(opts, fullname, 4, TRUE)) {
2523 if (negated) {
2524 bad_negation(fullname, FALSE);
2525 return;
2526 } else if (!(op = string_for_opt(opts, FALSE))) return;
2528 if (!change_inv_order(op))
2529 badoption(opts);
2530 return;
2533 /* maximum burden picked up before prompt (Warren Cheung) */
2534 fullname = "pickup_burden";
2535 if (match_optname(opts, fullname, 8, TRUE)) {
2536 if (negated) {
2537 bad_negation(fullname, FALSE);
2538 return;
2539 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
2540 switch (tolower(*op)) {
2541 /* Unencumbered */
2542 case 'u':
2543 flags.pickup_burden = UNENCUMBERED;
2544 break;
2545 /* Burdened (slight encumbrance) */
2546 case 'b':
2547 flags.pickup_burden = SLT_ENCUMBER;
2548 break;
2549 /* streSsed (moderate encumbrance) */
2550 case 's':
2551 flags.pickup_burden = MOD_ENCUMBER;
2552 break;
2553 /* straiNed (heavy encumbrance) */
2554 case 'n':
2555 flags.pickup_burden = HVY_ENCUMBER;
2556 break;
2557 /* OverTaxed (extreme encumbrance) */
2558 case 'o':
2559 case 't':
2560 flags.pickup_burden = EXT_ENCUMBER;
2561 break;
2562 /* overLoaded */
2563 case 'l':
2564 flags.pickup_burden = OVERLOADED;
2565 break;
2566 default:
2567 badoption(opts);
2570 return;
2573 /* types of objects to pick up automatically */
2574 if (match_optname(opts, "pickup_types", 8, TRUE)) {
2575 char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1],
2576 qbuf[QBUFSZ], abuf[BUFSZ];
2577 int oc_sym;
2578 boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
2580 oc_to_str(flags.pickup_types, tbuf);
2581 flags.pickup_types[0] = '\0'; /* all */
2582 op = string_for_opt(opts, (compat || !initial));
2583 if (!op) {
2584 if (compat || negated || initial) {
2585 /* for backwards compatibility, "pickup" without a
2586 value is a synonym for autopickup of all types
2587 (and during initialization, we can't prompt yet) */
2588 flags.pickup = !negated;
2589 return;
2591 oc_to_str(flags.inv_order, ocl);
2592 use_menu = TRUE;
2593 if (flags.menu_style == MENU_TRADITIONAL ||
2594 flags.menu_style == MENU_COMBINATION) {
2595 use_menu = FALSE;
2596 sprintf(qbuf, "New pickup_types: [%s am] (%s)",
2597 ocl, *tbuf ? tbuf : "none");
2598 getlin(qbuf, abuf);
2599 op = mungspaces(abuf);
2600 if (abuf[0] == '\0' || abuf[0] == '\033')
2601 op = tbuf; /* restore */
2602 else if (abuf[0] == 'm')
2603 use_menu = TRUE;
2605 if (use_menu) {
2606 (void) choose_classes_menu("Auto-Pickup what?", 1,
2607 TRUE, ocl, tbuf);
2608 op = tbuf;
2611 if (negated) {
2612 bad_negation("pickup_types", TRUE);
2613 return;
2615 while (*op == ' ') op++;
2616 if (*op != 'a' && *op != 'A') {
2617 num = 0;
2618 while (*op) {
2619 oc_sym = def_char_to_objclass(*op);
2620 /* make sure all are valid obj symbols occuring once */
2621 if (oc_sym != MAXOCLASSES &&
2622 !index(flags.pickup_types, oc_sym)) {
2623 flags.pickup_types[num] = (char)oc_sym;
2624 flags.pickup_types[++num] = '\0';
2625 } else
2626 badopt = TRUE;
2627 op++;
2629 if (badopt) badoption(opts);
2631 return;
2634 fullname = "pilesize";
2635 if (match_optname(opts, fullname, sizeof("pilesize")-1, TRUE)) {
2636 if (negated) {
2637 bad_negation(fullname, FALSE);
2638 return;
2639 } else if (!(op = string_for_opt(opts, FALSE))) return;
2640 iflags.pilesize = atoi(op);
2641 if (iflags.pilesize < 1) iflags.pilesize = 1;
2642 return;
2645 /* WINCAP
2646 * player_selection: dialog | prompts */
2647 fullname = "player_selection";
2648 if (match_optname(opts, fullname, sizeof("player_selection")-1, TRUE)) {
2649 op = string_for_opt(opts, negated);
2650 if (op && !negated) {
2651 if (!strncmpi (op, "dialog", sizeof("dialog")-1))
2652 iflags.wc_player_selection = VIA_DIALOG;
2653 else if (!strncmpi (op, "prompt", sizeof("prompt")-1))
2654 iflags.wc_player_selection = VIA_PROMPTS;
2655 else
2656 badoption(opts);
2657 } else if (negated) bad_negation(fullname, TRUE);
2658 return;
2661 /* things to disclose at end of game */
2662 if (match_optname(opts, "disclose", 7, TRUE)) {
2664 * The order that the end_disclore options are stored:
2665 * inventory, attribs, vanquished, genocided, conduct
2666 * There is an array in flags:
2667 * end_disclose[NUM_DISCLOSURE_OPT];
2668 * with option settings for the each of the following:
2669 * iagvc [see disclosure_options in decl.c]:
2670 * Legal setting values in that array are:
2671 * DISCLOSE_PROMPT_DEFAULT_YES ask with default answer yes
2672 * DISCLOSE_PROMPT_DEFAULT_NO ask with default answer no
2673 * DISCLOSE_YES_WITHOUT_PROMPT always disclose and don't ask
2674 * DISCLOSE_NO_WITHOUT_PROMPT never disclose and don't ask
2676 * Those setting values can be used in the option
2677 * string as a prefix to get the desired behaviour.
2679 * For backward compatibility, no prefix is required,
2680 * and the presence of a i,a,g,v, or c without a prefix
2681 * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
2683 boolean badopt = FALSE;
2684 int idx, prefix_val;
2686 op = string_for_opt(opts, TRUE);
2687 if (op && negated) {
2688 bad_negation("disclose", TRUE);
2689 return;
2691 /* "disclose" without a value means "all with prompting"
2692 and negated means "none without prompting" */
2693 if (!op || !strcmpi(op, "all") || !strcmpi(op, "none")) {
2694 if (op && !strcmpi(op, "none")) negated = TRUE;
2695 for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++)
2696 flags.end_disclose[num] = negated ?
2697 DISCLOSE_NO_WITHOUT_PROMPT :
2698 DISCLOSE_PROMPT_DEFAULT_YES;
2699 return;
2702 num = 0;
2703 prefix_val = -1;
2704 while (*op && num < sizeof flags.end_disclose - 1) {
2705 register char c, *dop;
2706 static char valid_settings[] = {
2707 DISCLOSE_PROMPT_DEFAULT_YES,
2708 DISCLOSE_PROMPT_DEFAULT_NO,
2709 DISCLOSE_YES_WITHOUT_PROMPT,
2710 DISCLOSE_NO_WITHOUT_PROMPT,
2711 '\0'
2713 c = lowc(*op);
2714 if (c == 'k') c = 'v'; /* killed -> vanquished */
2715 dop = index(disclosure_options, c);
2716 if (dop) {
2717 idx = dop - disclosure_options;
2718 if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) {
2719 impossible("bad disclosure index %d %c",
2720 idx, c);
2721 continue;
2723 if (prefix_val != -1) {
2724 flags.end_disclose[idx] = prefix_val;
2725 prefix_val = -1;
2726 } else
2727 flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT;
2728 } else if (index(valid_settings, c)) {
2729 prefix_val = c;
2730 } else if (c == ' ') {
2731 /* do nothing */
2732 } else
2733 badopt = TRUE;
2734 op++;
2736 if (badopt) badoption(opts);
2737 return;
2740 /* scores:5t[op] 5a[round] o[wn] */
2741 if (match_optname(opts, "scores", 4, TRUE)) {
2742 if (negated) {
2743 bad_negation("scores", FALSE);
2744 return;
2746 if (!(op = string_for_opt(opts, FALSE))) return;
2748 while (*op) {
2749 int inum = 1;
2751 if (digit(*op)) {
2752 inum = atoi(op);
2753 while (digit(*op)) op++;
2754 } else if (*op == '!') {
2755 negated = !negated;
2756 op++;
2758 while (*op == ' ') op++;
2760 switch (*op) {
2761 case 't':
2762 case 'T': flags.end_top = inum;
2763 break;
2764 case 'a':
2765 case 'A': flags.end_around = inum;
2766 break;
2767 case 'o':
2768 case 'O': flags.end_own = !negated;
2769 break;
2770 default: badoption(opts);
2771 return;
2773 while (letter(*++op) || *op == ' ') continue;
2774 if (*op == '/') op++;
2776 return;
2779 fullname = "statuscolor";
2780 if (match_optname(opts, fullname, 11, TRUE)) {
2781 #if defined(STATUS_COLORS) && defined(TEXTCOLOR)
2782 if (negated) bad_negation(fullname, FALSE);
2783 else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
2784 if (!parse_status_color_options(op))
2785 badoption(opts);
2786 #endif
2787 return;
2790 fullname = "sortloot";
2791 if (match_optname(opts, fullname, 4, TRUE)) {
2792 op = string_for_env_opt(fullname, opts, FALSE);
2793 if (op) {
2794 switch (tolower(*op)) {
2795 case 'n':
2796 case 'l':
2797 case 'f': iflags.sortloot = tolower(*op);
2798 break;
2799 default: badoption(opts);
2800 return;
2803 return;
2806 fullname = "suppress_alert";
2807 if (match_optname(opts, fullname, 4, TRUE)) {
2808 op = string_for_opt(opts, negated);
2809 if (negated) bad_negation(fullname, FALSE);
2810 else if (op) (void) feature_alert_opts(op,fullname);
2811 return;
2814 fullname = "tileset";
2815 if (match_optname(opts, fullname, 4, TRUE)) {
2816 if (negated || (op = string_for_opt(opts, TRUE)) == 0)
2817 tileset[0] = '\0';
2818 else {
2820 * The tileset may not be defined (yet) if we're
2821 * in initial mode, otherwise it must exist.
2823 if (!initial) {
2824 int len = strlen(op);
2825 for(i = 0; i < no_tilesets; i++)
2826 if (len == strlen(tilesets[i].name) &&
2827 !strncmpi(tilesets[i].name, op, len))
2828 break;
2829 if (i == no_tilesets) {
2830 pline("Tileset %s not defined.", op);
2831 return;
2833 else /* Use canonical case */
2834 strcpy(tileset, tilesets[i].name);
2836 else
2837 nmcpy(tileset, op, PL_PSIZ);
2839 if (!initial)
2840 need_redraw = TRUE;
2841 return;
2844 #if defined(VIDEOSHADES) && !defined(NO_TERMS)
2845 /* videocolors:string */
2846 fullname = "videocolors";
2847 if (match_optname(opts, fullname, 6, TRUE) ||
2848 match_optname(opts, "videocolours", 10, TRUE)) {
2849 if (negated) {
2850 bad_negation(fullname, FALSE);
2851 return;
2853 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2854 return;
2856 if (!assign_videocolors(opts))
2857 badoption(opts);
2858 return;
2860 # ifdef MSDOS
2861 /* videoshades:string */
2862 fullname = "videoshades";
2863 if (match_optname(opts, fullname, 6, TRUE)) {
2864 if (negated) {
2865 bad_negation(fullname, FALSE);
2866 return;
2868 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2869 return;
2871 if (!assign_videoshades(opts))
2872 badoption(opts);
2873 return;
2875 # endif
2876 #endif /* VIDEOSHADES */
2877 #ifdef MSDOS
2878 # ifdef NO_TERMS
2879 /* video:string -- must be after longer tests */
2880 fullname = "video";
2881 if (match_optname(opts, fullname, 5, TRUE)) {
2882 if (negated) {
2883 bad_negation(fullname, FALSE);
2884 return;
2886 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2887 return;
2889 if (!assign_video(opts))
2890 badoption(opts);
2891 return;
2893 # endif /* NO_TERMS */
2894 /* soundcard:string -- careful not to match boolean 'sound' */
2895 fullname = "soundcard";
2896 if (match_optname(opts, fullname, 6, TRUE)) {
2897 if (negated) {
2898 bad_negation(fullname, FALSE);
2899 return;
2901 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
2902 return;
2904 if (!assign_soundcard(opts))
2905 badoption(opts);
2906 return;
2908 #endif /* MSDOS */
2910 /* WINCAP
2911 * map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|ascii8x12|
2912 ascii16x12|ascii12x16|ascii10x18|fit_to_screen] */
2913 fullname = "map_mode";
2914 if (match_optname(opts, fullname, sizeof("map_mode")-1, TRUE)) {
2915 op = string_for_opt(opts, negated);
2916 if (op && !negated) {
2917 if (!strncmpi (op, "tiles", sizeof("tiles")-1))
2918 iflags.wc_map_mode = MAP_MODE_TILES;
2919 else if (!strncmpi (op, "ascii4x6", sizeof("ascii4x6")-1))
2920 iflags.wc_map_mode = MAP_MODE_ASCII4x6;
2921 else if (!strncmpi (op, "ascii6x8", sizeof("ascii6x8")-1))
2922 iflags.wc_map_mode = MAP_MODE_ASCII6x8;
2923 else if (!strncmpi (op, "ascii8x8", sizeof("ascii8x8")-1))
2924 iflags.wc_map_mode = MAP_MODE_ASCII8x8;
2925 else if (!strncmpi (op, "ascii16x8", sizeof("ascii16x8")-1))
2926 iflags.wc_map_mode = MAP_MODE_ASCII16x8;
2927 else if (!strncmpi (op, "ascii7x12", sizeof("ascii7x12")-1))
2928 iflags.wc_map_mode = MAP_MODE_ASCII7x12;
2929 else if (!strncmpi (op, "ascii8x12", sizeof("ascii8x12")-1))
2930 iflags.wc_map_mode = MAP_MODE_ASCII8x12;
2931 else if (!strncmpi (op, "ascii16x12", sizeof("ascii16x12")-1))
2932 iflags.wc_map_mode = MAP_MODE_ASCII16x12;
2933 else if (!strncmpi (op, "ascii12x16", sizeof("ascii12x16")-1))
2934 iflags.wc_map_mode = MAP_MODE_ASCII12x16;
2935 else if (!strncmpi (op, "ascii10x18", sizeof("ascii10x18")-1))
2936 iflags.wc_map_mode = MAP_MODE_ASCII10x18;
2937 else if (!strncmpi (op, "fit_to_screen", sizeof("fit_to_screen")-1))
2938 iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN;
2939 else
2940 badoption(opts);
2941 } else if (negated) bad_negation(fullname, TRUE);
2942 return;
2944 /* WINCAP
2945 * scroll_amount:nn */
2946 fullname = "scroll_amount";
2947 if (match_optname(opts, fullname, sizeof("scroll_amount")-1, TRUE)) {
2948 op = string_for_opt(opts, negated);
2949 if ((negated && !op) || (!negated && op)) {
2950 iflags.wc_scroll_amount = negated ? 1 : atoi(op);
2951 } else if (negated) bad_negation(fullname, TRUE);
2952 return;
2954 /* WINCAP
2955 * scroll_margin:nn */
2956 fullname = "scroll_margin";
2957 if (match_optname(opts, fullname, sizeof("scroll_margin")-1, TRUE)) {
2958 op = string_for_opt(opts, negated);
2959 if ((negated && !op) || (!negated && op)) {
2960 iflags.wc_scroll_margin = negated ? 5 : atoi(op);
2961 } else if (negated) bad_negation(fullname, TRUE);
2962 return;
2964 fullname = "subkeyvalue";
2965 if (match_optname(opts, fullname, 5, TRUE)) {
2966 if (negated) bad_negation(fullname, FALSE);
2967 else {
2968 #if defined(WIN32CON)
2969 op = string_for_opt(opts, 0);
2970 map_subkeyvalue(op);
2971 #endif
2973 return;
2975 /* WINCAP
2976 * tile_width:nn */
2977 fullname = "tile_width";
2978 if (match_optname(opts, fullname, sizeof("tile_width")-1, TRUE)) {
2979 op = string_for_opt(opts, negated);
2980 if ((negated && !op) || (!negated && op)) {
2981 iflags.wc_tile_width = negated ? 0 : atoi(op);
2982 } else if (negated) bad_negation(fullname, TRUE);
2983 return;
2985 /* WINCAP
2986 * tile_file:name */
2987 fullname = "tile_file";
2988 if (match_optname(opts, fullname, sizeof("tile_file")-1, TRUE)) {
2989 if ((op = string_for_opt(opts, FALSE)) != 0) {
2990 if (iflags.wc_tile_file) free(iflags.wc_tile_file);
2991 iflags.wc_tile_file = (char *)alloc(strlen(op) + 1);
2992 strcpy(iflags.wc_tile_file, op);
2994 return;
2996 /* WINCAP
2997 * tile_height:nn */
2998 fullname = "tile_height";
2999 if (match_optname(opts, fullname, sizeof("tile_height")-1, TRUE)) {
3000 op = string_for_opt(opts, negated);
3001 if ((negated && !op) || (!negated && op)) {
3002 iflags.wc_tile_height = negated ? 0 : atoi(op);
3003 } else if (negated) bad_negation(fullname, TRUE);
3004 return;
3006 /* WINCAP
3007 * vary_msgcount:nn */
3008 fullname = "vary_msgcount";
3009 if (match_optname(opts, fullname, sizeof("vary_msgcount")-1, TRUE)) {
3010 op = string_for_opt(opts, negated);
3011 if ((negated && !op) || (!negated && op)) {
3012 iflags.wc_vary_msgcount = negated ? 0 : atoi(op);
3013 } else if (negated) bad_negation(fullname, TRUE);
3014 return;
3016 fullname = "windowtype";
3018 if (
3019 #ifdef AWFUL_CURSES
3020 FALSE &&
3021 #endif
3022 match_optname(opts, fullname, 3, TRUE)) {
3023 if (negated) {
3024 bad_negation(fullname, FALSE);
3025 return;
3026 } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) {
3027 char buf[WINTYPELEN];
3028 nmcpy(buf, op, WINTYPELEN);
3029 choose_windows(buf);
3031 return;
3034 /* WINCAP
3035 * setting window colors
3036 * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd
3038 fullname = "windowcolors";
3039 if (match_optname(opts, fullname, 7, TRUE)) {
3040 if ((op = string_for_opt(opts, FALSE)) != 0) {
3041 if (!wc_set_window_colors(op))
3042 badoption(opts);
3043 } else if (negated) bad_negation(fullname, TRUE);
3044 return;
3047 /* WINCAP2
3048 * term_cols:amount */
3049 fullname = "term_cols";
3050 if (match_optname(opts, fullname, sizeof("term_cols")-1, TRUE)) {
3051 op = string_for_opt(opts, negated);
3052 iflags.wc2_term_cols = op ? atoi(op) : 0;
3053 if (negated) bad_negation(fullname, FALSE);
3054 return;
3057 /* WINCAP2
3058 * term_rows:amount */
3059 fullname = "term_rows";
3060 if (match_optname(opts, fullname, sizeof("term_rows")-1, TRUE)) {
3061 op = string_for_opt(opts, negated);
3062 iflags.wc2_term_rows = op ? atoi(op) : 0;
3063 if (negated) bad_negation(fullname, FALSE);
3064 return;
3068 /* WINCAP2
3069 * petattr:string */
3070 fullname = "petattr";
3071 if (match_optname(opts, fullname, sizeof("petattr")-1, TRUE)) {
3072 op = string_for_opt(opts, negated);
3073 if (op && !negated) {
3074 iflags.wc2_petattr = atoi(op);
3075 if (!atoi(op))
3076 badoption(opts);
3077 } else if (negated) bad_negation(fullname, TRUE);
3078 return;
3082 /* WINCAP2
3083 * windowborders:n */
3084 fullname = "windowborders";
3085 if (match_optname(opts, fullname, sizeof("windowborders")-1, TRUE)) {
3086 op = string_for_opt(opts, negated);
3087 if (negated && op) bad_negation(fullname, TRUE);
3088 else {
3089 if (negated)
3090 iflags.wc2_windowborders = 2; /* Off */
3091 else if (!op)
3092 iflags.wc2_windowborders = 1; /* On */
3093 else /* Value supplied */
3094 iflags.wc2_windowborders = atoi(op);
3095 if ((iflags.wc2_windowborders > 3) ||
3096 (iflags.wc2_windowborders < 1)) {
3097 iflags.wc2_windowborders = 0;
3098 badoption(opts);
3101 return;
3104 /* menustyle:traditional or combo or full or partial */
3105 if (match_optname(opts, "menustyle", 4, TRUE)) {
3106 int tmp;
3107 boolean val_required = (strlen(opts) > 5 && !negated);
3109 if (!(op = string_for_opt(opts, !val_required))) {
3110 if (val_required) return; /* string_for_opt gave feedback */
3111 tmp = negated ? 'n' : 'f';
3112 } else {
3113 tmp = tolower(*op);
3115 switch (tmp) {
3116 case 'n': /* none */
3117 case 't': /* traditional */
3118 flags.menu_style = MENU_TRADITIONAL;
3119 break;
3120 case 'c': /* combo: trad.class sel+menu */
3121 flags.menu_style = MENU_COMBINATION;
3122 break;
3123 case 'p': /* partial: no class menu */
3124 flags.menu_style = MENU_PARTIAL;
3125 break;
3126 case 'f': /* full: class menu + menu */
3127 flags.menu_style = MENU_FULL;
3128 break;
3129 default:
3130 badoption(opts);
3132 return;
3135 fullname = "menu_headings";
3136 if (match_optname(opts, fullname, 12, TRUE)) {
3137 if (negated) {
3138 bad_negation(fullname, FALSE);
3139 return;
3141 else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
3142 return;
3144 if (!strcmpi(opts,"bold"))
3145 iflags.menu_headings = ATR_BOLD;
3146 else if (!strcmpi(opts,"inverse"))
3147 iflags.menu_headings = ATR_INVERSE;
3148 else if (!strcmpi(opts,"underline"))
3149 iflags.menu_headings = ATR_ULINE;
3150 else
3151 badoption(opts);
3152 return;
3155 /* check for menu command mapping */
3156 for (i = 0; i < NUM_MENU_CMDS; i++) {
3157 fullname = default_menu_cmd_info[i].name;
3158 if (match_optname(opts, fullname, (int)strlen(fullname), TRUE)) {
3159 if (negated)
3160 bad_negation(fullname, FALSE);
3161 else if ((op = string_for_opt(opts, FALSE)) != 0) {
3162 int j;
3163 char c, op_buf[BUFSZ];
3164 boolean isbad = FALSE;
3166 escapes(op, op_buf);
3167 c = *op_buf;
3169 if (c == 0 || c == '\r' || c == '\n' || c == '\033' ||
3170 c == ' ' || digit(c) || (letter(c) && c != '@'))
3171 isbad = TRUE;
3172 else /* reject default object class symbols */
3173 for (j = 1; j < MAXOCLASSES; j++)
3174 if (c == def_oc_syms[i]) {
3175 isbad = TRUE;
3176 break;
3179 if (isbad)
3180 badoption(opts);
3181 else
3182 add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd);
3184 return;
3188 /* OK, if we still haven't recognized the option, check the boolean
3189 * options list
3191 for (i = 0; boolopt[i].name; i++) {
3192 if (match_optname(opts, boolopt[i].name, 3, FALSE)) {
3193 /* options that don't exist */
3194 if (!boolopt[i].addr) {
3195 if (!initial && !negated)
3196 pline_The("\"%s\" option is not available.",
3197 boolopt[i].name);
3198 return;
3200 /* options that must come from config file */
3201 if (!initial && (boolopt[i].optflags == SET_IN_FILE)) {
3202 rejectoption(boolopt[i].name);
3203 return;
3206 if (iflags.debug_fuzzer && !initial) {
3207 /* don't randomly toggle this/these */
3208 if (boolopt[i].addr == &flags.silent) return;
3209 if (boolopt[i].addr == &flags.ins_chkpt) return;
3212 *(boolopt[i].addr) = !negated;
3214 duplicate_opt_detection(boolopt[i].name, 0);
3216 #if defined(TERMLIB) || defined(ASCIIGRAPH) || defined(MAC_GRAPHICS_ENV) || defined(CURSES_GRAPHICS)
3217 if (FALSE
3218 # ifdef TERMLIB
3219 || (boolopt[i].addr) == &iflags.DECgraphics
3220 # endif
3221 # ifdef ASCIIGRAPH
3222 || (boolopt[i].addr) == &iflags.IBMgraphics
3223 # endif
3224 # ifdef MAC_GRAPHICS_ENV
3225 || (boolopt[i].addr) == &iflags.MACgraphics
3226 # endif
3227 # ifdef CURSES_GRAPHICS
3228 || (boolopt[i].addr) == &iflags.cursesgraphics
3229 # endif
3231 # ifdef REINCARNATION
3232 /* [ALI] GTK port may call doset() after initial
3233 * but before we start a game. Prevent false match.
3235 if (!initial && u.uz.dlevel &&
3236 Is_rogue_level(&u.uz))
3237 assign_rogue_graphics(isrougelike);
3238 # endif
3239 need_redraw = TRUE;
3240 # ifdef TERMLIB
3241 if ((boolopt[i].addr) == &iflags.DECgraphics)
3242 switch_graphics(iflags.DECgraphics ?
3243 DEC_GRAPHICS : ASCII_GRAPHICS);
3244 # endif
3245 # ifdef ASCIIGRAPH
3246 if ((boolopt[i].addr) == &iflags.IBMgraphics)
3247 switch_graphics(iflags.IBMgraphics ?
3248 IBM_GRAPHICS : ASCII_GRAPHICS);
3249 # endif
3250 # ifdef MAC_GRAPHICS_ENV
3251 if ((boolopt[i].addr) == &iflags.MACgraphics)
3252 switch_graphics(iflags.MACgraphics ?
3253 MAC_GRAPHICS : ASCII_GRAPHICS);
3254 # endif
3255 # ifdef CURSES_GRAPHICS
3256 if ((boolopt[i].addr) == &iflags.cursesgraphics)
3257 switch_graphics(iflags.cursesgraphics ?
3258 CURS_GRAPHICS : ASCII_GRAPHICS);
3259 # endif
3260 # ifdef REINCARNATION
3261 if (!initial && u.uz.dlevel &&
3262 Is_rogue_level(&u.uz))
3263 assign_rogue_graphics(TRUE);
3264 # endif
3266 #endif /* TERMLIB || ASCIIGRAPH || MAC_GRAPHICS_ENV */
3268 /* only do processing below if setting with doset() */
3269 if (initial) return;
3271 if ((boolopt[i].addr) == &flags.time
3272 || (boolopt[i].addr) == &flags.showexp
3273 || (boolopt[i].addr) == &flags.showscore
3274 #ifdef SHOW_WEIGHT
3275 || (boolopt[i].addr) == &flags.showweight
3276 #endif
3277 || (boolopt[i].addr) == &flags.showmc
3278 || (boolopt[i].addr) == &flags.showmovement
3279 || (boolopt[i].addr) == &flags.showsanity
3280 || (boolopt[i].addr) == &flags.showlongstats
3281 || (boolopt[i].addr) == &flags.showsymbiotehp
3284 bot_reconfig();
3286 else if ((boolopt[i].addr) == &flags.epyxmode) {
3287 if (isrougelike || Is_rogue_level(&u.uz)) assign_rogue_graphics(TRUE);
3288 need_redraw = TRUE;
3291 else if ((boolopt[i].addr) == &flags.invlet_constant) {
3292 if (flags.invlet_constant) reassign();
3294 #ifdef LAN_MAIL
3295 else if ((boolopt[i].addr) == &flags.biff) {
3296 if (flags.biff) lan_mail_init();
3297 else lan_mail_finish();
3299 #endif
3300 else if ((boolopt[i].addr) == &flags.lit_corridor) {
3302 * All corridor squares seen via night vision or
3303 * candles & lamps change. Update them by calling
3304 * newsym() on them. Don't do this if we are
3305 * initializing the options --- the vision system
3306 * isn't set up yet.
3308 if (u.uz.dlevel)
3310 vision_recalc(2); /* shut down vision */
3311 vision_full_recalc = 1; /* delayed recalc */
3312 if (iflags.use_color) need_redraw = TRUE; /* darkroom refresh */
3315 else if ((boolopt[i].addr) == &iflags.use_inverse ||
3316 (boolopt[i].addr) == &iflags.showrace ||
3317 (boolopt[i].addr) == &iflags.hilite_pet ||
3318 (boolopt[i].addr) == &iflags.wc2_guicolor) {
3319 need_redraw = TRUE;
3321 #ifdef CURSES_GRAPHICS
3322 else if ((boolopt[i].addr) == &iflags.cursesgraphics) {
3323 need_redraw = TRUE;
3325 #endif
3326 #ifdef TEXTCOLOR
3327 else if ((boolopt[i].addr) == &iflags.use_color) {
3328 need_redraw = TRUE;
3329 # ifdef TOS
3330 if ((boolopt[i].addr) == &iflags.use_color
3331 && iflags.BIOS) {
3332 if (colors_changed)
3333 restore_colors();
3334 else
3335 set_colors();
3337 # endif
3339 #endif
3340 else if ((boolopt[i].addr) == &flags.perm_invent)
3341 update_inventory();
3343 return;
3347 /* out of valid options */
3348 badoption(opts);
3351 static void
3352 parseauthopt(opts)
3353 register char *opts;
3355 register char *op;
3356 boolean negated;
3357 const char *fullname;
3359 if (strlen(opts) > BUFSZ/2) {
3360 badauthoption("option too long");
3361 return;
3364 /* strip leading and trailing white space */
3365 while (isspace((int)*opts)) opts++;
3366 op = eos(opts);
3367 while (--op >= opts && isspace((int)*op)) *op = '\0';
3369 if (!*opts) return;
3370 negated = FALSE;
3371 while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
3372 if (*opts == '!') opts++; else opts += 2;
3373 negated = !negated;
3376 /* compound options */
3378 fullname = "prog";
3379 if (match_optname(opts, fullname, 4, TRUE)) {
3380 if (negated) bad_negation(fullname, FALSE);
3381 else if ((op = string_for_auth_opt(opts, FALSE)) != 0)
3382 nmcpy(authentication.prog, op, BUFSZ);
3383 return;
3386 fullname = "args";
3387 if (match_optname(opts, fullname, 4, TRUE)) {
3388 if (negated) bad_negation(fullname, FALSE);
3389 else if ((op = string_for_auth_opt(opts, FALSE)) != 0)
3390 nmcpy(authentication.args, op, BUFSZ);
3391 return;
3394 /* out of valid options */
3395 badauthoption(opts);
3398 void
3399 parseauthentication(opts)
3400 register char *opts;
3402 register char *op;
3404 /* Initial values */
3405 authentication.prog[0] = '\0';
3406 authentication.args[0] = '\0';
3408 while ((op = index(opts, ',')) != 0) {
3409 *op++ = 0;
3410 parseauthopt(opts);
3411 opts = op;
3413 parseauthopt(opts);
3415 if (!authentication.prog[0] && authentication.args[0])
3416 badauthoption("Arguments given but no program specified.");
3419 static void
3420 parsetilesetopt(opts)
3421 register char *opts;
3423 register char *op;
3424 boolean negated;
3425 int i;
3426 const char *fullname;
3428 if (strlen(opts) > BUFSZ/2) {
3429 badtileoption("option too long");
3430 return;
3433 /* strip leading and trailing white space */
3434 while (isspace((int)*opts)) opts++;
3435 op = eos(opts);
3436 while (--op >= opts && isspace((int)*op)) *op = '\0';
3438 if (!*opts) return;
3439 negated = FALSE;
3440 while ((*opts == '!') || !strncmpi(opts, "no", 2)) {
3441 if (*opts == '!') opts++; else opts += 2;
3442 negated = !negated;
3445 /* compound options */
3447 fullname = "name";
3448 if (match_optname(opts, fullname, 4, TRUE)) {
3449 if (negated) bad_negation(fullname, FALSE);
3450 else if ((op = string_for_tile_opt(opts, FALSE)) != 0)
3451 nmcpy(tilesets[no_tilesets].name, op, PL_PSIZ);
3452 return;
3455 fullname = "filename";
3456 if (match_optname(opts, fullname, 4, TRUE)) {
3457 if (negated) bad_negation(fullname, FALSE);
3458 else if ((op = string_for_tile_opt(opts, FALSE)) != 0)
3459 nmcpy(tilesets[no_tilesets].file, op,
3460 TILESET_MAX_FILENAME);
3461 return;
3464 /* OK, if we still haven't recognized the option, check the boolean
3465 * options list
3467 for (i = 0; booltileopt[i].name; i++) {
3468 if (match_optname(opts, booltileopt[i].name, 3, FALSE)) {
3469 if (negated)
3470 tilesets[no_tilesets].flags &= ~booltileopt[i].flag;
3471 else
3472 tilesets[no_tilesets].flags |= booltileopt[i].flag;
3473 return;
3477 /* out of valid options */
3478 badtileoption(opts);
3481 void
3482 parsetileset(opts)
3483 register char *opts;
3485 register char *op;
3486 int i;
3488 if (no_tilesets >= MAXNOTILESETS) {
3489 badtileoption("too many tilesets");
3490 return;
3493 /* Initial values */
3494 tilesets[no_tilesets].name[0] = '\0';
3495 tilesets[no_tilesets].file[0] = '\0';
3496 tilesets[no_tilesets].flags = 0;
3497 for (i = 0; booltileopt[i].name; i++)
3498 tilesets[no_tilesets].flags |= booltileopt[i].initvalue;
3500 while ((op = index(opts, ',')) != 0) {
3501 *op++ = 0;
3502 parsetilesetopt(opts);
3503 opts = op;
3505 parsetilesetopt(opts);
3507 if (tilesets[no_tilesets].name[0] == '\0' ||
3508 tilesets[no_tilesets].file[0] == '\0') {
3509 badtileoption("Incomplete tileset definition.");
3511 else
3512 no_tilesets++;
3516 static NEARDATA const char *menutype[] = {
3517 "traditional", "combination", "partial", "full"
3520 static NEARDATA const char *burdentype[] = {
3521 "unencumbered", "burdened", "stressed",
3522 "strained", "overtaxed", "overloaded"
3525 static NEARDATA const char *runmodes[] = {
3526 "teleport", "run", "walk", "crawl"
3529 static NEARDATA const char *sortltype[] = {
3530 "none", "loot", "full"
3534 * Convert the given string of object classes to a string of default object
3535 * symbols.
3537 STATIC_OVL void
3538 oc_to_str(src,dest)
3539 char *src, *dest;
3541 int i;
3543 while ((i = (int) *src++) != 0) {
3544 if (i < 0 || i >= MAXOCLASSES)
3545 impossible("oc_to_str: illegal object class %d", i);
3546 else
3547 *dest++ = def_oc_syms[i];
3549 *dest = '\0';
3553 * Add the given mapping to the menu command map list. Always keep the
3554 * maps valid C strings.
3556 void
3557 add_menu_cmd_alias(from_ch, to_ch)
3558 char from_ch, to_ch;
3560 if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS)
3561 pline("out of menu map space.");
3562 else {
3563 mapped_menu_cmds[n_menu_mapped] = from_ch;
3564 mapped_menu_op[n_menu_mapped] = to_ch;
3565 n_menu_mapped++;
3566 mapped_menu_cmds[n_menu_mapped] = 0;
3567 mapped_menu_op[n_menu_mapped] = 0;
3572 * Map the given character to its corresponding menu command. If it
3573 * doesn't match anything, just return the original.
3575 char
3576 map_menu_cmd(ch)
3577 char ch;
3579 char *found = index(mapped_menu_cmds, ch);
3580 if (found) {
3581 int idx = found - mapped_menu_cmds;
3582 ch = mapped_menu_op[idx];
3584 return ch;
3588 #if defined(MICRO) || defined(MAC) || defined(WIN32)
3589 # define OPTIONS_HEADING "OPTIONS"
3590 #else
3591 # define OPTIONS_HEADING NETHACK_ENV_OPTIONS
3592 #endif
3594 static char fmtstr_doset_add_menu[] = "%s%-15s [%s] ";
3595 static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]";
3597 STATIC_OVL void
3598 doset_add_menu(win, option, indexoffset)
3599 winid win; /* window to add to */
3600 const char *option; /* option name */
3601 int indexoffset; /* value to add to index in compopt[], or zero
3602 if option cannot be changed */
3604 const char *value = "unknown"; /* current value */
3605 char buf[BUFSZ], buf2[BUFSZ];
3606 anything any;
3607 int i;
3609 any.a_void = 0;
3610 if (indexoffset == 0) {
3611 any.a_int = 0;
3612 value = get_compopt_value(option, buf2);
3613 } else {
3614 for (i=0; compopt[i].name; i++)
3615 if (strcmp(option, compopt[i].name) == 0) break;
3617 if (compopt[i].name) {
3618 any.a_int = i + 1 + indexoffset;
3619 value = get_compopt_value(option, buf2);
3620 } else {
3621 /* We are trying to add an option not found in compopt[].
3622 This is almost certainly bad, but we'll let it through anyway
3623 (with a zero value, so it can't be selected). */
3624 any.a_int = 0;
3627 /* " " replaces "a - " -- assumes menus follow that style */
3628 if (!iflags.menu_tab_sep)
3629 sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", option, value);
3630 else
3631 sprintf(buf, fmtstr_doset_add_menu_tab, option, value);
3632 add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
3635 /* Changing options via menu by Per Liboriussen */
3637 doset()
3639 char buf[BUFSZ], buf2[BUFSZ];
3640 int i, pass, boolcount, pick_cnt, pick_idx, opt_indx;
3641 boolean *bool_p;
3642 winid tmpwin;
3643 anything any;
3644 menu_item *pick_list;
3645 int indexoffset, startpass, endpass;
3646 boolean setinitial = FALSE, fromfile = FALSE;
3647 int biggest_name = 0;
3649 if (moves < 50 && iflags.numpadmessage) {
3651 if (!(iflags.num_pad)) {
3652 if (yn("Do you want to turn on the number pad?") == 'y') {
3653 iflags.num_pad = 2;
3654 iflags.num_pad_mode = 1;
3655 iflags.numpadmessage = FALSE;
3656 } else if (yn("Do you want to turn this annoying message off?") == 'y') {
3657 iflags.numpadmessage = FALSE;
3658 pline("In order to turn the message off for all subsequent games too, add OPTIONS=nonumpadmessage to your configuration file.");
3660 if (u.annoyingmessages++ > 5) iflags.numpadmessage = FALSE;
3663 else if (iflags.num_pad) {
3664 if (yn("Do you want to turn off the number pad?") == 'y') {
3665 iflags.num_pad = 0;
3666 iflags.num_pad_mode = 0;
3667 iflags.numpadmessage = FALSE;
3668 } else if (yn("Do you want to turn this annoying message off?") == 'y') {
3669 iflags.numpadmessage = FALSE;
3670 pline("In order to turn the message off for all subsequent games too, add OPTIONS=nonumpadmessage to your configuration file.");
3672 if (u.annoyingmessages++ > 5) iflags.numpadmessage = FALSE;
3677 tmpwin = create_nhwindow(NHW_MENU);
3678 start_menu(tmpwin);
3680 any.a_void = 0;
3682 /* I'm just so sick of seeing players spend half an hour staring at the boolean options when all they want to do is
3683 * obviously to turn the goddamn number pad on. --Amy */
3684 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3685 "IMPORTANT: The number_pad option is all the way down at the compound options,", MENU_UNSELECTED);
3686 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3687 "so scroll down there if you want to turn the number pad on!!!", MENU_UNSELECTED);
3688 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3689 "Scroll with the space bar or the > key, NOT the arrow keys!", MENU_UNSELECTED);
3691 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
3692 " ", MENU_UNSELECTED);
3694 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3695 "Booleans (selecting will toggle value):", MENU_UNSELECTED);
3696 any.a_int = 0;
3697 /* first list any other non-modifiable booleans, then modifiable ones */
3698 for (pass = 0; pass <= 1; pass++)
3699 for (i = 0; boolopt[i].name; i++)
3700 if ((bool_p = boolopt[i].addr) != 0 &&
3701 ((boolopt[i].optflags == DISP_IN_GAME && pass == 0) ||
3702 (boolopt[i].optflags == SET_IN_GAME && pass == 1))) {
3703 if (bool_p == &flags.female) continue; /* obsolete */
3704 #ifdef WIZARD
3705 #ifndef OBJ_SANITY
3706 if (bool_p == &iflags.sanity_check && !wizard) continue;
3707 #endif
3708 if (bool_p == &iflags.menu_tab_sep && !wizard) continue;
3709 #endif
3710 if (is_wc_option(boolopt[i].name) &&
3711 !wc_supported(boolopt[i].name)) continue;
3712 if (is_wc2_option(boolopt[i].name) &&
3713 !wc2_supported(boolopt[i].name)) continue;
3714 any.a_int = (pass == 0) ? 0 : i + 1;
3715 if (!iflags.menu_tab_sep)
3716 sprintf(buf, "%s%-13s [%s]",
3717 pass == 0 ? " " : "",
3718 boolopt[i].name, *bool_p ? "true" : "false");
3719 else
3720 sprintf(buf, "%s\t[%s]",
3721 boolopt[i].name, *bool_p ? "true" : "false");
3722 add_menu(tmpwin, NO_GLYPH, &any, 0, 0,
3723 ATR_NONE, buf, MENU_UNSELECTED);
3726 boolcount = i;
3727 indexoffset = boolcount;
3728 any.a_void = 0;
3729 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
3730 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3731 "Compounds (selecting will prompt for new value):",
3732 MENU_UNSELECTED);
3734 startpass = DISP_IN_GAME;
3735 endpass = SET_IN_GAME;
3737 /* spin through the options to find the biggest name
3738 and adjust the format string accordingly if needed */
3739 biggest_name = 0;
3740 for (i = 0; compopt[i].name; i++)
3741 if (compopt[i].optflags >= startpass && compopt[i].optflags <= endpass &&
3742 strlen(compopt[i].name) > (unsigned) biggest_name)
3743 biggest_name = (int) strlen(compopt[i].name);
3744 if (biggest_name > 30) biggest_name = 30;
3745 if (!iflags.menu_tab_sep)
3746 sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name);
3748 /* deliberately put `name', `role', `race', `gender' first */
3749 doset_add_menu(tmpwin, "name", 0);
3750 doset_add_menu(tmpwin, "role", 0);
3751 doset_add_menu(tmpwin, "race", 0);
3752 doset_add_menu(tmpwin, "gender", 0);
3754 for (pass = startpass; pass <= endpass; pass++)
3755 for (i = 0; compopt[i].name; i++)
3756 if (compopt[i].optflags == pass) {
3757 if (!strcmp(compopt[i].name, "name") ||
3758 !strcmp(compopt[i].name, "role") ||
3759 !strcmp(compopt[i].name, "race") ||
3760 !strcmp(compopt[i].name, "gender"))
3761 continue;
3762 else if (is_wc_option(compopt[i].name) &&
3763 !wc_supported(compopt[i].name))
3764 continue;
3765 else if (is_wc2_option(compopt[i].name) &&
3766 !wc2_supported(compopt[i].name))
3767 continue;
3768 else
3769 doset_add_menu(tmpwin, compopt[i].name,
3770 (pass == DISP_IN_GAME) ? 0 : indexoffset);
3772 #ifdef AUTOPICKUP_EXCEPTIONS
3773 any.a_int = -1;
3774 sprintf(buf, "autopickup exceptions (%d currently set)",
3775 count_ape_maps((int *)0, (int *)0));
3776 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
3778 #endif /* AUTOPICKUP_EXCEPTIONS */
3779 #ifdef PREFIXES_IN_USE
3780 any.a_void = 0;
3781 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
3782 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3783 "Variable playground locations:", MENU_UNSELECTED);
3784 for (i = 0; i < PREFIX_COUNT; i++)
3785 doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
3786 #endif
3788 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
3789 " ", MENU_UNSELECTED);
3790 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3791 "Attention: DO NOT press ESC here or you'll cancel your changes!!", MENU_UNSELECTED);
3792 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
3793 "Scroll out of the menu via spacebar or > to save your changes!!!", MENU_UNSELECTED);
3795 end_menu(tmpwin, "Set what options?");
3796 need_redraw = FALSE;
3797 if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) {
3799 * Walk down the selection list and either invert the booleans
3800 * or prompt for new values. In most cases, call parseoptions()
3801 * to take care of options that require special attention, like
3802 * redraws.
3804 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
3805 opt_indx = pick_list[pick_idx].item.a_int - 1;
3806 #ifdef AUTOPICKUP_EXCEPTIONS
3807 if (opt_indx == -2) {
3808 special_handling("autopickup_exception",
3809 setinitial, fromfile);
3810 } else
3811 #endif
3812 if (opt_indx < boolcount) {
3813 /* boolean option */
3814 sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
3815 boolopt[opt_indx].name);
3816 parseoptions(buf, setinitial, fromfile);
3817 if (wc_supported(boolopt[opt_indx].name) ||
3818 wc2_supported(boolopt[opt_indx].name))
3819 preference_update(boolopt[opt_indx].name);
3820 } else {
3821 /* compound option */
3822 opt_indx -= boolcount;
3824 if (!special_handling(compopt[opt_indx].name,
3825 setinitial, fromfile)) {
3826 sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
3827 getlin(buf, buf2);
3828 if (buf2[0] == '\033')
3829 continue;
3830 sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2);
3831 /* pass the buck */
3832 parseoptions(buf, setinitial, fromfile);
3834 if (wc_supported(compopt[opt_indx].name) ||
3835 wc2_supported(compopt[opt_indx].name))
3836 preference_update(compopt[opt_indx].name);
3839 free((void *)pick_list);
3840 pick_list = (menu_item *)0;
3843 destroy_nhwindow(tmpwin);
3844 if (need_redraw) {
3845 if (flags.lit_corridor && iflags.use_color) {
3846 showsyms[S_darkroom]=showsyms[S_room];
3847 } else {
3848 showsyms[S_darkroom]=showsyms[S_stone];
3850 if (!(InterfaceScrewed || u.uprops[INTERFACE_SCREW].extrinsic || have_interfacescrewstone())) (void) doredraw();
3852 return 0;
3855 STATIC_OVL boolean
3856 special_handling(optname, setinitial, setfromfile)
3857 const char *optname;
3858 boolean setinitial,setfromfile;
3860 winid tmpwin;
3861 anything any;
3862 int i;
3863 char buf[BUFSZ];
3864 boolean retval = FALSE;
3866 /* Special handling of menustyle, pickup_burden, pickup_types,
3867 * disclose, runmode, msg_window, menu_headings, and number_pad options.
3868 #ifdef AUTOPICKUP_EXCEPTIONS
3869 * Also takes care of interactive autopickup_exception_handling changes.
3870 #endif
3872 if (!strcmp("menustyle", optname)) {
3873 const char *style_name;
3874 menu_item *style_pick = (menu_item *)0;
3875 tmpwin = create_nhwindow(NHW_MENU);
3876 start_menu(tmpwin);
3877 for (i = 0; i < SIZE(menutype); i++) {
3878 style_name = menutype[i];
3879 /* note: separate `style_name' variable used
3880 to avoid an optimizer bug in VAX C V2.3 */
3881 any.a_int = i + 1;
3882 add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0,
3883 ATR_NONE, style_name, MENU_UNSELECTED);
3885 end_menu(tmpwin, "Select menustyle:");
3886 if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) {
3887 flags.menu_style = style_pick->item.a_int - 1;
3888 free((void *)style_pick);
3890 destroy_nhwindow(tmpwin);
3891 retval = TRUE;
3892 } else if (!strcmp("pickup_burden", optname)) {
3893 const char *burden_name, *burden_letters = "ubsntl";
3894 menu_item *burden_pick = (menu_item *)0;
3895 tmpwin = create_nhwindow(NHW_MENU);
3896 start_menu(tmpwin);
3897 for (i = 0; i < SIZE(burdentype); i++) {
3898 burden_name = burdentype[i];
3899 any.a_int = i + 1;
3900 add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0,
3901 ATR_NONE, burden_name, MENU_UNSELECTED);
3903 end_menu(tmpwin, "Select encumbrance level:");
3904 if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) {
3905 flags.pickup_burden = burden_pick->item.a_int - 1;
3906 free((void *)burden_pick);
3908 destroy_nhwindow(tmpwin);
3909 retval = TRUE;
3910 } else if (!strcmp("pickup_types", optname)) {
3911 /* parseoptions will prompt for the list of types */
3912 parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile);
3913 retval = TRUE;
3914 } else if (!strcmp("disclose", optname)) {
3915 int pick_cnt, pick_idx, opt_idx;
3916 menu_item *disclosure_category_pick = (menu_item *)0;
3918 * The order of disclose_names[]
3919 * must correspond to disclosure_options in decl.h
3921 static const char *disclosure_names[] = {
3922 "inventory", "attributes", "vanquished", "genocides", "conduct"
3924 int disc_cat[NUM_DISCLOSURE_OPTIONS];
3925 const char *disclosure_name;
3927 tmpwin = create_nhwindow(NHW_MENU);
3928 start_menu(tmpwin);
3929 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
3930 disclosure_name = disclosure_names[i];
3931 any.a_int = i + 1;
3932 add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0,
3933 ATR_NONE, disclosure_name, MENU_UNSELECTED);
3934 disc_cat[i] = 0;
3936 end_menu(tmpwin, "Change which disclosure options categories:");
3937 if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_category_pick)) > 0) {
3938 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
3939 opt_idx = disclosure_category_pick[pick_idx].item.a_int - 1;
3940 disc_cat[opt_idx] = 1;
3942 free((void *)disclosure_category_pick);
3943 disclosure_category_pick = (menu_item *)0;
3945 destroy_nhwindow(tmpwin);
3947 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
3948 if (disc_cat[i]) {
3949 char dbuf[BUFSZ];
3950 menu_item *disclosure_option_pick = (menu_item *)0;
3951 sprintf(dbuf, "Disclosure options for %s:", disclosure_names[i]);
3952 tmpwin = create_nhwindow(NHW_MENU);
3953 start_menu(tmpwin);
3954 any.a_char = DISCLOSE_NO_WITHOUT_PROMPT;
3955 add_menu(tmpwin, NO_GLYPH, &any, 'a', 0,
3956 ATR_NONE,"Never disclose and don't prompt", MENU_UNSELECTED);
3957 any.a_void = 0;
3958 any.a_char = DISCLOSE_YES_WITHOUT_PROMPT;
3959 add_menu(tmpwin, NO_GLYPH, &any, 'b', 0,
3960 ATR_NONE,"Always disclose and don't prompt", MENU_UNSELECTED);
3961 any.a_void = 0;
3962 any.a_char = DISCLOSE_PROMPT_DEFAULT_NO;
3963 add_menu(tmpwin, NO_GLYPH, &any, 'c', 0,
3964 ATR_NONE,"Prompt and default answer to \"No\"", MENU_UNSELECTED);
3965 any.a_void = 0;
3966 any.a_char = DISCLOSE_PROMPT_DEFAULT_YES;
3967 add_menu(tmpwin, NO_GLYPH, &any, 'd', 0,
3968 ATR_NONE,"Prompt and default answer to \"Yes\"", MENU_UNSELECTED);
3969 end_menu(tmpwin, dbuf);
3970 if (select_menu(tmpwin, PICK_ONE, &disclosure_option_pick) > 0) {
3971 flags.end_disclose[i] = disclosure_option_pick->item.a_char;
3972 free((void *)disclosure_option_pick);
3974 destroy_nhwindow(tmpwin);
3977 retval = TRUE;
3978 } else if (!strcmp("runmode", optname)) {
3979 const char *mode_name;
3980 menu_item *mode_pick = (menu_item *)0;
3981 tmpwin = create_nhwindow(NHW_MENU);
3982 start_menu(tmpwin);
3983 for (i = 0; i < SIZE(runmodes); i++) {
3984 mode_name = runmodes[i];
3985 any.a_int = i + 1;
3986 add_menu(tmpwin, NO_GLYPH, &any, *mode_name, 0,
3987 ATR_NONE, mode_name, MENU_UNSELECTED);
3989 end_menu(tmpwin, "Select run/travel display mode:");
3990 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
3991 iflags.runmode = mode_pick->item.a_int - 1;
3992 free((void *)mode_pick);
3994 destroy_nhwindow(tmpwin);
3995 retval = TRUE;
3996 } else if (!strcmp("sortloot", optname)) {
3997 const char *sortl_name;
3998 menu_item *sortl_pick = (menu_item *)0;
3999 tmpwin = create_nhwindow(NHW_MENU);
4000 start_menu(tmpwin);
4001 for (i = 0; i < SIZE(sortltype); i++) {
4002 sortl_name = sortltype[i];
4003 any.a_char = *sortl_name;
4004 add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0,
4005 ATR_NONE, sortl_name, MENU_UNSELECTED);
4007 end_menu(tmpwin, "Select loot sorting type:");
4008 if (select_menu(tmpwin, PICK_ONE, &sortl_pick) > 0) {
4009 iflags.sortloot = sortl_pick->item.a_char;
4010 free((void *)sortl_pick);
4012 destroy_nhwindow(tmpwin);
4013 retval = TRUE;
4015 #ifdef TTY_GRAPHICS
4016 else if (!strcmp("msg_window", optname)) {
4017 /* by Christian W. Cooper */
4018 menu_item *window_pick = (menu_item *)0;
4019 tmpwin = create_nhwindow(NHW_MENU);
4020 start_menu(tmpwin);
4021 any.a_char = 's';
4022 add_menu(tmpwin, NO_GLYPH, &any, 's', 0,
4023 ATR_NONE, "single", MENU_UNSELECTED);
4024 any.a_char = 'c';
4025 add_menu(tmpwin, NO_GLYPH, &any, 'c', 0,
4026 ATR_NONE, "combination", MENU_UNSELECTED);
4027 any.a_char = 'f';
4028 add_menu(tmpwin, NO_GLYPH, &any, 'f', 0,
4029 ATR_NONE, "full", MENU_UNSELECTED);
4030 any.a_char = 'r';
4031 add_menu(tmpwin, NO_GLYPH, &any, 'r', 0,
4032 ATR_NONE, "reversed", MENU_UNSELECTED);
4033 end_menu(tmpwin, "Select message history display type:");
4034 if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
4035 iflags.prevmsg_window = window_pick->item.a_char;
4036 free((void *)window_pick);
4038 destroy_nhwindow(tmpwin);
4039 retval = TRUE;
4041 #endif
4042 else if (!strcmp("align_message", optname) ||
4043 !strcmp("align_status", optname)) {
4044 menu_item *window_pick = (menu_item *)0;
4045 char abuf[BUFSZ];
4046 boolean msg = (*(optname+6) == 'm');
4048 tmpwin = create_nhwindow(NHW_MENU);
4049 start_menu(tmpwin);
4050 any.a_int = ALIGN_TOP;
4051 add_menu(tmpwin, NO_GLYPH, &any, 't', 0,
4052 ATR_NONE, "top", MENU_UNSELECTED);
4053 any.a_int = ALIGN_BOTTOM;
4054 add_menu(tmpwin, NO_GLYPH, &any, 'b', 0,
4055 ATR_NONE, "bottom", MENU_UNSELECTED);
4056 any.a_int = ALIGN_LEFT;
4057 add_menu(tmpwin, NO_GLYPH, &any, 'l', 0,
4058 ATR_NONE, "left", MENU_UNSELECTED);
4059 any.a_int = ALIGN_RIGHT;
4060 add_menu(tmpwin, NO_GLYPH, &any, 'r', 0,
4061 ATR_NONE, "right", MENU_UNSELECTED);
4062 sprintf(abuf, "Select %s window placement relative to the map:",
4063 msg ? "message" : "status");
4064 end_menu(tmpwin, abuf);
4065 if (select_menu(tmpwin, PICK_ONE, &window_pick) > 0) {
4066 if (msg) iflags.wc_align_message = window_pick->item.a_int;
4067 else iflags.wc_align_status = window_pick->item.a_int;
4068 free((void *)window_pick);
4070 destroy_nhwindow(tmpwin);
4071 retval = TRUE;
4072 } else if (!strcmp("number_pad", optname)) {
4073 static const char *npchoices[3] =
4074 {"0 (off)", "1 (on)", "2 (on, DOS compatible)"};
4075 const char *npletters = "abc";
4076 menu_item *mode_pick = (menu_item *)0;
4078 tmpwin = create_nhwindow(NHW_MENU);
4079 start_menu(tmpwin);
4080 for (i = 0; i < SIZE(npchoices); i++) {
4081 any.a_int = i + 1;
4082 add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
4083 ATR_NONE, npchoices[i], MENU_UNSELECTED);
4085 end_menu(tmpwin, "Select number_pad mode:");
4086 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
4087 int mode = mode_pick->item.a_int - 1;
4088 switch(mode) {
4089 case 2:
4090 iflags.num_pad = 1;
4091 iflags.num_pad_mode = 1;
4092 break;
4093 case 1:
4094 iflags.num_pad = 1;
4095 iflags.num_pad_mode = 0;
4096 break;
4097 case 0:
4098 default:
4099 iflags.num_pad = 0;
4100 iflags.num_pad_mode = 0;
4102 free((void *)mode_pick);
4103 number_pad(iflags.num_pad);
4105 destroy_nhwindow(tmpwin);
4106 retval = TRUE;
4107 } else if (!strcmp("menu_headings", optname)) {
4108 static const char *mhchoices[3] = {"bold", "inverse", "underline"};
4109 const char *npletters = "biu";
4110 menu_item *mode_pick = (menu_item *)0;
4112 tmpwin = create_nhwindow(NHW_MENU);
4113 start_menu(tmpwin);
4114 for (i = 0; i < SIZE(mhchoices); i++) {
4115 any.a_int = i + 1;
4116 add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
4117 ATR_NONE, mhchoices[i], MENU_UNSELECTED);
4119 end_menu(tmpwin, "How to highlight menu headings:");
4120 if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
4121 int mode = mode_pick->item.a_int - 1;
4122 switch(mode) {
4123 case 2:
4124 iflags.menu_headings = ATR_ULINE;
4125 break;
4126 case 0:
4127 iflags.menu_headings = ATR_BOLD;
4128 break;
4129 case 1:
4130 default:
4131 iflags.menu_headings = ATR_INVERSE;
4133 free((void *)mode_pick);
4135 destroy_nhwindow(tmpwin);
4136 retval = TRUE;
4137 #ifdef AUTOPICKUP_EXCEPTIONS
4138 } else if (!strcmp("autopickup_exception", optname)) {
4139 boolean retval;
4140 int pick_cnt, pick_idx, opt_idx, pass;
4141 int totalapes = 0, numapes[2] = {0,0};
4142 menu_item *pick_list = (menu_item *)0;
4143 anything any;
4144 char apebuf[BUFSZ];
4145 struct autopickup_exception *ape;
4146 static const char *action_titles[] = {
4147 "a", "add new autopickup exception",
4148 "l", "list autopickup exceptions",
4149 "r", "remove existing autopickup exception",
4150 "e", "exit this menu",
4152 ape_again:
4153 opt_idx = 0;
4154 totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
4155 tmpwin = create_nhwindow(NHW_MENU);
4156 start_menu(tmpwin);
4157 any.a_int = 0;
4158 for (i = 0; i < SIZE(action_titles) ; i += 2) {
4159 any.a_int++;
4160 if (!totalapes && (i >= 2 && i < 6)) continue;
4161 add_menu(tmpwin, NO_GLYPH, &any, *action_titles[i],
4162 0, ATR_NONE, action_titles[i+1], MENU_UNSELECTED);
4164 end_menu(tmpwin, "Do what?");
4165 if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
4166 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
4167 opt_idx = pick_list[pick_idx].item.a_int - 1;
4169 free((void *)pick_list);
4170 pick_list = (menu_item *)0;
4172 destroy_nhwindow(tmpwin);
4173 if (pick_cnt < 1) return FALSE;
4175 if (opt_idx == 0) { /* add new */
4176 getlin("What new autopickup exception pattern?", &apebuf[1]);
4177 if (apebuf[1] == '\033') return FALSE;
4178 apebuf[0] = '"';
4179 strcat(apebuf,"\"");
4180 add_autopickup_exception(apebuf);
4181 goto ape_again;
4182 } else if (opt_idx == 3) {
4183 retval = TRUE;
4184 } else { /* remove */
4185 tmpwin = create_nhwindow(NHW_MENU);
4186 start_menu(tmpwin);
4187 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
4188 if (numapes[pass] == 0) continue;
4189 ape = iflags.autopickup_exceptions[pass];
4190 any.a_void = 0;
4191 add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
4192 (pass == 0) ? "Never pickup" : "Always pickup",
4193 MENU_UNSELECTED);
4194 for (i = 0; i < numapes[pass] && ape; i++) {
4195 any.a_void = (opt_idx == 1) ? 0 : ape;
4196 sprintf(apebuf, "\"%s\"", ape->pattern);
4197 add_menu(tmpwin, NO_GLYPH, &any,
4198 0, 0, ATR_NONE, apebuf, MENU_UNSELECTED);
4199 ape = ape->next;
4202 sprintf(apebuf, "%s autopickup exceptions",
4203 (opt_idx == 1) ? "List of" : "Remove which");
4204 end_menu(tmpwin, apebuf);
4205 pick_cnt = select_menu(tmpwin,
4206 (opt_idx == 1) ? PICK_NONE : PICK_ANY,
4207 &pick_list);
4208 if (pick_cnt > 0) {
4209 for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
4210 remove_autopickup_exception(
4211 (struct autopickup_exception *)pick_list[pick_idx].item.a_void);
4213 free((void *)pick_list);
4214 pick_list = (menu_item *)0;
4215 destroy_nhwindow(tmpwin);
4216 goto ape_again;
4218 retval = TRUE;
4219 #endif /* AUTOPICKUP_EXCEPTIONS */
4221 return retval;
4224 #define rolestring(val,array,field) ((val >= 0) ? array[val].field : \
4225 (val == ROLE_RANDOM) ? randomrole : none)
4227 /* This is ugly. We have all the option names in the compopt[] array,
4228 but we need to look at each option individually to get the value. */
4229 STATIC_OVL const char *
4230 get_compopt_value(optname, buf)
4231 const char *optname;
4232 char *buf;
4234 char ocl[MAXOCLASSES+1];
4235 static const char none[] = "(none)", randomrole[] = "random",
4236 to_be_done[] = "(to be done)",
4237 defopt[] = "default",
4238 defbrief[] = "def";
4239 int i;
4241 buf[0] = '\0';
4242 if (!strcmp(optname,"align_message"))
4243 sprintf(buf, "%s", iflags.wc_align_message == ALIGN_TOP ? "top" :
4244 iflags.wc_align_message == ALIGN_LEFT ? "left" :
4245 iflags.wc_align_message == ALIGN_BOTTOM ? "bottom" :
4246 iflags.wc_align_message == ALIGN_RIGHT ? "right" :
4247 defopt);
4248 else if (!strcmp(optname,"align_status"))
4249 sprintf(buf, "%s", iflags.wc_align_status == ALIGN_TOP ? "top" :
4250 iflags.wc_align_status == ALIGN_LEFT ? "left" :
4251 iflags.wc_align_status == ALIGN_BOTTOM ? "bottom" :
4252 iflags.wc_align_status == ALIGN_RIGHT ? "right" :
4253 defopt);
4254 else if (!strcmp(optname,"align"))
4255 sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj));
4256 #ifdef WIN32CON
4257 else if (!strcmp(optname,"altkeyhandler"))
4258 sprintf(buf, "%s", iflags.altkeyhandler[0] ?
4259 iflags.altkeyhandler : "default");
4260 #endif
4261 else if (!strcmp(optname, "boulder"))
4262 sprintf(buf, "%c", iflags.bouldersym ?
4263 iflags.bouldersym : oc_syms[(int)objects[BOULDER].oc_class]);
4264 else if (!strcmp(optname, "catname"))
4265 sprintf(buf, "%s", catname[0] ? catname : none );
4266 /* else if (!strcmp(optname, "coinsname"))
4267 sprintf(buf, "%s", coinsname[0] ? coinsname : none );*/
4268 else if (!strcmp(optname, "disclose")) {
4269 for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) {
4270 char topt[2];
4271 if (i) strcat(buf," ");
4272 topt[1] = '\0';
4273 topt[0] = flags.end_disclose[i];
4274 strcat(buf, topt);
4275 topt[0] = disclosure_options[i];
4276 strcat(buf, topt);
4279 else if (!strcmp(optname, "dogname"))
4280 sprintf(buf, "%s", dogname[0] ? dogname : none );
4281 else if (!strcmp(optname, "dragonname"))
4282 sprintf(buf, "%s", dragonname[0] ? dragonname : none );
4283 else if (!strcmp(optname, "monkeyname"))
4284 sprintf(buf, "%s", monkeyname[0] ? monkeyname : none );
4285 else if (!strcmp(optname, "parrotname"))
4286 sprintf(buf, "%s", parrotname[0] ? parrotname : none );
4287 else if (!strcmp(optname, "girlname"))
4288 sprintf(buf, "%s", girlname[0] ? girlname : none );
4289 else if (!strcmp(optname, "boyname"))
4290 sprintf(buf, "%s", boyname[0] ? boyname : none );
4291 else if (!strcmp(optname, "ravenname"))
4292 sprintf(buf, "%s", ravenname[0] ? ravenname : none );
4293 else if (!strcmp(optname, "plalias"))
4294 sprintf(buf, "%s", plalias[0] ? plalias : none );
4295 #ifdef DUMP_LOG
4296 else if (!strcmp(optname, "dumpfile"))
4297 sprintf(buf, "%s", dump_fn[0] ? dump_fn: none );
4298 #endif
4299 else if (!strcmp(optname, "dungeon"))
4300 sprintf(buf, "%s", to_be_done);
4301 else if (!strcmp(optname, "effects"))
4302 sprintf(buf, "%s", to_be_done);
4303 else if (!strcmp(optname, "font_map"))
4304 sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt);
4305 else if (!strcmp(optname, "font_message"))
4306 sprintf(buf, "%s", iflags.wc_font_message ? iflags.wc_font_message : defopt);
4307 else if (!strcmp(optname, "font_status"))
4308 sprintf(buf, "%s", iflags.wc_font_status ? iflags.wc_font_status : defopt);
4309 else if (!strcmp(optname, "font_menu"))
4310 sprintf(buf, "%s", iflags.wc_font_menu ? iflags.wc_font_menu : defopt);
4311 else if (!strcmp(optname, "font_text"))
4312 sprintf(buf, "%s", iflags.wc_font_text ? iflags.wc_font_text : defopt);
4313 else if (!strcmp(optname, "font_size_map")) {
4314 if (iflags.wc_fontsiz_map) sprintf(buf, "%d", iflags.wc_fontsiz_map);
4315 else strcpy(buf, defopt);
4317 else if (!strcmp(optname, "font_size_message")) {
4318 if (iflags.wc_fontsiz_message) sprintf(buf, "%d",
4319 iflags.wc_fontsiz_message);
4320 else strcpy(buf, defopt);
4322 else if (!strcmp(optname, "font_size_status")) {
4323 if (iflags.wc_fontsiz_status) sprintf(buf, "%d", iflags.wc_fontsiz_status);
4324 else strcpy(buf, defopt);
4326 else if (!strcmp(optname, "font_size_menu")) {
4327 if (iflags.wc_fontsiz_menu) sprintf(buf, "%d", iflags.wc_fontsiz_menu);
4328 else strcpy(buf, defopt);
4330 else if (!strcmp(optname, "font_size_text")) {
4331 if (iflags.wc_fontsiz_text) sprintf(buf, "%d",iflags.wc_fontsiz_text);
4332 else strcpy(buf, defopt);
4334 else if (!strcmp(optname, "fruit"))
4335 sprintf(buf, "%s", pl_fruit);
4336 else if (!strcmp(optname, "gender"))
4337 sprintf(buf, "%s", rolestring(flags.initgend, genders, adj));
4338 else if (!strcmp(optname, "ghoulname"))
4339 sprintf(buf, "%s", ghoulname[0] ? ghoulname : none );
4340 else if (!strcmp(optname, "horsename"))
4341 sprintf(buf, "%s", horsename[0] ? horsename : none);
4342 /* else if (!strcmp(optname, "lichenname"))
4343 sprintf(buf, "%s", lichenname[0] ? lichenname : none );*/
4344 else if (!strcmp(optname, "map_mode"))
4345 sprintf(buf, "%s",
4346 iflags.wc_map_mode == MAP_MODE_TILES ? "tiles" :
4347 iflags.wc_map_mode == MAP_MODE_ASCII4x6 ? "ascii4x6" :
4348 iflags.wc_map_mode == MAP_MODE_ASCII6x8 ? "ascii6x8" :
4349 iflags.wc_map_mode == MAP_MODE_ASCII8x8 ? "ascii8x8" :
4350 iflags.wc_map_mode == MAP_MODE_ASCII16x8 ? "ascii16x8" :
4351 iflags.wc_map_mode == MAP_MODE_ASCII7x12 ? "ascii7x12" :
4352 iflags.wc_map_mode == MAP_MODE_ASCII8x12 ? "ascii8x12" :
4353 iflags.wc_map_mode == MAP_MODE_ASCII16x12 ? "ascii16x12" :
4354 iflags.wc_map_mode == MAP_MODE_ASCII12x16 ? "ascii12x16" :
4355 iflags.wc_map_mode == MAP_MODE_ASCII10x18 ? "ascii10x18" :
4356 iflags.wc_map_mode == MAP_MODE_ASCII_FIT_TO_SCREEN ?
4357 "fit_to_screen" : defopt);
4358 else if (!strcmp(optname, "menustyle"))
4359 sprintf(buf, "%s", menutype[(int)flags.menu_style] );
4360 else if (!strcmp(optname, "menu_deselect_all"))
4361 sprintf(buf, "%s", to_be_done);
4362 else if (!strcmp(optname, "menu_deselect_page"))
4363 sprintf(buf, "%s", to_be_done);
4364 else if (!strcmp(optname, "menu_first_page"))
4365 sprintf(buf, "%s", to_be_done);
4366 else if (!strcmp(optname, "menu_invert_all"))
4367 sprintf(buf, "%s", to_be_done);
4368 else if (!strcmp(optname, "menu_headings")) {
4369 sprintf(buf, "%s", (iflags.menu_headings == ATR_BOLD) ?
4370 "bold" : (iflags.menu_headings == ATR_INVERSE) ?
4371 "inverse" : (iflags.menu_headings == ATR_ULINE) ?
4372 "underline" : "unknown");
4374 else if (!strcmp(optname, "menu_invert_page"))
4375 sprintf(buf, "%s", to_be_done);
4376 else if (!strcmp(optname, "menu_last_page"))
4377 sprintf(buf, "%s", to_be_done);
4378 else if (!strcmp(optname, "menu_next_page"))
4379 sprintf(buf, "%s", to_be_done);
4380 else if (!strcmp(optname, "menu_previous_page"))
4381 sprintf(buf, "%s", to_be_done);
4382 else if (!strcmp(optname, "menu_search"))
4383 sprintf(buf, "%s", to_be_done);
4384 else if (!strcmp(optname, "menu_select_all"))
4385 sprintf(buf, "%s", to_be_done);
4386 else if (!strcmp(optname, "menu_select_page"))
4387 sprintf(buf, "%s", to_be_done);
4388 else if (!strcmp(optname, "monsters"))
4389 sprintf(buf, "%s", to_be_done);
4390 else if (!strcmp(optname, "msghistory"))
4391 sprintf(buf, "%u", iflags.msg_history);
4392 #ifdef TTY_GRAPHICS
4393 else if (!strcmp(optname, "msg_window"))
4394 sprintf(buf, "%s", (iflags.prevmsg_window=='s') ? "single" :
4395 (iflags.prevmsg_window=='c') ? "combination" :
4396 (iflags.prevmsg_window=='f') ? "full" : "reversed");
4397 #endif
4398 else if (!strcmp(optname, "name"))
4399 sprintf(buf, "%s", plname);
4400 else if (!strcmp(optname, "number_pad"))
4401 sprintf(buf, "%s",
4402 (!iflags.num_pad) ? "0=off" :
4403 (iflags.num_pad_mode) ? "2=on, DOS compatible" : "1=on");
4404 else if (!strcmp(optname, "objects"))
4405 sprintf(buf, "%s", to_be_done);
4406 else if (!strcmp(optname, "packorder")) {
4407 oc_to_str(flags.inv_order, ocl);
4408 sprintf(buf, "%s", ocl);
4410 #ifdef CHANGE_COLOR
4411 else if (!strcmp(optname, "palette"))
4412 sprintf(buf, "%s", get_color_string());
4413 #endif
4414 else if (!strcmp(optname, "pettype"))
4415 sprintf(buf, "%s", (preferred_pet == 'c') ? "cat" :
4416 (preferred_pet == 'd') ? "dog" :
4417 (preferred_pet == 'n') ? "none" : "random");
4418 else if (!strcmp(optname, "pickup_burden"))
4419 sprintf(buf, "%s", burdentype[flags.pickup_burden] );
4420 else if (!strcmp(optname, "pickup_types")) {
4421 oc_to_str(flags.pickup_types, ocl);
4422 sprintf(buf, "%s", ocl[0] ? ocl : "none" );
4424 else if (!strcmp(optname, "pilesize")) {
4425 sprintf(buf, "%u", iflags.pilesize);
4427 else if (!strcmp(optname, "race"))
4428 sprintf(buf, "%s", rolestring(flags.initrace, races, noun));
4429 else if (!strcmp(optname, "role"))
4430 sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m));
4431 else if (!strcmp(optname, "ratname"))
4432 sprintf(buf, "%s", ratname[0] ? ratname : none );
4433 /* else if (!strcmp(optname, "rothename"))
4434 sprintf(buf, "%s", rothename[0] ? rothename : none );*/
4435 else if (!strcmp(optname, "runmode"))
4436 sprintf(buf, "%s", runmodes[iflags.runmode]);
4437 else if (!strcmp(optname, "scores")) {
4438 sprintf(buf, "%d top/%d around%s", flags.end_top,
4439 flags.end_around, flags.end_own ? "/own" : "");
4441 else if (!strcmp(optname, "scroll_amount")) {
4442 if (iflags.wc_scroll_amount) sprintf(buf, "%d",iflags.wc_scroll_amount);
4443 else strcpy(buf, defopt);
4445 else if (!strcmp(optname, "scroll_margin")) {
4446 if (iflags.wc_scroll_margin) sprintf(buf, "%d",iflags.wc_scroll_margin);
4447 else strcpy(buf, defopt);
4449 else if (!strcmp(optname, "sortloot")) {
4450 char *sortname = (char *)NULL;
4451 for (i=0; i < SIZE(sortltype) && sortname==(char *)NULL; i++) {
4452 if (iflags.sortloot == sortltype[i][0])
4453 sortname = (char *)sortltype[i];
4455 if (sortname != (char *)NULL)
4456 sprintf(buf, "%s", sortname);
4458 else if (!strcmp(optname, "player_selection"))
4459 sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
4460 #ifdef MSDOS
4461 else if (!strcmp(optname, "soundcard"))
4462 sprintf(buf, "%s", to_be_done);
4463 #endif
4464 else if (!strcmp(optname, "suppress_alert")) {
4465 if (flags.suppress_alert == 0L)
4466 strcpy(buf, none);
4467 else
4468 sprintf(buf, "%lu.%lu.%lu",
4469 FEATURE_NOTICE_VER_MAJ,
4470 FEATURE_NOTICE_VER_MIN,
4471 FEATURE_NOTICE_VER_PATCH);
4473 else if (!strcmp(optname, "term_cols")) {
4474 if (iflags.wc2_term_cols) sprintf(buf, "%d",iflags.wc2_term_cols);
4475 else strcpy(buf, defopt);
4477 else if (!strcmp(optname, "term_rows")) {
4478 if (iflags.wc2_term_rows) sprintf(buf, "%d",iflags.wc2_term_rows);
4479 else strcpy(buf, defopt);
4481 else if (!strcmp(optname, "tile_file"))
4482 sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
4483 else if (!strcmp(optname, "tile_height")) {
4484 if (iflags.wc_tile_height) sprintf(buf, "%d",iflags.wc_tile_height);
4485 else strcpy(buf, defopt);
4487 else if (!strcmp(optname, "tile_width")) {
4488 if (iflags.wc_tile_width) sprintf(buf, "%d",iflags.wc_tile_width);
4489 else strcpy(buf, defopt);
4491 else if (!strcmp(optname, "tileset"))
4492 sprintf(buf, "%s", tileset[0] ? tileset : none );
4493 else if (!strcmp(optname, "traps"))
4494 sprintf(buf, "%s", to_be_done);
4495 else if (!strcmp(optname, "vary_msgcount")) {
4496 if (iflags.wc_vary_msgcount) sprintf(buf, "%d",iflags.wc_vary_msgcount);
4497 else strcpy(buf, defopt);
4499 #ifdef MSDOS
4500 else if (!strcmp(optname, "video"))
4501 sprintf(buf, "%s", to_be_done);
4502 #endif
4503 #ifdef VIDEOSHADES
4504 # ifdef MSDOS
4505 else if (!strcmp(optname, "videoshades"))
4506 sprintf(buf, "%s-%s-%s", shade[0],shade[1],shade[2]);
4507 else if (!strcmp(optname, "videocolors"))
4508 sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
4509 ttycolors[CLR_RED], ttycolors[CLR_GREEN],
4510 ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
4511 ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN],
4512 ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
4513 ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
4514 ttycolors[CLR_BRIGHT_MAGENTA],
4515 ttycolors[CLR_BRIGHT_CYAN]);
4516 # else
4517 else if (!strcmp(optname, "videocolors"))
4518 sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d",
4519 ttycolors[CLR_RED], ttycolors[CLR_GREEN],
4520 ttycolors[CLR_BROWN], ttycolors[CLR_BLUE],
4521 ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN],
4522 ttycolors[CLR_GRAY], ttycolors[CLR_BLACK],
4523 ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN],
4524 ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE],
4525 ttycolors[CLR_BRIGHT_MAGENTA],
4526 ttycolors[CLR_BRIGHT_CYAN], ttycolors[CLR_WHITE]);
4527 # endif /* MSDOS */
4528 #endif /* VIDEOSHADES */
4529 else if (!strcmp(optname,"windowborders"))
4530 sprintf(buf, "%s", iflags.wc2_windowborders == 1 ? "1=on" :
4531 iflags.wc2_windowborders == 2 ? "2=off" :
4532 iflags.wc2_windowborders == 3 ? "3=auto" :
4533 defopt);
4534 else if (!strcmp(optname, "windowtype"))
4535 sprintf(buf, "%s", windowprocs.name);
4536 else if (!strcmp(optname, "windowcolors"))
4537 sprintf(buf, "%s/%s %s/%s %s/%s %s/%s",
4538 iflags.wc_foregrnd_menu ? iflags.wc_foregrnd_menu : defbrief,
4539 iflags.wc_backgrnd_menu ? iflags.wc_backgrnd_menu : defbrief,
4540 iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message : defbrief,
4541 iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message : defbrief,
4542 iflags.wc_foregrnd_status ? iflags.wc_foregrnd_status : defbrief,
4543 iflags.wc_backgrnd_status ? iflags.wc_backgrnd_status : defbrief,
4544 iflags.wc_foregrnd_text ? iflags.wc_foregrnd_text : defbrief,
4545 iflags.wc_backgrnd_text ? iflags.wc_backgrnd_text : defbrief);
4546 else if (!strcmp(optname, "wolfname"))
4547 sprintf(buf, "%s", wolfname[0] ? wolfname : none );
4548 #ifdef PREFIXES_IN_USE
4549 else {
4550 for (i = 0; i < PREFIX_COUNT; ++i)
4551 if (!strcmp(optname, fqn_prefix_names[i]) && fqn_prefix[i])
4552 sprintf(buf, "%s", fqn_prefix[i]);
4554 #endif
4556 if (buf[0]) return buf;
4557 else return "unknown";
4561 dotogglepickup()
4563 char buf[BUFSZ], ocl[MAXOCLASSES+1];
4565 flags.pickup = !flags.pickup;
4566 if (flags.pickup) {
4567 oc_to_str(flags.pickup_types, ocl);
4568 sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "no",
4569 #ifdef AUTOPICKUP_EXCEPTIONS
4570 (iflags.autopickup_exceptions[AP_LEAVE] ||
4571 iflags.autopickup_exceptions[AP_GRAB]) ?
4572 ((count_ape_maps((int *)0, (int *)0) == 1) ?
4573 ", with one exception" : ", with some exceptions") :
4574 #endif
4575 "");
4576 } else {
4577 strcpy(buf, "OFF");
4579 pline("Autopickup: %s.", buf);
4580 return 0;
4583 #ifdef AUTOPICKUP_EXCEPTIONS
4585 add_autopickup_exception(mapping)
4586 const char *mapping;
4588 struct autopickup_exception *ape, **apehead;
4589 char text[256], *text2;
4590 int textsize = 0;
4591 boolean grab = FALSE;
4593 if (sscanf(mapping, "\"%255[^\"]\"", text) == 1) {
4594 text2 = &text[0];
4595 if (*text2 == '<') { /* force autopickup */
4596 grab = TRUE;
4597 ++text2;
4598 } else if (*text2 == '>') { /* default - Do not pickup */
4599 grab = FALSE;
4600 ++text2;
4602 textsize = strlen(text2);
4603 apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB] :
4604 &iflags.autopickup_exceptions[AP_LEAVE];
4605 ape = (struct autopickup_exception *)
4606 alloc(sizeof(struct autopickup_exception));
4607 ape->pattern = (char *) alloc(textsize+1);
4608 strcpy(ape->pattern, text2);
4609 ape->grab = grab;
4610 if (!*apehead) ape->next = (struct autopickup_exception *)0;
4611 else ape->next = *apehead;
4612 *apehead = ape;
4613 } else {
4614 raw_print("syntax error in AUTOPICKUP_EXCEPTION");
4615 return 0;
4617 return 1;
4620 STATIC_OVL void
4621 remove_autopickup_exception(whichape)
4622 struct autopickup_exception *whichape;
4624 struct autopickup_exception *ape, *prev = 0;
4625 int chain = whichape->grab ? AP_GRAB : AP_LEAVE;
4627 for (ape = iflags.autopickup_exceptions[chain]; ape;) {
4628 if (ape == whichape) {
4629 struct autopickup_exception *freeape = ape;
4630 ape = ape->next;
4631 if (prev) prev->next = ape;
4632 else iflags.autopickup_exceptions[chain] = ape;
4633 free(freeape->pattern);
4634 free(freeape);
4635 } else {
4636 prev = ape;
4637 ape = ape->next;
4642 STATIC_OVL int
4643 count_ape_maps(leave, grab)
4644 int *leave, *grab;
4646 struct autopickup_exception *ape;
4647 int pass, totalapes, numapes[2] = {0,0};
4649 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
4650 ape = iflags.autopickup_exceptions[pass];
4651 while(ape) {
4652 ape = ape->next;
4653 numapes[pass]++;
4656 totalapes = numapes[AP_LEAVE] + numapes[AP_GRAB];
4657 if (leave) *leave = numapes[AP_LEAVE];
4658 if (grab) *grab = numapes[AP_GRAB];
4659 return totalapes;
4662 void
4663 free_autopickup_exceptions()
4665 struct autopickup_exception *ape;
4666 int pass;
4668 for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
4669 while((ape = iflags.autopickup_exceptions[pass]) != 0) {
4670 free(ape->pattern);
4671 iflags.autopickup_exceptions[pass] = ape->next;
4672 free(ape);
4676 #endif /* AUTOPICKUP_EXCEPTIONS */
4678 /* data for option_help() */
4679 static const char *opt_intro[] = {
4681 " SlashEM Options Help:",
4683 #define CONFIG_SLOT 3 /* fill in next value at run-time */
4684 (char *)0,
4685 #define ENV_SLOT 4 /* substitute variable name in next value at run-time */
4686 #if !defined(MICRO) && !defined(MAC)
4687 "or use `%s=\"<options>\"' in your environment",
4688 #endif
4689 "(<options> is a list of options separated by commas)",
4690 #ifdef VMS
4691 "-- for example, $ DEFINE %s \"noautopickup,fruit:kumquat\"",
4692 #endif
4693 "or press \"O\" while playing and use the menu.",
4695 "Boolean options (which can be negated by prefixing them with '!' or \"no\"):",
4696 (char *)0
4699 static const char *opt_epilog[] = {
4701 "Some of the options can be set only before the game is started; those",
4702 "items will not be selectable in the 'O' command's menu.",
4703 (char *)0
4706 void
4707 option_help()
4709 char buf[BUFSZ], buf2[BUFSZ];
4710 register int i;
4711 winid datawin;
4713 datawin = create_nhwindow(NHW_TEXT);
4714 sprintf(buf, "Set options as OPTIONS=<options> in %s", configfile);
4715 opt_intro[CONFIG_SLOT] = (const char *) buf;
4716 for (i = 0; opt_intro[i]; i++)
4717 if (i==ENV_SLOT)
4719 sprintf(buf2, opt_intro[ENV_SLOT], NETHACK_ENV_OPTIONS);
4720 putstr(datawin, 0, buf2);;
4722 else
4723 putstr(datawin, 0, opt_intro[i]);
4725 /* Boolean options */
4726 for (i = 0; boolopt[i].name; i++) {
4727 if (boolopt[i].addr) {
4728 #ifdef WIZARD
4729 #ifndef OBJ_SANITY
4730 if (boolopt[i].addr == &iflags.sanity_check && !wizard) continue;
4731 #endif
4732 if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard) continue;
4733 #endif
4734 next_opt(datawin, boolopt[i].name);
4737 next_opt(datawin, "");
4739 /* Compound options */
4740 putstr(datawin, 0, "Compound options:");
4741 for (i = 0; compopt[i].name; i++) {
4742 sprintf(buf2, "`%s'", compopt[i].name);
4743 sprintf(buf, "%-20s - %s%c", buf2, compopt[i].descr,
4744 compopt[i+1].name ? ',' : '.');
4745 putstr(datawin, 0, buf);
4748 for (i = 0; opt_epilog[i]; i++)
4749 putstr(datawin, 0, opt_epilog[i]);
4751 display_nhwindow(datawin, FALSE);
4752 destroy_nhwindow(datawin);
4753 return;
4757 * prints the next boolean option, on the same line if possible, on a new
4758 * line if not. End with next_opt("").
4760 void
4761 next_opt(datawin, str)
4762 winid datawin;
4763 const char *str;
4765 static char *buf = 0;
4766 int i;
4767 char *s;
4769 if (!buf) *(buf = (char *)alloc(BUFSZ)) = '\0';
4771 if (!*str) {
4772 s = eos(buf);
4773 if (s > &buf[1] && s[-2] == ',')
4774 strcpy(s - 2, "."); /* replace last ", " */
4775 i = COLNO; /* (greater than COLNO - 2) */
4776 } else {
4777 i = strlen(buf) + strlen(str) + 2;
4780 if (i > COLNO - 2) { /* rule of thumb */
4781 putstr(datawin, 0, buf);
4782 buf[0] = 0;
4784 if (*str) {
4785 strcat(buf, str);
4786 strcat(buf, ", ");
4787 } else {
4788 putstr(datawin, 0, str);
4789 free(buf), buf = 0;
4791 return;
4794 /* Returns the fid of the fruit type; if that type already exists, it
4795 * returns the fid of that one; if it does not exist, it adds a new fruit
4796 * type to the chain and returns the new one.
4799 fruitadd(str)
4800 char *str;
4802 register int i;
4803 register struct fruit *f;
4804 struct fruit *lastf = 0;
4805 int highest_fruit_id = 0;
4806 char buf[PL_FSIZ];
4807 boolean user_specified = (str == pl_fruit);
4808 int len = strlen(str);
4809 /* if not user-specified, then it's a fruit name for a fruit on
4810 * a bones level...
4813 /* Note: every fruit has an id (spe for fruit objects) of at least
4814 * 1; 0 is an error.
4816 if (user_specified) {
4817 /* disallow naming after other foods (since it'd be impossible
4818 * to tell the difference)
4821 boolean found = FALSE, numeric = FALSE;
4823 for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS;
4824 i++) {
4825 if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) {
4826 found = TRUE;
4827 break;
4831 char *c;
4833 c = pl_fruit;
4835 for(c = pl_fruit; *c >= '0' && *c <= '9'; c++)
4837 if (isspace(*c) || *c == 0) numeric = TRUE;
4839 if (found || numeric ||
4840 !strncmp(str, "cursed ", 7) ||
4841 !strncmp(str, "uncursed ", 9) ||
4842 !strncmp(str, "blessed ", 8) ||
4843 !strncmp(str, "partly eaten ", 13) ||
4844 (!strncmp(str, "tin of ", 7) &&
4845 (!strcmp(str+7, "spinach") ||
4846 name_to_mon(str+7) >= LOW_PM)) ||
4847 !strcmp(str, "empty tin") ||
4848 (((len > 7 && !strncmp(eos(str)-7," corpse",7)) ||
4849 (len > 4 && !strncmp(eos(str)-4, " egg",4))) &&
4850 name_to_mon(str) >= LOW_PM))
4852 strcpy(buf, pl_fruit);
4853 strcpy(pl_fruit, "candied ");
4854 nmcpy(pl_fruit+8, buf, PL_FSIZ-8);
4857 for(f=ffruit; f; f = f->nextf) {
4858 lastf = f;
4859 if(f->fid > highest_fruit_id) highest_fruit_id = f->fid;
4860 if(!strncmp(str, f->fname, PL_FSIZ))
4861 goto nonew;
4863 /* if adding another fruit would overflow spe, use a random
4864 fruit instead... we've got a lot to choose from. */
4865 if (highest_fruit_id >= 127) return rnd(127);
4866 highest_fruit_id++;
4867 f = newfruit();
4868 if (ffruit) lastf->nextf = f;
4869 else ffruit = f;
4870 strcpy(f->fname, str);
4871 f->fid = highest_fruit_id;
4872 f->nextf = 0;
4873 nonew:
4874 if (user_specified) current_fruit = highest_fruit_id;
4875 return f->fid;
4879 * This is a somewhat generic menu for taking a list of NetHack style
4880 * class choices and presenting them via a description
4881 * rather than the traditional NetHack characters.
4882 * (Benefits users whose first exposure to NetHack is via tiles).
4884 * prompt
4885 * The title at the top of the menu.
4887 * category: 0 = monster class
4888 * 1 = object class
4890 * way
4891 * FALSE = PICK_ONE, TRUE = PICK_ANY
4893 * class_list
4894 * a null terminated string containing the list of choices.
4896 * class_selection
4897 * a null terminated string containing the selected characters.
4899 * Returns number selected.
4902 choose_classes_menu(prompt, category, way, class_list, class_select)
4903 const char *prompt;
4904 int category;
4905 boolean way;
4906 char *class_list;
4907 char *class_select;
4909 menu_item *pick_list = (menu_item *)0;
4910 winid win;
4911 anything any;
4912 char buf[BUFSZ];
4913 int i, n;
4914 int ret;
4915 int next_accelerator, accelerator;
4917 if (class_list == (char *)0 || class_select == (char *)0) return 0;
4918 accelerator = 0;
4919 next_accelerator = 'a';
4920 any.a_void = 0;
4921 win = create_nhwindow(NHW_MENU);
4922 start_menu(win);
4923 while (*class_list) {
4924 const char *text;
4925 boolean selected;
4927 text = (char *)0;
4928 selected = FALSE;
4929 switch (category) {
4930 case 0:
4931 text = monexplain[def_char_to_monclass(*class_list)];
4932 accelerator = *class_list;
4933 sprintf(buf, "%s", text);
4934 break;
4935 case 1:
4936 text = objexplain[def_char_to_objclass(*class_list)];
4937 accelerator = next_accelerator;
4938 sprintf(buf, "%c %s", *class_list, text);
4939 break;
4940 default:
4941 impossible("choose_classes_menu: invalid category %d",
4942 category);
4944 if (way && *class_select) { /* Selections there already */
4945 if (index(class_select, *class_list)) {
4946 selected = TRUE;
4949 any.a_int = *class_list;
4950 add_menu(win, NO_GLYPH, &any, accelerator,
4951 category ? *class_list : 0,
4952 ATR_NONE, buf, selected);
4953 ++class_list;
4954 if (category > 0) {
4955 ++next_accelerator;
4956 if (next_accelerator == ('z' + 1)) next_accelerator = 'A';
4957 if (next_accelerator == ('Z' + 1)) break;
4960 end_menu(win, prompt);
4961 n = select_menu(win, way ? PICK_ANY : PICK_ONE, &pick_list);
4962 destroy_nhwindow(win);
4963 if (n > 0) {
4964 for (i = 0; i < n; ++i)
4965 *class_select++ = (char)pick_list[i].item.a_int;
4966 free((void *)pick_list);
4967 ret = n;
4968 } else if (n == -1) {
4969 class_select = eos(class_select);
4970 ret = -1;
4971 } else
4972 ret = 0;
4973 *class_select = '\0';
4974 return ret;
4977 struct wc_Opt wc_options[] = {
4978 {"ascii_map", WC_ASCII_MAP},
4979 {"color", WC_COLOR},
4980 {"eight_bit_tty", WC_EIGHT_BIT_IN},
4981 {"hilite_pet", WC_HILITE_PET},
4982 {"popup_dialog", WC_POPUP_DIALOG},
4983 {"player_selection", WC_PLAYER_SELECTION},
4984 {"preload_tiles", WC_PRELOAD_TILES},
4985 {"tiled_map", WC_TILED_MAP},
4986 {"tile_file", WC_TILE_FILE},
4987 {"tile_width", WC_TILE_WIDTH},
4988 {"tile_height", WC_TILE_HEIGHT},
4989 {"use_inverse", WC_INVERSE},
4990 {"align_message", WC_ALIGN_MESSAGE},
4991 {"align_status", WC_ALIGN_STATUS},
4992 {"font_map", WC_FONT_MAP},
4993 {"font_menu", WC_FONT_MENU},
4994 {"font_message",WC_FONT_MESSAGE},
4995 #if 0
4996 {"perm_invent",WC_PERM_INVENT},
4997 #endif
4998 {"font_size_map", WC_FONTSIZ_MAP},
4999 {"font_size_menu", WC_FONTSIZ_MENU},
5000 {"font_size_message", WC_FONTSIZ_MESSAGE},
5001 {"font_size_status", WC_FONTSIZ_STATUS},
5002 {"font_size_text", WC_FONTSIZ_TEXT},
5003 {"font_status", WC_FONT_STATUS},
5004 {"font_text", WC_FONT_TEXT},
5005 {"map_mode", WC_MAP_MODE},
5006 {"scroll_amount", WC_SCROLL_AMOUNT},
5007 {"scroll_margin", WC_SCROLL_MARGIN},
5008 {"splash_screen", WC_SPLASH_SCREEN},
5009 {"vary_msgcount",WC_VARY_MSGCOUNT},
5010 {"windowcolors", WC_WINDOWCOLORS},
5011 {"mouse_support", WC_MOUSE_SUPPORT},
5012 {(char *)0, 0L}
5015 struct wc_Opt wc2_options[] = {
5016 {"fullscreen", WC2_FULLSCREEN},
5017 {"softkeyboard", WC2_SOFTKEYBOARD},
5018 {"wraptext", WC2_WRAPTEXT},
5019 {"term_cols", WC2_TERM_COLS},
5020 {"term_rows", WC2_TERM_ROWS},
5021 {"windowborders", WC2_WINDOWBORDERS},
5022 {"petattr", WC2_PETATTR},
5023 {"guicolor", WC2_GUICOLOR},
5024 {(char *)0, 0L}
5029 * If a port wants to change or ensure that the
5030 * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is
5031 * correct (for controlling its display in the option menu) call
5032 * set_option_mod_status()
5033 * with the second argument of 0,2, or 3 respectively.
5035 void
5036 set_option_mod_status(optnam, status)
5037 const char *optnam;
5038 int status;
5040 int k;
5041 if (status < SET_IN_FILE || status > SET_IN_GAME) {
5042 impossible("set_option_mod_status: status out of range %d.",
5043 status);
5044 return;
5046 for (k = 0; boolopt[k].name; k++) {
5047 if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) {
5048 boolopt[k].optflags = status;
5049 return;
5052 for (k = 0; compopt[k].name; k++) {
5053 if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) {
5054 compopt[k].optflags = status;
5055 return;
5061 * You can set several wc_options in one call to
5062 * set_wc_option_mod_status() by setting
5063 * the appropriate bits for each option that you
5064 * are setting in the optmask argument
5065 * prior to calling.
5066 * example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN, SET_IN_GAME);
5068 void
5069 set_wc_option_mod_status(optmask, status)
5070 unsigned long optmask;
5071 int status;
5073 int k = 0;
5074 if (status < SET_IN_FILE || status > SET_IN_GAME) {
5075 impossible("set_wc_option_mod_status: status out of range %d.",
5076 status);
5077 return;
5079 while (wc_options[k].wc_name) {
5080 if (optmask & wc_options[k].wc_bit) {
5081 set_option_mod_status(wc_options[k].wc_name, status);
5083 k++;
5087 STATIC_OVL boolean
5088 is_wc_option(optnam)
5089 const char *optnam;
5091 int k = 0;
5092 while (wc_options[k].wc_name) {
5093 if (strcmp(wc_options[k].wc_name, optnam) == 0)
5094 return TRUE;
5095 k++;
5097 return FALSE;
5100 STATIC_OVL boolean
5101 wc_supported(optnam)
5102 const char *optnam;
5104 int k = 0;
5105 while (wc_options[k].wc_name) {
5106 if (!strcmp(wc_options[k].wc_name, optnam) &&
5107 (windowprocs.wincap & wc_options[k].wc_bit))
5108 return TRUE;
5109 k++;
5111 return FALSE;
5116 * You can set several wc2_options in one call to
5117 * set_wc2_option_mod_status() by setting
5118 * the appropriate bits for each option that you
5119 * are setting in the optmask argument
5120 * prior to calling.
5121 * example: set_wc2_option_mod_status(WC2_FULLSCREEN|WC2_SOFTKEYBOARD|WC2_WRAPTEXT, SET_IN_FILE);
5124 void
5125 set_wc2_option_mod_status(optmask, status)
5126 unsigned long optmask;
5127 int status;
5129 int k = 0;
5130 if (status < SET_IN_FILE || status > SET_IN_GAME) {
5131 impossible("set_wc2_option_mod_status: status out of range %d.",
5132 status);
5133 return;
5135 while (wc2_options[k].wc_name) {
5136 if (optmask & wc2_options[k].wc_bit) {
5137 set_option_mod_status(wc2_options[k].wc_name, status);
5139 k++;
5143 STATIC_OVL boolean
5144 is_wc2_option(optnam)
5145 const char *optnam;
5147 int k = 0;
5148 while (wc2_options[k].wc_name) {
5149 if (strcmp(wc2_options[k].wc_name, optnam) == 0)
5150 return TRUE;
5151 k++;
5153 return FALSE;
5156 STATIC_OVL boolean
5157 wc2_supported(optnam)
5158 const char *optnam;
5160 int k = 0;
5161 while (wc2_options[k].wc_name) {
5162 if (!strcmp(wc2_options[k].wc_name, optnam) &&
5163 (windowprocs.wincap2 & wc2_options[k].wc_bit))
5164 return TRUE;
5165 k++;
5167 return FALSE;
5171 STATIC_OVL void
5172 wc_set_font_name(wtype, fontname)
5173 int wtype;
5174 char *fontname;
5176 char **fn = (char **)0;
5177 if (!fontname) return;
5178 switch(wtype) {
5179 case NHW_MAP:
5180 fn = &iflags.wc_font_map;
5181 break;
5182 case NHW_MESSAGE:
5183 fn = &iflags.wc_font_message;
5184 break;
5185 case NHW_TEXT:
5186 fn = &iflags.wc_font_text;
5187 break;
5188 case NHW_MENU:
5189 fn = &iflags.wc_font_menu;
5190 break;
5191 case NHW_STATUS:
5192 fn = &iflags.wc_font_status;
5193 break;
5194 default:
5195 return;
5197 if (fn) {
5198 if (*fn) free(*fn);
5199 *fn = (char *)alloc(strlen(fontname) + 1);
5200 strcpy(*fn, fontname);
5202 return;
5205 STATIC_OVL int
5206 wc_set_window_colors(op)
5207 char *op;
5209 /* syntax:
5210 * menu white/black message green/yellow status white/blue text white/black
5213 int j;
5214 char buf[BUFSZ];
5215 char *wn, *tfg, *tbg, *newop;
5216 static const char *wnames[] = { "menu", "message", "status", "text" };
5217 static const char *shortnames[] = { "mnu", "msg", "sts", "txt" };
5218 static char **fgp[] = {
5219 &iflags.wc_foregrnd_menu,
5220 &iflags.wc_foregrnd_message,
5221 &iflags.wc_foregrnd_status,
5222 &iflags.wc_foregrnd_text
5224 static char **bgp[] = {
5225 &iflags.wc_backgrnd_menu,
5226 &iflags.wc_backgrnd_message,
5227 &iflags.wc_backgrnd_status,
5228 &iflags.wc_backgrnd_text
5231 strcpy(buf, op);
5232 newop = mungspaces(buf);
5233 while (newop && *newop) {
5235 wn = tfg = tbg = (char *)0;
5237 /* until first non-space in case there's leading spaces - before colorname*/
5238 while(*newop && isspace(*newop)) newop++;
5239 if (*newop) wn = newop;
5240 else return 0;
5242 /* until first space - colorname*/
5243 while(*newop && !isspace(*newop)) newop++;
5244 if (*newop) *newop = '\0';
5245 else return 0;
5246 newop++;
5248 /* until first non-space - before foreground*/
5249 while(*newop && isspace(*newop)) newop++;
5250 if (*newop) tfg = newop;
5251 else return 0;
5253 /* until slash - foreground */
5254 while(*newop && *newop != '/') newop++;
5255 if (*newop) *newop = '\0';
5256 else return 0;
5257 newop++;
5259 /* until first non-space (in case there's leading space after slash) - before background */
5260 while(*newop && isspace(*newop)) newop++;
5261 if (*newop) tbg = newop;
5262 else return 0;
5264 /* until first space - background */
5265 while(*newop && !isspace(*newop)) newop++;
5266 if (*newop) *newop++ = '\0';
5268 for (j = 0; j < 4; ++j) {
5269 if (!strcmpi(wn, wnames[j]) ||
5270 !strcmpi(wn, shortnames[j])) {
5271 if (tfg && !strstri(tfg, " ")) {
5272 if (*fgp[j]) free(*fgp[j]);
5273 *fgp[j] = (char *)alloc(strlen(tfg) + 1);
5274 strcpy(*fgp[j], tfg);
5276 if (tbg && !strstri(tbg, " ")) {
5277 if (*bgp[j]) free(*bgp[j]);
5278 *bgp[j] = (char *)alloc(strlen(tbg) + 1);
5279 strcpy(*bgp[j], tbg);
5281 break;
5285 return 1;
5288 #endif /* OPTION_LISTS_ONLY */
5290 /* for option nastytrap by Amy: select a random option and change its value
5291 * booleans just become true if they were false and in reverse, compound options get set to some random value
5292 * known problem: some options might not always be compiled into the game */
5293 void
5294 randomoptionchange()
5296 switch (rnd(76)) {
5297 case 1:
5298 flags.autodig = !flags.autodig;
5299 break;
5300 case 2:
5301 flags.pickup = !flags.pickup;
5302 break;
5303 case 3:
5304 #ifdef AUTO_OPEN
5305 iflags.autoopen = !iflags.autoopen;
5306 #endif
5307 break;
5308 case 4:
5309 flags.autoquiver = !flags.autoquiver;
5310 break;
5311 case 5:
5312 flags.bash_reminder = !flags.bash_reminder;
5313 break;
5314 case 6:
5315 flags.ins_chkpt = !flags.ins_chkpt;
5316 break;
5317 case 7:
5318 iflags.cmdassist = !iflags.cmdassist;
5319 break;
5320 case 8:
5321 iflags.wc_color = !iflags.wc_color;
5322 break;
5323 case 9:
5324 flags.confirm = !flags.confirm;
5325 break;
5326 case 10:
5327 flags.eatingboulders = !flags.eatingboulders;
5328 break;
5329 case 11:
5330 flags.eatingconfirm = !flags.eatingconfirm;
5331 break;
5332 case 12:
5333 flags.eatingdoors = !flags.eatingdoors;
5334 break;
5335 case 13:
5336 flags.eatingwalls = !flags.eatingwalls;
5337 break;
5338 case 14:
5339 iflags.wc_eight_bit_input = !iflags.wc_eight_bit_input;
5340 break;
5341 case 15:
5342 #if defined(TTY_GRAPHICS) || defined(CURSES_GRAPIHCS)
5343 iflags.extmenu = !iflags.extmenu;
5344 #endif
5345 break;
5346 case 16:
5347 flags.invlet_constant = !flags.invlet_constant;
5348 break;
5349 case 17:
5350 flags.graffitihilite = !flags.graffitihilite;
5351 break;
5352 case 18:
5353 flags.help = !flags.help;
5354 break;
5355 case 19:
5356 iflags.wc_hilite_pet = !iflags.wc_hilite_pet;
5357 break;
5358 case 20:
5359 flags.hitpointbar = !flags.hitpointbar;
5360 break;
5361 case 21:
5362 flags.inertiaconfirm = !flags.inertiaconfirm;
5363 break;
5364 case 22:
5365 #ifdef SHOW_WEIGHT
5366 flags.invweight = !flags.invweight;
5367 #endif
5368 break;
5369 case 23:
5370 flags.knapsacklimit = !flags.knapsacklimit;
5371 break;
5372 case 24:
5373 flags.lit_corridor = !flags.lit_corridor;
5374 break;
5375 case 25:
5376 iflags.lootabc = !iflags.lootabc;
5377 break;
5378 case 26:
5379 flags.materialglyph = !flags.materialglyph;
5380 break;
5381 case 27:
5382 iflags.memorizationknown = !iflags.memorizationknown;
5383 break;
5384 case 28:
5385 flags.menu_on_esc = !flags.menu_on_esc;
5386 break;
5387 case 29:
5388 iflags.use_menu_glyphs = !iflags.use_menu_glyphs;
5389 break;
5390 case 30:
5391 flags.moreforced = !flags.moreforced;
5392 break;
5393 case 31:
5394 iflags.numpadmessage = !iflags.numpadmessage;
5395 break;
5396 case 32:
5397 flags.paranoidquit = !flags.paranoidquit;
5398 break;
5399 case 33:
5400 flags.pickup_thrown = !flags.pickup_thrown;
5401 break;
5402 case 34:
5403 flags.pickup_cursed = !flags.pickup_cursed;
5404 break;
5405 case 35:
5406 flags.pokedex = !flags.pokedex;
5407 break;
5408 case 36:
5409 iflags.wc_popup_dialog = !iflags.wc_popup_dialog;
5410 break;
5411 case 37:
5412 flags.prayconfirm = !flags.prayconfirm;
5413 break;
5414 case 38:
5415 flags.pushweapon = !flags.pushweapon;
5416 break;
5417 case 39:
5418 iflags.quiver_fired = !iflags.quiver_fired;
5419 break;
5420 case 40:
5421 iflags.qwertz_layout = !iflags.qwertz_layout;
5422 break;
5423 case 41:
5424 flags.rest_on_space = !flags.rest_on_space;
5425 break;
5426 case 42:
5427 flags.safe_dog = !flags.safe_dog;
5428 break;
5429 case 43:
5430 iflags.should_change_color = !iflags.should_change_color;
5431 break;
5432 case 44:
5433 flags.showexp = !flags.showexp;
5434 break;
5435 case 45:
5436 iflags.showrace = !iflags.showrace;
5437 break;
5438 case 46:
5439 #ifdef REALTIME_ON_BOTL
5440 iflags.showrealtime = !iflags.showrealtime;
5441 #endif
5442 break;
5443 case 47:
5444 flags.showscore = !flags.showscore;
5445 break;
5446 case 48:
5447 iflags.showsym = !iflags.showsym;
5448 break;
5449 case 49:
5450 #ifdef SHOW_DMG
5451 flags.showdmg = !flags.showdmg;
5452 #endif
5453 break;
5454 case 50:
5455 #ifdef SHOW_WEIGHT
5456 flags.showweight = !flags.showweight;
5457 #endif
5458 break;
5459 case 51:
5460 flags.showmc = !flags.showmc;
5461 break;
5462 case 52:
5463 flags.showmovement = !flags.showmovement;
5464 break;
5465 case 53:
5466 flags.showlongstats = !flags.showlongstats;
5467 break;
5468 case 54:
5469 flags.showsanity = !flags.showsanity;
5470 break;
5471 case 55:
5472 flags.showsymbiotehp = !flags.showsymbiotehp;
5473 break;
5474 case 56:
5475 flags.silent = !flags.silent;
5476 break;
5477 case 57:
5478 flags.simpledescs = !flags.simpledescs;
5479 break;
5480 case 58:
5481 flags.sortpack = !flags.sortpack;
5482 break;
5483 case 59:
5484 flags.sparkle = !flags.sparkle;
5485 break;
5486 case 60:
5487 flags.standout = !flags.standout;
5488 break;
5489 case 61:
5490 flags.tech_description = !flags.tech_description;
5491 break;
5492 case 62:
5493 flags.tombstone = !flags.tombstone;
5494 break;
5495 case 63:
5496 flags.toptenwin = !flags.toptenwin;
5497 break;
5498 case 64:
5499 iflags.travelcmd = !iflags.travelcmd;
5500 break;
5501 case 65:
5502 iflags.wc_inverse = !iflags.wc_inverse;
5503 break;
5504 case 66:
5505 flags.verbose = !flags.verbose;
5506 break;
5507 case 67:
5508 flags.wallglyph = !flags.wallglyph;
5509 break;
5510 case 68:
5511 switch (rnd(4)) {
5512 case 1:
5513 flags.menu_style = MENU_TRADITIONAL;
5514 break;
5515 case 2:
5516 flags.menu_style = MENU_COMBINATION;
5517 break;
5518 case 3:
5519 flags.menu_style = MENU_PARTIAL;
5520 break;
5521 case 4:
5522 flags.menu_style = MENU_FULL;
5523 break;
5525 break;
5526 case 69:
5527 switch (rnd(3)) {
5528 case 1:
5529 iflags.num_pad = 0;
5530 iflags.num_pad_mode = 0;
5531 break;
5532 case 2:
5533 iflags.num_pad = 1;
5534 iflags.num_pad_mode = 0;
5535 break;
5536 case 3:
5537 iflags.num_pad = 1;
5538 iflags.num_pad_mode = 1;
5539 break;
5541 break;
5542 case 70:
5543 switch (rnd(4)) {
5544 case 1:
5545 iflags.runmode = RUN_TPORT;
5546 break;
5547 case 2:
5548 iflags.runmode = RUN_LEAP;
5549 break;
5550 case 3:
5551 iflags.runmode = RUN_STEP;
5552 break;
5553 case 4:
5554 iflags.runmode = RUN_CRAWL;
5555 break;
5557 break;
5558 case 71:
5559 iflags.msg_history = rnd(60);
5560 break;
5561 case 72:
5562 switch (rnd(4)) {
5563 case 1:
5564 iflags.prevmsg_window = 's';
5565 break;
5566 case 2:
5567 iflags.prevmsg_window = 'c';
5568 break;
5569 case 3:
5570 iflags.prevmsg_window = 'f';
5571 break;
5572 case 4:
5573 iflags.prevmsg_window = 'r';
5574 break;
5576 break;
5577 case 73:
5578 switch (rnd(6)) {
5579 case 1:
5580 flags.pickup_burden = UNENCUMBERED;
5581 break;
5582 case 2:
5583 flags.pickup_burden = SLT_ENCUMBER;
5584 break;
5585 case 3:
5586 flags.pickup_burden = MOD_ENCUMBER;
5587 break;
5588 case 4:
5589 flags.pickup_burden = HVY_ENCUMBER;
5590 break;
5591 case 5:
5592 flags.pickup_burden = EXT_ENCUMBER;
5593 break;
5594 case 6:
5595 flags.pickup_burden = OVERLOADED;
5596 break;
5598 break;
5599 case 74:
5600 iflags.pilesize = rnd(10);
5601 break;
5602 case 75:
5603 switch (rnd(3)) {
5604 case 1:
5605 iflags.sortloot = 'n';
5606 break;
5607 case 2:
5608 iflags.sortloot = 'l';
5609 break;
5610 case 3:
5611 iflags.sortloot = 'f';
5612 break;
5614 break;
5615 case 76:
5616 flags.epyxmode = !flags.epyxmode;
5617 if (isrougelike || Is_rogue_level(&u.uz)) assign_rogue_graphics(TRUE);
5618 break;
5619 default:
5620 break;
5624 /*options.c*/