Source:NetHack 3.0.0/options.c
Revision as of 05:10, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/options.c moved to Source:NetHack 3.0.0/options.c: Robot: moved page)
Below is the full text to options.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.0 88/11/09 2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "hack.h" 6. static boolean set_order; 7. 8. static void nmcpy(); 9. 10. void 11. initoptions() 12. { 13. register char *opts; 14. 15. flags.time = flags.nonews = flags.notombstone = flags.end_own = 16. flags.standout = flags.nonull = flags.ignintr = FALSE; 17. flags.no_rest_on_space = flags.invlet_constant = TRUE; 18. flags.end_top = 5; 19. flags.end_around = 4; 20. flags.female = FALSE; /* players are usually male */ 21. flags.sortpack = TRUE; 22. flags.soundok = TRUE; 23. flags.verbose = TRUE; 24. flags.confirm = TRUE; 25. flags.safe_dog = TRUE; 26. flags.silent = flags.pickup = TRUE; 27. nmcpy(pl_fruit, objects[SLIME_MOLD].oc_name, PL_FSIZ); 28. flags.num_pad = FALSE; 29. #ifdef MSDOS 30. #ifdef DECRAINBOW 31. flags.DECRainbow = FALSE; 32. #endif 33. #ifdef DGK 34. flags.IBMBIOS = 35. flags.rawio = FALSE; 36. #endif 37. read_config_file(); 38. #endif /* MSDOS */ 39. if(opts = getenv("NETHACKOPTIONS")) 40. parseoptions(opts,TRUE); 41. (void)fruitadd(pl_fruit); 42. objects[SLIME_MOLD].oc_name = "\033"; 43. /* Put something untypable in there */ 44. /* We cannot just use NULL because that marks the end of objects */ 45. } 46. 47. static void 48. nmcpy(dest, source, maxlen) 49. char *dest, *source; 50. int maxlen; 51. { 52. char *cs, *cd; 53. int count; 54. 55. cd = dest; 56. cs = source; 57. for(count = 1; count < maxlen; count++) { 58. if(*cs == ',' || *cs == '\0') break; /*exit on \0 terminator*/ 59. *cd++ = *cs++; 60. } 61. *cd = 0; 62. } 63. 64. /* 65. * escapes: escape expansion for showsyms. C-style escapes understood include 66. * \n, \b, \t, \r, \xnnn (hex), \onnn (octal), \nnn (decimal). The ^-prefix 67. * for control characters is also understood, and \[mM] followed by any of the 68. * previous forms or by a character has the effect of 'meta'-ing the value (so 69. * that the alternate character set will be enabled). 70. */ 71. void 72. escapes(cp, tp) 73. char *cp, *tp; 74. { 75. while (*cp) 76. { 77. int cval = 0, meta = 0; 78. 79. if (*cp == '\\' && index("mM", cp[1])) { 80. meta = 1; 81. cp += 2; 82. } 83. if (*cp == '\\' && index("0123456789xXoO", cp[1])) 84. { 85. char *dp, *hex = "00112233445566778899aAbBcCdDeEfF"; 86. int dcount = 0; 87. 88. cp++; 89. if (*cp == 'x' || *cp == 'X') 90. for (++cp; (dp = index(hex, *cp)) && (dcount++ < 2); cp++) 91. cval = (cval * 16) + (dp - hex) / 2; 92. else if (*cp == 'o' || *cp == 'O') 93. for (++cp; (index("01234567",*cp)) && (dcount++ < 3); cp++) 94. cval = (cval * 8) + (*cp - '0'); 95. else 96. for (; (index("0123456789",*cp)) && (dcount++ < 3); cp++) 97. cval = (cval * 10) + (*cp - '0'); 98. } 99. else if (*cp == '\\') /* C-style character escapes */ 100. { 101. switch (*++cp) 102. { 103. case '\\': cval = '\\'; break; 104. case 'n': cval = '\n'; break; 105. case 't': cval = '\t'; break; 106. case 'b': cval = '\b'; break; 107. case 'r': cval = '\r'; break; 108. default: cval = *cp; 109. } 110. cp++; 111. } 112. else if (*cp == '^') /* expand control-character syntax */ 113. { 114. cval = (*++cp & 0x1f); 115. cp++; 116. } 117. else 118. cval = *cp++; 119. if (meta) 120. cval |= 0x80; 121. *tp++ = cval; 122. } 123. *tp = '\0'; 124. } 125. 126. void 127. parseoptions(opts, from_env) 128. register char *opts; 129. boolean from_env; 130. { 131. register char *op; 132. /* 133. register char *op2; 134. */ 135. unsigned num; 136. boolean negated; 137. 138. if(op = index(opts, ',')) { 139. *op++ = 0; 140. parseoptions(op, from_env); 141. } 142. /* 143. if(op = index(opts, ' ')) { 144. op2 = op; 145. while(*op++) 146. if(*op != ' ') *op2++ = *op; 147. } 148. */ 149. if(!*opts) return; 150. negated = FALSE; 151. while((*opts == '!') || !strncmp(opts, "no", 2)) { 152. if(*opts == '!') opts++; else opts += 2; 153. negated = !negated; 154. } 155. 156. #ifndef MSDOS 157. if (!strncmp(opts, "standout", 4)) { 158. flags.standout = !negated; 159. return; 160. } 161. 162. if (!strncmp(opts, "null", 4)) { 163. flags.nonull = negated; 164. return; 165. } 166. #endif 167. 168. if (!strncmp(opts, "ignintr", 3)) { 169. flags.ignintr = !negated; 170. return; 171. } 172. 173. if (!strncmp(opts, "tombstone", 4)) { 174. flags.notombstone = negated; 175. return; 176. } 177. 178. #ifdef NEWS 179. if (!strncmp(opts, "news", 4)) { 180. flags.nonews = negated; 181. return; 182. } 183. #endif 184. 185. if (!strncmp(opts, "confirm", 4)) { 186. flags.confirm = !negated; 187. return; 188. } 189. if (!strncmp(opts, "safe", 4)) { 190. flags.safe_dog = !negated; 191. return; 192. } 193. 194. if (!strncmp(opts, "silent", 4)) { 195. flags.silent = !negated; 196. return; 197. } 198. 199. if (!strncmp(opts, "verbose", 4)) { 200. flags.verbose = !negated; 201. return; 202. } 203. 204. if (!strncmp(opts, "pickup", 4)) { 205. flags.pickup = !negated; 206. return; 207. } 208. 209. if (!strncmp(opts, "number_pad", 4)) { 210. flags.num_pad = !negated; 211. return; 212. } 213. 214. #ifdef DGK 215. if (!strncmp(opts, "IBM", 3)) { 216. flags.IBMBIOS = !negated; 217. return; 218. } 219. 220. if (!strncmp(opts, "rawio", 4)) { 221. if (from_env) 222. flags.rawio = !negated; 223. else 224. pline("\"rawio\" settable only from %s.", configfile); 225. return; 226. } 227. 228. #ifdef DECRAINBOW 229. if (!strncmp(opts, "DEC", 3)) { 230. flags.DECRainbow = !negated; 231. return; 232. } 233. #endif /* DECRAINBOW */ 234. #endif 235. 236. if (!strncmp(opts, "sort", 4)) { 237. flags.sortpack = !negated; 238. return; 239. } 240. 241. /* 242. * the order to list the pack 243. */ 244. if (!strncmp(opts, "packorder", 4)) { 245. register char *sp, *tmp; 246. int tmpend; 247. 248. op = index(opts,':'); 249. if(!op) goto bad; 250. op++; /* skip : */ 251. 252. /* Missing characters in new order are filled in at the end 253. * from inv_order. 254. */ 255. for (sp = op; *sp; sp++) 256. if (!index(inv_order, *sp)) 257. goto bad; /* bad char in order */ 258. else if (index(sp + 1, *sp)) 259. goto bad; /* dup char in order */ 260. tmp = (char *) alloc((unsigned)(strlen(inv_order)+1)); 261. Strcpy(tmp, op); 262. for (sp = inv_order, tmpend = strlen(tmp); *sp; sp++) 263. if (!index(tmp, *sp)) { 264. tmp[tmpend++] = *sp; 265. tmp[tmpend] = 0; 266. } 267. Strcpy(inv_order, tmp); 268. free((genericptr_t)tmp); 269. set_order = TRUE; 270. return; 271. } 272. 273. if (!strncmp(opts, "time", 4)) { 274. flags.time = !negated; 275. flags.botl = 1; 276. return; 277. } 278. 279. if (!strncmp(opts, "rest_on_space", 4)) { 280. flags.no_rest_on_space = negated; 281. return; 282. } 283. 284. if (!strncmp(opts, "fixinv", 3)) { 285. flags.invlet_constant = !negated; 286. if(!from_env && flags.invlet_constant) reassign (); 287. return; 288. } 289. 290. if (!strncmp(opts, "male", 4)) { 291. if(!from_env && flags.female != negated) 292. pline("That is not anatomically possible."); 293. else 294. flags.female = negated; 295. return; 296. } 297. if (!strncmp(opts, "female", 3)) { 298. if(!from_env && flags.female == negated) 299. pline("That is not anatomically possible."); 300. else 301. flags.female = !negated; 302. return; 303. } 304. 305. /* name:string */ 306. if (!strncmp(opts, "name", 4)) { 307. if(!from_env) { 308. #ifdef MSDOS 309. pline("\"name\" settable only from %s.", configfile); 310. #else 311. pline("The playername can be set only from NETHACKOPTIONS."); 312. #endif 313. return; 314. } 315. op = index(opts,':'); 316. if(!op) goto bad; 317. nmcpy(plname, op+1, sizeof(plname)-1); 318. return; 319. } 320. 321. /* graphics:string */ 322. if (!strncmp(opts, "graphics", 4)) { 323. if(!from_env) { 324. #ifdef MSDOS 325. pline("\"graphics\" settable only from %s.", configfile); 326. #else 327. pline("The graphics string can be set only from NETHACKOPTIONS."); 328. #endif 329. return; 330. } 331. op = index(opts,':'); 332. if(!op) 333. goto bad; 334. else 335. opts = op + 1; 336. escapes(opts, opts); 337. #define SETPCHAR(f, n) showsyms.f = (strlen(opts) > n) ? opts[n] : defsyms.f 338. SETPCHAR(stone, 0); 339. SETPCHAR(vwall, 1); 340. SETPCHAR(hwall, 2); 341. SETPCHAR(tlcorn, 3); 342. SETPCHAR(trcorn, 4); 343. SETPCHAR(blcorn, 5); 344. SETPCHAR(brcorn, 6); 345. SETPCHAR(crwall, 7); 346. SETPCHAR(tuwall, 8); 347. SETPCHAR(tdwall, 9); 348. SETPCHAR(tlwall, 10); 349. SETPCHAR(trwall, 11); 350. SETPCHAR(vbeam, 12); 351. SETPCHAR(hbeam, 13); 352. SETPCHAR(lslant, 14); 353. SETPCHAR(rslant, 15); 354. SETPCHAR(door, 16); 355. SETPCHAR(room, 17); 356. SETPCHAR(corr, 18); 357. SETPCHAR(upstair, 19); 358. SETPCHAR(dnstair, 20); 359. SETPCHAR(trap, 21); 360. SETPCHAR(web, 22); 361. SETPCHAR(pool, 23); 362. #ifdef FOUNTAINS 363. SETPCHAR(fountain, 24); 364. #endif 365. #ifdef SINKS 366. SETPCHAR(sink, 25); 367. #endif 368. #ifdef THRONES 369. SETPCHAR(throne, 26); 370. #endif 371. #ifdef ALTARS 372. SETPCHAR(altar, 27); 373. #endif 374. #ifdef STRONGHOLD 375. SETPCHAR(upladder, 28); 376. SETPCHAR(dnladder, 29); 377. SETPCHAR(dbvwall, 30); 378. SETPCHAR(dbhwall, 31); 379. #endif 380. #undef SETPCHAR 381. return; 382. } 383. 384. /* endgame:5t[op] 5a[round] o[wn] */ 385. if (!strncmp(opts, "endgame", 3)) { 386. op = index(opts,':'); 387. if(!op) goto bad; 388. op++; 389. while(*op) { 390. num = 1; 391. if(digit(*op)) { 392. num = atoi(op); 393. while(digit(*op)) op++; 394. } else 395. if(*op == '!') { 396. negated = !negated; 397. op++; 398. } 399. switch(*op) { 400. case 't': 401. flags.end_top = num; 402. break; 403. case 'a': 404. flags.end_around = num; 405. break; 406. case 'o': 407. flags.end_own = !negated; 408. break; 409. default: 410. goto bad; 411. } 412. while(letter(*++op)) ; 413. if(*op == '/') op++; 414. } 415. return; 416. } 417. if (!strncmp(opts, "dogname", 3)) { 418. if(!from_env) { 419. #ifdef MSDOS 420. pline("\"dogname\" settable only from %s.", configfile); 421. #else 422. Your("dog's name can be set only from NETHACKOPTIONS."); 423. #endif 424. return; 425. } 426. op = index(opts, ':'); 427. if (!op) goto bad; 428. nmcpy(dogname, ++op, 62); 429. return; 430. } 431. if (!strncmp(opts, "catname", 3)) { 432. if(!from_env) { 433. #ifdef MSDOS 434. pline("\"catname\" settable only from %s.", configfile); 435. #else 436. Your("cat's name can be set only from NETHACKOPTIONS."); 437. #endif 438. return; 439. } 440. op = index(opts, ':'); 441. if (!op) goto bad; 442. nmcpy(catname, ++op, 62); 443. return; 444. } 445. if (!strncmp(opts, "fruit", 2)) { 446. op = index(opts, ':'); 447. if (!op++) goto bad; 448. if (!from_env) { 449. struct fruit *f; 450. int numfruits = 0; 451. 452. for(f=ffruit; f; f=f->nextf) { 453. if (!strcmp(op, f->fname)) goto goodfruit; 454. numfruits++; 455. } 456. if (numfruits >= 100) { 457. pline("Doing that so many times isn't very fruitful."); 458. return; 459. } 460. } 461. goodfruit: 462. nmcpy(pl_fruit, op, PL_FSIZ); 463. if (!from_env) 464. (void)fruitadd(pl_fruit); 465. /* If from_env, then initoptions is allowed to do it instead 466. * of here (initoptions always has to do it even if there's 467. * no fruit option at all. Also, we don't want people 468. * setting multiple fruits in their options.) 469. */ 470. return; 471. } 472. bad: 473. if(!from_env) { 474. if(!strncmp(opts, "h", 1) || 475. !strncmp(opts, "?", 1)) { 476. option_help(); 477. return; 478. } 479. pline("Unknown option: %s. Enter \"O?\" for help.", opts); 480. return; 481. } 482. #ifdef MSDOS 483. Printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts); 484. #else 485. Printf("Bad syntax in NETHACKOPTIONS: %s.", opts); 486. (void) puts("Use for example:"); 487. (void) puts( 488. "NETHACKOPTIONS=\"!rest_on_space,notombstone,endgame:own/5 topscorers/4 around me\"" 489. ); 490. #endif 491. getret(); 492. } 493. 494. int 495. doset() 496. { 497. char buf[BUFSZ]; 498. 499. pline("What options do you want to set? "); 500. getlin(buf); 501. if(!buf[0] || buf[0] == '\033') { 502. #ifdef MSDOS 503. Strcpy(buf,"OPTIONS="); 504. #ifdef DGK 505. if (flags.rawio) Strcat(buf,"rawio,"); 506. if (flags.IBMBIOS) Strcat(buf,"IBM_BIOS,"); 507. #endif /* DGK */ 508. #ifdef DECRAINBOW 509. if (flags.DECRainbow) Strcat(buf,"DEC_Rainbow,"); 510. #endif /* DECRAINBOW */ 511. #else /* MSDOS */ 512. Strcpy(buf,"NETHACKOPTIONS="); 513. if(flags.standout) Strcat(buf,"standout,"); 514. if(flags.nonull) Strcat(buf,"nonull,"); 515. #endif /* MSDOS */ 516. if(flags.ignintr) Strcat(buf,"ignintr,"); 517. if(flags.num_pad) Strcat(buf,"number_pad,"); 518. #ifdef NEWS 519. if(flags.nonews) Strcat(buf,"nonews,"); 520. #endif 521. if(flags.notombstone) Strcat(buf,"notombstone,"); 522. Strcat(buf, flags.female ? "female," : "male,"); 523. if(flags.no_rest_on_space) Strcat(buf,"!rest_on_space,"); 524. if (flags.invlet_constant) Strcat(buf,"fixinv,"); 525. if (flags.sortpack) Strcat(buf,"sortpack,"); 526. if (set_order){ 527. Strcat(buf, "packorder: "); 528. Strcat(buf, inv_order); 529. Strcat(buf, ","); 530. } 531. if (flags.confirm) Strcat(buf,"confirm,"); 532. if (flags.safe_dog) Strcat(buf,"safe_pet,"); 533. if (flags.pickup) Strcat(buf,"pickup,"); 534. if (flags.silent) Strcat(buf,"silent,"); 535. if (flags.time) Strcat(buf,"time,"); 536. if (flags.verbose) Strcat(buf,"verbose,"); 537. Sprintf(eos(buf), "fruit:%s,", pl_fruit); 538. if(flags.end_top != 5 || flags.end_around != 4 || flags.end_own){ 539. Sprintf(eos(buf), "endgame: %u top scores/%u around me", 540. flags.end_top, flags.end_around); 541. if(flags.end_own) Strcat(buf, "/own scores"); 542. } else { 543. register char *eop = eos(buf); 544. if(*--eop == ',') *eop = 0; 545. } 546. pline(buf); 547. } else { 548. clrlin(); 549. parseoptions(buf, FALSE); 550. } 551. 552. return 0; 553. } 554. 555. int 556. dotogglepickup() { 557. flags.pickup = !flags.pickup; 558. pline("Pickup: %s.", flags.pickup ? "ON" : "OFF"); 559. return 0; 560. } 561. 562. char packorder[] = { 563. AMULET_SYM, WEAPON_SYM, ARMOR_SYM, FOOD_SYM, SCROLL_SYM, 564. # ifdef SPELLS 565. SPBOOK_SYM, 566. # endif 567. WAND_SYM, RING_SYM, POTION_SYM, TOOL_SYM, GEM_SYM, BALL_SYM, ROCK_SYM }; 568. #define Page_line(x) if(page_line(x)) goto quit 569. 570. void 571. option_help() { 572. char buf[BUFSZ]; 573. 574. set_pager(0); 575. Sprintf(buf, " NetHack Options Help:"); 576. if(page_line("") || page_line(buf) || page_line("")) goto quit; 577. 578. #ifdef MSDOS 579. Sprintf(buf, "To set options use OPTIONS=<options> in %s;", configfile); 580. Page_line(buf); 581. #else 582. Page_line("To set options use `NETHACKOPTIONS=\"<options>\"' in your environment;"); 583. #endif 584. 585. Page_line("or press \"O\" while playing, and type your <options> at the prompt."); 586. Page_line("In either case, <options> is a list of options separated by commas."); 587. Page_line(""); 588. 589. Page_line("Boolean options (which can be negated by prefixing them with '!' or \"no\"):"); 590. Page_line("confirm, (fe)male, fixinv, pickup, rest_on_space, safe_pet, silent, sortpack,"); 591. #ifdef MSDOS 592. #ifdef NEWS 593. Page_line("time, tombstone, verbose, news, number_pad, rawio, and IBM_BIOS"); 594. #else 595. Page_line("time, tombstone, verbose, number_pad, rawio, and IBM_BIOS"); 596. #endif 597. #ifdef DECRAINBOW 598. Page_line("and DEC_Rainbow."); 599. #endif /* DECRAINBOW */ 600. #else /* MSDOS */ 601. #ifdef NEWS 602. Page_line("time, tombstone, verbose, news, null, ignintr, and standout."); 603. #else 604. Page_line("time, tombstone, verbose, null, ignintr, and standout."); 605. #endif 606. #endif /* MSDOS */ 607. Page_line(""); 608. 609. Page_line("Compound options:"); 610. Page_line("`name' - your character's name (e.g., name:Merlin-W),"); 611. Page_line("`dogname' - the name of your (first) dog (e.g., dogname:Fang),"); 612. 613. Page_line("`packorder' - the inventory order of the items in your pack"); 614. Sprintf(buf, " (currently, packorder:%s ),", packorder); 615. Page_line(buf); 616. Page_line("`fruit' - the name of a fruit you enjoy eating,"); 617. 618. Page_line("`endgame' - the parts of the score list you wish to see,"); 619. 620. Page_line("`graphics' - defines the symbols to use in drawing the dungeon map."); 621. Page_line(""); 622. Page_line("Some of the options can be set only before the game is started. You will"); 623. Page_line("be so informed, if you attempt to set them while in the game."); 624. set_pager(1); 625. return; 626. quit: 627. set_pager(2); 628. return; 629. } 630. 631. /* Returns the fid of the fruit type; if that type already exists, it 632. * returns the fid of that one; if it does not exist, it adds a new fruit 633. * type to the chain and returns the new one. 634. */ 635. int 636. fruitadd(str) 637. char *str; 638. { 639. register int i,j; 640. register struct fruit *f; 641. struct fruit *lastf; 642. int highest_fruit_id = 0; 643. char buf[PL_FSIZ]; 644. boolean user_specified = (str == pl_fruit); 645. /* if not user-specified, then it's a fruit name for a fruit on 646. * a bones level... 647. */ 648. 649. /* Note: every fruit has an id (spe for fruit objects) of at least 650. * 1; 0 is an error. 651. */ 652. if (user_specified) { 653. /* disallow naming after other foods (since it'd be impossible 654. * to tell the difference) 655. */ 656. 657. boolean found = FALSE; 658. 659. for(i = bases[j=letindex(FOOD_SYM)]; i < bases[j+1]; i++) { 660. if (!strcmp(objects[i].oc_name, pl_fruit)) { 661. found = TRUE; 662. break; 663. } 664. } 665. if (found || 666. (!strncmp(buf, "tin of ", 7) && name_to_mon(buf+7) > -1) || 667. !strcmp(buf, "empty tin") || 668. !strcmp(buf, "tin of spinach") || 669. (!strncmp(eos(buf)-6," corpse",6) && name_to_mon(buf) > -1)) 670. { 671. Strcpy(buf, pl_fruit); 672. Strcpy(pl_fruit, "candied "); 673. nmcpy(pl_fruit+8, buf, PL_FSIZ-8); 674. } 675. } 676. for(f=ffruit; f; f = f->nextf) { 677. lastf = f; 678. if(f->fid > highest_fruit_id) highest_fruit_id = f->fid; 679. if(!strncmp(str, f->fname, PL_FSIZ)) 680. goto nonew; 681. } 682. /* if adding another fruit would overflow spe, use a random 683. fruit instead... we've got a lot to choose from. */ 684. if (highest_fruit_id >= 127) return rnd(127); 685. highest_fruit_id++; 686. f = newfruit(); 687. if (ffruit) lastf->nextf = f; 688. else ffruit = f; 689. Strcpy(f->fname, str); 690. f->fid = highest_fruit_id; 691. f->nextf = 0; 692. nonew: 693. if (user_specified) current_fruit = highest_fruit_id; 694. return f->fid; 695. }