abstract
| - Below is the full text to options.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/options.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)options.c 3.4 2002/02/07 */ 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 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 16. #endif 17. 18. #define WINTYPELEN 16 19. 20. /* 21. * NOTE: If you add (or delete) an option, please update the short 22. * options help (option_help()), the long options help (dat/opthelp), 23. * and the current options setting display function (doset()), 24. * and also the Guidebooks. 25. * 26. * The order matters. If an option is a an initial substring of another 27. * option (e.g. time and timed_delay) the shorter one must come first. 28. */ 29. 30. static struct Bool_Opt 31. { 32. const char *name; 33. boolean *addr, initvalue; 34. int optflags; 35. } boolopt[] = { 36. #ifdef AMIGA 37. {"altmeta", &flags.altmeta, TRUE, DISP_IN_GAME}, 38. #else 39. {"altmeta", (boolean *)0, TRUE, DISP_IN_GAME}, 40. #endif 41. {"ascii_map", &iflags.wc_ascii_map, TRUE, SET_IN_GAME}, /*WC*/ 42. #ifdef MFLOPPY 43. {"asksavedisk", &flags.asksavedisk, FALSE, SET_IN_GAME}, 44. #else 45. {"asksavedisk", (boolean *)0, FALSE, SET_IN_FILE}, 46. #endif 47. {"autodig", &flags.autodig, FALSE, SET_IN_GAME}, 48. {"autopickup", &flags.pickup, TRUE, SET_IN_GAME}, 49. {"autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME}, 50. #if defined(MICRO) && !defined(AMIGA) 51. {"BIOS", &iflags.BIOS, FALSE, SET_IN_FILE}, 52. #else 53. {"BIOS", (boolean *)0, FALSE, SET_IN_FILE}, 54. #endif 55. #ifdef INSURANCE 56. {"checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME}, 57. #else 58. {"checkpoint", (boolean *)0, FALSE, SET_IN_FILE}, 59. #endif 60. #ifdef MFLOPPY 61. {"checkspace", &iflags.checkspace, TRUE, SET_IN_GAME}, 62. #else 63. {"checkspace", (boolean *)0, FALSE, SET_IN_FILE}, 64. #endif 65. # ifdef MICRO 66. {"color", &iflags.wc_color,TRUE, SET_IN_GAME}, /*WC*/ 67. # else /* systems that support multiple terminals, many monochrome */ 68. {"color", &iflags.wc_color, FALSE, SET_IN_GAME}, /*WC*/ 69. # endif 70. {"confirm",&flags.confirm, TRUE, SET_IN_GAME}, 71. #if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV) 72. {"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME}, 73. #else 74. {"DECgraphics", (boolean *)0, FALSE, SET_IN_FILE}, 75. #endif 76. {"eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME}, /*WC*/ 77. #ifdef TTY_GRAPHICS 78. {"extmenu", &iflags.extmenu, FALSE, SET_IN_GAME}, 79. #else 80. {"extmenu", (boolean *)0, FALSE, SET_IN_FILE}, 81. #endif 82. #ifdef OPT_DISPMAP 83. {"fast_map", &flags.fast_map, TRUE, SET_IN_GAME}, 84. #else 85. {"fast_map", (boolean *)0, TRUE, SET_IN_FILE}, 86. #endif 87. {"female", &flags.female, FALSE, DISP_IN_GAME}, 88. {"fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME}, 89. #ifdef AMIFLUSH 90. {"flush", &flags.amiflush, FALSE, SET_IN_GAME}, 91. #else 92. {"flush", (boolean *)0, FALSE, SET_IN_FILE}, 93. #endif 94. {"help", &flags.help, TRUE, SET_IN_GAME}, 95. {"hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME}, /*WC*/ 96. #ifdef ASCIIGRAPH 97. {"IBMgraphics", &iflags.IBMgraphics, FALSE, SET_IN_GAME}, 98. #else 99. {"IBMgraphics", (boolean *)0, FALSE, SET_IN_FILE}, 100. #endif 101. #ifndef MAC 102. {"ignintr", &flags.ignintr, FALSE, SET_IN_GAME}, 103. #else 104. {"ignintr", (boolean *)0, FALSE, SET_IN_FILE}, 105. #endif 106. {"large_font", &iflags.wc_large_font, FALSE, SET_IN_FILE}, /*WC*/ 107. {"legacy", &flags.legacy, TRUE, DISP_IN_GAME}, 108. {"lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME}, 109. #ifdef MAC_GRAPHICS_ENV 110. {"Macgraphics", &iflags.MACgraphics, TRUE, SET_IN_GAME}, 111. #else 112. {"Macgraphics", (boolean *)0, FALSE, SET_IN_FILE}, 113. #endif 114. #ifdef MAIL 115. {"mail", &flags.biff, TRUE, SET_IN_GAME}, 116. #else 117. {"mail", (boolean *)0, TRUE, SET_IN_FILE}, 118. #endif 119. #ifdef WIZARD 120. /* for menu debugging only*/ 121. {"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME}, 122. #else 123. {"menu_tab_sep", (boolean *)0, FALSE, SET_IN_FILE}, 124. #endif 125. #ifdef TTY_GRAPHICS 126. {"msg_window", &iflags.prevmsg_window, FALSE, SET_IN_GAME}, 127. #else 128. {"msg_window", (boolean *)0, FALSE, SET_IN_FILE}, 129. #endif 130. #ifdef NEWS 131. {"news", &iflags.news, TRUE, DISP_IN_GAME}, 132. #else 133. {"news", (boolean *)0, FALSE, SET_IN_FILE}, 134. #endif 135. {"null", &flags.null, TRUE, SET_IN_GAME}, 136. {"number_pad", &iflags.num_pad, FALSE, SET_IN_GAME}, 137. #ifdef MAC 138. {"page_wait", &flags.page_wait, TRUE, SET_IN_GAME}, 139. #else 140. {"page_wait", (boolean *)0, FALSE, SET_IN_FILE}, 141. #endif 142. {"perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME}, 143. {"popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME}, /*WC*/ 144. {"prayconfirm", &flags.prayconfirm, TRUE, SET_IN_GAME}, 145. {"preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME}, /*WC*/ 146. {"pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME}, 147. #if defined(MICRO) && !defined(AMIGA) && !defined(MSWIN_GRAPHICS) 148. {"rawio", &iflags.rawio, FALSE, DISP_IN_GAME}, 149. #else 150. {"rawio", (boolean *)0, FALSE, SET_IN_FILE}, 151. #endif 152. {"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME}, 153. {"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME}, 154. #ifdef WIZARD 155. {"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME}, 156. #else 157. {"sanity_check", (boolean *)0, FALSE, SET_IN_FILE}, 158. #endif 159. #ifdef EXP_ON_BOTL 160. {"showexp", &flags.showexp, FALSE, SET_IN_GAME}, 161. #else 162. {"showexp", (boolean *)0, FALSE, SET_IN_FILE}, 163. #endif 164. #ifdef SCORE_ON_BOTL 165. {"showscore", &flags.showscore, FALSE, SET_IN_GAME}, 166. #else 167. {"showscore", (boolean *)0, FALSE, SET_IN_FILE}, 168. #endif 169. {"silent", &flags.silent, TRUE, SET_IN_GAME}, 170. {"sortpack", &flags.sortpack, TRUE, SET_IN_GAME}, 171. {"sound", &flags.soundok, TRUE, SET_IN_GAME}, 172. {"sparkle", &flags.sparkle, TRUE, SET_IN_GAME}, 173. {"standout", &flags.standout, FALSE, SET_IN_GAME}, 174. {"splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME}, /*WC*/ 175. {"tiled_map", &iflags.wc_tiled_map, FALSE, DISP_IN_GAME}, /*WC*/ 176. {"time", &flags.time, FALSE, SET_IN_GAME}, 177. #ifdef TIMED_DELAY 178. {"timed_delay", &flags.nap, TRUE, SET_IN_GAME}, 179. #else 180. {"timed_delay", (boolean *)0, FALSE, SET_IN_GAME}, 181. #endif 182. {"tombstone",&flags.tombstone, TRUE, SET_IN_GAME}, 183. {"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME}, 184. {"use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME}, /*WC*/ 185. {"verbose", &flags.verbose, TRUE, SET_IN_GAME}, 186. {(char *)0, (boolean *)0, FALSE, 0} 187. }; 188. 189. /* compound options, for option_help() and external programs like Amiga 190. * frontend */ 191. static struct Comp_Opt 192. { 193. const char *name, *descr; 194. int size; /* for frontends and such allocating space -- 195. * usually allowed size of data in game, but 196. * occasionally maximum reasonable size for 197. * typing when game maintains information in 198. * a different format */ 199. int optflags; 200. } compopt[] = { 201. { "align", "your starting alignment (lawful, neutral, or chaotic)", 202. 8, DISP_IN_GAME }, 203. { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/ 204. { "align_status", "status window alignment", 20, DISP_IN_GAME }, /*WC*/ 205. #ifdef MAC 206. { "background", "the color of the background (black or white)", 207. 6, SET_IN_FILE }, 208. #endif 209. { "boulder", "the symbol to use for displaying boulders", 210. 1, SET_IN_GAME }, 211. { "catname", "the name of your (first) cat (e.g., catname:Tabby)", 212. PL_PSIZ, DISP_IN_GAME }, 213. { "disclose", "the kinds of information to disclose at end of game", 214. sizeof(flags.end_disclose) * 2, 215. SET_IN_GAME }, 216. { "dogname", "the name of your (first) dog (e.g., dogname:Fang)", 217. PL_PSIZ, DISP_IN_GAME }, 218. { "dungeon", "the symbols to use in drawing the dungeon map", 219. MAXDCHARS+1, SET_IN_FILE }, 220. { "effects", "the symbols to use in drawing special effects", 221. MAXECHARS+1, SET_IN_FILE }, 222. { "font_map", "the font to use in the map window", 40, DISP_IN_GAME }, /*WC*/ 223. { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/ 224. { "font_message", "the font to use in the message window", 225. 40, DISP_IN_GAME }, /*WC*/ 226. { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ 227. { "font_size_menu", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ 228. { "font_size_message", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ 229. { "font_size_status", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ 230. { "font_size_text", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ 231. { "font_status", "the font to use in status window", 40, DISP_IN_GAME }, /*WC*/ 232. { "font_text", "the font to use in text windows", 40, DISP_IN_GAME }, /*WC*/ 233. { "fruit", "the name of a fruit you enjoy eating", 234. PL_FSIZ, SET_IN_GAME }, 235. { "gender", "your starting gender (male or female)", 236. 8, DISP_IN_GAME }, 237. { "horsename", "the name of your (first) horse (e.g., horsename:Silver)", 238. PL_PSIZ, DISP_IN_GAME }, 239. { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/ 240. { "menustyle", "user interface for object selection", 241. MENUTYPELEN, SET_IN_GAME }, 242. { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE }, 243. { "menu_deselect_page", "deselect all items on this page of a menu", 244. 4, SET_IN_FILE }, 245. { "menu_first_page", "jump to the first page in a menu", 246. 4, SET_IN_FILE }, 247. { "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE }, 248. { "menu_invert_page", "invert all items on this page of a menu", 249. 4, SET_IN_FILE }, 250. { "menu_last_page", "jump to the last page in a menu", 4, SET_IN_FILE }, 251. { "menu_next_page", "goto the next menu page", 4, SET_IN_FILE }, 252. { "menu_previous_page", "goto the previous menu page", 4, SET_IN_FILE }, 253. { "menu_search", "search for a menu item", 4, SET_IN_FILE }, 254. { "menu_select_all", "select all items in a menu", 4, SET_IN_FILE }, 255. { "menu_select_page", "select all items on this page of a menu", 256. 4, SET_IN_FILE }, 257. { "monsters", "the symbols to use for monsters", 258. MAXMCLASSES, SET_IN_FILE }, 259. { "msghistory", "number of top line messages to save", 260. 5, DISP_IN_GAME }, 261. { "name", "your character's name (e.g., name:Merlin-W)", 262. PL_NSIZ, DISP_IN_GAME }, 263. { "objects", "the symbols to use for objects", 264. MAXOCLASSES, SET_IN_FILE }, 265. { "packorder", "the inventory order of the items in your pack", 266. MAXOCLASSES, SET_IN_GAME }, 267. #ifdef CHANGE_COLOR 268. { "palette", "palette (00c/880/-fff is blue/yellow/reverse white)", 269. 15 , SET_IN_GAME }, 270. # if defined(MAC) 271. { "hicolor", "same as palette, only order is reversed", 272. 15, SET_IN_FILE }, 273. # endif 274. #endif 275. { "pettype", "your preferred initial pet type", 4, DISP_IN_GAME }, 276. { "pickup_burden", "maximum burden picked up before prompt", 277. 20, SET_IN_GAME }, 278. { "pickup_types", "types of objects to pick up automatically", 279. MAXOCLASSES, SET_IN_GAME }, 280. { "player_selection", "choose character via dialog or prompts", 281. 12, DISP_IN_GAME }, 282. { "race", "your starting race (e.g., Human, Elf)", 283. PL_CSIZ, DISP_IN_GAME }, 284. { "role", "your starting role (e.g., Barbarian, Valkyrie)", 285. PL_CSIZ, DISP_IN_GAME }, 286. { "scores", "the parts of the score list you wish to see", 287. 32, SET_IN_GAME }, 288. { "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/ 289. #ifdef MSDOS 290. { "soundcard", "type of sound card to use", 20, SET_IN_FILE }, 291. #endif 292. { "suppress_alert", "suppress alerts about version-specific features", 293. 8, SET_IN_GAME }, 294. { "tile_width", "width of tiles", 20, DISP_IN_GAME}, /*WC*/ 295. { "tile_height", "height of tiles", 20, DISP_IN_GAME}, /*WC*/ 296. { "tile_file", "name of tile file", 70, DISP_IN_GAME}, /*WC*/ 297. { "traps", "the symbols to use in drawing traps", 298. MAXTCHARS+1, SET_IN_FILE }, 299. #ifdef MAC 300. {"use_stone", "use stone background patterns", 8, SET_IN_FILE }, 301. #endif 302. { "vary_msgcount", "show more old messages at a time", 20, DISP_IN_GAME }, /*WC*/ 303. #ifdef MSDOS 304. { "video", "method of video updating", 20, SET_IN_FILE }, 305. #endif 306. #ifdef VIDEOSHADES 307. { "videocolors", "color mappings for internal screen routines", 308. 40, DISP_IN_GAME }, 309. { "videoshades", "gray shades to map to black/gray/white", 310. 32, DISP_IN_GAME }, 311. #endif 312. { "windowcolors", "the foreground/background colors of windows", /*WC*/ 313. 80, DISP_IN_GAME }, 314. { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME }, 315. { (char *)0, (char *)0, 0, 0 } 316. }; 317. 318. #ifdef OPTION_LISTS_ONLY 319. #undef static 320. 321. #else /* use rest of file */ 322. 323. static boolean need_redraw; /* for doset() */ 324. 325. #if defined(TOS) && defined(TEXTCOLOR) 326. extern boolean colors_changed; /* in tos.c */ 327. #endif 328. 329. #ifdef VIDEOSHADES 330. extern char *shade[3]; /* in sys/msdos/video.c */ 331. extern char ttycolors[CLR_MAX]; /* in sys/msdos/video.c */ 332. #endif 333. 334. static char def_inv_order[MAXOCLASSES] = { 335. GOLD_CLASS, AMULET_CLASS, WEAPON_CLASS, ARMOR_CLASS, FOOD_CLASS, 336. SCROLL_CLASS, SPBOOK_CLASS, POTION_CLASS, RING_CLASS, WAND_CLASS, 337. TOOL_CLASS, GEM_CLASS, ROCK_CLASS, BALL_CLASS, CHAIN_CLASS, 0, 338. }; 339. 340. /* 341. * Default menu manipulation command accelerators. These may _not_ be: 342. * 343. * + a number - reserved for counts 344. * + an upper or lower case US ASCII letter - used for accelerators 345. * + ESC - reserved for escaping the menu 346. * + NULL, CR or LF - reserved for commiting the selection(s). NULL 347. * is kind of odd, but the tty's xwaitforspace() will return it if 348. * someone hits a . 349. * + a default object class symbol - used for object class accelerators 350. * 351. * Standard letters (for now) are: 352. * 353. * < back 1 page 354. * > forward 1 page 355. * ^ first page 356. * | last page 357. * : search 358. * 359. * page all 360. * , select . 361. * \ deselect - 362. * ~ invert @ 363. * 364. * The command name list is duplicated in the compopt array. 365. */ 366. typedef struct { 367. const char *name; 368. char cmd; 369. } menu_cmd_t; 370. 371. #define NUM_MENU_CMDS 11 372. static const menu_cmd_t default_menu_cmd_info[NUM_MENU_CMDS] = { 373. /* 0*/ { "menu_first_page", MENU_FIRST_PAGE }, 374. { "menu_last_page", MENU_LAST_PAGE }, 375. { "menu_next_page", MENU_NEXT_PAGE }, 376. { "menu_previous_page", MENU_PREVIOUS_PAGE }, 377. { "menu_select_all", MENU_SELECT_ALL }, 378. /* 5*/ { "menu_deselect_all", MENU_UNSELECT_ALL }, 379. { "menu_invert_all", MENU_INVERT_ALL }, 380. { "menu_select_page", MENU_SELECT_PAGE }, 381. { "menu_deselect_page", MENU_UNSELECT_PAGE }, 382. { "menu_invert_page", MENU_INVERT_PAGE }, 383. /*10*/ { "menu_search", MENU_SEARCH }, 384. }; 385. 386. /* 387. * Allow the user to map incoming characters to various menu commands. 388. * The accelerator list must be a valid C string. 389. */ 390. #define MAX_MENU_MAPPED_CMDS 32 /* some number */ 391. char mapped_menu_cmds[MAX_MENU_MAPPED_CMDS+1]; /* exported */ 392. static char mapped_menu_op[MAX_MENU_MAPPED_CMDS+1]; 393. static short n_menu_mapped = 0; 394. 395. 396. static boolean initial, from_file; 397. 398. STATIC_DCL void FDECL(doset_add_menu, (winid,const char *,int)); 399. STATIC_DCL void FDECL(nmcpy, (char *, const char *, int)); 400. STATIC_DCL void FDECL(escapes, (const char *, char *)); 401. STATIC_DCL void FDECL(rejectoption, (const char *)); 402. STATIC_DCL void FDECL(badoption, (const char *)); 403. STATIC_DCL char *FDECL(string_for_opt, (char *,BOOLEAN_P)); 404. STATIC_DCL char *FDECL(string_for_env_opt, (const char *, char *,BOOLEAN_P)); 405. STATIC_DCL void FDECL(bad_negation, (const char *,BOOLEAN_P)); 406. STATIC_DCL int FDECL(change_inv_order, (char *)); 407. STATIC_DCL void FDECL(oc_to_str, (char *, char *)); 408. STATIC_DCL void FDECL(graphics_opts, (char *,const char *,int,int)); 409. STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *)); 410. STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *)); 411. STATIC_DCL boolean FDECL(special_handling, (const char *, BOOLEAN_P, BOOLEAN_P)); 412. STATIC_DCL void FDECL(warning_opts, (char *,const char *)); 413. STATIC_DCL void FDECL(duplicate_opt_detection, (const char *, int)); 414. 415. STATIC_OVL void FDECL(wc_set_font_name, (int, char *)); 416. STATIC_OVL int FDECL(wc_set_window_colors, (char *)); 417. STATIC_OVL boolean FDECL(is_wc_option, (const char *)); 418. STATIC_OVL boolean FDECL(wc_supported, (const char *)); 419. 420. /* check whether a user-supplied option string is a proper leading 421. substring of a particular option name; option string might have 422. a colon or equals sign and arbitrary value appended to it */ 423. boolean 424. match_optname(user_string, opt_name, min_length, val_allowed) 425. const char *user_string, *opt_name; 426. int min_length; 427. boolean val_allowed; 428. { 429. int len = (int)strlen(user_string); 430. 431. if (val_allowed) { 432. const char *p = index(user_string, ':'), 433. *q = index(user_string, '='); 434. 435. if (!p || (q && q < p)) p = q; 436. while(p && p > user_string && isspace(*(p-1))) p--; 437. if (p) len = (int)(p - user_string); 438. } 439. 440. return (len >= min_length) && !strncmpi(opt_name, user_string, len); 441. } 442. 443. /* most environment variables will eventually be printed in an error 444. * message if they don't work, and most error message paths go through 445. * BUFSZ buffers, which could be overflowed by a maliciously long 446. * environment variable. if a variable can legitimately be long, or 447. * if it's put in a smaller buffer, the responsible code will have to 448. * bounds-check itself. 449. */ 450. char * 451. nh_getenv(ev) 452. const char *ev; 453. { 454. char *getev = getenv(ev); 455. 456. if (getev && strlen(getev) <= (BUFSZ / 2)) 457. return getev; 458. else 459. return (char *)0; 460. } 461. 462. void 463. initoptions() 464. { 465. char *opts; 466. int i; 467. 468. /* initialize the random number generator */ 469. setrandom(); 470. 471. /* for detection of configfile options specified multiple times */ 472. iflags.opt_booldup = iflags.opt_compdup = (int *)0; 473. 474. for (i = 0; boolopt[i].name; i++) { 475. if (boolopt[i].addr) 476. *(boolopt[i].addr) = boolopt[i].initvalue; 477. } 478. flags.end_own = FALSE; 479. flags.end_top = 3; 480. flags.end_around = 2; 481. iflags.msg_history = 20; 482. 483. /* Use negative indices to indicate not yet selected */ 484. flags.initrole = -1; 485. flags.initrace = -1; 486. flags.initgend = -1; 487. flags.initalign = -1; 488. 489. /* Set the default monster and object class symbols. Don't use */ 490. /* memcpy() --- sizeof char != sizeof uchar on some machines. */ 491. for (i = 0; i < MAXOCLASSES; i++) 492. oc_syms[i] = (uchar) def_oc_syms[i]; 493. for (i = 0; i < MAXMCLASSES; i++) 494. monsyms[i] = (uchar) def_monsyms[i]; 495. for (i = 0; i < WARNCOUNT; i++) 496. warnsyms[i] = def_warnsyms[i].sym; 497. iflags.bouldersym = 0; 498. flags.warnlevel = 1; 499. flags.warntype = 0L; 500. 501. /* assert( sizeof flags.inv_order == sizeof def_inv_order ); */ 502. (void)memcpy((genericptr_t)flags.inv_order, 503. (genericptr_t)def_inv_order, sizeof flags.inv_order); 504. flags.pickup_types[0] = '\0'; 505. flags.pickup_burden = MOD_ENCUMBER; 506. 507. for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) 508. flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO; 509. switch_graphics(ASCII_GRAPHICS); /* set default characters */ 510. #if defined(UNIX) && defined(TTY_GRAPHICS) 511. /* 512. * Set defaults for some options depending on what we can 513. * detect about the environment's capabilities. 514. * This has to be done after the global initialization above 515. * and before reading user-specific initialization via 516. * config file/environment variable below. 517. */ 518. /* this detects the IBM-compatible console on most 386 boxes */ 519. if (!strncmp(nh_getenv("TERM"), "AT", 2)) { 520. switch_graphics(IBM_GRAPHICS); 521. # ifdef TEXTCOLOR 522. iflags.use_color = TRUE; 523. # endif 524. } 525. #endif /* UNIX && TTY_GRAPHICS */ 526. #if defined(UNIX) || defined(VMS) 527. # ifdef TTY_GRAPHICS 528. /* detect whether a "vt" terminal can handle alternate charsets */ 529. if (!strncmpi(nh_getenv("TERM"), "vt", 2) && (AS && AE) && 530. index(AS, '\016') && index(AE, '\017')) { 531. switch_graphics(DEC_GRAPHICS); 532. } 533. # endif 534. #endif /* UNIX || VMS */ 535. 536. #ifdef MAC_GRAPHICS_ENV 537. switch_graphics(MAC_GRAPHICS); 538. #endif /* MAC_GRAPHICS_ENV */ 539. flags.menu_style = MENU_FULL; 540. 541. /* since this is done before init_objects(), do partial init here */ 542. objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD; 543. nmcpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ); 544. #ifndef MAC 545. opts = getenv("NETHACKOPTIONS"); 546. if (!opts) opts = getenv("HACKOPTIONS"); 547. if (opts) { 548. if (*opts == '/' || *opts == '\\' || *opts == '@') { 549. if (*opts == '@') opts++; /* @filename */ 550. /* looks like a filename */ 551. if (strlen(opts) < BUFSZ/2) 552. read_config_file(opts); 553. } else { 554. read_config_file((char *)0); 555. /* let the total length of options be long; 556. * parseoptions() will check each individually 557. */ 558. parseoptions(opts, TRUE, FALSE); 559. } 560. } else 561. #endif 562. read_config_file((char *)0); 563. 564. (void)fruitadd(pl_fruit); 565. /* Remove "slime mold" from list of object names; this will */ 566. /* prevent it from being wished unless it's actually present */ 567. /* as a named (or default) fruit. Wishing for "fruit" will */ 568. /* result in the player's preferred fruit [better than "\033"]. */ 569. obj_descr[SLIME_MOLD].oc_name = "fruit"; 570. 571. return; 572. } 573. 574. STATIC_OVL void 575. nmcpy(dest, src, maxlen) 576. char *dest; 577. const char *src; 578. int maxlen; 579. { 580. int count; 581. 582. for(count = 1; count < maxlen; count++) { 583. if(*src == ',' || *src == '\0') break; /*exit on \0 terminator*/ 584. *dest++ = *src++; 585. } 586. *dest = 0; 587. } 588. 589. /* 590. * escapes: escape expansion for showsyms. C-style escapes understood include 591. *
, \b, , , \xnnn (hex), \onnn (octal),
nn (decimal). The ^-prefix 592. * for control characters is also understood, and \[mM] followed by any of the 593. * previous forms or by a character has the effect of 'meta'-ing the value (so 594. * that the alternate character set will be enabled). 595. */ 596. STATIC_OVL void 597. escapes(cp, tp) 598. const char *cp; 599. char *tp; 600. { 601. while (*cp) 602. { 603. int cval = 0, meta = 0; 604. 605. if (*cp == '\\' && index("mM", cp[1])) { 606. meta = 1; 607. cp += 2; 608. } 609. if (*cp == '\\' && index("0123456789xXoO", cp[1])) 610. { 611. const char *dp, *hex = "00112233445566778899aAbBcCdDeEfF"; 612. int dcount = 0; 613. 614. cp++; 615. if (*cp == 'x' || *cp == 'X') 616. for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++) 617. cval = (cval * 16) + (dp - hex) / 2; 618. else if (*cp == 'o' || *cp == 'O') 619. for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++) 620. cval = (cval * 8) + (*cp - '0'); 621. else 622. for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++) 623. cval = (cval * 10) + (*cp - '0'); 624. } 625. else if (*cp == '\\') /* C-style character escapes */ 626. { 627. switch (*++cp) 628. { 629. case '\\': cval = '\\'; break; 630. case 'n': cval = '
'; break; 631. case 't': cval = ' '; break; 632. case 'b': cval = '\b'; break; 633. case 'r': cval = ''; break; 634. default: cval = *cp; 635. } 636. cp++; 637. } 638. else if (*cp == '^') /* expand control-character syntax */ 639. { 640. cval = (*++cp & 0x1f); 641. cp++; 642. } 643. else 644. cval = *cp++; 645. if (meta) 646. cval |= 0x80; 647. *tp++ = cval; 648. } 649. *tp = '\0'; 650. } 651. 652. STATIC_OVL void 653. rejectoption(optname) 654. const char *optname; 655. { 656. #ifdef MICRO 657. pline("\"%s\" settable only from %s.", optname, configfile); 658. #else 659. pline("%s can be set only from NETHACKOPTIONS or %s.", optname, 660. configfile); 661. #endif 662. } 663. 664. STATIC_OVL void 665. badoption(opts) 666. const char *opts; 667. { 668. if (!initial) { 669. if (!strncmp(opts, "h", 1) || !strncmp(opts, "?", 1)) 670. option_help(); 671. else 672. pline("Bad syntax: %s. Enter \"?g\" for help.", opts); 673. return; 674. } 675. #ifdef MAC 676. else return; 677. #endif 678. 679. if(from_file) 680. raw_printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts); 681. else 682. raw_printf("Bad syntax in NETHACKOPTIONS: %s.", opts); 683. 684. wait_synch(); 685. } 686. 687. STATIC_OVL char * 688. string_for_opt(opts, val_optional) 689. char *opts; 690. boolean val_optional; 691. { 692. char *colon, *equals; 693. 694. colon = index(opts, ':'); 695. equals = index(opts, '='); 696. if (!colon || (equals && equals < colon)) colon = equals; 697. 698. if (!colon || !*++colon) { 699. if (!val_optional) badoption(opts); 700. return (char *)0; 701. } 702. return colon; 703. } 704. 705. STATIC_OVL char * 706. string_for_env_opt(optname, opts, val_optional) 707. const char *optname; 708. char *opts; 709. boolean val_optional; 710. { 711. if(!initial) { 712. rejectoption(optname); 713. return (char *)0; 714. } 715. return string_for_opt(opts, val_optional); 716. } 717. 718. STATIC_OVL void 719. bad_negation(optname, with_parameter) 720. const char *optname; 721. boolean with_parameter; 722. { 723. pline_The("%s option may not %sbe negated.", 724. optname, 725. with_parameter ? "both have a value and " : ""); 726. } 727. 728. /* 729. * Change the inventory order, using the given string as the new order. 730. * Missing characters in the new order are filled in at the end from 731. * the current inv_order, except for gold, which is forced to be first 732. * if not explicitly present. 733. * 734. * This routine returns 1 unless there is a duplicate or bad char in 735. * the string. 736. */ 737. STATIC_OVL int 738. change_inv_order(op) 739. char *op; 740. { 741. int oc_sym, num; 742. char *sp, buf[BUFSZ]; 743. 744. num = 0; 745. #ifndef GOLDOBJ 746. if (!index(op, GOLD_SYM)) 747. buf[num++] = GOLD_CLASS; 748. #else 749. /* !!!! probably unnecessary with gold as normal inventory */ 750. #endif 751. 752. for (sp = op; *sp; sp++) { 753. oc_sym = def_char_to_objclass(*sp); 754. /* reject bad or duplicate entries */ 755. if (oc_sym == MAXOCLASSES || 756. oc_sym == RANDOM_CLASS || oc_sym == ILLOBJ_CLASS || 757. !index(flags.inv_order, oc_sym) || index(sp+1, *sp)) 758. return 0; 759. /* retain good ones */ 760. buf[num++] = (char) oc_sym; 761. } 762. buf[num] = '\0'; 763. 764. /* fill in any omitted classes, using previous ordering */ 765. for (sp = flags.inv_order; *sp; sp++) 766. if (!index(buf, *sp)) { 767. buf[num++] = *sp; 768. buf[num] = '\0'; /* explicitly terminate for next index() */ 769. } 770. 771. Strcpy(flags.inv_order, buf); 772. return 1; 773. } 774. 775. STATIC_OVL void 776. graphics_opts(opts, optype, maxlen, offset) 777. register char *opts; 778. const char *optype; 779. int maxlen, offset; 780. { 781. uchar translate[MAXPCHARS+1]; 782. int length, i; 783. 784. if (!(opts = string_for_env_opt(optype, opts, FALSE))) 785. return; 786. escapes(opts, opts); 787. 788. length = strlen(opts); 789. if (length > maxlen) length = maxlen; 790. /* match the form obtained from PC configuration files */ 791. for (i = 0; i < length; i++) 792. translate[i] = (uchar) opts[i]; 793. assign_graphics(translate, length, maxlen, offset); 794. } 795. 796. STATIC_OVL void 797. warning_opts(opts, optype) 798. register char *opts; 799. const char *optype; 800. { 801. uchar translate[MAXPCHARS+1]; 802. int length, i; 803. 804. if (!(opts = string_for_env_opt(optype, opts, FALSE))) 805. return; 806. escapes(opts, opts); 807. 808. length = strlen(opts); 809. if (length > WARNCOUNT) length = WARNCOUNT; 810. /* match the form obtained from PC configuration files */ 811. for (i = 0; i < length; i++) 812. translate[i] = (((i < WARNCOUNT) && opts[i]) ? 813. (uchar) opts[i] : def_warnsyms[i].sym); 814. assign_warnings(translate); 815. } 816. 817. void 818. assign_warnings(graph_chars) 819. register uchar *graph_chars; 820. { 821. int i; 822. for (i = 0; i < WARNCOUNT; i++) 823. warnsyms[i] = graph_chars[i]; 824. } 825. 826. STATIC_OVL int 827. feature_alert_opts(op, optn) 828. char *op; 829. const char *optn; 830. { 831. char buf[BUFSZ]; 832. boolean rejectver = FALSE; 833. unsigned long fnv = get_feature_notice_ver(op); /* version.c */ 834. if (fnv == 0L) return 0; 835. if (fnv > get_current_feature_ver()) 836. rejectver = TRUE; 837. else 838. flags.suppress_alert = fnv; 839. if (rejectver) { 840. if (!initial) 841. You_cant("disable new feature alerts for future versions."); 842. else { 843. Sprintf(buf, 844. "
%s=%s Invalid reference to a future version ignored", 845. optn, op); 846. badoption(buf); 847. } 848. return 0; 849. } 850. if (!initial) { 851. Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ, 852. FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH); 853. pline("Feature change alerts disabled for NetHack %s features and prior.", 854. buf); 855. } 856. return 1; 857. } 858. 859. void 860. set_duplicate_opt_detection(on_or_off) 861. int on_or_off; 862. { 863. int k, *optptr; 864. if (on_or_off != 0) { 865. /*-- ON --*/ 866. if (iflags.opt_booldup) 867. impossible("iflags.opt_booldup already on (memory leak)"); 868. iflags.opt_booldup = (int *)alloc(SIZE(boolopt) * sizeof(int)); 869. optptr = iflags.opt_booldup; 870. for (k = 0; k < SIZE(boolopt); ++k) 871. *optptr++ = 0; 872. 873. if (iflags.opt_compdup) 874. impossible("iflags.opt_compdup already on (memory leak)"); 875. iflags.opt_compdup = (int *)alloc(SIZE(compopt) * sizeof(int)); 876. optptr = iflags.opt_compdup; 877. for (k = 0; k < SIZE(compopt); ++k) 878. *optptr++ = 0; 879. } else { 880. /*-- OFF --*/ 881. if (iflags.opt_booldup) free((genericptr_t) iflags.opt_booldup); 882. iflags.opt_booldup = (int *)0; 883. if (iflags.opt_compdup) free((genericptr_t) iflags.opt_compdup); 884. iflags.opt_compdup = (int *)0; 885. } 886. } 887. 888. STATIC_OVL void 889. duplicate_opt_detection(opts, bool_or_comp) 890. const char *opts; 891. int bool_or_comp; /* 0 == boolean option, 1 == compound */ 892. { 893. int i, *optptr; 894. #if defined(MAC) 895. /* the Mac has trouble dealing with the output of messages while 896. * processing the config file. That should get fixed one day. 897. * For now just return. 898. */ 899. return; 900. #endif 901. if ((bool_or_comp == 0) && iflags.opt_booldup && initial && from_file) { 902. for (i = 0; boolopt[i].name; i++) { 903. if (match_optname(opts, boolopt[i].name, 3, FALSE)) { 904. optptr = iflags.opt_booldup + i; 905. if (*optptr == 1) { 906. raw_printf( 907. "
Warning - Boolean option specified multiple times: %s.
", 908. opts); 909. wait_synch(); 910. } 911. *optptr += 1; 912. break; /* don't match multiple options */ 913. } 914. } 915. } else if ((bool_or_comp == 1) && iflags.opt_compdup && initial && from_file) { 916. for (i = 0; compopt[i].name; i++) { 917. if (match_optname(opts, compopt[i].name, strlen(compopt[i].name), TRUE)) { 918. optptr = iflags.opt_compdup + i; 919. if (*optptr == 1) { 920. raw_printf( 921. "
Warning - compound option specified multiple times: %s.
", 922. compopt[i].name); 923. wait_synch(); 924. } 925. *optptr += 1; 926. break; /* don't match multiple options */ 927. } 928. } 929. } 930. } 931. 932. void 933. parseoptions(opts, tinitial, tfrom_file) 934. register char *opts; 935. boolean tinitial, tfrom_file; 936. { 937. register char *op; 938. unsigned num; 939. boolean negated; 940. int i; 941. const char *fullname; 942. 943. initial = tinitial; 944. from_file = tfrom_file; 945. if ((op = index(opts, ',')) != 0) { 946. *op++ = 0; 947. parseoptions(op, initial, from_file); 948. } 949. if (strlen(opts) > BUFSZ/2) { 950. badoption("option too long"); 951. return; 952. } 953. 954. /* strip leading and trailing white space */ 955. while (isspace(*opts)) opts++; 956. op = eos(opts); 957. while (--op >= opts && isspace(*op)) *op = '\0'; 958. 959. if (!*opts) return; 960. negated = FALSE; 961. while ((*opts == '!') || !strncmpi(opts, "no", 2)) { 962. if (*opts == '!') opts++; else opts += 2; 963. negated = !negated; 964. } 965. 966. /* variant spelling */ 967. 968. if (match_optname(opts, "colour", 5, FALSE)) 969. Strcpy(opts, "color"); /* fortunately this isn't longer */ 970. 971. duplicate_opt_detection(opts, 1); /* 1 means compound opts */ 972. 973. /* special boolean options */ 974. 975. if (match_optname(opts, "female", 3, FALSE)) { 976. if(!initial && flags.female == negated) 977. pline("That is not anatomically possible."); 978. else 979. flags.initgend = flags.female = !negated; 980. return; 981. } 982. 983. if (match_optname(opts, "male", 4, FALSE)) { 984. if(!initial && flags.female != negated) 985. pline("That is not anatomically possible."); 986. else 987. flags.initgend = flags.female = negated; 988. return; 989. } 990. 991. #if defined(MICRO) && !defined(AMIGA) 992. /* included for compatibility with old NetHack.cnf files */ 993. if (match_optname(opts, "IBM_", 4, FALSE)) { 994. iflags.BIOS = !negated; 995. return; 996. } 997. #endif /* MICRO */ 998. 999. /* compound options */ 1000. 1001. fullname = "pettype"; 1002. if (match_optname(opts, fullname, 3, TRUE)) { 1003. if ((op = string_for_env_opt(fullname, opts, negated)) != 0) { 1004. if (negated) bad_negation(fullname, TRUE); 1005. else switch (*op) { 1006. case 'd': /* dog */ 1007. case 'D': 1008. preferred_pet = 'd'; 1009. break; 1010. case 'c': /* cat */ 1011. case 'C': 1012. case 'f': /* feline */ 1013. case 'F': 1014. preferred_pet = 'c'; 1015. break; 1016. case 'n': /* no pet */ 1017. case 'N': 1018. preferred_pet = 'n'; 1019. break; 1020. default: 1021. pline("Unrecognized pet type '%s'", op); 1022. break; 1023. } 1024. } else if (negated) preferred_pet = 'n'; 1025. return; 1026. } 1027. 1028. fullname = "catname"; 1029. if (match_optname(opts, fullname, 3, TRUE)) { 1030. if (negated) bad_negation(fullname, FALSE); 1031. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1032. nmcpy(catname, op, PL_PSIZ); 1033. return; 1034. } 1035. 1036. fullname = "dogname"; 1037. if (match_optname(opts, fullname, 3, TRUE)) { 1038. if (negated) bad_negation(fullname, FALSE); 1039. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1040. nmcpy(dogname, op, PL_PSIZ); 1041. return; 1042. } 1043. 1044. fullname = "horsename"; 1045. if (match_optname(opts, fullname, 5, TRUE)) { 1046. if (negated) bad_negation(fullname, FALSE); 1047. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1048. nmcpy(horsename, op, PL_PSIZ); 1049. return; 1050. } 1051. 1052. fullname = "msghistory"; 1053. if (match_optname(opts, fullname, 3, TRUE)) { 1054. op = string_for_env_opt(fullname, opts, negated); 1055. if ((negated && !op) || (!negated && op)) { 1056. iflags.msg_history = negated ? 0 : atoi(op); 1057. } else if (negated) bad_negation(fullname, TRUE); 1058. return; 1059. } 1060. 1061. /* WINCAP 1062. * setting font options */ 1063. fullname = "font"; 1064. if (!strncmpi(opts, fullname, 4)) 1065. { 1066. int wintype = -1; 1067. char *fontopts = opts + 4; 1068. 1069. if (!strncmpi(fontopts, "map", 3) || 1070. !strncmpi(fontopts, "_map", 4)) 1071. wintype = NHW_MAP; 1072. else if (!strncmpi(fontopts, "message", 7) || 1073. !strncmpi(fontopts, "_message", 8)) 1074. wintype = NHW_MESSAGE; 1075. else if (!strncmpi(fontopts, "text", 4) || 1076. !strncmpi(fontopts, "_text", 5)) 1077. wintype = NHW_TEXT; 1078. else if (!strncmpi(fontopts, "menu", 4) || 1079. !strncmpi(fontopts, "_menu", 5)) 1080. wintype = NHW_MENU; 1081. else if (!strncmpi(fontopts, "status", 6) || 1082. !strncmpi(fontopts, "_status", 7)) 1083. wintype = NHW_STATUS; 1084. else if (!strncmpi(fontopts, "_size", 5)) { 1085. if (!strncmpi(fontopts, "_size_map", 8)) 1086. wintype = NHW_MAP; 1087. else if (!strncmpi(fontopts, "_size_message", 12)) 1088. wintype = NHW_MESSAGE; 1089. else if (!strncmpi(fontopts, "_size_text", 9)) 1090. wintype = NHW_TEXT; 1091. else if (!strncmpi(fontopts, "_size_menu", 9)) 1092. wintype = NHW_MENU; 1093. else if (!strncmpi(fontopts, "_size_status", 11)) 1094. wintype = NHW_STATUS; 1095. else { 1096. badoption(opts); 1097. return; 1098. } 1099. if (wintype > 0 && !negated && 1100. (op = string_for_opt(opts, FALSE)) != 0) { 1101. switch(wintype) { 1102. case NHW_MAP: 1103. iflags.wc_fontsiz_map = atoi(op); 1104. break; 1105. case NHW_MESSAGE: 1106. iflags.wc_fontsiz_message = atoi(op); 1107. break; 1108. case NHW_TEXT: 1109. iflags.wc_fontsiz_text = atoi(op); 1110. break; 1111. case NHW_MENU: 1112. iflags.wc_fontsiz_menu = atoi(op); 1113. break; 1114. case NHW_STATUS: 1115. iflags.wc_fontsiz_status = atoi(op); 1116. break; 1117. } 1118. } 1119. return; 1120. } else { 1121. badoption(opts); 1122. } 1123. if (wintype > 0 && 1124. (op = string_for_opt(opts, FALSE)) != 0) { 1125. wc_set_font_name(wintype, op); 1126. #ifdef MAC 1127. set_font_name (wintype, op); 1128. #endif 1129. return; 1130. } else if (negated) bad_negation(fullname, TRUE); 1131. return; 1132. } 1133. #ifdef CHANGE_COLOR 1134. #ifdef MAC 1135. fullname = "use_stone"; 1136. if (match_optname(opts, fullname, 6, TRUE)) { 1137. op = string_for_env_opt(fullname, opts, negated); 1138. if ((negated && !op) || (!negated && op)) { 1139. iflags.use_stone = negated ? 0 : atoi(op); 1140. } else if (negated) bad_negation(fullname, TRUE); 1141. return; 1142. } 1143. 1144. fullname = "background"; 1145. if (match_optname(opts, fullname, 5,TRUE)) 1146. { 1147. if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1148. { 1149. if (!strncmpi (op, "white", 5)) 1150. change_background (1); 1151. else if (!strncmpi (op, "black", 5)) 1152. change_background (0); 1153. } 1154. return; 1155. } 1156. #endif 1157. 1158. if (match_optname(opts, "palette", 3, TRUE) 1159. # ifdef MAC 1160. || match_optname(opts, "hicolor", 3, TRUE) 1161. # endif 1162. ) { 1163. int color_number, color_incr; 1164. 1165. # ifdef MAC 1166. if (match_optname(opts, "hicolor", 3, TRUE)) { 1167. if (negated) { 1168. bad_negation("hicolor", FALSE); 1169. return; 1170. } 1171. color_number = CLR_MAX + 4; /* HARDCODED inverse number */ 1172. color_incr = -1; 1173. } else { 1174. # endif 1175. if (negated) { 1176. bad_negation("palette", FALSE); 1177. return; 1178. } 1179. color_number = 0; 1180. color_incr = 1; 1181. # ifdef MAC 1182. } 1183. # endif 1184. if ((op = string_for_opt(opts, FALSE)) != (char *)0) { 1185. char *pt = op; 1186. int cnt, tmp, reverse; 1187. long rgb; 1188. 1189. while (*pt && color_number >= 0) { 1190. cnt = 3; 1191. rgb = 0L; 1192. if (*pt == '-') { 1193. reverse = 1; 1194. pt++; 1195. } else { 1196. reverse = 0; 1197. } 1198. while (cnt-- > 0) { 1199. if (*pt && *pt != '/') { 1200. # ifdef AMIGA 1201. rgb <<= 4; 1202. # else 1203. rgb <<= 8; 1204. # endif 1205. tmp = *(pt++); 1206. if (isalpha(tmp)) { 1207. tmp = (tmp + 9) & 0xf; /* Assumes ASCII... */ 1208. } else { 1209. tmp &= 0xf; /* Digits in ASCII too... */ 1210. } 1211. # ifndef AMIGA 1212. /* Add an extra so we fill f -> ff and 0 -> 00 */ 1213. rgb += tmp << 4; 1214. # endif 1215. rgb += tmp; 1216. } 1217. } 1218. if (*pt == '/') { 1219. pt++; 1220. } 1221. change_color(color_number, rgb, reverse); 1222. color_number += color_incr; 1223. } 1224. } 1225. if (!initial) { 1226. need_redraw = TRUE; 1227. } 1228. return; 1229. } 1230. #endif /* CHANGE_COLOR */ 1231. 1232. if (match_optname(opts, "fruit", 2, TRUE)) { 1233. char empty_str = '\0'; 1234. op = string_for_opt(opts, negated); 1235. if (negated) { 1236. if (op) { 1237. bad_negation("fruit", TRUE); 1238. return; 1239. } 1240. op = &empty_str; 1241. goto goodfruit; 1242. } 1243. if (!op) return; 1244. if (!initial) { 1245. struct fruit *f; 1246. 1247. num = 0; 1248. for(f=ffruit; f; f=f->nextf) { 1249. if (!strcmp(op, f->fname)) goto goodfruit; 1250. num++; 1251. } 1252. if (num >= 100) { 1253. pline("Doing that so many times isn't very fruitful."); 1254. return; 1255. } 1256. } 1257. goodfruit: 1258. nmcpy(pl_fruit, op, PL_FSIZ); 1259. /* OBJ_NAME(objects[SLIME_MOLD]) won't work after initialization */ 1260. if (!*pl_fruit) 1261. nmcpy(pl_fruit, "slime mold", PL_FSIZ); 1262. if (!initial) 1263. (void)fruitadd(pl_fruit); 1264. /* If initial, then initoptions is allowed to do it instead 1265. * of here (initoptions always has to do it even if there's 1266. * no fruit option at all. Also, we don't want people 1267. * setting multiple fruits in their options.) 1268. */ 1269. return; 1270. } 1271. 1272. /* graphics:string */ 1273. fullname = "graphics"; 1274. if (match_optname(opts, fullname, 2, TRUE)) { 1275. if (negated) bad_negation(fullname, FALSE); 1276. else graphics_opts(opts, fullname, MAXPCHARS, 0); 1277. return; 1278. } 1279. fullname = "dungeon"; 1280. if (match_optname(opts, fullname, 2, TRUE)) { 1281. if (negated) bad_negation(fullname, FALSE); 1282. else graphics_opts(opts, fullname, MAXDCHARS, 0); 1283. return; 1284. } 1285. fullname = "traps"; 1286. if (match_optname(opts, fullname, 2, TRUE)) { 1287. if (negated) bad_negation(fullname, FALSE); 1288. else graphics_opts(opts, fullname, MAXTCHARS, MAXDCHARS); 1289. return; 1290. } 1291. fullname = "effects"; 1292. if (match_optname(opts, fullname, 2, TRUE)) { 1293. if (negated) bad_negation(fullname, FALSE); 1294. else 1295. graphics_opts(opts, fullname, MAXECHARS, MAXDCHARS+MAXTCHARS); 1296. return; 1297. } 1298. 1299. /* objects:string */ 1300. fullname = "objects"; 1301. if (match_optname(opts, fullname, 7, TRUE)) { 1302. int length; 1303. 1304. if (negated) { 1305. bad_negation(fullname, FALSE); 1306. return; 1307. } 1308. if (!(opts = string_for_env_opt(fullname, opts, FALSE))) 1309. return; 1310. escapes(opts, opts); 1311. 1312. /* 1313. * Override the default object class symbols. The first 1314. * object in the object class is the "random object". I 1315. * don't want to use 0 as an object class, so the "random 1316. * object" is basically a place holder. 1317. * 1318. * The object class symbols have already been initialized in 1319. * initoptions(). 1320. */ 1321. length = strlen(opts); 1322. if (length >= MAXOCLASSES) 1323. length = MAXOCLASSES-1; /* don't count RANDOM_OBJECT */ 1324. 1325. for (i = 0; i < length; i++) 1326. oc_syms[i+1] = (uchar) opts[i]; 1327. return; 1328. } 1329. 1330. /* monsters:string */ 1331. fullname = "monsters"; 1332. if (match_optname(opts, fullname, 8, TRUE)) { 1333. int length; 1334. 1335. if (negated) { 1336. bad_negation(fullname, FALSE); 1337. return; 1338. } 1339. if (!(opts = string_for_env_opt(fullname, opts, FALSE))) 1340. return; 1341. escapes(opts, opts); 1342. 1343. /* Override default mon class symbols set in initoptions(). */ 1344. length = strlen(opts); 1345. if (length >= MAXMCLASSES) 1346. length = MAXMCLASSES-1; /* mon class 0 unused */ 1347. 1348. for (i = 0; i < length; i++) 1349. monsyms[i+1] = (uchar) opts[i]; 1350. return; 1351. } 1352. fullname = "warnings"; 1353. if (match_optname(opts, fullname, 5, TRUE)) { 1354. if (negated) bad_negation(fullname, FALSE); 1355. else warning_opts(opts, fullname); 1356. return; 1357. } 1358. /* boulder:symbol */ 1359. fullname = "boulder"; 1360. if (match_optname(opts, fullname, 7, TRUE)) { 1361. if (negated) { 1362. bad_negation(fullname, FALSE); 1363. return; 1364. } 1365. /* if (!(opts = string_for_env_opt(fullname, opts, FALSE))) */ 1366. if (!(opts = string_for_opt(opts, FALSE))) 1367. return; 1368. escapes(opts, opts); 1369. 1370. /* 1371. * Override the default boulder symbol. 1372. */ 1373. iflags.bouldersym = (uchar) opts[0]; 1374. if (!initial) need_redraw = TRUE; 1375. return; 1376. } 1377. 1378. /* name:string */ 1379. fullname = "name"; 1380. if (match_optname(opts, fullname, 4, TRUE)) { 1381. if (negated) bad_negation(fullname, FALSE); 1382. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1383. nmcpy(plname, op, PL_NSIZ); 1384. return; 1385. } 1386. 1387. /* role:string or character:string */ 1388. fullname = "role"; 1389. if (match_optname(opts, fullname, 4, TRUE) || 1390. match_optname(opts, (fullname = "character"), 4, TRUE)) { 1391. if (negated) bad_negation(fullname, FALSE); 1392. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1393. if ((flags.initrole = str2role(op)) == ROLE_NONE) 1394. badoption(opts); 1395. else /* Backwards compatibility */ 1396. nmcpy(pl_character, op, PL_NSIZ); 1397. } 1398. return; 1399. } 1400. 1401. /* race:string */ 1402. fullname = "race"; 1403. if (match_optname(opts, fullname, 4, TRUE)) { 1404. if (negated) bad_negation(fullname, FALSE); 1405. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1406. if ((flags.initrace = str2race(op)) == ROLE_NONE) 1407. badoption(opts); 1408. else /* Backwards compatibility */ 1409. pl_race = *op; 1410. } 1411. return; 1412. } 1413. 1414. /* gender:string */ 1415. fullname = "gender"; 1416. if (match_optname(opts, fullname, 4, TRUE)) { 1417. if (negated) bad_negation(fullname, FALSE); 1418. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1419. if ((flags.initgend = str2gend(op)) == ROLE_NONE) 1420. badoption(opts); 1421. else 1422. flags.female = flags.initgend; 1423. } 1424. return; 1425. } 1426. 1427. /* WINCAP 1428. * align_status:[left|top|right|bottom] */ 1429. fullname = "align_status"; 1430. if (match_optname(opts, fullname, sizeof("align_status")-1, TRUE)) { 1431. op = string_for_opt(opts, negated); 1432. if (op && !negated) { 1433. if (!strncmpi (op, "left", sizeof("left")-1)) 1434. iflags.wc_align_status = ALIGN_LEFT; 1435. else if (!strncmpi (op, "top", sizeof("top")-1)) 1436. iflags.wc_align_status = ALIGN_TOP; 1437. else if (!strncmpi (op, "right", sizeof("right")-1)) 1438. iflags.wc_align_status = ALIGN_RIGHT; 1439. else if (!strncmpi (op, "bottom", sizeof("bottom")-1)) 1440. iflags.wc_align_status = ALIGN_BOTTOM; 1441. else 1442. badoption(opts); 1443. } else if (negated) bad_negation(fullname, TRUE); 1444. return; 1445. } 1446. /* WINCAP 1447. * align_message:[left|top|right|bottom] */ 1448. fullname = "align_message"; 1449. if (match_optname(opts, fullname, sizeof("align_message")-1, TRUE)) { 1450. op = string_for_opt(opts, negated); 1451. if (op && !negated) { 1452. if (!strncmpi (op, "left", sizeof("left")-1)) 1453. iflags.wc_align_message = ALIGN_LEFT; 1454. else if (!strncmpi (op, "top", sizeof("top")-1)) 1455. iflags.wc_align_message = ALIGN_TOP; 1456. else if (!strncmpi (op, "right", sizeof("right")-1)) 1457. iflags.wc_align_message = ALIGN_RIGHT; 1458. else if (!strncmpi (op, "bottom", sizeof("bottom")-1)) 1459. iflags.wc_align_message = ALIGN_BOTTOM; 1460. else 1461. badoption(opts); 1462. } else if (negated) bad_negation(fullname, TRUE); 1463. return; 1464. } 1465. /* align:string */ 1466. fullname = "align"; 1467. if (match_optname(opts, fullname, sizeof("align")-1, TRUE)) { 1468. if (negated) bad_negation(fullname, FALSE); 1469. else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) 1470. if ((flags.initalign = str2align(op)) == ROLE_NONE) 1471. badoption(opts); 1472. return; 1473. } 1474. 1475. /* the order to list the pack */ 1476. fullname = "packorder"; 1477. if (match_optname(opts, fullname, 4, TRUE)) { 1478. if (negated) { 1479. bad_negation(fullname, FALSE); 1480. return; 1481. } else if (!(op = string_for_opt(opts, FALSE))) return; 1482. 1483. if (!change_inv_order(op)) 1484. badoption(opts); 1485. return; 1486. } 1487. 1488. /* maximum burden picked up before prompt (Warren Cheung) */ 1489. fullname = "pickup_burden"; 1490. if (match_optname(opts, fullname, 8, TRUE)) { 1491. if (negated) { 1492. bad_negation(fullname, FALSE); 1493. return; 1494. } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1495. switch (tolower(*op)) { 1496. /* Unencumbered */ 1497. case 'u': 1498. flags.pickup_burden = UNENCUMBERED; 1499. break; 1500. /* Burdened (slight encumbrance) */ 1501. case 'b': 1502. flags.pickup_burden = SLT_ENCUMBER; 1503. break; 1504. /* streSsed (moderate encumbrance) */ 1505. case 's': 1506. flags.pickup_burden = MOD_ENCUMBER; 1507. break; 1508. /* straiNed (heavy encumbrance) */ 1509. case 'n': 1510. flags.pickup_burden = HVY_ENCUMBER; 1511. break; 1512. /* OverTaxed (extreme encumbrance) */ 1513. case 'o': 1514. case 't': 1515. flags.pickup_burden = EXT_ENCUMBER; 1516. break; 1517. /* overLoaded */ 1518. case 'l': 1519. flags.pickup_burden = OVERLOADED; 1520. break; 1521. default: 1522. badoption(opts); 1523. } 1524. } 1525. return; 1526. } 1527. 1528. /* types of objects to pick up automatically */ 1529. if (match_optname(opts, "pickup_types", 8, TRUE)) { 1530. char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], 1531. qbuf[QBUFSZ], abuf[BUFSZ]; 1532. int oc_sym; 1533. boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu; 1534. 1535. oc_to_str(flags.pickup_types, tbuf); 1536. flags.pickup_types[0] = '\0'; /* all */ 1537. op = string_for_opt(opts, (compat || !initial)); 1538. if (!op) { 1539. if (compat || negated || initial) { 1540. /* for backwards compatibility, "pickup" without a 1541. value is a synonym for autopickup of all types 1542. (and during initialization, we can't prompt yet) */ 1543. flags.pickup = !negated; 1544. return; 1545. } 1546. oc_to_str(flags.inv_order, ocl); 1547. use_menu = TRUE; 1548. if (flags.menu_style == MENU_TRADITIONAL || 1549. flags.menu_style == MENU_COMBINATION) { 1550. use_menu = FALSE; 1551. Sprintf(qbuf, "New pickup_types: [%s am] (%s)", 1552. ocl, *tbuf ? tbuf : "all"); 1553. getlin(qbuf, abuf); 1554. op = mungspaces(abuf); 1555. if (abuf[0] == '\0' || abuf[0] == '\033') 1556. op = tbuf; /* restore */ 1557. else if (abuf[0] == 'm') 1558. use_menu = TRUE; 1559. } 1560. if (use_menu) { 1561. (void) choose_classes_menu("Auto-Pickup what?", 1, 1562. TRUE, ocl, tbuf); 1563. op = tbuf; 1564. } 1565. } 1566. if (negated) { 1567. bad_negation("pickup_types", TRUE); 1568. return; 1569. } 1570. while (*op == ' ') op++; 1571. if (*op != 'a' && *op != 'A') { 1572. num = 0; 1573. while (*op) { 1574. oc_sym = def_char_to_objclass(*op); 1575. /* make sure all are valid obj symbols occuring once */ 1576. if (oc_sym != MAXOCLASSES && 1577. !index(flags.pickup_types, oc_sym)) { 1578. flags.pickup_types[num] = (char)oc_sym; 1579. flags.pickup_types[++num] = '\0'; 1580. } else 1581. badopt = TRUE; 1582. op++; 1583. } 1584. if (badopt) badoption(opts); 1585. } 1586. return; 1587. } 1588. /* WINCAP 1589. * player_selection: dialog | prompts */ 1590. fullname = "player_selection"; 1591. if (match_optname(opts, fullname, sizeof("player_selection")-1, TRUE)) { 1592. op = string_for_opt(opts, negated); 1593. if (op && !negated) { 1594. if (!strncmpi (op, "dialog", sizeof("dialog")-1)) 1595. iflags.wc_player_selection = VIA_DIALOG; 1596. else if (!strncmpi (op, "prompt", sizeof("prompt")-1)) 1597. iflags.wc_player_selection = VIA_PROMPTS; 1598. else 1599. badoption(opts); 1600. } else if (negated) bad_negation(fullname, TRUE); 1601. return; 1602. } 1603. 1604. /* things to disclose at end of game */ 1605. if (match_optname(opts, "disclose", 7, TRUE)) { 1606. /* 1607. * The order that the end_disclore options are stored: 1608. * inventory, attribs, vanquished, genocided, conduct 1609. * There is an array in flags: 1610. * end_disclose[NUM_DISCLOSURE_OPT]; 1611. * with option settings for the each of the following: 1612. * iagvc [see disclosure_options in decl.c]: 1613. * Legal setting values in that array are: 1614. * DISCLOSE_PROMPT_DEFAULT_YES ask with default answer yes 1615. * DISCLOSE_PROMPT_DEFAULT_NO ask with default answer no 1616. * DISCLOSE_YES_WITHOUT_PROMPT always disclose and don't ask 1617. * DISCLOSE_NO_WITHOUT_PROMPT never disclose and don't ask 1618. * 1619. * Those setting values can be used in the option 1620. * string as a prefix to get the desired behaviour. 1621. * 1622. * For backward compatibility, no prefix is required, 1623. * and the presence of a i,a,g,v, or c without a 1624. * prefix sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT; 1625. */ 1626. boolean badopt = FALSE; 1627. int idx, prefix_val; 1628. if (!(op = string_for_opt(opts, TRUE))) { 1629. /* for backwards compatibility, "disclose" without a 1630. * value means all (was inventory and attributes, 1631. * the only things available then), but negated 1632. * it means "none" 1633. * (note "none" contains none of "iavkgc") 1634. */ 1635. for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++) { 1636. if (negated) 1637. flags.end_disclose[num] = DISCLOSE_NO_WITHOUT_PROMPT; 1638. else flags.end_disclose[num] = DISCLOSE_PROMPT_DEFAULT_YES; 1639. } 1640. return; 1641. } 1642. if (negated) { 1643. bad_negation("disclose", TRUE); 1644. return; 1645. } 1646. num = 0; 1647. prefix_val = -1; 1648. while (*op && num < sizeof flags.end_disclose - 1) { 1649. register char c, *dop; 1650. static char valid_settings[] = { 1651. DISCLOSE_PROMPT_DEFAULT_YES, 1652. DISCLOSE_PROMPT_DEFAULT_NO, 1653. DISCLOSE_YES_WITHOUT_PROMPT, 1654. DISCLOSE_NO_WITHOUT_PROMPT, 1655. '\0' 1656. }; 1657. c = lowc(*op); 1658. if (c == 'k') c = 'v'; /* killed -> vanquished */ 1659. dop = index(disclosure_options, c); 1660. if (dop) { 1661. idx = dop - disclosure_options; 1662. if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) { 1663. impossible("bad disclosure index %d %c", 1664. idx, c); 1665. continue; 1666. } 1667. if (prefix_val != -1) { 1668. flags.end_disclose[idx] = prefix_val; 1669. prefix_val = -1; 1670. } else 1671. flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT; 1672. } else if (index(valid_settings, c)) { 1673. prefix_val = c; 1674. } else if (c == ' ') { 1675. /* do nothing */ 1676. } else 1677. badopt = TRUE; 1678. op++; 1679. } 1680. if (badopt) badoption(opts); 1681. return; 1682. } 1683. 1684. /* scores:5t[op] 5a[round] o[wn] */ 1685. if (match_optname(opts, "scores", 4, TRUE)) { 1686. if (negated) { 1687. bad_negation("scores", FALSE); 1688. return; 1689. } 1690. if (!(op = string_for_opt(opts, FALSE))) return; 1691. 1692. while (*op) { 1693. int inum = 1; 1694. 1695. if (digit(*op)) { 1696. inum = atoi(op); 1697. while (digit(*op)) op++; 1698. } else if (*op == '!') { 1699. negated = !negated; 1700. op++; 1701. } 1702. while (*op == ' ') op++; 1703. 1704. switch (*op) { 1705. case 't': 1706. case 'T': flags.end_top = inum; 1707. break; 1708. case 'a': 1709. case 'A': flags.end_around = inum; 1710. break; 1711. case 'o': 1712. case 'O': flags.end_own = !negated; 1713. break; 1714. default: badoption(opts); 1715. return; 1716. } 1717. while (letter(*++op) || *op == ' ') continue; 1718. if (*op == '/') op++; 1719. } 1720. return; 1721. } 1722. 1723. fullname = "suppress_alert"; 1724. if (match_optname(opts, fullname, 4, TRUE)) { 1725. op = string_for_opt(opts, negated); 1726. if (negated) bad_negation(fullname, FALSE); 1727. else if (op) (void) feature_alert_opts(op,fullname); 1728. return; 1729. } 1730. 1731. #ifdef VIDEOSHADES 1732. /* videocolors:string */ 1733. fullname = "videocolors"; 1734. if (match_optname(opts, fullname, 6, TRUE) || 1735. match_optname(opts, "videocolours", 10, TRUE)) { 1736. if (negated) { 1737. bad_negation(fullname, FALSE); 1738. return; 1739. } 1740. else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { 1741. return; 1742. } 1743. if (!assign_videocolors(opts)) 1744. badoption(opts); 1745. return; 1746. } 1747. /* videoshades:string */ 1748. fullname = "videoshades"; 1749. if (match_optname(opts, fullname, 6, TRUE)) { 1750. if (negated) { 1751. bad_negation(fullname, FALSE); 1752. return; 1753. } 1754. else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { 1755. return; 1756. } 1757. if (!assign_videoshades(opts)) 1758. badoption(opts); 1759. return; 1760. } 1761. #endif /* VIDEOSHADES */ 1762. #ifdef MSDOS 1763. # ifdef NO_TERMS 1764. /* video:string -- must be after longer tests */ 1765. fullname = "video"; 1766. if (match_optname(opts, fullname, 5, TRUE)) { 1767. if (negated) { 1768. bad_negation(fullname, FALSE); 1769. return; 1770. } 1771. else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { 1772. return; 1773. } 1774. if (!assign_video(opts)) 1775. badoption(opts); 1776. return; 1777. } 1778. # endif /* NO_TERMS */ 1779. /* soundcard:string -- careful not to match boolean 'sound' */ 1780. fullname = "soundcard"; 1781. if (match_optname(opts, fullname, 6, TRUE)) { 1782. if (negated) { 1783. bad_negation(fullname, FALSE); 1784. return; 1785. } 1786. else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) { 1787. return; 1788. } 1789. if (!assign_soundcard(opts)) 1790. badoption(opts); 1791. return; 1792. } 1793. #endif /* MSDOS */ 1794. 1795. /* WINCAP 1796. * map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|ascii8x12| 1797. ascii16x12|ascii12x16|ascii10x18|fit_to_screen] */ 1798. fullname = "map_mode"; 1799. if (match_optname(opts, fullname, sizeof("map_mode")-1, TRUE)) { 1800. op = string_for_opt(opts, negated); 1801. if (op && !negated) { 1802. if (!strncmpi (op, "tiles", sizeof("tiles")-1)) 1803. iflags.wc_map_mode = MAP_MODE_TILES; 1804. else if (!strncmpi (op, "ascii4x6", sizeof("ascii4x6")-1)) 1805. iflags.wc_map_mode = MAP_MODE_ASCII4x6; 1806. else if (!strncmpi (op, "ascii6x8", sizeof("ascii6x8")-1)) 1807. iflags.wc_map_mode = MAP_MODE_ASCII6x8; 1808. else if (!strncmpi (op, "ascii8x8", sizeof("ascii8x8")-1)) 1809. iflags.wc_map_mode = MAP_MODE_ASCII8x8; 1810. else if (!strncmpi (op, "ascii16x8", sizeof("ascii16x8")-1)) 1811. iflags.wc_map_mode = MAP_MODE_ASCII16x8; 1812. else if (!strncmpi (op, "ascii7x12", sizeof("ascii7x12")-1)) 1813. iflags.wc_map_mode = MAP_MODE_ASCII7x12; 1814. else if (!strncmpi (op, "ascii8x12", sizeof("ascii8x12")-1)) 1815. iflags.wc_map_mode = MAP_MODE_ASCII8x12; 1816. else if (!strncmpi (op, "ascii16x12", sizeof("ascii16x12")-1)) 1817. iflags.wc_map_mode = MAP_MODE_ASCII16x12; 1818. else if (!strncmpi (op, "ascii12x16", sizeof("ascii12x16")-1)) 1819. iflags.wc_map_mode = MAP_MODE_ASCII12x16; 1820. else if (!strncmpi (op, "ascii10x18", sizeof("ascii10x18")-1)) 1821. iflags.wc_map_mode = MAP_MODE_ASCII10x18; 1822. else if (!strncmpi (op, "fit_to_screen", sizeof("fit_to_screen")-1)) 1823. iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN; 1824. else 1825. badoption(opts); 1826. } else if (negated) bad_negation(fullname, TRUE); 1827. return; 1828. } 1829. /* WINCAP 1830. * scroll_margin:nn */ 1831. fullname = "scroll_margin"; 1832. if (match_optname(opts, fullname, sizeof("scroll_margin")-1, TRUE)) { 1833. op = string_for_opt(opts, negated); 1834. if ((negated && !op) || (!negated && op)) { 1835. iflags.wc_scroll_margin = negated ? 5 : atoi(op); 1836. } else if (negated) bad_negation(fullname, TRUE); 1837. return; 1838. } 1839. /* WINCAP 1840. * tile_width:nn */ 1841. fullname = "tile_width"; 1842. if (match_optname(opts, fullname, sizeof("tile_width")-1, TRUE)) { 1843. op = string_for_opt(opts, negated); 1844. if ((negated && !op) || (!negated && op)) { 1845. iflags.wc_tile_width = negated ? 0 : atoi(op); 1846. } else if (negated) bad_negation(fullname, TRUE); 1847. return; 1848. } 1849. /* WINCAP 1850. * tile_file:name */ 1851. fullname = "tile_file"; 1852. if (match_optname(opts, fullname, sizeof("tile_file")-1, TRUE)) { 1853. if ((op = string_for_opt(opts, FALSE)) != 0) { 1854. if (iflags.wc_tile_file) free(iflags.wc_tile_file); 1855. iflags.wc_tile_file = (char *)alloc(strlen(op) + 1); 1856. Strcpy(iflags.wc_tile_file, op); 1857. } 1858. return; 1859. } 1860. /* WINCAP 1861. * tile_height:nn */ 1862. fullname = "tile_height"; 1863. if (match_optname(opts, fullname, sizeof("tile_height")-1, TRUE)) { 1864. op = string_for_opt(opts, negated); 1865. if ((negated && !op) || (!negated && op)) { 1866. iflags.wc_tile_height = negated ? 0 : atoi(op); 1867. } else if (negated) bad_negation(fullname, TRUE); 1868. return; 1869. } 1870. /* WINCAP 1871. * vary_msgcount:nn */ 1872. fullname = "vary_msgcount"; 1873. if (match_optname(opts, fullname, sizeof("vary_msgcount")-1, TRUE)) { 1874. op = string_for_opt(opts, negated); 1875. if ((negated && !op) || (!negated && op)) { 1876. iflags.wc_vary_msgcount = negated ? 0 : atoi(op); 1877. } else if (negated) bad_negation(fullname, TRUE); 1878. return; 1879. } 1880. 1881. fullname = "windowtype"; 1882. if (match_optname(opts, fullname, 3, TRUE)) { 1883. if (negated) { 1884. bad_negation(fullname, FALSE); 1885. return; 1886. } else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) { 1887. char buf[WINTYPELEN]; 1888. nmcpy(buf, op, WINTYPELEN); 1889. choose_windows(buf); 1890. } 1891. return; 1892. } 1893. 1894. /* WINCAP 1895. * setting window colors 1896. * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd 1897. */ 1898. fullname = "windowcolors"; 1899. if (match_optname(opts, fullname, 7, TRUE)) { 1900. if ((op = string_for_opt(opts, FALSE)) != 0) { 1901. if (!wc_set_window_colors(op)) 1902. badoption(opts); 1903. } else if (negated) bad_negation(fullname, TRUE); 1904. return; 1905. } 1906. 1907. /* menustyle:traditional or combo or full or partial */ 1908. if (match_optname(opts, "menustyle", 4, TRUE)) { 1909. int tmp; 1910. boolean val_required = (strlen(opts) > 5 && !negated); 1911. 1912. if (!(op = string_for_opt(opts, !val_required))) { 1913. if (val_required) return; /* string_for_opt gave feedback */ 1914. tmp = negated ? 'n' : 'f'; 1915. } else { 1916. tmp = tolower(*op); 1917. } 1918. switch (tmp) { 1919. case 'n': /* none */ 1920. case 't': /* traditional */ 1921. flags.menu_style = MENU_TRADITIONAL; 1922. break; 1923. case 'c': /* combo: trad.class sel+menu */ 1924. flags.menu_style = MENU_COMBINATION; 1925. break; 1926. case 'p': /* partial: no class menu */ 1927. flags.menu_style = MENU_PARTIAL; 1928. break; 1929. case 'f': /* full: class menu + menu */ 1930. flags.menu_style = MENU_FULL; 1931. break; 1932. default: 1933. badoption(opts); 1934. } 1935. return; 1936. } 1937. 1938. /* check for menu command mapping */ 1939. for (i = 0; i < NUM_MENU_CMDS; i++) { 1940. fullname = default_menu_cmd_info[i].name; 1941. if (match_optname(opts, fullname, (int)strlen(fullname), TRUE)) { 1942. if (negated) 1943. bad_negation(fullname, FALSE); 1944. else if ((op = string_for_opt(opts, FALSE)) != 0) { 1945. int j; 1946. char c, op_buf[BUFSZ]; 1947. boolean isbad = FALSE; 1948. 1949. escapes(op, op_buf); 1950. c = *op_buf; 1951. 1952. if (c == 0 || c == '' || c == '
' || c == '\033' || 1953. c == ' ' || digit(c) || (letter(c) && c != '@')) 1954. isbad = TRUE; 1955. else /* reject default object class symbols */ 1956. for (j = 1; j < MAXOCLASSES; j++) 1957. if (c == def_oc_syms[i]) { 1958. isbad = TRUE; 1959. break; 1960. } 1961. 1962. if (isbad) 1963. badoption(opts); 1964. else 1965. add_menu_cmd_alias(c, default_menu_cmd_info[i].cmd); 1966. } 1967. return; 1968. } 1969. } 1970. 1971. /* OK, if we still haven't recognized the option, check the boolean 1972. * options list 1973. */ 1974. for (i = 0; boolopt[i].name; i++) { 1975. if (match_optname(opts, boolopt[i].name, 3, FALSE)) { 1976. /* options that don't exist */ 1977. if (!boolopt[i].addr) { 1978. if (!initial && !negated) 1979. pline_The("\"%s\" option is not available.", 1980. boolopt[i].name); 1981. return; 1982. } 1983. /* options that must come from config file */ 1984. if (!initial && (boolopt[i].optflags == SET_IN_FILE)) { 1985. rejectoption(boolopt[i].name); 1986. return; 1987. } 1988. 1989. *(boolopt[i].addr) = !negated; 1990. 1991. duplicate_opt_detection(boolopt[i].name, 0); 1992. 1993. #if defined(TERMLIB) || defined(ASCIIGRAPH) || defined(MAC_GRAPHICS_ENV) 1994. if (FALSE 1995. # ifdef TERMLIB 1996. || (boolopt[i].addr) == &iflags.DECgraphics 1997. # endif 1998. # ifdef ASCIIGRAPH 1999. || (boolopt[i].addr) == &iflags.IBMgraphics 2000. # endif 2001. # ifdef MAC_GRAPHICS_ENV 2002. || (boolopt[i].addr) == &iflags.MACgraphics 2003. # endif 2004. ) { 2005. # ifdef REINCARNATION 2006. if (!initial && Is_rogue_level(&u.uz)) 2007. assign_rogue_graphics(FALSE); 2008. # endif 2009. need_redraw = TRUE; 2010. # ifdef TERMLIB 2011. if ((boolopt[i].addr) == &iflags.DECgraphics) 2012. switch_graphics(iflags.DECgraphics ? 2013. DEC_GRAPHICS : ASCII_GRAPHICS); 2014. # endif 2015. # ifdef ASCIIGRAPH 2016. if ((boolopt[i].addr) == &iflags.IBMgraphics) 2017. switch_graphics(iflags.IBMgraphics ? 2018. IBM_GRAPHICS : ASCII_GRAPHICS); 2019. # endif 2020. # ifdef MAC_GRAPHICS_ENV 2021. if ((boolopt[i].addr) == &iflags.MACgraphics) 2022. switch_graphics(iflags.MACgraphics ? 2023. MAC_GRAPHICS : ASCII_GRAPHICS); 2024. # endif 2025. # ifdef REINCARNATION 2026. if (!initial && Is_rogue_level(&u.uz)) 2027. assign_rogue_graphics(TRUE); 2028. # endif 2029. } 2030. #endif /* TERMLIB || ASCIIGRAPH || MAC_GRAPHICS_ENV */ 2031. 2032. /* only do processing below if setting with doset() */ 2033. if (initial) return; 2034. 2035. if ((boolopt[i].addr) == &flags.time 2036. #ifdef EXP_ON_BOTL 2037. || (boolopt[i].addr) == &flags.showexp 2038. #endif 2039. #ifdef SCORE_ON_BOTL 2040. || (boolopt[i].addr) == &flags.showscore 2041. #endif 2042. ) 2043. flags.botl = TRUE; 2044. 2045. else if ((boolopt[i].addr) == &flags.invlet_constant) { 2046. if (flags.invlet_constant) reassign(); 2047. } 2048. #ifdef LAN_MAIL 2049. else if ((boolopt[i].addr) == &flags.biff) { 2050. if (flags.biff) lan_mail_init(); 2051. else lan_mail_finish(); 2052. } 2053. #endif 2054. else if ((boolopt[i].addr) == &iflags.num_pad) 2055. number_pad(iflags.num_pad ? 1 : 0); 2056. 2057. else if ((boolopt[i].addr) == &flags.lit_corridor) { 2058. /* 2059. * All corridor squares seen via night vision or 2060. * candles & lamps change. Update them by calling 2061. * newsym() on them. Don't do this if we are 2062. * initializing the options --- the vision system 2063. * isn't set up yet. 2064. */ 2065. vision_recalc(2); /* shut down vision */ 2066. vision_full_recalc = 1; /* delayed recalc */ 2067. } 2068. else if ((boolopt[i].addr) == &iflags.use_inverse) { 2069. need_redraw = TRUE; 2070. } 2071. else if ((boolopt[i].addr) == &iflags.hilite_pet) { 2072. need_redraw = TRUE; 2073. } 2074. #ifdef TEXTCOLOR 2075. else if ((boolopt[i].addr) == &iflags.use_color) { 2076. need_redraw = TRUE; 2077. # ifdef TOS 2078. if ((boolopt[i].addr) == &iflags.use_color 2079. && iflags.BIOS) { 2080. if (colors_changed) 2081. restore_colors(); 2082. else 2083. set_colors(); 2084. } 2085. # endif 2086. } 2087. #endif 2088. 2089. return; 2090. } 2091. } 2092. 2093. /* out of valid options */ 2094. badoption(opts); 2095. } 2096. 2097. 2098. static NEARDATA const char *menutype[] = { 2099. "traditional", "combination", "partial", "full" 2100. }; 2101. 2102. static NEARDATA const char *burdentype[] = { 2103. "unencumbered", "burdened", "stressed", 2104. "strained", "overtaxed", "overloaded" 2105. }; 2106. 2107. 2108. /* 2109. * Convert the given string of object classes to a string of default object 2110. * symbols. 2111. */ 2112. STATIC_OVL void 2113. oc_to_str(src,dest) 2114. char *src, *dest; 2115. { 2116. int i; 2117. 2118. while ((i = (int) *src++) != 0) { 2119. if (i < 0 || i >= MAXOCLASSES) 2120. impossible("oc_to_str: illegal object class %d", i); 2121. else 2122. *dest++ = def_oc_syms[i]; 2123. } 2124. *dest = '\0'; 2125. } 2126. 2127. /* 2128. * Add the given mapping to the menu command map list. Always keep the 2129. * maps valid C strings. 2130. */ 2131. void 2132. add_menu_cmd_alias(from_ch, to_ch) 2133. char from_ch, to_ch; 2134. { 2135. if (n_menu_mapped >= MAX_MENU_MAPPED_CMDS) 2136. pline("out of menu map space"); 2137. else { 2138. mapped_menu_cmds[n_menu_mapped] = from_ch; 2139. mapped_menu_op[n_menu_mapped] = to_ch; 2140. n_menu_mapped++; 2141. mapped_menu_cmds[n_menu_mapped] = 0; 2142. mapped_menu_op[n_menu_mapped] = 0; 2143. } 2144. } 2145. 2146. /* 2147. * Map the given character to its corresponding menu command. If it 2148. * doesn't match anything, just return the original. 2149. */ 2150. char 2151. map_menu_cmd(ch) 2152. char ch; 2153. { 2154. char *found = index(mapped_menu_cmds, ch); 2155. if (found) { 2156. int idx = found - mapped_menu_cmds; 2157. ch = mapped_menu_op[idx]; 2158. } 2159. return ch; 2160. } 2161. 2162. 2163. #if defined(MICRO) || defined(MAC) 2164. # define OPTIONS_HEADING "OPTIONS" 2165. #else 2166. # define OPTIONS_HEADING "NETHACKOPTIONS" 2167. #endif 2168. 2169. static char fmtstr_doset_add_menu[] = "%s%-15s [%s] "; 2170. static char fmtstr_doset_add_menu_tab[] = "%s [%s]"; 2171. 2172. STATIC_OVL void 2173. doset_add_menu(win, option, indexoffset) 2174. winid win; /* window to add to */ 2175. const char *option; /* option name */ 2176. int indexoffset; /* value to add to index in compopt[], or zero 2177. if option cannot be changed */ 2178. { 2179. const char *value = "unknown"; /* current value */ 2180. char buf[BUFSZ], buf2[BUFSZ]; 2181. anything any; 2182. int i; 2183. 2184. any.a_void = 0; 2185. if (indexoffset == 0) { 2186. any.a_int = 0; 2187. value = get_compopt_value(option, buf2); 2188. } else { 2189. for (i=0; compopt[i].name; i++) 2190. if (strcmp(option, compopt[i].name) == 0) break; 2191. 2192. if (compopt[i].name) { 2193. any.a_int = i + 1 + indexoffset; 2194. value = get_compopt_value(option, buf2); 2195. } else { 2196. /* We are trying to add an option not found in compopt[]. 2197. This is almost certainly bad, but we'll let it through anyway 2198. (with a zero value, so it can't be selected). */ 2199. any.a_int = 0; 2200. } 2201. } 2202. /* " " replaces "a - " -- assumes menus follow that style */ 2203. if (!iflags.menu_tab_sep) 2204. Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", option, value); 2205. else 2206. Sprintf(buf, fmtstr_doset_add_menu_tab, option, value); 2207. add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); 2208. } 2209. 2210. /* Changing options via menu by Per Liboriussen */ 2211. int 2212. doset() 2213. { 2214. char buf[BUFSZ], buf2[BUFSZ]; 2215. int i, pass, boolcount, pick_cnt, pick_idx, opt_indx; 2216. boolean *bool_p; 2217. winid tmpwin; 2218. anything any; 2219. menu_item *pick_list; 2220. int indexoffset, startpass, endpass; 2221. boolean setinitial = FALSE, fromfile = FALSE; 2222. int biggest_name = 0; 2223. 2224. tmpwin = create_nhwindow(NHW_MENU); 2225. start_menu(tmpwin); 2226. 2227. any.a_void = 0; 2228. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, 2229. "Booleans (selecting will toggle value):", MENU_UNSELECTED); 2230. any.a_int = 0; 2231. /* first list any other non-modifiable booleans, then modifiable ones */ 2232. for (pass = 0; pass <= 1; pass++) 2233. for (i = 0; boolopt[i].name; i++) 2234. if ((bool_p = boolopt[i].addr) != 0 && 2235. ((boolopt[i].optflags == DISP_IN_GAME && pass == 0) || 2236. (boolopt[i].optflags == SET_IN_GAME && pass == 1))) { 2237. if (bool_p == &flags.female) continue; /* obsolete */ 2238. #ifdef WIZARD 2239. if (bool_p == &iflags.sanity_check && !wizard) continue; 2240. if (bool_p == &iflags.menu_tab_sep && !wizard) continue; 2241. #endif 2242. if (is_wc_option(boolopt[i].name) && 2243. !wc_supported(boolopt[i].name)) continue; 2244. any.a_int = (pass == 0) ? 0 : i + 1; 2245. if (!iflags.menu_tab_sep) 2246. Sprintf(buf, "%s%-13s [%s]", 2247. pass == 0 ? " " : "", 2248. boolopt[i].name, *bool_p ? "true" : "false"); 2249. else 2250. Sprintf(buf, "%s [%s]", 2251. boolopt[i].name, *bool_p ? "true" : "false"); 2252. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, 2253. ATR_NONE, buf, MENU_UNSELECTED); 2254. } 2255. 2256. boolcount = i; 2257. indexoffset = boolcount; 2258. any.a_void = 0; 2259. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED); 2260. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, 2261. "Compounds (selecting will prompt for new value):", 2262. MENU_UNSELECTED); 2263. 2264. startpass = DISP_IN_GAME; 2265. endpass = SET_IN_GAME; 2266. 2267. /* spin through the options to find the biggest name 2268. and adjust the format string accordingly if needed */ 2269. biggest_name = 0; 2270. for (i = 0; compopt[i].name; i++) 2271. if (compopt[i].optflags >= startpass && compopt[i].optflags <= endpass && 2272. strlen(compopt[i].name) > (unsigned) biggest_name) 2273. biggest_name = (int) strlen(compopt[i].name); 2274. if (biggest_name > 30) biggest_name = 30; 2275. if (!iflags.menu_tab_sep) 2276. Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name); 2277. 2278. /* deliberately put `name', `role', `race', `gender' first */ 2279. doset_add_menu(tmpwin, "name", 0); 2280. doset_add_menu(tmpwin, "role", 0); 2281. doset_add_menu(tmpwin, "race", 0); 2282. doset_add_menu(tmpwin, "gender", 0); 2283. 2284. for (pass = startpass; pass <= endpass; pass++) 2285. for (i = 0; compopt[i].name; i++) 2286. if (compopt[i].optflags == pass) { 2287. if (!strcmp(compopt[i].name, "name") || 2288. !strcmp(compopt[i].name, "role") || 2289. !strcmp(compopt[i].name, "race") || 2290. !strcmp(compopt[i].name, "gender")) 2291. continue; 2292. else if (is_wc_option(compopt[i].name) && 2293. !wc_supported(compopt[i].name)) 2294. continue; 2295. else 2296. doset_add_menu(tmpwin, compopt[i].name, 2297. (pass == DISP_IN_GAME) ? 0 : indexoffset); 2298. } 2299. #ifdef PREFIXES_IN_USE 2300. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED); 2301. add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, 2302. "Variable playground locations:", MENU_UNSELECTED); 2303. for (i = 0; i < PREFIX_COUNT; i++) 2304. doset_add_menu(tmpwin, fqn_prefix_names[i], 0); 2305. #endif 2306. end_menu(tmpwin, "Set what options?"); 2307. need_redraw = FALSE; 2308. if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &pick_list)) > 0) { 2309. /* 2310. * Walk down the selection list and either invert the booleans 2311. * or prompt for new values. In most cases, call parseoptions() 2312. * to take care of options that require special attention, like 2313. * redraws. 2314. */ 2315. for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) { 2316. opt_indx = pick_list[pick_idx].item.a_int - 1; 2317. if (opt_indx < boolcount) { 2318. /* boolean option */ 2319. Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "", 2320. boolopt[opt_indx].name); 2321. parseoptions(buf, setinitial, fromfile); 2322. if (wc_supported(boolopt[opt_indx].name)) 2323. preference_update(boolopt[opt_indx].name); 2324. } else { 2325. /* compound option */ 2326. opt_indx -= boolcount; 2327. 2328. if (!special_handling(compopt[opt_indx].name, 2329. setinitial, fromfile)) { 2330. Sprintf(buf, "Set %s to what?", compopt[opt_indx].name); 2331. getlin(buf, buf2); 2332. Sprintf(buf, "%s:%s", compopt[opt_indx].name, buf2); 2333. /* pass the buck */ 2334. parseoptions(buf, setinitial, fromfile); 2335. } 2336. if (wc_supported(compopt[opt_indx].name)) 2337. preference_update(compopt[opt_indx].name); 2338. } 2339. } 2340. free((genericptr_t)pick_list); 2341. pick_list = (menu_item *)0; 2342. } 2343. 2344. destroy_nhwindow(tmpwin); 2345. if (need_redraw) 2346. (void) doredraw(); 2347. return 0; 2348. } 2349. 2350. STATIC_OVL boolean 2351. special_handling(optname, setinitial, setfromfile) 2352. const char *optname; 2353. boolean setinitial,setfromfile; 2354. { 2355. winid tmpwin; 2356. anything any; 2357. int i; 2358. char buf[BUFSZ]; 2359. boolean retval = FALSE; 2360. 2361. /* Special handling of menustyle, pickup_burden, and pickup_types, disclose options. */ 2362. if (!strcmp("menustyle", optname)) { 2363. const char *style_name; 2364. menu_item *style_pick = (menu_item *)0; 2365. tmpwin = create_nhwindow(NHW_MENU); 2366. start_menu(tmpwin); 2367. for (i = 0; i < SIZE(menutype); i++) { 2368. style_name = menutype[i]; 2369. /* note: separate `style_name' variable used 2370. to avoid an optimizer bug in VAX C V2.3 */ 2371. any.a_int = i + 1; 2372. add_menu(tmpwin, NO_GLYPH, &any, *style_name, 0, 2373. ATR_NONE, style_name, MENU_UNSELECTED); 2374. } 2375. end_menu(tmpwin, "Select menustyle:"); 2376. if (select_menu(tmpwin, PICK_ONE, &style_pick) > 0) { 2377. flags.menu_style = style_pick->item.a_int - 1; 2378. free((genericptr_t)style_pick); 2379. } 2380. destroy_nhwindow(tmpwin); 2381. retval = TRUE; 2382. } else if (!strcmp("pickup_burden", optname)) { 2383. const char *burden_name, *burden_letters = "ubsntl"; 2384. menu_item *burden_pick = (menu_item *)0; 2385. tmpwin = create_nhwindow(NHW_MENU); 2386. start_menu(tmpwin); 2387. for (i = 0; i < SIZE(burdentype); i++) { 2388. burden_name = burdentype[i]; 2389. any.a_int = i + 1; 2390. add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0, 2391. ATR_NONE, burden_name, MENU_UNSELECTED); 2392. } 2393. end_menu(tmpwin, "Select encumbrance level:"); 2394. if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) { 2395. flags.pickup_burden = burden_pick->item.a_int - 1; 2396. free((genericptr_t)burden_pick); 2397. } 2398. destroy_nhwindow(tmpwin); 2399. retval = TRUE; 2400. } else if (!strcmp("pickup_types", optname)) { 2401. /* parseoptions will prompt for the list of types */ 2402. parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile); 2403. retval = TRUE; 2404. } else if (!strcmp("disclose", optname)) { 2405. int pick_cnt, pick_idx, opt_idx; 2406. menu_item *disclosure_category_pick = (menu_item *)0; 2407. /* 2408. * The order of disclose_names[] 2409. * must correspond to disclosure_options in decl.h 2410. */ 2411. static const char *disclosure_names[] = { 2412. "inventory", "attributes", "vanquished", "genocides", "conduct" 2413. }; 2414. int disc_cat[NUM_DISCLOSURE_OPTIONS]; 2415. const char *disclosure_name; 2416. 2417. tmpwin = create_nhwindow(NHW_MENU); 2418. start_menu(tmpwin); 2419. for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) { 2420. disclosure_name = disclosure_names[i]; 2421. any.a_int = i + 1; 2422. add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0, 2423. ATR_NONE, disclosure_name, MENU_UNSELECTED); 2424. disc_cat[i] = 0; 2425. } 2426. end_menu(tmpwin, "Change which disclosure options categories:"); 2427. if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_category_pick)) > 0) { 2428. for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) { 2429. opt_idx = disclosure_category_pick[pick_idx].item.a_int - 1; 2430. disc_cat[opt_idx] = 1; 2431. } 2432. free((genericptr_t)disclosure_category_pick); 2433. disclosure_category_pick = (menu_item *)0; 2434. } 2435. destroy_nhwindow(tmpwin); 2436. 2437. for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) { 2438. if (disc_cat[i]) { 2439. char dbuf[BUFSZ]; 2440. menu_item *disclosure_option_pick = (menu_item *)0; 2441. Sprintf(dbuf, "Disclosure options for %s:", disclosure_names[i]); 2442. tmpwin = create_nhwindow(NHW_MENU); 2443. start_menu(tmpwin); 2444. any.a_char = DISCLOSE_NO_WITHOUT_PROMPT; 2445. add_menu(tmpwin, NO_GLYPH, &any, 'a', 0, 2446. ATR_NONE,"Never disclose and don't prompt", MENU_UNSELECTED); 2447. any.a_void = 0; 2448. any.a_char = DISCLOSE_YES_WITHOUT_PROMPT; 2449. add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, 2450. ATR_NONE,"Always disclose and don't prompt", MENU_UNSELECTED); 2451. any.a_void = 0; 2452. any.a_char = DISCLOSE_PROMPT_DEFAULT_NO; 2453. add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, 2454. ATR_NONE,"Prompt and default answer to \"No\"", MENU_UNSELECTED); 2455. any.a_void = 0; 2456. any.a_char = DISCLOSE_PROMPT_DEFAULT_YES; 2457. add_menu(tmpwin, NO_GLYPH, &any, 'd', 0, 2458. ATR_NONE,"Prompt and default answer to \"Yes\"", MENU_UNSELECTED); 2459. end_menu(tmpwin, dbuf); 2460. if (select_menu(tmpwin, PICK_ONE, &disclosure_option_pick) > 0) { 2461. flags.end_disclose[i] = disclosure_option_pick->item.a_char; 2462. free((genericptr_t)disclosure_option_pick); 2463. } 2464. destroy_nhwindow(tmpwin); 2465. } 2466. } 2467. retval = TRUE; 2468. } 2469. return retval; 2470. } 2471. 2472. #define rolestring(val,array,field) ((val >= 0) ? array[val].field : \ 2473. (val == ROLE_RANDOM) ? randomrole : none) 2474. 2475. /* This is ugly. We have all the option names in the compopt[] array, 2476. but we need to look at each option individually to get the value. */ 2477. STATIC_OVL const char * 2478. get_compopt_value(optname, buf) 2479. const char *optname; 2480. char *buf; 2481. { 2482. char ocl[MAXOCLASSES+1]; 2483. static const char none[] = "(none)", randomrole[] = "random", 2484. to_be_done[] = "(to be done)", 2485. defopt[] = "default", 2486. defbrief[] = "def"; 2487. int i; 2488. 2489. buf[0] = '\0'; 2490. if (!strcmp(optname,"align_message")) 2491. Sprintf(buf, "%s", iflags.wc_align_message == ALIGN_TOP ? "top" : 2492. iflags.wc_align_message == ALIGN_LEFT ? "left" : 2493. iflags.wc_align_message == ALIGN_BOTTOM ? "bottom" : 2494. iflags.wc_align_message == ALIGN_RIGHT ? "right" : 2495. defopt); 2496. else if (!strcmp(optname,"align_status")) 2497. Sprintf(buf, "%s", iflags.wc_align_status == ALIGN_TOP ? "top" : 2498. iflags.wc_align_status == ALIGN_LEFT ? "left" : 2499. iflags.wc_align_status == ALIGN_BOTTOM ? "bottom" : 2500. iflags.wc_align_status == ALIGN_RIGHT ? "right" : 2501. defopt); 2502. else if (!strcmp(optname,"align")) 2503. Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj)); 2504. else if (!strcmp(optname, "boulder")) 2505. Sprintf(buf, "%c", iflags.bouldersym ? 2506. iflags.bouldersym : oc_syms[(int)objects[BOULDER].oc_class]); 2507. else if (!strcmp(optname, "catname")) 2508. Sprintf(buf, "%s", catname[0] ? catname : none ); 2509. else if (!strcmp(optname, "disclose")) { 2510. for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) { 2511. char topt[2]; 2512. if (i) Strcat(buf," "); 2513. topt[1] = '\0'; 2514. topt[0] = flags.end_disclose[i]; 2515. Strcat(buf, topt); 2516. topt[0] = disclosure_options[i]; 2517. Strcat(buf, topt); 2518. } 2519. } 2520. else if (!strcmp(optname, "dogname")) 2521. Sprintf(buf, "%s", dogname[0] ? dogname : none ); 2522. else if (!strcmp(optname, "dungeon")) 2523. Sprintf(buf, "%s", to_be_done); 2524. else if (!strcmp(optname, "effects")) 2525. Sprintf(buf, "%s", to_be_done); 2526. else if (!strcmp(optname, "font_map")) 2527. Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt); 2528. else if (!strcmp(optname, "font_message")) 2529. Sprintf(buf, "%s", iflags.wc_font_message ? iflags.wc_font_message : defopt); 2530. else if (!strcmp(optname, "font_status")) 2531. Sprintf(buf, "%s", iflags.wc_font_status ? iflags.wc_font_status : defopt); 2532. else if (!strcmp(optname, "font_menu")) 2533. Sprintf(buf, "%s", iflags.wc_font_menu ? iflags.wc_font_menu : defopt); 2534. else if (!strcmp(optname, "font_text")) 2535. Sprintf(buf, "%s", iflags.wc_font_text ? iflags.wc_font_text : defopt); 2536. else if (!strcmp(optname, "font_size_map")) { 2537. if (iflags.wc_fontsiz_map) Sprintf(buf, "%d", iflags.wc_fontsiz_map); 2538. else Strcpy(buf, defopt); 2539. } 2540. else if (!strcmp(optname, "font_size_message")) { 2541. if (iflags.wc_fontsiz_message) Sprintf(buf, "%d", 2542. iflags.wc_fontsiz_message); 2543. else Strcpy(buf, defopt); 2544. } 2545. else if (!strcmp(optname, "font_size_status")) { 2546. if (iflags.wc_fontsiz_status) Sprintf(buf, "%d", iflags.wc_fontsiz_status); 2547. else Strcpy(buf, defopt); 2548. } 2549. else if (!strcmp(optname, "font_size_menu")) { 2550. if (iflags.wc_fontsiz_menu) Sprintf(buf, "%d", iflags.wc_fontsiz_menu); 2551. else Strcpy(buf, defopt); 2552. } 2553. else if (!strcmp(optname, "font_size_text")) { 2554. if (iflags.wc_fontsiz_text) Sprintf(buf, "%d",iflags.wc_fontsiz_text); 2555. else Strcpy(buf, defopt); 2556. } 2557. else if (!strcmp(optname, "fruit")) 2558. Sprintf(buf, "%s", pl_fruit); 2559. else if (!strcmp(optname, "gender")) 2560. Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj)); 2561. else if (!strcmp(optname, "horsename")) 2562. Sprintf(buf, "%s", horsename[0] ? horsename : none); 2563. else if (!strcmp(optname, "map_mode")) 2564. Sprintf(buf, "%s", 2565. iflags.wc_map_mode == MAP_MODE_TILES ? "tiles" : 2566. iflags.wc_map_mode == MAP_MODE_ASCII4x6 ? "ascii4x6" : 2567. iflags.wc_map_mode == MAP_MODE_ASCII6x8 ? "ascii6x8" : 2568. iflags.wc_map_mode == MAP_MODE_ASCII8x8 ? "ascii8x8" : 2569. iflags.wc_map_mode == MAP_MODE_ASCII16x8 ? "ascii16x8" : 2570. iflags.wc_map_mode == MAP_MODE_ASCII7x12 ? "ascii7x12" : 2571. iflags.wc_map_mode == MAP_MODE_ASCII8x12 ? "ascii8x12" : 2572. iflags.wc_map_mode == MAP_MODE_ASCII16x12 ? "ascii16x12" : 2573. iflags.wc_map_mode == MAP_MODE_ASCII12x16 ? "ascii12x16" : 2574. iflags.wc_map_mode == MAP_MODE_ASCII10x18 ? "ascii10x18" : 2575. iflags.wc_map_mode == MAP_MODE_ASCII_FIT_TO_SCREEN ? 2576. "fit_to_screen" : defopt); 2577. else if (!strcmp(optname, "menustyle")) 2578. Sprintf(buf, "%s", menutype[(int)flags.menu_style] ); 2579. else if (!strcmp(optname, "menu_deselect_all")) 2580. Sprintf(buf, "%s", to_be_done); 2581. else if (!strcmp(optname, "menu_deselect_page")) 2582. Sprintf(buf, "%s", to_be_done); 2583. else if (!strcmp(optname, "menu_first_page")) 2584. Sprintf(buf, "%s", to_be_done); 2585. else if (!strcmp(optname, "menu_invert_all")) 2586. Sprintf(buf, "%s", to_be_done); 2587. else if (!strcmp(optname, "menu_invert_page")) 2588. Sprintf(buf, "%s", to_be_done); 2589. else if (!strcmp(optname, "menu_last_page")) 2590. Sprintf(buf, "%s", to_be_done); 2591. else if (!strcmp(optname, "menu_next_page")) 2592. Sprintf(buf, "%s", to_be_done); 2593. else if (!strcmp(optname, "menu_previous_page")) 2594. Sprintf(buf, "%s", to_be_done); 2595. else if (!strcmp(optname, "menu_search")) 2596. Sprintf(buf, "%s", to_be_done); 2597. else if (!strcmp(optname, "menu_select_all")) 2598. Sprintf(buf, "%s", to_be_done); 2599. else if (!strcmp(optname, "menu_select_page")) 2600. Sprintf(buf, "%s", to_be_done); 2601. else if (!strcmp(optname, "monsters")) 2602. Sprintf(buf, "%s", to_be_done); 2603. else if (!strcmp(optname, "msghistory")) 2604. Sprintf(buf, "%u", iflags.msg_history); 2605. else if (!strcmp(optname, "name")) 2606. Sprintf(buf, "%s", plname); 2607. else if (!strcmp(optname, "objects")) 2608. Sprintf(buf, "%s", to_be_done); 2609. else if (!strcmp(optname, "packorder")) { 2610. oc_to_str(flags.inv_order, ocl); 2611. Sprintf(buf, "%s", ocl); 2612. } 2613. #ifdef CHANGE_COLOR 2614. else if (!strcmp(optname, "palette")) 2615. Sprintf(buf, "%s", get_color_string()); 2616. #endif 2617. else if (!strcmp(optname, "pettype")) 2618. Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat" : 2619. (preferred_pet == 'd') ? "dog" : 2620. (preferred_pet == 'n') ? "none" : "random"); 2621. else if (!strcmp(optname, "pickup_burden")) 2622. Sprintf(buf, "%s", burdentype[flags.pickup_burden] ); 2623. else if (!strcmp(optname, "pickup_types")) { 2624. oc_to_str(flags.pickup_types, ocl); 2625. Sprintf(buf, "%s", ocl[0] ? ocl : "all" ); 2626. } 2627. else if (!strcmp(optname, "race")) 2628. Sprintf(buf, "%s", rolestring(flags.initrace, races, noun)); 2629. else if (!strcmp(optname, "role")) 2630. Sprintf(buf, "%s", rolestring(flags.initrole, roles, name.m)); 2631. else if (!strcmp(optname, "scores")) { 2632. Sprintf(buf, "%d top/%d around%s", flags.end_top, 2633. flags.end_around, flags.end_own ? "/own" : ""); 2634. } 2635. else if (!strcmp(optname, "scroll_margin")) { 2636. if (iflags.wc_scroll_margin) Sprintf(buf, "%d",iflags.wc_scroll_margin); 2637. else Strcpy(buf, defopt); 2638. } 2639. else if (!strcmp(optname, "player_selection")) 2640. Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog"); 2641. #ifdef MSDOS 2642. else if (!strcmp(optname, "soundcard")) 2643. Sprintf(buf, "%s", to_be_done); 2644. #endif 2645. else if (!strcmp(optname, "suppress_alert")) { 2646. if (flags.suppress_alert == 0L) 2647. Strcpy(buf, none); 2648. else 2649. Sprintf(buf, "%lu.%lu.%lu", 2650. FEATURE_NOTICE_VER_MAJ, 2651. FEATURE_NOTICE_VER_MIN, 2652. FEATURE_NOTICE_VER_PATCH); 2653. } 2654. else if (!strcmp(optname, "tile_file")) 2655. Sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt); 2656. else if (!strcmp(optname, "tile_height")) { 2657. if (iflags.wc_tile_height) Sprintf(buf, "%d",iflags.wc_tile_height); 2658. else Strcpy(buf, defopt); 2659. } 2660. else if (!strcmp(optname, "tile_width")) { 2661. if (iflags.wc_tile_width) Sprintf(buf, "%d",iflags.wc_tile_width); 2662. else Strcpy(buf, defopt); 2663. } 2664. else if (!strcmp(optname, "traps")) 2665. Sprintf(buf, "%s", to_be_done); 2666. else if (!strcmp(optname, "vary_msgcount")) { 2667. if (iflags.wc_vary_msgcount) Sprintf(buf, "%d",iflags.wc_vary_msgcount); 2668. else Strcpy(buf, defopt); 2669. } 2670. #ifdef MSDOS 2671. else if (!strcmp(optname, "video")) 2672. Sprintf(buf, "%s", to_be_done); 2673. #endif 2674. #ifdef VIDEOSHADES 2675. else if (!strcmp(optname, "videoshades")) 2676. Sprintf(buf, "%s-%s-%s", shade[0],shade[1],shade[2]); 2677. else if (!strcmp(optname, "videocolors")) 2678. Sprintf(buf, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", 2679. ttycolors[CLR_RED], ttycolors[CLR_GREEN], 2680. ttycolors[CLR_BROWN], ttycolors[CLR_BLUE], 2681. ttycolors[CLR_MAGENTA], ttycolors[CLR_CYAN], 2682. ttycolors[CLR_ORANGE], ttycolors[CLR_BRIGHT_GREEN], 2683. ttycolors[CLR_YELLOW], ttycolors[CLR_BRIGHT_BLUE], 2684. ttycolors[CLR_BRIGHT_MAGENTA], 2685. ttycolors[CLR_BRIGHT_CYAN]); 2686. #endif /* VIDEOSHADES */ 2687. else if (!strcmp(optname, "windowtype")) 2688. Sprintf(buf, "%s", windowprocs.name); 2689. else if (!strcmp(optname, "windowcolors")) 2690. Sprintf(buf, "%s/%s %s/%s %s/%s %s/%s", 2691. iflags.wc_foregrnd_menu ? iflags.wc_foregrnd_menu : defbrief, 2692. iflags.wc_backgrnd_menu ? iflags.wc_backgrnd_menu : defbrief, 2693. iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message : defbrief, 2694. iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message : defbrief, 2695. iflags.wc_foregrnd_status ? iflags.wc_foregrnd_status : defbrief, 2696. iflags.wc_backgrnd_status ? iflags.wc_backgrnd_status : defbrief, 2697. iflags.wc_foregrnd_text ? iflags.wc_foregrnd_text : defbrief, 2698. iflags.wc_backgrnd_text ? iflags.wc_backgrnd_text : defbrief); 2699. #ifdef PREFIXES_IN_USE 2700. else { 2701. for (i = 0; i < PREFIX_COUNT; ++i) 2702. if (!strcmp(optname, fqn_prefix_names[i]) && fqn_prefix[i]) 2703. Sprintf(buf, "%s", fqn_prefix[i]); 2704. } 2705. #endif 2706. 2707. if (buf[0]) return buf; 2708. else return "unknown"; 2709. } 2710. 2711. int 2712. dotogglepickup() 2713. { 2714. char buf[BUFSZ], ocl[MAXOCLASSES+1]; 2715. 2716. flags.pickup = !flags.pickup; 2717. if (flags.pickup) { 2718. oc_to_str(flags.pickup_types, ocl); 2719. Sprintf(buf, "ON, for %s objects", ocl[0] ? ocl : "all"); 2720. } else { 2721. Strcpy(buf, "OFF"); 2722. } 2723. pline("Autopickup: %s.", buf); 2724. return 0; 2725. } 2726. 2727. /* data for option_help() */ 2728. static const char *opt_intro[] = { 2729. "", 2730. " NetHack Options Help:", 2731. "", 2732. #define CONFIG_SLOT 3 /* fill in next value at run-time */ 2733. (char *)0, 2734. #if !defined(MICRO) && !defined(MAC) 2735. "or use `NETHACKOPTIONS=\"\"' in your environment", 2736. #endif 2737. "( is a list of options separated by commas)", 2738. #ifdef VMS 2739. "-- for example, $ DEFINE NETHACKOPTIONS \"noautopickup,fruit:kumquat\"", 2740. #endif 2741. "or press \"O\" while playing and use the menu.", 2742. "", 2743. "Boolean options (which can be negated by prefixing them with '!' or \"no\"):", 2744. (char *)0 2745. }; 2746. 2747. static const char *opt_epilog[] = { 2748. "", 2749. "Some of the options can be set only before the game is started; those", 2750. "items will not be selectable in the 'O' command's menu.", 2751. (char *)0 2752. }; 2753. 2754. void 2755. option_help() 2756. { 2757. char buf[BUFSZ], buf2[BUFSZ]; 2758. register int i; 2759. winid datawin; 2760. 2761. datawin = create_nhwindow(NHW_TEXT); 2762. Sprintf(buf, "Set options as OPTIONS= in %s", configfile); 2763. opt_intro[CONFIG_SLOT] = (const char *) buf; 2764. for (i = 0; opt_intro[i]; i++) 2765. putstr(datawin, 0, opt_intro[i]); 2766. 2767. /* Boolean options */ 2768. for (i = 0; boolopt[i].name; i++) { 2769. if (boolopt[i].addr) { 2770. #ifdef WIZARD 2771. if (boolopt[i].addr == &iflags.sanity_check && !wizard) continue; 2772. if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard) continue; 2773. #endif 2774. next_opt(datawin, boolopt[i].name); 2775. } 2776. } 2777. next_opt(datawin, ""); 2778. 2779. /* Compound options */ 2780. putstr(datawin, 0, "Compound options:"); 2781. for (i = 0; compopt[i].name; i++) { 2782. Sprintf(buf2, "`%s'", compopt[i].name); 2783. Sprintf(buf, "%-20s - %s%c", buf2, compopt[i].descr, 2784. compopt[i+1].name ? ',' : '.'); 2785. putstr(datawin, 0, buf); 2786. } 2787. 2788. for (i = 0; opt_epilog[i]; i++) 2789. putstr(datawin, 0, opt_epilog[i]); 2790. 2791. display_nhwindow(datawin, FALSE); 2792. destroy_nhwindow(datawin); 2793. return; 2794. } 2795. 2796. /* 2797. * prints the next boolean option, on the same line if possible, on a new 2798. * line if not. End with next_opt(""). 2799. */ 2800. void 2801. next_opt(datawin, str) 2802. winid datawin; 2803. const char *str; 2804. { 2805. static char *buf = 0; 2806. int i; 2807. char *s; 2808. 2809. if (!buf) *(buf = (char *)alloc(BUFSZ)) = '\0'; 2810. 2811. if (!*str) { 2812. s = eos(buf); 2813. if (s > &buf[1] && s[-2] == ',') 2814. Strcpy(s - 2, "."); /* replace last ", " */ 2815. i = COLNO; /* (greater than COLNO - 2) */ 2816. } else { 2817. i = strlen(buf) + strlen(str) + 2; 2818. } 2819. 2820. if (i > COLNO - 2) { /* rule of thumb */ 2821. putstr(datawin, 0, buf); 2822. buf[0] = 0; 2823. } 2824. if (*str) { 2825. Strcat(buf, str); 2826. Strcat(buf, ", "); 2827. } else { 2828. putstr(datawin, 0, str); 2829. free(buf), buf = 0; 2830. } 2831. return; 2832. } 2833. 2834. /* Returns the fid of the fruit type; if that type already exists, it 2835. * returns the fid of that one; if it does not exist, it adds a new fruit 2836. * type to the chain and returns the new one. 2837. */ 2838. int 2839. fruitadd(str) 2840. char *str; 2841. { 2842. register int i; 2843. register struct fruit *f; 2844. struct fruit *lastf = 0; 2845. int highest_fruit_id = 0; 2846. char buf[PL_FSIZ]; 2847. boolean user_specified = (str == pl_fruit); 2848. /* if not user-specified, then it's a fruit name for a fruit on 2849. * a bones level... 2850. */ 2851. 2852. /* Note: every fruit has an id (spe for fruit objects) of at least 2853. * 1; 0 is an error. 2854. */ 2855. if (user_specified) { 2856. /* disallow naming after other foods (since it'd be impossible 2857. * to tell the difference) 2858. */ 2859. 2860. boolean found = FALSE, numeric = FALSE; 2861. 2862. for (i = bases[FOOD_CLASS]; objects[i].oc_class == FOOD_CLASS; 2863. i++) { 2864. if (!strcmp(OBJ_NAME(objects[i]), pl_fruit)) { 2865. found = TRUE; 2866. break; 2867. } 2868. } 2869. { 2870. char *c; 2871. 2872. c = pl_fruit; 2873. 2874. for(c = pl_fruit; *c >= '0' && *c <= '9'; c++) 2875. ; 2876. if (isspace(*c) || *c == 0) numeric = TRUE; 2877. } 2878. if (found || numeric || 2879. !strncmp(str, "cursed ", 7) || 2880. !strncmp(str, "uncursed ", 9) || 2881. !strncmp(str, "blessed ", 8) || 2882. !strncmp(str, "partly eaten ", 13) || 2883. (!strncmp(str, "tin of ", 7) && 2884. (!strcmp(str+7, "spinach") || 2885. name_to_mon(str+7) >= LOW_PM)) || 2886. !strcmp(str, "empty tin") || 2887. ((!strncmp(eos(str)-7," corpse",7) || 2888. !strncmp(eos(str)-4, " egg",4)) && 2889. name_to_mon(str) >= LOW_PM)) 2890. { 2891. Strcpy(buf, pl_fruit); 2892. Strcpy(pl_fruit, "candied "); 2893. nmcpy(pl_fruit+8, buf, PL_FSIZ-8); 2894. } 2895. } 2896. for(f=ffruit; f; f = f->nextf) { 2897. lastf = f; 2898. if(f->fid > highest_fruit_id) highest_fruit_id = f->fid; 2899. if(!strncmp(str, f->fname, PL_FSIZ)) 2900. goto nonew; 2901. } 2902. /* if adding another fruit would overflow spe, use a random 2903. fruit instead... we've got a lot to choose from. */ 2904. if (highest_fruit_id >= 127) return rnd(127); 2905. highest_fruit_id++; 2906. f = newfruit(); 2907. if (ffruit) lastf->nextf = f; 2908. else ffruit = f; 2909. Strcpy(f->fname, str); 2910. f->fid = highest_fruit_id; 2911. f->nextf = 0; 2912. nonew: 2913. if (user_specified) current_fruit = highest_fruit_id; 2914. return f->fid; 2915. } 2916. 2917. /* 2918. * This is a somewhat generic menu for taking a list of NetHack style 2919. * class choices and presenting them via a description 2920. * rather than the traditional NetHack characters. 2921. * (Benefits users whose first exposure to NetHack is via tiles). 2922. * 2923. * prompt 2924. * The title at the top of the menu. 2925. * 2926. * category: 0 = monster class 2927. * 1 = object class 2928. * 2929. * way 2930. * FALSE = PICK_ONE, TRUE = PICK_ANY 2931. * 2932. * class_list 2933. * a null terminated string containing the list of choices. 2934. * 2935. * class_selection 2936. * a null terminated string containing the selected characters. 2937. * 2938. * Returns number selected. 2939. */ 2940. int 2941. choose_classes_menu(prompt, category, way, class_list, class_select) 2942. const char *prompt; 2943. int category; 2944. boolean way; 2945. char *class_list; 2946. char *class_select; 2947. { 2948. menu_item *pick_list = (menu_item *)0; 2949. winid win; 2950. anything any; 2951. char buf[BUFSZ]; 2952. int i, n; 2953. int ret; 2954. int next_accelerator, accelerator; 2955. 2956. if (class_list == (char *)0 || class_select == (char *)0) return 0; 2957. accelerator = 0; 2958. next_accelerator = 'a'; 2959. any.a_void = 0; 2960. win = create_nhwindow(NHW_MENU); 2961. start_menu(win); 2962. while (*class_list) { 2963. const char *text; 2964. boolean selected; 2965. 2966. text = (char *)0; 2967. selected = FALSE; 2968. switch (category) { 2969. case 0: 2970. text = monexplain[def_char_to_monclass(*class_list)]; 2971. accelerator = *class_list; 2972. Sprintf(buf, "%s", text); 2973. break; 2974. case 1: 2975. text = objexplain[def_char_to_objclass(*class_list)]; 2976. accelerator = next_accelerator; 2977. Sprintf(buf, "%c %s", *class_list, text); 2978. break; 2979. default: 2980. impossible("choose_classes_menu: invalid category %d", 2981. category); 2982. } 2983. if (way && *class_select) { /* Selections there already */ 2984. if (index(class_select, *class_list)) { 2985. selected = TRUE; 2986. } 2987. } 2988. any.a_int = *class_list; 2989. add_menu(win, NO_GLYPH, &any, accelerator, 2990. category ? *class_list : 0, 2991. ATR_NONE, buf, selected); 2992. ++class_list; 2993. if (category > 0) { 2994. ++next_accelerator; 2995. if (next_accelerator == ('z' + 1)) next_accelerator = 'A'; 2996. if (next_accelerator == ('Z' + 1)) break; 2997. } 2998. } 2999. end_menu(win, prompt); 3000. n = select_menu(win, way ? PICK_ANY : PICK_ONE, &pick_list); 3001. destroy_nhwindow(win); 3002. if (n > 0) { 3003. for (i = 0; i < n; ++i) 3004. *class_select++ = (char)pick_list[i].item.a_int; 3005. free((genericptr_t)pick_list); 3006. ret = n; 3007. } else if (n == -1) { 3008. class_select = eos(class_select); 3009. ret = -1; 3010. } else 3011. ret = 0; 3012. *class_select = '\0'; 3013. return ret; 3014. } 3015. 3016. struct wc_Opt wc_options[] = { 3017. {"ascii_map", WC_ASCII_MAP}, 3018. {"color", WC_COLOR}, 3019. {"eight_bit_tty", WC_EIGHT_BIT_IN}, 3020. {"hilite_pet", WC_HILITE_PET}, 3021. {"large_font", WC_LARGE_FONT}, /* now obsolete */ 3022. {"popup_dialog", WC_POPUP_DIALOG}, 3023. {"preload_tiles", WC_PRELOAD_TILES}, 3024. {"tiled_map", WC_TILED_MAP}, 3025. {"tile_file", WC_TILE_FILE}, 3026. {"tile_width", WC_TILE_WIDTH}, 3027. {"tile_height", WC_TILE_HEIGHT}, 3028. {"use_inverse", WC_INVERSE}, 3029. {"align_message", WC_ALIGN_MESSAGE}, 3030. {"align_status", WC_ALIGN_STATUS}, 3031. {"font_map", WC_FONT_MAP}, 3032. {"font_menu", WC_FONT_MENU}, 3033. {"font_message",WC_FONT_MESSAGE}, 3034. #if 0 3035. {"perm_invent",WC_PERM_INVENT}, 3036. #endif 3037. {"font_size_map", WC_FONTSIZ_MAP}, 3038. {"font_size_menu", WC_FONTSIZ_MENU}, 3039. {"font_size_message", WC_FONTSIZ_MESSAGE}, 3040. {"font_size_status", WC_FONTSIZ_STATUS}, 3041. {"font_size_text", WC_FONTSIZ_TEXT}, 3042. {"font_status", WC_FONT_STATUS}, 3043. {"font_text", WC_FONT_TEXT}, 3044. {"map_mode", WC_MAP_MODE}, 3045. {"scroll_margin", WC_SCROLL_MARGIN}, 3046. {"vary_msgcount",WC_VARY_MSGCOUNT}, 3047. {(char *)0, 0L} 3048. }; 3049. 3050. 3051. /* 3052. * If a port wants to change or ensure that the 3053. * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is 3054. * correct (for controlling its display in the option menu) call 3055. * set_option_mod_status() 3056. * with the second argument of 0,2, or 3 respectively. 3057. */ 3058. void 3059. set_option_mod_status(optnam, status) 3060. char *optnam; 3061. int status; 3062. { 3063. int k; 3064. if (status < SET_IN_FILE || status > SET_IN_GAME) { 3065. impossible("set_option_mod_status: status out of range %d.", status); 3066. return; 3067. } 3068. for (k = 0; boolopt[k].name; k++) { 3069. if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) { 3070. boolopt[k].optflags = status; 3071. return; 3072. } 3073. } 3074. for (k = 0; compopt[k].name; k++) { 3075. if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) { 3076. compopt[k].optflags = status; 3077. return; 3078. } 3079. } 3080. } 3081. 3082. /* 3083. * You can set several wc_options in one call to 3084. * set_wc_option_mod_status() by setting 3085. * the appropriate bits for each option that you 3086. * are setting in the optmask argument 3087. * prior to calling. 3088. * example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN, SET_IN_GAME); 3089. */ 3090. void 3091. set_wc_option_mod_status(optmask, status) 3092. unsigned long optmask; 3093. int status; 3094. { 3095. int k = 0; 3096. if (status < SET_IN_FILE || status > SET_IN_GAME) { 3097. impossible("set_option_mod_status: status out of range %d.", status); 3098. return; 3099. } 3100. while (wc_options[k].wc_name) { 3101. if (optmask & wc_options[k].wc_bit) { 3102. set_option_mod_status(wc_options[k].wc_name, status); 3103. } 3104. k++; 3105. } 3106. } 3107. 3108. STATIC_OVL boolean 3109. is_wc_option(optnam) 3110. const char *optnam; 3111. { 3112. int k = 0; 3113. while (wc_options[k].wc_name) { 3114. if (strcmp(wc_options[k].wc_name, optnam) == 0) 3115. return TRUE; 3116. k++; 3117. } 3118. return FALSE; 3119. } 3120. 3121. STATIC_OVL boolean 3122. wc_supported(optnam) 3123. const char *optnam; 3124. { 3125. int k = 0; 3126. while (wc_options[k].wc_name) { 3127. if (!strcmp(wc_options[k].wc_name, optnam) && 3128. (windowprocs.wincap & wc_options[k].wc_bit)) 3129. return TRUE; 3130. k++; 3131. } 3132. return FALSE; 3133. } 3134. 3135. STATIC_OVL void 3136. wc_set_font_name(wtype, fontname) 3137. int wtype; 3138. char *fontname; 3139. { 3140. char **fn = (char **)0; 3141. if (!fontname) return; 3142. switch(wtype) { 3143. case NHW_MAP: 3144. fn = &iflags.wc_font_map; 3145. break; 3146. case NHW_MESSAGE: 3147. fn = &iflags.wc_font_message; 3148. break; 3149. case NHW_TEXT: 3150. fn = &iflags.wc_font_text; 3151. break; 3152. case NHW_MENU: 3153. fn = &iflags.wc_font_menu; 3154. break; 3155. case NHW_STATUS: 3156. fn = &iflags.wc_font_status; 3157. break; 3158. default: 3159. return; 3160. } 3161. if (fn) { 3162. if (*fn) free(*fn); 3163. *fn = (char *)alloc(strlen(fontname) + 1); 3164. Strcpy(*fn, fontname); 3165. } 3166. return; 3167. } 3168. 3169. STATIC_OVL int 3170. wc_set_window_colors(op) 3171. char *op; 3172. { 3173. /* syntax: 3174. * menu white/black message green/yellow status white/blue text white/black 3175. */ 3176. 3177. int j; 3178. char buf[BUFSZ]; 3179. char *wn, *tfg, *tbg, *newop; 3180. static char *wnames[] = {"menu", "message", "status", "text"}; 3181. static char *shortnames[] = {"mnu", "msg", "sts", "txt"}; 3182. static char **fgp[] = { 3183. &iflags.wc_foregrnd_menu, 3184. &iflags.wc_foregrnd_message, 3185. &iflags.wc_foregrnd_status, 3186. &iflags.wc_foregrnd_text 3187. }; 3188. static char **bgp[] = { 3189. &iflags.wc_backgrnd_menu, 3190. &iflags.wc_backgrnd_message, 3191. &iflags.wc_backgrnd_status, 3192. &iflags.wc_backgrnd_text 3193. }; 3194. 3195. Strcpy(buf, op); 3196. newop = mungspaces(buf); 3197. while (newop && *newop) { 3198. 3199. wn = tfg = tbg = (char *)0; 3200. 3201. /* until first non-space in case there's leading spaces - before colorname*/ 3202. while(*newop && isspace(*newop)) newop++; 3203. if (*newop) wn = newop; 3204. else return 0; 3205. 3206. /* until first space - colorname*/ 3207. while(*newop && !isspace(*newop)) newop++; 3208. if (*newop) *newop = '\0'; 3209. else return 0; 3210. newop++; 3211. 3212. /* until first non-space - before foreground*/ 3213. while(*newop && isspace(*newop)) newop++; 3214. if (*newop) tfg = newop; 3215. else return 0; 3216. 3217. /* until slash - foreground */ 3218. while(*newop && *newop != '/') newop++; 3219. if (*newop) *newop = '\0'; 3220. else return 0; 3221. newop++; 3222. 3223. /* until first non-space (in case there's leading space after slash) - before background */ 3224. while(*newop && isspace(*newop)) newop++; 3225. if (*newop) tbg = newop; 3226. else return 0; 3227. 3228. /* until first space - background */ 3229. while(*newop && !isspace(*newop)) newop++; 3230. if (*newop) *newop++ = '\0'; 3231. 3232. for (j = 0; j < 4; ++j) { 3233. if (!strcmpi(wn, wnames[j]) || 3234. !strcmpi(wn, shortnames[j])) { 3235. if (tfg && !strstri(tfg, " ")) { 3236. if (*fgp[j]) free(*fgp[j]); 3237. *fgp[j] = (char *)alloc(strlen(tfg) + 1); 3238. Strcpy(*fgp[j], tfg); 3239. } 3240. if (tbg && !strstri(tbg, " ")) { 3241. if (*bgp[j]) free(*bgp[j]); 3242. *bgp[j] = (char *)alloc(strlen(tbg) + 1); 3243. Strcpy(*bgp[j], tbg); 3244. } 3245. break; 3246. } 3247. } 3248. } 3249. return 1; 3250. } 3251. 3252. #endif /* OPTION_LISTS_ONLY */ 3253. 3254. /*options.c*/
|