Source:NetHack 3.4.0/options.c
Jump to navigation
Jump to search
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
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.
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 <ctype.h> 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 <ret>. 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. * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (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 = '\n'; break; 631. case 't': cval = '\t'; break; 632. case 'b': cval = '\b'; break; 633. case 'r': cval = '\r'; 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. "\n%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. "\nWarning - Boolean option specified multiple times: %s.\n", 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. "\nWarning - compound option specified multiple times: %s.\n", 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 == '\r' || c == '\n' || 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\t[%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\t[%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=\"<options>\"' in your environment", 2736. #endif 2737. "(<options> 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=<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*/