Source:Options.c
From Wikihack
(Redirected from Options.c)
Below is the full text to src/options.c from NetHack 3.4.3. To link to a particular line, write [[options.c#line123]], for example.
[edit] Top of file
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. */ 4.
| The NetHack General Public License applies to screenshots, source code and other content from NetHack. |
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 17. 18. #define WINTYPELEN 16 19. 20. #ifdef DEFAULT_WC_TILED_MAP 21. #define PREFER_TILED TRUE 22. #else 23. #define PREFER_TILED FALSE 24. #endif 25.
[edit] Bool_Opt
26. /* 27. * NOTE: If you add (or delete) an option, please update the short 28. * options help (option_help()), the long options help (dat/opthelp), 29. * and the current options setting display function (doset()), 30. * and also the Guidebooks. 31. * 32. * The order matters. If an option is a an initial substring of another 33. * option (e.g. time and timed_delay) the shorter one must come first. 34. */ 35. 36. static struct Bool_Opt 37. { 38. const char *name; 39. boolean *addr, initvalue; 40. int optflags; 41. } boolopt[] = { 42. #ifdef AMIGA 43. {"altmeta", &flags.altmeta, TRUE, DISP_IN_GAME}, 44. #else 45. {"altmeta", (boolean *)0, TRUE, DISP_IN_GAME}, 46. #endif 47. {"ascii_map", &iflags.wc_ascii_map, !PREFER_TILED, SET_IN_GAME}, /*WC*/ 48. #ifdef MFLOPPY 49. {"asksavedisk", &flags.asksavedisk, FALSE, SET_IN_GAME}, 50. #else 51. {"asksavedisk", (boolean *)0, FALSE, SET_IN_FILE}, 52. #endif 53. {"autodig", &flags.autodig, FALSE, SET_IN_GAME}, 54. {"autopickup", &flags.pickup, TRUE, SET_IN_GAME}, 55. {"autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME}, 56. #if defined(MICRO) && !defined(AMIGA) 57. {"BIOS", &iflags.BIOS, FALSE, SET_IN_FILE}, 58. #else 59. {"BIOS", (boolean *)0, FALSE, SET_IN_FILE}, 60. #endif 61. #ifdef INSURANCE 62. {"checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME}, 63. #else 64. {"checkpoint", (boolean *)0, FALSE, SET_IN_FILE}, 65. #endif 66. #ifdef MFLOPPY 67. {"checkspace", &iflags.checkspace, TRUE, SET_IN_GAME}, 68. #else 69. {"checkspace", (boolean *)0, FALSE, SET_IN_FILE}, 70. #endif 71. {"cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME}, 72. # if defined(MICRO) || defined(WIN32) 73. {"color", &iflags.wc_color,TRUE, SET_IN_GAME}, /*WC*/ 74. # else /* systems that support multiple terminals, many monochrome */ 75. {"color", &iflags.wc_color, FALSE, SET_IN_GAME}, /*WC*/ 76. # endif 77. {"confirm",&flags.confirm, TRUE, SET_IN_GAME}, 78. #if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV) 79. {"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME}, 80. #else 81. {"DECgraphics", (boolean *)0, FALSE, SET_IN_FILE}, 82. #endif 83. {"eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME}, /*WC*/ 84. #ifdef TTY_GRAPHICS 85. {"extmenu", &iflags.extmenu, FALSE, SET_IN_GAME}, 86. #else 87. {"extmenu", (boolean *)0, FALSE, SET_IN_FILE}, 88. #endif 89. #ifdef OPT_DISPMAP 90. {"fast_map", &flags.fast_map, TRUE, SET_IN_GAME}, 91. #else 92. {"fast_map", (boolean *)0, TRUE, SET_IN_FILE}, 93. #endif 94. {"female", &flags.female, FALSE, DISP_IN_GAME}, 95. {"fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME}, 96. #ifdef AMIFLUSH 97. {"flush", &flags.amiflush, FALSE, SET_IN_GAME}, 98. #else 99. {"flush", (boolean *)0, FALSE, SET_IN_FILE}, 100. #endif 101. {"fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE}, 102. {"help", &flags.help, TRUE, SET_IN_GAME}, 103. {"hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME}, /*WC*/ 104. #ifdef ASCIIGRAPH 105. {"IBMgraphics", &iflags.IBMgraphics, FALSE, SET_IN_GAME}, 106. #else 107. {"IBMgraphics", (boolean *)0, FALSE, SET_IN_FILE}, 108. #endif 109. #ifndef MAC 110. {"ignintr", &flags.ignintr, FALSE, SET_IN_GAME}, 111. #else 112. {"ignintr", (boolean *)0, FALSE, SET_IN_FILE}, 113. #endif 114. {"large_font", &iflags.obsolete, FALSE, SET_IN_FILE}, /* OBSOLETE */ 115. {"legacy", &flags.legacy, TRUE, DISP_IN_GAME}, 116. {"lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME}, 117. {"lootabc", &iflags.lootabc, FALSE, SET_IN_GAME}, 118. #ifdef MAC_GRAPHICS_ENV 119. {"Macgraphics", &iflags.MACgraphics, TRUE, SET_IN_GAME}, 120. #else 121. {"Macgraphics", (boolean *)0, FALSE, SET_IN_FILE}, 122. #endif 123. #ifdef MAIL 124. {"mail", &flags.biff, TRUE, SET_IN_GAME}, 125. #else 126. {"mail", (boolean *)0, TRUE, SET_IN_FILE}, 127. #endif 128. #ifdef WIZARD 129. /* for menu debugging only*/ 130. {"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME}, 131. #else 132. {"menu_tab_sep", (boolean *)0, FALSE, SET_IN_FILE}, 133. #endif 134. {"mouse_support", &iflags.wc_mouse_support, TRUE, DISP_IN_GAME}, /*WC*/ 135. #ifdef NEWS 136. {"news", &iflags.news, TRUE, DISP_IN_GAME}, 137. #else 138. {"news", (boolean *)0, FALSE, SET_IN_FILE}, 139. #endif 140. {"null", &flags.null, TRUE, SET_IN_GAME}, 141. #ifdef MAC 142. {"page_wait", &flags.page_wait, TRUE, SET_IN_GAME}, 143. #else 144. {"page_wait", (boolean *)0, FALSE, SET_IN_FILE}, 145. #endif 146. {"perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME}, 147. {"popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME}, /*WC*/ 148. {"prayconfirm", &flags.prayconfirm, TRUE, SET_IN_GAME}, 149. {"preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME}, /*WC*/ 150. {"pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME}, 151. #if defined(MICRO) && !defined(AMIGA) 152. {"rawio", &iflags.rawio, FALSE, DISP_IN_GAME}, 153. #else 154. {"rawio", (boolean *)0, FALSE, SET_IN_FILE}, 155. #endif 156. {"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME}, 157. {"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME}, 158. #ifdef WIZARD 159. {"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME}, 160. #else 161. {"sanity_check", (boolean *)0, FALSE, SET_IN_FILE}, 162. #endif 163. #ifdef EXP_ON_BOTL 164. {"showexp", &flags.showexp, FALSE, SET_IN_GAME}, 165. #else 166. {"showexp", (boolean *)0, FALSE, SET_IN_FILE}, 167. #endif 168. {"showrace", &iflags.showrace, FALSE, SET_IN_GAME}, 169. #ifdef SCORE_ON_BOTL 170. {"showscore", &flags.showscore, FALSE, SET_IN_GAME}, 171. #else 172. {"showscore", (boolean *)0, FALSE, SET_IN_FILE}, 173. #endif 174. {"silent", &flags.silent, TRUE, SET_IN_GAME}, 175. {"softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE}, 176. {"sortpack", &flags.sortpack, TRUE, SET_IN_GAME}, 177. {"sound", &flags.soundok, TRUE, SET_IN_GAME}, 178. {"sparkle", &flags.sparkle, TRUE, SET_IN_GAME}, 179. {"standout", &flags.standout, FALSE, SET_IN_GAME}, 180. {"splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME}, /*WC*/ 181. {"tiled_map", &iflags.wc_tiled_map, PREFER_TILED, DISP_IN_GAME}, /*WC*/ 182. {"time", &flags.time, FALSE, SET_IN_GAME}, 183. #ifdef TIMED_DELAY 184. {"timed_delay", &flags.nap, TRUE, SET_IN_GAME}, 185. #else 186. {"timed_delay", (boolean *)0, FALSE, SET_IN_GAME}, 187. #endif 188. {"tombstone",&flags.tombstone, TRUE, SET_IN_GAME}, 189. {"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME}, 190. {"travel", &iflags.travelcmd, TRUE, SET_IN_GAME}, 191. #ifdef WIN32CON 192. {"use_inverse", &iflags.wc_inverse, TRUE, SET_IN_GAME}, /*WC*/ 193. #else 194. {"use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME}, /*WC*/ 195. #endif 196. {"verbose", &flags.verbose, TRUE, SET_IN_GAME}, 197. {"wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME}, 198. {(char *)0, (boolean *)0, FALSE, 0} 199. }; 200.
[edit] Comp_Opt
201. /* compound options, for option_help() and external programs like Amiga 202. * frontend */ 203. static struct Comp_Opt 204. { 205. const char *name, *descr; 206. int size; /* for frontends and such allocating space -- 207. * usually allowed size of data in game, but 208. * occasionally maximum reasonable size for 209. * typing when game maintains information in 210. * a different format */ 211. int optflags; 212. } compopt[] = { 213. { "align", "your starting alignment (lawful, neutral, or chaotic)", 214. 8, DISP_IN_GAME }, 215. { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/ 216. { "align_status", "status window alignment", 20, DISP_IN_GAME }, /*WC*/ 217. { "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME }, 218. { "boulder", "the symbol to use for displaying boulders", 219. 1, SET_IN_GAME }, 220. { "catname", "the name of your (first) cat (e.g., catname:Tabby)", 221. PL_PSIZ, DISP_IN_GAME }, 222. { "disclose", "the kinds of information to disclose at end of game", 223. sizeof(flags.end_disclose) * 2, 224. SET_IN_GAME }, 225. { "dogname", "the name of your (first) dog (e.g., dogname:Fang)", 226. PL_PSIZ, DISP_IN_GAME }, 227. { "dungeon", "the symbols to use in drawing the dungeon map", 228. MAXDCHARS+1, SET_IN_FILE }, 229. { "effects", "the symbols to use in drawing special effects", 230. MAXECHARS+1, SET_IN_FILE }, 231. { "font_map", "the font to use in the map window", 40, DISP_IN_GAME }, /*WC*/ 232. { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/ 233. { "font_message", "the font to use in the message window", 234. 40, DISP_IN_GAME }, /*WC*/ 235. { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ 236. { "font_size_menu", "the size of the menu font", 20, DISP_IN_GAME }, /*WC*/ 237. { "font_size_message", "the size of the message font", 20, DISP_IN_GAME }, /*WC*/ 238. { "font_size_status", "the size of the status font", 20, DISP_IN_GAME }, /*WC*/ 239. { "font_size_text", "the size of the text font", 20, DISP_IN_GAME }, /*WC*/ 240. { "font_status", "the font to use in status window", 40, DISP_IN_GAME }, /*WC*/ 241. { "font_text", "the font to use in text windows", 40, DISP_IN_GAME }, /*WC*/ 242. { "fruit", "the name of a fruit you enjoy eating", 243. PL_FSIZ, SET_IN_GAME }, 244. { "gender", "your starting gender (male or female)", 245. 8, DISP_IN_GAME }, 246. { "horsename", "the name of your (first) horse (e.g., horsename:Silver)", 247. PL_PSIZ, DISP_IN_GAME }, 248. { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/ 249. { "menustyle", "user interface for object selection", 250. MENUTYPELEN, SET_IN_GAME }, 251. { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE }, 252. { "menu_deselect_page", "deselect all items on this page of a menu", 253. 4, SET_IN_FILE }, 254. { "menu_first_page", "jump to the first page in a menu", 255. 4, SET_IN_FILE }, 256. { "menu_headings", "bold, inverse, or underline headings", 9, SET_IN_GAME }, 257. { "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE }, 258. { "menu_invert_page", "invert all items on this page of a menu", 259. 4, SET_IN_FILE }, 260. { "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE }, 261. { "menu_next_page", "goto the next menu page", 4, SET_IN_FILE }, 262. { "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE }, 263. { "menu_search", "search for a menu item", 4, SET_IN_FILE }, 264. { "menu_select_all", "select all items in a menu", 4, SET_IN_FILE }, 265. { "menu_select_page", "select all items on this page of a menu", 266. 4, SET_IN_FILE }, 267. { "monsters", "the symbols to use for monsters", 268. MAXMCLASSES, SET_IN_FILE }, 269. { "msghistory", "number of top line messages to save", 270. 5, DISP_IN_GAME }, 271. # ifdef TTY_GRAPHICS 272. {"msg_window", "the type of message window required",1, SET_IN_GAME}, 273. # else 274. {"msg_window", "the type of message window required", 1, SET_IN_FILE}, 275. # endif 276. { "name", "your character's name (e.g., name:Merlin-W)", 277. PL_NSIZ, DISP_IN_GAME }, 278. { "number_pad", "use the number pad", 1, SET_IN_GAME}, 279. { "objects", "the symbols to use for objects", 280. MAXOCLASSES, SET_IN_FILE }, 281. { "packorder", "the inventory order of the items in your pack", 282. MAXOCLASSES, SET_IN_GAME }, 283. #ifdef CHANGE_COLOR 284. { "palette", "palette (00c/880/-fff is blue/yellow/reverse white)", 285. 15 , SET_IN_GAME }, 286. # if defined(MAC) 287. { "hicolor", "same as palette, only order is reversed", 288. 15, SET_IN_FILE }, 289. # endif 290. #endif 291. { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME }, 292. { "pickup_burden", "maximum burden picked up before prompt", 293. 20, SET_IN_GAME }, 294. { "pickup_types", "types of objects to pick up automatically", 295. MAXOCLASSES, SET_IN_GAME }, 296. { "player_selection", "choose character via dialog or prompts", 297. 12, DISP_IN_GAME }, 298. { "race", "your starting race (e.g., Human, Elf)", 299. PL_CSIZ, DISP_IN_GAME }, 300. { "role", "your starting role (e.g., Barbarian, Valkyrie)", 301. PL_CSIZ, DISP_IN_GAME }, 302. { "runmode", "display frequency when `running' or `travelling'", 303. sizeof "teleport", SET_IN_GAME }, 304. { "scores", "the parts of the score list you wish to see", 305. 32, SET_IN_GAME }, 306. { "scroll_amount", "amount to scroll map when scroll_margin is reached", 307. 20, DISP_IN_GAME }, /*WC*/ 308. { "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/ 309. #ifdef MSDOS 310. { "soundcard", "type of sound card to use", 20, SET_IN_FILE }, 311. #endif 312. { "suppress_alert", "suppress alerts about version-specific features", 313. 8, SET_IN_GAME }, 314. { "tile_width", "width of tiles", 20, DISP_IN_GAME}, /*WC*/ 315. { "tile_height", "height of tiles", 20, DISP_IN_GAME}, /*WC*/ 316. { "tile_file", "name of tile file", 70, DISP_IN_GAME}, /*WC*/ 317. { "traps", "the symbols to use in drawing traps", 318. MAXTCHARS+1, SET_IN_FILE }, 319. { "vary_msgcount", "show more old messages at a time", 20, DISP_IN_GAME }, /*WC*/ 320. #ifdef MSDOS 321. { "video", "method of video updating", 20, SET_IN_FILE }, 322. #endif 323. #ifdef VIDEOSHADES 324. { "videocolors", "color mappings for internal screen routines", 325. 40, DISP_IN_GAME }, 326. { "videoshades", "gray shades to map to black/gray/white", 327. 32, DISP_IN_GAME }, 328. #endif 329. #ifdef WIN32CON 330. {"subkeyvalue", "override keystroke value", 7, SET_IN_FILE}, 331. #endif 332. { "windowcolors", "the foreground/background colors of windows", /*WC*/ 333. 80, DISP_IN_GAME }, 334. { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME }, 335. { (char *)0, (char *)0, 0, 0 } 336. }; 337.
338. #ifdef OPTION_LISTS_ONLY 339. #undef static 340. 341. #else /* use rest of file */ 342. 343. static boolean need_redraw; /* for doset() */ 344. 345. #if defined(TOS) && defined(TEXTCOLOR) 346. extern boolean colors_changed; /* in tos.c */ 347. #endif 348. 349. #ifdef VIDEOSHADES 350. extern char *shade[3]; /* in sys/msdos/video.c */ 351. extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */ 352. #endif 353. 354. static char def_inv_order[MAXOCLASSES] = { 355. COIN_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS, 356. SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS, 357. TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0, 358. }; 359.
[edit] Menu accelerators
360. /* 361. * Default menu manipulation command accelerators. These may _not_ be: 362. * 363. * + a number - reserved for counts 364. * + an upper or lower case US ASCII letter - used for accelerators 365. * + ESC - reserved for escaping the menu 366. * + NULL, CR or LF - reserved for commiting the selection(s). NULL 367. * is kind of odd, but the tty's xwaitforspace() will return it if 368. * someone hits a <ret>. 369. * + a default object class symbol - used for object class accelerators 370. * 371. * Standard letters (for now) are: 372. * 373. * < back 1 page 374. * > forward 1 page 375. * ^ first page 376. * | last page 377. * : search 378. * 379. * page all 380. * , select . 381. * \ deselect - 382. * ~ invert @ 383. * 384. * The command name list is duplicated in the compopt array. 385. */ 386. typedef struct { 387. const char *name; 388. char cmd; 389. } menu_cmd_t; 390. 391. #define NUM_MENU_CMDS 11 392. static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = { 393. /* 0*/ { "menu_first_page", MENU_FIRST_PAGE }, 394. { "menu_last_page", MENU_LAST_PAGE }, 395. { "menu_next_page", MENU_NEXT_PAGE }, 396. { "menu_previous_page", MENU_PREVIOUS_PAGE }, 397. { "menu_select_all", MENU_SELECT_ALL }, 398. /* 5*/ { "menu_deselect_all", MENU_UNSELECT_ALL }, 399. { "menu_invert_all", MENU_INVERT_ALL }, 400. { "menu_select_page", MENU_SELECT_PAGE }, 401. { "menu_deselect_page", MENU_UNSELECT_PAGE }, 402. { "menu_invert_page", MENU_INVERT_PAGE }, 403. /*10*/ { "menu_search", MENU_SEARCH }, 404. }; 405.
406. /* 407. * Allow the user to map incoming characters to various menu commands. 408. * The accelerator list must be a valid C string. 409. */ 410. #define MAX_MENU_MAPPED_CMDS 32 /* some number */ 411. char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS+1]; /* exported */ 412. static char mapped_menu_op[MAX_MENU_MAPPED_CMDS+1]; 413. static short n_menu_mapped = 0; 414. 415. 416. static boolean initial, from_file; 417. 418. STATIC_DCL void FDECL(doset_add_menu, (winid,const char *,int)); 419. STATIC_DCL void FDECL(nmcpy, (char *, const char *, int)); 420. STATIC_DCL void FDECL(escapes, (const char *, char *)); 421. STATIC_DCL void FDECL(rejectoption, (const char *)); 422. STATIC_DCL void FDECL(badoption, (const char *)); 423. STATIC_DCL char *FDECL(string_for_opt, (char *,BOOLEAN_P)); 424. STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *,BOOLEAN_P)); 425. STATIC_DCL void FDECL(bad_negation, (const char *,BOOLEAN_P)); 426. STATIC_DCL int FDECL(change_inv_order, (char *)); 427. STATIC_DCL void FDECL(oc_to_str, (char *, char *)); 428. STATIC_DCL void FDECL(graphics_opts, (char *,const char *,int,int)); 429. STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *)); 430. STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *)); 431. STATIC_DCL boolean FDECL(special_handling, (const char *, BOOLEAN_P, BOOLEAN_P)); 432. STATIC_DCL void FDECL(warning_opts, (char *,const char *)); 433. STATIC_DCL void FDECL(duplicate_opt_detection, (const char *, int)); 434. 435. STATIC_OVL void FDECL(wc_set_font_name, (int, char *)); 436. STATIC_OVL int FDECL(wc_set_window_colors, (char *)); 437. STATIC_OVL boolean FDECL(is_wc_option, (const char *)); 438. STATIC_OVL boolean FDECL(wc_supported, (const char *)); 439. STATIC_OVL boolean FDECL(is_wc2_option, (const char *)); 440. STATIC_OVL boolean FDECL(wc2_supported, (const char *)); 441. #ifdef AUTOPICKUP_EXCEPTIONS 442. STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *)); 443. STATIC_OVL int FDECL(count_ape_maps, (int *, int *)); 444. #endif 445.
[edit] match_optname
446. /* check whether a user-supplied option string is a proper leading 447. substring of a particular option name; option string might have 448. a colon or equals sign and arbitrary value appended to it */ 449. boolean 450. match_optname(user_string, opt_name, min_length, val_allowed) 451. const char *user_string, *opt_name; 452. int min_length; 453. boolean val_allowed; 454. { 455. int len = (int)strlen(user_string); 456. 457. if (val_allowed) { 458. const char *p = index(user_string, ':'), 459. *q = index(user_string, '='); 460. 461. if (!p || (q && q < p)) p = q; 462. while(p && p > user_string && isspace(*(p-1))) p--; 463. if (p) len = (int)(p - user_string); 464. } 465. 466. return (len >= min_length) && !strncmpi(opt_name, user_string, len); 467. } 468.
[edit] nh_getenv
469. /* most environment variables will eventually be printed in an error 470. * message if they don't work, and most error message paths go through 471. * BUFSZ buffers, which could be overflowed by a maliciously long 472. * environment variable. if a variable can legitimately be long, or 473. * if it's put in a smaller buffer, the responsible code will have to 474. * bounds-check itself. 475. */ 476. char * 477. nh_getenv(ev) 478. const char *ev; 479. { 480. char *getev = getenv(ev); 481. 482. if (getev && strlen(getev) <= (BUFSZ / 2)) 483. return getev; 484. else 485. return (char *)0; 486. } 487.
[edit] initoptions
488. void 489. initoptions() 490. { 491. #ifndef MAC 492. char *opts; 493. #endif 494. int i; 495. 496. /* initialize the random number generator */ 497. setrandom(); 498. 499. /* for detection of configfile options specified multiple times */ 500. iflags.opt_booldup = iflags.opt_compdup = (int *)0; 501. 502. for (i = 0; boolopt[i].name; i++) { 503. if (boolopt[i].addr) 504. *(boolopt[i].addr) = boolopt[i].initvalue; 505. } 506. flags.end_own = FALSE; 507. flags.end_top = 3; 508. flags.end_around = 2; 509. iflags.runmode = RUN_LEAP; 510. iflags.msg_history = 20; 511. #ifdef TTY_GRAPHICS 512. iflags.prevmsg_window = 's'; 513. #endif 514. iflags.menu_headings = ATR_INVERSE; 515. 516. /* Use negative indices to indicate not yet selected */ 517. flags.initrole = -1; 518. flags.initrace = -1; 519. flags.initgend = -1; 520. flags.initalign = -1; 521. 522. /* Set the default monster and object class symbols. Don't use */ 523. /* memcpy() --- sizeof char != sizeof uchar on some machines. */ 524. for (i = 0; i < MAXOCLASSES; i++) 525. oc_syms[i] = (uchar) def_oc_syms[i]; 526. for (i = 0; i < MAXMCLASSES; i++) 527. monsyms[i] = (uchar) def_monsyms[i]; 528. for (i = 0; i < WARNCOUNT; i++) 529. warnsyms[i] = def_warnsyms[i].sym; 530. iflags.bouldersym = 0; 531. iflags.travelcc.x = iflags.travelcc.y = -1; 532. flags.warnlevel = 1; 533. flags.warntype = 0L; 534. 535. /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */ 536. (void)memcpy((genericptr_t)flags.inv_order, 537. (genericptr_t)def_inv_order, sizeof flags.inv_order); 538. flags.pickup_types[0] = '\0'; 539. flags.pickup_burden = MOD_ENCUMBER; 540. 541. for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) 542. flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO; 543. switch_graphics(ASCII_GRAPHICS); /* set default characters */ 544. #if defined(UNIX) && defined(TTY_GRAPHICS) 545. /* 546. * Set defaults for some options depending on what we can 547. * detect about the environment's capabilities. 548. * This has to be done after the global initialization above 549. * and before reading user-specific initialization via 550. * config file/environment variable below. 551. */ 552. /* this detects the IBM-compatible console on most 386 boxes */ 553. if ((opts = nh_getenv("TERM")) && !strncmp(opts, "AT", 2)) { 554. switch_graphics(IBM_GRAPHICS); 555. # ifdef TEXTCOLOR 556. iflags.use_color = TRUE; 557. # endif 558. } 559. #endif /* UNIX && TTY_GRAPHICS */ 560. #if defined(UNIX) || defined(VMS) 561. # ifdef TTY_GRAPHICS 562. /* detect whether a "vt" terminal can handle alternate charsets */ 563. if ((opts = nh_getenv("TERM")) && 564. !strncmpi(opts, "vt", 2) && AS && AE && 565. index(AS, '\016') && index(AE, '\017')) { 566. switch_graphics(DEC_GRAPHICS); 567. } 568. # endif 569. #endif /* UNIX || VMS */ 570. 571. #ifdef MAC_GRAPHICS_ENV 572. switch_graphics(MAC_GRAPHICS); 573. #endif /* MAC_GRAPHICS_ENV */ 574. flags.menu_style = MENU_FULL; 575. 576. /* since this is done before init_objects(), do partial init here */ 577. objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD; 578. nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ); 579. #ifndef MAC 580. opts = getenv("NETHACKOPTIONS"); 581. if (!opts) opts = getenv("HACKOPTIONS"); 582. if (opts) { 583. if (*opts == '/' || *opts == '\\' || *opts == '@') { 584. if (*opts == '@') opts++; /* @filename */ 585. /* looks like a filename */ 586. if (strlen(opts) < BUFSZ/2) 587. read_config_file(opts); 588. } else { 589. read_config_file((char *)0); 590. /* let the total length of options be long; 591. * parseoptions() will check each individually 592. */ 593. parseoptions(opts, TRUE, FALSE); 594. } 595. } else 596. #endif 597. read_config_file((char *)0); 598. 599. (void)fruitadd(pl_fruit); 600. /* Remove "slime mold" from list of object names; this will */ 601. /* prevent it from being wished unless it's actually present */ 602. /* as a named (or default) fruit. Wishing for "fruit" will */ 603. /* result in the player's preferred fruit [better than "\033"]. */ 604. obj_descr[SLIME_MOLD].oc_name = "fruit"; 605. 606. return; 607. } 608.
[edit] nmcpy
609. STATIC_OVL void 610. nmcpy(dest, src, maxlen) 611. char *dest; 612. const char *src; 613. int maxlen; 614. { 615. int count; 616. 617. for(count = 1; count < maxlen; count++) { 618. if(*src == ',' || *src == '\0') break; /*exit on \0 terminator*/ 619. *dest++ = *src++; 620. } 621. *dest = 0; 622. } 623.
[edit] escapes
624. /* 625. * escapes: escape expansion for showsyms. C-style escapes understood include 626. * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix 627. * for control characters is also understood, and \[mM] followed by any of the 628. * previous forms or by a character has the effect of 'meta'-ing the value (so 629. * that the alternate character set will be enabled). 630. */ 631. STATIC_OVL void 632. escapes(cp, tp) 633. const char *cp; 634. char *tp; 635. { 636. while (*cp) 637. { 638. int cval = 0, meta = 0; 639. 640. if (*cp == '\\' && index("mM", cp[1])) { 641. meta = 1; 642. cp += 2; 643. } 644. if (*cp == '\\' && index("0123456789xXoO", cp[1])) 645. { 646. const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF"; 647. int dcount = 0; 648. 649. cp++; 650. if (*cp == 'x' || *cp == 'X') 651. for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++) 652. cval = (cval * 16) + (dp - hex) / 2; 653. else if (*cp == 'o' || *cp == 'O') 654. for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++) 655. cval = (cval * 8) + (*cp - '0'); 656. else 657. for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++) 658. cval = (cval * 10) + (*cp - '0'); 659. } 660. else if (*cp == '\\') /* C-style character escapes */ 661. { 662. switch (*++cp) 663. { 664. case '\\': cval = '\\'; break; 665. case 'n': cval = '\n'; break; 666. case 't': cval = '\t'; break; 667. case 'b': cval = '\b'; break; 668. case 'r': cval = '\r'; break; 669. default: cval = *cp; 670. } 671. cp++; 672. } 673. else if (*cp == '^') /* expand control-character syntax */ 674. { 675. cval = (*++cp & 0x1f); 676. cp++; 677. } 678. else 679. cval = *cp++; 680. if (meta) 681. cval |= 0x80; 682. *tp++ = cval; 683. } 684. *tp = '\0'; 685. } 686.
[edit] rejectoption
687. STATIC_OVL void 688. rejectoption(optname) 689. const char *optname; 690. { 691. #ifdef MICRO 692. pline("\"%s\" settable only from %s.", optname, configfile); 693. #else 694. pline("%s can be set only from NETHACKOPTIONS or %s.", optname, 695. configfile); 696. #endif 697. } 698.
[edit] badoption
699. STATIC_OVL void 700. badoption(opts) 701. const char *opts; 702. { 703. if (!initial) { 704. if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1)) 705. option_help(); 706. else 707. pline("Bad syntax: %s. Enter \"?g\" for help.", opts); 708. return; 709. } 710. #ifdef MAC 711. else return; 712. #endif 713. 714. if(from_file) 715. raw_printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts); 716. else 717. raw_printf("Bad syntax in NETHACKOPTIONS: %s.", opts); 718. 719. wait_synch(); 720. } 721.
[edit] string_for_opt
722. STATIC_OVL char * 723. string_for_opt(opts, val_optional) 724. char *opts; 725. boolean val_optional; 726. { 727. char *colon, *equals; 728. 729. colon = index(opts, ':'); 730. equals = index(opts, '='); 731. if (!colon || (equals && equals < colon)) colon = equals; 732. 733. if (!colon || !*++colon) { 734. if (!val_optional) badoption(opts); 735. return (char *)0; 736. } 737. return colon; 738. } 739.
[edit] string_for_env_opt
740. STATIC_OVL char * 741. string_for_env_opt(optname, opts, val_optional) 742. const char *optname; 743. char *opts; 744. boolean val_optional; 745. { 746. if(!initial) { 747. rejectoption(optname); 748. return (char *)0; 749. } 750. return string_for_opt(opts, val_optional); 751. } 752.
[edit] bad_negation
753. STATIC_OVL void 754. bad_negation(optname, with_parameter) 755. const char *optname; 756. boolean with_parameter; 757. { 758. pline_The("%s option may not %sbe negated.", 759. optname, 760. with_parameter ? "both have a value and " : ""); 761. } 762.
[edit] change_inv_order
763. /* 764. * Change the inventory order, using the given string as the new order. 765. * Missing characters in the new order are filled in at the end from 766. * the current inv_order, except for gold, which is forced to be first 767. * if not explicitly present. 768. * 769. * This routine returns 1 unless there is a duplicate or bad char in 770. * the string. 771. */ 772. STATIC_OVL int 773. change_inv_order(op) 774. char *op; 775. { 776. int oc_sym, num; 777. char *sp, buf[BUFSZ]; 778. 779. num = 0; 780. #ifndef GOLDOBJ 781. if (!index(op, GOLD_SYM)) 782. buf[num++] = COIN_CLASS; 783. #else 784. /* !!!! probably unnecessary with gold as normal inventory */ 785. #endif 786. 787. for (sp = op; *sp; sp++) { 788. oc_sym = def_char_to_objclass(*sp); 789. /* reject bad or duplicate entries */ 790. if (oc_sym == MAXOCLASSES || 791. oc_sym == RANDOM_CLASS || oc_sym == ILLOBJ_CLASS || 792. !index(flags.inv_order, oc_sym) || index(sp+1, *sp)) 793. return 0; 794. /* retain good ones */ 795. buf[num++] = (char) oc_sym; 796. } 797. buf[num] = '\0'; 798. 799. /* fill in any omitted classes, using previous ordering */ 800. for (sp = flags.inv_order; *sp; sp++) 801. if (!index(buf, *sp)) { 802. buf[num++] = *sp; 803. buf[num] = '\0'; /* explicitly terminate for next index() */ 804. } 805. 806. Strcpy(flags.inv_order, buf); 807. return 1; 808. } 809.
[edit] graphics_opts
810. STATIC_OVL void 811. graphics_opts(opts, optype, maxlen, offset) 812. register char *opts; 813. const char *optype; 814. int maxlen, offset; 815. { 816. uchar translate[MAXPCHARS+1]; 817. int length, i; 818. 819. if (!(opts = string_for_env_opt(optype, opts, FALSE))) 820. return; 821. escapes(opts, opts); 822. 823. length = strlen(opts); 824. if (length > maxlen) length = maxlen; 825. /* match the form obtained from PC configuration files */ 826. for (i = 0; i < length; i++) 827. translate[i] = (uchar) opts[i]; 828. assign_graphics(translate, length, maxlen, offset); 829. } 830.
[edit] warning_opts
831. STATIC_OVL void 832. warning_opts(opts, optype) 833. register char *opts; 834. const char *optype; 835. { 836. uchar translate[MAXPCHARS+1]; 837. int length, i; 838. 839. if (!(opts = string_for_env_opt(optype, opts, FALSE))) 840. return; 841. escapes(opts, opts); 842. 843. length = strlen(opts); 844. if (length > WARNCOUNT) length = WARNCOUNT; 845. /* match the form obtained from PC configuration files */ 846. for (i = 0; i < length; i++) 847. translate[i] = (((i < WARNCOUNT) && opts[i]) ? 848. (uchar) opts[i] : def_warnsyms[i].sym); 849. assign_warnings(translate); 850. } 851.
[edit] assign_warnings
852. void 853. assign_warnings(graph_chars) 854. register uchar *graph_chars; 855. { 856. int i; 857. for (i = 0; i < WARNCOUNT; i++) 858. if (graph_chars[i]) warnsyms[i] = graph_chars[i]; 859. } 860.
[edit] feature_alert_opts
861. STATIC_OVL int 862. feature_alert_opts(op, optn) 863. char *op; 864. const char *optn; 865. { 866. char buf[BUFSZ]; 867. boolean rejectver = FALSE; 868. unsigned long fnv = get_feature_notice_ver(op); /* version.c */ 869. if (fnv == 0L) return 0; 870. if (fnv > get_current_feature_ver()) 871. rejectver = TRUE; 872. else 873. flags.suppress_alert = fnv; 874. if (rejectver) { 875. if (!initial) 876. You_cant("disable new feature alerts for future versions."); 877. else { 878. Sprintf(buf, 879. "\n%s=%s Invalid reference to a future version ignored", 880. optn, op); 881. badoption(buf); 882. } 883. return 0; 884. } 885. if (!initial) { 886. Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ, 887. FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH); 888. pline("Feature change alerts disabled for NetHack %s features and prior.", 889. buf); 890. } 891. return 1; 892. } 893.
[edit] set_duplicate_opt_detection
894. void 895. set_duplicate_opt_detection(on_or_off) 896. int on_or_off; 897. { 898. int k, *optptr; 899. if (on_or_off != 0) { 900. /*-- ON --*/ 901. if (iflags.opt_booldup) 902. impossible("iflags.opt_booldup already on (memory leak)"); 903. iflags.opt_booldup = (int *)alloc(SIZE(boolopt) * sizeof(int)); 904. optptr = iflags.opt_booldup; 905. for (k = 0; k < SIZE(boolopt); ++k) 906. *optptr++ = 0; 907. 908. if (iflags.opt_compdup) 909. impossible("iflags.opt_compdup already on (memory leak)"); 910. iflags.opt_compdup = (int *)alloc(SIZE(compopt) * sizeof(int)); 911. optptr = iflags.opt_compdup; 912. for (k = 0; k < SIZE(compopt); ++k) 913. *optptr++ = 0; 914. } else { 915. /*-- OFF --*/ 916. if (iflags.opt_booldup) free((genericptr_t) iflags.opt_booldup); 917. iflags.opt_booldup = (int *)0; 918. if (iflags.opt_compdup) free((genericptr_t) iflags.opt_compdup); 919. iflags.opt_compdup = (int *)0; 920. } 921. } 922.
[edit] duplicate_opt_detection
923. STATIC_OVL void 924. duplicate_opt_detection(opts, bool_or_comp) 925. const char *opts; 926. int bool_or_comp; /* 0 == boolean option, 1 == compound */ 927. { 928. int i, *optptr; 929. #if defined(MAC) 930. /* the Mac has trouble dealing with the output of messages while 931. * processing the config file. That should get fixed one day. 932. * For now just return. 933. */ 934. return; 935. #endif 936. if ((bool_or_comp == 0) && iflags.opt_booldup && initial && from_file) { 937. for (i = 0; boolopt[i].name; i++) { 938. if (match_optname(opts, boolopt[i].name, 3, FALSE)) { 939. optptr = iflags.opt_booldup + i; 940. if (*optptr == 1) { 941. raw_printf( 942. "\nWarning - Boolean option specified multiple times: %s.\n", 943. opts); 944. wait_synch(); 945. } 946. *optptr += 1; 947. break; /* don't match multiple options */ 948. } 949. } 950. } else if ((bool_or_comp == 1) && iflags.opt_compdup && initial && from_file) { 951. for (i = 0; compopt[i].name; i++) { 952. if (match_optname(opts, compopt[i].name, strlen(compopt[i].name), TRUE)) { 953. optptr = iflags.opt_compdup + i; 954. if (*optptr == 1) { 955. raw_printf( 956. "\nWarning - compound option specified multiple times: %s.\n", 957. compopt[i].name); 958. wait_synch(); 959. } 960. *optptr += 1; 961. break; /* don't match multiple options */ 962. } 963. } 964. } 965. } 966.
[edit] parseoptions
967. void 968. parseoptions(opts, tinitial, tfrom_file) 969. register char *opts; 970. boolean tinitial, tfrom_file; 971. { 972. register char *op; 973. unsigned num; 974. boolean negated; 975. int i; 976. const char *fullname; 977. 978. initial = tinitial; 979. from_file = tfrom_file; 980. if ((op = index(opts, ',')) != 0) { 981. *op++ = 0; 982. parseoptions(op, initial, from_file); 983. } 984. if (strlen(opts) > BUFSZ/2) { 985. badoption("option too long"); 986. return; 987. } 988. 989. /* strip leading and trailing white space */ 990. while (isspace(*opts)) opts++; 991. op = eos(opts); 992. while (--op >= opts && isspace(*op)) *op = '\0'; 993. 994. if (!*opts) return; 995. negated = FALSE; 996. while ((*opts == '!') || !strncmpi(opts, "no", 2)) { 997. if (*opts == '!') opts++; else opts += 2; 998. negated = !negated; 999. } 1000. 1001. /* variant spelling */ 1002. 1003. if (match_optname(opts, "colour", 5, FALSE)) 1004. Strcpy(opts, "color"); /* fortunately this isn't longer */ 1005. 1006. if (!match_optname(opts, "subkeyvalue", 11, TRUE)) /* allow multiple */ 1007. duplicate_opt_detection(opts, 1); /* 1 means compound opts */ 1008. 1009. /* special boolean options */ 1010. 1011. if (match_optname(opts, "female", 3, FALSE)) { 1012. if(!initial && flags.female == negated) 1013. pline("That is not anatomically possible."); 1014. else 1015. flags.initgend = flags.female = !negated; 1016. return; 1017. } 1018. 1019. if (match_optname(opts, "male", 4, FALSE)) { 1020. if(!initial && flags.female != negated) 1021. pline("That is not anatomically possible."); 1022. else 1023. flags.initgend = flags.female = negated; 1024. return; 1025. } 1026. 1027. #if defined(MICRO) && !defined(AMIGA) 1028. /* included for compatibility with old NetHack.cnf files */ 1029. if (match_optname(opts, "IBM_", 4, FALSE)) { 1030. iflags.BIOS = !negated; 1031. return; 1032. } 1033. #endif /* MICRO */ 1034. 1035. /* compound options */ 1036. 1037. fullname = "pettype"; 1038. if (match_optname(opts, fullname, 3, TRUE)) { 1039. if ((op = string_for_env_opt(fullname, opts, negated)) != 0) { 1040. if (negated) bad_negation(fullname, TRUE); 1041. else switch (*op) { 1042. case 'd': /* dog */ 1043. case 'D': 1044. preferred_pet = 'd'; 1045. break; 1046. case 'c': /* cat */ 1047. case 'C': 1048. case 'f': /* feline */ 1049. case 'F': 1050. preferred_pet = 'c'; 1051. break; 1052. case 'n': /* no pet */ 1053. case 'N': 1054. preferred_pet = 'n'; 1055. break; 1056. default: 1057. pline("Unrecognized pet type '%s'.", op); 1058. break; 1059. } 1060. } else if (negated) preferred_pet = 'n'; 1061. return; 1062. } 1063. 1064. fullname = "catname"; 1065. if (match_optname(opts, fullname, 3, TRUE)) { 1066. if (negated) bad_negation(fullname, FALSE); 1067. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1068. nmcpy(catname, op, PL_PSIZ); 1069. return; 1070. } 1071. 1072. fullname = "dogname"; 1073. if (match_optname(opts, fullname, 3, TRUE)) { 1074. if (negated) bad_negation(fullname, FALSE); 1075. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1076. nmcpy(dogname, op, PL_PSIZ); 1077. return; 1078. } 1079. 1080. fullname = "horsename"; 1081. if (match_optname(opts, fullname, 5, TRUE)) { 1082. if (negated) bad_negation(fullname, FALSE); 1083. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1084. nmcpy(horsename, op, PL_PSIZ); 1085. return; 1086. } 1087. 1088. fullname = "number_pad"; 1089. if (match_optname(opts, fullname, 10, TRUE)) { 1090. boolean compat = (strlen(opts) <= 10); 1091. number_pad(iflags.num_pad ? 1 : 0); 1092. op = string_for_opt(opts, (compat || !initial)); 1093. if (!op) { 1094. if (compat || negated || initial) { 1095. /* for backwards compatibility, "number_pad" without a 1096. value is a synonym for number_pad:1 */ 1097. iflags.num_pad = !negated; 1098. if (iflags.num_pad) iflags.num_pad_mode = 0; 1099. } 1100. return; 1101. } 1102. if (negated) { 1103. bad_negation("number_pad", TRUE); 1104. return; 1105. } 1106. if (*op == '1' || *op == '2') { 1107. iflags.num_pad = 1; 1108. if (*op == '2') iflags.num_pad_mode = 1; 1109. else iflags.num_pad_mode = 0; 1110. } else if (*op == '0') { 1111. iflags.num_pad = 0; 1112. iflags.num_pad_mode = 0; 1113. } else badoption(opts); 1114. return; 1115. } 1116. 1117. fullname = "runmode"; 1118. if (match_optname(opts, fullname, 4, TRUE)) { 1119. if (negated) { 1120. iflags.runmode = RUN_TPORT; 1121. } else if ((op = string_for_opt(opts, FALSE)) != 0) { 1122. if (!strncmpi(op, "teleport", strlen(op))) 1123. iflags.runmode = RUN_TPORT; 1124. else if (!strncmpi(op, "run", strlen(op))) 1125. iflags.runmode = RUN_LEAP; 1126. else if (!strncmpi(op, "walk", strlen(op))) 1127. iflags.runmode = RUN_STEP; 1128. else if (!strncmpi(op, "crawl", strlen(op))) 1129. iflags.runmode = RUN_CRAWL; 1130. else 1131. badoption(opts); 1132. } 1133. return; 1134. } 1135. 1136. fullname = "msghistory"; 1137. if (match_optname(opts, fullname, 3, TRUE)) { 1138. op = string_for_env_opt(fullname, opts, negated); 1139. if ((negated && !op) || (!negated && op)) { 1140. iflags.msg_history = negated ? 0 : atoi(op); 1141. } else if (negated) bad_negation(fullname, TRUE); 1142. return; 1143. } 1144. 1145. fullname="msg_window"; 1146. /* msg_window:single, combo, full or reversed */ 1147. if (match_optname(opts, fullname, 4, TRUE)) { 1148. /* allow option to be silently ignored by non-tty ports */ 1149. #ifdef TTY_GRAPHICS 1150. int tmp; 1151. if (!(op = string_for_opt(opts, TRUE))) { 1152. tmp = negated ? 's' : 'f'; 1153. } else { 1154. if (negated) { 1155. bad_negation(fullname, TRUE); 1156. return; 1157. } 1158. tmp = tolower(*op); 1159. } 1160. switch (tmp) { 1161. case 's': /* single message history cycle (default if negated) */ 1162. iflags.prevmsg_window = 's'; 1163. break; 1164. case 'c': /* combination: two singles, then full page reversed */ 1165. iflags.prevmsg_window = 'c'; 1166. break; 1167. case 'f': /* full page (default if no opts) */ 1168. iflags.prevmsg_window = 'f'; 1169. break; 1170. case 'r': /* full page (reversed) */ 1171. iflags.prevmsg_window = 'r'; 1172. break; 1173. default: 1174. badoption(opts); 1175. } 1176. #endif 1177. return; 1178. } 1179. 1180. /* WINCAP 1181. * setting font options */ 1182. fullname = "font"; 1183. if (!strncmpi(opts, fullname, 4)) 1184. { 1185. int wintype = -1; 1186. char *fontopts = opts + 4; 1187. 1188. if (!strncmpi(fontopts, "map", 3) || 1189. !strncmpi(fontopts, "_map", 4)) 1190. wintype = NHW_MAP; 1191. else if (!strncmpi(fontopts, "message", 7) || 1192. !strncmpi(fontopts, "_message", 8)) 1193. wintype = NHW_MESSAGE; 1194. else if (!strncmpi(fontopts, "text", 4) || 1195. !strncmpi(fontopts, "_text", 5)) 1196. wintype = NHW_TEXT; 1197. else if (!strncmpi(fontopts, "menu", 4) || 1198. !strncmpi(fontopts, "_menu", 5)) 1199. wintype = NHW_MENU; 1200. else if (!strncmpi(fontopts, "status", 6) || 1201. !strncmpi(fontopts, "_status", 7)) 1202. wintype = NHW_STATUS; 1203. else if (!strncmpi(fontopts, "_size", 5)) { 1204. if (!strncmpi(fontopts, "_size_map", 8)) 1205. wintype = NHW_MAP; 1206. else if (!strncmpi(fontopts, "_size_message", 12)) 1207. wintype = NHW_MESSAGE; 1208. else if (!strncmpi(fontopts, "_size_text", 9)) 1209. wintype = NHW_TEXT; 1210. else if (!strncmpi(fontopts, "_size_menu", 9)) 1211. wintype = NHW_MENU; 1212. else if (!strncmpi(fontopts, "_size_status", 11)) 1213. wintype = NHW_STATUS; 1214. else { 1215. badoption(opts); 1216. return; 1217. } 1218. if (wintype > 0 && !negated && 1219. (op = string_for_opt(opts, FALSE)) != 0) { 1220. switch(wintype) { 1221. case NHW_MAP: 1222. iflags.wc_fontsiz_map = atoi(op); 1223. break; 1224. case NHW_MESSAGE: 1225. iflags.wc_fontsiz_message = atoi(op); 1226. break; 1227. case NHW_TEXT: 1228. iflags.wc_fontsiz_text = atoi(op); 1229. break; 1230. case NHW_MENU: 1231. iflags.wc_fontsiz_menu = atoi(op); 1232. break; 1233. case NHW_STATUS: 1234. iflags.wc_fontsiz_status = atoi(op); 1235. break; 1236. } 1237. } 1238. return; 1239. } else { 1240. badoption(opts); 1241. } 1242. if (wintype > 0 && 1243. (op = string_for_opt(opts, FALSE)) != 0) { 1244. wc_set_font_name(wintype, op); 1245. #ifdef MAC 1246. set_font_name (wintype, op); 1247. #endif 1248. return; 1249. } else if (negated) bad_negation(fullname, TRUE); 1250. return; 1251. } 1252. #ifdef CHANGE_COLOR 1253. if (match_optname(opts, "palette", 3, TRUE) 1254. # ifdef MAC 1255. || match_optname(opts, "hicolor", 3, TRUE) 1256. # endif 1257. ) { 1258. int color_number, color_incr; 1259. 1260. # ifdef MAC 1261. if (match_optname(opts, "hicolor", 3, TRUE)) { 1262. if (negated) { 1263. bad_negation("hicolor", FALSE); 1264. return; 1265. } 1266. color_number = CLR_MAX + 4; /* HARDCODED inverse number */ 1267. color_incr = -1; 1268. } else { 1269. # endif 1270. if (negated) { 1271. bad_negation("palette", FALSE); 1272. return; 1273. } 1274. color_number = 0; 1275. color_incr = 1; 1276. # ifdef MAC 1277. } 1278. # endif 1279. if ((op = string_for_opt(opts, FALSE)) != (char *)0) { 1280. char *pt = op; 1281. int cnt, tmp, reverse; 1282. long rgb; 1283. 1284. while (*pt && color_number >= 0) { 1285. cnt = 3; 1286. rgb = 0L; 1287. if (*pt == '-') { 1288. reverse = 1; 1289. pt++; 1290. } else { 1291. reverse = 0; 1292. } 1293. while (cnt-- > 0) { 1294. if (*pt && *pt != '/') { 1295. # ifdef AMIGA 1296. rgb <<= 4; 1297. # else 1298. rgb <<= 8; 1299. # endif 1300. tmp = *(pt++); 1301. if (isalpha(tmp)) { 1302. tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */ 1303. } else { 1304. tmp &= 0xf; /* Digits in ASCII too... */ 1305. } 1306. # ifndef AMIGA 1307. /* Add an extra so we fill f -> ff and 0 -> 00 */ 1308. rgb += tmp << 4; 1309. # endif 1310. rgb += tmp; 1311. } 1312. } 1313. if (*pt == '/') { 1314. pt++; 1315. } 1316. change_color(color_number, rgb, reverse); 1317. color_number += color_incr; 1318. } 1319. } 1320. if (!initial) { 1321. need_redraw = TRUE; 1322. } 1323. return; 1324. } 1325. #endif /* CHANGE_COLOR */ 1326. 1327. if (match_optname(opts, "fruit", 2, TRUE)) { 1328. char empty_str = '\0'; 1329. op = string_for_opt(opts, negated); 1330. if (negated) { 1331. if (op) { 1332. bad_negation("fruit", TRUE); 1333. return; 1334. } 1335. op = &empty_str; 1336. goto goodfruit; 1337. } 1338. if (!op) return; 1339. if (!initial) { 1340. struct fruit *f; 1341. 1342. num = 0; 1343. for(f=ffruit; f; f=f->nextf) { 1344. if (!strcmp(op, f->fname)) goto goodfruit; 1345. num++; 1346. } 1347. if (num >= 100) { 1348. pline("Doing that so many times isn't very fruitful."); 1349. return; 1350. } 1351. } 1352. goodfruit: 1353. nmcpy(pl_fruit, op, PL_FSIZ); 1354. /* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */ 1355. if (!*pl_fruit) 1356. nmcpy(pl_fruit, "slime mold", PL_FSIZ); 1357. if (!initial) 1358. (void)fruitadd(pl_fruit); 1359. /* If initial, then initoptions is allowed to do it instead 1360. * of here (initoptions always has to do it even if there's 1361. * no fruit option at all. Also, we don't want people 1362. * setting multiple fruits in their options.) 1363. */ 1364. return; 1365. } 1366. 1367. /* graphics:string */ 1368. fullname = "graphics"; 1369. if (match_optname(opts, fullname, 2, TRUE)) { 1370. if (negated) bad_negation(fullname, FALSE); 1371. else graphics_opts(opts, fullname, MAXPCHARS, 0); 1372. return; 1373. } 1374. fullname = "dungeon"; 1375. if (match_optname(opts, fullname, 2, TRUE)) { 1376. if (negated) bad_negation(fullname, FALSE); 1377. else graphics_opts(opts, fullname, MAXDCHARS, 0); 1378. return; 1379. } 1380. fullname = "traps"; 1381. if (match_optname(opts, fullname, 2, TRUE)) { 1382. if (negated) bad_negation(fullname, FALSE); 1383. else graphics_opts(opts, fullname, MAXTCHARS, MAXDCHARS); 1384. return; 1385. } 1386. fullname = "effects"; 1387. if (match_optname(opts, fullname, 2, TRUE)) { 1388. if (negated) bad_negation(fullname, FALSE); 1389. else 1390. graphics_opts(opts, fullname, MAXECHARS, MAXDCHARS+MAXTCHARS); 1391. return; 1392. } 1393. 1394. /* objects:string */ 1395. fullname = "objects"; 1396. if (match_optname(opts, fullname, 7, TRUE)) { 1397. int length; 1398. 1399. if (negated) { 1400. bad_negation(fullname, FALSE); 1401. return; 1402. } 1403. if (!(opts = string_for_env_opt(fullname, opts, FALSE))) 1404. return; 1405. escapes(opts, opts); 1406. 1407. /* 1408. * Override the default object class symbols. The first 1409. * object in the object class is the "random object". I 1410. * don't want to use 0 as an object class, so the "random 1411. * object" is basically a place holder. 1412. * 1413. * The object class symbols have already been initialized in 1414. * initoptions(). 1415. */ 1416. length = strlen(opts); 1417. if (length >= MAXOCLASSES) 1418. length = MAXOCLASSES-1; /* don't count RANDOM_OBJECT */ 1419. 1420. for (i = 0; i < length; i++) 1421. oc_syms[i+1] = (uchar) opts[i]; 1422. return; 1423. } 1424. 1425. /* monsters:string */ 1426. fullname = "monsters"; 1427. if (match_optname(opts, fullname, 8, TRUE)) { 1428. int length; 1429. 1430. if (negated) { 1431. bad_negation(fullname, FALSE); 1432. return; 1433. } 1434. if (!(opts = string_for_env_opt(fullname, opts, FALSE))) 1435. return; 1436. escapes(opts, opts); 1437. 1438. /* Override default mon class symbols set in initoptions(). */ 1439. length = strlen(opts); 1440. if (length >= MAXMCLASSES) 1441. length = MAXMCLASSES-1; /* mon class 0 unused */ 1442. 1443. for (i = 0; i < length; i++) 1444. monsyms[i+1] = (uchar) opts[i]; 1445. return; 1446. } 1447. fullname = "warnings"; 1448. if (match_optname(opts, fullname, 5, TRUE)) { 1449. if (negated) bad_negation(fullname, FALSE); 1450. else warning_opts(opts, fullname); 1451. return; 1452. } 1453. /* boulder:symbol */ 1454. fullname = "boulder"; 1455. if (match_optname(opts, fullname, 7, TRUE)) { 1456. int clash = 0; 1457. if (negated) { 1458. bad_negation(fullname, FALSE); 1459. return; 1460. } 1461. /* if (!(opts = string_for_env_opt(fullname, opts, FALSE))) */ 1462. if (!(opts = string_for_opt(opts, FALSE))) 1463. return; 1464. escapes(opts, opts); 1465. if (def_char_to_monclass(opts[0]) != MAXMCLASSES) 1466. clash = 1; 1467. else if (opts[0] >= '1' && opts[0] <= '5') 1468. clash = 2; 1469. if (clash) { 1470. /* symbol chosen matches a used monster or warning 1471. symbol which is not good - reject it*/ 1472. pline( 1473. "Badoption - boulder symbol '%c' conflicts with a %s symbol.", 1474. opts[0], (clash == 1) ? "monster" : "warning"); 1475. } else { 1476. /* 1477. * Override the default boulder symbol. 1478. */ 1479. iflags.bouldersym = (uchar) opts[0]; 1480. } 1481. if (!initial) need_redraw = TRUE; 1482. return; 1483. } 1484. 1485. /* name:string */ 1486. fullname = "name"; 1487. if (match_optname(opts, fullname, 4, TRUE)) { 1488. if (negated) bad_negation(fullname, FALSE); 1489. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1490. nmcpy(plname, op, PL_NSIZ); 1491. return; 1492. } 1493. 1494. /* role:string or character:string */ 1495. fullname = "role"; 1496. if (match_optname(opts, fullname, 4, TRUE) || 1497. match_optname(opts, (fullname = "character"), 4, TRUE)) { 1498. if (negated) bad_negation(fullname, FALSE); 1499. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1500. if ((flags.initrole = str2role(op)) == ROLE_NONE) 1501. badoption(opts); 1502. else /* Backwards compatibility */ 1503. nmcpy(pl_character, op, PL_NSIZ); 1504. } 1505. return; 1506. } 1507. 1508. /* race:string */ 1509. fullname = "race"; 1510. if (match_optname(opts, fullname, 4, TRUE)) { 1511. if (negated) bad_negation(fullname, FALSE); 1512. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1513. if ((flags.initrace = str2race(op)) == ROLE_NONE) 1514. badoption(opts); 1515. else /* Backwards compatibility */ 1516. pl_race = *op; 1517. } 1518. return; 1519. } 1520. 1521. /* gender:string */ 1522. fullname = "gender"; 1523. if (match_optname(opts, fullname, 4, TRUE)) { 1524. if (negated) bad_negation(fullname, FALSE); 1525. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1526. if ((flags.initgend = str2gend(op)) == ROLE_NONE) 1527. badoption(opts); 1528. else 1529. flags.female = flags.initgend; 1530. } 1531. return; 1532. } 1533. 1534. /* altkeyhandler:string */ 1535. fullname = "altkeyhandler"; 1536. if (match_optname(opts, fullname, 4, TRUE)) { 1537. if (negated) bad_negation(fullname, FALSE); 1538. else if ((op = string_for_opt(opts, negated))) { 1539. #ifdef WIN32CON 1540. (void)strncpy(iflags.altkeyhandler, op, MAX_ALTKEYHANDLER - 5); 1541. load_keyboard_handler(); 1542. #endif 1543. } 1544. return; 1545. } 1546. 1547. /* WINCAP 1548. * align_status:[left|top|right|bottom] */ 1549. fullname = "align_status"; 1550. if (match_optname(opts, fullname, sizeof("align_status")-1, TRUE)) { 1551. op = string_for_opt(opts, negated); 1552. if (op && !negated) { 1553. if (!strncmpi (op, "left", sizeof("left")-1)) 1554. iflags.wc_align_status = ALIGN_LEFT; 1555. else if (!strncmpi (op, "top", sizeof("top")-1)) 1556. iflags.wc_align_status = ALIGN_TOP; 1557. else if (!strncmpi (op, "right", sizeof("right")-1)) 1558. iflags.wc_align_status = ALIGN_RIGHT; 1559. else if (!strncmpi (op, "bottom", sizeof("bottom")-1)) 1560. iflags.wc_align_status = ALIGN_BOTTOM; 1561. else 1562. badoption(opts); 1563. } else if (negated) bad_negation(fullname, TRUE); 1564. return; 1565. } 1566. /* WINCAP 1567. * align_message:[left|top|right|bottom] */ 1568. fullname = "align_message"; 1569. if (match_optname(opts, fullname, sizeof("align_message")-1, TRUE)) { 1570. op = string_for_opt(opts, negated); 1571. if (op && !negated) { 1572. if (!strncmpi (op, "left", sizeof("left")-1)) 1573. iflags.wc_align_message = ALIGN_LEFT; 1574. else if (!strncmpi (op, "top", sizeof("top")-1)) 1575. iflags.wc_align_message = ALIGN_TOP; 1576. else if (!strncmpi (op, "right", sizeof("right")-1)) 1577. iflags.wc_align_message = ALIGN_RIGHT; 1578. else if (!strncmpi (op, "bottom", sizeof("bottom")-1)) 1579. iflags.wc_align_message = ALIGN_BOTTOM; 1580. else 1581. badoption(opts); 1582. } else if (negated) bad_negation(fullname, TRUE); 1583. return; 1584. } 1585. /* align:string */ 1586. fullname = "align"; 1587. if (match_optname(opts, fullname, sizeof("align")-1, TRUE)) { 1588. if (negated) bad_negation(fullname, FALSE); 1589. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1590. if ((flags.initalign = str2align(op)) == ROLE_NONE) 1591. badoption(opts); 1592. return; 1593. } 1594. 1595. /* the order to list the pack */ 1596. fullname = "packorder"; 1597. if (match_optname(opts, fullname, 4, TRUE)) { 1598. if (negated) { 1599. bad_negation(fullname, FALSE); 1600. return; 1601. } else if (!(op = string_for_opt(opts, FALSE))) return; 1602. 1603. if (!change_inv_order(op)) 1604. badoption(opts); 1605. return; 1606. } 1607. 1608. /* maximum burden picked up before prompt (Warren Cheung) */ 1609. fullname = "pickup_burden"; 1610. if (match_optname(opts, fullname, 8, TRUE)) { 1611. if (negated) { 1612. bad_negation(fullname, FALSE); 1613. return; 1614. } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1615. switch (tolower(*op)) { 1616. /* Unencumbered */ 1617. case 'u': 1618. flags.pickup_burden = UNENCUMBERED; 1619. break; 1620. /* Burdened (slight encumbrance) */ 1621. case 'b': 1622. flags.pickup_burden = SLT_ENCUMBER; 1623. break; 1624. /* streSsed (moderate encumbrance) */ 1625. case 's': 1626. flags.pickup_burden = MOD_ENCUMBER; 1627. break; 1628. /* straiNed (heavy encumbrance) */ 1629. case 'n': 1630. flags.pickup_burden = HVY_ENCUMBER; 1631. break; 1632. /* OverTaxed (extreme encumbrance) */ 1633. case 'o': 1634. case 't': 1635. flags.pickup_burden = EXT_ENCUMBER; 1636. break; 1637. /* overLoaded */ 1638. case 'l': 1639. flags.pickup_burden = OVERLOADED; 1640. break; 1641. default: 1642. badoption(opts); 1643. } 1644. } 1645. return; 1646. } 1647. 1648. /* types of objects to pick up automatically */ 1649. if (match_optname(opts, "pickup_types", 8, TRUE)) { 1650. char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], 1651. qbuf[QBUFSZ], abuf[BUFSZ]; 1652. int oc_sym; 1653. boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu; 1654. 1655. oc_to_str(flags.pickup_types, tbuf); 1656. flags.pickup_types[0] = '\0'; /* all */ 1657. op = string_for_opt(opts, (compat || !initial)); 1658. if (!op) { 1659. if (compat || negated || initial) { 1660. /* for backwards compatibility, "pickup" without a 1661. value is a synonym for autopickup of all types 1662. (and during initialization, we can't prompt yet) */ 1663. flags.pickup = !negated; 1664. return; 1665. } 1666. oc_to_str(flags.inv_order, ocl); 1667. use_menu = TRUE; 1668. if (flags.menu_style == MENU_TRADITIONAL || 1669. flags.menu_style == MENU_COMBINATION) { 1670. use_menu = FALSE; 1671. Sprintf(qbuf, "New pickup_types: [%s am] (%s)", 1672. ocl, *tbuf ? tbuf : "all"); 1673. getlin(qbuf, abuf); 1674. op = mungspaces(abuf); 1675. if (abuf[0] == '\0' || abuf[0] == '\033') 1676. op = tbuf; /* restore */ 1677. else if (abuf[0] == 'm') 1678. use_menu = TRUE; 1679. } 1680. if (use_menu) { 1681. (void) choose_classes_menu("Auto-Pickup what?", 1, 1682. TRUE, ocl, tbuf); 1683. op = tbuf; 1684. } 1685. } 1686. if (negated) { 1687. bad_negation("pickup_types", TRUE); 1688. return; 1689. }